fix(i18n): comprehensive audit of translated strings across web and native

- Replace hand-rolled pluralization (ternary suffix hacks) with `plural` macro
- Wrap 40+ untranslated user-facing strings with LingUI macros: aria-labels,
  accessibilityLabels/Hints, placeholders, error fallbacks, toast overrides
- Unify episode progress format to `${watched}/${plural(total, ...)}` across
  all 4 call sites (title-card, continue-watching, season-accordion)
- Unify capitalization: "Sign in", "Sign out", "Create account",
  "Change password", "Update password", "Image cache", "Remove from library",
  "Mark Watched", "Trending Today", "On Watchlist", "or"
- Translate cron schedule strings in system health via `i18n._(msg)` with
  locale-aware day names via `Intl.DateTimeFormat`
- Move Zod validation schemas inside components with `useMemo(() => ..., [t])`
  so validation messages are translatable at runtime
- Unify "Watched all of" variable naming to `seasonLabel` across all call
  sites to produce a single msgid
- Remove trailing period from lone "Failed to..." error message
- Add EAS build i18n template extraction step

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
jakeandClaude Opus 4.6 committed 2026-03-23 16:21:54 -04:00
1 parent b289b7abed
commit eb9c7ae6df
35 files changed
+489 -161

No files matched your search

