diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx
index 3e6428287d..de484322fb 100644
--- a/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx
+++ b/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx
@@ -12,7 +12,7 @@ import {
} from 'mastodon/actions/statuses';
import type { IconProp } from 'mastodon/components/icon';
import { Icon } from 'mastodon/components/icon';
-import Status from 'mastodon/containers/status_container';
+import { StatusQuoteManager } from 'mastodon/components/status_quoted';
import { getStatusHidden } from 'mastodon/selectors/filters';
import { useAppSelector, useAppDispatch } from 'mastodon/store';
@@ -102,8 +102,7 @@ export const NotificationWithStatus: React.FC<{
{label}
- is not yet typed
+
))}
diff --git a/app/javascript/mastodon/features/search/index.tsx b/app/javascript/mastodon/features/search/index.tsx
index f85fba1f78..cdb506140f 100644
--- a/app/javascript/mastodon/features/search/index.tsx
+++ b/app/javascript/mastodon/features/search/index.tsx
@@ -17,7 +17,7 @@ import { ColumnHeader } from 'mastodon/components/column_header';
import { CompatibilityHashtag as Hashtag } from 'mastodon/components/hashtag';
import { Icon } from 'mastodon/components/icon';
import ScrollableList from 'mastodon/components/scrollable_list';
-import Status from 'mastodon/containers/status_container';
+import { StatusQuoteManager } from 'mastodon/components/status_quoted';
import { Search } from 'mastodon/features/compose/components/search';
import { useSearchParam } from 'mastodon/hooks/useSearchParam';
import type { Hashtag as HashtagType } from 'mastodon/models/tags';
@@ -53,8 +53,7 @@ const renderHashtags = (hashtags: HashtagType[]) =>
const renderStatuses = (statusIds: string[]) =>
hidePeek(statusIds).map((id) => (
- // @ts-expect-error inferred props are wrong
-
+
));
type SearchType = 'all' | ApiSearchType;
@@ -190,8 +189,7 @@ export const SearchResults: React.FC<{ multiColumn: boolean }> = ({
onClickMore={handleSelectStatuses}
>
{results.statuses.slice(0, INITIAL_DISPLAY).map((id) => (
- // @ts-expect-error inferred props are wrong
-
+
))}
)}
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.tsx b/app/javascript/mastodon/features/status/components/detailed_status.tsx
index 75d995b1e0..650e439348 100644
--- a/app/javascript/mastodon/features/status/components/detailed_status.tsx
+++ b/app/javascript/mastodon/features/status/components/detailed_status.tsx
@@ -26,6 +26,7 @@ import { IconLogo } from 'mastodon/components/logo';
import MediaGallery from 'mastodon/components/media_gallery';
import { PictureInPicturePlaceholder } from 'mastodon/components/picture_in_picture_placeholder';
import StatusContent from 'mastodon/components/status_content';
+import { QuotedStatus } from 'mastodon/components/status_quoted';
import { VisibilityIcon } from 'mastodon/components/visibility_icon';
import { Audio } from 'mastodon/features/audio';
import scheduleIdleTask from 'mastodon/features/ui/util/schedule_idle_task';
@@ -226,7 +227,7 @@ export const DetailedStatus: React.FC<{
/>
);
}
- } else if (status.get('card')) {
+ } else if (status.get('card') && !status.get('quote')) {
media = (
-
+
{status.get('visibility') === 'direct' && (
@@ -371,6 +377,10 @@ export const DetailedStatus: React.FC<{
{...(statusContentProps as any)}
/>
+ {status.get('quote') && (
+
+ )}
+
{media}
{hashtagBar}
>
diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx
index 7da2df3742..0f02e7b50f 100644
--- a/app/javascript/mastodon/features/status/index.jsx
+++ b/app/javascript/mastodon/features/status/index.jsx
@@ -6,8 +6,6 @@ import classNames from 'classnames';
import { Helmet } from 'react-helmet';
import { withRouter } from 'react-router-dom';
-import { createSelector } from '@reduxjs/toolkit';
-import { List as ImmutableList } from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
@@ -62,7 +60,7 @@ import {
} from '../../actions/statuses';
import ColumnHeader from '../../components/column_header';
import { textForScreenReader, defaultMediaVisibility } from '../../components/status';
-import StatusContainer from '../../containers/status_container';
+import { StatusQuoteManager } from '../../components/status_quoted';
import { deleteModal } from '../../initial_state';
import { makeGetStatus, makeGetPictureInPicture } from '../../selectors';
import { getAncestorsIds, getDescendantsIds } from 'mastodon/selectors/contexts';
@@ -477,7 +475,7 @@ class Status extends ImmutablePureComponent {
const { params: { statusId } } = this.props;
return list.map((id, i) => (
- {
- if (item) {
- onDismiss(item);
- }
+ onDismiss(item);
},
});
diff --git a/app/javascript/mastodon/locales/az.json b/app/javascript/mastodon/locales/az.json
index c7463581cd..e988140fa0 100644
--- a/app/javascript/mastodon/locales/az.json
+++ b/app/javascript/mastodon/locales/az.json
@@ -23,9 +23,11 @@
"account.copy": "Profil linkini kopyala",
"account.direct": "@{name} istifadəçisini fərdi olaraq etiketlə",
"account.disable_notifications": "@{name} paylaşım edəndə mənə bildiriş göndərməyi dayandır",
+ "account.domain_blocking": "Domenin bloklanması",
"account.edit_profile": "Profili redaktə et",
"account.enable_notifications": "@{name} paylaşım edəndə mənə bildiriş göndər",
"account.endorse": "Profildə seçilmişlərə əlavə et",
+ "account.featured.hashtags": "Etiketler",
"account.featured_tags.last_status_at": "Son paylaşım {date} tarixində olub",
"account.featured_tags.last_status_never": "Paylaşım yoxdur",
"account.follow": "İzlə",
diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json
index 8f79d7a05d..ddd8ff3f2d 100644
--- a/app/javascript/mastodon/locales/br.json
+++ b/app/javascript/mastodon/locales/br.json
@@ -34,6 +34,7 @@
"account.followers": "Tud koumanantet",
"account.followers.empty": "Den na heul an implijer·ez-mañ c'hoazh.",
"account.followers_counter": "{count, plural, one {{counter} heulier} two {{counter} heulier} few {{counter} heulier} many {{counter} heulier} other {{counter} heulier}}",
+ "account.followers_you_know_counter": "{counter} a anavezit",
"account.following": "Koumanantoù",
"account.follows.empty": "An implijer·ez-mañ na heul den ebet.",
"account.go_to_profile": "Gwelet ar profil",
@@ -577,6 +578,7 @@
"status.mute": "Kuzhat @{name}",
"status.mute_conversation": "Kuzhat ar gaozeadenn",
"status.open": "Digeriñ ar c'hannad-mañ",
+ "status.quote_post_author": "Embannadenn gant {name}",
"status.read_more": "Lenn muioc'h",
"status.reblog": "Skignañ",
"status.reblog_private": "Skignañ gant ar weledenn gentañ",
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index ce71e1cf5a..b8bba92496 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -42,6 +42,7 @@
"account.followers": "Sledující",
"account.followers.empty": "Tohoto uživatele zatím nikdo nesleduje.",
"account.followers_counter": "{count, plural, one {{counter} sledující} few {{counter} sledující} many {{counter} sledujících} other {{counter} sledujících}}",
+ "account.followers_you_know_counter": "{count, one {{counter}, kterého znáte}, few {{counter}, které znáte}, many {{counter}, kterých znáte} other {{counter}, kterých znáte}}",
"account.following": "Sledujete",
"account.following_counter": "{count, plural, one {{counter} sledovaný} few {{counter} sledovaní} many {{counter} sledovaných} other {{counter} sledovaných}}",
"account.follows.empty": "Tento uživatel zatím nikoho nesleduje.",
@@ -683,7 +684,7 @@
"notifications.policy.filter_not_followers_title": "Lidé, kteří vás nesledují",
"notifications.policy.filter_not_following_hint": "Dokud je ručně neschválíte",
"notifications.policy.filter_not_following_title": "Lidé, které nesledujete",
- "notifications.policy.filter_private_mentions_hint": "Vyfiltrováno, pokud to není odpověď na vaši zmínku nebo pokud sledujete odesílatele",
+ "notifications.policy.filter_private_mentions_hint": "Filtrováno, pokud to není v odpovědi na vaši vlastní zmínku nebo pokud nesledujete odesílatele",
"notifications.policy.filter_private_mentions_title": "Nevyžádané soukromé zmínky",
"notifications.policy.title": "Spravovat oznámení od…",
"notifications_permission_banner.enable": "Povolit oznámení na ploše",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Skrýt konverzaci",
"status.open": "Rozbalit tento příspěvek",
"status.pin": "Zvýraznit na profilu",
+ "status.quote_error.not_found": "Tento příspěvek nelze zobrazit.",
+ "status.quote_error.pending_approval": "Tento příspěvek čeká na schválení od původního autora.",
+ "status.quote_error.rejected": "Tento příspěvek nemůže být zobrazen, protože původní autor neumožňuje, aby byl citován.",
+ "status.quote_error.removed": "Tento příspěvek byl odstraněn jeho autorem.",
+ "status.quote_error.unauthorized": "Tento příspěvek nelze zobrazit, protože nemáte oprávnění k jeho zobrazení.",
+ "status.quote_post_author": "Příspěvek od {name}",
"status.read_more": "Číst více",
"status.reblog": "Boostnout",
"status.reblog_private": "Boostnout s původní viditelností",
diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json
index 6a86a4926c..7acce4ac5a 100644
--- a/app/javascript/mastodon/locales/cy.json
+++ b/app/javascript/mastodon/locales/cy.json
@@ -42,6 +42,7 @@
"account.followers": "Dilynwyr",
"account.followers.empty": "Does neb yn dilyn y defnyddiwr hwn eto.",
"account.followers_counter": "{count, plural, one {{counter} dilynwr} two {{counter} ddilynwr} other {{counter} dilynwyr}}",
+ "account.followers_you_know_counter": "{counter} rydych chi'n adnabod",
"account.following": "Yn dilyn",
"account.following_counter": "{count, plural, one {Yn dilyn {counter}} other {Yn dilyn {counter} arall}}",
"account.follows.empty": "Dyw'r defnyddiwr hwn ddim yn dilyn unrhyw un eto.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Anwybyddu sgwrs",
"status.open": "Ehangu'r post hwn",
"status.pin": "Dangos ar y proffil",
+ "status.quote_error.not_found": "Does dim modd dangos y postiad hwn.",
+ "status.quote_error.pending_approval": "Mae'r postiad hwn yn aros am gymeradwyaeth yr awdur gwreiddiol.",
+ "status.quote_error.rejected": "Does dim modd dangos y postiad hwn gan nad yw'r awdur gwreiddiol yn caniatáu iddo gael ei ddyfynnu.",
+ "status.quote_error.removed": "Cafodd y postiad hwn ei ddileu gan ei awdur.",
+ "status.quote_error.unauthorized": "Does dim modd dangos y postiad hwn gan nad oes gennych awdurdod i'w weld.",
+ "status.quote_post_author": "Postiad gan {name}",
"status.read_more": "Darllen rhagor",
"status.reblog": "Hybu",
"status.reblog_private": "Hybu i'r gynulleidfa wreiddiol",
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index db5e66fe94..c5514a56ac 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -863,6 +863,12 @@
"status.mute_conversation": "Skjul samtale",
"status.open": "Udvid dette indlæg",
"status.pin": "Fremhæv på profil",
+ "status.quote_error.not_found": "Dette indlæg kan ikke vises.",
+ "status.quote_error.pending_approval": "Dette indlæg afventer godkendelse fra den oprindelige forfatter.",
+ "status.quote_error.rejected": "Dette indlæg kan ikke vises, da den oprindelige forfatter ikke tillader citering heraf.",
+ "status.quote_error.removed": "Dette indlæg er fjernet af forfatteren.",
+ "status.quote_error.unauthorized": "Dette indlæg kan ikke vises, da man ikke har tilladelse til at se det.",
+ "status.quote_post_author": "Indlæg fra {name}",
"status.read_more": "Læs mere",
"status.reblog": "Fremhæv",
"status.reblog_private": "Fremhæv med oprindelig synlighed",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 01b195e5d4..172645480e 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -42,6 +42,7 @@
"account.followers": "Follower",
"account.followers.empty": "Diesem Profil folgt noch niemand.",
"account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Follower}}",
+ "account.followers_you_know_counter": "{counter} bekannt",
"account.following": "Folge ich",
"account.following_counter": "{count, plural, one {{counter} Folge ich} other {{counter} Folge ich}}",
"account.follows.empty": "Dieses Profil folgt noch niemandem.",
@@ -360,7 +361,7 @@
"filter_modal.select_filter.title": "Diesen Beitrag filtern",
"filter_modal.title.status": "Beitrag per Filter ausblenden",
"filter_warning.matches_filter": "Übereinstimmend mit dem Filter „{title}“",
- "filtered_notifications_banner.pending_requests": "Von {count, plural, =0 {keinem, den} one {einer Person, die} other {# Personen, die}} du möglicherweise kennst",
+ "filtered_notifications_banner.pending_requests": "Von {count, plural, =0 {keinem Profil, das dir möglicherweise bekannt ist} one {einem Profil, das dir möglicherweise bekannt ist} other {# Profilen, die dir möglicherweise bekannt sind}}",
"filtered_notifications_banner.title": "Gefilterte Benachrichtigungen",
"firehose.all": "Alle Server",
"firehose.local": "Dieser Server",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Unterhaltung stummschalten",
"status.open": "Beitrag öffnen",
"status.pin": "Im Profil vorstellen",
+ "status.quote_error.not_found": "Dieser Beitrag kann nicht angezeigt werden.",
+ "status.quote_error.pending_approval": "Dieser Beitrag muss noch durch das ursprüngliche Profil genehmigt werden.",
+ "status.quote_error.rejected": "Dieser Beitrag kann nicht angezeigt werden, weil das ursprüngliche Profil das Zitieren nicht erlaubt.",
+ "status.quote_error.removed": "Dieser Beitrag wurde durch das Profil entfernt.",
+ "status.quote_error.unauthorized": "Dieser Beitrag kann nicht angezeigt werden, weil du zum Ansehen nicht berechtigt bist.",
+ "status.quote_post_author": "Beitrag von {name}",
"status.read_more": "Gesamten Beitrag anschauen",
"status.reblog": "Teilen",
"status.reblog_private": "Mit der ursprünglichen Zielgruppe teilen",
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index ee494c7e45..12b933004d 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -42,6 +42,7 @@
"account.followers": "Followers",
"account.followers.empty": "No one follows this user yet.",
"account.followers_counter": "{count, plural, one {{counter} follower} other {{counter} followers}}",
+ "account.followers_you_know_counter": "{counter} you know",
"account.following": "Following",
"account.following_counter": "{count, plural, one {{counter} following} other {{counter} following}}",
"account.follows.empty": "This user doesn't follow anyone yet.",
@@ -863,6 +864,13 @@
"status.mute_conversation": "Mute conversation",
"status.open": "Expand this post",
"status.pin": "Feature on profile",
+ "status.quote_error.filtered": "Hidden due to one of your filters",
+ "status.quote_error.not_found": "This post cannot be displayed.",
+ "status.quote_error.pending_approval": "This post is pending approval from the original author.",
+ "status.quote_error.rejected": "This post cannot be displayed as the original author does not allow it to be quoted.",
+ "status.quote_error.removed": "This post was removed by its author.",
+ "status.quote_error.unauthorized": "This post cannot be displayed as you are not authorized to view it.",
+ "status.quote_post_author": "Post by {name}",
"status.read_more": "Read more",
"status.reblog": "Boost",
"status.reblog_private": "Boost with original visibility",
diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json
index 73260068fe..158a937ae1 100644
--- a/app/javascript/mastodon/locales/es-AR.json
+++ b/app/javascript/mastodon/locales/es-AR.json
@@ -42,6 +42,7 @@
"account.followers": "Seguidores",
"account.followers.empty": "Todavía nadie sigue a este usuario.",
"account.followers_counter": "{count, plural, one {{counter} seguidor} other {{counter} seguidores}}",
+ "account.followers_you_know_counter": "{counter} seguidores que conocés",
"account.following": "Siguiendo",
"account.following_counter": "{count, plural, one {siguiendo a {counter}} other {siguiendo a {counter}}}",
"account.follows.empty": "Todavía este usuario no sigue a nadie.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir este mensaje",
"status.pin": "Destacar en el perfil",
+ "status.quote_error.not_found": "No se puede mostrar este mensaje.",
+ "status.quote_error.pending_approval": "Este mensaje está pendiente de aprobación del autor original.",
+ "status.quote_error.rejected": "No se puede mostrar este mensaje, ya que el autor original no permite que se cite.",
+ "status.quote_error.removed": "Este mensaje fue eliminado por su autor.",
+ "status.quote_error.unauthorized": "No se puede mostrar este mensaje, ya que no tenés autorización para verlo.",
+ "status.quote_post_author": "Mensaje de @{name}",
"status.read_more": "Leé más",
"status.reblog": "Adherir",
"status.reblog_private": "Adherir a la audiencia original",
diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json
index f3c00a64ef..e50a6e80a3 100644
--- a/app/javascript/mastodon/locales/es-MX.json
+++ b/app/javascript/mastodon/locales/es-MX.json
@@ -42,6 +42,7 @@
"account.followers": "Seguidores",
"account.followers.empty": "Nadie sigue a este usuario todavía.",
"account.followers_counter": "{count, plural, one {{counter} seguidor} other {{counter} seguidores}}",
+ "account.followers_you_know_counter": "{counter} que conoces",
"account.following": "Siguiendo",
"account.following_counter": "{count, plural, one {{counter} siguiendo} other {{counter} siguiendo}}",
"account.follows.empty": "Este usuario no sigue a nadie todavía.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir estado",
"status.pin": "Destacar en el perfil",
+ "status.quote_error.not_found": "No se puede mostrar esta publicación.",
+ "status.quote_error.pending_approval": "Esta publicación está pendiente de aprobación del autor original.",
+ "status.quote_error.rejected": "No se puede mostrar esta publicación, puesto que el autor original no permite que sea citado.",
+ "status.quote_error.removed": "Esta publicación fue eliminada por su autor.",
+ "status.quote_error.unauthorized": "No se puede mostrar esta publicación, puesto que no estás autorizado a verla.",
+ "status.quote_post_author": "Publicado por {name}",
"status.read_more": "Leer más",
"status.reblog": "Impulsar",
"status.reblog_private": "Implusar a la audiencia original",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 28d88e01fe..e0a969732e 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -42,6 +42,7 @@
"account.followers": "Seguidores",
"account.followers.empty": "Todavía nadie sigue a este usuario.",
"account.followers_counter": "{count, plural, one {{counter} seguidor} other {{counter} seguidores}}",
+ "account.followers_you_know_counter": "{counter} seguidores que conoces",
"account.following": "Siguiendo",
"account.following_counter": "{count, plural, one {{counter} siguiendo} other {{counter} siguiendo}}",
"account.follows.empty": "Este usuario todavía no sigue a nadie.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir publicación",
"status.pin": "Destacar en el perfil",
+ "status.quote_error.not_found": "No se puede mostrar esta publicación.",
+ "status.quote_error.pending_approval": "Esta publicación está pendiente de aprobación del autor original.",
+ "status.quote_error.rejected": "Esta publicación no puede mostrarse porque el autor original no permite que se cite.",
+ "status.quote_error.removed": "Esta publicación fue eliminada por su autor.",
+ "status.quote_error.unauthorized": "Esta publicación no puede mostrarse, ya que no estás autorizado a verla.",
+ "status.quote_post_author": "Publicación de {name}",
"status.read_more": "Leer más",
"status.reblog": "Impulsar",
"status.reblog_private": "Impulsar a la audiencia original",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index c65ed1288a..07279c107c 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -42,6 +42,7 @@
"account.followers": "Seuraajat",
"account.followers.empty": "Kukaan ei seuraa tätä käyttäjää vielä.",
"account.followers_counter": "{count, plural, one {{counter} seuraaja} other {{counter} seuraajaa}}",
+ "account.followers_you_know_counter": "{count, plural, one {{counter} tuntemasi} other {{counter} tuntemaasi}}",
"account.following": "Seurattavat",
"account.following_counter": "{count, plural, one {{counter} seurattava} other {{counter} seurattavaa}}",
"account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Mykistä keskustelu",
"status.open": "Laajenna julkaisu",
"status.pin": "Suosittele profiilissa",
+ "status.quote_error.not_found": "Tätä julkaisua ei voi näyttää.",
+ "status.quote_error.pending_approval": "Tämä julkaisu odottaa alkuperäisen tekijänsä hyväksyntää.",
+ "status.quote_error.rejected": "Tätä julkaisua ei voi näyttää, sillä sen alkuperäinen tekijä ei salli lainattavan julkaisua.",
+ "status.quote_error.removed": "Tekijä on poistanut julkaisun.",
+ "status.quote_error.unauthorized": "Tätä julkaisua ei voi näyttää, koska sinulla ei ole oikeutta tarkastella sitä.",
+ "status.quote_post_author": "Julkaisu käyttäjältä {name}",
"status.read_more": "Näytä enemmän",
"status.reblog": "Tehosta",
"status.reblog_private": "Tehosta alkuperäiselle yleisölle",
diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json
index 1bb9bb29b0..2004364832 100644
--- a/app/javascript/mastodon/locales/fo.json
+++ b/app/javascript/mastodon/locales/fo.json
@@ -42,6 +42,7 @@
"account.followers": "Fylgjarar",
"account.followers.empty": "Ongar fylgjarar enn.",
"account.followers_counter": "{count, plural, one {{counter} fylgjari} other {{counter} fylgjarar}}",
+ "account.followers_you_know_counter": "{counter} tú kennir",
"account.following": "Fylgir",
"account.following_counter": "{count, plural, one {{counter} fylgir} other {{counter} fylgja}}",
"account.follows.empty": "Hesin brúkari fylgir ongum enn.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Doyv samrøðu",
"status.open": "Víðka henda postin",
"status.pin": "Vís á vanga",
+ "status.quote_error.not_found": "Tað ber ikki til at vísa hendan postin.",
+ "status.quote_error.pending_approval": "Hesin posturin bíðar eftir góðkenning frá upprunahøvundinum.",
+ "status.quote_error.rejected": "Hesin posturin kann ikki vísast, tí upprunahøvundurin loyvir ikki at posturin verður siteraður.",
+ "status.quote_error.removed": "Hesin posturin var strikaður av høvundinum.",
+ "status.quote_error.unauthorized": "Hesin posturin kann ikki vísast, tí tú hevur ikki rættindi at síggja hann.",
+ "status.quote_post_author": "Postur hjá @{name}",
"status.read_more": "Les meira",
"status.reblog": "Stimbra",
"status.reblog_private": "Stimbra við upprunasýni",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index 9db5c4dfbd..1322551ae8 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -42,6 +42,7 @@
"account.followers": "Seguidoras",
"account.followers.empty": "Aínda ninguén segue esta usuaria.",
"account.followers_counter": "{count, plural, one {{counter} seguidora} other {{counter} seguidoras}}",
+ "account.followers_you_know_counter": "{counter} que coñeces",
"account.following": "Seguindo",
"account.following_counter": "{count, plural, one {{counter} seguimento} other {{counter} seguimentos}}",
"account.follows.empty": "Esta usuaria aínda non segue a ninguén.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Silenciar conversa",
"status.open": "Estender esta publicación",
"status.pin": "Destacar no perfil",
+ "status.quote_error.not_found": "Non se pode mostrar a publicación.",
+ "status.quote_error.pending_approval": "A publicación está pendente da aprobación pola autora orixinal.",
+ "status.quote_error.rejected": "Non se pode mostrar esta publicación xa que a autora orixinal non permite que se cite.",
+ "status.quote_error.removed": "Publicación eliminada pola autora.",
+ "status.quote_error.unauthorized": "Non se pode mostrar esta publicación porque non tes permiso para vela.",
+ "status.quote_post_author": "Publicación de {name}",
"status.read_more": "Ler máis",
"status.reblog": "Promover",
"status.reblog_private": "Compartir coa audiencia orixinal",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index d3811a75c4..ccb4fdb895 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -863,6 +863,12 @@
"status.mute_conversation": "השתקת שיחה",
"status.open": "הרחבת הודעה זו",
"status.pin": "מובלט בפרופיל",
+ "status.quote_error.not_found": "לא ניתן להציג הודעה זו.",
+ "status.quote_error.pending_approval": "הודעה זו מחכה לאישור מידי היוצר המקורי.",
+ "status.quote_error.rejected": "לא ניתן להציג הודעה זו שכן המחבר.ת המקוריים לא הרשו לצטט אותה.",
+ "status.quote_error.removed": "הודעה זו הוסרה על ידי השולחים המקוריים.",
+ "status.quote_error.unauthorized": "הודעה זו לא מוצגת כיוון שאין לך רשות לראותה.",
+ "status.quote_post_author": "פרסום מאת {name}",
"status.read_more": "לקרוא עוד",
"status.reblog": "הדהוד",
"status.reblog_private": "להדהד ברמת הנראות המקורית",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index b4edfd4818..4566468386 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -42,6 +42,7 @@
"account.followers": "Követő",
"account.followers.empty": "Ezt a felhasználót még senki sem követi.",
"account.followers_counter": "{count, plural, one {{counter} követő} other {{counter} követő}}",
+ "account.followers_you_know_counter": "{counter} ismerős",
"account.following": "Követve",
"account.following_counter": "{count, plural, one {{counter} követett} other {{counter} követett}}",
"account.follows.empty": "Ez a felhasználó még senkit sem követ.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Beszélgetés némítása",
"status.open": "Bejegyzés kibontása",
"status.pin": "Kiemelés a profilodon",
+ "status.quote_error.not_found": "Ez a bejegyzés nem jeleníthető meg.",
+ "status.quote_error.pending_approval": "Ez a bejegyzés az eredeti szerző jóváhagyására vár.",
+ "status.quote_error.rejected": "Ez a bejegyzés nem jeleníthető meg, mert az eredeti szerzője nem engedélyezi az idézését.",
+ "status.quote_error.removed": "Ezt a bejegyzés eltávolította a szerzője.",
+ "status.quote_error.unauthorized": "Ez a bejegyzés nem jeleníthető meg, mert nem jogosult a megtekintésére.",
+ "status.quote_post_author": "Szerző: {name}",
"status.read_more": "Bővebben",
"status.reblog": "Megtolás",
"status.reblog_private": "Megtolás az eredeti közönségnek",
diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json
index aff74649fe..a2081dde92 100644
--- a/app/javascript/mastodon/locales/is.json
+++ b/app/javascript/mastodon/locales/is.json
@@ -42,6 +42,7 @@
"account.followers": "Fylgjendur",
"account.followers.empty": "Ennþá fylgist enginn með þessum notanda.",
"account.followers_counter": "{count, plural, one {Fylgjandi: {counter}} other {Fylgjendur: {counter}}}",
+ "account.followers_you_know_counter": "{counter} sem þú þekkir",
"account.following": "Fylgist með",
"account.following_counter": "{count, plural, one {Fylgist með: {counter}} other {Fylgist með: {counter}}}",
"account.follows.empty": "Þessi notandi fylgist ennþá ekki með neinum.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Þagga niður í samtali",
"status.open": "Opna þessa færslu",
"status.pin": "Birta á notandasniði",
+ "status.quote_error.not_found": "Þessa færslu er ekki hægt að birta.",
+ "status.quote_error.pending_approval": "Þessi færsla bíður eftir samþykki frá upprunalegum höfundi hennar.",
+ "status.quote_error.rejected": "Þessa færslu er ekki hægt að birta þar sem upphaflegur höfundur hennar leyfir ekki að vitnað sé til hennar.",
+ "status.quote_error.removed": "Þessi færsla var fjarlægð af höfundi hennar.",
+ "status.quote_error.unauthorized": "Þessa færslu er ekki hægt að birta þar sem þú hefur ekki heimild til að skoða hana.",
+ "status.quote_post_author": "Færsla frá {name}",
"status.read_more": "Lesa meira",
"status.reblog": "Endurbirting",
"status.reblog_private": "Endurbirta til upphaflegra lesenda",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index ece77c01d4..7d295f23d8 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -28,6 +28,9 @@
"account.edit_profile": "프로필 편집",
"account.enable_notifications": "@{name} 의 게시물 알림 켜기",
"account.endorse": "프로필에 추천하기",
+ "account.familiar_followers_many": "{name1}, {name2} 님 외 내가 아는 {othersCount, plural, other {#}} 명이 팔로우함",
+ "account.familiar_followers_one": "{name1} 님이 팔로우함",
+ "account.familiar_followers_two": "{name1}, {name2} 님이 팔로우함",
"account.featured": "추천",
"account.featured.accounts": "프로필",
"account.featured.hashtags": "해시태그",
@@ -406,8 +409,10 @@
"hashtag.counter_by_accounts": "{count, plural, other {참여자 {counter}명}}",
"hashtag.counter_by_uses": "{count, plural, other {게시물 {counter}개}}",
"hashtag.counter_by_uses_today": "오늘 {count, plural, other {{counter} 개의 게시물}}",
+ "hashtag.feature": "프로필에 추천하기",
"hashtag.follow": "해시태그 팔로우",
"hashtag.mute": "#{hashtag} 뮤트",
+ "hashtag.unfeature": "프로필에 추천하지 않기",
"hashtag.unfollow": "해시태그 팔로우 해제",
"hashtags.and_other": "…및 {count, plural,other {#개}}",
"hints.profiles.followers_may_be_missing": "이 프로필의 팔로워 목록은 일부 누락되었을 수 있습니다.",
@@ -858,6 +863,11 @@
"status.mute_conversation": "대화 뮤트",
"status.open": "상세 정보 표시",
"status.pin": "고정",
+ "status.quote_error.not_found": "이 게시물은 표시할 수 없습니다.",
+ "status.quote_error.pending_approval": "이 게시물은 원작자의 승인을 기다리고 있습니다.",
+ "status.quote_error.rejected": "이 게시물은 원작자가 인용을 허용하지 않았기 때문에 표시할 수 없습니다.",
+ "status.quote_error.removed": "이 게시물은 작성자에 의해 삭제되었습니다.",
+ "status.quote_error.unauthorized": "이 게시물은 권한이 없기 때문에 볼 수 없습니다.",
"status.read_more": "더 보기",
"status.reblog": "부스트",
"status.reblog_private": "원래의 수신자들에게 부스트",
diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json
index 7f5393a66c..bf6fd15de3 100644
--- a/app/javascript/mastodon/locales/lv.json
+++ b/app/javascript/mastodon/locales/lv.json
@@ -41,6 +41,7 @@
"account.followers": "Sekotāji",
"account.followers.empty": "Šim lietotājam vēl nav sekotāju.",
"account.followers_counter": "{count, plural, zero {{count} sekotāju} one {{count} sekotājs} other {{count} sekotāji}}",
+ "account.followers_you_know_counter": "{counter} jūs pazīstiet",
"account.following": "Seko",
"account.following_counter": "{count, plural, one {seko {counter}} other {seko {counter}}}",
"account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.",
@@ -75,6 +76,7 @@
"account.statuses_counter": "{count, plural, zero {{counter} ierakstu} one {{counter} ieraksts} other {{counter} ieraksti}}",
"account.unblock": "Atbloķēt @{name}",
"account.unblock_domain": "Atbloķēt domēnu {domain}",
+ "account.unblock_domain_short": "Atbloķēt",
"account.unblock_short": "Atbloķēt",
"account.unendorse": "Neizcelt profilā",
"account.unfollow": "Pārstāt sekot",
@@ -367,6 +369,8 @@
"generic.saved": "Saglabāts",
"getting_started.heading": "Darba sākšana",
"hashtag.admin_moderation": "Atvērt #{name} satura pārraudzības saskarni",
+ "hashtag.browse": "Pārlūkot #{hashtag} ierakstus",
+ "hashtag.browse_from_account": "Pārlūkot @{name} #{hashtag} ierakstus",
"hashtag.column_header.tag_mode.all": "un {additional}",
"hashtag.column_header.tag_mode.any": "vai {additional}",
"hashtag.column_header.tag_mode.none": "bez {additional}",
@@ -381,6 +385,7 @@
"hashtag.counter_by_uses_today": "{count, plural, zero {{counter} ierakstu} one {{counter} ieraksts} other {{counter} ieraksti}} šodien",
"hashtag.feature": "Attēlot profilā",
"hashtag.follow": "Sekot tēmturim",
+ "hashtag.mute": "Apklusināt #{hashtag}",
"hashtag.unfeature": "Neattēlot profilā",
"hashtag.unfollow": "Pārstāt sekot tēmturim",
"hashtags.and_other": "… un {count, plural, other {vēl #}}",
@@ -448,6 +453,7 @@
"keyboard_shortcuts.toggle_hidden": "Rādīt/slēpt tekstu aiz satura brīdinājuma",
"keyboard_shortcuts.toggle_sensitivity": "Rādīt/slēpt multividi",
"keyboard_shortcuts.toot": "Uzsākt jaunu ierakstu",
+ "keyboard_shortcuts.translate": "tulkot ierakstu",
"keyboard_shortcuts.unfocus": "Atfokusēt veidojamā teksta/meklēšanas lauku",
"keyboard_shortcuts.up": "Pārvietoties augšup sarakstā",
"lightbox.close": "Aizvērt",
@@ -515,6 +521,7 @@
"notification.favourite": "{name} pievienoja izlasei Tavu ierakstu",
"notification.follow": "{name} uzsāka Tev sekot",
"notification.follow_request": "{name} nosūtīja Tev sekošanas pieprasījumu",
+ "notification.mentioned_you": "{name} pieminēja jūs",
"notification.moderation-warning.learn_more": "Uzzināt vairāk",
"notification.moderation_warning": "Ir saņemts satura pārraudzības brīdinājums",
"notification.moderation_warning.action_delete_statuses": "Daži no Taviem ierakstiem tika noņemti.",
@@ -741,6 +748,12 @@
"status.mute_conversation": "Apklusināt sarunu",
"status.open": "Izvērst šo ierakstu",
"status.pin": "Attēlot profilā",
+ "status.quote_error.not_found": "Šo ierakstu nevar parādīt.",
+ "status.quote_error.pending_approval": "Šis ieraksts gaida apstiprinājumu no tā autora.",
+ "status.quote_error.rejected": "Šo ierakstu nevar parādīt, jo tā autors neļauj to citēt.",
+ "status.quote_error.removed": "Šo ierakstu noņēma tā autors.",
+ "status.quote_error.unauthorized": "Šo ierakstu nevar parādīt, jo jums nav atļaujas to skatīt.",
+ "status.quote_post_author": "Publicēja {name}",
"status.read_more": "Lasīt vairāk",
"status.reblog": "Pastiprināt",
"status.reblog_private": "Pastiprināt ar sākotnējo redzamību",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index 404b0e0395..b9bc523fe7 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -42,6 +42,7 @@
"account.followers": "Volgers",
"account.followers.empty": "Deze gebruiker heeft nog geen volgers of heeft deze verborgen.",
"account.followers_counter": "{count, plural, one {{counter} volger} other {{counter} volgers}}",
+ "account.followers_you_know_counter": "{counter} die je kent",
"account.following": "Volgend",
"account.following_counter": "{count, plural, one {{counter} volgend} other {{counter} volgend}}",
"account.follows.empty": "Deze gebruiker volgt nog niemand of heeft deze verborgen.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Gesprek negeren",
"status.open": "Volledig bericht tonen",
"status.pin": "Op profiel uitlichten",
+ "status.quote_error.not_found": "Dit bericht kan niet worden weergegeven.",
+ "status.quote_error.pending_approval": "Dit bericht is in afwachting van goedkeuring door de oorspronkelijke auteur.",
+ "status.quote_error.rejected": "Dit bericht kan niet worden weergegeven omdat de oorspronkelijke auteur niet toestaat dat het wordt geciteerd.",
+ "status.quote_error.removed": "Dit bericht is verwijderd door de auteur.",
+ "status.quote_error.unauthorized": "Dit bericht kan niet worden weergegeven omdat je niet bevoegd bent om het te bekijken.",
+ "status.quote_post_author": "Bericht van {name}",
"status.read_more": "Meer lezen",
"status.reblog": "Boosten",
"status.reblog_private": "Boost naar oorspronkelijke ontvangers",
diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json
index 88fd9bf427..4eb45a1a80 100644
--- a/app/javascript/mastodon/locales/pt-PT.json
+++ b/app/javascript/mastodon/locales/pt-PT.json
@@ -42,6 +42,7 @@
"account.followers": "Seguidores",
"account.followers.empty": "Ainda ninguém segue este utilizador.",
"account.followers_counter": "{count, plural, one {{counter} seguidor} other {{counter} seguidores}}",
+ "account.followers_you_know_counter": "{counter} que conhece",
"account.following": "A seguir",
"account.following_counter": "{count, plural, one {A seguir {counter}} other {A seguir {counter}}}",
"account.follows.empty": "Este utilizador ainda não segue ninguém.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Ocultar conversa",
"status.open": "Expandir esta publicação",
"status.pin": "Destacar no perfil",
+ "status.quote_error.not_found": "Esta publicação não pode ser exibida.",
+ "status.quote_error.pending_approval": "Esta publicação está a aguardar a aprovação do autor original.",
+ "status.quote_error.rejected": "Esta publicação não pode ser exibida porque o autor original não permite que seja citada.",
+ "status.quote_error.removed": "Esta publicação foi removida pelo seu autor.",
+ "status.quote_error.unauthorized": "Esta publicação não pode ser exibida porque o utilizador não está autorizado a visualizá-la.",
+ "status.quote_post_author": "Publicação de {name}",
"status.read_more": "Ler mais",
"status.reblog": "Impulsionar",
"status.reblog_private": "Impulsionar com a visibilidade original",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index a82eab47d5..30415b247d 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -86,10 +86,10 @@
"admin.dashboard.retention.average": "В среднем",
"admin.dashboard.retention.cohort": "Месяц регистрации",
"admin.dashboard.retention.cohort_size": "Новые пользователи",
- "admin.impact_report.instance_accounts": "Профили учетных записей, которые будут удалены",
- "admin.impact_report.instance_followers": "Подписчики, которых потеряют наши пользователи",
- "admin.impact_report.instance_follows": "Подписчики, которых потеряют их пользователи",
- "admin.impact_report.title": "Резюме воздействия",
+ "admin.impact_report.instance_accounts": "Число профилей, которые будут удалены",
+ "admin.impact_report.instance_followers": "Число подписчиков, которых лишатся наши пользователи",
+ "admin.impact_report.instance_follows": "Число подписчиков, которых лишатся их пользователи",
+ "admin.impact_report.title": "Сводка последствий",
"alert.rate_limited.message": "Подождите до {retry_time, time, medium}, прежде чем делать что-либо ещё.",
"alert.rate_limited.title": "Слишком много запросов",
"alert.unexpected.message": "Произошла непредвиденная ошибка.",
@@ -305,8 +305,8 @@
"emoji_button.search_results": "Результаты поиска",
"emoji_button.symbols": "Символы",
"emoji_button.travel": "Путешествия и места",
- "empty_column.account_featured.me": "Вы ещё ничего не закрепили в своём профиле. Знаете ли вы, что вы можете рекомендовать в этом разделе свои посты, часто используемые вами хэштеги и даже профили друзей?",
- "empty_column.account_featured.other": "{acct} ещё ничего не закрепил(а) в своём профиле. Знаете ли вы, что вы можете рекомендовать в этом разделе свои посты, часто используемые вами хэштеги и даже профили друзей?",
+ "empty_column.account_featured.me": "Вы ещё ничего не закрепили в своём профиле. Знаете ли вы, что вы можете рекомендовать в этом разделе свои посты, часто используемые вами хештеги и даже профили друзей?",
+ "empty_column.account_featured.other": "{acct} ещё ничего не закрепил(а) в своём профиле. Знаете ли вы, что вы можете рекомендовать в этом разделе свои посты, часто используемые вами хештеги и даже профили друзей?",
"empty_column.account_featured_other.unknown": "Этот пользователь ещё ничего не закрепил в своём профиле.",
"empty_column.account_hides_collections": "Пользователь предпочёл не раскрывать эту информацию",
"empty_column.account_suspended": "Учётная запись заблокирована",
@@ -357,7 +357,7 @@
"filter_modal.select_filter.title": "Фильтровать этот пост",
"filter_modal.title.status": "Фильтровать пост",
"filter_warning.matches_filter": "Соответствует фильтру «{title}»",
- "filtered_notifications_banner.pending_requests": "От {count, plural, =0 {не известных вам людей} one {# возможно вам известного человека} other {# возможно вам известных человек}}",
+ "filtered_notifications_banner.pending_requests": "От {count, plural, =0 {не знакомых вам людей} one {# человека, которого вы можете знать} other {# человек, которых вы можете знать}}",
"filtered_notifications_banner.title": "Отфильтрованные уведомления",
"firehose.all": "Всё вместе",
"firehose.local": "Этот сервер",
@@ -392,8 +392,8 @@
"generic.saved": "Сохранено",
"getting_started.heading": "Добро пожаловать",
"hashtag.admin_moderation": "Открыть интерфейс модератора для #{name}",
- "hashtag.browse": "Обзор постов с хэштегом #{hashtag}",
- "hashtag.browse_from_account": "Обзор постов от @{name} с хэштегом #{hashtag}",
+ "hashtag.browse": "Обзор постов с хештегом #{hashtag}",
+ "hashtag.browse_from_account": "Обзор постов от @{name} с хештегом #{hashtag}",
"hashtag.column_header.tag_mode.all": "и {additional}",
"hashtag.column_header.tag_mode.any": "или {additional}",
"hashtag.column_header.tag_mode.none": "без {additional}",
@@ -454,7 +454,7 @@
"interaction_modal.title.reblog": "Продвинуть пост {name}",
"interaction_modal.title.reply": "Ответить на пост {name}",
"interaction_modal.title.vote": "Голосовать в опросе {name}",
- "interaction_modal.username_prompt": "Например {example}",
+ "interaction_modal.username_prompt": "Например, {example}",
"intervals.full.days": "{number, plural, one {# день} few {# дня} other {# дней}}",
"intervals.full.hours": "{number, plural, one {# час} few {# часа} other {# часов}}",
"intervals.full.minutes": "{number, plural, one {# минута} few {# минуты} other {# минут}}",
diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json
index af3fd9761f..fb99b87fc3 100644
--- a/app/javascript/mastodon/locales/sq.json
+++ b/app/javascript/mastodon/locales/sq.json
@@ -42,6 +42,7 @@
"account.followers": "Ndjekës",
"account.followers.empty": "Këtë përdorues ende s’e ndjek kush.",
"account.followers_counter": "{count, plural, one {{counter} ndjekës} other {{counter} ndjekës}}",
+ "account.followers_you_know_counter": "{counter} që njihni",
"account.following": "Ndjekje",
"account.following_counter": "{count, plural, one {{counter} i ndjekur} other {{counter} të ndjekur}}",
"account.follows.empty": "Ky përdorues ende s’ndjek kënd.",
@@ -858,6 +859,12 @@
"status.mute_conversation": "Heshtoje bisedën",
"status.open": "Zgjeroje këtë mesazh",
"status.pin": "Pasqyrojeni në profil",
+ "status.quote_error.not_found": "Ky postim s’mund të shfaqet.",
+ "status.quote_error.pending_approval": "Ky postim është në pritje të miratimit nga autori origjinal.",
+ "status.quote_error.rejected": "Ky postim s’mund të shfaqet, ngaqë autori origjinal nuk lejon citim të tij.",
+ "status.quote_error.removed": "Ky postim u hoq nga autori i tij.",
+ "status.quote_error.unauthorized": "Ky postim s’mund të shfaqet, ngaqë s’jeni i autorizuar ta shihni.",
+ "status.quote_post_author": "Postim nga {name}",
"status.read_more": "Lexoni më tepër",
"status.reblog": "Përforcojeni",
"status.reblog_private": "Përforcim për publikun origjinal",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index 566b7ddff0..6f2e22fc6e 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -42,6 +42,7 @@
"account.followers": "Takipçi",
"account.followers.empty": "Henüz kimse bu kullanıcıyı takip etmiyor.",
"account.followers_counter": "{count, plural, one {{counter} takipçi} other {{counter} takipçi}}",
+ "account.followers_you_know_counter": "bildiğiniz {counter}",
"account.following": "Takip Ediliyor",
"account.following_counter": "{count, plural, one {{counter} takip edilen} other {{counter} takip edilen}}",
"account.follows.empty": "Bu kullanıcı henüz kimseyi takip etmiyor.",
@@ -863,6 +864,12 @@
"status.mute_conversation": "Sohbeti sessize al",
"status.open": "Bu gönderiyi genişlet",
"status.pin": "Profilimde öne çıkar",
+ "status.quote_error.not_found": "Bu gönderi görüntülenemez.",
+ "status.quote_error.pending_approval": "Bu gönderi özgün yazarın onayını bekliyor.",
+ "status.quote_error.rejected": "Bu gönderi, özgün yazar alıntılanmasına izin vermediği için görüntülenemez.",
+ "status.quote_error.removed": "Bu gönderi yazarı tarafından kaldırıldı.",
+ "status.quote_error.unauthorized": "Bu gönderiyi, yetkiniz olmadığı için görüntüleyemiyorsunuz.",
+ "status.quote_post_author": "{name} gönderisi",
"status.read_more": "Devamını okuyun",
"status.reblog": "Yeniden paylaş",
"status.reblog_private": "Özgün görünürlük ile yeniden paylaş",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index f006b4015a..18b0e36068 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -843,6 +843,7 @@
"status.mute": "Приховати @{name}",
"status.mute_conversation": "Ігнорувати розмову",
"status.open": "Розгорнути допис",
+ "status.quote_post_author": "@{name} опублікував допис",
"status.read_more": "Дізнатися більше",
"status.reblog": "Поширити",
"status.reblog_private": "Поширити для початкової аудиторії",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 14c64c92b8..248b2fcdf8 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -42,6 +42,7 @@
"account.followers": "跟隨者",
"account.followers.empty": "尚未有人跟隨這位使用者。",
"account.followers_counter": "被 {count, plural, other {{count} 人}}跟隨",
+ "account.followers_you_know_counter": "{counter} 位您知道的跟隨者",
"account.following": "跟隨中",
"account.following_counter": "正在跟隨 {count,plural,other {{count} 人}}",
"account.follows.empty": "這位使用者尚未跟隨任何人。",
@@ -863,6 +864,12 @@
"status.mute_conversation": "靜音對話",
"status.open": "展開此嘟文",
"status.pin": "於個人檔案推薦",
+ "status.quote_error.not_found": "這則嘟文無法被顯示。",
+ "status.quote_error.pending_approval": "此嘟文正在等待原作者審核。",
+ "status.quote_error.rejected": "由於原作者不允許引用,此嘟文無法被顯示。",
+ "status.quote_error.removed": "此嘟文已被其作者移除。",
+ "status.quote_error.unauthorized": "由於您未被授權檢視,此嘟文無法被顯示。",
+ "status.quote_post_author": "由 {name} 發嘟",
"status.read_more": "閱讀更多",
"status.reblog": "轉嘟",
"status.reblog_private": "依照原嘟可見性轉嘟",
diff --git a/app/javascript/material-icons/400-24px/article-fill.svg b/app/javascript/material-icons/400-24px/article-fill.svg
new file mode 100644
index 0000000000..5ea367df92
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/article-fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/article.svg b/app/javascript/material-icons/400-24px/article.svg
new file mode 100644
index 0000000000..1265c26dad
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/article.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/README.md b/app/javascript/material-icons/README.md
index 1479cb2255..c583d5ee2c 100644
--- a/app/javascript/material-icons/README.md
+++ b/app/javascript/material-icons/README.md
@@ -1 +1,12 @@
-Files in this directory are Material Symbols icons fetched using the `icons:download` task.
+Files in this directory are Material Symbols icons fetched using the `icons:download` rake task (see `/lib/tasks/icons.rake`).
+
+To add another icon, follow these steps:
+
+- Determine the name of the Material Symbols icon you want to download.
+ You can find a searchable overview of all icons on [https://fonts.google.com/icons].
+ Click on the icon you want to use and find the icon name towards the bottom of the slide-out panel (it'll be something like `icon_name`)
+- Import the icon in your React component using the following format:
+ `import IconName from '@/material-icons/400-24px/icon_name.svg?react';`
+- Run `RAILS_ENV=development rails icons:download` to download any newly imported icons.
+
+The import should now work and the icon should appear when passed to the ` component
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index f9f70c4da2..40a68a79cf 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -1421,6 +1421,10 @@ body > [data-popper-placement] {
}
}
+.status--has-quote .quote-inline {
+ display: none;
+}
+
.status {
padding: 16px;
min-height: 54px;
@@ -1491,8 +1495,12 @@ body > [data-popper-placement] {
}
}
+ &--is-quote {
+ border: none;
+ }
+
&--in-thread {
- $thread-margin: 46px + 10px;
+ --thread-margin: calc(46px + 8px);
border-bottom: 0;
@@ -1508,16 +1516,16 @@ body > [data-popper-placement] {
.hashtag-bar,
.content-warning,
.filter-warning {
- margin-inline-start: $thread-margin;
- width: calc(100% - $thread-margin);
+ margin-inline-start: var(--thread-margin);
+ width: calc(100% - var(--thread-margin));
}
.more-from-author {
- width: calc(100% - $thread-margin + 2px);
+ width: calc(100% - var(--thread-margin) + 2px);
}
.status__content__read-more-button {
- margin-inline-start: $thread-margin;
+ margin-inline-start: var(--thread-margin);
}
}
@@ -1873,6 +1881,81 @@ body > [data-popper-placement] {
}
}
+.status__quote {
+ position: relative;
+ margin-block-start: 16px;
+ margin-inline-start: 36px;
+ border-radius: 8px;
+ color: var(--nested-card-text);
+ background: var(--nested-card-background);
+ border: var(--nested-card-border);
+
+ @media screen and (min-width: $mobile-breakpoint) {
+ margin-inline-start: 56px;
+ }
+}
+
+.status__quote--error {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 12px;
+ font-size: 15px;
+}
+
+.status__quote-author-button {
+ position: relative;
+ overflow: hidden;
+ display: inline-flex;
+ width: auto;
+ margin-block-start: 10px;
+ padding: 5px 12px;
+ align-items: center;
+ gap: 6px;
+ font-family: inherit;
+ font-size: 14px;
+ font-weight: 700;
+ line-height: normal;
+ letter-spacing: 0;
+ text-decoration: none;
+ color: $highlight-text-color;
+ background: var(--nested-card-background);
+ border: var(--nested-card-border);
+ border-radius: 4px;
+
+ &:active,
+ &:focus,
+ &:hover {
+ border-color: lighten($highlight-text-color, 4%);
+ color: lighten($highlight-text-color, 4%);
+ }
+
+ &:focus-visible {
+ outline: $ui-button-icon-focus-outline;
+ }
+}
+
+.status__quote-icon {
+ position: absolute;
+ inset-block-start: 18px;
+ inset-inline-start: -40px;
+ display: block;
+ width: 26px;
+ height: 26px;
+ padding: 5px;
+ color: #6a49ba;
+ z-index: 10;
+
+ .status__quote--error & {
+ inset-block-start: 50%;
+ transform: translateY(-50%);
+ }
+
+ @media screen and (min-width: $mobile-breakpoint) {
+ inset-inline-start: -50px;
+ }
+}
+
.detailed-status__link {
display: inline-flex;
align-items: center;
@@ -2170,14 +2253,18 @@ a .account__avatar {
.avatar-group {
display: flex;
- gap: 8px;
- flex-wrap: wrap;
+
+ --avatar-height: 28px;
+
+ &:not(.avatar-group--compact) {
+ gap: 8px;
+ flex-wrap: wrap;
+ height: var(--avatar-height);
+ overflow-y: clip;
+ }
}
.avatar-group--compact {
- gap: 0;
- flex-wrap: nowrap;
-
& > :not(:first-child) {
margin-inline-start: -12px;
}
@@ -2306,11 +2393,6 @@ a.account__display-name {
}
}
-.status__avatar {
- width: 46px;
- height: 46px;
-}
-
.muted {
.status__content,
.status__content p,
@@ -10334,7 +10416,8 @@ noscript {
padding: 15px;
display: flex;
align-items: center;
- gap: 8px;
+ flex-wrap: wrap;
+ gap: 4px 8px;
.logo {
width: 16px;
@@ -10428,12 +10511,6 @@ noscript {
overflow: hidden;
container-type: inline-size;
- @container (width < 350px) {
- &__header time {
- display: none;
- }
- }
-
&__header {
display: flex;
flex-direction: column;
@@ -10446,7 +10523,8 @@ noscript {
&__label {
display: flex;
- gap: 8px;
+ flex-wrap: wrap;
+ gap: 2px 8px;
font-size: 15px;
line-height: 22px;
color: $darker-text-color;
@@ -10464,6 +10542,13 @@ noscript {
time {
color: $dark-text-color;
}
+
+ @container (width < 350px) {
+ time,
+ &-separator {
+ display: none;
+ }
+ }
}
}
@@ -10515,6 +10600,7 @@ noscript {
line-height: 22px;
color: $darker-text-color;
-webkit-line-clamp: 4;
+ line-clamp: 4;
-webkit-box-orient: vertical;
max-height: none;
overflow: hidden;
@@ -10670,7 +10756,15 @@ noscript {
color: inherit;
}
- &__number {
+ &__numbers,
+ &__familiar-followers {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 10px;
+ }
+
+ &__numbers {
font-size: 15px;
line-height: 22px;
color: $secondary-text-color;
@@ -10818,9 +10912,9 @@ noscript {
.content-warning {
display: block;
box-sizing: border-box;
- background: rgba($ui-highlight-color, 0.05);
- color: $secondary-text-color;
- border: 1px solid rgba($ui-highlight-color, 0.15);
+ background: var(--nested-card-background);
+ color: var(--nested-card-text);
+ border: var(--nested-card-border);
border-radius: 8px;
padding: 8px (5px + 8px);
position: relative;
diff --git a/app/javascript/styles/mastodon/css_variables.scss b/app/javascript/styles/mastodon/css_variables.scss
index 782e08e283..413efca3f6 100644
--- a/app/javascript/styles/mastodon/css_variables.scss
+++ b/app/javascript/styles/mastodon/css_variables.scss
@@ -27,6 +27,10 @@
--rich-text-container-color: rgba(87, 24, 60, 100%);
--rich-text-text-color: rgba(255, 175, 212, 100%);
--rich-text-decorations-color: rgba(128, 58, 95, 100%);
+ --nested-card-background: color(from #{$ui-highlight-color} srgb r g b / 5%);
+ --nested-card-text: #{$secondary-text-color};
+ --nested-card-border: 1px solid
+ color(from #{$ui-highlight-color} srgb r g b / 15%);
--input-placeholder-color: #{$dark-text-color};
--input-background-color: var(--surface-variant-background-color);
--on-input-color: #{$secondary-text-color};
diff --git a/app/lib/fasp/request.rb b/app/lib/fasp/request.rb
index 7d8c05d406..6ea837b89c 100644
--- a/app/lib/fasp/request.rb
+++ b/app/lib/fasp/request.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Fasp::Request
+ COVERED_COMPONENTS = %w(@method @target-uri content-digest).freeze
+
def initialize(provider)
@provider = provider
end
@@ -23,55 +25,36 @@ class Fasp::Request
url = @provider.url(path)
body = body.present? ? body.to_json : ''
headers = request_headers(verb, url, body)
- response = HTTP.headers(headers).send(verb, url, body:)
+ key = Linzer.new_ed25519_key(@provider.server_private_key_pem, @provider.remote_identifier)
+ response = HTTP
+ .headers(headers)
+ .use(http_signature: { key:, covered_components: COVERED_COMPONENTS })
+ .send(verb, url, body:)
+
validate!(response)
response.parse if response.body.present?
end
- def request_headers(verb, url, body = '')
- result = {
+ def request_headers(_verb, _url, body = '')
+ {
'accept' => 'application/json',
'content-type' => 'application/json',
'content-digest' => content_digest(body),
}
- result.merge(signature_headers(verb, url, result))
end
def content_digest(body)
"sha-256=:#{OpenSSL::Digest.base64digest('sha256', body || '')}:"
end
- def signature_headers(verb, url, headers)
- linzer_request = Linzer.new_request(verb, url, {}, headers)
- message = Linzer::Message.new(linzer_request)
- key = Linzer.new_ed25519_key(@provider.server_private_key_pem, @provider.remote_identifier)
- signature = Linzer.sign(key, message, %w(@method @target-uri content-digest))
- Linzer::Signer.send(:populate_parameters, key, {})
-
- signature.to_h
- end
-
def validate!(response)
content_digest_header = response.headers['content-digest']
raise Mastodon::SignatureVerificationError, 'content-digest missing' if content_digest_header.blank?
raise Mastodon::SignatureVerificationError, 'content-digest does not match' if content_digest_header != content_digest(response.body)
+ raise Mastodon::SignatureVerificationError, 'signature-input is missing' if response.headers['signature-input'].blank?
- signature_input = response.headers['signature-input']&.encode('UTF-8')
- raise Mastodon::SignatureVerificationError, 'signature-input is missing' if signature_input.blank?
-
- linzer_response = Linzer.new_response(
- response.body,
- response.status,
- {
- 'content-digest' => content_digest_header,
- 'signature-input' => signature_input,
- 'signature' => response.headers['signature'],
- }
- )
- message = Linzer::Message.new(linzer_response)
key = Linzer.new_ed25519_public_key(@provider.provider_public_key_pem)
- signature = Linzer::Signature.build(message.headers)
- Linzer.verify(key, message, signature)
+ Linzer.verify!(response, key:)
end
end
diff --git a/app/models/rule.rb b/app/models/rule.rb
index 8f36f11abb..c7b532fe5d 100644
--- a/app/models/rule.rb
+++ b/app/models/rule.rb
@@ -42,6 +42,6 @@ class Rule < ApplicationRecord
def translation_for(locale)
@cached_translations ||= {}
- @cached_translations[locale] ||= translations.find_by(language: locale) || RuleTranslation.new(language: locale, text: text, hint: hint)
+ @cached_translations[locale] ||= translations.where(language: [locale, locale.to_s.split('-').first]).order('length(language) desc').first || RuleTranslation.new(language: locale, text: text, hint: hint)
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 7735c0d04d..0ddf1bd799 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -73,7 +73,6 @@ class User < ApplicationRecord
ACTIVE_DURATION = ENV.fetch('USER_ACTIVE_DAYS', 7).to_i.days.freeze
devise :two_factor_authenticatable,
- otp_secret_encryption_key: Rails.configuration.x.otp_secret,
otp_secret_length: 32
devise :two_factor_backupable,
diff --git a/app/services/activitypub/fetch_featured_collection_service.rb b/app/services/activitypub/fetch_featured_collection_service.rb
index 25c62f3be6..e1fa560a8a 100644
--- a/app/services/activitypub/fetch_featured_collection_service.rb
+++ b/app/services/activitypub/fetch_featured_collection_service.rb
@@ -4,13 +4,11 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService
include JsonLdHelper
def call(account, **options)
- return if account.featured_collection_url.blank? || account.suspended? || account.local?
+ return if (account.featured_collection_url.blank? && options[:collection].blank?) || account.suspended? || account.local?
@account = account
@options = options
- @json = fetch_resource(@account.featured_collection_url, true, local_follower)
-
- return unless supported_context?(@json)
+ @json = fetch_collection(options[:collection].presence || @account.featured_collection_url)
process_items(collection_items(@json))
end
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index e5c2319728..201f7513b9 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -57,7 +57,7 @@ class ActivityPub::ProcessAccountService < BaseService
after_suspension_change! if suspension_changed?
unless @options[:only_key] || @account.suspended?
- check_featured_collection! if @account.featured_collection_url.present?
+ check_featured_collection! if @json['featured'].present?
check_featured_tags_collection! if @json['featuredTags'].present?
check_links! if @account.fields.any?(&:requires_verification?)
end
@@ -121,7 +121,7 @@ class ActivityPub::ProcessAccountService < BaseService
end
def set_immediate_attributes!
- @account.featured_collection_url = @json['featured'] || ''
+ @account.featured_collection_url = valid_collection_uri(@json['featured'])
@account.display_name = @json['name'] || ''
@account.note = @json['summary'] || ''
@account.locked = @json['manuallyApprovesFollowers'] || false
@@ -186,7 +186,7 @@ class ActivityPub::ProcessAccountService < BaseService
end
def check_featured_collection!
- ActivityPub::SynchronizeFeaturedCollectionWorker.perform_async(@account.id, { 'hashtag' => @json['featuredTags'].blank?, 'request_id' => @options[:request_id] })
+ ActivityPub::SynchronizeFeaturedCollectionWorker.perform_async(@account.id, { 'hashtag' => @json['featuredTags'].blank?, 'collection' => @json['featured'], 'request_id' => @options[:request_id] })
end
def check_featured_tags_collection!
diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb
index 4141fb43df..84c4ba06f1 100644
--- a/app/services/fetch_link_card_service.rb
+++ b/app/services/fetch_link_card_service.rb
@@ -19,7 +19,7 @@ class FetchLinkCardService < BaseService
@status = status
@original_url = parse_urls
- return if @original_url.nil? || @status.with_preview_card?
+ return if @original_url.nil? || @status.with_preview_card? || @status.with_media? || @status.quote.present?
@url = @original_url.to_s
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 57069d2dc6..d0dabc298a 100755
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -28,6 +28,7 @@
= theme_style_tags current_theme
= vite_client_tag
= vite_react_refresh_tag
+ = vite_polyfills_tag
-# Needed for the wicg-inert polyfill. It needs to be on it's own