feat(tracking): add a paginated watch history and Last watched library sort

Adds tracking.history (cursor-paginated, movies and episodes merged), a
last_watched library sort, and a /history web page.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
jakeandClaude Sonnet 5.5 committed 2026-10-05 14:36:44 -04:00
1 parent 6cd99a39a9
commit b292fe37ab
30 files changed
+1711 -6

No files matched your search

@@ -7,7 +7,14 @@ import { MenuTrigger } from "@/components/ui/menu-trigger";
import { ScaledIcon } from "@/components/ui/scaled-icon"; import { ScaledIcon } from "@/components/ui/scaled-icon";
import * as Haptics from "@/utils/haptics"; import * as Haptics from "@/utils/haptics";
type SortBy = "added_at" | "title" | "release_date" | "user_rating" | "vote_average" | "popularity"; type SortBy =
| "added_at"
| "title"
| "release_date"
| "user_rating"
| "vote_average"
| "popularity"
| "last_watched";
type SortDirection = "asc" | "desc"; type SortDirection = "asc" | "desc";
interface SortOption { interface SortOption {
@@ -33,6 +40,7 @@ export function SortMenu({ sortBy, sortDirection, onSortChange }: SortMenuProps)
{ sortBy: "release_date", sortDirection: "desc", label: t`Release Date` }, { sortBy: "release_date", sortDirection: "desc", label: t`Release Date` },
{ sortBy: "user_rating", sortDirection: "desc", label: t`User Rating` }, { sortBy: "user_rating", sortDirection: "desc", label: t`User Rating` },
{ sortBy: "vote_average", sortDirection: "desc", label: t`TMDB Rating` }, { sortBy: "vote_average", sortDirection: "desc", label: t`TMDB Rating` },
{ sortBy: "last_watched", sortDirection: "desc", label: t`Last watched` },
{ sortBy: "popularity", sortDirection: "desc", label: t`Popularity` }, { sortBy: "popularity", sortDirection: "desc", label: t`Popularity` },
]; ];
+2 -1
View File
@@ -6,7 +6,8 @@ export type SortBy =
| "release_date" | "release_date"
| "user_rating" | "user_rating"
| "vote_average" | "vote_average"
| "popularity"; | "popularity"
| "last_watched";
export const libraryActiveFilterCountAtom = atom(0); export const libraryActiveFilterCountAtom = atom(0);
export const librarySortByAtom = atom<SortBy>("added_at"); export const librarySortByAtom = atom<SortBy>("added_at");
@@ -7,6 +7,7 @@ import { getOrFetchTitleByTmdbId } from "@sofa/core/metadata";
import { import {
getDisplayStatusesByTitleIds, getDisplayStatusesByTitleIds,
getUserTitleInfo, getUserTitleInfo,
listWatchHistory,
logEpisodeWatch, logEpisodeWatch,
logEpisodeWatchBatch, logEpisodeWatchBatch,
logMovieWatch, logMovieWatch,
@@ -21,6 +22,7 @@ import {
watchSeason, watchSeason,
} from "@sofa/core/tracking"; } from "@sofa/core/tracking";
import { createLogger } from "@sofa/logger"; import { createLogger } from "@sofa/logger";
import { tmdbImageUrl } from "@sofa/tmdb/image";
import { os } from "../context"; import { os } from "../context";
import { authed } from "../middleware"; import { authed } from "../middleware";
@@ -122,3 +124,21 @@ export const stats = os.tracking.stats.use(authed).handler(({ input, context })
const history = getWatchHistory(context.user.id, coreType, input.period); const history = getWatchHistory(context.user.id, coreType, input.period);
return { count, history }; return { count, history };
}); });
export const history = os.tracking.history.use(authed).handler(({ input, context }) => {
const result = listWatchHistory(context.user.id, input);
return {
items: result.items.map((item) => ({
watchId: item.watchId,
kind: item.kind,
watchedAt: item.watchedAt.toISOString(),
source: item.source,
title: {
...item.title,
posterPath: tmdbImageUrl(item.title.posterPath, "posters"),
},
episode: item.episode,
})),
nextCursor: result.nextCursor,
};
});
+1
View File
@@ -21,6 +21,7 @@ export const implementedRouter = {
rate: tracking.rate, rate: tracking.rate,
userInfo: tracking.userInfo, userInfo: tracking.userInfo,
stats: tracking.stats, stats: tracking.stats,
history: tracking.history,
}, },
library: { library: {
list: library.list, list: library.list,
@@ -0,0 +1,78 @@
import { useLingui } from "@lingui/react/macro";
import { IconMovie } from "@tabler/icons-react";
import { Link } from "@tanstack/react-router";
import type { z } from "zod";
import { thumbHashToUrl } from "@/lib/thumbhash";
import type { WatchHistoryItemSchema } from "@sofa/api/schemas";
import { formatDate } from "@sofa/i18n/format";
type WatchHistoryItem = z.infer<typeof WatchHistoryItemSchema>;
export function HistoryRow({ item }: { item: WatchHistoryItem }) {
const { t } = useLingui();
const sourceLabels = {
manual: t`Manual`,
import: t`Import`,
plex: t`Plex`,
jellyfin: t`Jellyfin`,
emby: t`Emby`,
} as const;
let subtitle: string | null = null;
if (item.episode) {
const season = item.episode.seasonNumber;
const episode = item.episode.episodeNumber;
const name = item.episode.name;
subtitle = name ? t`S${season} E${episode} · ${name}` : t`S${season} E${episode}`;
}
const time = formatDate(item.watchedAt, {
year: undefined,
month: undefined,
day: undefined,
hour: "numeric",
minute: "2-digit",
});
return (
<Link
to="/titles/$id"
params={{ id: item.title.id }}
className="group bg-card/40 hover:bg-card/60 hover:ring-primary/25 flex items-center gap-4 rounded-xl p-3 ring-1 ring-white/[0.06] transition-[background,ring-color] duration-200"
>
<div className="relative h-[66px] w-11 shrink-0 overflow-hidden rounded-lg ring-1 ring-white/[0.06]">
{item.title.posterPath ? (
<img
src={item.title.posterPath}
alt=""
className="size-full object-cover"
loading="lazy"
{...(item.title.posterThumbHash
? {
style: {
background: `url(${thumbHashToUrl(item.title.posterThumbHash)}) center/cover`,
},
}
: {})}
/>
) : (
<div className="bg-muted flex size-full items-center justify-center">
<IconMovie className="text-muted-foreground size-5" />
</div>
)}
</div>
<div className="min-w-0 flex-1">
<div className="truncate text-sm font-medium">{item.title.title}</div>
{subtitle && <div className="text-muted-foreground mt-1 truncate text-xs">{subtitle}</div>}
</div>
<div className="flex shrink-0 flex-col items-end gap-1">
<span className="text-muted-foreground text-xs tabular-nums">{time}</span>
<span className="bg-muted text-muted-foreground rounded px-1.5 py-0.5 text-[10px] font-medium tracking-wider uppercase">
{sourceLabels[item.source]}
</span>
</div>
</Link>
);
}
@@ -51,6 +51,7 @@ export function LibraryToolbar({
{ label: t`Release Date`, sortBy: "release_date", direction: "desc" }, { label: t`Release Date`, sortBy: "release_date", direction: "desc" },
{ label: t`User Rating`, sortBy: "user_rating", direction: "desc" }, { label: t`User Rating`, sortBy: "user_rating", direction: "desc" },
{ label: t`TMDB Rating`, sortBy: "vote_average", direction: "desc" }, { label: t`TMDB Rating`, sortBy: "vote_average", direction: "desc" },
{ label: t`Last watched`, sortBy: "last_watched", direction: "desc" },
{ label: t`Popularity`, sortBy: "popularity", direction: "desc" }, { label: t`Popularity`, sortBy: "popularity", direction: "desc" },
], ],
[t], [t],
+3
View File
@@ -3,6 +3,7 @@ import {
IconBooks, IconBooks,
IconCalendarEvent, IconCalendarEvent,
IconCompass, IconCompass,
IconHistory,
IconHome, IconHome,
IconLogout, IconLogout,
IconSearch, IconSearch,
@@ -125,6 +126,7 @@ export function NavBar({
{ href: "/library", label: t`Library` }, { href: "/library", label: t`Library` },
{ href: "/explore", label: t`Explore` }, { href: "/explore", label: t`Explore` },
{ href: "/upcoming", label: t`Upcoming` }, { href: "/upcoming", label: t`Upcoming` },
{ href: "/history", label: t`History` },
] as const; ] as const;
const initial = userName?.charAt(0).toUpperCase() ?? "?"; const initial = userName?.charAt(0).toUpperCase() ?? "?";
@@ -289,6 +291,7 @@ export function MobileTabBar() {
{ href: "/library", label: t`Library`, icon: IconBooks }, { href: "/library", label: t`Library`, icon: IconBooks },
{ href: "/explore", label: t`Explore`, icon: IconCompass }, { href: "/explore", label: t`Explore`, icon: IconCompass },
{ href: "/upcoming", label: t`Upcoming`, icon: IconCalendarEvent }, { href: "/upcoming", label: t`Upcoming`, icon: IconCalendarEvent },
{ href: "/history", label: t`History`, icon: IconHistory },
{ href: "/settings", label: t`Settings`, icon: IconSettings }, { href: "/settings", label: t`Settings`, icon: IconSettings },
] as const; ] as const;
+21
View File
@@ -15,6 +15,7 @@ import { Route as AuthRouteImport } from './routes/_auth'
import { Route as SetupRouteImport } from './routes/setup' import { Route as SetupRouteImport } from './routes/setup'
import { Route as AppDashboardRouteImport } from './routes/_app/dashboard' import { Route as AppDashboardRouteImport } from './routes/_app/dashboard'
import { Route as AppExploreRouteImport } from './routes/_app/explore' import { Route as AppExploreRouteImport } from './routes/_app/explore'
import { Route as AppHistoryRouteImport } from './routes/_app/history'
import { Route as AppLibraryRouteImport } from './routes/_app/library' import { Route as AppLibraryRouteImport } from './routes/_app/library'
import { Route as AppOnboardingRouteImport } from './routes/_app/onboarding' import { Route as AppOnboardingRouteImport } from './routes/_app/onboarding'
import { Route as AppSettingsRouteImport } from './routes/_app/settings' import { Route as AppSettingsRouteImport } from './routes/_app/settings'
@@ -52,6 +53,11 @@ const AppExploreRoute = AppExploreRouteImport.update({
path: '/explore', path: '/explore',
getParentRoute: () => AppRoute, getParentRoute: () => AppRoute,
} as any) } as any)
const AppHistoryRoute = AppHistoryRouteImport.update({
id: '/history',
path: '/history',
getParentRoute: () => AppRoute,
} as any)
const AppLibraryRoute = AppLibraryRouteImport.update({ const AppLibraryRoute = AppLibraryRouteImport.update({
id: '/library', id: '/library',
path: '/library', path: '/library',
@@ -98,6 +104,7 @@ export interface FileRoutesByFullPath {
'/setup': typeof SetupRoute '/setup': typeof SetupRoute
'/dashboard': typeof AppDashboardRoute '/dashboard': typeof AppDashboardRoute
'/explore': typeof AppExploreRoute '/explore': typeof AppExploreRoute
'/history': typeof AppHistoryRoute
'/library': typeof AppLibraryRoute '/library': typeof AppLibraryRoute
'/onboarding': typeof AppOnboardingRoute '/onboarding': typeof AppOnboardingRoute
'/settings': typeof AppSettingsRoute '/settings': typeof AppSettingsRoute
@@ -112,6 +119,7 @@ export interface FileRoutesByTo {
'/setup': typeof SetupRoute '/setup': typeof SetupRoute
'/dashboard': typeof AppDashboardRoute '/dashboard': typeof AppDashboardRoute
'/explore': typeof AppExploreRoute '/explore': typeof AppExploreRoute
'/history': typeof AppHistoryRoute
'/library': typeof AppLibraryRoute '/library': typeof AppLibraryRoute
'/onboarding': typeof AppOnboardingRoute '/onboarding': typeof AppOnboardingRoute
'/settings': typeof AppSettingsRoute '/settings': typeof AppSettingsRoute
@@ -129,6 +137,7 @@ export interface FileRoutesById {
'/setup': typeof SetupRoute '/setup': typeof SetupRoute
'/_app/dashboard': typeof AppDashboardRoute '/_app/dashboard': typeof AppDashboardRoute
'/_app/explore': typeof AppExploreRoute '/_app/explore': typeof AppExploreRoute
'/_app/history': typeof AppHistoryRoute
'/_app/library': typeof AppLibraryRoute '/_app/library': typeof AppLibraryRoute
'/_app/onboarding': typeof AppOnboardingRoute '/_app/onboarding': typeof AppOnboardingRoute
'/_app/settings': typeof AppSettingsRoute '/_app/settings': typeof AppSettingsRoute
@@ -145,6 +154,7 @@ export interface FileRouteTypes {
| '/setup' | '/setup'
| '/dashboard' | '/dashboard'
| '/explore' | '/explore'
| '/history'
| '/library' | '/library'
| '/onboarding' | '/onboarding'
| '/settings' | '/settings'
@@ -159,6 +169,7 @@ export interface FileRouteTypes {
| '/setup' | '/setup'
| '/dashboard' | '/dashboard'
| '/explore' | '/explore'
| '/history'
| '/library' | '/library'
| '/onboarding' | '/onboarding'
| '/settings' | '/settings'
@@ -175,6 +186,7 @@ export interface FileRouteTypes {
| '/setup' | '/setup'
| '/_app/dashboard' | '/_app/dashboard'
| '/_app/explore' | '/_app/explore'
| '/_app/history'
| '/_app/library' | '/_app/library'
| '/_app/onboarding' | '/_app/onboarding'
| '/_app/settings' | '/_app/settings'
@@ -236,6 +248,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppExploreRouteImport preLoaderRoute: typeof AppExploreRouteImport
parentRoute: typeof AppRoute parentRoute: typeof AppRoute
} }
'/_app/history': {
id: '/_app/history'
path: '/history'
fullPath: '/history'
preLoaderRoute: typeof AppHistoryRouteImport
parentRoute: typeof AppRoute
}
'/_app/library': { '/_app/library': {
id: '/_app/library' id: '/_app/library'
path: '/library' path: '/library'
@@ -298,6 +317,7 @@ declare module '@tanstack/react-router' {
interface AppRouteChildren { interface AppRouteChildren {
AppDashboardRoute: typeof AppDashboardRoute AppDashboardRoute: typeof AppDashboardRoute
AppExploreRoute: typeof AppExploreRoute AppExploreRoute: typeof AppExploreRoute
AppHistoryRoute: typeof AppHistoryRoute
AppLibraryRoute: typeof AppLibraryRoute AppLibraryRoute: typeof AppLibraryRoute
AppOnboardingRoute: typeof AppOnboardingRoute AppOnboardingRoute: typeof AppOnboardingRoute
AppSettingsRoute: typeof AppSettingsRoute AppSettingsRoute: typeof AppSettingsRoute
@@ -309,6 +329,7 @@ interface AppRouteChildren {
const AppRouteChildren: AppRouteChildren = { const AppRouteChildren: AppRouteChildren = {
AppDashboardRoute: AppDashboardRoute, AppDashboardRoute: AppDashboardRoute,
AppExploreRoute: AppExploreRoute, AppExploreRoute: AppExploreRoute,
AppHistoryRoute: AppHistoryRoute,
AppLibraryRoute: AppLibraryRoute, AppLibraryRoute: AppLibraryRoute,
AppOnboardingRoute: AppOnboardingRoute, AppOnboardingRoute: AppOnboardingRoute,
AppSettingsRoute: AppSettingsRoute, AppSettingsRoute: AppSettingsRoute,
+212
View File
@@ -0,0 +1,212 @@
import { Trans, useLingui } from "@lingui/react/macro";
import { IconHistory } from "@tabler/icons-react";
import { useInfiniteQuery } from "@tanstack/react-query";
import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { zodValidator } from "@tanstack/zod-adapter";
import { z } from "zod";
import { HistoryRow } from "@/components/history/history-row";
import { RouteError } from "@/components/route-error";
import { Skeleton } from "@/components/ui/skeleton";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { useInfiniteScroll } from "@/hooks/use-infinite-scroll";
import { orpc } from "@/lib/orpc/client";
import { formatLocalDate } from "@sofa/i18n/date-buckets";
import { formatDate } from "@sofa/i18n/format";
const historySearchSchema = z.object({
type: z.enum(["all", "movie", "tv"]).optional().catch(undefined),
source: z
.enum(["all", "manual", "import", "plex", "jellyfin", "emby"])
.optional()
.catch(undefined),
});
type SourceFilter = "manual" | "import" | "plex" | "jellyfin" | "emby";
export const Route = createFileRoute("/_app/history")({
validateSearch: zodValidator(historySearchSchema),
staleTime: 30_000,
loader: async ({ context }) => {
await context.queryClient.ensureInfiniteQueryData(
orpc.tracking.history.infiniteOptions({
input: (pageParam: string | undefined) => ({
limit: 30,
cursor: pageParam,
}),
initialPageParam: undefined as string | undefined,
getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
}),
);
},
head: () => ({ meta: [{ title: "History — Sofa" }] }),
pendingComponent: HistorySkeleton,
errorComponent: RouteError,
component: HistoryPage,
});
function HistorySkeleton() {
return (
<div className="mx-auto max-w-2xl space-y-6">
<div>
<Skeleton className="h-8 w-48" />
<Skeleton className="mt-2 h-4 w-64" />
</div>
{Array.from({ length: 5 }, (_, i) => (
<div key={i} className="flex items-center gap-3.5 py-2">
<Skeleton className="size-[52px] rounded-md" />
<div className="flex-1 space-y-1.5">
<Skeleton className="h-4 w-40" />
<Skeleton className="h-3 w-28" />
</div>
</div>
))}
</div>
);
}
function HistoryPage() {
const { t } = useLingui();
const search = Route.useSearch();
const navigate = useNavigate({ from: Route.fullPath });
const typeFilter = search.type ?? "all";
const sourceFilter = search.source ?? "all";
const { data, isPending, fetchNextPage, hasNextPage, isFetchingNextPage, isFetchNextPageError } =
useInfiniteQuery(
orpc.tracking.history.infiniteOptions({
// Omit filter keys (rather than sending "all") so the default input
// matches the loader's prefetch key.
input: (pageParam: string | undefined) => ({
limit: 30,
cursor: pageParam,
...(typeFilter !== "all" ? { type: typeFilter } : {}),
...(sourceFilter !== "all" ? { source: sourceFilter } : {}),
}),
initialPageParam: undefined as string | undefined,
getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
}),
);
const sentinelRef = useInfiniteScroll({
fetchNextPage,
hasNextPage,
isFetchingNextPage,
isFetchNextPageError,
});
function setTypeFilter(value: string) {
void navigate({
search: (prev) => ({
...prev,
type: value === "all" ? undefined : (value as "movie" | "tv"),
}),
replace: true,
});
}
function setSourceFilter(value: string) {
void navigate({
search: (prev) => ({
...prev,
source: value === "all" ? undefined : (value as SourceFilter),
}),
replace: true,
});
}
const header = (
<div>
<h1 className="font-display text-2xl tracking-tight">{t`History`}</h1>
<p className="text-muted-foreground mt-1 text-sm">
<Trans>Everything you've watched, newest first.</Trans>
</p>
</div>
);
const filterToggles = (
<div className="flex flex-wrap gap-3">
<ToggleGroup
value={[typeFilter]}
onValueChange={(values) => setTypeFilter(values.find((v) => v !== typeFilter) ?? "all")}
variant="outline"
size="sm"
>
<ToggleGroupItem value="all">{t`All`}</ToggleGroupItem>
<ToggleGroupItem value="movie">{t`Movies`}</ToggleGroupItem>
<ToggleGroupItem value="tv">{t`TV Shows`}</ToggleGroupItem>
</ToggleGroup>
<ToggleGroup
value={[sourceFilter]}
onValueChange={(values) => setSourceFilter(values.find((v) => v !== sourceFilter) ?? "all")}
variant="outline"
size="sm"
>
<ToggleGroupItem value="all">{t`All`}</ToggleGroupItem>
<ToggleGroupItem value="manual">{t`Manual`}</ToggleGroupItem>
<ToggleGroupItem value="import">{t`Import`}</ToggleGroupItem>
<ToggleGroupItem value="plex">{t`Plex`}</ToggleGroupItem>
<ToggleGroupItem value="jellyfin">{t`Jellyfin`}</ToggleGroupItem>
<ToggleGroupItem value="emby">{t`Emby`}</ToggleGroupItem>
</ToggleGroup>
</div>
);
if (isPending) return <HistorySkeleton />;
const allItems = data?.pages.flatMap((p) => p.items) ?? [];
if (allItems.length === 0) {
return (
<div className="mx-auto max-w-2xl space-y-6">
{header}
{filterToggles}
<div className="flex flex-col items-center justify-center py-20 text-center">
<IconHistory className="text-muted-foreground/40 size-12" />
<p className="text-muted-foreground mt-4 text-sm">
<Trans>Nothing watched yet.</Trans>
</p>
</div>
</div>
);
}
// Group by local calendar day, preserving newest-first order.
const days: { key: string; label: string; items: typeof allItems }[] = [];
for (const item of allItems) {
const date = new Date(item.watchedAt);
const key = formatLocalDate(date);
const last = days[days.length - 1];
if (last && last.key === key) {
last.items.push(item);
} else {
days.push({
key,
label: formatDate(date, { weekday: "long" }),
items: [item],
});
}
}
return (
<div className="mx-auto max-w-2xl space-y-6">
{header}
{filterToggles}
{days.map((day) => (
<section key={day.key}>
<h2 className="font-display text-muted-foreground mb-2 text-sm font-medium tracking-wider uppercase">
{day.label}
</h2>
<div className="space-y-2">
{day.items.map((item) => (
<HistoryRow key={item.watchId} item={item} />
))}
</div>
</section>
))}
<div ref={sentinelRef} />
{isFetchingNextPage && <HistorySkeleton />}
</div>
);
}
@@ -0,0 +1,27 @@
---
title: List watch history
full: true
_openapi:
preload:
- ./public/openapi.json
method: GET
webhook: false
toc: []
structuredData:
headings: []
contents:
- content: List the user's watches (movies and episodes), newest first, with
cursor pagination.
---
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
export default function Layout(props) {
const { OpenAPIPage } = props.components ?? {};
return (
<>
{props.children}
<OpenAPIPage document="./public/openapi.json" operations={[{"path":"/tracking/history","method":"get"}]} showDescription />
</>
);
}
+241 -1
View File
@@ -2294,6 +2294,245 @@
] ]
} }
}, },
"/tracking/history": {
"get": {
"operationId": "tracking.history",
"summary": "List watch history",
"description": "List the user's watches (movies and episodes), newest first, with cursor pagination.",
"tags": [
"Tracking"
],
"parameters": [
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"default": 30,
"description": "Maximum items to return"
},
"allowEmptyValue": true,
"allowReserved": true
},
{
"name": "cursor",
"in": "query",
"schema": {
"type": "string",
"description": "Opaque cursor from a previous response's nextCursor"
},
"allowEmptyValue": true,
"allowReserved": true
},
{
"name": "type",
"in": "query",
"schema": {
"enum": [
"movie",
"tv"
],
"type": "string",
"description": "Only movies or only TV episodes"
},
"allowEmptyValue": true,
"allowReserved": true
},
{
"name": "source",
"in": "query",
"schema": {
"enum": [
"manual",
"import",
"plex",
"jellyfin",
"emby"
],
"type": "string",
"description": "Only watches logged by this source"
},
"allowEmptyValue": true,
"allowReserved": true
}
],
"responses": {
"200": {
"description": "A page of watch history",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"watchId": {
"type": "string",
"description": "Watch record ID"
},
"kind": {
"enum": [
"movie",
"episode"
],
"type": "string",
"description": "Whether this watch is a movie or an episode"
},
"watchedAt": {
"type": "string",
"description": "ISO 8601 timestamp of the watch"
},
"source": {
"enum": [
"manual",
"import",
"plex",
"jellyfin",
"emby"
],
"type": "string",
"description": "How the watch was logged"
},
"title": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Title ID"
},
"title": {
"type": "string",
"description": "Display title"
},
"type": {
"enum": [
"movie",
"tv"
],
"type": "string",
"description": "Title type"
},
"posterPath": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Poster image URL"
},
"posterThumbHash": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Poster ThumbHash placeholder"
}
},
"required": [
"id",
"title",
"type",
"posterPath",
"posterThumbHash"
],
"description": "The movie or show"
},
"episode": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Episode ID"
},
"seasonNumber": {
"type": "number",
"description": "Season number"
},
"episodeNumber": {
"type": "number",
"description": "Episode number"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Episode name"
}
},
"required": [
"id",
"seasonNumber",
"episodeNumber",
"name"
]
},
{
"type": "null"
}
],
"description": "Episode details (null for movies)"
}
},
"required": [
"watchId",
"kind",
"watchedAt",
"source",
"title",
"episode"
],
"description": "A single watch event"
},
"description": "Watches, newest first"
},
"nextCursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Cursor for the next page, or null at the end"
}
},
"required": [
"items",
"nextCursor"
],
"description": "A page of watch history"
}
}
}
}
},
"security": [
{
"session": []
}
]
}
},
"/library": { "/library": {
"get": { "get": {
"operationId": "library.list", "operationId": "library.list",
@@ -2439,7 +2678,8 @@
"release_date", "release_date",
"popularity", "popularity",
"user_rating", "user_rating",
"vote_average" "vote_average",
"last_watched"
], ],
"type": "string", "type": "string",
"default": "added_at", "default": "added_at",
+14
View File
@@ -62,6 +62,8 @@ import {
UserInfoOutput, UserInfoOutput,
UserPlatformsOutput, UserPlatformsOutput,
WatchHistoryInput, WatchHistoryInput,
WatchHistoryListInput,
WatchHistoryListOutput,
WatchHistoryOutput, WatchHistoryOutput,
WatchInput, WatchInput,
} from "./schemas"; } from "./schemas";
@@ -183,6 +185,18 @@ export const contract = {
}) })
.input(WatchHistoryInput) .input(WatchHistoryInput)
.output(WatchHistoryOutput), .output(WatchHistoryOutput),
history: oc
.route({
method: "GET",
path: "/tracking/history",
tags: ["Tracking"],
summary: "List watch history",
description:
"List the user's watches (movies and episodes), newest first, with cursor pagination.",
successDescription: "A page of watch history",
})
.input(WatchHistoryListInput)
.output(WatchHistoryListOutput),
}, },
// ─── Library ──────────────────────────────────────────────── // ─── Library ────────────────────────────────────────────────
+56 -1
View File
@@ -134,6 +134,53 @@ export const WatchHistoryInput = z
}) })
.meta({ description: "Filters for watch history chart data" }); .meta({ description: "Filters for watch history chart data" });
// ─── Watch history list ────────────────────────────────────────
const watchSource = z.enum(["manual", "import", "plex", "jellyfin", "emby"]);
export const WatchHistoryListInput = z
.object({
limit: z.number().int().min(1).max(50).default(30).describe("Maximum items to return"),
cursor: z.string().optional().describe("Opaque cursor from a previous response's nextCursor"),
type: z.enum(["movie", "tv"]).optional().describe("Only movies or only TV episodes"),
source: watchSource.optional().describe("Only watches logged by this source"),
})
.meta({ description: "Filters and pagination for watch history" });
export const WatchHistoryItemSchema = z
.object({
watchId: z.string().describe("Watch record ID"),
kind: z.enum(["movie", "episode"]).describe("Whether this watch is a movie or an episode"),
watchedAt: z.string().describe("ISO 8601 timestamp of the watch"),
source: watchSource.describe("How the watch was logged"),
title: z
.object({
id: z.string().describe("Title ID"),
title: z.string().describe("Display title"),
type: z.enum(["movie", "tv"]).describe("Title type"),
posterPath: z.string().nullable().describe("Poster image URL"),
posterThumbHash: z.string().nullable().describe("Poster ThumbHash placeholder"),
})
.describe("The movie or show"),
episode: z
.object({
id: z.string().describe("Episode ID"),
seasonNumber: z.number().describe("Season number"),
episodeNumber: z.number().describe("Episode number"),
name: z.string().nullable().describe("Episode name"),
})
.nullable()
.describe("Episode details (null for movies)"),
})
.meta({ description: "A single watch event" });
export const WatchHistoryListOutput = z
.object({
items: z.array(WatchHistoryItemSchema).describe("Watches, newest first"),
nextCursor: z.string().nullable().describe("Cursor for the next page, or null at the end"),
})
.meta({ description: "A page of watch history" });
// ─── Integration inputs ──────────────────────────────────────── // ─── Integration inputs ────────────────────────────────────────
export const CreateIntegrationInput = z export const CreateIntegrationInput = z
@@ -603,7 +650,15 @@ export const LibraryListInput = z
.optional() .optional()
.describe("Only show titles available on the user's streaming services"), .describe("Only show titles available on the user's streaming services"),
sortBy: z sortBy: z
.enum(["title", "added_at", "release_date", "popularity", "user_rating", "vote_average"]) .enum([
"title",
"added_at",
"release_date",
"popularity",
"user_rating",
"vote_average",
"last_watched",
])
.default("added_at") .default("added_at")
.describe("Sort field"), .describe("Sort field"),
sortDirection: z.enum(["asc", "desc"]).default("desc").describe("Sort direction"), sortDirection: z.enum(["asc", "desc"]).default("desc").describe("Sort direction"),
+132
View File
@@ -14,7 +14,9 @@ import {
getEpisodeProgressByTitleIds as getEpisodeProgressByTitleIdsQuery, getEpisodeProgressByTitleIds as getEpisodeProgressByTitleIdsQuery,
getEpisodeTitleId, getEpisodeTitleId,
getEpisodeTitleIds, getEpisodeTitleIds,
getEpisodeWatchHistory,
getExistingEpisodeWatchIds, getExistingEpisodeWatchIds,
getMovieWatchHistory,
getSeasonById, getSeasonById,
getSeasonEpisodeIds, getSeasonEpisodeIds,
getTitleStatus, getTitleStatus,
@@ -289,3 +291,133 @@ export function quickAddTitle(
export function watchSeason(userId: string, seasonId: string): void { export function watchSeason(userId: string, seasonId: string): void {
logEpisodeWatchBatch(userId, getSeasonEpisodeIds(seasonId)); logEpisodeWatchBatch(userId, getSeasonEpisodeIds(seasonId));
} }
// ─── Watch history timeline ─────────────────────────────────────────
type WatchSource = "manual" | "import" | "plex" | "jellyfin" | "emby";
interface WatchHistoryCursorKey {
/** watchedAt in epoch ms */
t: number;
/** watch row id */
i: string;
}
function encodeWatchHistoryCursor(key: WatchHistoryCursorKey): string {
return Buffer.from(JSON.stringify(key), "utf8").toString("base64url");
}
function decodeWatchHistoryCursor(cursor: string): WatchHistoryCursorKey | null {
try {
const parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
if (
typeof parsed?.t !== "number" ||
!Number.isFinite(parsed.t) ||
typeof parsed?.i !== "string"
) {
return null;
}
return { t: parsed.t, i: parsed.i };
} catch {
return null;
}
}
export interface WatchHistoryEntry {
watchId: string;
kind: "movie" | "episode";
watchedAt: Date;
source: WatchSource;
title: {
id: string;
title: string;
type: "movie" | "tv";
posterPath: string | null;
posterThumbHash: string | null;
};
episode: {
id: string;
seasonNumber: number;
episodeNumber: number;
name: string | null;
} | null;
}
/**
* One page of the user's watch history (movies + episodes merged), newest first.
* Keyset-paginated on (watchedAt desc, id desc). Image paths are raw DB paths.
*/
export function listWatchHistory(
userId: string,
input: { limit: number; cursor?: string; type?: "movie" | "tv"; source?: WatchSource },
): { items: WatchHistoryEntry[]; nextCursor: string | null } {
const { limit, type, source } = input;
const key = input.cursor ? decodeWatchHistoryCursor(input.cursor) : null;
const opts = {
limit: limit + 1,
source,
before: key ? { watchedAt: new Date(key.t), id: key.i } : undefined,
};
const entries: WatchHistoryEntry[] = [];
if (type !== "tv") {
for (const r of getMovieWatchHistory(userId, opts)) {
entries.push({
watchId: r.watchId,
kind: "movie",
watchedAt: r.watchedAt,
source: r.source,
title: {
id: r.titleId,
title: r.title,
type: r.type,
posterPath: r.posterPath,
posterThumbHash: r.posterThumbHash,
},
episode: null,
});
}
}
if (type !== "movie") {
for (const r of getEpisodeWatchHistory(userId, opts)) {
entries.push({
watchId: r.watchId,
kind: "episode",
watchedAt: r.watchedAt,
source: r.source,
title: {
id: r.titleId,
title: r.title,
type: r.type,
posterPath: r.posterPath,
posterThumbHash: r.posterThumbHash,
},
episode: {
id: r.episodeId,
seasonNumber: r.seasonNumber,
episodeNumber: r.episodeNumber,
name: r.episodeName,
},
});
}
}
entries.sort(
(a, b) =>
b.watchedAt.getTime() - a.watchedAt.getTime() ||
(a.watchId < b.watchId ? 1 : a.watchId > b.watchId ? -1 : 0),
);
const hasMore = entries.length > limit;
const items = entries.slice(0, limit);
const last = items[items.length - 1];
return {
items,
nextCursor:
hasMore && last
? encodeWatchHistoryCursor({ t: last.watchedAt.getTime(), i: last.watchId })
: null,
};
}
+132
View File
@@ -0,0 +1,132 @@
import { beforeEach, describe, expect, test } from "vitest";
import { userEpisodeWatches, userMovieWatches } from "@sofa/db/schema";
import { clearAllTables, insertTitle, insertTvShow, insertUser, testDb } from "@sofa/test/db";
import { listWatchHistory } from "../src/tracking";
type Source = "manual" | "import" | "plex" | "jellyfin" | "emby";
function movieWatch(
id: string,
userId: string,
titleId: string,
at: number,
source: Source = "manual",
) {
testDb
.insert(userMovieWatches)
.values({ id, userId, titleId, watchedAt: new Date(at * 1000), source })
.run();
}
function episodeWatch(
id: string,
userId: string,
episodeId: string,
at: number,
source: Source = "manual",
) {
testDb
.insert(userEpisodeWatches)
.values({ id, userId, episodeId, watchedAt: new Date(at * 1000), source })
.run();
}
beforeEach(() => {
clearAllTables();
insertUser("user-1");
insertUser("user-2");
insertTitle({ id: "m1", tmdbId: 1, title: "Movie One" });
insertTitle({ id: "m2", tmdbId: 2, title: "Movie Two" });
insertTvShow("tv-1", 100, 1, 3);
});
function ids(items: { watchId: string }[]) {
return items.map((i) => i.watchId);
}
describe("listWatchHistory", () => {
test("merges movies and episodes newest-first with episode details", () => {
movieWatch("w1", "user-1", "m1", 1000);
episodeWatch("w2", "user-1", "tv-1-s1e1", 3000);
movieWatch("w3", "user-1", "m2", 2000);
const { items, nextCursor } = listWatchHistory("user-1", { limit: 10 });
expect(ids(items)).toEqual(["w2", "w3", "w1"]);
expect(nextCursor).toBeNull();
expect(items[0].kind).toBe("episode");
expect(items[0].episode).toMatchObject({ seasonNumber: 1, episodeNumber: 1 });
expect(items[0].title.id).toBe("tv-1");
expect(items[1].kind).toBe("movie");
expect(items[1].episode).toBeNull();
});
test("respects limit and returns null cursor on the last page", () => {
for (let i = 1; i <= 5; i++) movieWatch(`w${i}`, "user-1", "m1", i * 100);
const p1 = listWatchHistory("user-1", { limit: 2 });
expect(ids(p1.items)).toEqual(["w5", "w4"]);
expect(p1.nextCursor).not.toBeNull();
const p2 = listWatchHistory("user-1", { limit: 2, cursor: p1.nextCursor! });
expect(ids(p2.items)).toEqual(["w3", "w2"]);
expect(p2.nextCursor).not.toBeNull();
const p3 = listWatchHistory("user-1", { limit: 2, cursor: p2.nextCursor! });
expect(ids(p3.items)).toEqual(["w1"]);
expect(p3.nextCursor).toBeNull();
});
test("paginates without duplicates or gaps when watches share a timestamp", () => {
// Same watchedAt across movies and episodes; ties broken by id desc.
movieWatch("a1", "user-1", "m1", 500);
movieWatch("a3", "user-1", "m2", 500);
episodeWatch("a2", "user-1", "tv-1-s1e1", 500);
episodeWatch("a4", "user-1", "tv-1-s1e2", 500);
movieWatch("a0", "user-1", "m1", 400);
episodeWatch("a5", "user-1", "tv-1-s1e3", 600);
const seen: string[] = [];
let cursor: string | undefined;
for (let guard = 0; guard < 10; guard++) {
const page = listWatchHistory("user-1", { limit: 2, cursor });
seen.push(...ids(page.items));
if (!page.nextCursor) break;
cursor = page.nextCursor;
}
expect(seen).toEqual(["a5", "a4", "a3", "a2", "a1", "a0"]);
});
test("ignores an invalid cursor", () => {
movieWatch("w1", "user-1", "m1", 100);
const { items } = listWatchHistory("user-1", { limit: 10, cursor: "not-a-cursor" });
expect(items).toHaveLength(1);
});
test("filters by type", () => {
movieWatch("w1", "user-1", "m1", 100);
episodeWatch("w2", "user-1", "tv-1-s1e1", 200);
expect(ids(listWatchHistory("user-1", { limit: 10, type: "movie" }).items)).toEqual(["w1"]);
expect(ids(listWatchHistory("user-1", { limit: 10, type: "tv" }).items)).toEqual(["w2"]);
});
test("filters by source", () => {
movieWatch("w1", "user-1", "m1", 100, "plex");
movieWatch("w2", "user-1", "m2", 200, "manual");
episodeWatch("w3", "user-1", "tv-1-s1e1", 300, "plex");
const { items } = listWatchHistory("user-1", { limit: 10, source: "plex" });
expect(ids(items)).toEqual(["w3", "w1"]);
});
test("never includes other users' watches", () => {
movieWatch("w1", "user-1", "m1", 100);
movieWatch("w2", "user-2", "m1", 200);
episodeWatch("w3", "user-2", "tv-1-s1e1", 300);
const { items } = listWatchHistory("user-1", { limit: 10 });
expect(ids(items)).toEqual(["w1"]);
});
});
+41 -1
View File
@@ -1,6 +1,14 @@
import { beforeAll, beforeEach, describe, expect, test } from "vitest"; import { beforeAll, beforeEach, describe, expect, test } from "vitest";
import { clearAllTables, insertStatus, insertTitle, insertUser } from "@sofa/test/db"; import {
clearAllTables,
insertEpisodeWatch,
insertMovieWatch,
insertStatus,
insertTitle,
insertTvShow,
insertUser,
} from "@sofa/test/db";
import { getFilteredLibraryFeed, getLibraryGenresList } from "../src/library"; import { getFilteredLibraryFeed, getLibraryGenresList } from "../src/library";
@@ -136,6 +144,38 @@ describe("getFilteredLibraryFeed", () => {
// ── getLibraryGenresList ────────────────────────────────────────────── // ── getLibraryGenresList ──────────────────────────────────────────────
describe("getFilteredLibraryFeed last_watched sort", () => {
test("orders by most recent watch (movies and shows) with unwatched last", () => {
insertUser();
insertTitle({ id: "old-movie", tmdbId: 1 });
insertTitle({ id: "never", tmdbId: 2 });
insertTitle({ id: "recent-movie", tmdbId: 3 });
const { episodeIds } = insertTvShow("show", 4, 1, 2);
for (const id of ["old-movie", "never", "recent-movie", "show"]) {
insertStatus("user-1", id, "watchlist");
}
insertMovieWatch("user-1", "old-movie", new Date("2024-01-01T00:00:00Z"));
insertMovieWatch("user-1", "recent-movie", new Date("2024-03-01T00:00:00Z"));
insertEpisodeWatch("user-1", episodeIds[0], new Date("2024-02-01T00:00:00Z"));
insertEpisodeWatch("user-1", episodeIds[1], new Date("2024-02-10T00:00:00Z"));
const desc = getFilteredLibraryFeed("user-1", { ...defaultFilters, sortBy: "last_watched" });
expect(desc.items.map((i) => i.titleId)).toEqual([
"recent-movie",
"show",
"old-movie",
"never",
]);
const asc = getFilteredLibraryFeed("user-1", {
...defaultFilters,
sortBy: "last_watched",
sortDirection: "asc",
});
expect(asc.items.map((i) => i.titleId)).toEqual(["old-movie", "show", "recent-movie", "never"]);
});
});
describe("getLibraryGenresList", () => { describe("getLibraryGenresList", () => {
test("returns empty array when user has no titles", () => { test("returns empty array when user has no titles", () => {
insertUser(); insertUser();
+19
View File
@@ -11,6 +11,7 @@ import {
titleGenres, titleGenres,
titles, titles,
userEpisodeWatches, userEpisodeWatches,
userMovieWatches,
userPlatforms, userPlatforms,
userRatings, userRatings,
userTitleStatus, userTitleStatus,
@@ -220,6 +221,24 @@ export function getFilteredLibrary(userId: string, filters: LibraryFilters) {
case "vote_average": case "vote_average":
sortExpressions.push(dirFn(titles.voteAverage)); sortExpressions.push(dirFn(titles.voteAverage));
break; break;
case "last_watched": {
// Latest watch per title (movie watch, or any episode watch for a show);
// never-watched titles sort last regardless of direction.
const lastWatched = sql<number | null>`(
SELECT MAX(w.watchedAt) FROM (
SELECT ${userMovieWatches.watchedAt} AS watchedAt FROM ${userMovieWatches}
WHERE ${userMovieWatches.titleId} = ${titles.id} AND ${userMovieWatches.userId} = ${userId}
UNION ALL
SELECT uew.watchedAt AS watchedAt FROM ${userEpisodeWatches} uew
JOIN ${episodes} e ON e.id = uew.episodeId
JOIN ${seasons} s ON s.id = e.seasonId
WHERE s.titleId = ${titles.id} AND uew.userId = ${userId}
) w
)`;
sortExpressions.push(asc(sql`CASE WHEN ${lastWatched} IS NULL THEN 1 ELSE 0 END`));
sortExpressions.push(dirFn(lastWatched));
break;
}
default: default:
sortExpressions.push(desc(userTitleStatus.addedAt)); sortExpressions.push(desc(userTitleStatus.addedAt));
} }
+90 -1
View File
@@ -1,4 +1,4 @@
import { and, eq, inArray, sql } from "drizzle-orm"; import { and, desc, eq, inArray, lt, or, sql } from "drizzle-orm";
import { localDateString } from "@sofa/config"; import { localDateString } from "@sofa/config";
@@ -349,3 +349,92 @@ export function deleteAllEpisodeWatchesForTitle(userId: string, titleId: string)
if (titleEpisodeIds.length === 0) return; if (titleEpisodeIds.length === 0) return;
deleteEpisodeWatches(userId, titleEpisodeIds); deleteEpisodeWatches(userId, titleEpisodeIds);
} }
// ─── Watch history ──────────────────────────────────────────────────
type WatchSource = "manual" | "import" | "plex" | "jellyfin" | "emby";
export interface WatchHistoryCursor {
/** watchedAt in epoch ms */
t: number;
/** watch row id */
i: string;
}
export interface WatchHistoryQueryOptions {
limit: number;
source?: WatchSource;
before?: { watchedAt: Date; id: string };
}
export function getMovieWatchHistory(userId: string, opts: WatchHistoryQueryOptions) {
const conditions = [eq(userMovieWatches.userId, userId)];
if (opts.source) conditions.push(eq(userMovieWatches.source, opts.source));
if (opts.before) {
conditions.push(
or(
lt(userMovieWatches.watchedAt, opts.before.watchedAt),
and(
eq(userMovieWatches.watchedAt, opts.before.watchedAt),
lt(userMovieWatches.id, opts.before.id),
),
)!,
);
}
return db
.select({
watchId: userMovieWatches.id,
watchedAt: userMovieWatches.watchedAt,
source: userMovieWatches.source,
titleId: titles.id,
title: titles.title,
type: titles.type,
posterPath: titles.posterPath,
posterThumbHash: titles.posterThumbHash,
})
.from(userMovieWatches)
.innerJoin(titles, eq(userMovieWatches.titleId, titles.id))
.where(and(...conditions))
.orderBy(desc(userMovieWatches.watchedAt), desc(userMovieWatches.id))
.limit(opts.limit)
.all();
}
export function getEpisodeWatchHistory(userId: string, opts: WatchHistoryQueryOptions) {
const conditions = [eq(userEpisodeWatches.userId, userId)];
if (opts.source) conditions.push(eq(userEpisodeWatches.source, opts.source));
if (opts.before) {
conditions.push(
or(
lt(userEpisodeWatches.watchedAt, opts.before.watchedAt),
and(
eq(userEpisodeWatches.watchedAt, opts.before.watchedAt),
lt(userEpisodeWatches.id, opts.before.id),
),
)!,
);
}
return db
.select({
watchId: userEpisodeWatches.id,
watchedAt: userEpisodeWatches.watchedAt,
source: userEpisodeWatches.source,
titleId: titles.id,
title: titles.title,
type: titles.type,
posterPath: titles.posterPath,
posterThumbHash: titles.posterThumbHash,
episodeId: episodes.id,
seasonNumber: seasons.seasonNumber,
episodeNumber: episodes.episodeNumber,
episodeName: episodes.name,
})
.from(userEpisodeWatches)
.innerJoin(episodes, eq(userEpisodeWatches.episodeId, episodes.id))
.innerJoin(seasons, eq(episodes.seasonId, seasons.id))
.innerJoin(titles, eq(seasons.titleId, titles.id))
.where(and(...conditions))
.orderBy(desc(userEpisodeWatches.watchedAt), desc(userEpisodeWatches.id))
.limit(opts.limit)
.all();
}
+51
View File
@@ -378,6 +378,7 @@ msgstr "العمر {age}"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "الكل" msgstr "الكل"
@@ -1096,6 +1097,11 @@ msgstr "البريد الإلكتروني"
msgid "Email is required" msgid "Email is required"
msgstr "البريد الإلكتروني مطلوب" msgstr "البريد الإلكتروني مطلوب"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "فعّل نوع الإشعار \"Playback Stop\"" msgstr "فعّل نوع الإشعار \"Playback Stop\""
@@ -1216,6 +1222,10 @@ msgstr "الأخطاء ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "كل {n} ساعة" msgstr "كل {n} ساعة"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "الأعلى تقييماً"
msgid "Hindi" msgid "Hindi"
msgstr "الهندية" msgstr "الهندية"
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "ذاكرة التخزين المؤقت للصور"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "استخدام القرص لذاكرة التخزين المؤقت للصور والنسخ الاحتياطية" msgstr "استخدام القرص لذاكرة التخزين المؤقت للصور والنسخ الاحتياطية"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "الاستيراد" msgstr "الاستيراد"
@@ -1717,6 +1734,11 @@ msgstr "الإيطالية"
msgid "Japanese" msgid "Japanese"
msgstr "اليابانية" msgstr "اليابانية"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "المهمة" msgstr "المهمة"
@@ -1799,6 +1821,11 @@ msgstr "فشل آخر تشغيل"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "نجح آخر تشغيل" msgstr "نجح آخر تشغيل"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "انقطع الاتصال بعملية الاستيراد. تحقق من
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "إدارة حسابك وتفضيلاتك" msgstr "إدارة حسابك وتفضيلاتك"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "نسخة احتياطية يدوية" msgstr "نسخة احتياطية يدوية"
@@ -2031,6 +2063,7 @@ msgstr "فيلم"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "أفلام" msgstr "أفلام"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "يرجى تأكيد كلمة المرور"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "يرجى تسجيل الدخول مرة أخرى." msgstr "يرجى تسجيل الدخول مرة أخرى."
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "تشغيل الآن"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "حلقات المسلسلات"
msgid "TV show" msgid "TV show"
msgstr "مسلسل تلفزيوني" msgstr "مسلسل تلفزيوني"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "المسلسلات" msgstr "المسلسلات"
+51
View File
@@ -378,6 +378,7 @@ msgstr "Alter {age}"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "Alle" msgstr "Alle"
@@ -1096,6 +1097,11 @@ msgstr "E-Mail"
msgid "Email is required" msgid "Email is required"
msgstr "E-Mail ist erforderlich" msgstr "E-Mail ist erforderlich"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "Benachrichtigungstyp \"Playback Stop\" aktivieren" msgstr "Benachrichtigungstyp \"Playback Stop\" aktivieren"
@@ -1216,6 +1222,10 @@ msgstr "Fehler ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "Alle {n}h" msgstr "Alle {n}h"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "Bestbewertet"
msgid "Hindi" msgid "Hindi"
msgstr "" msgstr ""
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "Bild-Cache"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "Speichernutzung für Bild-Cache und Backups" msgstr "Speichernutzung für Bild-Cache und Backups"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "Importieren" msgstr "Importieren"
@@ -1717,6 +1734,11 @@ msgstr "Italienisch"
msgid "Japanese" msgid "Japanese"
msgstr "Japanisch" msgstr "Japanisch"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "Aufgabe" msgstr "Aufgabe"
@@ -1799,6 +1821,11 @@ msgstr "Letzter Lauf fehlgeschlagen"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "Letzter Lauf erfolgreich" msgstr "Letzter Lauf erfolgreich"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "Verbindung zum Import verloren. Status in den Einstellungen prüfen."
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "Konto und Einstellungen verwalten" msgstr "Konto und Einstellungen verwalten"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "Manuelles Backup" msgstr "Manuelles Backup"
@@ -2031,6 +2063,7 @@ msgstr "Film"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "Filme" msgstr "Filme"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "Bitte bestätige dein Passwort"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "Bitte melde dich erneut an." msgstr "Bitte melde dich erneut an."
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "Jetzt ausführen"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "TV-Episoden"
msgid "TV show" msgid "TV show"
msgstr "Serie" msgstr "Serie"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "Serien" msgstr "Serien"
+51
View File
@@ -378,6 +378,7 @@ msgstr ""
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "" msgstr ""
@@ -1096,6 +1097,11 @@ msgstr ""
msgid "Email is required" msgid "Email is required"
msgstr "Email is required" msgstr "Email is required"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr "Emby"
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "" msgstr ""
@@ -1216,6 +1222,10 @@ msgstr "Errors ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "Every {n}h" msgstr "Every {n}h"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr "Everything you've watched, newest first."
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "Highest rated"
msgid "Hindi" msgid "Hindi"
msgstr "Hindi" msgstr "Hindi"
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr "History"
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr ""
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "" msgstr ""
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "" msgstr ""
@@ -1717,6 +1734,11 @@ msgstr "Italian"
msgid "Japanese" msgid "Japanese"
msgstr "Japanese" msgstr "Japanese"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr "Jellyfin"
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "" msgstr ""
@@ -1799,6 +1821,11 @@ msgstr ""
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "" msgstr ""
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr "Last watched"
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr ""
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "" msgstr ""
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr "Manual"
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "" msgstr ""
@@ -2031,6 +2063,7 @@ msgstr ""
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "" msgstr ""
@@ -2210,6 +2243,10 @@ msgstr "Nothing to watch"
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "Nothing upcoming" msgstr "Nothing upcoming"
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr "Nothing watched yet."
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "Please confirm your password"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "Please sign in again." msgstr "Please sign in again."
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr "Plex"
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr ""
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr "S{season} E{episode}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr "S{season} E{episode} · {name}"
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr ""
msgid "TV show" msgid "TV show"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "TV Shows" msgstr "TV Shows"
+51
View File
@@ -378,6 +378,7 @@ msgstr "edad {age}"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "Todo" msgstr "Todo"
@@ -1096,6 +1097,11 @@ msgstr "Correo electrónico"
msgid "Email is required" msgid "Email is required"
msgstr "El correo electrónico es obligatorio" msgstr "El correo electrónico es obligatorio"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "Activa el tipo de notificación \"Playback Stop\"" msgstr "Activa el tipo de notificación \"Playback Stop\""
@@ -1216,6 +1222,10 @@ msgstr "Errores ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "Cada {n}h" msgstr "Cada {n}h"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "Mejor valorados"
msgid "Hindi" msgid "Hindi"
msgstr "" msgstr ""
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "Caché de imágenes"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "Uso del disco de caché de imágenes y copias de seguridad" msgstr "Uso del disco de caché de imágenes y copias de seguridad"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "Importar" msgstr "Importar"
@@ -1717,6 +1734,11 @@ msgstr "Italiano"
msgid "Japanese" msgid "Japanese"
msgstr "Japonés" msgstr "Japonés"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "Tarea" msgstr "Tarea"
@@ -1799,6 +1821,11 @@ msgstr "Última ejecución fallida"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "Última ejecución exitosa" msgstr "Última ejecución exitosa"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "Se perdió la conexión con la importación. Comprueba el estado en ajus
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "Gestiona tu cuenta y preferencias" msgstr "Gestiona tu cuenta y preferencias"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "Copia de seguridad manual" msgstr "Copia de seguridad manual"
@@ -2031,6 +2063,7 @@ msgstr "Película"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "Películas" msgstr "Películas"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "Por favor, confirma tu contraseña"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "Por favor, inicia sesión de nuevo." msgstr "Por favor, inicia sesión de nuevo."
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "Ejecutar ahora"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "Episodios de series"
msgid "TV show" msgid "TV show"
msgstr "Serie" msgstr "Serie"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "Series de TV" msgstr "Series de TV"
+51
View File
@@ -378,6 +378,7 @@ msgstr "âge {age}"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "Tout" msgstr "Tout"
@@ -1096,6 +1097,11 @@ msgstr "E-mail"
msgid "Email is required" msgid "Email is required"
msgstr "L'adresse e-mail est requise" msgstr "L'adresse e-mail est requise"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "Activez le type de notification « Playback Stop »" msgstr "Activez le type de notification « Playback Stop »"
@@ -1216,6 +1222,10 @@ msgstr "Erreurs ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "Toutes les {n}h" msgstr "Toutes les {n}h"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "Mieux notés"
msgid "Hindi" msgid "Hindi"
msgstr "" msgstr ""
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "Cache d'images"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "Utilisation du disque : cache d'images et sauvegardes" msgstr "Utilisation du disque : cache d'images et sauvegardes"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "Importation" msgstr "Importation"
@@ -1717,6 +1734,11 @@ msgstr "Italien"
msgid "Japanese" msgid "Japanese"
msgstr "Japonais" msgstr "Japonais"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "Tâche" msgstr "Tâche"
@@ -1799,6 +1821,11 @@ msgstr "Dernière exécution échouée"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "Dernière exécution réussie" msgstr "Dernière exécution réussie"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "Connexion à l'importation perdue. Vérifiez l'état dans les paramètre
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "Gérez votre compte et vos préférences" msgstr "Gérez votre compte et vos préférences"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "Sauvegarde manuelle" msgstr "Sauvegarde manuelle"
@@ -2031,6 +2063,7 @@ msgstr "Film"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "Films" msgstr "Films"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "Veuillez confirmer votre mot de passe"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "Veuillez vous reconnecter." msgstr "Veuillez vous reconnecter."
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "Exécuter maintenant"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "Épisodes de séries"
msgid "TV show" msgid "TV show"
msgstr "Série TV" msgstr "Série TV"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "Séries TV" msgstr "Séries TV"
+51
View File
@@ -378,6 +378,7 @@ msgstr "גיל {age}"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "הכל" msgstr "הכל"
@@ -1096,6 +1097,11 @@ msgstr "דוא\"ל"
msgid "Email is required" msgid "Email is required"
msgstr "כתובת דוא\"ל נדרשת" msgstr "כתובת דוא\"ל נדרשת"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "הפעל את סוג ההתראה \"Playback Stop\"" msgstr "הפעל את סוג ההתראה \"Playback Stop\""
@@ -1216,6 +1222,10 @@ msgstr "שגיאות ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "כל {n} שעות" msgstr "כל {n} שעות"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "בדירוג הגבוה ביותר"
msgid "Hindi" msgid "Hindi"
msgstr "הינדי" msgstr "הינדי"
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "מטמון תמונות"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "שימוש בדיסק של מטמון תמונות וגיבויים" msgstr "שימוש בדיסק של מטמון תמונות וגיבויים"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "ייבוא" msgstr "ייבוא"
@@ -1717,6 +1734,11 @@ msgstr "איטלקית"
msgid "Japanese" msgid "Japanese"
msgstr "יפנית" msgstr "יפנית"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "משימה" msgstr "משימה"
@@ -1799,6 +1821,11 @@ msgstr "ההרצה האחרונה נכשלה"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "ההרצה האחרונה הצליחה" msgstr "ההרצה האחרונה הצליחה"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "אבד החיבור לייבוא. בדוק את הסטטוס בהגדר
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "נהל את החשבון וההעדפות שלך" msgstr "נהל את החשבון וההעדפות שלך"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "גיבוי ידני" msgstr "גיבוי ידני"
@@ -2031,6 +2063,7 @@ msgstr "סרט"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "סרטים" msgstr "סרטים"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "אנא אשר את הסיסמה שלך"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "אנא התחבר שוב." msgstr "אנא התחבר שוב."
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "הפעל עכשיו"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "פרקי טלוויזיה"
msgid "TV show" msgid "TV show"
msgstr "סדרת טלוויזיה" msgstr "סדרת טלוויזיה"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "תוכניות טלוויזיה" msgstr "תוכניות טלוויזיה"
+51
View File
@@ -378,6 +378,7 @@ msgstr "età {age}"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "Tutti" msgstr "Tutti"
@@ -1096,6 +1097,11 @@ msgstr ""
msgid "Email is required" msgid "Email is required"
msgstr "L'email è obbligatoria" msgstr "L'email è obbligatoria"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "Abilita il tipo di notifica \"Playback Stop\"" msgstr "Abilita il tipo di notifica \"Playback Stop\""
@@ -1216,6 +1222,10 @@ msgstr "Errori ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "Ogni {n}h" msgstr "Ogni {n}h"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "Meglio valutati"
msgid "Hindi" msgid "Hindi"
msgstr "" msgstr ""
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "Cache immagini"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "Utilizzo disco: cache immagini e backup" msgstr "Utilizzo disco: cache immagini e backup"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "Importazione" msgstr "Importazione"
@@ -1717,6 +1734,11 @@ msgstr "Italiano"
msgid "Japanese" msgid "Japanese"
msgstr "Giapponese" msgstr "Giapponese"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "Attività" msgstr "Attività"
@@ -1799,6 +1821,11 @@ msgstr "Ultima esecuzione fallita"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "Ultima esecuzione riuscita" msgstr "Ultima esecuzione riuscita"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "Connessione all'importazione persa. Controlla lo stato nelle impostazion
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "Gestisci il tuo account e le tue preferenze" msgstr "Gestisci il tuo account e le tue preferenze"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "Backup manuale" msgstr "Backup manuale"
@@ -2031,6 +2063,7 @@ msgstr "Film"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "Film" msgstr "Film"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "Conferma la tua password"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "Accedi di nuovo." msgstr "Accedi di nuovo."
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "Esegui ora"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "Episodi TV"
msgid "TV show" msgid "TV show"
msgstr "Serie TV" msgstr "Serie TV"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "Serie TV" msgstr "Serie TV"
+51
View File
@@ -378,6 +378,7 @@ msgstr "年齢 {age}"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "すべて" msgstr "すべて"
@@ -1096,6 +1097,11 @@ msgstr "メールアドレス"
msgid "Email is required" msgid "Email is required"
msgstr "メールアドレスは必須です" msgstr "メールアドレスは必須です"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "「Playback Stop」通知タイプを有効にしてください" msgstr "「Playback Stop」通知タイプを有効にしてください"
@@ -1216,6 +1222,10 @@ msgstr "エラー ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "{n}時間ごと" msgstr "{n}時間ごと"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "評価が高い順"
msgid "Hindi" msgid "Hindi"
msgstr "ヒンディー語" msgstr "ヒンディー語"
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "画像キャッシュ"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "画像キャッシュとバックアップのディスク使用量" msgstr "画像キャッシュとバックアップのディスク使用量"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "インポート" msgstr "インポート"
@@ -1717,6 +1734,11 @@ msgstr "イタリア語"
msgid "Japanese" msgid "Japanese"
msgstr "日本語" msgstr "日本語"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "ジョブ" msgstr "ジョブ"
@@ -1799,6 +1821,11 @@ msgstr "最終実行失敗"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "最終実行成功" msgstr "最終実行成功"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "インポートへの接続が切断されました。設定でステー
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "アカウントと設定を管理する" msgstr "アカウントと設定を管理する"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "手動バックアップ" msgstr "手動バックアップ"
@@ -2031,6 +2063,7 @@ msgstr "映画"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "映画" msgstr "映画"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "パスワードを確認してください"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "再度サインインしてください。" msgstr "再度サインインしてください。"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "今すぐ実行"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "TVエピソード"
msgid "TV show" msgid "TV show"
msgstr "TV番組" msgstr "TV番組"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "TVシリーズ" msgstr "TVシリーズ"
+51
View File
@@ -378,6 +378,7 @@ msgstr "나이 {age}"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "전체" msgstr "전체"
@@ -1096,6 +1097,11 @@ msgstr "이메일"
msgid "Email is required" msgid "Email is required"
msgstr "이메일을 입력해주세요" msgstr "이메일을 입력해주세요"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "\"Playback Stop\" 알림 유형 활성화" msgstr "\"Playback Stop\" 알림 유형 활성화"
@@ -1216,6 +1222,10 @@ msgstr "오류 ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "매 {n}시간" msgstr "매 {n}시간"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "평점 높은 순"
msgid "Hindi" msgid "Hindi"
msgstr "힌디어" msgstr "힌디어"
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "이미지 캐시"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "이미지 캐시 및 백업 디스크 사용량" msgstr "이미지 캐시 및 백업 디스크 사용량"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "가져오기" msgstr "가져오기"
@@ -1717,6 +1734,11 @@ msgstr "이탈리아어"
msgid "Japanese" msgid "Japanese"
msgstr "일본어" msgstr "일본어"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "작업" msgstr "작업"
@@ -1799,6 +1821,11 @@ msgstr "마지막 실행 실패"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "마지막 실행 성공" msgstr "마지막 실행 성공"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "가져오기 연결이 끊어졌습니다. 설정에서 상태를 확인
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "계정 및 환경설정을 관리하세요" msgstr "계정 및 환경설정을 관리하세요"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "수동 백업" msgstr "수동 백업"
@@ -2031,6 +2063,7 @@ msgstr "영화"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "영화" msgstr "영화"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "비밀번호를 확인해주세요"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "다시 로그인해주세요." msgstr "다시 로그인해주세요."
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "지금 실행"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "TV 에피소드"
msgid "TV show" msgid "TV show"
msgstr "TV 프로그램" msgstr "TV 프로그램"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "TV 프로그램" msgstr "TV 프로그램"
+51
View File
@@ -378,6 +378,7 @@ msgstr "leeftijd {age}"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "Alles" msgstr "Alles"
@@ -1096,6 +1097,11 @@ msgstr "E-mail"
msgid "Email is required" msgid "Email is required"
msgstr "E-mail is vereist" msgstr "E-mail is vereist"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "Schakel het meldingstype \"Playback Stop\" in" msgstr "Schakel het meldingstype \"Playback Stop\" in"
@@ -1216,6 +1222,10 @@ msgstr "Fouten ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "Elke {n}u" msgstr "Elke {n}u"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "Hoogst beoordeeld"
msgid "Hindi" msgid "Hindi"
msgstr "" msgstr ""
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "Afbeeldingscache"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "Schijfgebruik voor afbeeldingscache en back-ups" msgstr "Schijfgebruik voor afbeeldingscache en back-ups"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "Importeren" msgstr "Importeren"
@@ -1717,6 +1734,11 @@ msgstr "Italiaans"
msgid "Japanese" msgid "Japanese"
msgstr "Japans" msgstr "Japans"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "Taak" msgstr "Taak"
@@ -1799,6 +1821,11 @@ msgstr "Laatste uitvoering mislukt"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "Laatste uitvoering geslaagd" msgstr "Laatste uitvoering geslaagd"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "Verbinding met de import verbroken. Controleer de status in de instellin
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "Beheer je account en voorkeuren" msgstr "Beheer je account en voorkeuren"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "Handmatige back-up" msgstr "Handmatige back-up"
@@ -2031,6 +2063,7 @@ msgstr "Film"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "Films" msgstr "Films"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "Bevestig je wachtwoord"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "Meld je opnieuw aan." msgstr "Meld je opnieuw aan."
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "Nu uitvoeren"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "Tv-afleveringen"
msgid "TV show" msgid "TV show"
msgstr "Tv-serie" msgstr "Tv-serie"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "Tv-series" msgstr "Tv-series"
+51
View File
@@ -378,6 +378,7 @@ msgstr "idade {age}"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "Todos" msgstr "Todos"
@@ -1096,6 +1097,11 @@ msgstr "E-mail"
msgid "Email is required" msgid "Email is required"
msgstr "O email é obrigatório" msgstr "O email é obrigatório"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "Ative o tipo de notificação \"Playback Stop\"" msgstr "Ative o tipo de notificação \"Playback Stop\""
@@ -1216,6 +1222,10 @@ msgstr "Erros ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "A cada {n}h" msgstr "A cada {n}h"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "Melhor avaliados"
msgid "Hindi" msgid "Hindi"
msgstr "" msgstr ""
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "Cache de imagens"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "Uso de disco de cache de imagens e backups" msgstr "Uso de disco de cache de imagens e backups"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "Importar" msgstr "Importar"
@@ -1717,6 +1734,11 @@ msgstr "Italiano"
msgid "Japanese" msgid "Japanese"
msgstr "Japonês" msgstr "Japonês"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "Tarefa" msgstr "Tarefa"
@@ -1799,6 +1821,11 @@ msgstr "Última execução falhou"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "Última execução bem-sucedida" msgstr "Última execução bem-sucedida"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "Conexão de importação perdida. Verifique o status nas configurações
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "Gerencie sua conta e preferências" msgstr "Gerencie sua conta e preferências"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "Backup manual" msgstr "Backup manual"
@@ -2031,6 +2063,7 @@ msgstr "Filme"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "Filmes" msgstr "Filmes"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "Por favor confirme a sua palavra-passe"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "Por favor inicie sessão novamente." msgstr "Por favor inicie sessão novamente."
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "Executar agora"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "Episódios de séries"
msgid "TV show" msgid "TV show"
msgstr "Série" msgstr "Série"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "Séries" msgstr "Séries"
+51
View File
@@ -378,6 +378,7 @@ msgstr "{age} 岁"
#: apps/native/src/components/library/filter-sheet.tsx #: apps/native/src/components/library/filter-sheet.tsx
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "All" msgid "All"
msgstr "全部" msgstr "全部"
@@ -1096,6 +1097,11 @@ msgstr "邮箱"
msgid "Email is required" msgid "Email is required"
msgstr "邮箱不能为空" msgstr "邮箱不能为空"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Emby"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Enable the \"Playback Stop\" notification type" msgid "Enable the \"Playback Stop\" notification type"
msgstr "启用“Playback Stop”通知类型" msgstr "启用“Playback Stop”通知类型"
@@ -1216,6 +1222,10 @@ msgstr "错误 ({errorCount})"
msgid "Every {n}h" msgid "Every {n}h"
msgstr "每 {n} 小时" msgstr "每 {n} 小时"
#: apps/web/src/routes/_app/history.tsx
msgid "Everything you've watched, newest first."
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/_layout.tsx #: apps/native/src/app/(tabs)/(explore)/_layout.tsx
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
@@ -1570,6 +1580,11 @@ msgstr "评分最高"
msgid "Hindi" msgid "Hindi"
msgstr "印地语" msgstr "印地语"
#: apps/web/src/components/nav-bar.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "History"
msgstr ""
#: apps/native/src/app/(tabs)/(home)/_layout.tsx #: apps/native/src/app/(tabs)/(home)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1590,7 +1605,9 @@ msgstr "图片缓存"
msgid "Image cache and backup disk usage" msgid "Image cache and backup disk usage"
msgstr "图片缓存与备份磁盘用量" msgstr "图片缓存与备份磁盘用量"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Import" msgid "Import"
msgstr "导入" msgstr "导入"
@@ -1717,6 +1734,11 @@ msgstr "意大利语"
msgid "Japanese" msgid "Japanese"
msgstr "日语" msgstr "日语"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Jellyfin"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Job" msgid "Job"
msgstr "任务" msgstr "任务"
@@ -1799,6 +1821,11 @@ msgstr "上次运行失败"
msgid "Last run succeeded" msgid "Last run succeeded"
msgstr "上次运行成功" msgstr "上次运行成功"
#: apps/native/src/components/library/sort-menu.tsx
#: apps/web/src/components/library/library-toolbar.tsx
msgid "Last watched"
msgstr ""
#: apps/native/src/app/(tabs)/(library)/_layout.tsx #: apps/native/src/app/(tabs)/(library)/_layout.tsx
#: apps/native/src/components/navigation/native-tab-bar.android.tsx #: apps/native/src/components/navigation/native-tab-bar.android.tsx
#: apps/native/src/components/navigation/native-tab-bar.tsx #: apps/native/src/components/navigation/native-tab-bar.tsx
@@ -1837,6 +1864,11 @@ msgstr "导入连接已断开,请在设置中查看状态。"
msgid "Manage your account and preferences" msgid "Manage your account and preferences"
msgstr "管理您的账户和偏好设置" msgstr "管理您的账户和偏好设置"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Manual"
msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Manual backup" msgid "Manual backup"
msgstr "手动备份" msgstr "手动备份"
@@ -2031,6 +2063,7 @@ msgstr "电影"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "Movies" msgid "Movies"
msgstr "电影" msgstr "电影"
@@ -2210,6 +2243,10 @@ msgstr ""
msgid "Nothing upcoming" msgid "Nothing upcoming"
msgstr "" msgstr ""
#: apps/web/src/routes/_app/history.tsx
msgid "Nothing watched yet."
msgstr ""
#: apps/web/src/components/library/library-filters.tsx #: apps/web/src/components/library/library-filters.tsx
#~ msgid "Older" #~ msgid "Older"
#~ msgstr "Older" #~ msgstr "Older"
@@ -2399,6 +2436,11 @@ msgstr "请确认您的密码"
msgid "Please sign in again." msgid "Please sign in again."
msgstr "请重新登录。" msgstr "请重新登录。"
#: apps/web/src/components/history/history-row.tsx
#: apps/web/src/routes/_app/history.tsx
msgid "Plex"
msgstr ""
#: apps/native/src/app/(tabs)/(explore)/index.tsx #: apps/native/src/app/(tabs)/(explore)/index.tsx
#: apps/web/src/routes/_app/explore.tsx #: apps/web/src/routes/_app/explore.tsx
msgid "Popular Movies" msgid "Popular Movies"
@@ -2817,6 +2859,14 @@ msgstr "立即运行"
#~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgid "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}" #~ msgstr "S{0} · {1} {2, plural, one {episode} other {episodes}}"
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode}"
msgstr ""
#: apps/web/src/components/history/history-row.tsx
msgid "S{season} E{episode} · {name}"
msgstr ""
#: apps/native/src/components/dashboard/upcoming-row.tsx #: apps/native/src/components/dashboard/upcoming-row.tsx
#: apps/native/src/lib/widgets.ts #: apps/native/src/lib/widgets.ts
#: apps/web/src/components/dashboard/upcoming-item.tsx #: apps/web/src/components/dashboard/upcoming-item.tsx
@@ -3486,6 +3536,7 @@ msgstr "电视剧集"
msgid "TV show" msgid "TV show"
msgstr "电视剧" msgstr "电视剧"
#: apps/web/src/routes/_app/history.tsx
#: apps/web/src/routes/_app/upcoming.tsx #: apps/web/src/routes/_app/upcoming.tsx
msgid "TV Shows" msgid "TV Shows"
msgstr "电视剧" msgstr "电视剧"