feat(i18n): add RTL layout support for Arabic and other RTL locales

- Export `isLocaleRTL` from `@sofa/i18n` to detect right-to-left locales
- Native: call `I18nManager.allowRTL` / `forceRTL` on locale init and on locale change; reload the app immediately if the current layout direction doesn't match the persisted locale, and prompt the user to restart when switching between LTR and RTL locales
- Native: flip the `SettingsRow` chevron to `IconChevronLeft` when `I18nManager.isRTL` is true
- Native: add Arabic Intl polyfill locale data (PluralRules, NumberFormat, DateTimeFormat, RelativeTimeFormat)
- Web: enable `"rtl": true` in `components.json` and regenerate all shadcn UI components to use CSS logical properties (`ms-*`, `me-*`, `ps-*`, `pe-*`, `text-start`, `text-end`) instead of physical `ml-*`/`mr-*`/`text-left` equivalents
- Web: apply the same logical-property conversions to non-generated components (nav-bar, settings sections, title cards, hero banner, continue-watching card)
- Web: set `document.dir` based on the active locale's RTL flag in the i18n initialiser and root route
- Add `../../packages/i18n/src/po.d.ts` to native `tsconfig.json` includes so TypeScript accepts `.po` imports
This commit is contained in:
2026-03-20 19:25:04 -04:00
parent b540a9111a
commit 5aaf88591b
86 changed files with 18380 additions and 1398 deletions
+16 -1
View File
@@ -1,6 +1,7 @@
{ {
"$schema": "./node_modules/oxlint/configuration_schema.json", "$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["oxc", "eslint", "typescript", "react", "import", "unicorn"], "plugins": ["oxc", "eslint", "typescript", "react", "import", "unicorn"],
"jsPlugins": ["eslint-plugin-lingui"],
"env": { "env": {
"builtin": true "builtin": true
}, },
@@ -20,7 +21,21 @@
"no-await-in-loop": "off", "no-await-in-loop": "off",
"react/no-array-index-key": "off", "react/no-array-index-key": "off",
"react/jsx-no-useless-fragment": "error", "react/jsx-no-useless-fragment": "error",
"react/rules-of-hooks": "error" "react/rules-of-hooks": "error",
"lingui/no-unlocalized-strings": "off",
"lingui/t-call-in-function": "error",
"lingui/no-single-variables-to-translate": "error",
"lingui/no-expression-in-message": "error",
"lingui/no-single-tag-to-translate": "error",
"lingui/no-trans-inside-trans": "error"
}, },
"overrides": [
{
"files": ["apps/web/src/**/*", "apps/native/src/**/*"],
"rules": {
"lingui/no-unlocalized-strings": "warn"
}
}
],
"ignorePatterns": ["node_modules", "dist", "build", "docs", "**/routeTree.gen.ts"] "ignorePatterns": ["node_modules", "dist", "build", "docs", "**/routeTree.gen.ts"]
} }
+1 -1
View File
@@ -64,7 +64,7 @@
"expo-system-ui": "55.0.10", "expo-system-ui": "55.0.10",
"expo-tracking-transparency": "55.0.9", "expo-tracking-transparency": "55.0.9",
"expo-web-browser": "55.0.10", "expo-web-browser": "55.0.10",
"posthog-react-native": "4.37.4", "posthog-react-native": "4.37.5",
"react": "19.2.0", "react": "19.2.0",
"react-dom": "19.2.0", "react-dom": "19.2.0",
"react-native": "0.83.2", "react-native": "0.83.2",
+31 -27
View File
@@ -84,34 +84,38 @@ export default function LoginScreen() {
return ( return (
<AuthScreen title="Sofa" subtitle={t`Sign in to continue`}> <AuthScreen title="Sofa" subtitle={t`Sign in to continue`}>
{showOidc && ( {showOidc &&
<Animated.View entering={FadeInDown.duration(300).delay(100)} className="mb-4"> (() => {
<Button const providerName = authConfig.data?.oidcProviderName ?? "SSO";
onPress={() => { return (
authClient.signIn.oauth2({ <Animated.View entering={FadeInDown.duration(300).delay(100)} className="mb-4">
providerId: "oidc", <Button
callbackURL: "/(tabs)/(home)", onPress={() => {
}); authClient.signIn.oauth2({
}} providerId: "oidc",
variant="secondary" callbackURL: "/(tabs)/(home)",
className="w-full" });
> }}
<ButtonLabel> variant="secondary"
<Trans>Sign in with {authConfig.data?.oidcProviderName ?? "SSO"}</Trans> className="w-full"
</ButtonLabel> >
</Button> <ButtonLabel>
<Trans>Sign in with {providerName}</Trans>
</ButtonLabel>
</Button>
{showPasswordLogin && ( {showPasswordLogin && (
<View className="my-4 flex-row items-center"> <View className="my-4 flex-row items-center">
<View className="bg-border h-px flex-1" /> <View className="bg-border h-px flex-1" />
<Text className="text-muted-foreground px-3 text-xs"> <Text className="text-muted-foreground px-3 text-xs">
<Trans>OR</Trans> <Trans>OR</Trans>
</Text> </Text>
<View className="bg-border h-px flex-1" /> <View className="bg-border h-px flex-1" />
</View> </View>
)} )}
</Animated.View> </Animated.View>
)} );
})()}
{showPasswordLogin && ( {showPasswordLogin && (
<View className="gap-3"> <View className="gap-3">
+8 -2
View File
@@ -111,7 +111,10 @@ export default function DashboardScreen() {
<View className="gap-3"> <View className="gap-3">
<View className="flex-row gap-3"> <View className="flex-row gap-3">
<StatsCard <StatsCard
label={t`Movies ${periodLabels[moviePeriod]}`} label={(() => {
const period = periodLabels[moviePeriod];
return t`Movies ${period}`;
})()}
value={movieCount} value={movieCount}
icon={IconMovie} icon={IconMovie}
color="text-primary" color="text-primary"
@@ -122,7 +125,10 @@ export default function DashboardScreen() {
onPeriodChange={setMoviePeriod} onPeriodChange={setMoviePeriod}
/> />
<StatsCard <StatsCard
label={t`Episodes ${periodLabels[episodePeriod]}`} label={(() => {
const period = periodLabels[episodePeriod];
return t`Episodes ${period}`;
})()}
value={episodeCount} value={episodeCount}
icon={IconDeviceTvOld} icon={IconDeviceTvOld}
color="text-status-watching" color="text-status-watching"
+31 -11
View File
@@ -21,6 +21,7 @@ import {
IconWorld, IconWorld,
} from "@tabler/icons-react-native"; } from "@tabler/icons-react-native";
import { useMutation, useQuery } from "@tanstack/react-query"; import { useMutation, useQuery } from "@tanstack/react-query";
import { reloadAppAsync } from "expo";
import * as Application from "expo-application"; import * as Application from "expo-application";
import * as ImagePicker from "expo-image-picker"; import * as ImagePicker from "expo-image-picker";
import { useRouter } from "expo-router"; import { useRouter } from "expo-router";
@@ -54,7 +55,7 @@ import { isAnalyticsEnabled, setAnalyticsEnabled } from "@/lib/posthog";
import { queryClient } from "@/lib/query-client"; import { queryClient } from "@/lib/query-client";
import { authClient, getServerUrl } from "@/lib/server"; import { authClient, getServerUrl } from "@/lib/server";
import { toast } from "@/lib/toast"; import { toast } from "@/lib/toast";
import { activateLocale, type SupportedLocale } from "@sofa/i18n"; import { activateLocale, isLocaleRTL, type SupportedLocale } from "@sofa/i18n";
import { LOCALE_INFO } from "@sofa/i18n/locales"; import { LOCALE_INFO } from "@sofa/i18n/locales";
const settingsContentContainerStyle = { const settingsContentContainerStyle = {
@@ -421,7 +422,10 @@ export default function SettingsScreen() {
label={t`Database`} label={t`Database`}
value={ value={
systemHealth.data?.database systemHealth.data?.database
? t`${plural(systemHealth.data.database.titleCount, { one: "# title", other: "# titles" })}` ? plural(systemHealth.data.database.titleCount, {
one: "# title",
other: "# titles",
})
: "—" : "—"
} }
icon={IconDatabase} icon={IconDatabase}
@@ -435,7 +439,10 @@ export default function SettingsScreen() {
label={t`Image Cache`} label={t`Image Cache`}
value={ value={
systemHealth.data?.imageCache systemHealth.data?.imageCache
? t`${plural(systemHealth.data.imageCache.imageCount, { one: "# image", other: "# images" })}` ? plural(systemHealth.data.imageCache.imageCount, {
one: "# image",
other: "# images",
})
: "—" : "—"
} }
icon={IconPhoto} icon={IconPhoto}
@@ -472,13 +479,16 @@ export default function SettingsScreen() {
/> />
} }
/> />
{updateCheck.data?.updateCheck?.updateAvailable && ( {(() => {
<View className="py-3.5"> const latestVersion = updateCheck.data?.updateCheck?.latestVersion;
<Text className="text-status-completed font-sans text-sm font-medium"> return updateCheck.data?.updateCheck?.updateAvailable ? (
<Trans>Update available: {updateCheck.data.updateCheck.latestVersion}</Trans> <View className="py-3.5">
</Text> <Text className="text-status-completed font-sans text-sm font-medium">
</View> <Trans>Update available: {latestVersion}</Trans>
)} </Text>
</View>
) : null;
})()}
</SettingsSection> </SettingsSection>
</Animated.View> </Animated.View>
)} )}
@@ -512,8 +522,18 @@ export default function SettingsScreen() {
}))} }))}
onSelect={(locale) => { onSelect={(locale) => {
setLanguageModalOpen(false); setLanguageModalOpen(false);
const previousLocale = i18n.locale;
activateLocale(locale as SupportedLocale).then( activateLocale(locale as SupportedLocale).then(
() => setPersistedLocale(locale as SupportedLocale), () => {
setPersistedLocale(locale as SupportedLocale);
if (isLocaleRTL(locale) !== isLocaleRTL(previousLocale)) {
Alert.alert(
t`Restart Required`,
t`Sofa needs to restart to apply the new layout direction.`,
[{ text: t`Restart`, onPress: () => reloadAppAsync() }],
);
}
},
() => {}, () => {},
); );
}} }}
@@ -1,7 +1,7 @@
import type { Icon } from "@tabler/icons-react-native"; import type { Icon } from "@tabler/icons-react-native";
import { IconChevronRight } from "@tabler/icons-react-native"; import { IconChevronLeft, IconChevronRight } from "@tabler/icons-react-native";
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import { Pressable, View } from "react-native"; import { I18nManager, Pressable, View } from "react-native";
import { useCSSVariable } from "uniwind"; import { useCSSVariable } from "uniwind";
import { ScaledIcon } from "@/components/ui/scaled-icon"; import { ScaledIcon } from "@/components/ui/scaled-icon";
@@ -53,7 +53,12 @@ export function SettingsRow({
</Text> </Text>
) : null} ) : null}
{!right && onPress && ( {!right && onPress && (
<ScaledIcon icon={IconChevronRight} size={16} color={mutedFgColor} accessible={false} /> <ScaledIcon
icon={I18nManager.isRTL ? IconChevronLeft : IconChevronRight}
size={16}
color={mutedFgColor}
accessible={false}
/>
)} )}
</> </>
); );
@@ -99,6 +99,9 @@ export function SeasonAccordion({
[watchedEpisodeIds, unwatchEpisode, watchEpisode], [watchedEpisodeIds, unwatchEpisode, watchEpisode],
); );
const seasonNumber = season.seasonNumber;
const episodeCount = episodes.length;
return ( return (
<View <View
className="bg-card mb-2 overflow-hidden rounded-xl border" className="bg-card mb-2 overflow-hidden rounded-xl border"
@@ -110,16 +113,16 @@ export function SeasonAccordion({
<Pressable <Pressable
onPress={toggleExpanded} onPress={toggleExpanded}
accessibilityRole="button" accessibilityRole="button"
accessibilityLabel={`${season.name ?? t`Season ${season.seasonNumber}`}, ${t`${watchedCount} of ${episodes.length} episodes watched`}`} accessibilityLabel={`${season.name ?? t`Season ${seasonNumber}`}, ${t`${watchedCount} of ${episodeCount} episodes watched`}`}
accessibilityState={{ expanded }} accessibilityState={{ expanded }}
className="flex-row items-center justify-between p-4" className="flex-row items-center justify-between p-4"
> >
<View className="flex-1"> <View className="flex-1">
<Text className="text-foreground font-sans text-base font-medium"> <Text className="text-foreground font-sans text-base font-medium">
{season.name ?? t`Season ${season.seasonNumber}`} {season.name ?? t`Season ${seasonNumber}`}
</Text> </Text>
<Text className="text-muted-foreground mt-0.5 text-xs"> <Text className="text-muted-foreground mt-0.5 text-xs">
{t`${watchedCount}/${episodes.length} ${plural(episodes.length, { one: "episode", other: "episodes" })}`} {t`${watchedCount}/${plural(episodeCount, { one: "# episode", other: "# episodes" })}`}
</Text> </Text>
</View> </View>
+3 -2
View File
@@ -81,9 +81,10 @@ export function useTitleActions(options?: UseTitleActionsOptions) {
const updateRating = useMutation( const updateRating = useMutation(
orpc.titles.updateRating.mutationOptions({ orpc.titles.updateRating.mutationOptions({
onSuccess: (_data, input) => { onSuccess: (_data, input) => {
const stars = input.stars;
const defaultMsg = const defaultMsg =
input.stars > 0 stars > 0
? t`Rated ${input.stars} ${plural(input.stars, { one: "star", other: "stars" })}` ? t`Rated ${plural(stars, { one: "# star", other: "# stars" })}`
: t`Rating removed`; : t`Rating removed`;
toast.success(resolveToast(toastOverrides?.updateRating, defaultMsg, input)); toast.success(resolveToast(toastOverrides?.updateRating, defaultMsg, input));
// Rating only invalidates title queries, not dashboard // Rating only invalidates title queries, not dashboard
+14 -1
View File
@@ -1,6 +1,8 @@
import { reloadAppAsync } from "expo";
import * as Localization from "expo-localization"; import * as Localization from "expo-localization";
import { I18nManager } from "react-native";
import { activateLocale, SUPPORTED_LOCALES, type SupportedLocale } from "@sofa/i18n"; import { activateLocale, isLocaleRTL, SUPPORTED_LOCALES, type SupportedLocale } from "@sofa/i18n";
import { globalStorage } from "./mmkv"; import { globalStorage } from "./mmkv";
@@ -23,10 +25,21 @@ export function getPersistedLocale(): SupportedLocale {
export function setPersistedLocale(locale: SupportedLocale): void { export function setPersistedLocale(locale: SupportedLocale): void {
globalStorage.set(LOCALE_STORAGE_KEY, locale); globalStorage.set(LOCALE_STORAGE_KEY, locale);
const rtl = isLocaleRTL(locale);
I18nManager.allowRTL(rtl);
I18nManager.forceRTL(rtl);
} }
export function initLocale(): Promise<void> { export function initLocale(): Promise<void> {
const locale = getPersistedLocale(); const locale = getPersistedLocale();
const rtl = isLocaleRTL(locale);
I18nManager.allowRTL(rtl);
I18nManager.forceRTL(rtl);
// forceRTL only takes effect on the next launch — if the current layout
// doesn't match (e.g. fresh install on an RTL device), reload immediately.
if (I18nManager.isRTL !== rtl) {
reloadAppAsync();
}
if (locale !== "en") { if (locale !== "en") {
return activateLocale(locale); return activateLocale(locale);
} }
+24
View File
@@ -20,6 +20,12 @@ import "@formatjs/intl-pluralrules/locale-data/de.js";
import "@formatjs/intl-pluralrules/locale-data/es.js"; import "@formatjs/intl-pluralrules/locale-data/es.js";
import "@formatjs/intl-pluralrules/locale-data/it.js"; import "@formatjs/intl-pluralrules/locale-data/it.js";
import "@formatjs/intl-pluralrules/locale-data/pt.js"; import "@formatjs/intl-pluralrules/locale-data/pt.js";
import "@formatjs/intl-pluralrules/locale-data/ar.js";
import "@formatjs/intl-pluralrules/locale-data/nl.js";
import "@formatjs/intl-pluralrules/locale-data/he.js";
import "@formatjs/intl-pluralrules/locale-data/zh.js";
import "@formatjs/intl-pluralrules/locale-data/ja.js";
import "@formatjs/intl-pluralrules/locale-data/ko.js";
// 4. NumberFormat (depends on PluralRules, Locale) // 4. NumberFormat (depends on PluralRules, Locale)
import "@formatjs/intl-numberformat/polyfill.js"; import "@formatjs/intl-numberformat/polyfill.js";
import "@formatjs/intl-numberformat/locale-data/en.js"; import "@formatjs/intl-numberformat/locale-data/en.js";
@@ -28,6 +34,12 @@ import "@formatjs/intl-numberformat/locale-data/de.js";
import "@formatjs/intl-numberformat/locale-data/es.js"; import "@formatjs/intl-numberformat/locale-data/es.js";
import "@formatjs/intl-numberformat/locale-data/it.js"; import "@formatjs/intl-numberformat/locale-data/it.js";
import "@formatjs/intl-numberformat/locale-data/pt.js"; import "@formatjs/intl-numberformat/locale-data/pt.js";
import "@formatjs/intl-numberformat/locale-data/ar.js";
import "@formatjs/intl-numberformat/locale-data/nl.js";
import "@formatjs/intl-numberformat/locale-data/he.js";
import "@formatjs/intl-numberformat/locale-data/zh.js";
import "@formatjs/intl-numberformat/locale-data/ja.js";
import "@formatjs/intl-numberformat/locale-data/ko.js";
// 5. DateTimeFormat (depends on Locale) // 5. DateTimeFormat (depends on Locale)
import "@formatjs/intl-datetimeformat/polyfill.js"; import "@formatjs/intl-datetimeformat/polyfill.js";
import "@formatjs/intl-datetimeformat/locale-data/en.js"; import "@formatjs/intl-datetimeformat/locale-data/en.js";
@@ -36,6 +48,12 @@ import "@formatjs/intl-datetimeformat/locale-data/de.js";
import "@formatjs/intl-datetimeformat/locale-data/es.js"; import "@formatjs/intl-datetimeformat/locale-data/es.js";
import "@formatjs/intl-datetimeformat/locale-data/it.js"; import "@formatjs/intl-datetimeformat/locale-data/it.js";
import "@formatjs/intl-datetimeformat/locale-data/pt.js"; import "@formatjs/intl-datetimeformat/locale-data/pt.js";
import "@formatjs/intl-datetimeformat/locale-data/ar.js";
import "@formatjs/intl-datetimeformat/locale-data/nl.js";
import "@formatjs/intl-datetimeformat/locale-data/he.js";
import "@formatjs/intl-datetimeformat/locale-data/zh.js";
import "@formatjs/intl-datetimeformat/locale-data/ja.js";
import "@formatjs/intl-datetimeformat/locale-data/ko.js";
// 6. RelativeTimeFormat (depends on PluralRules, Locale) // 6. RelativeTimeFormat (depends on PluralRules, Locale)
import "@formatjs/intl-relativetimeformat/polyfill.js"; import "@formatjs/intl-relativetimeformat/polyfill.js";
import "@formatjs/intl-relativetimeformat/locale-data/en.js"; import "@formatjs/intl-relativetimeformat/locale-data/en.js";
@@ -44,3 +62,9 @@ import "@formatjs/intl-relativetimeformat/locale-data/de.js";
import "@formatjs/intl-relativetimeformat/locale-data/es.js"; import "@formatjs/intl-relativetimeformat/locale-data/es.js";
import "@formatjs/intl-relativetimeformat/locale-data/it.js"; import "@formatjs/intl-relativetimeformat/locale-data/it.js";
import "@formatjs/intl-relativetimeformat/locale-data/pt.js"; import "@formatjs/intl-relativetimeformat/locale-data/pt.js";
import "@formatjs/intl-relativetimeformat/locale-data/ar.js";
import "@formatjs/intl-relativetimeformat/locale-data/nl.js";
import "@formatjs/intl-relativetimeformat/locale-data/he.js";
import "@formatjs/intl-relativetimeformat/locale-data/zh.js";
import "@formatjs/intl-relativetimeformat/locale-data/ja.js";
import "@formatjs/intl-relativetimeformat/locale-data/ko.js";
+8 -1
View File
@@ -7,5 +7,12 @@
"@/*": ["./src/*"] "@/*": ["./src/*"]
} }
}, },
"include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts", "uniwind-types.d.ts"] "include": [
"**/*.ts",
"**/*.tsx",
".expo/types/**/*.ts",
"expo-env.d.ts",
"uniwind-types.d.ts",
"../../packages/i18n/src/po.d.ts"
]
} }
+1 -1
View File
@@ -11,7 +11,7 @@
"prefix": "" "prefix": ""
}, },
"iconLibrary": "tabler", "iconLibrary": "tabler",
"rtl": false, "rtl": true,
"aliases": { "aliases": {
"components": "@/components", "components": "@/components",
"utils": "@/lib/utils", "utils": "@/lib/utils",
+4 -4
View File
@@ -28,7 +28,7 @@
"@tabler/icons-react": "3.40.0", "@tabler/icons-react": "3.40.0",
"@tanstack/react-hotkeys": "0.4.2", "@tanstack/react-hotkeys": "0.4.2",
"@tanstack/react-query": "catalog:", "@tanstack/react-query": "catalog:",
"@tanstack/react-router": "1.167.5", "@tanstack/react-router": "1.168.1",
"better-auth": "catalog:", "better-auth": "catalog:",
"class-variance-authority": "0.7.1", "class-variance-authority": "0.7.1",
"clsx": "2.1.1", "clsx": "2.1.1",
@@ -37,7 +37,7 @@
"motion": "12.38.0", "motion": "12.38.0",
"react": "catalog:", "react": "catalog:",
"react-dom": "catalog:", "react-dom": "catalog:",
"shadcn": "4.0.8", "shadcn": "4.1.0",
"sonner": "2.0.7", "sonner": "2.0.7",
"tailwind-merge": "catalog:", "tailwind-merge": "catalog:",
"thumbhash": "catalog:", "thumbhash": "catalog:",
@@ -51,8 +51,8 @@
"@tanstack/devtools-vite": "0.6.0", "@tanstack/devtools-vite": "0.6.0",
"@tanstack/react-devtools": "0.10.0", "@tanstack/react-devtools": "0.10.0",
"@tanstack/react-query-devtools": "5.91.3", "@tanstack/react-query-devtools": "5.91.3",
"@tanstack/react-router-devtools": "1.166.9", "@tanstack/react-router-devtools": "1.166.10",
"@tanstack/router-plugin": "1.166.14", "@tanstack/router-plugin": "1.167.1",
"@types/bun": "catalog:", "@types/bun": "catalog:",
"@types/node": "catalog:", "@types/node": "catalog:",
"@types/react": "catalog:", "@types/react": "catalog:",
+2 -1
View File
@@ -48,6 +48,7 @@ export function AuthForm({
const isRegister = mode === "register"; const isRegister = mode === "register";
const showOidc = authConfig?.oidcEnabled ?? false; const showOidc = authConfig?.oidcEnabled ?? false;
const showPasswordForm = !(authConfig?.passwordLoginDisabled ?? false); const showPasswordForm = !(authConfig?.passwordLoginDisabled ?? false);
const oidcProviderName = authConfig?.oidcProviderName || "SSO";
async function handleSubmit(e: React.FormEvent) { async function handleSubmit(e: React.FormEvent) {
e.preventDefault(); e.preventDefault();
@@ -139,7 +140,7 @@ export function AuthForm({
{oidcLoading ? ( {oidcLoading ? (
<Trans>Redirecting</Trans> <Trans>Redirecting</Trans>
) : ( ) : (
<Trans>Sign in with {authConfig?.oidcProviderName || "SSO"}</Trans> <Trans>Sign in with {oidcProviderName}</Trans>
)} )}
</Button> </Button>
</motion.div> </motion.div>
@@ -27,6 +27,8 @@ export function ContinueWatchingCard({ item }: { item: ContinueWatchingItemProps
const { t } = useLingui(); const { t } = useLingui();
const stillUrl = item.nextEpisode?.stillPath ?? item.title.backdropPath ?? null; const stillUrl = item.nextEpisode?.stillPath ?? item.title.backdropPath ?? null;
const progress = item.totalEpisodes > 0 ? (item.watchedEpisodes / item.totalEpisodes) * 100 : 0; const progress = item.totalEpisodes > 0 ? (item.watchedEpisodes / item.totalEpisodes) * 100 : 0;
const watchedEpisodes = item.watchedEpisodes;
const totalEpisodes = item.totalEpisodes;
return ( return (
<Link <Link
@@ -63,7 +65,7 @@ export function ContinueWatchingCard({ item }: { item: ContinueWatchingItemProps
{t`Up next`} {t`Up next`}
</p> </p>
<p className="mt-0.5 truncate text-sm font-medium text-white"> <p className="mt-0.5 truncate text-sm font-medium text-white">
<span className="mr-0.5 font-mono text-xs text-white/60 [word-spacing:-0.25em]"> <span className="me-0.5 font-mono text-xs text-white/60 [word-spacing:-0.25em]">
S{item.nextEpisode.seasonNumber} E{item.nextEpisode.episodeNumber} S{item.nextEpisode.seasonNumber} E{item.nextEpisode.episodeNumber}
</span>{" "} </span>{" "}
{item.nextEpisode.name} {item.nextEpisode.name}
@@ -75,7 +77,7 @@ export function ContinueWatchingCard({ item }: { item: ContinueWatchingItemProps
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="truncate text-sm font-medium">{item.title.title}</p> <p className="truncate text-sm font-medium">{item.title.title}</p>
<p className="text-muted-foreground text-xs"> <p className="text-muted-foreground text-xs">
{t`${item.watchedEpisodes}/${item.totalEpisodes} ${plural(item.totalEpisodes, { one: "episode", other: "episodes" })}`} {t`${watchedEpisodes}/${plural(totalEpisodes, { one: "# episode", other: "# episodes" })}`}
</p> </p>
</div> </div>
<div className="bg-primary/10 text-primary group-hover:bg-primary group-hover:text-primary-foreground flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition-colors"> <div className="bg-primary/10 text-primary group-hover:bg-primary group-hover:text-primary-foreground flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition-colors">
@@ -70,7 +70,7 @@ export function HeroBanner({
<Trans>Trending today</Trans> <Trans>Trending today</Trans>
</span> </span>
</div> </div>
<Link to="/titles/$id" params={{ id }} className="group/title text-left"> <Link to="/titles/$id" params={{ id }} className="group/title text-start">
<h2 className="font-display group-hover/title:text-primary text-3xl tracking-tight text-balance transition-colors sm:text-4xl"> <h2 className="font-display group-hover/title:text-primary text-3xl tracking-tight text-balance transition-colors sm:text-4xl">
{title} {title}
</h2> </h2>
+3 -3
View File
@@ -188,7 +188,7 @@ export function NavBar({
> >
<IconSearch aria-hidden={true} className="size-3.5" /> <IconSearch aria-hidden={true} className="size-3.5" />
<span>{t`Search…`}</span> <span>{t`Search…`}</span>
<Kbd className="ml-2.5"> K</Kbd> <Kbd className="ms-2.5"> K</Kbd>
</button> </button>
<Separator <Separator
orientation="vertical" orientation="vertical"
@@ -219,7 +219,7 @@ export function NavBar({
<p className="text-foreground truncate text-sm leading-tight font-medium"> <p className="text-foreground truncate text-sm leading-tight font-medium">
{userName} {userName}
{userRole === "admin" && ( {userRole === "admin" && (
<Badge className="bg-primary/10 text-primary mb-0.5 ml-1.5 rounded-md border-0 align-middle"> <Badge className="bg-primary/10 text-primary ms-1.5 mb-0.5 rounded-md border-0 align-middle">
<Trans>Admin</Trans> <Trans>Admin</Trans>
</Badge> </Badge>
)} )}
@@ -291,7 +291,7 @@ export function MobileTabBar() {
return ( return (
<nav <nav
aria-label="Primary" aria-label="Primary"
className="border-border/50 bg-background/90 fixed right-0 bottom-0 left-0 z-50 border-t pr-[env(safe-area-inset-right)] pl-[env(safe-area-inset-left)] backdrop-blur-xl sm:hidden" className="border-border/50 bg-background/90 fixed right-0 bottom-0 left-0 z-50 border-t ps-[env(safe-area-inset-left)] pe-[env(safe-area-inset-right)] backdrop-blur-xl sm:hidden"
> >
<div ref={containerRef} className="relative flex h-14 items-stretch"> <div ref={containerRef} className="relative flex h-14 items-stretch">
{mobileTabs.map((tab, i) => { {mobileTabs.map((tab, i) => {
@@ -294,7 +294,7 @@ export function AccountSection({
transition={{ duration: 0.1 }} transition={{ duration: 0.1 }}
type="button" type="button"
onClick={() => setIsEditingName(true)} onClick={() => setIsEditingName(true)}
className="group/name hover:text-primary inline-flex items-center gap-1.5 rounded-md px-0 text-left transition-colors" className="group/name hover:text-primary inline-flex items-center gap-1.5 rounded-md px-0 text-start transition-colors"
> >
{displayName} {displayName}
<IconPencil className="group-hover/name:text-muted-foreground size-3 text-transparent transition-colors" /> <IconPencil className="group-hover/name:text-muted-foreground size-3 text-transparent transition-colors" />
@@ -305,7 +305,7 @@ export function AccountSection({
<CardDescription> <CardDescription>
{user.email} {user.email}
{user.role === "admin" && ( {user.role === "admin" && (
<Badge className="bg-primary/10 text-primary ml-1.5 rounded-md border-0 align-middle"> <Badge className="bg-primary/10 text-primary ms-1.5 rounded-md border-0 align-middle">
<Trans>Admin</Trans> <Trans>Admin</Trans>
</Badge> </Badge>
)} )}
@@ -218,31 +218,28 @@ export function BackupScheduleSection() {
<CardDescription> <CardDescription>
{enabled ? ( {enabled ? (
<span className="inline-flex flex-wrap items-baseline" suppressHydrationWarning> <span className="inline-flex flex-wrap items-baseline" suppressHydrationWarning>
{formatNextBackup(frequency, time, dow)}.{" "} {formatNextBackup(frequency, time, dow)}. <Trans>Keeping</Trans>{" "}
<Trans> <Select
Keeping{" "} value={String(maxRetention)}
<Select onValueChange={(v) => v && changeMaxRetention(Number(v))}
value={String(maxRetention)} modal={false}
onValueChange={(v) => v && changeMaxRetention(Number(v))} >
modal={false} <SelectTrigger className="decoration-muted-foreground/50 hover:text-foreground hover:decoration-foreground/50 focus-visible:decoration-foreground ms-1.5 me-0.5 !h-auto w-auto gap-0.5 rounded-none border-0 bg-transparent p-0 underline decoration-dotted underline-offset-4 shadow-none hover:bg-transparent focus-visible:decoration-solid focus-visible:ring-0 dark:bg-transparent dark:hover:bg-transparent">
> <SelectValue>
<SelectTrigger className="decoration-muted-foreground/50 hover:text-foreground hover:decoration-foreground/50 focus-visible:decoration-foreground mr-0.5 ml-1.5 !h-auto w-auto gap-0.5 rounded-none border-0 bg-transparent p-0 underline decoration-dotted underline-offset-4 shadow-none hover:bg-transparent focus-visible:decoration-solid focus-visible:ring-0 dark:bg-transparent dark:hover:bg-transparent"> {(value: string | null) =>
<SelectValue> value === "0" ? t`unlimited` : value ? t`last ${value}` : null
{(value: string | null) => }
value === "0" ? t`unlimited` : value ? t`last ${value}` : null </SelectValue>
} </SelectTrigger>
</SelectValue> <SelectContent align="start" alignItemWithTrigger={false} className="p-1">
</SelectTrigger> {[3, 5, 7, 14, 30, 0].map((n) => (
<SelectContent align="start" alignItemWithTrigger={false} className="p-1"> <SelectItem key={n} value={String(n)}>
{[3, 5, 7, 14, 30, 0].map((n) => ( {n === 0 ? t`unlimited` : t`last ${n}`}
<SelectItem key={n} value={String(n)}> </SelectItem>
{n === 0 ? t`unlimited` : t`last ${n}`} ))}
</SelectItem> </SelectContent>
))} </Select>{" "}
</SelectContent> <Trans>backups.</Trans>
</Select>{" "}
backups.
</Trans>
</span> </span>
) : ( ) : (
<Trans>Automatically back up your database on a schedule</Trans> <Trans>Automatically back up your database on a schedule</Trans>
@@ -93,9 +93,10 @@ export function BackupSection() {
const creating = createMutation.isPending; const creating = createMutation.isPending;
const deleting = deleteMutation.isPending ? (deleteMutation.variables?.filename ?? null) : null; const deleting = deleteMutation.isPending ? (deleteMutation.variables?.filename ?? null) : null;
const backupCount = displayBackups.length;
const backupCountLabel = const backupCountLabel =
displayBackups.length > 0 backupCount > 0
? t`${displayBackups.length} ${plural(displayBackups.length, { one: "backup", other: "backups" })} stored` ? t`${plural(backupCount, { one: "# backup", other: "# backups" })} stored`
: t`No backups yet`; : t`No backups yet`;
return ( return (
@@ -126,136 +127,136 @@ export function BackupSection() {
{displayBackups.length > 0 && ( {displayBackups.length > 0 && (
<CardContent className="border-border/30 border-t pt-4"> <CardContent className="border-border/30 border-t pt-4">
<div className="space-y-1.5"> <div className="space-y-1.5">
{displayBackups.map((backup: BackupInfo) => ( {displayBackups.map((backup: BackupInfo) => {
<motion.div const backupDate = formatBackupDate(backup.createdAt);
key={backup.filename} return (
initial={{ opacity: 0, height: 0 }} <motion.div
animate={{ opacity: 1, height: "auto" }} key={backup.filename}
exit={{ opacity: 0, height: 0 }} initial={{ opacity: 0, height: 0 }}
transition={{ duration: 0.2 }} animate={{ opacity: 1, height: "auto" }}
className="overflow-hidden" exit={{ opacity: 0, height: 0 }}
> transition={{ duration: 0.2 }}
<div className="group hover:bg-muted/40 flex items-center gap-3 rounded-md px-2.5 py-1.5 transition-colors"> className="overflow-hidden"
<Tooltip> >
<TooltipTrigger <div className="group hover:bg-muted/40 flex items-center gap-3 rounded-md px-2.5 py-1.5 transition-colors">
render={
<span className="text-muted-foreground flex shrink-0 items-center" />
}
>
{backup.source === "scheduled" ? (
<IconClock aria-hidden={true} className="size-3.5" />
) : backup.source === "pre-restore" ? (
<IconShieldCheck aria-hidden={true} className="size-3.5" />
) : (
<IconPointer aria-hidden={true} className="size-3.5" />
)}
</TooltipTrigger>
<TooltipContent>
{backup.source === "scheduled"
? t`Scheduled backup`
: backup.source === "pre-restore"
? t`Pre-restore backup`
: t`Manual backup`}
</TooltipContent>
</Tooltip>
<div className="min-w-0 flex-1">
<div className="flex items-baseline gap-2">
<span className="text-foreground text-xs font-medium">
{formatBackupDate(backup.createdAt)}
</span>
<span className="text-muted-foreground text-[11px]">
{formatBytesI18n(backup.sizeBytes)}
</span>
<span
className="text-muted-foreground/50 text-[11px]"
suppressHydrationWarning
>
{formatRelativeTime(backup.createdAt)}
</span>
</div>
</div>
<div className="flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-focus-within:opacity-100 group-hover:opacity-100">
<Tooltip> <Tooltip>
<TooltipTrigger <TooltipTrigger
render={ render={
<Button <span className="text-muted-foreground flex shrink-0 items-center" />
variant="ghost"
size="icon-sm"
className="text-muted-foreground hover:text-foreground"
nativeButton={false}
render={
<a
href={`/api/backup/${backup.filename}`}
download
aria-label={t`Download backup`}
>
<IconCloudDownload />
</a>
}
/>
} }
/> >
{backup.source === "scheduled" ? (
<IconClock aria-hidden={true} className="size-3.5" />
) : backup.source === "pre-restore" ? (
<IconShieldCheck aria-hidden={true} className="size-3.5" />
) : (
<IconPointer aria-hidden={true} className="size-3.5" />
)}
</TooltipTrigger>
<TooltipContent> <TooltipContent>
<Trans>Download</Trans> {backup.source === "scheduled"
? t`Scheduled backup`
: backup.source === "pre-restore"
? t`Pre-restore backup`
: t`Manual backup`}
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
<AlertDialog> <div className="min-w-0 flex-1">
<div className="flex items-baseline gap-2">
<span className="text-foreground text-xs font-medium">{backupDate}</span>
<span className="text-muted-foreground text-[11px]">
{formatBytesI18n(backup.sizeBytes)}
</span>
<span
className="text-muted-foreground/50 text-[11px]"
suppressHydrationWarning
>
{formatRelativeTime(backup.createdAt)}
</span>
</div>
</div>
<div className="flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-focus-within:opacity-100 group-hover:opacity-100">
<Tooltip> <Tooltip>
<AlertDialogTrigger <TooltipTrigger
render={ render={
<TooltipTrigger <Button
variant="ghost"
size="icon-sm"
className="text-muted-foreground hover:text-foreground"
nativeButton={false}
render={ render={
<Button <a
variant="ghost" href={`/api/backup/${backup.filename}`}
size="icon-sm" download
aria-label={t`Delete backup`} aria-label={t`Download backup`}
className="text-muted-foreground hover:text-destructive" >
disabled={deleting === backup.filename} <IconCloudDownload />
/> </a>
} }
/> />
} }
> />
{deleting === backup.filename ? <Spinner /> : <IconTrash />}
</AlertDialogTrigger>
<TooltipContent> <TooltipContent>
<Trans>Delete</Trans> <Trans>Download</Trans>
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
<AlertDialogContent> <AlertDialog>
<AlertDialogHeader> <Tooltip>
<AlertDialogTitle> <AlertDialogTrigger
<Trans>Delete backup?</Trans> render={
</AlertDialogTitle> <TooltipTrigger
<AlertDialogDescription> render={
<Trans> <Button
This will permanently delete the backup from{" "} variant="ghost"
<strong>{formatBackupDate(backup.createdAt)}</strong>. This cannot size="icon-sm"
be undone. aria-label={t`Delete backup`}
</Trans> className="text-muted-foreground hover:text-destructive"
</AlertDialogDescription> disabled={deleting === backup.filename}
</AlertDialogHeader> />
<AlertDialogFooter> }
<AlertDialogCancel> />
<Trans>Cancel</Trans>
</AlertDialogCancel>
<AlertDialogAction
variant="destructive"
onClick={() =>
deleteMutation.mutate({
filename: backup.filename,
})
} }
> >
{deleting === backup.filename ? <Spinner /> : <IconTrash />}
</AlertDialogTrigger>
<TooltipContent>
<Trans>Delete</Trans> <Trans>Delete</Trans>
</AlertDialogAction> </TooltipContent>
</AlertDialogFooter> </Tooltip>
</AlertDialogContent> <AlertDialogContent>
</AlertDialog> <AlertDialogHeader>
<AlertDialogTitle>
<Trans>Delete backup?</Trans>
</AlertDialogTitle>
<AlertDialogDescription>
<Trans>
This will permanently delete the backup from{" "}
<strong>{backupDate}</strong>. This cannot be undone.
</Trans>
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>
<Trans>Cancel</Trans>
</AlertDialogCancel>
<AlertDialogAction
variant="destructive"
onClick={() =>
deleteMutation.mutate({
filename: backup.filename,
})
}
>
<Trans>Delete</Trans>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
</div> </div>
</div> </motion.div>
</motion.div> );
))} })}
</div> </div>
</CardContent> </CardContent>
)} )}
@@ -277,8 +277,10 @@ function ImportSourceCard({ config }: { config: SourceConfig }) {
warnings: event.job.warnings, warnings: event.job.warnings,
}); });
setStep("done"); setStep("done");
if (event.job.importedCount > 0) { const importedCount = event.job.importedCount;
toast.success(t`Imported ${event.job.importedCount} items from ${config.label}`); const sourceLabel = config.label;
if (importedCount > 0) {
toast.success(t`Imported ${importedCount} items from ${sourceLabel}`);
} }
} else if (event.type === "timeout") { } else if (event.type === "timeout") {
receivedComplete = true; receivedComplete = true;
@@ -366,8 +368,9 @@ function ImportSourceCard({ config }: { config: SourceConfig }) {
}); });
if (!res.ok) { if (!res.ok) {
const err = await res.json().catch(() => ({})); const err = await res.json().catch(() => ({}));
const sourceLabel = config.label;
throw new Error( throw new Error(
(err as { error?: string }).error ?? t`Failed to start ${config.label} connection`, (err as { error?: string }).error ?? t`Failed to start ${sourceLabel} connection`,
); );
} }
const data = (await res.json()) as DeviceCodeInfo; const data = (await res.json()) as DeviceCodeInfo;
@@ -546,14 +549,16 @@ function ChooseStep({
onCancel: () => void; onCancel: () => void;
}) { }) {
const { t } = useLingui(); const { t } = useLingui();
const sourceLabel = config.label;
const acceptFormat = config.accept;
return ( return (
<> <>
<DialogHeader> <DialogHeader>
<DialogTitle> <DialogTitle>
<Trans>Import from {config.label}</Trans> <Trans>Import from {sourceLabel}</Trans>
</DialogTitle> </DialogTitle>
<DialogDescription> <DialogDescription>
<Trans>Choose how to import your {config.label} data.</Trans> <Trans>Choose how to import your {sourceLabel} data.</Trans>
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
@@ -566,7 +571,7 @@ function ChooseStep({
<button <button
type="button" type="button"
className="border-border/50 hover:bg-muted/50 flex w-full items-center gap-3 rounded-lg border p-4 text-left transition-colors" className="border-border/50 hover:bg-muted/50 flex w-full items-center gap-3 rounded-lg border p-4 text-start transition-colors"
onClick={onConnect} onClick={onConnect}
> >
<div className="bg-primary/10 flex h-10 w-10 shrink-0 items-center justify-center rounded-lg"> <div className="bg-primary/10 flex h-10 w-10 shrink-0 items-center justify-center rounded-lg">
@@ -574,17 +579,17 @@ function ChooseStep({
</div> </div>
<div> <div>
<p className="text-sm font-medium"> <p className="text-sm font-medium">
<Trans>Connect with {config.label}</Trans> <Trans>Connect with {sourceLabel}</Trans>
</p> </p>
<p className="text-muted-foreground text-xs"> <p className="text-muted-foreground text-xs">
<Trans>Authorize Sofa to read your {config.label} library. No password shared.</Trans> <Trans>Authorize Sofa to read your {sourceLabel} library. No password shared.</Trans>
</p> </p>
</div> </div>
</button> </button>
<button <button
type="button" type="button"
className="border-border/50 hover:bg-muted/50 flex w-full items-center gap-3 rounded-lg border p-4 text-left transition-colors" className="border-border/50 hover:bg-muted/50 flex w-full items-center gap-3 rounded-lg border p-4 text-start transition-colors"
onClick={() => { onClick={() => {
onCancel(); onCancel();
// Small delay so the dialog closes before file picker opens // Small delay so the dialog closes before file picker opens
@@ -600,7 +605,7 @@ function ChooseStep({
<Trans>Upload export file</Trans> <Trans>Upload export file</Trans>
</p> </p>
<p className="text-muted-foreground text-xs"> <p className="text-muted-foreground text-xs">
{t`Upload a ${config.accept} export from your ${config.label} account settings.`} {t`Upload a ${acceptFormat} export from your ${sourceLabel} account settings.`}
</p> </p>
</div> </div>
</button> </button>
@@ -725,6 +730,12 @@ function PreviewStep({
(options.importWatchlist ? stats.watchlist : 0) + (options.importWatchlist ? stats.watchlist : 0) +
(options.importRatings ? stats.ratings : 0); (options.importRatings ? stats.ratings : 0);
const movieCount = stats.movies;
const episodeCount = stats.episodes;
const watchlistCount = stats.watchlist;
const ratingCount = stats.ratings;
const unresolvedCount = preview.diagnostics?.unresolved ?? 0;
return ( return (
<> <>
<DialogHeader> <DialogHeader>
@@ -738,18 +749,18 @@ function PreviewStep({
<div className="space-y-4 py-2"> <div className="space-y-4 py-2">
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<StatBadge label={t`Movies`} count={stats.movies} /> <StatBadge label={t`Movies`} count={movieCount} />
<StatBadge label={t`Episodes`} count={stats.episodes} /> <StatBadge label={t`Episodes`} count={episodeCount} />
<StatBadge label={t`Watchlist`} count={stats.watchlist} /> <StatBadge label={t`Watchlist`} count={watchlistCount} />
<StatBadge label={t`Ratings`} count={stats.ratings} /> <StatBadge label={t`Ratings`} count={ratingCount} />
</div> </div>
{preview.diagnostics && preview.diagnostics.unresolved > 0 && ( {preview.diagnostics && unresolvedCount > 0 && (
<div className="bg-muted/50 rounded-lg p-3"> <div className="bg-muted/50 rounded-lg p-3">
<p className="text-muted-foreground text-xs"> <p className="text-muted-foreground text-xs">
<Trans> <Trans>
{preview.diagnostics.unresolved} items have no external IDs and will be resolved by {unresolvedCount} items have no external IDs and will be resolved by title search,
title search, which may be less accurate. which may be less accurate.
</Trans> </Trans>
</p> </p>
</div> </div>
@@ -761,19 +772,19 @@ function PreviewStep({
</p> </p>
<OptionCheckbox <OptionCheckbox
label={t`Watch history`} label={t`Watch history`}
description={t`${stats.movies} movies, ${stats.episodes} episodes`} description={t`${movieCount} movies, ${episodeCount} episodes`}
checked={options.importWatches} checked={options.importWatches}
onChange={(v) => setOptions({ ...options, importWatches: v })} onChange={(v) => setOptions({ ...options, importWatches: v })}
/> />
<OptionCheckbox <OptionCheckbox
label={t`Watchlist`} label={t`Watchlist`}
description={t`${stats.watchlist} items`} description={t`${watchlistCount} items`}
checked={options.importWatchlist} checked={options.importWatchlist}
onChange={(v) => setOptions({ ...options, importWatchlist: v })} onChange={(v) => setOptions({ ...options, importWatchlist: v })}
/> />
<OptionCheckbox <OptionCheckbox
label={t`Ratings`} label={t`Ratings`}
description={t`${stats.ratings} ratings`} description={t`${ratingCount} ratings`}
checked={options.importRatings} checked={options.importRatings}
onChange={(v) => setOptions({ ...options, importRatings: v })} onChange={(v) => setOptions({ ...options, importRatings: v })}
/> />
@@ -863,6 +874,9 @@ function DoneStep({
onClose: () => void; onClose: () => void;
}) { }) {
const { t } = useLingui(); const { t } = useLingui();
const errorCount = result.errors.length;
const warningCount = result.warnings.length;
const remainingErrors = errorCount - 50;
return ( return (
<> <>
<DialogHeader> <DialogHeader>
@@ -881,28 +895,28 @@ function DoneStep({
<StatBadge label={t`Failed`} count={result.failed} /> <StatBadge label={t`Failed`} count={result.failed} />
</div> </div>
{result.errors.length > 0 && ( {errorCount > 0 && (
<div className="bg-destructive/10 max-h-40 overflow-y-auto rounded-lg p-3"> <div className="bg-destructive/10 max-h-40 overflow-y-auto rounded-lg p-3">
<p className="text-destructive mb-1 text-xs font-medium"> <p className="text-destructive mb-1 text-xs font-medium">
<Trans>Errors ({result.errors.length})</Trans> <Trans>Errors ({errorCount})</Trans>
</p> </p>
<ul className="text-destructive/80 space-y-0.5 text-xs"> <ul className="text-destructive/80 space-y-0.5 text-xs">
{result.errors.slice(0, 50).map((e, i) => ( {result.errors.slice(0, 50).map((e, i) => (
<li key={i}>{e}</li> <li key={i}>{e}</li>
))} ))}
{result.errors.length > 50 && ( {errorCount > 50 && (
<li> <li>
<Trans>...and {result.errors.length - 50} more</Trans> <Trans>...and {remainingErrors} more</Trans>
</li> </li>
)} )}
</ul> </ul>
</div> </div>
)} )}
{result.warnings.length > 0 && ( {warningCount > 0 && (
<div className="max-h-32 overflow-y-auto rounded-lg bg-yellow-500/10 p-3"> <div className="max-h-32 overflow-y-auto rounded-lg bg-yellow-500/10 p-3">
<p className="mb-1 text-xs font-medium text-yellow-600"> <p className="mb-1 text-xs font-medium text-yellow-600">
<Trans>Warnings ({result.warnings.length})</Trans> <Trans>Warnings ({warningCount})</Trans>
</p> </p>
<ul className="space-y-0.5 text-xs text-yellow-600/80"> <ul className="space-y-0.5 text-xs text-yellow-600/80">
{result.warnings.slice(0, 20).map((w, i) => ( {result.warnings.slice(0, 20).map((w, i) => (
@@ -147,7 +147,7 @@ export function IntegrationCard({
<div className="bg-primary/10 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg"> <div className="bg-primary/10 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg">
<Icon className="text-primary size-4" /> <Icon className="text-primary size-4" />
</div> </div>
<div className="text-left"> <div className="text-start">
<CardTitle>{config.label}</CardTitle> <CardTitle>{config.label}</CardTitle>
<CardDescription> <CardDescription>
{connection ? config.connectedStatus(connection.lastEventAt) : t`Not configured`} {connection ? config.connectedStatus(connection.lastEventAt) : t`Not configured`}
@@ -172,7 +172,7 @@ export function IntegrationCard({
size="lg" size="lg"
className="w-full" className="w-full"
> >
{connecting ? <Trans>Connecting...</Trans> : <Trans>Connect {config.label}</Trans>} {connecting ? <Trans>Connecting...</Trans> : <Trans>Connect {label}</Trans>}
</Button> </Button>
) : ( ) : (
<AnimatePresence> <AnimatePresence>
@@ -251,10 +251,10 @@ export function IntegrationCard({
<div className="border-border/50 bg-muted/30 text-muted-foreground mt-2 rounded-lg border p-3 text-xs leading-relaxed"> <div className="border-border/50 bg-muted/30 text-muted-foreground mt-2 rounded-lg border p-3 text-xs leading-relaxed">
<ol className="list-inside list-decimal space-y-1.5">{config.setupSteps}</ol> <ol className="list-inside list-decimal space-y-1.5">{config.setupSteps}</ol>
{config.docsUrl && ( {config.docsUrl && (
<p className="mt-2 -ml-0.5"> <p className="-ms-0.5 mt-2">
<IconBook2 <IconBook2
aria-hidden={true} aria-hidden={true}
className="mr-1 inline-block size-3 translate-y-[-1px]" className="me-1 inline-block size-3 translate-y-[-1px]"
/> />
<Trans>Need more help?</Trans>{" "} <Trans>Need more help?</Trans>{" "}
<a <a
@@ -285,14 +285,18 @@ export function IntegrationCard({
/** Status line for webhook integrations (shows last event time). */ /** Status line for webhook integrations (shows last event time). */
export function webhookStatus(lastEventAt: string | null): string { export function webhookStatus(lastEventAt: string | null): string {
return lastEventAt if (lastEventAt) {
? i18n._(msg`Last event ${formatRelativeTime(lastEventAt)}`) const relativeTime = formatRelativeTime(lastEventAt);
: i18n._(msg`Ready — nothing received yet`); return i18n._(msg`Last event ${relativeTime}`);
}
return i18n._(msg`Ready — nothing received yet`);
} }
/** Status line for list integrations (shows last event time). */ /** Status line for list integrations (shows last event time). */
export function listStatus(lastEventAt: string | null): string { export function listStatus(lastEventAt: string | null): string {
return lastEventAt if (lastEventAt) {
? i18n._(msg`Last polled ${formatRelativeTime(lastEventAt)}`) const relativeTime = formatRelativeTime(lastEventAt);
: i18n._(msg`Ready — not polled yet`); return i18n._(msg`Last polled ${relativeTime}`);
}
return i18n._(msg`Ready — not polled yet`);
} }
@@ -29,7 +29,7 @@ export function LanguageSection() {
<div className="bg-primary/10 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg"> <div className="bg-primary/10 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg">
<IconLanguage className="text-primary size-4" /> <IconLanguage className="text-primary size-4" />
</div> </div>
<div className="text-left"> <div className="text-start">
<CardTitle> <CardTitle>
<Trans>Language</Trans> <Trans>Language</Trans>
</CardTitle> </CardTitle>
@@ -46,28 +46,31 @@ export function LanguageSection() {
<CollapsibleContent className="h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-200 ease-out data-[ending-style]:h-0 data-[starting-style]:h-0"> <CollapsibleContent className="h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-200 ease-out data-[ending-style]:h-0 data-[starting-style]:h-0">
<CardContent className="border-border/30 border-t pt-4"> <CardContent className="border-border/30 border-t pt-4">
<div className="grid grid-cols-2 gap-2 sm:grid-cols-3"> <div className="grid grid-cols-2 gap-2 sm:grid-cols-3">
{LOCALE_INFO.map((info) => ( {LOCALE_INFO.map((info) => {
<button const name = info.name;
key={info.code} return (
type="button" <button
onClick={() => handleLocaleChange(info.code)} key={info.code}
className={`relative flex items-center gap-2 rounded-lg border px-3 py-2 text-left text-sm transition-colors ${ type="button"
currentLocale === info.code onClick={() => handleLocaleChange(info.code)}
? "border-primary bg-primary/5 text-foreground" className={`relative flex items-center gap-2 rounded-lg border px-3 py-2 text-start text-sm transition-colors ${
: "border-border hover:border-primary/40 hover:bg-primary/5" currentLocale === info.code
}`} ? "border-primary bg-primary/5 text-foreground"
aria-label={t`Switch to ${info.name}`} : "border-border hover:border-primary/40 hover:bg-primary/5"
aria-pressed={currentLocale === info.code} }`}
> aria-label={t`Switch to ${name}`}
<div className="min-w-0"> aria-pressed={currentLocale === info.code}
<div className="truncate font-medium">{info.nativeName}</div> >
<div className="text-muted-foreground truncate text-xs">{info.name}</div> <div className="min-w-0">
</div> <div className="truncate font-medium">{info.nativeName}</div>
{currentLocale === info.code && ( <div className="text-muted-foreground truncate text-xs">{info.name}</div>
<IconCheck className="text-primary ml-auto size-4 shrink-0" /> </div>
)} {currentLocale === info.code && (
</button> <IconCheck className="text-primary ml-auto size-4 shrink-0" />
))} )}
</button>
);
})}
</div> </div>
</CardContent> </CardContent>
</CollapsibleContent> </CollapsibleContent>
@@ -80,7 +80,7 @@ export function SkeletonCards() {
return ( return (
<div className="space-y-3"> <div className="space-y-3">
{["status", "jobs", "storage"].map((s) => ( {["status", "jobs", "storage"].map((s) => (
<Card key={s} className="border-l-primary/30 border-l-2"> <Card key={s} className="border-s-primary/30 border-s-2">
<CardContent> <CardContent>
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<Skeleton className="mt-0.5 h-8 w-8 rounded-lg" /> <Skeleton className="mt-0.5 h-8 w-8 rounded-lg" />
@@ -181,7 +181,7 @@ function SystemStatusCard({
onRefresh: () => void; onRefresh: () => void;
}) { }) {
return ( return (
<Card className="border-l-primary/30 border-l-2"> <Card className="border-s-primary/30 border-s-2">
<CardContent> <CardContent>
<div className="flex items-center justify-between gap-4"> <div className="flex items-center justify-between gap-4">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
@@ -313,7 +313,8 @@ function BackgroundJobsCard({
const triggerJobMutation = useMutation( const triggerJobMutation = useMutation(
orpc.admin.triggerJob.mutationOptions({ orpc.admin.triggerJob.mutationOptions({
onSuccess: (_, { name }) => { onSuccess: (_, { name }) => {
toast.success(t`${JOB_LABELS[name] ?? name} triggered`); const jobLabel = JOB_LABELS[name] ?? name;
toast.success(t`${jobLabel} triggered`);
setTimeout(onRefresh, 1500); setTimeout(onRefresh, 1500);
}, },
onError: (err) => { onError: (err) => {
@@ -334,9 +335,10 @@ function BackgroundJobsCard({
}); });
const activeJobs = jobs.filter((j) => !j.disabled); const activeJobs = jobs.filter((j) => !j.disabled);
const healthyCount = activeJobs.filter((j) => j.lastStatus === "success").length; const healthyCount = activeJobs.filter((j) => j.lastStatus === "success").length;
const activeJobCount = activeJobs.length;
return ( return (
<Card className="border-l-primary/30 border-l-2"> <Card className="border-s-primary/30 border-s-2">
<CardContent> <CardContent>
<div className="flex items-center justify-between gap-4"> <div className="flex items-center justify-between gap-4">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
@@ -349,7 +351,7 @@ function BackgroundJobsCard({
</CardTitle> </CardTitle>
<CardDescription> <CardDescription>
<Trans> <Trans>
{healthyCount} of {activeJobs.length} jobs healthy {healthyCount} of {activeJobCount} jobs healthy
</Trans> </Trans>
</CardDescription> </CardDescription>
</div> </div>
@@ -361,7 +363,7 @@ function BackgroundJobsCard({
<Table> <Table>
<TableHeader> <TableHeader>
<TableRow className="border-b-border/30 hover:bg-transparent"> <TableRow className="border-b-border/30 hover:bg-transparent">
<TableHead className="text-muted-foreground h-8 pl-5 text-[10px] font-medium tracking-wider uppercase"> <TableHead className="text-muted-foreground h-8 ps-5 text-[10px] font-medium tracking-wider uppercase">
<Trans>Job</Trans> <Trans>Job</Trans>
</TableHead> </TableHead>
<TableHead className="text-muted-foreground h-8 text-[10px] font-medium tracking-wider uppercase"> <TableHead className="text-muted-foreground h-8 text-[10px] font-medium tracking-wider uppercase">
@@ -373,7 +375,7 @@ function BackgroundJobsCard({
<TableHead className="text-muted-foreground h-8 text-[10px] font-medium tracking-wider uppercase"> <TableHead className="text-muted-foreground h-8 text-[10px] font-medium tracking-wider uppercase">
<Trans>Next run</Trans> <Trans>Next run</Trans>
</TableHead> </TableHead>
<TableHead className="text-muted-foreground h-8 pr-5 text-right text-[10px] font-medium tracking-wider uppercase"> <TableHead className="text-muted-foreground h-8 pe-5 text-end text-[10px] font-medium tracking-wider uppercase">
<span className="sr-only"> <span className="sr-only">
<Trans>Actions</Trans> <Trans>Actions</Trans>
</span> </span>
@@ -388,7 +390,7 @@ function BackgroundJobsCard({
return ( return (
<TableRow key={job.jobName} className="border-b-border/20 hover:bg-muted/30"> <TableRow key={job.jobName} className="border-b-border/20 hover:bg-muted/30">
{/* Job name + status */} {/* Job name + status */}
<TableCell className="pl-5"> <TableCell className="ps-5">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{job.disabled ? ( {job.disabled ? (
<StatusDot status="inactive" label={t`Disabled`} /> <StatusDot status="inactive" label={t`Disabled`} />
@@ -472,7 +474,7 @@ function BackgroundJobsCard({
</TableCell> </TableCell>
{/* Trigger button */} {/* Trigger button */}
<TableCell className="pr-5 text-right"> <TableCell className="pe-5 text-end">
<Tooltip> <Tooltip>
<TooltipTrigger <TooltipTrigger
render={ render={
@@ -524,8 +526,11 @@ function StorageCard({
onRefresh: () => void; onRefresh: () => void;
}) { }) {
const { t } = useLingui(); const { t } = useLingui();
const cachedImageCount = imageCache.imageCount.toLocaleString();
const backupCount = backups.backupCount;
const lastBackupAt = backups.lastBackupAt;
return ( return (
<Card className="border-l-primary/30 border-l-2"> <Card className="border-s-primary/30 border-s-2">
<CardContent> <CardContent>
<div className="flex items-center justify-between gap-4"> <div className="flex items-center justify-between gap-4">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
@@ -560,7 +565,7 @@ function StorageCard({
{imageCache.enabled ? ( {imageCache.enabled ? (
<> <>
<p className="text-muted-foreground mt-1 text-xs"> <p className="text-muted-foreground mt-1 text-xs">
{t`${imageCache.imageCount.toLocaleString()} cached images`} {t`${cachedImageCount} cached images`}
</p> </p>
<p className="text-muted-foreground/50 mt-0.5 text-[10px] leading-relaxed"> <p className="text-muted-foreground/50 mt-0.5 text-[10px] leading-relaxed">
{Object.entries(imageCache.categories) {Object.entries(imageCache.categories)
@@ -582,17 +587,16 @@ function StorageCard({
<span className="text-muted-foreground/70 text-[11px] font-medium tracking-wider uppercase"> <span className="text-muted-foreground/70 text-[11px] font-medium tracking-wider uppercase">
<Trans>Backups</Trans> <Trans>Backups</Trans>
</span> </span>
{backups.backupCount > 0 && ( {backupCount > 0 && (
<span className="text-muted-foreground/50 font-mono text-[11px]"> <span className="text-muted-foreground/50 font-mono text-[11px]">
{formatBytes(backups.totalSizeBytes)} {formatBytes(backups.totalSizeBytes)}
</span> </span>
)} )}
</div> </div>
{backups.backupCount > 0 ? ( {backupCount > 0 ? (
<p className="text-muted-foreground mt-1 text-xs"> <p className="text-muted-foreground mt-1 text-xs">
<Trans> <Trans>
{backups.backupCount} backups · last{" "} {backupCount} backups · last <LiveTimeAgo date={lastBackupAt} fallback={t`unknown`} />
<LiveTimeAgo date={backups.lastBackupAt} fallback={t`unknown`} />
</Trans> </Trans>
</p> </p>
) : ( ) : (
+2 -2
View File
@@ -115,7 +115,7 @@ function QuickAddButton({ id, userStatus }: { id: string; userStatus?: TitleStat
return ( return (
<Tooltip> <Tooltip>
<TooltipTrigger <TooltipTrigger
className="absolute top-2 right-2 z-10 flex size-8 cursor-default items-center justify-center rounded-full bg-black/50 text-white backdrop-blur-sm" className="absolute end-2 top-2 z-10 flex size-8 cursor-default items-center justify-center rounded-full bg-black/50 text-white backdrop-blur-sm"
render={<div />} render={<div />}
> >
<StatusIcon className="size-4" /> <StatusIcon className="size-4" />
@@ -129,7 +129,7 @@ function QuickAddButton({ id, userStatus }: { id: string; userStatus?: TitleStat
<Tooltip> <Tooltip>
<TooltipTrigger <TooltipTrigger
onClick={handleClick} onClick={handleClick}
className="absolute top-2 right-2 z-10 flex size-8 items-center justify-center rounded-full bg-black/50 text-white opacity-60 backdrop-blur-sm transition-opacity hover:bg-black/70 focus-visible:opacity-100 sm:opacity-0 sm:group-hover:opacity-100" className="absolute end-2 top-2 z-10 flex size-8 items-center justify-center rounded-full bg-black/50 text-white opacity-60 backdrop-blur-sm transition-opacity hover:bg-black/70 focus-visible:opacity-100 sm:opacity-0 sm:group-hover:opacity-100"
render={<button type="button" />} render={<button type="button" />}
> >
{!quickAddMutation.isPending && <IconPlus className="size-4" />} {!quickAddMutation.isPending && <IconPlus className="size-4" />}
@@ -6,13 +6,18 @@ import { ScrollArea } from "@/components/ui/scroll-area";
import { thumbHashToUrl } from "@/lib/thumbhash"; import { thumbHashToUrl } from "@/lib/thumbhash";
import type { CastMember } from "@sofa/api/schemas"; import type { CastMember } from "@sofa/api/schemas";
function EpisodeCountLabel({ count }: { count: number }) {
const { t } = useLingui();
const suffix = count !== 1 ? "s" : "";
return <p className="text-muted-foreground/70 text-[10px]">{t`${count} ep${suffix}`}</p>;
}
interface CastCarouselProps { interface CastCarouselProps {
actors: CastMember[]; actors: CastMember[];
titleType: "movie" | "tv"; titleType: "movie" | "tv";
} }
export function CastCarousel({ actors, titleType }: CastCarouselProps) { export function CastCarousel({ actors, titleType }: CastCarouselProps) {
const { t } = useLingui();
return ( return (
<section className="space-y-4"> <section className="space-y-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -74,9 +79,7 @@ export function CastCarousel({ actors, titleType }: CastCarouselProps) {
</p> </p>
)} )}
{titleType === "tv" && member.episodeCount && ( {titleType === "tv" && member.episodeCount && (
<p className="text-muted-foreground/70 text-[10px]"> <EpisodeCountLabel count={member.episodeCount} />
{t`${member.episodeCount} ep${member.episodeCount !== 1 ? "s" : ""}`}
</p>
)} )}
</div> </div>
</Link> </Link>
@@ -161,7 +161,7 @@ export function TitleSeasons({
setOpenSeason(isOpen ? null : season.seasonNumber); setOpenSeason(isOpen ? null : season.seasonNumber);
} }
}} }}
className="group/season hover:bg-accent/50 flex w-full cursor-pointer items-center justify-between p-4 text-left transition-colors" className="group/season hover:bg-accent/50 flex w-full cursor-pointer items-center justify-between p-4 text-start transition-colors"
> >
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<span className="font-medium"> <span className="font-medium">
@@ -253,7 +253,7 @@ export function TitleSeasons({
className="h-full w-full object-cover" className="h-full w-full object-cover"
/> />
<div className="absolute inset-0 bg-gradient-to-t from-black/40 via-transparent to-transparent" /> <div className="absolute inset-0 bg-gradient-to-t from-black/40 via-transparent to-transparent" />
<span className="absolute bottom-2 left-3 font-mono text-[10px] text-white/70"> <span className="absolute start-3 bottom-2 font-mono text-[10px] text-white/70">
E{String(ep.episodeNumber).padStart(2, "0")} E{String(ep.episodeNumber).padStart(2, "0")}
</span> </span>
</div> </div>
@@ -65,8 +65,9 @@ export function useTitleActions() {
try { try {
await batchWatchMutation.mutateAsync({ episodeIds }); await batchWatchMutation.mutateAsync({ episodeIds });
await queryClient.invalidateQueries({ queryKey: userInfoKey }); await queryClient.invalidateQueries({ queryKey: userInfoKey });
const count = episodeIds.length;
toast.success( toast.success(
t`Caught up — marked ${episodeIds.length} ${plural(episodeIds.length, { one: "episode", other: "episodes" })} as watched`, t`Caught up — marked ${plural(count, { one: "# episode", other: "# episodes" })} as watched`,
); );
} catch { } catch {
setUserInfo((old) => ({ setUserInfo((old) => ({
@@ -112,7 +113,7 @@ export function useTitleActions() {
}); });
toast.success( toast.success(
ratingStars > 0 ratingStars > 0
? t`Rated ${ratingStars} ${plural(ratingStars, { one: "star", other: "stars" })}` ? t`Rated ${plural(ratingStars, { one: "# star", other: "# stars" })}`
: t`Rating removed`, : t`Rating removed`,
); );
} catch { } catch {
@@ -195,7 +196,7 @@ export function useTitleActions() {
if (previousUnwatched.length > 0) { if (previousUnwatched.length > 0) {
const count = previousUnwatched.length; const count = previousUnwatched.length;
toast.success(t`Watched S${seasonNum} E${epNum}`, { toast.success(t`Watched S${seasonNum} E${epNum}`, {
description: t`${count} earlier ${plural(count, { one: "episode", other: "episodes" })} unwatched`, description: t`${plural(count, { one: "# earlier episode", other: "# earlier episodes" })} unwatched`,
action: { action: {
label: t`Catch up`, label: t`Catch up`,
onClick: () => catchUp(previousUnwatched), onClick: () => catchUp(previousUnwatched),
@@ -263,11 +264,12 @@ export function useTitleActions() {
} }
} }
const seasonLabel = season.name ?? t`Season ${season.seasonNumber}`; const seasonNumber = season.seasonNumber;
const seasonLabel = season.name ?? t`Season ${seasonNumber}`;
if (previousUnwatched.length > 0) { if (previousUnwatched.length > 0) {
const count = previousUnwatched.length; const count = previousUnwatched.length;
toast.success(t`Watched all of ${seasonLabel}`, { toast.success(t`Watched all of ${seasonLabel}`, {
description: t`${count} earlier ${plural(count, { one: "episode", other: "episodes" })} unwatched`, description: t`${plural(count, { one: "# earlier episode", other: "# earlier episodes" })} unwatched`,
action: { action: {
label: t`Catch up`, label: t`Catch up`,
onClick: () => catchUp(previousUnwatched), onClick: () => catchUp(previousUnwatched),
@@ -302,7 +304,9 @@ export function useTitleActions() {
try { try {
await unwatchSeasonMutation.mutateAsync({ id: season.id }); await unwatchSeasonMutation.mutateAsync({ id: season.id });
toast.success(t`Unwatched all of ${season.name ?? t`Season ${season.seasonNumber}`}`); const seasonNumber = season.seasonNumber;
const seasonLabel = season.name ?? t`Season ${seasonNumber}`;
toast.success(t`Unwatched all of ${seasonLabel}`);
} catch { } catch {
setUserInfo((old) => ({ setUserInfo((old) => ({
...old, ...old,
+1 -1
View File
@@ -29,7 +29,7 @@ function AccordionTrigger({ className, children, ...props }: AccordionPrimitive.
<AccordionPrimitive.Trigger <AccordionPrimitive.Trigger
data-slot="accordion-trigger" data-slot="accordion-trigger"
className={cn( className={cn(
"group/accordion-trigger **:data-[slot=accordion-trigger-icon]:text-muted-foreground relative flex flex-1 items-start justify-between gap-6 border border-transparent p-2 text-left text-xs/relaxed font-medium transition-all outline-none hover:underline aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4", "group/accordion-trigger **:data-[slot=accordion-trigger-icon]:text-muted-foreground relative flex flex-1 items-start justify-between gap-6 border border-transparent p-2 text-start text-xs/relaxed font-medium transition-all outline-none hover:underline aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ms-auto **:data-[slot=accordion-trigger-icon]:size-4",
className, className,
)} )}
{...props} {...props}
+2 -2
View File
@@ -43,7 +43,7 @@ function AlertDialogContent({
data-slot="alert-dialog-content" data-slot="alert-dialog-content"
data-size={size} data-size={size}
className={cn( className={cn(
"data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 group/alert-dialog-content bg-background ring-foreground/10 data-closed:animate-out data-open:animate-in fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-3 rounded-xl p-4 ring-1 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-64 data-[size=default]:sm:max-w-sm", "data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 group/alert-dialog-content bg-background ring-foreground/10 data-closed:animate-out data-open:animate-in fixed start-1/2 top-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-3 rounded-xl p-4 ring-1 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-64 data-[size=default]:sm:max-w-sm rtl:translate-x-1/2",
className, className,
)} )}
{...props} {...props}
@@ -57,7 +57,7 @@ function AlertDialogHeader({ className, ...props }: React.ComponentProps<"div">)
<div <div
data-slot="alert-dialog-header" data-slot="alert-dialog-header"
className={cn( className={cn(
"grid grid-rows-[auto_1fr] place-items-center gap-1 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", "grid grid-rows-[auto_1fr] place-items-center gap-1 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-start sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
className, className,
)} )}
{...props} {...props}
+2 -6
View File
@@ -4,7 +4,7 @@ import type * as React from "react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
const alertVariants = cva( const alertVariants = cva(
"group/alert relative grid w-full gap-0.5 rounded-lg border px-2 py-1.5 text-left text-xs/relaxed has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-1.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-3.5", "group/alert relative grid w-full gap-0.5 rounded-lg border px-2 py-1.5 text-start text-xs/relaxed has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pe-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-1.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-3.5",
{ {
variants: { variants: {
variant: { variant: {
@@ -62,11 +62,7 @@ function AlertDescription({ className, ...props }: React.ComponentProps<"div">)
function AlertAction({ className, ...props }: React.ComponentProps<"div">) { function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
return ( return (
<div <div data-slot="alert-action" className={cn("absolute end-2 top-1.5", className)} {...props} />
data-slot="alert-action"
className={cn("absolute top-1.5 right-2", className)}
{...props}
/>
); );
} }
+1 -1
View File
@@ -51,7 +51,7 @@ function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
<span <span
data-slot="avatar-badge" data-slot="avatar-badge"
className={cn( className={cn(
"bg-primary text-primary-foreground ring-background absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-blend-color ring-2 select-none", "bg-primary text-primary-foreground ring-background absolute end-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-blend-color ring-2 select-none",
"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden", "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
+1 -1
View File
@@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
const badgeVariants = cva( const badgeVariants = cva(
"group/badge focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-[0.625rem] font-medium whitespace-nowrap transition-all focus-visible:ring-[3px] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:pointer-events-none [&>svg]:size-2.5!", "group/badge focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-[0.625rem] font-medium whitespace-nowrap transition-all focus-visible:ring-[3px] has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&>svg]:pointer-events-none [&>svg]:size-2.5!",
{ {
variants: { variants: {
variant: { variant: {
+2 -2
View File
@@ -6,12 +6,12 @@ import { Separator } from "@/components/ui/separator";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
const buttonGroupVariants = cva( const buttonGroupVariants = cva(
"flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1", "flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-e-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
{ {
variants: { variants: {
orientation: { orientation: {
horizontal: horizontal:
"*:data-slot:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-md! [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0", "*:data-slot:rounded-e-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-e-md! [&>[data-slot]~[data-slot]]:rounded-s-none [&>[data-slot]~[data-slot]]:border-s-0",
vertical: vertical:
"flex-col *:data-slot:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-md! [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0", "flex-col *:data-slot:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-md! [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0",
}, },
+4 -4
View File
@@ -21,10 +21,10 @@ const buttonVariants = cva(
}, },
size: { size: {
default: default:
"h-7 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5", "h-7 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&_svg:not([class*='size-'])]:size-3.5",
xs: "h-5 gap-1 rounded-sm px-2 text-[0.625rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-2.5", xs: "h-5 gap-1 rounded-sm px-2 text-[0.625rem] has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&_svg:not([class*='size-'])]:size-2.5",
sm: "h-6 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3", sm: "h-6 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&_svg:not([class*='size-'])]:size-3",
lg: "h-8 gap-1 px-2.5 text-xs/relaxed has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-4", lg: "h-8 gap-1 px-2.5 text-xs/relaxed has-data-[icon=inline-end]:pe-2 has-data-[icon=inline-start]:ps-2 [&_svg:not([class*='size-'])]:size-4",
icon: "size-7 [&_svg:not([class*='size-'])]:size-3.5", icon: "size-7 [&_svg:not([class*='size-'])]:size-3.5",
"icon-xs": "size-5 rounded-sm [&_svg:not([class*='size-'])]:size-2.5", "icon-xs": "size-5 rounded-sm [&_svg:not([class*='size-'])]:size-2.5",
"icon-sm": "size-6 [&_svg:not([class*='size-'])]:size-3", "icon-sm": "size-6 [&_svg:not([class*='size-'])]:size-3",
+4 -4
View File
@@ -102,7 +102,7 @@ function ComboboxContent({
data-slot="combobox-content" data-slot="combobox-content"
data-chips={!!anchor} data-chips={!!anchor}
className={cn( className={cn(
"data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 group/combobox-content bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in *:data-[slot=input-group]:bg-input/20 dark:bg-popover relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg shadow-md ring-1 duration-100 data-[chips=true]:min-w-(--anchor-width) *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-7 *:data-[slot=input-group]:border-none *:data-[slot=input-group]:shadow-none", "data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 group/combobox-content bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in *:data-[slot=input-group]:bg-input/20 dark:bg-popover relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg shadow-md ring-1 duration-100 data-[chips=true]:min-w-(--anchor-width) *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-7 *:data-[slot=input-group]:border-none *:data-[slot=input-group]:shadow-none",
className, className,
)} )}
{...props} {...props}
@@ -138,7 +138,7 @@ function ComboboxItem({ className, children, ...props }: ComboboxPrimitive.Item.
{children} {children}
<ComboboxPrimitive.ItemIndicator <ComboboxPrimitive.ItemIndicator
render={ render={
<span className="pointer-events-none absolute right-2 flex items-center justify-center" /> <span className="pointer-events-none absolute end-2 flex items-center justify-center" />
} }
> >
<IconCheck className="pointer-events-none" /> <IconCheck className="pointer-events-none" />
@@ -218,7 +218,7 @@ function ComboboxChip({
<ComboboxPrimitive.Chip <ComboboxPrimitive.Chip
data-slot="combobox-chip" data-slot="combobox-chip"
className={cn( className={cn(
"bg-muted-foreground/10 text-foreground flex h-[calc(--spacing(4.75))] w-fit items-center justify-center gap-1 rounded-[calc(var(--radius-sm)-2px)] px-1.5 text-xs/relaxed font-medium whitespace-nowrap has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0", "bg-muted-foreground/10 text-foreground flex h-[calc(--spacing(4.75))] w-fit items-center justify-center gap-1 rounded-[calc(var(--radius-sm)-2px)] px-1.5 text-xs/relaxed font-medium whitespace-nowrap has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pe-0",
className, className,
)} )}
{...props} {...props}
@@ -227,7 +227,7 @@ function ComboboxChip({
{showRemove && ( {showRemove && (
<ComboboxPrimitive.ChipRemove <ComboboxPrimitive.ChipRemove
render={<Button variant="ghost" size="icon-xs" />} render={<Button variant="ghost" size="icon-xs" />}
className="-ml-1 opacity-50 hover:opacity-100" className="-ms-1 opacity-50 hover:opacity-100"
data-slot="combobox-chip-remove" data-slot="combobox-chip-remove"
> >
<IconX className="pointer-events-none" /> <IconX className="pointer-events-none" />
+2 -2
View File
@@ -148,7 +148,7 @@ function CommandItem({
{...props} {...props}
> >
{children} {children}
<IconCheck className="ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" /> <IconCheck className="ms-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
</CommandPrimitive.Item> </CommandPrimitive.Item>
); );
} }
@@ -158,7 +158,7 @@ function CommandShortcut({ className, ...props }: React.ComponentProps<"span">)
<span <span
data-slot="command-shortcut" data-slot="command-shortcut"
className={cn( className={cn(
"text-muted-foreground group-data-selected/command-item:text-foreground ml-auto text-[0.625rem] tracking-widest", "text-muted-foreground group-data-selected/command-item:text-foreground ms-auto text-[0.625rem] tracking-widest",
className, className,
)} )}
{...props} {...props}
+12 -12
View File
@@ -26,7 +26,7 @@ function ContextMenuContent({
className, className,
align = "start", align = "start",
alignOffset = 4, alignOffset = 4,
side = "right", side = "inline-end",
sideOffset = 0, sideOffset = 0,
...props ...props
}: ContextMenuPrimitive.Popup.Props & }: ContextMenuPrimitive.Popup.Props &
@@ -43,7 +43,7 @@ function ContextMenuContent({
<ContextMenuPrimitive.Popup <ContextMenuPrimitive.Popup
data-slot="context-menu-content" data-slot="context-menu-content"
className={cn( className={cn(
"data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in z-50 max-h-(--available-height) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg p-1 shadow-md ring-1 duration-100 outline-none", "data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in z-50 max-h-(--available-height) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg p-1 shadow-md ring-1 duration-100 outline-none",
className, className,
)} )}
{...props} {...props}
@@ -68,7 +68,7 @@ function ContextMenuLabel({
<ContextMenuPrimitive.GroupLabel <ContextMenuPrimitive.GroupLabel
data-slot="context-menu-label" data-slot="context-menu-label"
data-inset={inset} data-inset={inset}
className={cn("text-muted-foreground px-2 py-1.5 text-xs data-inset:pl-7.5", className)} className={cn("text-muted-foreground px-2 py-1.5 text-xs data-inset:ps-7.5", className)}
{...props} {...props}
/> />
); );
@@ -89,7 +89,7 @@ function ContextMenuItem({
data-inset={inset} data-inset={inset}
data-variant={variant} data-variant={variant}
className={cn( className={cn(
"group/context-menu-item focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:*:[svg]:text-destructive relative flex min-h-7 cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs/relaxed outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", "group/context-menu-item focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:*:[svg]:text-destructive relative flex min-h-7 cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs/relaxed outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:ps-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
{...props} {...props}
@@ -114,13 +114,13 @@ function ContextMenuSubTrigger({
data-slot="context-menu-sub-trigger" data-slot="context-menu-sub-trigger"
data-inset={inset} data-inset={inset}
className={cn( className={cn(
"focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground flex min-h-7 cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs outline-hidden select-none data-inset:pl-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", "focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground flex min-h-7 cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs outline-hidden select-none data-inset:ps-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
{...props} {...props}
> >
{children} {children}
<IconChevronRight className="ml-auto" /> <IconChevronRight className="ms-auto" />
</ContextMenuPrimitive.SubmenuTrigger> </ContextMenuPrimitive.SubmenuTrigger>
); );
} }
@@ -130,7 +130,7 @@ function ContextMenuSubContent({ ...props }: React.ComponentProps<typeof Context
<ContextMenuContent <ContextMenuContent
data-slot="context-menu-sub-content" data-slot="context-menu-sub-content"
className="shadow-lg" className="shadow-lg"
side="right" side="inline-end"
{...props} {...props}
/> />
); );
@@ -150,13 +150,13 @@ function ContextMenuCheckboxItem({
data-slot="context-menu-checkbox-item" data-slot="context-menu-checkbox-item"
data-inset={inset} data-inset={inset}
className={cn( className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 ps-2 pe-8 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:ps-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
checked={checked} checked={checked}
{...props} {...props}
> >
<span className="pointer-events-none absolute right-2 flex items-center justify-center"> <span className="pointer-events-none absolute end-2 flex items-center justify-center">
<ContextMenuPrimitive.CheckboxItemIndicator> <ContextMenuPrimitive.CheckboxItemIndicator>
<IconCheck /> <IconCheck />
</ContextMenuPrimitive.CheckboxItemIndicator> </ContextMenuPrimitive.CheckboxItemIndicator>
@@ -183,12 +183,12 @@ function ContextMenuRadioItem({
data-slot="context-menu-radio-item" data-slot="context-menu-radio-item"
data-inset={inset} data-inset={inset}
className={cn( className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 ps-2 pe-8 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:ps-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
{...props} {...props}
> >
<span className="pointer-events-none absolute right-2 flex items-center justify-center"> <span className="pointer-events-none absolute end-2 flex items-center justify-center">
<ContextMenuPrimitive.RadioItemIndicator> <ContextMenuPrimitive.RadioItemIndicator>
<IconCheck /> <IconCheck />
</ContextMenuPrimitive.RadioItemIndicator> </ContextMenuPrimitive.RadioItemIndicator>
@@ -213,7 +213,7 @@ function ContextMenuShortcut({ className, ...props }: React.ComponentProps<"span
<span <span
data-slot="context-menu-shortcut" data-slot="context-menu-shortcut"
className={cn( className={cn(
"text-muted-foreground group-focus/context-menu-item:text-accent-foreground ml-auto text-[0.625rem] tracking-widest", "text-muted-foreground group-focus/context-menu-item:text-accent-foreground ms-auto text-[0.625rem] tracking-widest",
className, className,
)} )}
{...props} {...props}
+2 -2
View File
@@ -48,7 +48,7 @@ function DialogContent({
<DialogPrimitive.Popup <DialogPrimitive.Popup
data-slot="dialog-content" data-slot="dialog-content"
className={cn( className={cn(
"data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 data-closed:animate-out data-open:animate-in fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl p-4 text-xs/relaxed ring-1 duration-100 outline-none sm:max-w-sm", "data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 data-closed:animate-out data-open:animate-in fixed start-1/2 top-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl p-4 text-xs/relaxed ring-1 duration-100 outline-none sm:max-w-sm rtl:translate-x-1/2",
className, className,
)} )}
{...props} {...props}
@@ -57,7 +57,7 @@ function DialogContent({
{showCloseButton && ( {showCloseButton && (
<DialogPrimitive.Close <DialogPrimitive.Close
data-slot="dialog-close" data-slot="dialog-close"
render={<Button variant="ghost" className="absolute top-2 right-2" size="icon-sm" />} render={<Button variant="ghost" className="absolute end-2 top-2" size="icon-sm" />}
> >
<IconX /> <IconX />
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
+11 -11
View File
@@ -37,7 +37,7 @@ function DropdownMenuContent({
<MenuPrimitive.Popup <MenuPrimitive.Popup
data-slot="dropdown-menu-content" data-slot="dropdown-menu-content"
className={cn( className={cn(
"data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg p-1 shadow-md ring-1 duration-100 outline-none data-closed:overflow-hidden", "data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg p-1 shadow-md ring-1 duration-100 outline-none data-closed:overflow-hidden",
className, className,
)} )}
{...props} {...props}
@@ -62,7 +62,7 @@ function DropdownMenuLabel({
<MenuPrimitive.GroupLabel <MenuPrimitive.GroupLabel
data-slot="dropdown-menu-label" data-slot="dropdown-menu-label"
data-inset={inset} data-inset={inset}
className={cn("text-muted-foreground px-2 py-1.5 text-xs data-inset:pl-7.5", className)} className={cn("text-muted-foreground px-2 py-1.5 text-xs data-inset:ps-7.5", className)}
{...props} {...props}
/> />
); );
@@ -83,7 +83,7 @@ function DropdownMenuItem({
data-inset={inset} data-inset={inset}
data-variant={variant} data-variant={variant}
className={cn( className={cn(
"group/dropdown-menu-item focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:*:[svg]:text-destructive relative flex min-h-7 cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs/relaxed outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", "group/dropdown-menu-item focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:*:[svg]:text-destructive relative flex min-h-7 cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs/relaxed outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:ps-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
{...props} {...props}
@@ -108,13 +108,13 @@ function DropdownMenuSubTrigger({
data-slot="dropdown-menu-sub-trigger" data-slot="dropdown-menu-sub-trigger"
data-inset={inset} data-inset={inset}
className={cn( className={cn(
"focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-open:bg-accent data-popup-open:bg-accent data-open:text-accent-foreground data-popup-open:text-accent-foreground flex min-h-7 cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs outline-hidden select-none data-inset:pl-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", "focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-open:bg-accent data-popup-open:bg-accent data-open:text-accent-foreground data-popup-open:text-accent-foreground flex min-h-7 cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs outline-hidden select-none data-inset:ps-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
{...props} {...props}
> >
{children} {children}
<IconChevronRight className="ml-auto" /> <IconChevronRight className="ms-auto" />
</MenuPrimitive.SubmenuTrigger> </MenuPrimitive.SubmenuTrigger>
); );
} }
@@ -122,7 +122,7 @@ function DropdownMenuSubTrigger({
function DropdownMenuSubContent({ function DropdownMenuSubContent({
align = "start", align = "start",
alignOffset = -3, alignOffset = -3,
side = "right", side = "inline-end",
sideOffset = 0, sideOffset = 0,
className, className,
...props ...props
@@ -157,14 +157,14 @@ function DropdownMenuCheckboxItem({
data-slot="dropdown-menu-checkbox-item" data-slot="dropdown-menu-checkbox-item"
data-inset={inset} data-inset={inset}
className={cn( className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 ps-2 pe-8 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:ps-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
checked={checked} checked={checked}
{...props} {...props}
> >
<span <span
className="pointer-events-none absolute right-2 flex items-center justify-center" className="pointer-events-none absolute end-2 flex items-center justify-center"
data-slot="dropdown-menu-checkbox-item-indicator" data-slot="dropdown-menu-checkbox-item-indicator"
> >
<MenuPrimitive.CheckboxItemIndicator> <MenuPrimitive.CheckboxItemIndicator>
@@ -193,13 +193,13 @@ function DropdownMenuRadioItem({
data-slot="dropdown-menu-radio-item" data-slot="dropdown-menu-radio-item"
data-inset={inset} data-inset={inset}
className={cn( className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 ps-2 pe-8 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:ps-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
{...props} {...props}
> >
<span <span
className="pointer-events-none absolute right-2 flex items-center justify-center" className="pointer-events-none absolute end-2 flex items-center justify-center"
data-slot="dropdown-menu-radio-item-indicator" data-slot="dropdown-menu-radio-item-indicator"
> >
<MenuPrimitive.RadioItemIndicator> <MenuPrimitive.RadioItemIndicator>
@@ -226,7 +226,7 @@ function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<"spa
<span <span
data-slot="dropdown-menu-shortcut" data-slot="dropdown-menu-shortcut"
className={cn( className={cn(
"text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-[0.625rem] tracking-widest", "text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ms-auto text-[0.625rem] tracking-widest",
className, className,
)} )}
{...props} {...props}
+2 -2
View File
@@ -122,7 +122,7 @@ function FieldDescription({ className, ...props }: React.ComponentProps<"p">) {
<p <p
data-slot="field-description" data-slot="field-description"
className={cn( className={cn(
"text-muted-foreground text-left text-xs/relaxed leading-normal font-normal group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5", "text-muted-foreground text-start text-xs/relaxed leading-normal font-normal group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5",
"last:mt-0 nth-last-2:-mt-1", "last:mt-0 nth-last-2:-mt-1",
"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4", "[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4",
className, className,
@@ -186,7 +186,7 @@ function FieldError({
} }
return ( return (
<ul className="ml-4 flex list-disc flex-col gap-1"> <ul className="ms-4 flex list-disc flex-col gap-1">
{uniqueErrors.map((error, index) => error?.message && <li key={index}>{error.message}</li>)} {uniqueErrors.map((error, index) => error?.message && <li key={index}>{error.message}</li>)}
</ul> </ul>
); );
+1 -1
View File
@@ -31,7 +31,7 @@ function HoverCardContent({
<PreviewCardPrimitive.Popup <PreviewCardPrimitive.Popup
data-slot="hover-card-content" data-slot="hover-card-content"
className={cn( className={cn(
"data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in z-50 w-72 origin-(--transform-origin) rounded-lg p-2.5 text-xs/relaxed shadow-md ring-1 outline-hidden duration-100", "data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in z-50 w-72 origin-(--transform-origin) rounded-lg p-2.5 text-xs/relaxed shadow-md ring-1 outline-hidden duration-100",
className, className,
)} )}
{...props} {...props}
+3 -3
View File
@@ -12,7 +12,7 @@ function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
data-slot="input-group" data-slot="input-group"
role="group" role="group"
className={cn( className={cn(
"group/input-group border-input bg-input/20 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot=input-group-control]:focus-visible]:ring-ring/30 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:bg-input/30 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 relative flex h-7 w-full min-w-0 items-center rounded-md border transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-data-[align=block-end]:rounded-md has-data-[align=block-start]:rounded-md has-[[data-slot=input-group-control]:focus-visible]:ring-2 has-[[data-slot][aria-invalid=true]]:ring-2 has-[textarea]:rounded-md has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5", "group/input-group border-input bg-input/20 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot=input-group-control]:focus-visible]:ring-ring/30 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:bg-input/30 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 relative flex h-7 w-full min-w-0 items-center rounded-md border transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-data-[align=block-end]:rounded-md has-data-[align=block-start]:rounded-md has-[[data-slot=input-group-control]:focus-visible]:ring-2 has-[[data-slot][aria-invalid=true]]:ring-2 has-[textarea]:rounded-md has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pe-1.5 has-[>[data-align=inline-start]]:[&>input]:ps-1.5",
className, className,
)} )}
{...props} {...props}
@@ -25,8 +25,8 @@ const inputGroupAddonVariants = cva(
{ {
variants: { variants: {
align: { align: {
"inline-start": "order-first pl-2 has-[>button]:ml-[-0.275rem] has-[>kbd]:ml-[-0.275rem]", "inline-start": "order-first ps-2 has-[>button]:ms-[-0.275rem] has-[>kbd]:ms-[-0.275rem]",
"inline-end": "order-last pr-2 has-[>button]:mr-[-0.275rem] has-[>kbd]:mr-[-0.275rem]", "inline-end": "order-last pe-2 has-[>button]:me-[-0.275rem] has-[>kbd]:me-[-0.275rem]",
"block-start": "block-start":
"order-first w-full justify-start px-2 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2", "order-first w-full justify-start px-2 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
"block-end": "block-end":
+1 -1
View File
@@ -140,7 +140,7 @@ function ItemDescription({ className, ...props }: React.ComponentProps<"p">) {
<p <p
data-slot="item-description" data-slot="item-description"
className={cn( className={cn(
"text-muted-foreground [&>a:hover]:text-primary line-clamp-2 text-left text-xs/relaxed font-normal [&>a]:underline [&>a]:underline-offset-4", "text-muted-foreground [&>a:hover]:text-primary line-clamp-2 text-start text-xs/relaxed font-normal [&>a]:underline [&>a]:underline-offset-4",
className, className,
)} )}
{...props} {...props}
+9 -9
View File
@@ -69,7 +69,7 @@ function MenubarContent({
alignOffset={alignOffset} alignOffset={alignOffset}
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( className={cn(
"data-open:fade-in-0 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 bg-popover text-popover-foreground ring-foreground/10 data-open:animate-in min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100", "data-open:fade-in-0 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 bg-popover text-popover-foreground ring-foreground/10 data-open:animate-in min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100",
className, className,
)} )}
{...props} {...props}
@@ -89,7 +89,7 @@ function MenubarItem({
data-inset={inset} data-inset={inset}
data-variant={variant} data-variant={variant}
className={cn( className={cn(
"group/menubar-item focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:*:[svg]:text-destructive! min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed data-disabled:opacity-50 data-inset:pl-7.5 [&_svg:not([class*='size-'])]:size-3.5", "group/menubar-item focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:*:[svg]:text-destructive! min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed data-disabled:opacity-50 data-inset:ps-7.5 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
{...props} {...props}
@@ -111,13 +111,13 @@ function MenubarCheckboxItem({
data-slot="menubar-checkbox-item" data-slot="menubar-checkbox-item"
data-inset={inset} data-inset={inset}
className={cn( className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 pr-2 pl-7.5 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0", "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 ps-7.5 pe-2 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:ps-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0",
className, className,
)} )}
checked={checked} checked={checked}
{...props} {...props}
> >
<span className="pointer-events-none absolute left-2 flex size-4 items-center justify-center [&_svg:not([class*='size-'])]:size-4"> <span className="pointer-events-none absolute start-2 flex size-4 items-center justify-center [&_svg:not([class*='size-'])]:size-4">
<MenuPrimitive.CheckboxItemIndicator> <MenuPrimitive.CheckboxItemIndicator>
<IconCheck /> <IconCheck />
</MenuPrimitive.CheckboxItemIndicator> </MenuPrimitive.CheckboxItemIndicator>
@@ -144,12 +144,12 @@ function MenubarRadioItem({
data-slot="menubar-radio-item" data-slot="menubar-radio-item"
data-inset={inset} data-inset={inset}
className={cn( className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 pr-2 pl-7.5 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md py-1.5 ps-7.5 pe-2 text-xs outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:ps-7.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
{...props} {...props}
> >
<span className="pointer-events-none absolute left-2 flex size-4 items-center justify-center [&_svg:not([class*='size-'])]:size-4"> <span className="pointer-events-none absolute start-2 flex size-4 items-center justify-center [&_svg:not([class*='size-'])]:size-4">
<MenuPrimitive.RadioItemIndicator> <MenuPrimitive.RadioItemIndicator>
<IconCheck /> <IconCheck />
</MenuPrimitive.RadioItemIndicator> </MenuPrimitive.RadioItemIndicator>
@@ -170,7 +170,7 @@ function MenubarLabel({
<DropdownMenuLabel <DropdownMenuLabel
data-slot="menubar-label" data-slot="menubar-label"
data-inset={inset} data-inset={inset}
className={cn("text-muted-foreground px-2 py-1.5 text-xs data-inset:pl-7.5", className)} className={cn("text-muted-foreground px-2 py-1.5 text-xs data-inset:ps-7.5", className)}
{...props} {...props}
/> />
); );
@@ -197,7 +197,7 @@ function MenubarShortcut({
<DropdownMenuShortcut <DropdownMenuShortcut
data-slot="menubar-shortcut" data-slot="menubar-shortcut"
className={cn( className={cn(
"text-muted-foreground group-focus/menubar-item:text-accent-foreground ml-auto text-[0.625rem] tracking-widest", "text-muted-foreground group-focus/menubar-item:text-accent-foreground ms-auto text-[0.625rem] tracking-widest",
className, className,
)} )}
{...props} {...props}
@@ -221,7 +221,7 @@ function MenubarSubTrigger({
data-slot="menubar-sub-trigger" data-slot="menubar-sub-trigger"
data-inset={inset} data-inset={inset}
className={cn( className={cn(
"focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs data-inset:pl-7.5 [&_svg:not([class*='size-'])]:size-3.5", "focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs data-inset:ps-7.5 [&_svg:not([class*='size-'])]:size-3.5",
className, className,
)} )}
{...props} {...props}
@@ -68,7 +68,7 @@ function NavigationMenuTrigger({
> >
{children}{" "} {children}{" "}
<IconChevronDown <IconChevronDown
className="relative top-px ml-1 size-3 transition duration-300 group-data-open/navigation-menu-trigger:rotate-180 group-data-popup-open/navigation-menu-trigger:rotate-180" className="relative top-px ms-1 size-3 transition duration-300 group-data-open/navigation-menu-trigger:rotate-180 group-data-popup-open/navigation-menu-trigger:rotate-180"
aria-hidden="true" aria-hidden="true"
/> />
</NavigationMenuPrimitive.Trigger> </NavigationMenuPrimitive.Trigger>
@@ -80,7 +80,7 @@ function NavigationMenuContent({ className, ...props }: NavigationMenuPrimitive.
<NavigationMenuPrimitive.Content <NavigationMenuPrimitive.Content
data-slot="navigation-menu-content" data-slot="navigation-menu-content"
className={cn( className={cn(
"data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 group-data-[viewport=false]/navigation-menu:data-closed:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-open:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-open:fade-in-0 group-data-[viewport=false]/navigation-menu:data-closed:fade-out-0 data-ending-style:data-activation-direction=left:translate-x-[50%] data-ending-style:data-activation-direction=right:translate-x-[-50%] data-starting-style:data-activation-direction=left:translate-x-[-50%] data-starting-style:data-activation-direction=right:translate-x-[50%] data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:ring-foreground/10 group-data-[viewport=false]/navigation-menu:data-closed:animate-out group-data-[viewport=false]/navigation-menu:data-open:animate-in h-full w-auto p-1.5 transition-[opacity,transform,translate] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] group-data-[viewport=false]/navigation-menu:rounded-xl group-data-[viewport=false]/navigation-menu:shadow-md group-data-[viewport=false]/navigation-menu:ring-1 group-data-[viewport=false]/navigation-menu:duration-300 data-ending-style:opacity-0 data-starting-style:opacity-0 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none", "data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 group-data-[viewport=false]/navigation-menu:data-closed:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-open:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-open:fade-in-0 group-data-[viewport=false]/navigation-menu:data-closed:fade-out-0 data-ending-style:data-activation-direction=left:translate-x-[50%] rtl:data-ending-style:data-activation-direction=left:-translate-x-[50%] data-ending-style:data-activation-direction=right:translate-x-[-50%] rtl:data-ending-style:data-activation-direction=right:-translate-x-[-50%] data-starting-style:data-activation-direction=left:translate-x-[-50%] rtl:data-starting-style:data-activation-direction=left:-translate-x-[-50%] data-starting-style:data-activation-direction=right:translate-x-[50%] rtl:data-starting-style:data-activation-direction=right:-translate-x-[50%] data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:ring-foreground/10 group-data-[viewport=false]/navigation-menu:data-closed:animate-out group-data-[viewport=false]/navigation-menu:data-open:animate-in h-full w-auto p-1.5 transition-[opacity,transform,translate] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] group-data-[viewport=false]/navigation-menu:rounded-xl group-data-[viewport=false]/navigation-menu:shadow-md group-data-[viewport=false]/navigation-menu:ring-1 group-data-[viewport=false]/navigation-menu:duration-300 data-ending-style:opacity-0 data-starting-style:opacity-0 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none",
className, className,
)} )}
{...props} {...props}
@@ -104,7 +104,7 @@ function NavigationMenuPositioner({
align={align} align={align}
alignOffset={alignOffset} alignOffset={alignOffset}
className={cn( className={cn(
"isolate z-50 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] data-instant:transition-none data-[side=bottom]:before:top-[-10px] data-[side=bottom]:before:right-0 data-[side=bottom]:before:left-0", "isolate z-50 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] data-instant:transition-none data-[side=bottom]:before:start-0 data-[side=bottom]:before:end-0 data-[side=bottom]:before:top-[-10px]",
className, className,
)} )}
{...props} {...props}
@@ -143,7 +143,7 @@ function NavigationMenuIndicator({
)} )}
{...props} {...props}
> >
<div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" /> <div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-ss-sm shadow-md" />
</NavigationMenuPrimitive.Icon> </NavigationMenuPrimitive.Icon>
); );
} }
+2 -2
View File
@@ -62,7 +62,7 @@ function PaginationPrevious({
<PaginationLink <PaginationLink
aria-label="Go to previous page" aria-label="Go to previous page"
size="default" size="default"
className={cn("pl-2!", className)} className={cn("ps-2!", className)}
{...props} {...props}
> >
<IconChevronLeft data-icon="inline-start" /> <IconChevronLeft data-icon="inline-start" />
@@ -80,7 +80,7 @@ function PaginationNext({
<PaginationLink <PaginationLink
aria-label="Go to next page" aria-label="Go to next page"
size="default" size="default"
className={cn("pr-2!", className)} className={cn("pe-2!", className)}
{...props} {...props}
> >
<span className="hidden sm:block">{text}</span> <span className="hidden sm:block">{text}</span>
+1 -1
View File
@@ -32,7 +32,7 @@ function PopoverContent({
<PopoverPrimitive.Popup <PopoverPrimitive.Popup
data-slot="popover-content" data-slot="popover-content"
className={cn( className={cn(
"data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in z-50 flex w-72 origin-(--transform-origin) flex-col gap-4 rounded-lg p-2.5 text-xs shadow-md ring-1 outline-hidden duration-100", "data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in z-50 flex w-72 origin-(--transform-origin) flex-col gap-4 rounded-lg p-2.5 text-xs shadow-md ring-1 outline-hidden duration-100",
className, className,
)} )}
{...props} {...props}
+1 -1
View File
@@ -54,7 +54,7 @@ function ProgressLabel({ className, ...props }: ProgressPrimitive.Label.Props) {
function ProgressValue({ className, ...props }: ProgressPrimitive.Value.Props) { function ProgressValue({ className, ...props }: ProgressPrimitive.Value.Props) {
return ( return (
<ProgressPrimitive.Value <ProgressPrimitive.Value
className={cn("text-muted-foreground ml-auto text-xs/relaxed tabular-nums", className)} className={cn("text-muted-foreground ms-auto text-xs/relaxed tabular-nums", className)}
data-slot="progress-value" data-slot="progress-value"
{...props} {...props}
/> />
+1 -1
View File
@@ -27,7 +27,7 @@ function RadioGroupItem({ className, ...props }: RadioPrimitive.Root.Props) {
data-slot="radio-group-indicator" data-slot="radio-group-indicator"
className="flex size-4 items-center justify-center" className="flex size-4 items-center justify-center"
> >
<span className="bg-primary-foreground absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full" /> <span className="bg-primary-foreground absolute start-1/2 top-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full rtl:translate-x-1/2" />
</RadioPrimitive.Indicator> </RadioPrimitive.Indicator>
</RadioPrimitive.Root> </RadioPrimitive.Root>
); );
+1 -1
View File
@@ -36,7 +36,7 @@ function ScrollArea({
"no-scrollbar focus-visible:ring-ring/50 flex-1 rounded-[inherit] outline-none focus-visible:ring-[3px] focus-visible:outline-1 data-has-overflow-x:overscroll-x-contain", "no-scrollbar focus-visible:ring-ring/50 flex-1 rounded-[inherit] outline-none focus-visible:ring-[3px] focus-visible:outline-1 data-has-overflow-x:overscroll-x-contain",
scrollFade && scrollFade &&
"mask-t-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-y-start)))] mask-r-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-x-end)))] mask-b-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-y-end)))] mask-l-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-x-start)))] [--fade-size:1.5rem]", "mask-t-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-y-start)))] mask-r-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-x-end)))] mask-b-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-y-end)))] mask-l-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-x-start)))] [--fade-size:1.5rem]",
scrollbarGutter && "data-has-overflow-x:pb-2.5 data-has-overflow-y:pr-2.5", scrollbarGutter && "data-has-overflow-x:pb-2.5 data-has-overflow-y:pe-2.5",
)} )}
> >
<ScrollAreaPrimitive.Content data-slot="scroll-area-content" ref={contentRef}> <ScrollAreaPrimitive.Content data-slot="scroll-area-content" ref={contentRef}>
+3 -3
View File
@@ -20,7 +20,7 @@ function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
return ( return (
<SelectPrimitive.Value <SelectPrimitive.Value
data-slot="select-value" data-slot="select-value"
className={cn("flex flex-1 text-left", className)} className={cn("flex flex-1 text-start", className)}
{...props} {...props}
/> />
); );
@@ -80,7 +80,7 @@ function SelectContent({
data-slot="select-content" data-slot="select-content"
data-align-trigger={alignItemWithTrigger} data-align-trigger={alignItemWithTrigger}
className={cn( className={cn(
"data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg shadow-md ring-1 duration-100 data-[align-trigger=true]:animate-none", "data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 bg-popover text-popover-foreground ring-foreground/10 data-closed:animate-out data-open:animate-in relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg shadow-md ring-1 duration-100 data-[align-trigger=true]:animate-none",
className, className,
)} )}
{...props} {...props}
@@ -119,7 +119,7 @@ function SelectItem({ className, children, ...props }: SelectPrimitive.Item.Prop
</SelectPrimitive.ItemText> </SelectPrimitive.ItemText>
<SelectPrimitive.ItemIndicator <SelectPrimitive.ItemIndicator
render={ render={
<span className="pointer-events-none absolute right-2 flex items-center justify-center" /> <span className="pointer-events-none absolute end-2 flex items-center justify-center" />
} }
> >
<IconCheck className="pointer-events-none" /> <IconCheck className="pointer-events-none" />
+2 -2
View File
@@ -51,7 +51,7 @@ function SheetContent({
data-slot="sheet-content" data-slot="sheet-content"
data-side={side} data-side={side}
className={cn( className={cn(
"data-[side=right]:data-closed:slide-out-to-right-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=top]:data-closed:slide-out-to-top-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:fade-out-0 data-open:fade-in-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=bottom]:data-open:slide-in-from-bottom-10 bg-background data-closed:animate-out data-open:animate-in fixed z-50 flex flex-col bg-clip-padding text-xs/relaxed shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm", "data-[side=right]:data-closed:slide-out-to-right-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=top]:data-closed:slide-out-to-top-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:fade-out-0 data-open:fade-in-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=bottom]:data-open:slide-in-from-bottom-10 bg-background data-closed:animate-out data-open:animate-in fixed z-50 flex flex-col bg-clip-padding text-xs/relaxed shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-e data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-s data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm",
className, className,
)} )}
{...props} {...props}
@@ -60,7 +60,7 @@ function SheetContent({
{showCloseButton && ( {showCloseButton && (
<SheetPrimitive.Close <SheetPrimitive.Close
data-slot="sheet-close" data-slot="sheet-close"
render={<Button variant="ghost" className="absolute top-4 right-4" size="icon-sm" />} render={<Button variant="ghost" className="absolute end-4 top-4" size="icon-sm" />}
> >
<IconX /> <IconX />
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
+13 -13
View File
@@ -225,7 +225,7 @@ function Sidebar({
// Adjust the padding for floating and inset variants. // Adjust the padding for floating and inset variants.
variant === "floating" || variant === "inset" variant === "floating" || variant === "inset"
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l", : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-e group-data-[side=right]:border-s",
className, className,
)} )}
{...props} {...props}
@@ -277,11 +277,11 @@ function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
title="Toggle Sidebar" title="Toggle Sidebar"
className={cn( className={cn(
"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2", "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2",
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize", "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize rtl:in-data-[side=left]:cursor-e-resize rtl:in-data-[side=right]:cursor-w-resize",
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize rtl:[[data-side=left][data-state=collapsed]_&]:cursor-w-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize rtl:[[data-side=right][data-state=collapsed]_&]:cursor-e-resize",
"hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full", "hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:start-full rtl:group-data-[collapsible=offcanvas]:-translate-x-0",
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", "[[data-side=left][data-collapsible=offcanvas]_&]:-end-2",
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", "[[data-side=right][data-collapsible=offcanvas]_&]:-start-2",
className, className,
)} )}
{...props} {...props}
@@ -294,7 +294,7 @@ function SidebarInset({ className, ...props }: React.ComponentProps<"main">) {
<main <main
data-slot="sidebar-inset" data-slot="sidebar-inset"
className={cn( className={cn(
"bg-background relative flex w-full flex-1 flex-col md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2", "bg-background relative flex w-full flex-1 flex-col md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ms-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2",
className, className,
)} )}
{...props} {...props}
@@ -405,7 +405,7 @@ function SidebarGroupAction({
props: mergeProps<"button">( props: mergeProps<"button">(
{ {
className: cn( className: cn(
"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0", "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute end-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
className, className,
), ),
}, },
@@ -453,7 +453,7 @@ function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) {
} }
const sidebarMenuButtonVariants = cva( const sidebarMenuButtonVariants = cva(
"peer/menu-button group/menu-button ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground flex w-full items-center gap-2 overflow-hidden rounded-[calc(var(--radius-sm)+2px)] p-2 text-left text-xs outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-active:font-medium [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate", "peer/menu-button group/menu-button ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground flex w-full items-center gap-2 overflow-hidden rounded-[calc(var(--radius-sm)+2px)] p-2 text-start text-xs outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pe-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-active:font-medium [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate",
{ {
variants: { variants: {
variant: { variant: {
@@ -542,7 +542,7 @@ function SidebarMenuAction({
props: mergeProps<"button">( props: mergeProps<"button">(
{ {
className: cn( className: cn(
"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-[calc(var(--radius-sm)-2px)] p-0 outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0", "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute end-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-[calc(var(--radius-sm)-2px)] p-0 outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
showOnHover && showOnHover &&
"peer-data-active/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 aria-expanded:opacity-100 md:opacity-0", "peer-data-active/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 aria-expanded:opacity-100 md:opacity-0",
className, className,
@@ -564,7 +564,7 @@ function SidebarMenuBadge({ className, ...props }: React.ComponentProps<"div">)
data-slot="sidebar-menu-badge" data-slot="sidebar-menu-badge"
data-sidebar="menu-badge" data-sidebar="menu-badge"
className={cn( className={cn(
"text-sidebar-foreground peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-[calc(var(--radius-sm)-2px)] px-1 text-xs font-medium tabular-nums select-none group-data-[collapsible=icon]:hidden peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1", "text-sidebar-foreground peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground pointer-events-none absolute end-1 flex h-5 min-w-5 items-center justify-center rounded-[calc(var(--radius-sm)-2px)] px-1 text-xs font-medium tabular-nums select-none group-data-[collapsible=icon]:hidden peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1",
className, className,
)} )}
{...props} {...props}
@@ -611,7 +611,7 @@ function SidebarMenuSub({ className, ...props }: React.ComponentProps<"ul">) {
data-slot="sidebar-menu-sub" data-slot="sidebar-menu-sub"
data-sidebar="menu-sub" data-sidebar="menu-sub"
className={cn( className={cn(
"border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5 group-data-[collapsible=icon]:hidden", "border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-s px-2.5 py-0.5 group-data-[collapsible=icon]:hidden rtl:-translate-x-px",
className, className,
)} )}
{...props} {...props}
@@ -646,7 +646,7 @@ function SidebarMenuSubButton({
props: mergeProps<"a">( props: mergeProps<"a">(
{ {
className: cn( className: cn(
"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden group-data-[collapsible=icon]:hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-xs data-[size=sm]:text-xs [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden group-data-[collapsible=icon]:hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-xs data-[size=sm]:text-xs rtl:translate-x-px [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
className, className,
), ),
}, },
+1 -1
View File
@@ -21,7 +21,7 @@ function Switch({
> >
<SwitchPrimitive.Thumb <SwitchPrimitive.Thumb
data-slot="switch-thumb" data-slot="switch-thumb"
className="bg-background dark:data-checked:bg-primary-foreground dark:data-unchecked:bg-foreground pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-3.5 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-1px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-1px)] group-data-[size=default]/switch:data-unchecked:translate-x-px group-data-[size=sm]/switch:data-unchecked:translate-x-px" className="bg-background dark:data-checked:bg-primary-foreground dark:data-unchecked:bg-foreground pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-3.5 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-1px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-1px)] group-data-[size=default]/switch:data-unchecked:translate-x-px group-data-[size=sm]/switch:data-unchecked:translate-x-px rtl:group-data-[size=default]/switch:data-checked:-translate-x-[calc(100%-1px)] rtl:group-data-[size=sm]/switch:data-checked:-translate-x-[calc(100%-1px)] rtl:group-data-[size=default]/switch:data-unchecked:-translate-x-px rtl:group-data-[size=sm]/switch:data-unchecked:-translate-x-px"
/> />
</SwitchPrimitive.Root> </SwitchPrimitive.Root>
); );
+2 -2
View File
@@ -56,7 +56,7 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
<th <th
data-slot="table-head" data-slot="table-head"
className={cn( className={cn(
"text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0", "text-foreground h-10 px-2 text-start align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pe-0",
className, className,
)} )}
{...props} {...props}
@@ -68,7 +68,7 @@ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
return ( return (
<td <td
data-slot="table-cell" data-slot="table-cell"
className={cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0", className)} className={cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pe-0", className)}
{...props} {...props}
/> />
); );
+1 -1
View File
@@ -52,7 +52,7 @@ function TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {
"text-foreground/60 hover:text-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-ring/50 dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-xs font-medium whitespace-nowrap transition-colors group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start group-data-vertical/tabs:py-[calc(--spacing(1.25))] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", "text-foreground/60 hover:text-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-ring/50 dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-xs font-medium whitespace-nowrap transition-colors group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start group-data-vertical/tabs:py-[calc(--spacing(1.25))] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent", "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent",
"data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground", "data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground",
"after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100", "after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-end-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
className, className,
)} )}
{...props} {...props}
+1 -1
View File
@@ -70,7 +70,7 @@ function ToggleGroupItem({
data-size={context.size || size} data-size={context.size || size}
data-spacing={context.spacing} data-spacing={context.spacing}
className={cn( className={cn(
"shrink-0 group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 focus:z-10 focus-visible:z-10 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-md group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-md group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-md group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-md group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t", "shrink-0 group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 focus:z-10 focus-visible:z-10 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-s-md group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-md group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-e-md group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-md group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-s-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-s group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t",
toggleVariants({ toggleVariants({
variant: context.variant || variant, variant: context.variant || variant,
size: context.size || size, size: context.size || size,
+2 -2
View File
@@ -36,13 +36,13 @@ function TooltipContent({
<TooltipPrimitive.Popup <TooltipPrimitive.Popup
data-slot="tooltip-content" data-slot="tooltip-content"
className={cn( className={cn(
"data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 bg-foreground text-background data-[state=delayed-open]:animate-in data-closed:animate-out data-open:animate-in z-50 w-fit max-w-xs origin-(--transform-origin) rounded-md px-3 py-1.5 text-xs **:data-[slot=kbd]:rounded-md", "data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-end-2 data-[side=inline-end]:slide-in-from-start-2 bg-foreground text-background data-[state=delayed-open]:animate-in data-closed:animate-out data-open:animate-in z-50 w-fit max-w-xs origin-(--transform-origin) rounded-md px-3 py-1.5 text-xs **:data-[slot=kbd]:rounded-md",
className, className,
)} )}
{...props} {...props}
> >
{children} {children}
<TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" /> <TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] data-[side=bottom]:top-1 data-[side=inline-end]:-start-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:-end-1 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" />
</TooltipPrimitive.Popup> </TooltipPrimitive.Popup>
</TooltipPrimitive.Positioner> </TooltipPrimitive.Positioner>
</TooltipPrimitive.Portal> </TooltipPrimitive.Portal>
+4 -2
View File
@@ -15,8 +15,10 @@ export function UpdateToast({ data }: { data: UpdateCheckResult | null }) {
if (dismissedVersion === data.latestVersion) return; if (dismissedVersion === data.latestVersion) return;
setDismissedVersion(data.latestVersion); setDismissedVersion(data.latestVersion);
toast.info(t`Sofa v${data.latestVersion} is available`, { const latestVersion = data.latestVersion;
description: t`You're running v${data.currentVersion}.`, const currentVersion = data.currentVersion;
toast.info(t`Sofa v${latestVersion} is available`, {
description: t`You're running v${currentVersion}.`,
duration: 15_000, duration: 15_000,
action: data.releaseUrl action: data.releaseUrl
? { ? {
+3 -1
View File
@@ -1,4 +1,4 @@
import { activateLocale, SUPPORTED_LOCALES, type SupportedLocale } from "@sofa/i18n"; import { activateLocale, getDirection, SUPPORTED_LOCALES, type SupportedLocale } from "@sofa/i18n";
const LOCALE_STORAGE_KEY = "sofa:locale"; const LOCALE_STORAGE_KEY = "sofa:locale";
@@ -17,6 +17,7 @@ export function getPersistedLocale(): SupportedLocale {
export function setPersistedLocale(locale: SupportedLocale): void { export function setPersistedLocale(locale: SupportedLocale): void {
localStorage.setItem(LOCALE_STORAGE_KEY, locale); localStorage.setItem(LOCALE_STORAGE_KEY, locale);
document.documentElement.lang = locale; document.documentElement.lang = locale;
document.documentElement.dir = getDirection(locale);
} }
let initialized = false; let initialized = false;
@@ -26,6 +27,7 @@ export async function initLocale(): Promise<void> {
initialized = true; initialized = true;
const locale = getPersistedLocale(); const locale = getPersistedLocale();
document.documentElement.lang = locale; document.documentElement.lang = locale;
document.documentElement.dir = getDirection(locale);
if (locale !== "en") { if (locale !== "en") {
await activateLocale(locale); await activateLocale(locale);
} }
+21 -9
View File
@@ -1,5 +1,5 @@
import { I18nProvider } from "@lingui/react"; import { I18nProvider } from "@lingui/react";
import { Trans } from "@lingui/react/macro"; import { Trans, useLingui } from "@lingui/react/macro";
import { IconAlertTriangle } from "@tabler/icons-react"; import { IconAlertTriangle } from "@tabler/icons-react";
import { TanStackDevtools } from "@tanstack/react-devtools"; import { TanStackDevtools } from "@tanstack/react-devtools";
import type { QueryClient } from "@tanstack/react-query"; import type { QueryClient } from "@tanstack/react-query";
@@ -11,11 +11,12 @@ import { MotionConfig } from "motion/react";
import { NavigationProgress } from "@/components/navigation-progress"; import { NavigationProgress } from "@/components/navigation-progress";
import { SofaLogo } from "@/components/sofa-logo"; import { SofaLogo } from "@/components/sofa-logo";
import { DirectionProvider } from "@/components/ui/direction";
import { Toaster } from "@/components/ui/sonner"; import { Toaster } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip"; import { TooltipProvider } from "@/components/ui/tooltip";
import { initLocale } from "@/lib/i18n"; import { initLocale } from "@/lib/i18n";
import type { orpc } from "@/lib/orpc/client"; import type { orpc } from "@/lib/orpc/client";
import { i18n } from "@sofa/i18n"; import { getDirection, i18n } from "@sofa/i18n";
import "@/styles/globals.css"; import "@/styles/globals.css";
@@ -53,13 +54,7 @@ function RootComponent() {
<HeadContent /> <HeadContent />
<StoreProvider> <StoreProvider>
<I18nProvider i18n={i18n}> <I18nProvider i18n={i18n}>
<MotionConfig reducedMotion="user"> <AppShell />
<NavigationProgress />
<TooltipProvider>
<Outlet />
</TooltipProvider>
<Toaster position="bottom-right" />
</MotionConfig>
</I18nProvider> </I18nProvider>
</StoreProvider> </StoreProvider>
<TanStackDevtools <TanStackDevtools
@@ -78,6 +73,23 @@ function RootComponent() {
); );
} }
function AppShell() {
const { i18n: linguiI18n } = useLingui();
const direction = getDirection(linguiI18n.locale);
return (
<DirectionProvider direction={direction}>
<MotionConfig reducedMotion="user">
<NavigationProgress />
<TooltipProvider>
<Outlet />
</TooltipProvider>
<Toaster position={direction === "rtl" ? "bottom-left" : "bottom-right"} />
</MotionConfig>
</DirectionProvider>
);
}
function GlobalNotFound() { function GlobalNotFound() {
return ( return (
<div className="relative flex min-h-screen flex-col items-center justify-center overflow-hidden px-6"> <div className="relative flex min-h-screen flex-col items-center justify-center overflow-hidden px-6">
+1 -1
View File
@@ -41,7 +41,7 @@ function AppLayout() {
<div className="bg-primary/3 pointer-events-none fixed top-1/4 left-1/2 h-[600px] w-[800px] -translate-x-1/2 -translate-y-1/2 rounded-full blur-[200px]" /> <div className="bg-primary/3 pointer-events-none fixed top-1/4 left-1/2 h-[600px] w-[800px] -translate-x-1/2 -translate-y-1/2 rounded-full blur-[200px]" />
<main <main
id="main-content" id="main-content"
className="relative mx-auto max-w-6xl py-6 pr-[max(1rem,env(safe-area-inset-right))] pl-[max(1rem,env(safe-area-inset-left))] sm:pr-[max(1.5rem,env(safe-area-inset-right))] sm:pl-[max(1.5rem,env(safe-area-inset-left))]" className="relative mx-auto max-w-6xl py-6 ps-[max(1rem,env(safe-area-inset-left))] pe-[max(1rem,env(safe-area-inset-right))] sm:ps-[max(1.5rem,env(safe-area-inset-left))] sm:pe-[max(1.5rem,env(safe-area-inset-right))]"
> >
<Outlet /> <Outlet />
</main> </main>
+6 -6
View File
@@ -173,10 +173,10 @@ function SettingsPage() {
</span> </span>
</div> </div>
<div className="space-y-3"> <div className="space-y-3">
<Card className="border-l-primary/30 border-l-2"> <Card className="border-s-primary/30 border-s-2">
<RegistrationSection /> <RegistrationSection />
</Card> </Card>
<Card className="border-l-primary/30 border-l-2"> <Card className="border-s-primary/30 border-s-2">
<UpdateCheckSection /> <UpdateCheckSection />
</Card> </Card>
</div> </div>
@@ -196,13 +196,13 @@ function SettingsPage() {
</span> </span>
</div> </div>
<div className="space-y-3"> <div className="space-y-3">
<Card className="border-l-primary/30 border-l-2"> <Card className="border-s-primary/30 border-s-2">
<BackupSection /> <BackupSection />
</Card> </Card>
<Card className="border-l-primary/30 border-l-2"> <Card className="border-s-primary/30 border-s-2">
<BackupScheduleSection /> <BackupScheduleSection />
</Card> </Card>
<Card className="border-l-primary/30 border-l-2"> <Card className="border-s-primary/30 border-s-2">
<BackupRestoreSection /> <BackupRestoreSection />
</Card> </Card>
</div> </div>
@@ -221,7 +221,7 @@ function SettingsPage() {
Admin only Admin only
</span> </span>
</div> </div>
<Card className="border-l-primary/30 border-l-2"> <Card className="border-s-primary/30 border-s-2">
<CacheSection /> <CacheSection />
</Card> </Card>
</div> </div>
+1 -1
View File
@@ -14,6 +14,6 @@
}, },
"types": ["bun"] "types": ["bun"]
}, },
"include": ["src", "vite.config.ts"], "include": ["src", "vite.config.ts", "../../packages/i18n/src/po.d.ts"],
"exclude": ["node_modules", "dist"] "exclude": ["node_modules", "dist"]
} }
+171 -22
View File
@@ -8,6 +8,7 @@
"@lingui/cli": "catalog:", "@lingui/cli": "catalog:",
"@lingui/conf": "catalog:", "@lingui/conf": "catalog:",
"@lingui/format-po": "catalog:", "@lingui/format-po": "catalog:",
"eslint-plugin-lingui": "0.11.0",
"oxfmt": "0.41.0", "oxfmt": "0.41.0",
"oxlint": "1.56.0", "oxlint": "1.56.0",
"turbo": "2.8.20", "turbo": "2.8.20",
@@ -67,7 +68,7 @@
"expo-system-ui": "55.0.10", "expo-system-ui": "55.0.10",
"expo-tracking-transparency": "55.0.9", "expo-tracking-transparency": "55.0.9",
"expo-web-browser": "55.0.10", "expo-web-browser": "55.0.10",
"posthog-react-native": "4.37.4", "posthog-react-native": "4.37.5",
"react": "19.2.0", "react": "19.2.0",
"react-dom": "19.2.0", "react-dom": "19.2.0",
"react-native": "0.83.2", "react-native": "0.83.2",
@@ -156,7 +157,7 @@
"@tabler/icons-react": "3.40.0", "@tabler/icons-react": "3.40.0",
"@tanstack/react-hotkeys": "0.4.2", "@tanstack/react-hotkeys": "0.4.2",
"@tanstack/react-query": "catalog:", "@tanstack/react-query": "catalog:",
"@tanstack/react-router": "1.167.5", "@tanstack/react-router": "1.168.1",
"better-auth": "catalog:", "better-auth": "catalog:",
"class-variance-authority": "0.7.1", "class-variance-authority": "0.7.1",
"clsx": "2.1.1", "clsx": "2.1.1",
@@ -165,7 +166,7 @@
"motion": "12.38.0", "motion": "12.38.0",
"react": "catalog:", "react": "catalog:",
"react-dom": "catalog:", "react-dom": "catalog:",
"shadcn": "4.0.8", "shadcn": "4.1.0",
"sonner": "2.0.7", "sonner": "2.0.7",
"tailwind-merge": "catalog:", "tailwind-merge": "catalog:",
"thumbhash": "catalog:", "thumbhash": "catalog:",
@@ -179,8 +180,8 @@
"@tanstack/devtools-vite": "0.6.0", "@tanstack/devtools-vite": "0.6.0",
"@tanstack/react-devtools": "0.10.0", "@tanstack/react-devtools": "0.10.0",
"@tanstack/react-query-devtools": "5.91.3", "@tanstack/react-query-devtools": "5.91.3",
"@tanstack/react-router-devtools": "1.166.9", "@tanstack/react-router-devtools": "1.166.10",
"@tanstack/router-plugin": "1.166.14", "@tanstack/router-plugin": "1.167.1",
"@types/bun": "catalog:", "@types/bun": "catalog:",
"@types/node": "catalog:", "@types/node": "catalog:",
"@types/react": "catalog:", "@types/react": "catalog:",
@@ -315,7 +316,7 @@
"@orpc/client": "1.13.9", "@orpc/client": "1.13.9",
"@orpc/contract": "1.13.9", "@orpc/contract": "1.13.9",
"@orpc/tanstack-query": "1.13.9", "@orpc/tanstack-query": "1.13.9",
"@tanstack/react-query": "5.91.2", "@tanstack/react-query": "5.91.3",
"@types/bun": "1.3.11", "@types/bun": "1.3.11",
"@types/node": "25.5.0", "@types/node": "25.5.0",
"@types/react": "19.2.14", "@types/react": "19.2.14",
@@ -641,6 +642,24 @@
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
"@eslint/config-array": ["@eslint/config-array@0.21.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.5" } }, "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw=="],
"@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="],
"@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.5", "", { "dependencies": { "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" } }, "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg=="],
"@eslint/js": ["@eslint/js@9.39.4", "", {}, "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw=="],
"@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="],
"@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.27", "", {}, "sha512-cnb3DZnWUWpezGFkJ8y4MT5f/lw6FcgDzeJzic+T+vpQHLHG1cg3SC3i1w1i8Bk4xKR4HPY3t9iIRNvtr5ml8A=="], "@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.27", "", {}, "sha512-cnb3DZnWUWpezGFkJ8y4MT5f/lw6FcgDzeJzic+T+vpQHLHG1cg3SC3i1w1i8Bk4xKR4HPY3t9iIRNvtr5ml8A=="],
"@expo/cli": ["@expo/cli@55.0.18", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~55.0.10", "@expo/config-plugins": "~55.0.7", "@expo/devcert": "^1.2.1", "@expo/env": "~2.1.1", "@expo/image-utils": "^0.8.12", "@expo/json-file": "^10.0.12", "@expo/log-box": "55.0.7", "@expo/metro": "~54.2.0", "@expo/metro-config": "~55.0.11", "@expo/osascript": "^2.4.2", "@expo/package-manager": "^1.10.3", "@expo/plist": "^0.5.2", "@expo/prebuild-config": "^55.0.10", "@expo/require-utils": "^55.0.3", "@expo/router-server": "^55.0.11", "@expo/schema-utils": "^55.0.2", "@expo/spawn-async": "^1.7.2", "@expo/ws-tunnel": "^1.0.1", "@expo/xcpretty": "^4.4.0", "@react-native/dev-middleware": "0.83.2", "accepts": "^1.3.8", "arg": "^5.0.2", "better-opn": "~3.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.3", "expo-server": "^55.0.6", "fetch-nodeshim": "^0.4.6", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.0", "multitars": "^0.2.3", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.3", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "source-map-support": "~0.5.21", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "build/bin/cli" } }, "sha512-3sJwu8KvCvQIXBnhUlHgLBZBe+ZK4Da9R5rgI4znaowJavYWMqzRClLzyE6Kri66WVoMX7Q4HUVIh8prRlO0XA=="], "@expo/cli": ["@expo/cli@55.0.18", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~55.0.10", "@expo/config-plugins": "~55.0.7", "@expo/devcert": "^1.2.1", "@expo/env": "~2.1.1", "@expo/image-utils": "^0.8.12", "@expo/json-file": "^10.0.12", "@expo/log-box": "55.0.7", "@expo/metro": "~54.2.0", "@expo/metro-config": "~55.0.11", "@expo/osascript": "^2.4.2", "@expo/package-manager": "^1.10.3", "@expo/plist": "^0.5.2", "@expo/prebuild-config": "^55.0.10", "@expo/require-utils": "^55.0.3", "@expo/router-server": "^55.0.11", "@expo/schema-utils": "^55.0.2", "@expo/spawn-async": "^1.7.2", "@expo/ws-tunnel": "^1.0.1", "@expo/xcpretty": "^4.4.0", "@react-native/dev-middleware": "0.83.2", "accepts": "^1.3.8", "arg": "^5.0.2", "better-opn": "~3.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.3", "expo-server": "^55.0.6", "fetch-nodeshim": "^0.4.6", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.0", "multitars": "^0.2.3", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.3", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "source-map-support": "~0.5.21", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "build/bin/cli" } }, "sha512-3sJwu8KvCvQIXBnhUlHgLBZBe+ZK4Da9R5rgI4znaowJavYWMqzRClLzyE6Kri66WVoMX7Q4HUVIh8prRlO0XA=="],
@@ -745,6 +764,14 @@
"@hono/zod-validator": ["@hono/zod-validator@0.7.6", "", { "peerDependencies": { "hono": ">=3.9.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Io1B6d011Gj1KknV4rXYz4le5+5EubcWEU/speUjuw9XMMIaP3n78yXLhjd2A3PXaXaUwEAluOiAyLqhBEJgsw=="], "@hono/zod-validator": ["@hono/zod-validator@0.7.6", "", { "peerDependencies": { "hono": ">=3.9.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Io1B6d011Gj1KknV4rXYz4le5+5EubcWEU/speUjuw9XMMIaP3n78yXLhjd2A3PXaXaUwEAluOiAyLqhBEJgsw=="],
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
"@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
@@ -1023,7 +1050,7 @@
"@player.style/sutro": ["@player.style/sutro@0.2.1", "", { "peerDependencies": { "media-chrome": ">=1.0.0" } }, "sha512-vWtFAdu4z3+1HcDPAriX+41q+bYSOgM898XO4TxEgoNyeaBq/Aoz2cRgWFpsWaK368+n7uWCbO5n2vAszN5fhw=="], "@player.style/sutro": ["@player.style/sutro@0.2.1", "", { "peerDependencies": { "media-chrome": ">=1.0.0" } }, "sha512-vWtFAdu4z3+1HcDPAriX+41q+bYSOgM898XO4TxEgoNyeaBq/Aoz2cRgWFpsWaK368+n7uWCbO5n2vAszN5fhw=="],
"@posthog/core": ["@posthog/core@1.24.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-Wkp9mgNfgdf6+G4C1VMKakm2RXKQFf4bb5/CPQRAjpqv9l6BY36zZrD1+X5Y2XIAzZqbMKRxsDu3V1r6uKu7/A=="], "@posthog/core": ["@posthog/core@1.24.1", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-e8AciAnc6MRFws89ux8lJKFAaI03yEon0ASDoUO7yS91FVqbUGXYekObUUR3LHplcg+pmyiJBI0jolY0SFbGRA=="],
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
@@ -1275,25 +1302,25 @@
"@tanstack/react-hotkeys": ["@tanstack/react-hotkeys@0.4.2", "", { "dependencies": { "@tanstack/hotkeys": "0.4.2", "@tanstack/react-store": "^0.9.2" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-7AMAmX+l1k0tHCaDgT5lHHF0cmtrmK0aaKxR6DliSdAVVjfmyraPZQapLwpyNKoTKNYIROj+2Wg+OvWYP52Oog=="], "@tanstack/react-hotkeys": ["@tanstack/react-hotkeys@0.4.2", "", { "dependencies": { "@tanstack/hotkeys": "0.4.2", "@tanstack/react-store": "^0.9.2" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-7AMAmX+l1k0tHCaDgT5lHHF0cmtrmK0aaKxR6DliSdAVVjfmyraPZQapLwpyNKoTKNYIROj+2Wg+OvWYP52Oog=="],
"@tanstack/react-query": ["@tanstack/react-query@5.91.2", "", { "dependencies": { "@tanstack/query-core": "5.91.2" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-GClLPzbM57iFXv+FlvOUL56XVe00PxuTaVEyj1zAObhRiKF008J5vedmaq7O6ehs+VmPHe8+PUQhMuEyv8d9wQ=="], "@tanstack/react-query": ["@tanstack/react-query@5.91.3", "", { "dependencies": { "@tanstack/query-core": "5.91.2" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-D8jsCexxS5crZxAeiH6VlLHOUzmHOxeW5c11y8rZu0c34u/cy18hUKQXA/gn1Ila3ZIFzP+Pzv76YnliC0EtZQ=="],
"@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.91.3", "", { "dependencies": { "@tanstack/query-devtools": "5.93.0" }, "peerDependencies": { "@tanstack/react-query": "^5.90.20", "react": "^18 || ^19" } }, "sha512-nlahjMtd/J1h7IzOOfqeyDh5LNfG0eULwlltPEonYy0QL+nqrBB+nyzJfULV+moL7sZyxc2sHdNJki+vLA9BSA=="], "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.91.3", "", { "dependencies": { "@tanstack/query-devtools": "5.93.0" }, "peerDependencies": { "@tanstack/react-query": "^5.90.20", "react": "^18 || ^19" } }, "sha512-nlahjMtd/J1h7IzOOfqeyDh5LNfG0eULwlltPEonYy0QL+nqrBB+nyzJfULV+moL7sZyxc2sHdNJki+vLA9BSA=="],
"@tanstack/react-query-persist-client": ["@tanstack/react-query-persist-client@5.90.27", "", { "dependencies": { "@tanstack/query-persist-client-core": "5.92.4" }, "peerDependencies": { "@tanstack/react-query": "^5.91.2", "react": "^18 || ^19" } }, "sha512-rKiCZ2C0kzmyDoLfrPHz2UdEDKHo/oXkKVRbhgtHya/bWH6jWDFX5cSFc1SLB33FDrgR8uOG1MwVohBrI4+F8A=="], "@tanstack/react-query-persist-client": ["@tanstack/react-query-persist-client@5.90.27", "", { "dependencies": { "@tanstack/query-persist-client-core": "5.92.4" }, "peerDependencies": { "@tanstack/react-query": "^5.91.2", "react": "^18 || ^19" } }, "sha512-rKiCZ2C0kzmyDoLfrPHz2UdEDKHo/oXkKVRbhgtHya/bWH6jWDFX5cSFc1SLB33FDrgR8uOG1MwVohBrI4+F8A=="],
"@tanstack/react-router": ["@tanstack/react-router@1.167.5", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-store": "^0.9.1", "@tanstack/router-core": "1.167.5", "isbot": "^5.1.22", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-s1nP6l/7BYZfSwhoNbB7/rUmZ07q/AvkmhBoiDQl3tgy5dpb9Q1qjtIapYdvCOrao1aA/QCaWqxcbGc2Ct1bvQ=="], "@tanstack/react-router": ["@tanstack/react-router@1.168.1", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-store": "^0.9.2", "@tanstack/router-core": "1.168.1", "isbot": "^5.1.22", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-DsQzbfwcr2Xugqs4G8yShUO9hVQ/tbWhIiLNJSxmZZOgaZCB3JP+ngN1EJBYZz+JBQdvyVHfiEsPXy0P1h3yVA=="],
"@tanstack/react-router-devtools": ["@tanstack/react-router-devtools@1.166.9", "", { "dependencies": { "@tanstack/router-devtools-core": "1.166.9" }, "peerDependencies": { "@tanstack/react-router": "^1.167.2", "@tanstack/router-core": "^1.167.2", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["@tanstack/router-core"] }, "sha512-O49eZmaeEKB5YnKH/qd61AbxV/lW8ICm4stfZ4GNQNpzQQ6rhPIB0p3PMZDIgX+6DoMivdNvLRmXAOOpzpIpDg=="], "@tanstack/react-router-devtools": ["@tanstack/react-router-devtools@1.166.10", "", { "dependencies": { "@tanstack/router-devtools-core": "1.167.0" }, "peerDependencies": { "@tanstack/react-router": "^1.168.0", "@tanstack/router-core": "^1.168.0", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["@tanstack/router-core"] }, "sha512-+C4doh9D+ag8yA4WjR3Og4RGvuwvwwqN0j67Pg+Hu1I1ebZAKowtUREH8iT4acUxgtH6hzt8pAuzMVskdLc4SQ=="],
"@tanstack/react-store": ["@tanstack/react-store@0.9.2", "", { "dependencies": { "@tanstack/store": "0.9.2", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Vt5usJE5sHG/cMechQfmwvwne6ktGCELe89Lmvoxe3LKRoFrhPa8OCKWs0NliG8HTJElEIj7PLtaBQIcux5pAQ=="], "@tanstack/react-store": ["@tanstack/react-store@0.9.2", "", { "dependencies": { "@tanstack/store": "0.9.2", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Vt5usJE5sHG/cMechQfmwvwne6ktGCELe89Lmvoxe3LKRoFrhPa8OCKWs0NliG8HTJElEIj7PLtaBQIcux5pAQ=="],
"@tanstack/router-core": ["@tanstack/router-core@1.167.5", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/store": "^0.9.1", "cookie-es": "^2.0.0", "seroval": "^1.4.2", "seroval-plugins": "^1.4.2", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "bin": { "intent": "bin/intent.js" } }, "sha512-8fRgJ0zNJf77R4grCaJQ5Imatjyc4YT5v8rlsPkYYYeUlcFNLbuFRhLlAMdND9gRUMznpnbRDXngpTPgx2K7HQ=="], "@tanstack/router-core": ["@tanstack/router-core@1.168.1", "", { "dependencies": { "@tanstack/history": "1.161.6", "cookie-es": "^2.0.0", "seroval": "^1.4.2", "seroval-plugins": "^1.4.2", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "bin": { "intent": "bin/intent.js" } }, "sha512-RtpshTLZsMOkwW7rI52WFWGZSSfMAyDR1zWP9kVm91UX28gedc+LXih1CTP6TchS+TvxK4q8oW7ApMTvnpiY1w=="],
"@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.166.9", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16", "tiny-invariant": "^1.3.3" }, "peerDependencies": { "@tanstack/router-core": "^1.167.2", "csstype": "^3.0.10" }, "optionalPeers": ["csstype"] }, "sha512-PNlA7GmOUX9wY7LUG709Pk3Lg33dfHBztQwzjzrOiOsuf4ggp2R6bwarF8nYGNjG79z/MaB5PN+5yvkCVk8jGw=="], "@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.167.0", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16", "tiny-invariant": "^1.3.3" }, "peerDependencies": { "@tanstack/router-core": "^1.168.0", "csstype": "^3.0.10" }, "optionalPeers": ["csstype"] }, "sha512-icgcpE7CQqOzZs4hbFfmICvwk4k7R8ErhUUuUHIKbAYioowQWKm1F3oJhkv6CtoTiofzplUrv9Jy8KE+U/sTKA=="],
"@tanstack/router-generator": ["@tanstack/router-generator@1.166.13", "", { "dependencies": { "@tanstack/router-core": "1.167.5", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-ALxSs6OzimiSgpOuIm+AXmc7eUx/oGPwSPpdQbpZ/kX7WHRh6qM7lv8DAN0K3jWcBpzF8eeOIdryWryX8gH+Yg=="], "@tanstack/router-generator": ["@tanstack/router-generator@1.166.15", "", { "dependencies": { "@tanstack/router-core": "1.168.1", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-W8ybCktgN/45fc7ohWJKAyG5Al1pnTg7V8Z6RiG8NkSrN7Igo4BqanUmXULnhnkdCID5XhMbkhP84r2hzkXbPw=="],
"@tanstack/router-plugin": ["@tanstack/router-plugin@1.166.14", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@tanstack/router-core": "1.167.5", "@tanstack/router-generator": "1.166.13", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.167.5", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"], "bin": { "intent": "bin/intent.js" } }, "sha512-hypyj0qlsAbJf60/glmVYqSVwnRB4hKRrMCUsSXjrPdO2g6gs3z6xHmcWsHQ831C4G9+bSFEK9Uy5EjO3A4THQ=="], "@tanstack/router-plugin": ["@tanstack/router-plugin@1.167.1", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@tanstack/router-core": "1.168.1", "@tanstack/router-generator": "1.166.15", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.168.1", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"], "bin": { "intent": "bin/intent.js" } }, "sha512-bPDdwvpoznjyCUWd+w2ss+y9GemXvF3R6Zzi36rxiWUGwuqDhQbvs1fWkjsx2oBqXSG8vkF74yFdUxFEX90o4g=="],
"@tanstack/router-utils": ["@tanstack/router-utils@1.161.6", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "ansis": "^4.1.0", "babel-dead-code-elimination": "^1.0.12", "diff": "^8.0.2", "pathe": "^2.0.3", "tinyglobby": "^0.2.15" } }, "sha512-nRcYw+w2OEgK6VfjirYvGyPLOK+tZQz1jkYcmH5AjMamQ9PycnlxZF2aEZtPpNoUsaceX2bHptn6Ub5hGXqNvw=="], "@tanstack/router-utils": ["@tanstack/router-utils@1.161.6", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "ansis": "^4.1.0", "babel-dead-code-elimination": "^1.0.12", "diff": "^8.0.2", "pathe": "^2.0.3", "tinyglobby": "^0.2.15" } }, "sha512-nRcYw+w2OEgK6VfjirYvGyPLOK+tZQz1jkYcmH5AjMamQ9PycnlxZF2aEZtPpNoUsaceX2bHptn6Ub5hGXqNvw=="],
@@ -1333,6 +1360,8 @@
"@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="], "@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
"@types/graceful-fs": ["@types/graceful-fs@4.1.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ=="], "@types/graceful-fs": ["@types/graceful-fs@4.1.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ=="],
"@types/hammerjs": ["@types/hammerjs@2.0.46", "", {}, "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw=="], "@types/hammerjs": ["@types/hammerjs@2.0.46", "", {}, "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw=="],
@@ -1343,6 +1372,8 @@
"@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="], "@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="],
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
"@types/mssql": ["@types/mssql@9.1.9", "", { "dependencies": { "@types/node": "*", "tarn": "^3.0.1", "tedious": "*" } }, "sha512-P0nCgw6vzY23UxZMnbI4N7fnLGANt4LI4yvxze1paPj+LuN28cFv5EI+QidP8udnId/BKhkcRhm/BleNsjK65A=="], "@types/mssql": ["@types/mssql@9.1.9", "", { "dependencies": { "@types/node": "*", "tarn": "^3.0.1", "tedious": "*" } }, "sha512-P0nCgw6vzY23UxZMnbI4N7fnLGANt4LI4yvxze1paPj+LuN28cFv5EI+QidP8udnId/BKhkcRhm/BleNsjK65A=="],
"@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="], "@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
@@ -1367,6 +1398,20 @@
"@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="], "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="],
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.1", "@typescript-eslint/types": "^8.57.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vx1F37BRO1OftsYlmG9xay1TqnjNVlqALymwWVuYTdo18XuKxtBpCj1QlzNIEHlvlB27osvXFWptYiEWsVdYsg=="],
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.1", "", { "dependencies": { "@typescript-eslint/types": "8.57.1", "@typescript-eslint/visitor-keys": "8.57.1" } }, "sha512-hs/QcpCwlwT2L5S+3fT6gp0PabyGk4Q0Rv2doJXA0435/OpnSR3VRgvrp8Xdoc3UAYSg9cyUjTeFXZEPg/3OKg=="],
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-0lgOZB8cl19fHO4eI46YUx2EceQqhgkPSuCGLlGi79L2jwYY1cxeYc1Nae8Aw1xjgW3PKVDLlr3YJ6Bxx8HkWg=="],
"@typescript-eslint/types": ["@typescript-eslint/types@8.57.1", "", {}, "sha512-S29BOBPJSFUiblEl6RzPPjJt6w25A6XsBqRVDt53tA/tlL8q7ceQNZHTjPeONt/3S7KRI4quk+yP9jK2WjBiPQ=="],
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.1", "@typescript-eslint/tsconfig-utils": "8.57.1", "@typescript-eslint/types": "8.57.1", "@typescript-eslint/visitor-keys": "8.57.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ybe2hS9G6pXpqGtPli9Gx9quNV0TWLOmh58ADlmZe9DguLq0tiAKVjirSbtM1szG6+QH6rVXyU6GTLQbWnMY+g=="],
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.1", "@typescript-eslint/types": "8.57.1", "@typescript-eslint/typescript-estree": "8.57.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XUNSJ/lEVFttPMMoDVA2r2bwrl8/oPx8cURtczkSEswY5T3AeLmCy+EKWQNdL4u0MmAHOjcWrqJp2cdvgjn8dQ=="],
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.1", "", { "dependencies": { "@typescript-eslint/types": "8.57.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-YWnmJkXbofiz9KbnbbwuA2rpGkFPLbAIetcCNO6mJ8gdhdZ/v7WDXsoGFAJuM6ikUFKTlSQnjWnVO4ux+UzS6A=="],
"@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.4", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-CI0NhTrz4EBaa0U+HaaUZrJhPoso8sG7ZFya8uQoBA57fjzrjRSv87ekCjLZOFExN+gXE/z0xuN2QfH4H2HrLQ=="], "@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.4", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-CI0NhTrz4EBaa0U+HaaUZrJhPoso8sG7ZFya8uQoBA57fjzrjRSv87ekCjLZOFExN+gXE/z0xuN2QfH4H2HrLQ=="],
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
@@ -1405,11 +1450,13 @@
"acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
"adm-zip": ["adm-zip@0.5.16", "", {}, "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ=="], "adm-zip": ["adm-zip@0.5.16", "", {}, "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ=="],
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
"ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], "ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
"ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
@@ -1633,6 +1680,8 @@
"dedent": ["dedent@1.7.2", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA=="], "dedent": ["dedent@1.7.2", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA=="],
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
"default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="], "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],
@@ -1711,10 +1760,28 @@
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
"eslint": ["eslint@9.39.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.5", "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ=="],
"eslint-plugin-lingui": ["eslint-plugin-lingui@0.11.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.0.0", "micromatch": "^4.0.0" }, "peerDependencies": { "eslint": "^8.37.0 || ^9.0.0" } }, "sha512-O2Ixoapt5fa4VKZJgXhVwb6BHnzByIUDNMfZOhHWGMYk40GfGCho4MUfspLVrHAFLimgBPKXtCcJ8GC4YNZmfg=="],
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
"eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
"esm": ["esm@3.2.25", "", {}, "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="], "esm": ["esm@3.2.25", "", {}, "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="],
"espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
"esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
"etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
@@ -1815,6 +1882,8 @@
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
"fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="], "fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="],
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
@@ -1833,6 +1902,8 @@
"figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="], "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="],
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
"file-type": ["file-type@16.5.4", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="], "file-type": ["file-type@16.5.4", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
@@ -1841,7 +1912,11 @@
"finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="], "finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="],
"find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
"flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
"flow-enums-runtime": ["flow-enums-runtime@0.0.6", "", {}, "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw=="], "flow-enums-runtime": ["flow-enums-runtime@0.0.6", "", {}, "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw=="],
@@ -1895,6 +1970,8 @@
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
"goober": ["goober@2.1.18", "", { "peerDependencies": { "csstype": "^3.0.10" } }, "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw=="], "goober": ["goober@2.1.18", "", { "peerDependencies": { "csstype": "^3.0.10" } }, "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw=="],
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
@@ -2053,12 +2130,16 @@
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
"json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="], "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
"jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],
@@ -2069,6 +2150,8 @@
"jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
"kysely": ["kysely@0.28.13", "", {}, "sha512-jCkYDvlfzOyHaVsrvR4vnNZxG30oNv2jbbFBjTQAUG8n0h07HW0sZJHk4KAQIRyu9ay+Rg+L8qGa3lwt8Gve9w=="], "kysely": ["kysely@0.28.13", "", {}, "sha512-jCkYDvlfzOyHaVsrvR4vnNZxG30oNv2jbbFBjTQAUG8n0h07HW0sZJHk4KAQIRyu9ay+Rg+L8qGa3lwt8Gve9w=="],
@@ -2079,6 +2162,8 @@
"leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="], "leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
"lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="], "lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="],
"lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="], "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
@@ -2107,7 +2192,7 @@
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
"locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
"lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
@@ -2123,6 +2208,8 @@
"lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="], "lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="],
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
"lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="], "lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="],
"lodash.throttle": ["lodash.throttle@4.1.1", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="], "lodash.throttle": ["lodash.throttle@4.1.1", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="],
@@ -2235,6 +2322,8 @@
"native-duplexpair": ["native-duplexpair@1.0.0", "", {}, "sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA=="], "native-duplexpair": ["native-duplexpair@1.0.0", "", {}, "sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA=="],
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
"negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
@@ -2289,6 +2378,8 @@
"openapi-typescript-helpers": ["openapi-typescript-helpers@0.1.0", "", {}, "sha512-OKTGPthhivLw/fHz6c3OPtg72vi86qaMlqbJuVJ23qOvQ+53uw1n7HdmkJFibloF7QEjDrDkzJiOJuockM/ljw=="], "openapi-typescript-helpers": ["openapi-typescript-helpers@0.1.0", "", {}, "sha512-OKTGPthhivLw/fHz6c3OPtg72vi86qaMlqbJuVJ23qOvQ+53uw1n7HdmkJFibloF7QEjDrDkzJiOJuockM/ljw=="],
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
"ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="], "ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="],
"outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="], "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="],
@@ -2297,9 +2388,9 @@
"oxlint": ["oxlint@1.56.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.56.0", "@oxlint/binding-android-arm64": "1.56.0", "@oxlint/binding-darwin-arm64": "1.56.0", "@oxlint/binding-darwin-x64": "1.56.0", "@oxlint/binding-freebsd-x64": "1.56.0", "@oxlint/binding-linux-arm-gnueabihf": "1.56.0", "@oxlint/binding-linux-arm-musleabihf": "1.56.0", "@oxlint/binding-linux-arm64-gnu": "1.56.0", "@oxlint/binding-linux-arm64-musl": "1.56.0", "@oxlint/binding-linux-ppc64-gnu": "1.56.0", "@oxlint/binding-linux-riscv64-gnu": "1.56.0", "@oxlint/binding-linux-riscv64-musl": "1.56.0", "@oxlint/binding-linux-s390x-gnu": "1.56.0", "@oxlint/binding-linux-x64-gnu": "1.56.0", "@oxlint/binding-linux-x64-musl": "1.56.0", "@oxlint/binding-openharmony-arm64": "1.56.0", "@oxlint/binding-win32-arm64-msvc": "1.56.0", "@oxlint/binding-win32-ia32-msvc": "1.56.0", "@oxlint/binding-win32-x64-msvc": "1.56.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.15.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-Q+5Mj5PVaH/R6/fhMMFzw4dT+KPB+kQW4kaL8FOIq7tfhlnEVp6+3lcWqFruuTNlUo9srZUW3qH7Id4pskeR6g=="], "oxlint": ["oxlint@1.56.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.56.0", "@oxlint/binding-android-arm64": "1.56.0", "@oxlint/binding-darwin-arm64": "1.56.0", "@oxlint/binding-darwin-x64": "1.56.0", "@oxlint/binding-freebsd-x64": "1.56.0", "@oxlint/binding-linux-arm-gnueabihf": "1.56.0", "@oxlint/binding-linux-arm-musleabihf": "1.56.0", "@oxlint/binding-linux-arm64-gnu": "1.56.0", "@oxlint/binding-linux-arm64-musl": "1.56.0", "@oxlint/binding-linux-ppc64-gnu": "1.56.0", "@oxlint/binding-linux-riscv64-gnu": "1.56.0", "@oxlint/binding-linux-riscv64-musl": "1.56.0", "@oxlint/binding-linux-s390x-gnu": "1.56.0", "@oxlint/binding-linux-x64-gnu": "1.56.0", "@oxlint/binding-linux-x64-musl": "1.56.0", "@oxlint/binding-openharmony-arm64": "1.56.0", "@oxlint/binding-win32-arm64-msvc": "1.56.0", "@oxlint/binding-win32-ia32-msvc": "1.56.0", "@oxlint/binding-win32-x64-msvc": "1.56.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.15.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-Q+5Mj5PVaH/R6/fhMMFzw4dT+KPB+kQW4kaL8FOIq7tfhlnEVp6+3lcWqFruuTNlUo9srZUW3qH7Id4pskeR6g=="],
"p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
"p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
"p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
@@ -2365,10 +2456,12 @@
"postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="], "postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="],
"posthog-react-native": ["posthog-react-native@4.37.4", "", { "dependencies": { "@posthog/core": "1.24.0" }, "peerDependencies": { "@react-native-async-storage/async-storage": ">=1.0.0", "@react-navigation/native": ">= 5.0.0", "expo-application": ">= 4.0.0", "expo-device": ">= 4.0.0", "expo-file-system": ">= 13.0.0", "expo-localization": ">= 11.0.0", "posthog-react-native-session-replay": ">= 1.5.0", "react-native-device-info": ">= 10.0.0", "react-native-localize": ">= 3.0.0", "react-native-navigation": ">= 6.0.0", "react-native-safe-area-context": ">= 4.0.0", "react-native-svg": ">= 15.0.0" }, "optionalPeers": ["@react-native-async-storage/async-storage", "@react-navigation/native", "expo-application", "expo-device", "expo-file-system", "expo-localization", "posthog-react-native-session-replay", "react-native-device-info", "react-native-localize", "react-native-navigation", "react-native-safe-area-context"] }, "sha512-0/zHFZ1bnIlo0mDl2JvuS7EgDNs2XTol1kbR6M0R9OFn9aH7q2UVA0c9ixmIqYntKrSW7ava9TxCOO5QNIE+fw=="], "posthog-react-native": ["posthog-react-native@4.37.5", "", { "dependencies": { "@posthog/core": "1.24.1" }, "peerDependencies": { "@react-native-async-storage/async-storage": ">=1.0.0", "@react-navigation/native": ">= 5.0.0", "expo-application": ">= 4.0.0", "expo-device": ">= 4.0.0", "expo-file-system": ">= 13.0.0", "expo-localization": ">= 11.0.0", "posthog-react-native-session-replay": ">= 1.5.0", "react-native-device-info": ">= 10.0.0", "react-native-localize": ">= 3.0.0", "react-native-navigation": ">= 6.0.0", "react-native-safe-area-context": ">= 4.0.0", "react-native-svg": ">= 15.0.0" }, "optionalPeers": ["@react-native-async-storage/async-storage", "@react-navigation/native", "expo-application", "expo-device", "expo-file-system", "expo-localization", "posthog-react-native-session-replay", "react-native-device-info", "react-native-localize", "react-native-navigation", "react-native-safe-area-context"] }, "sha512-5q5cFcu7541nXrsoWaRtCbmYrbd0IqYPm8FhRO3uMquPj2900+2777Xhwi89HuXLpq5XsrPEr2hR/8SL1MZttA=="],
"powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="], "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="],
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
"prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
"pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="], "pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="],
@@ -2547,7 +2640,7 @@
"sf-symbols-typescript": ["sf-symbols-typescript@2.2.0", "", {}, "sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw=="], "sf-symbols-typescript": ["sf-symbols-typescript@2.2.0", "", {}, "sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw=="],
"shadcn": ["shadcn@4.0.8", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "https-proxy-agent": "^7.0.6", "kleur": "^4.1.5", "msw": "^2.10.4", "node-fetch": "^3.3.2", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-DVAyeo95TQ/OvaHugLm5V0Dqz3al+dnoP3mZdWWxKJ33IYG1jN5B3sGZyNaYsfzm7JsWokfksSzDl83LnmMing=="], "shadcn": ["shadcn@4.1.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "https-proxy-agent": "^7.0.6", "kleur": "^4.1.5", "msw": "^2.10.4", "node-fetch": "^3.3.2", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-3zETJ+0Ezj69FS6RL0HOkLKKAR5yXisXx1iISJdfLQfrUqj/VIQlanQi1Ukk+9OE+XHZVj4FQNTBSfbr2CyCYg=="],
"shallowequal": ["shallowequal@1.1.0", "", {}, "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="], "shallowequal": ["shallowequal@1.1.0", "", {}, "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="],
@@ -2699,6 +2792,8 @@
"tr46": ["tr46@5.1.1", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw=="], "tr46": ["tr46@5.1.1", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw=="],
"ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
"ts-morph": ["ts-morph@26.0.0", "", { "dependencies": { "@ts-morph/common": "~0.27.0", "code-block-writer": "^13.0.3" } }, "sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug=="], "ts-morph": ["ts-morph@26.0.0", "", { "dependencies": { "@ts-morph/common": "~0.27.0", "code-block-writer": "^13.0.3" } }, "sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug=="],
"tsconfig-paths": ["tsconfig-paths@4.2.0", "", { "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg=="], "tsconfig-paths": ["tsconfig-paths@4.2.0", "", { "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg=="],
@@ -2711,6 +2806,8 @@
"tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
"type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="], "type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="],
"type-fest": ["type-fest@5.5.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g=="], "type-fest": ["type-fest@5.5.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g=="],
@@ -2745,6 +2842,8 @@
"update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
"use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
"use-latest-callback": ["use-latest-callback@0.2.6", "", { "peerDependencies": { "react": ">=16.8" } }, "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg=="], "use-latest-callback": ["use-latest-callback@0.2.6", "", { "peerDependencies": { "react": ">=16.8" } }, "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg=="],
@@ -2793,6 +2892,8 @@
"wildcard-match": ["wildcard-match@5.1.4", "", {}, "sha512-wldeCaczs8XXq7hj+5d/F38JE2r7EXgb6WQDM84RVwxy81T/sxB5e9+uZLK9Q9oNz1mlvjut+QtvgaOQFPVq/g=="], "wildcard-match": ["wildcard-match@5.1.4", "", {}, "sha512-wldeCaczs8XXq7hj+5d/F38JE2r7EXgb6WQDM84RVwxy81T/sxB5e9+uZLK9Q9oNz1mlvjut+QtvgaOQFPVq/g=="],
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
@@ -2819,6 +2920,8 @@
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
"yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="],
"yoctocolors-cjs": ["yoctocolors-cjs@2.1.3", "", {}, "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw=="], "yoctocolors-cjs": ["yoctocolors-cjs@2.1.3", "", {}, "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw=="],
@@ -2851,6 +2954,14 @@
"@ecies/ciphers/@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="], "@ecies/ciphers/@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
"@eslint/config-array/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
"@eslint/eslintrc/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
"@eslint/eslintrc/strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
"@expo/cli/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "@expo/cli/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"@expo/cli/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], "@expo/cli/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
@@ -2903,12 +3014,16 @@
"@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="], "@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
"@istanbuljs/load-nyc-config/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
"@istanbuljs/load-nyc-config/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], "@istanbuljs/load-nyc-config/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
"@jest/transform/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "@jest/transform/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"@modelcontextprotocol/sdk/ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="],
"@noble/curves/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], "@noble/curves/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
"@orpc/zod/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], "@orpc/zod/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
@@ -2979,6 +3094,10 @@
"@tanstack/router-plugin/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "@tanstack/router-plugin/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
"@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
"ajv-formats/ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="],
"ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
@@ -3013,6 +3132,12 @@
"eciesjs/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], "eciesjs/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
"eslint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"eslint/glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
"eslint/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
"expo-modules-autolinking/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "expo-modules-autolinking/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], "expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
@@ -3197,6 +3322,10 @@
"@dotenvx/dotenvx/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="], "@dotenvx/dotenvx/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
"@eslint/config-array/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"@eslint/eslintrc/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"@expo/cli/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "@expo/cli/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"@expo/cli/ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], "@expo/cli/ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
@@ -3259,12 +3388,16 @@
"@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "@inquirer/core/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"@istanbuljs/load-nyc-config/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
"@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], "@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
"@jest/transform/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "@jest/transform/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"@jest/types/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "@jest/types/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"@modelcontextprotocol/sdk/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
"@radix-ui/react-arrow/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], "@radix-ui/react-arrow/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-context-menu/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], "@radix-ui/react-context-menu/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
@@ -3341,6 +3474,8 @@
"@tanstack/router-plugin/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "@tanstack/router-plugin/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
"ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
"babel-jest/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "babel-jest/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="], "babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
@@ -3361,6 +3496,10 @@
"cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"eslint/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"eslint/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"expo-modules-autolinking/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "expo-modules-autolinking/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"express/accepts/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], "express/accepts/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
@@ -3499,6 +3638,10 @@
"vite/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="], "vite/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
"@eslint/config-array/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"@eslint/eslintrc/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"@expo/cli/ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], "@expo/cli/ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
"@expo/cli/ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], "@expo/cli/ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
@@ -3519,6 +3662,8 @@
"@expo/package-manager/ora/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="], "@expo/package-manager/ora/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
"@istanbuljs/load-nyc-config/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
"@istanbuljs/load-nyc-config/js-yaml/argparse/sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], "@istanbuljs/load-nyc-config/js-yaml/argparse/sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
"@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], "@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
@@ -3557,6 +3702,8 @@
"@tanstack/router-plugin/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "@tanstack/router-plugin/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"eslint/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"isomorphic-fetch/node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], "isomorphic-fetch/node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
"isomorphic-fetch/node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], "isomorphic-fetch/node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
@@ -3591,6 +3738,8 @@
"@expo/package-manager/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], "@expo/package-manager/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
"@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
"@react-native/codegen/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "@react-native/codegen/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"react-native/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "react-native/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
+6 -6
View File
@@ -7,10 +7,10 @@
"dependencies": { "dependencies": {
"@takumi-rs/image-response": "^0.73.1", "@takumi-rs/image-response": "^0.73.1",
"@vercel/analytics": "^2.0.1", "@vercel/analytics": "^2.0.1",
"fumadocs-core": "^16.7.0", "fumadocs-core": "^16.7.2",
"fumadocs-mdx": "^14.2.11", "fumadocs-mdx": "^14.2.11",
"fumadocs-openapi": "^10.4.0", "fumadocs-openapi": "^10.4.1",
"fumadocs-ui": "^16.7.0", "fumadocs-ui": "^16.7.2",
"lucide-react": "^0.577.0", "lucide-react": "^0.577.0",
"next": "16.2.0", "next": "16.2.0",
"react": "19.2.4", "react": "19.2.4",
@@ -568,13 +568,13 @@
"framer-motion": ["framer-motion@12.38.0", "", { "dependencies": { "motion-dom": "^12.38.0", "motion-utils": "^12.36.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g=="], "framer-motion": ["framer-motion@12.38.0", "", { "dependencies": { "motion-dom": "^12.38.0", "motion-utils": "^12.36.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g=="],
"fumadocs-core": ["fumadocs-core@16.7.0", "", { "dependencies": { "@formatjs/intl-localematcher": "^0.8.2", "@orama/orama": "^3.1.18", "@shikijs/rehype": "^4.0.2", "@shikijs/transformers": "^4.0.2", "estree-util-value-to-estree": "^3.5.0", "github-slugger": "^2.0.0", "hast-util-to-estree": "^3.1.3", "hast-util-to-jsx-runtime": "^2.3.6", "image-size": "^2.0.2", "mdast-util-mdx": "^3.0.0", "mdast-util-to-markdown": "^2.1.2", "negotiator": "^1.0.0", "npm-to-yarn": "^3.0.1", "path-to-regexp": "^8.3.0", "remark": "^15.0.1", "remark-gfm": "^4.0.1", "remark-rehype": "^11.1.2", "scroll-into-view-if-needed": "^3.1.0", "shiki": "^4.0.2", "tinyglobby": "^0.2.15", "unified": "^11.0.5", "unist-util-visit": "^5.1.0", "vfile": "^6.0.3" }, "peerDependencies": { "@mdx-js/mdx": "*", "@mixedbread/sdk": "^0.46.0", "@orama/core": "1.x.x", "@oramacloud/client": "2.x.x", "@tanstack/react-router": "1.x.x", "@types/estree-jsx": "*", "@types/hast": "*", "@types/mdast": "*", "@types/react": "*", "algoliasearch": "5.x.x", "flexsearch": "*", "lucide-react": "*", "next": "16.x.x", "react": "^19.2.0", "react-dom": "^19.2.0", "react-router": "7.x.x", "waku": "^0.26.0 || ^0.27.0 || ^1.0.0", "zod": "4.x.x" }, "optionalPeers": ["@mdx-js/mdx", "@mixedbread/sdk", "@orama/core", "@oramacloud/client", "@tanstack/react-router", "@types/estree-jsx", "@types/hast", "@types/mdast", "@types/react", "algoliasearch", "flexsearch", "lucide-react", "next", "react", "react-dom", "react-router", "waku", "zod"] }, "sha512-6QkOLy3LZfVin5/SOYMnVoKHJRO8vGtGbG4seWTYlaLj3jAhlRiefxIUilP+px1tpDTr6G6jGv6TeWtU0aP71Q=="], "fumadocs-core": ["fumadocs-core@16.7.2", "", { "dependencies": { "@formatjs/intl-localematcher": "^0.8.2", "@orama/orama": "^3.1.18", "@shikijs/rehype": "^4.0.2", "@shikijs/transformers": "^4.0.2", "estree-util-value-to-estree": "^3.5.0", "github-slugger": "^2.0.0", "hast-util-to-estree": "^3.1.3", "hast-util-to-jsx-runtime": "^2.3.6", "image-size": "^2.0.2", "mdast-util-mdx": "^3.0.0", "mdast-util-to-markdown": "^2.1.2", "negotiator": "^1.0.0", "npm-to-yarn": "^3.0.1", "path-to-regexp": "^8.3.0", "remark": "^15.0.1", "remark-gfm": "^4.0.1", "remark-rehype": "^11.1.2", "scroll-into-view-if-needed": "^3.1.0", "shiki": "^4.0.2", "tinyglobby": "^0.2.15", "unified": "^11.0.5", "unist-util-visit": "^5.1.0", "vfile": "^6.0.3" }, "peerDependencies": { "@mdx-js/mdx": "*", "@mixedbread/sdk": "^0.46.0", "@orama/core": "1.x.x", "@oramacloud/client": "2.x.x", "@tanstack/react-router": "1.x.x", "@types/estree-jsx": "*", "@types/hast": "*", "@types/mdast": "*", "@types/react": "*", "algoliasearch": "5.x.x", "flexsearch": "*", "lucide-react": "*", "next": "16.x.x", "react": "^19.2.0", "react-dom": "^19.2.0", "react-router": "7.x.x", "waku": "^0.26.0 || ^0.27.0 || ^1.0.0", "zod": "4.x.x" }, "optionalPeers": ["@mdx-js/mdx", "@mixedbread/sdk", "@orama/core", "@oramacloud/client", "@tanstack/react-router", "@types/estree-jsx", "@types/hast", "@types/mdast", "@types/react", "algoliasearch", "flexsearch", "lucide-react", "next", "react", "react-dom", "react-router", "waku", "zod"] }, "sha512-dPOp4KdaqKVTnCvwMp5XKAushq1rb9IeH20Nbtp8ocG0RhtL7QtE17UC6qXEbmcCFL5NgxRhG+MW2RS7kFFKGw=="],
"fumadocs-mdx": ["fumadocs-mdx@14.2.11", "", { "dependencies": { "@mdx-js/mdx": "^3.1.1", "@standard-schema/spec": "^1.1.0", "chokidar": "^5.0.0", "esbuild": "^0.27.3", "estree-util-value-to-estree": "^3.5.0", "js-yaml": "^4.1.1", "mdast-util-mdx": "^3.0.0", "mdast-util-to-markdown": "^2.1.2", "picocolors": "^1.1.1", "picomatch": "^4.0.3", "tinyexec": "^1.0.4", "tinyglobby": "^0.2.15", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.1.0", "vfile": "^6.0.3", "zod": "^4.3.6" }, "peerDependencies": { "@fumadocs/mdx-remote": "^1.4.0", "@types/mdast": "*", "@types/mdx": "*", "@types/react": "*", "fumadocs-core": "^15.0.0 || ^16.0.0", "mdast-util-directive": "*", "next": "^15.3.0 || ^16.0.0", "react": "*", "vite": "6.x.x || 7.x.x || 8.x.x" }, "optionalPeers": ["@fumadocs/mdx-remote", "@types/mdast", "@types/mdx", "@types/react", "mdast-util-directive", "next", "react", "vite"], "bin": { "fumadocs-mdx": "dist/bin.js" } }, "sha512-j0gHKs45c62ARteE8/yBM2Nu2I8AE2Cs37ktPEdc/8EX7TL66XP74un5OpHp6itLyWTu8Jur0imOiiIDq8+rDg=="], "fumadocs-mdx": ["fumadocs-mdx@14.2.11", "", { "dependencies": { "@mdx-js/mdx": "^3.1.1", "@standard-schema/spec": "^1.1.0", "chokidar": "^5.0.0", "esbuild": "^0.27.3", "estree-util-value-to-estree": "^3.5.0", "js-yaml": "^4.1.1", "mdast-util-mdx": "^3.0.0", "mdast-util-to-markdown": "^2.1.2", "picocolors": "^1.1.1", "picomatch": "^4.0.3", "tinyexec": "^1.0.4", "tinyglobby": "^0.2.15", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.1.0", "vfile": "^6.0.3", "zod": "^4.3.6" }, "peerDependencies": { "@fumadocs/mdx-remote": "^1.4.0", "@types/mdast": "*", "@types/mdx": "*", "@types/react": "*", "fumadocs-core": "^15.0.0 || ^16.0.0", "mdast-util-directive": "*", "next": "^15.3.0 || ^16.0.0", "react": "*", "vite": "6.x.x || 7.x.x || 8.x.x" }, "optionalPeers": ["@fumadocs/mdx-remote", "@types/mdast", "@types/mdx", "@types/react", "mdast-util-directive", "next", "react", "vite"], "bin": { "fumadocs-mdx": "dist/bin.js" } }, "sha512-j0gHKs45c62ARteE8/yBM2Nu2I8AE2Cs37ktPEdc/8EX7TL66XP74un5OpHp6itLyWTu8Jur0imOiiIDq8+rDg=="],
"fumadocs-openapi": ["fumadocs-openapi@10.4.0", "", { "dependencies": { "@fastify/deepmerge": "^3.2.1", "@fumari/json-schema-ts": "^0.0.2", "@fumari/stf": "1.0.3", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-slot": "^1.2.4", "@scalar/json-magic": "^0.12.4", "@scalar/openapi-upgrader": "^0.2.1", "ajv": "^8.18.0", "class-variance-authority": "^0.7.1", "dereference-json-schema": "^0.2.2", "github-slugger": "^2.0.0", "hast-util-to-jsx-runtime": "^2.3.6", "js-yaml": "^4.1.1", "lucide-react": "^0.577.0", "next-themes": "^0.4.6", "openapi-sampler": "^1.7.2", "react-hook-form": "^7.71.2", "remark": "^15.0.1", "remark-rehype": "^11.1.2", "tailwind-merge": "^3.5.0", "xml-js": "^1.6.11" }, "peerDependencies": { "@scalar/api-client-react": "*", "@types/react": "*", "fumadocs-core": "^16.7.0", "fumadocs-ui": "^16.7.0", "json-schema-typed": "*", "react": "^19.2.0", "react-dom": "^19.2.0", "shiki": "*" }, "optionalPeers": ["@scalar/api-client-react", "@types/react", "json-schema-typed", "shiki"] }, "sha512-DI5C1N3MHmKyegPebgnD1/ULzBtdnhOC2bj3J3LgQ7gqC+WEql+UYKfqVr1CoM7WRfn0vQ4sGfZhfjA42+mmPQ=="], "fumadocs-openapi": ["fumadocs-openapi@10.4.1", "", { "dependencies": { "@fastify/deepmerge": "^3.2.1", "@fumari/json-schema-ts": "^0.0.2", "@fumari/stf": "1.0.3", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-slot": "^1.2.4", "@scalar/json-magic": "^0.12.4", "@scalar/openapi-upgrader": "^0.2.1", "ajv": "^8.18.0", "class-variance-authority": "^0.7.1", "dereference-json-schema": "^0.2.2", "github-slugger": "^2.0.0", "hast-util-to-jsx-runtime": "^2.3.6", "js-yaml": "^4.1.1", "lucide-react": "^0.577.0", "next-themes": "^0.4.6", "openapi-sampler": "^1.7.2", "react-hook-form": "^7.71.2", "remark": "^15.0.1", "remark-rehype": "^11.1.2", "tailwind-merge": "^3.5.0", "xml-js": "^1.6.11" }, "peerDependencies": { "@scalar/api-client-react": "*", "@types/react": "*", "fumadocs-core": "^16.7.0", "fumadocs-ui": "^16.7.0", "json-schema-typed": "*", "react": "^19.2.0", "react-dom": "^19.2.0", "shiki": "*" }, "optionalPeers": ["@scalar/api-client-react", "@types/react", "json-schema-typed", "shiki"] }, "sha512-iMEDyANcikDePUFlBE5sffjTbrUI5LELuIla+6kTZJYEuoQMLUK+plOnXq1iacPBMeCS7cSFadvE/Vp/h7oA+g=="],
"fumadocs-ui": ["fumadocs-ui@16.7.0", "", { "dependencies": { "@fumadocs/tailwind": "0.0.3", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-direction": "^1.1.1", "@radix-ui/react-navigation-menu": "^1.2.14", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-presence": "^1.1.5", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-tabs": "^1.1.13", "class-variance-authority": "^0.7.1", "lucide-react": "^0.577.0", "motion": "^12.38.0", "next-themes": "^0.4.6", "react-medium-image-zoom": "^5.4.1", "react-remove-scroll": "^2.7.2", "rehype-raw": "^7.0.0", "scroll-into-view-if-needed": "^3.1.0", "tailwind-merge": "^3.5.0", "unist-util-visit": "^5.1.0" }, "peerDependencies": { "@takumi-rs/image-response": "*", "@types/mdx": "*", "@types/react": "*", "fumadocs-core": "16.7.0", "next": "16.x.x", "react": "^19.2.0", "react-dom": "^19.2.0", "shiki": "*" }, "optionalPeers": ["@takumi-rs/image-response", "@types/mdx", "@types/react", "next", "shiki"] }, "sha512-EHxijMwafP96sVDPh+8x2yrolcC9VCz/Xnm8a8pY/fjzO8i2gEXwnQ3Fy2KiiBji/ClRp5XjmnYo1uQO35hzLQ=="], "fumadocs-ui": ["fumadocs-ui@16.7.2", "", { "dependencies": { "@fumadocs/tailwind": "0.0.3", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-direction": "^1.1.1", "@radix-ui/react-navigation-menu": "^1.2.14", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-presence": "^1.1.5", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-tabs": "^1.1.13", "class-variance-authority": "^0.7.1", "lucide-react": "^0.577.0", "motion": "^12.38.0", "next-themes": "^0.4.6", "react-medium-image-zoom": "^5.4.1", "react-remove-scroll": "^2.7.2", "rehype-raw": "^7.0.0", "scroll-into-view-if-needed": "^3.1.0", "tailwind-merge": "^3.5.0", "unist-util-visit": "^5.1.0" }, "peerDependencies": { "@takumi-rs/image-response": "*", "@types/mdx": "*", "@types/react": "*", "fumadocs-core": "16.7.2", "next": "16.x.x", "react": "^19.2.0", "react-dom": "^19.2.0", "shiki": "*" }, "optionalPeers": ["@takumi-rs/image-response", "@types/mdx", "@types/react", "next", "shiki"] }, "sha512-k4/QlWUMEL3WuzdO36gyrVSrr7ePGMhvD5/Zqaoqb8PMun8HWn8sAzg0FnHtWwn4kO6YrIw1puaA2U5vUCH6iA=="],
"get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="],
+7 -1
View File
@@ -7,11 +7,17 @@ icon: Languages
Sofa supports multiple languages for the web and mobile apps. The current supported locales are: Sofa supports multiple languages for the web and mobile apps. The current supported locales are:
- English (source) - English (source)
- Arabic
- Chinese
- Dutch
- French - French
- German - German
- Spanish - Hebrew
- Italian - Italian
- Japanese
- Korean
- Portuguese - Portuguese
- Spanish
You can switch languages in **Settings > Language** on web or the mobile app. Sofa detects your browser or device language on first launch and defaults to it if supported. This setting is **not** saved to the server — it is only persisted to the current browser or device. You can switch languages in **Settings > Language** on web or the mobile app. Sofa detects your browser or device language on first launch and defaults to it if supported. This setting is **not** saved to the server — it is only persisted to the current browser or device.
+3 -3
View File
@@ -16,10 +16,10 @@
"dependencies": { "dependencies": {
"@takumi-rs/image-response": "^0.73.1", "@takumi-rs/image-response": "^0.73.1",
"@vercel/analytics": "^2.0.1", "@vercel/analytics": "^2.0.1",
"fumadocs-core": "^16.7.0", "fumadocs-core": "^16.7.2",
"fumadocs-mdx": "^14.2.11", "fumadocs-mdx": "^14.2.11",
"fumadocs-openapi": "^10.4.0", "fumadocs-openapi": "^10.4.1",
"fumadocs-ui": "^16.7.0", "fumadocs-ui": "^16.7.2",
"lucide-react": "^0.577.0", "lucide-react": "^0.577.0",
"next": "16.2.0", "next": "16.2.0",
"react": "19.2.4", "react": "19.2.4",
+1 -1
View File
@@ -2,7 +2,7 @@ import { defineConfig } from "@lingui/conf";
import { formatter } from "@lingui/format-po"; import { formatter } from "@lingui/format-po";
export default defineConfig({ export default defineConfig({
locales: ["en", "fr", "de", "es", "it", "pt"], locales: ["en", "fr", "de", "es", "it", "pt", "nl", "ar", "he", "zh", "ja", "ko"],
sourceLocale: "en", sourceLocale: "en",
catalogs: [ catalogs: [
{ {
+2 -1
View File
@@ -11,7 +11,7 @@
"@orpc/client": "1.13.9", "@orpc/client": "1.13.9",
"@orpc/contract": "1.13.9", "@orpc/contract": "1.13.9",
"@orpc/tanstack-query": "1.13.9", "@orpc/tanstack-query": "1.13.9",
"@tanstack/react-query": "5.91.2", "@tanstack/react-query": "5.91.3",
"@types/bun": "1.3.11", "@types/bun": "1.3.11",
"@types/node": "25.5.0", "@types/node": "25.5.0",
"@types/react": "19.2.14", "@types/react": "19.2.14",
@@ -52,6 +52,7 @@
"@lingui/cli": "catalog:", "@lingui/cli": "catalog:",
"@lingui/conf": "catalog:", "@lingui/conf": "catalog:",
"@lingui/format-po": "catalog:", "@lingui/format-po": "catalog:",
"eslint-plugin-lingui": "0.11.0",
"oxfmt": "0.41.0", "oxfmt": "0.41.0",
"oxlint": "1.56.0", "oxlint": "1.56.0",
"turbo": "2.8.20", "turbo": "2.8.20",
+13 -13
View File
@@ -518,18 +518,18 @@ for (const locale of locales) {
await translateLocale(locale, model, batchSize, dryRun, contextMap); await translateLocale(locale, model, batchSize, dryRun, contextMap);
} }
if (!dryRun) { // if (!dryRun) {
// Re-extract to restore #. placeholder comments that @lingui/format-po's // // Re-extract to restore #. placeholder comments that @lingui/format-po's
// serialize() strips during the round-trip. // // serialize() strips during the round-trip.
console.log("Re-extracting to restore comments..."); // console.log("Re-extracting to restore comments...");
const extract = Bun.spawn(["bun", "run", "i18n:extract"], { // const extract = Bun.spawn(["bun", "run", "i18n:extract"], {
stdout: "inherit", // stdout: "inherit",
stderr: "inherit", // stderr: "inherit",
}); // });
if ((await extract.exited) !== 0) { // if ((await extract.exited) !== 0) {
console.error("Extraction failed"); // console.error("Extraction failed");
process.exit(1); // process.exit(1);
} // }
} // }
console.log("Done!"); console.log("Done!");
+13 -1
View File
@@ -3,7 +3,13 @@ import { i18n, type Messages } from "@lingui/core";
import type { SupportedLocale } from "./locales"; import type { SupportedLocale } from "./locales";
import { messages as enMessages } from "./po/en.po"; import { messages as enMessages } from "./po/en.po";
export { SUPPORTED_LOCALES, type SupportedLocale } from "./locales"; export {
LOCALE_INFO,
SUPPORTED_LOCALES,
type SupportedLocale,
isLocaleRTL,
getDirection,
} from "./locales";
// English always bundled — zero async on default locale // English always bundled — zero async on default locale
i18n.load("en", enMessages); i18n.load("en", enMessages);
@@ -15,6 +21,12 @@ const loaders: Record<Exclude<SupportedLocale, "en">, () => Promise<{ messages:
es: () => import("./po/es.po"), es: () => import("./po/es.po"),
it: () => import("./po/it.po"), it: () => import("./po/it.po"),
pt: () => import("./po/pt.po"), pt: () => import("./po/pt.po"),
nl: () => import("./po/nl.po"),
ar: () => import("./po/ar.po"),
he: () => import("./po/he.po"),
zh: () => import("./po/zh.po"),
ja: () => import("./po/ja.po"),
ko: () => import("./po/ko.po"),
}; };
export async function activateLocale(locale: SupportedLocale): Promise<void> { export async function activateLocale(locale: SupportedLocale): Promise<void> {
+46 -6
View File
@@ -2,17 +2,57 @@ export interface LocaleInfo {
code: string; code: string;
name: string; name: string;
nativeName: string; nativeName: string;
isRTL: boolean;
} }
export const LOCALE_INFO = [ export const LOCALE_INFO = [
{ code: "en", name: "English", nativeName: "English" }, { code: "en", name: "English", nativeName: "English", isRTL: false },
{ code: "fr", name: "French", nativeName: "Fran\u00e7ais" }, { code: "fr", name: "French", nativeName: "Fran\u00e7ais", isRTL: false },
{ code: "de", name: "German", nativeName: "Deutsch" }, { code: "de", name: "German", nativeName: "Deutsch", isRTL: false },
{ code: "es", name: "Spanish", nativeName: "Espa\u00f1ol" }, { code: "es", name: "Spanish", nativeName: "Espa\u00f1ol", isRTL: false },
{ code: "it", name: "Italian", nativeName: "Italiano" }, { code: "it", name: "Italian", nativeName: "Italiano", isRTL: false },
{ code: "pt", name: "Portuguese", nativeName: "Portugu\u00eas" }, { code: "pt", name: "Portuguese", nativeName: "Portugu\u00eas", isRTL: false },
{ code: "nl", name: "Dutch", nativeName: "Nederlands", isRTL: false },
{
code: "ar",
name: "Arabic",
nativeName: "\u0627\u0644\u0639\u0631\u0628\u064a\u0629",
isRTL: true,
},
{
code: "he",
name: "Hebrew",
nativeName: "\u05e2\u05d1\u05e8\u05d9\u05ea",
isRTL: true,
},
{
code: "zh",
name: "Chinese",
nativeName: "\u4e2d\u6587",
isRTL: false,
},
{
code: "ja",
name: "Japanese",
nativeName: "\u65e5\u672c\u8a9e",
isRTL: false,
},
{
code: "ko",
name: "Korean",
nativeName: "\ud55c\uad6d\uc5b4",
isRTL: false,
},
] as const satisfies readonly LocaleInfo[]; ] as const satisfies readonly LocaleInfo[];
export type SupportedLocale = (typeof LOCALE_INFO)[number]["code"]; export type SupportedLocale = (typeof LOCALE_INFO)[number]["code"];
export const SUPPORTED_LOCALES = LOCALE_INFO.map((l) => l.code) as SupportedLocale[]; export const SUPPORTED_LOCALES = LOCALE_INFO.map((l) => l.code) as SupportedLocale[];
export function isLocaleRTL(code: string): boolean {
return LOCALE_INFO.find((l) => l.code === code)?.isRTL ?? false;
}
export function getDirection(code: string): "ltr" | "rtl" {
return isLocaleRTL(code) ? "rtl" : "ltr";
}
File diff suppressed because it is too large Load Diff
+285 -161
View File
@@ -8,20 +8,23 @@ msgstr ""
"Language: de\n" "Language: de\n"
"Project-Id-Version: sofa\n" "Project-Id-Version: sofa\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-03-19 00:35\n" "PO-Revision-Date: 2026-03-20 23:13\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: German\n" "Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: sofa\n" "X-Crowdin-Project: sofa\n"
"X-Crowdin-Project-ID: 881052\n" "X-Crowdin-Project-ID: 881052\n"
"X-Crowdin-Language: de\n" "X-Crowdin-Language: de\n"
"X-Crowdin-File: en.po\n" "X-Crowdin-File: /packages/i18n/src/po/en.po\n"
"X-Crowdin-File-ID: 14\n" "X-Crowdin-File-ID: 26\n"
#. placeholder {0}: result.errors.length - 50
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "...and {0} more" #~ msgid "...and {0} more"
msgstr "...und {0} weitere" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "...and {remainingErrors} more"
msgstr ""
#. placeholder {0}: systemHealth.data.imageCache.imageCount #. placeholder {0}: systemHealth.data.imageCache.imageCount
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -33,86 +36,99 @@ msgstr "{0, plural, one {# Bild} other {# Bilder}}"
msgid "{0, plural, one {# title} other {# titles}}" msgid "{0, plural, one {# title} other {# titles}}"
msgstr "{0, plural, one {# Titel} other {# Titel}}" msgstr "{0, plural, one {# Titel} other {# Titel}}"
#. placeholder {0}: displayBackups.length
#. placeholder {1}: displayBackups.length
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "{0} {1, plural, one {backup} other {backups}} stored" #~ msgid "{0} {1, plural, one {backup} other {backups}} stored"
msgstr "{0} {1, plural, one {Backup} other {Backups}} gespeichert" #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
#~ msgid "{0} backup{1} stored" #~ msgid "{0} backup{1} stored"
#~ msgstr "{0} backup{1} stored" #~ msgstr "{0} backup{1} stored"
#. placeholder {0}: backups.backupCount
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} backups · last <0/>" #~ msgid "{0} backups · last <0/>"
msgstr "{0} Backups · zuletzt <0/>" #~ msgstr ""
#. placeholder {0}: imageCache.imageCount.toLocaleString()
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} cached images" #~ msgid "{0} cached images"
msgstr "{0} gecachte Bilder" #~ msgstr ""
#. placeholder {0}: member.episodeCount
#. placeholder {1}: member.episodeCount !== 1 ? "s" : ""
#: apps/web/src/components/titles/cast-carousel.tsx #: apps/web/src/components/titles/cast-carousel.tsx
msgid "{0} ep{1}" #~ msgid "{0} ep{1}"
msgstr "{0} Ep{1}" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} images" #~ msgid "{0} images"
#~ msgstr "{0} images" #~ msgstr "{0} images"
#. placeholder {0}: stats.watchlist
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items" #~ msgid "{0} items"
msgstr "{0} Einträge" #~ msgstr ""
#. placeholder {0}: preview.diagnostics.unresolved
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate." #~ msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr "{0} Einträge haben keine externen IDs und werden über die Titelsuche gefunden, was weniger genau sein kann." #~ msgstr ""
#. placeholder {0}: stats.movies
#. placeholder {1}: stats.episodes
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} movies, {1} episodes" #~ msgid "{0} movies, {1} episodes"
msgstr "{0} Filme, {1} Episoden" #~ msgstr ""
#. placeholder {0}: stats.ratings
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} ratings" #~ msgid "{0} ratings"
msgstr "{0} Bewertungen" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} titles" #~ msgid "{0} titles"
#~ msgstr "{0} titles" #~ msgstr "{0} titles"
#. placeholder {0}: JOB_LABELS[name] ?? name
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} triggered" #~ msgid "{0} triggered"
msgstr "{0} ausgelöst" #~ msgstr ""
#. placeholder {0}: item.watchedEpisodes
#. placeholder {1}: item.totalEpisodes
#. placeholder {2}: item.totalEpisodes
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{0}/{1} {2, plural, one {episode} other {episodes}}" #~ msgid "{0}/{1} {2, plural, one {episode} other {episodes}}"
msgstr "{0}/{1} {2, plural, one {Episode} other {Episoden}}" #~ msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
#~ msgid "{0}/{1} episodes" #~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes" #~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/settings/backup-section.tsx
#: apps/web/src/components/titles/use-title-actions.ts msgid "{backupCount, plural, one {# backup} other {# backups}} stored"
msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched" msgstr ""
msgstr "{count} {count, plural, one {frühere Episode} other {frühere Episoden}} noch ungesehen"
#. placeholder {0}: activeJobs.length
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {0} jobs healthy" msgid "{backupCount} backups · last <0/>"
msgstr "{healthyCount} von {0} Jobs fehlerfrei" msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{cachedImageCount} cached images"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "{count, plural, one {# earlier episode} other {# earlier episodes}} unwatched"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
#~ msgstr ""
#: apps/web/src/components/titles/cast-carousel.tsx
msgid "{count} ep{suffix}"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
#~ msgid "{healthyCount} of {0} jobs healthy"
#~ msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {activeJobCount} jobs healthy"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{jobLabel} triggered"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
@@ -129,25 +145,50 @@ msgstr "{label} getrennt"
msgid "{label} URL regenerated" msgid "{label} URL regenerated"
msgstr "{label}-URL neu generiert" msgstr "{label}-URL neu generiert"
#: apps/web/src/components/settings/imports-section.tsx
msgid "{movieCount} movies, {episodeCount} episodes"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{ratingCount} ratings"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{unresolvedCount} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr ""
#: apps/web/src/components/title-card.tsx #: apps/web/src/components/title-card.tsx
msgid "{watched}/{total} episodes" msgid "{watched}/{total} episodes"
msgstr "{watched}/{total} Episoden" msgstr "{watched}/{total} Episoden"
#. placeholder {0}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount} of {0} episodes watched" #~ msgid "{watchedCount} of {0} episodes watched"
msgstr "{watchedCount} von {0} Episoden gesehen" #~ msgstr ""
#. placeholder {0}: episodes.length
#. placeholder {1}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}" msgid "{watchedCount} of {episodeCount} episodes watched"
msgstr "{watchedCount}/{0} {1, plural, one {Episode} other {Episoden}}" msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}"
#~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} episodes" #~ msgid "{watchedCount}/{0} episodes"
#~ msgstr "{watchedCount}/{0} episodes" #~ msgstr "{watchedCount}/{0} episodes"
#: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{episodeCount, plural, one {# episode} other {# episodes}}"
msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{watchedEpisodes}/{totalEpisodes, plural, one {# episode} other {# episodes}}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{watchlistCount} items"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Account" msgid "Account"
@@ -207,7 +248,7 @@ msgstr "Zur Merkliste hinzugefügt"
#: apps/web/src/components/nav-bar.tsx #: apps/web/src/components/nav-bar.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Admin" msgid "Admin"
msgstr "Admin" msgstr ""
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Admin only" msgid "Admin only"
@@ -268,10 +309,13 @@ msgstr "Autorisierung erfolgreich, aber die Bibliothek konnte nicht abgerufen we
msgid "Authorization was denied. Please try again." msgid "Authorization was denied. Please try again."
msgstr "Autorisierung wurde verweigert. Bitte versuche es erneut." msgstr "Autorisierung wurde verweigert. Bitte versuche es erneut."
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {0} library. No password shared." #~ msgid "Authorize Sofa to read your {0} library. No password shared."
msgstr "Sofa autorisieren, deine {0}-Bibliothek zu lesen. Kein Passwort wird geteilt." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {sourceLabel} library. No password shared."
msgstr ""
#: apps/web/src/components/settings/update-check-section.tsx #: apps/web/src/components/settings/update-check-section.tsx
msgid "Automatic update checks" msgid "Automatic update checks"
@@ -295,7 +339,7 @@ msgstr "Hintergrundaufgaben"
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Backup" msgid "Backup"
msgstr "Backup" msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Backup created" msgid "Backup created"
@@ -312,11 +356,11 @@ msgstr "Backup-Zeitplan"
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Backups" msgid "Backups"
msgstr "Backups" msgstr ""
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "backups." msgid "backups."
#~ msgstr "backups." msgstr ""
#: apps/web/src/components/titles/title-availability.tsx #: apps/web/src/components/titles/title-availability.tsx
msgid "Buy" msgid "Buy"
@@ -374,11 +418,13 @@ msgstr "Aufholen"
msgid "Caught Up" msgid "Caught Up"
msgstr "Auf dem Laufenden" msgstr "Auf dem Laufenden"
#. placeholder {0}: episodeIds.length
#. placeholder {1}: episodeIds.length
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched" #~ msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched"
msgstr "Aufgeholt - {0} {1, plural, one {Episode} other {Episoden}} als gesehen markiert" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {count, plural, one {# episode} other {# episodes}} as watched"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
@@ -414,10 +460,13 @@ msgstr "Geprüft <0/>"
msgid "Checking…" msgid "Checking…"
msgstr "Prüfe..." msgstr "Prüfe..."
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {0} data." #~ msgid "Choose how to import your {0} data."
msgstr "Wähle aus, wie du deine {0}-Daten importieren möchtest." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {sourceLabel} data."
msgstr ""
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
#~ msgid "Choose your preferred display language" #~ msgid "Choose your preferred display language"
@@ -480,12 +529,12 @@ msgstr "Neues Passwort bestätigen"
msgid "Connect" msgid "Connect"
msgstr "Verbinden" msgstr "Verbinden"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {0}" #~ msgid "Connect {0}"
msgstr "{0} verbinden" #~ msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {label}" msgid "Connect {label}"
msgstr "{label} verbinden" msgstr "{label} verbinden"
@@ -497,10 +546,13 @@ msgstr "Mit {source} verbinden"
msgid "Connect to TMDB" msgid "Connect to TMDB"
msgstr "Mit TMDB verbinden" msgstr "Mit TMDB verbinden"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {0}" #~ msgid "Connect with {0}"
msgstr "Mit {0} verbinden" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {sourceLabel}"
msgstr ""
#: apps/native/src/app/(auth)/server-url.tsx #: apps/native/src/app/(auth)/server-url.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -596,7 +648,7 @@ msgstr "Gefahrenzone"
#: apps/web/src/routes/_app/titles.$id.tsx #: apps/web/src/routes/_app/titles.$id.tsx
#: apps/web/src/routes/_app/titles.$id.tsx #: apps/web/src/routes/_app/titles.$id.tsx
msgid "Dashboard" msgid "Dashboard"
msgstr "Dashboard" msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
@@ -740,11 +792,11 @@ msgstr "Umgebung"
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#~ msgid "Episode {0}" #~ msgid "Episode {0}"
#~ msgstr "Folge {0}" #~ msgstr ""
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#~ msgid "Episode {0}, {episodeLabel}" #~ msgid "Episode {0}, {episodeLabel}"
#~ msgstr "Folge {0}, {episodeLabel}" #~ msgstr ""
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
@@ -770,10 +822,13 @@ msgstr "Episode als gesehen markiert"
msgid "Episodes" msgid "Episodes"
msgstr "Episoden" msgstr "Episoden"
#. placeholder {0}: periodLabels[episodePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {0}" #~ msgid "Episodes {0}"
msgstr "Folgen {0}" #~ msgstr "Episodes {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {period}"
msgstr ""
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Episodes {periodSelect}" #~ msgid "Episodes {periodSelect}"
@@ -785,17 +840,20 @@ msgstr "Episoden {select}"
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#~ msgid "Episodes this week" #~ msgid "Episodes this week"
#~ msgstr "Episoden diese Woche" #~ msgstr ""
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
msgid "Error" msgid "Error"
msgstr "Fehler" msgstr "Fehler"
#. placeholder {0}: result.errors.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({0})" #~ msgid "Errors ({0})"
msgstr "Fehler ({0})" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({errorCount})"
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
@@ -923,10 +981,13 @@ msgstr "Profilbild konnte nicht entfernt werden"
msgid "Failed to sign in" msgid "Failed to sign in"
msgstr "Anmeldung fehlgeschlagen" msgstr "Anmeldung fehlgeschlagen"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {0} connection" #~ msgid "Failed to start {0} connection"
msgstr "{0}-Verbindung konnte nicht gestartet werden" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {sourceLabel} connection"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Failed to trigger job" msgid "Failed to trigger job"
@@ -1072,7 +1133,7 @@ msgstr "Speichernutzung für Bild-Cache und Backups"
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import" msgid "Import"
msgstr "Import" msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import {totalItems} items" msgid "Import {totalItems} items"
@@ -1086,15 +1147,18 @@ msgstr "Import abgeschlossen"
msgid "Import failed" msgid "Import failed"
msgstr "Import fehlgeschlagen" msgstr "Import fehlgeschlagen"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {0}" #~ msgid "Import from {0}"
msgstr "Von {0} importieren" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {source}" msgid "Import from {source}"
msgstr "Von {source} importieren" msgstr "Von {source} importieren"
#: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {sourceLabel}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import is still running in the background. Check back later." msgid "Import is still running in the background. Check back later."
@@ -1108,11 +1172,13 @@ msgstr "Importoptionen"
msgid "Imported" msgid "Imported"
msgstr "Importiert" msgstr "Importiert"
#. placeholder {0}: event.job.importedCount
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {0} items from {1}" #~ msgid "Imported {0} items from {1}"
msgstr "{0} Einträge von {1} importiert" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {importedCount} items from {sourceLabel}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Importing from {source}" msgid "Importing from {source}"
@@ -1158,14 +1224,12 @@ msgid "Job"
msgstr "Aufgabe" msgstr "Aufgabe"
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "Keeping" msgid "Keeping"
#~ msgstr "Keeping" msgstr ""
#. placeholder {0}: (value: string | null) => value === "0" ? t`unlimited` : value ? t`last ${value}` : null
#. placeholder {1}: [3, 5, 7, 14, 30, 0].map((n) => ( <SelectItem key={n} value={String(n)}> {n === 0 ? t`unlimited` : t`last ${n}`} </SelectItem> ))
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups." #~ msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups."
msgstr "<0><1><2>{0}</2></1><3>{1}</3></0> Backups werden aufbewahrt." #~ msgstr ""
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
@@ -1186,19 +1250,25 @@ msgstr "letzte {n}"
msgid "last {value}" msgid "last {value}"
msgstr "letzte {value}" msgstr "letzte {value}"
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {0}" #~ msgid "Last event {0}"
msgstr "Letztes Ereignis {0}" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {relativeTime}"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last event {timeAgo}" msgid "Last event {timeAgo}"
msgstr "Letztes Ereignis {timeAgo}" msgstr "Letztes Ereignis {timeAgo}"
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {0}" #~ msgid "Last polled {0}"
msgstr "Zuletzt abgefragt {0}" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {relativeTime}"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last polled {timeAgo}" msgid "Last polled {timeAgo}"
@@ -1249,7 +1319,7 @@ msgstr "Alle als gesehen markieren"
#: apps/native/src/components/dashboard/continue-watching-card.tsx #: apps/native/src/components/dashboard/continue-watching-card.tsx
#~ msgid "Mark as Completed" #~ msgid "Mark as Completed"
#~ msgstr "Als abgeschlossen markieren" #~ msgstr ""
#: apps/native/src/components/ui/poster-card.tsx #: apps/native/src/components/ui/poster-card.tsx
msgid "Mark as Watched" msgid "Mark as Watched"
@@ -1257,7 +1327,7 @@ msgstr "Als gesehen markieren"
#: apps/native/src/components/ui/poster-card.tsx #: apps/native/src/components/ui/poster-card.tsx
#~ msgid "Mark as Watching" #~ msgid "Mark as Watching"
#~ msgstr "Als am Schauen markieren" #~ msgstr ""
#: apps/native/src/app/title/[id].tsx #: apps/native/src/app/title/[id].tsx
#: apps/web/src/components/titles/title-actions.tsx #: apps/web/src/components/titles/title-actions.tsx
@@ -1266,7 +1336,7 @@ msgstr "Als gesehen markieren"
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked \"{titleName}\" as completed" #~ msgid "Marked \"{titleName}\" as completed"
#~ msgstr "\"{titleName}\" als abgeschlossen markiert" #~ msgstr ""
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
@@ -1285,7 +1355,7 @@ msgstr "Alle Folgen von \"{titleName}\" als gesehen markiert"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked as completed" #~ msgid "Marked as completed"
#~ msgstr "Als abgeschlossen markiert" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -1295,7 +1365,7 @@ msgstr "Als gesehen markiert"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked as watching" #~ msgid "Marked as watching"
#~ msgstr "Als am Schauen markiert" #~ msgstr ""
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Member since {memberSince}" msgid "Member since {memberSince}"
@@ -1327,10 +1397,13 @@ msgstr "Film"
msgid "Movies" msgid "Movies"
msgstr "Filme" msgstr "Filme"
#. placeholder {0}: periodLabels[moviePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {0}" #~ msgid "Movies {0}"
msgstr "Filme {0}" #~ msgstr "Movies {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {period}"
msgstr ""
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Movies {periodSelect}" #~ msgid "Movies {periodSelect}"
@@ -1342,12 +1415,12 @@ msgstr "Filme {select}"
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#~ msgid "Movies this month" #~ msgid "Movies this month"
#~ msgstr "Filme diesen Monat" #~ msgstr ""
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
msgid "Name" msgid "Name"
msgstr "Name" msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
@@ -1540,7 +1613,7 @@ msgstr "GitHub regelmäßig auf neue Sofa-Versionen prüfen"
#: apps/native/src/components/search/search-result-row.tsx #: apps/native/src/components/search/search-result-row.tsx
#: apps/native/src/components/search/search-result-row.tsx #: apps/native/src/components/search/search-result-row.tsx
msgid "Person" msgid "Person"
msgstr "Person" msgstr ""
#: apps/native/src/app/person/[id].tsx #: apps/native/src/app/person/[id].tsx
#: apps/web/src/routes/_app/people.$id.tsx #: apps/web/src/routes/_app/people.$id.tsx
@@ -1635,20 +1708,23 @@ msgstr "Schnellaktionen"
msgid "Radarr List URL" msgid "Radarr List URL"
msgstr "Radarr-Listen-URL" msgstr "Radarr-Listen-URL"
#. placeholder {0}: input.stars
#. placeholder {1}: input.stars
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
msgid "Rated {0} {1, plural, one {star} other {stars}}" #~ msgid "Rated {0} {1, plural, one {star} other {stars}}"
msgstr "{0} {1, plural, one {Stern} other {Sterne}} bewertet" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#~ msgid "Rated {0} star{1}" #~ msgid "Rated {0} star{1}"
#~ msgstr "Rated {0} star{1}" #~ msgstr "Rated {0} star{1}"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}" msgid "Rated {ratingStars, plural, one {# star} other {# stars}}"
msgstr "{ratingStars} {ratingStars, plural, one {Stern} other {Sterne}} bewertet" msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}"
#~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
msgid "Rated {stars, plural, one {# star} other {# stars}}" msgid "Rated {stars, plural, one {# star} other {# stars}}"
msgstr "{stars, plural, one {# Stern} other {# Sterne}} vergeben" msgstr "{stars, plural, one {# Stern} other {# Sterne}} vergeben"
@@ -1810,6 +1886,14 @@ msgstr "Erfordert ein aktives Plex Pass-Abonnement."
msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license." msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license."
msgstr "Erfordert Emby Server 4.7.9+ und eine aktive Emby Premiere-Lizenz." msgstr "Erfordert Emby Server 4.7.9+ und eine aktive Emby Premiere-Lizenz."
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart Required"
msgstr ""
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
msgid "Restore" msgid "Restore"
@@ -1921,13 +2005,19 @@ msgstr "Filme, Serien, Personen suchen..."
msgid "Search…" msgid "Search…"
msgstr "Suchen..." msgstr "Suchen..."
#. placeholder {0}: season.seasonNumber
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {0}" #~ msgid "Season {0}"
msgstr "Staffel {0}" #~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {seasonNumber}"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -1949,7 +2039,7 @@ msgstr "Selbstgehosteter Film- & Serien-Tracker"
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Server" msgid "Server"
msgstr "Server" msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Server Health" msgid "Server Health"
@@ -2018,12 +2108,18 @@ msgstr "Stattdessen anmelden"
msgid "Sign in to continue" msgid "Sign in to continue"
msgstr "Anmelden, um fortzufahren" msgstr "Anmelden, um fortzufahren"
#. placeholder {0}: authConfig.data?.oidcProviderName ?? "SSO"
#. placeholder {0}: authConfig?.oidcProviderName || "SSO"
#: apps/native/src/app/(auth)/login.tsx #: apps/native/src/app/(auth)/login.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
msgid "Sign in with {0}" #~ msgid "Sign in with {0}"
msgstr "Mit {0} anmelden" #~ msgstr ""
#: apps/web/src/components/auth-form.tsx
msgid "Sign in with {oidcProviderName}"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
msgid "Sign in with {providerName}"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/components/header-avatar.tsx #: apps/native/src/components/header-avatar.tsx
@@ -2048,10 +2144,17 @@ msgstr "Von anderen Sitzungen abmelden"
msgid "Skipped" msgid "Skipped"
msgstr "Übersprungen" msgstr "Übersprungen"
#. placeholder {0}: data.latestVersion #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Sofa needs to restart to apply the new layout direction."
msgstr ""
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "Sofa v{0} is available" #~ msgid "Sofa v{0} is available"
msgstr "Sofa v{0} ist verfügbar" #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "Sofa v{latestVersion} is available"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2118,10 +2221,13 @@ msgstr "Streamen"
msgid "Sunday" msgid "Sunday"
msgstr "Sonntag" msgstr "Sonntag"
#. placeholder {0}: info.name
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {0}" #~ msgid "Switch to {0}"
msgstr "Zu {0} wechseln" #~ msgstr ""
#: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {name}"
msgstr ""
#: apps/native/src/app/+not-found.tsx #: apps/native/src/app/+not-found.tsx
msgid "The page you're looking for doesn't exist." msgid "The page you're looking for doesn't exist."
@@ -2192,10 +2298,13 @@ msgstr "Dadurch wird die aktuelle {label}-URL ungültig. Du musst sie in {label}
msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons." msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons."
msgstr "Dadurch werden alle Episoden dieser Serie als gesehen markiert. Du kannst dies später rückgängig machen, indem du einzelne Staffeln abwählst." msgstr "Dadurch werden alle Episoden dieser Serie als gesehen markiert. Du kannst dies später rückgängig machen, indem du einzelne Staffeln abwählst."
#. placeholder {0}: formatBackupDate(backup.createdAt)
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone." #~ msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone."
msgstr "Dadurch wird das Backup vom <0>{0}</0> dauerhaft gelöscht. Dies kann nicht rückgängig gemacht werden." #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{backupDate}</0>. This cannot be undone."
msgstr ""
#: apps/native/src/components/search/recently-viewed-list.ios.tsx #: apps/native/src/components/search/recently-viewed-list.ios.tsx
#: apps/native/src/components/search/recently-viewed-list.tsx #: apps/native/src/components/search/recently-viewed-list.tsx
@@ -2266,7 +2375,7 @@ msgstr "Verfolge, was du schaust. Wisse, was als Nächstes kommt.<0/>Deine Bibli
#: apps/web/src/components/titles/trailer-dialog.tsx #: apps/web/src/components/titles/trailer-dialog.tsx
#: apps/web/src/components/titles/trailer-dialog.tsx #: apps/web/src/components/titles/trailer-dialog.tsx
msgid "Trailer" msgid "Trailer"
msgstr "Trailer" msgstr ""
#: apps/web/src/components/explore/hero-banner.tsx #: apps/web/src/components/explore/hero-banner.tsx
msgid "Trending today" msgid "Trending today"
@@ -2327,10 +2436,13 @@ msgstr "Ohne Titel"
msgid "Unwatch all" msgid "Unwatch all"
msgstr "Alle als ungesehen markieren" msgstr "Alle als ungesehen markieren"
#. placeholder {0}: season.name ?? t`Season ${season.seasonNumber}`
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {0}" #~ msgid "Unwatched all of {0}"
msgstr "Alle Episoden von {0} als ungesehen markiert" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {seasonLabel}"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched S{seasonNum} E{epNum}" msgid "Unwatched S{seasonNum} E{epNum}"
@@ -2341,10 +2453,13 @@ msgstr "S{seasonNum} E{epNum} als ungesehen markiert"
msgid "Up next" msgid "Up next"
msgstr "Als Nächstes" msgstr "Als Nächstes"
#. placeholder {0}: updateCheck.data.updateCheck.latestVersion
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {0}" #~ msgid "Update available: {0}"
msgstr "Update verfügbar: {0}" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {latestVersion}"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Update check" msgid "Update check"
@@ -2381,11 +2496,13 @@ msgstr "Hochladen"
msgid "Upload a .db file to replace the current database. A safety backup is created first." msgid "Upload a .db file to replace the current database. A safety backup is created first."
msgstr "Lade eine .db-Datei hoch, um die aktuelle Datenbank zu ersetzen. Zuerst wird ein Sicherheits-Backup erstellt." msgstr "Lade eine .db-Datei hoch, um die aktuelle Datenbank zu ersetzen. Zuerst wird ein Sicherheits-Backup erstellt."
#. placeholder {0}: config.accept
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {0} export from your {1} account settings." #~ msgid "Upload a {0} export from your {1} account settings."
msgstr "Lade einen {0}-Export aus deinen {1}-Kontoeinstellungen hoch." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {acceptFormat} export from your {sourceLabel} account settings."
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload export file" msgid "Upload export file"
@@ -2419,10 +2536,13 @@ msgstr "Warte auf Autorisierung..."
msgid "Warnings" msgid "Warnings"
msgstr "Warnungen" msgstr "Warnungen"
#. placeholder {0}: result.warnings.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({0})" #~ msgid "Warnings ({0})"
msgstr "Warnungen ({0})" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({warningCount})"
msgstr ""
#: apps/web/src/components/titles/title-seasons.tsx #: apps/web/src/components/titles/title-seasons.tsx
msgid "Watch all" msgid "Watch all"
@@ -2465,7 +2585,7 @@ msgstr "Merkliste"
#: apps/native/src/components/titles/status-action-button.tsx #: apps/native/src/components/titles/status-action-button.tsx
#~ msgid "Watchlisted" #~ msgid "Watchlisted"
#~ msgstr "Auf Merkliste" #~ msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2505,10 +2625,13 @@ msgstr "Autor"
msgid "You'll be signed out to change the server URL." msgid "You'll be signed out to change the server URL."
msgstr "Du wirst abgemeldet, um die Server-URL zu ändern." msgstr "Du wirst abgemeldet, um die Server-URL zu ändern."
#. placeholder {0}: data.currentVersion
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "You're running v{0}." #~ msgid "You're running v{0}."
msgstr "Du verwendest v{0}." #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "You're running v{currentVersion}."
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Your code:" msgid "Your code:"
@@ -2522,3 +2645,4 @@ msgstr "Deine Bibliothek ist leer"
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
msgid "Your name" msgid "Your name"
msgstr "Dein Name" msgstr "Dein Name"
+262 -139
View File
@@ -18,10 +18,13 @@ msgstr ""
"X-Crowdin-File: /packages/i18n/src/po/en.po\n" "X-Crowdin-File: /packages/i18n/src/po/en.po\n"
"X-Crowdin-File-ID: 12\n" "X-Crowdin-File-ID: 12\n"
#. placeholder {0}: result.errors.length - 50
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "...and {0} more" #~ msgid "...and {0} more"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "...and {remainingErrors} more"
msgstr "...and {remainingErrors} more"
#. placeholder {0}: systemHealth.data.imageCache.imageCount #. placeholder {0}: systemHealth.data.imageCache.imageCount
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -33,86 +36,99 @@ msgstr ""
msgid "{0, plural, one {# title} other {# titles}}" msgid "{0, plural, one {# title} other {# titles}}"
msgstr "" msgstr ""
#. placeholder {0}: displayBackups.length
#. placeholder {1}: displayBackups.length
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "{0} {1, plural, one {backup} other {backups}} stored" #~ msgid "{0} {1, plural, one {backup} other {backups}} stored"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
#~ msgid "{0} backup{1} stored" #~ msgid "{0} backup{1} stored"
#~ msgstr "{0} backup{1} stored" #~ msgstr "{0} backup{1} stored"
#. placeholder {0}: backups.backupCount
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} backups · last <0/>" #~ msgid "{0} backups · last <0/>"
msgstr "" #~ msgstr ""
#. placeholder {0}: imageCache.imageCount.toLocaleString()
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} cached images" #~ msgid "{0} cached images"
msgstr "" #~ msgstr ""
#. placeholder {0}: member.episodeCount
#. placeholder {1}: member.episodeCount !== 1 ? "s" : ""
#: apps/web/src/components/titles/cast-carousel.tsx #: apps/web/src/components/titles/cast-carousel.tsx
msgid "{0} ep{1}" #~ msgid "{0} ep{1}"
msgstr "" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} images" #~ msgid "{0} images"
#~ msgstr "{0} images" #~ msgstr "{0} images"
#. placeholder {0}: stats.watchlist
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items" #~ msgid "{0} items"
msgstr "" #~ msgstr ""
#. placeholder {0}: preview.diagnostics.unresolved
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate." #~ msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr "" #~ msgstr ""
#. placeholder {0}: stats.movies
#. placeholder {1}: stats.episodes
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} movies, {1} episodes" #~ msgid "{0} movies, {1} episodes"
msgstr "" #~ msgstr ""
#. placeholder {0}: stats.ratings
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} ratings" #~ msgid "{0} ratings"
msgstr "" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} titles" #~ msgid "{0} titles"
#~ msgstr "{0} titles" #~ msgstr "{0} titles"
#. placeholder {0}: JOB_LABELS[name] ?? name
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} triggered" #~ msgid "{0} triggered"
msgstr "" #~ msgstr ""
#. placeholder {0}: item.watchedEpisodes
#. placeholder {1}: item.totalEpisodes
#. placeholder {2}: item.totalEpisodes
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{0}/{1} {2, plural, one {episode} other {episodes}}" #~ msgid "{0}/{1} {2, plural, one {episode} other {episodes}}"
msgstr "" #~ msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
#~ msgid "{0}/{1} episodes" #~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes" #~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/settings/backup-section.tsx
#: apps/web/src/components/titles/use-title-actions.ts msgid "{backupCount, plural, one {# backup} other {# backups}} stored"
msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched" msgstr "{backupCount, plural, one {# backup} other {# backups}} stored"
msgstr ""
#. placeholder {0}: activeJobs.length
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {0} jobs healthy" msgid "{backupCount} backups · last <0/>"
msgstr "" msgstr "{backupCount} backups · last <0/>"
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{cachedImageCount} cached images"
msgstr "{cachedImageCount} cached images"
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "{count, plural, one {# earlier episode} other {# earlier episodes}} unwatched"
msgstr "{count, plural, one {# earlier episode} other {# earlier episodes}} unwatched"
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
#~ msgstr ""
#: apps/web/src/components/titles/cast-carousel.tsx
msgid "{count} ep{suffix}"
msgstr "{count} ep{suffix}"
#: apps/web/src/components/settings/system-health-section.tsx
#~ msgid "{healthyCount} of {0} jobs healthy"
#~ msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {activeJobCount} jobs healthy"
msgstr "{healthyCount} of {activeJobCount} jobs healthy"
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{jobLabel} triggered"
msgstr "{jobLabel} triggered"
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
@@ -129,25 +145,50 @@ msgstr ""
msgid "{label} URL regenerated" msgid "{label} URL regenerated"
msgstr "" msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{movieCount} movies, {episodeCount} episodes"
msgstr "{movieCount} movies, {episodeCount} episodes"
#: apps/web/src/components/settings/imports-section.tsx
msgid "{ratingCount} ratings"
msgstr "{ratingCount} ratings"
#: apps/web/src/components/settings/imports-section.tsx
msgid "{unresolvedCount} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr "{unresolvedCount} items have no external IDs and will be resolved by title search, which may be less accurate."
#: apps/web/src/components/title-card.tsx #: apps/web/src/components/title-card.tsx
msgid "{watched}/{total} episodes" msgid "{watched}/{total} episodes"
msgstr "" msgstr ""
#. placeholder {0}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount} of {0} episodes watched" #~ msgid "{watchedCount} of {0} episodes watched"
msgstr "" #~ msgstr ""
#. placeholder {0}: episodes.length
#. placeholder {1}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}" msgid "{watchedCount} of {episodeCount} episodes watched"
msgstr "" msgstr "{watchedCount} of {episodeCount} episodes watched"
#: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}"
#~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} episodes" #~ msgid "{watchedCount}/{0} episodes"
#~ msgstr "{watchedCount}/{0} episodes" #~ msgstr "{watchedCount}/{0} episodes"
#: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{episodeCount, plural, one {# episode} other {# episodes}}"
msgstr "{watchedCount}/{episodeCount, plural, one {# episode} other {# episodes}}"
#: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{watchedEpisodes}/{totalEpisodes, plural, one {# episode} other {# episodes}}"
msgstr "{watchedEpisodes}/{totalEpisodes, plural, one {# episode} other {# episodes}}"
#: apps/web/src/components/settings/imports-section.tsx
msgid "{watchlistCount} items"
msgstr "{watchlistCount} items"
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Account" msgid "Account"
@@ -268,10 +309,13 @@ msgstr ""
msgid "Authorization was denied. Please try again." msgid "Authorization was denied. Please try again."
msgstr "" msgstr ""
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {0} library. No password shared." #~ msgid "Authorize Sofa to read your {0} library. No password shared."
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {sourceLabel} library. No password shared."
msgstr "Authorize Sofa to read your {sourceLabel} library. No password shared."
#: apps/web/src/components/settings/update-check-section.tsx #: apps/web/src/components/settings/update-check-section.tsx
msgid "Automatic update checks" msgid "Automatic update checks"
@@ -315,8 +359,8 @@ msgid "Backups"
msgstr "" msgstr ""
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "backups." msgid "backups."
#~ msgstr "backups." msgstr "backups."
#: apps/web/src/components/titles/title-availability.tsx #: apps/web/src/components/titles/title-availability.tsx
msgid "Buy" msgid "Buy"
@@ -374,11 +418,13 @@ msgstr ""
msgid "Caught Up" msgid "Caught Up"
msgstr "Caught Up" msgstr "Caught Up"
#. placeholder {0}: episodeIds.length
#. placeholder {1}: episodeIds.length
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched" #~ msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched"
msgstr "" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {count, plural, one {# episode} other {# episodes}} as watched"
msgstr "Caught up — marked {count, plural, one {# episode} other {# episodes}} as watched"
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
@@ -414,10 +460,13 @@ msgstr ""
msgid "Checking…" msgid "Checking…"
msgstr "" msgstr ""
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {0} data." #~ msgid "Choose how to import your {0} data."
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {sourceLabel} data."
msgstr "Choose how to import your {sourceLabel} data."
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
#~ msgid "Choose your preferred display language" #~ msgid "Choose your preferred display language"
@@ -480,12 +529,12 @@ msgstr ""
msgid "Connect" msgid "Connect"
msgstr "" msgstr ""
#. placeholder {0}: config.label
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {0}" #~ msgid "Connect {0}"
msgstr "" #~ msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {label}" msgid "Connect {label}"
msgstr "" msgstr ""
@@ -497,10 +546,13 @@ msgstr ""
msgid "Connect to TMDB" msgid "Connect to TMDB"
msgstr "" msgstr ""
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {0}" #~ msgid "Connect with {0}"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {sourceLabel}"
msgstr "Connect with {sourceLabel}"
#: apps/native/src/app/(auth)/server-url.tsx #: apps/native/src/app/(auth)/server-url.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -770,10 +822,13 @@ msgstr ""
msgid "Episodes" msgid "Episodes"
msgstr "" msgstr ""
#. placeholder {0}: periodLabels[episodePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {0}" #~ msgid "Episodes {0}"
msgstr "Episodes {0}" #~ msgstr "Episodes {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {period}"
msgstr "Episodes {period}"
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Episodes {periodSelect}" #~ msgid "Episodes {periodSelect}"
@@ -792,10 +847,13 @@ msgstr ""
msgid "Error" msgid "Error"
msgstr "" msgstr ""
#. placeholder {0}: result.errors.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({0})" #~ msgid "Errors ({0})"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({errorCount})"
msgstr "Errors ({errorCount})"
#: 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
@@ -923,10 +981,13 @@ msgstr ""
msgid "Failed to sign in" msgid "Failed to sign in"
msgstr "" msgstr ""
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {0} connection" #~ msgid "Failed to start {0} connection"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {sourceLabel} connection"
msgstr "Failed to start {sourceLabel} connection"
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Failed to trigger job" msgid "Failed to trigger job"
@@ -1086,15 +1147,18 @@ msgstr ""
msgid "Import failed" msgid "Import failed"
msgstr "" msgstr ""
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {0}" #~ msgid "Import from {0}"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {source}" msgid "Import from {source}"
msgstr "" msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {sourceLabel}"
msgstr "Import from {sourceLabel}"
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import is still running in the background. Check back later." msgid "Import is still running in the background. Check back later."
@@ -1108,11 +1172,13 @@ msgstr ""
msgid "Imported" msgid "Imported"
msgstr "" msgstr ""
#. placeholder {0}: event.job.importedCount
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {0} items from {1}" #~ msgid "Imported {0} items from {1}"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {importedCount} items from {sourceLabel}"
msgstr "Imported {importedCount} items from {sourceLabel}"
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Importing from {source}" msgid "Importing from {source}"
@@ -1158,14 +1224,12 @@ msgid "Job"
msgstr "" msgstr ""
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "Keeping" msgid "Keeping"
#~ msgstr "Keeping" msgstr "Keeping"
#. placeholder {0}: (value: string | null) => value === "0" ? t`unlimited` : value ? t`last ${value}` : null
#. placeholder {1}: [3, 5, 7, 14, 30, 0].map((n) => ( <SelectItem key={n} value={String(n)}> {n === 0 ? t`unlimited` : t`last ${n}`} </SelectItem> ))
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups." #~ msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups."
msgstr "" #~ msgstr ""
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
@@ -1186,19 +1250,25 @@ msgstr ""
msgid "last {value}" msgid "last {value}"
msgstr "" msgstr ""
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {0}" #~ msgid "Last event {0}"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {relativeTime}"
msgstr "Last event {relativeTime}"
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last event {timeAgo}" msgid "Last event {timeAgo}"
msgstr "" msgstr ""
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {0}" #~ msgid "Last polled {0}"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {relativeTime}"
msgstr "Last polled {relativeTime}"
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last polled {timeAgo}" msgid "Last polled {timeAgo}"
@@ -1327,10 +1397,13 @@ msgstr ""
msgid "Movies" msgid "Movies"
msgstr "" msgstr ""
#. placeholder {0}: periodLabels[moviePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {0}" #~ msgid "Movies {0}"
msgstr "Movies {0}" #~ msgstr "Movies {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {period}"
msgstr "Movies {period}"
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Movies {periodSelect}" #~ msgid "Movies {periodSelect}"
@@ -1635,20 +1708,23 @@ msgstr ""
msgid "Radarr List URL" msgid "Radarr List URL"
msgstr "" msgstr ""
#. placeholder {0}: input.stars
#. placeholder {1}: input.stars
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
msgid "Rated {0} {1, plural, one {star} other {stars}}" #~ msgid "Rated {0} {1, plural, one {star} other {stars}}"
msgstr "" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#~ msgid "Rated {0} star{1}" #~ msgid "Rated {0} star{1}"
#~ msgstr "Rated {0} star{1}" #~ msgstr "Rated {0} star{1}"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}" msgid "Rated {ratingStars, plural, one {# star} other {# stars}}"
msgstr "" msgstr "Rated {ratingStars, plural, one {# star} other {# stars}}"
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}"
#~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
msgid "Rated {stars, plural, one {# star} other {# stars}}" msgid "Rated {stars, plural, one {# star} other {# stars}}"
msgstr "" msgstr ""
@@ -1810,6 +1886,14 @@ msgstr ""
msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license." msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license."
msgstr "" msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart"
msgstr "Restart"
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart Required"
msgstr "Restart Required"
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
msgid "Restore" msgid "Restore"
@@ -1921,13 +2005,19 @@ msgstr ""
msgid "Search…" msgid "Search…"
msgstr "" msgstr ""
#. placeholder {0}: season.seasonNumber
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {0}" #~ msgid "Season {0}"
msgstr "" #~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {seasonNumber}"
msgstr "Season {seasonNumber}"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -2018,12 +2108,18 @@ msgstr ""
msgid "Sign in to continue" msgid "Sign in to continue"
msgstr "" msgstr ""
#. placeholder {0}: authConfig.data?.oidcProviderName ?? "SSO"
#. placeholder {0}: authConfig?.oidcProviderName || "SSO"
#: apps/native/src/app/(auth)/login.tsx #: apps/native/src/app/(auth)/login.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
msgid "Sign in with {0}" #~ msgid "Sign in with {0}"
msgstr "" #~ msgstr ""
#: apps/web/src/components/auth-form.tsx
msgid "Sign in with {oidcProviderName}"
msgstr "Sign in with {oidcProviderName}"
#: apps/native/src/app/(auth)/login.tsx
msgid "Sign in with {providerName}"
msgstr "Sign in with {providerName}"
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/components/header-avatar.tsx #: apps/native/src/components/header-avatar.tsx
@@ -2048,10 +2144,17 @@ msgstr ""
msgid "Skipped" msgid "Skipped"
msgstr "" msgstr ""
#. placeholder {0}: data.latestVersion #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Sofa needs to restart to apply the new layout direction."
msgstr "Sofa needs to restart to apply the new layout direction."
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "Sofa v{0} is available" #~ msgid "Sofa v{0} is available"
msgstr "" #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "Sofa v{latestVersion} is available"
msgstr "Sofa v{latestVersion} is available"
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2118,10 +2221,13 @@ msgstr ""
msgid "Sunday" msgid "Sunday"
msgstr "" msgstr ""
#. placeholder {0}: info.name
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {0}" #~ msgid "Switch to {0}"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {name}"
msgstr "Switch to {name}"
#: apps/native/src/app/+not-found.tsx #: apps/native/src/app/+not-found.tsx
msgid "The page you're looking for doesn't exist." msgid "The page you're looking for doesn't exist."
@@ -2192,10 +2298,13 @@ msgstr ""
msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons." msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons."
msgstr "" msgstr ""
#. placeholder {0}: formatBackupDate(backup.createdAt)
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone." #~ msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone."
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{backupDate}</0>. This cannot be undone."
msgstr "This will permanently delete the backup from <0>{backupDate}</0>. This cannot be undone."
#: apps/native/src/components/search/recently-viewed-list.ios.tsx #: apps/native/src/components/search/recently-viewed-list.ios.tsx
#: apps/native/src/components/search/recently-viewed-list.tsx #: apps/native/src/components/search/recently-viewed-list.tsx
@@ -2327,10 +2436,13 @@ msgstr ""
msgid "Unwatch all" msgid "Unwatch all"
msgstr "" msgstr ""
#. placeholder {0}: season.name ?? t`Season ${season.seasonNumber}`
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {0}" #~ msgid "Unwatched all of {0}"
msgstr "" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {seasonLabel}"
msgstr "Unwatched all of {seasonLabel}"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched S{seasonNum} E{epNum}" msgid "Unwatched S{seasonNum} E{epNum}"
@@ -2341,10 +2453,13 @@ msgstr ""
msgid "Up next" msgid "Up next"
msgstr "" msgstr ""
#. placeholder {0}: updateCheck.data.updateCheck.latestVersion
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {0}" #~ msgid "Update available: {0}"
msgstr "" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {latestVersion}"
msgstr "Update available: {latestVersion}"
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Update check" msgid "Update check"
@@ -2381,11 +2496,13 @@ msgstr ""
msgid "Upload a .db file to replace the current database. A safety backup is created first." msgid "Upload a .db file to replace the current database. A safety backup is created first."
msgstr "" msgstr ""
#. placeholder {0}: config.accept
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {0} export from your {1} account settings." #~ msgid "Upload a {0} export from your {1} account settings."
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {acceptFormat} export from your {sourceLabel} account settings."
msgstr "Upload a {acceptFormat} export from your {sourceLabel} account settings."
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload export file" msgid "Upload export file"
@@ -2419,10 +2536,13 @@ msgstr ""
msgid "Warnings" msgid "Warnings"
msgstr "" msgstr ""
#. placeholder {0}: result.warnings.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({0})" #~ msgid "Warnings ({0})"
msgstr "" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({warningCount})"
msgstr "Warnings ({warningCount})"
#: apps/web/src/components/titles/title-seasons.tsx #: apps/web/src/components/titles/title-seasons.tsx
msgid "Watch all" msgid "Watch all"
@@ -2505,10 +2625,13 @@ msgstr ""
msgid "You'll be signed out to change the server URL." msgid "You'll be signed out to change the server URL."
msgstr "" msgstr ""
#. placeholder {0}: data.currentVersion
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "You're running v{0}." #~ msgid "You're running v{0}."
msgstr "" #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "You're running v{currentVersion}."
msgstr "You're running v{currentVersion}."
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Your code:" msgid "Your code:"
+281 -157
View File
@@ -8,20 +8,23 @@ msgstr ""
"Language: es\n" "Language: es\n"
"Project-Id-Version: sofa\n" "Project-Id-Version: sofa\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-03-19 00:35\n" "PO-Revision-Date: 2026-03-20 23:13\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Spanish\n" "Language-Team: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: sofa\n" "X-Crowdin-Project: sofa\n"
"X-Crowdin-Project-ID: 881052\n" "X-Crowdin-Project-ID: 881052\n"
"X-Crowdin-Language: es-ES\n" "X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: en.po\n" "X-Crowdin-File: /packages/i18n/src/po/en.po\n"
"X-Crowdin-File-ID: 14\n" "X-Crowdin-File-ID: 26\n"
#. placeholder {0}: result.errors.length - 50
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "...and {0} more" #~ msgid "...and {0} more"
msgstr "...y {0} más" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "...and {remainingErrors} more"
msgstr ""
#. placeholder {0}: systemHealth.data.imageCache.imageCount #. placeholder {0}: systemHealth.data.imageCache.imageCount
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -33,86 +36,99 @@ msgstr "{0, plural, one {# imagen} other {# imágenes}}"
msgid "{0, plural, one {# title} other {# titles}}" msgid "{0, plural, one {# title} other {# titles}}"
msgstr "{0, plural, one {# título} other {# títulos}}" msgstr "{0, plural, one {# título} other {# títulos}}"
#. placeholder {0}: displayBackups.length
#. placeholder {1}: displayBackups.length
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "{0} {1, plural, one {backup} other {backups}} stored" #~ msgid "{0} {1, plural, one {backup} other {backups}} stored"
msgstr "{0} {1, plural, one {backup almacenado} other {backups almacenados}}" #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
#~ msgid "{0} backup{1} stored" #~ msgid "{0} backup{1} stored"
#~ msgstr "{0} backup{1} stored" #~ msgstr "{0} backup{1} stored"
#. placeholder {0}: backups.backupCount
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} backups · last <0/>" #~ msgid "{0} backups · last <0/>"
msgstr "{0} backups · último <0/>" #~ msgstr ""
#. placeholder {0}: imageCache.imageCount.toLocaleString()
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} cached images" #~ msgid "{0} cached images"
msgstr "{0} imágenes en caché" #~ msgstr ""
#. placeholder {0}: member.episodeCount
#. placeholder {1}: member.episodeCount !== 1 ? "s" : ""
#: apps/web/src/components/titles/cast-carousel.tsx #: apps/web/src/components/titles/cast-carousel.tsx
msgid "{0} ep{1}" #~ msgid "{0} ep{1}"
msgstr "{0} ep{1}" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} images" #~ msgid "{0} images"
#~ msgstr "{0} images" #~ msgstr "{0} images"
#. placeholder {0}: stats.watchlist
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items" #~ msgid "{0} items"
msgstr "{0} elementos" #~ msgstr ""
#. placeholder {0}: preview.diagnostics.unresolved
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate." #~ msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr "{0} elementos no tienen IDs externos y se resolverán por búsqueda de título, lo que puede ser menos preciso." #~ msgstr ""
#. placeholder {0}: stats.movies
#. placeholder {1}: stats.episodes
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} movies, {1} episodes" #~ msgid "{0} movies, {1} episodes"
msgstr "{0} películas, {1} episodios" #~ msgstr ""
#. placeholder {0}: stats.ratings
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} ratings" #~ msgid "{0} ratings"
msgstr "{0} valoraciones" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} titles" #~ msgid "{0} titles"
#~ msgstr "{0} titles" #~ msgstr "{0} titles"
#. placeholder {0}: JOB_LABELS[name] ?? name
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} triggered" #~ msgid "{0} triggered"
msgstr "{0} iniciado" #~ msgstr ""
#. placeholder {0}: item.watchedEpisodes
#. placeholder {1}: item.totalEpisodes
#. placeholder {2}: item.totalEpisodes
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{0}/{1} {2, plural, one {episode} other {episodes}}" #~ msgid "{0}/{1} {2, plural, one {episode} other {episodes}}"
msgstr "{0}/{1} {2, plural, one {episodio} other {episodios}}" #~ msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
#~ msgid "{0}/{1} episodes" #~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes" #~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/settings/backup-section.tsx
#: apps/web/src/components/titles/use-title-actions.ts msgid "{backupCount, plural, one {# backup} other {# backups}} stored"
msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched" msgstr ""
msgstr "{count} {count, plural, one {episodio anterior sin ver} other {episodios anteriores sin ver}}"
#. placeholder {0}: activeJobs.length
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {0} jobs healthy" msgid "{backupCount} backups · last <0/>"
msgstr "{healthyCount} de {0} tareas en buen estado" msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{cachedImageCount} cached images"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "{count, plural, one {# earlier episode} other {# earlier episodes}} unwatched"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
#~ msgstr ""
#: apps/web/src/components/titles/cast-carousel.tsx
msgid "{count} ep{suffix}"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
#~ msgid "{healthyCount} of {0} jobs healthy"
#~ msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {activeJobCount} jobs healthy"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{jobLabel} triggered"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
@@ -129,25 +145,50 @@ msgstr "{label} desconectado"
msgid "{label} URL regenerated" msgid "{label} URL regenerated"
msgstr "URL de {label} regenerada" msgstr "URL de {label} regenerada"
#: apps/web/src/components/settings/imports-section.tsx
msgid "{movieCount} movies, {episodeCount} episodes"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{ratingCount} ratings"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{unresolvedCount} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr ""
#: apps/web/src/components/title-card.tsx #: apps/web/src/components/title-card.tsx
msgid "{watched}/{total} episodes" msgid "{watched}/{total} episodes"
msgstr "{watched}/{total} episodios" msgstr "{watched}/{total} episodios"
#. placeholder {0}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount} of {0} episodes watched" #~ msgid "{watchedCount} of {0} episodes watched"
msgstr "{watchedCount} de {0} episodios vistos" #~ msgstr ""
#. placeholder {0}: episodes.length
#. placeholder {1}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}" msgid "{watchedCount} of {episodeCount} episodes watched"
msgstr "{watchedCount}/{0} {1, plural, one {episodio} other {episodios}}" msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}"
#~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} episodes" #~ msgid "{watchedCount}/{0} episodes"
#~ msgstr "{watchedCount}/{0} episodes" #~ msgstr "{watchedCount}/{0} episodes"
#: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{episodeCount, plural, one {# episode} other {# episodes}}"
msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{watchedEpisodes}/{totalEpisodes, plural, one {# episode} other {# episodes}}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{watchlistCount} items"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Account" msgid "Account"
@@ -161,7 +202,7 @@ msgstr "Acciones"
#: apps/native/src/components/search/recently-viewed-row-content.tsx #: apps/native/src/components/search/recently-viewed-row-content.tsx
#: apps/web/src/components/people/person-hero.tsx #: apps/web/src/components/people/person-hero.tsx
msgid "Actor" msgid "Actor"
msgstr "Actor" msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Add a \"Generic Destination\" and paste the URL above" msgid "Add a \"Generic Destination\" and paste the URL above"
@@ -207,7 +248,7 @@ msgstr "Añadido a la lista"
#: apps/web/src/components/nav-bar.tsx #: apps/web/src/components/nav-bar.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Admin" msgid "Admin"
msgstr "Admin" msgstr ""
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Admin only" msgid "Admin only"
@@ -268,10 +309,13 @@ msgstr "La autorización fue exitosa, pero no se pudo obtener tu biblioteca. Por
msgid "Authorization was denied. Please try again." msgid "Authorization was denied. Please try again."
msgstr "La autorización fue denegada. Por favor, inténtalo de nuevo." msgstr "La autorización fue denegada. Por favor, inténtalo de nuevo."
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {0} library. No password shared." #~ msgid "Authorize Sofa to read your {0} library. No password shared."
msgstr "Autoriza a Sofa a leer tu biblioteca de {0}. No se comparte ninguna contraseña." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {sourceLabel} library. No password shared."
msgstr ""
#: apps/web/src/components/settings/update-check-section.tsx #: apps/web/src/components/settings/update-check-section.tsx
msgid "Automatic update checks" msgid "Automatic update checks"
@@ -315,8 +359,8 @@ msgid "Backups"
msgstr "Copias de seguridad" msgstr "Copias de seguridad"
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "backups." msgid "backups."
#~ msgstr "backups." msgstr ""
#: apps/web/src/components/titles/title-availability.tsx #: apps/web/src/components/titles/title-availability.tsx
msgid "Buy" msgid "Buy"
@@ -374,11 +418,13 @@ msgstr "Ponerse al día"
msgid "Caught Up" msgid "Caught Up"
msgstr "Al día" msgstr "Al día"
#. placeholder {0}: episodeIds.length
#. placeholder {1}: episodeIds.length
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched" #~ msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched"
msgstr "Al día — {0} {1, plural, one {episodio marcado como visto} other {episodios marcados como vistos}}" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {count, plural, one {# episode} other {# episodes}} as watched"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
@@ -414,10 +460,13 @@ msgstr "Comprobado <0/>"
msgid "Checking…" msgid "Checking…"
msgstr "Comprobando…" msgstr "Comprobando…"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {0} data." #~ msgid "Choose how to import your {0} data."
msgstr "Elige cómo importar tus datos de {0}." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {sourceLabel} data."
msgstr ""
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
#~ msgid "Choose your preferred display language" #~ msgid "Choose your preferred display language"
@@ -480,12 +529,12 @@ msgstr "Confirmar nueva contraseña"
msgid "Connect" msgid "Connect"
msgstr "Conectar" msgstr "Conectar"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {0}" #~ msgid "Connect {0}"
msgstr "Conectar {0}" #~ msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {label}" msgid "Connect {label}"
msgstr "Conectar {label}" msgstr "Conectar {label}"
@@ -497,10 +546,13 @@ msgstr "Conectar con {source}"
msgid "Connect to TMDB" msgid "Connect to TMDB"
msgstr "Conectar con TMDB" msgstr "Conectar con TMDB"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {0}" #~ msgid "Connect with {0}"
msgstr "Conectar con {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {sourceLabel}"
msgstr ""
#: apps/native/src/app/(auth)/server-url.tsx #: apps/native/src/app/(auth)/server-url.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -647,7 +699,7 @@ msgstr "falleció a los {age}"
#: apps/native/src/components/search/recently-viewed-row-content.tsx #: apps/native/src/components/search/recently-viewed-row-content.tsx
#: apps/web/src/components/people/person-hero.tsx #: apps/web/src/components/people/person-hero.tsx
msgid "Director" msgid "Director"
msgstr "Director" msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
@@ -697,7 +749,7 @@ msgstr "Descargar copia de seguridad"
#: apps/native/src/components/search/recently-viewed-row-content.tsx #: apps/native/src/components/search/recently-viewed-row-content.tsx
#: apps/web/src/components/people/person-hero.tsx #: apps/web/src/components/people/person-hero.tsx
msgid "Editor" msgid "Editor"
msgstr "Editor" msgstr ""
#: apps/native/src/app/(auth)/login.tsx #: apps/native/src/app/(auth)/login.tsx
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
@@ -740,11 +792,11 @@ msgstr "Entorno"
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#~ msgid "Episode {0}" #~ msgid "Episode {0}"
#~ msgstr "Episodio {0}" #~ msgstr ""
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#~ msgid "Episode {0}, {episodeLabel}" #~ msgid "Episode {0}, {episodeLabel}"
#~ msgstr "Episodio {0}, {episodeLabel}" #~ msgstr ""
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
@@ -770,10 +822,13 @@ msgstr "Episodio marcado como visto"
msgid "Episodes" msgid "Episodes"
msgstr "Episodios" msgstr "Episodios"
#. placeholder {0}: periodLabels[episodePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {0}" #~ msgid "Episodes {0}"
msgstr "Episodios {0}" #~ msgstr "Episodes {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {period}"
msgstr ""
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Episodes {periodSelect}" #~ msgid "Episodes {periodSelect}"
@@ -785,17 +840,20 @@ msgstr "Episodios {select}"
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#~ msgid "Episodes this week" #~ msgid "Episodes this week"
#~ msgstr "Episodios esta semana" #~ msgstr ""
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
msgid "Error" msgid "Error"
msgstr "Error" msgstr ""
#. placeholder {0}: result.errors.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({0})" #~ msgid "Errors ({0})"
msgstr "Errores ({0})" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({errorCount})"
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
@@ -923,10 +981,13 @@ msgstr "Error al eliminar la foto de perfil"
msgid "Failed to sign in" msgid "Failed to sign in"
msgstr "Error al iniciar sesión" msgstr "Error al iniciar sesión"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {0} connection" #~ msgid "Failed to start {0} connection"
msgstr "Error al iniciar la conexión con {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {sourceLabel} connection"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Failed to trigger job" msgid "Failed to trigger job"
@@ -1086,15 +1147,18 @@ msgstr "Importación completada"
msgid "Import failed" msgid "Import failed"
msgstr "Error en la importación" msgstr "Error en la importación"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {0}" #~ msgid "Import from {0}"
msgstr "Importar desde {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {source}" msgid "Import from {source}"
msgstr "Importar desde {source}" msgstr "Importar desde {source}"
#: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {sourceLabel}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import is still running in the background. Check back later." msgid "Import is still running in the background. Check back later."
@@ -1108,11 +1172,13 @@ msgstr "Opciones de importación"
msgid "Imported" msgid "Imported"
msgstr "Importado" msgstr "Importado"
#. placeholder {0}: event.job.importedCount
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {0} items from {1}" #~ msgid "Imported {0} items from {1}"
msgstr "{0} elementos importados desde {1}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {importedCount} items from {sourceLabel}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Importing from {source}" msgid "Importing from {source}"
@@ -1158,14 +1224,12 @@ msgid "Job"
msgstr "Tarea" msgstr "Tarea"
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "Keeping" msgid "Keeping"
#~ msgstr "Keeping" msgstr ""
#. placeholder {0}: (value: string | null) => value === "0" ? t`unlimited` : value ? t`last ${value}` : null
#. placeholder {1}: [3, 5, 7, 14, 30, 0].map((n) => ( <SelectItem key={n} value={String(n)}> {n === 0 ? t`unlimited` : t`last ${n}`} </SelectItem> ))
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups." #~ msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups."
msgstr "Guardando <0><1><2>{0}</2></1><3>{1}</3></0> copias de seguridad." #~ msgstr ""
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
@@ -1186,19 +1250,25 @@ msgstr "últimos {n}"
msgid "last {value}" msgid "last {value}"
msgstr "últimos {value}" msgstr "últimos {value}"
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {0}" #~ msgid "Last event {0}"
msgstr "Último evento {0}" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {relativeTime}"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last event {timeAgo}" msgid "Last event {timeAgo}"
msgstr "Último evento {timeAgo}" msgstr "Último evento {timeAgo}"
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {0}" #~ msgid "Last polled {0}"
msgstr "Última consulta {0}" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {relativeTime}"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last polled {timeAgo}" msgid "Last polled {timeAgo}"
@@ -1249,7 +1319,7 @@ msgstr "Marcar todos como vistos"
#: apps/native/src/components/dashboard/continue-watching-card.tsx #: apps/native/src/components/dashboard/continue-watching-card.tsx
#~ msgid "Mark as Completed" #~ msgid "Mark as Completed"
#~ msgstr "Marcar como completado" #~ msgstr ""
#: apps/native/src/components/ui/poster-card.tsx #: apps/native/src/components/ui/poster-card.tsx
msgid "Mark as Watched" msgid "Mark as Watched"
@@ -1257,7 +1327,7 @@ msgstr "Marcar como visto"
#: apps/native/src/components/ui/poster-card.tsx #: apps/native/src/components/ui/poster-card.tsx
#~ msgid "Mark as Watching" #~ msgid "Mark as Watching"
#~ msgstr "Marcar como en curso" #~ msgstr ""
#: apps/native/src/app/title/[id].tsx #: apps/native/src/app/title/[id].tsx
#: apps/web/src/components/titles/title-actions.tsx #: apps/web/src/components/titles/title-actions.tsx
@@ -1266,7 +1336,7 @@ msgstr "Marcar como visto"
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked \"{titleName}\" as completed" #~ msgid "Marked \"{titleName}\" as completed"
#~ msgstr "\"{titleName}\" marcado como completado" #~ msgstr ""
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
@@ -1285,7 +1355,7 @@ msgstr "Se marcaron todos los episodios de \"{titleName}\" como vistos"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked as completed" #~ msgid "Marked as completed"
#~ msgstr "Marcado como completado" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -1295,7 +1365,7 @@ msgstr "Marcado como visto"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked as watching" #~ msgid "Marked as watching"
#~ msgstr "Marcado como en curso" #~ msgstr ""
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Member since {memberSince}" msgid "Member since {memberSince}"
@@ -1327,10 +1397,13 @@ msgstr "Película"
msgid "Movies" msgid "Movies"
msgstr "Películas" msgstr "Películas"
#. placeholder {0}: periodLabels[moviePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {0}" #~ msgid "Movies {0}"
msgstr "Películas {0}" #~ msgstr "Movies {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {period}"
msgstr ""
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Movies {periodSelect}" #~ msgid "Movies {periodSelect}"
@@ -1342,7 +1415,7 @@ msgstr "Películas {select}"
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#~ msgid "Movies this month" #~ msgid "Movies this month"
#~ msgstr "Películas este mes" #~ msgstr ""
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
@@ -1635,20 +1708,23 @@ msgstr "Acciones rápidas"
msgid "Radarr List URL" msgid "Radarr List URL"
msgstr "URL de lista de Radarr" msgstr "URL de lista de Radarr"
#. placeholder {0}: input.stars
#. placeholder {1}: input.stars
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
msgid "Rated {0} {1, plural, one {star} other {stars}}" #~ msgid "Rated {0} {1, plural, one {star} other {stars}}"
msgstr "Valorado con {0} {1, plural, one {estrella} other {estrellas}}" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#~ msgid "Rated {0} star{1}" #~ msgid "Rated {0} star{1}"
#~ msgstr "Rated {0} star{1}" #~ msgstr "Rated {0} star{1}"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}" msgid "Rated {ratingStars, plural, one {# star} other {# stars}}"
msgstr "Valorado con {ratingStars} {ratingStars, plural, one {estrella} other {estrellas}}" msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}"
#~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
msgid "Rated {stars, plural, one {# star} other {# stars}}" msgid "Rated {stars, plural, one {# star} other {# stars}}"
msgstr "Valorado con {stars, plural, one {# estrella} other {# estrellas}}" msgstr "Valorado con {stars, plural, one {# estrella} other {# estrellas}}"
@@ -1810,6 +1886,14 @@ msgstr "Requiere una suscripción activa de Plex Pass."
msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license." msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license."
msgstr "Requiere Emby Server 4.7.9+ y una licencia activa de Emby Premiere." msgstr "Requiere Emby Server 4.7.9+ y una licencia activa de Emby Premiere."
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart Required"
msgstr ""
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
msgid "Restore" msgid "Restore"
@@ -1921,13 +2005,19 @@ msgstr "Buscar películas, series, personas..."
msgid "Search…" msgid "Search…"
msgstr "Buscar…" msgstr "Buscar…"
#. placeholder {0}: season.seasonNumber
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {0}" #~ msgid "Season {0}"
msgstr "Temporada {0}" #~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {seasonNumber}"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -2018,12 +2108,18 @@ msgstr "Iniciar sesión"
msgid "Sign in to continue" msgid "Sign in to continue"
msgstr "Inicia sesión para continuar" msgstr "Inicia sesión para continuar"
#. placeholder {0}: authConfig.data?.oidcProviderName ?? "SSO"
#. placeholder {0}: authConfig?.oidcProviderName || "SSO"
#: apps/native/src/app/(auth)/login.tsx #: apps/native/src/app/(auth)/login.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
msgid "Sign in with {0}" #~ msgid "Sign in with {0}"
msgstr "Iniciar sesión con {0}" #~ msgstr ""
#: apps/web/src/components/auth-form.tsx
msgid "Sign in with {oidcProviderName}"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
msgid "Sign in with {providerName}"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/components/header-avatar.tsx #: apps/native/src/components/header-avatar.tsx
@@ -2048,10 +2144,17 @@ msgstr "Cerrar otras sesiones"
msgid "Skipped" msgid "Skipped"
msgstr "Omitido" msgstr "Omitido"
#. placeholder {0}: data.latestVersion #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Sofa needs to restart to apply the new layout direction."
msgstr ""
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "Sofa v{0} is available" #~ msgid "Sofa v{0} is available"
msgstr "Sofa v{0} disponible" #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "Sofa v{latestVersion} is available"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2118,10 +2221,13 @@ msgstr "Streaming"
msgid "Sunday" msgid "Sunday"
msgstr "Domingo" msgstr "Domingo"
#. placeholder {0}: info.name
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {0}" #~ msgid "Switch to {0}"
msgstr "Cambiar a {0}" #~ msgstr ""
#: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {name}"
msgstr ""
#: apps/native/src/app/+not-found.tsx #: apps/native/src/app/+not-found.tsx
msgid "The page you're looking for doesn't exist." msgid "The page you're looking for doesn't exist."
@@ -2192,10 +2298,13 @@ msgstr "Esto invalidará la URL actual de {label}. Tendrás que actualizarla en
msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons." msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons."
msgstr "Esto marcará todos los episodios de esta serie como vistos. Puedes deshacerlo más tarde desmarcando temporadas individuales." msgstr "Esto marcará todos los episodios de esta serie como vistos. Puedes deshacerlo más tarde desmarcando temporadas individuales."
#. placeholder {0}: formatBackupDate(backup.createdAt)
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone." #~ msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone."
msgstr "Esto eliminará permanentemente la copia de seguridad del <0>{0}</0>. Esta acción no se puede deshacer." #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{backupDate}</0>. This cannot be undone."
msgstr ""
#: apps/native/src/components/search/recently-viewed-list.ios.tsx #: apps/native/src/components/search/recently-viewed-list.ios.tsx
#: apps/native/src/components/search/recently-viewed-list.tsx #: apps/native/src/components/search/recently-viewed-list.tsx
@@ -2327,10 +2436,13 @@ msgstr "Sin título"
msgid "Unwatch all" msgid "Unwatch all"
msgstr "Desmarcar todo" msgstr "Desmarcar todo"
#. placeholder {0}: season.name ?? t`Season ${season.seasonNumber}`
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {0}" #~ msgid "Unwatched all of {0}"
msgstr "Todo de {0} marcado como no visto" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {seasonLabel}"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched S{seasonNum} E{epNum}" msgid "Unwatched S{seasonNum} E{epNum}"
@@ -2341,10 +2453,13 @@ msgstr "No visto T{seasonNum} E{epNum}"
msgid "Up next" msgid "Up next"
msgstr "A continuación" msgstr "A continuación"
#. placeholder {0}: updateCheck.data.updateCheck.latestVersion
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {0}" #~ msgid "Update available: {0}"
msgstr "Actualización disponible: {0}" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {latestVersion}"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Update check" msgid "Update check"
@@ -2381,11 +2496,13 @@ msgstr "Subir"
msgid "Upload a .db file to replace the current database. A safety backup is created first." msgid "Upload a .db file to replace the current database. A safety backup is created first."
msgstr "Sube un archivo .db para reemplazar la base de datos actual. Primero se crea una copia de seguridad." msgstr "Sube un archivo .db para reemplazar la base de datos actual. Primero se crea una copia de seguridad."
#. placeholder {0}: config.accept
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {0} export from your {1} account settings." #~ msgid "Upload a {0} export from your {1} account settings."
msgstr "Sube una exportación {0} desde los ajustes de tu cuenta de {1}." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {acceptFormat} export from your {sourceLabel} account settings."
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload export file" msgid "Upload export file"
@@ -2419,10 +2536,13 @@ msgstr "Esperando autorización..."
msgid "Warnings" msgid "Warnings"
msgstr "Advertencias" msgstr "Advertencias"
#. placeholder {0}: result.warnings.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({0})" #~ msgid "Warnings ({0})"
msgstr "Advertencias ({0})" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({warningCount})"
msgstr ""
#: apps/web/src/components/titles/title-seasons.tsx #: apps/web/src/components/titles/title-seasons.tsx
msgid "Watch all" msgid "Watch all"
@@ -2465,7 +2585,7 @@ msgstr "Lista"
#: apps/native/src/components/titles/status-action-button.tsx #: apps/native/src/components/titles/status-action-button.tsx
#~ msgid "Watchlisted" #~ msgid "Watchlisted"
#~ msgstr "En lista" #~ msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2505,10 +2625,13 @@ msgstr "Guionista"
msgid "You'll be signed out to change the server URL." msgid "You'll be signed out to change the server URL."
msgstr "Se cerrará tu sesión para cambiar la URL del servidor." msgstr "Se cerrará tu sesión para cambiar la URL del servidor."
#. placeholder {0}: data.currentVersion
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "You're running v{0}." #~ msgid "You're running v{0}."
msgstr "Estás usando la v{0}." #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "You're running v{currentVersion}."
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Your code:" msgid "Your code:"
@@ -2522,3 +2645,4 @@ msgstr "Tu biblioteca está vacía"
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
msgid "Your name" msgid "Your name"
msgstr "Tu nombre" msgstr "Tu nombre"
+280 -156
View File
@@ -8,111 +8,127 @@ msgstr ""
"Language: fr\n" "Language: fr\n"
"Project-Id-Version: sofa\n" "Project-Id-Version: sofa\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-03-19 00:35\n" "PO-Revision-Date: 2026-03-20 23:13\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: French\n" "Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Crowdin-Project: sofa\n" "X-Crowdin-Project: sofa\n"
"X-Crowdin-Project-ID: 881052\n" "X-Crowdin-Project-ID: 881052\n"
"X-Crowdin-Language: fr\n" "X-Crowdin-Language: fr\n"
"X-Crowdin-File: en.po\n" "X-Crowdin-File: /packages/i18n/src/po/en.po\n"
"X-Crowdin-File-ID: 14\n" "X-Crowdin-File-ID: 26\n"
#. placeholder {0}: result.errors.length - 50
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "...and {0} more" #~ msgid "...and {0} more"
msgstr "...et {0} de plus" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "...and {remainingErrors} more"
msgstr ""
#. placeholder {0}: systemHealth.data.imageCache.imageCount #. placeholder {0}: systemHealth.data.imageCache.imageCount
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "{0, plural, one {# image} other {# images}}" msgid "{0, plural, one {# image} other {# images}}"
msgstr "{0, plural, one {# image} other {# images}}" msgstr ""
#. placeholder {0}: systemHealth.data.database.titleCount #. placeholder {0}: systemHealth.data.database.titleCount
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "{0, plural, one {# title} other {# titles}}" msgid "{0, plural, one {# title} other {# titles}}"
msgstr "{0, plural, one {# titre} other {# titres}}" msgstr "{0, plural, one {# titre} other {# titres}}"
#. placeholder {0}: displayBackups.length
#. placeholder {1}: displayBackups.length
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "{0} {1, plural, one {backup} other {backups}} stored" #~ msgid "{0} {1, plural, one {backup} other {backups}} stored"
msgstr "{0} {1, plural, one {sauvegarde stockée} other {sauvegardes stockées}}" #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
#~ msgid "{0} backup{1} stored" #~ msgid "{0} backup{1} stored"
#~ msgstr "{0} backup{1} stored" #~ msgstr "{0} backup{1} stored"
#. placeholder {0}: backups.backupCount
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} backups · last <0/>" #~ msgid "{0} backups · last <0/>"
msgstr "{0} sauvegardes · dernière <0/>" #~ msgstr ""
#. placeholder {0}: imageCache.imageCount.toLocaleString()
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} cached images" #~ msgid "{0} cached images"
msgstr "{0} images en cache" #~ msgstr ""
#. placeholder {0}: member.episodeCount
#. placeholder {1}: member.episodeCount !== 1 ? "s" : ""
#: apps/web/src/components/titles/cast-carousel.tsx #: apps/web/src/components/titles/cast-carousel.tsx
msgid "{0} ep{1}" #~ msgid "{0} ep{1}"
msgstr "{0} ép{1}" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} images" #~ msgid "{0} images"
#~ msgstr "{0} images" #~ msgstr "{0} images"
#. placeholder {0}: stats.watchlist
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items" #~ msgid "{0} items"
msgstr "{0} éléments" #~ msgstr ""
#. placeholder {0}: preview.diagnostics.unresolved
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate." #~ msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr "{0} éléments n'ont pas d'identifiants externes et seront résolus par recherche de titre, ce qui peut être moins précis." #~ msgstr ""
#. placeholder {0}: stats.movies
#. placeholder {1}: stats.episodes
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} movies, {1} episodes" #~ msgid "{0} movies, {1} episodes"
msgstr "{0} films, {1} épisodes" #~ msgstr ""
#. placeholder {0}: stats.ratings
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} ratings" #~ msgid "{0} ratings"
msgstr "{0} notes" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} titles" #~ msgid "{0} titles"
#~ msgstr "{0} titles" #~ msgstr "{0} titles"
#. placeholder {0}: JOB_LABELS[name] ?? name
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} triggered" #~ msgid "{0} triggered"
msgstr "{0} déclenché" #~ msgstr ""
#. placeholder {0}: item.watchedEpisodes
#. placeholder {1}: item.totalEpisodes
#. placeholder {2}: item.totalEpisodes
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{0}/{1} {2, plural, one {episode} other {episodes}}" #~ msgid "{0}/{1} {2, plural, one {episode} other {episodes}}"
msgstr "{0}/{1} {2, plural, one {épisode} other {épisodes}}" #~ msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
#~ msgid "{0}/{1} episodes" #~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes" #~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/settings/backup-section.tsx
#: apps/web/src/components/titles/use-title-actions.ts msgid "{backupCount, plural, one {# backup} other {# backups}} stored"
msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched" msgstr ""
msgstr "{count} {count, plural, one {épisode précédent non visionné} other {épisodes précédents non visionnés}}"
#. placeholder {0}: activeJobs.length
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {0} jobs healthy" msgid "{backupCount} backups · last <0/>"
msgstr "{healthyCount} sur {0} tâches en bonne santé" msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{cachedImageCount} cached images"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "{count, plural, one {# earlier episode} other {# earlier episodes}} unwatched"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
#~ msgstr ""
#: apps/web/src/components/titles/cast-carousel.tsx
msgid "{count} ep{suffix}"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
#~ msgid "{healthyCount} of {0} jobs healthy"
#~ msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {activeJobCount} jobs healthy"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{jobLabel} triggered"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
@@ -129,25 +145,50 @@ msgstr "{label} déconnecté"
msgid "{label} URL regenerated" msgid "{label} URL regenerated"
msgstr "URL {label} régénérée" msgstr "URL {label} régénérée"
#: apps/web/src/components/settings/imports-section.tsx
msgid "{movieCount} movies, {episodeCount} episodes"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{ratingCount} ratings"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{unresolvedCount} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr ""
#: apps/web/src/components/title-card.tsx #: apps/web/src/components/title-card.tsx
msgid "{watched}/{total} episodes" msgid "{watched}/{total} episodes"
msgstr "{watched}/{total} épisodes" msgstr "{watched}/{total} épisodes"
#. placeholder {0}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount} of {0} episodes watched" #~ msgid "{watchedCount} of {0} episodes watched"
msgstr "{watchedCount} sur {0} épisodes regardés" #~ msgstr ""
#. placeholder {0}: episodes.length
#. placeholder {1}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}" msgid "{watchedCount} of {episodeCount} episodes watched"
msgstr "{watchedCount}/{0} {1, plural, one {épisode} other {épisodes}}" msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}"
#~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} episodes" #~ msgid "{watchedCount}/{0} episodes"
#~ msgstr "{watchedCount}/{0} episodes" #~ msgstr "{watchedCount}/{0} episodes"
#: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{episodeCount, plural, one {# episode} other {# episodes}}"
msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{watchedEpisodes}/{totalEpisodes, plural, one {# episode} other {# episodes}}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{watchlistCount} items"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Account" msgid "Account"
@@ -155,7 +196,7 @@ msgstr "Compte"
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Actions" msgid "Actions"
msgstr "Actions" msgstr ""
#: apps/native/src/app/person/[id].tsx #: apps/native/src/app/person/[id].tsx
#: apps/native/src/components/search/recently-viewed-row-content.tsx #: apps/native/src/components/search/recently-viewed-row-content.tsx
@@ -207,7 +248,7 @@ msgstr "Ajouté à la liste de suivi"
#: apps/web/src/components/nav-bar.tsx #: apps/web/src/components/nav-bar.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Admin" msgid "Admin"
msgstr "Admin" msgstr ""
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Admin only" msgid "Admin only"
@@ -249,7 +290,7 @@ msgstr "Paramètres de l'application"
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Application" msgid "Application"
msgstr "Application" msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
msgid "Are you sure you want to disconnect {label}? The current URL will stop working." msgid "Are you sure you want to disconnect {label}? The current URL will stop working."
@@ -268,10 +309,13 @@ msgstr "L'autorisation a réussi mais la récupération de votre bibliothèque a
msgid "Authorization was denied. Please try again." msgid "Authorization was denied. Please try again."
msgstr "L'autorisation a été refusée. Veuillez réessayer." msgstr "L'autorisation a été refusée. Veuillez réessayer."
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {0} library. No password shared." #~ msgid "Authorize Sofa to read your {0} library. No password shared."
msgstr "Autorisez Sofa à lire votre bibliothèque {0}. Aucun mot de passe partagé." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {sourceLabel} library. No password shared."
msgstr ""
#: apps/web/src/components/settings/update-check-section.tsx #: apps/web/src/components/settings/update-check-section.tsx
msgid "Automatic update checks" msgid "Automatic update checks"
@@ -315,8 +359,8 @@ msgid "Backups"
msgstr "Sauvegardes" msgstr "Sauvegardes"
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "backups." msgid "backups."
#~ msgstr "backups." msgstr ""
#: apps/web/src/components/titles/title-availability.tsx #: apps/web/src/components/titles/title-availability.tsx
msgid "Buy" msgid "Buy"
@@ -374,11 +418,13 @@ msgstr "Rattraper"
msgid "Caught Up" msgid "Caught Up"
msgstr "À jour" msgstr "À jour"
#. placeholder {0}: episodeIds.length
#. placeholder {1}: episodeIds.length
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched" #~ msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched"
msgstr "Rattrapé — {0} {1, plural, one {épisode marqué comme visionné} other {épisodes marqués comme visionnés}}" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {count, plural, one {# episode} other {# episodes}} as watched"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
@@ -414,10 +460,13 @@ msgstr "Vérifié <0/>"
msgid "Checking…" msgid "Checking…"
msgstr "Vérification…" msgstr "Vérification…"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {0} data." #~ msgid "Choose how to import your {0} data."
msgstr "Choisissez comment importer vos données {0}." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {sourceLabel} data."
msgstr ""
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
#~ msgid "Choose your preferred display language" #~ msgid "Choose your preferred display language"
@@ -480,12 +529,12 @@ msgstr "Confirmer le nouveau mot de passe"
msgid "Connect" msgid "Connect"
msgstr "Connecter" msgstr "Connecter"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {0}" #~ msgid "Connect {0}"
msgstr "Connecter {0}" #~ msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {label}" msgid "Connect {label}"
msgstr "Connecter {label}" msgstr "Connecter {label}"
@@ -497,10 +546,13 @@ msgstr "Se connecter à {source}"
msgid "Connect to TMDB" msgid "Connect to TMDB"
msgstr "Se connecter à TMDB" msgstr "Se connecter à TMDB"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {0}" #~ msgid "Connect with {0}"
msgstr "Se connecter avec {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {sourceLabel}"
msgstr ""
#: apps/native/src/app/(auth)/server-url.tsx #: apps/native/src/app/(auth)/server-url.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -740,11 +792,11 @@ msgstr "Environnement"
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#~ msgid "Episode {0}" #~ msgid "Episode {0}"
#~ msgstr "Épisode {0}" #~ msgstr ""
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#~ msgid "Episode {0}, {episodeLabel}" #~ msgid "Episode {0}, {episodeLabel}"
#~ msgstr "Épisode {0}, {episodeLabel}" #~ msgstr ""
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
@@ -770,10 +822,13 @@ msgstr "Épisode visionné"
msgid "Episodes" msgid "Episodes"
msgstr "Épisodes" msgstr "Épisodes"
#. placeholder {0}: periodLabels[episodePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {0}" #~ msgid "Episodes {0}"
msgstr pisodes {0}" #~ msgstr "Episodes {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {period}"
msgstr ""
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Episodes {periodSelect}" #~ msgid "Episodes {periodSelect}"
@@ -785,17 +840,20 @@ msgstr "Épisodes {select}"
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#~ msgid "Episodes this week" #~ msgid "Episodes this week"
#~ msgstr "Épisodes cette semaine" #~ msgstr ""
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
msgid "Error" msgid "Error"
msgstr "Erreur" msgstr "Erreur"
#. placeholder {0}: result.errors.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({0})" #~ msgid "Errors ({0})"
msgstr "Erreurs ({0})" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({errorCount})"
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
@@ -923,10 +981,13 @@ msgstr "Échec de la suppression de la photo de profil"
msgid "Failed to sign in" msgid "Failed to sign in"
msgstr "Échec de la connexion" msgstr "Échec de la connexion"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {0} connection" #~ msgid "Failed to start {0} connection"
msgstr "Échec du démarrage de la connexion {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {sourceLabel} connection"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Failed to trigger job" msgid "Failed to trigger job"
@@ -1086,15 +1147,18 @@ msgstr "Importation terminée"
msgid "Import failed" msgid "Import failed"
msgstr "Importation échouée" msgstr "Importation échouée"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {0}" #~ msgid "Import from {0}"
msgstr "Importer depuis {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {source}" msgid "Import from {source}"
msgstr "Importer depuis {source}" msgstr "Importer depuis {source}"
#: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {sourceLabel}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import is still running in the background. Check back later." msgid "Import is still running in the background. Check back later."
@@ -1108,11 +1172,13 @@ msgstr "Options d'importation"
msgid "Imported" msgid "Imported"
msgstr "Importé" msgstr "Importé"
#. placeholder {0}: event.job.importedCount
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {0} items from {1}" #~ msgid "Imported {0} items from {1}"
msgstr "{0} éléments importés depuis {1}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {importedCount} items from {sourceLabel}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Importing from {source}" msgid "Importing from {source}"
@@ -1158,14 +1224,12 @@ msgid "Job"
msgstr "Tâche" msgstr "Tâche"
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "Keeping" msgid "Keeping"
#~ msgstr "Keeping" msgstr ""
#. placeholder {0}: (value: string | null) => value === "0" ? t`unlimited` : value ? t`last ${value}` : null
#. placeholder {1}: [3, 5, 7, 14, 30, 0].map((n) => ( <SelectItem key={n} value={String(n)}> {n === 0 ? t`unlimited` : t`last ${n}`} </SelectItem> ))
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups." #~ msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups."
msgstr "Conservation de <0><1><2>{0}</2></1><3>{1}</3></0> sauvegardes." #~ msgstr ""
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
@@ -1186,19 +1250,25 @@ msgstr "{n} dernières"
msgid "last {value}" msgid "last {value}"
msgstr "{value} dernières" msgstr "{value} dernières"
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {0}" #~ msgid "Last event {0}"
msgstr "Dernier événement {0}" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {relativeTime}"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last event {timeAgo}" msgid "Last event {timeAgo}"
msgstr "Dernier événement {timeAgo}" msgstr "Dernier événement {timeAgo}"
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {0}" #~ msgid "Last polled {0}"
msgstr "Dernière interrogation {0}" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {relativeTime}"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last polled {timeAgo}" msgid "Last polled {timeAgo}"
@@ -1249,7 +1319,7 @@ msgstr "Tout marquer comme visionné"
#: apps/native/src/components/dashboard/continue-watching-card.tsx #: apps/native/src/components/dashboard/continue-watching-card.tsx
#~ msgid "Mark as Completed" #~ msgid "Mark as Completed"
#~ msgstr "Marquer comme terminé" #~ msgstr ""
#: apps/native/src/components/ui/poster-card.tsx #: apps/native/src/components/ui/poster-card.tsx
msgid "Mark as Watched" msgid "Mark as Watched"
@@ -1257,7 +1327,7 @@ msgstr "Marquer comme visionné"
#: apps/native/src/components/ui/poster-card.tsx #: apps/native/src/components/ui/poster-card.tsx
#~ msgid "Mark as Watching" #~ msgid "Mark as Watching"
#~ msgstr "Marquer comme en cours" #~ msgstr ""
#: apps/native/src/app/title/[id].tsx #: apps/native/src/app/title/[id].tsx
#: apps/web/src/components/titles/title-actions.tsx #: apps/web/src/components/titles/title-actions.tsx
@@ -1266,7 +1336,7 @@ msgstr "Marquer comme visionné"
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked \"{titleName}\" as completed" #~ msgid "Marked \"{titleName}\" as completed"
#~ msgstr "« {titleName} » marqué comme terminé" #~ msgstr ""
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
@@ -1285,7 +1355,7 @@ msgstr "Tous les épisodes de \"{titleName}\" marqués comme vus"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked as completed" #~ msgid "Marked as completed"
#~ msgstr "Marqué comme terminé" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -1295,7 +1365,7 @@ msgstr "Marqué comme visionné"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked as watching" #~ msgid "Marked as watching"
#~ msgstr "Marqué comme en cours" #~ msgstr ""
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Member since {memberSince}" msgid "Member since {memberSince}"
@@ -1327,10 +1397,13 @@ msgstr "Film"
msgid "Movies" msgid "Movies"
msgstr "Films" msgstr "Films"
#. placeholder {0}: periodLabels[moviePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {0}" #~ msgid "Movies {0}"
msgstr "Films {0}" #~ msgstr "Movies {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {period}"
msgstr ""
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Movies {periodSelect}" #~ msgid "Movies {periodSelect}"
@@ -1342,7 +1415,7 @@ msgstr "Films {select}"
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#~ msgid "Movies this month" #~ msgid "Movies this month"
#~ msgstr "Films ce mois-ci" #~ msgstr ""
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
@@ -1635,20 +1708,23 @@ msgstr "Actions rapides"
msgid "Radarr List URL" msgid "Radarr List URL"
msgstr "URL de liste Radarr" msgstr "URL de liste Radarr"
#. placeholder {0}: input.stars
#. placeholder {1}: input.stars
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
msgid "Rated {0} {1, plural, one {star} other {stars}}" #~ msgid "Rated {0} {1, plural, one {star} other {stars}}"
msgstr "Noté {0} {1, plural, one {étoile} other {étoiles}}" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#~ msgid "Rated {0} star{1}" #~ msgid "Rated {0} star{1}"
#~ msgstr "Rated {0} star{1}" #~ msgstr "Rated {0} star{1}"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}" msgid "Rated {ratingStars, plural, one {# star} other {# stars}}"
msgstr "Noté {ratingStars} {ratingStars, plural, one {étoile} other {étoiles}}" msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}"
#~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
msgid "Rated {stars, plural, one {# star} other {# stars}}" msgid "Rated {stars, plural, one {# star} other {# stars}}"
msgstr "Noté {stars, plural, one {# étoile} other {# étoiles}}" msgstr "Noté {stars, plural, one {# étoile} other {# étoiles}}"
@@ -1810,6 +1886,14 @@ msgstr "Nécessite un abonnement Plex Pass actif."
msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license." msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license."
msgstr "Nécessite Emby Server 4.7.9+ et une licence Emby Premiere active." msgstr "Nécessite Emby Server 4.7.9+ et une licence Emby Premiere active."
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart Required"
msgstr ""
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
msgid "Restore" msgid "Restore"
@@ -1921,13 +2005,19 @@ msgstr "Rechercher des films, séries, personnes..."
msgid "Search…" msgid "Search…"
msgstr "Rechercher…" msgstr "Rechercher…"
#. placeholder {0}: season.seasonNumber
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {0}" #~ msgid "Season {0}"
msgstr "Saison {0}" #~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {seasonNumber}"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -2018,12 +2108,18 @@ msgstr "Se connecter"
msgid "Sign in to continue" msgid "Sign in to continue"
msgstr "Connectez-vous pour continuer" msgstr "Connectez-vous pour continuer"
#. placeholder {0}: authConfig.data?.oidcProviderName ?? "SSO"
#. placeholder {0}: authConfig?.oidcProviderName || "SSO"
#: apps/native/src/app/(auth)/login.tsx #: apps/native/src/app/(auth)/login.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
msgid "Sign in with {0}" #~ msgid "Sign in with {0}"
msgstr "Se connecter avec {0}" #~ msgstr ""
#: apps/web/src/components/auth-form.tsx
msgid "Sign in with {oidcProviderName}"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
msgid "Sign in with {providerName}"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/components/header-avatar.tsx #: apps/native/src/components/header-avatar.tsx
@@ -2048,10 +2144,17 @@ msgstr "Se déconnecter des autres sessions"
msgid "Skipped" msgid "Skipped"
msgstr "Ignoré" msgstr "Ignoré"
#. placeholder {0}: data.latestVersion #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Sofa needs to restart to apply the new layout direction."
msgstr ""
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "Sofa v{0} is available" #~ msgid "Sofa v{0} is available"
msgstr "Sofa v{0} est disponible" #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "Sofa v{latestVersion} is available"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2118,10 +2221,13 @@ msgstr "Streaming"
msgid "Sunday" msgid "Sunday"
msgstr "Dimanche" msgstr "Dimanche"
#. placeholder {0}: info.name
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {0}" #~ msgid "Switch to {0}"
msgstr "Passer à {0}" #~ msgstr ""
#: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {name}"
msgstr ""
#: apps/native/src/app/+not-found.tsx #: apps/native/src/app/+not-found.tsx
msgid "The page you're looking for doesn't exist." msgid "The page you're looking for doesn't exist."
@@ -2192,10 +2298,13 @@ msgstr "Cela invalidera l'URL {label} actuelle. Vous devrez la mettre à jour da
msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons." msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons."
msgstr "Cela marquera tous les épisodes de cette série comme visionnés. Vous pourrez annuler cela en démarquant des saisons individuelles." msgstr "Cela marquera tous les épisodes de cette série comme visionnés. Vous pourrez annuler cela en démarquant des saisons individuelles."
#. placeholder {0}: formatBackupDate(backup.createdAt)
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone." #~ msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone."
msgstr "Cela supprimera définitivement la sauvegarde du <0>{0}</0>. Cette action est irréversible." #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{backupDate}</0>. This cannot be undone."
msgstr ""
#: apps/native/src/components/search/recently-viewed-list.ios.tsx #: apps/native/src/components/search/recently-viewed-list.ios.tsx
#: apps/native/src/components/search/recently-viewed-list.tsx #: apps/native/src/components/search/recently-viewed-list.tsx
@@ -2327,10 +2436,13 @@ msgstr "Sans titre"
msgid "Unwatch all" msgid "Unwatch all"
msgstr "Tout démarquer" msgstr "Tout démarquer"
#. placeholder {0}: season.name ?? t`Season ${season.seasonNumber}`
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {0}" #~ msgid "Unwatched all of {0}"
msgstr "Tout démarqué de {0}" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {seasonLabel}"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched S{seasonNum} E{epNum}" msgid "Unwatched S{seasonNum} E{epNum}"
@@ -2341,10 +2453,13 @@ msgstr "Démarqué S{seasonNum} E{epNum}"
msgid "Up next" msgid "Up next"
msgstr "Suivant" msgstr "Suivant"
#. placeholder {0}: updateCheck.data.updateCheck.latestVersion
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {0}" #~ msgid "Update available: {0}"
msgstr "Mise à jour disponible : {0}" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {latestVersion}"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Update check" msgid "Update check"
@@ -2381,11 +2496,13 @@ msgstr "Télécharger"
msgid "Upload a .db file to replace the current database. A safety backup is created first." msgid "Upload a .db file to replace the current database. A safety backup is created first."
msgstr "Téléchargez un fichier .db pour remplacer la base de données actuelle. Une sauvegarde de sécurité est créée au préalable." msgstr "Téléchargez un fichier .db pour remplacer la base de données actuelle. Une sauvegarde de sécurité est créée au préalable."
#. placeholder {0}: config.accept
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {0} export from your {1} account settings." #~ msgid "Upload a {0} export from your {1} account settings."
msgstr "Téléchargez un export {0} depuis les paramètres de votre compte {1}." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {acceptFormat} export from your {sourceLabel} account settings."
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload export file" msgid "Upload export file"
@@ -2419,10 +2536,13 @@ msgstr "En attente d'autorisation..."
msgid "Warnings" msgid "Warnings"
msgstr "Avertissements" msgstr "Avertissements"
#. placeholder {0}: result.warnings.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({0})" #~ msgid "Warnings ({0})"
msgstr "Avertissements ({0})" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({warningCount})"
msgstr ""
#: apps/web/src/components/titles/title-seasons.tsx #: apps/web/src/components/titles/title-seasons.tsx
msgid "Watch all" msgid "Watch all"
@@ -2465,7 +2585,7 @@ msgstr "Liste de suivi"
#: apps/native/src/components/titles/status-action-button.tsx #: apps/native/src/components/titles/status-action-button.tsx
#~ msgid "Watchlisted" #~ msgid "Watchlisted"
#~ msgstr "Dans la liste de suivi" #~ msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2505,10 +2625,13 @@ msgstr "Scénariste"
msgid "You'll be signed out to change the server URL." msgid "You'll be signed out to change the server URL."
msgstr "Vous serez déconnecté pour modifier l'URL du serveur." msgstr "Vous serez déconnecté pour modifier l'URL du serveur."
#. placeholder {0}: data.currentVersion
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "You're running v{0}." #~ msgid "You're running v{0}."
msgstr "Vous utilisez la v{0}." #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "You're running v{currentVersion}."
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Your code:" msgid "Your code:"
@@ -2522,3 +2645,4 @@ msgstr "Votre bibliothèque est vide"
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
msgid "Your name" msgid "Your name"
msgstr "Votre nom" msgstr "Votre nom"
File diff suppressed because it is too large Load Diff
+289 -165
View File
@@ -8,20 +8,23 @@ msgstr ""
"Language: it\n" "Language: it\n"
"Project-Id-Version: sofa\n" "Project-Id-Version: sofa\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-03-19 00:35\n" "PO-Revision-Date: 2026-03-20 23:13\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Italian\n" "Language-Team: Italian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: sofa\n" "X-Crowdin-Project: sofa\n"
"X-Crowdin-Project-ID: 881052\n" "X-Crowdin-Project-ID: 881052\n"
"X-Crowdin-Language: it\n" "X-Crowdin-Language: it\n"
"X-Crowdin-File: en.po\n" "X-Crowdin-File: /packages/i18n/src/po/en.po\n"
"X-Crowdin-File-ID: 14\n" "X-Crowdin-File-ID: 26\n"
#. placeholder {0}: result.errors.length - 50
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "...and {0} more" #~ msgid "...and {0} more"
msgstr "...e altri {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "...and {remainingErrors} more"
msgstr ""
#. placeholder {0}: systemHealth.data.imageCache.imageCount #. placeholder {0}: systemHealth.data.imageCache.imageCount
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -33,86 +36,99 @@ msgstr "{0, plural, one {# immagine} other {# immagini}}"
msgid "{0, plural, one {# title} other {# titles}}" msgid "{0, plural, one {# title} other {# titles}}"
msgstr "{0, plural, one {# titolo} other {# titoli}}" msgstr "{0, plural, one {# titolo} other {# titoli}}"
#. placeholder {0}: displayBackups.length
#. placeholder {1}: displayBackups.length
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "{0} {1, plural, one {backup} other {backups}} stored" #~ msgid "{0} {1, plural, one {backup} other {backups}} stored"
msgstr "{0} {1, plural, one {backup} other {backup}} archiviati" #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
#~ msgid "{0} backup{1} stored" #~ msgid "{0} backup{1} stored"
#~ msgstr "{0} backup{1} stored" #~ msgstr "{0} backup{1} stored"
#. placeholder {0}: backups.backupCount
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} backups · last <0/>" #~ msgid "{0} backups · last <0/>"
msgstr "{0} backup · ultimo <0/>" #~ msgstr ""
#. placeholder {0}: imageCache.imageCount.toLocaleString()
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} cached images" #~ msgid "{0} cached images"
msgstr "{0} immagini in cache" #~ msgstr ""
#. placeholder {0}: member.episodeCount
#. placeholder {1}: member.episodeCount !== 1 ? "s" : ""
#: apps/web/src/components/titles/cast-carousel.tsx #: apps/web/src/components/titles/cast-carousel.tsx
msgid "{0} ep{1}" #~ msgid "{0} ep{1}"
msgstr "{0} ep{1}" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} images" #~ msgid "{0} images"
#~ msgstr "{0} images" #~ msgstr "{0} images"
#. placeholder {0}: stats.watchlist
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items" #~ msgid "{0} items"
msgstr "{0} elementi" #~ msgstr ""
#. placeholder {0}: preview.diagnostics.unresolved
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate." #~ msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr "{0} elementi non hanno ID esterni e verranno risolti tramite ricerca per titolo, che potrebbe essere meno accurata." #~ msgstr ""
#. placeholder {0}: stats.movies
#. placeholder {1}: stats.episodes
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} movies, {1} episodes" #~ msgid "{0} movies, {1} episodes"
msgstr "{0} film, {1} episodi" #~ msgstr ""
#. placeholder {0}: stats.ratings
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} ratings" #~ msgid "{0} ratings"
msgstr "{0} valutazioni" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} titles" #~ msgid "{0} titles"
#~ msgstr "{0} titles" #~ msgstr "{0} titles"
#. placeholder {0}: JOB_LABELS[name] ?? name
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} triggered" #~ msgid "{0} triggered"
msgstr "{0} attivato" #~ msgstr ""
#. placeholder {0}: item.watchedEpisodes
#. placeholder {1}: item.totalEpisodes
#. placeholder {2}: item.totalEpisodes
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{0}/{1} {2, plural, one {episode} other {episodes}}" #~ msgid "{0}/{1} {2, plural, one {episode} other {episodes}}"
msgstr "{0}/{1} {2, plural, one {episodio} other {episodi}}" #~ msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
#~ msgid "{0}/{1} episodes" #~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes" #~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/settings/backup-section.tsx
#: apps/web/src/components/titles/use-title-actions.ts msgid "{backupCount, plural, one {# backup} other {# backups}} stored"
msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched" msgstr ""
msgstr "{count} {count, plural, one {episodio precedente non visto} other {episodi precedenti non visti}}"
#. placeholder {0}: activeJobs.length
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {0} jobs healthy" msgid "{backupCount} backups · last <0/>"
msgstr "{healthyCount} di {0} job attivi" msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{cachedImageCount} cached images"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "{count, plural, one {# earlier episode} other {# earlier episodes}} unwatched"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
#~ msgstr ""
#: apps/web/src/components/titles/cast-carousel.tsx
msgid "{count} ep{suffix}"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
#~ msgid "{healthyCount} of {0} jobs healthy"
#~ msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {activeJobCount} jobs healthy"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{jobLabel} triggered"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
@@ -129,29 +145,54 @@ msgstr "Disconnesso: {label}"
msgid "{label} URL regenerated" msgid "{label} URL regenerated"
msgstr "URL {label} rigenerato" msgstr "URL {label} rigenerato"
#: apps/web/src/components/settings/imports-section.tsx
msgid "{movieCount} movies, {episodeCount} episodes"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{ratingCount} ratings"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{unresolvedCount} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr ""
#: apps/web/src/components/title-card.tsx #: apps/web/src/components/title-card.tsx
msgid "{watched}/{total} episodes" msgid "{watched}/{total} episodes"
msgstr "{watched}/{total} episodi" msgstr "{watched}/{total} episodi"
#. placeholder {0}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount} of {0} episodes watched" #~ msgid "{watchedCount} of {0} episodes watched"
msgstr "{watchedCount} di {0} episodi visti" #~ msgstr ""
#. placeholder {0}: episodes.length
#. placeholder {1}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}" msgid "{watchedCount} of {episodeCount} episodes watched"
msgstr "{watchedCount}/{0} {1, plural, one {episodio} other {episodi}}" msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}"
#~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} episodes" #~ msgid "{watchedCount}/{0} episodes"
#~ msgstr "{watchedCount}/{0} episodes" #~ msgstr "{watchedCount}/{0} episodes"
#: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{episodeCount, plural, one {# episode} other {# episodes}}"
msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{watchedEpisodes}/{totalEpisodes, plural, one {# episode} other {# episodes}}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{watchlistCount} items"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Account" msgid "Account"
msgstr "Account" msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Actions" msgid "Actions"
@@ -207,7 +248,7 @@ msgstr "Aggiunto alla watchlist"
#: apps/web/src/components/nav-bar.tsx #: apps/web/src/components/nav-bar.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Admin" msgid "Admin"
msgstr "Admin" msgstr ""
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Admin only" msgid "Admin only"
@@ -268,10 +309,13 @@ msgstr "Autorizzazione riuscita ma impossibile recuperare la libreria. Riprova."
msgid "Authorization was denied. Please try again." msgid "Authorization was denied. Please try again."
msgstr "Autorizzazione negata. Riprova." msgstr "Autorizzazione negata. Riprova."
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {0} library. No password shared." #~ msgid "Authorize Sofa to read your {0} library. No password shared."
msgstr "Autorizza Sofa a leggere la tua libreria {0}. Nessuna password condivisa." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {sourceLabel} library. No password shared."
msgstr ""
#: apps/web/src/components/settings/update-check-section.tsx #: apps/web/src/components/settings/update-check-section.tsx
msgid "Automatic update checks" msgid "Automatic update checks"
@@ -295,7 +339,7 @@ msgstr "Job in background"
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Backup" msgid "Backup"
msgstr "Backup" msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Backup created" msgid "Backup created"
@@ -315,8 +359,8 @@ msgid "Backups"
msgstr "Backup" msgstr "Backup"
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "backups." msgid "backups."
#~ msgstr "backups." msgstr ""
#: apps/web/src/components/titles/title-availability.tsx #: apps/web/src/components/titles/title-availability.tsx
msgid "Buy" msgid "Buy"
@@ -361,7 +405,7 @@ msgstr "Annulla modifica"
#: apps/native/src/app/title/[id].tsx #: apps/native/src/app/title/[id].tsx
#: apps/web/src/components/titles/cast-carousel.tsx #: apps/web/src/components/titles/cast-carousel.tsx
msgid "Cast" msgid "Cast"
msgstr "Cast" msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
@@ -374,11 +418,13 @@ msgstr "Recupera episodi"
msgid "Caught Up" msgid "Caught Up"
msgstr "In pari" msgstr "In pari"
#. placeholder {0}: episodeIds.length
#. placeholder {1}: episodeIds.length
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched" #~ msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched"
msgstr "Recuperati — {0} {1, plural, one {episodio} other {episodi}} segnati come visti" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {count, plural, one {# episode} other {# episodes}} as watched"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
@@ -414,10 +460,13 @@ msgstr "Controllato <0/>"
msgid "Checking…" msgid "Checking…"
msgstr "Verifica in corso…" msgstr "Verifica in corso…"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {0} data." #~ msgid "Choose how to import your {0} data."
msgstr "Scegli come importare i tuoi dati {0}." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {sourceLabel} data."
msgstr ""
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
#~ msgid "Choose your preferred display language" #~ msgid "Choose your preferred display language"
@@ -480,12 +529,12 @@ msgstr "Conferma nuova password"
msgid "Connect" msgid "Connect"
msgstr "Connetti" msgstr "Connetti"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {0}" #~ msgid "Connect {0}"
msgstr "Connetti {0}" #~ msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {label}" msgid "Connect {label}"
msgstr "Connetti {label}" msgstr "Connetti {label}"
@@ -497,10 +546,13 @@ msgstr "Connetti a {source}"
msgid "Connect to TMDB" msgid "Connect to TMDB"
msgstr "Connetti a TMDB" msgstr "Connetti a TMDB"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {0}" #~ msgid "Connect with {0}"
msgstr "Connetti con {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {sourceLabel}"
msgstr ""
#: apps/native/src/app/(auth)/server-url.tsx #: apps/native/src/app/(auth)/server-url.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -596,12 +648,12 @@ msgstr "Zona pericolosa"
#: apps/web/src/routes/_app/titles.$id.tsx #: apps/web/src/routes/_app/titles.$id.tsx
#: apps/web/src/routes/_app/titles.$id.tsx #: apps/web/src/routes/_app/titles.$id.tsx
msgid "Dashboard" msgid "Dashboard"
msgstr "Dashboard" msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Database" msgid "Database"
msgstr "Database" msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Database backups" msgid "Database backups"
@@ -703,7 +755,7 @@ msgstr "Montatore"
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
msgid "Email" msgid "Email"
msgstr "Email" 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"
@@ -740,11 +792,11 @@ msgstr "Ambiente"
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#~ msgid "Episode {0}" #~ msgid "Episode {0}"
#~ msgstr "Episodio {0}" #~ msgstr ""
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#~ msgid "Episode {0}, {episodeLabel}" #~ msgid "Episode {0}, {episodeLabel}"
#~ msgstr "Episodio {0}, {episodeLabel}" #~ msgstr ""
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
@@ -770,10 +822,13 @@ msgstr "Episodio visto"
msgid "Episodes" msgid "Episodes"
msgstr "Episodi" msgstr "Episodi"
#. placeholder {0}: periodLabels[episodePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {0}" #~ msgid "Episodes {0}"
msgstr "Episodi {0}" #~ msgstr "Episodes {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {period}"
msgstr ""
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Episodes {periodSelect}" #~ msgid "Episodes {periodSelect}"
@@ -785,17 +840,20 @@ msgstr "Episodi {select}"
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#~ msgid "Episodes this week" #~ msgid "Episodes this week"
#~ msgstr "Episodi di questa settimana" #~ msgstr ""
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
msgid "Error" msgid "Error"
msgstr "Errore" msgstr "Errore"
#. placeholder {0}: result.errors.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({0})" #~ msgid "Errors ({0})"
msgstr "Errori ({0})" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({errorCount})"
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
@@ -923,10 +981,13 @@ msgstr "Impossibile rimuovere l'immagine del profilo"
msgid "Failed to sign in" msgid "Failed to sign in"
msgstr "Impossibile accedere" msgstr "Impossibile accedere"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {0} connection" #~ msgid "Failed to start {0} connection"
msgstr "Impossibile avviare la connessione {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {sourceLabel} connection"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Failed to trigger job" msgid "Failed to trigger job"
@@ -1055,7 +1116,7 @@ msgstr "Ecco cosa sta succedendo nella tua libreria"
#: apps/web/src/components/nav-bar.tsx #: apps/web/src/components/nav-bar.tsx
#: apps/web/src/components/nav-bar.tsx #: apps/web/src/components/nav-bar.tsx
msgid "Home" msgid "Home"
msgstr "Home" msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
@@ -1086,15 +1147,18 @@ msgstr "Importazione completata"
msgid "Import failed" msgid "Import failed"
msgstr "Importazione fallita" msgstr "Importazione fallita"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {0}" #~ msgid "Import from {0}"
msgstr "Importa da {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {source}" msgid "Import from {source}"
msgstr "Importa da {source}" msgstr "Importa da {source}"
#: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {sourceLabel}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import is still running in the background. Check back later." msgid "Import is still running in the background. Check back later."
@@ -1108,11 +1172,13 @@ msgstr "Opzioni di importazione"
msgid "Imported" msgid "Imported"
msgstr "Importati" msgstr "Importati"
#. placeholder {0}: event.job.importedCount
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {0} items from {1}" #~ msgid "Imported {0} items from {1}"
msgstr "Importati {0} elementi da {1}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {importedCount} items from {sourceLabel}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Importing from {source}" msgid "Importing from {source}"
@@ -1158,14 +1224,12 @@ msgid "Job"
msgstr "Attività" msgstr "Attività"
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "Keeping" msgid "Keeping"
#~ msgstr "Keeping" msgstr ""
#. placeholder {0}: (value: string | null) => value === "0" ? t`unlimited` : value ? t`last ${value}` : null
#. placeholder {1}: [3, 5, 7, 14, 30, 0].map((n) => ( <SelectItem key={n} value={String(n)}> {n === 0 ? t`unlimited` : t`last ${n}`} </SelectItem> ))
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups." #~ msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups."
msgstr "Mantenendo <0><1><2>{0}</2></1><3>{1}</3></0> backup." #~ msgstr ""
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
@@ -1186,19 +1250,25 @@ msgstr "ultimi {n}"
msgid "last {value}" msgid "last {value}"
msgstr "ultimi {value}" msgstr "ultimi {value}"
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {0}" #~ msgid "Last event {0}"
msgstr "Ultimo evento {0}" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {relativeTime}"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last event {timeAgo}" msgid "Last event {timeAgo}"
msgstr "Ultimo evento {timeAgo}" msgstr "Ultimo evento {timeAgo}"
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {0}" #~ msgid "Last polled {0}"
msgstr "Ultimo polling {0}" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {relativeTime}"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last polled {timeAgo}" msgid "Last polled {timeAgo}"
@@ -1249,7 +1319,7 @@ msgstr "Segna tutti come visti"
#: apps/native/src/components/dashboard/continue-watching-card.tsx #: apps/native/src/components/dashboard/continue-watching-card.tsx
#~ msgid "Mark as Completed" #~ msgid "Mark as Completed"
#~ msgstr "Segna come completato" #~ msgstr ""
#: apps/native/src/components/ui/poster-card.tsx #: apps/native/src/components/ui/poster-card.tsx
msgid "Mark as Watched" msgid "Mark as Watched"
@@ -1257,7 +1327,7 @@ msgstr "Segna come visto"
#: apps/native/src/components/ui/poster-card.tsx #: apps/native/src/components/ui/poster-card.tsx
#~ msgid "Mark as Watching" #~ msgid "Mark as Watching"
#~ msgstr "Segna come in visione" #~ msgstr ""
#: apps/native/src/app/title/[id].tsx #: apps/native/src/app/title/[id].tsx
#: apps/web/src/components/titles/title-actions.tsx #: apps/web/src/components/titles/title-actions.tsx
@@ -1266,7 +1336,7 @@ msgstr "Segna come visto"
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked \"{titleName}\" as completed" #~ msgid "Marked \"{titleName}\" as completed"
#~ msgstr "Segnato \"{titleName}\" come completato" #~ msgstr ""
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
@@ -1285,7 +1355,7 @@ msgstr "Tutti gli episodi di \"{titleName}\" segnati come visti"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked as completed" #~ msgid "Marked as completed"
#~ msgstr "Segnato come completato" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -1295,7 +1365,7 @@ msgstr "Segnato come visto"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked as watching" #~ msgid "Marked as watching"
#~ msgstr "Segnato come in visione" #~ msgstr ""
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Member since {memberSince}" msgid "Member since {memberSince}"
@@ -1327,10 +1397,13 @@ msgstr "Film"
msgid "Movies" msgid "Movies"
msgstr "Film" msgstr "Film"
#. placeholder {0}: periodLabels[moviePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {0}" #~ msgid "Movies {0}"
msgstr "Film {0}" #~ msgstr "Movies {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {period}"
msgstr ""
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Movies {periodSelect}" #~ msgid "Movies {periodSelect}"
@@ -1342,7 +1415,7 @@ msgstr "Film {select}"
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#~ msgid "Movies this month" #~ msgid "Movies this month"
#~ msgstr "Film di questo mese" #~ msgstr ""
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
@@ -1511,7 +1584,7 @@ msgstr "Analisi in corso..."
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
msgid "Password" msgid "Password"
msgstr "Password" msgstr ""
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
@@ -1635,20 +1708,23 @@ msgstr "Azioni rapide"
msgid "Radarr List URL" msgid "Radarr List URL"
msgstr "URL lista Radarr" msgstr "URL lista Radarr"
#. placeholder {0}: input.stars
#. placeholder {1}: input.stars
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
msgid "Rated {0} {1, plural, one {star} other {stars}}" #~ msgid "Rated {0} {1, plural, one {star} other {stars}}"
msgstr "Valutato {0} {1, plural, one {stella} other {stelle}}" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#~ msgid "Rated {0} star{1}" #~ msgid "Rated {0} star{1}"
#~ msgstr "Rated {0} star{1}" #~ msgstr "Rated {0} star{1}"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}" msgid "Rated {ratingStars, plural, one {# star} other {# stars}}"
msgstr "Valutato {ratingStars} {ratingStars, plural, one {stella} other {stelle}}" msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}"
#~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
msgid "Rated {stars, plural, one {# star} other {# stars}}" msgid "Rated {stars, plural, one {# star} other {# stars}}"
msgstr "{stars, plural, one {# stella} other {# stelle}}" msgstr "{stars, plural, one {# stella} other {# stelle}}"
@@ -1810,6 +1886,14 @@ msgstr "Richiede un abbonamento Plex Pass attivo."
msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license." msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license."
msgstr "Richiede Emby Server 4.7.9+ e una licenza Emby Premiere attiva." msgstr "Richiede Emby Server 4.7.9+ e una licenza Emby Premiere attiva."
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart Required"
msgstr ""
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
msgid "Restore" msgid "Restore"
@@ -1921,13 +2005,19 @@ msgstr "Cerca film, serie, persone..."
msgid "Search…" msgid "Search…"
msgstr "Cerca…" msgstr "Cerca…"
#. placeholder {0}: season.seasonNumber
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {0}" #~ msgid "Season {0}"
msgstr "Stagione {0}" #~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {seasonNumber}"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -1949,7 +2039,7 @@ msgstr "Tracker film & TV self-hosted"
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Server" msgid "Server"
msgstr "Server" msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Server Health" msgid "Server Health"
@@ -2018,12 +2108,18 @@ msgstr "Accedi invece"
msgid "Sign in to continue" msgid "Sign in to continue"
msgstr "Accedi per continuare" msgstr "Accedi per continuare"
#. placeholder {0}: authConfig.data?.oidcProviderName ?? "SSO"
#. placeholder {0}: authConfig?.oidcProviderName || "SSO"
#: apps/native/src/app/(auth)/login.tsx #: apps/native/src/app/(auth)/login.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
msgid "Sign in with {0}" #~ msgid "Sign in with {0}"
msgstr "Accedi con {0}" #~ msgstr ""
#: apps/web/src/components/auth-form.tsx
msgid "Sign in with {oidcProviderName}"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
msgid "Sign in with {providerName}"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/components/header-avatar.tsx #: apps/native/src/components/header-avatar.tsx
@@ -2048,10 +2144,17 @@ msgstr "Esci dalle altre sessioni"
msgid "Skipped" msgid "Skipped"
msgstr "Ignorati" msgstr "Ignorati"
#. placeholder {0}: data.latestVersion #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Sofa needs to restart to apply the new layout direction."
msgstr ""
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "Sofa v{0} is available" #~ msgid "Sofa v{0} is available"
msgstr "Sofa v{0} è disponibile" #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "Sofa v{latestVersion} is available"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2118,10 +2221,13 @@ msgstr "Streaming"
msgid "Sunday" msgid "Sunday"
msgstr "Domenica" msgstr "Domenica"
#. placeholder {0}: info.name
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {0}" #~ msgid "Switch to {0}"
msgstr "Passa a {0}" #~ msgstr ""
#: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {name}"
msgstr ""
#: apps/native/src/app/+not-found.tsx #: apps/native/src/app/+not-found.tsx
msgid "The page you're looking for doesn't exist." msgid "The page you're looking for doesn't exist."
@@ -2192,10 +2298,13 @@ msgstr "Questo invaliderà l'URL attuale di {label}. Dovrai aggiornarlo in {labe
msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons." msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons."
msgstr "Questo segnerà tutti gli episodi di questa serie come visti. Puoi annullarlo in seguito de-segnando le singole stagioni." msgstr "Questo segnerà tutti gli episodi di questa serie come visti. Puoi annullarlo in seguito de-segnando le singole stagioni."
#. placeholder {0}: formatBackupDate(backup.createdAt)
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone." #~ msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone."
msgstr "Questo eliminerà definitivamente il backup del <0>{0}</0>. L'operazione non può essere annullata." #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{backupDate}</0>. This cannot be undone."
msgstr ""
#: apps/native/src/components/search/recently-viewed-list.ios.tsx #: apps/native/src/components/search/recently-viewed-list.ios.tsx
#: apps/native/src/components/search/recently-viewed-list.tsx #: apps/native/src/components/search/recently-viewed-list.tsx
@@ -2266,7 +2375,7 @@ msgstr "Traccia cosa guardi. Sai cosa ti aspetta.<0/>La tua libreria, i tuoi dat
#: apps/web/src/components/titles/trailer-dialog.tsx #: apps/web/src/components/titles/trailer-dialog.tsx
#: apps/web/src/components/titles/trailer-dialog.tsx #: apps/web/src/components/titles/trailer-dialog.tsx
msgid "Trailer" msgid "Trailer"
msgstr "Trailer" msgstr ""
#: apps/web/src/components/explore/hero-banner.tsx #: apps/web/src/components/explore/hero-banner.tsx
msgid "Trending today" msgid "Trending today"
@@ -2296,7 +2405,7 @@ msgstr "Martedì"
#: apps/web/src/components/people/filmography-grid.tsx #: apps/web/src/components/people/filmography-grid.tsx
#: apps/web/src/components/titles/title-hero.tsx #: apps/web/src/components/titles/title-hero.tsx
msgid "TV" msgid "TV"
msgstr "TV" msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "TV episodes" msgid "TV episodes"
@@ -2327,10 +2436,13 @@ msgstr "Senza titolo"
msgid "Unwatch all" msgid "Unwatch all"
msgstr "Rimuovi visione dalla stagione" msgstr "Rimuovi visione dalla stagione"
#. placeholder {0}: season.name ?? t`Season ${season.seasonNumber}`
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {0}" #~ msgid "Unwatched all of {0}"
msgstr "Rimossa visione di {0}" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {seasonLabel}"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched S{seasonNum} E{epNum}" msgid "Unwatched S{seasonNum} E{epNum}"
@@ -2341,10 +2453,13 @@ msgstr "Non visto S{seasonNum} E{epNum}"
msgid "Up next" msgid "Up next"
msgstr "Prossimo" msgstr "Prossimo"
#. placeholder {0}: updateCheck.data.updateCheck.latestVersion
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {0}" #~ msgid "Update available: {0}"
msgstr "Aggiornamento disponibile: {0}" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {latestVersion}"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Update check" msgid "Update check"
@@ -2381,11 +2496,13 @@ msgstr "Carica"
msgid "Upload a .db file to replace the current database. A safety backup is created first." msgid "Upload a .db file to replace the current database. A safety backup is created first."
msgstr "Carica un file .db per sostituire il database attuale. Prima viene creato un backup di sicurezza." msgstr "Carica un file .db per sostituire il database attuale. Prima viene creato un backup di sicurezza."
#. placeholder {0}: config.accept
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {0} export from your {1} account settings." #~ msgid "Upload a {0} export from your {1} account settings."
msgstr "Carica un'esportazione {0} dalle impostazioni del tuo account {1}." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {acceptFormat} export from your {sourceLabel} account settings."
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload export file" msgid "Upload export file"
@@ -2419,10 +2536,13 @@ msgstr "In attesa di autorizzazione..."
msgid "Warnings" msgid "Warnings"
msgstr "Avvisi" msgstr "Avvisi"
#. placeholder {0}: result.warnings.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({0})" #~ msgid "Warnings ({0})"
msgstr "Avvisi ({0})" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({warningCount})"
msgstr ""
#: apps/web/src/components/titles/title-seasons.tsx #: apps/web/src/components/titles/title-seasons.tsx
msgid "Watch all" msgid "Watch all"
@@ -2461,11 +2581,11 @@ msgstr "In visione"
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/components/titles/status-button.tsx #: apps/web/src/components/titles/status-button.tsx
msgid "Watchlist" msgid "Watchlist"
msgstr "Watchlist" msgstr ""
#: apps/native/src/components/titles/status-action-button.tsx #: apps/native/src/components/titles/status-action-button.tsx
#~ msgid "Watchlisted" #~ msgid "Watchlisted"
#~ msgstr "In watchlist" #~ msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2505,10 +2625,13 @@ msgstr "Sceneggiatore"
msgid "You'll be signed out to change the server URL." msgid "You'll be signed out to change the server URL."
msgstr "Verrai disconnesso per cambiare l'URL del server." msgstr "Verrai disconnesso per cambiare l'URL del server."
#. placeholder {0}: data.currentVersion
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "You're running v{0}." #~ msgid "You're running v{0}."
msgstr "Stai usando la v{0}." #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "You're running v{currentVersion}."
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Your code:" msgid "Your code:"
@@ -2522,3 +2645,4 @@ msgstr "La tua libreria è vuota"
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
msgid "Your name" msgid "Your name"
msgstr "Il tuo nome" msgstr "Il tuo nome"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+280 -156
View File
@@ -8,20 +8,23 @@ msgstr ""
"Language: pt\n" "Language: pt\n"
"Project-Id-Version: sofa\n" "Project-Id-Version: sofa\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-03-19 00:35\n" "PO-Revision-Date: 2026-03-20 23:13\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Portuguese\n" "Language-Team: Portuguese\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: sofa\n" "X-Crowdin-Project: sofa\n"
"X-Crowdin-Project-ID: 881052\n" "X-Crowdin-Project-ID: 881052\n"
"X-Crowdin-Language: pt-PT\n" "X-Crowdin-Language: pt-PT\n"
"X-Crowdin-File: en.po\n" "X-Crowdin-File: /packages/i18n/src/po/en.po\n"
"X-Crowdin-File-ID: 14\n" "X-Crowdin-File-ID: 26\n"
#. placeholder {0}: result.errors.length - 50
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "...and {0} more" #~ msgid "...and {0} more"
msgstr "...e mais {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "...and {remainingErrors} more"
msgstr ""
#. placeholder {0}: systemHealth.data.imageCache.imageCount #. placeholder {0}: systemHealth.data.imageCache.imageCount
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -33,86 +36,99 @@ msgstr "{0, plural, one {# imagem} other {# imagens}}"
msgid "{0, plural, one {# title} other {# titles}}" msgid "{0, plural, one {# title} other {# titles}}"
msgstr "{0, plural, one {# título} other {# títulos}}" msgstr "{0, plural, one {# título} other {# títulos}}"
#. placeholder {0}: displayBackups.length
#. placeholder {1}: displayBackups.length
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "{0} {1, plural, one {backup} other {backups}} stored" #~ msgid "{0} {1, plural, one {backup} other {backups}} stored"
msgstr "{0} {1, plural, one {backup armazenado} other {backups armazenados}}" #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
#~ msgid "{0} backup{1} stored" #~ msgid "{0} backup{1} stored"
#~ msgstr "{0} backup{1} stored" #~ msgstr "{0} backup{1} stored"
#. placeholder {0}: backups.backupCount
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} backups · last <0/>" #~ msgid "{0} backups · last <0/>"
msgstr "{0} backups · último <0/>" #~ msgstr ""
#. placeholder {0}: imageCache.imageCount.toLocaleString()
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} cached images" #~ msgid "{0} cached images"
msgstr "{0} imagens em cache" #~ msgstr ""
#. placeholder {0}: member.episodeCount
#. placeholder {1}: member.episodeCount !== 1 ? "s" : ""
#: apps/web/src/components/titles/cast-carousel.tsx #: apps/web/src/components/titles/cast-carousel.tsx
msgid "{0} ep{1}" #~ msgid "{0} ep{1}"
msgstr "{0} ep{1}" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} images" #~ msgid "{0} images"
#~ msgstr "{0} images" #~ msgstr "{0} images"
#. placeholder {0}: stats.watchlist
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items" #~ msgid "{0} items"
msgstr "{0} itens" #~ msgstr ""
#. placeholder {0}: preview.diagnostics.unresolved
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate." #~ msgid "{0} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr "{0} itens não têm IDs externos e serão resolvidos por pesquisa de título, o que pode ser menos preciso." #~ msgstr ""
#. placeholder {0}: stats.movies
#. placeholder {1}: stats.episodes
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} movies, {1} episodes" #~ msgid "{0} movies, {1} episodes"
msgstr "{0} filmes, {1} episódios" #~ msgstr ""
#. placeholder {0}: stats.ratings
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "{0} ratings" #~ msgid "{0} ratings"
msgstr "{0} avaliações" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#~ msgid "{0} titles" #~ msgid "{0} titles"
#~ msgstr "{0} titles" #~ msgstr "{0} titles"
#. placeholder {0}: JOB_LABELS[name] ?? name
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{0} triggered" #~ msgid "{0} triggered"
msgstr "{0} acionado" #~ msgstr ""
#. placeholder {0}: item.watchedEpisodes
#. placeholder {1}: item.totalEpisodes
#. placeholder {2}: item.totalEpisodes
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{0}/{1} {2, plural, one {episode} other {episodes}}" #~ msgid "{0}/{1} {2, plural, one {episode} other {episodes}}"
msgstr "{0}/{1} {2, plural, one {episódio} other {episódios}}" #~ msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx #: apps/web/src/components/dashboard/continue-watching-card.tsx
#~ msgid "{0}/{1} episodes" #~ msgid "{0}/{1} episodes"
#~ msgstr "{0}/{1} episodes" #~ msgstr "{0}/{1} episodes"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/settings/backup-section.tsx
#: apps/web/src/components/titles/use-title-actions.ts msgid "{backupCount, plural, one {# backup} other {# backups}} stored"
msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched" msgstr ""
msgstr "{count} {count, plural, one {episódio anterior não assistido} other {episódios anteriores não assistidos}}"
#. placeholder {0}: activeJobs.length
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {0} jobs healthy" msgid "{backupCount} backups · last <0/>"
msgstr "{healthyCount} de {0} tarefas saudáveis" msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{cachedImageCount} cached images"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "{count, plural, one {# earlier episode} other {# earlier episodes}} unwatched"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "{count} earlier {count, plural, one {episode} other {episodes}} unwatched"
#~ msgstr ""
#: apps/web/src/components/titles/cast-carousel.tsx
msgid "{count} ep{suffix}"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
#~ msgid "{healthyCount} of {0} jobs healthy"
#~ msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{healthyCount} of {activeJobCount} jobs healthy"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx
msgid "{jobLabel} triggered"
msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
@@ -129,25 +145,50 @@ msgstr "{label} desconectado"
msgid "{label} URL regenerated" msgid "{label} URL regenerated"
msgstr "URL de {label} regenerada" msgstr "URL de {label} regenerada"
#: apps/web/src/components/settings/imports-section.tsx
msgid "{movieCount} movies, {episodeCount} episodes"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{ratingCount} ratings"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{unresolvedCount} items have no external IDs and will be resolved by title search, which may be less accurate."
msgstr ""
#: apps/web/src/components/title-card.tsx #: apps/web/src/components/title-card.tsx
msgid "{watched}/{total} episodes" msgid "{watched}/{total} episodes"
msgstr "{watched}/{total} episódios" msgstr "{watched}/{total} episódios"
#. placeholder {0}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount} of {0} episodes watched" #~ msgid "{watchedCount} of {0} episodes watched"
msgstr "{watchedCount} de {0} episódios assistidos" #~ msgstr ""
#. placeholder {0}: episodes.length
#. placeholder {1}: episodes.length
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}" msgid "{watchedCount} of {episodeCount} episodes watched"
msgstr "{watchedCount}/{0} {1, plural, one {episódio} other {episódios}}" msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} {1, plural, one {episode} other {episodes}}"
#~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#~ msgid "{watchedCount}/{0} episodes" #~ msgid "{watchedCount}/{0} episodes"
#~ msgstr "{watchedCount}/{0} episodes" #~ msgstr "{watchedCount}/{0} episodes"
#: apps/native/src/components/titles/season-accordion.tsx
msgid "{watchedCount}/{episodeCount, plural, one {# episode} other {# episodes}}"
msgstr ""
#: apps/web/src/components/dashboard/continue-watching-card.tsx
msgid "{watchedEpisodes}/{totalEpisodes, plural, one {# episode} other {# episodes}}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "{watchlistCount} items"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Account" msgid "Account"
@@ -268,10 +309,13 @@ msgstr "Autorização concluída, mas falha ao buscar sua biblioteca. Tente nova
msgid "Authorization was denied. Please try again." msgid "Authorization was denied. Please try again."
msgstr "Autorização negada. Tente novamente." msgstr "Autorização negada. Tente novamente."
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {0} library. No password shared." #~ msgid "Authorize Sofa to read your {0} library. No password shared."
msgstr "Autorize o Sofa a ler sua biblioteca do {0}. Nenhuma senha é compartilhada." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Authorize Sofa to read your {sourceLabel} library. No password shared."
msgstr ""
#: apps/web/src/components/settings/update-check-section.tsx #: apps/web/src/components/settings/update-check-section.tsx
msgid "Automatic update checks" msgid "Automatic update checks"
@@ -295,7 +339,7 @@ msgstr "Tarefas em segundo plano"
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Backup" msgid "Backup"
msgstr "Backup" msgstr ""
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "Backup created" msgid "Backup created"
@@ -312,11 +356,11 @@ msgstr "Agendamento de backup"
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
#: apps/web/src/routes/_app/settings.tsx #: apps/web/src/routes/_app/settings.tsx
msgid "Backups" msgid "Backups"
msgstr "Backups" msgstr ""
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "backups." msgid "backups."
#~ msgstr "backups." msgstr ""
#: apps/web/src/components/titles/title-availability.tsx #: apps/web/src/components/titles/title-availability.tsx
msgid "Buy" msgid "Buy"
@@ -374,11 +418,13 @@ msgstr "Colocar em dia"
msgid "Caught Up" msgid "Caught Up"
msgstr "Em dia" msgstr "Em dia"
#. placeholder {0}: episodeIds.length
#. placeholder {1}: episodeIds.length
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched" #~ msgid "Caught up — marked {0} {1, plural, one {episode} other {episodes}} as watched"
msgstr "Em dia — {0} {1, plural, one {episódio marcado como assistido} other {episódios marcados como assistidos}}" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Caught up — marked {count, plural, one {# episode} other {# episodes}} as watched"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
@@ -414,10 +460,13 @@ msgstr "Verificado <0/>"
msgid "Checking…" msgid "Checking…"
msgstr "Verificando…" msgstr "Verificando…"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {0} data." #~ msgid "Choose how to import your {0} data."
msgstr "Escolha como importar seus dados do {0}." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Choose how to import your {sourceLabel} data."
msgstr ""
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
#~ msgid "Choose your preferred display language" #~ msgid "Choose your preferred display language"
@@ -480,12 +529,12 @@ msgstr "Confirmar nova senha"
msgid "Connect" msgid "Connect"
msgstr "Conectar" msgstr "Conectar"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {0}" #~ msgid "Connect {0}"
msgstr "Conectar {0}" #~ msgstr ""
#: apps/native/src/components/settings/integration-card.tsx #: apps/native/src/components/settings/integration-card.tsx
#: apps/web/src/components/settings/integration-card.tsx
msgid "Connect {label}" msgid "Connect {label}"
msgstr "Conectar {label}" msgstr "Conectar {label}"
@@ -497,10 +546,13 @@ msgstr "Conectar a {source}"
msgid "Connect to TMDB" msgid "Connect to TMDB"
msgstr "Conectar ao TMDB" msgstr "Conectar ao TMDB"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {0}" #~ msgid "Connect with {0}"
msgstr "Conectar com {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Connect with {sourceLabel}"
msgstr ""
#: apps/native/src/app/(auth)/server-url.tsx #: apps/native/src/app/(auth)/server-url.tsx
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
@@ -697,7 +749,7 @@ msgstr "Baixar backup"
#: apps/native/src/components/search/recently-viewed-row-content.tsx #: apps/native/src/components/search/recently-viewed-row-content.tsx
#: apps/web/src/components/people/person-hero.tsx #: apps/web/src/components/people/person-hero.tsx
msgid "Editor" msgid "Editor"
msgstr "Editor" msgstr ""
#: apps/native/src/app/(auth)/login.tsx #: apps/native/src/app/(auth)/login.tsx
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
@@ -740,11 +792,11 @@ msgstr "Ambiente"
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#~ msgid "Episode {0}" #~ msgid "Episode {0}"
#~ msgstr "Episódio {0}" #~ msgstr ""
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#~ msgid "Episode {0}, {episodeLabel}" #~ msgid "Episode {0}, {episodeLabel}"
#~ msgstr "Episódio {0}, {episodeLabel}" #~ msgstr ""
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
#: apps/native/src/components/titles/episode-row.tsx #: apps/native/src/components/titles/episode-row.tsx
@@ -770,10 +822,13 @@ msgstr "Episódio assistido"
msgid "Episodes" msgid "Episodes"
msgstr "Episódios" msgstr "Episódios"
#. placeholder {0}: periodLabels[episodePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {0}" #~ msgid "Episodes {0}"
msgstr "Episódios {0}" #~ msgstr "Episodes {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Episodes {period}"
msgstr ""
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Episodes {periodSelect}" #~ msgid "Episodes {periodSelect}"
@@ -785,17 +840,20 @@ msgstr "Episódios {select}"
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#~ msgid "Episodes this week" #~ msgid "Episodes this week"
#~ msgstr "Episódios desta semana" #~ msgstr ""
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
#: apps/native/src/app/change-password.tsx #: apps/native/src/app/change-password.tsx
msgid "Error" msgid "Error"
msgstr "Erro" msgstr "Erro"
#. placeholder {0}: result.errors.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({0})" #~ msgid "Errors ({0})"
msgstr "Erros ({0})" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Errors ({errorCount})"
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
@@ -923,10 +981,13 @@ msgstr "Falha ao remover foto de perfil"
msgid "Failed to sign in" msgid "Failed to sign in"
msgstr "Falha ao entrar" msgstr "Falha ao entrar"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {0} connection" #~ msgid "Failed to start {0} connection"
msgstr "Falha ao iniciar conexão com {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Failed to start {sourceLabel} connection"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Failed to trigger job" msgid "Failed to trigger job"
@@ -1086,15 +1147,18 @@ msgstr "Importação concluída"
msgid "Import failed" msgid "Import failed"
msgstr "Importação falhou" msgstr "Importação falhou"
#. placeholder {0}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {0}" #~ msgid "Import from {0}"
msgstr "Importar de {0}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {source}" msgid "Import from {source}"
msgstr "Importar de {source}" msgstr "Importar de {source}"
#: apps/web/src/components/settings/imports-section.tsx
msgid "Import from {sourceLabel}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Import is still running in the background. Check back later." msgid "Import is still running in the background. Check back later."
@@ -1108,11 +1172,13 @@ msgstr "Opções de importação"
msgid "Imported" msgid "Imported"
msgstr "Importado" msgstr "Importado"
#. placeholder {0}: event.job.importedCount
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {0} items from {1}" #~ msgid "Imported {0} items from {1}"
msgstr "Importados {0} itens de {1}" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Imported {importedCount} items from {sourceLabel}"
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Importing from {source}" msgid "Importing from {source}"
@@ -1158,14 +1224,12 @@ msgid "Job"
msgstr "Tarefa" msgstr "Tarefa"
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
#~ msgid "Keeping" msgid "Keeping"
#~ msgstr "Keeping" msgstr ""
#. placeholder {0}: (value: string | null) => value === "0" ? t`unlimited` : value ? t`last ${value}` : null
#. placeholder {1}: [3, 5, 7, 14, 30, 0].map((n) => ( <SelectItem key={n} value={String(n)}> {n === 0 ? t`unlimited` : t`last ${n}`} </SelectItem> ))
#: apps/web/src/components/settings/backup-schedule-section.tsx #: apps/web/src/components/settings/backup-schedule-section.tsx
msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups." #~ msgid "Keeping <0><1><2>{0}</2></1><3>{1}</3></0> backups."
msgstr "Mantendo <0><1><2>{0}</2></1><3>{1}</3></0> backups." #~ msgstr ""
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
#: apps/web/src/components/command-palette.tsx #: apps/web/src/components/command-palette.tsx
@@ -1186,19 +1250,25 @@ msgstr "últimos {n}"
msgid "last {value}" msgid "last {value}"
msgstr "últimos {value}" msgstr "últimos {value}"
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {0}" #~ msgid "Last event {0}"
msgstr "Último evento {0}" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last event {relativeTime}"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last event {timeAgo}" msgid "Last event {timeAgo}"
msgstr "Último evento {timeAgo}" msgstr "Último evento {timeAgo}"
#. placeholder {0}: formatRelativeTime(lastEventAt)
#: apps/web/src/components/settings/integration-card.tsx #: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {0}" #~ msgid "Last polled {0}"
msgstr "Última verificação {0}" #~ msgstr ""
#: apps/web/src/components/settings/integration-card.tsx
msgid "Last polled {relativeTime}"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
msgid "Last polled {timeAgo}" msgid "Last polled {timeAgo}"
@@ -1249,7 +1319,7 @@ msgstr "Marcar Todos como Assistidos"
#: apps/native/src/components/dashboard/continue-watching-card.tsx #: apps/native/src/components/dashboard/continue-watching-card.tsx
#~ msgid "Mark as Completed" #~ msgid "Mark as Completed"
#~ msgstr "Marcar como Concluído" #~ msgstr ""
#: apps/native/src/components/ui/poster-card.tsx #: apps/native/src/components/ui/poster-card.tsx
msgid "Mark as Watched" msgid "Mark as Watched"
@@ -1257,7 +1327,7 @@ msgstr "Marcar como Assistido"
#: apps/native/src/components/ui/poster-card.tsx #: apps/native/src/components/ui/poster-card.tsx
#~ msgid "Mark as Watching" #~ msgid "Mark as Watching"
#~ msgstr "Marcar como Assistindo" #~ msgstr ""
#: apps/native/src/app/title/[id].tsx #: apps/native/src/app/title/[id].tsx
#: apps/web/src/components/titles/title-actions.tsx #: apps/web/src/components/titles/title-actions.tsx
@@ -1266,7 +1336,7 @@ msgstr "Marcar como Assistido"
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked \"{titleName}\" as completed" #~ msgid "Marked \"{titleName}\" as completed"
#~ msgstr "Marcado \"{titleName}\" como concluído" #~ msgstr ""
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
@@ -1285,7 +1355,7 @@ msgstr "Todos os episódios de \"{titleName}\" marcados como vistos"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked as completed" #~ msgid "Marked as completed"
#~ msgstr "Marcado como concluído" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -1295,7 +1365,7 @@ msgstr "Marcado como assistido"
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
#~ msgid "Marked as watching" #~ msgid "Marked as watching"
#~ msgstr "Marcado como assistindo" #~ msgstr ""
#: apps/web/src/components/settings/account-section.tsx #: apps/web/src/components/settings/account-section.tsx
msgid "Member since {memberSince}" msgid "Member since {memberSince}"
@@ -1327,10 +1397,13 @@ msgstr "Filme"
msgid "Movies" msgid "Movies"
msgstr "Filmes" msgstr "Filmes"
#. placeholder {0}: periodLabels[moviePeriod]
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {0}" #~ msgid "Movies {0}"
msgstr "Filmes {0}" #~ msgstr "Movies {0}"
#: apps/native/src/app/(tabs)/(home)/index.tsx
msgid "Movies {period}"
msgstr ""
#: apps/web/src/components/dashboard/stats-display.tsx #: apps/web/src/components/dashboard/stats-display.tsx
#~ msgid "Movies {periodSelect}" #~ msgid "Movies {periodSelect}"
@@ -1342,7 +1415,7 @@ msgstr "Filmes {select}"
#: apps/native/src/app/(tabs)/(home)/index.tsx #: apps/native/src/app/(tabs)/(home)/index.tsx
#~ msgid "Movies this month" #~ msgid "Movies this month"
#~ msgstr "Filmes este mês" #~ msgstr ""
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
@@ -1635,20 +1708,23 @@ msgstr "Ações Rápidas"
msgid "Radarr List URL" msgid "Radarr List URL"
msgstr "URL da Lista do Radarr" msgstr "URL da Lista do Radarr"
#. placeholder {0}: input.stars
#. placeholder {1}: input.stars
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
msgid "Rated {0} {1, plural, one {star} other {stars}}" #~ msgid "Rated {0} {1, plural, one {star} other {stars}}"
msgstr "Avaliado com {0} {1, plural, one {estrela} other {estrelas}}" #~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#~ msgid "Rated {0} star{1}" #~ msgid "Rated {0} star{1}"
#~ msgstr "Rated {0} star{1}" #~ msgstr "Rated {0} star{1}"
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}" msgid "Rated {ratingStars, plural, one {# star} other {# stars}}"
msgstr "Avaliado com {ratingStars} {ratingStars, plural, one {estrela} other {estrelas}}" msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
#~ msgid "Rated {ratingStars} {ratingStars, plural, one {star} other {stars}}"
#~ msgstr ""
#: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
msgid "Rated {stars, plural, one {# star} other {# stars}}" msgid "Rated {stars, plural, one {# star} other {# stars}}"
msgstr "Avaliado com {stars, plural, one {# estrela} other {# estrelas}}" msgstr "Avaliado com {stars, plural, one {# estrela} other {# estrelas}}"
@@ -1810,6 +1886,14 @@ msgstr "Requer uma assinatura ativa do Plex Pass."
msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license." msgid "Requires Emby Server 4.7.9+ and an active Emby Premiere license."
msgstr "Requer Emby Server 4.7.9+ e uma licença ativa do Emby Premiere." msgstr "Requer Emby Server 4.7.9+ e uma licença ativa do Emby Premiere."
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Restart Required"
msgstr ""
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
#: apps/web/src/components/settings/backup-restore-section.tsx #: apps/web/src/components/settings/backup-restore-section.tsx
msgid "Restore" msgid "Restore"
@@ -1921,13 +2005,19 @@ msgstr "Pesquisar filmes, séries, pessoas..."
msgid "Search…" msgid "Search…"
msgstr "Pesquisar…" msgstr "Pesquisar…"
#. placeholder {0}: season.seasonNumber
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx #: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {0}" #~ msgid "Season {0}"
msgstr "Temporada {0}" #~ msgstr ""
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/native/src/components/titles/season-accordion.tsx
#: apps/web/src/components/titles/use-title-actions.ts
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Season {seasonNumber}"
msgstr ""
#: apps/native/src/hooks/use-title-actions.ts #: apps/native/src/hooks/use-title-actions.ts
#: apps/native/src/lib/title-actions.ts #: apps/native/src/lib/title-actions.ts
@@ -2018,12 +2108,18 @@ msgstr "Entrar em vez disso"
msgid "Sign in to continue" msgid "Sign in to continue"
msgstr "Entre para continuar" msgstr "Entre para continuar"
#. placeholder {0}: authConfig.data?.oidcProviderName ?? "SSO"
#. placeholder {0}: authConfig?.oidcProviderName || "SSO"
#: apps/native/src/app/(auth)/login.tsx #: apps/native/src/app/(auth)/login.tsx
#: apps/web/src/components/auth-form.tsx #: apps/web/src/components/auth-form.tsx
msgid "Sign in with {0}" #~ msgid "Sign in with {0}"
msgstr "Entrar com {0}" #~ msgstr ""
#: apps/web/src/components/auth-form.tsx
msgid "Sign in with {oidcProviderName}"
msgstr ""
#: apps/native/src/app/(auth)/login.tsx
msgid "Sign in with {providerName}"
msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
#: apps/native/src/components/header-avatar.tsx #: apps/native/src/components/header-avatar.tsx
@@ -2048,10 +2144,17 @@ msgstr "Sair de outras sessões"
msgid "Skipped" msgid "Skipped"
msgstr "Ignorado" msgstr "Ignorado"
#. placeholder {0}: data.latestVersion #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Sofa needs to restart to apply the new layout direction."
msgstr ""
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "Sofa v{0} is available" #~ msgid "Sofa v{0} is available"
msgstr "Sofa v{0} está disponível" #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "Sofa v{latestVersion} is available"
msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2118,10 +2221,13 @@ msgstr "Streaming"
msgid "Sunday" msgid "Sunday"
msgstr "Domingo" msgstr "Domingo"
#. placeholder {0}: info.name
#: apps/web/src/components/settings/language-section.tsx #: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {0}" #~ msgid "Switch to {0}"
msgstr "Mudar para {0}" #~ msgstr ""
#: apps/web/src/components/settings/language-section.tsx
msgid "Switch to {name}"
msgstr ""
#: apps/native/src/app/+not-found.tsx #: apps/native/src/app/+not-found.tsx
msgid "The page you're looking for doesn't exist." msgid "The page you're looking for doesn't exist."
@@ -2192,10 +2298,13 @@ msgstr "Isso invalidará a URL atual do {label}. Você precisará atualizá-la n
msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons." msgid "This will mark every episode of this show as watched. You can undo this later by unmarking individual seasons."
msgstr "Isso marcará todos os episódios desta série como assistidos. Você pode desfazer isso mais tarde desmarcando temporadas individuais." msgstr "Isso marcará todos os episódios desta série como assistidos. Você pode desfazer isso mais tarde desmarcando temporadas individuais."
#. placeholder {0}: formatBackupDate(backup.createdAt)
#: apps/web/src/components/settings/backup-section.tsx #: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone." #~ msgid "This will permanently delete the backup from <0>{0}</0>. This cannot be undone."
msgstr "Isso excluirá permanentemente o backup de <0>{0}</0>. Esta ação não pode ser desfeita." #~ msgstr ""
#: apps/web/src/components/settings/backup-section.tsx
msgid "This will permanently delete the backup from <0>{backupDate}</0>. This cannot be undone."
msgstr ""
#: apps/native/src/components/search/recently-viewed-list.ios.tsx #: apps/native/src/components/search/recently-viewed-list.ios.tsx
#: apps/native/src/components/search/recently-viewed-list.tsx #: apps/native/src/components/search/recently-viewed-list.tsx
@@ -2266,7 +2375,7 @@ msgstr "Acompanhe o que você assiste. Saiba o que vem a seguir.<0/>Sua bibliote
#: apps/web/src/components/titles/trailer-dialog.tsx #: apps/web/src/components/titles/trailer-dialog.tsx
#: apps/web/src/components/titles/trailer-dialog.tsx #: apps/web/src/components/titles/trailer-dialog.tsx
msgid "Trailer" msgid "Trailer"
msgstr "Trailer" msgstr ""
#: apps/web/src/components/explore/hero-banner.tsx #: apps/web/src/components/explore/hero-banner.tsx
msgid "Trending today" msgid "Trending today"
@@ -2327,10 +2436,13 @@ msgstr "Sem título"
msgid "Unwatch all" msgid "Unwatch all"
msgstr "Desmarcar todos" msgstr "Desmarcar todos"
#. placeholder {0}: season.name ?? t`Season ${season.seasonNumber}`
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {0}" #~ msgid "Unwatched all of {0}"
msgstr "Desmarcados todos os episódios de {0}" #~ msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched all of {seasonLabel}"
msgstr ""
#: apps/web/src/components/titles/use-title-actions.ts #: apps/web/src/components/titles/use-title-actions.ts
msgid "Unwatched S{seasonNum} E{epNum}" msgid "Unwatched S{seasonNum} E{epNum}"
@@ -2341,10 +2453,13 @@ msgstr "Desmarcado T{seasonNum} E{epNum}"
msgid "Up next" msgid "Up next"
msgstr "A seguir" msgstr "A seguir"
#. placeholder {0}: updateCheck.data.updateCheck.latestVersion
#: apps/native/src/app/(tabs)/(settings)/index.tsx #: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {0}" #~ msgid "Update available: {0}"
msgstr "Atualização disponível: {0}" #~ msgstr ""
#: apps/native/src/app/(tabs)/(settings)/index.tsx
msgid "Update available: {latestVersion}"
msgstr ""
#: apps/web/src/components/settings/system-health-section.tsx #: apps/web/src/components/settings/system-health-section.tsx
msgid "Update check" msgid "Update check"
@@ -2381,11 +2496,13 @@ msgstr "Enviar"
msgid "Upload a .db file to replace the current database. A safety backup is created first." msgid "Upload a .db file to replace the current database. A safety backup is created first."
msgstr "Envie um arquivo .db para substituir o banco de dados atual. Um backup de segurança é criado primeiro." msgstr "Envie um arquivo .db para substituir o banco de dados atual. Um backup de segurança é criado primeiro."
#. placeholder {0}: config.accept
#. placeholder {1}: config.label
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {0} export from your {1} account settings." #~ msgid "Upload a {0} export from your {1} account settings."
msgstr "Envie um export {0} das configurações da sua conta {1}." #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Upload a {acceptFormat} export from your {sourceLabel} account settings."
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Upload export file" msgid "Upload export file"
@@ -2419,10 +2536,13 @@ msgstr "Aguardando autorização..."
msgid "Warnings" msgid "Warnings"
msgstr "Avisos" msgstr "Avisos"
#. placeholder {0}: result.warnings.length
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({0})" #~ msgid "Warnings ({0})"
msgstr "Avisos ({0})" #~ msgstr ""
#: apps/web/src/components/settings/imports-section.tsx
msgid "Warnings ({warningCount})"
msgstr ""
#: apps/web/src/components/titles/title-seasons.tsx #: apps/web/src/components/titles/title-seasons.tsx
msgid "Watch all" msgid "Watch all"
@@ -2465,7 +2585,7 @@ msgstr "Lista de Desejos"
#: apps/native/src/components/titles/status-action-button.tsx #: apps/native/src/components/titles/status-action-button.tsx
#~ msgid "Watchlisted" #~ msgid "Watchlisted"
#~ msgstr "Na Lista de Desejos" #~ msgstr ""
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
#: apps/native/src/components/settings/integration-configs.ts #: apps/native/src/components/settings/integration-configs.ts
@@ -2505,10 +2625,13 @@ msgstr "Roteirista"
msgid "You'll be signed out to change the server URL." msgid "You'll be signed out to change the server URL."
msgstr "Você será desconectado para alterar a URL do servidor." msgstr "Você será desconectado para alterar a URL do servidor."
#. placeholder {0}: data.currentVersion
#: apps/web/src/components/update-toast.tsx #: apps/web/src/components/update-toast.tsx
msgid "You're running v{0}." #~ msgid "You're running v{0}."
msgstr "Você está usando a v{0}." #~ msgstr ""
#: apps/web/src/components/update-toast.tsx
msgid "You're running v{currentVersion}."
msgstr ""
#: apps/web/src/components/settings/imports-section.tsx #: apps/web/src/components/settings/imports-section.tsx
msgid "Your code:" msgid "Your code:"
@@ -2522,3 +2645,4 @@ msgstr "Sua biblioteca está vazia"
#: apps/native/src/app/(auth)/register.tsx #: apps/native/src/app/(auth)/register.tsx
msgid "Your name" msgid "Your name"
msgstr "Seu nome" msgstr "Seu nome"
File diff suppressed because it is too large Load Diff