diff --git a/api/mail/digest.ts b/api/mail/digest.ts index 06db66bc..3cb8d701 100644 --- a/api/mail/digest.ts +++ b/api/mail/digest.ts @@ -12,6 +12,7 @@ import { EMAIL_LOCALE, OG_SITE_NAME } from "../config.ts"; import type { DigestCadence } from "../../shared/settings.ts"; import { i18n } from "./i18n.ts"; +import { DIGEST_MESSAGES } from "../../shared/digest-messages.ts"; import { EmailKit, type EmailLook, @@ -127,17 +128,33 @@ const ACTIVITY_ORDER: ActivityKind[] = [ function countLabel(kind: ActivityKind, n: number): string { switch (kind) { case "upvotes": - return i18n._("digest.count.upvotes", { n }); + return i18n._({ ...DIGEST_MESSAGES.countUpvotes, values: { n } }); case "followers": - return i18n._("email.digest.count.followers", { n }); + return i18n._({ + id: "email.digest.count.followers", + message: "{n, plural, one {new follower} other {new followers}}", + values: { n }, + }); case "comments": - return i18n._("digest.count.comments", { n }); + return i18n._({ ...DIGEST_MESSAGES.countComments, values: { n } }); case "mentions": - return i18n._("email.digest.count.mentions", { n }); + return i18n._({ + id: "email.digest.count.mentions", + message: "{n, plural, one {mention} other {mentions}}", + values: { n }, + }); case "likes": - return i18n._("email.digest.count.likes", { n }); + return i18n._({ + id: "email.digest.count.likes", + message: "{n, plural, one {comment like} other {comment likes}}", + values: { n }, + }); case "playlistFollows": - return i18n._("email.digest.count.playlistFollows", { n }); + return i18n._({ + id: "email.digest.count.playlistFollows", + message: "{n, plural, one {playlist follow} other {playlist follows}}", + values: { n }, + }); } } @@ -153,36 +170,87 @@ function highlightSentence( const values = { who, target }; switch (kind) { case "mentionComment": - return i18n._("email.digest.hl.mentionComment", values); + return i18n._({ + id: "email.digest.hl.mentionComment", + message: "{who} mentioned you in a comment on {target}", + values, + }); case "mentionDump": case "mentionChat": - return i18n._("email.digest.hl.mentionIn", values); + return i18n._({ + id: "email.digest.hl.mentionIn", + message: "{who} mentioned you in {target}", + values, + }); case "mentionPlaylist": - return i18n._("email.digest.hl.mentionPlaylist", values); + return i18n._({ + id: "email.digest.hl.mentionPlaylist", + message: "{who} mentioned you in the playlist {target}", + values, + }); case "mentionEveryone": - return i18n._("email.digest.hl.mentionEveryone", values); + return i18n._({ + id: "email.digest.hl.mentionEveryone", + message: "{who} mentioned everyone in {target}", + values, + }); case "comment": - return i18n._("email.digest.hl.comment", values); + return i18n._({ + id: "email.digest.hl.comment", + message: "{who} commented on your dump {target}", + values, + }); case "playlistFollow": - return i18n._("email.digest.hl.playlistFollow", values); + return i18n._({ + id: "email.digest.hl.playlistFollow", + message: "{who} followed your playlist {target}", + values, + }); case "userFollow": - return i18n._("email.digest.hl.userFollow", values); + return i18n._({ + id: "email.digest.hl.userFollow", + message: "{who} started following you", + values, + }); case "commentLike": - return i18n._("email.digest.hl.commentLike", values); + return i18n._({ + id: "email.digest.hl.commentLike", + message: "{who} liked your comment on {target}", + values, + }); } } -const byLine = (username: string) => i18n._("email.digest.by", { username }); +const byLine = (username: string) => + i18n._({ + id: "email.digest.by", + message: "by @{username}", + values: { username }, + }); const addedToLine = (playlist: string) => - i18n._("email.digest.addedTo", { playlist }); -const uploadLabel = () => i18n._("email.digest.upload"); + i18n._({ + id: "email.digest.addedTo", + message: "added to {playlist}", + values: { playlist }, + }); +const uploadLabel = () => + i18n._({ id: "email.digest.upload", message: "upload" }); const invitedLine = (inviter: string, reader: string) => inviter === reader - ? i18n._("digest.invitedByYou") - : i18n._("digest.invitedBy", { username: inviter }); -const andMoreLine = (n: number) => i18n._("email.digest.andMore", { n }); + ? i18n._(DIGEST_MESSAGES.invitedByYou) + : i18n._({ ...DIGEST_MESSAGES.invitedBy, values: { username: inviter } }); +const andMoreLine = (n: number) => + i18n._({ + id: "email.digest.andMore", + message: "and {n} more", + values: { n }, + }); const playlistMeta = (owner: string, n: number) => - i18n._("email.digest.playlistMeta", { username: owner, n }); + i18n._({ + id: "email.digest.playlistMeta", + message: "by @{username} · {n, plural, one {# dump} other {# dumps}}", + values: { username: owner, n }, + }); /** * Returns the digest `content` describes, written as Markdown and drawn in @@ -205,7 +273,7 @@ export function renderDigestEmail( new Intl.DateTimeFormat(EMAIL_LOCALE, { weekday: "short" }).format(d); const figure = (n: number, label: string) => `**${nf.format(n)}** ${escMd(label)}`; - const yours = i18n._("email.digest.yours"); + const yours = i18n._({ id: "email.digest.yours", message: "yours" }); /** A dump as a list item: its thumbnail, title, pill and detail. */ const dumpItem = (d: DigestDump, bullet: string, image = true) => `${bullet} ${image && d.thumbnail ? `![](${d.thumbnail}) ` : ""}${ @@ -223,16 +291,26 @@ export function renderDigestEmail( const md: string[] = [ `*${ escMd( - `${monthly ? i18n._("digest.monthly") : i18n._("digest.weekly")} · ${ - range(true) - }`, + `${ + monthly + ? i18n._(DIGEST_MESSAGES.monthly) + : i18n._(DIGEST_MESSAGES.weekly) + } · ${range(true)}`, ) }*`, `# ${ escMd( monthly - ? i18n._("email.digest.monthly.title", { site: OG_SITE_NAME }) - : i18n._("email.digest.weekly.title", { username: content.reader }), + ? i18n._({ + id: "email.digest.monthly.title", + message: "The month on {site}", + values: { site: OG_SITE_NAME }, + }) + : i18n._({ + id: "email.digest.weekly.title", + message: "Your week, {username}", + values: { username: content.reader }, + }), ) }`, ]; @@ -240,7 +318,7 @@ export function renderDigestEmail( const { activity, network, community } = content; if (activity) { md.push( - `## ${escMd(i18n._("email.digest.forYou"))}`, + `## ${escMd(i18n._({ id: "email.digest.forYou", message: "For you" }))}`, ACTIVITY_ORDER.filter((k) => (activity.counts[k] ?? 0) > 0) .map((k) => figure(activity.counts[k]!, countLabel(k, activity.counts[k]!)) @@ -249,7 +327,7 @@ export function renderDigestEmail( activity.highlights.map((h) => { const target = h.kind === "mentionChat" || h.kind === "mentionEveryone" ? mdLink( - i18n._("email.digest.theChat"), + i18n._({ id: "email.digest.theChat", message: "the chat" }), content.links.chat, ) : h.target?.url @@ -264,7 +342,12 @@ export function renderDigestEmail( }).join("\n"), `${ mdLink( - i18n._("email.digest.seeAll", { n: activity.total }), + i18n._({ + id: "email.digest.seeAll", + message: + "{n, plural, one {See the notification} other {See all # notifications}}", + values: { n: activity.total }, + }), content.links.notifications, ) } →`, @@ -273,13 +356,24 @@ export function renderDigestEmail( if (network) { md.push( - `## ${escMd(i18n._("email.digest.network"))}`, + `## ${ + escMd( + i18n._({ + id: "email.digest.network", + message: "From people you follow", + }), + ) + }`, network.dumps.map((d) => dumpItem(d, "-")).join("\n"), ); if (network.more > 0) { md.push(`${ mdLink( - i18n._("email.digest.more", { n: network.more }), + i18n._({ + id: "email.digest.more", + message: "{n} more on your Followed feed", + values: { n: network.more }, + }), content.links.followed, ) } →`); @@ -291,7 +385,9 @@ export function renderDigestEmail( md.push( `## ${ escMd( - monthly ? i18n._("digest.topMonth") : i18n._("digest.topWeek"), + monthly + ? i18n._(DIGEST_MESSAGES.topMonth) + : i18n._(DIGEST_MESSAGES.topWeek), ) }`, ); @@ -307,20 +403,23 @@ export function renderDigestEmail( if (community) { const { dumps, upvotes, comments } = community.totals; md.push( - `## ${escMd(i18n._("digest.community"))}`, + `## ${escMd(i18n._(DIGEST_MESSAGES.community))}`, ); if (monthly) { md.push( [ figure( dumps, - i18n._("digest.stat.dumps", { n: dumps }), + i18n._({ ...DIGEST_MESSAGES.statDumps, values: { n: dumps } }), ), figure(upvotes, countLabel("upvotes", upvotes)), figure(comments, countLabel("comments", comments)), figure( community.chatMessages, - i18n._("digest.stat.chat", { n: community.chatMessages }), + i18n._({ + ...DIGEST_MESSAGES.statChat, + values: { n: community.chatMessages }, + }), ), ].join(" · "), ); @@ -329,7 +428,7 @@ export function renderDigestEmail( md.push( `### ${ escMd( - i18n._("digest.newMembers"), + i18n._(DIGEST_MESSAGES.newMembers), ) }`, [ @@ -348,7 +447,7 @@ export function renderDigestEmail( } if (community.playlists.length > 0) { md.push( - `### ${escMd(i18n._("digest.newPlaylists"))}`, + `### ${escMd(i18n._(DIGEST_MESSAGES.newPlaylists))}`, [ ...community.playlists.map((p) => `- ${mdLink(p.title, p.url)} · ${ @@ -363,12 +462,21 @@ export function renderDigestEmail( } if (!monthly && community.chatMessages > 0) { md.push( - `### ${escMd(i18n._("email.digest.inChat"))}`, + `### ${ + escMd(i18n._({ id: "email.digest.inChat", message: "In the chat" })) + }`, `${ - escMd(i18n._("email.digest.chatWeek", { n: community.chatMessages })) + escMd( + i18n._({ + id: "email.digest.chatWeek", + message: + "{n, plural, one {# message this week} other {# messages this week}}", + values: { n: community.chatMessages }, + }), + ) } · ${ mdLink( - i18n._("email.digest.openChat"), + i18n._({ id: "email.digest.openChat", message: "Open the chat" }), content.links.chat, ) }`, @@ -377,13 +485,21 @@ export function renderDigestEmail( if (!monthly && dumps + upvotes + comments > 0) { md.push( `*${ - escMd(i18n._("email.digest.totals", { dumps, upvotes, comments })) + escMd(i18n._({ + id: "email.digest.totals", + message: + "{dumps, plural, one {# dump} other {# dumps}}, {upvotes, plural, one {# upvote} other {# upvotes}} and {comments, plural, one {# comment} other {# comments}}.", + values: { dumps, upvotes, comments }, + })) }*`, ); } md.push(`${ mdLink( - i18n._("email.digest.communityPage"), + i18n._({ + id: "email.digest.communityPage", + message: "See it all on the community page", + }), content.links.community, ) } →`); @@ -393,17 +509,27 @@ export function renderDigestEmail( "---", escMd( monthly - ? i18n._("email.digest.monthly.reason") - : i18n._("email.digest.weekly.reason"), + ? i18n._({ + id: "email.digest.monthly.reason", + message: + "You're getting the monthly recap because it's on in your settings.", + }) + : i18n._({ + id: "email.digest.weekly.reason", + message: + "You're getting the weekly digest because it's on in your settings.", + }), ), `${ mdLink( - monthly ? i18n._("digest.monthly.off") : i18n._("digest.weekly.off"), + monthly + ? i18n._(DIGEST_MESSAGES.monthlyOff) + : i18n._(DIGEST_MESSAGES.weeklyOff), content.links.unsubscribe, ) } · ${ mdLink( - i18n._("email.settings"), + i18n._({ id: "email.settings", message: "Settings" }), content.links.settings, ) }`, @@ -411,13 +537,15 @@ export function renderDigestEmail( return new EmailKit(look).render({ subject: monthly - ? i18n._("email.digest.monthly.subject", { - site: OG_SITE_NAME, - range: range(false), + ? i18n._({ + id: "email.digest.monthly.subject", + message: "The month on {site}, {range}", + values: { site: OG_SITE_NAME, range: range(false) }, }) - : i18n._("email.digest.weekly.subject", { - site: OG_SITE_NAME, - range: range(false), + : i18n._({ + id: "email.digest.weekly.subject", + message: "Your week on {site}, {range}", + values: { site: OG_SITE_NAME, range: range(false) }, }), preheader: preheader(content), markdown: md.join("\n\n"), @@ -438,7 +566,14 @@ function preheader(content: DigestContent): string { const n = (content.network?.dumps.length ?? 0) + (content.network?.more ?? 0); if (n > 0) { - parts.push(i18n._("email.digest.pre.network", { n })); + parts.push( + i18n._({ + id: "email.digest.pre.network", + message: + "{n, plural, one {# new dump from people you follow} other {# new dumps from people you follow}}", + values: { n }, + }), + ); } } else { const members = (content.community?.members.length ?? 0) + @@ -447,18 +582,42 @@ function preheader(content: DigestContent): string { (content.community?.playlistsMore ?? 0); if (content.top.length > 0) { parts.push( - i18n._("email.digest.pre.topMonth", { n: content.top.length }), + i18n._({ + id: "email.digest.pre.topMonth", + message: + "{n, plural, one {the most upvoted dump of the month} other {the # most upvoted dumps of the month}}", + values: { n: content.top.length }, + }), ); } if (members > 0) { - parts.push(i18n._("email.digest.pre.members", { n: members })); + parts.push( + i18n._({ + id: "email.digest.pre.members", + message: "{n, plural, one {# new member} other {# new members}}", + values: { n: members }, + }), + ); } if (playlists > 0) { - parts.push(i18n._("email.digest.pre.playlists", { n: playlists })); + parts.push( + i18n._({ + id: "email.digest.pre.playlists", + message: "{n, plural, one {# new playlist} other {# new playlists}}", + values: { n: playlists }, + }), + ); } } if (parts.length === 0 && content.top.length > 0) { - parts.push(i18n._("email.digest.pre.topWeek", { n: content.top.length })); + parts.push( + i18n._({ + id: "email.digest.pre.topWeek", + message: + "{n, plural, one {the most upvoted dump of the week} other {the # most upvoted dumps of the week}}", + values: { n: content.top.length }, + }), + ); } if (parts.length === 0) return ""; const line = new Intl.ListFormat(EMAIL_LOCALE, { type: "conjunction" }) diff --git a/api/mail/i18n.ts b/api/mail/i18n.ts index c38aef2b..de90d766 100644 --- a/api/mail/i18n.ts +++ b/api/mail/i18n.ts @@ -1,12 +1,13 @@ /** * Lets the emails speak the instance's language from the same catalogs as - * the interface. A template names each message by its id, as - * `i18n._("email.reset.title", values)`, and its words, English included, - * are written in `locales/.po` only. `lingui extract` lists the ids it - * finds there beside the interface's messages, and `lingui compile` turns - * the catalogs into the `locales/.mjs` imported here, failing when a - * language lacks one. The ids are named rather than hashed from the English, - * since the server runs no Lingui macro. + * the interface. A template passes each message as a descriptor holding its + * id and its English, as `i18n._({ id: "email.reset.title", message: "Reset + * your password" })`, or one of `shared/digest-messages.ts`, which a page + * says too. `lingui extract` reads them into `locales/.po` beside the + * interface's messages, and `lingui compile` turns the catalogs into the + * `locales/.mjs` imported here, failing when a language lacks one. The + * ids are named rather than hashed from the English, since the server runs + * no Lingui macro. * * @module */ diff --git a/api/mail/password-reset.ts b/api/mail/password-reset.ts index d71cc2b0..430d04a9 100644 --- a/api/mail/password-reset.ts +++ b/api/mail/password-reset.ts @@ -26,23 +26,67 @@ export function renderPasswordResetEmail( hours: number, ): RenderedEmail { const markdown = [ - `# ${escMd(i18n._("email.reset.title"))}`, - escMd(i18n._("email.reset.hi", { username })), - escMd(i18n._("email.reset.body", { site: OG_SITE_NAME, hours })), + `# ${ + escMd(i18n._({ id: "email.reset.title", message: "Reset your password" })) + }`, + escMd( + i18n._({ + id: "email.reset.hi", + message: "Hi {username},", + values: { username }, + }), + ), + escMd(i18n._({ + id: "email.reset.body", + message: + "Someone asked to reset the password of your {site} account. The button below lets you choose a new one. It works once, for {hours, plural, one {# hour} other {# hours}}.", + values: { site: OG_SITE_NAME, hours }, + })), mdLink( - i18n._("email.reset.button"), + i18n._({ id: "email.reset.button", message: "Reset password" }), resetUrl, ), - `*${escMd(i18n._("email.reset.fallback"))}*`, + `*${ + escMd( + i18n._({ + id: "email.reset.fallback", + message: + "If the button doesn't work, paste this link into your browser:", + }), + ) + }*`, "```\n" + resetUrl + "\n```", - `*${escMd(i18n._("email.reset.ignore"))}*`, + `*${ + escMd( + i18n._({ + id: "email.reset.ignore", + message: + "If you didn't ask for this, ignore this email. Your password stays the same.", + }), + ) + }*`, "---", - escMd(i18n._("email.reset.reason")), + escMd( + i18n._({ + id: "email.reset.reason", + message: + "You're getting this email because a password reset was requested for this address.", + }), + ), ].join("\n\n"); return new EmailKit(lookOf()).render({ - subject: i18n._("email.reset.subject", { site: OG_SITE_NAME }), - preheader: i18n._("email.reset.preheader", { hours }), + subject: i18n._({ + id: "email.reset.subject", + message: "Reset your {site} password", + values: { site: OG_SITE_NAME }, + }), + preheader: i18n._({ + id: "email.reset.preheader", + message: + "The link works once, for {hours, plural, one {# hour} other {# hours}}.", + values: { hours }, + }), markdown, }); } diff --git a/api/mail/welcome.ts b/api/mail/welcome.ts index bc87611a..2d97f904 100644 --- a/api/mail/welcome.ts +++ b/api/mail/welcome.ts @@ -29,24 +29,52 @@ export function renderWelcomeEmail(username: string): RenderedEmail { ? WELCOME_EMAIL_BODY .replaceAll("{{username}}", escMd(username)) .replaceAll("{{site_name}}", escMd(OG_SITE_NAME)) - : i18n._("email.welcome.body", { - site: escMd(OG_SITE_NAME), - username: escMd(username), + : i18n._({ + id: "email.welcome.body", + message: + "# Welcome to {site}!\n\nHi **{username}**,\n\nYour account has been created successfully. Welcome aboard!", + values: { site: escMd(OG_SITE_NAME), username: escMd(username) }, }); const markdown = [ body, mdLink( - i18n._("email.welcome.button", { site: OG_SITE_NAME }), + i18n._({ + id: "email.welcome.button", + message: "Open {site}", + values: { site: OG_SITE_NAME }, + }), FRONTEND_URL, ), - `*${escMd(i18n._("email.welcome.digests"))}*`, + `*${ + escMd( + i18n._({ + id: "email.welcome.digests", + message: + "Once a week you'll get a digest of what happened here, and once a month a recap of the most upvoted dumps. You can turn either off in your settings.", + }), + ) + }*`, "---", - escMd(i18n._("email.welcome.reason", { site: OG_SITE_NAME })), + escMd( + i18n._({ + id: "email.welcome.reason", + message: + "You're getting this email because an account was created on {site} with this address.", + values: { site: OG_SITE_NAME }, + }), + ), ].join("\n\n"); return new EmailKit(lookOf()).render({ - subject: i18n._("email.welcome.subject", { site: OG_SITE_NAME }), - preheader: i18n._("email.welcome.preheader"), + subject: i18n._({ + id: "email.welcome.subject", + message: "Welcome to {site}", + values: { site: OG_SITE_NAME }, + }), + preheader: i18n._({ + id: "email.welcome.preheader", + message: "Your account is ready.", + }), markdown, }); } diff --git a/deno.json b/deno.json index fc2b613c..a757ae17 100644 --- a/deno.json +++ b/deno.json @@ -5,7 +5,7 @@ "server:start": "deno run --env-file -A --watch api/main.ts", "icons": "deno run --env-file -A api/scripts/generate-icons.ts", "serve": "deno task build && deno task icons dist && deno task server:start", - "i18n:extract": "deno run -A npm:@lingui/cli extract --clean --workers 1", + "i18n:extract": "deno run -A npm:@lingui/cli extract --clean --overwrite --workers 1", "i18n:compile": "deno run -A npm:@lingui/cli compile --strict --workers 1", "start": "deno task icons dist && deno run --env-file -A api/main.ts", "test": "deno test -A api/ shared/", diff --git a/lingui.config.ts b/lingui.config.ts index a3dd6a25..3d459334 100644 --- a/lingui.config.ts +++ b/lingui.config.ts @@ -7,12 +7,12 @@ const config: LinguiConfig = { sourceLocale: SOURCE_LOCALE, catalogs: [ { - // One catalog per language for the whole app: the interface's messages - // and the emails' (api/mail/), which the server imports compiled. A - // message named by id has its English in en.po only, which is why - // extract runs without --overwrite (it would write the id there). + // One catalog per language for the whole app: the interface's messages, + // the emails' (api/mail/), which the server imports compiled, and those + // both say (shared/digest-messages.ts). Every message's English is in + // the code, so extract --overwrite writes en.po from it. path: "locales/{locale}", - include: ["src", "api/mail"], + include: ["src", "api/mail", "shared"], }, ], format: formatter(), diff --git a/locales/en.po b/locales/en.po index 027a8f85..9d276137 100644 --- a/locales/en.po +++ b/locales/en.po @@ -13,377 +13,6 @@ msgstr "" "Language-Team: \n" "Plural-Forms: \n" -#. js-lingui-explicit-id -#: api/mail/digest.ts:163 -msgid "email.digest.hl.mentionEveryone" -msgstr "{who} mentioned everyone in {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:130 -#: src/pages/Community.tsx:49 -msgid "digest.count.upvotes" -msgstr "{n, plural, one {upvote} other {upvotes}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:132 -msgid "email.digest.count.followers" -msgstr "{n, plural, one {new follower} other {new followers}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:134 -#: src/pages/Community.tsx:50 -msgid "digest.count.comments" -msgstr "{n, plural, one {comment} other {comments}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:136 -msgid "email.digest.count.mentions" -msgstr "{n, plural, one {mention} other {mentions}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:138 -msgid "email.digest.count.likes" -msgstr "{n, plural, one {comment like} other {comment likes}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:140 -msgid "email.digest.count.playlistFollows" -msgstr "{n, plural, one {playlist follow} other {playlist follows}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:156 -msgid "email.digest.hl.mentionComment" -msgstr "{who} mentioned you in a comment on {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:159 -msgid "email.digest.hl.mentionIn" -msgstr "{who} mentioned you in {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:161 -msgid "email.digest.hl.mentionPlaylist" -msgstr "{who} mentioned you in the playlist {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:165 -msgid "email.digest.hl.comment" -msgstr "{who} commented on your dump {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:167 -msgid "email.digest.hl.playlistFollow" -msgstr "{who} followed your playlist {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:169 -msgid "email.digest.hl.userFollow" -msgstr "{who} started following you" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:171 -msgid "email.digest.hl.commentLike" -msgstr "{who} liked your comment on {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:175 -msgid "email.digest.by" -msgstr "by @{username}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:177 -msgid "email.digest.addedTo" -msgstr "added to {playlist}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:178 -msgid "email.digest.upload" -msgstr "upload" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:181 -#: src/pages/Community.tsx:141 -msgid "digest.invitedByYou" -msgstr "invited by you" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:182 -#: src/pages/Community.tsx:143 -msgid "digest.invitedBy" -msgstr "invited by @{username}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:183 -msgid "email.digest.andMore" -msgstr "and {n} more" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:185 -msgid "email.digest.playlistMeta" -msgstr "by @{username} · {n, plural, one {# dump} other {# dumps}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:208 -msgid "email.digest.yours" -msgstr "yours" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:226 -#: src/pages/Settings.tsx:154 -msgid "digest.monthly" -msgstr "Monthly recap" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:226 -#: src/pages/Settings.tsx:145 -msgid "digest.weekly" -msgstr "Weekly digest" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:234 -msgid "email.digest.monthly.title" -msgstr "The month on {site}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:235 -msgid "email.digest.weekly.title" -msgstr "Your week, {username}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:243 -msgid "email.digest.forYou" -msgstr "For you" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:252 -msgid "email.digest.theChat" -msgstr "the chat" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:267 -msgid "email.digest.seeAll" -msgstr "{n, plural, one {See the notification} other {See all # notifications}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:276 -msgid "email.digest.network" -msgstr "From people you follow" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:282 -msgid "email.digest.more" -msgstr "{n} more on your Followed feed" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:294 -#: src/pages/Community.tsx:127 -msgid "digest.topMonth" -msgstr "Top this month" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:294 -#: src/pages/Community.tsx:126 -msgid "digest.topWeek" -msgstr "Top this week" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:310 -#: src/components/layout/UserMenu.tsx:94 -#: src/pages/Community.tsx:73 -#: src/pages/Community.tsx:100 -msgid "digest.community" -msgstr "Community" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:317 -#: src/pages/Community.tsx:48 -msgid "digest.stat.dumps" -msgstr "{n, plural, one {dump} other {dumps}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:323 -#: src/pages/Community.tsx:53 -msgid "digest.stat.chat" -msgstr "{n, plural, one {chat message} other {chat messages}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:332 -#: src/pages/Community.tsx:133 -msgid "digest.newMembers" -msgstr "New members" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:351 -#: src/pages/Community.tsx:154 -msgid "digest.newPlaylists" -msgstr "New public playlists" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:366 -msgid "email.digest.inChat" -msgstr "In the chat" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:368 -msgid "email.digest.chatWeek" -msgstr "{n, plural, one {# message this week} other {# messages this week}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:371 -msgid "email.digest.openChat" -msgstr "Open the chat" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:380 -msgid "email.digest.totals" -msgstr "{dumps, plural, one {# dump} other {# dumps}}, {upvotes, plural, one {# upvote} other {# upvotes}} and {comments, plural, one {# comment} other {# comments}}." - -#. js-lingui-explicit-id -#: api/mail/digest.ts:386 -msgid "email.digest.communityPage" -msgstr "See it all on the community page" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:396 -msgid "email.digest.monthly.reason" -msgstr "You're getting the monthly recap because it's on in your settings." - -#. js-lingui-explicit-id -#: api/mail/digest.ts:397 -msgid "email.digest.weekly.reason" -msgstr "You're getting the weekly digest because it's on in your settings." - -#. js-lingui-explicit-id -#: api/mail/digest.ts:401 -#: src/pages/Unsubscribe.tsx:118 -msgid "digest.monthly.off" -msgstr "Turn off monthly recaps" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:401 -#: src/pages/Unsubscribe.tsx:117 -msgid "digest.weekly.off" -msgstr "Turn off weekly digests" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:406 -msgid "email.settings" -msgstr "Settings" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:414 -msgid "email.digest.monthly.subject" -msgstr "The month on {site}, {range}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:418 -msgid "email.digest.weekly.subject" -msgstr "Your week on {site}, {range}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:441 -msgid "email.digest.pre.network" -msgstr "{n, plural, one {# new dump from people you follow} other {# new dumps from people you follow}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:450 -msgid "email.digest.pre.topMonth" -msgstr "{n, plural, one {the most upvoted dump of the month} other {the # most upvoted dumps of the month}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:454 -msgid "email.digest.pre.members" -msgstr "{n, plural, one {# new member} other {# new members}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:457 -msgid "email.digest.pre.playlists" -msgstr "{n, plural, one {# new playlist} other {# new playlists}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:461 -msgid "email.digest.pre.topWeek" -msgstr "{n, plural, one {the most upvoted dump of the week} other {the # most upvoted dumps of the week}}" - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:29 -msgid "email.reset.title" -msgstr "Reset your password" - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:30 -msgid "email.reset.hi" -msgstr "Hi {username}," - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:31 -msgid "email.reset.body" -msgstr "Someone asked to reset the password of your {site} account. The button below lets you choose a new one. It works once, for {hours, plural, one {# hour} other {# hours}}." - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:33 -msgid "email.reset.button" -msgstr "Reset password" - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:36 -msgid "email.reset.fallback" -msgstr "If the button doesn't work, paste this link into your browser:" - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:38 -msgid "email.reset.ignore" -msgstr "If you didn't ask for this, ignore this email. Your password stays the same." - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:40 -msgid "email.reset.reason" -msgstr "You're getting this email because a password reset was requested for this address." - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:44 -msgid "email.reset.subject" -msgstr "Reset your {site} password" - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:45 -msgid "email.reset.preheader" -msgstr "The link works once, for {hours, plural, one {# hour} other {# hours}}." - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:32 -msgid "email.welcome.body" -msgstr "# Welcome to {site}!\n" -"\n" -"Hi **{username}**,\n" -"\n" -"Your account has been created successfully. Welcome aboard!" - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:39 -msgid "email.welcome.button" -msgstr "Open {site}" - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:42 -msgid "email.welcome.digests" -msgstr "Once a week you'll get a digest of what happened here, and once a month a recap of the most upvoted dumps. You can turn either off in your settings." - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:44 -msgid "email.welcome.reason" -msgstr "You're getting this email because an account was created on {site} with this address." - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:48 -msgid "email.welcome.subject" -msgstr "Welcome to {site}" - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:49 -msgid "email.welcome.preheader" -msgstr "Your account is ready." - #: src/components/comment/CommentNode.tsx:140 msgid "[deleted]" msgstr "[deleted]" @@ -426,10 +55,95 @@ msgstr "{0} more online: {restNames}" msgid "{0}–{1} characters: letters, numbers, or underscores" msgstr "{0}–{1} characters: letters, numbers, or underscores" +#. js-lingui-explicit-id +#: api/mail/digest.ts:488 +msgid "email.digest.totals" +msgstr "{dumps, plural, one {# dump} other {# dumps}}, {upvotes, plural, one {# upvote} other {# upvotes}} and {comments, plural, one {# comment} other {# comments}}." + #: src/pages/Search.tsx:124 msgid "{label} ({count})" msgstr "{label} ({count})" +#. js-lingui-explicit-id +#: api/mail/digest.ts:470 +msgid "email.digest.chatWeek" +msgstr "{n, plural, one {# message this week} other {# messages this week}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:570 +msgid "email.digest.pre.network" +msgstr "{n, plural, one {# new dump from people you follow} other {# new dumps from people you follow}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:595 +msgid "email.digest.pre.members" +msgstr "{n, plural, one {# new member} other {# new members}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:604 +msgid "email.digest.pre.playlists" +msgstr "{n, plural, one {# new playlist} other {# new playlists}}" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:68 +msgid "digest.stat.chat" +msgstr "{n, plural, one {chat message} other {chat messages}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:147 +msgid "email.digest.count.likes" +msgstr "{n, plural, one {comment like} other {comment likes}}" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:76 +msgid "digest.count.comments" +msgstr "{n, plural, one {comment} other {comments}}" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:64 +msgid "digest.stat.dumps" +msgstr "{n, plural, one {dump} other {dumps}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:141 +msgid "email.digest.count.mentions" +msgstr "{n, plural, one {mention} other {mentions}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:133 +msgid "email.digest.count.followers" +msgstr "{n, plural, one {new follower} other {new followers}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:153 +msgid "email.digest.count.playlistFollows" +msgstr "{n, plural, one {playlist follow} other {playlist follows}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:345 +msgid "email.digest.seeAll" +msgstr "{n, plural, one {See the notification} other {See all # notifications}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:585 +msgid "email.digest.pre.topMonth" +msgstr "{n, plural, one {the most upvoted dump of the month} other {the # most upvoted dumps of the month}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:614 +msgid "email.digest.pre.topWeek" +msgstr "{n, plural, one {the most upvoted dump of the week} other {the # most upvoted dumps of the week}}" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:72 +msgid "digest.count.upvotes" +msgstr "{n, plural, one {upvote} other {upvotes}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:372 +msgid "email.digest.more" +msgstr "{n} more on your Followed feed" + #: src/pages/Notifications.tsx:508 msgid "{totalUnread, plural, one {# new} other {# new}}" msgstr "{totalUnread, plural, one {# new} other {# new}}" @@ -442,6 +156,55 @@ msgstr "{unseenCount} new messages" msgid "{visibleCount, plural, one {# comment} other {# comments}}" msgstr "{visibleCount, plural, one {# comment} other {# comments}}" +#. js-lingui-explicit-id +#: api/mail/digest.ts:198 +msgid "email.digest.hl.comment" +msgstr "{who} commented on your dump {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:204 +msgid "email.digest.hl.playlistFollow" +msgstr "{who} followed your playlist {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:216 +msgid "email.digest.hl.commentLike" +msgstr "{who} liked your comment on {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:192 +msgid "email.digest.hl.mentionEveryone" +msgstr "{who} mentioned everyone in {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:180 +msgid "email.digest.hl.mentionIn" +msgstr "{who} mentioned you in {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:173 +msgid "email.digest.hl.mentionComment" +msgstr "{who} mentioned you in a comment on {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:186 +msgid "email.digest.hl.mentionPlaylist" +msgstr "{who} mentioned you in the playlist {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:210 +msgid "email.digest.hl.userFollow" +msgstr "{who} started following you" + +#. js-lingui-explicit-id +#: api/mail/welcome.ts:32 +msgid "email.welcome.body" +msgstr "# Welcome to {site}!\n" +"\n" +"Hi **{username}**,\n" +"\n" +"Your account has been created successfully. Welcome aboard!" + #: src/components/dump/create/DumpCreateModal.tsx:742 #: src/pages/PlaylistDetail.tsx:80 #: src/pages/UserPublicProfile.tsx:123 @@ -533,7 +296,7 @@ msgstr "A link is required" msgid "a post" msgstr "a post" -#: src/pages/Settings.tsx:83 +#: src/pages/Settings.tsx:85 msgid "Account" msgstr "Account" @@ -559,6 +322,11 @@ msgstr "Add image" msgid "Add to playlist" msgstr "Add to playlist" +#. js-lingui-explicit-id +#: api/mail/digest.ts:231 +msgid "email.digest.addedTo" +msgstr "added to {playlist}" + #: src/components/profile/RoleSwitcher.tsx:24 msgid "Admin" msgstr "Admin" @@ -582,7 +350,12 @@ msgstr "Already have an account? <0>Log in" msgid "An unexpected error occurred." msgstr "An unexpected error occurred." -#: src/pages/Settings.tsx:99 +#. js-lingui-explicit-id +#: api/mail/digest.ts:243 +msgid "email.digest.andMore" +msgstr "and {n} more" + +#: src/pages/Settings.tsx:101 msgid "Appearance" msgstr "Appearance" @@ -597,7 +370,7 @@ msgstr "At least {0} characters" msgid "At most {maxLength} characters." msgstr "At most {maxLength} characters." -#: src/pages/Settings.tsx:45 +#: src/pages/Settings.tsx:46 msgid "Auto" msgstr "Auto" @@ -606,6 +379,16 @@ msgstr "Auto" msgid "Back to login" msgstr "Back to login" +#. js-lingui-explicit-id +#: api/mail/digest.ts:225 +msgid "email.digest.by" +msgstr "by @{username}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:249 +msgid "email.digest.playlistMeta" +msgstr "by @{username} · {n, plural, one {# dump} other {# dumps}}" + #: src/contexts/ws/WSProvider.tsx:395 #: src/contexts/ws/WSProvider.tsx:764 msgid "Can't connect to the live updates server. Upvotes and notifications may not sync until it reconnects." @@ -661,7 +444,7 @@ msgstr "Change image" msgid "Change password" msgstr "Change password" -#: src/pages/Settings.tsx:94 +#: src/pages/Settings.tsx:96 msgid "Change password…" msgstr "Change password…" @@ -710,10 +493,15 @@ msgstr "Close without posting? The attached file won't be kept — everything yo msgid "Collapse player" msgstr "Collapse player" -#: src/pages/Settings.tsx:108 +#: src/pages/Settings.tsx:110 msgid "Color scheme" msgstr "Color scheme" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:36 +msgid "digest.community" +msgstr "Community" + #: src/components/profile/ChangePasswordModal.tsx:108 #: src/pages/ResetPassword.tsx:131 msgid "Confirm new password" @@ -760,7 +548,7 @@ msgstr "Couldn't load a preview for this link — check it, or post it as-is and msgid "Couldn't load the chat." msgstr "Couldn't load the chat." -#: src/pages/Unsubscribe.tsx:114 +#: src/pages/Unsubscribe.tsx:116 msgid "Couldn't unsubscribe" msgstr "Couldn't unsubscribe" @@ -788,11 +576,11 @@ msgstr "Creating…" msgid "Current password" msgstr "Current password" -#: src/pages/Settings.tsx:47 +#: src/pages/Settings.tsx:48 msgid "Dark" msgstr "Dark" -#: src/pages/Settings.tsx:119 +#: src/pages/Settings.tsx:121 msgid "Default tab" msgstr "Default tab" @@ -984,7 +772,7 @@ msgstr "Editing" msgid "Editing {0}" msgstr "Editing {0}" -#: src/pages/Settings.tsx:143 +#: src/pages/Settings.tsx:145 msgid "Email" msgstr "Email" @@ -1056,7 +844,7 @@ msgstr "Failed to update avatar" msgid "Failed to update role" msgstr "Failed to update role" -#: src/pages/Settings.tsx:117 +#: src/pages/Settings.tsx:119 msgid "Feeds" msgstr "Feeds" @@ -1091,7 +879,7 @@ msgstr "Follow some users to see their dumps here." #: src/components/feed/FeedTabBar.tsx:43 #: src/components/profile/ProfileFollowTab.tsx:140 -#: src/pages/Settings.tsx:54 +#: src/pages/Settings.tsx:55 #: src/pages/UserPublicProfile.tsx:161 msgid "Followed" msgstr "Followed" @@ -1101,6 +889,11 @@ msgstr "Followed" msgid "Following" msgstr "Following" +#. js-lingui-explicit-id +#: api/mail/digest.ts:321 +msgid "email.digest.forYou" +msgstr "For you" + #: src/pages/UserLogin.tsx:97 msgid "Forgot password?" msgstr "Forgot password?" @@ -1109,6 +902,11 @@ msgstr "Forgot password?" msgid "From people" msgstr "From people" +#. js-lingui-explicit-id +#: api/mail/digest.ts:361 +msgid "email.digest.network" +msgstr "From people you follow" + #: src/components/feed/FollowedFeed.tsx:133 msgid "From playlists" msgstr "From playlists" @@ -1125,8 +923,13 @@ msgstr "Go home" msgid "Go to login" msgstr "Go to login" +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:33 +msgid "email.reset.hi" +msgstr "Hi {username}," + #: src/components/feed/FeedTabBar.tsx:39 -#: src/pages/Settings.tsx:51 +#: src/pages/Settings.tsx:52 msgid "Hot" msgstr "Hot" @@ -1134,6 +937,16 @@ msgstr "Hot" msgid "If that address is registered you'll receive a reset link shortly." msgstr "If that address is registered you'll receive a reset link shortly." +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:51 +msgid "email.reset.fallback" +msgstr "If the button doesn't work, paste this link into your browser:" + +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:61 +msgid "email.reset.ignore" +msgstr "If you didn't ask for this, ignore this email. Your password stays the same." + #: src/utils/chat/message.ts:43 msgid "image" msgstr "image" @@ -1142,8 +955,13 @@ msgstr "image" msgid "In collections" msgstr "In collections" -#: src/components/editor/TextEditor.tsx:579 -#: src/components/editor/TextEditor.tsx:581 +#. js-lingui-explicit-id +#: api/mail/digest.ts:466 +msgid "email.digest.inChat" +msgstr "In the chat" + +#: src/components/editor/TextEditor.tsx:580 +#: src/components/editor/TextEditor.tsx:582 msgid "Insert emoji" msgstr "Insert emoji" @@ -1152,7 +970,7 @@ msgid "Invalid invite" msgstr "Invalid invite" #: src/pages/ResetPassword.tsx:64 -#: src/pages/Unsubscribe.tsx:64 +#: src/pages/Unsubscribe.tsx:66 msgid "Invalid link" msgstr "Invalid link" @@ -1165,13 +983,23 @@ msgstr "Invite link" msgid "invited by" msgstr "invited by" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:56 +msgid "digest.invitedBy" +msgstr "invited by @{username}" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:60 +msgid "digest.invitedByYou" +msgstr "invited by you" + #: src/components/profile/ProfileInviteesTab.tsx:77 #: src/pages/UserPublicProfile.tsx:162 msgid "Invitees" msgstr "Invitees" #: src/components/feed/FeedTabBar.tsx:41 -#: src/pages/Settings.tsx:53 +#: src/pages/Settings.tsx:54 msgid "Journal" msgstr "Journal" @@ -1183,7 +1011,7 @@ msgstr "Keep editing" msgid "Letters, numbers and underscores only" msgstr "Letters, numbers and underscores only" -#: src/pages/Settings.tsx:46 +#: src/pages/Settings.tsx:47 msgid "Light" msgstr "Light" @@ -1262,7 +1090,7 @@ msgstr "Log in to like" msgid "Log in to vote" msgstr "Log in to vote" -#: src/components/layout/UserMenu.tsx:124 +#: src/components/layout/UserMenu.tsx:126 #: src/pages/UserPublicProfile.tsx:131 msgid "Log out" msgstr "Log out" @@ -1279,7 +1107,7 @@ msgstr "Login failed" msgid "Lowercase letters, numbers and single hyphens only" msgstr "Lowercase letters, numbers and single hyphens only" -#: src/components/layout/UserMenu.tsx:111 +#: src/components/layout/UserMenu.tsx:113 #: src/pages/Manage.tsx:24 #: src/pages/Manage.tsx:29 #: src/pages/UserPublicProfile.tsx:164 @@ -1294,6 +1122,11 @@ msgstr "Max {limit}" msgid "Moderator" msgstr "Moderator" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:24 +msgid "digest.monthly" +msgstr "Monthly recap" + #: src/components/player/MediaPlayer.tsx:346 msgid "Mute" msgstr "Mute" @@ -1305,7 +1138,7 @@ msgstr "Name" #: src/components/chat/ChatModal.tsx:692 #: src/components/feed/FeedTabBar.tsx:40 -#: src/pages/Settings.tsx:52 +#: src/pages/Settings.tsx:53 msgid "New" msgstr "New" @@ -1316,6 +1149,11 @@ msgstr "New" msgid "New dump" msgstr "New dump" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:48 +msgid "digest.newMembers" +msgstr "New members" + #: src/components/profile/ChangePasswordModal.tsx:94 #: src/pages/ResetPassword.tsx:116 msgid "New password" @@ -1326,6 +1164,11 @@ msgstr "New password" msgid "New playlist" msgstr "New playlist" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:52 +msgid "digest.newPlaylists" +msgstr "New public playlists" + #: src/components/dump/create/DumpCreateModal.tsx:764 msgid "Next →" msgstr "Next →" @@ -1388,11 +1231,11 @@ msgstr "No users match \"{q}\"." msgid "Not following anyone yet." msgstr "Not following anyone yet." -#: src/pages/Community.tsx:116 +#: src/pages/Community.tsx:127 msgid "Nothing happened this month." msgstr "Nothing happened this month." -#: src/pages/Community.tsx:115 +#: src/pages/Community.tsx:126 msgid "Nothing happened this week." msgstr "Nothing happened this week." @@ -1405,7 +1248,7 @@ msgstr "Nothing here yet." #: src/components/layout/NotificationBell.tsx:57 #: src/pages/Notifications.tsx:387 #: src/pages/Notifications.tsx:505 -#: src/pages/Settings.tsx:128 +#: src/pages/Settings.tsx:130 msgid "Notifications" msgstr "Notifications" @@ -1413,15 +1256,20 @@ msgstr "Notifications" msgid "Notifications ({unreadNotificationCount} unread)" msgstr "Notifications ({unreadNotificationCount} unread)" -#: src/pages/Settings.tsx:59 +#: src/pages/Settings.tsx:60 msgid "Off" msgstr "Off" -#: src/pages/Settings.tsx:58 +#: src/pages/Settings.tsx:59 msgid "On" msgstr "On" -#: src/components/editor/TextEditor.tsx:391 +#. js-lingui-explicit-id +#: api/mail/welcome.ts:50 +msgid "email.welcome.digests" +msgstr "Once a week you'll get a digest of what happened here, and once a month a recap of the most upvoted dumps. You can turn either off in your settings." + +#: src/components/editor/TextEditor.tsx:392 msgid "Only images can be dropped here." msgstr "Only images can be dropped here." @@ -1429,6 +1277,11 @@ msgstr "Only images can be dropped here." msgid "Only its poster or a moderator can edit this dump." msgstr "Only its poster or a moderator can edit this dump." +#. js-lingui-explicit-id +#: api/mail/welcome.ts:41 +msgid "email.welcome.button" +msgstr "Open {site}" + #. placeholder {0}: richContent.siteName #: src/components/dump/RichContentCard.tsx:122 msgid "Open on {0}" @@ -1438,6 +1291,11 @@ msgstr "Open on {0}" msgid "Open source" msgstr "Open source" +#. js-lingui-explicit-id +#: api/mail/digest.ts:479 +msgid "email.digest.openChat" +msgstr "Open the chat" + #: src/components/form/FileDropZone.tsx:163 msgid "or <0>browse files" msgstr "or <0>browse files" @@ -1450,7 +1308,7 @@ msgstr "Overview" msgid "Page not found" msgstr "Page not found" -#: src/pages/Settings.tsx:88 +#: src/pages/Settings.tsx:90 #: src/pages/UserLogin.tsx:82 msgid "Password" msgstr "Password" @@ -1498,7 +1356,7 @@ msgstr "Play" #: src/components/dump/create/StepIndicator.tsx:21 #: src/components/layout/AppHeader.tsx:172 -#: src/components/layout/UserMenu.tsx:86 +#: src/components/layout/UserMenu.tsx:88 #: src/components/profile/ProfileFollowTab.tsx:144 #: src/components/profile/ProfilePlaylistsTab.tsx:118 #: src/pages/Search.tsx:123 @@ -1622,6 +1480,11 @@ msgstr "Request failed" msgid "Reset failed" msgstr "Reset failed" +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:46 +msgid "email.reset.button" +msgstr "Reset password" + #: src/pages/ResetPassword.tsx:34 msgid "Reset password" msgstr "Reset password" @@ -1636,6 +1499,16 @@ msgstr "Reset to default" msgid "Reset to the suggested title" msgstr "Reset to the suggested title" +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:79 +msgid "email.reset.subject" +msgstr "Reset your {site} password" + +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:30 +msgid "email.reset.title" +msgstr "Reset your password" + #: src/components/chat/PendingItem.tsx:86 #: src/pages/Dump.tsx:319 #: src/pages/DumpEdit.tsx:225 @@ -1693,6 +1566,11 @@ msgstr "Search failed" msgid "Searching…" msgstr "Searching…" +#. js-lingui-explicit-id +#: api/mail/digest.ts:499 +msgid "email.digest.communityPage" +msgstr "See it all on the community page" + #: src/components/player/SeekBar.tsx:50 msgid "Seek" msgstr "Seek" @@ -1719,9 +1597,14 @@ msgstr "Server unreachable" msgid "Set new password" msgstr "Set new password" -#: src/components/layout/UserMenu.tsx:102 -#: src/pages/Settings.tsx:70 -#: src/pages/Settings.tsx:82 +#. js-lingui-explicit-id +#: api/mail/digest.ts:532 +msgid "email.settings" +msgstr "Settings" + +#: src/components/layout/UserMenu.tsx:104 +#: src/pages/Settings.tsx:72 +#: src/pages/Settings.tsx:84 msgid "Settings" msgstr "Settings" @@ -1737,10 +1620,15 @@ msgstr "Single use, valid for 7 days." msgid "slug" msgstr "slug" -#: src/components/editor/TextEditor.tsx:349 +#: src/components/editor/TextEditor.tsx:350 msgid "Some images couldn't be uploaded." msgstr "Some images couldn't be uploaded." +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:39 +msgid "email.reset.body" +msgstr "Someone asked to reset the password of your {site} account. The button below lets you choose a new one. It works once, for {hours, plural, one {# hour} other {# hours}}." + #: src/components/form/FormError.tsx:31 #: src/components/layout/PageError.tsx:29 #: src/contexts/ws/WSProvider.tsx:732 @@ -1748,7 +1636,7 @@ msgstr "Some images couldn't be uploaded." msgid "Something went wrong" msgstr "Something went wrong" -#: src/pages/Settings.tsx:130 +#: src/pages/Settings.tsx:132 msgid "Sounds" msgstr "Sounds" @@ -1756,7 +1644,7 @@ msgstr "Sounds" msgid "Start fresh" msgstr "Start fresh" -#: src/pages/Settings.tsx:101 +#: src/pages/Settings.tsx:103 msgid "Style" msgstr "Style" @@ -1768,6 +1656,11 @@ msgstr "Submit search" msgid "That file is over {limit}." msgstr "That file is over {limit}." +#. js-lingui-explicit-id +#: api/mail/digest.ts:330 +msgid "email.digest.theChat" +msgstr "the chat" + #: src/pages/Notifications.tsx:262 msgid "the chat" msgstr "the chat" @@ -1776,10 +1669,25 @@ msgstr "the chat" msgid "The dump couldn't be removed. Try again." msgstr "The dump couldn't be removed. Try again." -#: src/components/editor/TextEditor.tsx:350 +#: src/components/editor/TextEditor.tsx:351 msgid "The image couldn't be uploaded." msgstr "The image couldn't be uploaded." +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:84 +msgid "email.reset.preheader" +msgstr "The link works once, for {hours, plural, one {# hour} other {# hours}}." + +#. js-lingui-explicit-id +#: api/mail/digest.ts:304 +msgid "email.digest.monthly.title" +msgstr "The month on {site}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:540 +msgid "email.digest.monthly.subject" +msgstr "The month on {site}, {range}" + #: src/hooks/playlist/usePlaylist.ts:322 msgid "The new order couldn't be saved. Try again." msgstr "The new order couldn't be saved. Try again." @@ -1796,7 +1704,7 @@ msgstr "This invite link is missing, expired, or already used." msgid "This is a mirage." msgstr "This is a mirage." -#: src/pages/Community.tsx:104 +#: src/pages/Community.tsx:115 msgid "This month" msgstr "This month" @@ -1808,15 +1716,15 @@ msgstr "This page does not exist." msgid "This reset link is missing or malformed." msgstr "This reset link is missing or malformed." -#: src/pages/Settings.tsx:166 +#: src/pages/Settings.tsx:168 msgid "This site doesn't send email, so no digest goes out." msgstr "This site doesn't send email, so no digest goes out." -#: src/pages/Unsubscribe.tsx:67 +#: src/pages/Unsubscribe.tsx:69 msgid "This unsubscribe link is missing or malformed." msgstr "This unsubscribe link is missing or malformed." -#: src/pages/Community.tsx:103 +#: src/pages/Community.tsx:114 msgid "This week" msgstr "This week" @@ -1840,6 +1748,16 @@ msgstr "Title is required." msgid "Today" msgstr "Today" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:44 +msgid "digest.topMonth" +msgstr "Top this month" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:40 +msgid "digest.topWeek" +msgstr "Top this week" + #. placeholder {0}: i + 1 #: src/components/player/GlobalPlayer.tsx:338 msgid "Track {0}" @@ -1849,15 +1767,25 @@ msgstr "Track {0}" msgid "Try again" msgstr "Try again" -#: src/pages/Unsubscribe.tsx:110 +#. js-lingui-explicit-id +#: shared/digest-messages.ts:32 +msgid "digest.monthly.off" +msgstr "Turn off monthly recaps" + +#: src/pages/Unsubscribe.tsx:112 msgid "Turn off the monthly recap?" msgstr "Turn off the monthly recap?" -#: src/pages/Unsubscribe.tsx:109 +#: src/pages/Unsubscribe.tsx:111 msgid "Turn off the weekly digest?" msgstr "Turn off the weekly digest?" -#: src/pages/Unsubscribe.tsx:115 +#. js-lingui-explicit-id +#: shared/digest-messages.ts:28 +msgid "digest.weekly.off" +msgstr "Turn off weekly digests" + +#: src/pages/Unsubscribe.tsx:117 msgid "Turning off…" msgstr "Turning off…" @@ -1885,14 +1813,19 @@ msgstr "Unfollow playlist" msgid "Unmute" msgstr "Unmute" -#: src/pages/Unsubscribe.tsx:33 +#: src/pages/Unsubscribe.tsx:35 msgid "Unsubscribe" msgstr "Unsubscribe" -#: src/pages/Unsubscribe.tsx:81 +#: src/pages/Unsubscribe.tsx:83 msgid "Unsubscribed" msgstr "Unsubscribed" +#. js-lingui-explicit-id +#: api/mail/digest.ts:237 +msgid "email.digest.upload" +msgstr "upload" + #: src/components/profile/ProfileHeader.tsx:72 msgid "Upload failed" msgstr "Upload failed" @@ -1902,7 +1835,7 @@ msgstr "Upload failed" msgid "Uploading {0}%" msgstr "Uploading {0}%" -#: src/components/editor/TextEditor.tsx:601 +#: src/components/editor/TextEditor.tsx:602 msgid "Uploading image…" msgstr "Uploading image…" @@ -1944,13 +1877,13 @@ msgstr "User" msgid "User management" msgstr "User management" -#: src/components/layout/UserMenu.tsx:61 +#: src/components/layout/UserMenu.tsx:63 msgid "User menu" msgstr "User menu" #: src/components/profile/ProfileManageTab.tsx:61 #: src/components/profile/UsernameField.tsx:51 -#: src/pages/Settings.tsx:85 +#: src/pages/Settings.tsx:87 #: src/pages/UserLogin.tsx:75 #: src/pages/UserRegister.tsx:137 msgid "Username" @@ -1973,6 +1906,16 @@ msgstr "View dump →" msgid "Volume" msgstr "Volume" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:20 +msgid "digest.weekly" +msgstr "Weekly digest" + +#. js-lingui-explicit-id +#: api/mail/welcome.ts:69 +msgid "email.welcome.subject" +msgstr "Welcome to {site}" + #: src/components/dump/create/DumpCreateModal.tsx:712 #: src/pages/DumpEdit.tsx:544 msgid "What makes it worth it?" @@ -2009,11 +1952,11 @@ msgstr "Yesterday" msgid "You can post it anyway." msgstr "You can post it anyway." -#: src/pages/Unsubscribe.tsx:92 +#: src/pages/Unsubscribe.tsx:94 msgid "You won't get the monthly recap any more. You can turn it back on in your settings." msgstr "You won't get the monthly recap any more. You can turn it back on in your settings." -#: src/pages/Unsubscribe.tsx:86 +#: src/pages/Unsubscribe.tsx:88 msgid "You won't get the weekly digest any more. You can turn it back on in your settings." msgstr "You won't get the weekly digest any more. You can turn it back on in your settings." @@ -2021,6 +1964,26 @@ msgstr "You won't get the weekly digest any more. You can turn it back on in you 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." +#. js-lingui-explicit-id +#: api/mail/digest.ts:512 +msgid "email.digest.monthly.reason" +msgstr "You're getting the monthly recap because it's on in your settings." + +#. js-lingui-explicit-id +#: api/mail/digest.ts:517 +msgid "email.digest.weekly.reason" +msgstr "You're getting the weekly digest because it's on in your settings." + +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:70 +msgid "email.reset.reason" +msgstr "You're getting this email because a password reset was requested for this address." + +#. js-lingui-explicit-id +#: api/mail/welcome.ts:59 +msgid "email.welcome.reason" +msgstr "You're getting this email because an account was created on {site} with this address." + #: src/contexts/ws/WSProvider.tsx:913 msgid "You're offline — not sent" msgstr "You're offline — not sent" @@ -2029,6 +1992,11 @@ msgstr "You're offline — not sent" msgid "You've reached the end." msgstr "You've reached the end." +#. js-lingui-explicit-id +#: api/mail/welcome.ts:74 +msgid "email.welcome.preheader" +msgstr "Your account is ready." + #: src/pages/UserLogin.tsx:152 msgid "Your email address" msgstr "Your email address" @@ -2037,6 +2005,21 @@ msgstr "Your email address" msgid "Your password has been changed. You can now log in." msgstr "Your password has been changed. You can now log in." -#: src/pages/Unsubscribe.tsx:54 +#: src/pages/Unsubscribe.tsx:56 msgid "Your settings" msgstr "Your settings" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:545 +msgid "email.digest.weekly.subject" +msgstr "Your week on {site}, {range}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:309 +msgid "email.digest.weekly.title" +msgstr "Your week, {username}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:276 +msgid "email.digest.yours" +msgstr "yours" diff --git a/locales/fr.po b/locales/fr.po index 1bee4efe..a86dddd0 100644 --- a/locales/fr.po +++ b/locales/fr.po @@ -13,377 +13,6 @@ msgstr "" "Last-Translator: \n" "Language-Team: \n" -#. js-lingui-explicit-id -#: api/mail/digest.ts:163 -msgid "email.digest.hl.mentionEveryone" -msgstr "{who} a mentionné tout le monde dans {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:130 -#: src/pages/Community.tsx:49 -msgid "digest.count.upvotes" -msgstr "{n, plural, one {vote} other {votes}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:132 -msgid "email.digest.count.followers" -msgstr "{n, plural, one {nouvel abonné} other {nouveaux abonnés}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:134 -#: src/pages/Community.tsx:50 -msgid "digest.count.comments" -msgstr "{n, plural, one {commentaire} other {commentaires}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:136 -msgid "email.digest.count.mentions" -msgstr "{n, plural, one {mention} other {mentions}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:138 -msgid "email.digest.count.likes" -msgstr "{n, plural, one {j'aime sur vos commentaires} other {j'aime sur vos commentaires}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:140 -msgid "email.digest.count.playlistFollows" -msgstr "{n, plural, one {abonnement à vos collections} other {abonnements à vos collections}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:156 -msgid "email.digest.hl.mentionComment" -msgstr "{who} vous a mentionné dans un commentaire sur {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:159 -msgid "email.digest.hl.mentionIn" -msgstr "{who} vous a mentionné dans {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:161 -msgid "email.digest.hl.mentionPlaylist" -msgstr "{who} vous a mentionné dans la collection {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:165 -msgid "email.digest.hl.comment" -msgstr "{who} a commenté votre reco {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:167 -msgid "email.digest.hl.playlistFollow" -msgstr "{who} a suivi votre collection {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:169 -msgid "email.digest.hl.userFollow" -msgstr "{who} vous suit désormais" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:171 -msgid "email.digest.hl.commentLike" -msgstr "{who} a aimé votre commentaire sur {target}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:175 -msgid "email.digest.by" -msgstr "par @{username}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:177 -msgid "email.digest.addedTo" -msgstr "ajoutée à {playlist}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:178 -msgid "email.digest.upload" -msgstr "fichier" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:181 -#: src/pages/Community.tsx:141 -msgid "digest.invitedByYou" -msgstr "sur votre invitation" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:182 -#: src/pages/Community.tsx:143 -msgid "digest.invitedBy" -msgstr "sur invitation de @{username}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:183 -msgid "email.digest.andMore" -msgstr "et {n} de plus" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:185 -msgid "email.digest.playlistMeta" -msgstr "par @{username} · {n, plural, one {# reco} other {# recos}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:208 -msgid "email.digest.yours" -msgstr "à vous" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:226 -#: src/pages/Settings.tsx:154 -msgid "digest.monthly" -msgstr "Récap mensuel" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:226 -#: src/pages/Settings.tsx:145 -msgid "digest.weekly" -msgstr "Résumé hebdomadaire" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:234 -msgid "email.digest.monthly.title" -msgstr "Le mois sur {site}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:235 -msgid "email.digest.weekly.title" -msgstr "Votre semaine, {username}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:243 -msgid "email.digest.forYou" -msgstr "Pour vous" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:252 -msgid "email.digest.theChat" -msgstr "la tribune" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:267 -msgid "email.digest.seeAll" -msgstr "{n, plural, one {Voir la notification} other {Voir les # notifications}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:276 -msgid "email.digest.network" -msgstr "De ceux que vous suivez" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:282 -msgid "email.digest.more" -msgstr "{n} de plus dans votre fil Suivi" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:294 -#: src/pages/Community.tsx:127 -msgid "digest.topMonth" -msgstr "Les plus votées du mois" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:294 -#: src/pages/Community.tsx:126 -msgid "digest.topWeek" -msgstr "Les plus votées de la semaine" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:310 -#: src/components/layout/UserMenu.tsx:94 -#: src/pages/Community.tsx:73 -#: src/pages/Community.tsx:100 -msgid "digest.community" -msgstr "Communauté" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:317 -#: src/pages/Community.tsx:48 -msgid "digest.stat.dumps" -msgstr "{n, plural, one {reco} other {recos}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:323 -#: src/pages/Community.tsx:53 -msgid "digest.stat.chat" -msgstr "{n, plural, one {message dans la tribune} other {messages dans la tribune}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:332 -#: src/pages/Community.tsx:133 -msgid "digest.newMembers" -msgstr "Nouveaux membres" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:351 -#: src/pages/Community.tsx:154 -msgid "digest.newPlaylists" -msgstr "Nouvelles collections publiques" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:366 -msgid "email.digest.inChat" -msgstr "Dans la tribune" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:368 -msgid "email.digest.chatWeek" -msgstr "{n, plural, one {# message cette semaine} other {# messages cette semaine}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:371 -msgid "email.digest.openChat" -msgstr "Ouvrir la tribune" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:380 -msgid "email.digest.totals" -msgstr "{dumps, plural, one {# reco} other {# recos}}, {upvotes, plural, one {# vote} other {# votes}} et {comments, plural, one {# commentaire} other {# commentaires}}." - -#. js-lingui-explicit-id -#: api/mail/digest.ts:386 -msgid "email.digest.communityPage" -msgstr "Tout voir sur la page de la communauté" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:396 -msgid "email.digest.monthly.reason" -msgstr "Vous recevez ce récap mensuel car il est activé dans vos paramètres." - -#. js-lingui-explicit-id -#: api/mail/digest.ts:397 -msgid "email.digest.weekly.reason" -msgstr "Vous recevez ce résumé hebdomadaire car il est activé dans vos paramètres." - -#. js-lingui-explicit-id -#: api/mail/digest.ts:401 -#: src/pages/Unsubscribe.tsx:118 -msgid "digest.monthly.off" -msgstr "Ne plus recevoir le récap mensuel" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:401 -#: src/pages/Unsubscribe.tsx:117 -msgid "digest.weekly.off" -msgstr "Ne plus recevoir le résumé hebdomadaire" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:406 -msgid "email.settings" -msgstr "Paramètres" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:414 -msgid "email.digest.monthly.subject" -msgstr "Le mois sur {site}, {range}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:418 -msgid "email.digest.weekly.subject" -msgstr "Votre semaine sur {site}, {range}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:441 -msgid "email.digest.pre.network" -msgstr "{n, plural, one {# nouvelle reco de ceux que vous suivez} other {# nouvelles recos de ceux que vous suivez}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:450 -msgid "email.digest.pre.topMonth" -msgstr "{n, plural, one {la reco la plus votée du mois} other {les # recos les plus votées du mois}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:454 -msgid "email.digest.pre.members" -msgstr "{n, plural, one {# nouveau membre} other {# nouveaux membres}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:457 -msgid "email.digest.pre.playlists" -msgstr "{n, plural, one {# nouvelle collection} other {# nouvelles collections}}" - -#. js-lingui-explicit-id -#: api/mail/digest.ts:461 -msgid "email.digest.pre.topWeek" -msgstr "{n, plural, one {la reco la plus votée de la semaine} other {les # recos les plus votées de la semaine}}" - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:29 -msgid "email.reset.title" -msgstr "Réinitialiser votre mot de passe" - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:30 -msgid "email.reset.hi" -msgstr "Bonjour {username}," - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:31 -msgid "email.reset.body" -msgstr "Quelqu'un a demandé à réinitialiser le mot de passe de votre compte {site}. Le bouton ci-dessous vous permet d'en choisir un nouveau. Il ne fonctionne qu'une fois, pendant {hours, plural, one {# heure} other {# heures}}." - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:33 -msgid "email.reset.button" -msgstr "Choisir un nouveau mot de passe" - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:36 -msgid "email.reset.fallback" -msgstr "Si le bouton ne fonctionne pas, collez ce lien dans votre navigateur :" - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:38 -msgid "email.reset.ignore" -msgstr "Si vous n'êtes pas à l'origine de cette demande, ignorez cet e-mail. Votre mot de passe ne change pas." - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:40 -msgid "email.reset.reason" -msgstr "Vous recevez cet e-mail car une réinitialisation de mot de passe a été demandée pour cette adresse." - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:44 -msgid "email.reset.subject" -msgstr "Réinitialisez votre mot de passe {site}" - -#. js-lingui-explicit-id -#: api/mail/password-reset.ts:45 -msgid "email.reset.preheader" -msgstr "Le lien ne fonctionne qu'une fois, pendant {hours, plural, one {# heure} other {# heures}}." - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:32 -msgid "email.welcome.body" -msgstr "# Bienvenue sur {site} !\n" -"\n" -"Bonjour **{username}**,\n" -"\n" -"Votre compte a bien été créé. Bienvenue à bord !" - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:39 -msgid "email.welcome.button" -msgstr "Ouvrir {site}" - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:42 -msgid "email.welcome.digests" -msgstr "Chaque semaine, vous recevrez un résumé de ce qui s'est passé ici, et chaque mois un récap des recos les plus votées. Vous pouvez désactiver l'un ou l'autre dans vos paramètres." - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:44 -msgid "email.welcome.reason" -msgstr "Vous recevez cet e-mail car un compte {site} a été créé avec cette adresse." - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:48 -msgid "email.welcome.subject" -msgstr "Bienvenue sur {site}" - -#. js-lingui-explicit-id -#: api/mail/welcome.ts:49 -msgid "email.welcome.preheader" -msgstr "Votre compte est prêt." - #: src/components/comment/CommentNode.tsx:140 msgid "[deleted]" msgstr "[supprimé]" @@ -426,10 +55,95 @@ msgstr "{0} de plus en ligne : {restNames}" msgid "{0}–{1} characters: letters, numbers, or underscores" msgstr "{0}–{1} caractères : lettres, chiffres ou tirets bas" +#. js-lingui-explicit-id +#: api/mail/digest.ts:488 +msgid "email.digest.totals" +msgstr "{dumps, plural, one {# reco} other {# recos}}, {upvotes, plural, one {# vote} other {# votes}} et {comments, plural, one {# commentaire} other {# commentaires}}." + #: src/pages/Search.tsx:124 msgid "{label} ({count})" msgstr "{label} ({count})" +#. js-lingui-explicit-id +#: api/mail/digest.ts:470 +msgid "email.digest.chatWeek" +msgstr "{n, plural, one {# message cette semaine} other {# messages cette semaine}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:570 +msgid "email.digest.pre.network" +msgstr "{n, plural, one {# nouvelle reco de ceux que vous suivez} other {# nouvelles recos de ceux que vous suivez}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:595 +msgid "email.digest.pre.members" +msgstr "{n, plural, one {# nouveau membre} other {# nouveaux membres}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:604 +msgid "email.digest.pre.playlists" +msgstr "{n, plural, one {# nouvelle collection} other {# nouvelles collections}}" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:68 +msgid "digest.stat.chat" +msgstr "{n, plural, one {message dans la tribune} other {messages dans la tribune}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:147 +msgid "email.digest.count.likes" +msgstr "{n, plural, one {j'aime sur vos commentaires} other {j'aime sur vos commentaires}}" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:76 +msgid "digest.count.comments" +msgstr "{n, plural, one {commentaire} other {commentaires}}" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:64 +msgid "digest.stat.dumps" +msgstr "{n, plural, one {reco} other {recos}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:141 +msgid "email.digest.count.mentions" +msgstr "{n, plural, one {mention} other {mentions}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:133 +msgid "email.digest.count.followers" +msgstr "{n, plural, one {nouvel abonné} other {nouveaux abonnés}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:153 +msgid "email.digest.count.playlistFollows" +msgstr "{n, plural, one {abonnement à vos collections} other {abonnements à vos collections}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:345 +msgid "email.digest.seeAll" +msgstr "{n, plural, one {Voir la notification} other {Voir les # notifications}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:585 +msgid "email.digest.pre.topMonth" +msgstr "{n, plural, one {la reco la plus votée du mois} other {les # recos les plus votées du mois}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:614 +msgid "email.digest.pre.topWeek" +msgstr "{n, plural, one {la reco la plus votée de la semaine} other {les # recos les plus votées de la semaine}}" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:72 +msgid "digest.count.upvotes" +msgstr "{n, plural, one {vote} other {votes}}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:372 +msgid "email.digest.more" +msgstr "{n} de plus dans votre fil Suivi" + #: src/pages/Notifications.tsx:508 msgid "{totalUnread, plural, one {# new} other {# new}}" msgstr "{totalUnread, plural, one {# nouvelle} other {# nouvelles}}" @@ -442,6 +156,55 @@ msgstr "{unseenCount} nouveaux messages" msgid "{visibleCount, plural, one {# comment} other {# comments}}" msgstr "{visibleCount, plural, one {# commentaire} other {# commentaires}}" +#. js-lingui-explicit-id +#: api/mail/digest.ts:198 +msgid "email.digest.hl.comment" +msgstr "{who} a commenté votre reco {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:204 +msgid "email.digest.hl.playlistFollow" +msgstr "{who} a suivi votre collection {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:216 +msgid "email.digest.hl.commentLike" +msgstr "{who} a aimé votre commentaire sur {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:192 +msgid "email.digest.hl.mentionEveryone" +msgstr "{who} a mentionné tout le monde dans {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:180 +msgid "email.digest.hl.mentionIn" +msgstr "{who} vous a mentionné dans {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:173 +msgid "email.digest.hl.mentionComment" +msgstr "{who} vous a mentionné dans un commentaire sur {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:186 +msgid "email.digest.hl.mentionPlaylist" +msgstr "{who} vous a mentionné dans la collection {target}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:210 +msgid "email.digest.hl.userFollow" +msgstr "{who} vous suit désormais" + +#. js-lingui-explicit-id +#: api/mail/welcome.ts:32 +msgid "email.welcome.body" +msgstr "# Bienvenue sur {site} !\n" +"\n" +"Bonjour **{username}**,\n" +"\n" +"Votre compte a bien été créé. Bienvenue à bord !" + #: src/components/dump/create/DumpCreateModal.tsx:742 #: src/pages/PlaylistDetail.tsx:80 #: src/pages/UserPublicProfile.tsx:123 @@ -533,7 +296,7 @@ msgstr "Il faut un lien" msgid "a post" msgstr "une publication" -#: src/pages/Settings.tsx:83 +#: src/pages/Settings.tsx:85 msgid "Account" msgstr "Compte" @@ -559,6 +322,11 @@ msgstr "Ajouter une image" msgid "Add to playlist" msgstr "Ajouter à la collection" +#. js-lingui-explicit-id +#: api/mail/digest.ts:231 +msgid "email.digest.addedTo" +msgstr "ajoutée à {playlist}" + #: src/components/profile/RoleSwitcher.tsx:24 msgid "Admin" msgstr "Administrateur" @@ -582,7 +350,12 @@ msgstr "Vous avez déjà un compte ? <0>Se connecter" msgid "An unexpected error occurred." msgstr "Une erreur inattendue s'est produite." -#: src/pages/Settings.tsx:99 +#. js-lingui-explicit-id +#: api/mail/digest.ts:243 +msgid "email.digest.andMore" +msgstr "et {n} de plus" + +#: src/pages/Settings.tsx:101 msgid "Appearance" msgstr "Apparence" @@ -597,7 +370,7 @@ msgstr "Au moins {0} caractères" msgid "At most {maxLength} characters." msgstr "{maxLength} caractères au maximum." -#: src/pages/Settings.tsx:45 +#: src/pages/Settings.tsx:46 msgid "Auto" msgstr "Auto" @@ -606,6 +379,16 @@ msgstr "Auto" msgid "Back to login" msgstr "Retour à la connexion" +#. js-lingui-explicit-id +#: api/mail/digest.ts:225 +msgid "email.digest.by" +msgstr "par @{username}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:249 +msgid "email.digest.playlistMeta" +msgstr "par @{username} · {n, plural, one {# reco} other {# recos}}" + #: src/contexts/ws/WSProvider.tsx:395 #: src/contexts/ws/WSProvider.tsx:764 msgid "Can't connect to the live updates server. Upvotes and notifications may not sync until it reconnects." @@ -661,7 +444,7 @@ msgstr "Changer l'image" msgid "Change password" msgstr "Changer le mot de passe" -#: src/pages/Settings.tsx:94 +#: src/pages/Settings.tsx:96 msgid "Change password…" msgstr "Changer le mot de passe…" @@ -710,10 +493,15 @@ msgstr "Fermer sans publier ? Le fichier joint sera perdu — ce que vous avez msgid "Collapse player" msgstr "Réduire le lecteur" -#: src/pages/Settings.tsx:108 +#: src/pages/Settings.tsx:110 msgid "Color scheme" msgstr "Thème de couleur" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:36 +msgid "digest.community" +msgstr "Communauté" + #: src/components/profile/ChangePasswordModal.tsx:108 #: src/pages/ResetPassword.tsx:131 msgid "Confirm new password" @@ -760,7 +548,7 @@ msgstr "Impossible de charger un aperçu pour ce lien — vérifiez-le, ou publi msgid "Couldn't load the chat." msgstr "Impossible de charger le chat." -#: src/pages/Unsubscribe.tsx:114 +#: src/pages/Unsubscribe.tsx:116 msgid "Couldn't unsubscribe" msgstr "Désabonnement impossible" @@ -788,11 +576,11 @@ msgstr "Création…" msgid "Current password" msgstr "Mot de passe actuel" -#: src/pages/Settings.tsx:47 +#: src/pages/Settings.tsx:48 msgid "Dark" msgstr "Sombre" -#: src/pages/Settings.tsx:119 +#: src/pages/Settings.tsx:121 msgid "Default tab" msgstr "Onglet par défaut" @@ -984,7 +772,7 @@ msgstr "Modification" msgid "Editing {0}" msgstr "Édition de {0}" -#: src/pages/Settings.tsx:143 +#: src/pages/Settings.tsx:145 msgid "Email" msgstr "E-mail" @@ -1056,7 +844,7 @@ msgstr "Impossible de mettre à jour l'avatar" msgid "Failed to update role" msgstr "Erreur lors de la mise à jour du rôle" -#: src/pages/Settings.tsx:117 +#: src/pages/Settings.tsx:119 msgid "Feeds" msgstr "Flux" @@ -1091,7 +879,7 @@ msgstr "Suivez des utilisateurs pour voir leurs recos ici." #: src/components/feed/FeedTabBar.tsx:43 #: src/components/profile/ProfileFollowTab.tsx:140 -#: src/pages/Settings.tsx:54 +#: src/pages/Settings.tsx:55 #: src/pages/UserPublicProfile.tsx:161 msgid "Followed" msgstr "Suivi" @@ -1101,6 +889,11 @@ msgstr "Suivi" msgid "Following" msgstr "Abonné" +#. js-lingui-explicit-id +#: api/mail/digest.ts:321 +msgid "email.digest.forYou" +msgstr "Pour vous" + #: src/pages/UserLogin.tsx:97 msgid "Forgot password?" msgstr "Mot de passe oublié ?" @@ -1109,6 +902,11 @@ msgstr "Mot de passe oublié ?" msgid "From people" msgstr "De personnes" +#. js-lingui-explicit-id +#: api/mail/digest.ts:361 +msgid "email.digest.network" +msgstr "De ceux que vous suivez" + #: src/components/feed/FollowedFeed.tsx:133 msgid "From playlists" msgstr "De collections" @@ -1125,8 +923,13 @@ msgstr "Accueil" msgid "Go to login" msgstr "Aller à la connexion" +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:33 +msgid "email.reset.hi" +msgstr "Bonjour {username}," + #: src/components/feed/FeedTabBar.tsx:39 -#: src/pages/Settings.tsx:51 +#: src/pages/Settings.tsx:52 msgid "Hot" msgstr "Tendances" @@ -1134,6 +937,16 @@ msgstr "Tendances" msgid "If that address is registered you'll receive a reset link shortly." msgstr "Si cette adresse est enregistrée, vous recevrez un lien de réinitialisation sous peu." +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:51 +msgid "email.reset.fallback" +msgstr "Si le bouton ne fonctionne pas, collez ce lien dans votre navigateur :" + +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:61 +msgid "email.reset.ignore" +msgstr "Si vous n'êtes pas à l'origine de cette demande, ignorez cet e-mail. Votre mot de passe ne change pas." + #: src/utils/chat/message.ts:43 msgid "image" msgstr "image" @@ -1142,8 +955,13 @@ msgstr "image" msgid "In collections" msgstr "Dans les collections" -#: src/components/editor/TextEditor.tsx:579 -#: src/components/editor/TextEditor.tsx:581 +#. js-lingui-explicit-id +#: api/mail/digest.ts:466 +msgid "email.digest.inChat" +msgstr "Dans la tribune" + +#: src/components/editor/TextEditor.tsx:580 +#: src/components/editor/TextEditor.tsx:582 msgid "Insert emoji" msgstr "Insérer un emoji" @@ -1152,7 +970,7 @@ msgid "Invalid invite" msgstr "Invitation invalide" #: src/pages/ResetPassword.tsx:64 -#: src/pages/Unsubscribe.tsx:64 +#: src/pages/Unsubscribe.tsx:66 msgid "Invalid link" msgstr "Lien invalide" @@ -1165,13 +983,23 @@ msgstr "Lien d'invitation" msgid "invited by" msgstr "invité par" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:56 +msgid "digest.invitedBy" +msgstr "sur invitation de @{username}" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:60 +msgid "digest.invitedByYou" +msgstr "sur votre invitation" + #: src/components/profile/ProfileInviteesTab.tsx:77 #: src/pages/UserPublicProfile.tsx:162 msgid "Invitees" msgstr "Invités" #: src/components/feed/FeedTabBar.tsx:41 -#: src/pages/Settings.tsx:53 +#: src/pages/Settings.tsx:54 msgid "Journal" msgstr "Journal" @@ -1183,7 +1011,7 @@ msgstr "Continuer l'édition" msgid "Letters, numbers and underscores only" msgstr "Lettres, chiffres et tirets bas seulement" -#: src/pages/Settings.tsx:46 +#: src/pages/Settings.tsx:47 msgid "Light" msgstr "Clair" @@ -1262,7 +1090,7 @@ msgstr "Se connecter pour aimer" msgid "Log in to vote" msgstr "Se connecter pour voter" -#: src/components/layout/UserMenu.tsx:124 +#: src/components/layout/UserMenu.tsx:126 #: src/pages/UserPublicProfile.tsx:131 msgid "Log out" msgstr "Se déconnecter" @@ -1279,7 +1107,7 @@ msgstr "Connexion échouée" msgid "Lowercase letters, numbers and single hyphens only" msgstr "Minuscules, chiffres et tirets simples seulement" -#: src/components/layout/UserMenu.tsx:111 +#: src/components/layout/UserMenu.tsx:113 #: src/pages/Manage.tsx:24 #: src/pages/Manage.tsx:29 #: src/pages/UserPublicProfile.tsx:164 @@ -1294,6 +1122,11 @@ msgstr "Max {limit}" msgid "Moderator" msgstr "Modérateur" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:24 +msgid "digest.monthly" +msgstr "Récap mensuel" + #: src/components/player/MediaPlayer.tsx:346 msgid "Mute" msgstr "Couper le son" @@ -1305,7 +1138,7 @@ msgstr "Nom" #: src/components/chat/ChatModal.tsx:692 #: src/components/feed/FeedTabBar.tsx:40 -#: src/pages/Settings.tsx:52 +#: src/pages/Settings.tsx:53 msgid "New" msgstr "Nouveau" @@ -1316,6 +1149,11 @@ msgstr "Nouveau" msgid "New dump" msgstr "Nouvelle reco" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:48 +msgid "digest.newMembers" +msgstr "Nouveaux membres" + #: src/components/profile/ChangePasswordModal.tsx:94 #: src/pages/ResetPassword.tsx:116 msgid "New password" @@ -1326,6 +1164,11 @@ msgstr "Nouveau mot de passe" msgid "New playlist" msgstr "Nouvelle collection" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:52 +msgid "digest.newPlaylists" +msgstr "Nouvelles collections publiques" + #: src/components/dump/create/DumpCreateModal.tsx:764 msgid "Next →" msgstr "Suivant →" @@ -1388,11 +1231,11 @@ msgstr "Aucun utilisateur ne correspond à « {q} »." msgid "Not following anyone yet." msgstr "Aucun abonnement pour le moment." -#: src/pages/Community.tsx:116 +#: src/pages/Community.tsx:127 msgid "Nothing happened this month." msgstr "Rien de neuf ce mois-ci." -#: src/pages/Community.tsx:115 +#: src/pages/Community.tsx:126 msgid "Nothing happened this week." msgstr "Rien de neuf cette semaine." @@ -1405,7 +1248,7 @@ msgstr "Rien ici pour l'instant." #: src/components/layout/NotificationBell.tsx:57 #: src/pages/Notifications.tsx:387 #: src/pages/Notifications.tsx:505 -#: src/pages/Settings.tsx:128 +#: src/pages/Settings.tsx:130 msgid "Notifications" msgstr "Notifications" @@ -1413,15 +1256,20 @@ msgstr "Notifications" msgid "Notifications ({unreadNotificationCount} unread)" msgstr "Notifications ({unreadNotificationCount} non lues)" -#: src/pages/Settings.tsx:59 +#: src/pages/Settings.tsx:60 msgid "Off" msgstr "Désactivés" -#: src/pages/Settings.tsx:58 +#: src/pages/Settings.tsx:59 msgid "On" msgstr "Activés" -#: src/components/editor/TextEditor.tsx:391 +#. js-lingui-explicit-id +#: api/mail/welcome.ts:50 +msgid "email.welcome.digests" +msgstr "Chaque semaine, vous recevrez un résumé de ce qui s'est passé ici, et chaque mois un récap des recos les plus votées. Vous pouvez désactiver l'un ou l'autre dans vos paramètres." + +#: src/components/editor/TextEditor.tsx:392 msgid "Only images can be dropped here." msgstr "Seules les images peuvent être déposées ici." @@ -1429,6 +1277,11 @@ msgstr "Seules les images peuvent être déposées ici." msgid "Only its poster or a moderator can edit this dump." msgstr "Seuls son auteur et les modérateurs peuvent modifier ce dump." +#. js-lingui-explicit-id +#: api/mail/welcome.ts:41 +msgid "email.welcome.button" +msgstr "Ouvrir {site}" + #. placeholder {0}: richContent.siteName #: src/components/dump/RichContentCard.tsx:122 msgid "Open on {0}" @@ -1438,6 +1291,11 @@ msgstr "Ouvrir sur {0}" msgid "Open source" msgstr "Ouvrir la source" +#. js-lingui-explicit-id +#: api/mail/digest.ts:479 +msgid "email.digest.openChat" +msgstr "Ouvrir la tribune" + #: src/components/form/FileDropZone.tsx:163 msgid "or <0>browse files" msgstr "ou <0>parcourir les fichiers" @@ -1450,7 +1308,7 @@ msgstr "Aperçu" msgid "Page not found" msgstr "Page introuvable" -#: src/pages/Settings.tsx:88 +#: src/pages/Settings.tsx:90 #: src/pages/UserLogin.tsx:82 msgid "Password" msgstr "Mot de passe" @@ -1498,7 +1356,7 @@ msgstr "Lecture" #: src/components/dump/create/StepIndicator.tsx:21 #: src/components/layout/AppHeader.tsx:172 -#: src/components/layout/UserMenu.tsx:86 +#: src/components/layout/UserMenu.tsx:88 #: src/components/profile/ProfileFollowTab.tsx:144 #: src/components/profile/ProfilePlaylistsTab.tsx:118 #: src/pages/Search.tsx:123 @@ -1622,6 +1480,11 @@ msgstr "Échec de la demande" msgid "Reset failed" msgstr "Échec de la réinitialisation" +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:46 +msgid "email.reset.button" +msgstr "Choisir un nouveau mot de passe" + #: src/pages/ResetPassword.tsx:34 msgid "Reset password" msgstr "Réinitialiser le mot de passe" @@ -1636,6 +1499,16 @@ msgstr "Réinitialiser par défaut" msgid "Reset to the suggested title" msgstr "Rétablir le titre suggéré" +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:79 +msgid "email.reset.subject" +msgstr "Réinitialisez votre mot de passe {site}" + +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:30 +msgid "email.reset.title" +msgstr "Réinitialiser votre mot de passe" + #: src/components/chat/PendingItem.tsx:86 #: src/pages/Dump.tsx:319 #: src/pages/DumpEdit.tsx:225 @@ -1693,6 +1566,11 @@ msgstr "Recherche échouée" msgid "Searching…" msgstr "Recherche…" +#. js-lingui-explicit-id +#: api/mail/digest.ts:499 +msgid "email.digest.communityPage" +msgstr "Tout voir sur la page de la communauté" + #: src/components/player/SeekBar.tsx:50 msgid "Seek" msgstr "Position" @@ -1719,9 +1597,14 @@ msgstr "Serveur inaccessible" msgid "Set new password" msgstr "Définir un nouveau mot de passe" -#: src/components/layout/UserMenu.tsx:102 -#: src/pages/Settings.tsx:70 -#: src/pages/Settings.tsx:82 +#. js-lingui-explicit-id +#: api/mail/digest.ts:532 +msgid "email.settings" +msgstr "Paramètres" + +#: src/components/layout/UserMenu.tsx:104 +#: src/pages/Settings.tsx:72 +#: src/pages/Settings.tsx:84 msgid "Settings" msgstr "Paramètres" @@ -1737,10 +1620,15 @@ msgstr "Usage unique, valable 7 jours." msgid "slug" msgstr "identifiant" -#: src/components/editor/TextEditor.tsx:349 +#: src/components/editor/TextEditor.tsx:350 msgid "Some images couldn't be uploaded." msgstr "Certaines images n'ont pas pu être envoyées." +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:39 +msgid "email.reset.body" +msgstr "Quelqu'un a demandé à réinitialiser le mot de passe de votre compte {site}. Le bouton ci-dessous vous permet d'en choisir un nouveau. Il ne fonctionne qu'une fois, pendant {hours, plural, one {# heure} other {# heures}}." + #: src/components/form/FormError.tsx:31 #: src/components/layout/PageError.tsx:29 #: src/contexts/ws/WSProvider.tsx:732 @@ -1748,7 +1636,7 @@ msgstr "Certaines images n'ont pas pu être envoyées." msgid "Something went wrong" msgstr "Une erreur est survenue" -#: src/pages/Settings.tsx:130 +#: src/pages/Settings.tsx:132 msgid "Sounds" msgstr "Sons" @@ -1756,7 +1644,7 @@ msgstr "Sons" msgid "Start fresh" msgstr "Repartir de zéro" -#: src/pages/Settings.tsx:101 +#: src/pages/Settings.tsx:103 msgid "Style" msgstr "Style" @@ -1768,6 +1656,11 @@ msgstr "Lancer la recherche" msgid "That file is over {limit}." msgstr "Ce fichier dépasse {limit}." +#. js-lingui-explicit-id +#: api/mail/digest.ts:330 +msgid "email.digest.theChat" +msgstr "la tribune" + #: src/pages/Notifications.tsx:262 msgid "the chat" msgstr "la tribune" @@ -1776,10 +1669,25 @@ msgstr "la tribune" msgid "The dump couldn't be removed. Try again." msgstr "Le dump n'a pas pu être retiré. Réessayez." -#: src/components/editor/TextEditor.tsx:350 +#: src/components/editor/TextEditor.tsx:351 msgid "The image couldn't be uploaded." msgstr "L'image n'a pas pu être envoyée." +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:84 +msgid "email.reset.preheader" +msgstr "Le lien ne fonctionne qu'une fois, pendant {hours, plural, one {# heure} other {# heures}}." + +#. js-lingui-explicit-id +#: api/mail/digest.ts:304 +msgid "email.digest.monthly.title" +msgstr "Le mois sur {site}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:540 +msgid "email.digest.monthly.subject" +msgstr "Le mois sur {site}, {range}" + #: src/hooks/playlist/usePlaylist.ts:322 msgid "The new order couldn't be saved. Try again." msgstr "Le nouvel ordre n'a pas pu être enregistré. Réessayez." @@ -1796,7 +1704,7 @@ msgstr "Ce lien d'invitation est manquant, expiré ou déjà utilisé." msgid "This is a mirage." msgstr "C'est un mirage." -#: src/pages/Community.tsx:104 +#: src/pages/Community.tsx:115 msgid "This month" msgstr "Ce mois-ci" @@ -1808,15 +1716,15 @@ msgstr "Rien à voir, circulez." msgid "This reset link is missing or malformed." msgstr "Ce lien de réinitialisation est absent ou malformé." -#: src/pages/Settings.tsx:166 +#: src/pages/Settings.tsx:168 msgid "This site doesn't send email, so no digest goes out." msgstr "Ce site n'envoie pas d'e-mails, aucun résumé ne part donc." -#: src/pages/Unsubscribe.tsx:67 +#: src/pages/Unsubscribe.tsx:69 msgid "This unsubscribe link is missing or malformed." msgstr "Ce lien de désabonnement est absent ou mal formé." -#: src/pages/Community.tsx:103 +#: src/pages/Community.tsx:114 msgid "This week" msgstr "Cette semaine" @@ -1840,6 +1748,16 @@ msgstr "Un titre est requis." msgid "Today" msgstr "Aujourd'hui" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:44 +msgid "digest.topMonth" +msgstr "Les plus votées du mois" + +#. js-lingui-explicit-id +#: shared/digest-messages.ts:40 +msgid "digest.topWeek" +msgstr "Les plus votées de la semaine" + #. placeholder {0}: i + 1 #: src/components/player/GlobalPlayer.tsx:338 msgid "Track {0}" @@ -1849,15 +1767,25 @@ msgstr "Piste {0}" msgid "Try again" msgstr "Réessayer" -#: src/pages/Unsubscribe.tsx:110 +#. js-lingui-explicit-id +#: shared/digest-messages.ts:32 +msgid "digest.monthly.off" +msgstr "Ne plus recevoir le récap mensuel" + +#: src/pages/Unsubscribe.tsx:112 msgid "Turn off the monthly recap?" msgstr "Ne plus recevoir le récap mensuel ?" -#: src/pages/Unsubscribe.tsx:109 +#: src/pages/Unsubscribe.tsx:111 msgid "Turn off the weekly digest?" msgstr "Ne plus recevoir le résumé hebdomadaire ?" -#: src/pages/Unsubscribe.tsx:115 +#. js-lingui-explicit-id +#: shared/digest-messages.ts:28 +msgid "digest.weekly.off" +msgstr "Ne plus recevoir le résumé hebdomadaire" + +#: src/pages/Unsubscribe.tsx:117 msgid "Turning off…" msgstr "Désactivation…" @@ -1885,14 +1813,19 @@ msgstr "Ne plus suivre la collection" msgid "Unmute" msgstr "Rétablir le son" -#: src/pages/Unsubscribe.tsx:33 +#: src/pages/Unsubscribe.tsx:35 msgid "Unsubscribe" msgstr "Se désabonner" -#: src/pages/Unsubscribe.tsx:81 +#: src/pages/Unsubscribe.tsx:83 msgid "Unsubscribed" msgstr "Désabonné" +#. js-lingui-explicit-id +#: api/mail/digest.ts:237 +msgid "email.digest.upload" +msgstr "fichier" + #: src/components/profile/ProfileHeader.tsx:72 msgid "Upload failed" msgstr "Envoi échoué" @@ -1902,7 +1835,7 @@ msgstr "Envoi échoué" msgid "Uploading {0}%" msgstr "Envoi {0} %" -#: src/components/editor/TextEditor.tsx:601 +#: src/components/editor/TextEditor.tsx:602 msgid "Uploading image…" msgstr "Envoi de l'image…" @@ -1944,13 +1877,13 @@ msgstr "Utilisateur" msgid "User management" msgstr "Gestion utilisateur" -#: src/components/layout/UserMenu.tsx:61 +#: src/components/layout/UserMenu.tsx:63 msgid "User menu" msgstr "Menu utilisateur" #: src/components/profile/ProfileManageTab.tsx:61 #: src/components/profile/UsernameField.tsx:51 -#: src/pages/Settings.tsx:85 +#: src/pages/Settings.tsx:87 #: src/pages/UserLogin.tsx:75 #: src/pages/UserRegister.tsx:137 msgid "Username" @@ -1973,6 +1906,16 @@ msgstr "Voir la reco →" msgid "Volume" msgstr "Volume" +#. js-lingui-explicit-id +#: shared/digest-messages.ts:20 +msgid "digest.weekly" +msgstr "Résumé hebdomadaire" + +#. js-lingui-explicit-id +#: api/mail/welcome.ts:69 +msgid "email.welcome.subject" +msgstr "Bienvenue sur {site}" + #: src/components/dump/create/DumpCreateModal.tsx:712 #: src/pages/DumpEdit.tsx:544 msgid "What makes it worth it?" @@ -2009,11 +1952,11 @@ msgstr "Hier" msgid "You can post it anyway." msgstr "Vous pouvez la publier quand même." -#: src/pages/Unsubscribe.tsx:92 +#: src/pages/Unsubscribe.tsx:94 msgid "You won't get the monthly recap any more. You can turn it back on in your settings." msgstr "Vous ne recevrez plus le récap mensuel. Vous pouvez le réactiver dans vos paramètres." -#: src/pages/Unsubscribe.tsx:86 +#: src/pages/Unsubscribe.tsx:88 msgid "You won't get the weekly digest any more. You can turn it back on in your settings." msgstr "Vous ne recevrez plus le résumé hebdomadaire. Vous pouvez le réactiver dans vos paramètres." @@ -2021,6 +1964,26 @@ msgstr "Vous ne recevrez plus le résumé hebdomadaire. Vous pouvez le réactive 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." +#. js-lingui-explicit-id +#: api/mail/digest.ts:512 +msgid "email.digest.monthly.reason" +msgstr "Vous recevez ce récap mensuel car il est activé dans vos paramètres." + +#. js-lingui-explicit-id +#: api/mail/digest.ts:517 +msgid "email.digest.weekly.reason" +msgstr "Vous recevez ce résumé hebdomadaire car il est activé dans vos paramètres." + +#. js-lingui-explicit-id +#: api/mail/password-reset.ts:70 +msgid "email.reset.reason" +msgstr "Vous recevez cet e-mail car une réinitialisation de mot de passe a été demandée pour cette adresse." + +#. js-lingui-explicit-id +#: api/mail/welcome.ts:59 +msgid "email.welcome.reason" +msgstr "Vous recevez cet e-mail car un compte {site} a été créé avec cette adresse." + #: src/contexts/ws/WSProvider.tsx:913 msgid "You're offline — not sent" msgstr "Hors ligne — message non envoyé" @@ -2029,6 +1992,11 @@ msgstr "Hors ligne — message non envoyé" msgid "You've reached the end." msgstr "Vous avez tout lu, tout vu, tout bu." +#. js-lingui-explicit-id +#: api/mail/welcome.ts:74 +msgid "email.welcome.preheader" +msgstr "Votre compte est prêt." + #: src/pages/UserLogin.tsx:152 msgid "Your email address" msgstr "Votre adresse e-mail" @@ -2037,6 +2005,21 @@ msgstr "Votre adresse e-mail" msgid "Your password has been changed. You can now log in." msgstr "Votre mot de passe a été modifié. Vous pouvez maintenant vous connecter." -#: src/pages/Unsubscribe.tsx:54 +#: src/pages/Unsubscribe.tsx:56 msgid "Your settings" msgstr "Vos paramètres" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:545 +msgid "email.digest.weekly.subject" +msgstr "Votre semaine sur {site}, {range}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:309 +msgid "email.digest.weekly.title" +msgstr "Votre semaine, {username}" + +#. js-lingui-explicit-id +#: api/mail/digest.ts:276 +msgid "email.digest.yours" +msgstr "à vous" diff --git a/shared/digest-messages.ts b/shared/digest-messages.ts new file mode 100644 index 00000000..d2ecd8e0 --- /dev/null +++ b/shared/digest-messages.ts @@ -0,0 +1,80 @@ +/** + * Words the digest emails share with the pages that show or govern them: the + * `/community` page shows the digests' figures and sections, Settings and the + * unsubscribe page name the digests, the avatar menu links the community + * page. `api/mail/digest.ts` and those pages translate them from here, so an + * email and a page always say the same. + * + * Each is a Lingui message descriptor with an explicit id, since the server + * runs no macro; the `i18n` comment has `lingui extract` read its English into + * the catalogs. Pass one to `i18n._`, with its values: on the client, the + * `i18n` of `useLingui()`. + * + * @module + */ + +import type { MessageDescriptor } from "@lingui/core"; + +/** The shared messages, by name. */ +export const DIGEST_MESSAGES = { + weekly: /*i18n*/ { + id: "digest.weekly", + message: "Weekly digest", + }, + monthly: /*i18n*/ { + id: "digest.monthly", + message: "Monthly recap", + }, + weeklyOff: /*i18n*/ { + id: "digest.weekly.off", + message: "Turn off weekly digests", + }, + monthlyOff: /*i18n*/ { + id: "digest.monthly.off", + message: "Turn off monthly recaps", + }, + community: /*i18n*/ { + id: "digest.community", + message: "Community", + }, + topWeek: /*i18n*/ { + id: "digest.topWeek", + message: "Top this week", + }, + topMonth: /*i18n*/ { + id: "digest.topMonth", + message: "Top this month", + }, + newMembers: /*i18n*/ { + id: "digest.newMembers", + message: "New members", + }, + newPlaylists: /*i18n*/ { + id: "digest.newPlaylists", + message: "New public playlists", + }, + invitedBy: /*i18n*/ { + id: "digest.invitedBy", + message: "invited by @{username}", + }, + invitedByYou: /*i18n*/ { + id: "digest.invitedByYou", + message: "invited by you", + }, + statDumps: /*i18n*/ { + id: "digest.stat.dumps", + message: "{n, plural, one {dump} other {dumps}}", + }, + statChat: /*i18n*/ { + id: "digest.stat.chat", + message: "{n, plural, one {chat message} other {chat messages}}", + }, + countUpvotes: /*i18n*/ { + id: "digest.count.upvotes", + message: "{n, plural, one {upvote} other {upvotes}}", + }, + countComments: /*i18n*/ { + id: "digest.count.comments", + message: "{n, plural, one {comment} other {comments}}", + }, +} as const satisfies Record; diff --git a/src/components/layout/UserMenu.tsx b/src/components/layout/UserMenu.tsx index ddce6d6a..a5839e17 100644 --- a/src/components/layout/UserMenu.tsx +++ b/src/components/layout/UserMenu.tsx @@ -10,7 +10,8 @@ import { useEffect, useRef, useState } from "react"; import { Link } from "react-router"; import { t } from "@lingui/core/macro"; import { Trans } from "@lingui/react/macro"; -import { Trans as Message } from "@lingui/react"; +import { useLingui } from "@lingui/react"; +import { DIGEST_MESSAGES } from "../../../shared/digest-messages.ts"; import { Avatar } from "../shared/Avatar.tsx"; import type { SelfUser } from "../../../shared/user.ts"; import { can } from "../../utils/auth/permissions.ts"; @@ -29,6 +30,7 @@ export interface UserMenuProps { * Escape closes it. */ export function UserMenu({ user }: UserMenuProps): React.JSX.Element { + const { i18n } = useLingui(); const { logout } = useAuth(); const [open, setOpen] = useState(false); const ref = useRef(null); @@ -91,7 +93,7 @@ export function UserMenu({ user }: UserMenuProps): React.JSX.Element { role="menuitem" onClick={() => setOpen(false)} > - + {i18n._(DIGEST_MESSAGES.community)} ( communityPath(), @@ -97,7 +108,7 @@ export function Community(): React.JSX.Element { return ( - } /> + This week }, @@ -122,15 +133,15 @@ export function Community(): React.JSX.Element { {data.top.length > 0 && ( - : } + label={i18n._( + weekly ? DIGEST_MESSAGES.topWeek : DIGEST_MESSAGES.topMonth, + )} > )} {data.members.length > 0 && ( - }> +
    {data.members.map((m) => ( - : ( - - ))} + ? i18n._(DIGEST_MESSAGES.invitedByYou) + : i18n._({ + ...DIGEST_MESSAGES.invitedBy, + values: { username: m.invitedByUsername }, + }))} /> ))}
)} {data.playlists.length > 0 && ( - }> + )} diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index d2c054b6..23c5fb77 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -10,7 +10,8 @@ import { t } from "@lingui/core/macro"; import { Trans } from "@lingui/react/macro"; // A label shared with the emails is named by its id, its words being in // locales/ only; the macro's Trans takes the English in place. -import { Trans as Message } from "@lingui/react"; +import { useLingui } from "@lingui/react"; +import { DIGEST_MESSAGES } from "../../shared/digest-messages.ts"; import type { ColorScheme, StyleName } from "../../shared/theme.ts"; import type { FeedTab } from "../../shared/paths.ts"; import { useTheme } from "../hooks/theme/useTheme.ts"; @@ -67,6 +68,7 @@ const ON_OFF_OPTIONS: SegmentedOption[] = [ * default feed tab and sounds, for now, to this browser. */ export function Settings(): React.JSX.Element { + const { i18n } = useLingui(); useDocumentTitle(t`Settings`); const { user } = useRequiredAuth(); const { style, colorScheme, setStyle, setColorScheme } = useTheme(); @@ -142,7 +144,7 @@ export function Settings(): React.JSX.Element { Email}>
- }> + {})} /> - }> + Turning off…}> - {weekly - ? - : } + {i18n._( + weekly ? DIGEST_MESSAGES.weeklyOff : DIGEST_MESSAGES.monthlyOff, + )}