v3: lots of small UI tweaks and fixes
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 46s
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 46s
This commit is contained in:
89
src/App.css
89
src/App.css
@@ -1288,6 +1288,36 @@ body.has-player .fab-new {
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.profile-info {
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.profile-info-scroll {
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
padding-bottom: 0.25rem;
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
|
||||
.profile-info-scroll::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Fade hint only at narrow viewports where the info column can actually overflow */
|
||||
@media (max-width: 600px) {
|
||||
.profile-info::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 2rem;
|
||||
background: linear-gradient(to right, transparent, var(--color-bg));
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-tabs-scroller {
|
||||
margin-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
@@ -1854,6 +1884,33 @@ body.has-player .fab-new {
|
||||
.app-header-center {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.app-header-center .search-bar-btn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Below-header search row — small viewports only */
|
||||
.header-search-below {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem 1rem;
|
||||
background: var(--color-surface);
|
||||
border-bottom: 2px solid var(--color-border);
|
||||
}
|
||||
|
||||
.header-search-below .search-bar {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.header-search-below .search-bar-input {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@media (min-width: 860px) {
|
||||
.header-search-below {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* When the search bar is expanded, immediately clear the rest of the center —
|
||||
@@ -1917,12 +1974,32 @@ body.has-player .fab-new {
|
||||
.app-header-nav button {
|
||||
padding: 0.35rem 0.85rem;
|
||||
font-size: 0.95rem;
|
||||
font-family: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.app-header-nav .btn-primary {
|
||||
padding: 0.35rem 1rem;
|
||||
}
|
||||
|
||||
/* Ghost search button — always visible except when the center search bar is shown */
|
||||
.nav-search-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.35rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.nav-search-btn:hover {
|
||||
background: var(--color-surface);
|
||||
}
|
||||
|
||||
/* Text links — visible only at wide viewports */
|
||||
.nav-links {
|
||||
display: none;
|
||||
@@ -2204,6 +2281,7 @@ body.has-player .fab-new {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.25em;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
@@ -2360,7 +2438,7 @@ body.has-player .fab-new {
|
||||
/* Right-edge gradient: absolutely positioned over the scroll container,
|
||||
always at the viewport-right edge regardless of scroll position */
|
||||
.feed-sort-scroller::after {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
@@ -2387,6 +2465,7 @@ body.has-player .fab-new {
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
padding-bottom: 0.3rem;
|
||||
padding-right: 0.25rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@@ -2525,7 +2604,6 @@ body.has-player .fab-new {
|
||||
order: 0;
|
||||
}
|
||||
|
||||
|
||||
/* Left column: preview + vote stacked with fixed gap, independent of body height */
|
||||
.dump-card-left {
|
||||
display: flex;
|
||||
@@ -3052,7 +3130,6 @@ body.has-player .fab-new {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
.playlist-detail-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
@@ -3907,6 +3984,7 @@ body.has-player .fab-new {
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
padding: 0.35rem 0.85rem;
|
||||
border-radius: 8px;
|
||||
transition: background 0.15s;
|
||||
@@ -4398,12 +4476,9 @@ body.has-player .fab-new {
|
||||
}
|
||||
|
||||
.search-tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
padding: 1rem 1.25rem 0;
|
||||
width: 100%;
|
||||
max-width: 860px;
|
||||
padding: 1rem 1.25rem 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ const ResetPassword = lazy(() =>
|
||||
default: m.ResetPassword,
|
||||
}))
|
||||
);
|
||||
const NotFound = lazy(() =>
|
||||
import("./pages/NotFound.tsx").then((m) => ({ default: m.NotFound }))
|
||||
);
|
||||
|
||||
function AppRoutes() {
|
||||
return (
|
||||
@@ -111,6 +114,7 @@ function AppRoutes() {
|
||||
</RestrictedLoggedIn>
|
||||
}
|
||||
/>
|
||||
<Route path="*" element={<NotFound />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { lazy, type ReactNode, Suspense, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router";
|
||||
import { Link, useLocation, useNavigate } from "react-router";
|
||||
import { t } from "@lingui/core/macro";
|
||||
import { Trans } from "@lingui/react/macro";
|
||||
import { useAuth } from "../hooks/useAuth.ts";
|
||||
import { useWS } from "../hooks/useWS.ts";
|
||||
import { NotificationBell } from "./NotificationBell.tsx";
|
||||
import { UserMenu } from "./UserMenu.tsx";
|
||||
import { SearchBar } from "./SearchBar.tsx";
|
||||
|
||||
const DumpCreateModal = lazy(() =>
|
||||
import("./DumpCreateModal.tsx").then((m) => ({ default: m.DumpCreateModal }))
|
||||
@@ -21,21 +22,51 @@ export function AppHeader(
|
||||
const { user } = useAuth();
|
||||
const { wsStatus, wsErrorMessage } = useWS();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const isSearchPage = location.pathname === "/search";
|
||||
const [searchExpanded, setSearchExpanded] = useState(isSearchPage);
|
||||
const [createModalOpen, setCreateModalOpen] = useState(!!initialDumpUrl);
|
||||
|
||||
function handleSearchToggle() {
|
||||
if (searchExpanded) {
|
||||
if (isSearchPage) {
|
||||
navigate(-1);
|
||||
} else {
|
||||
setSearchExpanded(false);
|
||||
}
|
||||
} else {
|
||||
setSearchExpanded(true);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<header
|
||||
className={`app-header${centerSlot ? " app-header--has-center" : ""}`}
|
||||
>
|
||||
<header className="app-header app-header--has-center">
|
||||
<Link to="/?tab=hot" className="app-header-brand">
|
||||
🚚<span className="app-header-brand-name">{" "}{document.querySelector<HTMLMetaElement>('meta[name="site-name"]')
|
||||
?.content ?? "gerbeur"}</span>
|
||||
🚚<span className="app-header-brand-name">
|
||||
{" "}
|
||||
{document.querySelector<HTMLMetaElement>('meta[name="site-name"]')
|
||||
?.content ?? "gerbeur"}
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{centerSlot && <div className="app-header-center">{centerSlot}</div>}
|
||||
<div className="app-header-center">
|
||||
{centerSlot}
|
||||
<SearchBar
|
||||
expanded={searchExpanded}
|
||||
onExpandedChange={setSearchExpanded}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<nav className="app-header-nav">
|
||||
<button
|
||||
type="button"
|
||||
className="nav-search-btn"
|
||||
aria-label={searchExpanded ? t`Cancel search` : t`Search`}
|
||||
onClick={handleSearchToggle}
|
||||
>
|
||||
{searchExpanded ? "✕" : "🔍"}
|
||||
</button>
|
||||
{user
|
||||
? (
|
||||
<>
|
||||
@@ -68,7 +99,9 @@ export function AppHeader(
|
||||
disabled={disableNew}
|
||||
title={disableNew ? t`Server unreachable` : undefined}
|
||||
>
|
||||
+<span className="btn-new-label"><Trans> Dump</Trans></span>
|
||||
+<span className="btn-new-label">
|
||||
<Trans>Dump</Trans>
|
||||
</span>
|
||||
</button>
|
||||
</>
|
||||
)
|
||||
@@ -82,6 +115,15 @@ export function AppHeader(
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
{searchExpanded && (
|
||||
<div className="header-search-below">
|
||||
<SearchBar
|
||||
expanded={searchExpanded}
|
||||
onExpandedChange={setSearchExpanded}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{wsStatus === "disconnected" && wsErrorMessage && (
|
||||
<div className="app-header-status" role="alert">
|
||||
<strong>
|
||||
|
||||
@@ -106,7 +106,6 @@ export function DumpCard(
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useLocation, useNavigate } from "react-router";
|
||||
import { Trans } from "@lingui/react/macro";
|
||||
import { useAuth } from "../hooks/useAuth.ts";
|
||||
import { type FeedTab, VALID_TABS } from "../config/feedTabs.ts";
|
||||
import { TabBar } from "./TabBar.tsx";
|
||||
|
||||
export function FeedTabBar() {
|
||||
const location = useLocation();
|
||||
@@ -11,44 +12,20 @@ export function FeedTabBar() {
|
||||
const rawTab = new URLSearchParams(location.search).get("tab") ?? "hot";
|
||||
const tab: FeedTab = VALID_TABS.has(rawTab) ? (rawTab as FeedTab) : "hot";
|
||||
|
||||
function setTab(t: FeedTab) {
|
||||
navigate(`/?tab=${t}`, { replace: true });
|
||||
}
|
||||
const tabs = [
|
||||
{ key: "hot" as FeedTab, label: <Trans>Hot</Trans> },
|
||||
{ key: "new" as FeedTab, label: <Trans>New</Trans> },
|
||||
{ key: "journal" as FeedTab, label: <Trans>Journal</Trans> },
|
||||
...(user
|
||||
? [{ key: "followed" as FeedTab, label: <Trans>Followed</Trans> }]
|
||||
: []),
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="feed-sort-scroller">
|
||||
<div className="feed-sort">
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${tab === "hot" ? " active" : ""}`}
|
||||
onClick={() => setTab("hot")}
|
||||
>
|
||||
<Trans>Hot</Trans>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${tab === "new" ? " active" : ""}`}
|
||||
onClick={() => setTab("new")}
|
||||
>
|
||||
<Trans>New</Trans>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${tab === "journal" ? " active" : ""}`}
|
||||
onClick={() => setTab("journal")}
|
||||
>
|
||||
<Trans>Journal</Trans>
|
||||
</button>
|
||||
{user && (
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${tab === "followed" ? " active" : ""}`}
|
||||
onClick={() => setTab("followed")}
|
||||
>
|
||||
<Trans>Followed</Trans>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<TabBar
|
||||
tabs={tabs}
|
||||
activeTab={tab}
|
||||
onChange={(t) => navigate(`/?tab=${t}`, { replace: true })}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useContext } from "react";
|
||||
import { Link, useNavigate } from "react-router";
|
||||
import { Plural, Trans } from "@lingui/react/macro";
|
||||
import type { Dump } from "../model.ts";
|
||||
import { API_URL } from "../config/api.ts";
|
||||
import { relativeTime } from "../utils/relativeTime.ts";
|
||||
@@ -73,12 +74,18 @@ export function JournalCard(
|
||||
</time>
|
||||
</Tooltip>
|
||||
{dump.commentCount > 0 && (
|
||||
<span>
|
||||
{dump.commentCount} {dump.commentCount === 1 ? "comment" : "comments"}
|
||||
<span className="dump-card-comment-count">
|
||||
<Plural
|
||||
value={dump.commentCount}
|
||||
one="# comment"
|
||||
other="# comments"
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
{dump.isPrivate && isOwner && (
|
||||
<span className="dump-card-private-badge">private</span>
|
||||
<span className="dump-card-private-badge">
|
||||
<Trans>private</Trans>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -27,7 +27,13 @@ export function NewPlaylistForm(
|
||||
className={toggleClassName}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
{toggleLabel ?? <>+<span className="btn-new-label"><Trans> New playlist</Trans></span></>}
|
||||
{toggleLabel ?? (
|
||||
<>
|
||||
+<span className="btn-new-label">
|
||||
<Trans>New playlist</Trans>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{open && (
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { type ReactNode } from "react";
|
||||
import { AppHeader } from "./AppHeader.tsx";
|
||||
import { SearchBar } from "./SearchBar.tsx";
|
||||
|
||||
interface PageShellProps {
|
||||
children: ReactNode;
|
||||
@@ -14,7 +13,7 @@ export function PageShell(
|
||||
) {
|
||||
return (
|
||||
<div className="page-shell">
|
||||
<AppHeader centerSlot={centerSlot ?? <SearchBar />} />
|
||||
<AppHeader centerSlot={centerSlot} />
|
||||
<main
|
||||
className={`page-content${centered ? " page-content--centered" : ""}`}
|
||||
>
|
||||
|
||||
@@ -4,22 +4,35 @@ import { t } from "@lingui/core/macro";
|
||||
|
||||
interface SearchBarProps {
|
||||
collapsible?: boolean;
|
||||
expanded?: boolean;
|
||||
onExpandedChange?: (v: boolean) => void;
|
||||
}
|
||||
|
||||
export function SearchBar({ collapsible = false }: SearchBarProps) {
|
||||
const [value, setValue] = useState(
|
||||
() => new URLSearchParams(location.search).get("q") ?? "",
|
||||
);
|
||||
const [expanded, setExpanded] = useState(!collapsible);
|
||||
export function SearchBar(
|
||||
{ collapsible = false, expanded: expandedProp, onExpandedChange }:
|
||||
SearchBarProps,
|
||||
) {
|
||||
const isControlled = expandedProp !== undefined;
|
||||
const [expandedState, setExpandedState] = useState(!collapsible);
|
||||
const expanded = isControlled ? expandedProp! : expandedState;
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [value, setValue] = useState(
|
||||
() => new URLSearchParams(location.search).get("q") ?? "",
|
||||
);
|
||||
|
||||
function setExpanded(v: boolean) {
|
||||
if (!isControlled) setExpandedState(v);
|
||||
onExpandedChange?.(v);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (collapsible && expanded) inputRef.current?.focus();
|
||||
}, [expanded, collapsible]);
|
||||
if ((collapsible || isControlled) && expanded) inputRef.current?.focus();
|
||||
}, [expanded, collapsible, isControlled]);
|
||||
|
||||
function handleIconClick() {
|
||||
if (!collapsible) return;
|
||||
if (!collapsible && !isControlled) return;
|
||||
if (expanded) {
|
||||
setExpanded(false);
|
||||
setValue("");
|
||||
@@ -33,14 +46,14 @@ export function SearchBar({ collapsible = false }: SearchBarProps) {
|
||||
const q = value.trim();
|
||||
if (!q) return;
|
||||
navigate(`/search?q=${encodeURIComponent(q)}&tab=dumps`);
|
||||
if (collapsible) {
|
||||
if (collapsible || isControlled) {
|
||||
setExpanded(false);
|
||||
setValue("");
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyDown(e: React.KeyboardEvent) {
|
||||
if (e.key === "Escape" && collapsible) {
|
||||
if (e.key === "Escape" && (collapsible || isControlled)) {
|
||||
setExpanded(false);
|
||||
setValue("");
|
||||
}
|
||||
@@ -48,9 +61,9 @@ export function SearchBar({ collapsible = false }: SearchBarProps) {
|
||||
|
||||
return (
|
||||
<form
|
||||
className={`search-bar${collapsible ? " search-bar--collapsible" : ""}${
|
||||
expanded ? " search-bar--expanded" : ""
|
||||
}`}
|
||||
className={`search-bar${
|
||||
collapsible || isControlled ? " search-bar--collapsible" : ""
|
||||
}${expanded ? " search-bar--expanded" : ""}`}
|
||||
onSubmit={handleSubmit}
|
||||
role="search"
|
||||
>
|
||||
@@ -66,10 +79,12 @@ export function SearchBar({ collapsible = false }: SearchBarProps) {
|
||||
tabIndex={expanded ? 0 : -1}
|
||||
/>
|
||||
<button
|
||||
type={expanded && !collapsible ? "submit" : "button"}
|
||||
type={expanded ? "submit" : "button"}
|
||||
className="search-bar-btn"
|
||||
aria-label={expanded ? t`Submit search` : t`Open search`}
|
||||
onClick={collapsible ? handleIconClick : undefined}
|
||||
onClick={!expanded && (collapsible || isControlled)
|
||||
? handleIconClick
|
||||
: undefined}
|
||||
>
|
||||
🔍
|
||||
</button>
|
||||
|
||||
35
src/components/TabBar.tsx
Normal file
35
src/components/TabBar.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { type ReactNode } from "react";
|
||||
|
||||
interface Tab<T extends string> {
|
||||
key: T;
|
||||
label: ReactNode;
|
||||
}
|
||||
|
||||
interface TabBarProps<T extends string> {
|
||||
tabs: Tab<T>[];
|
||||
activeTab: T;
|
||||
onChange: (key: T) => void;
|
||||
className?: string;
|
||||
innerClassName?: string;
|
||||
}
|
||||
|
||||
export function TabBar<T extends string>(
|
||||
{ tabs, activeTab, onChange, className, innerClassName }: TabBarProps<T>,
|
||||
) {
|
||||
return (
|
||||
<div className={`feed-sort-scroller${className ? ` ${className}` : ""}`}>
|
||||
<div className={`feed-sort${innerClassName ? ` ${innerClassName}` : ""}`}>
|
||||
{tabs.map(({ key, label }) => (
|
||||
<button
|
||||
key={key}
|
||||
type="button"
|
||||
className={`feed-sort-btn${activeTab === key ? " active" : ""}`}
|
||||
onClick={() => onChange(key)}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -13,25 +13,13 @@ msgstr ""
|
||||
"Language-Team: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#: src/components/AppHeader.tsx:71
|
||||
msgid " Dump"
|
||||
msgstr " Dump"
|
||||
|
||||
#: src/pages/UserDumps.tsx:114
|
||||
#: src/pages/UserPublicProfile.tsx:1332
|
||||
msgid " New dump"
|
||||
msgstr " New dump"
|
||||
|
||||
#: src/components/NewPlaylistForm.tsx:30
|
||||
msgid " New playlist"
|
||||
msgstr " New playlist"
|
||||
|
||||
#: src/components/CommentThread.tsx:176
|
||||
msgid "[deleted]"
|
||||
msgstr "[deleted]"
|
||||
|
||||
#. placeholder {0}: dump.commentCount
|
||||
#: src/components/DumpCard.tsx:95
|
||||
#: src/components/JournalCard.tsx:78
|
||||
msgid "{0, plural, one {# comment} other {# comments}}"
|
||||
msgstr "{0, plural, one {# comment} other {# comments}}"
|
||||
|
||||
@@ -83,14 +71,10 @@ msgstr "← Back to all dumps"
|
||||
msgid "← Back to profile"
|
||||
msgstr "← Back to profile"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:100
|
||||
#: src/pages/UserPublicProfile.tsx:101
|
||||
msgid "+ Invite someone"
|
||||
msgstr "+ Invite someone"
|
||||
|
||||
#: src/components/AppHeader.tsx:71
|
||||
msgid "+ New"
|
||||
msgstr "+ New"
|
||||
|
||||
#: src/pages/UserDumps.tsx:114
|
||||
#: src/pages/UserPublicProfile.tsx:1332
|
||||
msgid "+ New dump"
|
||||
@@ -152,7 +136,7 @@ msgstr "a comment"
|
||||
msgid "a post"
|
||||
msgstr "a post"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1217
|
||||
#: src/pages/UserPublicProfile.tsx:1193
|
||||
msgid "Account"
|
||||
msgstr "Account"
|
||||
|
||||
@@ -160,7 +144,7 @@ msgstr "Account"
|
||||
msgid "Add a comment…"
|
||||
msgstr "Add a comment…"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:859
|
||||
#: src/pages/UserPublicProfile.tsx:860
|
||||
msgid "Add email…"
|
||||
msgstr "Add email…"
|
||||
|
||||
@@ -181,7 +165,7 @@ msgstr "All {0, plural, one {# upvoted dump} other {# upvoted dumps}} loaded."
|
||||
msgid "Already have an account? <0>Log in</0>"
|
||||
msgstr "Already have an account? <0>Log in</0>"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1236
|
||||
#: src/pages/UserPublicProfile.tsx:1212
|
||||
msgid "Appearance"
|
||||
msgstr "Appearance"
|
||||
|
||||
@@ -191,7 +175,7 @@ msgstr "Appearance"
|
||||
msgid "At least {0} characters"
|
||||
msgstr "At least {0} characters"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1270
|
||||
#: src/pages/UserPublicProfile.tsx:1246
|
||||
msgid "Auto"
|
||||
msgstr "Auto"
|
||||
|
||||
@@ -214,8 +198,8 @@ msgstr "Can't connect to the live updates server. Upvotes and notifications may
|
||||
#: src/components/PlaylistCreateForm.tsx:112
|
||||
#: src/pages/DumpEdit.tsx:299
|
||||
#: src/pages/PlaylistDetail.tsx:680
|
||||
#: src/pages/UserPublicProfile.tsx:841
|
||||
#: src/pages/UserPublicProfile.tsx:919
|
||||
#: src/pages/UserPublicProfile.tsx:842
|
||||
#: src/pages/UserPublicProfile.tsx:921
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
@@ -223,6 +207,10 @@ msgstr "Cancel"
|
||||
msgid "Cancel removal"
|
||||
msgstr "Cancel removal"
|
||||
|
||||
#: src/components/AppHeader.tsx:62
|
||||
msgid "Cancel search"
|
||||
msgstr "Cancel search"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:772
|
||||
msgid "Change avatar"
|
||||
msgstr "Change avatar"
|
||||
@@ -232,7 +220,7 @@ msgstr "Change avatar"
|
||||
msgid "Change password"
|
||||
msgstr "Change password"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1229
|
||||
#: src/pages/UserPublicProfile.tsx:1205
|
||||
msgid "Change password…"
|
||||
msgstr "Change password…"
|
||||
|
||||
@@ -245,7 +233,7 @@ msgstr "Checking invite…"
|
||||
msgid "Close"
|
||||
msgstr "Close"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1262
|
||||
#: src/pages/UserPublicProfile.tsx:1238
|
||||
msgid "Color scheme"
|
||||
msgstr "Color scheme"
|
||||
|
||||
@@ -254,11 +242,11 @@ msgstr "Color scheme"
|
||||
msgid "Confirm new password"
|
||||
msgstr "Confirm new password"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:91
|
||||
#: src/pages/UserPublicProfile.tsx:92
|
||||
msgid "Copied!"
|
||||
msgstr "Copied!"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:91
|
||||
#: src/pages/UserPublicProfile.tsx:92
|
||||
msgid "Copy"
|
||||
msgstr "Copy"
|
||||
|
||||
@@ -299,7 +287,7 @@ msgstr "Creating…"
|
||||
msgid "Current password"
|
||||
msgstr "Current password"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1284
|
||||
#: src/pages/UserPublicProfile.tsx:1260
|
||||
msgid "Dark"
|
||||
msgstr "Dark"
|
||||
|
||||
@@ -351,6 +339,10 @@ msgstr "Drop a file here"
|
||||
msgid "Drop a replacement here"
|
||||
msgstr "Drop a replacement here"
|
||||
|
||||
#: src/components/AppHeader.tsx:99
|
||||
msgid "Dump"
|
||||
msgstr "Dump"
|
||||
|
||||
#: src/components/DumpCreateModal.tsx:427
|
||||
msgid "Dump it"
|
||||
msgstr "Dump it"
|
||||
@@ -361,13 +353,13 @@ msgstr "Dumped!"
|
||||
|
||||
#: src/pages/Search.tsx:172
|
||||
#: src/pages/UserDumps.tsx:107
|
||||
#: src/pages/UserPublicProfile.tsx:968
|
||||
#: src/pages/UserPublicProfile.tsx:965
|
||||
msgid "Dumps"
|
||||
msgstr "Dumps"
|
||||
|
||||
#. placeholder {0}: dumps.items.length
|
||||
#. placeholder {1}: dumps.hasMore ? "+" : ""
|
||||
#: src/pages/UserPublicProfile.tsx:1006
|
||||
#: src/pages/UserPublicProfile.tsx:982
|
||||
msgid "Dumps ({0}{1})"
|
||||
msgstr "Dumps ({0}{1})"
|
||||
|
||||
@@ -407,7 +399,7 @@ msgstr "Editing"
|
||||
msgid "Email address"
|
||||
msgstr "Email address"
|
||||
|
||||
#: src/pages/Search.tsx:207
|
||||
#: src/pages/Search.tsx:198
|
||||
msgid "Enter a query to search."
|
||||
msgstr "Enter a query to search."
|
||||
|
||||
@@ -420,20 +412,20 @@ msgstr "Failed to change password"
|
||||
msgid "Failed to create playlist"
|
||||
msgstr "Failed to create playlist"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:72
|
||||
#: src/pages/UserPublicProfile.tsx:75
|
||||
#: src/pages/UserPublicProfile.tsx:103
|
||||
#: src/pages/UserPublicProfile.tsx:73
|
||||
#: src/pages/UserPublicProfile.tsx:76
|
||||
#: src/pages/UserPublicProfile.tsx:104
|
||||
msgid "Failed to generate invite"
|
||||
msgstr "Failed to generate invite"
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:81
|
||||
#: src/pages/index/FollowedFeed.tsx:82
|
||||
#: src/pages/index/HotFeed.tsx:36
|
||||
#: src/pages/index/JournalFeed.tsx:48
|
||||
#: src/pages/index/NewFeed.tsx:36
|
||||
#: src/pages/Notifications.tsx:342
|
||||
#: src/pages/UserPublicProfile.tsx:1108
|
||||
#: src/pages/UserPublicProfile.tsx:1150
|
||||
#: src/pages/UserPublicProfile.tsx:1195
|
||||
#: src/pages/UserPublicProfile.tsx:1084
|
||||
#: src/pages/UserPublicProfile.tsx:1126
|
||||
#: src/pages/UserPublicProfile.tsx:1171
|
||||
msgid "Failed to load"
|
||||
msgstr "Failed to load"
|
||||
|
||||
@@ -452,8 +444,8 @@ msgstr "Failed to post reply"
|
||||
#: src/pages/PlaylistDetail.tsx:789
|
||||
#: src/pages/UserPublicProfile.tsx:680
|
||||
#: src/pages/UserPublicProfile.tsx:718
|
||||
#: src/pages/UserPublicProfile.tsx:845
|
||||
#: src/pages/UserPublicProfile.tsx:922
|
||||
#: src/pages/UserPublicProfile.tsx:846
|
||||
#: src/pages/UserPublicProfile.tsx:924
|
||||
msgid "Failed to save"
|
||||
msgstr "Failed to save"
|
||||
|
||||
@@ -461,7 +453,7 @@ msgstr "Failed to save"
|
||||
msgid "Failed to save edit"
|
||||
msgstr "Failed to save edit"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:868
|
||||
#: src/pages/UserPublicProfile.tsx:869
|
||||
msgid "Failed to update avatar"
|
||||
msgstr "Failed to update avatar"
|
||||
|
||||
@@ -495,16 +487,16 @@ msgstr "Follow {targetUsername}"
|
||||
msgid "Follow playlist"
|
||||
msgstr "Follow playlist"
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:371
|
||||
#: src/pages/index/FollowedFeed.tsx:365
|
||||
msgid "Follow some public playlists to see their dumps here."
|
||||
msgstr "Follow some public playlists to see their dumps here."
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:357
|
||||
#: src/pages/index/FollowedFeed.tsx:351
|
||||
msgid "Follow some users to see their dumps here."
|
||||
msgstr "Follow some users to see their dumps here."
|
||||
|
||||
#: src/components/FeedTabBar.tsx:48
|
||||
#: src/pages/UserPublicProfile.tsx:982
|
||||
#: src/components/FeedTabBar.tsx:19
|
||||
#: src/pages/UserPublicProfile.tsx:967
|
||||
msgid "Followed"
|
||||
msgstr "Followed"
|
||||
|
||||
@@ -514,13 +506,13 @@ msgstr "Followed"
|
||||
msgid "Followed ({0}{1})"
|
||||
msgstr "Followed ({0}{1})"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1139
|
||||
#: src/pages/UserPublicProfile.tsx:1115
|
||||
msgid "Followed playlists"
|
||||
msgstr "Followed playlists"
|
||||
|
||||
#: src/components/FollowButton.tsx:37
|
||||
#: src/components/FollowButton.tsx:64
|
||||
#: src/pages/UserPublicProfile.tsx:1097
|
||||
#: src/pages/UserPublicProfile.tsx:1073
|
||||
msgid "Following"
|
||||
msgstr "Following"
|
||||
|
||||
@@ -528,19 +520,23 @@ msgstr "Following"
|
||||
msgid "Forgot password?"
|
||||
msgstr "Forgot password?"
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:337
|
||||
#: src/pages/index/FollowedFeed.tsx:334
|
||||
msgid "From people"
|
||||
msgstr "From people"
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:344
|
||||
#: src/pages/index/FollowedFeed.tsx:335
|
||||
msgid "From playlists"
|
||||
msgstr "From playlists"
|
||||
|
||||
#: src/pages/NotFound.tsx:13
|
||||
msgid "Go home"
|
||||
msgstr "Go home"
|
||||
|
||||
#: src/pages/ResetPassword.tsx:66
|
||||
msgid "Go to login"
|
||||
msgstr "Go to login"
|
||||
|
||||
#: src/components/FeedTabBar.tsx:26
|
||||
#: src/components/FeedTabBar.tsx:16
|
||||
msgid "Hot"
|
||||
msgstr "Hot"
|
||||
|
||||
@@ -556,16 +552,16 @@ msgstr "Invalid invite"
|
||||
msgid "Invalid link"
|
||||
msgstr "Invalid link"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:790
|
||||
#: src/pages/UserPublicProfile.tsx:791
|
||||
msgid "invited by"
|
||||
msgstr "invited by"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:989
|
||||
#: src/pages/UserPublicProfile.tsx:1184
|
||||
#: src/pages/UserPublicProfile.tsx:968
|
||||
#: src/pages/UserPublicProfile.tsx:1160
|
||||
msgid "Invitees"
|
||||
msgstr "Invitees"
|
||||
|
||||
#: src/components/FeedTabBar.tsx:40
|
||||
#: src/components/FeedTabBar.tsx:18
|
||||
msgid "Journal"
|
||||
msgstr "Journal"
|
||||
|
||||
@@ -573,7 +569,7 @@ msgstr "Journal"
|
||||
msgid "just now"
|
||||
msgstr "just now"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1277
|
||||
#: src/pages/UserPublicProfile.tsx:1253
|
||||
msgid "Light"
|
||||
msgstr "Light"
|
||||
|
||||
@@ -581,7 +577,7 @@ msgstr "Light"
|
||||
msgid "Live updates are temporarily disconnected. Trying to reconnect…"
|
||||
msgstr "Live updates are temporarily disconnected. Trying to reconnect…"
|
||||
|
||||
#: src/components/AppHeader.tsx:88
|
||||
#: src/components/AppHeader.tsx:125
|
||||
msgid "Live updates unavailable."
|
||||
msgstr "Live updates unavailable."
|
||||
|
||||
@@ -594,11 +590,11 @@ msgstr "Load more"
|
||||
msgid "Loading dump…"
|
||||
msgstr "Loading dump…"
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:109
|
||||
#: src/pages/index/FollowedFeed.tsx:110
|
||||
#: src/pages/index/HotFeed.tsx:64
|
||||
#: src/pages/index/JournalFeed.tsx:77
|
||||
#: src/pages/index/NewFeed.tsx:64
|
||||
#: src/pages/Search.tsx:244
|
||||
#: src/pages/Search.tsx:235
|
||||
#: src/pages/UserDumps.tsx:93
|
||||
#: src/pages/UserPlaylists.tsx:417
|
||||
#: src/pages/UserPlaylists.tsx:452
|
||||
@@ -616,7 +612,7 @@ msgstr "Loading profile…"
|
||||
|
||||
#: src/components/PlaylistMembershipPanel.tsx:28
|
||||
#: src/components/TextEditor.tsx:289
|
||||
#: src/pages/index/FollowedFeed.tsx:76
|
||||
#: src/pages/index/FollowedFeed.tsx:77
|
||||
#: src/pages/index/HotFeed.tsx:32
|
||||
#: src/pages/index/JournalFeed.tsx:44
|
||||
#: src/pages/index/NewFeed.tsx:32
|
||||
@@ -624,21 +620,21 @@ msgstr "Loading profile…"
|
||||
#: src/pages/Notifications.tsx:414
|
||||
#: src/pages/UserDumps.tsx:51
|
||||
#: src/pages/UserPlaylists.tsx:342
|
||||
#: src/pages/UserPublicProfile.tsx:1102
|
||||
#: src/pages/UserPublicProfile.tsx:1144
|
||||
#: src/pages/UserPublicProfile.tsx:1189
|
||||
#: src/pages/UserPublicProfile.tsx:1078
|
||||
#: src/pages/UserPublicProfile.tsx:1120
|
||||
#: src/pages/UserPublicProfile.tsx:1165
|
||||
#: src/pages/UserUpvoted.tsx:123
|
||||
msgid "Loading…"
|
||||
msgstr "Loading…"
|
||||
|
||||
#: src/components/AppHeader.tsx:78
|
||||
#: src/components/AppHeader.tsx:106
|
||||
#: src/pages/UserLogin.tsx:87
|
||||
#: src/pages/UserLogin.tsx:117
|
||||
msgid "Log in"
|
||||
msgstr "Log in"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:749
|
||||
#: src/pages/UserPublicProfile.tsx:882
|
||||
#: src/pages/UserPublicProfile.tsx:883
|
||||
msgid "Log out"
|
||||
msgstr "Log out"
|
||||
|
||||
@@ -658,11 +654,13 @@ msgstr "Max 50 MB"
|
||||
msgid "new"
|
||||
msgstr "new"
|
||||
|
||||
#: src/components/FeedTabBar.tsx:33
|
||||
#: src/components/FeedTabBar.tsx:17
|
||||
msgid "New"
|
||||
msgstr "New"
|
||||
|
||||
#: src/components/DumpCreateModal.tsx:277
|
||||
#: src/pages/UserDumps.tsx:114
|
||||
#: src/pages/UserPublicProfile.tsx:1308
|
||||
msgid "New dump"
|
||||
msgstr "New dump"
|
||||
|
||||
@@ -671,6 +669,7 @@ msgstr "New dump"
|
||||
msgid "New password"
|
||||
msgstr "New password"
|
||||
|
||||
#: src/components/NewPlaylistForm.tsx:30
|
||||
#: src/components/NewPlaylistForm.tsx:34
|
||||
msgid "New playlist"
|
||||
msgstr "New playlist"
|
||||
@@ -679,7 +678,7 @@ msgstr "New playlist"
|
||||
msgid "No dumps in this playlist yet."
|
||||
msgstr "No dumps in this playlist yet."
|
||||
|
||||
#: src/pages/Search.tsx:224
|
||||
#: src/pages/Search.tsx:215
|
||||
msgid "No dumps match \"{q}\"."
|
||||
msgstr "No dumps match \"{q}\"."
|
||||
|
||||
@@ -694,36 +693,36 @@ msgid "No emoji found."
|
||||
msgstr "No emoji found."
|
||||
|
||||
#: src/pages/UserPlaylists.tsx:439
|
||||
#: src/pages/UserPublicProfile.tsx:1157
|
||||
#: src/pages/UserPublicProfile.tsx:1133
|
||||
msgid "No followed playlists yet."
|
||||
msgstr "No followed playlists yet."
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1202
|
||||
#: src/pages/UserPublicProfile.tsx:1178
|
||||
msgid "No invitees yet."
|
||||
msgstr "No invitees yet."
|
||||
|
||||
#: src/pages/Search.tsx:283
|
||||
#: src/pages/Search.tsx:274
|
||||
msgid "No playlists match \"{q}\"."
|
||||
msgstr "No playlists match \"{q}\"."
|
||||
|
||||
#: src/components/PlaylistMembershipPanel.tsx:34
|
||||
#: src/pages/UserPlaylists.tsx:397
|
||||
#: src/pages/UserPublicProfile.tsx:1068
|
||||
#: src/pages/UserPublicProfile.tsx:1044
|
||||
msgid "No playlists yet."
|
||||
msgstr "No playlists yet."
|
||||
|
||||
#: src/pages/Search.tsx:257
|
||||
#: src/pages/Search.tsx:248
|
||||
msgid "No users match \"{q}\"."
|
||||
msgstr "No users match \"{q}\"."
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1115
|
||||
#: src/pages/UserPublicProfile.tsx:1091
|
||||
msgid "Not following anyone yet."
|
||||
msgstr "Not following anyone yet."
|
||||
|
||||
#: src/pages/Notifications.tsx:349
|
||||
#: src/pages/UserDumps.tsx:123
|
||||
#: src/pages/UserPublicProfile.tsx:1342
|
||||
#: src/pages/UserPublicProfile.tsx:1465
|
||||
#: src/pages/UserPublicProfile.tsx:1318
|
||||
#: src/pages/UserPublicProfile.tsx:1441
|
||||
#: src/pages/UserUpvoted.tsx:195
|
||||
msgid "Nothing here yet."
|
||||
msgstr "Nothing here yet."
|
||||
@@ -737,7 +736,7 @@ msgstr "Notifications"
|
||||
msgid "Notifications ({unreadNotificationCount} unread)"
|
||||
msgstr "Notifications ({unreadNotificationCount} unread)"
|
||||
|
||||
#: src/components/SearchBar.tsx:71
|
||||
#: src/components/SearchBar.tsx:83
|
||||
msgid "Open search"
|
||||
msgstr "Open search"
|
||||
|
||||
@@ -746,7 +745,7 @@ msgid "or <0>browse files</0>"
|
||||
msgstr "or <0>browse files</0>"
|
||||
|
||||
#: src/pages/UserLogin.tsx:106
|
||||
#: src/pages/UserPublicProfile.tsx:1222
|
||||
#: src/pages/UserPublicProfile.tsx:1198
|
||||
msgid "Password"
|
||||
msgstr "Password"
|
||||
|
||||
@@ -768,17 +767,17 @@ msgstr "Password updated"
|
||||
msgid "Passwords do not match"
|
||||
msgstr "Passwords do not match"
|
||||
|
||||
#: src/components/AppHeader.tsx:54
|
||||
#: src/components/AppHeader.tsx:82
|
||||
#: src/components/UserMenu.tsx:62
|
||||
#: src/pages/Search.tsx:175
|
||||
#: src/pages/UserPlaylists.tsx:368
|
||||
#: src/pages/UserPublicProfile.tsx:975
|
||||
#: src/pages/UserPublicProfile.tsx:966
|
||||
msgid "Playlists"
|
||||
msgstr "Playlists"
|
||||
|
||||
#. placeholder {0}: playlists.items.length
|
||||
#. placeholder {1}: playlists.hasMore ? "+" : ""
|
||||
#: src/pages/UserPublicProfile.tsx:1037
|
||||
#: src/pages/UserPublicProfile.tsx:1013
|
||||
msgid "Playlists ({0}{1})"
|
||||
msgstr "Playlists ({0}{1})"
|
||||
|
||||
@@ -800,6 +799,7 @@ msgid "Posting…"
|
||||
msgstr "Posting…"
|
||||
|
||||
#: src/components/DumpCard.tsx:104
|
||||
#: src/components/JournalCard.tsx:87
|
||||
#: src/components/PlaylistCard.tsx:73
|
||||
#: src/components/PlaylistMembershipPanel.tsx:55
|
||||
#: src/pages/Dump.tsx:287
|
||||
@@ -879,8 +879,8 @@ msgstr "Retry"
|
||||
#: src/components/CommentThread.tsx:270
|
||||
#: src/pages/DumpEdit.tsx:306
|
||||
#: src/pages/PlaylistDetail.tsx:673
|
||||
#: src/pages/UserPublicProfile.tsx:833
|
||||
#: src/pages/UserPublicProfile.tsx:911
|
||||
#: src/pages/UserPublicProfile.tsx:834
|
||||
#: src/pages/UserPublicProfile.tsx:913
|
||||
msgid "Save"
|
||||
msgstr "Save"
|
||||
|
||||
@@ -888,24 +888,25 @@ msgstr "Save"
|
||||
#: src/components/CommentThread.tsx:269
|
||||
#: src/pages/PlaylistDetail.tsx:673
|
||||
#: src/pages/ResetPassword.tsx:152
|
||||
#: src/pages/UserPublicProfile.tsx:832
|
||||
#: src/pages/UserPublicProfile.tsx:911
|
||||
#: src/pages/UserPublicProfile.tsx:833
|
||||
#: src/pages/UserPublicProfile.tsx:913
|
||||
msgid "Saving…"
|
||||
msgstr "Saving…"
|
||||
|
||||
#: src/components/SearchBar.tsx:65
|
||||
#: src/components/AppHeader.tsx:62
|
||||
#: src/components/SearchBar.tsx:77
|
||||
msgid "Search"
|
||||
msgstr "Search"
|
||||
|
||||
#: src/components/SearchBar.tsx:61
|
||||
#: src/components/SearchBar.tsx:73
|
||||
msgid "Search dumps, users, playlists…"
|
||||
msgstr "Search dumps, users, playlists…"
|
||||
|
||||
#: src/pages/Search.tsx:218
|
||||
#: src/pages/Search.tsx:209
|
||||
msgid "Search failed"
|
||||
msgstr "Search failed"
|
||||
|
||||
#: src/pages/Search.tsx:213
|
||||
#: src/pages/Search.tsx:204
|
||||
msgid "Searching…"
|
||||
msgstr "Searching…"
|
||||
|
||||
@@ -917,7 +918,7 @@ msgstr "Send reset link"
|
||||
msgid "Sending…"
|
||||
msgstr "Sending…"
|
||||
|
||||
#: src/components/AppHeader.tsx:69
|
||||
#: src/components/AppHeader.tsx:97
|
||||
msgid "Server unreachable"
|
||||
msgstr "Server unreachable"
|
||||
|
||||
@@ -926,7 +927,7 @@ msgstr "Server unreachable"
|
||||
msgid "Set new password"
|
||||
msgstr "Set new password"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:997
|
||||
#: src/pages/UserPublicProfile.tsx:970
|
||||
msgid "Settings"
|
||||
msgstr "Settings"
|
||||
|
||||
@@ -934,11 +935,11 @@ msgstr "Settings"
|
||||
msgid "Something went wrong"
|
||||
msgstr "Something went wrong"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1241
|
||||
#: src/pages/UserPublicProfile.tsx:1217
|
||||
msgid "Style"
|
||||
msgstr "Style"
|
||||
|
||||
#: src/components/SearchBar.tsx:71
|
||||
#: src/components/SearchBar.tsx:83
|
||||
msgid "Submit search"
|
||||
msgstr "Submit search"
|
||||
|
||||
@@ -950,6 +951,10 @@ msgstr "This invite link is missing, expired, or already used."
|
||||
msgid "This is a mirage."
|
||||
msgstr "This is a mirage."
|
||||
|
||||
#: src/pages/NotFound.tsx:10
|
||||
msgid "This page does not exist."
|
||||
msgstr "This page does not exist."
|
||||
|
||||
#: src/pages/ResetPassword.tsx:37
|
||||
msgid "This reset link is missing or malformed."
|
||||
msgstr "This reset link is missing or malformed."
|
||||
@@ -993,7 +998,7 @@ msgstr "Upvoted"
|
||||
|
||||
#. placeholder {0}: votes.items.length
|
||||
#. placeholder {1}: votes.hasMore ? "+" : ""
|
||||
#: src/pages/UserPublicProfile.tsx:1017
|
||||
#: src/pages/UserPublicProfile.tsx:993
|
||||
msgid "Upvoted ({0}{1})"
|
||||
msgstr "Upvoted ({0}{1})"
|
||||
|
||||
@@ -1019,11 +1024,11 @@ msgstr "Username"
|
||||
msgid "Users"
|
||||
msgstr "Users"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1087
|
||||
#: src/pages/UserPublicProfile.tsx:1130
|
||||
#: src/pages/UserPublicProfile.tsx:1172
|
||||
#: src/pages/UserPublicProfile.tsx:1363
|
||||
#: src/pages/UserPublicProfile.tsx:1495
|
||||
#: src/pages/UserPublicProfile.tsx:1063
|
||||
#: src/pages/UserPublicProfile.tsx:1106
|
||||
#: src/pages/UserPublicProfile.tsx:1148
|
||||
#: src/pages/UserPublicProfile.tsx:1339
|
||||
#: src/pages/UserPublicProfile.tsx:1471
|
||||
msgid "View all →"
|
||||
msgstr "View all →"
|
||||
|
||||
@@ -1036,8 +1041,8 @@ msgstr "View dump →"
|
||||
msgid "What makes it worth it?"
|
||||
msgstr "What makes it worth it?"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:899
|
||||
#: src/pages/UserPublicProfile.tsx:948
|
||||
#: src/pages/UserPublicProfile.tsx:901
|
||||
#: src/pages/UserPublicProfile.tsx:950
|
||||
msgid "Who am I?"
|
||||
msgstr "Who am I?"
|
||||
|
||||
@@ -1058,11 +1063,11 @@ msgstr "Yesterday"
|
||||
msgid "You'll be notified when someone follows your playlists, upvotes your dumps, or posts new content."
|
||||
msgstr "You'll be notified when someone follows your playlists, upvotes your dumps, or posts new content."
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:114
|
||||
#: src/pages/index/FollowedFeed.tsx:115
|
||||
#: src/pages/index/HotFeed.tsx:69
|
||||
#: src/pages/index/JournalFeed.tsx:82
|
||||
#: src/pages/index/NewFeed.tsx:69
|
||||
#: src/pages/Search.tsx:249
|
||||
#: src/pages/Search.tsx:240
|
||||
#: src/pages/UserDumps.tsx:98
|
||||
#: src/pages/UserPlaylists.tsx:422
|
||||
#: src/pages/UserPlaylists.tsx:457
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -13,25 +13,13 @@ msgstr ""
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
|
||||
#: src/components/AppHeader.tsx:71
|
||||
msgid " Dump"
|
||||
msgstr " Reco"
|
||||
|
||||
#: src/pages/UserDumps.tsx:114
|
||||
#: src/pages/UserPublicProfile.tsx:1332
|
||||
msgid " New dump"
|
||||
msgstr " Nouvelle reco"
|
||||
|
||||
#: src/components/NewPlaylistForm.tsx:30
|
||||
msgid " New playlist"
|
||||
msgstr " Nouvelle collection"
|
||||
|
||||
#: src/components/CommentThread.tsx:176
|
||||
msgid "[deleted]"
|
||||
msgstr "[supprimé]"
|
||||
|
||||
#. placeholder {0}: dump.commentCount
|
||||
#: src/components/DumpCard.tsx:95
|
||||
#: src/components/JournalCard.tsx:78
|
||||
msgid "{0, plural, one {# comment} other {# comments}}"
|
||||
msgstr "{0, plural, one {# commentaire} other {# commentaires}}"
|
||||
|
||||
@@ -83,14 +71,10 @@ msgstr "← Retour à toutes les recos"
|
||||
msgid "← Back to profile"
|
||||
msgstr "← Retour au profil"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:100
|
||||
#: src/pages/UserPublicProfile.tsx:101
|
||||
msgid "+ Invite someone"
|
||||
msgstr "+ Inviter quelqu'un"
|
||||
|
||||
#: src/components/AppHeader.tsx:71
|
||||
msgid "+ New"
|
||||
msgstr "+ Nouveau"
|
||||
|
||||
#: src/pages/UserDumps.tsx:114
|
||||
#: src/pages/UserPublicProfile.tsx:1332
|
||||
msgid "+ New dump"
|
||||
@@ -152,7 +136,7 @@ msgstr "un commentaire"
|
||||
msgid "a post"
|
||||
msgstr "une publication"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1217
|
||||
#: src/pages/UserPublicProfile.tsx:1193
|
||||
msgid "Account"
|
||||
msgstr "Compte"
|
||||
|
||||
@@ -160,7 +144,7 @@ msgstr "Compte"
|
||||
msgid "Add a comment…"
|
||||
msgstr "Ajouter un commentaire…"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:859
|
||||
#: src/pages/UserPublicProfile.tsx:860
|
||||
msgid "Add email…"
|
||||
msgstr "Ajouter un e-mail…"
|
||||
|
||||
@@ -181,7 +165,7 @@ msgstr "Toutes les {0, plural, one {# reco votée} other {# recos votées}} char
|
||||
msgid "Already have an account? <0>Log in</0>"
|
||||
msgstr "Vous avez déjà un compte ? <0>Se connecter</0>"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1236
|
||||
#: src/pages/UserPublicProfile.tsx:1212
|
||||
msgid "Appearance"
|
||||
msgstr "Apparence"
|
||||
|
||||
@@ -191,7 +175,7 @@ msgstr "Apparence"
|
||||
msgid "At least {0} characters"
|
||||
msgstr "Au moins {0} caractères"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1270
|
||||
#: src/pages/UserPublicProfile.tsx:1246
|
||||
msgid "Auto"
|
||||
msgstr "Auto"
|
||||
|
||||
@@ -214,8 +198,8 @@ msgstr "Impossible de se connecter au serveur de mises à jour en direct. Les vo
|
||||
#: src/components/PlaylistCreateForm.tsx:112
|
||||
#: src/pages/DumpEdit.tsx:299
|
||||
#: src/pages/PlaylistDetail.tsx:680
|
||||
#: src/pages/UserPublicProfile.tsx:841
|
||||
#: src/pages/UserPublicProfile.tsx:919
|
||||
#: src/pages/UserPublicProfile.tsx:842
|
||||
#: src/pages/UserPublicProfile.tsx:921
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
@@ -223,6 +207,10 @@ msgstr "Annuler"
|
||||
msgid "Cancel removal"
|
||||
msgstr "Annuler la suppression"
|
||||
|
||||
#: src/components/AppHeader.tsx:62
|
||||
msgid "Cancel search"
|
||||
msgstr "Annuler la recherche"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:772
|
||||
msgid "Change avatar"
|
||||
msgstr "Changer l'avatar"
|
||||
@@ -232,7 +220,7 @@ msgstr "Changer l'avatar"
|
||||
msgid "Change password"
|
||||
msgstr "Changer le mot de passe"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1229
|
||||
#: src/pages/UserPublicProfile.tsx:1205
|
||||
msgid "Change password…"
|
||||
msgstr "Changer le mot de passe…"
|
||||
|
||||
@@ -245,7 +233,7 @@ msgstr "Vérification de l'invitation…"
|
||||
msgid "Close"
|
||||
msgstr "Fermer"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1262
|
||||
#: src/pages/UserPublicProfile.tsx:1238
|
||||
msgid "Color scheme"
|
||||
msgstr "Thème de couleur"
|
||||
|
||||
@@ -254,11 +242,11 @@ msgstr "Thème de couleur"
|
||||
msgid "Confirm new password"
|
||||
msgstr "Confirmer le nouveau mot de passe"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:91
|
||||
#: src/pages/UserPublicProfile.tsx:92
|
||||
msgid "Copied!"
|
||||
msgstr "Copié !"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:91
|
||||
#: src/pages/UserPublicProfile.tsx:92
|
||||
msgid "Copy"
|
||||
msgstr "Copier"
|
||||
|
||||
@@ -299,7 +287,7 @@ msgstr "Création…"
|
||||
msgid "Current password"
|
||||
msgstr "Mot de passe actuel"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1284
|
||||
#: src/pages/UserPublicProfile.tsx:1260
|
||||
msgid "Dark"
|
||||
msgstr "Sombre"
|
||||
|
||||
@@ -351,6 +339,10 @@ msgstr "Déposez un fichier ici"
|
||||
msgid "Drop a replacement here"
|
||||
msgstr "Déposez un fichier de remplacement ici"
|
||||
|
||||
#: src/components/AppHeader.tsx:99
|
||||
msgid "Dump"
|
||||
msgstr "Reco"
|
||||
|
||||
#: src/components/DumpCreateModal.tsx:427
|
||||
msgid "Dump it"
|
||||
msgstr "Recommander"
|
||||
@@ -361,13 +353,13 @@ msgstr "Recommandé !"
|
||||
|
||||
#: src/pages/Search.tsx:172
|
||||
#: src/pages/UserDumps.tsx:107
|
||||
#: src/pages/UserPublicProfile.tsx:968
|
||||
#: src/pages/UserPublicProfile.tsx:965
|
||||
msgid "Dumps"
|
||||
msgstr "Recos"
|
||||
|
||||
#. placeholder {0}: dumps.items.length
|
||||
#. placeholder {1}: dumps.hasMore ? "+" : ""
|
||||
#: src/pages/UserPublicProfile.tsx:1006
|
||||
#: src/pages/UserPublicProfile.tsx:982
|
||||
msgid "Dumps ({0}{1})"
|
||||
msgstr "Recos ({0}{1})"
|
||||
|
||||
@@ -407,7 +399,7 @@ msgstr "Modification"
|
||||
msgid "Email address"
|
||||
msgstr "Adresse e-mail"
|
||||
|
||||
#: src/pages/Search.tsx:207
|
||||
#: src/pages/Search.tsx:198
|
||||
msgid "Enter a query to search."
|
||||
msgstr "Saisissez une recherche."
|
||||
|
||||
@@ -420,20 +412,20 @@ msgstr "Impossible de changer le mot de passe"
|
||||
msgid "Failed to create playlist"
|
||||
msgstr "Impossible de créer la collection"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:72
|
||||
#: src/pages/UserPublicProfile.tsx:75
|
||||
#: src/pages/UserPublicProfile.tsx:103
|
||||
#: src/pages/UserPublicProfile.tsx:73
|
||||
#: src/pages/UserPublicProfile.tsx:76
|
||||
#: src/pages/UserPublicProfile.tsx:104
|
||||
msgid "Failed to generate invite"
|
||||
msgstr "Impossible de générer une invitation"
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:81
|
||||
#: src/pages/index/FollowedFeed.tsx:82
|
||||
#: src/pages/index/HotFeed.tsx:36
|
||||
#: src/pages/index/JournalFeed.tsx:48
|
||||
#: src/pages/index/NewFeed.tsx:36
|
||||
#: src/pages/Notifications.tsx:342
|
||||
#: src/pages/UserPublicProfile.tsx:1108
|
||||
#: src/pages/UserPublicProfile.tsx:1150
|
||||
#: src/pages/UserPublicProfile.tsx:1195
|
||||
#: src/pages/UserPublicProfile.tsx:1084
|
||||
#: src/pages/UserPublicProfile.tsx:1126
|
||||
#: src/pages/UserPublicProfile.tsx:1171
|
||||
msgid "Failed to load"
|
||||
msgstr "Chargement échoué"
|
||||
|
||||
@@ -452,8 +444,8 @@ msgstr "Impossible de publier la réponse"
|
||||
#: src/pages/PlaylistDetail.tsx:789
|
||||
#: src/pages/UserPublicProfile.tsx:680
|
||||
#: src/pages/UserPublicProfile.tsx:718
|
||||
#: src/pages/UserPublicProfile.tsx:845
|
||||
#: src/pages/UserPublicProfile.tsx:922
|
||||
#: src/pages/UserPublicProfile.tsx:846
|
||||
#: src/pages/UserPublicProfile.tsx:924
|
||||
msgid "Failed to save"
|
||||
msgstr "Enregistrement échoué"
|
||||
|
||||
@@ -461,7 +453,7 @@ msgstr "Enregistrement échoué"
|
||||
msgid "Failed to save edit"
|
||||
msgstr "Impossible d'enregistrer la modification"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:868
|
||||
#: src/pages/UserPublicProfile.tsx:869
|
||||
msgid "Failed to update avatar"
|
||||
msgstr "Impossible de mettre à jour l'avatar"
|
||||
|
||||
@@ -495,16 +487,16 @@ msgstr "Suivre {targetUsername}"
|
||||
msgid "Follow playlist"
|
||||
msgstr "Suivre la collection"
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:371
|
||||
#: src/pages/index/FollowedFeed.tsx:365
|
||||
msgid "Follow some public playlists to see their dumps here."
|
||||
msgstr "Suivez des collections publiques pour voir leurs recos ici."
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:357
|
||||
#: src/pages/index/FollowedFeed.tsx:351
|
||||
msgid "Follow some users to see their dumps here."
|
||||
msgstr "Suivez des utilisateurs pour voir leurs recos ici."
|
||||
|
||||
#: src/components/FeedTabBar.tsx:48
|
||||
#: src/pages/UserPublicProfile.tsx:982
|
||||
#: src/components/FeedTabBar.tsx:19
|
||||
#: src/pages/UserPublicProfile.tsx:967
|
||||
msgid "Followed"
|
||||
msgstr "Suivi"
|
||||
|
||||
@@ -514,13 +506,13 @@ msgstr "Suivi"
|
||||
msgid "Followed ({0}{1})"
|
||||
msgstr "Suivies ({0}{1})"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1139
|
||||
#: src/pages/UserPublicProfile.tsx:1115
|
||||
msgid "Followed playlists"
|
||||
msgstr "Collections suivies"
|
||||
|
||||
#: src/components/FollowButton.tsx:37
|
||||
#: src/components/FollowButton.tsx:64
|
||||
#: src/pages/UserPublicProfile.tsx:1097
|
||||
#: src/pages/UserPublicProfile.tsx:1073
|
||||
msgid "Following"
|
||||
msgstr "Abonné"
|
||||
|
||||
@@ -528,19 +520,23 @@ msgstr "Abonné"
|
||||
msgid "Forgot password?"
|
||||
msgstr "Mot de passe oublié ?"
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:337
|
||||
#: src/pages/index/FollowedFeed.tsx:334
|
||||
msgid "From people"
|
||||
msgstr "De personnes"
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:344
|
||||
#: src/pages/index/FollowedFeed.tsx:335
|
||||
msgid "From playlists"
|
||||
msgstr "De collections"
|
||||
|
||||
#: src/pages/NotFound.tsx:13
|
||||
msgid "Go home"
|
||||
msgstr "Accueil"
|
||||
|
||||
#: src/pages/ResetPassword.tsx:66
|
||||
msgid "Go to login"
|
||||
msgstr "Aller à la connexion"
|
||||
|
||||
#: src/components/FeedTabBar.tsx:26
|
||||
#: src/components/FeedTabBar.tsx:16
|
||||
msgid "Hot"
|
||||
msgstr "Tendances"
|
||||
|
||||
@@ -556,16 +552,16 @@ msgstr "Invitation invalide"
|
||||
msgid "Invalid link"
|
||||
msgstr "Lien invalide"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:790
|
||||
#: src/pages/UserPublicProfile.tsx:791
|
||||
msgid "invited by"
|
||||
msgstr "invité par"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:989
|
||||
#: src/pages/UserPublicProfile.tsx:1184
|
||||
#: src/pages/UserPublicProfile.tsx:968
|
||||
#: src/pages/UserPublicProfile.tsx:1160
|
||||
msgid "Invitees"
|
||||
msgstr "Invités"
|
||||
|
||||
#: src/components/FeedTabBar.tsx:40
|
||||
#: src/components/FeedTabBar.tsx:18
|
||||
msgid "Journal"
|
||||
msgstr "Journal"
|
||||
|
||||
@@ -573,7 +569,7 @@ msgstr "Journal"
|
||||
msgid "just now"
|
||||
msgstr "à l'instant"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1277
|
||||
#: src/pages/UserPublicProfile.tsx:1253
|
||||
msgid "Light"
|
||||
msgstr "Clair"
|
||||
|
||||
@@ -581,7 +577,7 @@ msgstr "Clair"
|
||||
msgid "Live updates are temporarily disconnected. Trying to reconnect…"
|
||||
msgstr "Les mises à jour en direct sont temporairement interrompues. Tentative de reconnexion…"
|
||||
|
||||
#: src/components/AppHeader.tsx:88
|
||||
#: src/components/AppHeader.tsx:125
|
||||
msgid "Live updates unavailable."
|
||||
msgstr "Mises à jour en direct indisponibles."
|
||||
|
||||
@@ -594,11 +590,11 @@ msgstr "Charger plus"
|
||||
msgid "Loading dump…"
|
||||
msgstr "Chargement de la reco…"
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:109
|
||||
#: src/pages/index/FollowedFeed.tsx:110
|
||||
#: src/pages/index/HotFeed.tsx:64
|
||||
#: src/pages/index/JournalFeed.tsx:77
|
||||
#: src/pages/index/NewFeed.tsx:64
|
||||
#: src/pages/Search.tsx:244
|
||||
#: src/pages/Search.tsx:235
|
||||
#: src/pages/UserDumps.tsx:93
|
||||
#: src/pages/UserPlaylists.tsx:417
|
||||
#: src/pages/UserPlaylists.tsx:452
|
||||
@@ -616,7 +612,7 @@ msgstr "Chargement du profil…"
|
||||
|
||||
#: src/components/PlaylistMembershipPanel.tsx:28
|
||||
#: src/components/TextEditor.tsx:289
|
||||
#: src/pages/index/FollowedFeed.tsx:76
|
||||
#: src/pages/index/FollowedFeed.tsx:77
|
||||
#: src/pages/index/HotFeed.tsx:32
|
||||
#: src/pages/index/JournalFeed.tsx:44
|
||||
#: src/pages/index/NewFeed.tsx:32
|
||||
@@ -624,21 +620,21 @@ msgstr "Chargement du profil…"
|
||||
#: src/pages/Notifications.tsx:414
|
||||
#: src/pages/UserDumps.tsx:51
|
||||
#: src/pages/UserPlaylists.tsx:342
|
||||
#: src/pages/UserPublicProfile.tsx:1102
|
||||
#: src/pages/UserPublicProfile.tsx:1144
|
||||
#: src/pages/UserPublicProfile.tsx:1189
|
||||
#: src/pages/UserPublicProfile.tsx:1078
|
||||
#: src/pages/UserPublicProfile.tsx:1120
|
||||
#: src/pages/UserPublicProfile.tsx:1165
|
||||
#: src/pages/UserUpvoted.tsx:123
|
||||
msgid "Loading…"
|
||||
msgstr "Chargement…"
|
||||
|
||||
#: src/components/AppHeader.tsx:78
|
||||
#: src/components/AppHeader.tsx:106
|
||||
#: src/pages/UserLogin.tsx:87
|
||||
#: src/pages/UserLogin.tsx:117
|
||||
msgid "Log in"
|
||||
msgstr "Se connecter"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:749
|
||||
#: src/pages/UserPublicProfile.tsx:882
|
||||
#: src/pages/UserPublicProfile.tsx:883
|
||||
msgid "Log out"
|
||||
msgstr "Se déconnecter"
|
||||
|
||||
@@ -658,11 +654,13 @@ msgstr "Max 50 Mo"
|
||||
msgid "new"
|
||||
msgstr "nouveau"
|
||||
|
||||
#: src/components/FeedTabBar.tsx:33
|
||||
#: src/components/FeedTabBar.tsx:17
|
||||
msgid "New"
|
||||
msgstr "Nouveau"
|
||||
|
||||
#: src/components/DumpCreateModal.tsx:277
|
||||
#: src/pages/UserDumps.tsx:114
|
||||
#: src/pages/UserPublicProfile.tsx:1308
|
||||
msgid "New dump"
|
||||
msgstr "Nouvelle reco"
|
||||
|
||||
@@ -671,6 +669,7 @@ msgstr "Nouvelle reco"
|
||||
msgid "New password"
|
||||
msgstr "Nouveau mot de passe"
|
||||
|
||||
#: src/components/NewPlaylistForm.tsx:30
|
||||
#: src/components/NewPlaylistForm.tsx:34
|
||||
msgid "New playlist"
|
||||
msgstr "Nouvelle collection"
|
||||
@@ -679,7 +678,7 @@ msgstr "Nouvelle collection"
|
||||
msgid "No dumps in this playlist yet."
|
||||
msgstr "Aucune reco dans cette collection pour l'instant."
|
||||
|
||||
#: src/pages/Search.tsx:224
|
||||
#: src/pages/Search.tsx:215
|
||||
msgid "No dumps match \"{q}\"."
|
||||
msgstr "Aucune reco ne correspond à « {q} »."
|
||||
|
||||
@@ -694,36 +693,36 @@ msgid "No emoji found."
|
||||
msgstr "Aucun emoji trouvé."
|
||||
|
||||
#: src/pages/UserPlaylists.tsx:439
|
||||
#: src/pages/UserPublicProfile.tsx:1157
|
||||
#: src/pages/UserPublicProfile.tsx:1133
|
||||
msgid "No followed playlists yet."
|
||||
msgstr "Pas encore de collections suivies."
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1202
|
||||
#: src/pages/UserPublicProfile.tsx:1178
|
||||
msgid "No invitees yet."
|
||||
msgstr "Aucun invité pour le moment."
|
||||
|
||||
#: src/pages/Search.tsx:283
|
||||
#: src/pages/Search.tsx:274
|
||||
msgid "No playlists match \"{q}\"."
|
||||
msgstr "Aucune collection ne correspond à « {q} »."
|
||||
|
||||
#: src/components/PlaylistMembershipPanel.tsx:34
|
||||
#: src/pages/UserPlaylists.tsx:397
|
||||
#: src/pages/UserPublicProfile.tsx:1068
|
||||
#: src/pages/UserPublicProfile.tsx:1044
|
||||
msgid "No playlists yet."
|
||||
msgstr "Pas encore de collections."
|
||||
|
||||
#: src/pages/Search.tsx:257
|
||||
#: src/pages/Search.tsx:248
|
||||
msgid "No users match \"{q}\"."
|
||||
msgstr "Aucun utilisateur ne correspond à « {q} »."
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1115
|
||||
#: src/pages/UserPublicProfile.tsx:1091
|
||||
msgid "Not following anyone yet."
|
||||
msgstr "Aucun abonnement pour le moment."
|
||||
|
||||
#: src/pages/Notifications.tsx:349
|
||||
#: src/pages/UserDumps.tsx:123
|
||||
#: src/pages/UserPublicProfile.tsx:1342
|
||||
#: src/pages/UserPublicProfile.tsx:1465
|
||||
#: src/pages/UserPublicProfile.tsx:1318
|
||||
#: src/pages/UserPublicProfile.tsx:1441
|
||||
#: src/pages/UserUpvoted.tsx:195
|
||||
msgid "Nothing here yet."
|
||||
msgstr "Rien ici pour l'instant."
|
||||
@@ -737,7 +736,7 @@ msgstr "Notifications"
|
||||
msgid "Notifications ({unreadNotificationCount} unread)"
|
||||
msgstr "Notifications ({unreadNotificationCount} non lues)"
|
||||
|
||||
#: src/components/SearchBar.tsx:71
|
||||
#: src/components/SearchBar.tsx:83
|
||||
msgid "Open search"
|
||||
msgstr "Ouvrir la recherche"
|
||||
|
||||
@@ -746,7 +745,7 @@ msgid "or <0>browse files</0>"
|
||||
msgstr "ou <0>parcourir les fichiers</0>"
|
||||
|
||||
#: src/pages/UserLogin.tsx:106
|
||||
#: src/pages/UserPublicProfile.tsx:1222
|
||||
#: src/pages/UserPublicProfile.tsx:1198
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
@@ -768,17 +767,17 @@ msgstr "Mot de passe mis à jour"
|
||||
msgid "Passwords do not match"
|
||||
msgstr "Les mots de passe ne correspondent pas"
|
||||
|
||||
#: src/components/AppHeader.tsx:54
|
||||
#: src/components/AppHeader.tsx:82
|
||||
#: src/components/UserMenu.tsx:62
|
||||
#: src/pages/Search.tsx:175
|
||||
#: src/pages/UserPlaylists.tsx:368
|
||||
#: src/pages/UserPublicProfile.tsx:975
|
||||
#: src/pages/UserPublicProfile.tsx:966
|
||||
msgid "Playlists"
|
||||
msgstr "Collections"
|
||||
|
||||
#. placeholder {0}: playlists.items.length
|
||||
#. placeholder {1}: playlists.hasMore ? "+" : ""
|
||||
#: src/pages/UserPublicProfile.tsx:1037
|
||||
#: src/pages/UserPublicProfile.tsx:1013
|
||||
msgid "Playlists ({0}{1})"
|
||||
msgstr "Collections ({0}{1})"
|
||||
|
||||
@@ -800,6 +799,7 @@ msgid "Posting…"
|
||||
msgstr "Publication…"
|
||||
|
||||
#: src/components/DumpCard.tsx:104
|
||||
#: src/components/JournalCard.tsx:87
|
||||
#: src/components/PlaylistCard.tsx:73
|
||||
#: src/components/PlaylistMembershipPanel.tsx:55
|
||||
#: src/pages/Dump.tsx:287
|
||||
@@ -879,8 +879,8 @@ msgstr "Réessayer"
|
||||
#: src/components/CommentThread.tsx:270
|
||||
#: src/pages/DumpEdit.tsx:306
|
||||
#: src/pages/PlaylistDetail.tsx:673
|
||||
#: src/pages/UserPublicProfile.tsx:833
|
||||
#: src/pages/UserPublicProfile.tsx:911
|
||||
#: src/pages/UserPublicProfile.tsx:834
|
||||
#: src/pages/UserPublicProfile.tsx:913
|
||||
msgid "Save"
|
||||
msgstr "Enregistrer"
|
||||
|
||||
@@ -888,24 +888,25 @@ msgstr "Enregistrer"
|
||||
#: src/components/CommentThread.tsx:269
|
||||
#: src/pages/PlaylistDetail.tsx:673
|
||||
#: src/pages/ResetPassword.tsx:152
|
||||
#: src/pages/UserPublicProfile.tsx:832
|
||||
#: src/pages/UserPublicProfile.tsx:911
|
||||
#: src/pages/UserPublicProfile.tsx:833
|
||||
#: src/pages/UserPublicProfile.tsx:913
|
||||
msgid "Saving…"
|
||||
msgstr "Enregistrement…"
|
||||
|
||||
#: src/components/SearchBar.tsx:65
|
||||
#: src/components/AppHeader.tsx:62
|
||||
#: src/components/SearchBar.tsx:77
|
||||
msgid "Search"
|
||||
msgstr "Rechercher"
|
||||
|
||||
#: src/components/SearchBar.tsx:61
|
||||
#: src/components/SearchBar.tsx:73
|
||||
msgid "Search dumps, users, playlists…"
|
||||
msgstr "Rechercher des recos, utilisateurs, collections…"
|
||||
|
||||
#: src/pages/Search.tsx:218
|
||||
#: src/pages/Search.tsx:209
|
||||
msgid "Search failed"
|
||||
msgstr "Recherche échouée"
|
||||
|
||||
#: src/pages/Search.tsx:213
|
||||
#: src/pages/Search.tsx:204
|
||||
msgid "Searching…"
|
||||
msgstr "Recherche…"
|
||||
|
||||
@@ -917,7 +918,7 @@ msgstr "Envoyer le lien de réinitialisation"
|
||||
msgid "Sending…"
|
||||
msgstr "Envoi…"
|
||||
|
||||
#: src/components/AppHeader.tsx:69
|
||||
#: src/components/AppHeader.tsx:97
|
||||
msgid "Server unreachable"
|
||||
msgstr "Serveur inaccessible"
|
||||
|
||||
@@ -926,7 +927,7 @@ msgstr "Serveur inaccessible"
|
||||
msgid "Set new password"
|
||||
msgstr "Définir un nouveau mot de passe"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:997
|
||||
#: src/pages/UserPublicProfile.tsx:970
|
||||
msgid "Settings"
|
||||
msgstr "Paramètres"
|
||||
|
||||
@@ -934,11 +935,11 @@ msgstr "Paramètres"
|
||||
msgid "Something went wrong"
|
||||
msgstr "Une erreur est survenue"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1241
|
||||
#: src/pages/UserPublicProfile.tsx:1217
|
||||
msgid "Style"
|
||||
msgstr "Style"
|
||||
|
||||
#: src/components/SearchBar.tsx:71
|
||||
#: src/components/SearchBar.tsx:83
|
||||
msgid "Submit search"
|
||||
msgstr "Lancer la recherche"
|
||||
|
||||
@@ -950,6 +951,10 @@ msgstr "Ce lien d'invitation est manquant, expiré ou déjà utilisé."
|
||||
msgid "This is a mirage."
|
||||
msgstr "C'est un mirage."
|
||||
|
||||
#: src/pages/NotFound.tsx:10
|
||||
msgid "This page does not exist."
|
||||
msgstr "Rien à voir, circulez."
|
||||
|
||||
#: src/pages/ResetPassword.tsx:37
|
||||
msgid "This reset link is missing or malformed."
|
||||
msgstr "Ce lien de réinitialisation est absent ou malformé."
|
||||
@@ -993,7 +998,7 @@ msgstr "Voté"
|
||||
|
||||
#. placeholder {0}: votes.items.length
|
||||
#. placeholder {1}: votes.hasMore ? "+" : ""
|
||||
#: src/pages/UserPublicProfile.tsx:1017
|
||||
#: src/pages/UserPublicProfile.tsx:993
|
||||
msgid "Upvoted ({0}{1})"
|
||||
msgstr "Votés ({0}{1})"
|
||||
|
||||
@@ -1019,11 +1024,11 @@ msgstr "Nom d'utilisateur"
|
||||
msgid "Users"
|
||||
msgstr "Utilisateurs"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:1087
|
||||
#: src/pages/UserPublicProfile.tsx:1130
|
||||
#: src/pages/UserPublicProfile.tsx:1172
|
||||
#: src/pages/UserPublicProfile.tsx:1363
|
||||
#: src/pages/UserPublicProfile.tsx:1495
|
||||
#: src/pages/UserPublicProfile.tsx:1063
|
||||
#: src/pages/UserPublicProfile.tsx:1106
|
||||
#: src/pages/UserPublicProfile.tsx:1148
|
||||
#: src/pages/UserPublicProfile.tsx:1339
|
||||
#: src/pages/UserPublicProfile.tsx:1471
|
||||
msgid "View all →"
|
||||
msgstr "Tout voir →"
|
||||
|
||||
@@ -1036,8 +1041,8 @@ msgstr "Voir la reco →"
|
||||
msgid "What makes it worth it?"
|
||||
msgstr "Pourquoi on en voudrait ?"
|
||||
|
||||
#: src/pages/UserPublicProfile.tsx:899
|
||||
#: src/pages/UserPublicProfile.tsx:948
|
||||
#: src/pages/UserPublicProfile.tsx:901
|
||||
#: src/pages/UserPublicProfile.tsx:950
|
||||
msgid "Who am I?"
|
||||
msgstr "Qui suis-je ?"
|
||||
|
||||
@@ -1058,11 +1063,11 @@ msgstr "Hier"
|
||||
msgid "You'll be notified when someone follows your playlists, upvotes your dumps, or posts new content."
|
||||
msgstr "Vous serez notifié lorsque quelqu'un suit vos collections, vote pour vos recos ou publie du nouveau contenu."
|
||||
|
||||
#: src/pages/index/FollowedFeed.tsx:114
|
||||
#: src/pages/index/FollowedFeed.tsx:115
|
||||
#: src/pages/index/HotFeed.tsx:69
|
||||
#: src/pages/index/JournalFeed.tsx:82
|
||||
#: src/pages/index/NewFeed.tsx:69
|
||||
#: src/pages/Search.tsx:249
|
||||
#: src/pages/Search.tsx:240
|
||||
#: src/pages/UserDumps.tsx:98
|
||||
#: src/pages/UserPlaylists.tsx:422
|
||||
#: src/pages/UserPlaylists.tsx:457
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
import { useLocation } from "react-router";
|
||||
|
||||
import { AppHeader } from "../components/AppHeader.tsx";
|
||||
import { SearchBar } from "../components/SearchBar.tsx";
|
||||
import { PresenceRow } from "../components/PresenceRow.tsx";
|
||||
import { FeedTabBar } from "../components/FeedTabBar.tsx";
|
||||
import { type FeedTab, VALID_TABS } from "../config/feedTabs.ts";
|
||||
@@ -249,7 +248,6 @@ export function Index() {
|
||||
<div className="header-center-slot">
|
||||
<PresenceRow />
|
||||
<FeedTabBar />
|
||||
<SearchBar collapsible />
|
||||
</div>
|
||||
}
|
||||
disableNew={dumpsState.status === "error"}
|
||||
|
||||
17
src/pages/NotFound.tsx
Normal file
17
src/pages/NotFound.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Link } from "react-router";
|
||||
import { Trans } from "@lingui/react/macro";
|
||||
import { PageShell } from "../components/PageShell.tsx";
|
||||
|
||||
export function NotFound() {
|
||||
return (
|
||||
<PageShell centered>
|
||||
<h1>404</h1>
|
||||
<p>
|
||||
<Trans>This page does not exist.</Trans>
|
||||
</p>
|
||||
<Link to="/" className="btn-primary">
|
||||
<Trans>Go home</Trans>
|
||||
</Link>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { Link, useSearchParams } from "react-router";
|
||||
import { t } from "@lingui/core/macro";
|
||||
import { Trans } from "@lingui/react/macro";
|
||||
import { AppHeader } from "../components/AppHeader.tsx";
|
||||
import { SearchBar } from "../components/SearchBar.tsx";
|
||||
import { TabBar } from "../components/TabBar.tsx";
|
||||
import { DumpCard } from "../components/DumpCard.tsx";
|
||||
import { PlaylistCard } from "../components/PlaylistCard.tsx";
|
||||
import { ErrorCard } from "../components/ErrorCard.tsx";
|
||||
@@ -178,28 +178,26 @@ export function Search() {
|
||||
|
||||
return (
|
||||
<div className="page-shell">
|
||||
<AppHeader centerSlot={<SearchBar />} />
|
||||
<AppHeader />
|
||||
<main className="search-page">
|
||||
{q && (
|
||||
<div className="search-tabs">
|
||||
{(["dumps", "users", "playlists"] as Tab[]).map((tabKey) => (
|
||||
<button
|
||||
key={tabKey}
|
||||
type="button"
|
||||
className={`feed-sort-btn${tab === tabKey ? " active" : ""}`}
|
||||
onClick={() => setTab(tabKey)}
|
||||
>
|
||||
{tabLabel(
|
||||
tabKey,
|
||||
tabKey === "dumps"
|
||||
<TabBar
|
||||
tabs={(["dumps", "users", "playlists"] as Tab[]).map((key) => ({
|
||||
key,
|
||||
label: tabLabel(
|
||||
key,
|
||||
key === "dumps"
|
||||
? dumpCount
|
||||
: tabKey === "users"
|
||||
: key === "users"
|
||||
? userCount
|
||||
: playlistCount,
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
}))}
|
||||
activeTab={tab}
|
||||
onChange={setTab}
|
||||
className="search-tabs"
|
||||
innerClassName="search-tabs-inner"
|
||||
/>
|
||||
)}
|
||||
|
||||
{state.status === "idle" && (
|
||||
|
||||
@@ -111,7 +111,9 @@ export function UserDumps() {
|
||||
className="new-playlist-toggle"
|
||||
onClick={() => setCreateModalOpen(true)}
|
||||
>
|
||||
+<span className="btn-new-label"><Trans> New dump</Trans></span>
|
||||
+<span className="btn-new-label">
|
||||
<Trans>New dump</Trans>
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -53,6 +53,7 @@ import { friendlyFetchError } from "../utils/apiError.ts";
|
||||
import { TextEditor } from "../components/TextEditor.tsx";
|
||||
import { Markdown } from "../components/Markdown.tsx";
|
||||
import { ChangePasswordModal } from "../components/ChangePasswordModal.tsx";
|
||||
import { TabBar } from "../components/TabBar.tsx";
|
||||
|
||||
function InviteButton() {
|
||||
const { authFetch } = useAuth();
|
||||
@@ -145,6 +146,7 @@ type InviteTreeState =
|
||||
| { status: "loaded"; entries: InviteTreeEntry[] };
|
||||
|
||||
type InviteTreeNode = InviteTreeEntry & { children: InviteTreeNode[] };
|
||||
type ProfileTab = "dumps" | "playlists" | "followed" | "invitees" | "settings";
|
||||
|
||||
function buildInviteTree(
|
||||
entries: InviteTreeEntry[],
|
||||
@@ -282,9 +284,7 @@ export function UserPublicProfile() {
|
||||
const [emailError, setEmailError] = useState<string | null>(null);
|
||||
const prevMyVotesRef = useRef<Set<string> | null>(null);
|
||||
|
||||
const [tab, setTab] = useState<
|
||||
"dumps" | "playlists" | "followed" | "invitees" | "settings"
|
||||
>("dumps");
|
||||
const [tab, setTab] = useState<ProfileTab>("dumps");
|
||||
const [changePasswordOpen, setChangePasswordOpen] = useState(false);
|
||||
const [followedState, setFollowedState] = useState<FollowedState>(null);
|
||||
const [inviteTreeState, setInviteTreeState] = useState<InviteTreeState>(null);
|
||||
@@ -782,7 +782,8 @@ export function UserPublicProfile() {
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<div className="profile-info">
|
||||
<div className="profile-info-scroll">
|
||||
<h1 className="profile-username">{profileUser.username}</h1>
|
||||
{profileUser.invitedByUsername
|
||||
? (
|
||||
@@ -842,7 +843,10 @@ export function UserPublicProfile() {
|
||||
</button>
|
||||
</div>
|
||||
{emailError && (
|
||||
<ErrorCard title={t`Failed to save`} message={emailError} />
|
||||
<ErrorCard
|
||||
title={t`Failed to save`}
|
||||
message={emailError}
|
||||
/>
|
||||
)}
|
||||
</form>
|
||||
)
|
||||
@@ -885,6 +889,7 @@ export function UserPublicProfile() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{(profileUser.description || isOwnProfile) && (
|
||||
<div className="profile-description">
|
||||
@@ -958,47 +963,21 @@ export function UserPublicProfile() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="feed-sort-scroller profile-tabs-scroller">
|
||||
<div className="profile-tabs feed-sort">
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${tab === "dumps" ? " active" : ""}`}
|
||||
onClick={() => setTab("dumps")}
|
||||
>
|
||||
<Trans>Dumps</Trans>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${tab === "playlists" ? " active" : ""}`}
|
||||
onClick={() => setTab("playlists")}
|
||||
>
|
||||
<Trans>Playlists</Trans>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${tab === "followed" ? " active" : ""}`}
|
||||
onClick={() => setTab("followed")}
|
||||
>
|
||||
<Trans>Followed</Trans>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${tab === "invitees" ? " active" : ""}`}
|
||||
onClick={() => setTab("invitees")}
|
||||
>
|
||||
<Trans>Invitees</Trans>
|
||||
</button>
|
||||
{isOwnProfile && (
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${tab === "settings" ? " active" : ""}`}
|
||||
onClick={() => setTab("settings")}
|
||||
>
|
||||
<Trans>Settings</Trans>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<TabBar
|
||||
tabs={[
|
||||
{ key: "dumps", label: <Trans>Dumps</Trans> },
|
||||
{ key: "playlists", label: <Trans>Playlists</Trans> },
|
||||
{ key: "followed", label: <Trans>Followed</Trans> },
|
||||
{ key: "invitees", label: <Trans>Invitees</Trans> },
|
||||
...(isOwnProfile
|
||||
? [{ key: "settings" as const, label: <Trans>Settings</Trans> }]
|
||||
: []),
|
||||
]}
|
||||
activeTab={tab}
|
||||
onChange={(key) => setTab(key)}
|
||||
className="profile-tabs-scroller"
|
||||
innerClassName="profile-tabs"
|
||||
/>
|
||||
|
||||
{tab === "dumps" && (
|
||||
<div className="profile-columns">
|
||||
@@ -1329,7 +1308,9 @@ function DumpList(
|
||||
className="new-playlist-toggle"
|
||||
onClick={() => setCreateModalOpen(true)}
|
||||
>
|
||||
+<span className="btn-new-label"><Trans> New dump</Trans></span>
|
||||
+<span className="btn-new-label">
|
||||
<Trans>New dump</Trans>
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { TabBar } from "../../components/TabBar.tsx";
|
||||
import { t } from "@lingui/core/macro";
|
||||
import { Trans } from "@lingui/react/macro";
|
||||
import { DumpCard } from "../../components/DumpCard.tsx";
|
||||
@@ -328,22 +329,15 @@ export function FollowedFeed({
|
||||
|
||||
return (
|
||||
<div className="followed-feed">
|
||||
<div className="feed-sort followed-sub-nav">
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${section === "users" ? " active" : ""}`}
|
||||
onClick={() => setSection("users")}
|
||||
>
|
||||
<Trans>From people</Trans>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`feed-sort-btn${section === "playlists" ? " active" : ""}`}
|
||||
onClick={() => setSection("playlists")}
|
||||
>
|
||||
<Trans>From playlists</Trans>
|
||||
</button>
|
||||
</div>
|
||||
<TabBar
|
||||
tabs={[
|
||||
{ key: "users", label: <Trans>From people</Trans> },
|
||||
{ key: "playlists", label: <Trans>From playlists</Trans> },
|
||||
]}
|
||||
activeTab={section}
|
||||
onChange={setSection}
|
||||
innerClassName="followed-sub-nav"
|
||||
/>
|
||||
|
||||
{section === "users" && (
|
||||
<FollowedSubFeed
|
||||
|
||||
@@ -174,13 +174,19 @@
|
||||
[data-style="brutalist"] .audio-player-btn,
|
||||
[data-style="brutalist"] .audio-player-vol-btn,
|
||||
[data-style="brutalist"] .rich-content-thumbnail-btn,
|
||||
[data-style="brutalist"] .user-menu-trigger {
|
||||
[data-style="brutalist"] .user-menu-trigger,
|
||||
[data-style="brutalist"] .nav-search-btn,
|
||||
[data-style="brutalist"] .auth-link-btn {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
[data-style="brutalist"] .user-menu-trigger:hover:not(:disabled),
|
||||
[data-style="brutalist"] .user-menu-trigger:active {
|
||||
[data-style="brutalist"] .user-menu-trigger:active,
|
||||
[data-style="brutalist"] .nav-search-btn:hover:not(:disabled),
|
||||
[data-style="brutalist"] .nav-search-btn:active,
|
||||
[data-style="brutalist"] .auth-link-btn:hover:not(:disabled),
|
||||
[data-style="brutalist"] .auth-link-btn:active {
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user