refactor: consolidate watchlist states (#18)

- Rename `watchlist` → `in_watchlist` and `in_progress` → `watching` across the full stack (DB migration, Drizzle schema, core services, API contract, web, native)
- Add a new `caught_up` status for TV shows where all aired episodes are watched but the show is still airing
- Add `titles.watchAll` procedure and `markAllWatched` action to mark every episode of a TV show as watched in one step; replace the old "Mark as Watching" / "Mark as Completed" context-menu actions with "Mark All Watched" (TV) and "Mark as Watched" (movie)
- Extract `display-status.ts` in `@sofa/api` to share status → display label/color logic between web and native
- Add `getDisplayStatusesByTitleIds` to `@sofa/core/tracking` and wire it into the dashboard library feed so clients receive resolved display statuses
- Show a destructive Alert confirmation before removing a title from the library (native)
- Remove "Mark as Completed" from the continue-watching card context menu
- Update i18n catalogs for all 6 locales (de, en, es, fr, it, pt)
This commit is contained in:
2026-03-20 15:31:31 -04:00
committed by GitHub
parent 4b4d35ce31
commit 5c70d29fac
49 changed files with 4889 additions and 1309 deletions
@@ -48,7 +48,7 @@ export default function ExploreScreen() {
() =>
Object.assign({}, ...(trending.data?.pages.map((p) => p.userStatuses) ?? [])) as Record<
string,
"watchlist" | "in_progress" | "completed"
"in_watchlist" | "watching" | "caught_up" | "completed"
>,
[trending.data?.pages],
);
+1 -1
View File
@@ -84,7 +84,7 @@ export default function PersonDetailScreen() {
() =>
Object.assign({}, ...(data?.pages.map((p) => p.userStatuses) ?? [])) as Record<
string,
"watchlist" | "in_progress" | "completed"
"in_watchlist" | "watching" | "caught_up" | "completed"
>,
[data?.pages],
);
+1 -1
View File
@@ -374,7 +374,7 @@ export default function TitleDetailScreen() {
<StatusActionButton
currentStatus={userInfo.data?.status ?? null}
onStatusChange={(status) => {
if (status === "watchlist") {
if (status === "in_watchlist") {
quickAddMutation.mutate({ id });
} else {
updateStatus.mutate({ id, status: null });
@@ -104,11 +104,6 @@ export const ContinueWatchingCard = memo(function ContinueWatchingCard({
</Link.Trigger>
<Link.Preview />
<Link.Menu>
<Link.MenuAction
title={t`Mark as Completed`}
icon="checkmark.circle"
onPress={() => titleActions.markCompleted(item.title.id, item.title.title)}
/>
<Link.MenuAction
title={t`Remove from Library`}
icon="trash"
@@ -18,7 +18,7 @@ export interface PosterRowItem {
releaseDate?: string | null;
firstAirDate?: string | null;
voteAverage?: number | null;
userStatus?: "watchlist" | "in_progress" | "completed" | null;
userStatus?: "in_watchlist" | "watching" | "caught_up" | "completed" | null;
episodeProgress?: { watched: number; total: number } | null;
}
@@ -13,7 +13,7 @@ import { SectionHeader } from "@/components/ui/section-header";
import { Text } from "@/components/ui/text";
import { orpc } from "@/lib/orpc";
type TitleStatus = "watchlist" | "in_progress" | "completed";
type TitleStatus = "in_watchlist" | "watching" | "caught_up" | "completed";
const genreChipsContentStyle = { paddingHorizontal: 16 };
export function FilterableTitleRow({
@@ -32,7 +32,7 @@ export function ContinueWatchingBanner({
[seasons, watchedEpisodeIds],
);
if (userStatus !== "in_progress" || !nextEpisode) return null;
if (userStatus !== "watching" || !nextEpisode) return null;
const stillUrl = nextEpisode.stillPath ?? backdropPath ?? null;
const progress = totalEpisodes > 0 ? (watchedEpisodes / totalEpisodes) * 100 : 0;
@@ -5,30 +5,35 @@ import {
IconPlayerPlayFilled,
IconPlus,
} from "@tabler/icons-react-native";
import { Pressable } from "react-native";
import { Alert, Pressable } from "react-native";
import { useCSSVariable } from "uniwind";
import { ScaledIcon } from "@/components/ui/scaled-icon";
import { Text } from "@/components/ui/text";
import * as Haptics from "@/utils/haptics";
type TitleStatus = "watchlist" | "in_progress" | "completed";
type TitleStatus = "in_watchlist" | "watching" | "caught_up" | "completed";
const STATUS_ICONS = {
watchlist: IconBookmarkFilled,
in_progress: IconPlayerPlayFilled,
in_watchlist: IconBookmarkFilled,
watching: IconPlayerPlayFilled,
caught_up: IconCheck,
completed: IconCheck,
} as const;
const STATUS_STYLES = {
watchlist: {
in_watchlist: {
bgClass: "bg-title-accent/10 border-title-accent/20",
textClass: "text-title-accent",
},
in_progress: {
watching: {
bgClass: "bg-title-accent/10 border-title-accent/20",
textClass: "text-title-accent",
},
caught_up: {
bgClass: "bg-status-completed/10 border-status-completed/20",
textClass: "text-status-completed",
},
completed: {
bgClass: "bg-status-completed/10 border-status-completed/20",
textClass: "text-status-completed",
@@ -37,10 +42,12 @@ const STATUS_STYLES = {
function StatusLabel({ status }: { status: TitleStatus }) {
switch (status) {
case "watchlist":
return <Trans>Watchlisted</Trans>;
case "in_progress":
case "in_watchlist":
return <Trans>In Watchlist</Trans>;
case "watching":
return <Trans>Watching</Trans>;
case "caught_up":
return <Trans>Caught Up</Trans>;
case "completed":
return <Trans>Completed</Trans>;
}
@@ -66,7 +73,7 @@ export function StatusActionButton({
<Pressable
onPress={() => {
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
onStatusChange("watchlist");
onStatusChange("in_watchlist");
}}
disabled={isPending}
accessibilityRole="button"
@@ -83,13 +90,25 @@ export function StatusActionButton({
const StatusIcon = STATUS_ICONS[currentStatus];
const styles = STATUS_STYLES[currentStatus];
const iconColor = currentStatus === "completed" ? completedColor : titleAccent;
const iconColor =
currentStatus === "completed" || currentStatus === "caught_up" ? completedColor : titleAccent;
return (
<Pressable
onPress={() => {
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
onStatusChange(null);
Alert.alert(
t`Remove from library?`,
t`This title will be removed from your library. Your watch history and ratings will be kept.`,
[
{ text: t`Cancel`, style: "cancel" },
{
text: t`Remove`,
style: "destructive",
onPress: () => onStatusChange(null),
},
],
);
}}
disabled={isPending}
accessibilityRole="button"
+20 -17
View File
@@ -23,7 +23,7 @@ import { Text } from "@/components/ui/text";
import { usePressAnimation } from "@/hooks/use-press-animation";
import { titleActions } from "@/lib/title-actions";
type TitleStatus = "watchlist" | "in_progress" | "completed";
type TitleStatus = "in_watchlist" | "watching" | "caught_up" | "completed";
interface PosterCardProps {
id: string;
@@ -61,8 +61,9 @@ export const PosterCard = memo(function PosterCard({
const completedColor = useCSSVariable("--color-status-completed") as string;
const statusColors: Record<TitleStatus, string> = {
watchlist: watchlistColor,
in_progress: watchingColor,
in_watchlist: watchlistColor,
watching: watchingColor,
caught_up: completedColor,
completed: completedColor,
};
@@ -79,11 +80,13 @@ export const PosterCard = memo(function PosterCard({
const statusLabel =
userStatus === "completed"
? "completed"
: userStatus === "in_progress"
? "watching"
: userStatus === "watchlist"
? "on watchlist"
: undefined;
: userStatus === "caught_up"
? "caught up"
: userStatus === "watching"
? "watching"
: userStatus === "in_watchlist"
? "on watchlist"
: undefined;
const cardAccessibilityLabel = [title, type === "movie" ? "movie" : "TV show", year, statusLabel]
.filter(Boolean)
.join(", ");
@@ -119,9 +122,9 @@ export const PosterCard = memo(function PosterCard({
className="absolute top-2 right-2 size-[30px] items-center justify-center rounded-full"
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
>
{userStatus === "completed" ? (
{userStatus === "completed" || userStatus === "caught_up" ? (
<IconCheckbox size={16} color="white" />
) : userStatus === "in_progress" ? (
) : userStatus === "watching" ? (
<IconPlayerPlayFilled size={16} color="white" />
) : (
<IconBookmarkFilled size={16} color="white" />
@@ -214,13 +217,6 @@ export const PosterCard = memo(function PosterCard({
onPress={handleQuickAddPress}
/>
)}
{userStatus !== "in_progress" && (
<Link.MenuAction
title={t`Mark as Watching`}
icon="play.fill"
onPress={() => titleActions.markWatching(id)}
/>
)}
{type === "movie" && (
<Link.MenuAction
title={t`Mark as Watched`}
@@ -228,6 +224,13 @@ export const PosterCard = memo(function PosterCard({
onPress={() => titleActions.markMovieWatched(id, title)}
/>
)}
{type === "tv" && userStatus && (
<Link.MenuAction
title={t`Mark All Watched`}
icon="checkmark.circle"
onPress={() => titleActions.markAllWatched(id, title)}
/>
)}
{userStatus && (
<Link.MenuAction
title={t`Remove from Library`}
@@ -57,8 +57,6 @@ export function useTitleActions(options?: UseTitleActionsOptions) {
onSuccess: (_data, input) => {
const statusMessages: Record<string, string> = {
watchlist: t`Added to watchlist`,
in_progress: t`Marked as watching`,
completed: t`Marked as completed`,
};
const defaultMsg = input.status
? (statusMessages[input.status] ?? t`Status updated`)
+14 -24
View File
@@ -32,30 +32,6 @@ export const titleActions = {
}
},
async markWatching(id: string) {
try {
await client.titles.updateStatus({ id, status: "in_progress" });
toast.success(i18n._(msg`Marked as watching`));
invalidateTitleQueries();
} catch {
toast.error(i18n._(msg`Failed to update status`));
}
},
async markCompleted(id: string, titleName?: string) {
try {
await client.titles.updateStatus({ id, status: "completed" });
toast.success(
titleName
? i18n._(msg`Marked "${titleName}" as completed`)
: i18n._(msg`Marked as completed`),
);
invalidateTitleQueries();
} catch {
toast.error(i18n._(msg`Failed to update status`));
}
},
async markMovieWatched(id: string, titleName?: string) {
try {
await client.titles.watchMovie({ id });
@@ -112,6 +88,20 @@ export const titleActions = {
}
},
async markAllWatched(id: string, titleName?: string) {
try {
await client.titles.watchAll({ id });
toast.success(
titleName
? i18n._(msg`Marked all episodes of "${titleName}" as watched`)
: i18n._(msg`Marked all episodes as watched`),
);
invalidateTitleQueries();
} catch {
toast.error(i18n._(msg`Failed to mark all episodes as watched`));
}
},
async watchSeason(id: string, seasonName?: string) {
try {
await client.seasons.watch({ id });
+6 -1
View File
@@ -6,6 +6,7 @@ import {
getWatchCount,
getWatchHistory,
} from "@sofa/core/discovery";
import { getDisplayStatusesByTitleIds } from "@sofa/core/tracking";
import { tmdbImageUrl } from "@sofa/tmdb/image";
import { os } from "../context";
@@ -48,6 +49,10 @@ export const library = os.dashboard.library.use(authed).handler(({ input, contex
totalPages,
totalResults,
} = getLibraryFeed(context.user.id, input.page, input.limit);
const titleIds = feed.map((t) => t.titleId);
const displayStatuses = getDisplayStatusesByTitleIds(context.user.id, titleIds);
const items = feed.map((t) => ({
id: t.titleId,
tmdbId: t.tmdbId,
@@ -58,7 +63,7 @@ export const library = os.dashboard.library.use(authed).handler(({ input, contex
releaseDate: t.releaseDate ?? null,
firstAirDate: t.firstAirDate ?? null,
voteAverage: t.voteAverage,
userStatus: t.userStatus,
userStatus: displayStatuses[t.titleId] ?? null,
}));
return { items, page, totalPages, totalResults };
});
+2 -2
View File
@@ -2,7 +2,7 @@ import { ORPCError } from "@orpc/server";
import { AppErrorCode } from "@sofa/api/errors";
import { ensureBrowseTitlesExist } from "@sofa/core/metadata";
import { getEpisodeProgressByTitleIds, getUserStatusesByTitleIds } from "@sofa/core/tracking";
import { getEpisodeProgressByTitleIds, getDisplayStatusesByTitleIds } from "@sofa/core/tracking";
import { discover as discoverTmdb } from "@sofa/tmdb/client";
import { isTmdbConfigured } from "@sofa/tmdb/config";
import { tmdbImageUrl } from "@sofa/tmdb/image";
@@ -61,7 +61,7 @@ export const discover = os.discover.use(authed).handler(async ({ input, context
const [userStatuses, episodeProgress] =
titleIds.length > 0
? [
getUserStatusesByTitleIds(context.user.id, titleIds),
getDisplayStatusesByTitleIds(context.user.id, titleIds),
getEpisodeProgressByTitleIds(context.user.id, titleIds),
]
: [{}, {}];
+3 -3
View File
@@ -2,7 +2,7 @@ import { ORPCError } from "@orpc/server";
import { AppErrorCode } from "@sofa/api/errors";
import { ensureBrowseTitlesExist } from "@sofa/core/metadata";
import { getEpisodeProgressByTitleIds, getUserStatusesByTitleIds } from "@sofa/core/tracking";
import { getEpisodeProgressByTitleIds, getDisplayStatusesByTitleIds } from "@sofa/core/tracking";
import { getGenres, getPopular, getTrending } from "@sofa/tmdb/client";
import { isTmdbConfigured } from "@sofa/tmdb/config";
import { tmdbImageUrl } from "@sofa/tmdb/image";
@@ -90,7 +90,7 @@ export const trending = os.explore.trending.use(authed).handler(async ({ input,
const [userStatuses, episodeProgress] =
titleIds.length > 0
? [
getUserStatusesByTitleIds(context.user.id, titleIds),
getDisplayStatusesByTitleIds(context.user.id, titleIds),
getEpisodeProgressByTitleIds(context.user.id, titleIds),
]
: [{}, {}];
@@ -136,7 +136,7 @@ export const popular = os.explore.popular.use(authed).handler(async ({ input, co
const [userStatuses, episodeProgress] =
titleIds.length > 0
? [
getUserStatusesByTitleIds(context.user.id, titleIds),
getDisplayStatusesByTitleIds(context.user.id, titleIds),
getEpisodeProgressByTitleIds(context.user.id, titleIds),
]
: [{}, {}];
+2 -2
View File
@@ -2,7 +2,7 @@ import { ORPCError } from "@orpc/server";
import { AppErrorCode } from "@sofa/api/errors";
import { fetchFullFilmography, getOrFetchPerson } from "@sofa/core/person";
import { getUserStatusesByTitleIds } from "@sofa/core/tracking";
import { getDisplayStatusesByTitleIds } from "@sofa/core/tracking";
import { os } from "../context";
import { authed } from "../middleware";
@@ -20,7 +20,7 @@ export const detail = os.people.detail.use(authed).handler(async ({ input, conte
const start = (input.page - 1) * input.limit;
const pageCredits = allCredits.slice(start, start + input.limit);
const userStatuses = getUserStatusesByTitleIds(
const userStatuses = getDisplayStatusesByTitleIds(
context.user.id,
pageCredits.map((c) => c.titleId),
);
+8 -3
View File
@@ -4,7 +4,7 @@ import { AppErrorCode } from "@sofa/api/errors";
import { getRecommendationsForTitle } from "@sofa/core/discovery";
import { getOrFetchTitle, getOrFetchTitleByTmdbId } from "@sofa/core/metadata";
import {
getUserStatusesByTitleIds,
getDisplayStatusesByTitleIds,
getUserTitleInfo,
logMovieWatch,
markAllEpisodesWatched,
@@ -48,14 +48,19 @@ export const watchAll = os.titles.watchAll.use(authed).handler(({ input, context
});
export const userInfo = os.titles.userInfo.use(authed).handler(({ input, context }) => {
return getUserTitleInfo(context.user.id, input.id);
const info = getUserTitleInfo(context.user.id, input.id);
if (!info.status) return { ...info, status: null };
// Convert stored status to display status
const displayStatuses = getDisplayStatusesByTitleIds(context.user.id, [input.id]);
return { ...info, status: displayStatuses[input.id] ?? null };
});
export const recommendations = os.titles.recommendations
.use(authed)
.handler(({ input, context }) => {
const recs = getRecommendationsForTitle(input.id);
const userStatuses = getUserStatusesByTitleIds(
const userStatuses = getDisplayStatusesByTitleIds(
context.user.id,
recs.map((r) => r.id),
);
@@ -10,7 +10,7 @@ interface TitleGridItem {
releaseDate?: string | null;
firstAirDate?: string | null;
voteAverage?: number | null;
userStatus?: "watchlist" | "in_progress" | "completed" | null;
userStatus?: "in_watchlist" | "watching" | "caught_up" | "completed" | null;
}
export function TitleGridSectionSkeleton() {
@@ -24,7 +24,7 @@ interface TitleRowItem {
voteAverage: number | null;
}
type TitleStatus = "watchlist" | "in_progress" | "completed";
type TitleStatus = "in_watchlist" | "watching" | "caught_up" | "completed";
interface FilterableTitleRowProps {
heading: string;
@@ -19,7 +19,7 @@ interface TitleRowProps {
heading: string;
icon: React.ReactNode;
items: TitleRowItem[];
userStatuses?: Record<string, "watchlist" | "in_progress" | "completed">;
userStatuses?: Record<string, "in_watchlist" | "watching" | "caught_up" | "completed">;
episodeProgress?: Record<string, { watched: number; total: number }>;
onEndReached?: () => void;
hasNextPage?: boolean;
@@ -18,7 +18,7 @@ type Sort = "newest" | "rating";
interface FilmographyGridProps {
credits: PersonCredit[];
userStatuses?: Record<string, "watchlist" | "in_progress" | "completed">;
userStatuses?: Record<string, "in_watchlist" | "watching" | "caught_up" | "completed">;
}
export function FilmographyGrid({ credits, userStatuses }: FilmographyGridProps) {
@@ -53,7 +53,7 @@ export function PersonDetailClient({ id }: { id: string }) {
() =>
Object.assign({}, ...(data?.pages.map((p) => p.userStatuses) ?? [])) as Record<
string,
"watchlist" | "in_progress" | "completed"
"in_watchlist" | "watching" | "caught_up" | "completed"
>,
[data?.pages],
);
+9 -4
View File
@@ -32,7 +32,7 @@ export function TitleCardSkeleton() {
);
}
type TitleStatus = "watchlist" | "in_progress" | "completed";
type TitleStatus = "in_watchlist" | "watching" | "caught_up" | "completed";
interface TiltStyles {
imageStyle: MotionStyle;
@@ -59,16 +59,21 @@ export interface TitleCardProps extends CardInnerProps {
function useStatusConfig() {
const { t } = useLingui();
return {
watchlist: {
in_watchlist: {
icon: IconBookmarkFilled,
label: t`On Watchlist`,
badgeClass: "bg-status-watching/90 text-white",
},
in_progress: {
watching: {
icon: IconPlayerPlayFilled,
label: t`Watching`,
badgeClass: "bg-status-watching/90 text-white",
},
caught_up: {
icon: IconCircleCheckFilled,
label: t`Caught Up`,
badgeClass: "bg-status-watching/90 text-white",
},
completed: {
icon: IconCircleCheckFilled,
label: t`Completed`,
@@ -91,7 +96,7 @@ function QuickAddButton({ id, userStatus }: { id: string; userStatus?: TitleStat
const quickAddMutation = useMutation(
orpc.titles.quickAdd.mutationOptions({
onSuccess: () => setAddedStatus("watchlist"),
onSuccess: () => setAddedStatus("in_watchlist"),
}),
);
+121 -58
View File
@@ -1,6 +1,24 @@
import { useLingui } from "@lingui/react/macro";
import { IconCheck, IconPlayerPlayFilled, IconPlus, IconX } from "@tabler/icons-react";
import { Trans, useLingui } from "@lingui/react/macro";
import {
IconBookmarkFilled,
IconCheck,
IconPlayerPlayFilled,
IconPlus,
IconX,
} from "@tabler/icons-react";
import { AnimatePresence, motion } from "motion/react";
import { useState } from "react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
interface StatusButtonProps {
currentStatus: string | null;
@@ -9,75 +27,120 @@ interface StatusButtonProps {
export function StatusButton({ currentStatus, onChange }: StatusButtonProps) {
const { t } = useLingui();
const [confirmOpen, setConfirmOpen] = useState(false);
const watchingStyle = {
label: t`Watching`,
icon: IconPlayerPlayFilled,
class: "text-status-watching",
bgClass: "bg-status-watching/10 hover:bg-status-watching/15",
borderClass: "ring-status-watching/20",
const completedStyle = {
class: "text-status-completed",
bgClass: "bg-status-completed/10 hover:bg-status-completed/15",
borderClass: "ring-status-completed/20",
};
const statusConfig = {
watchlist: watchingStyle,
in_progress: watchingStyle,
in_watchlist: {
label: t`In Watchlist`,
icon: IconBookmarkFilled,
class: "text-primary",
bgClass: "bg-primary/10 hover:bg-primary/15",
borderClass: "ring-primary/20",
},
watching: {
label: t`Watching`,
icon: IconPlayerPlayFilled,
class: "text-status-watching",
bgClass: "bg-status-watching/10 hover:bg-status-watching/15",
borderClass: "ring-status-watching/20",
},
caught_up: {
label: t`Caught Up`,
icon: IconCheck,
...completedStyle,
},
completed: {
label: t`Completed`,
icon: IconCheck,
class: "text-status-completed",
bgClass: "bg-status-completed/10 hover:bg-status-completed/15",
borderClass: "ring-status-completed/20",
...completedStyle,
},
} as const;
const config = statusConfig[currentStatus as keyof typeof statusConfig] ?? null;
return (
<AnimatePresence mode="wait" initial={false}>
{!config ? (
<motion.button
key="add"
type="button"
onClick={() => onChange("watchlist")}
initial={{ opacity: 0, y: 4 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -4 }}
transition={{ duration: 0.15 }}
className="bg-primary/10 text-primary ring-primary/20 hover:bg-primary/15 hover:ring-primary/30 inline-flex h-9 items-center gap-2 rounded-lg px-4 text-sm font-medium ring-1 transition-all active:scale-[0.97]"
>
<IconPlus aria-hidden={true} className="size-3.5" strokeWidth={2.5} />
{t`Watchlist`}
</motion.button>
) : (
<motion.button
key="status"
type="button"
onClick={() => onChange(null)}
initial={{ opacity: 0, y: 4 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -4 }}
transition={{ duration: 0.15 }}
title={t`Remove from library`}
className={`group inline-flex h-9 items-center gap-2 rounded-lg px-4 text-sm font-medium ring-1 transition-all active:scale-[0.97] ${config.class} ${config.bgClass} ${config.borderClass} hover:!bg-destructive/10 hover:!text-destructive hover:!ring-destructive/30`}
>
<span className="grid [&>svg]:col-start-1 [&>svg]:row-start-1">
<config.icon
aria-hidden={true}
className="size-3.5 transition-opacity group-hover:opacity-0"
/>
<IconX
aria-hidden={true}
className="text-destructive size-3.5 opacity-0 transition-opacity group-hover:opacity-100"
/>
</span>
<span className="grid [&>span]:col-start-1 [&>span]:row-start-1">
<span className="transition-opacity group-hover:opacity-0">{config.label}</span>
<span className="opacity-0 transition-opacity group-hover:opacity-100">
{t`Remove`}
<>
<AnimatePresence mode="wait" initial={false}>
{!config ? (
<motion.button
key="add"
type="button"
onClick={() => onChange("watchlist")}
initial={{ opacity: 0, y: 4 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -4 }}
transition={{ duration: 0.15 }}
className="bg-primary/10 text-primary ring-primary/20 hover:bg-primary/15 hover:ring-primary/30 inline-flex h-9 items-center gap-2 rounded-lg px-4 text-sm font-medium ring-1 transition-all active:scale-[0.97]"
>
<IconPlus aria-hidden={true} className="size-3.5" strokeWidth={2.5} />
{t`Watchlist`}
</motion.button>
) : (
<motion.button
key="status"
type="button"
onClick={() => setConfirmOpen(true)}
initial={{ opacity: 0, y: 4 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -4 }}
transition={{ duration: 0.15 }}
title={t`Remove from library`}
className={`group inline-flex h-9 items-center gap-2 rounded-lg px-4 text-sm font-medium ring-1 transition-all active:scale-[0.97] ${config.class} ${config.bgClass} ${config.borderClass} hover:!bg-destructive/10 hover:!text-destructive hover:!ring-destructive/30`}
>
<span className="grid [&>svg]:col-start-1 [&>svg]:row-start-1">
<config.icon
aria-hidden={true}
className="size-3.5 transition-opacity group-hover:opacity-0"
/>
<IconX
aria-hidden={true}
className="text-destructive size-3.5 opacity-0 transition-opacity group-hover:opacity-100"
/>
</span>
</span>
</motion.button>
)}
</AnimatePresence>
<span className="grid [&>span]:col-start-1 [&>span]:row-start-1">
<span className="transition-opacity group-hover:opacity-0">{config.label}</span>
<span className="opacity-0 transition-opacity group-hover:opacity-100">
{t`Remove`}
</span>
</span>
</motion.button>
)}
</AnimatePresence>
<AlertDialog open={confirmOpen} onOpenChange={setConfirmOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
<Trans>Remove from library?</Trans>
</AlertDialogTitle>
<AlertDialogDescription>
<Trans>
This title will be removed from your library. Your watch history and ratings will be
kept.
</Trans>
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>
<Trans>Cancel</Trans>
</AlertDialogCancel>
<AlertDialogAction
onClick={() => {
onChange(null);
setConfirmOpen(false);
}}
>
<Trans>Remove</Trans>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
}
@@ -10,7 +10,7 @@ import type { Season } from "@sofa/api/schemas";
import { useTitleContext } from "./title-context";
type UserInfo = {
status: "watchlist" | "in_progress" | "completed" | null;
status: "in_watchlist" | "watching" | "caught_up" | "completed" | null;
rating: number | null;
episodeWatches: string[];
};
@@ -57,17 +57,14 @@ export function useTitleActions() {
for (const id of episodeIds) newWatchSet.add(id);
const newWatches = [...newWatchSet];
const allEpIds = seasons.flatMap((s) => s.episodes.map((ep) => ep.id));
const allWatched = allEpIds.every((id) => newWatchSet.has(id));
setUserInfo((old) => ({
...old,
episodeWatches: newWatches,
status: allWatched ? "completed" : old.status,
}));
try {
await batchWatchMutation.mutateAsync({ episodeIds });
await queryClient.invalidateQueries({ queryKey: userInfoKey });
toast.success(
t`Caught up — marked ${episodeIds.length} ${plural(episodeIds.length, { one: "episode", other: "episodes" })} as watched`,
);
@@ -80,7 +77,7 @@ export function useTitleActions() {
toast.error(t`Failed to catch up`);
}
},
[getUserInfo, setUserInfo, seasons, batchWatchMutation, t],
[getUserInfo, setUserInfo, batchWatchMutation, queryClient, userInfoKey, t],
);
const handleStatusChange = useCallback(
@@ -88,12 +85,12 @@ export function useTitleActions() {
const prevStatus = getUserInfo().status;
setUserInfo((old) => ({
...old,
status: status === "watchlist" ? "in_progress" : (status as UserInfo["status"]),
status: status ? "in_watchlist" : null,
}));
try {
await updateStatusMutation.mutateAsync({
id: titleId,
status: status ? "in_progress" : null,
status: status ? "watchlist" : null,
});
toast.success(status ? t`Added to watchlist` : t`Removed from library`);
} catch {
@@ -148,7 +145,8 @@ export function useTitleActions() {
setUserInfo((old) => ({
...old,
episodeWatches: old.episodeWatches.filter((id) => id !== episodeId),
status: old.status === "completed" ? "in_progress" : old.status,
status:
old.status === "completed" || old.status === "caught_up" ? "watching" : old.status,
}));
try {
@@ -173,7 +171,7 @@ export function useTitleActions() {
setUserInfo((old) => ({
...old,
episodeWatches: newWatches,
status: old.status === null || old.status === "watchlist" ? "in_progress" : old.status,
status: old.status === null || old.status === "in_watchlist" ? "watching" : old.status,
}));
try {
@@ -243,21 +241,15 @@ export function useTitleActions() {
for (const ep of unwatched) newWatchSet.add(ep.id);
const newWatches = [...newWatchSet];
const allEpIds = seasons.flatMap((s) => s.episodes.map((ep) => ep.id));
const allWatched = allEpIds.every((id) => newWatchSet.has(id));
setUserInfo((old) => ({
...old,
episodeWatches: newWatches,
status: allWatched
? "completed"
: old.status === null || old.status === "watchlist"
? "in_progress"
: old.status,
status: old.status === null || old.status === "in_watchlist" ? "watching" : old.status,
}));
try {
await watchSeasonMutation.mutateAsync({ id: season.id });
await queryClient.invalidateQueries({ queryKey: userInfoKey });
const currentWatchSet = new Set(getUserInfo().episodeWatches);
const previousUnwatched: string[] = [];
@@ -294,7 +286,7 @@ export function useTitleActions() {
toast.error(t`Failed to mark some episodes`);
}
},
[getUserInfo, setUserInfo, seasons, catchUp, watchSeasonMutation, t],
[getUserInfo, setUserInfo, seasons, catchUp, watchSeasonMutation, queryClient, userInfoKey, t],
);
const handleUnmarkSeason = useCallback(
@@ -305,7 +297,7 @@ export function useTitleActions() {
setUserInfo((old) => ({
...old,
episodeWatches: old.episodeWatches.filter((id) => !seasonEpIds.has(id)),
status: old.status === "completed" ? "in_progress" : old.status,
status: old.status === "completed" || old.status === "caught_up" ? "watching" : old.status,
}));
try {
@@ -330,10 +322,12 @@ export function useTitleActions() {
setUserInfo((old) => ({
...old,
episodeWatches: allEpIds,
status: "completed",
status: old.status ?? "watching",
}));
try {
await watchAllMutation.mutateAsync({ id: titleId });
// Refresh to get server-derived display status (caught_up / completed)
await queryClient.invalidateQueries({ queryKey: userInfoKey });
toast.success(t`Marked all episodes as watched`);
} catch {
setUserInfo((old) => ({
@@ -343,7 +337,7 @@ export function useTitleActions() {
}));
toast.error(t`Failed to mark all episodes as watched`);
}
}, [getUserInfo, setUserInfo, seasons, titleId, watchAllMutation, t]);
}, [getUserInfo, setUserInfo, seasons, titleId, watchAllMutation, queryClient, userInfoKey, t]);
return {
handleStatusChange,
+2 -1
View File
@@ -7,7 +7,8 @@
"./contract": "./src/contract.ts",
"./schemas": "./src/schemas.ts",
"./errors": "./src/errors.ts",
"./utils": "./src/utils.ts"
"./utils": "./src/utils.ts",
"./display-status": "./src/display-status.ts"
},
"scripts": {
"lint": "oxlint",
+32
View File
@@ -0,0 +1,32 @@
export type StoredStatus = "watchlist" | "in_progress" | "completed";
export type DisplayStatus = "in_watchlist" | "watching" | "caught_up" | "completed";
export const ONGOING_TMDB_STATUSES = ["Returning Series", "In Production"];
/**
* Derive the user-facing display status from stored status + context.
*
* Movies: watchlist → in_watchlist, completed → completed
* TV: watchlist → in_watchlist, in_progress → watching | caught_up | completed
*/
export function getDisplayStatus(
storedStatus: StoredStatus,
titleType: "movie" | "tv",
tmdbStatus: string | null,
episodeProgress: { watched: number; total: number } | null,
): DisplayStatus {
if (storedStatus === "watchlist") return "in_watchlist";
if (titleType === "movie") return storedStatus === "completed" ? "completed" : "in_watchlist";
// TV with in_progress: derive from episode progress + TMDB show status
if (
episodeProgress &&
episodeProgress.total > 0 &&
episodeProgress.watched >= episodeProgress.total
) {
return ONGOING_TMDB_STATUSES.includes(tmdbStatus ?? "") ? "caught_up" : "completed";
}
return "watching";
}
+10 -12
View File
@@ -50,13 +50,13 @@ export const UpdateStatusInput = z
.object({
id: z.string().min(1).describe("Title ID"),
status: z
.enum(["in_progress", "completed"])
.enum(["watchlist"])
.nullable()
.describe(
"Tracking status: in_progress (currently watching), completed (finished), or null to remove from library",
"Set to watchlist to add to library, or null to remove. Other transitions happen via watch endpoints.",
),
})
.meta({ description: "Update the user's tracking status for a title" });
.meta({ description: "Add a title to the user's watchlist or remove from library" });
export const UpdateRatingInput = z
.object({
@@ -391,9 +391,11 @@ export const RecommendationItemSchema = z
})
.meta({ description: "A recommended title" });
const displayStatusEnum = z.enum(["in_watchlist", "watching", "caught_up", "completed"]);
const userStatusMap = z
.record(z.string(), z.enum(["watchlist", "in_progress", "completed"]))
.describe("Map of title ID to the user's tracking status");
.record(z.string(), displayStatusEnum)
.describe("Map of title ID to the user's display status");
const episodeProgressMap = z
.record(z.string(), z.object({ watched: z.number(), total: z.number() }))
.describe("Map of title ID to episode watch progress");
@@ -425,10 +427,9 @@ export const TitleDetailOutput = z
export const UserInfoOutput = z
.object({
status: z
.enum(["watchlist", "in_progress", "completed"])
status: displayStatusEnum
.nullable()
.describe("User's tracking status, or null if not in library"),
.describe("User's display status, or null if not in library"),
rating: z.number().nullable().describe("User's star rating (0-5), or null if unrated"),
episodeWatches: z.array(z.string()).describe("IDs of episodes the user has watched"),
})
@@ -523,10 +524,7 @@ export const LibraryOutput = z
releaseDate: z.string().nullable().describe("Release date (ISO 8601)"),
firstAirDate: z.string().nullable().describe("First air date (ISO 8601)"),
voteAverage: z.number().nullable().describe("Average rating (0-10)"),
userStatus: z
.enum(["watchlist", "in_progress", "completed"])
.nullable()
.describe("User's tracking status"),
userStatus: displayStatusEnum.nullable().describe("User's display status"),
})
.meta({ description: "A library item with user status" }),
),
+2 -2
View File
@@ -1,6 +1,6 @@
import {
getAllTrackedTitleIds,
getCompletedTitleIds,
getEngagedTitleIds,
getEpisodesBySeasonIds,
getEpisodeWatchCountSince,
getEpisodeWatchesByEpisodeIds,
@@ -299,7 +299,7 @@ export { getLibraryFeed } from "@sofa/db/queries/discovery";
export function getRecommendationsFeed(userId: string) {
// Get recommendations from user's highly-rated or completed titles
const userCompletedOrRated = getCompletedTitleIds(userId);
const userCompletedOrRated = getEngagedTitleIds(userId);
const ratedIds = getHighlyRatedTitleIds(userId);
+5 -1
View File
@@ -48,7 +48,11 @@ export async function getSonarrList(
userId: string,
statuses: Status[] = ["watchlist"],
): Promise<{ TvdbId: number; Title: string }[]> {
const rows = getSonarrShows(userId, statuses);
// TV never stores 'completed' — map it to 'in_progress' (completion is derived)
const mappedStatuses = [
...new Set(statuses.map((s) => (s === "completed" ? "in_progress" : s))),
] as Status[];
const rows = getSonarrShows(userId, mappedStatuses);
// Resolve missing TVDB IDs in parallel instead of sequentially
const needsResolution = rows.filter((r) => r.tvdbId == null);
+59 -25
View File
@@ -1,3 +1,6 @@
import type { DisplayStatus } from "@sofa/api/display-status";
import { getDisplayStatus } from "@sofa/api/display-status";
import { getTitlesByIds } from "@sofa/db/queries/discovery";
import { getTitleById } from "@sofa/db/queries/title";
import {
batchInsertEpisodeWatchesTransaction,
@@ -64,19 +67,16 @@ export function logEpisodeWatch(
const now = watchedAt ?? new Date();
insertEpisodeWatch(userId, episodeId, now, source);
// Find the title for this episode (single JOIN instead of 2 queries)
// Find the title for this episode
const titleId = getEpisodeTitleId(episodeId);
if (!titleId) return;
// Auto-set status to in_progress if not set
// Auto-set status to in_progress if not set or still on watchlist
const existing = getTitleStatus(userId, titleId);
if (!existing || existing.status === "watchlist") {
setTitleStatus(userId, titleId, "in_progress", source);
}
// Check if all episodes are watched -> auto-complete
checkAllEpisodesWatched(userId, titleId);
}
export function logEpisodeWatchBatch(
@@ -104,33 +104,24 @@ export function markAllEpisodesWatched(
batchInsertMissingEpisodeWatches(userId, epIds, existingWatches, source, now);
setTitleStatus(userId, titleId, "completed", source);
}
function checkAllEpisodesWatched(userId: string, titleId: string) {
const epIds = getAllEpisodeIdsForTitle(titleId);
const totalEpisodes = epIds.length;
if (totalEpisodes === 0) return;
const watchCount = countDistinctEpisodeWatches(userId, epIds);
if (watchCount >= totalEpisodes) {
setTitleStatus(userId, titleId, "completed");
}
// TV never stores 'completed' — set in_progress and let display status derive the rest
setTitleStatus(userId, titleId, "in_progress", source);
}
export function unwatchEpisode(userId: string, episodeId: string) {
deleteEpisodeWatch(userId, episodeId);
// Find parent title and downgrade from completed to in_progress
const titleId = getEpisodeTitleId(episodeId);
if (!titleId) return;
const existing = getTitleStatus(userId, titleId);
if (!existing || existing.status !== "in_progress") return;
if (existing?.status === "completed") {
setTitleStatus(userId, titleId, "in_progress");
// If no episodes remain watched, downgrade to watchlist
const epIds = getAllEpisodeIdsForTitle(titleId);
const watchCount = countDistinctEpisodeWatches(userId, epIds);
if (watchCount === 0) {
setTitleStatus(userId, titleId, "watchlist");
}
}
@@ -142,14 +133,17 @@ export function unwatchSeason(userId: string, seasonId: string) {
deleteEpisodeWatches(userId, epIds);
}
// Find parent title and downgrade from completed to in_progress
const season = getSeasonById(seasonId);
if (!season) return;
const existing = getTitleStatus(userId, season.titleId);
if (!existing || existing.status !== "in_progress") return;
if (existing?.status === "completed") {
setTitleStatus(userId, season.titleId, "in_progress");
// If no episodes remain watched, downgrade to watchlist
const allEpIds = getAllEpisodeIdsForTitle(season.titleId);
const watchCount = countDistinctEpisodeWatches(userId, allEpIds);
if (watchCount === 0) {
setTitleStatus(userId, season.titleId, "watchlist");
}
}
@@ -182,6 +176,46 @@ export function getUserStatusesByTitleIds(
return result;
}
/**
* Derive display statuses for a set of titles.
* Resolves stored status + episode progress + TMDB show status into display status.
*/
export function getDisplayStatusesByTitleIds(
userId: string,
titleIds: string[],
): Record<string, DisplayStatus> {
if (titleIds.length === 0) return {};
const storedStatuses = getUserStatusesByTitleIds(userId, titleIds);
const statusEntries = Object.entries(storedStatuses);
if (statusEntries.length === 0) return {};
// Find TV titles with in_progress status that need episode progress resolution
const tvInProgressIds = statusEntries
.filter(([, status]) => status === "in_progress")
.map(([id]) => id);
// Fetch title data for type + TMDB status
const trackedIds = statusEntries.map(([id]) => id);
const titles = getTitlesByIds(trackedIds);
const titleMap = new Map(titles.map((t) => [t.id, t]));
// Fetch episode progress for TV in_progress titles
const episodeProgress =
tvInProgressIds.length > 0 ? getEpisodeProgressByTitleIds(userId, tvInProgressIds) : {};
const result: Record<string, DisplayStatus> = {};
for (const [titleId, storedStatus] of statusEntries) {
const title = titleMap.get(titleId);
const titleType = (title?.type ?? "movie") as "movie" | "tv";
const tmdbStatus = title?.status ?? null;
const progress = episodeProgress[titleId] ?? null;
result[titleId] = getDisplayStatus(storedStatus, titleType, tmdbStatus, progress);
}
return result;
}
export function getEpisodeProgressByTitleIds(
userId: string,
titleIds: string[],
+2 -1
View File
@@ -193,11 +193,12 @@ describe("getSonarrList", () => {
title: "Show B",
});
insertStatus("user-1", "tv1", "watchlist");
insertStatus("user-1", "tv2", "completed");
insertStatus("user-1", "tv2", "in_progress");
const watchlist = await getSonarrList("user-1", ["watchlist"]);
expect(watchlist).toEqual([{ TvdbId: 111, Title: "Show A" }]);
// 'completed' maps to 'in_progress' for TV (completion is derived)
const all = await getSonarrList("user-1", ["watchlist", "completed"]);
expect(all).toHaveLength(2);
});
+46 -28
View File
@@ -235,7 +235,7 @@ describe("logEpisodeWatch", () => {
expect(row?.status).toBe("completed");
});
test("auto-completes when all episodes are watched", () => {
test("stays in_progress when all episodes are watched", () => {
insertUser();
const { titleId, episodeIds } = insertTvShow("tv-1", 99999, 1, 3);
@@ -248,7 +248,7 @@ describe("logEpisodeWatch", () => {
.from(userTitleStatus)
.where(and(eq(userTitleStatus.userId, "user-1"), eq(userTitleStatus.titleId, titleId)))
.get();
expect(row?.status).toBe("completed");
expect(row?.status).toBe("in_progress");
});
});
@@ -281,7 +281,7 @@ describe("logEpisodeWatchBatch", () => {
expect(row?.status).toBe("in_progress");
});
test("auto-completes if batch covers all episodes", () => {
test("stays in_progress if batch covers all episodes", () => {
insertUser();
const { titleId, episodeIds } = insertTvShow("tv-1", 99999, 1, 3);
logEpisodeWatchBatch("user-1", episodeIds);
@@ -291,7 +291,7 @@ describe("logEpisodeWatchBatch", () => {
.from(userTitleStatus)
.where(and(eq(userTitleStatus.userId, "user-1"), eq(userTitleStatus.titleId, titleId)))
.get();
expect(row?.status).toBe("completed");
expect(row?.status).toBe("in_progress");
});
test("no-op for empty array", () => {
@@ -310,7 +310,7 @@ describe("logEpisodeWatchBatch", () => {
// ── markAllEpisodesWatched ──────────────────────────────────────────
describe("markAllEpisodesWatched", () => {
test("marks all episodes as watched and sets completed", () => {
test("marks all episodes as watched and sets in_progress", () => {
insertUser();
const { titleId, episodeIds } = insertTvShow("tv-1", 99999, 1, 3);
markAllEpisodesWatched("user-1", titleId);
@@ -327,7 +327,7 @@ describe("markAllEpisodesWatched", () => {
.from(userTitleStatus)
.where(and(eq(userTitleStatus.userId, "user-1"), eq(userTitleStatus.titleId, titleId)))
.get();
expect(row?.status).toBe("completed");
expect(row?.status).toBe("in_progress");
});
test("skips already-watched episodes (no duplicates)", () => {
@@ -379,23 +379,15 @@ describe("unwatchEpisode", () => {
expect(watches).toHaveLength(0);
});
test("downgrades completed to in_progress", () => {
test("keeps in_progress when some episodes remain watched", () => {
insertUser();
const { titleId, episodeIds } = insertTvShow("tv-1", 99999, 1, 3);
markAllEpisodesWatched("user-1", titleId);
// Verify completed first
let row = testDb
.select()
.from(userTitleStatus)
.where(and(eq(userTitleStatus.userId, "user-1"), eq(userTitleStatus.titleId, titleId)))
.get();
expect(row?.status).toBe("completed");
// Unwatch one episode
// Unwatch one episode — still has 2 watched
unwatchEpisode("user-1", episodeIds[0]);
row = testDb
const row = testDb
.select()
.from(userTitleStatus)
.where(and(eq(userTitleStatus.userId, "user-1"), eq(userTitleStatus.titleId, titleId)))
@@ -403,7 +395,23 @@ describe("unwatchEpisode", () => {
expect(row?.status).toBe("in_progress");
});
test("doesn't change in_progress status", () => {
test("downgrades to watchlist when all episodes unwatched", () => {
insertUser();
const { titleId, episodeIds } = insertTvShow("tv-1", 99999, 1, 3);
// Watch one episode then unwatch it
logEpisodeWatch("user-1", episodeIds[0]);
unwatchEpisode("user-1", episodeIds[0]);
const row = testDb
.select()
.from(userTitleStatus)
.where(and(eq(userTitleStatus.userId, "user-1"), eq(userTitleStatus.titleId, titleId)))
.get();
expect(row?.status).toBe("watchlist");
});
test("doesn't change in_progress status when episodes remain", () => {
insertUser();
const { titleId, episodeIds } = insertTvShow("tv-1", 99999, 1, 3);
logEpisodeWatch("user-1", episodeIds[0]);
@@ -448,30 +456,40 @@ describe("unwatchSeason", () => {
expect(watches).toHaveLength(0);
});
test("downgrades completed to in_progress", () => {
test("keeps in_progress when other seasons have watches", () => {
insertUser();
const { titleId } = insertTvShow("tv-1", 99999, 2, 2);
// Watch all episodes across both seasons
markAllEpisodesWatched("user-1", titleId);
let row = testDb
.select()
.from(userTitleStatus)
.where(and(eq(userTitleStatus.userId, "user-1"), eq(userTitleStatus.titleId, titleId)))
.get();
expect(row?.status).toBe("completed");
// Unwatch season 1
// Unwatch season 1 — season 2 still has watches
unwatchSeason("user-1", "tv-1-s1");
row = testDb
const row = testDb
.select()
.from(userTitleStatus)
.where(and(eq(userTitleStatus.userId, "user-1"), eq(userTitleStatus.titleId, titleId)))
.get();
expect(row?.status).toBe("in_progress");
});
test("downgrades to watchlist when all episodes unwatched", () => {
insertUser();
const { titleId } = insertTvShow("tv-1", 99999, 1, 2);
markAllEpisodesWatched("user-1", titleId);
// Unwatch the only season — no episodes remain
unwatchSeason("user-1", "tv-1-s1");
const row = testDb
.select()
.from(userTitleStatus)
.where(and(eq(userTitleStatus.userId, "user-1"), eq(userTitleStatus.titleId, titleId)))
.get();
expect(row?.status).toBe("watchlist");
});
});
// ── rateTitleStars ──────────────────────────────────────────────────
@@ -0,0 +1,12 @@
-- TV shows should never have 'completed' stored — convert to 'in_progress'.
-- Display status (caught_up / completed) is now derived at read time from
-- episode progress + TMDB show status.
UPDATE userTitleStatus SET status = 'in_progress'
WHERE status = 'completed'
AND titleId IN (SELECT id FROM titles WHERE type = 'tv');
--> statement-breakpoint
-- Legacy movie rows stored as 'in_progress' (old UI always sent in_progress
-- when clicking Watchlist). Convert to 'watchlist' since no watch was logged.
UPDATE userTitleStatus SET status = 'watchlist'
WHERE status = 'in_progress'
AND titleId IN (SELECT id FROM titles WHERE type = 'movie');
File diff suppressed because it is too large Load Diff
+44 -4
View File
@@ -74,12 +74,47 @@ export function getUserStatusCounts(userId: string) {
const [row] = db
.select({
librarySize: sql<number>`count(*)`,
completed: sql<number>`sum(case when ${userTitleStatus.status} = 'completed' then 1 else 0 end)`,
movieCompleted: sql<number>`sum(case when ${userTitleStatus.status} = 'completed' then 1 else 0 end)`,
})
.from(userTitleStatus)
.where(eq(userTitleStatus.userId, userId))
.all();
return row;
// Count TV shows where all aired episodes are watched (caught_up + completed display states)
const today = new Date().toISOString().slice(0, 10);
const [tvRow] = db
.select({ count: sql<number>`count(*)` })
.from(userTitleStatus)
.innerJoin(titles, eq(titles.id, userTitleStatus.titleId))
.where(
and(
eq(userTitleStatus.userId, userId),
eq(userTitleStatus.status, "in_progress"),
eq(titles.type, "tv"),
sql`(
SELECT count(distinct e.id) FROM episodes e
INNER JOIN seasons s ON e.seasonId = s.id
WHERE s.titleId = ${titles.id} AND e.airDate IS NOT NULL AND e.airDate <= ${today}
) > 0`,
sql`(
SELECT count(distinct e.id) FROM episodes e
INNER JOIN seasons s ON e.seasonId = s.id
WHERE s.titleId = ${titles.id} AND e.airDate IS NOT NULL AND e.airDate <= ${today}
) = (
SELECT count(distinct ew.episodeId) FROM userEpisodeWatches ew
INNER JOIN episodes e2 ON ew.episodeId = e2.id
INNER JOIN seasons s2 ON e2.seasonId = s2.id
WHERE s2.titleId = ${titles.id} AND ew.userId = ${userTitleStatus.userId}
AND e2.airDate IS NOT NULL AND e2.airDate <= ${today}
)`,
),
)
.all();
return {
librarySize: row?.librarySize ?? 0,
completed: (row?.movieCompleted ?? 0) + (tvRow?.count ?? 0),
};
}
export function getInProgressTitleIds(userId: string) {
@@ -212,11 +247,16 @@ export function getLibraryFeed(userId: string, page = 1, limit = 20) {
};
}
export function getCompletedTitleIds(userId: string) {
export function getEngagedTitleIds(userId: string) {
return db
.select({ titleId: userTitleStatus.titleId })
.from(userTitleStatus)
.where(and(eq(userTitleStatus.userId, userId), eq(userTitleStatus.status, "completed")))
.where(
and(
eq(userTitleStatus.userId, userId),
sql`${userTitleStatus.status} IN ('completed', 'in_progress')`,
),
)
.all()
.map((r) => r.titleId);
}
+9 -43
View File
@@ -74,11 +74,10 @@ export function batchInsertEpisodeWatchesTransaction(
episodeIds: string[],
source: "manual" | "import" | "plex" | "jellyfin" | "emby",
watchedAt?: Date,
): { titleId: string | null; completionReached: boolean } {
if (episodeIds.length === 0) return { titleId: null, completionReached: false };
): { titleId: string | null } {
if (episodeIds.length === 0) return { titleId: null };
let resultTitleId: string | null = null;
let completionReached = false;
db.transaction((tx) => {
const now = watchedAt ?? new Date();
@@ -119,46 +118,9 @@ export function batchInsertEpisodeWatchesTransaction(
})
.run();
}
const allSeasons = tx.select().from(seasons).where(eq(seasons.titleId, titleId)).all();
if (allSeasons.length === 0) return;
const allSeasonIds = allSeasons.map((s) => s.id);
const allEps = tx.select().from(episodes).where(inArray(episodes.seasonId, allSeasonIds)).all();
const totalEpisodes = allEps.length;
if (totalEpisodes === 0) return;
const allEpIds = allEps.map((ep) => ep.id);
const [watchCount] = tx
.select({
count: sql<number>`count(distinct ${userEpisodeWatches.episodeId})`,
})
.from(userEpisodeWatches)
.where(
and(eq(userEpisodeWatches.userId, userId), inArray(userEpisodeWatches.episodeId, allEpIds)),
)
.all();
if (watchCount.count >= totalEpisodes) {
completionReached = true;
const completeNow = new Date();
tx.insert(userTitleStatus)
.values({
userId,
titleId,
status: "completed",
addedAt: completeNow,
updatedAt: completeNow,
})
.onConflictDoUpdate({
target: [userTitleStatus.userId, userTitleStatus.titleId],
set: { status: "completed", updatedAt: completeNow },
})
.run();
}
});
return { titleId: resultTitleId, completionReached };
return { titleId: resultTitleId };
}
export function getAllEpisodeIdsForTitle(titleId: string): string[] {
@@ -253,12 +215,16 @@ export function getUserStatusesByTitleIds(userId: string, titleIds: string[]) {
export function getEpisodeProgressByTitleIds(userId: string, titleIds: string[]) {
if (titleIds.length === 0) return [];
const today = new Date().toISOString().slice(0, 10);
return db
.select({
titleId: titles.id,
totalEpisodes: sql<number>`count(distinct ${episodes.id})`.as("totalEpisodes"),
totalEpisodes:
sql<number>`count(distinct case when ${episodes.airDate} IS NOT NULL AND ${episodes.airDate} <= ${today} then ${episodes.id} end)`.as(
"totalEpisodes",
),
watchedEpisodes:
sql<number>`count(distinct case when ${userEpisodeWatches.id} is not null then ${episodes.id} end)`.as(
sql<number>`count(distinct case when ${userEpisodeWatches.id} is not null AND ${episodes.airDate} IS NOT NULL AND ${episodes.airDate} <= ${today} then ${episodes.id} end)`.as(
"watchedEpisodes",
),
})
+29 -3
View File
@@ -182,9 +182,35 @@ function getUntranslatedEntries(catalog: CatalogType): UntranslatedEntry[] {
// does not detect argument type changes, malformed plural/select, or nested corruption.
function extractSimplePlaceholders(text: string): string[] {
// Intentionally conservative. This catches the common placeholder cases:
// {0}, {name}, {count}
return [...text.matchAll(/\{[a-zA-Z0-9_]+\}/g)].map((m) => m[0]).sort();
// Extract top-level ICU placeholders ({0}, {name}, {count}) while skipping
// content words nested inside plural/select branches like {episode} in
// "{count, plural, one {episode} other {episodes}}".
const results: string[] = [];
let depth = 0;
let argStart = -1;
for (let i = 0; i < text.length; i++) {
if (text[i] === "{") {
if (depth === 0) argStart = i;
depth++;
} else if (text[i] === "}") {
depth--;
if (depth === 0 && argStart >= 0) {
const inner = text.slice(argStart + 1, i);
// Top-level simple placeholder: just an identifier, no comma (not plural/select)
if (/^[a-zA-Z0-9_]+$/.test(inner)) {
results.push(`{${inner}}`);
} else {
// Complex ICU argument — extract just the argument name before the comma
const argName = inner.match(/^([a-zA-Z0-9_]+)\s*,/)?.[1];
if (argName) results.push(`{${argName}}`);
}
argStart = -1;
}
}
}
return results.sort();
}
function extractNumberedTags(text: string): string[] {
+210 -173
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+194 -157
View File
@@ -104,8 +104,8 @@ msgstr ""
#~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/titles/use-title-actions.ts:200
#: apps/web/src/components/titles/use-title-actions.ts:278
#: apps/web/src/components/titles/use-title-actions.ts:198
#: apps/web/src/components/titles/use-title-actions.ts:270
msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
msgstr ""
@@ -114,22 +114,22 @@ msgstr ""
msgid "{healthyCount} of {0} jobs healthy"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:84
#: apps/native/src/components/settings/integration-card.tsx:86
#: apps/web/src/components/settings/integration-card.tsx:89
msgid "{label} connected"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:94
#: apps/native/src/components/settings/integration-card.tsx:96
#: apps/web/src/components/settings/integration-card.tsx:105
msgid "{label} disconnected"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:104
#: apps/native/src/components/settings/integration-card.tsx:106
#: apps/web/src/components/settings/integration-card.tsx:119
msgid "{label} URL regenerated"
msgstr ""
#: apps/web/src/components/title-card.tsx:152
#: apps/web/src/components/title-card.tsx:157
msgid "{watched}/{total} episodes"
msgstr ""
@@ -157,7 +157,7 @@ msgstr ""
msgid "Actions"
msgstr ""
#: apps/native/src/app/person/[id].tsx:50
#: apps/native/src/app/person/[id].tsx:138
#: apps/native/src/components/search/recently-viewed-row-content.tsx:28
#: apps/web/src/components/people/person-hero.tsx:69
msgid "Actor"
@@ -180,13 +180,13 @@ msgstr ""
msgid "Add to Library"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx:73
#: apps/native/src/components/titles/status-action-button.tsx:80
msgid "Add to watchlist"
msgstr ""
#: apps/native/src/components/explore/hero-banner.tsx:132
#: apps/native/src/components/ui/poster-card.tsx:212
#: apps/web/src/components/title-card.tsx:133
#: apps/native/src/components/ui/poster-card.tsx:215
#: apps/web/src/components/title-card.tsx:138
msgid "Add to Watchlist"
msgstr ""
@@ -197,7 +197,7 @@ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:44
#: apps/native/src/hooks/use-title-actions.ts:59
#: apps/native/src/lib/title-actions.ts:25
#: apps/web/src/components/titles/use-title-actions.ts:98
#: apps/web/src/components/titles/use-title-actions.ts:95
msgid "Added to watchlist"
msgstr ""
@@ -209,11 +209,11 @@ msgstr ""
msgid "Admin"
msgstr ""
#: apps/web/src/routes/_app/settings.tsx:154
#: apps/web/src/routes/_app/settings.tsx:156
msgid "Admin only"
msgstr ""
#: apps/native/src/app/person/[id].tsx:249
#: apps/native/src/app/person/[id].tsx:189
#: apps/web/src/components/people/person-hero.tsx:89
msgid "age {age}"
msgstr ""
@@ -243,7 +243,7 @@ msgstr ""
msgid "Anonymous usage reporting"
msgstr ""
#: apps/web/src/routes/_app/settings.tsx:135
#: apps/web/src/routes/_app/settings.tsx:137
msgid "App Settings"
msgstr ""
@@ -251,7 +251,7 @@ msgstr ""
msgid "Application"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:139
#: apps/native/src/components/settings/integration-card.tsx:148
msgid "Are you sure you want to disconnect {label}? The current URL will stop working."
msgstr ""
@@ -310,7 +310,7 @@ msgid "Backup schedule"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx:583
#: apps/web/src/routes/_app/settings.tsx:190
#: apps/web/src/routes/_app/settings.tsx:192
msgid "Backups"
msgstr ""
@@ -337,8 +337,9 @@ msgstr ""
#: apps/native/src/components/header-avatar.tsx:63
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:58
#: apps/native/src/components/search/recently-viewed-list.tsx:32
#: apps/native/src/components/settings/integration-card.tsx:126
#: apps/native/src/components/settings/integration-card.tsx:141
#: apps/native/src/components/settings/integration-card.tsx:135
#: apps/native/src/components/settings/integration-card.tsx:150
#: apps/native/src/components/titles/status-action-button.tsx:104
#: apps/web/src/components/settings/account-section.tsx:477
#: apps/web/src/components/settings/backup-restore-section.tsx:101
#: apps/web/src/components/settings/backup-section.tsx:240
@@ -348,6 +349,7 @@ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx:611
#: apps/web/src/components/settings/imports-section.tsx:674
#: apps/web/src/components/settings/imports-section.tsx:798
#: apps/web/src/components/titles/status-button.tsx:131
#: apps/web/src/components/titles/title-seasons.tsx:127
msgid "Cancel"
msgstr ""
@@ -361,14 +363,20 @@ msgstr ""
msgid "Cast"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts:202
#: apps/web/src/components/titles/use-title-actions.ts:280
#: apps/web/src/components/titles/use-title-actions.ts:200
#: apps/web/src/components/titles/use-title-actions.ts:272
msgid "Catch up"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx:50
#: apps/web/src/components/title-card.tsx:74
#: apps/web/src/components/titles/status-button.tsx:54
msgid "Caught Up"
msgstr "Caught Up"
#. placeholder {0}: episodeIds.length
#. placeholder {1}: episodeIds.length
#: apps/web/src/components/titles/use-title-actions.ts:72
#: apps/web/src/components/titles/use-title-actions.ts:69
msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched"
msgstr ""
@@ -418,7 +426,7 @@ msgstr ""
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:60
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:104
#: apps/native/src/components/search/recently-viewed-list.tsx:34
#: apps/native/src/components/search/recently-viewed-list.tsx:86
#: apps/native/src/components/search/recently-viewed-list.tsx:68
msgid "Clear"
msgstr ""
@@ -455,10 +463,10 @@ msgid "Close"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/index.tsx:146
#: apps/native/src/components/titles/status-action-button.tsx:45
#: apps/native/src/components/titles/status-action-button.tsx:52
#: apps/web/src/components/dashboard/stats-display.tsx:219
#: apps/web/src/components/title-card.tsx:74
#: apps/web/src/components/titles/status-button.tsx:25
#: apps/web/src/components/title-card.tsx:79
#: apps/web/src/components/titles/status-button.tsx:59
msgid "Completed"
msgstr ""
@@ -477,7 +485,7 @@ msgstr ""
msgid "Connect {0}"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:207
#: apps/native/src/components/settings/integration-card.tsx:216
msgid "Connect {label}"
msgstr ""
@@ -485,7 +493,7 @@ msgstr ""
msgid "Connect to {source}"
msgstr ""
#: apps/web/src/routes/setup.tsx:98
#: apps/web/src/routes/setup.tsx:99
msgid "Connect to TMDB"
msgstr ""
@@ -516,7 +524,7 @@ msgstr ""
msgid "Connecting..."
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:207
#: apps/native/src/components/settings/integration-card.tsx:216
msgid "Connecting…"
msgstr ""
@@ -545,7 +553,7 @@ msgstr ""
msgid "Could not load integrations"
msgstr ""
#: apps/native/src/app/person/[id].tsx:172
#: apps/native/src/app/person/[id].tsx:257
msgid "Could not load person details"
msgstr ""
@@ -579,14 +587,14 @@ msgstr ""
msgid "Current password is required"
msgstr ""
#: apps/web/src/routes/_app/settings.tsx:216
#: apps/web/src/routes/_app/settings.tsx:218
msgid "Danger Zone"
msgstr ""
#: apps/web/src/routes/__root.tsx:163
#: apps/web/src/routes/_app/people.$id.tsx:76
#: apps/web/src/routes/_app/titles.$id.tsx:119
#: apps/web/src/routes/_app/titles.$id.tsx:165
#: apps/web/src/routes/_app/people.$id.tsx:78
#: apps/web/src/routes/_app/titles.$id.tsx:120
#: apps/web/src/routes/_app/titles.$id.tsx:166
msgid "Dashboard"
msgstr ""
@@ -630,12 +638,12 @@ msgstr ""
msgid "Device code expired. Please try again."
msgstr ""
#: apps/native/src/app/person/[id].tsx:249
#: apps/native/src/app/person/[id].tsx:189
#: apps/web/src/components/people/person-hero.tsx:89
msgid "died at {age}"
msgstr ""
#: apps/native/src/app/person/[id].tsx:51
#: apps/native/src/app/person/[id].tsx:139
#: apps/native/src/components/search/recently-viewed-row-content.tsx:29
#: apps/web/src/components/people/person-hero.tsx:71
msgid "Director"
@@ -646,13 +654,13 @@ msgstr ""
msgid "Disabled"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:143
#: apps/native/src/components/settings/integration-card.tsx:257
#: apps/native/src/components/settings/integration-card.tsx:152
#: apps/native/src/components/settings/integration-card.tsx:266
#: apps/web/src/components/settings/integration-card.tsx:234
msgid "Disconnect"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:138
#: apps/native/src/components/settings/integration-card.tsx:147
msgid "Disconnect {label}"
msgstr ""
@@ -685,7 +693,7 @@ msgstr ""
msgid "Download backup"
msgstr ""
#: apps/native/src/app/person/[id].tsx:54
#: apps/native/src/app/person/[id].tsx:142
#: apps/native/src/components/search/recently-viewed-row-content.tsx:32
#: apps/web/src/components/people/person-hero.tsx:77
msgid "Editor"
@@ -729,24 +737,31 @@ msgstr ""
msgid "Environment"
msgstr ""
#. placeholder {0}: episode.episodeNumber
#: apps/native/src/components/titles/episode-row.tsx:27
#: apps/native/src/components/titles/episode-row.tsx:48
msgid "Episode {0}"
msgstr ""
#~ msgid "Episode {0}"
#~ msgstr ""
#. placeholder {0}: episode.episodeNumber
#: apps/native/src/components/titles/episode-row.tsx:34
msgid "Episode {0}, {episodeLabel}"
msgstr ""
#~ msgid "Episode {0}, {episodeLabel}"
#~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:111
#: apps/native/src/lib/title-actions.ts:108
#: apps/native/src/components/titles/episode-row.tsx:29
#: apps/native/src/components/titles/episode-row.tsx:52
msgid "Episode {episodeNumber}"
msgstr "Episode {episodeNumber}"
#: apps/native/src/components/titles/episode-row.tsx:38
msgid "Episode {episodeNumber}, {episodeLabel}"
msgstr "Episode {episodeNumber}, {episodeLabel}"
#: apps/native/src/hooks/use-title-actions.ts:109
#: apps/native/src/lib/title-actions.ts:84
msgid "Episode unwatched"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:101
#: apps/native/src/lib/title-actions.ts:98
#: apps/native/src/hooks/use-title-actions.ts:99
#: apps/native/src/lib/title-actions.ts:74
msgid "Episode watched"
msgstr ""
@@ -790,8 +805,8 @@ msgstr ""
msgid "Explore"
msgstr ""
#: apps/web/src/routes/_app/people.$id.tsx:68
#: apps/web/src/routes/_app/titles.$id.tsx:157
#: apps/web/src/routes/_app/people.$id.tsx:70
#: apps/web/src/routes/_app/titles.$id.tsx:158
msgid "Explore titles"
msgstr ""
@@ -804,7 +819,7 @@ msgstr ""
msgid "Failed to add to watchlist"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts:80
#: apps/web/src/components/titles/use-title-actions.ts:77
msgid "Failed to catch up"
msgstr ""
@@ -817,7 +832,7 @@ msgstr ""
msgid "Failed to connect"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:87
#: apps/native/src/components/settings/integration-card.tsx:89
#: apps/web/src/components/settings/integration-card.tsx:91
msgid "Failed to connect {label}"
msgstr ""
@@ -834,7 +849,7 @@ msgstr ""
msgid "Failed to delete backup"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:97
#: apps/native/src/components/settings/integration-card.tsx:99
#: apps/web/src/components/settings/integration-card.tsx:108
msgid "Failed to disconnect {label}"
msgstr ""
@@ -843,29 +858,30 @@ msgstr ""
msgid "Failed to load backup schedule settings."
msgstr ""
#: apps/web/src/routes/_app/titles.$id.tsx:110
#: apps/web/src/routes/_app/titles.$id.tsx:111
msgid "Failed to load title"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts:344
#: apps/native/src/lib/title-actions.ts:101
#: apps/web/src/components/titles/use-title-actions.ts:338
msgid "Failed to mark all episodes as watched"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:79
#: apps/native/src/lib/title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:137
#: apps/native/src/hooks/use-title-actions.ts:77
#: apps/native/src/lib/title-actions.ts:43
#: apps/web/src/components/titles/use-title-actions.ts:134
msgid "Failed to mark as watched"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:104
#: apps/native/src/lib/title-actions.ts:101
#: apps/web/src/components/titles/use-title-actions.ts:216
#: apps/native/src/hooks/use-title-actions.ts:102
#: apps/native/src/lib/title-actions.ts:77
#: apps/web/src/components/titles/use-title-actions.ts:214
msgid "Failed to mark episode"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:124
#: apps/native/src/lib/title-actions.ts:123
#: apps/web/src/components/titles/use-title-actions.ts:294
#: apps/native/src/hooks/use-title-actions.ts:122
#: apps/native/src/lib/title-actions.ts:113
#: apps/web/src/components/titles/use-title-actions.ts:286
msgid "Failed to mark some episodes"
msgstr ""
@@ -889,12 +905,12 @@ msgstr ""
msgid "Failed to purge metadata cache"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:107
#: apps/native/src/components/settings/integration-card.tsx:109
#: apps/web/src/components/settings/integration-card.tsx:121
msgid "Failed to regenerate {label} URL"
msgstr ""
#: apps/native/src/lib/title-actions.ts:77
#: apps/native/src/lib/title-actions.ts:53
msgid "Failed to remove from library"
msgstr ""
@@ -916,13 +932,13 @@ msgstr ""
msgid "Failed to trigger job"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:114
#: apps/native/src/lib/title-actions.ts:111
#: apps/web/src/components/titles/use-title-actions.ts:163
#: apps/native/src/hooks/use-title-actions.ts:112
#: apps/native/src/lib/title-actions.ts:87
#: apps/web/src/components/titles/use-title-actions.ts:161
msgid "Failed to unmark episode"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts:320
#: apps/web/src/components/titles/use-title-actions.ts:312
msgid "Failed to unmark some episodes"
msgstr ""
@@ -930,9 +946,9 @@ msgstr ""
msgid "Failed to update name"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:94
#: apps/native/src/lib/title-actions.ts:91
#: apps/web/src/components/titles/use-title-actions.ts:123
#: apps/native/src/hooks/use-title-actions.ts:92
#: apps/native/src/lib/title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:120
msgid "Failed to update rating"
msgstr ""
@@ -958,10 +974,8 @@ msgstr ""
msgid "Failed to update setting"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:69
#: apps/native/src/lib/title-actions.ts:41
#: apps/native/src/lib/title-actions.ts:55
#: apps/web/src/components/titles/use-title-actions.ts:101
#: apps/native/src/hooks/use-title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:98
msgid "Failed to update status"
msgstr ""
@@ -973,7 +987,7 @@ msgstr ""
msgid "Fetching your library data from {source}..."
msgstr ""
#: apps/native/src/app/person/[id].tsx:279
#: apps/native/src/app/person/[id].tsx:219
#: apps/web/src/components/people/filmography-grid.tsx:67
msgid "Filmography"
msgstr ""
@@ -1002,8 +1016,8 @@ msgstr ""
msgid "Get Started"
msgstr ""
#: apps/native/src/app/person/[id].tsx:176
#: apps/native/src/app/person/[id].tsx:196
#: apps/native/src/app/person/[id].tsx:261
#: apps/native/src/app/person/[id].tsx:281
#: apps/native/src/app/title/[id].tsx:235
msgid "Go back"
msgstr ""
@@ -1112,6 +1126,11 @@ msgstr ""
msgid "In Library"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx:46
#: apps/web/src/components/titles/status-button.tsx:40
msgid "In Watchlist"
msgstr "In Watchlist"
#: apps/native/src/app/(tabs)/(home)/index.tsx:179
#: apps/web/src/components/dashboard/library-section.tsx:35
msgid "In Your Library"
@@ -1222,22 +1241,23 @@ msgid "Mark all episodes as watched?"
msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx:152
#: apps/native/src/components/ui/poster-card.tsx:229
#: apps/web/src/components/titles/title-seasons.tsx:109
#: apps/web/src/components/titles/title-seasons.tsx:135
msgid "Mark All Watched"
msgstr ""
#: apps/native/src/components/dashboard/continue-watching-card.tsx:103
msgid "Mark as Completed"
msgstr ""
#~ msgid "Mark as Completed"
#~ msgstr ""
#: apps/native/src/components/ui/poster-card.tsx:226
#: apps/native/src/components/ui/poster-card.tsx:222
msgid "Mark as Watched"
msgstr ""
#: apps/native/src/components/ui/poster-card.tsx:219
msgid "Mark as Watching"
msgstr ""
#~ msgid "Mark as Watching"
#~ msgstr ""
#: apps/native/src/app/title/[id].tsx:400
#: apps/web/src/components/titles/title-actions.tsx:27
@@ -1245,32 +1265,37 @@ msgid "Mark Watched"
msgstr ""
#: apps/native/src/lib/title-actions.ts:50
msgid "Marked \"{titleName}\" as completed"
msgstr ""
#~ msgid "Marked \"{titleName}\" as completed"
#~ msgstr ""
#: apps/native/src/lib/title-actions.ts:63
#: apps/web/src/components/titles/use-title-actions.ts:134
#: apps/native/src/lib/title-actions.ts:39
#: apps/web/src/components/titles/use-title-actions.ts:131
msgid "Marked \"{titleName}\" as watched"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts:337
#: apps/native/src/lib/title-actions.ts:97
#: apps/web/src/components/titles/use-title-actions.ts:331
msgid "Marked all episodes as watched"
msgstr ""
#: apps/native/src/lib/title-actions.ts:96
msgid "Marked all episodes of \"{titleName}\" as watched"
msgstr "Marked all episodes of \"{titleName}\" as watched"
#: apps/native/src/hooks/use-title-actions.ts:61
#: apps/native/src/lib/title-actions.ts:51
msgid "Marked as completed"
msgstr ""
#~ msgid "Marked as completed"
#~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:76
#: apps/native/src/lib/title-actions.ts:63
#: apps/native/src/hooks/use-title-actions.ts:74
#: apps/native/src/lib/title-actions.ts:39
msgid "Marked as watched"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:60
#: apps/native/src/lib/title-actions.ts:38
msgid "Marked as watching"
msgstr ""
#~ msgid "Marked as watching"
#~ msgstr ""
#: apps/web/src/components/settings/account-section.tsx:314
msgid "Member since {memberSince}"
@@ -1345,7 +1370,7 @@ msgstr ""
msgid "New account creation is currently disabled."
msgstr ""
#: apps/web/src/routes/_auth/register.tsx:36
#: apps/web/src/routes/_auth/register.tsx:33
msgid "New accounts are not being accepted right now. Contact the admin if you need access."
msgstr ""
@@ -1403,7 +1428,7 @@ msgstr ""
msgid "No titles found for this genre."
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:174
#: apps/native/src/components/settings/integration-card.tsx:183
#: apps/web/src/components/settings/integration-card.tsx:153
#: apps/web/src/components/settings/system-health-section.tsx:229
msgid "Not configured"
@@ -1517,8 +1542,8 @@ msgstr ""
msgid "Person"
msgstr ""
#: apps/native/src/app/person/[id].tsx:192
#: apps/web/src/routes/_app/people.$id.tsx:50
#: apps/native/src/app/person/[id].tsx:277
#: apps/web/src/routes/_app/people.$id.tsx:52
msgid "Person not found"
msgstr ""
@@ -1527,12 +1552,12 @@ msgid "Play trailer"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx:89
#: apps/web/src/routes/_app/explore.tsx:141
#: apps/web/src/routes/_app/explore.tsx:143
msgid "Popular Movies"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx:102
#: apps/web/src/routes/_app/explore.tsx:151
#: apps/web/src/routes/_app/explore.tsx:153
msgid "Popular TV Shows"
msgstr ""
@@ -1540,7 +1565,7 @@ msgstr ""
msgid "Pre-restore backup"
msgstr ""
#: apps/native/src/app/person/[id].tsx:53
#: apps/native/src/app/person/[id].tsx:141
#: apps/native/src/components/search/recently-viewed-row-content.tsx:31
#: apps/web/src/components/people/person-hero.tsx:75
msgid "Producer"
@@ -1612,7 +1637,7 @@ msgstr ""
#. placeholder {0}: input.stars
#. placeholder {1}: input.stars
#: apps/native/src/hooks/use-title-actions.ts:88
#: apps/native/src/hooks/use-title-actions.ts:86
msgid "Rated {0} {1, plural, one {star} other {stars}}"
msgstr ""
@@ -1620,11 +1645,11 @@ msgstr ""
#~ msgid "Rated {0} star{1}"
#~ msgstr "Rated {0} star{1}"
#: apps/web/src/components/titles/use-title-actions.ts:118
#: apps/web/src/components/titles/use-title-actions.ts:115
msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}"
msgstr ""
#: apps/native/src/lib/title-actions.ts:86
#: apps/native/src/lib/title-actions.ts:62
msgid "Rated {stars, plural, one {# star} other {# stars}}"
msgstr ""
@@ -1633,9 +1658,9 @@ msgstr ""
msgid "Rating"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:89
#: apps/native/src/lib/title-actions.ts:87
#: apps/web/src/components/titles/use-title-actions.ts:119
#: apps/native/src/hooks/use-title-actions.ts:87
#: apps/native/src/lib/title-actions.ts:63
#: apps/web/src/components/titles/use-title-actions.ts:116
msgid "Rating removed"
msgstr ""
@@ -1663,7 +1688,7 @@ msgid "Recent Searches"
msgstr ""
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:95
#: apps/native/src/components/search/recently-viewed-list.tsx:77
#: apps/native/src/components/search/recently-viewed-list.tsx:59
msgid "Recently Viewed"
msgstr ""
@@ -1692,12 +1717,12 @@ msgstr ""
msgid "Refresh system health"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:128
#: apps/native/src/components/settings/integration-card.tsx:248
#: apps/native/src/components/settings/integration-card.tsx:137
#: apps/native/src/components/settings/integration-card.tsx:257
msgid "Regenerate"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:123
#: apps/native/src/components/settings/integration-card.tsx:132
#: apps/web/src/components/settings/integration-card.tsx:226
msgid "Regenerate URL"
msgstr ""
@@ -1717,7 +1742,7 @@ msgid "Registration closed"
msgstr ""
#: apps/native/src/app/(auth)/register.tsx:87
#: apps/web/src/routes/_auth/register.tsx:33
#: apps/web/src/routes/_auth/register.tsx:30
msgid "Registration Closed"
msgstr ""
@@ -1726,20 +1751,27 @@ msgstr ""
msgid "Registration opened"
msgstr ""
#: apps/web/src/components/titles/status-button.tsx:76
#: apps/native/src/components/titles/status-action-button.tsx:106
#: apps/web/src/components/titles/status-button.tsx:109
#: apps/web/src/components/titles/status-button.tsx:139
msgid "Remove"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx:96
#: apps/web/src/components/titles/status-button.tsx:60
#: apps/native/src/components/titles/status-action-button.tsx:115
#: apps/web/src/components/titles/status-button.tsx:93
msgid "Remove from library"
msgstr ""
#: apps/native/src/components/dashboard/continue-watching-card.tsx:108
#: apps/native/src/components/ui/poster-card.tsx:233
#: apps/native/src/components/ui/poster-card.tsx:236
msgid "Remove from Library"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx:101
#: apps/web/src/components/titles/status-button.tsx:120
msgid "Remove from library?"
msgstr "Remove from library?"
#: apps/native/src/app/(tabs)/(settings)/index.tsx:268
msgid "Remove Photo"
msgstr ""
@@ -1752,9 +1784,9 @@ msgstr ""
msgid "Remove profile picture"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:65
#: apps/native/src/lib/title-actions.ts:74
#: apps/web/src/components/titles/use-title-actions.ts:98
#: apps/native/src/hooks/use-title-actions.ts:63
#: apps/native/src/lib/title-actions.ts:50
#: apps/web/src/components/titles/use-title-actions.ts:95
msgid "Removed from library"
msgstr ""
@@ -1868,7 +1900,7 @@ msgid "Search for movies and TV shows to start tracking"
msgstr ""
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:72
#: apps/native/src/components/search/recently-viewed-list.tsx:55
#: apps/native/src/components/search/recently-viewed-list.tsx:81
msgid "Search for movies, shows, or people"
msgstr ""
@@ -1892,13 +1924,13 @@ msgstr ""
#. placeholder {0}: season.seasonNumber
#: apps/native/src/components/titles/season-accordion.tsx:113
#: apps/native/src/components/titles/season-accordion.tsx:119
#: apps/web/src/components/titles/use-title-actions.ts:274
#: apps/web/src/components/titles/use-title-actions.ts:313
#: apps/web/src/components/titles/use-title-actions.ts:266
#: apps/web/src/components/titles/use-title-actions.ts:305
msgid "Season {0}"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:121
#: apps/native/src/lib/title-actions.ts:119
#: apps/native/src/hooks/use-title-actions.ts:119
#: apps/native/src/lib/title-actions.ts:109
msgid "Season watched"
msgstr ""
@@ -1907,7 +1939,7 @@ msgid "Seasons"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx:452
#: apps/web/src/routes/_app/settings.tsx:167
#: apps/web/src/routes/_app/settings.tsx:169
msgid "Security"
msgstr ""
@@ -1915,7 +1947,7 @@ msgstr ""
msgid "Self-hosted movie & TV tracker"
msgstr ""
#: apps/web/src/routes/_app/settings.tsx:151
#: apps/web/src/routes/_app/settings.tsx:153
msgid "Server"
msgstr ""
@@ -1947,12 +1979,12 @@ msgstr ""
msgid "Settings"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:271
#: apps/native/src/components/settings/integration-card.tsx:280
#: apps/web/src/components/settings/integration-card.tsx:248
msgid "Setup instructions"
msgstr ""
#: apps/web/src/routes/setup.tsx:95
#: apps/web/src/routes/setup.tsx:96
msgid "Setup required"
msgstr ""
@@ -1977,7 +2009,7 @@ msgstr ""
msgid "Sign In"
msgstr ""
#: apps/web/src/routes/_auth/register.tsx:45
#: apps/web/src/routes/_auth/register.tsx:42
msgid "Sign in instead"
msgstr ""
@@ -2031,13 +2063,13 @@ msgid "Sofa will automatically log movies and episodes when you finish watching
msgstr ""
#: apps/native/src/app/change-password.tsx:77
#: apps/native/src/app/person/[id].tsx:169
#: apps/native/src/app/person/[id].tsx:254
#: apps/web/src/components/settings/account-section.tsx:391
#: apps/web/src/routes/__root.tsx:139
msgid "Something went wrong"
msgstr ""
#: apps/web/src/routes/_app/titles.$id.tsx:113
#: apps/web/src/routes/_app/titles.$id.tsx:114
msgid "Something went wrong while loading this title. Please try again."
msgstr ""
@@ -2070,7 +2102,7 @@ msgstr ""
msgid "Starting import..."
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts:64
#: apps/native/src/hooks/use-title-actions.ts:62
msgid "Status updated"
msgstr ""
@@ -2095,11 +2127,11 @@ msgstr ""
msgid "The page you're looking for doesn't exist."
msgstr ""
#: apps/web/src/routes/_app/people.$id.tsx:53
#: apps/web/src/routes/_app/people.$id.tsx:55
msgid "The person you're looking for doesn't exist or may have been removed from the database."
msgstr ""
#: apps/web/src/routes/_app/titles.$id.tsx:142
#: apps/web/src/routes/_app/titles.$id.tsx:143
msgid "The title you're looking for doesn't exist or may have been removed from the database."
msgstr ""
@@ -2121,11 +2153,16 @@ msgid "This page was left on the cutting room floor. It may have been moved, rem
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx:559
#: apps/web/src/routes/_app/settings.tsx:112
#: apps/web/src/routes/setup.tsx:180
#: apps/web/src/routes/_app/settings.tsx:114
#: apps/web/src/routes/setup.tsx:181
msgid "This product uses the TMDB API but is not endorsed or certified by TMDB."
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx:102
#: apps/web/src/components/titles/status-button.tsx:123
msgid "This title will be removed from your library. Your watch history and ratings will be kept."
msgstr "This title will be removed from your library. Your watch history and ratings will be kept."
#: apps/native/src/app/(tabs)/(home)/index.tsx:88
msgid "this week"
msgstr "this week"
@@ -2147,7 +2184,7 @@ msgstr ""
msgid "This will delete un-enriched stub titles that aren't in any user's library and clean up orphaned person records. Deleted titles will be re-imported if accessed again."
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:124
#: apps/native/src/components/settings/integration-card.tsx:133
msgid "This will invalidate the current {label} URL. You'll need to update it in {label}."
msgstr ""
@@ -2187,7 +2224,7 @@ msgid "Time:"
msgstr ""
#: apps/native/src/app/title/[id].tsx:231
#: apps/web/src/routes/_app/titles.$id.tsx:139
#: apps/web/src/routes/_app/titles.$id.tsx:140
msgid "Title not found"
msgstr ""
@@ -2236,7 +2273,7 @@ msgid "Trending today"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx:77
#: apps/web/src/routes/_app/explore.tsx:129
#: apps/web/src/routes/_app/explore.tsx:131
msgid "Trending Today"
msgstr ""
@@ -2291,11 +2328,11 @@ msgid "Unwatch all"
msgstr ""
#. placeholder {0}: season.name ?? t`Season ${season.seasonNumber}`
#: apps/web/src/components/titles/use-title-actions.ts:313
#: apps/web/src/components/titles/use-title-actions.ts:305
msgid "Unwatched all of {0}"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts:156
#: apps/web/src/components/titles/use-title-actions.ts:154
msgid "Unwatched S{seasonNum} E{epNum}"
msgstr ""
@@ -2366,7 +2403,7 @@ msgstr ""
msgid "Upload profile picture"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx:117
#: apps/native/src/components/settings/integration-card.tsx:125
msgid "URL copied to clipboard"
msgstr ""
@@ -2399,36 +2436,36 @@ msgstr ""
msgid "Watch on {name}"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts:277
#: apps/web/src/components/titles/use-title-actions.ts:286
#: apps/web/src/components/titles/use-title-actions.ts:269
#: apps/web/src/components/titles/use-title-actions.ts:278
msgid "Watched all of {seasonLabel}"
msgstr ""
#: apps/native/src/lib/title-actions.ts:119
#: apps/native/src/lib/title-actions.ts:109
msgid "Watched all of {seasonName}"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts:199
#: apps/web/src/components/titles/use-title-actions.ts:208
#: apps/web/src/components/titles/use-title-actions.ts:197
#: apps/web/src/components/titles/use-title-actions.ts:206
msgid "Watched S{seasonNum} E{epNum}"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx:43
#: apps/native/src/components/titles/status-action-button.tsx:48
#: apps/web/src/components/title-card.tsx:69
#: apps/web/src/components/titles/status-button.tsx:14
#: apps/web/src/components/titles/status-button.tsx:47
msgid "Watching"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx:78
#: apps/native/src/components/titles/status-action-button.tsx:85
#: apps/web/src/components/settings/imports-section.tsx:743
#: apps/web/src/components/settings/imports-section.tsx:769
#: apps/web/src/components/titles/status-button.tsx:49
#: apps/web/src/components/titles/status-button.tsx:82
msgid "Watchlist"
msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx:41
msgid "Watchlisted"
msgstr ""
#~ msgid "Watchlisted"
#~ msgstr ""
#: apps/native/src/components/settings/integration-configs.ts:51
#: apps/native/src/components/settings/integration-configs.ts:66
@@ -2458,7 +2495,7 @@ msgstr ""
msgid "With Ads"
msgstr ""
#: apps/native/src/app/person/[id].tsx:52
#: apps/native/src/app/person/[id].tsx:140
#: apps/native/src/components/search/recently-viewed-row-content.tsx:30
#: apps/web/src/components/people/person-hero.tsx:73
msgid "Writer"
File diff suppressed because one or more lines are too long
+207 -170
View File
@@ -57,7 +57,7 @@ msgstr "{0} imágenes en caché"
#. placeholder {1}: member.episodeCount !== 1 ? "s" : ""
#: apps/web/src/components/titles/cast-carousel.tsx:78
msgid "{0} ep{1}"
msgstr ""
msgstr "{0} ep{1}"
#: apps/native/src/app/(tabs)/(settings)/index.tsx:472
#~ msgid "{0} images"
@@ -104,8 +104,8 @@ msgstr "{0}/{1} {2, plural, one {episodio} other {episodios}}"
#~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/titles/use-title-actions.ts:200
#: apps/web/src/components/titles/use-title-actions.ts:278
#: apps/web/src/components/titles/use-title-actions.ts:198
#: apps/web/src/components/titles/use-title-actions.ts:270
msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
msgstr "{count} {count, plural, one {episodio anterior sin ver} other {episodios anteriores sin ver}}"
@@ -114,22 +114,22 @@ msgstr "{count} {count, plural, one {episodio anterior sin ver} other {episodios
msgid "{healthyCount} of {0} jobs healthy"
msgstr "{healthyCount} de {0} tareas en buen estado"
#: apps/native/src/components/settings/integration-card.tsx:84
#: apps/native/src/components/settings/integration-card.tsx:86
#: apps/web/src/components/settings/integration-card.tsx:89
msgid "{label} connected"
msgstr "{label} conectado"
#: apps/native/src/components/settings/integration-card.tsx:94
#: apps/native/src/components/settings/integration-card.tsx:96
#: apps/web/src/components/settings/integration-card.tsx:105
msgid "{label} disconnected"
msgstr "{label} desconectado"
#: apps/native/src/components/settings/integration-card.tsx:104
#: apps/native/src/components/settings/integration-card.tsx:106
#: apps/web/src/components/settings/integration-card.tsx:119
msgid "{label} URL regenerated"
msgstr "URL de {label} regenerada"
#: apps/web/src/components/title-card.tsx:152
#: apps/web/src/components/title-card.tsx:157
msgid "{watched}/{total} episodes"
msgstr "{watched}/{total} episodios"
@@ -157,11 +157,11 @@ msgstr "Cuenta"
msgid "Actions"
msgstr "Acciones"
#: apps/native/src/app/person/[id].tsx:50
#: apps/native/src/app/person/[id].tsx:138
#: apps/native/src/components/search/recently-viewed-row-content.tsx:28
#: apps/web/src/components/people/person-hero.tsx:69
msgid "Actor"
msgstr ""
msgstr "Actor"
#: apps/native/src/components/settings/integration-configs.ts:71
msgid "Add a \"Generic Destination\" and paste the URL above"
@@ -180,13 +180,13 @@ msgstr "Añade un nuevo webhook y pega la URL anterior"
msgid "Add to Library"
msgstr "Añadir a la biblioteca"
#: apps/native/src/components/titles/status-action-button.tsx:73
#: apps/native/src/components/titles/status-action-button.tsx:80
msgid "Add to watchlist"
msgstr "Añadir a la lista"
#: apps/native/src/components/explore/hero-banner.tsx:132
#: apps/native/src/components/ui/poster-card.tsx:212
#: apps/web/src/components/title-card.tsx:133
#: apps/native/src/components/ui/poster-card.tsx:215
#: apps/web/src/components/title-card.tsx:138
msgid "Add to Watchlist"
msgstr "Añadir a la lista"
@@ -197,7 +197,7 @@ msgstr "\"{titleName}\" añadido a la lista"
#: apps/native/src/hooks/use-title-actions.ts:44
#: apps/native/src/hooks/use-title-actions.ts:59
#: apps/native/src/lib/title-actions.ts:25
#: apps/web/src/components/titles/use-title-actions.ts:98
#: apps/web/src/components/titles/use-title-actions.ts:95
msgid "Added to watchlist"
msgstr "Añadido a la lista"
@@ -207,13 +207,13 @@ msgstr "Añadido a la lista"
#: apps/web/src/components/nav-bar.tsx:223
#: apps/web/src/components/settings/account-section.tsx:309
msgid "Admin"
msgstr ""
msgstr "Admin"
#: apps/web/src/routes/_app/settings.tsx:154
#: apps/web/src/routes/_app/settings.tsx:156
msgid "Admin only"
msgstr "Solo administradores"
#: apps/native/src/app/person/[id].tsx:249
#: apps/native/src/app/person/[id].tsx:189
#: apps/web/src/components/people/person-hero.tsx:89
msgid "age {age}"
msgstr "edad {age}"
@@ -243,7 +243,7 @@ msgstr "Ocurrió un error inesperado al cargar esta página. Puedes intentarlo d
msgid "Anonymous usage reporting"
msgstr "Informe de uso anónimo"
#: apps/web/src/routes/_app/settings.tsx:135
#: apps/web/src/routes/_app/settings.tsx:137
msgid "App Settings"
msgstr "Ajustes de la app"
@@ -251,7 +251,7 @@ msgstr "Ajustes de la app"
msgid "Application"
msgstr "Aplicación"
#: apps/native/src/components/settings/integration-card.tsx:139
#: apps/native/src/components/settings/integration-card.tsx:148
msgid "Are you sure you want to disconnect {label}? The current URL will stop working."
msgstr "¿Seguro que quieres desconectar {label}? La URL actual dejará de funcionar."
@@ -310,7 +310,7 @@ msgid "Backup schedule"
msgstr "Programación de copias de seguridad"
#: apps/web/src/components/settings/system-health-section.tsx:583
#: apps/web/src/routes/_app/settings.tsx:190
#: apps/web/src/routes/_app/settings.tsx:192
msgid "Backups"
msgstr "Copias de seguridad"
@@ -337,8 +337,9 @@ msgstr "No se puede contactar con el servidor"
#: apps/native/src/components/header-avatar.tsx:63
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:58
#: apps/native/src/components/search/recently-viewed-list.tsx:32
#: apps/native/src/components/settings/integration-card.tsx:126
#: apps/native/src/components/settings/integration-card.tsx:141
#: apps/native/src/components/settings/integration-card.tsx:135
#: apps/native/src/components/settings/integration-card.tsx:150
#: apps/native/src/components/titles/status-action-button.tsx:104
#: apps/web/src/components/settings/account-section.tsx:477
#: apps/web/src/components/settings/backup-restore-section.tsx:101
#: apps/web/src/components/settings/backup-section.tsx:240
@@ -348,6 +349,7 @@ msgstr "No se puede contactar con el servidor"
#: apps/web/src/components/settings/imports-section.tsx:611
#: apps/web/src/components/settings/imports-section.tsx:674
#: apps/web/src/components/settings/imports-section.tsx:798
#: apps/web/src/components/titles/status-button.tsx:131
#: apps/web/src/components/titles/title-seasons.tsx:127
msgid "Cancel"
msgstr "Cancelar"
@@ -361,14 +363,20 @@ msgstr "Cancelar edición"
msgid "Cast"
msgstr "Reparto"
#: apps/web/src/components/titles/use-title-actions.ts:202
#: apps/web/src/components/titles/use-title-actions.ts:280
#: apps/web/src/components/titles/use-title-actions.ts:200
#: apps/web/src/components/titles/use-title-actions.ts:272
msgid "Catch up"
msgstr "Ponerse al día"
#: apps/native/src/components/titles/status-action-button.tsx:50
#: apps/web/src/components/title-card.tsx:74
#: apps/web/src/components/titles/status-button.tsx:54
msgid "Caught Up"
msgstr "Al día"
#. placeholder {0}: episodeIds.length
#. placeholder {1}: episodeIds.length
#: apps/web/src/components/titles/use-title-actions.ts:72
#: apps/web/src/components/titles/use-title-actions.ts:69
msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched"
msgstr "Al día — {0} {1, plural, one {episodio marcado como visto} other {episodios marcados como vistos}}"
@@ -418,7 +426,7 @@ msgstr "Elige cómo importar tus datos de {0}."
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:60
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:104
#: apps/native/src/components/search/recently-viewed-list.tsx:34
#: apps/native/src/components/search/recently-viewed-list.tsx:86
#: apps/native/src/components/search/recently-viewed-list.tsx:68
msgid "Clear"
msgstr "Limpiar"
@@ -455,10 +463,10 @@ msgid "Close"
msgstr "Cerrar"
#: apps/native/src/app/(tabs)/(home)/index.tsx:146
#: apps/native/src/components/titles/status-action-button.tsx:45
#: apps/native/src/components/titles/status-action-button.tsx:52
#: apps/web/src/components/dashboard/stats-display.tsx:219
#: apps/web/src/components/title-card.tsx:74
#: apps/web/src/components/titles/status-button.tsx:25
#: apps/web/src/components/title-card.tsx:79
#: apps/web/src/components/titles/status-button.tsx:59
msgid "Completed"
msgstr "Completado"
@@ -477,7 +485,7 @@ msgstr "Conectar"
msgid "Connect {0}"
msgstr "Conectar {0}"
#: apps/native/src/components/settings/integration-card.tsx:207
#: apps/native/src/components/settings/integration-card.tsx:216
msgid "Connect {label}"
msgstr "Conectar {label}"
@@ -485,7 +493,7 @@ msgstr "Conectar {label}"
msgid "Connect to {source}"
msgstr "Conectar con {source}"
#: apps/web/src/routes/setup.tsx:98
#: apps/web/src/routes/setup.tsx:99
msgid "Connect to TMDB"
msgstr "Conectar con TMDB"
@@ -516,7 +524,7 @@ msgstr "Conectando al servidor..."
msgid "Connecting..."
msgstr "Conectando..."
#: apps/native/src/components/settings/integration-card.tsx:207
#: apps/native/src/components/settings/integration-card.tsx:216
msgid "Connecting…"
msgstr "Conectando…"
@@ -545,7 +553,7 @@ msgstr "Copiar URL"
msgid "Could not load integrations"
msgstr "No se pudieron cargar las integraciones"
#: apps/native/src/app/person/[id].tsx:172
#: apps/native/src/app/person/[id].tsx:257
msgid "Could not load person details"
msgstr "No se pudieron cargar los detalles de la persona"
@@ -579,14 +587,14 @@ msgstr "Contraseña actual"
msgid "Current password is required"
msgstr "La contraseña actual es obligatoria"
#: apps/web/src/routes/_app/settings.tsx:216
#: apps/web/src/routes/_app/settings.tsx:218
msgid "Danger Zone"
msgstr "Zona de peligro"
#: apps/web/src/routes/__root.tsx:163
#: apps/web/src/routes/_app/people.$id.tsx:76
#: apps/web/src/routes/_app/titles.$id.tsx:119
#: apps/web/src/routes/_app/titles.$id.tsx:165
#: apps/web/src/routes/_app/people.$id.tsx:78
#: apps/web/src/routes/_app/titles.$id.tsx:120
#: apps/web/src/routes/_app/titles.$id.tsx:166
msgid "Dashboard"
msgstr "Panel"
@@ -630,29 +638,29 @@ msgstr "{0, plural, one {# archivo eliminado} other {# archivos eliminados}}, li
msgid "Device code expired. Please try again."
msgstr "El código del dispositivo ha expirado. Por favor, inténtalo de nuevo."
#: apps/native/src/app/person/[id].tsx:249
#: apps/native/src/app/person/[id].tsx:189
#: apps/web/src/components/people/person-hero.tsx:89
msgid "died at {age}"
msgstr "falleció a los {age}"
#: apps/native/src/app/person/[id].tsx:51
#: apps/native/src/app/person/[id].tsx:139
#: apps/native/src/components/search/recently-viewed-row-content.tsx:29
#: apps/web/src/components/people/person-hero.tsx:71
msgid "Director"
msgstr ""
msgstr "Director"
#: apps/web/src/components/settings/system-health-section.tsx:394
#: apps/web/src/components/settings/system-health-section.tsx:574
msgid "Disabled"
msgstr "Desactivado"
#: apps/native/src/components/settings/integration-card.tsx:143
#: apps/native/src/components/settings/integration-card.tsx:257
#: apps/native/src/components/settings/integration-card.tsx:152
#: apps/native/src/components/settings/integration-card.tsx:266
#: apps/web/src/components/settings/integration-card.tsx:234
msgid "Disconnect"
msgstr "Desconectar"
#: apps/native/src/components/settings/integration-card.tsx:138
#: apps/native/src/components/settings/integration-card.tsx:147
msgid "Disconnect {label}"
msgstr "Desconectar {label}"
@@ -685,11 +693,11 @@ msgstr "Descargar"
msgid "Download backup"
msgstr "Descargar copia de seguridad"
#: apps/native/src/app/person/[id].tsx:54
#: apps/native/src/app/person/[id].tsx:142
#: apps/native/src/components/search/recently-viewed-row-content.tsx:32
#: apps/web/src/components/people/person-hero.tsx:77
msgid "Editor"
msgstr ""
msgstr "Editor"
#: apps/native/src/app/(auth)/login.tsx:123
#: apps/native/src/app/(auth)/register.tsx:139
@@ -729,24 +737,31 @@ msgstr "Introduce la URL de tu servidor Sofa para comenzar"
msgid "Environment"
msgstr "Entorno"
#. placeholder {0}: episode.episodeNumber
#: apps/native/src/components/titles/episode-row.tsx:27
#: apps/native/src/components/titles/episode-row.tsx:48
msgid "Episode {0}"
msgstr "Episodio {0}"
#~ msgid "Episode {0}"
#~ msgstr "Episodio {0}"
#. placeholder {0}: episode.episodeNumber
#: apps/native/src/components/titles/episode-row.tsx:34
msgid "Episode {0}, {episodeLabel}"
msgstr "Episodio {0}, {episodeLabel}"
#~ msgid "Episode {0}, {episodeLabel}"
#~ msgstr "Episodio {0}, {episodeLabel}"
#: apps/native/src/hooks/use-title-actions.ts:111
#: apps/native/src/lib/title-actions.ts:108
#: apps/native/src/components/titles/episode-row.tsx:29
#: apps/native/src/components/titles/episode-row.tsx:52
msgid "Episode {episodeNumber}"
msgstr "Episodio {episodeNumber}"
#: apps/native/src/components/titles/episode-row.tsx:38
msgid "Episode {episodeNumber}, {episodeLabel}"
msgstr "Episodio {episodeNumber}, {episodeLabel}"
#: apps/native/src/hooks/use-title-actions.ts:109
#: apps/native/src/lib/title-actions.ts:84
msgid "Episode unwatched"
msgstr "Episodio marcado como no visto"
#: apps/native/src/hooks/use-title-actions.ts:101
#: apps/native/src/lib/title-actions.ts:98
#: apps/native/src/hooks/use-title-actions.ts:99
#: apps/native/src/lib/title-actions.ts:74
msgid "Episode watched"
msgstr "Episodio marcado como visto"
@@ -758,7 +773,7 @@ msgstr "Episodios"
#. placeholder {0}: periodLabels[episodePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx:125
msgid "Episodes {0}"
msgstr ""
msgstr "Episodios {0}"
#: apps/web/src/components/dashboard/stats-display.tsx:162
#~ msgid "Episodes {periodSelect}"
@@ -775,7 +790,7 @@ msgstr "Episodios {select}"
#: apps/native/src/app/change-password.tsx:67
#: apps/native/src/app/change-password.tsx:77
msgid "Error"
msgstr ""
msgstr "Error"
#. placeholder {0}: result.errors.length
#: apps/web/src/components/settings/imports-section.tsx:887
@@ -790,8 +805,8 @@ msgstr "Errores ({0})"
msgid "Explore"
msgstr "Explorar"
#: apps/web/src/routes/_app/people.$id.tsx:68
#: apps/web/src/routes/_app/titles.$id.tsx:157
#: apps/web/src/routes/_app/people.$id.tsx:70
#: apps/web/src/routes/_app/titles.$id.tsx:158
msgid "Explore titles"
msgstr "Explorar títulos"
@@ -804,7 +819,7 @@ msgstr "Fallido"
msgid "Failed to add to watchlist"
msgstr "Error al añadir a la lista"
#: apps/web/src/components/titles/use-title-actions.ts:80
#: apps/web/src/components/titles/use-title-actions.ts:77
msgid "Failed to catch up"
msgstr "Error al ponerse al día"
@@ -817,7 +832,7 @@ msgstr "Error al cambiar la contraseña"
msgid "Failed to connect"
msgstr "Error al conectar"
#: apps/native/src/components/settings/integration-card.tsx:87
#: apps/native/src/components/settings/integration-card.tsx:89
#: apps/web/src/components/settings/integration-card.tsx:91
msgid "Failed to connect {label}"
msgstr "Error al conectar {label}"
@@ -834,7 +849,7 @@ msgstr "Error al crear la copia de seguridad"
msgid "Failed to delete backup"
msgstr "Error al eliminar la copia de seguridad"
#: apps/native/src/components/settings/integration-card.tsx:97
#: apps/native/src/components/settings/integration-card.tsx:99
#: apps/web/src/components/settings/integration-card.tsx:108
msgid "Failed to disconnect {label}"
msgstr "Error al desconectar {label}"
@@ -843,29 +858,30 @@ msgstr "Error al desconectar {label}"
msgid "Failed to load backup schedule settings."
msgstr "Error al cargar los ajustes de programación de copias de seguridad."
#: apps/web/src/routes/_app/titles.$id.tsx:110
#: apps/web/src/routes/_app/titles.$id.tsx:111
msgid "Failed to load title"
msgstr "Error al cargar el título"
#: apps/web/src/components/titles/use-title-actions.ts:344
#: apps/native/src/lib/title-actions.ts:101
#: apps/web/src/components/titles/use-title-actions.ts:338
msgid "Failed to mark all episodes as watched"
msgstr "Error al marcar todos los episodios como vistos"
#: apps/native/src/hooks/use-title-actions.ts:79
#: apps/native/src/lib/title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:137
#: apps/native/src/hooks/use-title-actions.ts:77
#: apps/native/src/lib/title-actions.ts:43
#: apps/web/src/components/titles/use-title-actions.ts:134
msgid "Failed to mark as watched"
msgstr "Error al marcar como visto"
#: apps/native/src/hooks/use-title-actions.ts:104
#: apps/native/src/lib/title-actions.ts:101
#: apps/web/src/components/titles/use-title-actions.ts:216
#: apps/native/src/hooks/use-title-actions.ts:102
#: apps/native/src/lib/title-actions.ts:77
#: apps/web/src/components/titles/use-title-actions.ts:214
msgid "Failed to mark episode"
msgstr "Error al marcar el episodio"
#: apps/native/src/hooks/use-title-actions.ts:124
#: apps/native/src/lib/title-actions.ts:123
#: apps/web/src/components/titles/use-title-actions.ts:294
#: apps/native/src/hooks/use-title-actions.ts:122
#: apps/native/src/lib/title-actions.ts:113
#: apps/web/src/components/titles/use-title-actions.ts:286
msgid "Failed to mark some episodes"
msgstr "Error al marcar algunos episodios"
@@ -889,12 +905,12 @@ msgstr "Error al purgar la caché de imágenes"
msgid "Failed to purge metadata cache"
msgstr "Error al purgar la caché de metadatos"
#: apps/native/src/components/settings/integration-card.tsx:107
#: apps/native/src/components/settings/integration-card.tsx:109
#: apps/web/src/components/settings/integration-card.tsx:121
msgid "Failed to regenerate {label} URL"
msgstr "Error al regenerar la URL de {label}"
#: apps/native/src/lib/title-actions.ts:77
#: apps/native/src/lib/title-actions.ts:53
msgid "Failed to remove from library"
msgstr "Error al eliminar de la biblioteca"
@@ -916,13 +932,13 @@ msgstr "Error al iniciar la conexión con {0}"
msgid "Failed to trigger job"
msgstr "Error al iniciar la tarea"
#: apps/native/src/hooks/use-title-actions.ts:114
#: apps/native/src/lib/title-actions.ts:111
#: apps/web/src/components/titles/use-title-actions.ts:163
#: apps/native/src/hooks/use-title-actions.ts:112
#: apps/native/src/lib/title-actions.ts:87
#: apps/web/src/components/titles/use-title-actions.ts:161
msgid "Failed to unmark episode"
msgstr "Error al desmarcar el episodio"
#: apps/web/src/components/titles/use-title-actions.ts:320
#: apps/web/src/components/titles/use-title-actions.ts:312
msgid "Failed to unmark some episodes"
msgstr "Error al desmarcar algunos episodios"
@@ -930,9 +946,9 @@ msgstr "Error al desmarcar algunos episodios"
msgid "Failed to update name"
msgstr "Error al actualizar el nombre"
#: apps/native/src/hooks/use-title-actions.ts:94
#: apps/native/src/lib/title-actions.ts:91
#: apps/web/src/components/titles/use-title-actions.ts:123
#: apps/native/src/hooks/use-title-actions.ts:92
#: apps/native/src/lib/title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:120
msgid "Failed to update rating"
msgstr "Error al actualizar la valoración"
@@ -958,10 +974,8 @@ msgstr "Error al actualizar el ajuste de copia de seguridad programada"
msgid "Failed to update setting"
msgstr "Error al actualizar el ajuste"
#: apps/native/src/hooks/use-title-actions.ts:69
#: apps/native/src/lib/title-actions.ts:41
#: apps/native/src/lib/title-actions.ts:55
#: apps/web/src/components/titles/use-title-actions.ts:101
#: apps/native/src/hooks/use-title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:98
msgid "Failed to update status"
msgstr "Error al actualizar el estado"
@@ -973,7 +987,7 @@ msgstr "Error al subir el avatar"
msgid "Fetching your library data from {source}..."
msgstr "Obteniendo datos de tu biblioteca desde {source}..."
#: apps/native/src/app/person/[id].tsx:279
#: apps/native/src/app/person/[id].tsx:219
#: apps/web/src/components/people/filmography-grid.tsx:67
msgid "Filmography"
msgstr "Filmografía"
@@ -1002,8 +1016,8 @@ msgstr "Viernes"
msgid "Get Started"
msgstr "Comenzar"
#: apps/native/src/app/person/[id].tsx:176
#: apps/native/src/app/person/[id].tsx:196
#: apps/native/src/app/person/[id].tsx:261
#: apps/native/src/app/person/[id].tsx:281
#: apps/native/src/app/title/[id].tsx:235
msgid "Go back"
msgstr "Volver"
@@ -1112,6 +1126,11 @@ msgstr "En la biblioteca"
msgid "In Library"
msgstr "En la biblioteca"
#: apps/native/src/components/titles/status-action-button.tsx:46
#: apps/web/src/components/titles/status-button.tsx:40
msgid "In Watchlist"
msgstr "En lista de seguimiento"
#: apps/native/src/app/(tabs)/(home)/index.tsx:179
#: apps/web/src/components/dashboard/library-section.tsx:35
msgid "In Your Library"
@@ -1222,22 +1241,23 @@ msgid "Mark all episodes as watched?"
msgstr "¿Marcar todos los episodios como vistos?"
#: apps/native/src/components/titles/season-accordion.tsx:152
#: apps/native/src/components/ui/poster-card.tsx:229
#: apps/web/src/components/titles/title-seasons.tsx:109
#: apps/web/src/components/titles/title-seasons.tsx:135
msgid "Mark All Watched"
msgstr "Marcar todos como vistos"
#: apps/native/src/components/dashboard/continue-watching-card.tsx:103
msgid "Mark as Completed"
msgstr "Marcar como completado"
#~ msgid "Mark as Completed"
#~ msgstr "Marcar como completado"
#: apps/native/src/components/ui/poster-card.tsx:226
#: apps/native/src/components/ui/poster-card.tsx:222
msgid "Mark as Watched"
msgstr "Marcar como visto"
#: apps/native/src/components/ui/poster-card.tsx:219
msgid "Mark as Watching"
msgstr "Marcar como en curso"
#~ msgid "Mark as Watching"
#~ msgstr "Marcar como en curso"
#: apps/native/src/app/title/[id].tsx:400
#: apps/web/src/components/titles/title-actions.tsx:27
@@ -1245,32 +1265,37 @@ msgid "Mark Watched"
msgstr "Marcar como visto"
#: apps/native/src/lib/title-actions.ts:50
msgid "Marked \"{titleName}\" as completed"
msgstr "\"{titleName}\" marcado como completado"
#~ msgid "Marked \"{titleName}\" as completed"
#~ msgstr "\"{titleName}\" marcado como completado"
#: apps/native/src/lib/title-actions.ts:63
#: apps/web/src/components/titles/use-title-actions.ts:134
#: apps/native/src/lib/title-actions.ts:39
#: apps/web/src/components/titles/use-title-actions.ts:131
msgid "Marked \"{titleName}\" as watched"
msgstr "\"{titleName}\" marcado como visto"
#: apps/web/src/components/titles/use-title-actions.ts:337
#: apps/native/src/lib/title-actions.ts:97
#: apps/web/src/components/titles/use-title-actions.ts:331
msgid "Marked all episodes as watched"
msgstr "Todos los episodios marcados como vistos"
#: apps/native/src/lib/title-actions.ts:96
msgid "Marked all episodes of \"{titleName}\" as watched"
msgstr "Se marcaron todos los episodios de \"{titleName}\" como vistos"
#: apps/native/src/hooks/use-title-actions.ts:61
#: apps/native/src/lib/title-actions.ts:51
msgid "Marked as completed"
msgstr "Marcado como completado"
#~ msgid "Marked as completed"
#~ msgstr "Marcado como completado"
#: apps/native/src/hooks/use-title-actions.ts:76
#: apps/native/src/lib/title-actions.ts:63
#: apps/native/src/hooks/use-title-actions.ts:74
#: apps/native/src/lib/title-actions.ts:39
msgid "Marked as watched"
msgstr "Marcado como visto"
#: apps/native/src/hooks/use-title-actions.ts:60
#: apps/native/src/lib/title-actions.ts:38
msgid "Marked as watching"
msgstr "Marcado como en curso"
#~ msgid "Marked as watching"
#~ msgstr "Marcado como en curso"
#: apps/web/src/components/settings/account-section.tsx:314
msgid "Member since {memberSince}"
@@ -1305,7 +1330,7 @@ msgstr "Películas"
#. placeholder {0}: periodLabels[moviePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx:114
msgid "Movies {0}"
msgstr ""
msgstr "Películas {0}"
#: apps/web/src/components/dashboard/stats-display.tsx:161
#~ msgid "Movies {periodSelect}"
@@ -1345,7 +1370,7 @@ msgstr "Nunca ejecutado"
msgid "New account creation is currently disabled."
msgstr "La creación de nuevas cuentas está desactivada actualmente."
#: apps/web/src/routes/_auth/register.tsx:36
#: apps/web/src/routes/_auth/register.tsx:33
msgid "New accounts are not being accepted right now. Contact the admin if you need access."
msgstr "No se aceptan nuevas cuentas en este momento. Contacta al administrador si necesitas acceso."
@@ -1403,7 +1428,7 @@ msgstr "No se encontraron resultados."
msgid "No titles found for this genre."
msgstr "No se encontraron títulos para este género."
#: apps/native/src/components/settings/integration-card.tsx:174
#: apps/native/src/components/settings/integration-card.tsx:183
#: apps/web/src/components/settings/integration-card.tsx:153
#: apps/web/src/components/settings/system-health-section.tsx:229
msgid "Not configured"
@@ -1517,8 +1542,8 @@ msgstr "Comprobar periódicamente GitHub para nuevas versiones de Sofa"
msgid "Person"
msgstr "Persona"
#: apps/native/src/app/person/[id].tsx:192
#: apps/web/src/routes/_app/people.$id.tsx:50
#: apps/native/src/app/person/[id].tsx:277
#: apps/web/src/routes/_app/people.$id.tsx:52
msgid "Person not found"
msgstr "Persona no encontrada"
@@ -1527,12 +1552,12 @@ msgid "Play trailer"
msgstr "Reproducir tráiler"
#: apps/native/src/app/(tabs)/(explore)/index.tsx:89
#: apps/web/src/routes/_app/explore.tsx:141
#: apps/web/src/routes/_app/explore.tsx:143
msgid "Popular Movies"
msgstr "Películas populares"
#: apps/native/src/app/(tabs)/(explore)/index.tsx:102
#: apps/web/src/routes/_app/explore.tsx:151
#: apps/web/src/routes/_app/explore.tsx:153
msgid "Popular TV Shows"
msgstr "Series populares"
@@ -1540,7 +1565,7 @@ msgstr "Series populares"
msgid "Pre-restore backup"
msgstr "Copia de seguridad previa a restauración"
#: apps/native/src/app/person/[id].tsx:53
#: apps/native/src/app/person/[id].tsx:141
#: apps/native/src/components/search/recently-viewed-row-content.tsx:31
#: apps/web/src/components/people/person-hero.tsx:75
msgid "Producer"
@@ -1612,7 +1637,7 @@ msgstr "URL de lista de Radarr"
#. placeholder {0}: input.stars
#. placeholder {1}: input.stars
#: apps/native/src/hooks/use-title-actions.ts:88
#: apps/native/src/hooks/use-title-actions.ts:86
msgid "Rated {0} {1, plural, one {star} other {stars}}"
msgstr "Valorado con {0} {1, plural, one {estrella} other {estrellas}}"
@@ -1620,11 +1645,11 @@ msgstr "Valorado con {0} {1, plural, one {estrella} other {estrellas}}"
#~ msgid "Rated {0} star{1}"
#~ msgstr "Rated {0} star{1}"
#: apps/web/src/components/titles/use-title-actions.ts:118
#: apps/web/src/components/titles/use-title-actions.ts:115
msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}"
msgstr "Valorado con {ratingStars} {ratingStars, plural, one {estrella} other {estrellas}}"
#: apps/native/src/lib/title-actions.ts:86
#: apps/native/src/lib/title-actions.ts:62
msgid "Rated {stars, plural, one {# star} other {# stars}}"
msgstr "Valorado con {stars, plural, one {# estrella} other {# estrellas}}"
@@ -1633,9 +1658,9 @@ msgstr "Valorado con {stars, plural, one {# estrella} other {# estrellas}}"
msgid "Rating"
msgstr "Valoración"
#: apps/native/src/hooks/use-title-actions.ts:89
#: apps/native/src/lib/title-actions.ts:87
#: apps/web/src/components/titles/use-title-actions.ts:119
#: apps/native/src/hooks/use-title-actions.ts:87
#: apps/native/src/lib/title-actions.ts:63
#: apps/web/src/components/titles/use-title-actions.ts:116
msgid "Rating removed"
msgstr "Valoración eliminada"
@@ -1663,7 +1688,7 @@ msgid "Recent Searches"
msgstr "Búsquedas recientes"
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:95
#: apps/native/src/components/search/recently-viewed-list.tsx:77
#: apps/native/src/components/search/recently-viewed-list.tsx:59
msgid "Recently Viewed"
msgstr "Vistos recientemente"
@@ -1692,12 +1717,12 @@ msgstr "Actualizar"
msgid "Refresh system health"
msgstr "Actualizar estado del sistema"
#: apps/native/src/components/settings/integration-card.tsx:128
#: apps/native/src/components/settings/integration-card.tsx:248
#: apps/native/src/components/settings/integration-card.tsx:137
#: apps/native/src/components/settings/integration-card.tsx:257
msgid "Regenerate"
msgstr "Regenerar"
#: apps/native/src/components/settings/integration-card.tsx:123
#: apps/native/src/components/settings/integration-card.tsx:132
#: apps/web/src/components/settings/integration-card.tsx:226
msgid "Regenerate URL"
msgstr "Regenerar URL"
@@ -1717,7 +1742,7 @@ msgid "Registration closed"
msgstr "Registro cerrado"
#: apps/native/src/app/(auth)/register.tsx:87
#: apps/web/src/routes/_auth/register.tsx:33
#: apps/web/src/routes/_auth/register.tsx:30
msgid "Registration Closed"
msgstr "Registro cerrado"
@@ -1726,20 +1751,27 @@ msgstr "Registro cerrado"
msgid "Registration opened"
msgstr "Registro abierto"
#: apps/web/src/components/titles/status-button.tsx:76
#: apps/native/src/components/titles/status-action-button.tsx:106
#: apps/web/src/components/titles/status-button.tsx:109
#: apps/web/src/components/titles/status-button.tsx:139
msgid "Remove"
msgstr "Eliminar"
#: apps/native/src/components/titles/status-action-button.tsx:96
#: apps/web/src/components/titles/status-button.tsx:60
#: apps/native/src/components/titles/status-action-button.tsx:115
#: apps/web/src/components/titles/status-button.tsx:93
msgid "Remove from library"
msgstr "Eliminar de la biblioteca"
#: apps/native/src/components/dashboard/continue-watching-card.tsx:108
#: apps/native/src/components/ui/poster-card.tsx:233
#: apps/native/src/components/ui/poster-card.tsx:236
msgid "Remove from Library"
msgstr "Eliminar de la biblioteca"
#: apps/native/src/components/titles/status-action-button.tsx:101
#: apps/web/src/components/titles/status-button.tsx:120
msgid "Remove from library?"
msgstr "¿Eliminar de la biblioteca?"
#: apps/native/src/app/(tabs)/(settings)/index.tsx:268
msgid "Remove Photo"
msgstr "Eliminar foto"
@@ -1752,9 +1784,9 @@ msgstr "Eliminar foto"
msgid "Remove profile picture"
msgstr "Eliminar foto de perfil"
#: apps/native/src/hooks/use-title-actions.ts:65
#: apps/native/src/lib/title-actions.ts:74
#: apps/web/src/components/titles/use-title-actions.ts:98
#: apps/native/src/hooks/use-title-actions.ts:63
#: apps/native/src/lib/title-actions.ts:50
#: apps/web/src/components/titles/use-title-actions.ts:95
msgid "Removed from library"
msgstr "Eliminado de la biblioteca"
@@ -1861,14 +1893,14 @@ msgstr "Copias de seguridad programadas activadas"
#: apps/native/src/app/(tabs)/(search)/_layout.tsx:7
#: apps/native/src/components/navigation/native-tab-bar.tsx:41
msgid "Search"
msgstr ""
msgstr "Buscar"
#: apps/web/src/components/dashboard/stats-section.tsx:35
msgid "Search for movies and TV shows to start tracking"
msgstr "Busca películas y series para empezar a seguirlas"
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:72
#: apps/native/src/components/search/recently-viewed-list.tsx:55
#: apps/native/src/components/search/recently-viewed-list.tsx:81
msgid "Search for movies, shows, or people"
msgstr "Busca películas, series o personas"
@@ -1892,13 +1924,13 @@ msgstr "Buscar…"
#. placeholder {0}: season.seasonNumber
#: apps/native/src/components/titles/season-accordion.tsx:113
#: apps/native/src/components/titles/season-accordion.tsx:119
#: apps/web/src/components/titles/use-title-actions.ts:274
#: apps/web/src/components/titles/use-title-actions.ts:313
#: apps/web/src/components/titles/use-title-actions.ts:266
#: apps/web/src/components/titles/use-title-actions.ts:305
msgid "Season {0}"
msgstr "Temporada {0}"
#: apps/native/src/hooks/use-title-actions.ts:121
#: apps/native/src/lib/title-actions.ts:119
#: apps/native/src/hooks/use-title-actions.ts:119
#: apps/native/src/lib/title-actions.ts:109
msgid "Season watched"
msgstr "Temporada marcada como vista"
@@ -1907,7 +1939,7 @@ msgid "Seasons"
msgstr "Temporadas"
#: apps/native/src/app/(tabs)/(settings)/index.tsx:452
#: apps/web/src/routes/_app/settings.tsx:167
#: apps/web/src/routes/_app/settings.tsx:169
msgid "Security"
msgstr "Seguridad"
@@ -1915,7 +1947,7 @@ msgstr "Seguridad"
msgid "Self-hosted movie & TV tracker"
msgstr "Seguimiento de películas y series autoalojado"
#: apps/web/src/routes/_app/settings.tsx:151
#: apps/web/src/routes/_app/settings.tsx:153
msgid "Server"
msgstr "Servidor"
@@ -1947,12 +1979,12 @@ msgstr "Configura tu perfil de calidad y carpeta raíz preferidos"
msgid "Settings"
msgstr "Ajustes"
#: apps/native/src/components/settings/integration-card.tsx:271
#: apps/native/src/components/settings/integration-card.tsx:280
#: apps/web/src/components/settings/integration-card.tsx:248
msgid "Setup instructions"
msgstr "Instrucciones de configuración"
#: apps/web/src/routes/setup.tsx:95
#: apps/web/src/routes/setup.tsx:96
msgid "Setup required"
msgstr "Configuración requerida"
@@ -1977,7 +2009,7 @@ msgstr "Iniciar sesión"
msgid "Sign In"
msgstr "Iniciar sesión"
#: apps/web/src/routes/_auth/register.tsx:45
#: apps/web/src/routes/_auth/register.tsx:42
msgid "Sign in instead"
msgstr "Iniciar sesión"
@@ -2031,13 +2063,13 @@ msgid "Sofa will automatically log movies and episodes when you finish watching
msgstr "Sofa registrará automáticamente películas y episodios cuando termines de verlos"
#: apps/native/src/app/change-password.tsx:77
#: apps/native/src/app/person/[id].tsx:169
#: apps/native/src/app/person/[id].tsx:254
#: apps/web/src/components/settings/account-section.tsx:391
#: apps/web/src/routes/__root.tsx:139
msgid "Something went wrong"
msgstr "Algo salió mal"
#: apps/web/src/routes/_app/titles.$id.tsx:113
#: apps/web/src/routes/_app/titles.$id.tsx:114
msgid "Something went wrong while loading this title. Please try again."
msgstr "Algo salió mal al cargar este título. Por favor, inténtalo de nuevo."
@@ -2070,7 +2102,7 @@ msgstr "Comenzando a las"
msgid "Starting import..."
msgstr "Iniciando importación..."
#: apps/native/src/hooks/use-title-actions.ts:64
#: apps/native/src/hooks/use-title-actions.ts:62
msgid "Status updated"
msgstr "Estado actualizado"
@@ -2095,11 +2127,11 @@ msgstr "Cambiar a {0}"
msgid "The page you're looking for doesn't exist."
msgstr "La página que buscas no existe."
#: apps/web/src/routes/_app/people.$id.tsx:53
#: apps/web/src/routes/_app/people.$id.tsx:55
msgid "The person you're looking for doesn't exist or may have been removed from the database."
msgstr "La persona que buscas no existe o puede haber sido eliminada de la base de datos."
#: apps/web/src/routes/_app/titles.$id.tsx:142
#: apps/web/src/routes/_app/titles.$id.tsx:143
msgid "The title you're looking for doesn't exist or may have been removed from the database."
msgstr "El título que buscas no existe o puede haber sido eliminado de la base de datos."
@@ -2109,7 +2141,7 @@ msgstr "Esto puede tardar unos minutos para bibliotecas grandes. Por favor, no c
#: apps/native/src/app/(tabs)/(home)/index.tsx:89
msgid "this month"
msgstr ""
msgstr "este mes"
#: apps/native/src/components/dashboard/stats-card.tsx:31
#: apps/web/src/components/dashboard/stats-display.tsx:135
@@ -2121,14 +2153,19 @@ msgid "This page was left on the cutting room floor. It may have been moved, rem
msgstr "Esta página quedó en la sala de montaje. Puede que haya sido movida, eliminada o que nunca pasara del guion."
#: apps/native/src/app/(tabs)/(settings)/index.tsx:559
#: apps/web/src/routes/_app/settings.tsx:112
#: apps/web/src/routes/setup.tsx:180
#: apps/web/src/routes/_app/settings.tsx:114
#: apps/web/src/routes/setup.tsx:181
msgid "This product uses the TMDB API but is not endorsed or certified by TMDB."
msgstr "Este producto utiliza la API de TMDB pero no está respaldado ni certificado por TMDB."
#: apps/native/src/components/titles/status-action-button.tsx:102
#: apps/web/src/components/titles/status-button.tsx:123
msgid "This title will be removed from your library. Your watch history and ratings will be kept."
msgstr "Este título será eliminado de tu biblioteca. Tu historial de visualización y calificaciones se conservarán."
#: apps/native/src/app/(tabs)/(home)/index.tsx:88
msgid "this week"
msgstr ""
msgstr "esta semana"
#: apps/native/src/components/dashboard/stats-card.tsx:30
#: apps/web/src/components/dashboard/stats-display.tsx:134
@@ -2147,7 +2184,7 @@ msgstr "Esto eliminará todos los títulos parciales sin enriquecer y todas las
msgid "This will delete un-enriched stub titles that aren't in any user's library and clean up orphaned person records. Deleted titles will be re-imported if accessed again."
msgstr "Esto eliminará los títulos parciales sin enriquecer que no estén en la biblioteca de ningún usuario y limpiará los registros de personas huérfanas. Los títulos eliminados se reimportarán si se accede a ellos de nuevo."
#: apps/native/src/components/settings/integration-card.tsx:124
#: apps/native/src/components/settings/integration-card.tsx:133
msgid "This will invalidate the current {label} URL. You'll need to update it in {label}."
msgstr "Esto invalidará la URL actual de {label}. Tendrás que actualizarla en {label}."
@@ -2171,7 +2208,7 @@ msgstr "Esto reemplazará toda tu base de datos con el archivo subido. Primero s
#: apps/native/src/app/(tabs)/(home)/index.tsx:90
msgid "this year"
msgstr ""
msgstr "este año"
#: apps/native/src/components/dashboard/stats-card.tsx:32
#: apps/web/src/components/dashboard/stats-display.tsx:136
@@ -2187,7 +2224,7 @@ msgid "Time:"
msgstr "Hora:"
#: apps/native/src/app/title/[id].tsx:231
#: apps/web/src/routes/_app/titles.$id.tsx:139
#: apps/web/src/routes/_app/titles.$id.tsx:140
msgid "Title not found"
msgstr "Título no encontrado"
@@ -2203,7 +2240,7 @@ msgstr "Los títulos de tu lista de Sofa se añadirán automáticamente para des
#: apps/native/src/app/(tabs)/(home)/index.tsx:87
msgid "today"
msgstr ""
msgstr "hoy"
#: apps/native/src/components/dashboard/stats-card.tsx:29
#: apps/web/src/components/dashboard/stats-display.tsx:133
@@ -2236,7 +2273,7 @@ msgid "Trending today"
msgstr "Tendencia hoy"
#: apps/native/src/app/(tabs)/(explore)/index.tsx:77
#: apps/web/src/routes/_app/explore.tsx:129
#: apps/web/src/routes/_app/explore.tsx:131
msgid "Trending Today"
msgstr "Tendencias hoy"
@@ -2291,11 +2328,11 @@ msgid "Unwatch all"
msgstr "Desmarcar todo"
#. placeholder {0}: season.name ?? t`Season ${season.seasonNumber}`
#: apps/web/src/components/titles/use-title-actions.ts:313
#: apps/web/src/components/titles/use-title-actions.ts:305
msgid "Unwatched all of {0}"
msgstr "Todo de {0} marcado como no visto"
#: apps/web/src/components/titles/use-title-actions.ts:156
#: apps/web/src/components/titles/use-title-actions.ts:154
msgid "Unwatched S{seasonNum} E{epNum}"
msgstr "No visto T{seasonNum} E{epNum}"
@@ -2366,7 +2403,7 @@ msgstr "Subir foto"
msgid "Upload profile picture"
msgstr "Subir foto de perfil"
#: apps/native/src/components/settings/integration-card.tsx:117
#: apps/native/src/components/settings/integration-card.tsx:125
msgid "URL copied to clipboard"
msgstr "URL copiada al portapapeles"
@@ -2399,36 +2436,36 @@ msgstr "Historial de visionado"
msgid "Watch on {name}"
msgstr "Ver en {name}"
#: apps/web/src/components/titles/use-title-actions.ts:277
#: apps/web/src/components/titles/use-title-actions.ts:286
#: apps/web/src/components/titles/use-title-actions.ts:269
#: apps/web/src/components/titles/use-title-actions.ts:278
msgid "Watched all of {seasonLabel}"
msgstr "Visto todo de {seasonLabel}"
#: apps/native/src/lib/title-actions.ts:119
#: apps/native/src/lib/title-actions.ts:109
msgid "Watched all of {seasonName}"
msgstr "Visto todo de {seasonName}"
#: apps/web/src/components/titles/use-title-actions.ts:199
#: apps/web/src/components/titles/use-title-actions.ts:208
#: apps/web/src/components/titles/use-title-actions.ts:197
#: apps/web/src/components/titles/use-title-actions.ts:206
msgid "Watched S{seasonNum} E{epNum}"
msgstr "Visto T{seasonNum} E{epNum}"
#: apps/native/src/components/titles/status-action-button.tsx:43
#: apps/native/src/components/titles/status-action-button.tsx:48
#: apps/web/src/components/title-card.tsx:69
#: apps/web/src/components/titles/status-button.tsx:14
#: apps/web/src/components/titles/status-button.tsx:47
msgid "Watching"
msgstr "Viendo"
#: apps/native/src/components/titles/status-action-button.tsx:78
#: apps/native/src/components/titles/status-action-button.tsx:85
#: apps/web/src/components/settings/imports-section.tsx:743
#: apps/web/src/components/settings/imports-section.tsx:769
#: apps/web/src/components/titles/status-button.tsx:49
#: apps/web/src/components/titles/status-button.tsx:82
msgid "Watchlist"
msgstr "Lista"
#: apps/native/src/components/titles/status-action-button.tsx:41
msgid "Watchlisted"
msgstr "En lista"
#~ msgid "Watchlisted"
#~ msgstr "En lista"
#: apps/native/src/components/settings/integration-configs.ts:51
#: apps/native/src/components/settings/integration-configs.ts:66
@@ -2458,7 +2495,7 @@ msgstr "Dónde ver"
msgid "With Ads"
msgstr "Con anuncios"
#: apps/native/src/app/person/[id].tsx:52
#: apps/native/src/app/person/[id].tsx:140
#: apps/native/src/components/search/recently-viewed-row-content.tsx:30
#: apps/web/src/components/people/person-hero.tsx:73
msgid "Writer"
File diff suppressed because one or more lines are too long
+205 -168
View File
@@ -26,7 +26,7 @@ msgstr "...et {0} de plus"
#. placeholder {0}: systemHealth.data.imageCache.imageCount
#: apps/native/src/app/(tabs)/(settings)/index.tsx:438
msgid "{0, plural, one {# image} other {# images}}"
msgstr ""
msgstr "{0, plural, one {# image} other {# images}}"
#. placeholder {0}: systemHealth.data.database.titleCount
#: apps/native/src/app/(tabs)/(settings)/index.tsx:424
@@ -104,8 +104,8 @@ msgstr "{0}/{1} {2, plural, one {épisode} other {épisodes}}"
#~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/titles/use-title-actions.ts:200
#: apps/web/src/components/titles/use-title-actions.ts:278
#: apps/web/src/components/titles/use-title-actions.ts:198
#: apps/web/src/components/titles/use-title-actions.ts:270
msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
msgstr "{count} {count, plural, one {épisode précédent non visionné} other {épisodes précédents non visionnés}}"
@@ -114,22 +114,22 @@ msgstr "{count} {count, plural, one {épisode précédent non visionné} other {
msgid "{healthyCount} of {0} jobs healthy"
msgstr "{healthyCount} sur {0} tâches en bonne santé"
#: apps/native/src/components/settings/integration-card.tsx:84
#: apps/native/src/components/settings/integration-card.tsx:86
#: apps/web/src/components/settings/integration-card.tsx:89
msgid "{label} connected"
msgstr "{label} connecté"
#: apps/native/src/components/settings/integration-card.tsx:94
#: apps/native/src/components/settings/integration-card.tsx:96
#: apps/web/src/components/settings/integration-card.tsx:105
msgid "{label} disconnected"
msgstr "{label} déconnecté"
#: apps/native/src/components/settings/integration-card.tsx:104
#: apps/native/src/components/settings/integration-card.tsx:106
#: apps/web/src/components/settings/integration-card.tsx:119
msgid "{label} URL regenerated"
msgstr "URL {label} régénérée"
#: apps/web/src/components/title-card.tsx:152
#: apps/web/src/components/title-card.tsx:157
msgid "{watched}/{total} episodes"
msgstr "{watched}/{total} épisodes"
@@ -155,9 +155,9 @@ msgstr "Compte"
#: apps/web/src/components/settings/system-health-section.tsx:378
msgid "Actions"
msgstr ""
msgstr "Actions"
#: apps/native/src/app/person/[id].tsx:50
#: apps/native/src/app/person/[id].tsx:138
#: apps/native/src/components/search/recently-viewed-row-content.tsx:28
#: apps/web/src/components/people/person-hero.tsx:69
msgid "Actor"
@@ -180,13 +180,13 @@ msgstr "Ajoutez un nouveau webhook et collez l'URL ci-dessus"
msgid "Add to Library"
msgstr "Ajouter à la bibliothèque"
#: apps/native/src/components/titles/status-action-button.tsx:73
#: apps/native/src/components/titles/status-action-button.tsx:80
msgid "Add to watchlist"
msgstr "Ajouter à la liste de suivi"
#: apps/native/src/components/explore/hero-banner.tsx:132
#: apps/native/src/components/ui/poster-card.tsx:212
#: apps/web/src/components/title-card.tsx:133
#: apps/native/src/components/ui/poster-card.tsx:215
#: apps/web/src/components/title-card.tsx:138
msgid "Add to Watchlist"
msgstr "Ajouter à la liste de suivi"
@@ -197,7 +197,7 @@ msgstr "« {titleName} » ajouté à la liste de suivi"
#: apps/native/src/hooks/use-title-actions.ts:44
#: apps/native/src/hooks/use-title-actions.ts:59
#: apps/native/src/lib/title-actions.ts:25
#: apps/web/src/components/titles/use-title-actions.ts:98
#: apps/web/src/components/titles/use-title-actions.ts:95
msgid "Added to watchlist"
msgstr "Ajouté à la liste de suivi"
@@ -207,13 +207,13 @@ msgstr "Ajouté à la liste de suivi"
#: apps/web/src/components/nav-bar.tsx:223
#: apps/web/src/components/settings/account-section.tsx:309
msgid "Admin"
msgstr ""
msgstr "Admin"
#: apps/web/src/routes/_app/settings.tsx:154
#: apps/web/src/routes/_app/settings.tsx:156
msgid "Admin only"
msgstr "Admins uniquement"
#: apps/native/src/app/person/[id].tsx:249
#: apps/native/src/app/person/[id].tsx:189
#: apps/web/src/components/people/person-hero.tsx:89
msgid "age {age}"
msgstr "âge {age}"
@@ -243,15 +243,15 @@ msgstr "Une erreur inattendue s'est produite lors du chargement de cette page. V
msgid "Anonymous usage reporting"
msgstr "Rapports d'utilisation anonymes"
#: apps/web/src/routes/_app/settings.tsx:135
#: apps/web/src/routes/_app/settings.tsx:137
msgid "App Settings"
msgstr "Paramètres de l'application"
#: apps/native/src/app/(tabs)/(settings)/index.tsx:362
msgid "Application"
msgstr ""
msgstr "Application"
#: apps/native/src/components/settings/integration-card.tsx:139
#: apps/native/src/components/settings/integration-card.tsx:148
msgid "Are you sure you want to disconnect {label}? The current URL will stop working."
msgstr "Voulez-vous vraiment déconnecter {label} ? L'URL actuelle cessera de fonctionner."
@@ -310,7 +310,7 @@ msgid "Backup schedule"
msgstr "Planning de sauvegarde"
#: apps/web/src/components/settings/system-health-section.tsx:583
#: apps/web/src/routes/_app/settings.tsx:190
#: apps/web/src/routes/_app/settings.tsx:192
msgid "Backups"
msgstr "Sauvegardes"
@@ -337,8 +337,9 @@ msgstr "Impossible de joindre le serveur"
#: apps/native/src/components/header-avatar.tsx:63
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:58
#: apps/native/src/components/search/recently-viewed-list.tsx:32
#: apps/native/src/components/settings/integration-card.tsx:126
#: apps/native/src/components/settings/integration-card.tsx:141
#: apps/native/src/components/settings/integration-card.tsx:135
#: apps/native/src/components/settings/integration-card.tsx:150
#: apps/native/src/components/titles/status-action-button.tsx:104
#: apps/web/src/components/settings/account-section.tsx:477
#: apps/web/src/components/settings/backup-restore-section.tsx:101
#: apps/web/src/components/settings/backup-section.tsx:240
@@ -348,6 +349,7 @@ msgstr "Impossible de joindre le serveur"
#: apps/web/src/components/settings/imports-section.tsx:611
#: apps/web/src/components/settings/imports-section.tsx:674
#: apps/web/src/components/settings/imports-section.tsx:798
#: apps/web/src/components/titles/status-button.tsx:131
#: apps/web/src/components/titles/title-seasons.tsx:127
msgid "Cancel"
msgstr "Annuler"
@@ -361,14 +363,20 @@ msgstr "Annuler la modification"
msgid "Cast"
msgstr "Distribution"
#: apps/web/src/components/titles/use-title-actions.ts:202
#: apps/web/src/components/titles/use-title-actions.ts:280
#: apps/web/src/components/titles/use-title-actions.ts:200
#: apps/web/src/components/titles/use-title-actions.ts:272
msgid "Catch up"
msgstr "Rattraper"
#: apps/native/src/components/titles/status-action-button.tsx:50
#: apps/web/src/components/title-card.tsx:74
#: apps/web/src/components/titles/status-button.tsx:54
msgid "Caught Up"
msgstr "À jour"
#. placeholder {0}: episodeIds.length
#. placeholder {1}: episodeIds.length
#: apps/web/src/components/titles/use-title-actions.ts:72
#: apps/web/src/components/titles/use-title-actions.ts:69
msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched"
msgstr "Rattrapé — {0} {1, plural, one {épisode marqué comme visionné} other {épisodes marqués comme visionnés}}"
@@ -418,7 +426,7 @@ msgstr "Choisissez comment importer vos données {0}."
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:60
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:104
#: apps/native/src/components/search/recently-viewed-list.tsx:34
#: apps/native/src/components/search/recently-viewed-list.tsx:86
#: apps/native/src/components/search/recently-viewed-list.tsx:68
msgid "Clear"
msgstr "Effacer"
@@ -455,10 +463,10 @@ msgid "Close"
msgstr "Fermer"
#: apps/native/src/app/(tabs)/(home)/index.tsx:146
#: apps/native/src/components/titles/status-action-button.tsx:45
#: apps/native/src/components/titles/status-action-button.tsx:52
#: apps/web/src/components/dashboard/stats-display.tsx:219
#: apps/web/src/components/title-card.tsx:74
#: apps/web/src/components/titles/status-button.tsx:25
#: apps/web/src/components/title-card.tsx:79
#: apps/web/src/components/titles/status-button.tsx:59
msgid "Completed"
msgstr "Terminé"
@@ -477,7 +485,7 @@ msgstr "Connecter"
msgid "Connect {0}"
msgstr "Connecter {0}"
#: apps/native/src/components/settings/integration-card.tsx:207
#: apps/native/src/components/settings/integration-card.tsx:216
msgid "Connect {label}"
msgstr "Connecter {label}"
@@ -485,7 +493,7 @@ msgstr "Connecter {label}"
msgid "Connect to {source}"
msgstr "Se connecter à {source}"
#: apps/web/src/routes/setup.tsx:98
#: apps/web/src/routes/setup.tsx:99
msgid "Connect to TMDB"
msgstr "Se connecter à TMDB"
@@ -516,7 +524,7 @@ msgstr "Connexion au serveur..."
msgid "Connecting..."
msgstr "Connexion..."
#: apps/native/src/components/settings/integration-card.tsx:207
#: apps/native/src/components/settings/integration-card.tsx:216
msgid "Connecting…"
msgstr "Connexion…"
@@ -545,7 +553,7 @@ msgstr "Copier l'URL"
msgid "Could not load integrations"
msgstr "Impossible de charger les intégrations"
#: apps/native/src/app/person/[id].tsx:172
#: apps/native/src/app/person/[id].tsx:257
msgid "Could not load person details"
msgstr "Impossible de charger les détails de la personne"
@@ -579,14 +587,14 @@ msgstr "Mot de passe actuel"
msgid "Current password is required"
msgstr "Le mot de passe actuel est requis"
#: apps/web/src/routes/_app/settings.tsx:216
#: apps/web/src/routes/_app/settings.tsx:218
msgid "Danger Zone"
msgstr "Zone de danger"
#: apps/web/src/routes/__root.tsx:163
#: apps/web/src/routes/_app/people.$id.tsx:76
#: apps/web/src/routes/_app/titles.$id.tsx:119
#: apps/web/src/routes/_app/titles.$id.tsx:165
#: apps/web/src/routes/_app/people.$id.tsx:78
#: apps/web/src/routes/_app/titles.$id.tsx:120
#: apps/web/src/routes/_app/titles.$id.tsx:166
msgid "Dashboard"
msgstr "Tableau de bord"
@@ -630,12 +638,12 @@ msgstr "{0, plural, one {# fichier supprimé} other {# fichiers supprimés}}, {f
msgid "Device code expired. Please try again."
msgstr "Le code d'appareil a expiré. Veuillez réessayer."
#: apps/native/src/app/person/[id].tsx:249
#: apps/native/src/app/person/[id].tsx:189
#: apps/web/src/components/people/person-hero.tsx:89
msgid "died at {age}"
msgstr "décédé à {age} ans"
#: apps/native/src/app/person/[id].tsx:51
#: apps/native/src/app/person/[id].tsx:139
#: apps/native/src/components/search/recently-viewed-row-content.tsx:29
#: apps/web/src/components/people/person-hero.tsx:71
msgid "Director"
@@ -646,13 +654,13 @@ msgstr "Réalisateur"
msgid "Disabled"
msgstr "Désactivé"
#: apps/native/src/components/settings/integration-card.tsx:143
#: apps/native/src/components/settings/integration-card.tsx:257
#: apps/native/src/components/settings/integration-card.tsx:152
#: apps/native/src/components/settings/integration-card.tsx:266
#: apps/web/src/components/settings/integration-card.tsx:234
msgid "Disconnect"
msgstr "Déconnecter"
#: apps/native/src/components/settings/integration-card.tsx:138
#: apps/native/src/components/settings/integration-card.tsx:147
msgid "Disconnect {label}"
msgstr "Déconnecter {label}"
@@ -685,7 +693,7 @@ msgstr "Télécharger"
msgid "Download backup"
msgstr "Télécharger la sauvegarde"
#: apps/native/src/app/person/[id].tsx:54
#: apps/native/src/app/person/[id].tsx:142
#: apps/native/src/components/search/recently-viewed-row-content.tsx:32
#: apps/web/src/components/people/person-hero.tsx:77
msgid "Editor"
@@ -729,24 +737,31 @@ msgstr "Entrez l'URL de votre serveur Sofa pour commencer"
msgid "Environment"
msgstr "Environnement"
#. placeholder {0}: episode.episodeNumber
#: apps/native/src/components/titles/episode-row.tsx:27
#: apps/native/src/components/titles/episode-row.tsx:48
msgid "Episode {0}"
msgstr "Épisode {0}"
#~ msgid "Episode {0}"
#~ msgstr "Épisode {0}"
#. placeholder {0}: episode.episodeNumber
#: apps/native/src/components/titles/episode-row.tsx:34
msgid "Episode {0}, {episodeLabel}"
msgstr "Épisode {0}, {episodeLabel}"
#~ msgid "Episode {0}, {episodeLabel}"
#~ msgstr "Épisode {0}, {episodeLabel}"
#: apps/native/src/hooks/use-title-actions.ts:111
#: apps/native/src/lib/title-actions.ts:108
#: apps/native/src/components/titles/episode-row.tsx:29
#: apps/native/src/components/titles/episode-row.tsx:52
msgid "Episode {episodeNumber}"
msgstr "Épisode {episodeNumber}"
#: apps/native/src/components/titles/episode-row.tsx:38
msgid "Episode {episodeNumber}, {episodeLabel}"
msgstr "Épisode {episodeNumber}, {episodeLabel}"
#: apps/native/src/hooks/use-title-actions.ts:109
#: apps/native/src/lib/title-actions.ts:84
msgid "Episode unwatched"
msgstr "Épisode non visionné"
#: apps/native/src/hooks/use-title-actions.ts:101
#: apps/native/src/lib/title-actions.ts:98
#: apps/native/src/hooks/use-title-actions.ts:99
#: apps/native/src/lib/title-actions.ts:74
msgid "Episode watched"
msgstr "Épisode visionné"
@@ -758,7 +773,7 @@ msgstr "Épisodes"
#. placeholder {0}: periodLabels[episodePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx:125
msgid "Episodes {0}"
msgstr ""
msgstr "Épisodes {0}"
#: apps/web/src/components/dashboard/stats-display.tsx:162
#~ msgid "Episodes {periodSelect}"
@@ -790,8 +805,8 @@ msgstr "Erreurs ({0})"
msgid "Explore"
msgstr "Explorer"
#: apps/web/src/routes/_app/people.$id.tsx:68
#: apps/web/src/routes/_app/titles.$id.tsx:157
#: apps/web/src/routes/_app/people.$id.tsx:70
#: apps/web/src/routes/_app/titles.$id.tsx:158
msgid "Explore titles"
msgstr "Explorer les titres"
@@ -804,7 +819,7 @@ msgstr "Échoué"
msgid "Failed to add to watchlist"
msgstr "Échec de l'ajout à la liste de suivi"
#: apps/web/src/components/titles/use-title-actions.ts:80
#: apps/web/src/components/titles/use-title-actions.ts:77
msgid "Failed to catch up"
msgstr "Échec du rattrapage"
@@ -817,7 +832,7 @@ msgstr "Échec du changement de mot de passe"
msgid "Failed to connect"
msgstr "Échec de la connexion"
#: apps/native/src/components/settings/integration-card.tsx:87
#: apps/native/src/components/settings/integration-card.tsx:89
#: apps/web/src/components/settings/integration-card.tsx:91
msgid "Failed to connect {label}"
msgstr "Échec de la connexion à {label}"
@@ -834,7 +849,7 @@ msgstr "Échec de la création de la sauvegarde"
msgid "Failed to delete backup"
msgstr "Échec de la suppression de la sauvegarde"
#: apps/native/src/components/settings/integration-card.tsx:97
#: apps/native/src/components/settings/integration-card.tsx:99
#: apps/web/src/components/settings/integration-card.tsx:108
msgid "Failed to disconnect {label}"
msgstr "Échec de la déconnexion de {label}"
@@ -843,29 +858,30 @@ msgstr "Échec de la déconnexion de {label}"
msgid "Failed to load backup schedule settings."
msgstr "Échec du chargement des paramètres de planning de sauvegarde."
#: apps/web/src/routes/_app/titles.$id.tsx:110
#: apps/web/src/routes/_app/titles.$id.tsx:111
msgid "Failed to load title"
msgstr "Échec du chargement du titre"
#: apps/web/src/components/titles/use-title-actions.ts:344
#: apps/native/src/lib/title-actions.ts:101
#: apps/web/src/components/titles/use-title-actions.ts:338
msgid "Failed to mark all episodes as watched"
msgstr "Échec du marquage de tous les épisodes comme visionnés"
#: apps/native/src/hooks/use-title-actions.ts:79
#: apps/native/src/lib/title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:137
#: apps/native/src/hooks/use-title-actions.ts:77
#: apps/native/src/lib/title-actions.ts:43
#: apps/web/src/components/titles/use-title-actions.ts:134
msgid "Failed to mark as watched"
msgstr "Échec du marquage comme visionné"
#: apps/native/src/hooks/use-title-actions.ts:104
#: apps/native/src/lib/title-actions.ts:101
#: apps/web/src/components/titles/use-title-actions.ts:216
#: apps/native/src/hooks/use-title-actions.ts:102
#: apps/native/src/lib/title-actions.ts:77
#: apps/web/src/components/titles/use-title-actions.ts:214
msgid "Failed to mark episode"
msgstr "Échec du marquage de l'épisode"
#: apps/native/src/hooks/use-title-actions.ts:124
#: apps/native/src/lib/title-actions.ts:123
#: apps/web/src/components/titles/use-title-actions.ts:294
#: apps/native/src/hooks/use-title-actions.ts:122
#: apps/native/src/lib/title-actions.ts:113
#: apps/web/src/components/titles/use-title-actions.ts:286
msgid "Failed to mark some episodes"
msgstr "Échec du marquage de certains épisodes"
@@ -889,12 +905,12 @@ msgstr "Échec de la purge du cache d'images"
msgid "Failed to purge metadata cache"
msgstr "Échec de la purge du cache de métadonnées"
#: apps/native/src/components/settings/integration-card.tsx:107
#: apps/native/src/components/settings/integration-card.tsx:109
#: apps/web/src/components/settings/integration-card.tsx:121
msgid "Failed to regenerate {label} URL"
msgstr "Échec de la régénération de l'URL {label}"
#: apps/native/src/lib/title-actions.ts:77
#: apps/native/src/lib/title-actions.ts:53
msgid "Failed to remove from library"
msgstr "Échec de la suppression de la bibliothèque"
@@ -916,13 +932,13 @@ msgstr "Échec du démarrage de la connexion {0}"
msgid "Failed to trigger job"
msgstr "Échec du déclenchement de la tâche"
#: apps/native/src/hooks/use-title-actions.ts:114
#: apps/native/src/lib/title-actions.ts:111
#: apps/web/src/components/titles/use-title-actions.ts:163
#: apps/native/src/hooks/use-title-actions.ts:112
#: apps/native/src/lib/title-actions.ts:87
#: apps/web/src/components/titles/use-title-actions.ts:161
msgid "Failed to unmark episode"
msgstr "Échec du démarquage de l'épisode"
#: apps/web/src/components/titles/use-title-actions.ts:320
#: apps/web/src/components/titles/use-title-actions.ts:312
msgid "Failed to unmark some episodes"
msgstr "Échec du démarquage de certains épisodes"
@@ -930,9 +946,9 @@ msgstr "Échec du démarquage de certains épisodes"
msgid "Failed to update name"
msgstr "Échec de la mise à jour du nom"
#: apps/native/src/hooks/use-title-actions.ts:94
#: apps/native/src/lib/title-actions.ts:91
#: apps/web/src/components/titles/use-title-actions.ts:123
#: apps/native/src/hooks/use-title-actions.ts:92
#: apps/native/src/lib/title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:120
msgid "Failed to update rating"
msgstr "Échec de la mise à jour de la note"
@@ -958,10 +974,8 @@ msgstr "Échec de la mise à jour du paramètre de sauvegarde planifiée"
msgid "Failed to update setting"
msgstr "Échec de la mise à jour du paramètre"
#: apps/native/src/hooks/use-title-actions.ts:69
#: apps/native/src/lib/title-actions.ts:41
#: apps/native/src/lib/title-actions.ts:55
#: apps/web/src/components/titles/use-title-actions.ts:101
#: apps/native/src/hooks/use-title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:98
msgid "Failed to update status"
msgstr "Échec de la mise à jour du statut"
@@ -973,7 +987,7 @@ msgstr "Échec du téléchargement de l'avatar"
msgid "Fetching your library data from {source}..."
msgstr "Récupération de vos données depuis {source}..."
#: apps/native/src/app/person/[id].tsx:279
#: apps/native/src/app/person/[id].tsx:219
#: apps/web/src/components/people/filmography-grid.tsx:67
msgid "Filmography"
msgstr "Filmographie"
@@ -1002,8 +1016,8 @@ msgstr "Vendredi"
msgid "Get Started"
msgstr "Commencer"
#: apps/native/src/app/person/[id].tsx:176
#: apps/native/src/app/person/[id].tsx:196
#: apps/native/src/app/person/[id].tsx:261
#: apps/native/src/app/person/[id].tsx:281
#: apps/native/src/app/title/[id].tsx:235
msgid "Go back"
msgstr "Retour"
@@ -1112,6 +1126,11 @@ msgstr "Dans la bibliothèque"
msgid "In Library"
msgstr "Dans la bibliothèque"
#: apps/native/src/components/titles/status-action-button.tsx:46
#: apps/web/src/components/titles/status-button.tsx:40
msgid "In Watchlist"
msgstr "Dans la liste"
#: apps/native/src/app/(tabs)/(home)/index.tsx:179
#: apps/web/src/components/dashboard/library-section.tsx:35
msgid "In Your Library"
@@ -1222,22 +1241,23 @@ msgid "Mark all episodes as watched?"
msgstr "Marquer tous les épisodes comme visionnés ?"
#: apps/native/src/components/titles/season-accordion.tsx:152
#: apps/native/src/components/ui/poster-card.tsx:229
#: apps/web/src/components/titles/title-seasons.tsx:109
#: apps/web/src/components/titles/title-seasons.tsx:135
msgid "Mark All Watched"
msgstr "Tout marquer comme visionné"
#: apps/native/src/components/dashboard/continue-watching-card.tsx:103
msgid "Mark as Completed"
msgstr "Marquer comme terminé"
#~ msgid "Mark as Completed"
#~ msgstr "Marquer comme terminé"
#: apps/native/src/components/ui/poster-card.tsx:226
#: apps/native/src/components/ui/poster-card.tsx:222
msgid "Mark as Watched"
msgstr "Marquer comme visionné"
#: apps/native/src/components/ui/poster-card.tsx:219
msgid "Mark as Watching"
msgstr "Marquer comme en cours"
#~ msgid "Mark as Watching"
#~ msgstr "Marquer comme en cours"
#: apps/native/src/app/title/[id].tsx:400
#: apps/web/src/components/titles/title-actions.tsx:27
@@ -1245,32 +1265,37 @@ msgid "Mark Watched"
msgstr "Marquer comme visionné"
#: apps/native/src/lib/title-actions.ts:50
msgid "Marked \"{titleName}\" as completed"
msgstr "« {titleName} » marqué comme terminé"
#~ msgid "Marked \"{titleName}\" as completed"
#~ msgstr "« {titleName} » marqué comme terminé"
#: apps/native/src/lib/title-actions.ts:63
#: apps/web/src/components/titles/use-title-actions.ts:134
#: apps/native/src/lib/title-actions.ts:39
#: apps/web/src/components/titles/use-title-actions.ts:131
msgid "Marked \"{titleName}\" as watched"
msgstr "« {titleName} » marqué comme visionné"
#: apps/web/src/components/titles/use-title-actions.ts:337
#: apps/native/src/lib/title-actions.ts:97
#: apps/web/src/components/titles/use-title-actions.ts:331
msgid "Marked all episodes as watched"
msgstr "Tous les épisodes marqués comme visionnés"
#: apps/native/src/lib/title-actions.ts:96
msgid "Marked all episodes of \"{titleName}\" as watched"
msgstr "Tous les épisodes de \"{titleName}\" marqués comme vus"
#: apps/native/src/hooks/use-title-actions.ts:61
#: apps/native/src/lib/title-actions.ts:51
msgid "Marked as completed"
msgstr "Marqué comme terminé"
#~ msgid "Marked as completed"
#~ msgstr "Marqué comme terminé"
#: apps/native/src/hooks/use-title-actions.ts:76
#: apps/native/src/lib/title-actions.ts:63
#: apps/native/src/hooks/use-title-actions.ts:74
#: apps/native/src/lib/title-actions.ts:39
msgid "Marked as watched"
msgstr "Marqué comme visionné"
#: apps/native/src/hooks/use-title-actions.ts:60
#: apps/native/src/lib/title-actions.ts:38
msgid "Marked as watching"
msgstr "Marqué comme en cours"
#~ msgid "Marked as watching"
#~ msgstr "Marqué comme en cours"
#: apps/web/src/components/settings/account-section.tsx:314
msgid "Member since {memberSince}"
@@ -1305,7 +1330,7 @@ msgstr "Films"
#. placeholder {0}: periodLabels[moviePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx:114
msgid "Movies {0}"
msgstr ""
msgstr "Films {0}"
#: apps/web/src/components/dashboard/stats-display.tsx:161
#~ msgid "Movies {periodSelect}"
@@ -1345,7 +1370,7 @@ msgstr "Jamais exécuté"
msgid "New account creation is currently disabled."
msgstr "La création de nouveaux comptes est actuellement désactivée."
#: apps/web/src/routes/_auth/register.tsx:36
#: apps/web/src/routes/_auth/register.tsx:33
msgid "New accounts are not being accepted right now. Contact the admin if you need access."
msgstr "Les nouvelles inscriptions sont fermées. Contactez l'administrateur si vous avez besoin d'un accès."
@@ -1403,7 +1428,7 @@ msgstr "Aucun résultat trouvé."
msgid "No titles found for this genre."
msgstr "Aucun titre trouvé pour ce genre."
#: apps/native/src/components/settings/integration-card.tsx:174
#: apps/native/src/components/settings/integration-card.tsx:183
#: apps/web/src/components/settings/integration-card.tsx:153
#: apps/web/src/components/settings/system-health-section.tsx:229
msgid "Not configured"
@@ -1517,8 +1542,8 @@ msgstr "Vérifier périodiquement GitHub pour les nouvelles versions de Sofa"
msgid "Person"
msgstr "Personne"
#: apps/native/src/app/person/[id].tsx:192
#: apps/web/src/routes/_app/people.$id.tsx:50
#: apps/native/src/app/person/[id].tsx:277
#: apps/web/src/routes/_app/people.$id.tsx:52
msgid "Person not found"
msgstr "Personne introuvable"
@@ -1527,12 +1552,12 @@ msgid "Play trailer"
msgstr "Lire la bande-annonce"
#: apps/native/src/app/(tabs)/(explore)/index.tsx:89
#: apps/web/src/routes/_app/explore.tsx:141
#: apps/web/src/routes/_app/explore.tsx:143
msgid "Popular Movies"
msgstr "Films populaires"
#: apps/native/src/app/(tabs)/(explore)/index.tsx:102
#: apps/web/src/routes/_app/explore.tsx:151
#: apps/web/src/routes/_app/explore.tsx:153
msgid "Popular TV Shows"
msgstr "Séries populaires"
@@ -1540,7 +1565,7 @@ msgstr "Séries populaires"
msgid "Pre-restore backup"
msgstr "Sauvegarde pré-restauration"
#: apps/native/src/app/person/[id].tsx:53
#: apps/native/src/app/person/[id].tsx:141
#: apps/native/src/components/search/recently-viewed-row-content.tsx:31
#: apps/web/src/components/people/person-hero.tsx:75
msgid "Producer"
@@ -1612,7 +1637,7 @@ msgstr "URL de liste Radarr"
#. placeholder {0}: input.stars
#. placeholder {1}: input.stars
#: apps/native/src/hooks/use-title-actions.ts:88
#: apps/native/src/hooks/use-title-actions.ts:86
msgid "Rated {0} {1, plural, one {star} other {stars}}"
msgstr "Noté {0} {1, plural, one {étoile} other {étoiles}}"
@@ -1620,11 +1645,11 @@ msgstr "Noté {0} {1, plural, one {étoile} other {étoiles}}"
#~ msgid "Rated {0} star{1}"
#~ msgstr "Rated {0} star{1}"
#: apps/web/src/components/titles/use-title-actions.ts:118
#: apps/web/src/components/titles/use-title-actions.ts:115
msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}"
msgstr "Noté {ratingStars} {ratingStars, plural, one {étoile} other {étoiles}}"
#: apps/native/src/lib/title-actions.ts:86
#: apps/native/src/lib/title-actions.ts:62
msgid "Rated {stars, plural, one {# star} other {# stars}}"
msgstr "Noté {stars, plural, one {# étoile} other {# étoiles}}"
@@ -1633,9 +1658,9 @@ msgstr "Noté {stars, plural, one {# étoile} other {# étoiles}}"
msgid "Rating"
msgstr "Note"
#: apps/native/src/hooks/use-title-actions.ts:89
#: apps/native/src/lib/title-actions.ts:87
#: apps/web/src/components/titles/use-title-actions.ts:119
#: apps/native/src/hooks/use-title-actions.ts:87
#: apps/native/src/lib/title-actions.ts:63
#: apps/web/src/components/titles/use-title-actions.ts:116
msgid "Rating removed"
msgstr "Note supprimée"
@@ -1663,7 +1688,7 @@ msgid "Recent Searches"
msgstr "Recherches récentes"
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:95
#: apps/native/src/components/search/recently-viewed-list.tsx:77
#: apps/native/src/components/search/recently-viewed-list.tsx:59
msgid "Recently Viewed"
msgstr "Récemment consultés"
@@ -1692,12 +1717,12 @@ msgstr "Actualiser"
msgid "Refresh system health"
msgstr "Actualiser l'état du système"
#: apps/native/src/components/settings/integration-card.tsx:128
#: apps/native/src/components/settings/integration-card.tsx:248
#: apps/native/src/components/settings/integration-card.tsx:137
#: apps/native/src/components/settings/integration-card.tsx:257
msgid "Regenerate"
msgstr "Régénérer"
#: apps/native/src/components/settings/integration-card.tsx:123
#: apps/native/src/components/settings/integration-card.tsx:132
#: apps/web/src/components/settings/integration-card.tsx:226
msgid "Regenerate URL"
msgstr "Régénérer l'URL"
@@ -1717,7 +1742,7 @@ msgid "Registration closed"
msgstr "Inscriptions fermées"
#: apps/native/src/app/(auth)/register.tsx:87
#: apps/web/src/routes/_auth/register.tsx:33
#: apps/web/src/routes/_auth/register.tsx:30
msgid "Registration Closed"
msgstr "Inscriptions fermées"
@@ -1726,20 +1751,27 @@ msgstr "Inscriptions fermées"
msgid "Registration opened"
msgstr "Inscriptions ouvertes"
#: apps/web/src/components/titles/status-button.tsx:76
#: apps/native/src/components/titles/status-action-button.tsx:106
#: apps/web/src/components/titles/status-button.tsx:109
#: apps/web/src/components/titles/status-button.tsx:139
msgid "Remove"
msgstr "Supprimer"
#: apps/native/src/components/titles/status-action-button.tsx:96
#: apps/web/src/components/titles/status-button.tsx:60
#: apps/native/src/components/titles/status-action-button.tsx:115
#: apps/web/src/components/titles/status-button.tsx:93
msgid "Remove from library"
msgstr "Supprimer de la bibliothèque"
#: apps/native/src/components/dashboard/continue-watching-card.tsx:108
#: apps/native/src/components/ui/poster-card.tsx:233
#: apps/native/src/components/ui/poster-card.tsx:236
msgid "Remove from Library"
msgstr "Supprimer de la bibliothèque"
#: apps/native/src/components/titles/status-action-button.tsx:101
#: apps/web/src/components/titles/status-button.tsx:120
msgid "Remove from library?"
msgstr "Retirer de la bibliothèque ?"
#: apps/native/src/app/(tabs)/(settings)/index.tsx:268
msgid "Remove Photo"
msgstr "Supprimer la photo"
@@ -1752,9 +1784,9 @@ msgstr "Supprimer la photo"
msgid "Remove profile picture"
msgstr "Supprimer la photo de profil"
#: apps/native/src/hooks/use-title-actions.ts:65
#: apps/native/src/lib/title-actions.ts:74
#: apps/web/src/components/titles/use-title-actions.ts:98
#: apps/native/src/hooks/use-title-actions.ts:63
#: apps/native/src/lib/title-actions.ts:50
#: apps/web/src/components/titles/use-title-actions.ts:95
msgid "Removed from library"
msgstr "Supprimé de la bibliothèque"
@@ -1861,14 +1893,14 @@ msgstr "Sauvegardes planifiées activées"
#: apps/native/src/app/(tabs)/(search)/_layout.tsx:7
#: apps/native/src/components/navigation/native-tab-bar.tsx:41
msgid "Search"
msgstr ""
msgstr "Recherche"
#: apps/web/src/components/dashboard/stats-section.tsx:35
msgid "Search for movies and TV shows to start tracking"
msgstr "Recherchez des films et séries pour commencer à les suivre"
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:72
#: apps/native/src/components/search/recently-viewed-list.tsx:55
#: apps/native/src/components/search/recently-viewed-list.tsx:81
msgid "Search for movies, shows, or people"
msgstr "Rechercher des films, séries ou personnes"
@@ -1892,13 +1924,13 @@ msgstr "Rechercher…"
#. placeholder {0}: season.seasonNumber
#: apps/native/src/components/titles/season-accordion.tsx:113
#: apps/native/src/components/titles/season-accordion.tsx:119
#: apps/web/src/components/titles/use-title-actions.ts:274
#: apps/web/src/components/titles/use-title-actions.ts:313
#: apps/web/src/components/titles/use-title-actions.ts:266
#: apps/web/src/components/titles/use-title-actions.ts:305
msgid "Season {0}"
msgstr "Saison {0}"
#: apps/native/src/hooks/use-title-actions.ts:121
#: apps/native/src/lib/title-actions.ts:119
#: apps/native/src/hooks/use-title-actions.ts:119
#: apps/native/src/lib/title-actions.ts:109
msgid "Season watched"
msgstr "Saison visionnée"
@@ -1907,7 +1939,7 @@ msgid "Seasons"
msgstr "Saisons"
#: apps/native/src/app/(tabs)/(settings)/index.tsx:452
#: apps/web/src/routes/_app/settings.tsx:167
#: apps/web/src/routes/_app/settings.tsx:169
msgid "Security"
msgstr "Sécurité"
@@ -1915,7 +1947,7 @@ msgstr "Sécurité"
msgid "Self-hosted movie & TV tracker"
msgstr "Suivi de films et séries auto-hébergé"
#: apps/web/src/routes/_app/settings.tsx:151
#: apps/web/src/routes/_app/settings.tsx:153
msgid "Server"
msgstr "Serveur"
@@ -1947,12 +1979,12 @@ msgstr "Définissez votre profil de qualité et dossier racine préférés"
msgid "Settings"
msgstr "Paramètres"
#: apps/native/src/components/settings/integration-card.tsx:271
#: apps/native/src/components/settings/integration-card.tsx:280
#: apps/web/src/components/settings/integration-card.tsx:248
msgid "Setup instructions"
msgstr "Instructions de configuration"
#: apps/web/src/routes/setup.tsx:95
#: apps/web/src/routes/setup.tsx:96
msgid "Setup required"
msgstr "Configuration requise"
@@ -1977,7 +2009,7 @@ msgstr "Se connecter"
msgid "Sign In"
msgstr "Se connecter"
#: apps/web/src/routes/_auth/register.tsx:45
#: apps/web/src/routes/_auth/register.tsx:42
msgid "Sign in instead"
msgstr "Se connecter"
@@ -2031,13 +2063,13 @@ msgid "Sofa will automatically log movies and episodes when you finish watching
msgstr "Sofa enregistrera automatiquement les films et épisodes lorsque vous aurez fini de les regarder"
#: apps/native/src/app/change-password.tsx:77
#: apps/native/src/app/person/[id].tsx:169
#: apps/native/src/app/person/[id].tsx:254
#: apps/web/src/components/settings/account-section.tsx:391
#: apps/web/src/routes/__root.tsx:139
msgid "Something went wrong"
msgstr "Une erreur s'est produite"
#: apps/web/src/routes/_app/titles.$id.tsx:113
#: apps/web/src/routes/_app/titles.$id.tsx:114
msgid "Something went wrong while loading this title. Please try again."
msgstr "Une erreur s'est produite lors du chargement de ce titre. Veuillez réessayer."
@@ -2070,7 +2102,7 @@ msgstr "À partir de"
msgid "Starting import..."
msgstr "Démarrage de l'importation..."
#: apps/native/src/hooks/use-title-actions.ts:64
#: apps/native/src/hooks/use-title-actions.ts:62
msgid "Status updated"
msgstr "Statut mis à jour"
@@ -2095,11 +2127,11 @@ msgstr "Passer à {0}"
msgid "The page you're looking for doesn't exist."
msgstr "La page que vous recherchez n'existe pas."
#: apps/web/src/routes/_app/people.$id.tsx:53
#: apps/web/src/routes/_app/people.$id.tsx:55
msgid "The person you're looking for doesn't exist or may have been removed from the database."
msgstr "La personne que vous recherchez n'existe pas ou a peut-être été supprimée de la base de données."
#: apps/web/src/routes/_app/titles.$id.tsx:142
#: apps/web/src/routes/_app/titles.$id.tsx:143
msgid "The title you're looking for doesn't exist or may have been removed from the database."
msgstr "Le titre que vous recherchez n'existe pas ou a peut-être été supprimé de la base de données."
@@ -2109,7 +2141,7 @@ msgstr "Cela peut prendre quelques minutes pour les grandes bibliothèques. Ne f
#: apps/native/src/app/(tabs)/(home)/index.tsx:89
msgid "this month"
msgstr ""
msgstr "ce mois-ci"
#: apps/native/src/components/dashboard/stats-card.tsx:31
#: apps/web/src/components/dashboard/stats-display.tsx:135
@@ -2121,14 +2153,19 @@ msgid "This page was left on the cutting room floor. It may have been moved, rem
msgstr "Cette page est restée sur le plancher de la salle de montage. Elle a peut-être été déplacée, supprimée, ou n'a jamais dépassé le stade du scénario."
#: apps/native/src/app/(tabs)/(settings)/index.tsx:559
#: apps/web/src/routes/_app/settings.tsx:112
#: apps/web/src/routes/setup.tsx:180
#: apps/web/src/routes/_app/settings.tsx:114
#: apps/web/src/routes/setup.tsx:181
msgid "This product uses the TMDB API but is not endorsed or certified by TMDB."
msgstr "Ce produit utilise l'API TMDB mais n'est pas approuvé ni certifié par TMDB."
#: apps/native/src/components/titles/status-action-button.tsx:102
#: apps/web/src/components/titles/status-button.tsx:123
msgid "This title will be removed from your library. Your watch history and ratings will be kept."
msgstr "Ce titre sera retiré de votre bibliothèque. Votre historique de visionnage et vos notes seront conservés."
#: apps/native/src/app/(tabs)/(home)/index.tsx:88
msgid "this week"
msgstr ""
msgstr "cette semaine"
#: apps/native/src/components/dashboard/stats-card.tsx:30
#: apps/web/src/components/dashboard/stats-display.tsx:134
@@ -2147,7 +2184,7 @@ msgstr "Cela supprimera tous les titres ébauches non enrichis et toutes les ima
msgid "This will delete un-enriched stub titles that aren't in any user's library and clean up orphaned person records. Deleted titles will be re-imported if accessed again."
msgstr "Cela supprimera les titres ébauches non enrichis qui ne sont dans aucune bibliothèque et nettoiera les enregistrements de personnes orphelines. Les titres supprimés seront réimportés s'ils sont consultés à nouveau."
#: apps/native/src/components/settings/integration-card.tsx:124
#: apps/native/src/components/settings/integration-card.tsx:133
msgid "This will invalidate the current {label} URL. You'll need to update it in {label}."
msgstr "Cela invalidera l'URL {label} actuelle. Vous devrez la mettre à jour dans {label}."
@@ -2171,7 +2208,7 @@ msgstr "Cela remplacera toute votre base de données par le fichier télécharg
#: apps/native/src/app/(tabs)/(home)/index.tsx:90
msgid "this year"
msgstr ""
msgstr "cette année"
#: apps/native/src/components/dashboard/stats-card.tsx:32
#: apps/web/src/components/dashboard/stats-display.tsx:136
@@ -2187,7 +2224,7 @@ msgid "Time:"
msgstr "Heure :"
#: apps/native/src/app/title/[id].tsx:231
#: apps/web/src/routes/_app/titles.$id.tsx:139
#: apps/web/src/routes/_app/titles.$id.tsx:140
msgid "Title not found"
msgstr "Titre introuvable"
@@ -2203,7 +2240,7 @@ msgstr "Les titres de votre liste de suivi Sofa seront automatiquement ajoutés
#: apps/native/src/app/(tabs)/(home)/index.tsx:87
msgid "today"
msgstr ""
msgstr "aujourd'hui"
#: apps/native/src/components/dashboard/stats-card.tsx:29
#: apps/web/src/components/dashboard/stats-display.tsx:133
@@ -2236,7 +2273,7 @@ msgid "Trending today"
msgstr "Tendance aujourd'hui"
#: apps/native/src/app/(tabs)/(explore)/index.tsx:77
#: apps/web/src/routes/_app/explore.tsx:129
#: apps/web/src/routes/_app/explore.tsx:131
msgid "Trending Today"
msgstr "Tendances du jour"
@@ -2291,11 +2328,11 @@ msgid "Unwatch all"
msgstr "Tout démarquer"
#. placeholder {0}: season.name ?? t`Season ${season.seasonNumber}`
#: apps/web/src/components/titles/use-title-actions.ts:313
#: apps/web/src/components/titles/use-title-actions.ts:305
msgid "Unwatched all of {0}"
msgstr "Tout démarqué de {0}"
#: apps/web/src/components/titles/use-title-actions.ts:156
#: apps/web/src/components/titles/use-title-actions.ts:154
msgid "Unwatched S{seasonNum} E{epNum}"
msgstr "Démarqué S{seasonNum} E{epNum}"
@@ -2366,7 +2403,7 @@ msgstr "Télécharger une photo"
msgid "Upload profile picture"
msgstr "Télécharger une photo de profil"
#: apps/native/src/components/settings/integration-card.tsx:117
#: apps/native/src/components/settings/integration-card.tsx:125
msgid "URL copied to clipboard"
msgstr "URL copiée dans le presse-papiers"
@@ -2399,36 +2436,36 @@ msgstr "Historique de visionnage"
msgid "Watch on {name}"
msgstr "Regarder sur {name}"
#: apps/web/src/components/titles/use-title-actions.ts:277
#: apps/web/src/components/titles/use-title-actions.ts:286
#: apps/web/src/components/titles/use-title-actions.ts:269
#: apps/web/src/components/titles/use-title-actions.ts:278
msgid "Watched all of {seasonLabel}"
msgstr "Tout visionné de {seasonLabel}"
#: apps/native/src/lib/title-actions.ts:119
#: apps/native/src/lib/title-actions.ts:109
msgid "Watched all of {seasonName}"
msgstr "Tout visionné de {seasonName}"
#: apps/web/src/components/titles/use-title-actions.ts:199
#: apps/web/src/components/titles/use-title-actions.ts:208
#: apps/web/src/components/titles/use-title-actions.ts:197
#: apps/web/src/components/titles/use-title-actions.ts:206
msgid "Watched S{seasonNum} E{epNum}"
msgstr "Visionné S{seasonNum} E{epNum}"
#: apps/native/src/components/titles/status-action-button.tsx:43
#: apps/native/src/components/titles/status-action-button.tsx:48
#: apps/web/src/components/title-card.tsx:69
#: apps/web/src/components/titles/status-button.tsx:14
#: apps/web/src/components/titles/status-button.tsx:47
msgid "Watching"
msgstr "En cours"
#: apps/native/src/components/titles/status-action-button.tsx:78
#: apps/native/src/components/titles/status-action-button.tsx:85
#: apps/web/src/components/settings/imports-section.tsx:743
#: apps/web/src/components/settings/imports-section.tsx:769
#: apps/web/src/components/titles/status-button.tsx:49
#: apps/web/src/components/titles/status-button.tsx:82
msgid "Watchlist"
msgstr "Liste de suivi"
#: apps/native/src/components/titles/status-action-button.tsx:41
msgid "Watchlisted"
msgstr "Dans la liste de suivi"
#~ msgid "Watchlisted"
#~ msgstr "Dans la liste de suivi"
#: apps/native/src/components/settings/integration-configs.ts:51
#: apps/native/src/components/settings/integration-configs.ts:66
@@ -2458,7 +2495,7 @@ msgstr "Où regarder"
msgid "With Ads"
msgstr "Avec publicités"
#: apps/native/src/app/person/[id].tsx:52
#: apps/native/src/app/person/[id].tsx:140
#: apps/native/src/components/search/recently-viewed-row-content.tsx:30
#: apps/web/src/components/people/person-hero.tsx:73
msgid "Writer"
File diff suppressed because one or more lines are too long
+217 -180
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+206 -169
View File
@@ -57,7 +57,7 @@ msgstr "{0} imagens em cache"
#. placeholder {1}: member.episodeCount !== 1 ? "s" : ""
#: apps/web/src/components/titles/cast-carousel.tsx:78
msgid "{0} ep{1}"
msgstr ""
msgstr "{0} ep{1}"
#: apps/native/src/app/(tabs)/(settings)/index.tsx:472
#~ msgid "{0} images"
@@ -104,8 +104,8 @@ msgstr "{0}/{1} {2, plural, one {episódio} other {episódios}}"
#~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/titles/use-title-actions.ts:200
#: apps/web/src/components/titles/use-title-actions.ts:278
#: apps/web/src/components/titles/use-title-actions.ts:198
#: apps/web/src/components/titles/use-title-actions.ts:270
msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
msgstr "{count} {count, plural, one {episódio anterior não assistido} other {episódios anteriores não assistidos}}"
@@ -114,22 +114,22 @@ msgstr "{count} {count, plural, one {episódio anterior não assistido} other {e
msgid "{healthyCount} of {0} jobs healthy"
msgstr "{healthyCount} de {0} tarefas saudáveis"
#: apps/native/src/components/settings/integration-card.tsx:84
#: apps/native/src/components/settings/integration-card.tsx:86
#: apps/web/src/components/settings/integration-card.tsx:89
msgid "{label} connected"
msgstr "{label} conectado"
#: apps/native/src/components/settings/integration-card.tsx:94
#: apps/native/src/components/settings/integration-card.tsx:96
#: apps/web/src/components/settings/integration-card.tsx:105
msgid "{label} disconnected"
msgstr "{label} desconectado"
#: apps/native/src/components/settings/integration-card.tsx:104
#: apps/native/src/components/settings/integration-card.tsx:106
#: apps/web/src/components/settings/integration-card.tsx:119
msgid "{label} URL regenerated"
msgstr "URL de {label} regenerada"
#: apps/web/src/components/title-card.tsx:152
#: apps/web/src/components/title-card.tsx:157
msgid "{watched}/{total} episodes"
msgstr "{watched}/{total} episódios"
@@ -157,7 +157,7 @@ msgstr "Conta"
msgid "Actions"
msgstr "Ações"
#: apps/native/src/app/person/[id].tsx:50
#: apps/native/src/app/person/[id].tsx:138
#: apps/native/src/components/search/recently-viewed-row-content.tsx:28
#: apps/web/src/components/people/person-hero.tsx:69
msgid "Actor"
@@ -180,13 +180,13 @@ msgstr "Adicione um novo webhook e cole a URL acima"
msgid "Add to Library"
msgstr "Adicionar à Biblioteca"
#: apps/native/src/components/titles/status-action-button.tsx:73
#: apps/native/src/components/titles/status-action-button.tsx:80
msgid "Add to watchlist"
msgstr "Adicionar à lista de desejos"
#: apps/native/src/components/explore/hero-banner.tsx:132
#: apps/native/src/components/ui/poster-card.tsx:212
#: apps/web/src/components/title-card.tsx:133
#: apps/native/src/components/ui/poster-card.tsx:215
#: apps/web/src/components/title-card.tsx:138
msgid "Add to Watchlist"
msgstr "Adicionar à Lista de Desejos"
@@ -197,7 +197,7 @@ msgstr "Adicionado \"{titleName}\" à lista de desejos"
#: apps/native/src/hooks/use-title-actions.ts:44
#: apps/native/src/hooks/use-title-actions.ts:59
#: apps/native/src/lib/title-actions.ts:25
#: apps/web/src/components/titles/use-title-actions.ts:98
#: apps/web/src/components/titles/use-title-actions.ts:95
msgid "Added to watchlist"
msgstr "Adicionado à lista de desejos"
@@ -209,11 +209,11 @@ msgstr "Adicionado à lista de desejos"
msgid "Admin"
msgstr "Administrador"
#: apps/web/src/routes/_app/settings.tsx:154
#: apps/web/src/routes/_app/settings.tsx:156
msgid "Admin only"
msgstr "Apenas administradores"
#: apps/native/src/app/person/[id].tsx:249
#: apps/native/src/app/person/[id].tsx:189
#: apps/web/src/components/people/person-hero.tsx:89
msgid "age {age}"
msgstr "idade {age}"
@@ -243,7 +243,7 @@ msgstr "Ocorreu um erro inesperado ao carregar esta página. Você pode tentar n
msgid "Anonymous usage reporting"
msgstr "Relatório de uso anônimo"
#: apps/web/src/routes/_app/settings.tsx:135
#: apps/web/src/routes/_app/settings.tsx:137
msgid "App Settings"
msgstr "Configurações do App"
@@ -251,7 +251,7 @@ msgstr "Configurações do App"
msgid "Application"
msgstr "Aplicativo"
#: apps/native/src/components/settings/integration-card.tsx:139
#: apps/native/src/components/settings/integration-card.tsx:148
msgid "Are you sure you want to disconnect {label}? The current URL will stop working."
msgstr "Tem certeza que deseja desconectar {label}? A URL atual deixará de funcionar."
@@ -295,7 +295,7 @@ msgstr "Tarefas em segundo plano"
#: apps/web/src/components/settings/system-health-section.tsx:309
msgid "Backup"
msgstr ""
msgstr "Backup"
#: apps/web/src/components/settings/backup-section.tsx:62
msgid "Backup created"
@@ -310,9 +310,9 @@ msgid "Backup schedule"
msgstr "Agendamento de backup"
#: apps/web/src/components/settings/system-health-section.tsx:583
#: apps/web/src/routes/_app/settings.tsx:190
#: apps/web/src/routes/_app/settings.tsx:192
msgid "Backups"
msgstr ""
msgstr "Backups"
#: apps/web/src/components/settings/backup-schedule-section.tsx:272
#~ msgid "backups."
@@ -337,8 +337,9 @@ msgstr "Não foi possível alcançar o servidor"
#: apps/native/src/components/header-avatar.tsx:63
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:58
#: apps/native/src/components/search/recently-viewed-list.tsx:32
#: apps/native/src/components/settings/integration-card.tsx:126
#: apps/native/src/components/settings/integration-card.tsx:141
#: apps/native/src/components/settings/integration-card.tsx:135
#: apps/native/src/components/settings/integration-card.tsx:150
#: apps/native/src/components/titles/status-action-button.tsx:104
#: apps/web/src/components/settings/account-section.tsx:477
#: apps/web/src/components/settings/backup-restore-section.tsx:101
#: apps/web/src/components/settings/backup-section.tsx:240
@@ -348,6 +349,7 @@ msgstr "Não foi possível alcançar o servidor"
#: apps/web/src/components/settings/imports-section.tsx:611
#: apps/web/src/components/settings/imports-section.tsx:674
#: apps/web/src/components/settings/imports-section.tsx:798
#: apps/web/src/components/titles/status-button.tsx:131
#: apps/web/src/components/titles/title-seasons.tsx:127
msgid "Cancel"
msgstr "Cancelar"
@@ -361,14 +363,20 @@ msgstr "Cancelar edição"
msgid "Cast"
msgstr "Elenco"
#: apps/web/src/components/titles/use-title-actions.ts:202
#: apps/web/src/components/titles/use-title-actions.ts:280
#: apps/web/src/components/titles/use-title-actions.ts:200
#: apps/web/src/components/titles/use-title-actions.ts:272
msgid "Catch up"
msgstr "Colocar em dia"
#: apps/native/src/components/titles/status-action-button.tsx:50
#: apps/web/src/components/title-card.tsx:74
#: apps/web/src/components/titles/status-button.tsx:54
msgid "Caught Up"
msgstr "Em dia"
#. placeholder {0}: episodeIds.length
#. placeholder {1}: episodeIds.length
#: apps/web/src/components/titles/use-title-actions.ts:72
#: apps/web/src/components/titles/use-title-actions.ts:69
msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched"
msgstr "Em dia — {0} {1, plural, one {episódio marcado como assistido} other {episódios marcados como assistidos}}"
@@ -418,7 +426,7 @@ msgstr "Escolha como importar seus dados do {0}."
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:60
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:104
#: apps/native/src/components/search/recently-viewed-list.tsx:34
#: apps/native/src/components/search/recently-viewed-list.tsx:86
#: apps/native/src/components/search/recently-viewed-list.tsx:68
msgid "Clear"
msgstr "Limpar"
@@ -455,10 +463,10 @@ msgid "Close"
msgstr "Fechar"
#: apps/native/src/app/(tabs)/(home)/index.tsx:146
#: apps/native/src/components/titles/status-action-button.tsx:45
#: apps/native/src/components/titles/status-action-button.tsx:52
#: apps/web/src/components/dashboard/stats-display.tsx:219
#: apps/web/src/components/title-card.tsx:74
#: apps/web/src/components/titles/status-button.tsx:25
#: apps/web/src/components/title-card.tsx:79
#: apps/web/src/components/titles/status-button.tsx:59
msgid "Completed"
msgstr "Concluído"
@@ -477,7 +485,7 @@ msgstr "Conectar"
msgid "Connect {0}"
msgstr "Conectar {0}"
#: apps/native/src/components/settings/integration-card.tsx:207
#: apps/native/src/components/settings/integration-card.tsx:216
msgid "Connect {label}"
msgstr "Conectar {label}"
@@ -485,7 +493,7 @@ msgstr "Conectar {label}"
msgid "Connect to {source}"
msgstr "Conectar a {source}"
#: apps/web/src/routes/setup.tsx:98
#: apps/web/src/routes/setup.tsx:99
msgid "Connect to TMDB"
msgstr "Conectar ao TMDB"
@@ -516,7 +524,7 @@ msgstr "Conectando ao servidor..."
msgid "Connecting..."
msgstr "Conectando..."
#: apps/native/src/components/settings/integration-card.tsx:207
#: apps/native/src/components/settings/integration-card.tsx:216
msgid "Connecting…"
msgstr "Conectando…"
@@ -545,7 +553,7 @@ msgstr "Copiar URL"
msgid "Could not load integrations"
msgstr "Não foi possível carregar as integrações"
#: apps/native/src/app/person/[id].tsx:172
#: apps/native/src/app/person/[id].tsx:257
msgid "Could not load person details"
msgstr "Não foi possível carregar os detalhes da pessoa"
@@ -579,14 +587,14 @@ msgstr "Senha atual"
msgid "Current password is required"
msgstr "A senha atual é obrigatória"
#: apps/web/src/routes/_app/settings.tsx:216
#: apps/web/src/routes/_app/settings.tsx:218
msgid "Danger Zone"
msgstr "Zona de Perigo"
#: apps/web/src/routes/__root.tsx:163
#: apps/web/src/routes/_app/people.$id.tsx:76
#: apps/web/src/routes/_app/titles.$id.tsx:119
#: apps/web/src/routes/_app/titles.$id.tsx:165
#: apps/web/src/routes/_app/people.$id.tsx:78
#: apps/web/src/routes/_app/titles.$id.tsx:120
#: apps/web/src/routes/_app/titles.$id.tsx:166
msgid "Dashboard"
msgstr "Painel"
@@ -630,12 +638,12 @@ msgstr "{0, plural, one {# arquivo excluído} other {# arquivos excluídos}}, {f
msgid "Device code expired. Please try again."
msgstr "Código do dispositivo expirou. Tente novamente."
#: apps/native/src/app/person/[id].tsx:249
#: apps/native/src/app/person/[id].tsx:189
#: apps/web/src/components/people/person-hero.tsx:89
msgid "died at {age}"
msgstr "faleceu aos {age}"
#: apps/native/src/app/person/[id].tsx:51
#: apps/native/src/app/person/[id].tsx:139
#: apps/native/src/components/search/recently-viewed-row-content.tsx:29
#: apps/web/src/components/people/person-hero.tsx:71
msgid "Director"
@@ -646,13 +654,13 @@ msgstr "Diretor"
msgid "Disabled"
msgstr "Desativado"
#: apps/native/src/components/settings/integration-card.tsx:143
#: apps/native/src/components/settings/integration-card.tsx:257
#: apps/native/src/components/settings/integration-card.tsx:152
#: apps/native/src/components/settings/integration-card.tsx:266
#: apps/web/src/components/settings/integration-card.tsx:234
msgid "Disconnect"
msgstr "Desconectar"
#: apps/native/src/components/settings/integration-card.tsx:138
#: apps/native/src/components/settings/integration-card.tsx:147
msgid "Disconnect {label}"
msgstr "Desconectar {label}"
@@ -685,11 +693,11 @@ msgstr "Baixar"
msgid "Download backup"
msgstr "Baixar backup"
#: apps/native/src/app/person/[id].tsx:54
#: apps/native/src/app/person/[id].tsx:142
#: apps/native/src/components/search/recently-viewed-row-content.tsx:32
#: apps/web/src/components/people/person-hero.tsx:77
msgid "Editor"
msgstr ""
msgstr "Editor"
#: apps/native/src/app/(auth)/login.tsx:123
#: apps/native/src/app/(auth)/register.tsx:139
@@ -729,24 +737,31 @@ msgstr "Insira a URL do seu servidor Sofa para começar"
msgid "Environment"
msgstr "Ambiente"
#. placeholder {0}: episode.episodeNumber
#: apps/native/src/components/titles/episode-row.tsx:27
#: apps/native/src/components/titles/episode-row.tsx:48
msgid "Episode {0}"
msgstr "Episódio {0}"
#~ msgid "Episode {0}"
#~ msgstr "Episódio {0}"
#. placeholder {0}: episode.episodeNumber
#: apps/native/src/components/titles/episode-row.tsx:34
msgid "Episode {0}, {episodeLabel}"
msgstr "Episódio {0}, {episodeLabel}"
#~ msgid "Episode {0}, {episodeLabel}"
#~ msgstr "Episódio {0}, {episodeLabel}"
#: apps/native/src/hooks/use-title-actions.ts:111
#: apps/native/src/lib/title-actions.ts:108
#: apps/native/src/components/titles/episode-row.tsx:29
#: apps/native/src/components/titles/episode-row.tsx:52
msgid "Episode {episodeNumber}"
msgstr "Episódio {episodeNumber}"
#: apps/native/src/components/titles/episode-row.tsx:38
msgid "Episode {episodeNumber}, {episodeLabel}"
msgstr "Episódio {episodeNumber}, {episodeLabel}"
#: apps/native/src/hooks/use-title-actions.ts:109
#: apps/native/src/lib/title-actions.ts:84
msgid "Episode unwatched"
msgstr "Episódio não assistido"
#: apps/native/src/hooks/use-title-actions.ts:101
#: apps/native/src/lib/title-actions.ts:98
#: apps/native/src/hooks/use-title-actions.ts:99
#: apps/native/src/lib/title-actions.ts:74
msgid "Episode watched"
msgstr "Episódio assistido"
@@ -758,7 +773,7 @@ msgstr "Episódios"
#. placeholder {0}: periodLabels[episodePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx:125
msgid "Episodes {0}"
msgstr ""
msgstr "Episódios {0}"
#: apps/web/src/components/dashboard/stats-display.tsx:162
#~ msgid "Episodes {periodSelect}"
@@ -790,8 +805,8 @@ msgstr "Erros ({0})"
msgid "Explore"
msgstr "Explorar"
#: apps/web/src/routes/_app/people.$id.tsx:68
#: apps/web/src/routes/_app/titles.$id.tsx:157
#: apps/web/src/routes/_app/people.$id.tsx:70
#: apps/web/src/routes/_app/titles.$id.tsx:158
msgid "Explore titles"
msgstr "Explorar títulos"
@@ -804,7 +819,7 @@ msgstr "Falhou"
msgid "Failed to add to watchlist"
msgstr "Falha ao adicionar à lista de desejos"
#: apps/web/src/components/titles/use-title-actions.ts:80
#: apps/web/src/components/titles/use-title-actions.ts:77
msgid "Failed to catch up"
msgstr "Falha ao colocar em dia"
@@ -817,7 +832,7 @@ msgstr "Falha ao alterar senha"
msgid "Failed to connect"
msgstr "Falha ao conectar"
#: apps/native/src/components/settings/integration-card.tsx:87
#: apps/native/src/components/settings/integration-card.tsx:89
#: apps/web/src/components/settings/integration-card.tsx:91
msgid "Failed to connect {label}"
msgstr "Falha ao conectar {label}"
@@ -834,7 +849,7 @@ msgstr "Falha ao criar backup"
msgid "Failed to delete backup"
msgstr "Falha ao excluir backup"
#: apps/native/src/components/settings/integration-card.tsx:97
#: apps/native/src/components/settings/integration-card.tsx:99
#: apps/web/src/components/settings/integration-card.tsx:108
msgid "Failed to disconnect {label}"
msgstr "Falha ao desconectar {label}"
@@ -843,29 +858,30 @@ msgstr "Falha ao desconectar {label}"
msgid "Failed to load backup schedule settings."
msgstr "Falha ao carregar as configurações do agendamento de backup."
#: apps/web/src/routes/_app/titles.$id.tsx:110
#: apps/web/src/routes/_app/titles.$id.tsx:111
msgid "Failed to load title"
msgstr "Falha ao carregar título"
#: apps/web/src/components/titles/use-title-actions.ts:344
#: apps/native/src/lib/title-actions.ts:101
#: apps/web/src/components/titles/use-title-actions.ts:338
msgid "Failed to mark all episodes as watched"
msgstr "Falha ao marcar todos os episódios como assistidos"
#: apps/native/src/hooks/use-title-actions.ts:79
#: apps/native/src/lib/title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:137
#: apps/native/src/hooks/use-title-actions.ts:77
#: apps/native/src/lib/title-actions.ts:43
#: apps/web/src/components/titles/use-title-actions.ts:134
msgid "Failed to mark as watched"
msgstr "Falha ao marcar como assistido"
#: apps/native/src/hooks/use-title-actions.ts:104
#: apps/native/src/lib/title-actions.ts:101
#: apps/web/src/components/titles/use-title-actions.ts:216
#: apps/native/src/hooks/use-title-actions.ts:102
#: apps/native/src/lib/title-actions.ts:77
#: apps/web/src/components/titles/use-title-actions.ts:214
msgid "Failed to mark episode"
msgstr "Falha ao marcar episódio"
#: apps/native/src/hooks/use-title-actions.ts:124
#: apps/native/src/lib/title-actions.ts:123
#: apps/web/src/components/titles/use-title-actions.ts:294
#: apps/native/src/hooks/use-title-actions.ts:122
#: apps/native/src/lib/title-actions.ts:113
#: apps/web/src/components/titles/use-title-actions.ts:286
msgid "Failed to mark some episodes"
msgstr "Falha ao marcar alguns episódios"
@@ -889,12 +905,12 @@ msgstr "Falha ao limpar cache de imagens"
msgid "Failed to purge metadata cache"
msgstr "Falha ao limpar cache de metadados"
#: apps/native/src/components/settings/integration-card.tsx:107
#: apps/native/src/components/settings/integration-card.tsx:109
#: apps/web/src/components/settings/integration-card.tsx:121
msgid "Failed to regenerate {label} URL"
msgstr "Falha ao regenerar URL de {label}"
#: apps/native/src/lib/title-actions.ts:77
#: apps/native/src/lib/title-actions.ts:53
msgid "Failed to remove from library"
msgstr "Falha ao remover da biblioteca"
@@ -916,13 +932,13 @@ msgstr "Falha ao iniciar conexão com {0}"
msgid "Failed to trigger job"
msgstr "Falha ao acionar tarefa"
#: apps/native/src/hooks/use-title-actions.ts:114
#: apps/native/src/lib/title-actions.ts:111
#: apps/web/src/components/titles/use-title-actions.ts:163
#: apps/native/src/hooks/use-title-actions.ts:112
#: apps/native/src/lib/title-actions.ts:87
#: apps/web/src/components/titles/use-title-actions.ts:161
msgid "Failed to unmark episode"
msgstr "Falha ao desmarcar episódio"
#: apps/web/src/components/titles/use-title-actions.ts:320
#: apps/web/src/components/titles/use-title-actions.ts:312
msgid "Failed to unmark some episodes"
msgstr "Falha ao desmarcar alguns episódios"
@@ -930,9 +946,9 @@ msgstr "Falha ao desmarcar alguns episódios"
msgid "Failed to update name"
msgstr "Falha ao atualizar nome"
#: apps/native/src/hooks/use-title-actions.ts:94
#: apps/native/src/lib/title-actions.ts:91
#: apps/web/src/components/titles/use-title-actions.ts:123
#: apps/native/src/hooks/use-title-actions.ts:92
#: apps/native/src/lib/title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:120
msgid "Failed to update rating"
msgstr "Falha ao atualizar avaliação"
@@ -958,10 +974,8 @@ msgstr "Falha ao atualizar configuração de backup agendado"
msgid "Failed to update setting"
msgstr "Falha ao atualizar configuração"
#: apps/native/src/hooks/use-title-actions.ts:69
#: apps/native/src/lib/title-actions.ts:41
#: apps/native/src/lib/title-actions.ts:55
#: apps/web/src/components/titles/use-title-actions.ts:101
#: apps/native/src/hooks/use-title-actions.ts:67
#: apps/web/src/components/titles/use-title-actions.ts:98
msgid "Failed to update status"
msgstr "Falha ao atualizar status"
@@ -973,7 +987,7 @@ msgstr "Falha ao enviar avatar"
msgid "Fetching your library data from {source}..."
msgstr "Buscando seus dados da biblioteca em {source}..."
#: apps/native/src/app/person/[id].tsx:279
#: apps/native/src/app/person/[id].tsx:219
#: apps/web/src/components/people/filmography-grid.tsx:67
msgid "Filmography"
msgstr "Filmografia"
@@ -1002,8 +1016,8 @@ msgstr "Sexta-feira"
msgid "Get Started"
msgstr "Começar"
#: apps/native/src/app/person/[id].tsx:176
#: apps/native/src/app/person/[id].tsx:196
#: apps/native/src/app/person/[id].tsx:261
#: apps/native/src/app/person/[id].tsx:281
#: apps/native/src/app/title/[id].tsx:235
msgid "Go back"
msgstr "Voltar"
@@ -1112,6 +1126,11 @@ msgstr "Na biblioteca"
msgid "In Library"
msgstr "Na Biblioteca"
#: apps/native/src/components/titles/status-action-button.tsx:46
#: apps/web/src/components/titles/status-button.tsx:40
msgid "In Watchlist"
msgstr "Na lista"
#: apps/native/src/app/(tabs)/(home)/index.tsx:179
#: apps/web/src/components/dashboard/library-section.tsx:35
msgid "In Your Library"
@@ -1222,22 +1241,23 @@ msgid "Mark all episodes as watched?"
msgstr "Marcar todos os episódios como assistidos?"
#: apps/native/src/components/titles/season-accordion.tsx:152
#: apps/native/src/components/ui/poster-card.tsx:229
#: apps/web/src/components/titles/title-seasons.tsx:109
#: apps/web/src/components/titles/title-seasons.tsx:135
msgid "Mark All Watched"
msgstr "Marcar Todos como Assistidos"
#: apps/native/src/components/dashboard/continue-watching-card.tsx:103
msgid "Mark as Completed"
msgstr "Marcar como Concluído"
#~ msgid "Mark as Completed"
#~ msgstr "Marcar como Concluído"
#: apps/native/src/components/ui/poster-card.tsx:226
#: apps/native/src/components/ui/poster-card.tsx:222
msgid "Mark as Watched"
msgstr "Marcar como Assistido"
#: apps/native/src/components/ui/poster-card.tsx:219
msgid "Mark as Watching"
msgstr "Marcar como Assistindo"
#~ msgid "Mark as Watching"
#~ msgstr "Marcar como Assistindo"
#: apps/native/src/app/title/[id].tsx:400
#: apps/web/src/components/titles/title-actions.tsx:27
@@ -1245,32 +1265,37 @@ msgid "Mark Watched"
msgstr "Marcar como Assistido"
#: apps/native/src/lib/title-actions.ts:50
msgid "Marked \"{titleName}\" as completed"
msgstr "Marcado \"{titleName}\" como concluído"
#~ msgid "Marked \"{titleName}\" as completed"
#~ msgstr "Marcado \"{titleName}\" como concluído"
#: apps/native/src/lib/title-actions.ts:63
#: apps/web/src/components/titles/use-title-actions.ts:134
#: apps/native/src/lib/title-actions.ts:39
#: apps/web/src/components/titles/use-title-actions.ts:131
msgid "Marked \"{titleName}\" as watched"
msgstr "Marcado \"{titleName}\" como assistido"
#: apps/web/src/components/titles/use-title-actions.ts:337
#: apps/native/src/lib/title-actions.ts:97
#: apps/web/src/components/titles/use-title-actions.ts:331
msgid "Marked all episodes as watched"
msgstr "Todos os episódios marcados como assistidos"
#: apps/native/src/lib/title-actions.ts:96
msgid "Marked all episodes of \"{titleName}\" as watched"
msgstr "Todos os episódios de \"{titleName}\" marcados como vistos"
#: apps/native/src/hooks/use-title-actions.ts:61
#: apps/native/src/lib/title-actions.ts:51
msgid "Marked as completed"
msgstr "Marcado como concluído"
#~ msgid "Marked as completed"
#~ msgstr "Marcado como concluído"
#: apps/native/src/hooks/use-title-actions.ts:76
#: apps/native/src/lib/title-actions.ts:63
#: apps/native/src/hooks/use-title-actions.ts:74
#: apps/native/src/lib/title-actions.ts:39
msgid "Marked as watched"
msgstr "Marcado como assistido"
#: apps/native/src/hooks/use-title-actions.ts:60
#: apps/native/src/lib/title-actions.ts:38
msgid "Marked as watching"
msgstr "Marcado como assistindo"
#~ msgid "Marked as watching"
#~ msgstr "Marcado como assistindo"
#: apps/web/src/components/settings/account-section.tsx:314
msgid "Member since {memberSince}"
@@ -1305,7 +1330,7 @@ msgstr "Filmes"
#. placeholder {0}: periodLabels[moviePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx:114
msgid "Movies {0}"
msgstr ""
msgstr "Filmes {0}"
#: apps/web/src/components/dashboard/stats-display.tsx:161
#~ msgid "Movies {periodSelect}"
@@ -1345,7 +1370,7 @@ msgstr "Nunca executado"
msgid "New account creation is currently disabled."
msgstr "A criação de novas contas está desativada no momento."
#: apps/web/src/routes/_auth/register.tsx:36
#: apps/web/src/routes/_auth/register.tsx:33
msgid "New accounts are not being accepted right now. Contact the admin if you need access."
msgstr "Novas contas não estão sendo aceitas agora. Entre em contato com o administrador se precisar de acesso."
@@ -1403,7 +1428,7 @@ msgstr "Nenhum resultado encontrado."
msgid "No titles found for this genre."
msgstr "Nenhum título encontrado para este gênero."
#: apps/native/src/components/settings/integration-card.tsx:174
#: apps/native/src/components/settings/integration-card.tsx:183
#: apps/web/src/components/settings/integration-card.tsx:153
#: apps/web/src/components/settings/system-health-section.tsx:229
msgid "Not configured"
@@ -1517,8 +1542,8 @@ msgstr "Verificar periodicamente o GitHub por novas versões do Sofa"
msgid "Person"
msgstr "Pessoa"
#: apps/native/src/app/person/[id].tsx:192
#: apps/web/src/routes/_app/people.$id.tsx:50
#: apps/native/src/app/person/[id].tsx:277
#: apps/web/src/routes/_app/people.$id.tsx:52
msgid "Person not found"
msgstr "Pessoa não encontrada"
@@ -1527,12 +1552,12 @@ msgid "Play trailer"
msgstr "Reproduzir trailer"
#: apps/native/src/app/(tabs)/(explore)/index.tsx:89
#: apps/web/src/routes/_app/explore.tsx:141
#: apps/web/src/routes/_app/explore.tsx:143
msgid "Popular Movies"
msgstr "Filmes Populares"
#: apps/native/src/app/(tabs)/(explore)/index.tsx:102
#: apps/web/src/routes/_app/explore.tsx:151
#: apps/web/src/routes/_app/explore.tsx:153
msgid "Popular TV Shows"
msgstr "Séries Populares"
@@ -1540,7 +1565,7 @@ msgstr "Séries Populares"
msgid "Pre-restore backup"
msgstr "Backup pré-restauração"
#: apps/native/src/app/person/[id].tsx:53
#: apps/native/src/app/person/[id].tsx:141
#: apps/native/src/components/search/recently-viewed-row-content.tsx:31
#: apps/web/src/components/people/person-hero.tsx:75
msgid "Producer"
@@ -1612,7 +1637,7 @@ msgstr "URL da Lista do Radarr"
#. placeholder {0}: input.stars
#. placeholder {1}: input.stars
#: apps/native/src/hooks/use-title-actions.ts:88
#: apps/native/src/hooks/use-title-actions.ts:86
msgid "Rated {0} {1, plural, one {star} other {stars}}"
msgstr "Avaliado com {0} {1, plural, one {estrela} other {estrelas}}"
@@ -1620,11 +1645,11 @@ msgstr "Avaliado com {0} {1, plural, one {estrela} other {estrelas}}"
#~ msgid "Rated {0} star{1}"
#~ msgstr "Rated {0} star{1}"
#: apps/web/src/components/titles/use-title-actions.ts:118
#: apps/web/src/components/titles/use-title-actions.ts:115
msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}"
msgstr "Avaliado com {ratingStars} {ratingStars, plural, one {estrela} other {estrelas}}"
#: apps/native/src/lib/title-actions.ts:86
#: apps/native/src/lib/title-actions.ts:62
msgid "Rated {stars, plural, one {# star} other {# stars}}"
msgstr "Avaliado com {stars, plural, one {# estrela} other {# estrelas}}"
@@ -1633,9 +1658,9 @@ msgstr "Avaliado com {stars, plural, one {# estrela} other {# estrelas}}"
msgid "Rating"
msgstr "Avaliação"
#: apps/native/src/hooks/use-title-actions.ts:89
#: apps/native/src/lib/title-actions.ts:87
#: apps/web/src/components/titles/use-title-actions.ts:119
#: apps/native/src/hooks/use-title-actions.ts:87
#: apps/native/src/lib/title-actions.ts:63
#: apps/web/src/components/titles/use-title-actions.ts:116
msgid "Rating removed"
msgstr "Avaliação removida"
@@ -1663,7 +1688,7 @@ msgid "Recent Searches"
msgstr "Pesquisas Recentes"
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:95
#: apps/native/src/components/search/recently-viewed-list.tsx:77
#: apps/native/src/components/search/recently-viewed-list.tsx:59
msgid "Recently Viewed"
msgstr "Vistos Recentemente"
@@ -1692,12 +1717,12 @@ msgstr "Atualizar"
msgid "Refresh system health"
msgstr "Atualizar status de saúde do sistema"
#: apps/native/src/components/settings/integration-card.tsx:128
#: apps/native/src/components/settings/integration-card.tsx:248
#: apps/native/src/components/settings/integration-card.tsx:137
#: apps/native/src/components/settings/integration-card.tsx:257
msgid "Regenerate"
msgstr "Regenerar"
#: apps/native/src/components/settings/integration-card.tsx:123
#: apps/native/src/components/settings/integration-card.tsx:132
#: apps/web/src/components/settings/integration-card.tsx:226
msgid "Regenerate URL"
msgstr "Regenerar URL"
@@ -1717,7 +1742,7 @@ msgid "Registration closed"
msgstr "Registro fechado"
#: apps/native/src/app/(auth)/register.tsx:87
#: apps/web/src/routes/_auth/register.tsx:33
#: apps/web/src/routes/_auth/register.tsx:30
msgid "Registration Closed"
msgstr "Registro Fechado"
@@ -1726,20 +1751,27 @@ msgstr "Registro Fechado"
msgid "Registration opened"
msgstr "Registro aberto"
#: apps/web/src/components/titles/status-button.tsx:76
#: apps/native/src/components/titles/status-action-button.tsx:106
#: apps/web/src/components/titles/status-button.tsx:109
#: apps/web/src/components/titles/status-button.tsx:139
msgid "Remove"
msgstr "Remover"
#: apps/native/src/components/titles/status-action-button.tsx:96
#: apps/web/src/components/titles/status-button.tsx:60
#: apps/native/src/components/titles/status-action-button.tsx:115
#: apps/web/src/components/titles/status-button.tsx:93
msgid "Remove from library"
msgstr "Remover da biblioteca"
#: apps/native/src/components/dashboard/continue-watching-card.tsx:108
#: apps/native/src/components/ui/poster-card.tsx:233
#: apps/native/src/components/ui/poster-card.tsx:236
msgid "Remove from Library"
msgstr "Remover da Biblioteca"
#: apps/native/src/components/titles/status-action-button.tsx:101
#: apps/web/src/components/titles/status-button.tsx:120
msgid "Remove from library?"
msgstr "Remover da biblioteca?"
#: apps/native/src/app/(tabs)/(settings)/index.tsx:268
msgid "Remove Photo"
msgstr "Remover Foto"
@@ -1752,9 +1784,9 @@ msgstr "Remover foto"
msgid "Remove profile picture"
msgstr "Remover foto de perfil"
#: apps/native/src/hooks/use-title-actions.ts:65
#: apps/native/src/lib/title-actions.ts:74
#: apps/web/src/components/titles/use-title-actions.ts:98
#: apps/native/src/hooks/use-title-actions.ts:63
#: apps/native/src/lib/title-actions.ts:50
#: apps/web/src/components/titles/use-title-actions.ts:95
msgid "Removed from library"
msgstr "Removido da biblioteca"
@@ -1861,14 +1893,14 @@ msgstr "Backups agendados ativados"
#: apps/native/src/app/(tabs)/(search)/_layout.tsx:7
#: apps/native/src/components/navigation/native-tab-bar.tsx:41
msgid "Search"
msgstr ""
msgstr "Pesquisar"
#: apps/web/src/components/dashboard/stats-section.tsx:35
msgid "Search for movies and TV shows to start tracking"
msgstr "Pesquise filmes e séries para começar a acompanhar"
#: apps/native/src/components/search/recently-viewed-list.ios.tsx:72
#: apps/native/src/components/search/recently-viewed-list.tsx:55
#: apps/native/src/components/search/recently-viewed-list.tsx:81
msgid "Search for movies, shows, or people"
msgstr "Pesquise filmes, séries ou pessoas"
@@ -1892,13 +1924,13 @@ msgstr "Pesquisar…"
#. placeholder {0}: season.seasonNumber
#: apps/native/src/components/titles/season-accordion.tsx:113
#: apps/native/src/components/titles/season-accordion.tsx:119
#: apps/web/src/components/titles/use-title-actions.ts:274
#: apps/web/src/components/titles/use-title-actions.ts:313
#: apps/web/src/components/titles/use-title-actions.ts:266
#: apps/web/src/components/titles/use-title-actions.ts:305
msgid "Season {0}"
msgstr "Temporada {0}"
#: apps/native/src/hooks/use-title-actions.ts:121
#: apps/native/src/lib/title-actions.ts:119
#: apps/native/src/hooks/use-title-actions.ts:119
#: apps/native/src/lib/title-actions.ts:109
msgid "Season watched"
msgstr "Temporada assistida"
@@ -1907,7 +1939,7 @@ msgid "Seasons"
msgstr "Temporadas"
#: apps/native/src/app/(tabs)/(settings)/index.tsx:452
#: apps/web/src/routes/_app/settings.tsx:167
#: apps/web/src/routes/_app/settings.tsx:169
msgid "Security"
msgstr "Segurança"
@@ -1915,7 +1947,7 @@ msgstr "Segurança"
msgid "Self-hosted movie & TV tracker"
msgstr "Rastreador de filmes e séries auto-hospedado"
#: apps/web/src/routes/_app/settings.tsx:151
#: apps/web/src/routes/_app/settings.tsx:153
msgid "Server"
msgstr "Servidor"
@@ -1947,12 +1979,12 @@ msgstr "Defina seu perfil de qualidade preferido e pasta raiz"
msgid "Settings"
msgstr "Configurações"
#: apps/native/src/components/settings/integration-card.tsx:271
#: apps/native/src/components/settings/integration-card.tsx:280
#: apps/web/src/components/settings/integration-card.tsx:248
msgid "Setup instructions"
msgstr "Instruções de configuração"
#: apps/web/src/routes/setup.tsx:95
#: apps/web/src/routes/setup.tsx:96
msgid "Setup required"
msgstr "Configuração necessária"
@@ -1977,7 +2009,7 @@ msgstr "Entrar"
msgid "Sign In"
msgstr "Entrar"
#: apps/web/src/routes/_auth/register.tsx:45
#: apps/web/src/routes/_auth/register.tsx:42
msgid "Sign in instead"
msgstr "Entrar em vez disso"
@@ -2031,13 +2063,13 @@ msgid "Sofa will automatically log movies and episodes when you finish watching
msgstr "O Sofa registrará automaticamente filmes e episódios quando você terminar de assisti-los"
#: apps/native/src/app/change-password.tsx:77
#: apps/native/src/app/person/[id].tsx:169
#: apps/native/src/app/person/[id].tsx:254
#: apps/web/src/components/settings/account-section.tsx:391
#: apps/web/src/routes/__root.tsx:139
msgid "Something went wrong"
msgstr "Algo deu errado"
#: apps/web/src/routes/_app/titles.$id.tsx:113
#: apps/web/src/routes/_app/titles.$id.tsx:114
msgid "Something went wrong while loading this title. Please try again."
msgstr "Algo deu errado ao carregar este título. Tente novamente."
@@ -2070,7 +2102,7 @@ msgstr "Iniciando às"
msgid "Starting import..."
msgstr "Iniciando importação..."
#: apps/native/src/hooks/use-title-actions.ts:64
#: apps/native/src/hooks/use-title-actions.ts:62
msgid "Status updated"
msgstr "Status atualizado"
@@ -2095,11 +2127,11 @@ msgstr "Mudar para {0}"
msgid "The page you're looking for doesn't exist."
msgstr "A página que você está procurando não existe."
#: apps/web/src/routes/_app/people.$id.tsx:53
#: apps/web/src/routes/_app/people.$id.tsx:55
msgid "The person you're looking for doesn't exist or may have been removed from the database."
msgstr "A pessoa que você está procurando não existe ou pode ter sido removida do banco de dados."
#: apps/web/src/routes/_app/titles.$id.tsx:142
#: apps/web/src/routes/_app/titles.$id.tsx:143
msgid "The title you're looking for doesn't exist or may have been removed from the database."
msgstr "O título que você está procurando não existe ou pode ter sido removido do banco de dados."
@@ -2109,7 +2141,7 @@ msgstr "Isso pode levar alguns minutos para bibliotecas grandes. Por favor, não
#: apps/native/src/app/(tabs)/(home)/index.tsx:89
msgid "this month"
msgstr ""
msgstr "este mês"
#: apps/native/src/components/dashboard/stats-card.tsx:31
#: apps/web/src/components/dashboard/stats-display.tsx:135
@@ -2121,14 +2153,19 @@ msgid "This page was left on the cutting room floor. It may have been moved, rem
msgstr "Esta página ficou no chão da sala de montagem. Pode ter sido movida, removida ou nunca ter passado do roteiro."
#: apps/native/src/app/(tabs)/(settings)/index.tsx:559
#: apps/web/src/routes/_app/settings.tsx:112
#: apps/web/src/routes/setup.tsx:180
#: apps/web/src/routes/_app/settings.tsx:114
#: apps/web/src/routes/setup.tsx:181
msgid "This product uses the TMDB API but is not endorsed or certified by TMDB."
msgstr "Este produto usa a API do TMDB, mas não é endossado ou certificado pelo TMDB."
#: apps/native/src/components/titles/status-action-button.tsx:102
#: apps/web/src/components/titles/status-button.tsx:123
msgid "This title will be removed from your library. Your watch history and ratings will be kept."
msgstr "Este título será removido da sua biblioteca. O seu histórico de visualizações e avaliações serão mantidos."
#: apps/native/src/app/(tabs)/(home)/index.tsx:88
msgid "this week"
msgstr ""
msgstr "esta semana"
#: apps/native/src/components/dashboard/stats-card.tsx:30
#: apps/web/src/components/dashboard/stats-display.tsx:134
@@ -2147,7 +2184,7 @@ msgstr "Isso excluirá todos os títulos stub não enriquecidos e todas as image
msgid "This will delete un-enriched stub titles that aren't in any user's library and clean up orphaned person records. Deleted titles will be re-imported if accessed again."
msgstr "Isso excluirá títulos stub não enriquecidos que não estão na biblioteca de nenhum usuário e limpará registros de pessoas órfãs. Os títulos excluídos serão reimportados se acessados novamente."
#: apps/native/src/components/settings/integration-card.tsx:124
#: apps/native/src/components/settings/integration-card.tsx:133
msgid "This will invalidate the current {label} URL. You'll need to update it in {label}."
msgstr "Isso invalidará a URL atual do {label}. Você precisará atualizá-la no {label}."
@@ -2171,7 +2208,7 @@ msgstr "Isso substituirá todo o seu banco de dados pelo arquivo enviado. Um bac
#: apps/native/src/app/(tabs)/(home)/index.tsx:90
msgid "this year"
msgstr ""
msgstr "este ano"
#: apps/native/src/components/dashboard/stats-card.tsx:32
#: apps/web/src/components/dashboard/stats-display.tsx:136
@@ -2187,7 +2224,7 @@ msgid "Time:"
msgstr "Hora:"
#: apps/native/src/app/title/[id].tsx:231
#: apps/web/src/routes/_app/titles.$id.tsx:139
#: apps/web/src/routes/_app/titles.$id.tsx:140
msgid "Title not found"
msgstr "Título não encontrado"
@@ -2203,7 +2240,7 @@ msgstr "Os títulos na sua lista de desejos do Sofa serão automaticamente adici
#: apps/native/src/app/(tabs)/(home)/index.tsx:87
msgid "today"
msgstr ""
msgstr "hoje"
#: apps/native/src/components/dashboard/stats-card.tsx:29
#: apps/web/src/components/dashboard/stats-display.tsx:133
@@ -2229,14 +2266,14 @@ msgstr "Acompanhe o que você assiste. Saiba o que vem a seguir.<0/>Sua bibliote
#: apps/web/src/components/titles/trailer-dialog.tsx:38
#: apps/web/src/components/titles/trailer-dialog.tsx:42
msgid "Trailer"
msgstr ""
msgstr "Trailer"
#: apps/web/src/components/explore/hero-banner.tsx:70
msgid "Trending today"
msgstr "Em alta hoje"
#: apps/native/src/app/(tabs)/(explore)/index.tsx:77
#: apps/web/src/routes/_app/explore.tsx:129
#: apps/web/src/routes/_app/explore.tsx:131
msgid "Trending Today"
msgstr "Em Alta Hoje"
@@ -2291,11 +2328,11 @@ msgid "Unwatch all"
msgstr "Desmarcar todos"
#. placeholder {0}: season.name ?? t`Season ${season.seasonNumber}`
#: apps/web/src/components/titles/use-title-actions.ts:313
#: apps/web/src/components/titles/use-title-actions.ts:305
msgid "Unwatched all of {0}"
msgstr "Desmarcados todos os episódios de {0}"
#: apps/web/src/components/titles/use-title-actions.ts:156
#: apps/web/src/components/titles/use-title-actions.ts:154
msgid "Unwatched S{seasonNum} E{epNum}"
msgstr "Desmarcado T{seasonNum} E{epNum}"
@@ -2366,7 +2403,7 @@ msgstr "Enviar foto"
msgid "Upload profile picture"
msgstr "Enviar foto de perfil"
#: apps/native/src/components/settings/integration-card.tsx:117
#: apps/native/src/components/settings/integration-card.tsx:125
msgid "URL copied to clipboard"
msgstr "URL copiada para a área de transferência"
@@ -2399,36 +2436,36 @@ msgstr "Histórico de exibição"
msgid "Watch on {name}"
msgstr "Assistir em {name}"
#: apps/web/src/components/titles/use-title-actions.ts:277
#: apps/web/src/components/titles/use-title-actions.ts:286
#: apps/web/src/components/titles/use-title-actions.ts:269
#: apps/web/src/components/titles/use-title-actions.ts:278
msgid "Watched all of {seasonLabel}"
msgstr "Todos os episódios de {seasonLabel} assistidos"
#: apps/native/src/lib/title-actions.ts:119
#: apps/native/src/lib/title-actions.ts:109
msgid "Watched all of {seasonName}"
msgstr "Todos os episódios de {seasonName} assistidos"
#: apps/web/src/components/titles/use-title-actions.ts:199
#: apps/web/src/components/titles/use-title-actions.ts:208
#: apps/web/src/components/titles/use-title-actions.ts:197
#: apps/web/src/components/titles/use-title-actions.ts:206
msgid "Watched S{seasonNum} E{epNum}"
msgstr "Assistido T{seasonNum} E{epNum}"
#: apps/native/src/components/titles/status-action-button.tsx:43
#: apps/native/src/components/titles/status-action-button.tsx:48
#: apps/web/src/components/title-card.tsx:69
#: apps/web/src/components/titles/status-button.tsx:14
#: apps/web/src/components/titles/status-button.tsx:47
msgid "Watching"
msgstr "Assistindo"
#: apps/native/src/components/titles/status-action-button.tsx:78
#: apps/native/src/components/titles/status-action-button.tsx:85
#: apps/web/src/components/settings/imports-section.tsx:743
#: apps/web/src/components/settings/imports-section.tsx:769
#: apps/web/src/components/titles/status-button.tsx:49
#: apps/web/src/components/titles/status-button.tsx:82
msgid "Watchlist"
msgstr "Lista de Desejos"
#: apps/native/src/components/titles/status-action-button.tsx:41
msgid "Watchlisted"
msgstr "Na Lista de Desejos"
#~ msgid "Watchlisted"
#~ msgstr "Na Lista de Desejos"
#: apps/native/src/components/settings/integration-configs.ts:51
#: apps/native/src/components/settings/integration-configs.ts:66
@@ -2458,7 +2495,7 @@ msgstr "Onde Assistir"
msgid "With Ads"
msgstr "Com Anúncios"
#: apps/native/src/app/person/[id].tsx:52
#: apps/native/src/app/person/[id].tsx:140
#: apps/native/src/components/search/recently-viewed-row-content.tsx:30
#: apps/web/src/components/people/person-hero.tsx:73
msgid "Writer"
File diff suppressed because one or more lines are too long