+293 -40
View File
@@ -37,6 +37,11 @@ msgstr ""
msgid "{0, plural, one {# title} other {# titles}}"
msgstr ""
#. placeholder {0}: import { msg, plural } from "@lingui/core/macro"; import { Trans, useLingui } from "@lingui/react/macro"; import { IconActivity, IconAlertTriangle, IconCalendarCheck, IconCheck, IconDatabase, IconPlayerPlay, IconRefresh, } from "@tabler/icons-react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; import { StatusDot } from "@/components/status-dot"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardTitle } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; import { Spinner } from "@/components/ui/spinner"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { useTimeAgo } from "@/hooks/use-time-ago"; import { orpc } from "@/lib/orpc/client"; import type { CronJobName, SystemHealthData } from "@sofa/api/schemas"; import { i18n } from "@sofa/i18n"; const DIGITS_ONLY_RE = /^\d+$/; /** Convert a cron pattern to a short human-readable string */ function cronToHuman(pattern: string): string { const parts = pattern.split(" "); if (parts.length !== 5) return pattern; const [min, hour, _dom, _mon, dow] = parts; // Every N hours: "0 */6 * * *" if (hour.startsWith("*/")) { const n = Number.parseInt(hour.slice(2), 10); return i18n._(msg`Every ${n}h`); } // Twice daily: "0 1,13 * * *" if (hour.includes(",") && !hour.includes("/") && !hour.includes("-")) { const hours = hour.split(","); if (hours.length === 2) { const times = hours.map((h) => `${h.padStart(2, "0")}:${min.padStart(2, "0")}`).join(", "); return i18n._(msg`Daily at ${times}`); } } // Daily at specific time: "0 3 * * *" if (DIGITS_ONLY_RE.test(hour) && DIGITS_ONLY_RE.test(min) && dow === "*") { const time = `${hour.padStart(2, "0")}:${min.padStart(2, "0")}`; return i18n._(msg`Daily at ${time}`); } // Weekly — use Intl for locale-aware day name if (DIGITS_ONLY_RE.test(dow)) { const dayDate = new Date(2024, 0, 7 + Number(dow)); // 2024-01-07 is a Sunday const dayName = new Intl.DateTimeFormat(i18n.locale, { weekday: "short" }).format(dayDate); return i18n._(msg`Weekly on ${dayName}`); } return pattern; } function formatBytes(bytes: number): string { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`; } function formatDuration(ms: number): string { if (ms < 1000) return `${ms}ms`; if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`; return `${Math.round(ms / 60000)}m`; } export function SkeletonCards() { return ( <div className="space-y-3"> {["status", "jobs", "storage"].map((s) => ( <Card key={s} className="border-s-primary/30 border-s-2"> <CardContent> <div className="flex items-start gap-3"> <Skeleton className="mt-0.5 h-8 w-8 rounded-lg" /> <div className="flex-1 space-y-2"> <Skeleton className="h-4 w-28" /> <Skeleton className="h-3 w-48" /> </div> </div> </CardContent> </Card> ))} </div> ); } /** Inline component that live-updates a relative timestamp */ function LiveTimeAgo({ date, fallback = "", }: { date: string | Date | null | undefined; fallback?: string; }) { const text = useTimeAgo(date, { fallback }); return <span suppressHydrationWarning>{text}</span>; } /** Hydrates system health state and renders the 3 cards */ export function SystemHealthCards() { const queryClient = useQueryClient(); const { data, isPending, isFetching } = useQuery(orpc.admin.systemHealth.queryOptions()); const isRefreshing = isFetching; const refresh = () => queryClient.invalidateQueries({ queryKey: orpc.admin.systemHealth.key() }); if (isPending || !data) return <SkeletonCards />; return ( <div className="space-y-3"> <SystemStatusCard checkedAt={data.checkedAt} database={data.database} tmdb={data.tmdb} environment={data.environment} isRefreshing={isRefreshing} onRefresh={refresh} /> <BackgroundJobsCard jobs={data.jobs} isRefreshing={isRefreshing} onRefresh={refresh} /> <StorageCard imageCache={data.imageCache} backups={data.backups} isRefreshing={isRefreshing} onRefresh={refresh} /> </div> ); } function RefreshButton({ isRefreshing, onRefresh, }: { isRefreshing: boolean; onRefresh: () => void; }) { const { t } = useLingui(); return ( <Tooltip> <TooltipTrigger render={ <Button variant="ghost" size="icon" aria-label={t`Refresh system health`} onClick={onRefresh} disabled={isRefreshing} className="text-muted-foreground" /> } > {isRefreshing ? <Spinner /> : <IconRefresh />} </TooltipTrigger> <TooltipContent> <Trans>Refresh</Trans> </TooltipContent> </Tooltip> ); } function SystemStatusCard({ checkedAt, database, tmdb, environment, isRefreshing, onRefresh, }: Pick<SystemHealthData, "checkedAt" | "database" | "tmdb" | "environment"> & { isRefreshing: boolean; onRefresh: () => void; }) { rLine truncated
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} · last <0/>"
msgstr "{0} · last <0/>"
#: apps/web/src/components/settings/backup-section.tsx
#~ msgid "{0} {1, plural, one {backup} other {backups}} stored"
#~ msgstr ""
@@ -93,31 +98,43 @@ msgstr ""
#~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{backupCount, plural, one {# backup} other {# backups}}"
msgstr "{backupCount, plural, one {# backup} other {# backups}}"
#: apps/web/src/components/settings/backup-section.tsx
msgid "{backupCount, plural, one {# backup} other {# backups}} stored"
msgstr "{backupCount, plural, one {# backup} other {# backups}} stored"
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{backupCount} backups · last <0/>"
msgstr "{backupCount} backups · last <0/>"
#~ msgid "{backupCount} backups · last <0/>"
#~ msgstr "{backupCount} backups · last <0/>"
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{cachedImageCount} cached images"
msgstr "{cachedImageCount} cached images"
msgid "{cachedImageCount, plural, one {# cached image} other {# cached images}}"
msgstr "{cachedImageCount, plural, one {# cached image} other {# cached images}}"
#: apps/web/src/components/settings/system-health-section.tsx
#~ msgid "{cachedImageCount} cached images"
#~ msgstr "{cachedImageCount} cached images"
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "{count, plural, one {# earlier episode} other {# earlier episodes}} unwatched"
msgstr "{count, plural, one {# earlier episode} other {# earlier episodes}} unwatched"
#: apps/web/src/components/titles/cast-carousel.tsx
msgid "{count, plural, one {# ep} other {# eps}}"
msgstr "{count, plural, one {# ep} other {# eps}}"
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
#~ msgstr ""
#: apps/web/src/components/titles/cast-carousel.tsx
msgid "{count} ep{suffix}"
msgstr "{count} ep{suffix}"
#~ msgid "{count} ep{suffix}"
#~ msgstr "{count} ep{suffix}"
#: apps/web/src/components/settings/system-health-section.tsx
#~ msgid "{healthyCount} of {0} jobs healthy"
@@ -156,21 +173,29 @@ msgstr "{movieCount} movies, {episodeCount} episodes"
msgid "{ratingCount} ratings"
msgstr "{ratingCount} ratings"
#: apps/native/src/components/ui/star-rating.tsx
msgid "{star, plural, one {# star} other {# stars}}"
msgstr "{star, plural, one {# star} other {# stars}}"
#: apps/web/src/components/settings/imports-section.tsx
msgid "{unresolvedCount} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr "{unresolvedCount} items have no external IDs and will be resolved by title search, which may be less accurate."
#: apps/web/src/components/title-card.tsx
msgid "{watched}/{total} episodes"
msgstr ""
msgid "{watched}/{total, plural, one {# episode} other {# episodes}}"
msgstr "{watched}/{total, plural, one {# episode} other {# episodes}}"
#: apps/web/src/components/title-card.tsx
#~ msgid "{watched}/{total} episodes"
#~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount} of {0} episodes watched"
#~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount} of {episodeCount} episodes watched"
msgstr "{watchedCount} of {episodeCount} episodes watched"
#~ msgid "{watchedCount} of {episodeCount} episodes watched"
#~ msgstr "{watchedCount} of {episodeCount} episodes watched"
#: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}"
@@ -180,10 +205,12 @@ msgstr "{watchedCount} of {episodeCount} episodes watched"
#~ msgid "{watchedCount}/{0} episodes"
#~ msgstr "{watchedCount}/{0} episodes"
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{episodeCount, plural, one {# episode} other {# episodes}}"
msgstr "{watchedCount}/{episodeCount, plural, one {# episode} other {# episodes}}"
#: apps/native/src/components/dashboard/continue-watching-card.tsx
#: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{watchedEpisodes}/{totalEpisodes, plural, one {# episode} other {# episodes}}"
msgstr "{watchedEpisodes}/{totalEpisodes, plural, one {# episode} other {# episodes}}"
@@ -198,6 +225,10 @@ msgstr "{watchlistCount} items"
msgid "Account"
msgstr ""
#: apps/web/src/components/nav-bar.tsx
msgid "Account menu"
msgstr "Account menu"
#: apps/web/src/components/settings/system-health-section.tsx
msgid "Actions"
msgstr ""
@@ -221,15 +252,20 @@ msgstr ""
msgid "Add a new webhook and paste the URL above"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Add profile photo"
msgstr "Add profile photo"
#: apps/web/src/components/explore/hero-banner.tsx
msgid "Add to Library"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx
msgid "Add to watchlist"
msgstr ""
#~ msgid "Add to watchlist"
#~ msgstr ""
#: apps/native/src/components/explore/hero-banner.tsx
#: apps/native/src/components/titles/status-action-button.tsx
#: apps/native/src/components/ui/poster-card.tsx
#: apps/web/src/components/title-card.tsx
msgid "Add to Watchlist"
@@ -288,6 +324,7 @@ msgstr ""
msgid "An unexpected error occurred while loading this page. You can try again or head back to the dashboard."
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Anonymous usage reporting"
msgstr ""
@@ -437,14 +474,15 @@ msgid "Caught up — marked {count, plural, one {# episode} other {# episodes}}
msgstr "Caught up — marked {count, plural, one {# episode} other {# episodes}} as watched"
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/app/change-password.tsx
#: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/account-section.tsx
msgid "Change password"
msgstr ""
#: apps/native/src/app/change-password.tsx
msgid "Change Password"
msgstr ""
#~ msgid "Change Password"
#~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Change Photo"
@@ -458,6 +496,7 @@ msgstr ""
msgid "Check configuration"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Check for updates"
msgstr ""
@@ -530,6 +569,7 @@ msgstr ""
msgid "Completed"
msgstr ""
#: apps/native/src/app/change-password.tsx
#: apps/native/src/app/change-password.tsx
#: apps/web/src/components/settings/account-section.tsx
msgid "Confirm new password"
@@ -624,14 +664,16 @@ msgstr ""
msgid "Could not load title details"
msgstr "Could not load title details"
#: apps/native/src/app/(auth)/register.tsx
#: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx
msgid "Create account"
msgstr ""
#: apps/native/src/app/(auth)/register.tsx
#: apps/native/src/app/(auth)/register.tsx
msgid "Create Account"
msgstr ""
#~ msgid "Create Account"
#~ msgstr ""
#: apps/native/src/app/(auth)/login.tsx
msgid "Create an account"
@@ -645,15 +687,25 @@ msgstr ""
msgid "Creating…"
msgstr ""
#: apps/native/src/app/change-password.tsx
#: apps/native/src/app/change-password.tsx
#: apps/web/src/components/settings/account-section.tsx
msgid "Current password"
msgstr ""
#: apps/native/src/app/change-password.tsx
#: apps/web/src/components/settings/account-section.tsx
msgid "Current password is required"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "Daily at {time}"
msgstr "Daily at {time}"
#: apps/web/src/components/settings/system-health-section.tsx
msgid "Daily at {times}"
msgstr "Daily at {times}"
#: apps/web/src/routes/_app/settings.tsx
msgid "Danger Zone"
msgstr ""
@@ -732,6 +784,10 @@ msgstr ""
msgid "Disconnect {label}"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Display name"
msgstr "Display name"
#: apps/native/src/app/(auth)/server-url.tsx
msgid "Don't have a server?"
msgstr ""
@@ -745,6 +801,10 @@ msgstr ""
msgid "Done"
msgstr ""
#: apps/native/src/components/ui/star-rating.tsx
msgid "Double tap to clear rating"
msgstr "Double tap to clear rating"
#: apps/native/src/components/explore/genre-chip.tsx
msgid "Double tap to clear this filter"
msgstr ""
@@ -753,6 +813,10 @@ msgstr ""
msgid "Double tap to filter by {label}"
msgstr ""
#: apps/native/src/components/ui/star-rating.tsx
msgid "Double tap to rate {star, plural, one {# star} other {# stars}}"
msgstr "Double tap to rate {star, plural, one {# star} other {# stars}}"
#: apps/web/src/components/settings/backup-section.tsx
#: apps/web/src/components/settings/backup-section.tsx
msgid "Download"
@@ -766,6 +830,10 @@ msgstr ""
msgid "Download your library, watch history, and ratings as JSON"
msgstr "Download your library, watch history, and ratings as JSON"
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Edit profile photo"
msgstr "Edit profile photo"
#: apps/native/src/app/person/[id].tsx
#: apps/native/src/components/search/recently-viewed-row-content.tsx
#: apps/web/src/components/people/person-hero.tsx
@@ -773,11 +841,18 @@ msgid "Editor"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
#: apps/native/src/app/(auth)/login.tsx
#: apps/native/src/app/(auth)/register.tsx
#: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx
msgid "Email"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
#: apps/native/src/app/(auth)/register.tsx
msgid "Email is required"
msgstr "Email is required"
#: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type"
msgstr ""
@@ -794,10 +869,19 @@ msgstr ""
msgid "Enable the <0>Playback</0> event category"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
#: apps/native/src/app/(auth)/register.tsx
msgid "Enter a valid email address"
msgstr "Enter a valid email address"
#: apps/web/src/components/settings/imports-section.tsx
msgid "Enter the code below on {source}'s website to authorize Sofa."
msgstr ""
#: apps/native/src/app/(auth)/server-url.tsx
msgid "Enter the full URL for your Sofa server"
msgstr "Enter the full URL for your Sofa server"
#: apps/web/src/components/settings/account-section.tsx
msgid "Enter your current password and choose a new one."
msgstr ""
@@ -828,11 +912,13 @@ msgstr "Episode {episodeNumber}"
msgid "Episode {episodeNumber}, {episodeLabel}"
msgstr "Episode {episodeNumber}, {episodeLabel}"
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts
msgid "Episode unwatched"
msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts
msgid "Episode watched"
@@ -882,6 +968,10 @@ msgstr ""
msgid "Errors ({errorCount})"
msgstr "Errors ({errorCount})"
#: apps/web/src/components/settings/system-health-section.tsx
msgid "Every {n}h"
msgstr "Every {n}h"
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -945,8 +1035,12 @@ msgid "Failed to disconnect {label}"
msgstr ""
#: apps/web/src/components/settings/backup-schedule-section.tsx
msgid "Failed to load backup schedule settings."
msgstr ""
msgid "Failed to load backup schedule settings"
msgstr "Failed to load backup schedule settings"
#: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "Failed to load backup schedule settings."
#~ msgstr ""
#: apps/web/src/routes/_app/titles.$id.tsx
msgid "Failed to load title"
@@ -1022,6 +1116,10 @@ msgstr ""
msgid "Failed to start {sourceLabel} connection"
msgstr "Failed to start {sourceLabel} connection"
#: apps/web/src/components/auth-form.tsx
msgid "Failed to start SSO login"
msgstr "Failed to start SSO login"
#: apps/web/src/components/settings/system-health-section.tsx
msgid "Failed to trigger job"
msgstr ""
@@ -1156,14 +1254,15 @@ msgstr ""
msgid "Home"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/system-health-section.tsx
#: apps/web/src/components/settings/system-health-section.tsx
msgid "Image cache"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Image Cache"
msgstr ""
#~ msgid "Image Cache"
#~ msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "Image cache and backup disk usage"
@@ -1243,17 +1342,18 @@ msgid "Importing from {source}"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "In library"
msgstr ""
#~ msgid "In library"
#~ msgstr ""
#: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/web/src/components/dashboard/stats-display.tsx
msgid "In Library"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx
#: apps/web/src/components/titles/status-button.tsx
msgid "In Watchlist"
msgstr "In Watchlist"
#~ msgid "In Watchlist"
#~ msgstr "In Watchlist"
#: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/web/src/components/dashboard/library-section.tsx
@@ -1356,10 +1456,19 @@ msgstr ""
msgid "Library statuses"
msgstr "Library statuses"
#: apps/native/src/components/ui/skeleton.tsx
#: apps/web/src/components/ui/spinner.tsx
msgid "Loading"
msgstr "Loading"
#: apps/web/src/components/auth-form.tsx
msgid "Loading…"
msgstr ""
#: apps/web/src/components/auth-form.tsx
msgid "Login failed"
msgstr "Login failed"
#: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx
msgid "Lost connection to import. Check status in settings."
@@ -1390,22 +1499,32 @@ msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/components/ui/poster-card.tsx
msgid "Mark as Watched"
msgstr ""
#~ msgid "Mark as Watched"
#~ msgstr ""
#: apps/native/src/components/ui/poster-card.tsx
#~ msgid "Mark as Watching"
#~ msgstr ""
#: apps/web/src/components/titles/title-seasons.tsx
msgid "Mark episode {epNum} watched"
msgstr "Mark episode {epNum} watched"
#: apps/native/src/components/dashboard/upcoming-row.tsx
msgid "Mark Episode Watched"
msgstr "Mark Episode Watched"
#: apps/native/src/app/title/[id].tsx
#: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/components/ui/poster-card.tsx
#: apps/web/src/components/titles/title-actions.tsx
msgid "Mark Watched"
msgstr ""
#: apps/native/src/app/title/[id].tsx
msgid "Marked \"{name}\" as watched"
msgstr "Marked \"{name}\" as watched"
#: apps/native/src/lib/title-actions.ts
#~ msgid "Marked \"{titleName}\" as completed"
#~ msgstr ""
@@ -1429,6 +1548,7 @@ msgstr "Marked all episodes of \"{titleName}\" as watched"
#~ msgid "Marked as completed"
#~ msgstr ""
#: apps/native/src/app/title/[id].tsx
#: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts
msgid "Marked as watched"
@@ -1443,6 +1563,10 @@ msgstr ""
msgid "Member since {memberSince}"
msgstr ""
#: apps/web/src/components/auth-form.tsx
msgid "Min 8 characters…"
msgstr "Min 8 characters…"
#: apps/web/src/components/settings/backup-schedule-section.tsx
msgid "Monday"
msgstr ""
@@ -1490,11 +1614,20 @@ msgstr ""
#~ msgid "Movies this month"
#~ msgstr ""
#: apps/native/src/app/(auth)/register.tsx
#: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx
msgid "Name"
msgstr ""
#: apps/native/src/app/(auth)/register.tsx
msgid "Name is required"
msgstr "Name is required"
#: apps/native/src/app/(auth)/register.tsx
msgid "Name must be at least 2 characters"
msgstr "Name must be at least 2 characters"
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx
msgid "Name updated"
@@ -1528,6 +1661,7 @@ msgstr ""
msgid "New backup"
msgstr ""
#: apps/native/src/app/change-password.tsx
#: apps/native/src/app/change-password.tsx
#: apps/web/src/components/settings/account-section.tsx
msgid "New password"
@@ -1559,6 +1693,10 @@ msgstr ""
msgid "Next run"
msgstr ""
#: apps/native/src/components/dashboard/continue-watching-card.tsx
msgid "Next: S{seasonNum} E{epNum}"
msgstr "Next: S{seasonNum} E{epNum}"
#: apps/web/src/components/settings/backup-section.tsx
#: apps/web/src/components/settings/system-health-section.tsx
msgid "No backups yet"
@@ -1598,8 +1736,10 @@ msgstr ""
msgid "Not Found"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx
#: apps/web/src/components/dashboard/upcoming-item.tsx
#: apps/web/src/components/title-card.tsx
#: apps/web/src/components/titles/status-button.tsx
msgid "On Watchlist"
msgstr ""
@@ -1639,6 +1779,7 @@ msgstr ""
msgid "Open Radarr, go to Settings > Import Lists"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/registration-section.tsx
msgid "Open registration"
@@ -1652,13 +1793,26 @@ msgstr ""
msgid "Open Sonarr, go to Settings > Import Lists"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Opens options to change or remove your photo"
msgstr "Opens options to change or remove your photo"
#: apps/native/src/app/title/[id].tsx
msgid "Opens the trailer in YouTube"
msgstr "Opens the trailer in YouTube"
#: apps/native/src/components/explore/hero-banner.tsx
msgid "Opens title details"
msgstr "Opens title details"
#: apps/native/src/app/(auth)/login.tsx
#: apps/web/src/components/auth-form.tsx
msgid "or"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
msgid "OR"
msgstr ""
#~ msgid "OR"
#~ msgstr ""
#: apps/native/src/app/+not-found.tsx
msgid "Page Not Found"
@@ -1673,16 +1827,28 @@ msgid "Parsing..."
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
#: apps/native/src/app/(auth)/login.tsx
#: apps/native/src/app/(auth)/register.tsx
#: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx
msgid "Password"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
#: apps/native/src/app/(auth)/register.tsx
msgid "Password is required"
msgstr "Password is required"
#: apps/native/src/app/change-password.tsx
msgid "Password must be at least 8 characters"
msgstr "Password must be at least 8 characters"
#: apps/native/src/app/change-password.tsx
#: apps/web/src/components/settings/account-section.tsx
msgid "Password updated"
msgstr ""
#: apps/native/src/app/change-password.tsx
#: apps/web/src/components/settings/account-section.tsx
msgid "Passwords do not match"
msgstr ""
@@ -1716,6 +1882,14 @@ msgstr ""
msgid "Play trailer"
msgstr ""
#: apps/native/src/app/title/[id].tsx
msgid "Play trailer for {titleName}"
msgstr "Play trailer for {titleName}"
#: apps/native/src/app/change-password.tsx
msgid "Please confirm your password"
msgstr "Please confirm your password"
#: apps/native/src/hooks/use-server-connection.ts
msgid "Please sign in again."
msgstr "Please sign in again."
@@ -1734,6 +1908,11 @@ msgstr ""
msgid "Pre-restore backup"
msgstr ""
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/components/nav-bar.tsx
msgid "Primary"
msgstr "Primary"
#: apps/native/src/app/person/[id].tsx
#: apps/native/src/components/search/recently-viewed-row-content.tsx
#: apps/web/src/components/people/person-hero.tsx
@@ -1804,6 +1983,10 @@ msgstr ""
msgid "Radarr List URL"
msgstr ""
#: apps/web/src/components/titles/star-rating.tsx
msgid "Rate {star, plural, one {# star} other {# stars}}"
msgstr "Rate {star, plural, one {# star} other {# stars}}"
#: apps/native/src/hooks/use-title-actions.ts
#~ msgid "Rated {0} {1, plural, one {star} other {stars}}"
#~ msgstr ""
@@ -1827,6 +2010,7 @@ msgstr ""
#: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/titles/star-rating.tsx
msgid "Rating"
msgstr ""
@@ -1836,6 +2020,10 @@ msgstr ""
msgid "Rating removed"
msgstr ""
#: apps/native/src/components/ui/star-rating.tsx
msgid "Rating: {rating} out of 5 stars"
msgstr "Rating: {rating} out of 5 stars"
#: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx
@@ -1920,6 +2108,10 @@ msgstr ""
msgid "Registration Closed"
msgstr ""
#: apps/web/src/components/auth-form.tsx
msgid "Registration failed"
msgstr "Registration failed"
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/registration-section.tsx
msgid "Registration opened"
@@ -1931,7 +2123,10 @@ msgstr ""
msgid "Remove"
msgstr ""
#: apps/native/src/components/dashboard/continue-watching-card.tsx
#: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/components/titles/status-action-button.tsx
#: apps/native/src/components/ui/poster-card.tsx
#: apps/web/src/components/titles/status-button.tsx
msgid "Remove from library"
msgstr ""
@@ -1939,14 +2134,18 @@ msgstr ""
#: apps/native/src/components/dashboard/continue-watching-card.tsx
#: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/components/ui/poster-card.tsx
msgid "Remove from Library"
msgstr ""
#~ msgid "Remove from Library"
#~ msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx
#: apps/web/src/components/titles/status-button.tsx
msgid "Remove from library?"
msgstr "Remove from library?"
#: apps/web/src/components/command-palette.tsx
msgid "Remove from recent searches"
msgstr "Remove from recent searches"
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Remove Photo"
msgstr ""
@@ -2133,6 +2332,10 @@ msgstr ""
msgid "Season {seasonNumber}"
msgstr "Season {seasonNumber}"
#: apps/native/src/components/titles/season-accordion.tsx
msgid "Season {sn}"
msgstr "Season {sn}"
#: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts
msgid "Season watched"
@@ -2164,6 +2367,7 @@ msgstr ""
msgid "Server Health"
msgstr ""
#: apps/native/src/app/(auth)/server-url.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Server URL"
msgstr ""
@@ -2188,6 +2392,7 @@ msgstr ""
#: apps/native/src/components/navigation/native-tab-bar.tsx
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/components/settings/settings-shell.tsx
msgid "Settings"
msgstr ""
@@ -2212,15 +2417,17 @@ msgstr ""
msgid "Show more"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
#: apps/web/src/components/auth-form.tsx
#: apps/web/src/components/auth-form.tsx
#: apps/web/src/components/landing-page.tsx
msgid "Sign in"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
#: apps/web/src/components/landing-page.tsx
msgid "Sign In"
msgstr ""
#~ msgid "Sign In"
#~ msgstr ""
#: apps/web/src/routes/_auth/register.tsx
msgid "Sign in instead"
@@ -2245,6 +2452,10 @@ msgid "Sign in with {providerName}"
msgstr "Sign in with {providerName}"
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/components/header-avatar.tsx
#: apps/native/src/components/header-avatar.tsx
#: apps/native/src/components/header-avatar.tsx
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/components/settings/account-section.tsx
@@ -2255,9 +2466,10 @@ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/components/header-avatar.tsx
#: apps/native/src/components/header-avatar.tsx
msgid "Sign Out"
msgstr ""
#~ msgid "Sign Out"
#~ msgstr ""
#: apps/native/src/app/change-password.tsx
#: apps/native/src/app/change-password.tsx
#: apps/web/src/components/settings/account-section.tsx
msgid "Sign out of other sessions"
@@ -2292,6 +2504,7 @@ msgstr ""
#: apps/native/src/app/change-password.tsx
#: apps/native/src/app/person/[id].tsx
#: apps/native/src/app/title/[id].tsx
#: apps/web/src/components/auth-form.tsx
#: apps/web/src/components/route-error.tsx
#: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/__root.tsx
@@ -2311,6 +2524,10 @@ msgstr ""
msgid "Sonarr List URL"
msgstr ""
#: apps/web/src/components/people/filmography-grid.tsx
msgid "Sort filmography"
msgstr "Sort filmography"
#: apps/web/src/components/dashboard/stats-section.tsx
msgid "Start exploring"
msgstr ""
@@ -2506,10 +2723,11 @@ msgid "Trailer"
msgstr ""
#: apps/web/src/components/explore/hero-banner.tsx
msgid "Trending today"
msgstr ""
#~ msgid "Trending today"
#~ msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/components/explore/hero-banner.tsx
#: apps/web/src/routes/_app/explore.tsx
msgid "Trending Today"
msgstr ""
@@ -2554,6 +2772,10 @@ msgstr ""
msgid "unlimited"
msgstr ""
#: apps/web/src/components/titles/title-seasons.tsx
msgid "Unmark episode {epNum}"
msgstr "Unmark episode {epNum}"
#: apps/web/src/components/settings/system-health-section.tsx
msgid "Unreachable"
msgstr ""
@@ -2578,6 +2800,10 @@ msgstr "Unwatched all of {seasonLabel}"
msgid "Unwatched S{seasonNum} E{epNum}"
msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
msgid "Unwatched S{sNum} E{eNum}"
msgstr "Unwatched S{sNum} E{eNum}"
#: apps/native/src/components/titles/continue-watching-banner.tsx
#: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "Up next"
@@ -2618,13 +2844,14 @@ msgstr ""
msgid "Update failed"
msgstr ""
#: apps/native/src/app/change-password.tsx
#: apps/web/src/components/settings/account-section.tsx
msgid "Update password"
msgstr ""
#: apps/native/src/app/change-password.tsx
msgid "Update Password"
msgstr ""
#~ msgid "Update Password"
#~ msgstr ""
#: apps/web/src/components/settings/backup-restore-section.tsx
#: apps/web/src/components/settings/imports-section.tsx
@@ -2663,6 +2890,18 @@ msgstr ""
msgid "URL copied to clipboard"
msgstr ""
#: apps/native/src/app/(auth)/register.tsx
msgid "Use at least 8 characters"
msgstr "Use at least 8 characters"
#: apps/native/src/components/header-avatar.tsx
msgid "User menu"
msgstr "User menu"
#: apps/web/src/components/titles/title-hero.tsx
msgid "View on TMDB"
msgstr "View on TMDB"
#: apps/web/src/components/update-toast.tsx
msgid "View release"
msgstr ""
@@ -2699,20 +2938,26 @@ msgstr ""
msgid "Watch on {name}"
msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/lib/title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Watched all of {seasonLabel}"
msgstr ""
#: apps/native/src/lib/title-actions.ts
msgid "Watched all of {seasonName}"
msgstr ""
#~ msgid "Watched all of {seasonName}"
#~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Watched S{seasonNum} E{epNum}"
msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
msgid "Watched S{sNum} E{eNum}"
msgstr "Watched S{sNum} E{eNum}"
#: apps/native/src/components/titles/status-action-button.tsx
#: apps/web/src/components/dashboard/upcoming-item.tsx
#: apps/web/src/components/title-card.tsx
@@ -2741,6 +2986,10 @@ msgstr ""
msgid "Wednesday"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "Weekly on {dayName}"
msgstr "Weekly on {dayName}"
#: apps/web/src/components/auth-form.tsx
#: apps/web/src/components/dashboard/welcome-header.tsx
msgid "Welcome back"
@@ -2789,3 +3038,7 @@ msgstr ""
#: apps/native/src/app/(auth)/register.tsx
msgid "Your name"
msgstr ""
#: apps/web/src/components/auth-form.tsx
msgid "Your name…"
msgstr "Your name…"