+
-
+
+ {zoomable && }
+
+
{leftNav}
{rightNav}
diff --git a/app/javascript/mastodon/features/ui/components/mute_modal.jsx b/app/javascript/mastodon/features/ui/components/mute_modal.jsx
index df466cfac6..70d95b5931 100644
--- a/app/javascript/mastodon/features/ui/components/mute_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/mute_modal.jsx
@@ -137,7 +137,7 @@ export const MuteModal = ({ accountId, acct }) => {
-
diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
index 2648923bfc..0ca21e8976 100644
--- a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
+++ b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
@@ -7,16 +7,17 @@ import { Link } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
-
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
import BookmarksActiveIcon from '@/material-icons/400-24px/bookmarks-fill.svg?react';
import BookmarksIcon from '@/material-icons/400-24px/bookmarks.svg?react';
import ExploreActiveIcon from '@/material-icons/400-24px/explore-fill.svg?react';
import ExploreIcon from '@/material-icons/400-24px/explore.svg?react';
+import ModerationIcon from '@/material-icons/400-24px/gavel.svg?react';
import HomeActiveIcon from '@/material-icons/400-24px/home-fill.svg?react';
import HomeIcon from '@/material-icons/400-24px/home.svg?react';
import ListAltActiveIcon from '@/material-icons/400-24px/list_alt-fill.svg?react';
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
+import AdministrationIcon from '@/material-icons/400-24px/manufacturing.svg?react';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import NotificationsActiveIcon from '@/material-icons/400-24px/notifications-fill.svg?react';
import NotificationsIcon from '@/material-icons/400-24px/notifications.svg?react';
@@ -34,6 +35,7 @@ import { NavigationPortal } from 'mastodon/components/navigation_portal';
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
import { timelinePreview, trendsEnabled } from 'mastodon/initial_state';
import { transientSingleColumn } from 'mastodon/is_mobile';
+import { canManageReports, canViewAdminDashboard } from 'mastodon/permissions';
import { selectUnreadNotificationGroupsCount } from 'mastodon/selectors/notifications';
import ColumnLink from './column_link';
@@ -51,6 +53,8 @@ const messages = defineMessages({
bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' },
lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
+ administration: { id: 'navigation_bar.administration', defaultMessage: 'Administration' },
+ moderation: { id: 'navigation_bar.moderation', defaultMessage: 'Moderation' },
followsAndFollowers: { id: 'navigation_bar.follows_and_followers', defaultMessage: 'Follows and followers' },
about: { id: 'navigation_bar.about', defaultMessage: 'About' },
search: { id: 'navigation_bar.search', defaultMessage: 'Search' },
@@ -60,19 +64,17 @@ const messages = defineMessages({
});
const NotificationsLink = () => {
- const optedInGroupedNotifications = useSelector((state) => state.getIn(['settings', 'notifications', 'groupingBeta'], false));
- const count = useSelector(state => state.getIn(['notifications', 'unread']));
- const intl = useIntl();
- const newCount = useSelector(selectUnreadNotificationGroupsCount);
+ const count = useSelector(selectUnreadNotificationGroupsCount);
+ const intl = useIntl();
return (
}
- activeIcon={}
+ icon={}
+ activeIcon={}
text={intl.formatMessage(messages.notifications)}
/>
);
@@ -114,7 +116,7 @@ class NavigationPanel extends Component {
render () {
const { intl } = this.props;
- const { signedIn, disabledAccountId } = this.props.identity;
+ const { signedIn, disabledAccountId, permissions } = this.props.identity;
let banner = undefined;
@@ -176,6 +178,9 @@ class NavigationPanel extends Component {
+
+ {canManageReports(permissions) && }
+ {canViewAdminDashboard(permissions) && }
>
)}
diff --git a/app/javascript/mastodon/features/ui/components/zoomable_image.jsx b/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
index 272a3cff00..c4129bf260 100644
--- a/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
+++ b/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
@@ -1,17 +1,6 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
-import { defineMessages, injectIntl } from 'react-intl';
-
-import FullscreenExitIcon from '@/material-icons/400-24px/fullscreen_exit.svg?react';
-import RectangleIcon from '@/material-icons/400-24px/rectangle.svg?react';
-import { IconButton } from 'mastodon/components/icon_button';
-
-const messages = defineMessages({
- compress: { id: 'lightbox.compress', defaultMessage: 'Compress image view box' },
- expand: { id: 'lightbox.expand', defaultMessage: 'Expand image view box' },
-});
-
const MIN_SCALE = 1;
const MAX_SCALE = 4;
const NAV_BAR_HEIGHT = 66;
@@ -104,8 +93,7 @@ class ZoomableImage extends PureComponent {
width: PropTypes.number,
height: PropTypes.number,
onClick: PropTypes.func,
- zoomButtonHidden: PropTypes.bool,
- intl: PropTypes.object.isRequired,
+ zoomedIn: PropTypes.bool,
};
static defaultProps = {
@@ -131,8 +119,6 @@ class ZoomableImage extends PureComponent {
translateX: null,
translateY: null,
},
- zoomState: 'expand', // 'expand' 'compress'
- navigationHidden: false,
dragPosition: { top: 0, left: 0, x: 0, y: 0 },
dragged: false,
lockScroll: { x: 0, y: 0 },
@@ -169,35 +155,20 @@ class ZoomableImage extends PureComponent {
this.container.addEventListener('DOMMouseScroll', handler);
this.removers.push(() => this.container.removeEventListener('DOMMouseScroll', handler));
- this.initZoomMatrix();
+ this._initZoomMatrix();
}
componentWillUnmount () {
- this.removeEventListeners();
+ this._removeEventListeners();
}
- componentDidUpdate () {
- this.setState({ zoomState: this.state.scale >= this.state.zoomMatrix.rate ? 'compress' : 'expand' });
-
- if (this.state.scale === MIN_SCALE) {
- this.container.style.removeProperty('cursor');
+ componentDidUpdate (prevProps) {
+ if (prevProps.zoomedIn !== this.props.zoomedIn) {
+ this._toggleZoom();
}
}
- UNSAFE_componentWillReceiveProps () {
- // reset when slide to next image
- if (this.props.zoomButtonHidden) {
- this.setState({
- scale: MIN_SCALE,
- lockTranslate: { x: 0, y: 0 },
- }, () => {
- this.container.scrollLeft = 0;
- this.container.scrollTop = 0;
- });
- }
- }
-
- removeEventListeners () {
+ _removeEventListeners () {
this.removers.forEach(listeners => listeners());
this.removers = [];
}
@@ -220,9 +191,6 @@ class ZoomableImage extends PureComponent {
};
mouseDownHandler = e => {
- this.container.style.cursor = 'grabbing';
- this.container.style.userSelect = 'none';
-
this.setState({ dragPosition: {
left: this.container.scrollLeft,
top: this.container.scrollTop,
@@ -246,9 +214,6 @@ class ZoomableImage extends PureComponent {
};
mouseUpHandler = () => {
- this.container.style.cursor = 'grab';
- this.container.style.removeProperty('user-select');
-
this.image.removeEventListener('mousemove', this.mouseMoveHandler);
this.image.removeEventListener('mouseup', this.mouseUpHandler);
};
@@ -276,13 +241,13 @@ class ZoomableImage extends PureComponent {
const _MAX_SCALE = Math.max(MAX_SCALE, this.state.zoomMatrix.rate);
const scale = clamp(MIN_SCALE, _MAX_SCALE, this.state.scale * distance / this.lastDistance);
- this.zoom(scale, midpoint);
+ this._zoom(scale, midpoint);
this.lastMidpoint = midpoint;
this.lastDistance = distance;
};
- zoom(nextScale, midpoint) {
+ _zoom(nextScale, midpoint) {
const { scale, zoomMatrix } = this.state;
const { scrollLeft, scrollTop } = this.container;
@@ -318,14 +283,13 @@ class ZoomableImage extends PureComponent {
if (dragged) return;
const handler = this.props.onClick;
if (handler) handler();
- this.setState({ navigationHidden: !this.state.navigationHidden });
};
handleMouseDown = e => {
e.preventDefault();
};
- initZoomMatrix = () => {
+ _initZoomMatrix = () => {
const { width, height } = this.props;
const { clientWidth, clientHeight } = this.container;
const { offsetWidth, offsetHeight } = this.image;
@@ -357,10 +321,7 @@ class ZoomableImage extends PureComponent {
});
};
- handleZoomClick = e => {
- e.preventDefault();
- e.stopPropagation();
-
+ _toggleZoom () {
const { scale, zoomMatrix } = this.state;
if ( scale >= zoomMatrix.rate ) {
@@ -394,10 +355,7 @@ class ZoomableImage extends PureComponent {
this.container.scrollTop = zoomMatrix.scrollTop;
});
}
-
- this.container.style.cursor = 'grab';
- this.container.style.removeProperty('user-select');
- };
+ }
setContainerRef = c => {
this.container = c;
@@ -408,52 +366,37 @@ class ZoomableImage extends PureComponent {
};
render () {
- const { alt, lang, src, width, height, intl } = this.props;
- const { scale, lockTranslate } = this.state;
+ const { alt, lang, src, width, height } = this.props;
+ const { scale, lockTranslate, dragged } = this.state;
const overflow = scale === MIN_SCALE ? 'hidden' : 'scroll';
- const zoomButtonShouldHide = this.state.navigationHidden || this.props.zoomButtonHidden || this.state.zoomMatrix.rate <= MIN_SCALE ? 'media-modal__zoom-button--hidden' : '';
- const zoomButtonTitle = this.state.zoomState === 'compress' ? intl.formatMessage(messages.compress) : intl.formatMessage(messages.expand);
+ const cursor = scale === MIN_SCALE ? null : (dragged ? 'grabbing' : 'grab');
return (
- <>
-
+
-
-
-
- >
+
);
}
-
}
-export default injectIntl(ZoomableImage);
+export default ZoomableImage;
diff --git a/app/javascript/mastodon/features/ui/containers/modal_container.js b/app/javascript/mastodon/features/ui/containers/modal_container.js
index 1c3872cd50..63c568f847 100644
--- a/app/javascript/mastodon/features/ui/containers/modal_container.js
+++ b/app/javascript/mastodon/features/ui/containers/modal_container.js
@@ -3,10 +3,12 @@ import { connect } from 'react-redux';
import { openModal, closeModal } from '../../../actions/modal';
import ModalRoot from '../components/modal_root';
+const defaultProps = {};
+
const mapStateToProps = state => ({
ignoreFocus: state.getIn(['modal', 'ignoreFocus']),
type: state.getIn(['modal', 'stack', 0, 'modalType'], null),
- props: state.getIn(['modal', 'stack', 0, 'modalProps'], {}),
+ props: state.getIn(['modal', 'stack', 0, 'modalProps'], defaultProps),
});
const mapDispatchToProps = dispatch => ({
diff --git a/app/javascript/mastodon/features/ui/containers/notifications_container.js b/app/javascript/mastodon/features/ui/containers/notifications_container.js
index 3d60cfdad1..b8aa9bc461 100644
--- a/app/javascript/mastodon/features/ui/containers/notifications_container.js
+++ b/app/javascript/mastodon/features/ui/containers/notifications_container.js
@@ -4,24 +4,11 @@ import { connect } from 'react-redux';
import { NotificationStack } from 'react-notification';
-import { dismissAlert } from '../../../actions/alerts';
-import { getAlerts } from '../../../selectors';
-
-const formatIfNeeded = (intl, message, values) => {
- if (typeof message === 'object') {
- return intl.formatMessage(message, values);
- }
-
- return message;
-};
+import { dismissAlert } from 'mastodon/actions/alerts';
+import { getAlerts } from 'mastodon/selectors';
const mapStateToProps = (state, { intl }) => ({
- notifications: getAlerts(state).map(alert => ({
- ...alert,
- action: formatIfNeeded(intl, alert.action, alert.values),
- title: formatIfNeeded(intl, alert.title, alert.values),
- message: formatIfNeeded(intl, alert.message, alert.values),
- })),
+ notifications: getAlerts(state, { intl }),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx
index f36e0cf501..2f9f962b81 100644
--- a/app/javascript/mastodon/features/ui/index.jsx
+++ b/app/javascript/mastodon/features/ui/index.jsx
@@ -85,7 +85,7 @@ const mapStateToProps = state => ({
isComposing: state.getIn(['compose', 'is_composing']),
hasComposingText: state.getIn(['compose', 'text']).trim().length !== 0,
hasMediaAttachments: state.getIn(['compose', 'media_attachments']).size > 0,
- canUploadMore: !state.getIn(['compose', 'media_attachments']).some(x => ['audio', 'video'].includes(x.get('type'))) && state.getIn(['compose', 'media_attachments']).size < 4,
+ canUploadMore: !state.getIn(['compose', 'media_attachments']).some(x => ['audio', 'video'].includes(x.get('type'))) && state.getIn(['compose', 'media_attachments']).size < state.getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments']),
firstLaunch: state.getIn(['settings', 'introductionVersion'], 0) < INTRODUCTION_VERSION,
username: state.getIn(['accounts', me, 'username']),
});
@@ -186,7 +186,7 @@ class SwitchingColumnsArea extends PureComponent {
{redirect}
{singleColumn ?
: null}
- {singleColumn && pathName.startsWith('/deck/') ?
: null}
+ {singleColumn && pathName.startsWith('/deck/') ?
: null}
{/* Redirect old bookmarks (without /deck) with home-like routes to the advanced interface */}
{!singleColumn && pathName === '/getting-started' ?
: null}
{!singleColumn && pathName === '/home' ?
: null}
@@ -319,8 +319,8 @@ class UI extends PureComponent {
try {
e.dataTransfer.dropEffect = 'copy';
- } catch (err) {
-
+ } catch {
+ // do nothing
}
return false;
diff --git a/app/javascript/mastodon/locales/an.json b/app/javascript/mastodon/locales/an.json
index 7974cea640..be303985ee 100644
--- a/app/javascript/mastodon/locales/an.json
+++ b/app/javascript/mastodon/locales/an.json
@@ -288,8 +288,6 @@
"keyboard_shortcuts.unfocus": "Retirar lo foco d'a caixa de redacción/busqueda",
"keyboard_shortcuts.up": "Ir enta alto en a lista",
"lightbox.close": "Zarrar",
- "lightbox.compress": "Comprimir quadro de visualización d'imachen",
- "lightbox.expand": "Expandir quadro de visualización d'imachen",
"lightbox.next": "Siguient",
"lightbox.previous": "Anterior",
"limited_account_hint.action": "Amostrar perfil de totz modos",
@@ -308,7 +306,6 @@
"lists.search": "Buscar entre la chent a la quala sigues",
"lists.subheading": "Las tuyas listas",
"load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}",
- "media_gallery.toggle_visible": "{number, plural, one {Amaga la imachen} other {Amaga las imáchens}}",
"moved_to_account_banner.text": "La tuya cuenta {disabledAccount} ye actualment deshabilitada perque t'has mudau a {movedToAccount}.",
"navigation_bar.about": "Sobre",
"navigation_bar.blocks": "Usuarios blocaus",
@@ -481,7 +478,6 @@
"status.detailed_status": "Vista de conversación detallada",
"status.edit": "Editar",
"status.edited_x_times": "Editau {count, plural, one {{count} vez} other {{count} veces}}",
- "status.embed": "Incrustado",
"status.filter": "Filtrar esta publicación",
"status.history.created": "{name} creyó {date}",
"status.history.edited": "{name} editó {date}",
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 8d3289ff45..17b288723b 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -3,7 +3,7 @@
"about.contact": "للاتصال:",
"about.disclaimer": "ماستدون برنامج حر ومفتوح المصدر وعلامة تجارية لـ Mastodon GmbH.",
"about.domain_blocks.no_reason_available": "السبب غير متوفر",
- "about.domain_blocks.preamble": "يسمح لك ماستدون عموماً بعرض المحتوى من المستخدمين من أي خادم آخر في الفدرالية والتفاعل معهم. وهذه هي الاستثناءات التي وضعت على هذا الخادم بالذات.",
+ "about.domain_blocks.preamble": "يتيح مَستُدون عمومًا لمستخدميه مطالعة المحتوى من المستخدمين من الخواديم الأخرى في الفدرالية والتفاعل معهم. وهذه هي الاستثناءات التي وضعت على هذا الخادوم.",
"about.domain_blocks.silenced.explanation": "لن تظهر لك ملفات التعريف الشخصية والمحتوى من هذا الخادوم، إلا إن بحثت عنه عمدًا أو تابعته.",
"about.domain_blocks.silenced.title": "محدود",
"about.domain_blocks.suspended.explanation": "لن يتم معالجة أي بيانات من هذا الخادم أو تخزينها أو تبادلها، مما يجعل أي تفاعل أو اتصال مع المستخدمين من هذا الخادم مستحيلا.",
@@ -34,8 +34,9 @@
"account.follow_back": "تابعه بالمثل",
"account.followers": "مُتابِعون",
"account.followers.empty": "لا أحدَ يُتابع هذا المُستخدم إلى حد الآن.",
- "account.followers_counter": "{count, plural, zero {}one {{counter} متابع} two {{counter} متابعين} few {{counter} متابعين} many {{counter} متابعين} other {{counter} متابعين}}",
+ "account.followers_counter": "{count, plural, zero{لا مُتابع} one {مُتابعٌ واحِد} two {مُتابعانِ اِثنان} few {{counter} مُتابِعين} many {{counter} مُتابِعًا} other {{counter} مُتابع}}",
"account.following": "الاشتراكات",
+ "account.following_counter": "{count, plural, zero{لا يُتابِع أحدًا} one {يُتابِعُ واحد} two{يُتابِعُ اِثنان} few{يُتابِعُ {counter}} many{يُتابِعُ {counter}} other {يُتابِعُ {counter}}}",
"account.follows.empty": "لا يُتابع هذا المُستخدمُ أيَّ أحدٍ حتى الآن.",
"account.go_to_profile": "اذهب إلى الملف الشخصي",
"account.hide_reblogs": "إخفاء المعاد نشرها مِن @{name}",
@@ -43,7 +44,7 @@
"account.joined_short": "انضم في",
"account.languages": "تغيير اللغات المشترَك فيها",
"account.link_verified_on": "تمَّ التَّحقق مِن مِلْكيّة هذا الرابط بتاريخ {date}",
- "account.locked_info": "تمَّ تعيين حالة خصوصية هذا الحساب إلى مُقفَل. يُراجع المالك يدويًا من يمكنه متابعته.",
+ "account.locked_info": "تم ضبط حالة خصوصية هذا الحساب على أنه مؤمّن. إذ يراجع صاحبه يدويًا من يُسمح له بالمتابعة.",
"account.media": "وسائط",
"account.mention": "أذكُر @{name}",
"account.moved_to": "أشار {name} إلى أن حسابه الجديد الآن:",
@@ -95,6 +96,8 @@
"block_modal.title": "أتريد حظر هذا المستخدم؟",
"block_modal.you_wont_see_mentions": "لن تر المنشورات التي يُشار فيهم إليه.",
"boost_modal.combo": "يُمكنك الضّغط على {combo} لتخطي هذا في المرة المُقبلة",
+ "boost_modal.reblog": "أتريد إعادة نشر المنشور؟",
+ "boost_modal.undo_reblog": "أتريد إلغاء إعادة نشر المنشور؟",
"bundle_column_error.copy_stacktrace": "انسخ تقرير الخطأ",
"bundle_column_error.error.body": "لا يمكن تقديم الصفحة المطلوبة. قد يكون بسبب خطأ في التعليمات البرمجية، أو مشكلة توافق المتصفح.",
"bundle_column_error.error.title": "أوه لا!",
@@ -190,6 +193,8 @@
"confirmations.unfollow.confirm": "إلغاء المتابعة",
"confirmations.unfollow.message": "متأكد من أنك تريد إلغاء متابعة {name} ؟",
"confirmations.unfollow.title": "إلغاء متابعة المستخدم؟",
+ "content_warning.hide": "إخفاء المنشور",
+ "content_warning.show": "إظهار على أي حال",
"conversation.delete": "احذف المحادثة",
"conversation.mark_as_read": "اعتبرها كمقروءة",
"conversation.open": "اعرض المحادثة",
@@ -225,10 +230,10 @@
"domain_pill.their_username": "مُعرّفُهم الفريد على الخادم. من الممكن العثور على مستخدمين بنفس اسم المستخدم على خوادم مختلفة.",
"domain_pill.username": "اسم المستخدم",
"domain_pill.whats_in_a_handle": "ما المقصود بالمُعرِّف؟",
- "domain_pill.who_they_are": "بما أن المعرفات تقول من هو الشخص ومكان وجوده، يمكنك التفاعل مع الناس عبر الويب الاجتماعي لل
منصات التي تعمل ب ActivityPub.",
- "domain_pill.who_you_are": "بما أن معرفك يقول من أنت ومكان وجوده، يمكن للناس التفاعل معك عبر الويب الاجتماعي لل
منصات التي تعمل ب ActivityPub.",
+ "domain_pill.who_they_are": "بما أن المُعرّفات تحدد هوية الشخص ومكان وجوده، فبإمكانك التفاعل مع الأشخاص عبر الويب الاجتماعي لـ
المنصات التي تعمل بواسطة أكتيفيتي بوب.",
+ "domain_pill.who_you_are": "بما أن مُعرّفك يحدد هويتك ومكان وجوده، فبإمكانك الآخرين التفاعل معك عبر الويب الاجتماعي لـ
المنصات التي تعمل بواسطة أكتيفيتي بوب.",
"domain_pill.your_handle": "عنوانك الكامل:",
- "domain_pill.your_server": "منزلك الرقمي، حيث تعيش جميع مشاركاتك. لا تحب هذا؟ إنقل الخوادم في أي وقت واخضر متابعينك أيضًا.",
+ "domain_pill.your_server": "موطِنك الرقمي، حيث توجد فيه كافة منشوراتك. ألا يعجبك المكان؟ يمكنك الانتقال بين الخوادم في أي وقت واصطحاب متابعيك أيضاً.",
"domain_pill.your_username": "معرفك الفريد على هذا الخادم. من الممكن العثور على مستخدمين بنفس إسم المستخدم على خوادم مختلفة.",
"embed.instructions": "يمكنكم إدماج هذا المنشور على موقعكم الإلكتروني عن طريق نسخ الشفرة أدناه.",
"embed.preview": "إليك ما سيبدو عليه:",
@@ -288,7 +293,7 @@
"filter_modal.added.review_and_configure": "لمراجعة وزيادة تكوين فئة عوامل التصفية هذه، انتقل إلى {settings_link}.",
"filter_modal.added.review_and_configure_title": "إعدادات التصفية",
"filter_modal.added.settings_link": "صفحة الإعدادات",
- "filter_modal.added.short_explanation": "تمت إضافة هذه المشاركة إلى فئة الفلاتر التالية: {title}.",
+ "filter_modal.added.short_explanation": "تمت إضافة هذا المنشور إلى فئة عوامل التصفية التالية: {title}.",
"filter_modal.added.title": "تمت إضافة عامل التصفية!",
"filter_modal.select_filter.context_mismatch": "لا ينطبق على هذا السياق",
"filter_modal.select_filter.expired": "منتهية الصلاحيّة",
@@ -297,6 +302,7 @@
"filter_modal.select_filter.subtitle": "استخدم فئة موجودة أو قم بإنشاء فئة جديدة",
"filter_modal.select_filter.title": "تصفية هذا المنشور",
"filter_modal.title.status": "تصفية منشور",
+ "filter_warning.matches_filter": "يطابق عامل التصفية \"{title}\"",
"filtered_notifications_banner.title": "الإشعارات المصفاة",
"firehose.all": "الكل",
"firehose.local": "هذا الخادم",
@@ -304,7 +310,7 @@
"follow_request.authorize": "ترخيص",
"follow_request.reject": "رفض",
"follow_requests.unlocked_explanation": "حتى وإن كان حسابك غير مقفل، يعتقد فريق {domain} أنك قد ترغب في مراجعة طلبات المتابعة من هذه الحسابات يدوياً.",
- "follow_suggestions.curated_suggestion": "اختيار الموظفين",
+ "follow_suggestions.curated_suggestion": "انتقاه الفريق",
"follow_suggestions.dismiss": "لا تُظهرها مجدّدًا",
"follow_suggestions.featured_longer": "مختار يدوياً من قِبل فريق {domain}",
"follow_suggestions.friends_of_friends_longer": "مشهور بين الأشخاص الذين تتابعهم",
@@ -345,6 +351,10 @@
"hashtag.follow": "اتبع الوسم",
"hashtag.unfollow": "ألغِ متابعة الوسم",
"hashtags.and_other": "…و {count, plural, zero {} one {# واحد آخر} two {# اثنان آخران} few {# آخرون} many {# آخَرًا}other {# آخرون}}",
+ "hints.profiles.see_more_followers": "عرض المزيد من المتابعين على {domain}",
+ "hints.profiles.see_more_posts": "عرض المزيد من المنشورات من {domain}",
+ "hints.threads.replies_may_be_missing": "قد تكون الردود الواردة من الخوادم الأخرى غائبة.",
+ "hints.threads.see_more": "اطلع على المزيد من الردود على {domain}",
"home.column_settings.show_reblogs": "اعرض المعاد نشرها",
"home.column_settings.show_replies": "اعرض الردود",
"home.hide_announcements": "إخفاء الإعلانات",
@@ -353,8 +363,10 @@
"home.pending_critical_update.title": "تحديث أمان حرج متوفر!",
"home.show_announcements": "إظهار الإعلانات",
"ignore_notifications_modal.disclaimer": "لا يمكن لـ Mastodon إبلاغ المستخدمين بأنك قد تجاهلت إشعاراتهم. تجاهل الإشعارات لن يمنع إرسال الرسائل نفسها.",
+ "ignore_notifications_modal.filter_instead": "تصفيتها بدلا من ذلك",
"ignore_notifications_modal.ignore": "تجاهل الإشعارات",
"ignore_notifications_modal.limited_accounts_title": "تجاهل الإشعارات من الحسابات التي هي تحت الإشراف؟",
+ "ignore_notifications_modal.new_accounts_title": "تجاهل الإشعارات الصادرة من الحسابات الجديدة؟",
"interaction_modal.description.favourite": "بفضل حساب على ماستدون، يمكنك إضافة هذا المنشور إلى مفضلتك لإبلاغ الناشر عن تقديرك وكذا للاحتفاظ بالمنشور إلى وقت لاحق.",
"interaction_modal.description.follow": "بفضل حساب في ماستدون، يمكنك متابعة {name} وتلقي منشوراته في موجزات خيطك الرئيس.",
"interaction_modal.description.reblog": "مع حساب في ماستدون، يمكنك تعزيز هذا المنشور ومشاركته مع مُتابِعيك.",
@@ -408,8 +420,6 @@
"keyboard_shortcuts.unfocus": "لإلغاء التركيز على حقل النص أو نافذة البحث",
"keyboard_shortcuts.up": "للانتقال إلى أعلى القائمة",
"lightbox.close": "إغلاق",
- "lightbox.compress": "ضغط مربع عرض الصورة",
- "lightbox.expand": "توسيع مربع عرض الصور",
"lightbox.next": "التالي",
"lightbox.previous": "العودة",
"limited_account_hint.action": "إظهار الملف التعريفي على أي حال",
@@ -432,7 +442,7 @@
"lists.subheading": "قوائمك",
"load_pending": "{count, plural, one {# عنصر جديد} other {# عناصر جديدة}}",
"loading_indicator.label": "جاري التحميل…",
- "media_gallery.toggle_visible": "{number, plural, zero {} one {اخف الصورة} two {اخف الصورتين} few {اخف الصور} many {اخف الصور} other {اخف الصور}}",
+ "media_gallery.hide": "إخفاء",
"moved_to_account_banner.text": "حسابك {disabledAccount} معطل حاليًا لأنك انتقلت إلى {movedToAccount}.",
"mute_modal.hide_from_notifications": "إخفاء من قائمة الإشعارات",
"mute_modal.hide_options": "إخفاء الخيارات",
@@ -444,6 +454,7 @@
"mute_modal.you_wont_see_mentions": "لن تر المنشورات التي يُشار فيها إليه.",
"mute_modal.you_wont_see_posts": "سيكون بإمكانه رؤية منشوراتك، لكنك لن ترى منشوراته.",
"navigation_bar.about": "عن",
+ "navigation_bar.administration": "الإدارة",
"navigation_bar.advanced_interface": "افتحه في واجهة الويب المتقدمة",
"navigation_bar.blocks": "الحسابات المحجوبة",
"navigation_bar.bookmarks": "الفواصل المرجعية",
@@ -460,6 +471,7 @@
"navigation_bar.follows_and_followers": "المتابِعون والمتابَعون",
"navigation_bar.lists": "القوائم",
"navigation_bar.logout": "خروج",
+ "navigation_bar.moderation": "الإشراف",
"navigation_bar.mutes": "الحسابات المكتومة",
"navigation_bar.opened_in_classic_interface": "تُفتَح المنشورات والحسابات وغيرها من الصفحات الخاصة بشكل مبدئي على واجهة الويب التقليدية.",
"navigation_bar.personal": "شخصي",
@@ -481,7 +493,7 @@
"notification.mention": "إشارة",
"notification.moderation-warning.learn_more": "اعرف المزيد",
"notification.moderation_warning": "لقد تلقيت تحذيرًا بالإشراف",
- "notification.moderation_warning.action_delete_statuses": "تم إزالة بعض مشاركاتك.",
+ "notification.moderation_warning.action_delete_statuses": "تم حذف بعض من منشوراتك.",
"notification.moderation_warning.action_disable": "تم تعطيل حسابك.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "بعض من منشوراتك تم تصنيفها على أنها حساسة.",
"notification.moderation_warning.action_none": "لقد تلقى حسابك تحذيرا بالإشراف.",
@@ -499,22 +511,27 @@
"notification.status": "{name} نشر للتو",
"notification.update": "عدّلَ {name} منشورًا",
"notification_requests.accept": "موافقة",
+ "notification_requests.confirm_accept_multiple.title": "قبول طلبات الإشعار؟",
+ "notification_requests.confirm_dismiss_multiple.title": "تجاهل طلبات الإشعار؟",
"notification_requests.dismiss": "تخطي",
+ "notification_requests.edit_selection": "تعديل",
+ "notification_requests.exit_selection": "تمّ",
"notification_requests.explainer_for_limited_account": "تم تصفية الإشعارات من هذا الحساب لأن الحساب تم تقييده من قبل مشرف.",
+ "notification_requests.minimize_banner": "تصغير شريط الإشعارات المُصفاة",
"notification_requests.notifications_from": "إشعارات من {name}",
"notification_requests.title": "الإشعارات المصفاة",
+ "notification_requests.view": "عرض الإشعارات",
"notifications.clear": "مسح الإشعارات",
"notifications.clear_confirmation": "متأكد من أنك تود مسح جميع الإشعارات الخاصة بك و المتلقاة إلى حد الآن ؟",
+ "notifications.clear_title": "أترغب في مسح الإشعارات؟",
"notifications.column_settings.admin.report": "التبليغات الجديدة:",
"notifications.column_settings.admin.sign_up": "التسجيلات الجديدة:",
"notifications.column_settings.alert": "إشعارات سطح المكتب",
- "notifications.column_settings.beta.category": "ميزات تجريبية",
- "notifications.column_settings.beta.grouping": "جمّع الإشعارات",
"notifications.column_settings.favourite": "المفضلة:",
"notifications.column_settings.filter_bar.advanced": "عرض جميع الفئات",
"notifications.column_settings.filter_bar.category": "شريط التصفية السريعة",
"notifications.column_settings.follow": "متابعُون جُدُد:",
- "notifications.column_settings.follow_request": "الطلبات الجديد لِمتابَعتك:",
+ "notifications.column_settings.follow_request": "الطلبات الجديدة لِمتابَعتك:",
"notifications.column_settings.mention": "الإشارات:",
"notifications.column_settings.poll": "نتائج استطلاع الرأي:",
"notifications.column_settings.push": "الإشعارات",
@@ -713,6 +730,7 @@
"server_banner.about_active_users": "الأشخاص الذين يستخدمون هذا الخادم خلال الأيام الثلاثين الأخيرة (المستخدمون النشطون شهريًا)",
"server_banner.active_users": "مستخدم نشط",
"server_banner.administered_by": "يُديره:",
+ "server_banner.is_one_of_many": "{domain} هو واحد من بين العديد من خوادم ماستدون المستقلة التي يمكنك استخدامها للمشاركة في الفديفرس.",
"server_banner.server_stats": "إحصائيات الخادم:",
"sign_in_banner.create_account": "أنشئ حسابًا",
"sign_in_banner.sign_in": "تسجيل الدخول",
@@ -724,6 +742,7 @@
"status.bookmark": "أضفه إلى الفواصل المرجعية",
"status.cancel_reblog_private": "إلغاء إعادة النشر",
"status.cannot_reblog": "لا يمكن إعادة نشر هذا المنشور",
+ "status.continued_thread": "تكملة للخيط",
"status.copy": "انسخ رابط الرسالة",
"status.delete": "احذف",
"status.detailed_status": "تفاصيل المحادثة",
@@ -732,7 +751,7 @@
"status.edit": "تعديل",
"status.edited": "آخر تعديل يوم {date}",
"status.edited_x_times": "عُدّل {count, plural, zero {} one {مرةً واحدة} two {مرّتان} few {{count} مرات} many {{count} مرة} other {{count} مرة}}",
- "status.embed": "إدماج",
+ "status.embed": "الحصول على شيفرة الدمج",
"status.favourite": "فضّل",
"status.favourites": "{count, plural, zero {}one {مفضلة واحدة} two {مفضلتان} few {# مفضلات} many {# مفضلات} other {# مفضلات}}",
"status.filter": "تصفية هذا المنشور",
@@ -740,7 +759,7 @@
"status.history.edited": "عدله {name} {date}",
"status.load_more": "حمّل المزيد",
"status.media.open": "اضغط للفتح",
- "status.media.show": "اضغط للإظهار",
+ "status.media.show": "اضغط لإظهاره",
"status.media_hidden": "وسائط مخفية",
"status.mention": "أذكُر @{name}",
"status.more": "المزيد",
@@ -753,10 +772,11 @@
"status.reblog": "إعادة النشر",
"status.reblog_private": "إعادة النشر إلى الجمهور الأصلي",
"status.reblogged_by": "شارَكَه {name}",
- "status.reblogs": "{count, plural, one {تعزيز واحد} two {تعزيزتان} few {# تعزيزات} many {# تعزيزات} other {# تعزيزات}}",
+ "status.reblogs": "{count, plural, one {إعادة نشر واحدة} two {معاد نشرها مرتان} few {# إعادات نشر} many {# إعادات نشر} other {# إعادة نشر}}",
"status.reblogs.empty": "لم يقم أي أحد بمشاركة هذا المنشور بعد. عندما يقوم أحدهم بذلك سوف يظهر هنا.",
"status.redraft": "إزالة وإعادة الصياغة",
"status.remove_bookmark": "احذفه مِن الفواصل المرجعية",
+ "status.replied_in_thread": "رد في خيط",
"status.replied_to": "رَدًا على {name}",
"status.reply": "ردّ",
"status.replyAll": "رُد على الخيط",
diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json
index 74eb7021d3..219ea0d17c 100644
--- a/app/javascript/mastodon/locales/ast.json
+++ b/app/javascript/mastodon/locales/ast.json
@@ -268,7 +268,6 @@
"lists.search": "Buscar ente los perfiles que sigues",
"lists.subheading": "Les tos llistes",
"load_pending": "{count, plural, one {# elementu nuevu} other {# elementos nuevos}}",
- "media_gallery.toggle_visible": "{number, plural, one {Anubrir la imaxe} other {Anubrir les imáxenes}}",
"navigation_bar.about": "Tocante a",
"navigation_bar.blocks": "Perfiles bloquiaos",
"navigation_bar.bookmarks": "Marcadores",
@@ -298,7 +297,6 @@
"notifications.clear": "Borrar los avisos",
"notifications.column_settings.admin.report": "Informes nuevos:",
"notifications.column_settings.admin.sign_up": "Rexistros nuevos:",
- "notifications.column_settings.beta.category": "Funciones esperimentales",
"notifications.column_settings.follow": "Siguidores nuevos:",
"notifications.column_settings.follow_request": "Solicitúes de siguimientu nueves:",
"notifications.column_settings.mention": "Menciones:",
@@ -420,7 +418,6 @@
"status.direct": "Mentar a @{name} per privao",
"status.direct_indicator": "Mención privada",
"status.edited_x_times": "Editóse {count, plural, one {{count} vegada} other {{count} vegaes}}",
- "status.embed": "Empotrar",
"status.filter": "Peñerar esti artículu",
"status.history.created": "{name} creó {date}",
"status.history.edited": "{name} editó {date}",
diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json
index 6335b546d7..098c7a7e9d 100644
--- a/app/javascript/mastodon/locales/be.json
+++ b/app/javascript/mastodon/locales/be.json
@@ -192,6 +192,8 @@
"confirmations.unfollow.confirm": "Адпісацца",
"confirmations.unfollow.message": "Вы ўпэўненыя, што хочаце адпісацца ад {name}?",
"confirmations.unfollow.title": "Адпісацца ад карыстальніка?",
+ "content_warning.hide": "Схаваць допіс",
+ "content_warning.show": "Усё адно паказаць",
"conversation.delete": "Выдаліць размову",
"conversation.mark_as_read": "Адзначыць прачытаным",
"conversation.open": "Прагледзець размову",
@@ -299,6 +301,7 @@
"filter_modal.select_filter.subtitle": "Скарыстайцеся існуючай катэгорыяй або стварыце новую",
"filter_modal.select_filter.title": "Фільтраваць гэты допіс",
"filter_modal.title.status": "Фільтраваць допіс",
+ "filter_warning.matches_filter": "Адпавядае фільтру \"{title}\"",
"filtered_notifications_banner.pending_requests": "Ад {count, plural, =0 {# людзей якіх} one {# чалавека якіх} few {# чалавек якіх} many {# людзей якіх} other {# чалавека якіх}} вы магчыма ведаеце",
"filtered_notifications_banner.title": "Адфільтраваныя апавяшчэнні",
"firehose.all": "Усе",
@@ -355,6 +358,7 @@
"home.pending_critical_update.link": "Прагледзець абнаўленні",
"home.pending_critical_update.title": "Даступна крытычнае абнаўленне бяспекі!",
"home.show_announcements": "Паказаць аб'явы",
+ "ignore_notifications_modal.not_following_title": "Ігнараваць апавяшчэнні ад людзей на якіх вы не падпісаны?",
"interaction_modal.description.favourite": "Маючы ўліковы запіс Mastodon, вы можаце ўпадабаць гэты допіс, каб паведаміць аўтару, што ён вам падабаецца, і захаваць яго на будучыню.",
"interaction_modal.description.follow": "Маючы акаўнт у Mastodon, вы можаце падпісацца на {name}, каб бачыць яго/яе допісы ў сваёй хатняй стужцы.",
"interaction_modal.description.reblog": "З уліковым запісам Mastodon, вы можаце пашырыць гэты пост, каб падзяліцца ім са сваімі падпісчыкамі.",
@@ -408,8 +412,6 @@
"keyboard_shortcuts.unfocus": "Расфакусаваць тэкставую вобласць/пошукавы радок",
"keyboard_shortcuts.up": "Перамясціцца ўверх па спісе",
"lightbox.close": "Закрыць",
- "lightbox.compress": "Сціснуць бачную вобласць выявы",
- "lightbox.expand": "Павялічыць бачную вобласць выявы",
"lightbox.next": "Далей",
"lightbox.previous": "Назад",
"limited_account_hint.action": "Усе роўна паказваць профіль",
@@ -433,7 +435,6 @@
"lists.subheading": "Вашыя спісы",
"load_pending": "{count, plural, one {# новы элемент} few {# новыя элементы} many {# новых элементаў} other {# новых элементаў}}",
"loading_indicator.label": "Загрузка…",
- "media_gallery.toggle_visible": "{number, plural, one {Схаваць відарыс} other {Схаваць відарысы}}",
"moved_to_account_banner.text": "Ваш уліковы запіс {disabledAccount} зараз адключаны таму што вы перанесены на {movedToAccount}.",
"mute_modal.hide_from_notifications": "Схаваць з апавяшчэнняў",
"mute_modal.hide_options": "Схаваць опцыі",
@@ -504,7 +505,11 @@
"notification.status": "Новы допіс ад {name}",
"notification.update": "Допіс {name} адрэдагаваны",
"notification_requests.accept": "Прыняць",
+ "notification_requests.confirm_accept_multiple.title": "Прыняць запыты на апавяшчэнні?",
+ "notification_requests.confirm_dismiss_multiple.title": "Адхіліць запыты на апавяшчэнні?",
"notification_requests.dismiss": "Адхіліць",
+ "notification_requests.edit_selection": "Рэдагаваць",
+ "notification_requests.exit_selection": "Гатова",
"notification_requests.maximize": "Разгарнуць",
"notification_requests.minimize_banner": "Згарнуць банер адфільтраваных апавяшчэнняў",
"notification_requests.notifications_from": "Апавяшчэнні ад {name}",
@@ -516,8 +521,6 @@
"notifications.column_settings.admin.report": "Новыя скаргі:",
"notifications.column_settings.admin.sign_up": "Новыя ўваходы:",
"notifications.column_settings.alert": "Апавяшчэнні на працоўным стале",
- "notifications.column_settings.beta.category": "Эксперыментальныя функцыі",
- "notifications.column_settings.beta.grouping": "Групаваць апавяшчэннi",
"notifications.column_settings.favourite": "Упадабанае:",
"notifications.column_settings.filter_bar.advanced": "Паказаць усе катэгорыі",
"notifications.column_settings.filter_bar.category": "Панэль хуткай фільтрацыі",
@@ -741,7 +744,6 @@
"status.edit": "Рэдагаваць",
"status.edited": "Апошняе рэдагаванне {date}",
"status.edited_x_times": "Рэдагавана {count, plural, one {{count} раз} few {{count} разы} many {{count} разоў} other {{count} разу}}",
- "status.embed": "Убудаваць",
"status.favourite": "Упадабанае",
"status.favourites": "{count, plural, one {# упадабанае} few {# упадабаныя} many {# упадабаных} other {# упадабанага}}",
"status.filter": "Фільтраваць гэты допіс",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index 83d9c5343a..c8f8474e91 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -97,6 +97,8 @@
"block_modal.title": "Блокирате ли потребителя?",
"block_modal.you_wont_see_mentions": "Няма да виждате публикациите, които ги споменават.",
"boost_modal.combo": "Можете да натиснете {combo}, за да пропуснете това следващия път",
+ "boost_modal.reblog": "Подсилвате ли публикация?",
+ "boost_modal.undo_reblog": "Без подсилване на публикация ли?",
"bundle_column_error.copy_stacktrace": "Копиране на доклада за грешката",
"bundle_column_error.error.body": "Заявената страница не може да се изобрази. Това може да е заради грешка в кода ни или проблем със съвместимостта на браузъра.",
"bundle_column_error.error.title": "О, не!",
@@ -192,6 +194,7 @@
"confirmations.unfollow.confirm": "Без следване",
"confirmations.unfollow.message": "Наистина ли искате да не следвате {name}?",
"confirmations.unfollow.title": "Спирате ли да следвате потребителя?",
+ "content_warning.hide": "Скриване на публ.",
"conversation.delete": "Изтриване на разговора",
"conversation.mark_as_read": "Маркиране като прочетено",
"conversation.open": "Преглед на разговора",
@@ -348,6 +351,14 @@
"hashtag.follow": "Следване на хаштаг",
"hashtag.unfollow": "Спиране на следване на хаштаг",
"hashtags.and_other": "…и {count, plural, other {# още}}",
+ "hints.profiles.followers_may_be_missing": "Последователи за този профил може да липсват.",
+ "hints.profiles.follows_may_be_missing": "Последванията за този профил може да липсват.",
+ "hints.profiles.posts_may_be_missing": "Някои публикации от този профил може да липсват.",
+ "hints.profiles.see_more_followers": "Преглед на още последователи на {domain}",
+ "hints.profiles.see_more_follows": "Преглед на още последвания на {domain}",
+ "hints.profiles.see_more_posts": "Преглед на още публикации на {domain}",
+ "hints.threads.replies_may_be_missing": "Отговори от други сървъри може да липсват.",
+ "hints.threads.see_more": "Преглед на още отговори на {domain}",
"home.column_settings.show_reblogs": "Показване на подсилванията",
"home.column_settings.show_replies": "Показване на отговорите",
"home.hide_announcements": "Скриване на оповестяванията",
@@ -408,8 +419,6 @@
"keyboard_shortcuts.unfocus": "Разфокусиране на текстовото поле за съставяне/търсене",
"keyboard_shortcuts.up": "Преместване нагоре в списъка",
"lightbox.close": "Затваряне",
- "lightbox.compress": "Свиване на полето за преглед на образи",
- "lightbox.expand": "Разгъване на полето за преглед на образи",
"lightbox.next": "Напред",
"lightbox.previous": "Назад",
"limited_account_hint.action": "Показване на профила въпреки това",
@@ -433,7 +442,6 @@
"lists.subheading": "Вашите списъци",
"load_pending": "{count, plural, one {# нов елемент} other {# нови елемента}}",
"loading_indicator.label": "Зареждане…",
- "media_gallery.toggle_visible": "Скриване на {number, plural, one {изображение} other {изображения}}",
"moved_to_account_banner.text": "Вашият акаунт {disabledAccount} сега е изключен, защото се преместихте в {movedToAccount}.",
"mute_modal.hide_from_notifications": "Скриване от известията",
"mute_modal.hide_options": "Скриване на възможностите",
@@ -445,6 +453,7 @@
"mute_modal.you_wont_see_mentions": "Няма да виждате споменаващите ги публикации.",
"mute_modal.you_wont_see_posts": "Още могат да виждат публикациите ви, но вие техните не.",
"navigation_bar.about": "Относно",
+ "navigation_bar.administration": "Администрация",
"navigation_bar.advanced_interface": "Отваряне в разширен уебинтерфейс",
"navigation_bar.blocks": "Блокирани потребители",
"navigation_bar.bookmarks": "Отметки",
@@ -461,6 +470,7 @@
"navigation_bar.follows_and_followers": "Последвания и последователи",
"navigation_bar.lists": "Списъци",
"navigation_bar.logout": "Излизане",
+ "navigation_bar.moderation": "Модериране",
"navigation_bar.mutes": "Заглушени потребители",
"navigation_bar.opened_in_classic_interface": "Публикации, акаунти и други особени страници се отварят по подразбиране в класическия мрежови интерфейс.",
"navigation_bar.personal": "Лично",
@@ -476,10 +486,17 @@
"notification.admin.report_statuses": "{name} докладва {target} за {category}",
"notification.admin.report_statuses_other": "{name} докладва {target}",
"notification.admin.sign_up": "{name} се регистрира",
+ "notification.admin.sign_up.name_and_others": "{name} и {count, plural, one {# друг} other {# други}} се регистрираха",
"notification.favourite": "{name} направи любима публикацията ви",
+ "notification.favourite.name_and_others_with_link": "{name} и
{count, plural, one {# друг} other {# други}} направиха любима ваша публикация",
"notification.follow": "{name} ви последва",
+ "notification.follow.name_and_others": "{name} и {count, plural, one {# друг} other {# други}} ви последваха",
"notification.follow_request": "{name} поиска да ви последва",
+ "notification.follow_request.name_and_others": "{name} и {count, plural, one {# друг} other {# други}} поискаха да ви последват",
"notification.label.mention": "Споменаване",
+ "notification.label.private_mention": "Частно споменаване",
+ "notification.label.private_reply": "Личен отговор",
+ "notification.label.reply": "Отговор",
"notification.mention": "Споменаване",
"notification.moderation-warning.learn_more": "Научете повече",
"notification.moderation_warning": "Получихте предупреждение за модериране",
@@ -493,6 +510,7 @@
"notification.own_poll": "Анкетата ви приключи",
"notification.poll": "Анкета, в която гласувахте, приключи",
"notification.reblog": "{name} подсили ваша публикация",
+ "notification.reblog.name_and_others_with_link": "{name} и
{count, plural, one {# друг} other {# други}} подсилиха ваша публикация",
"notification.relationships_severance_event": "Изгуби се връзката с {name}",
"notification.relationships_severance_event.account_suspension": "Администратор от {from} спря {target}, което значи че повече не може да получавате новости от тях или да взаимодействате с тях.",
"notification.relationships_severance_event.domain_block": "Администратор от {from} блокира {target}, вкючващо {followersCount} от последователите ви и {followingCount, plural, one {# акаунт, който} other {# акаунта, които}} следвате.",
@@ -501,6 +519,9 @@
"notification.status": "{name} току-що публикува",
"notification.update": "{name} промени публикация",
"notification_requests.accept": "Приемам",
+ "notification_requests.confirm_accept_multiple.message": "На път сте да приемете {count, plural, one {едно известие за заявка} other {# известия за заявки}}. Наистина ли искате да продължите?",
+ "notification_requests.confirm_accept_multiple.title": "Приемате ли заявките за известие?",
+ "notification_requests.confirm_dismiss_multiple.title": "Отхвърляте ли заявките за известие?",
"notification_requests.dismiss": "Отхвърлям",
"notification_requests.edit_selection": "Редактиране",
"notification_requests.exit_selection": "Готово",
@@ -517,8 +538,6 @@
"notifications.column_settings.admin.report": "Нови доклади:",
"notifications.column_settings.admin.sign_up": "Нови регистрации:",
"notifications.column_settings.alert": "Известия на работния плот",
- "notifications.column_settings.beta.category": "Експериментални функции",
- "notifications.column_settings.beta.grouping": "Групови известия",
"notifications.column_settings.favourite": "Любими:",
"notifications.column_settings.filter_bar.advanced": "Показване на всички категории",
"notifications.column_settings.filter_bar.category": "Лента за бърз филтър",
@@ -560,6 +579,7 @@
"notifications.policy.filter_not_following_title": "Хора, които не следвате",
"notifications.policy.filter_private_mentions_hint": "Филтрирано, освен ако е отговор към ваше собствено споменаване или ако следвате подателя",
"notifications.policy.filter_private_mentions_title": "Непоискани частни споменавания",
+ "notifications.policy.title": "Управление на известията от…",
"notifications_permission_banner.enable": "Включване на известията на работния плот",
"notifications_permission_banner.how_to_control": "За да получавате известия, когато Mastodon не е отворен, включете известията на работния плот. Може да управлявате точно кои видове взаимодействия пораждат известия на работния плот чрез бутона {icon} по-горе, след като бъдат включени.",
"notifications_permission_banner.title": "Никога не пропускайте нищо",
@@ -742,7 +762,6 @@
"status.edit": "Редактиране",
"status.edited": "Последно редактирано на {date}",
"status.edited_x_times": "Редактирано {count, plural,one {{count} път} other {{count} пъти}}",
- "status.embed": "Вграждане",
"status.favourite": "Любимо",
"status.favourites": "{count, plural, one {любимо} other {любими}}",
"status.filter": "Филтриране на публ.",
diff --git a/app/javascript/mastodon/locales/bn.json b/app/javascript/mastodon/locales/bn.json
index 584bf303b1..9512f6a92b 100644
--- a/app/javascript/mastodon/locales/bn.json
+++ b/app/javascript/mastodon/locales/bn.json
@@ -288,7 +288,6 @@
"lists.search": "যাদের অনুসরণ করেন তাদের ভেতরে খুঁজুন",
"lists.subheading": "আপনার তালিকা",
"load_pending": "{count, plural, one {# নতুন জিনিস} other {# নতুন জিনিস}}",
- "media_gallery.toggle_visible": "দৃশ্যতার অবস্থা বদলান",
"navigation_bar.about": "পরিচিতি",
"navigation_bar.blocks": "বন্ধ করা ব্যবহারকারী",
"navigation_bar.bookmarks": "বুকমার্ক",
@@ -409,7 +408,6 @@
"status.detailed_status": "বিস্তারিত কথোপকথনের হিসেবে দেখতে",
"status.edit": "সম্পাদন",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "এমবেড করতে",
"status.favourite": "পছন্দ",
"status.load_more": "আরো দেখুন",
"status.media_hidden": "মিডিয়া লুকানো আছে",
diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json
index c8bb4975de..79949ed91f 100644
--- a/app/javascript/mastodon/locales/br.json
+++ b/app/javascript/mastodon/locales/br.json
@@ -338,8 +338,6 @@
"keyboard_shortcuts.unfocus": "Difokus an dachenn testenn/klask",
"keyboard_shortcuts.up": "Pignat er roll",
"lightbox.close": "Serriñ",
- "lightbox.compress": "Bihanaat boest hewel ar skeudenn",
- "lightbox.expand": "Ledanaat boest hewel ar skeudenn",
"lightbox.next": "Da-heul",
"lightbox.previous": "A-raok",
"limited_account_hint.action": "Diskouez an aelad memes tra",
@@ -360,7 +358,6 @@
"lists.subheading": "Ho listennoù",
"load_pending": "{count, plural, one {# dra nevez} other {# dra nevez}}",
"loading_indicator.label": "O kargañ…",
- "media_gallery.toggle_visible": "{number, plural, one {Kuzhat ar skeudenn} other {Kuzhat ar skeudenn}}",
"navigation_bar.about": "Diwar-benn",
"navigation_bar.blocks": "Implijer·ezed·ien berzet",
"navigation_bar.bookmarks": "Sinedoù",
@@ -576,7 +573,6 @@
"status.edit": "Kemmañ",
"status.edited": "Kemmet da ziwezhañ d'an {date}",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "Enframmañ",
"status.favourite": "Muiañ-karet",
"status.filter": "Silañ ar c'hannad-mañ",
"status.history.created": "Krouet gant {name} {date}",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index 727c161873..710ac594f5 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -97,6 +97,8 @@
"block_modal.title": "Bloquem l'usuari?",
"block_modal.you_wont_see_mentions": "No veureu publicacions que l'esmentin.",
"boost_modal.combo": "Pots prémer {combo} per a evitar-ho el pròxim cop",
+ "boost_modal.reblog": "Voleu impulsar la publicació?",
+ "boost_modal.undo_reblog": "Voleu retirar l'impuls a la publicació?",
"bundle_column_error.copy_stacktrace": "Copia l'informe d'error",
"bundle_column_error.error.body": "No s'ha pogut renderitzar la pàgina sol·licitada. Podria ser per un error en el nostre codi o per un problema de compatibilitat del navegador.",
"bundle_column_error.error.title": "Oh, no!",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Descentra l'àrea de composició de text/cerca",
"keyboard_shortcuts.up": "Apuja a la llista",
"lightbox.close": "Tanca",
- "lightbox.compress": "Comprimeix el quadre de visualització d’imatge",
- "lightbox.expand": "Amplia el quadre de visualització d’imatge",
"lightbox.next": "Següent",
"lightbox.previous": "Anterior",
+ "lightbox.zoom_in": "Amplia fins a la mida real",
+ "lightbox.zoom_out": "Amplia fins a encabir",
"limited_account_hint.action": "Mostra el perfil de totes maneres",
"limited_account_hint.title": "Aquest perfil l'han amagat els moderadors de {domain}.",
"link_preview.author": "Per {name}",
@@ -455,7 +457,7 @@
"lists.subheading": "Les teves llistes",
"load_pending": "{count, plural, one {# element nou} other {# elements nous}}",
"loading_indicator.label": "Es carrega…",
- "media_gallery.toggle_visible": "{number, plural, one {Amaga la imatge} other {Amaga les imatges}}",
+ "media_gallery.hide": "Amaga",
"moved_to_account_banner.text": "El teu compte {disabledAccount} està desactivat perquè l'has mogut a {movedToAccount}.",
"mute_modal.hide_from_notifications": "Amaga de les notificacions",
"mute_modal.hide_options": "Amaga les opcions",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "No veureu publicacions que els esmentin.",
"mute_modal.you_wont_see_posts": "Encara poden veure les vostres publicacions, però no veureu les seves.",
"navigation_bar.about": "Quant a",
+ "navigation_bar.administration": "Administració",
"navigation_bar.advanced_interface": "Obre en la interfície web avançada",
"navigation_bar.blocks": "Usuaris blocats",
"navigation_bar.bookmarks": "Marcadors",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Seguint i seguidors",
"navigation_bar.lists": "Llistes",
"navigation_bar.logout": "Tanca la sessió",
+ "navigation_bar.moderation": "Moderació",
"navigation_bar.mutes": "Usuaris silenciats",
"navigation_bar.opened_in_classic_interface": "Els tuts, comptes i altres pàgines especifiques s'obren per defecte en la interfície web clàssica.",
"navigation_bar.personal": "Personal",
@@ -555,8 +559,6 @@
"notifications.column_settings.admin.report": "Nous informes:",
"notifications.column_settings.admin.sign_up": "Registres nous:",
"notifications.column_settings.alert": "Notificacions d'escriptori",
- "notifications.column_settings.beta.category": "Característiques experimentals",
- "notifications.column_settings.beta.grouping": "Notificacions de grup",
"notifications.column_settings.favourite": "Favorits:",
"notifications.column_settings.filter_bar.advanced": "Mostra totes les categories",
"notifications.column_settings.filter_bar.category": "Barra ràpida de filtres",
@@ -776,6 +778,7 @@
"status.bookmark": "Marca",
"status.cancel_reblog_private": "Desfés l'impuls",
"status.cannot_reblog": "No es pot impulsar aquest tut",
+ "status.continued_thread": "Continuació del fil",
"status.copy": "Copia l'enllaç al tut",
"status.delete": "Elimina",
"status.detailed_status": "Vista detallada de la conversa",
@@ -784,7 +787,7 @@
"status.edit": "Edita",
"status.edited": "Darrera edició {date}",
"status.edited_x_times": "Editat {count, plural, one {{count} vegada} other {{count} vegades}}",
- "status.embed": "Incrusta",
+ "status.embed": "Obté el codi encastat",
"status.favourite": "Favorit",
"status.favourites": "{count, plural, one {favorit} other {favorits}}",
"status.filter": "Filtra aquest tut",
@@ -809,6 +812,7 @@
"status.reblogs.empty": "Encara no ha impulsat ningú aquest tut. Quan algú ho faci, apareixerà aquí.",
"status.redraft": "Esborra i reescriu",
"status.remove_bookmark": "Elimina el marcador",
+ "status.replied_in_thread": "Respost al fil",
"status.replied_to": "En resposta a {name}",
"status.reply": "Respon",
"status.replyAll": "Respon al fil",
diff --git a/app/javascript/mastodon/locales/ckb.json b/app/javascript/mastodon/locales/ckb.json
index 9def7533ae..bea6e5ceec 100644
--- a/app/javascript/mastodon/locales/ckb.json
+++ b/app/javascript/mastodon/locales/ckb.json
@@ -335,8 +335,6 @@
"keyboard_shortcuts.unfocus": "بۆ دروستکردنی ناوچەی دەق/گەڕان",
"keyboard_shortcuts.up": "بۆ ئەوەی لە لیستەکەدا بڕۆیت",
"lightbox.close": "دابخە",
- "lightbox.compress": "سندوقی نیشاندانی وێنە بپەستێنە",
- "lightbox.expand": "فراوانکردنی سندوقی بینینی وێنە",
"lightbox.next": "داهاتوو",
"lightbox.previous": "پێشوو",
"limited_account_hint.action": "بەهەر حاڵ پڕۆفایلی پیشان بدە",
@@ -355,7 +353,6 @@
"lists.search": "بگەڕێ لەناو ئەو کەسانەی کە شوێنیان کەوتویت",
"lists.subheading": "لیستەکانت",
"load_pending": "{count, plural, one {# بەڕگەی نوێ} other {# بەڕگەی نوێ}}",
- "media_gallery.toggle_visible": "شاردنەوەی {number, plural, one {image} other {images}}",
"moved_to_account_banner.text": "ئەکاونتەکەت {disabledAccount} لە ئێستادا لەکارخراوە چونکە تۆ چوویتە {movedToAccount}.",
"navigation_bar.about": "دەربارە",
"navigation_bar.blocks": "بەکارهێنەرە بلۆککراوەکان",
@@ -540,7 +537,6 @@
"status.direct_indicator": "ئاماژەی تایبەت",
"status.edit": "دەستکاری",
"status.edited_x_times": "دەستکاریکراوە {count, plural, one {{count} کات} other {{count} کات}}",
- "status.embed": "نیشتەجێ بکە",
"status.filter": "ئەم پۆستە فلتەر بکە",
"status.history.created": "{name} دروستکراوە لە{date}",
"status.history.edited": "{name} دروستکاریکراوە لە{date}",
diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json
index 3a72ecd3fb..043061769b 100644
--- a/app/javascript/mastodon/locales/co.json
+++ b/app/javascript/mastodon/locales/co.json
@@ -196,8 +196,6 @@
"keyboard_shortcuts.unfocus": "ùn fucalizà più l'area di testu",
"keyboard_shortcuts.up": "cullà indè a lista",
"lightbox.close": "Chjudà",
- "lightbox.compress": "Cumprime a finestra d'affissera di i ritratti",
- "lightbox.expand": "Ingrandà a finestra d'affissera di i ritratti",
"lightbox.next": "Siguente",
"lightbox.previous": "Pricidente",
"lists.account.add": "Aghjunghje à a lista",
@@ -214,7 +212,6 @@
"lists.search": "Circà indè i vostr'abbunamenti",
"lists.subheading": "E vo liste",
"load_pending": "{count, plural, one {# entrata nova} other {# entrate nove}}",
- "media_gallery.toggle_visible": "Piattà {number, plural, one {ritrattu} other {ritratti}}",
"navigation_bar.blocks": "Utilizatori bluccati",
"navigation_bar.bookmarks": "Segnalibri",
"navigation_bar.community_timeline": "Linea pubblica lucale",
@@ -320,7 +317,6 @@
"status.delete": "Toglie",
"status.detailed_status": "Vista in ditagliu di a cunversazione",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "Integrà",
"status.load_more": "Vede di più",
"status.media_hidden": "Media piattata",
"status.mention": "Mintuvà @{name}",
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index ebfaef3675..b70ff3ee2b 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -97,6 +97,8 @@
"block_modal.title": "Zablokovat uživatele?",
"block_modal.you_wont_see_mentions": "Neuvidíte příspěvky, které ho zmiňují.",
"boost_modal.combo": "Příště můžete pro přeskočení stisknout {combo}",
+ "boost_modal.reblog": "Boostnout příspěvek?",
+ "boost_modal.undo_reblog": "Zrušit boostování příspěvku?",
"bundle_column_error.copy_stacktrace": "Zkopírovat zprávu o chybě",
"bundle_column_error.error.body": "Požadovanou stránku nelze vykreslit. Může to být způsobeno chybou v našem kódu nebo problémem s kompatibilitou prohlížeče.",
"bundle_column_error.error.title": "Ale ne!",
@@ -192,6 +194,7 @@
"confirmations.unfollow.confirm": "Přestat sledovat",
"confirmations.unfollow.message": "Opravdu chcete {name} přestat sledovat?",
"confirmations.unfollow.title": "Přestat sledovat uživatele?",
+ "content_warning.hide": "Skrýt příspěvek",
"conversation.delete": "Smazat konverzaci",
"conversation.mark_as_read": "Označit jako přečtené",
"conversation.open": "Zobrazit konverzaci",
@@ -407,8 +410,6 @@
"keyboard_shortcuts.unfocus": "Zrušit zaměření na nový příspěvek/hledání",
"keyboard_shortcuts.up": "Posunout v seznamu nahoru",
"lightbox.close": "Zavřít",
- "lightbox.compress": "Sbalit pole zobrazení obrázku",
- "lightbox.expand": "Rozbalit pole zobrazení obrázku",
"lightbox.next": "Další",
"lightbox.previous": "Předchozí",
"limited_account_hint.action": "Přesto profil zobrazit",
@@ -432,7 +433,6 @@
"lists.subheading": "Vaše seznamy",
"load_pending": "{count, plural, one {# nová položka} few {# nové položky} many {# nových položek} other {# nových položek}}",
"loading_indicator.label": "Načítání…",
- "media_gallery.toggle_visible": "{number, plural, one {Skrýt obrázek} few {Skrýt obrázky} many {Skrýt obrázky} other {Skrýt obrázky}}",
"moved_to_account_banner.text": "Váš účet {disabledAccount} je momentálně deaktivován, protože jste se přesunul/a na {movedToAccount}.",
"mute_modal.hide_from_notifications": "Skrýt z notifikací",
"mute_modal.hide_options": "Skrýt možnosti",
@@ -507,8 +507,6 @@
"notifications.column_settings.admin.report": "Nová hlášení:",
"notifications.column_settings.admin.sign_up": "Nové registrace:",
"notifications.column_settings.alert": "Oznámení na počítači",
- "notifications.column_settings.beta.category": "Experimentální funkce",
- "notifications.column_settings.beta.grouping": "Seskupit notifikace",
"notifications.column_settings.favourite": "Oblíbené:",
"notifications.column_settings.filter_bar.advanced": "Zobrazit všechny kategorie",
"notifications.column_settings.filter_bar.category": "Panel rychlého filtrování",
@@ -727,7 +725,6 @@
"status.edit": "Upravit",
"status.edited": "Naposledy upraveno {date}",
"status.edited_x_times": "Upraveno {count, plural, one {{count}krát} few {{count}krát} many {{count}krát} other {{count}krát}}",
- "status.embed": "Vložit na web",
"status.favourite": "Oblíbit",
"status.favourites": "{count, plural, one {oblíbený} few {oblíbené} many {oblíbených} other {oblíbených}}",
"status.filter": "Filtrovat tento příspěvek",
diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json
index d029f6bad1..ec93a5b11b 100644
--- a/app/javascript/mastodon/locales/cy.json
+++ b/app/javascript/mastodon/locales/cy.json
@@ -1,5 +1,5 @@
{
- "about.blocks": "Gweinyddion sy'n cael eu cymedroli",
+ "about.blocks": "Gweinyddion gyda chymedrolwyr",
"about.contact": "Cysylltwch â:",
"about.disclaimer": "Mae Mastodon yn feddalwedd cod agored rhydd ac o dan hawlfraint Mastodon gGmbH.",
"about.domain_blocks.no_reason_available": "Nid yw'r rheswm ar gael",
@@ -95,15 +95,17 @@
"block_modal.they_cant_see_posts": "Nid ydynt yn gallu gweld eich postiadau ac ni fyddwch yn gweld eu rhai hwy.",
"block_modal.they_will_know": "Gallant weld eu bod wedi'u rhwystro.",
"block_modal.title": "Blocio defnyddiwr?",
- "block_modal.you_wont_see_mentions": "Ni welwch bostiadau sy'n sôn amdanynt.",
+ "block_modal.you_wont_see_mentions": "Fyddwch chi ddim yn gweld postiadau sy'n sôn amdanyn nhw.",
"boost_modal.combo": "Mae modd pwyso {combo} er mwyn hepgor hyn tro nesa",
+ "boost_modal.reblog": "Hybu postiad?",
+ "boost_modal.undo_reblog": "Dad-hybu postiad?",
"bundle_column_error.copy_stacktrace": "Copïo'r adroddiad gwall",
"bundle_column_error.error.body": "Nid oedd modd cynhyrchu'r dudalen honno. Gall fod oherwydd gwall yn ein cod neu fater cydnawsedd porwr.",
"bundle_column_error.error.title": "O na!",
"bundle_column_error.network.body": "Bu gwall wrth geisio llwytho'r dudalen hon. Gall hyn fod oherwydd anhawster dros-dro gyda'ch cysylltiad gwe neu'r gweinydd hwn.",
"bundle_column_error.network.title": "Gwall rhwydwaith",
"bundle_column_error.retry": "Ceisiwch eto",
- "bundle_column_error.return": "Mynd nôl adref",
+ "bundle_column_error.return": "Mynd i'r ffrwd gartref",
"bundle_column_error.routing.body": "Nid oedd modd canfod y dudalen honno. Ydych chi'n siŵr fod yr URL yn y bar cyfeiriad yn gywir?",
"bundle_column_error.routing.title": "404",
"bundle_modal_error.close": "Cau",
@@ -124,7 +126,7 @@
"column.favourites": "Ffefrynnau",
"column.firehose": "Ffrydiau byw",
"column.follow_requests": "Ceisiadau dilyn",
- "column.home": "Hafan",
+ "column.home": "Cartref",
"column.lists": "Rhestrau",
"column.mutes": "Defnyddwyr wedi'u tewi",
"column.notifications": "Hysbysiadau",
@@ -145,7 +147,7 @@
"compose.language.search": "Chwilio ieithoedd...",
"compose.published.body": "Postiad wedi ei gyhoeddi.",
"compose.published.open": "Agor",
- "compose.saved.body": "Post wedi'i gadw.",
+ "compose.saved.body": "Postiad wedi'i gadw.",
"compose_form.direct_message_warning_learn_more": "Dysgu mwy",
"compose_form.encryption_warning": "Dyw postiadau ar Mastodon ddim wedi'u hamgryptio o ben i ben. Peidiwch â rhannu unrhyw wybodaeth sensitif dros Mastodon.",
"compose_form.hashtag_warning": "Ni fydd y postiad hwn wedi ei restru o dan unrhyw hashnod gan nad yw'n gyhoeddus. Dim ond postiadau cyhoeddus y mae modd eu chwilio drwy hashnod.",
@@ -170,7 +172,7 @@
"confirmations.block.confirm": "Blocio",
"confirmations.delete.confirm": "Dileu",
"confirmations.delete.message": "Ydych chi'n sicr eich bod eisiau dileu y post hwn?",
- "confirmations.delete.title": "Dileu post?",
+ "confirmations.delete.title": "Dileu postiad?",
"confirmations.delete_list.confirm": "Dileu",
"confirmations.delete_list.message": "Ydych chi'n siŵr eich bod eisiau dileu'r rhestr hwn am byth?",
"confirmations.delete_list.title": "Dileu rhestr?",
@@ -178,20 +180,22 @@
"confirmations.discard_edit_media.message": "Mae gennych newidiadau heb eu cadw i'r disgrifiad cyfryngau neu'r rhagolwg - eu dileu beth bynnag?",
"confirmations.edit.confirm": "Golygu",
"confirmations.edit.message": "Bydd golygu nawr yn trosysgrifennu'r neges rydych yn ei ysgrifennu ar hyn o bryd. Ydych chi'n siŵr eich bod eisiau gwneud hyn?",
- "confirmations.edit.title": "Trosysgrifo post?",
+ "confirmations.edit.title": "Trosysgrifo'r postiad?",
"confirmations.logout.confirm": "Allgofnodi",
"confirmations.logout.message": "Ydych chi'n siŵr eich bod am allgofnodi?",
"confirmations.logout.title": "Allgofnodi?",
"confirmations.mute.confirm": "Tewi",
"confirmations.redraft.confirm": "Dileu ac ailddrafftio",
- "confirmations.redraft.message": "Ydych chi'n siŵr eich bod am ddileu'r postiad hwn a'i ailddrafftio? Bydd ffefrynnau a hybiau'n cael eu colli, a bydd atebion i'r post gwreiddiol yn mynd yn amddifad.",
- "confirmations.redraft.title": "Dileu & ailddraftio post?",
+ "confirmations.redraft.message": "Ydych chi wir eisiau'r dileu'r postiad hwn a'i ailddrafftio? Bydd ffefrynnau a hybiau'n cael eu colli, a bydd atebion i'r post gwreiddiol yn mynd yn amddifad.",
+ "confirmations.redraft.title": "Dileu & ailddraftio postiad?",
"confirmations.reply.confirm": "Ateb",
"confirmations.reply.message": "Bydd ateb nawr yn cymryd lle y neges yr ydych yn cyfansoddi ar hyn o bryd. Ydych chi'n siŵr eich bod am barhau?",
- "confirmations.reply.title": "Trosysgrifo post?",
+ "confirmations.reply.title": "Trosysgrifo'r postiad?",
"confirmations.unfollow.confirm": "Dad-ddilyn",
"confirmations.unfollow.message": "Ydych chi'n siŵr eich bod am ddad-ddilyn {name}?",
"confirmations.unfollow.title": "Dad-ddilyn defnyddiwr?",
+ "content_warning.hide": "Cuddio'r postiad",
+ "content_warning.show": "Dangos beth bynnag",
"conversation.delete": "Dileu sgwrs",
"conversation.mark_as_read": "Nodi fel wedi'i ddarllen",
"conversation.open": "Gweld sgwrs",
@@ -208,7 +212,7 @@
"dismissable_banner.community_timeline": "Dyma'r postiadau cyhoeddus diweddaraf gan bobl sydd â chyfrifon ar {domain}.",
"dismissable_banner.dismiss": "Cau",
"dismissable_banner.explore_links": "Dyma straeon newyddion sy’n cael eu rhannu fwyaf ar y we gymdeithasol heddiw. Mae'r straeon newyddion diweddaraf sy'n cael eu postio gan fwy o unigolion gwahanol yn cael eu graddio'n uwch.",
- "dismissable_banner.explore_statuses": "Mae'r rhain yn bostiadau o bob rhan o'r we gymdeithasol sydd ar gynnydd heddiw. Mae postiadau mwy diweddar sydd â mwy o hybiau a ffefrynu'n cael eu graddio'n uwch.",
+ "dismissable_banner.explore_statuses": "Dyma postiadau o bob gwr o'r we gymdeithasol sy'n derbyn sylw heddiw. Mae postiadau mwy diweddar sydd â mwy o hybiau a ffefrynnau'n cael eu graddio'n uwch.",
"dismissable_banner.explore_tags": "Mae'r rhain yn hashnodau sydd ar gynnydd ar y we gymdeithasol heddiw. Mae hashnodau sy'n cael eu defnyddio gan fwy o unigolion gwahanol yn cael eu graddio'n uwch.",
"dismissable_banner.public_timeline": "Dyma'r postiadau cyhoeddus diweddaraf gan bobl ar y we gymdeithasol y mae pobl ar {domain} yn eu dilyn.",
"domain_block_modal.block": "Blocio gweinydd",
@@ -254,17 +258,17 @@
"empty_column.account_timeline": "Dim postiadau yma!",
"empty_column.account_unavailable": "Nid yw'r proffil ar gael",
"empty_column.blocks": "Nid ydych wedi blocio unrhyw ddefnyddwyr eto.",
- "empty_column.bookmarked_statuses": "Nid oes gennych unrhyw bostiad wedi'u cadw fel llyfrnodau eto. Pan fyddwch yn gosod nod tudalen i un, mi fydd yn ymddangos yma.",
+ "empty_column.bookmarked_statuses": "Nid oes gennych unrhyw bostiad wedi'u cadw fel nod tudalen eto. Pan fyddwch yn gosod nod tudalen i un, mi fydd yn ymddangos yma.",
"empty_column.community": "Mae'r ffrwd lleol yn wag. Beth am ysgrifennu rhywbeth cyhoeddus!",
"empty_column.direct": "Nid oes gennych unrhyw grybwylliadau preifat eto. Pan fyddwch chi'n anfon neu'n derbyn un, bydd yn ymddangos yma.",
"empty_column.domain_blocks": "Nid oes unrhyw barthau wedi'u blocio eto.",
- "empty_column.explore_statuses": "Does dim yn trendio ar hyn o bryd. Dewch nôl nes ymlaen!",
- "empty_column.favourited_statuses": "Nid oes gennych unrhyw hoff bostiadau eto. Pan byddwch yn hoffi un, bydd yn ymddangos yma.",
- "empty_column.favourites": "Nid oes unrhyw un wedi hoffi'r postiad hwn eto. Pan fydd rhywun yn gwneud hynny, byddan nhw'n ymddangos yma.",
+ "empty_column.explore_statuses": "Does dim pynciau llosg ar hyn o bryd. Dewch nôl nes ymlaen!",
+ "empty_column.favourited_statuses": "Rydych chi heb ffafrio unrhyw bostiadau eto. Pan byddwch chi'n ffafrio un, bydd yn ymddangos yma.",
+ "empty_column.favourites": "Nid oes unrhyw un wedi ffafrio'r postiad hwn eto. Pan fydd rhywun yn gwneud hynny, byddan nhw'n ymddangos yma.",
"empty_column.follow_requests": "Nid oes gennych unrhyw geisiadau dilyn eto. Pan fyddwch yn derbyn un, byddan nhw'n ymddangos yma.",
"empty_column.followed_tags": "Nid ydych wedi dilyn unrhyw hashnodau eto. Pan fyddwch chi'n gwneud hynny, byddan nhw'n ymddangos yma.",
"empty_column.hashtag": "Nid oes dim ar yr hashnod hwn eto.",
- "empty_column.home": "Mae eich ffrwd gartref yn wag! Ymwelwch â {public} neu defnyddiwch y chwilotwr i ddechrau arni ac i gwrdd â defnyddwyr eraill.",
+ "empty_column.home": "Mae eich ffrwd gartref yn wag! Dilynwch fwy o bobl i'w llenwi.",
"empty_column.list": "Does dim yn y rhestr yma eto. Pan fydd aelodau'r rhestr yn cyhoeddi postiad newydd, mi fydd yn ymddangos yma.",
"empty_column.lists": "Nid oes gennych unrhyw restrau eto. Pan fyddwch yn creu un, mi fydd yn ymddangos yma.",
"empty_column.mutes": "Nid ydych wedi tewi unrhyw ddefnyddwyr eto.",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Defnyddiwch gategori sy'n bodoli eisoes neu crëu un newydd",
"filter_modal.select_filter.title": "Hidlo'r postiad hwn",
"filter_modal.title.status": "Hidlo postiad",
+ "filter_warning.matches_filter": "Yn cydweddu'r hidlydd “{title}”",
"filtered_notifications_banner.pending_requests": "Gan {count, plural, =0 {no one} one {un person} two {# berson} few {# pherson} other {# person}} efallai eich bod yn eu hadnabod",
"filtered_notifications_banner.title": "Hysbysiadau wedi'u hidlo",
"firehose.all": "Popeth",
@@ -348,11 +353,19 @@
"hashtag.follow": "Dilyn hashnod",
"hashtag.unfollow": "Dad-ddilyn hashnod",
"hashtags.and_other": "…a {count, plural, other {# more}}",
+ "hints.profiles.followers_may_be_missing": "Mae'n bosibl bod dilynwyr y proffil hwn ar goll.",
+ "hints.profiles.follows_may_be_missing": "Mae'n bosibl bod dilynwyr y proffil hwn ar goll.",
+ "hints.profiles.posts_may_be_missing": "Mae'n bosibl bod rhai postiadau y proffil hwn ar goll.",
+ "hints.profiles.see_more_followers": "Gweld mwy o ddilynwyr ar {domain}",
+ "hints.profiles.see_more_follows": "Gweld mwy o 'yn dilyn' ar {domain}",
+ "hints.profiles.see_more_posts": "Gweld mwy o bostiadau ar {domain}",
+ "hints.threads.replies_may_be_missing": "Mae'n bosibl y bydd atebion gan weinyddion eraill ar goll.",
+ "hints.threads.see_more": "Gweld mwy o atebion ar {domain}",
"home.column_settings.show_reblogs": "Dangos hybiau",
"home.column_settings.show_replies": "Dangos atebion",
"home.hide_announcements": "Cuddio cyhoeddiadau",
"home.pending_critical_update.body": "Diweddarwch eich gweinydd Mastodon cyn gynted â phosibl!",
- "home.pending_critical_update.link": "Gweld y diweddariadau",
+ "home.pending_critical_update.link": "Gweld diweddariadau",
"home.pending_critical_update.title": "Mae diweddariad diogelwch hanfodol ar gael!",
"home.show_announcements": "Dangos cyhoeddiadau",
"ignore_notifications_modal.disclaimer": "Ni all Mastodon hysbysu defnyddwyr eich bod wedi anwybyddu eu hysbysiadau. Ni fydd anwybyddu hysbysiadau yn atal y negeseuon eu hunain rhag cael eu hanfon.",
@@ -366,18 +379,18 @@
"ignore_notifications_modal.not_followers_title": "Anwybyddu hysbysiadau gan bobl nad ydynt yn eich dilyn?",
"ignore_notifications_modal.not_following_title": "Anwybyddu hysbysiadau gan bobl nad ydych yn eu dilyn?",
"ignore_notifications_modal.private_mentions_title": "Anwybyddu hysbysiadau o Grybwylliadau Preifat digymell?",
- "interaction_modal.description.favourite": "Gyda chyfrif ar Mastodon, gallwch chi hoffi'r postiad hwn er mwyn roi gwybod i'r awdur eich bod chi'n ei werthfawrogi ac yn ei gadw ar gyfer nes ymlaen.",
- "interaction_modal.description.follow": "Gyda chyfrif ar Mastodon, gallwch ddilyn {name} i dderbyn eu postiadau yn eich llif cartref.",
+ "interaction_modal.description.favourite": "Gyda chyfrif ar Mastodon, gallwch chi ffafrio'r postiad hwn er mwyn roi gwybod i'r awdur eich bod chi'n ei werthfawrogi ac yn ei gadw ar gyfer nes ymlaen.",
+ "interaction_modal.description.follow": "Gyda chyfrif ar Mastodon, gallwch ddilyn {name} i dderbyn eu postiadau yn eich ffrwd gartref.",
"interaction_modal.description.reblog": "Gyda chyfrif ar Mastodon, gallwch hybu'r postiad hwn i'w rannu â'ch dilynwyr.",
"interaction_modal.description.reply": "Gyda chyfrif ar Mastodon, gallwch ymateb i'r postiad hwn.",
- "interaction_modal.login.action": "Ewch â fi adref",
+ "interaction_modal.login.action": "Mynd i'm ffrwd gartref",
"interaction_modal.login.prompt": "Parth eich gweinydd cartref, e.e. mastodon.social",
"interaction_modal.no_account_yet": "Dim ar Mastodon?",
"interaction_modal.on_another_server": "Ar weinydd gwahanol",
"interaction_modal.on_this_server": "Ar y gweinydd hwn",
"interaction_modal.sign_in": "Nid ydych wedi mewngofnodi i'r gweinydd hwn. Ble mae eich cyfrif yn cael ei gynnal?",
"interaction_modal.sign_in_hint": "Awgrym: Dyna'r wefan lle gwnaethoch gofrestru. Os nad ydych yn cofio, edrychwch am yr e-bost croeso yn eich blwch derbyn. Gallwch hefyd nodi eich enw defnyddiwr llawn! (e.e. @Mastodon@mastodon.social)",
- "interaction_modal.title.favourite": "Hoffi postiad {name}",
+ "interaction_modal.title.favourite": "Ffafrio postiad {name}",
"interaction_modal.title.follow": "Dilyn {name}",
"interaction_modal.title.reblog": "Hybu postiad {name}",
"interaction_modal.title.reply": "Ymateb i bostiad {name}",
@@ -393,11 +406,11 @@
"keyboard_shortcuts.direct": "i agor colofn crybwylliadau preifat",
"keyboard_shortcuts.down": "Symud lawr yn y rhestr",
"keyboard_shortcuts.enter": "Agor post",
- "keyboard_shortcuts.favourite": "Hoffi postiad",
+ "keyboard_shortcuts.favourite": "Ffafrio postiad",
"keyboard_shortcuts.favourites": "Agor rhestr ffefrynnau",
"keyboard_shortcuts.federated": "Agor ffrwd y ffederasiwn",
"keyboard_shortcuts.heading": "Bysellau brys",
- "keyboard_shortcuts.home": "Agor ffrwd cartref",
+ "keyboard_shortcuts.home": "Agor ffrwd gartref",
"keyboard_shortcuts.hotkey": "Bysell boeth",
"keyboard_shortcuts.legend": "Dangos y rhestr hon",
"keyboard_shortcuts.local": "Agor ffrwd lleol",
@@ -419,21 +432,19 @@
"keyboard_shortcuts.unfocus": "Dad-ffocysu ardal cyfansoddi testun/chwilio",
"keyboard_shortcuts.up": "Symud yn uwch yn y rhestr",
"lightbox.close": "Cau",
- "lightbox.compress": "Cywasgu blwch gweld delwedd",
- "lightbox.expand": "Ehangu blwch gweld delwedd",
"lightbox.next": "Nesaf",
"lightbox.previous": "Blaenorol",
"limited_account_hint.action": "Dangos y proffil beth bynnag",
"limited_account_hint.title": "Mae'r proffil hwn wedi cael ei guddio gan gymedrolwyr {domain}.",
"link_preview.author": "Gan {name}",
"link_preview.more_from_author": "Mwy gan {name}",
- "link_preview.shares": "{count, plural, one {{counter} post} two {{counter} bost} few {{counter} phost} many {{counter} post} other {{counter} post}}",
+ "link_preview.shares": "{count, plural, one {{counter} ostiad } two {{counter} bostiad } few {{counter} postiad} many {{counter} postiad} other {{counter} postiad}}",
"lists.account.add": "Ychwanegu at restr",
"lists.account.remove": "Tynnu o'r rhestr",
"lists.delete": "Dileu rhestr",
"lists.edit": "Golygu rhestr",
"lists.edit.submit": "Newid teitl",
- "lists.exclusive": "Cuddiwch y postiadau hyn rhag cartref",
+ "lists.exclusive": "Cuddio'r postiadau hyn o'r ffrwd gartref",
"lists.new.create": "Ychwanegu rhestr",
"lists.new.title_placeholder": "Teitl rhestr newydd",
"lists.replies_policy.followed": "Unrhyw ddefnyddiwr sy'n cael ei ddilyn",
@@ -444,7 +455,7 @@
"lists.subheading": "Eich rhestrau",
"load_pending": "{count, plural, one {# eitem newydd} other {# eitem newydd}}",
"loading_indicator.label": "Yn llwytho…",
- "media_gallery.toggle_visible": "{number, plural, one {Cuddio delwedd} other {Cuddio delwedd}}",
+ "media_gallery.hide": "Cuddio",
"moved_to_account_banner.text": "Ar hyn y bryd, mae eich cyfrif {disabledAccount} wedi ei analluogi am i chi symud i {movedToAccount}.",
"mute_modal.hide_from_notifications": "Cuddio rhag hysbysiadau",
"mute_modal.hide_options": "Cuddio'r dewis",
@@ -456,6 +467,7 @@
"mute_modal.you_wont_see_mentions": "Welwch chi ddim postiadau sy'n sôn amdanyn nhw.",
"mute_modal.you_wont_see_posts": "Gallan nhw weld eich postiadau o hyd, ond fyddwch chi ddim yn gweld eu rhai hwy.",
"navigation_bar.about": "Ynghylch",
+ "navigation_bar.administration": "Gweinyddiaeth",
"navigation_bar.advanced_interface": "Agor mewn rhyngwyneb gwe uwch",
"navigation_bar.blocks": "Defnyddwyr wedi eu blocio",
"navigation_bar.bookmarks": "Nodau Tudalen",
@@ -472,6 +484,7 @@
"navigation_bar.follows_and_followers": "Yn dilyn a dilynwyr",
"navigation_bar.lists": "Rhestrau",
"navigation_bar.logout": "Allgofnodi",
+ "navigation_bar.moderation": "Cymedroil",
"navigation_bar.mutes": "Defnyddwyr wedi'u tewi",
"navigation_bar.opened_in_classic_interface": "Mae postiadau, cyfrifon a thudalennau penodol eraill yn cael eu hagor fel rhagosodiad yn y rhyngwyneb gwe clasurol.",
"navigation_bar.personal": "Personol",
@@ -482,14 +495,18 @@
"navigation_bar.security": "Diogelwch",
"not_signed_in_indicator.not_signed_in": "Rhaid i chi fewngofnodi i weld yr adnodd hwn.",
"notification.admin.report": "Adroddwyd ar {name} {target}",
- "notification.admin.report_account": "{name} reported {count, plural, one {un post} other {# postsiadau}} from {target} for {category}",
- "notification.admin.report_account_other": "Adroddodd {name} {count, plural, one {un post} two {# bost} few {# phost} other {# post}} gan {target}",
+ "notification.admin.report_account": "{name} reported {count, plural, one {un postiad} other {# postiad}} from {target} for {category}",
+ "notification.admin.report_account_other": "Adroddodd {name} {count, plural, one {un postiad} two {# bostiad} few {# phost} other {# postiad}} gan {target}",
"notification.admin.report_statuses": "Adroddodd {name} {target} ar gyfer {category}",
"notification.admin.report_statuses_other": "Adroddodd {name} {target}",
"notification.admin.sign_up": "Cofrestrodd {name}",
- "notification.favourite": "Hoffodd {name} eich postiad",
+ "notification.admin.sign_up.name_and_others": "Cofrestrodd {name} {count, plural, one {ac # arall} other {a # eraill}}",
+ "notification.favourite": "Ffafriodd {name} eich postiad",
+ "notification.favourite.name_and_others_with_link": "Ffafriodd {name} a
{count, plural, one {# arall} other {# eraill}} eich postiad",
"notification.follow": "Dilynodd {name} chi",
+ "notification.follow.name_and_others": "Mae {name} a {count, plural, one {# other} other {# others}} wedi'ch dilyn chi",
"notification.follow_request": "Mae {name} wedi gwneud cais i'ch dilyn",
+ "notification.follow_request.name_and_others": "Mae {name} a{count, plural, one {# other} other {# others}} wedi gofyn i'ch dilyn chi",
"notification.label.mention": "Crybwyll",
"notification.label.private_mention": "Crybwyll preifat",
"notification.label.private_reply": "Ateb preifat",
@@ -507,6 +524,7 @@
"notification.own_poll": "Mae eich pleidlais wedi dod i ben",
"notification.poll": "Mae arolwg y gwnaethoch bleidleisio ynddo wedi dod i ben",
"notification.reblog": "Hybodd {name} eich post",
+ "notification.reblog.name_and_others_with_link": "Mae {name} a
{count, plural, one {# other} other {# others}} wedi hybu eich postiad",
"notification.relationships_severance_event": "Wedi colli cysylltiad â {name}",
"notification.relationships_severance_event.account_suspension": "Mae gweinyddwr o {from} wedi atal {target}, sy'n golygu na allwch dderbyn diweddariadau ganddynt mwyach na rhyngweithio â nhw.",
"notification.relationships_severance_event.domain_block": "Mae gweinyddwr o {from} wedi blocio {target}, gan gynnwys {followersCount} o'ch dilynwyr a {followingCount, plural, one {# cyfrif} other {# cyfrif}} arall rydych chi'n ei ddilyn.",
@@ -515,7 +533,17 @@
"notification.status": "{name} newydd ei bostio",
"notification.update": "Golygodd {name} bostiad",
"notification_requests.accept": "Derbyn",
+ "notification_requests.accept_multiple": "{count, plural, one {Accept # request…} other {Accept # requests…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Accept request} other {Accept requests}}",
+ "notification_requests.confirm_accept_multiple.message": "Rydych ar fin derbyn {count, plural, one {one notification request} other {# notification requests}}. Ydych chi'n siŵr eich bod am barhau?",
+ "notification_requests.confirm_accept_multiple.title": "Derbyn ceisiadau hysbysu?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Diystyru cais} other {Diystyru ceisiadau}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Rydych ar fin diystyru {count, plural, one {un cais hysbysu} other {# cais hysbysiad}}. Fyddwch chi ddim yn gallu cyrchu {count, plural, one {it} other {them}} yn hawdd eto. Ydych chi'n yn siŵr eich bod am fwrw ymlaen?",
+ "notification_requests.confirm_dismiss_multiple.title": "Diystyru ceisiadau hysbysu?",
"notification_requests.dismiss": "Cau",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Diystyru # cais…} two {Diystyru # gais…} few {Diystyru # chais…} other {Diystyru # cais…}}",
+ "notification_requests.edit_selection": "Golygu",
+ "notification_requests.exit_selection": "Iawn",
"notification_requests.explainer_for_limited_account": "Mae hysbysiadau o'r cyfrif hwn wedi'u hidlo oherwydd bod y cyfrif wedi'i gyfyngu gan gymedrolwr.",
"notification_requests.explainer_for_limited_remote_account": "Mae hysbysiadau o'r cyfrif hwn wedi'u hidlo oherwydd bod y cyfrif neu ei weinydd wedi'i gyfyngu gan gymedrolwr.",
"notification_requests.maximize": "Mwyhau",
@@ -529,8 +557,6 @@
"notifications.column_settings.admin.report": "Adroddiadau newydd:",
"notifications.column_settings.admin.sign_up": "Cofrestriadau newydd:",
"notifications.column_settings.alert": "Hysbysiadau bwrdd gwaith",
- "notifications.column_settings.beta.category": "Nodweddion arbrofol",
- "notifications.column_settings.beta.grouping": "Grŵpio hysbysiadau",
"notifications.column_settings.favourite": "Ffefrynnau:",
"notifications.column_settings.filter_bar.advanced": "Dangos pob categori",
"notifications.column_settings.filter_bar.category": "Bar hidlo cyflym",
@@ -581,12 +607,12 @@
"notifications_permission_banner.title": "Peidiwch â cholli dim",
"onboarding.action.back": "Ewch â fi nôl",
"onboarding.actions.back": "Ewch â fi nôl",
- "onboarding.actions.go_to_explore": "Gweld beth sy'n trendio",
- "onboarding.actions.go_to_home": "Ewch i'ch ffrwd gartref",
+ "onboarding.actions.go_to_explore": "Gweld y pynciau llosg",
+ "onboarding.actions.go_to_home": "Ewch i'm ffrwd gartref",
"onboarding.compose.template": "Helo, #Mastodon!",
"onboarding.follows.empty": "Yn anffodus, nid oes modd dangos unrhyw ganlyniadau ar hyn o bryd. Gallwch geisio defnyddio chwilio neu bori'r dudalen archwilio i ddod o hyd i bobl i'w dilyn, neu ceisio eto yn nes ymlaen.",
"onboarding.follows.lead": "Rydych chi'n curadu eich ffrwd gartref eich hun. Po fwyaf o bobl y byddwch chi'n eu dilyn, y mwyaf egnïol a diddorol fydd hi. Gall y proffiliau hyn fod yn fan cychwyn da - gallwch chi bob amser eu dad-ddilyn yn nes ymlaen:",
- "onboarding.follows.title": "Yn boblogaidd ar Mastodon",
+ "onboarding.follows.title": "Personolwch eich ffrwd gartref",
"onboarding.profile.discoverable": "Gwnewch fy mhroffil yn un y gellir ei ddarganfod",
"onboarding.profile.discoverable_hint": "Pan fyddwch yn optio i mewn i ddarganfodadwyedd ar Mastodon, gall eich postiadau ymddangos mewn canlyniadau chwilio a threndiau, ac efallai y bydd eich proffil yn cael ei awgrymu i bobl sydd â diddordebau tebyg i chi.",
"onboarding.profile.display_name": "Enw dangos",
@@ -606,7 +632,7 @@
"onboarding.start.skip": "Eisiau mynd syth yn eich blaen?",
"onboarding.start.title": "Rydych chi wedi cyrraedd!",
"onboarding.steps.follow_people.body": "Rydych chi'n curadu eich ffrwd eich hun. Gadewch i ni ei lenwi â phobl ddiddorol.",
- "onboarding.steps.follow_people.title": "Dilynwch {count, plural, one {one person} other {# people}}",
+ "onboarding.steps.follow_people.title": "Personolwch eich ffrwd gartref",
"onboarding.steps.publish_status.body": "Dywedwch helo wrth y byd gyda thestun, lluniau, fideos neu arolygon barn {emoji}",
"onboarding.steps.publish_status.title": "Gwnewch eich postiad cyntaf",
"onboarding.steps.setup_profile.body": "Mae eraill yn fwy tebygol o ryngweithio â chi gyda phroffil wedi'i lenwi.",
@@ -631,7 +657,7 @@
"poll_button.add_poll": "Ychwanegu pleidlais",
"poll_button.remove_poll": "Tynnu pleidlais",
"privacy.change": "Addasu preifatrwdd y post",
- "privacy.direct.long": "Pawb sydd â son amdanyn nhw yn y postiad",
+ "privacy.direct.long": "Pawb sydd â sôn amdanyn nhw yn y postiad",
"privacy.direct.short": "Pobl benodol",
"privacy.private.long": "Eich dilynwyr yn unig",
"privacy.private.short": "Dilynwyr",
@@ -645,7 +671,7 @@
"recommended": "Argymhellwyd",
"refresh": "Adnewyddu",
"regeneration_indicator.label": "Yn llwytho…",
- "regeneration_indicator.sublabel": "Mae eich ffrwd cartref yn cael ei baratoi!",
+ "regeneration_indicator.sublabel": "Mae eich ffrwd cartref yn cael ei pharatoi!",
"relative_time.days": "{number}d",
"relative_time.full.days": "{number, plural, one {# diwrnod} other {# diwrnod}} yn ôl",
"relative_time.full.hours": "{number, plural, one {# awr} other {# awr}} yn ôl",
@@ -699,7 +725,7 @@
"report.thanks.title": "Ddim eisiau gweld hwn?",
"report.thanks.title_actionable": "Diolch am adrodd, byddwn yn ymchwilio i hyn.",
"report.unfollow": "Dad-ddilyn @{name}",
- "report.unfollow_explanation": "Rydych chi'n dilyn y cyfrif hwn. I beidio â gweld eu postiadau yn eich porthiant cartref mwyach, dad-ddilynwch nhw.",
+ "report.unfollow_explanation": "Rydych chi'n dilyn y cyfrif hwn. I beidio â gweld eu postiadau yn eich ffrwd gartref mwyach, dad-ddilynwch nhw.",
"report_notification.attached_statuses": "{count, plural, one {{count} postiad} arall {{count} postiad}} atodwyd",
"report_notification.categories.legal": "Cyfreithiol",
"report_notification.categories.legal_sentence": "cynnwys anghyfreithlon",
@@ -750,6 +776,7 @@
"status.bookmark": "Llyfrnodi",
"status.cancel_reblog_private": "Dadhybu",
"status.cannot_reblog": "Nid oes modd hybu'r postiad hwn",
+ "status.continued_thread": "Edefyn parhaus",
"status.copy": "Copïo dolen i'r post",
"status.delete": "Dileu",
"status.detailed_status": "Golwg manwl o'r sgwrs",
@@ -758,8 +785,7 @@
"status.edit": "Golygu",
"status.edited": "Golygwyd ddiwethaf {date}",
"status.edited_x_times": "Golygwyd {count, plural, one {count} two {count} other {{count} gwaith}}",
- "status.embed": "Mewnblannu",
- "status.favourite": "Hoffi",
+ "status.favourite": "Ffafrio",
"status.favourites": "{count, plural, one {ffefryn} other {ffefryn}}",
"status.filter": "Hidlo'r postiad hwn",
"status.history.created": "Crëwyd gan {name} {date}",
@@ -783,6 +809,7 @@
"status.reblogs.empty": "Does neb wedi hybio'r post yma eto. Pan y bydd rhywun yn gwneud, byddent yn ymddangos yma.",
"status.redraft": "Dileu ac ailddrafftio",
"status.remove_bookmark": "Tynnu nod tudalen",
+ "status.replied_in_thread": "Atebodd mewn edefyn",
"status.replied_to": "Wedi ateb {name}",
"status.reply": "Ateb",
"status.replyAll": "Ateb i edefyn",
@@ -798,7 +825,7 @@
"status.uncached_media_warning": "Dim rhagolwg ar gael",
"status.unmute_conversation": "Dad-dewi sgwrs",
"status.unpin": "Dadbinio o'r proffil",
- "subscribed_languages.lead": "Dim ond postiadau mewn ieithoedd penodol fydd yn ymddangos yn eich ffrydiau ar ôl y newid. Dewiswch ddim byd i dderbyn postiadau ym mhob iaith.",
+ "subscribed_languages.lead": "Dim ond postiadau mewn ieithoedd penodol fydd yn ymddangos yn eich ffrydiau cartref a rhestr ar ôl y newid. Dewiswch ddim byd i dderbyn postiadau ym mhob iaith.",
"subscribed_languages.save": "Cadw'r newidiadau",
"subscribed_languages.target": "Newid ieithoedd tanysgrifio {target}",
"tabs_bar.home": "Cartref",
@@ -809,7 +836,7 @@
"time_remaining.moments": "Munudau yn weddill",
"time_remaining.seconds": "{number, plural, one {# eiliad} other {# eiliad}} ar ôl",
"trends.counter_by_accounts": "{count, plural, zero {neb} one {{counter} person} two {{counter} berson} few {{counter} pherson} other {{counter} o bobl}} yn y {days, plural, one {diwrnod diwethaf} two {ddeuddydd diwethaf} other {{days} diwrnod diwethaf}}",
- "trends.trending_now": "Yn trendio nawr",
+ "trends.trending_now": "Pynciau llosg",
"ui.beforeunload": "Byddwch yn colli eich drafft os byddwch yn gadael Mastodon.",
"units.short.billion": "{count}biliwn",
"units.short.million": "{count}miliwn",
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index a791ec75e0..76752802b0 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -97,6 +97,8 @@
"block_modal.title": "Blokér bruger?",
"block_modal.you_wont_see_mentions": "Du vil ikke se indlæg, som nævner vedkommende.",
"boost_modal.combo": "Du kan trykke {combo} for at springe dette over næste gang",
+ "boost_modal.reblog": "Boost indlæg?",
+ "boost_modal.undo_reblog": "Fjern boost af indlæg?",
"bundle_column_error.copy_stacktrace": "Kopiér fejlrapport",
"bundle_column_error.error.body": "Den anmodede side kunne ikke gengives. Dette kan skyldes flere typer fejl.",
"bundle_column_error.error.title": "Åh nej!",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Fjern fokus fra tekstskrivningsområde/søgning",
"keyboard_shortcuts.up": "Flyt opad på listen",
"lightbox.close": "Luk",
- "lightbox.compress": "Komprimér billedvisningsfelt",
- "lightbox.expand": "Udvid billedvisningsfelt",
"lightbox.next": "Næste",
"lightbox.previous": "Forrige",
+ "lightbox.zoom_in": "Zoom til faktisk størrelse",
+ "lightbox.zoom_out": "Zoom for at tilpasse",
"limited_account_hint.action": "Vis profil alligevel",
"limited_account_hint.title": "Denne profil er blevet skjult af {domain}-moderatorerne.",
"link_preview.author": "Af {name}",
@@ -455,7 +457,7 @@
"lists.subheading": "Dine lister",
"load_pending": "{count, plural, one {# nyt emne} other {# nye emner}}",
"loading_indicator.label": "Indlæser…",
- "media_gallery.toggle_visible": "{number, plural, one {Skjul billede} other {Skjul billeder}}",
+ "media_gallery.hide": "Skjul",
"moved_to_account_banner.text": "Din konto {disabledAccount} er pt. deaktiveret, da du flyttede til {movedToAccount}.",
"mute_modal.hide_from_notifications": "Skjul fra notifikationer",
"mute_modal.hide_options": "Skjul valgmuligheder",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Indlæg, som nævner vedkommende, vises ikke.",
"mute_modal.you_wont_see_posts": "Vedkommende kan stadig se dine indlæg, med vedkommendes vise ikke.",
"navigation_bar.about": "Om",
+ "navigation_bar.administration": "Håndtering",
"navigation_bar.advanced_interface": "Åbn i avanceret webgrænseflade",
"navigation_bar.blocks": "Blokerede brugere",
"navigation_bar.bookmarks": "Bogmærker",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Følges og følgere",
"navigation_bar.lists": "Lister",
"navigation_bar.logout": "Log af",
+ "navigation_bar.moderation": "Moderering",
"navigation_bar.mutes": "Skjulte brugere (mutede)",
"navigation_bar.opened_in_classic_interface": "Indlæg, konti og visse andre sider åbnes som standard i den klassiske webgrænseflade.",
"navigation_bar.personal": "Personlig",
@@ -555,8 +559,6 @@
"notifications.column_settings.admin.report": "Nye anmeldelser:",
"notifications.column_settings.admin.sign_up": "Nye tilmeldinger:",
"notifications.column_settings.alert": "Computernotifikationer",
- "notifications.column_settings.beta.category": "Eksperimentelle funktioner",
- "notifications.column_settings.beta.grouping": "Gruppér notifikationer",
"notifications.column_settings.favourite": "Favoritter:",
"notifications.column_settings.filter_bar.advanced": "Vis alle kategorier",
"notifications.column_settings.filter_bar.category": "Hurtigfiltreringsbjælke",
@@ -776,6 +778,7 @@
"status.bookmark": "Bogmærk",
"status.cancel_reblog_private": "Fjern boost",
"status.cannot_reblog": "Dette indlæg kan ikke fremhæves",
+ "status.continued_thread": "Fortsat tråd",
"status.copy": "Kopiér link til indlæg",
"status.delete": "Slet",
"status.detailed_status": "Detaljeret samtalevisning",
@@ -784,7 +787,7 @@
"status.edit": "Redigér",
"status.edited": "Senest redigeret {date}",
"status.edited_x_times": "Redigeret {count, plural, one {{count} gang} other {{count} gange}}",
- "status.embed": "Indlejr",
+ "status.embed": "Hent indlejringskode",
"status.favourite": "Favorit",
"status.favourites": "{count, plural, one {# favorit} other {# favoritter}}",
"status.filter": "Filtrér dette indlæg",
@@ -809,6 +812,7 @@
"status.reblogs.empty": "Ingen har endnu fremhævet dette indlæg. Når nogen gør, vil det fremgå hér.",
"status.redraft": "Slet og omformulér",
"status.remove_bookmark": "Fjern bogmærke",
+ "status.replied_in_thread": "Svaret i tråd",
"status.replied_to": "Besvarede {name}",
"status.reply": "Besvar",
"status.replyAll": "Besvar alle",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index b960649eb2..1931ce23f1 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -97,6 +97,8 @@
"block_modal.title": "Profil blockieren?",
"block_modal.you_wont_see_mentions": "Du wirst keine Beiträge sehen, die dieses Profil erwähnen.",
"boost_modal.combo": "Mit {combo} erscheint dieses Fenster beim nächsten Mal nicht mehr",
+ "boost_modal.reblog": "Beitrag teilen?",
+ "boost_modal.undo_reblog": "Beitrag nicht mehr teilen?",
"bundle_column_error.copy_stacktrace": "Fehlerbericht kopieren",
"bundle_column_error.error.body": "Die angeforderte Seite konnte nicht dargestellt werden. Dies könnte auf einen Fehler in unserem Code oder auf ein Browser-Kompatibilitätsproblem zurückzuführen sein.",
"bundle_column_error.error.title": "Oh nein!",
@@ -153,7 +155,7 @@
"compose_form.lock_disclaimer.lock": "geschützt",
"compose_form.placeholder": "Was gibt’s Neues?",
"compose_form.poll.duration": "Umfragedauer",
- "compose_form.poll.multiple": "Multiple-Choice",
+ "compose_form.poll.multiple": "Mehrfachauswahl",
"compose_form.poll.option_placeholder": "Option {number}",
"compose_form.poll.single": "Einfachauswahl",
"compose_form.poll.switch_to_multiple": "Mehrfachauswahl erlauben",
@@ -234,7 +236,7 @@
"domain_pill.your_handle": "Deine Adresse:",
"domain_pill.your_server": "Dein digitales Zuhause. Hier „leben“ alle Beiträge von dir. Dir gefällt es hier nicht? Du kannst jederzeit den Server wechseln und ebenso deine Follower übertragen.",
"domain_pill.your_username": "Deine eindeutige Identität auf diesem Server. Es ist möglich, Profile mit dem gleichen Profilnamen auf verschiedenen Servern zu finden.",
- "embed.instructions": "Du kannst diesen Beitrag außerhalb des Fediverse (z. B. auf deiner Website) einbetten, indem du diesen iFrame-Code einfügst.",
+ "embed.instructions": "Du kannst diesen Beitrag auf deiner Website einbetten, indem du den nachfolgenden Code kopierst.",
"embed.preview": "Vorschau:",
"emoji_button.activity": "Aktivitäten",
"emoji_button.clear": "Leeren",
@@ -353,11 +355,11 @@
"hashtags.and_other": "… und {count, plural, one{# weiterer} other {# weitere}}",
"hints.profiles.followers_may_be_missing": "Möglicherweise werden für dieses Profil nicht alle Follower angezeigt.",
"hints.profiles.follows_may_be_missing": "Möglicherweise werden für dieses Profil nicht alle gefolgten Profile angezeigt.",
- "hints.profiles.posts_may_be_missing": "Möglicherweise werden für dieses Profil nicht alle Beiträge angezeigt.",
+ "hints.profiles.posts_may_be_missing": "Möglicherweise werden nicht alle Beiträge von diesem Profil angezeigt.",
"hints.profiles.see_more_followers": "Weitere Follower auf {domain} ansehen",
"hints.profiles.see_more_follows": "Weitere gefolgte Profile auf {domain} ansehen",
"hints.profiles.see_more_posts": "Weitere Beiträge auf {domain} ansehen",
- "hints.threads.replies_may_be_missing": "Möglicherweise werden für dieses Profil nicht alle Antworten angezeigt.",
+ "hints.threads.replies_may_be_missing": "Möglicherweise werden nicht alle Antworten von anderen Servern angezeigt.",
"hints.threads.see_more": "Weitere Antworten auf {domain} ansehen",
"home.column_settings.show_reblogs": "Geteilte Beiträge anzeigen",
"home.column_settings.show_replies": "Antworten anzeigen",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Eingabefeld/Suche nicht mehr fokussieren",
"keyboard_shortcuts.up": "Ansicht nach oben bewegen",
"lightbox.close": "Schließen",
- "lightbox.compress": "Bildansicht verkleinern",
- "lightbox.expand": "Bildansicht vergrößern",
"lightbox.next": "Vor",
"lightbox.previous": "Zurück",
+ "lightbox.zoom_in": "In Originalgröße anzeigen",
+ "lightbox.zoom_out": "In angepasster Größe anzeigen",
"limited_account_hint.action": "Profil trotzdem anzeigen",
"limited_account_hint.title": "Dieses Profil wurde von den Moderator*innen von {domain} ausgeblendet.",
"link_preview.author": "Von {name}",
@@ -455,7 +457,7 @@
"lists.subheading": "Deine Listen",
"load_pending": "{count, plural, one {# neuer Beitrag} other {# neue Beiträge}}",
"loading_indicator.label": "Wird geladen …",
- "media_gallery.toggle_visible": "{number, plural, one {Medium ausblenden} other {Medien ausblenden}}",
+ "media_gallery.hide": "Ausblenden",
"moved_to_account_banner.text": "Dein Konto {disabledAccount} ist derzeit deaktiviert, weil du zu {movedToAccount} umgezogen bist.",
"mute_modal.hide_from_notifications": "Benachrichtigungen ausblenden",
"mute_modal.hide_options": "Einstellungen ausblenden",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Du wirst keine Beiträge sehen, die dieses Profil erwähnen.",
"mute_modal.you_wont_see_posts": "Deine Beiträge können weiterhin angesehen werden, aber du wirst deren Beiträge nicht mehr sehen.",
"navigation_bar.about": "Über",
+ "navigation_bar.administration": "Administration",
"navigation_bar.advanced_interface": "Im erweiterten Webinterface öffnen",
"navigation_bar.blocks": "Blockierte Profile",
"navigation_bar.bookmarks": "Lesezeichen",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Follower und Folge ich",
"navigation_bar.lists": "Listen",
"navigation_bar.logout": "Abmelden",
+ "navigation_bar.moderation": "Moderation",
"navigation_bar.mutes": "Stummgeschaltete Profile",
"navigation_bar.opened_in_classic_interface": "Beiträge, Konten und andere bestimmte Seiten werden standardmäßig im klassischen Webinterface geöffnet.",
"navigation_bar.personal": "Persönlich",
@@ -555,8 +559,6 @@
"notifications.column_settings.admin.report": "Neue Meldungen:",
"notifications.column_settings.admin.sign_up": "Neue Registrierungen:",
"notifications.column_settings.alert": "Desktop-Benachrichtigungen",
- "notifications.column_settings.beta.category": "Experimentelle Funktionen",
- "notifications.column_settings.beta.grouping": "Benachrichtigungen gruppieren",
"notifications.column_settings.favourite": "Favoriten:",
"notifications.column_settings.filter_bar.advanced": "Alle Filterkategorien anzeigen",
"notifications.column_settings.filter_bar.category": "Filterleiste",
@@ -773,9 +775,10 @@
"status.admin_domain": "{domain} moderieren",
"status.admin_status": "Beitrag moderieren",
"status.block": "@{name} blockieren",
- "status.bookmark": "Beitrag als Lesezeichen setzen",
+ "status.bookmark": "Lesezeichen setzen",
"status.cancel_reblog_private": "Beitrag nicht mehr teilen",
"status.cannot_reblog": "Dieser Beitrag kann nicht geteilt werden",
+ "status.continued_thread": "Fortgeführter Thread",
"status.copy": "Link zum Beitrag kopieren",
"status.delete": "Beitrag löschen",
"status.detailed_status": "Detaillierte Ansicht der Unterhaltung",
@@ -784,7 +787,7 @@
"status.edit": "Beitrag bearbeiten",
"status.edited": "Zuletzt am {date} bearbeitet",
"status.edited_x_times": "{count, plural, one {{count}-mal} other {{count}-mal}} bearbeitet",
- "status.embed": "Beitrag per iFrame einbetten",
+ "status.embed": "Code zum Einbetten",
"status.favourite": "Favorisieren",
"status.favourites": "{count, plural, one {Mal favorisiert} other {Mal favorisiert}}",
"status.filter": "Beitrag filtern",
@@ -809,6 +812,7 @@
"status.reblogs.empty": "Diesen Beitrag hat bisher noch niemand geteilt. Sobald es jemand tut, wird das Profil hier erscheinen.",
"status.redraft": "Löschen und neu erstellen",
"status.remove_bookmark": "Lesezeichen entfernen",
+ "status.replied_in_thread": "Antwortete im Thread",
"status.replied_to": "Antwortete {name}",
"status.reply": "Antworten",
"status.replyAll": "Allen antworten",
diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json
index a3adaaf9d1..83f0227a0a 100644
--- a/app/javascript/mastodon/locales/el.json
+++ b/app/javascript/mastodon/locales/el.json
@@ -97,6 +97,8 @@
"block_modal.title": "Αποκλεισμός χρήστη;",
"block_modal.you_wont_see_mentions": "Δε θα βλέπεις τις αναρτήσεις που τον αναφέρουν.",
"boost_modal.combo": "Μπορείς να πατήσεις {combo} για να το προσπεράσεις την επόμενη φορά",
+ "boost_modal.reblog": "Ενίσχυση ανάρτησης;",
+ "boost_modal.undo_reblog": "Αναίρεση ενίσχυσης;",
"bundle_column_error.copy_stacktrace": "Αντιγραφή αναφοράς σφάλματος",
"bundle_column_error.error.body": "Δεν ήταν δυνατή η απόδοση της σελίδας που ζήτησες. Μπορεί να οφείλεται σε σφάλμα στον κώδικά μας ή σε πρόβλημα συμβατότητας του προγράμματος περιήγησης.",
"bundle_column_error.error.title": "Ωχ όχι!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Άρση ακολούθησης",
"confirmations.unfollow.message": "Σίγουρα θες να πάψεις να ακολουθείς τον/την {name};",
"confirmations.unfollow.title": "Άρση ακολούθησης;",
+ "content_warning.hide": "Απόκρυψη ανάρτησης",
+ "content_warning.show": "Εμφάνιση ούτως ή άλλως",
"conversation.delete": "Διαγραφή συζήτησης",
"conversation.mark_as_read": "Σήμανση ως αναγνωσμένο",
"conversation.open": "Προβολή συνομιλίας",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Χρησιμοποιήστε μια υπάρχουσα κατηγορία ή δημιουργήστε μια νέα",
"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.title": "Φιλτραρισμένες ειδοποιήσεις",
"firehose.all": "Όλα",
@@ -427,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Αποεστίαση του πεδίου σύνθεσης/αναζήτησης",
"keyboard_shortcuts.up": "Μετακίνηση προς τα πάνω στη λίστα",
"lightbox.close": "Κλείσιμο",
- "lightbox.compress": "Συμπίεση πλαισίου προβολής εικόνας",
- "lightbox.expand": "Ανάπτυξη πλαισίου εμφάνισης εικόνας",
"lightbox.next": "Επόμενο",
"lightbox.previous": "Προηγούμενο",
+ "lightbox.zoom_in": "Εστίαση στο πραγματικό μέγεθος",
+ "lightbox.zoom_out": "Εστίαση για προσαρμογή",
"limited_account_hint.action": "Εμφάνιση προφίλ ούτως ή άλλως",
"limited_account_hint.title": "Αυτό το προφίλ έχει αποκρυφτεί από τους διαχειριστές του διακομιστή {domain}.",
"link_preview.author": "Από {name}",
@@ -452,7 +457,7 @@
"lists.subheading": "Οι λίστες σου",
"load_pending": "{count, plural, one {# νέο στοιχείο} other {# νέα στοιχεία}}",
"loading_indicator.label": "Φόρτωση…",
- "media_gallery.toggle_visible": "{number, plural, one {Απόκρυψη εικόνας} other {Απόκρυψη εικόνων}}",
+ "media_gallery.hide": "Απόκρυψη",
"moved_to_account_banner.text": "Ο λογαριασμός σου {disabledAccount} είναι προσωρινά απενεργοποιημένος επειδή μεταφέρθηκες στον {movedToAccount}.",
"mute_modal.hide_from_notifications": "Απόκρυψη από ειδοποιήσεις",
"mute_modal.hide_options": "Απόκρυψη επιλογών",
@@ -464,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Δε θα βλέπεις τις αναρτήσεις που τον αναφέρουν.",
"mute_modal.you_wont_see_posts": "Μπορεί ακόμα να δει τις αναρτήσεις σου, αλλά δε θα βλέπεις τις δικές του.",
"navigation_bar.about": "Σχετικά με",
+ "navigation_bar.administration": "Διαχείριση",
"navigation_bar.advanced_interface": "Άνοιγμα σε προηγμένη διεπαφή ιστού",
"navigation_bar.blocks": "Αποκλεισμένοι χρήστες",
"navigation_bar.bookmarks": "Σελιδοδείκτες",
@@ -480,6 +486,7 @@
"navigation_bar.follows_and_followers": "Ακολουθείς και σε ακολουθούν",
"navigation_bar.lists": "Λίστες",
"navigation_bar.logout": "Αποσύνδεση",
+ "navigation_bar.moderation": "Συντονισμός",
"navigation_bar.mutes": "Αποσιωπημένοι χρήστες",
"navigation_bar.opened_in_classic_interface": "Δημοσιεύσεις, λογαριασμοί και άλλες συγκεκριμένες σελίδες ανοίγονται από προεπιλογή στην κλασική διεπαφή ιστού.",
"navigation_bar.personal": "Προσωπικά",
@@ -552,8 +559,6 @@
"notifications.column_settings.admin.report": "Νέες αναφορές:",
"notifications.column_settings.admin.sign_up": "Νέες εγγραφές:",
"notifications.column_settings.alert": "Ειδοποιήσεις επιφάνειας εργασίας",
- "notifications.column_settings.beta.category": "Πειραματικές λειτουργίες",
- "notifications.column_settings.beta.grouping": "Ομαδοποίηση ειδοποιήσεων",
"notifications.column_settings.favourite": "Αγαπημένα:",
"notifications.column_settings.filter_bar.advanced": "Εμφάνιση όλων των κατηγοριών",
"notifications.column_settings.filter_bar.category": "Μπάρα γρήγορου φίλτρου",
@@ -773,6 +778,7 @@
"status.bookmark": "Σελιδοδείκτης",
"status.cancel_reblog_private": "Ακύρωση ενίσχυσης",
"status.cannot_reblog": "Αυτή η ανάρτηση δεν μπορεί να ενισχυθεί",
+ "status.continued_thread": "Συνεχιζόμενο νήματος",
"status.copy": "Αντιγραφή συνδέσμου ανάρτησης",
"status.delete": "Διαγραφή",
"status.detailed_status": "Προβολή λεπτομερούς συζήτησης",
@@ -781,7 +787,7 @@
"status.edit": "Επεξεργασία",
"status.edited": "Τελευταία επεξεργασία {date}",
"status.edited_x_times": "Επεξεργάστηκε {count, plural, one {{count} φορά} other {{count} φορές}}",
- "status.embed": "Ενσωμάτωσε",
+ "status.embed": "Απόκτηση κώδικα ενσωμάτωσης",
"status.favourite": "Αγαπημένα",
"status.favourites": "{count, plural, one {# αγαπημένο} other {# αγαπημένα}}",
"status.filter": "Φιλτράρισμα αυτής της ανάρτησης",
@@ -806,6 +812,7 @@
"status.reblogs.empty": "Κανείς δεν ενίσχυσε αυτή την ανάρτηση ακόμα. Μόλις το κάνει κάποιος, θα εμφανιστεί εδώ.",
"status.redraft": "Σβήσε & ξαναγράψε",
"status.remove_bookmark": "Αφαίρεση σελιδοδείκτη",
+ "status.replied_in_thread": "Απαντήθηκε σε νήμα",
"status.replied_to": "Απάντησε στον {name}",
"status.reply": "Απάντησε",
"status.replyAll": "Απάντησε στο νήμα συζήτησης",
diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json
index 05d1dc0ec9..9adcfa0a0f 100644
--- a/app/javascript/mastodon/locales/en-GB.json
+++ b/app/javascript/mastodon/locales/en-GB.json
@@ -97,6 +97,8 @@
"block_modal.title": "Block user?",
"block_modal.you_wont_see_mentions": "You won't see posts that mention them.",
"boost_modal.combo": "You can press {combo} to skip this next time",
+ "boost_modal.reblog": "Boost post?",
+ "boost_modal.undo_reblog": "Unboost post?",
"bundle_column_error.copy_stacktrace": "Copy error report",
"bundle_column_error.error.body": "The requested page could not be rendered. It could be due to a bug in our code, or a browser compatibility issue.",
"bundle_column_error.error.title": "Oh, no!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"confirmations.unfollow.title": "Unfollow user?",
+ "content_warning.hide": "Hide post",
+ "content_warning.show": "Show anyway",
"conversation.delete": "Delete conversation",
"conversation.mark_as_read": "Mark as read",
"conversation.open": "View conversation",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
"filter_modal.select_filter.title": "Filter this post",
"filter_modal.title.status": "Filter a post",
+ "filter_warning.matches_filter": "Matches filter “{title}”",
"filtered_notifications_banner.pending_requests": "From {count, plural, =0 {no one} one {one person} other {# people}} you may know",
"filtered_notifications_banner.title": "Filtered notifications",
"firehose.all": "All",
@@ -427,10 +432,10 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "Move up in the list",
"lightbox.close": "Close",
- "lightbox.compress": "Compress image view box",
- "lightbox.expand": "Expand image view box",
"lightbox.next": "Next",
"lightbox.previous": "Previous",
+ "lightbox.zoom_in": "Zoom to actual size",
+ "lightbox.zoom_out": "Zoom to fit",
"limited_account_hint.action": "Show profile anyway",
"limited_account_hint.title": "This profile has been hidden by the moderators of {domain}.",
"link_preview.author": "By {name}",
@@ -452,7 +457,7 @@
"lists.subheading": "Your lists",
"load_pending": "{count, plural, one {# new item} other {# new items}}",
"loading_indicator.label": "Loading…",
- "media_gallery.toggle_visible": "{number, plural, one {Hide image} other {Hide images}}",
+ "media_gallery.hide": "Hide",
"moved_to_account_banner.text": "Your account {disabledAccount} is currently disabled because you moved to {movedToAccount}.",
"mute_modal.hide_from_notifications": "Hide from notifications",
"mute_modal.hide_options": "Hide options",
@@ -464,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "You won't see posts that mention them.",
"mute_modal.you_wont_see_posts": "They can still see your posts, but you won't see theirs.",
"navigation_bar.about": "About",
+ "navigation_bar.administration": "Administration",
"navigation_bar.advanced_interface": "Open in advanced web interface",
"navigation_bar.blocks": "Blocked users",
"navigation_bar.bookmarks": "Bookmarks",
@@ -480,6 +486,7 @@
"navigation_bar.follows_and_followers": "Follows and followers",
"navigation_bar.lists": "Lists",
"navigation_bar.logout": "Logout",
+ "navigation_bar.moderation": "Moderation",
"navigation_bar.mutes": "Muted users",
"navigation_bar.opened_in_classic_interface": "Posts, accounts, and other specific pages are opened by default in the classic web interface.",
"navigation_bar.personal": "Personal",
@@ -552,8 +559,6 @@
"notifications.column_settings.admin.report": "New reports:",
"notifications.column_settings.admin.sign_up": "New sign-ups:",
"notifications.column_settings.alert": "Desktop notifications",
- "notifications.column_settings.beta.category": "Experimental features",
- "notifications.column_settings.beta.grouping": "Group notifications",
"notifications.column_settings.favourite": "Favourites:",
"notifications.column_settings.filter_bar.advanced": "Display all categories",
"notifications.column_settings.filter_bar.category": "Quick filter bar",
@@ -773,6 +778,7 @@
"status.bookmark": "Bookmark",
"status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
+ "status.continued_thread": "Continued thread",
"status.copy": "Copy link to status",
"status.delete": "Delete",
"status.detailed_status": "Detailed conversation view",
@@ -781,7 +787,7 @@
"status.edit": "Edit",
"status.edited": "Last edited {date}",
"status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
- "status.embed": "Embed",
+ "status.embed": "Get embed code",
"status.favourite": "Favourite",
"status.favourites": "{count, plural, one {favorite} other {favorites}}",
"status.filter": "Filter this post",
@@ -806,6 +812,7 @@
"status.reblogs.empty": "No one has boosted this post yet. When someone does, they will show up here.",
"status.redraft": "Delete & re-draft",
"status.remove_bookmark": "Remove bookmark",
+ "status.replied_in_thread": "Replied in thread",
"status.replied_to": "Replied to {name}",
"status.reply": "Reply",
"status.replyAll": "Reply to thread",
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 6b83084797..999832d971 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -97,6 +97,8 @@
"block_modal.title": "Block user?",
"block_modal.you_wont_see_mentions": "You won't see posts that mention them.",
"boost_modal.combo": "You can press {combo} to skip this next time",
+ "boost_modal.reblog": "Boost post?",
+ "boost_modal.undo_reblog": "Unboost post?",
"bundle_column_error.copy_stacktrace": "Copy error report",
"bundle_column_error.error.body": "The requested page could not be rendered. It could be due to a bug in our code, or a browser compatibility issue.",
"bundle_column_error.error.title": "Oh, no!",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Unfocus compose textarea/search",
"keyboard_shortcuts.up": "Move up in the list",
"lightbox.close": "Close",
- "lightbox.compress": "Compress image view box",
- "lightbox.expand": "Expand image view box",
"lightbox.next": "Next",
"lightbox.previous": "Previous",
+ "lightbox.zoom_in": "Zoom to actual size",
+ "lightbox.zoom_out": "Zoom to fit",
"limited_account_hint.action": "Show profile anyway",
"limited_account_hint.title": "This profile has been hidden by the moderators of {domain}.",
"link_preview.author": "By {name}",
@@ -455,7 +457,7 @@
"lists.subheading": "Your lists",
"load_pending": "{count, plural, one {# new item} other {# new items}}",
"loading_indicator.label": "Loading…",
- "media_gallery.toggle_visible": "{number, plural, one {Hide image} other {Hide images}}",
+ "media_gallery.hide": "Hide",
"moved_to_account_banner.text": "Your account {disabledAccount} is currently disabled because you moved to {movedToAccount}.",
"mute_modal.hide_from_notifications": "Hide from notifications",
"mute_modal.hide_options": "Hide options",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "You won't see posts that mention them.",
"mute_modal.you_wont_see_posts": "They can still see your posts, but you won't see theirs.",
"navigation_bar.about": "About",
+ "navigation_bar.administration": "Administration",
"navigation_bar.advanced_interface": "Open in advanced web interface",
"navigation_bar.blocks": "Blocked users",
"navigation_bar.bookmarks": "Bookmarks",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Follows and followers",
"navigation_bar.lists": "Lists",
"navigation_bar.logout": "Logout",
+ "navigation_bar.moderation": "Moderation",
"navigation_bar.mutes": "Muted users",
"navigation_bar.opened_in_classic_interface": "Posts, accounts, and other specific pages are opened by default in the classic web interface.",
"navigation_bar.personal": "Personal",
@@ -556,8 +560,6 @@
"notifications.column_settings.admin.report": "New reports:",
"notifications.column_settings.admin.sign_up": "New sign-ups:",
"notifications.column_settings.alert": "Desktop notifications",
- "notifications.column_settings.beta.category": "Experimental features",
- "notifications.column_settings.beta.grouping": "Group notifications",
"notifications.column_settings.favourite": "Favorites:",
"notifications.column_settings.reaction": "Reactions:",
"notifications.column_settings.filter_bar.advanced": "Display all categories",
@@ -779,6 +781,7 @@
"status.bookmark": "Bookmark",
"status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
+ "status.continued_thread": "Continued thread",
"status.copy": "Copy link to post",
"status.delete": "Delete",
"status.detailed_status": "Detailed conversation view",
@@ -787,7 +790,7 @@
"status.edit": "Edit",
"status.edited": "Last edited {date}",
"status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
- "status.embed": "Embed",
+ "status.embed": "Get embed code",
"status.favourite": "Favorite",
"status.react": "React",
"status.favourites": "{count, plural, one {favorite} other {favorites}}",
@@ -814,6 +817,7 @@
"status.reblogs.empty": "No one has boosted this post yet. When someone does, they will show up here.",
"status.redraft": "Delete & re-draft",
"status.remove_bookmark": "Remove bookmark",
+ "status.replied_in_thread": "Replied in thread",
"status.replied_to": "Replied to {name}",
"status.reply": "Reply",
"status.replyAll": "Reply to thread",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 76ca4980fa..fbf74e9efa 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -67,7 +67,7 @@
"account.unblock_domain": "Malbloki la domajnon {domain}",
"account.unblock_short": "Malbloki",
"account.unendorse": "Ne plu rekomendi ĉe la profilo",
- "account.unfollow": "Malaboni",
+ "account.unfollow": "Ĉesi sekvi",
"account.unmute": "Ne plu silentigi @{name}",
"account.unmute_notifications_short": "Malsilentigu Sciigojn",
"account.unmute_short": "Ne plu silentigi",
@@ -97,6 +97,8 @@
"block_modal.title": "Ĉu bloki uzanton?",
"block_modal.you_wont_see_mentions": "Vi ne vidos afiŝojn, ke mencii ilin.",
"boost_modal.combo": "Vi povas premi {combo} por preterpasi sekvafoje",
+ "boost_modal.reblog": "Ĉu diskonigi afiŝon?",
+ "boost_modal.undo_reblog": "Ĉu ĉesi diskonigi afiŝon?",
"bundle_column_error.copy_stacktrace": "Kopii la eraran raporton",
"bundle_column_error.error.body": "La petita paĝo ne povas redonitis. Eble estas eraro.",
"bundle_column_error.error.title": "Ho, ve!",
@@ -188,8 +190,12 @@
"confirmations.redraft.title": "Ĉu forigi kaj redakcii afiŝon?",
"confirmations.reply.confirm": "Respondi",
"confirmations.reply.message": "Respondi nun anstataŭigos la skribatan afiŝon. Ĉu vi certas, ke vi volas daŭrigi?",
+ "confirmations.reply.title": "Ĉu superskribi afiŝon?",
"confirmations.unfollow.confirm": "Ne plu sekvi",
"confirmations.unfollow.message": "Ĉu vi certas, ke vi volas ĉesi sekvi {name}?",
+ "confirmations.unfollow.title": "Ĉu ĉesi sekvi uzanton?",
+ "content_warning.hide": "Kaŝi afiŝon",
+ "content_warning.show": "Montri ĉiukaze",
"conversation.delete": "Forigi konversacion",
"conversation.mark_as_read": "Marki legita",
"conversation.open": "Vidi konversacion",
@@ -209,6 +215,27 @@
"dismissable_banner.explore_statuses": "Ĉi tioj estas afiŝoj de socia reto kiu populariĝas hodiau.",
"dismissable_banner.explore_tags": "Ĉi tiuj kradvostoj populariĝas en ĉi tiu kaj aliaj serviloj en la malcentraliza reto nun.",
"dismissable_banner.public_timeline": "Ĉi tioj estas plej lastaj publikaj afiŝoj de personoj ĉe socia reto kiu personoj ĉe {domain} sekvas.",
+ "domain_block_modal.block": "Bloki servilon",
+ "domain_block_modal.block_account_instead": "Bloki @{name} anstataŭe",
+ "domain_block_modal.they_can_interact_with_old_posts": "Homoj de ĉi tiu servilo povas interagi kun viaj malnovaj afiŝoj.",
+ "domain_block_modal.they_cant_follow": "Neniu el ĉi tiu servilo povas sekvi vin.",
+ "domain_block_modal.they_wont_know": "Ili ne scios, ke ili estas blokitaj.",
+ "domain_block_modal.title": "Ĉu bloki la domajnon?",
+ "domain_block_modal.you_will_lose_followers": "Ĉiuj viaj sekvantoj de ĉi tiu servilo estos forigitaj.",
+ "domain_block_modal.you_wont_see_posts": "Vi ne vidos afiŝojn aŭ sciigojn de uzantoj sur ĉi tiu servilo.",
+ "domain_pill.activitypub_lets_connect": "Ĝi ebligas vin konekti kaj interagi kun homoj ne nur sur Mastodon, sed ankaŭ tra diversaj sociaj apoj.",
+ "domain_pill.activitypub_like_language": "ActivityPub estas kiel la lingvo kiun Mastodon parolas kun aliaj sociaj retoj.",
+ "domain_pill.server": "Servilo",
+ "domain_pill.their_handle": "Ilia identigo:",
+ "domain_pill.their_server": "Ilia cifereca hejmo, kie ĉiuj iliaj afiŝoj loĝas.",
+ "domain_pill.their_username": "Ilia unika identigilo sur ilia servilo. Eblas trovi uzantojn kun la sama uzantnomo sur malsamaj serviloj.",
+ "domain_pill.username": "Uzantnomo",
+ "domain_pill.whats_in_a_handle": "Kio estas en identigo?",
+ "domain_pill.who_they_are": "Ĉar identigoj diras, kiu iu estas kaj kie ili estas, vi povas interagi kun homoj tra la socia reto de
ActivityPub-funkciigitaj platformoj.",
+ "domain_pill.who_you_are": "Ĉar via identigo diras kiu vi estas kaj kie vi estas, homoj povas interagi kun vi tra la socia reto de
ActivityPub-funkciigitaj platformoj.",
+ "domain_pill.your_handle": "Via identigo:",
+ "domain_pill.your_server": "Via cifereca hejmo, kie loĝas ĉiuj viaj afiŝoj. Ĉu vi ne ŝatas ĉi tiun? Transloku servilojn iam ajn kaj alportu ankaŭ viajn sekvantojn.",
+ "domain_pill.your_username": "Via unika identigilo sur ĉi tiu servilo. Eblas trovi uzantojn kun la sama uzantnomo sur malsamaj serviloj.",
"embed.instructions": "Enkorpigu ĉi tiun afiŝon en vian retejon per kopio de la suba kodo.",
"embed.preview": "Ĝi aperos tiel:",
"emoji_button.activity": "Agadoj",
@@ -245,6 +272,7 @@
"empty_column.list": "Ankoraŭ estas nenio en ĉi tiu listo. Kiam membroj de ĉi tiu listo afiŝos novajn afiŝojn, ili aperos ĉi tie.",
"empty_column.lists": "Vi ankoraŭ ne havas liston. Kiam vi kreos iun, ĝi aperos ĉi tie.",
"empty_column.mutes": "Vi ne ankoraŭ silentigis iun uzanton.",
+ "empty_column.notification_requests": "Ĉio klara! Estas nenio tie ĉi. Kiam vi ricevas novajn sciigojn, ili aperos ĉi tie laŭ viaj agordoj.",
"empty_column.notifications": "Vi ankoraŭ ne havas sciigojn. Interagu kun aliaj por komenci konversacion.",
"empty_column.public": "Estas nenio ĉi tie! Publike skribu ion, aŭ mane sekvu uzantojn de aliaj serviloj por plenigi la publikan tempolinion",
"error.unexpected_crash.explanation": "Pro eraro en nia kodo, aŭ problemo de kongruo en via retumilo, ĉi tiu paĝo ne povis esti montrata ĝuste.",
@@ -275,12 +303,30 @@
"filter_modal.select_filter.subtitle": "Uzu ekzistantan kategorion aŭ kreu novan",
"filter_modal.select_filter.title": "Filtri ĉi tiun afiŝon",
"filter_modal.title.status": "Filtri mesaĝon",
+ "filter_warning.matches_filter": "Filtrilo de kongruoj “{title}”",
+ "filtered_notifications_banner.pending_requests": "El {count, plural, =0 {neniu} one {unu persono} other {# homoj}} vi eble konas",
+ "filtered_notifications_banner.title": "Filtritaj sciigoj",
"firehose.all": "Ĉiuj",
"firehose.local": "Ĉi tiu servilo",
"firehose.remote": "Aliaj serviloj",
"follow_request.authorize": "Rajtigi",
"follow_request.reject": "Rifuzi",
"follow_requests.unlocked_explanation": "Kvankam via konto ne estas ŝlosita, la dungitaro de {domain} opinias, ke vi eble volas revizii petojn pri sekvado de ĉi tiuj kontoj permane.",
+ "follow_suggestions.curated_suggestion": "Elekto de stabo",
+ "follow_suggestions.dismiss": "Ne montri denove",
+ "follow_suggestions.featured_longer": "Mane elektita de la teamo de {domain}",
+ "follow_suggestions.friends_of_friends_longer": "Populara inter homoj, kiujn vi sekvas",
+ "follow_suggestions.hints.featured": "Ĉi tiu profilo estis mane elektita de la teamo de {domain}.",
+ "follow_suggestions.hints.friends_of_friends": "Ĉi tiu profilo estas populara inter la homoj, kiujn vi sekvas.",
+ "follow_suggestions.hints.most_followed": "Ĉi tiu profilo estas unu el la plej sekvataj en {domain}.",
+ "follow_suggestions.hints.most_interactions": "Ĉi tiu profilo lastatempe ricevis multe da atento sur {domain}.",
+ "follow_suggestions.hints.similar_to_recently_followed": "Ĉi tiu profilo similas al la profiloj kiujn vi plej lastatempe sekvis.",
+ "follow_suggestions.personalized_suggestion": "Agordita propono",
+ "follow_suggestions.popular_suggestion": "Popularaj proponoj",
+ "follow_suggestions.popular_suggestion_longer": "Populara en {domain}",
+ "follow_suggestions.similar_to_recently_followed_longer": "Simile al profiloj, kiujn vi lastatempe sekvis",
+ "follow_suggestions.view_all": "Vidi ĉiujn",
+ "follow_suggestions.who_to_follow": "Kiun sekvi",
"followed_tags": "Sekvataj kradvortoj",
"footer.about": "Pri",
"footer.directory": "Profilujo",
@@ -307,6 +353,14 @@
"hashtag.follow": "Sekvi la kradvorton",
"hashtag.unfollow": "Ne plu sekvi la kradvorton",
"hashtags.and_other": "…kaj {count, plural,other {# pli}}",
+ "hints.profiles.followers_may_be_missing": "Sekvantoj por ĉi tiu profilo eble mankas.",
+ "hints.profiles.follows_may_be_missing": "Sekvatoj de ĉi tiu profilo eble mankas.",
+ "hints.profiles.posts_may_be_missing": "Iuj afiŝoj de ĉi tiu profilo eble mankas.",
+ "hints.profiles.see_more_followers": "Vidi pli da sekvantoj sur {domain}",
+ "hints.profiles.see_more_follows": "Vidi pli da sekvatoj sur {domain}",
+ "hints.profiles.see_more_posts": "Vidi pli da afiŝoj sur {domain}",
+ "hints.threads.replies_may_be_missing": "Respondoj de aliaj serviloj eble mankas.",
+ "hints.threads.see_more": "Vidi pli da respondoj sur {domain}",
"home.column_settings.show_reblogs": "Montri diskonigojn",
"home.column_settings.show_replies": "Montri respondojn",
"home.hide_announcements": "Kaŝi la anoncojn",
@@ -314,6 +368,17 @@
"home.pending_critical_update.link": "Vidi ĝisdatigojn",
"home.pending_critical_update.title": "Kritika sekurĝisdatigo estas disponebla!",
"home.show_announcements": "Montri anoncojn",
+ "ignore_notifications_modal.disclaimer": "Mastodon ne povas informi uzantojn, ke vi ignoris iliajn sciigojn. Ignori sciigojn ne malhelpos la mesaĝojn mem esti senditaj.",
+ "ignore_notifications_modal.filter_instead": "Filtri anstataŭe",
+ "ignore_notifications_modal.filter_to_act_users": "Vi ankoraŭ povos akcepti, malakcepti aŭ raporti uzantojn",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "Filtrado helpas eviti eblan konfuzon",
+ "ignore_notifications_modal.filter_to_review_separately": "Vi povas revizii filtritajn sciigojn aparte",
+ "ignore_notifications_modal.ignore": "Ignori sciigojn",
+ "ignore_notifications_modal.limited_accounts_title": "Ĉu ignori sciigojn de moderigitaj kontoj?",
+ "ignore_notifications_modal.new_accounts_title": "Ĉu ignori sciigojn de novaj kontoj?",
+ "ignore_notifications_modal.not_followers_title": "Ĉu ignori sciigojn de homoj, kiuj ne sekvas vin?",
+ "ignore_notifications_modal.not_following_title": "Ĉu ignori sciigojn de homoj, kiujn vi ne sekvas?",
+ "ignore_notifications_modal.private_mentions_title": "Ĉu ignori sciigojn de nepetitaj privataj mencioj?",
"interaction_modal.description.favourite": "Per konto ĉe Mastodon, vi povas stelumiti ĉi tiun afiŝon por sciigi la afiŝanton ke vi aprezigas ŝin kaj konservas por la estonteco.",
"interaction_modal.description.follow": "Kun konto ĉe Mastodon, vi povos sekvi {name} por vidi ties mesaĝojn en via hejmo.",
"interaction_modal.description.reblog": "Kun konto ĉe Mastodon, vi povas diskonigi ĉi tiun afiŝon, por ke viaj propraj sekvantoj vidu ĝin.",
@@ -367,13 +432,15 @@
"keyboard_shortcuts.unfocus": "malenfokusigi la tekstujon aŭ la serĉilon",
"keyboard_shortcuts.up": "iri supren en la listo",
"lightbox.close": "Fermi",
- "lightbox.compress": "Kunpremi bildan vidkeston",
- "lightbox.expand": "Pligrandigi bildan vidkeston",
"lightbox.next": "Antaŭen",
"lightbox.previous": "Malantaŭen",
+ "lightbox.zoom_in": "Zomi al reala grandeco",
+ "lightbox.zoom_out": "Zomi por konveni",
"limited_account_hint.action": "Montru profilon ĉiukaze",
"limited_account_hint.title": "La profilo estas kaŝita de la moderigantoj de {domain}.",
"link_preview.author": "De {name}",
+ "link_preview.more_from_author": "Pli de {name}",
+ "link_preview.shares": "{count, plural, one {{counter} afiŝo} other {{counter} afiŝoj}}",
"lists.account.add": "Aldoni al la listo",
"lists.account.remove": "Forigi de la listo",
"lists.delete": "Forigi la liston",
@@ -390,9 +457,19 @@
"lists.subheading": "Viaj listoj",
"load_pending": "{count,plural, one {# nova elemento} other {# novaj elementoj}}",
"loading_indicator.label": "Ŝargado…",
- "media_gallery.toggle_visible": "{number, plural, one {Kaŝi la bildon} other {Kaŝi la bildojn}}",
+ "media_gallery.hide": "Kaŝi",
"moved_to_account_banner.text": "Via konto {disabledAccount} estas malvalidigita ĉar vi movis ĝin al {movedToAccount}.",
+ "mute_modal.hide_from_notifications": "Kaŝi de sciigoj",
+ "mute_modal.hide_options": "Kaŝi agordojn",
+ "mute_modal.indefinite": "Ĝis mi malsilentas ilin",
+ "mute_modal.show_options": "Montri agordojn",
+ "mute_modal.they_can_mention_and_follow": "Ili povas mencii kaj sekvi vin, sed vi ne vidos ilin.",
+ "mute_modal.they_wont_know": "Ili ne scios, ke ili estas silentigitaj.",
+ "mute_modal.title": "Ĉu silentigi uzanton?",
+ "mute_modal.you_wont_see_mentions": "Vi ne vidos afiŝojn, kiuj mencias ilin.",
+ "mute_modal.you_wont_see_posts": "Ili ankoraŭ povas vidi viajn afiŝojn, sed vi ne vidos iliajn.",
"navigation_bar.about": "Pri",
+ "navigation_bar.administration": "Administrado",
"navigation_bar.advanced_interface": "Malfermi altnivelan retpaĝan interfacon",
"navigation_bar.blocks": "Blokitaj uzantoj",
"navigation_bar.bookmarks": "Legosignoj",
@@ -409,6 +486,7 @@
"navigation_bar.follows_and_followers": "Sekvatoj kaj sekvantoj",
"navigation_bar.lists": "Listoj",
"navigation_bar.logout": "Adiaŭi",
+ "navigation_bar.moderation": "Modereco",
"navigation_bar.mutes": "Silentigitaj uzantoj",
"navigation_bar.opened_in_classic_interface": "Afiŝoj, kontoj, kaj aliaj specifaj paĝoj kiuj estas malfermititaj defaulta en la klasika reta interfaco.",
"navigation_bar.personal": "Persone",
@@ -419,20 +497,71 @@
"navigation_bar.security": "Sekureco",
"not_signed_in_indicator.not_signed_in": "Necesas saluti por aliri tiun rimedon.",
"notification.admin.report": "{name} raportis {target}",
+ "notification.admin.report_account": "{name} raportis {count, plural, one {afiŝon} other {# afiŝojn}} de {target} por {category}",
+ "notification.admin.report_account_other": "{name} raportis {count, plural, one {afiŝon} other {# afiŝojn}} de {target}",
+ "notification.admin.report_statuses": "{name} raportis {target} por {category}",
+ "notification.admin.report_statuses_other": "{name} raportis {target}",
"notification.admin.sign_up": "{name} kreis konton",
+ "notification.admin.sign_up.name_and_others": "{name} kaj {count, plural, one {# alia} other {# aliaj}} kreis konton",
"notification.favourite": "{name} stelumis vian afiŝon",
+ "notification.favourite.name_and_others_with_link": "{name} kaj
{count, plural, one {# alia} other {# aliaj}} ŝatis vian afiŝon",
"notification.follow": "{name} eksekvis vin",
+ "notification.follow.name_and_others": "{name} kaj {count, plural, one {# alia} other {# aliaj}} sekvis vin",
"notification.follow_request": "{name} petis sekvi vin",
+ "notification.follow_request.name_and_others": "{name} kaj {count, plural, one {# alia} other {# aliaj}} petis sekvi vin",
+ "notification.label.mention": "Mencii",
+ "notification.label.private_mention": "Privata mencio",
+ "notification.label.private_reply": "Privata respondo",
+ "notification.label.reply": "Respondi",
+ "notification.mention": "Mencii",
+ "notification.moderation-warning.learn_more": "Lerni pli",
+ "notification.moderation_warning": "Vi ricevis moderigan averton",
+ "notification.moderation_warning.action_delete_statuses": "Kelkaj el viaj afiŝoj estis forigitaj.",
+ "notification.moderation_warning.action_disable": "Via konto estas malŝaltita.",
+ "notification.moderation_warning.action_mark_statuses_as_sensitive": "Kelkaj el viaj afiŝoj estis markitaj kiel sentemaj.",
+ "notification.moderation_warning.action_none": "Via konto ricevis moderigan averton.",
+ "notification.moderation_warning.action_sensitive": "Viaj afiŝoj estos markitaj kiel sentemaj ekde nun.",
+ "notification.moderation_warning.action_silence": "Via konto estis limigita.",
+ "notification.moderation_warning.action_suspend": "Via konto estas malakceptita.",
"notification.own_poll": "Via enketo finiĝis",
+ "notification.poll": "Balotenketo, en kiu vi voĉdonis, finiĝis",
"notification.reblog": "{name} diskonigis vian afiŝon",
+ "notification.reblog.name_and_others_with_link": "{name} kaj
{count, plural, one {# alia} other {# aliaj}} diskonigis vian afiŝon",
+ "notification.relationships_severance_event": "Perditaj konektoj kun {name}",
+ "notification.relationships_severance_event.account_suspension": "Administranto de {from} malakceptis {target}, kio signifas, ke vi ne plu povas ricevi ĝisdatigojn de ili aŭ interagi kun ili.",
+ "notification.relationships_severance_event.domain_block": "Administranto de {from} blokis {target}, inkluzive de {followersCount} de viaj sekvantoj kaj {followingCount, plural, one {# konto} other {# kontoj}} kiujn vi sekvas.",
+ "notification.relationships_severance_event.learn_more": "Lerni pli",
+ "notification.relationships_severance_event.user_domain_block": "Vi blokis {target}, forigante {followersCount} de viaj sekvantoj kaj {followingCount, plural, one {# konto} other {# kontoj}} kiujn vi sekvas.",
"notification.status": "{name} ĵus afiŝis",
"notification.update": "{name} redaktis afiŝon",
+ "notification_requests.accept": "Akcepti",
+ "notification_requests.accept_multiple": "{count, plural, one {Akcepti # peton…} other {Akcepti # petojn…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Akcepti peton} other {Akcepti petojn}}",
+ "notification_requests.confirm_accept_multiple.message": "Vi estas akceptonta {count, plural, one {unu sciigan peton} other {# sciigajn petojn}}. Ĉu vi certas, ke vi volas daŭrigi?",
+ "notification_requests.confirm_accept_multiple.title": "Ĉu akcepti sciigajn petojn?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Malakcepti peton} other {Malakcepti petojn}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Vi estas malakceptonta {count, plural, one {unu sciigan peton} other {# sciigajn petojn}}. Vi ne povos facile aliri {count, plural, one {ĝin} other {ilin}} denove. Ĉu vi certas, ke vi volas daŭrigi?",
+ "notification_requests.confirm_dismiss_multiple.title": "Ĉu malakcepti sciigajn petojn?",
+ "notification_requests.dismiss": "Forĵeti",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Malakcepti # peton…} other {# Malakcepti # petojn…}}",
+ "notification_requests.edit_selection": "Redakti",
+ "notification_requests.exit_selection": "Farita",
+ "notification_requests.explainer_for_limited_account": "Sciigoj de ĉi tiu konto estis filtritaj ĉar la konto estis limigita de moderanto.",
+ "notification_requests.explainer_for_limited_remote_account": "Sciigoj de ĉi tiu konto estis filtritaj ĉar la konto aŭ ĝia servilo estis limigitaj de moderanto.",
+ "notification_requests.maximize": "Maksimumigi",
+ "notification_requests.minimize_banner": "Minimumigi filtritajn sciigojn-rubandon",
+ "notification_requests.notifications_from": "Sciigoj de {name}",
+ "notification_requests.title": "Filtritaj sciigoj",
+ "notification_requests.view": "Vidi sciigojn",
"notifications.clear": "Forviŝi sciigojn",
"notifications.clear_confirmation": "Ĉu vi certas, ke vi volas porĉiame forviŝi ĉiujn viajn sciigojn?",
+ "notifications.clear_title": "Ĉu forigi sciigojn?",
"notifications.column_settings.admin.report": "Novaj raportoj:",
"notifications.column_settings.admin.sign_up": "Novaj registriĝoj:",
"notifications.column_settings.alert": "Sciigoj de la retumilo",
"notifications.column_settings.favourite": "Stelumoj:",
+ "notifications.column_settings.filter_bar.advanced": "Montri ĉiujn kategoriojn",
+ "notifications.column_settings.filter_bar.category": "Rapida filtrila breto",
"notifications.column_settings.follow": "Novaj sekvantoj:",
"notifications.column_settings.follow_request": "Novaj petoj de sekvado:",
"notifications.column_settings.mention": "Mencioj:",
@@ -448,7 +577,7 @@
"notifications.filter.all": "Ĉiuj",
"notifications.filter.boosts": "Diskonigoj",
"notifications.filter.favourites": "Stelumoj",
- "notifications.filter.follows": "Sekvoj",
+ "notifications.filter.follows": "Sekvatoj",
"notifications.filter.mentions": "Mencioj",
"notifications.filter.polls": "Balotenketaj rezultoj",
"notifications.filter.statuses": "Ĝisdatigoj de homoj, kiujn vi sekvas",
@@ -458,6 +587,23 @@
"notifications.permission_denied": "Labortablaj sciigoj ne disponeblas pro peto antaŭe rifuzita de retumiloj",
"notifications.permission_denied_alert": "Labortablaj sciigoj ne povas esti ebligitaj, ĉar retumilpermeso antaŭe estis rifuzita",
"notifications.permission_required": "Labortablaj sciigoj ne disponeblas ĉar la bezonata permeso ne estis donita.",
+ "notifications.policy.accept": "Akcepti",
+ "notifications.policy.accept_hint": "Montri en sciigoj",
+ "notifications.policy.drop": "Ignori",
+ "notifications.policy.drop_hint": "Sendi al la malpleno, por neniam esti vidita denove",
+ "notifications.policy.filter": "Filtri",
+ "notifications.policy.filter_hint": "Sendi al filtritaj sciigoj-enirkesto",
+ "notifications.policy.filter_limited_accounts_hint": "Limigita de servilaj moderigantoj",
+ "notifications.policy.filter_limited_accounts_title": "Moderigitaj kontoj",
+ "notifications.policy.filter_new_accounts.hint": "Kreite en la {days, plural, one {lasta tago} other {# lastaj tagoj}}",
+ "notifications.policy.filter_new_accounts_title": "Novaj kontoj",
+ "notifications.policy.filter_not_followers_hint": "Inkluzive de homoj, kiuj sekvis vin malpli ol {days, plural, one {unu tago} other {# tagoj}}",
+ "notifications.policy.filter_not_followers_title": "Homoj, kiuj ne sekvas vin",
+ "notifications.policy.filter_not_following_hint": "Ĝis vi permane aprobas ilin",
+ "notifications.policy.filter_not_following_title": "Homoj, kiujn vi ne sekvas",
+ "notifications.policy.filter_private_mentions_hint": "Filtrite krom se ĝi respondas al via propra mencio aŭ se vi sekvas la sendinton",
+ "notifications.policy.filter_private_mentions_title": "Nepetitaj privataj mencioj",
+ "notifications.policy.title": "Administri sciigojn de…",
"notifications_permission_banner.enable": "Ŝalti retumilajn sciigojn",
"notifications_permission_banner.how_to_control": "Por ricevi sciigojn kiam Mastodon ne estas malfermita, ebligu labortablajn sciigojn. Vi povas regi precize kiuj specoj de interagoj generas labortablajn sciigojn per la supra butono {icon} post kiam ili estas ebligitaj.",
"notifications_permission_banner.title": "Neniam preterlasas iun ajn",
@@ -467,8 +613,8 @@
"onboarding.actions.go_to_home": "Go to your home feed",
"onboarding.compose.template": "Saluton #Mastodon!",
"onboarding.follows.empty": "Bedaŭrinde, neniu rezulto estas montrebla nuntempe. Vi povas provi serĉi aŭ foliumi la esploran paĝon por trovi kontojn por sekvi, aŭ retrovi baldaŭ.",
- "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
- "onboarding.follows.title": "Popular on Mastodon",
+ "onboarding.follows.lead": "Via hejma fluo estas la ĉefa maniero sperti Mastodon. Ju pli da homoj vi sekvas, des pli aktiva kaj interesa ĝi estos. Por komenci, jen kelkaj sugestoj:",
+ "onboarding.follows.title": "Agordi vian hejman fluon",
"onboarding.profile.discoverable": "Trovebligi mian profilon",
"onboarding.profile.discoverable_hint": "Kiam vi aliĝi al trovebleco ĉe Mastodon, viaj afiŝoj eble aperos en serĉaj rezultoj kaj populariĝoj, kaj via profilo eble estas sugestota al personoj kun similaj intereseoj al vi.",
"onboarding.profile.display_name": "Publika nomo",
@@ -489,7 +635,7 @@
"onboarding.start.title": "Vi atingas ĝin!",
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
"onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}",
- "onboarding.steps.publish_status.body": "Say hello to the world.",
+ "onboarding.steps.publish_status.body": "Salutu la mondon per teksto, fotoj, filmetoj aŭ balotenketoj {emoji}",
"onboarding.steps.publish_status.title": "Fari vian unuan afiŝon",
"onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.",
"onboarding.steps.setup_profile.title": "Customize your profile",
@@ -519,6 +665,7 @@
"privacy.private.short": "Sekvantoj",
"privacy.public.long": "Ĉiujn ajn ĉe kaj ekster Mastodon",
"privacy.public.short": "Publika",
+ "privacy.unlisted.additional": "Ĉi tio kondutas ekzakte kiel publika, krom ke la afiŝo ne aperos en vivaj fluoj aŭ kradvortoj, esploro aŭ Mastodon-serĉo, eĉ se vi estas enskribita en la tuta konto.",
"privacy.unlisted.long": "Malpli algoritmaj fanfaroj",
"privacy.unlisted.short": "Diskrete publika",
"privacy_policy.last_updated": "Laste ĝisdatigita en {date}",
@@ -538,7 +685,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"relative_time.today": "hodiaŭ",
+ "reply_indicator.attachments": "{count, plural, one {# aldonaĵo} other {# aldonaĵoj}}",
"reply_indicator.cancel": "Nuligi",
+ "reply_indicator.poll": "Balotenketo",
"report.block": "Bloki",
"report.block_explanation": "Vi ne vidos iliajn afiŝojn. Ili ne povos vidi viajn afiŝojn, nek sekvi vin. Ili ne scios, ke vi blokas ilin.",
"report.categories.legal": "Laŭleĝa",
@@ -581,9 +730,13 @@
"report.unfollow_explanation": "Vi sekvas ĉi tiun konton. Por ne plu vidi ĝiajn afiŝojn en via hejma templinio, ĉesu sekvi ĝin.",
"report_notification.attached_statuses": "{count, plural, one {{count} afiŝo almetita} other {{count} afiŝoj almetitaj}}",
"report_notification.categories.legal": "Laŭleĝa",
+ "report_notification.categories.legal_sentence": "kontraŭleĝa enhavo",
"report_notification.categories.other": "Alia",
+ "report_notification.categories.other_sentence": "alia",
"report_notification.categories.spam": "Trudmesaĝo",
+ "report_notification.categories.spam_sentence": "trudmesaĝo",
"report_notification.categories.violation": "Malobservo de la regulo",
+ "report_notification.categories.violation_sentence": "malobservo de la regulo",
"report_notification.open": "Malfermi la raporton",
"search.no_recent_searches": "Neniuj lastaj serĉoj",
"search.placeholder": "Serĉi",
@@ -611,8 +764,11 @@
"server_banner.about_active_users": "Personoj uzantaj ĉi tiun servilon dum la lastaj 30 tagoj (Aktivaj Uzantoj Monate)",
"server_banner.active_users": "aktivaj uzantoj",
"server_banner.administered_by": "Administrata de:",
+ "server_banner.is_one_of_many": "{domain} estas unu el la multaj sendependaj Mastodon-serviloj, kiujn vi povas uzi por partopreni en la fediverso.",
"server_banner.server_stats": "Statistikoj de la servilo:",
"sign_in_banner.create_account": "Krei konton",
+ "sign_in_banner.follow_anyone": "Sekvi iun ajn tra la fediverso kaj vidi ĉion en kronologia ordo. Neniuj algoritmoj, reklamoj aŭ klakbetoj videblas.",
+ "sign_in_banner.mastodon_is": "Mastodonto estas la plej bona maniero por resti flank-al-flanke kun kio okazas.",
"sign_in_banner.sign_in": "Saluti",
"sign_in_banner.sso_redirect": "Ensalutu aŭ Registriĝi",
"status.admin_account": "Malfermi fasadon de moderigado por @{name}",
@@ -622,15 +778,18 @@
"status.bookmark": "Aldoni al la legosignoj",
"status.cancel_reblog_private": "Ne plu diskonigi",
"status.cannot_reblog": "Ĉi tiun afiŝon ne eblas diskonigi",
+ "status.continued_thread": "Daŭrigis fadenon",
"status.copy": "Kopii la ligilon al la mesaĝo",
"status.delete": "Forigi",
"status.detailed_status": "Detala konversacia vido",
"status.direct": "Private mencii @{name}",
"status.direct_indicator": "Privata mencio",
"status.edit": "Redakti",
+ "status.edited": "Laste redaktita {date}",
"status.edited_x_times": "Redactita {count, plural, one {{count} fojon} other {{count} fojojn}}",
- "status.embed": "Enkorpigi",
+ "status.embed": "Akiri enkorpigan kodon",
"status.favourite": "Ŝatata",
+ "status.favourites": "{count, plural, one {plej ŝatata} other {plej ŝatataj}}",
"status.filter": "Filtri ĉi tiun afiŝon",
"status.history.created": "{name} kreis {date}",
"status.history.edited": "{name} redaktis {date}",
@@ -649,9 +808,11 @@
"status.reblog": "Diskonigi",
"status.reblog_private": "Diskonigi kun la sama videbleco",
"status.reblogged_by": "{name} diskonigis",
+ "status.reblogs": "{count, plural, one {diskonigo} other {diskonigoj}}",
"status.reblogs.empty": "Ankoraŭ neniu diskonigis tiun afiŝon. Kiam iu faras tion, ri aperos ĉi tie.",
"status.redraft": "Forigi kaj reskribi",
"status.remove_bookmark": "Forigi legosignon",
+ "status.replied_in_thread": "Respondis en fadeno",
"status.replied_to": "Respondis al {name}",
"status.reply": "Respondi",
"status.replyAll": "Respondi al la fadeno",
diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json
index 85561495d7..8a37a33df2 100644
--- a/app/javascript/mastodon/locales/es-AR.json
+++ b/app/javascript/mastodon/locales/es-AR.json
@@ -97,6 +97,8 @@
"block_modal.title": "¿Bloquear usuario?",
"block_modal.you_wont_see_mentions": "No verás mensajes que los mencionen.",
"boost_modal.combo": "Podés hacer clic en {combo} para saltar esto la próxima vez",
+ "boost_modal.reblog": "¿Adherir al mensaje?",
+ "boost_modal.undo_reblog": "¿Dejar de adherir al mensaje?",
"bundle_column_error.copy_stacktrace": "Copiar informe de error",
"bundle_column_error.error.body": "La página solicitada no pudo ser cargada. Podría deberse a un error de programación en nuestro código o a un problema de compatibilidad con el navegador web.",
"bundle_column_error.error.title": "¡Epa!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Dejar de seguir",
"confirmations.unfollow.message": "¿Estás seguro que querés dejar de seguir a {name}?",
"confirmations.unfollow.title": "¿Dejar de seguir al usuario?",
+ "content_warning.hide": "Ocultar mensaje",
+ "content_warning.show": "Mostrar de todos modos",
"conversation.delete": "Eliminar conversación",
"conversation.mark_as_read": "Marcar como leída",
"conversation.open": "Ver conversación",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Usar una categoría existente o crear una nueva",
"filter_modal.select_filter.title": "Filtrar este mensaje",
"filter_modal.title.status": "Filtrar un mensaje",
+ "filter_warning.matches_filter": "Coincide con el filtro “{title}”",
"filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nadie} one {una persona} other {# personas}} que podrías conocer",
"filtered_notifications_banner.title": "Notificaciones filtradas",
"firehose.all": "Todos",
@@ -427,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Quitar el foco del área de texto de redacción o de búsqueda",
"keyboard_shortcuts.up": "Subir en la lista",
"lightbox.close": "Cerrar",
- "lightbox.compress": "Comprimir cuadro de vista de imagen",
- "lightbox.expand": "Expandir cuadro de vista de imagen",
"lightbox.next": "Siguiente",
"lightbox.previous": "Anterior",
+ "lightbox.zoom_in": "Ampliar al tamaño real",
+ "lightbox.zoom_out": "Ampliar hasta ajustar",
"limited_account_hint.action": "Mostrar perfil de todos modos",
"limited_account_hint.title": "Este perfil fue ocultado por los moderadores de {domain}.",
"link_preview.author": "Por {name}",
@@ -452,7 +457,7 @@
"lists.subheading": "Tus listas",
"load_pending": "{count, plural, one {# elemento nuevo} other {# elementos nuevos}}",
"loading_indicator.label": "Cargando…",
- "media_gallery.toggle_visible": "Ocultar {number, plural, one {imagen} other {imágenes}}",
+ "media_gallery.hide": "Ocultar",
"moved_to_account_banner.text": "Tu cuenta {disabledAccount} está actualmente deshabilitada porque te mudaste a {movedToAccount}.",
"mute_modal.hide_from_notifications": "Ocultar en las notificaciones",
"mute_modal.hide_options": "Ocultar opciones",
@@ -464,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "No verás mensajes que los mencionen.",
"mute_modal.you_wont_see_posts": "Todavía pueden ver tus mensajes, pero vos no verás los suyos.",
"navigation_bar.about": "Información",
+ "navigation_bar.administration": "Administración",
"navigation_bar.advanced_interface": "Abrir en interface web avanzada",
"navigation_bar.blocks": "Usuarios bloqueados",
"navigation_bar.bookmarks": "Marcadores",
@@ -480,6 +486,7 @@
"navigation_bar.follows_and_followers": "Cuentas seguidas y seguidores",
"navigation_bar.lists": "Listas",
"navigation_bar.logout": "Cerrar sesión",
+ "navigation_bar.moderation": "Moderación",
"navigation_bar.mutes": "Usuarios silenciados",
"navigation_bar.opened_in_classic_interface": "Los mensajes, las cuentas y otras páginas específicas se abren predeterminadamente en la interface web clásica.",
"navigation_bar.personal": "Personal",
@@ -552,8 +559,6 @@
"notifications.column_settings.admin.report": "Nuevas denuncias:",
"notifications.column_settings.admin.sign_up": "Nuevos registros:",
"notifications.column_settings.alert": "Notificaciones de escritorio",
- "notifications.column_settings.beta.category": "Funciones experimentales",
- "notifications.column_settings.beta.grouping": "Agrupar notificaciones",
"notifications.column_settings.favourite": "Favoritos:",
"notifications.column_settings.filter_bar.advanced": "Mostrar todas las categorías",
"notifications.column_settings.filter_bar.category": "Barra de filtrado rápido",
@@ -773,6 +778,7 @@
"status.bookmark": "Marcar",
"status.cancel_reblog_private": "Quitar adhesión",
"status.cannot_reblog": "No se puede adherir a este mensaje",
+ "status.continued_thread": "Continuación de hilo",
"status.copy": "Copiar enlace al mensaje",
"status.delete": "Eliminar",
"status.detailed_status": "Vista de conversación detallada",
@@ -781,7 +787,7 @@
"status.edit": "Editar",
"status.edited": "Última edición: {date}",
"status.edited_x_times": "Editado {count, plural, one {{count} vez} other {{count} veces}}",
- "status.embed": "Insertar",
+ "status.embed": "Obtener código para insertar",
"status.favourite": "Marcar como favorito",
"status.favourites": "{count, plural, one {# voto} other {# votos}}",
"status.filter": "Filtrar este mensaje",
@@ -806,6 +812,7 @@
"status.reblogs.empty": "Todavía nadie adhirió a este mensaje. Cuando alguien lo haga, se mostrará acá.",
"status.redraft": "Eliminar mensaje original y editarlo",
"status.remove_bookmark": "Quitar marcador",
+ "status.replied_in_thread": "Respuesta en hilo",
"status.replied_to": "Respondió a {name}",
"status.reply": "Responder",
"status.replyAll": "Responder al hilo",
diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json
index 30a3a42fde..52ebf0ae18 100644
--- a/app/javascript/mastodon/locales/es-MX.json
+++ b/app/javascript/mastodon/locales/es-MX.json
@@ -39,11 +39,11 @@
"account.following_counter": "{count, plural, one {{counter} siguiendo} other {{counter} siguiendo}}",
"account.follows.empty": "Este usuario todavía no sigue a nadie.",
"account.go_to_profile": "Ir al perfil",
- "account.hide_reblogs": "Ocultar retoots de @{name}",
+ "account.hide_reblogs": "Ocultar impulsos de @{name}",
"account.in_memoriam": "En memoria.",
"account.joined_short": "Se unió",
"account.languages": "Cambiar idiomas suscritos",
- "account.link_verified_on": "El proprietario de este link fue comprobado el {date}",
+ "account.link_verified_on": "El proprietario de este enlace fue comprobado el {date}",
"account.locked_info": "El estado de privacidad de esta cuenta està configurado como bloqueado. El proprietario debe revisar manualmente quien puede seguirle.",
"account.media": "Multimedia",
"account.mention": "Mencionar a @{name}",
@@ -61,7 +61,7 @@
"account.requested": "Esperando aprobación. Haga clic para cancelar la solicitud de seguimiento",
"account.requested_follow": "{name} ha solicitado seguirte",
"account.share": "Compartir el perfil de @{name}",
- "account.show_reblogs": "Mostrar retoots de @{name}",
+ "account.show_reblogs": "Mostrar impulsos de @{name}",
"account.statuses_counter": "{count, plural, one {{counter} publicación} other {{counter} publicaciones}}",
"account.unblock": "Desbloquear a @{name}",
"account.unblock_domain": "Mostrar a {domain}",
@@ -70,8 +70,8 @@
"account.unfollow": "Dejar de seguir",
"account.unmute": "Dejar de silenciar a @{name}",
"account.unmute_notifications_short": "Dejar de silenciar notificaciones",
- "account.unmute_short": "Desmutear",
- "account_note.placeholder": "Clic para añadir nota",
+ "account.unmute_short": "Dejar de silenciar",
+ "account_note.placeholder": "Haz clic para agregar una nota",
"admin.dashboard.daily_retention": "Tasa de retención de usuarios por día después de unirse",
"admin.dashboard.monthly_retention": "Tasa de retención de usuarios por mes después de unirse",
"admin.dashboard.retention.average": "Promedio",
@@ -97,6 +97,8 @@
"block_modal.title": "¿Bloquear usuario?",
"block_modal.you_wont_see_mentions": "No verás publicaciones que los mencionen.",
"boost_modal.combo": "Puedes hacer clic en {combo} para saltar este aviso la próxima vez",
+ "boost_modal.reblog": "¿Deseas impulsar la publicación?",
+ "boost_modal.undo_reblog": "¿Dejar de impulsar la publicación?",
"bundle_column_error.copy_stacktrace": "Copiar informe de error",
"bundle_column_error.error.body": "La página solicitada no pudo ser renderizada. Podría deberse a un error en nuestro código o a un problema de compatibilidad con el navegador.",
"bundle_column_error.error.title": "¡Oh, no!",
@@ -128,7 +130,7 @@
"column.lists": "Listas",
"column.mutes": "Usuarios silenciados",
"column.notifications": "Notificaciones",
- "column.pins": "Toots fijados",
+ "column.pins": "Publicaciones fijadas",
"column.public": "Línea de tiempo federada",
"column_back_button.label": "Atrás",
"column_header.hide_settings": "Ocultar configuración",
@@ -146,10 +148,10 @@
"compose.published.body": "Publicado.",
"compose.published.open": "Abrir",
"compose.saved.body": "Publicación guardada.",
- "compose_form.direct_message_warning_learn_more": "Aprender mas",
+ "compose_form.direct_message_warning_learn_more": "Saber más",
"compose_form.encryption_warning": "Las publicaciones en Mastodon no están cifradas de extremo a extremo. No comparta ninguna información sensible en Mastodon.",
- "compose_form.hashtag_warning": "Este toot no será listado bajo ningún hashtag dado que no es público. Solo toots públicos pueden ser buscados por hashtag.",
- "compose_form.lock_disclaimer": "Tu cuenta no está bloqueada. Todos pueden seguirte para ver tus toots solo para seguidores.",
+ "compose_form.hashtag_warning": "Esta publicación no será listada bajo ninguna etiqueta dado que no es pública. Solo publicaciones públicas pueden ser buscadas por etiqueta.",
+ "compose_form.lock_disclaimer": "Tu cuenta no está {locked}. Todos pueden seguirte para ver tus publicaciones solo para seguidores.",
"compose_form.lock_disclaimer.lock": "bloqueado",
"compose_form.placeholder": "¿En qué estás pensando?",
"compose_form.poll.duration": "Duración de la encuesta",
@@ -163,35 +165,37 @@
"compose_form.publish_form": "Publicar",
"compose_form.reply": "Respuesta",
"compose_form.save_changes": "Actualización",
- "compose_form.spoiler.marked": "Texto oculto tras la advertencia",
- "compose_form.spoiler.unmarked": "Texto no oculto",
+ "compose_form.spoiler.marked": "Quitar advertencia de contenido",
+ "compose_form.spoiler.unmarked": "Añadir advertencia de contenido",
"compose_form.spoiler_placeholder": "Advertencia de contenido (opcional)",
"confirmation_modal.cancel": "Cancelar",
"confirmations.block.confirm": "Bloquear",
"confirmations.delete.confirm": "Eliminar",
- "confirmations.delete.message": "¿Estás seguro de que quieres borrar este toot?",
+ "confirmations.delete.message": "¿Estás seguro de que quieres borrar esta publicación?",
"confirmations.delete.title": "¿Eliminar publicación?",
"confirmations.delete_list.confirm": "Eliminar",
"confirmations.delete_list.message": "¿Seguro que quieres borrar esta lista permanentemente?",
- "confirmations.delete_list.title": "¿Eliminar lista?",
+ "confirmations.delete_list.title": "¿Deseas eliminar la lista?",
"confirmations.discard_edit_media.confirm": "Descartar",
"confirmations.discard_edit_media.message": "Tienes cambios sin guardar en la descripción o vista previa del archivo, ¿deseas descartarlos de cualquier manera?",
"confirmations.edit.confirm": "Editar",
"confirmations.edit.message": "Editar sobrescribirá el mensaje que estás escribiendo. ¿Estás seguro de que deseas continuar?",
- "confirmations.edit.title": "¿Sobrescribir publicación?",
+ "confirmations.edit.title": "¿Sobreescribir publicación?",
"confirmations.logout.confirm": "Cerrar sesión",
- "confirmations.logout.message": "¿Estás seguro de querer cerrar la sesión?",
- "confirmations.logout.title": "¿Cerrar sesión?",
+ "confirmations.logout.message": "¿Estás seguro de que quieres cerrar la sesión?",
+ "confirmations.logout.title": "¿Deseas cerrar sesión?",
"confirmations.mute.confirm": "Silenciar",
"confirmations.redraft.confirm": "Borrar y volver a borrador",
"confirmations.redraft.message": "¿Estás seguro que quieres borrar esta publicación y editarla? Los favoritos e impulsos se perderán, y las respuestas a la publicación original quedarán separadas.",
"confirmations.redraft.title": "¿Borrar y volver a redactar la publicación?",
"confirmations.reply.confirm": "Responder",
"confirmations.reply.message": "Responder sobrescribirá el mensaje que estás escribiendo. ¿Estás seguro de que deseas continuar?",
- "confirmations.reply.title": "¿Sobrescribir publicación?",
+ "confirmations.reply.title": "¿Sobreescribir publicación?",
"confirmations.unfollow.confirm": "Dejar de seguir",
"confirmations.unfollow.message": "¿Estás seguro de que quieres dejar de seguir a {name}?",
"confirmations.unfollow.title": "¿Dejar de seguir al usuario?",
+ "content_warning.hide": "Ocultar publicación",
+ "content_warning.show": "Mostrar de todos modos",
"conversation.delete": "Borrar conversación",
"conversation.mark_as_read": "Marcar como leído",
"conversation.open": "Ver conversación",
@@ -209,8 +213,8 @@
"dismissable_banner.dismiss": "Descartar",
"dismissable_banner.explore_links": "Estas noticias están siendo discutidas por personas en este y otros servidores de la red descentralizada en este momento.",
"dismissable_banner.explore_statuses": "Estas son las publicaciones que están en tendencia en la red ahora. Las publicaciones recientes con más impulsos y favoritos se muestran más arriba.",
- "dismissable_banner.explore_tags": "Se trata de hashtags que están ganando adeptos en las redes sociales hoy en día. Los hashtags que son utilizados por más personas diferentes se clasifican mejor.",
- "dismissable_banner.public_timeline": "Estos son los toots públicos más recientes de personas en la web social a las que sigue la gente en {domain}.",
+ "dismissable_banner.explore_tags": "Se trata de etiquetas que están ganando adeptos en las redes sociales hoy en día. Las etiquetas que son utilizadas por más personas diferentes se clasifican mejor.",
+ "dismissable_banner.public_timeline": "Estas son las publicaciones públicas más recientes de personas en la web social a las que sigue la gente en {domain}.",
"domain_block_modal.block": "Bloquear servidor",
"domain_block_modal.block_account_instead": "Bloquear @{name} en su lugar",
"domain_block_modal.they_can_interact_with_old_posts": "Las personas de este servidor pueden interactuar con tus publicaciones antiguas.",
@@ -232,7 +236,7 @@
"domain_pill.your_handle": "Tu alias:",
"domain_pill.your_server": "Tu hogar digital, donde residen todas tus publicaciones. ¿No te gusta este sitio? Muévete a otro servidor en cualquier momento y llévate a tus seguidores.",
"domain_pill.your_username": "Tu identificador único en este servidor. Es posible encontrar usuarios con el mismo nombre de usuario en diferentes servidores.",
- "embed.instructions": "Añade este toot a tu sitio web con el siguiente código.",
+ "embed.instructions": "Añade esta publicación a tu sitio web con el siguiente código.",
"embed.preview": "Así es como se verá:",
"emoji_button.activity": "Actividad",
"emoji_button.clear": "Borrar",
@@ -245,16 +249,16 @@
"emoji_button.objects": "Objetos",
"emoji_button.people": "Gente",
"emoji_button.recent": "Usados frecuentemente",
- "emoji_button.search": "Buscar…",
+ "emoji_button.search": "Buscar...",
"emoji_button.search_results": "Resultados de búsqueda",
"emoji_button.symbols": "Símbolos",
"emoji_button.travel": "Viajes y lugares",
"empty_column.account_hides_collections": "Este usuario ha elegido no hacer disponible esta información",
"empty_column.account_suspended": "Cuenta suspendida",
- "empty_column.account_timeline": "¡No hay toots aquí!",
+ "empty_column.account_timeline": "¡No hay publicaciones aquí!",
"empty_column.account_unavailable": "Perfil no disponible",
"empty_column.blocks": "Aún no has bloqueado a ningún usuario.",
- "empty_column.bookmarked_statuses": "Aún no tienes ningún toot guardado como marcador. Cuando guardes uno, se mostrará aquí.",
+ "empty_column.bookmarked_statuses": "Aún no tienes ninguna publicación guardada como marcador. Cuando guardes una, se mostrará aquí.",
"empty_column.community": "La línea de tiempo local está vacía. ¡Escribe algo para empezar la fiesta!",
"empty_column.direct": "Aún no tienes menciones privadas. Cuando envíes o recibas una, aparecerán aquí.",
"empty_column.domain_blocks": "Todavía no hay dominios ocultos.",
@@ -262,8 +266,8 @@
"empty_column.favourited_statuses": "Todavía no tienes publicaciones favoritas. Cuando le des favorito a una publicación se mostrarán acá.",
"empty_column.favourites": "Todavía nadie marcó como favorito esta publicación. Cuando alguien lo haga, se mostrará aquí.",
"empty_column.follow_requests": "No tienes ninguna petición de seguidor. Cuando recibas una, se mostrará aquí.",
- "empty_column.followed_tags": "No estás siguiendo ningún hashtag todavía. Cuando lo hagas, aparecerá aquí.",
- "empty_column.hashtag": "No hay nada en este hashtag aún.",
+ "empty_column.followed_tags": "No estás siguiendo ninguna etiqueta todavía. Cuando lo hagas, aparecerá aquí.",
+ "empty_column.hashtag": "No hay nada en esta etiqueta aún.",
"empty_column.home": "No estás siguiendo a nadie aún. Visita {public} o haz búsquedas para empezar y conocer gente nueva.",
"empty_column.list": "No hay nada en esta lista aún. Cuando miembros de esta lista publiquen nuevos estatus, estos aparecerán qui.",
"empty_column.lists": "No tienes ninguna lista. cuando crees una, se mostrará aquí.",
@@ -299,7 +303,8 @@
"filter_modal.select_filter.subtitle": "Usar una categoría existente o crear una nueva",
"filter_modal.select_filter.title": "Filtrar esta publicación",
"filter_modal.title.status": "Filtrar una publicación",
- "filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nadie} one {una persona} other {# personas}} que puede que conozcas",
+ "filter_warning.matches_filter": "Coincide con el filtro “{title}”",
+ "filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nadie} one {una persona} other {# people}} que puede que tú conozcas",
"filtered_notifications_banner.title": "Notificaciones filtradas",
"firehose.all": "Todas",
"firehose.local": "Este servidor",
@@ -310,7 +315,7 @@
"follow_suggestions.curated_suggestion": "Recomendaciones del equipo",
"follow_suggestions.dismiss": "No mostrar de nuevo",
"follow_suggestions.featured_longer": "Escogidos por el equipo de {domain}",
- "follow_suggestions.friends_of_friends_longer": "Populares entre las personas a las que sigues",
+ "follow_suggestions.friends_of_friends_longer": "Popular entre las personas a las que sigues",
"follow_suggestions.hints.featured": "Este perfil ha sido seleccionado a mano por el equipo de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Este perfil es popular entre las personas que sigues.",
"follow_suggestions.hints.most_followed": "Este perfil es uno de los más seguidos en {domain}.",
@@ -318,11 +323,11 @@
"follow_suggestions.hints.similar_to_recently_followed": "Este perfil es similar a los perfiles que has seguido recientemente.",
"follow_suggestions.personalized_suggestion": "Sugerencia personalizada",
"follow_suggestions.popular_suggestion": "Sugerencia popular",
- "follow_suggestions.popular_suggestion_longer": "Populares en {domain}",
+ "follow_suggestions.popular_suggestion_longer": "Popular en {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Similares a los perfiles que has seguido recientemente",
"follow_suggestions.view_all": "Ver todo",
"follow_suggestions.who_to_follow": "Recomendamos seguir",
- "followed_tags": "Hashtags seguidos",
+ "followed_tags": "Etiquetas seguidas",
"footer.about": "Acerca de",
"footer.directory": "Directorio de perfiles",
"footer.get_app": "Obtener la aplicación",
@@ -339,8 +344,8 @@
"hashtag.column_settings.select.no_options_message": "No se encontraron sugerencias",
"hashtag.column_settings.select.placeholder": "Introducir etiquetas…",
"hashtag.column_settings.tag_mode.all": "Todos estos",
- "hashtag.column_settings.tag_mode.any": "Cualquiera de estos",
- "hashtag.column_settings.tag_mode.none": "Ninguno de estos",
+ "hashtag.column_settings.tag_mode.any": "Cualquiera de estas",
+ "hashtag.column_settings.tag_mode.none": "Ninguna de estas",
"hashtag.column_settings.tag_toggle": "Incluye etiquetas adicionales para esta columna",
"hashtag.counter_by_accounts": "{count, plural, one {{counter} participante} other {{counter} participantes}}",
"hashtag.counter_by_uses": "{count, plural, one {{counter} publicación} other {{counter} publicaciones}}",
@@ -356,7 +361,7 @@
"hints.profiles.see_more_posts": "Ver más publicaciones en {domain}",
"hints.threads.replies_may_be_missing": "Puede que no se muestren algunas respuestas de otros servidores.",
"hints.threads.see_more": "Ver más respuestas en {domain}",
- "home.column_settings.show_reblogs": "Mostrar retoots",
+ "home.column_settings.show_reblogs": "Mostrar impulsos",
"home.column_settings.show_replies": "Mostrar respuestas",
"home.hide_announcements": "Ocultar anuncios",
"home.pending_critical_update.body": "¡Por favor actualiza tu servidor Mastodon lo antes posible!",
@@ -364,14 +369,14 @@
"home.pending_critical_update.title": "¡Actualización de seguridad crítica disponible!",
"home.show_announcements": "Mostrar anuncios",
"ignore_notifications_modal.disclaimer": "Mastodon no puede informar a los usuarios que has ignorado sus notificaciones. Ignorar notificaciones no impedirá que se sigan enviando los mensajes.",
- "ignore_notifications_modal.filter_instead": "Filtrar en vez de ignorar",
+ "ignore_notifications_modal.filter_instead": "Filtrar en su lugar",
"ignore_notifications_modal.filter_to_act_users": "Aún podrás aceptar, rechazar o reportar usuarios",
"ignore_notifications_modal.filter_to_avoid_confusion": "Filtrar ayuda a evitar confusiones potenciales",
"ignore_notifications_modal.filter_to_review_separately": "Puedes revisar las notificaciones filtradas por separado",
"ignore_notifications_modal.ignore": "Ignorar notificaciones",
"ignore_notifications_modal.limited_accounts_title": "¿Ignorar notificaciones de cuentas moderadas?",
"ignore_notifications_modal.new_accounts_title": "¿Ignorar notificaciones de cuentas nuevas?",
- "ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de personas que no te sigue?",
+ "ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de personas que no te siguen?",
"ignore_notifications_modal.not_following_title": "¿Ignorar notificaciones de personas a las que no sigues?",
"ignore_notifications_modal.private_mentions_title": "¿Ignorar notificaciones de menciones privadas no solicitadas?",
"interaction_modal.description.favourite": "Con una cuenta en Mastodon, puedes marcar como favorita esta publicación para que el autor sepa que te gusta, y guardala para más adelante.",
@@ -394,13 +399,13 @@
"intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}",
"keyboard_shortcuts.back": "volver atrás",
"keyboard_shortcuts.blocked": "abrir una lista de usuarios bloqueados",
- "keyboard_shortcuts.boost": "retootear",
+ "keyboard_shortcuts.boost": "Impulsar publicación",
"keyboard_shortcuts.column": "enfocar un estado en una de las columnas",
"keyboard_shortcuts.compose": "enfocar el área de texto de redacción",
"keyboard_shortcuts.description": "Descripción",
"keyboard_shortcuts.direct": "para abrir la columna de menciones privadas",
"keyboard_shortcuts.down": "mover hacia abajo en la lista",
- "keyboard_shortcuts.enter": "abrir estado",
+ "keyboard_shortcuts.enter": "Abrir publicación",
"keyboard_shortcuts.favourite": "Marcar como favorita la publicación",
"keyboard_shortcuts.favourites": "Abrir lista de favoritos",
"keyboard_shortcuts.federated": "abrir el timeline federado",
@@ -414,23 +419,23 @@
"keyboard_shortcuts.my_profile": "abrir tu perfil",
"keyboard_shortcuts.notifications": "abrir la columna de notificaciones",
"keyboard_shortcuts.open_media": "para abrir archivos multimedia",
- "keyboard_shortcuts.pinned": "abrir la lista de toots destacados",
+ "keyboard_shortcuts.pinned": "Abrir la lista de publicaciones fijadas",
"keyboard_shortcuts.profile": "abrir el perfil del autor",
- "keyboard_shortcuts.reply": "para responder",
+ "keyboard_shortcuts.reply": "Responder a la publicación",
"keyboard_shortcuts.requests": "abrir la lista de peticiones de seguidores",
"keyboard_shortcuts.search": "para poner el foco en la búsqueda",
"keyboard_shortcuts.spoilers": "para mostrar/ocultar el campo CW",
"keyboard_shortcuts.start": "abrir la columna \"comenzar\"",
"keyboard_shortcuts.toggle_hidden": "mostrar/ocultar texto tras aviso de contenido (CW)",
"keyboard_shortcuts.toggle_sensitivity": "mostrar/ocultar medios",
- "keyboard_shortcuts.toot": "para comenzar un nuevo toot",
+ "keyboard_shortcuts.toot": "Comenzar una nueva publicación",
"keyboard_shortcuts.unfocus": "para retirar el foco de la caja de redacción/búsqueda",
"keyboard_shortcuts.up": "para ir hacia arriba en la lista",
"lightbox.close": "Cerrar",
- "lightbox.compress": "Comprimir cuadro de visualización de imagen",
- "lightbox.expand": "Expandir cuadro de visualización de imagen",
"lightbox.next": "Siguiente",
"lightbox.previous": "Anterior",
+ "lightbox.zoom_in": "Ampliar al tamaño real",
+ "lightbox.zoom_out": "Ampliar para ajustar",
"limited_account_hint.action": "Mostrar perfil de todos modos",
"limited_account_hint.title": "Este perfil ha sido ocultado por los moderadores de {domain}.",
"link_preview.author": "Por {name}",
@@ -452,7 +457,7 @@
"lists.subheading": "Tus listas",
"load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}",
"loading_indicator.label": "Cargando…",
- "media_gallery.toggle_visible": "Cambiar visibilidad",
+ "media_gallery.hide": "Ocultar",
"moved_to_account_banner.text": "Tu cuenta {disabledAccount} está actualmente deshabilitada porque te has mudado a {movedToAccount}.",
"mute_modal.hide_from_notifications": "Ocultar de las notificaciones",
"mute_modal.hide_options": "Ocultar opciones",
@@ -464,11 +469,12 @@
"mute_modal.you_wont_see_mentions": "No verás publicaciones que los mencionen.",
"mute_modal.you_wont_see_posts": "Todavía pueden ver tus publicaciones, pero tú no verás las de ellos.",
"navigation_bar.about": "Acerca de",
+ "navigation_bar.administration": "Administración",
"navigation_bar.advanced_interface": "Abrir en interfaz web avanzada",
"navigation_bar.blocks": "Usuarios bloqueados",
"navigation_bar.bookmarks": "Marcadores",
"navigation_bar.community_timeline": "Historia local",
- "navigation_bar.compose": "Escribir un nuevo toot",
+ "navigation_bar.compose": "Redactar una nueva publicación",
"navigation_bar.direct": "Menciones privadas",
"navigation_bar.discover": "Descubrir",
"navigation_bar.domain_blocks": "Dominios ocultos",
@@ -476,32 +482,33 @@
"navigation_bar.favourites": "Favoritos",
"navigation_bar.filters": "Palabras silenciadas",
"navigation_bar.follow_requests": "Solicitudes para seguirte",
- "navigation_bar.followed_tags": "Hashtags seguidos",
+ "navigation_bar.followed_tags": "Etiquetas seguidas",
"navigation_bar.follows_and_followers": "Siguiendo y seguidores",
"navigation_bar.lists": "Listas",
"navigation_bar.logout": "Cerrar sesión",
+ "navigation_bar.moderation": "Moderación",
"navigation_bar.mutes": "Usuarios silenciados",
"navigation_bar.opened_in_classic_interface": "Publicaciones, cuentas y otras páginas específicas se abren por defecto en la interfaz web clásica.",
"navigation_bar.personal": "Personal",
- "navigation_bar.pins": "Toots fijados",
+ "navigation_bar.pins": "Publicaciones fijadas",
"navigation_bar.preferences": "Preferencias",
"navigation_bar.public_timeline": "Historia federada",
"navigation_bar.search": "Buscar",
"navigation_bar.security": "Seguridad",
"not_signed_in_indicator.not_signed_in": "Necesitas iniciar sesión para acceder a este recurso.",
"notification.admin.report": "{name} denunció a {target}",
- "notification.admin.report_account": "{name} informó de {count, plural, one {una publicación} other {# publicaciones}} de {target} por {category}",
- "notification.admin.report_account_other": "{name} informó de {count, plural, one {una publicación} other {# publicaciones}} de {target}",
- "notification.admin.report_statuses": "{name} informó de {target} por {category}",
- "notification.admin.report_statuses_other": "{name} informó de {target}",
+ "notification.admin.report_account": "{name} reportó {count, plural, one {una publicación} other {# publicaciones}} de {target} por {category}",
+ "notification.admin.report_account_other": "{name} reportó {count, plural, one {una publicación} other {# publicaciones}} de {target}",
+ "notification.admin.report_statuses": "{name} reportó {target} por {category}",
+ "notification.admin.report_statuses_other": "{name} reportó {target}",
"notification.admin.sign_up": "{name} se unio",
- "notification.admin.sign_up.name_and_others": "{name} y {count, plural, one {# más} other {# más}} se registraron",
+ "notification.admin.sign_up.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} se registraron",
"notification.favourite": "{name} marcó como favorita tu publicación",
- "notification.favourite.name_and_others_with_link": "{name} y
{count, plural, one {# más} other {# más}} marcaron tu publicación como favorita",
+ "notification.favourite.name_and_others_with_link": "{name} y
{count, plural, one {# otro} other {# otros}} marcaron tu publicación como favorita",
"notification.follow": "{name} te empezó a seguir",
- "notification.follow.name_and_others": "{name} y {count, plural, one {# más} other {# más}} te siguieron",
+ "notification.follow.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} te siguieron",
"notification.follow_request": "{name} ha solicitado seguirte",
- "notification.follow_request.name_and_others": "{name} y {count, plural, one {# más} other {# más}} han solicitado seguirte",
+ "notification.follow_request.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} han solicitado seguirte",
"notification.label.mention": "Mención",
"notification.label.private_mention": "Mención privada",
"notification.label.private_reply": "Respuesta privada",
@@ -512,14 +519,14 @@
"notification.moderation_warning.action_delete_statuses": "Se han eliminado algunas de tus publicaciones.",
"notification.moderation_warning.action_disable": "Tu cuenta ha sido desactivada.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Se han marcado como sensibles algunas de tus publicaciones.",
- "notification.moderation_warning.action_none": "Tu cuenta ha recibido un aviso de moderación.",
+ "notification.moderation_warning.action_none": "Tu cuenta ha recibido una advertencia de moderación.",
"notification.moderation_warning.action_sensitive": "De ahora en adelante, todas tus publicaciones se marcarán como sensibles.",
"notification.moderation_warning.action_silence": "Tu cuenta ha sido limitada.",
"notification.moderation_warning.action_suspend": "Tu cuenta ha sido suspendida.",
"notification.own_poll": "Tu encuesta ha terminado",
- "notification.poll": "Una encuesta ha terminado",
- "notification.reblog": "{name} ha retooteado tu estado",
- "notification.reblog.name_and_others_with_link": "{name} y
{count, plural, one {# más} other {# más}} impulsaron tu publicación",
+ "notification.poll": "Una encuesta en la que has votado ha terminado",
+ "notification.reblog": "{name} ha impulsado tu publicación",
+ "notification.reblog.name_and_others_with_link": "{name} y
{count, plural, one {# otro} other {# otros}} impulsaron tu publicación",
"notification.relationships_severance_event": "Conexiones perdidas con {name}",
"notification.relationships_severance_event.account_suspension": "Un administrador de {from} ha suspendido {target}, lo que significa que ya no puedes recibir actualizaciones de sus cuentas o interactuar con ellas.",
"notification.relationships_severance_event.domain_block": "Un administrador de {from} ha bloqueado {target}, incluyendo {followersCount} de tus seguidores y {followingCount, plural, one {# cuenta} other {# cuentas}} que sigues.",
@@ -529,18 +536,18 @@
"notification.update": "{name} editó una publicación",
"notification_requests.accept": "Aceptar",
"notification_requests.accept_multiple": "{count, plural, one {Aceptar # solicitud…} other {Aceptar # solicitudes…}}",
- "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Aceptar solicitud} other {Aceptar solicitudes}}",
- "notification_requests.confirm_accept_multiple.message": "Vas a aceptar {count, plural, one {una solicitud} other {# solicitudes}}. ¿Quieres continuar?",
- "notification_requests.confirm_accept_multiple.title": "¿Aceptar las solicitudes?",
- "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Descartar solicitud} other {Descartar solicitudes}}",
- "notification_requests.confirm_dismiss_multiple.message": "Vas a descartar {count, plural, one {una solicitud} other {# solicitudes}}. No podrás volver a acceder fácilmente a {count, plural, one {ella} other {ellas}} de nuevo. ¿Seguro que quieres continuar?",
- "notification_requests.confirm_dismiss_multiple.title": "¿Descartar las solicitudes?",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Solicitud aceptada} other {Solicitudes aceptadas}}",
+ "notification_requests.confirm_accept_multiple.message": "Estás por aceptar {count, plural, one {una solicitud de notificación} other {# solicitudes de notificación}}. ¿Estás seguro de que quieres continuar?",
+ "notification_requests.confirm_accept_multiple.title": "¿Deseas aceptar las solicitudes de notificación?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Solicitud descartada} other {Solicitudes descartadas}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Estás por descartar {count, plural, one {una solicitud de notificación} other {# solicitudes de notificación}}. No serás capaz de acceder fácilmente a {count, plural, one {ella} other {ellas}} de nuevo. ¿Estás seguro de que quieres continuar?",
+ "notification_requests.confirm_dismiss_multiple.title": "¿Deseas descartar las solicitudes de notificación?",
"notification_requests.dismiss": "Descartar",
"notification_requests.dismiss_multiple": "{count, plural, one {Descartar # solicitud…} other {Descartar # solicitudes…}}",
"notification_requests.edit_selection": "Editar",
"notification_requests.exit_selection": "Hecho",
- "notification_requests.explainer_for_limited_account": "Las notificaciones de esta cuenta han sido filtradas porque la cuenta ha sido limitada por un moderador.",
- "notification_requests.explainer_for_limited_remote_account": "Las notificaciones de esta cuenta han sido filtradas porque la cuenta o su servidor ha sido limitada por un moderador.",
+ "notification_requests.explainer_for_limited_account": "Las notificaciones de esta cuenta han sido filtradas, ya que la cuenta ha sido limitada por un moderador.",
+ "notification_requests.explainer_for_limited_remote_account": "Las notificaciones de esta cuenta han sido filtradas, ya que la cuenta o su servidor ha sido limitada por un moderador.",
"notification_requests.maximize": "Maximizar",
"notification_requests.minimize_banner": "Minimizar banner de notificaciones filtradas",
"notification_requests.notifications_from": "Notificaciones de {name}",
@@ -548,12 +555,10 @@
"notification_requests.view": "Ver notificaciones",
"notifications.clear": "Limpiar notificaciones",
"notifications.clear_confirmation": "¿Seguro de querer borrar permanentemente todas tus notificaciones?",
- "notifications.clear_title": "¿Borrar notificaciones?",
+ "notifications.clear_title": "¿Limpiar notificaciones?",
"notifications.column_settings.admin.report": "Nuevas denuncias:",
"notifications.column_settings.admin.sign_up": "Registros nuevos:",
"notifications.column_settings.alert": "Notificaciones de escritorio",
- "notifications.column_settings.beta.category": "Características experimentales",
- "notifications.column_settings.beta.grouping": "Agrupar notificaciones",
"notifications.column_settings.favourite": "Favoritos:",
"notifications.column_settings.filter_bar.advanced": "Mostrar todas las categorías",
"notifications.column_settings.filter_bar.category": "Barra de filtrado rápido",
@@ -562,7 +567,7 @@
"notifications.column_settings.mention": "Menciones:",
"notifications.column_settings.poll": "Resultados de la votación:",
"notifications.column_settings.push": "Notificaciones push",
- "notifications.column_settings.reblog": "Retoots:",
+ "notifications.column_settings.reblog": "Impulsos:",
"notifications.column_settings.show": "Mostrar en columna",
"notifications.column_settings.sound": "Reproducir sonido",
"notifications.column_settings.status": "Nuevas publicaciones:",
@@ -570,7 +575,7 @@
"notifications.column_settings.unread_notifications.highlight": "Destacar notificaciones no leídas",
"notifications.column_settings.update": "Ediciones:",
"notifications.filter.all": "Todos",
- "notifications.filter.boosts": "Retoots",
+ "notifications.filter.boosts": "Impulsos",
"notifications.filter.favourites": "Favoritos",
"notifications.filter.follows": "Seguidores",
"notifications.filter.mentions": "Menciones",
@@ -616,7 +621,7 @@
"onboarding.profile.display_name_hint": "Tu nombre completo o tu apodo…",
"onboarding.profile.lead": "Siempre puedes completar esto más tarde en los ajustes, donde hay aún más opciones de personalización disponibles.",
"onboarding.profile.note": "Biografía",
- "onboarding.profile.note_hint": "Puedes @mencionar a otras personas o #hashtags…",
+ "onboarding.profile.note_hint": "Puedes @mencionar a otras personas o #etiquetas…",
"onboarding.profile.save_and_continue": "Guardar y continuar",
"onboarding.profile.title": "Configuración del perfil",
"onboarding.profile.upload_avatar": "Subir foto de perfil",
@@ -634,7 +639,7 @@
"onboarding.steps.publish_status.title": "Escribe tu primera publicación",
"onboarding.steps.setup_profile.body": "Si rellenas tu perfil tendrás más posibilidades de que otros interactúen contigo.",
"onboarding.steps.setup_profile.title": "Personaliza tu perfil",
- "onboarding.steps.share_profile.body": "¡Dile a tus amigos cómo encontrarte en Mastodon!",
+ "onboarding.steps.share_profile.body": "Dile a tus amigos cómo encontrarte en Mastodon",
"onboarding.steps.share_profile.title": "Comparte tu perfil",
"onboarding.tips.2fa": "
¿Sabías que? Puedes proteger tu cuenta configurando la autenticación de dos factores en la configuración de su cuenta. Funciona con cualquier aplicación TOTP de su elección, ¡no necesitas número de teléfono!",
"onboarding.tips.accounts_from_other_servers": "
¿Sabías que? Como Mastodon es descentralizado, algunos perfiles que encuentras están alojados en servidores distintos del tuyo. Y sin embargo, ¡puedes interactuar con ellos! ¡Su servidor corresponde a la segunda mitad de su nombre de usuario!",
@@ -660,7 +665,7 @@
"privacy.private.short": "Seguidores",
"privacy.public.long": "Cualquiera dentro y fuera de Mastodon",
"privacy.public.short": "Público",
- "privacy.unlisted.additional": "Esto se comporta exactamente igual que el público, excepto que el post no aparecerá en las cronologías en directo o en los hashtags, la exploración o busquedas en Mastodon, incluso si está optado por activar la cuenta de usuario.",
+ "privacy.unlisted.additional": "Esto se comporta exactamente igual que el público, excepto que el post no aparecerá en las cronologías en directo o en las etiquetas, la exploración o busquedas en Mastodon, incluso si está optado por activar la cuenta de usuario.",
"privacy.unlisted.long": "Menos fanfares algorítmicos",
"privacy.unlisted.short": "Público silencioso",
"privacy_policy.last_updated": "Actualizado por última vez {date}",
@@ -694,7 +699,7 @@
"report.category.title_account": "perfil",
"report.category.title_status": "publicación",
"report.close": "Realizado",
- "report.comment.title": "¿Hay algo más que usted cree que debamos saber?",
+ "report.comment.title": "¿Hay algo más que creas que deberíamos saber?",
"report.forward": "Reenviar a {target}",
"report.forward_hint": "Esta cuenta es de otro servidor. ¿Enviar una copia anonimizada del informe allí también?",
"report.mute": "Silenciar",
@@ -771,8 +776,9 @@
"status.admin_status": "Abrir este estado en la interfaz de moderación",
"status.block": "Bloquear a @{name}",
"status.bookmark": "Añadir marcador",
- "status.cancel_reblog_private": "Eliminar retoot",
- "status.cannot_reblog": "Este toot no puede retootearse",
+ "status.cancel_reblog_private": "Deshacer impulso",
+ "status.cannot_reblog": "Esta publicación no puede ser impulsada",
+ "status.continued_thread": "Hilo continuado",
"status.copy": "Copiar enlace al estado",
"status.delete": "Borrar",
"status.detailed_status": "Vista de conversación detallada",
@@ -781,7 +787,7 @@
"status.edit": "Editar",
"status.edited": "Última edición {date}",
"status.edited_x_times": "Editado {count, plural, one {{count} time} other {{count} veces}}",
- "status.embed": "Incrustado",
+ "status.embed": "Obtener código para incrustar",
"status.favourite": "Favorito",
"status.favourites": "{count, plural, one {favorito} other {favoritos}}",
"status.filter": "Filtrar esta publicación",
@@ -797,15 +803,16 @@
"status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir estado",
"status.pin": "Fijar",
- "status.pinned": "Toot fijado",
+ "status.pinned": "Publicación fijada",
"status.read_more": "Leer más",
- "status.reblog": "Retootear",
+ "status.reblog": "Impulsar",
"status.reblog_private": "Implusar a la audiencia original",
- "status.reblogged_by": "Retooteado por {name}",
+ "status.reblogged_by": "Impulsado por {name}",
"status.reblogs": "{count, plural, one {impulso} other {impulsos}}",
- "status.reblogs.empty": "Nadie retooteó este toot todavía. Cuando alguien lo haga, aparecerá aquí.",
+ "status.reblogs.empty": "Nadie impulsó esta publicación todavía. Cuando alguien lo haga, aparecerá aquí.",
"status.redraft": "Borrar y volver a borrador",
"status.remove_bookmark": "Eliminar marcador",
+ "status.replied_in_thread": "Respondido en el hilo",
"status.replied_to": "Respondió a {name}",
"status.reply": "Responder",
"status.replyAll": "Responder al hilo",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index c047a2aa89..5915c333c4 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -97,6 +97,8 @@
"block_modal.title": "¿Bloquear usuario?",
"block_modal.you_wont_see_mentions": "No verás mensajes que los mencionen.",
"boost_modal.combo": "Puedes hacer clic en {combo} para saltar este aviso la próxima vez",
+ "boost_modal.reblog": "¿Impulsar la publicación?",
+ "boost_modal.undo_reblog": "¿Dejar de impulsar la publicación?",
"bundle_column_error.copy_stacktrace": "Copiar informe de error",
"bundle_column_error.error.body": "La página solicitada no pudo ser renderizada. Podría deberse a un error en nuestro código o a un problema de compatibilidad con el navegador.",
"bundle_column_error.error.title": "¡Oh, no!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Dejar de seguir",
"confirmations.unfollow.message": "¿Seguro que quieres dejar de seguir a {name}?",
"confirmations.unfollow.title": "¿Dejar de seguir al usuario?",
+ "content_warning.hide": "Ocultar publicación",
+ "content_warning.show": "Mostrar de todos modos",
"conversation.delete": "Borrar conversación",
"conversation.mark_as_read": "Marcar como leído",
"conversation.open": "Ver conversación",
@@ -263,7 +267,7 @@
"empty_column.favourites": "Todavía nadie marcó esta publicación como favorita. Cuando alguien lo haga, se mostrarán aquí.",
"empty_column.follow_requests": "No tienes ninguna petición de seguidor. Cuando recibas una, se mostrará aquí.",
"empty_column.followed_tags": "No has seguido ninguna etiqueta todavía. Cuando lo hagas, se mostrarán aquí.",
- "empty_column.hashtag": "No hay nada en este hashtag aún.",
+ "empty_column.hashtag": "No hay nada en esta etiqueta todavía.",
"empty_column.home": "¡Tu línea temporal está vacía! Sigue a más personas para rellenarla.",
"empty_column.list": "Aún no hay nada en esta lista. Cuando los miembros de esta lista publiquen nuevos estados, estos aparecerán aquí.",
"empty_column.lists": "No tienes ninguna lista. Cuando crees una, se mostrará aquí.",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Usar una categoría existente o crear una nueva",
"filter_modal.select_filter.title": "Filtrar esta publicación",
"filter_modal.title.status": "Filtrar una publicación",
+ "filter_warning.matches_filter": "Coincide con el filtro “{title}”",
"filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nadie} one {una persona} other {# personas}} que puede que conozcas",
"filtered_notifications_banner.title": "Notificaciones filtradas",
"firehose.all": "Todas",
@@ -337,7 +342,7 @@
"hashtag.column_header.tag_mode.any": "o {additional}",
"hashtag.column_header.tag_mode.none": "sin {additional}",
"hashtag.column_settings.select.no_options_message": "No se encontraron sugerencias",
- "hashtag.column_settings.select.placeholder": "Introduzca hashtags…",
+ "hashtag.column_settings.select.placeholder": "Introduce etiquetas…",
"hashtag.column_settings.tag_mode.all": "Todos estos",
"hashtag.column_settings.tag_mode.any": "Cualquiera de estos",
"hashtag.column_settings.tag_mode.none": "Ninguno de estos",
@@ -371,7 +376,7 @@
"ignore_notifications_modal.ignore": "Ignorar notificaciones",
"ignore_notifications_modal.limited_accounts_title": "¿Ignorar notificaciones de cuentas moderadas?",
"ignore_notifications_modal.new_accounts_title": "¿Ignorar notificaciones de cuentas nuevas?",
- "ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de personas que no te sigue?",
+ "ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de personas que no te siguen?",
"ignore_notifications_modal.not_following_title": "¿Ignorar notificaciones de personas a las que no sigues?",
"ignore_notifications_modal.private_mentions_title": "¿Ignorar notificaciones de menciones privadas no solicitadas?",
"interaction_modal.description.favourite": "Con una cuenta en Mastodon, puedes marcar como favorita esta publicación para que el autor sepa que te gusta, y guardala para más adelante.",
@@ -427,10 +432,10 @@
"keyboard_shortcuts.unfocus": "para retirar el foco de la caja de redacción/búsqueda",
"keyboard_shortcuts.up": "para ir hacia arriba en la lista",
"lightbox.close": "Cerrar",
- "lightbox.compress": "Comprimir cuadro de visualización de imagen",
- "lightbox.expand": "Expandir cuadro de visualización de imagen",
"lightbox.next": "Siguiente",
"lightbox.previous": "Anterior",
+ "lightbox.zoom_in": "Ampliar al tamaño real",
+ "lightbox.zoom_out": "Ampliar para ajustar",
"limited_account_hint.action": "Mostrar perfil de todos modos",
"limited_account_hint.title": "Este perfil ha sido ocultado por los moderadores de {domain}.",
"link_preview.author": "Por {name}",
@@ -452,7 +457,7 @@
"lists.subheading": "Tus listas",
"load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}",
"loading_indicator.label": "Cargando…",
- "media_gallery.toggle_visible": "Cambiar visibilidad",
+ "media_gallery.hide": "Ocultar",
"moved_to_account_banner.text": "Tu cuenta {disabledAccount} está actualmente deshabilitada porque te has mudado a {movedToAccount}.",
"mute_modal.hide_from_notifications": "Ocultar de las notificaciones",
"mute_modal.hide_options": "Ocultar opciones",
@@ -464,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "No verás mensajes que los mencionen.",
"mute_modal.you_wont_see_posts": "Todavía pueden ver tus publicaciones, pero tú no verás las suyas.",
"navigation_bar.about": "Acerca de",
+ "navigation_bar.administration": "Administración",
"navigation_bar.advanced_interface": "Abrir en la interfaz web avanzada",
"navigation_bar.blocks": "Usuarios bloqueados",
"navigation_bar.bookmarks": "Marcadores",
@@ -480,6 +486,7 @@
"navigation_bar.follows_and_followers": "Siguiendo y seguidores",
"navigation_bar.lists": "Listas",
"navigation_bar.logout": "Cerrar sesión",
+ "navigation_bar.moderation": "Moderación",
"navigation_bar.mutes": "Usuarios silenciados",
"navigation_bar.opened_in_classic_interface": "Publicaciones, cuentas y otras páginas específicas se abren por defecto en la interfaz web clásica.",
"navigation_bar.personal": "Personal",
@@ -552,8 +559,6 @@
"notifications.column_settings.admin.report": "Nuevos informes:",
"notifications.column_settings.admin.sign_up": "Nuevos registros:",
"notifications.column_settings.alert": "Notificaciones de escritorio",
- "notifications.column_settings.beta.category": "Características experimentales",
- "notifications.column_settings.beta.grouping": "Agrupar notificaciones",
"notifications.column_settings.favourite": "Favoritos:",
"notifications.column_settings.filter_bar.advanced": "Mostrar todas las categorías",
"notifications.column_settings.filter_bar.category": "Barra de filtrado rápido",
@@ -632,7 +637,7 @@
"onboarding.steps.follow_people.title": "Personaliza tu línea de inicio",
"onboarding.steps.publish_status.body": "Di hola al mundo con texto, fotos, vídeos o encuestas {emoji}",
"onboarding.steps.publish_status.title": "Escribe tu primera publicación",
- "onboarding.steps.setup_profile.body": "Aumenta tus interacciones tcompletando tu perfil.",
+ "onboarding.steps.setup_profile.body": "Aumenta tus interacciones con un perfil completo.",
"onboarding.steps.setup_profile.title": "Personaliza tu perfil",
"onboarding.steps.share_profile.body": "¡Dile a tus amigos cómo encontrarte en Mastodon!",
"onboarding.steps.share_profile.title": "Comparte tu perfil de Mastodon",
@@ -773,6 +778,7 @@
"status.bookmark": "Añadir marcador",
"status.cancel_reblog_private": "Deshacer impulso",
"status.cannot_reblog": "Esta publicación no se puede impulsar",
+ "status.continued_thread": "Continuó el hilo",
"status.copy": "Copiar enlace a la publicación",
"status.delete": "Borrar",
"status.detailed_status": "Vista de conversación detallada",
@@ -781,7 +787,7 @@
"status.edit": "Editar",
"status.edited": "Última edición {date}",
"status.edited_x_times": "Editado {count, plural, one {{count} vez} other {{count} veces}}",
- "status.embed": "Incrustado",
+ "status.embed": "Obtener código para incrustar",
"status.favourite": "Favorito",
"status.favourites": "{count, plural, one {favorito} other {favoritos}}",
"status.filter": "Filtrar esta publicación",
@@ -806,6 +812,7 @@
"status.reblogs.empty": "Nadie ha impulsado esta publicación todavía. Cuando alguien lo haga, aparecerá aquí.",
"status.redraft": "Borrar y volver a borrador",
"status.remove_bookmark": "Eliminar marcador",
+ "status.replied_in_thread": "Respondió en el hilo",
"status.replied_to": "Respondió a {name}",
"status.reply": "Responder",
"status.replyAll": "Responder al hilo",
diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json
index 80c65804fa..287ffb9852 100644
--- a/app/javascript/mastodon/locales/et.json
+++ b/app/javascript/mastodon/locales/et.json
@@ -11,6 +11,7 @@
"about.not_available": "See info ei ole sellel serveril saadavaks tehtud.",
"about.powered_by": "Hajutatud sotsiaalmeedia, mille taga on {mastodon}",
"about.rules": "Serveri reeglid",
+ "account.account_note_header": "Isiklik märge",
"account.add_or_remove_from_list": "Lisa või Eemalda nimekirjadest",
"account.badges.bot": "Robot",
"account.badges.group": "Grupp",
@@ -33,7 +34,9 @@
"account.follow_back": "Jälgi vastu",
"account.followers": "Jälgijad",
"account.followers.empty": "Keegi ei jälgi veel seda kasutajat.",
+ "account.followers_counter": "{count, plural, one {{counter} jälgija} other {{counter} jälgijat}}",
"account.following": "Jälgib",
+ "account.following_counter": "{count, plural, one {{counter} jälgib} other {{counter} jälgib}}",
"account.follows.empty": "See kasutaja ei jälgi veel kedagi.",
"account.go_to_profile": "Mine profiilile",
"account.hide_reblogs": "Peida @{name} jagamised",
@@ -59,6 +62,7 @@
"account.requested_follow": "{name} on taodelnud sinu jälgimist",
"account.share": "Jaga @{name} profiili",
"account.show_reblogs": "Näita @{name} jagamisi",
+ "account.statuses_counter": "{count, plural, one {{counter} postitus} other {{counter} postitust}}",
"account.unblock": "Eemalda blokeering @{name}",
"account.unblock_domain": "Tee {domain} nähtavaks",
"account.unblock_short": "Eemalda blokeering",
@@ -93,6 +97,8 @@
"block_modal.title": "Blokeeri kasutaja?",
"block_modal.you_wont_see_mentions": "Sa ei näe postitusi, mis mainivad teda.",
"boost_modal.combo": "Vajutades {combo}, saab selle edaspidi vahele jätta",
+ "boost_modal.reblog": "Jagada postitust?",
+ "boost_modal.undo_reblog": "Tühista postituse jagamine?",
"bundle_column_error.copy_stacktrace": "Kopeeri veateade",
"bundle_column_error.error.body": "Soovitud lehte ei õnnestunud esitada. See võib olla meie koodiviga või probleem brauseri ühilduvusega.",
"bundle_column_error.error.title": "Oh, ei!",
@@ -166,21 +172,30 @@
"confirmations.block.confirm": "Blokeeri",
"confirmations.delete.confirm": "Kustuta",
"confirmations.delete.message": "Oled kindel, et soovid postituse kustutada?",
+ "confirmations.delete.title": "Kustutada postitus?",
"confirmations.delete_list.confirm": "Kustuta",
"confirmations.delete_list.message": "Oled kindel, et soovid selle loetelu pöördumatult kustutada?",
+ "confirmations.delete_list.title": "Kustutada loetelu?",
"confirmations.discard_edit_media.confirm": "Hülga",
"confirmations.discard_edit_media.message": "Sul on salvestamata muudatusi meediakirjelduses või eelvaates, kas hülgad need?",
"confirmations.edit.confirm": "Muuda",
"confirmations.edit.message": "Muutes praegu kirjutatakse hetkel loodav sõnum üle. Kas oled kindel, et soovid jätkata?",
+ "confirmations.edit.title": "Kirjutada postitus üle?",
"confirmations.logout.confirm": "Välju",
"confirmations.logout.message": "Kas oled kindel, et soovid välja logida?",
+ "confirmations.logout.title": "Logida välja?",
"confirmations.mute.confirm": "Vaigista",
"confirmations.redraft.confirm": "Kustuta & taasalusta",
"confirmations.redraft.message": "Kindel, et soovid postituse kustutada ja võtta uue aluseks? Lemmikuks märkimised ja jagamised lähevad kaotsi ning vastused jäävad ilma algse postituseta.",
+ "confirmations.redraft.title": "Kustudada ja luua postituse mustand?",
"confirmations.reply.confirm": "Vasta",
"confirmations.reply.message": "Praegu vastamine kirjutab hetkel koostatava sõnumi üle. Oled kindel, et soovid jätkata?",
+ "confirmations.reply.title": "Kirjutada postitus üle?",
"confirmations.unfollow.confirm": "Ära jälgi",
"confirmations.unfollow.message": "Oled kindel, et ei soovi rohkem jälgida kasutajat {name}?",
+ "confirmations.unfollow.title": "Ei jälgi enam kasutajat?",
+ "content_warning.hide": "Peida postitus",
+ "content_warning.show": "Näita ikkagi",
"conversation.delete": "Kustuta vestlus",
"conversation.mark_as_read": "Märgi loetuks",
"conversation.open": "Vaata vestlust",
@@ -288,6 +303,8 @@
"filter_modal.select_filter.subtitle": "Kasuta olemasolevat kategooriat või loo uus",
"filter_modal.select_filter.title": "Filtreeri seda postitust",
"filter_modal.title.status": "Postituse filtreerimine",
+ "filter_warning.matches_filter": "Sobib filtriga “{title}”",
+ "filtered_notifications_banner.pending_requests": "{count, plural, =0 {Mitte üheltki inimeselt} one {Ühelt inimeselt} other {# inimeselt}}, keda võid teada",
"filtered_notifications_banner.title": "Filtreeritud teavitused",
"firehose.all": "Kõik",
"firehose.local": "See server",
@@ -336,6 +353,14 @@
"hashtag.follow": "Jälgi silti",
"hashtag.unfollow": "Lõpeta sildi jälgimine",
"hashtags.and_other": "…ja {count, plural, one {}other {# veel}}",
+ "hints.profiles.followers_may_be_missing": "Selle profiili jälgijaid võib olla puudu.",
+ "hints.profiles.follows_may_be_missing": "Selle profiili poolt jälgitavaid võib olla puudu.",
+ "hints.profiles.posts_may_be_missing": "Mõned selle profiili postitused võivad olla puudu.",
+ "hints.profiles.see_more_followers": "Vaata rohkem jälgijaid kohas {domain}",
+ "hints.profiles.see_more_follows": "Vaata rohkem jälgitavaid kohas {domain}",
+ "hints.profiles.see_more_posts": "Vaata rohkem postitusi kohas {domain}",
+ "hints.threads.replies_may_be_missing": "Vastuseid teistest serveritest võib olla puudu.",
+ "hints.threads.see_more": "Vaata rohkem vastuseid kohas {domain}",
"home.column_settings.show_reblogs": "Näita jagamisi",
"home.column_settings.show_replies": "Näita vastuseid",
"home.hide_announcements": "Peida teadaanded",
@@ -343,6 +368,17 @@
"home.pending_critical_update.link": "Vaata uuendusi",
"home.pending_critical_update.title": "Saadaval kriitiline turvauuendus!",
"home.show_announcements": "Kuva teadaandeid",
+ "ignore_notifications_modal.disclaimer": "Mastodon ei saa teavitada kasutajaid, et ignoreerisid nende teavitusi. Teavituste ignoreerimine ei peata sõnumite endi saatmist.",
+ "ignore_notifications_modal.filter_instead": "Selle asemel filtreeri",
+ "ignore_notifications_modal.filter_to_act_users": "Saad endiselt kasutajaid vastu võtta, tagasi lükata või neist teatada",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "Filtreerimine aitab vältida võimalikke segaminiajamisi",
+ "ignore_notifications_modal.filter_to_review_separately": "Saad filtreeritud teateid eraldi vaadata",
+ "ignore_notifications_modal.ignore": "Ignoreeri teavitusi",
+ "ignore_notifications_modal.limited_accounts_title": "Ignoreeri modereeritud kontode teavitusi?",
+ "ignore_notifications_modal.new_accounts_title": "Ignoreeri uute kontode teavitusi?",
+ "ignore_notifications_modal.not_followers_title": "Ignoreeri inimeste teavitusi, kes sind ei jälgi?",
+ "ignore_notifications_modal.not_following_title": "Ignoreeri inimeste teavitusi, keda sa ei jälgi?",
+ "ignore_notifications_modal.private_mentions_title": "Ignoreeri soovimatute eraviisiliste mainimiste teateid?",
"interaction_modal.description.favourite": "Mastodoni kontoga saad postituse lemmikuks märkida, et autor teaks, et sa hindad seda, ja jätta see hiljemaks alles.",
"interaction_modal.description.follow": "Mastodoni kontoga saad jälgida kasutajat {name}, et tema postitusi oma koduvoos näha.",
"interaction_modal.description.reblog": "Mastodoni kontoga saad seda postitust levitada, jagades seda oma jälgijatele.",
@@ -396,8 +432,6 @@
"keyboard_shortcuts.unfocus": "Fookus tekstialalt/otsingult ära",
"keyboard_shortcuts.up": "Liigu loetelus üles",
"lightbox.close": "Sulge",
- "lightbox.compress": "Suru kokku pildi vaatamise kast",
- "lightbox.expand": "Laienda pildi vaatamise kast",
"lightbox.next": "Järgmine",
"lightbox.previous": "Eelmine",
"limited_account_hint.action": "Näita profilli sellegipoolest",
@@ -421,7 +455,7 @@
"lists.subheading": "Sinu nimekirjad",
"load_pending": "{count, plural, one {# uus kirje} other {# uut kirjet}}",
"loading_indicator.label": "Laadimine…",
- "media_gallery.toggle_visible": "{number, plural, one {Varja pilt} other {Varja pildid}}",
+ "media_gallery.hide": "Peida",
"moved_to_account_banner.text": "Kontot {disabledAccount} ei ole praegu võimalik kasutada, sest kolisid kontole {movedToAccount}.",
"mute_modal.hide_from_notifications": "Peida teavituste hulgast",
"mute_modal.hide_options": "Peida valikud",
@@ -433,6 +467,7 @@
"mute_modal.you_wont_see_mentions": "Sa ei näe postitusi, mis teda mainivad.",
"mute_modal.you_wont_see_posts": "Ta näeb jätkuvalt sinu postitusi, kuid sa ei näe tema omi.",
"navigation_bar.about": "Teave",
+ "navigation_bar.administration": "Administreerimine",
"navigation_bar.advanced_interface": "Ava kohandatud veebiliides",
"navigation_bar.blocks": "Blokeeritud kasutajad",
"navigation_bar.bookmarks": "Järjehoidjad",
@@ -449,6 +484,7 @@
"navigation_bar.follows_and_followers": "Jälgitavad ja jälgijad",
"navigation_bar.lists": "Nimekirjad",
"navigation_bar.logout": "Logi välja",
+ "navigation_bar.moderation": "Modereerimine",
"navigation_bar.mutes": "Vaigistatud kasutajad",
"navigation_bar.opened_in_classic_interface": "Postitused, kontod ja teised spetsiaalsed lehed avatakse vaikimisi klassikalises veebiliideses.",
"navigation_bar.personal": "Isiklik",
@@ -459,10 +495,23 @@
"navigation_bar.security": "Turvalisus",
"not_signed_in_indicator.not_signed_in": "Pead sisse logima, et saada ligipääsu sellele ressursile.",
"notification.admin.report": "{name} saatis teavituse {target} kohta",
+ "notification.admin.report_account": "{name} raporteeris {count, plural, one {ühest postitusest} other {# postitusest}} kohast {target} kategooriast {category}",
+ "notification.admin.report_account_other": "{name} raporteeris {count, plural, one {ühest postitusest} other {# postitusest}} kohast {target}",
+ "notification.admin.report_statuses": "{name} raporteeris {target} kategooriast {category}",
+ "notification.admin.report_statuses_other": "{name} raporteeris kohast {target}",
"notification.admin.sign_up": "{name} registreerus",
+ "notification.admin.sign_up.name_and_others": "{name} ja {count, plural, one {# veel} other {# teist}} liitus",
"notification.favourite": "{name} märkis su postituse lemmikuks",
+ "notification.favourite.name_and_others_with_link": "{name} ja
{count, plural, one {# veel} other {# teist}} märkis su postituse lemmikuks",
"notification.follow": "{name} alustas su jälgimist",
+ "notification.follow.name_and_others": "{name} ja {count, plural, one {# veel} other {# teist}} hakkas sind jälgima",
"notification.follow_request": "{name} soovib sind jälgida",
+ "notification.follow_request.name_and_others": "{name} ja {count, plural, one {# veel} other {# teist}} taotles sinu jälgimist",
+ "notification.label.mention": "Mainimine",
+ "notification.label.private_mention": "Privaatne mainimine",
+ "notification.label.private_reply": "Privaatne vastus",
+ "notification.label.reply": "Vastus",
+ "notification.mention": "Mainimine",
"notification.moderation-warning.learn_more": "Vaata lisa",
"notification.moderation_warning": "Said modereerimise hoiatuse",
"notification.moderation_warning.action_delete_statuses": "Mõni su postitus on eemaldatud.",
@@ -473,7 +522,9 @@
"notification.moderation_warning.action_silence": "Su kontole pandi piirang.",
"notification.moderation_warning.action_suspend": "Su konto on peatatud.",
"notification.own_poll": "Su küsitlus on lõppenud",
+ "notification.poll": "Hääletus, millel osalesid, on lõppenud",
"notification.reblog": "{name} jagas edasi postitust",
+ "notification.reblog.name_and_others_with_link": "{name} ja
{count, plural, one {# veel} other {# teist}} jagas su postitust",
"notification.relationships_severance_event": "Kadunud ühendus kasutajaga {name}",
"notification.relationships_severance_event.account_suspension": "{from} admin on kustutanud {target}, mis tähendab, et sa ei saa enam neilt uuendusi või suhelda nendega.",
"notification.relationships_severance_event.domain_block": "{from} admin on blokeerinud {target}, sealhulgas {followersCount} sinu jälgijat ja {followingCount, plural, one {# konto} other {# kontot}}, mida jälgid.",
@@ -482,11 +533,27 @@
"notification.status": "{name} just postitas",
"notification.update": "{name} muutis postitust",
"notification_requests.accept": "Nõus",
+ "notification_requests.accept_multiple": "{count, plural, one {Nõustu # taotlusega…} other {Nõustu # taotlusega…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Nõustu taotlusega} other {Nõustu taotlustega}}",
+ "notification_requests.confirm_accept_multiple.message": "Oled nõustumas {count, plural, one {ühe teavituse taotlusega} other {# teavituse taotlusega}}. Oled kindel, et soovid jätkata?",
+ "notification_requests.confirm_accept_multiple.title": "Nõustuda teavituste taotlustega?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Loobu taotlusest} other {Loobu taotlustest}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Oled loobumas {count, plural, one {ühest teavituse taotlusest} other {# teavituse taotlusest}}. {count, plural, one {Sellele} other {Neile}} pole hiljem lihtne ligi pääseda. Oled kindel, et soovid jätkata?",
+ "notification_requests.confirm_dismiss_multiple.title": "Hüljata teavituse taotlused?",
"notification_requests.dismiss": "Hülga",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Loobuda # taotlusest…} other {Loobuda # taotlusest…}}",
+ "notification_requests.edit_selection": "Muuda",
+ "notification_requests.exit_selection": "Valmis",
+ "notification_requests.explainer_for_limited_account": "Sellelt kontolt tulevad teavitused on filtreeritud, sest moderaator on seda kontot piiranud.",
+ "notification_requests.explainer_for_limited_remote_account": "Sellelt kontolt tulevad teavitused on filtreeritud, sest moderaator on seda kontot või serverit piiranud.",
+ "notification_requests.maximize": "Maksimeeri",
+ "notification_requests.minimize_banner": "Minimeeri filtreeritud teavituste bänner",
"notification_requests.notifications_from": "Teavitus kasutajalt {name}",
"notification_requests.title": "Filtreeritud teavitused",
+ "notification_requests.view": "Vaata teavitusi",
"notifications.clear": "Puhasta teated",
"notifications.clear_confirmation": "Oled kindel, et soovid püsivalt kõik oma teated eemaldada?",
+ "notifications.clear_title": "Tühjenda teavitus?",
"notifications.column_settings.admin.report": "Uued teavitused:",
"notifications.column_settings.admin.sign_up": "Uued kasutajad:",
"notifications.column_settings.alert": "Töölauateated",
@@ -518,6 +585,14 @@
"notifications.permission_denied": "Töölauamärguanded pole saadaval, kuna eelnevalt keelduti lehitsejale teavituste luba andmast",
"notifications.permission_denied_alert": "Töölaua märguandeid ei saa lubada, kuna brauseri luba on varem keeldutud",
"notifications.permission_required": "Töölaua märguanded ei ole saadaval, kuna vajalik luba pole antud.",
+ "notifications.policy.accept": "Nõustun",
+ "notifications.policy.accept_hint": "Näita teavitustes",
+ "notifications.policy.drop": "Ignoreeri",
+ "notifications.policy.drop_hint": "Saada tühjusse, mitte kunagi seda enam näha",
+ "notifications.policy.filter": "Filter",
+ "notifications.policy.filter_hint": "Saadetud filtreeritud teavituste sisendkasti",
+ "notifications.policy.filter_limited_accounts_hint": "Piiratud serveri moderaatorite poolt",
+ "notifications.policy.filter_limited_accounts_title": "Modereeritud kontod",
"notifications.policy.filter_new_accounts.hint": "Loodud viimase {days, plural, one {ühe päeva} other {# päeva}} jooksul",
"notifications.policy.filter_new_accounts_title": "Uued kontod",
"notifications.policy.filter_not_followers_hint": "Kaasates kasutajad, kes on sind jälginud vähem kui {days, plural, one {ühe päeva} other {# päeva}}",
@@ -526,6 +601,7 @@
"notifications.policy.filter_not_following_title": "Inimesed, keda sa ei jälgi",
"notifications.policy.filter_private_mentions_hint": "Filtreeritud, kui see pole vastus sinupoolt mainimisele või kui jälgid saatjat",
"notifications.policy.filter_private_mentions_title": "Soovimatud privaatsed mainimised",
+ "notifications.policy.title": "Halda teavitusi kohast…",
"notifications_permission_banner.enable": "Luba töölaua märguanded",
"notifications_permission_banner.how_to_control": "Et saada teateid, ajal mil Mastodon pole avatud, luba töölauamärguanded. Saad täpselt määrata, mis tüüpi tegevused tekitavad märguandeid, kasutates peale teadaannete sisse lülitamist üleval olevat nuppu {icon}.",
"notifications_permission_banner.title": "Ära jää millestki ilma",
@@ -652,9 +728,13 @@
"report.unfollow_explanation": "Jälgid seda kontot. Et mitte näha tema postitusi oma koduvoos, lõpeta ta jälgimine.",
"report_notification.attached_statuses": "{count, plural, one {{count} postitus} other {{count} postitust}} listatud",
"report_notification.categories.legal": "Õiguslik",
+ "report_notification.categories.legal_sentence": "ebaseaduslik sisu",
"report_notification.categories.other": "Muu",
+ "report_notification.categories.other_sentence": "muu",
"report_notification.categories.spam": "Rämpspost",
+ "report_notification.categories.spam_sentence": "rämps",
"report_notification.categories.violation": "Reeglite rikkumine",
+ "report_notification.categories.violation_sentence": "reeglite rikkumine",
"report_notification.open": "Ava teavitus",
"search.no_recent_searches": "Pole viimatisi otsinguid",
"search.placeholder": "Otsi",
@@ -696,6 +776,7 @@
"status.bookmark": "Järjehoidja",
"status.cancel_reblog_private": "Lõpeta jagamine",
"status.cannot_reblog": "Seda postitust ei saa jagada",
+ "status.continued_thread": "Jätkatud lõim",
"status.copy": "Kopeeri postituse link",
"status.delete": "Kustuta",
"status.detailed_status": "Detailne vestluskuva",
@@ -704,7 +785,7 @@
"status.edit": "Muuda",
"status.edited": "Viimati muudetud {date}",
"status.edited_x_times": "Muudetud {count, plural, one{{count} kord} other {{count} korda}}",
- "status.embed": "Manustamine",
+ "status.embed": "Hangi manustamiskood",
"status.favourite": "Lemmik",
"status.favourites": "{count, plural, one {lemmik} other {lemmikud}}",
"status.filter": "Filtreeri seda postitust",
@@ -729,6 +810,7 @@
"status.reblogs.empty": "Keegi pole seda postitust veel jaganud. Kui keegi seda teeb, näeb seda siin.",
"status.redraft": "Kustuta & alga uuesti",
"status.remove_bookmark": "Eemalda järjehoidja",
+ "status.replied_in_thread": "Vastatud lõimes",
"status.replied_to": "Vastas kasutajale {name}",
"status.reply": "Vasta",
"status.replyAll": "Vasta lõimele",
diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json
index a8e2e668c3..b3137bc21a 100644
--- a/app/javascript/mastodon/locales/eu.json
+++ b/app/javascript/mastodon/locales/eu.json
@@ -97,6 +97,8 @@
"block_modal.title": "Erabiltzailea blokeatu nahi duzu?",
"block_modal.you_wont_see_mentions": "Ez duzu ikusiko bera aipatzen duen argitalpenik.",
"boost_modal.combo": "{combo} sakatu dezakezu hurrengoan hau saltatzeko",
+ "boost_modal.reblog": "Bultzatu bidalketa?",
+ "boost_modal.undo_reblog": "Bidalketari bultzada kendu?",
"bundle_column_error.copy_stacktrace": "Kopiatu errore-txostena",
"bundle_column_error.error.body": "Eskatutako orria ezin izan da bistaratu. Kodeko errore bategatik izan daiteke edo nabigatzailearen bateragarritasun arazo bategatik.",
"bundle_column_error.error.title": "O ez!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Utzi jarraitzeari",
"confirmations.unfollow.message": "Ziur {name} jarraitzeari utzi nahi diozula?",
"confirmations.unfollow.title": "Erabiltzailea jarraitzeari utzi?",
+ "content_warning.hide": "Tuta ezkutatu",
+ "content_warning.show": "Erakutsi hala ere",
"conversation.delete": "Ezabatu elkarrizketa",
"conversation.mark_as_read": "Markatu irakurrita bezala",
"conversation.open": "Ikusi elkarrizketa",
@@ -299,6 +303,8 @@
"filter_modal.select_filter.subtitle": "Hautatu lehendik dagoen kategoria bat edo sortu berria",
"filter_modal.select_filter.title": "Iragazi bidalketa hau",
"filter_modal.title.status": "Iragazi bidalketa bat",
+ "filter_warning.matches_filter": "“{title}” iragazkiarekin bat dator",
+ "filtered_notifications_banner.pending_requests": "Ezagutu dezakezun {count, plural, =0 {inoren} one {pertsona baten} other {# pertsonen}}",
"filtered_notifications_banner.title": "Iragazitako jakinarazpenak",
"firehose.all": "Guztiak",
"firehose.local": "Zerbitzari hau",
@@ -347,6 +353,14 @@
"hashtag.follow": "Jarraitu traolari",
"hashtag.unfollow": "Utzi traola jarraitzeari",
"hashtags.and_other": "…eta {count, plural, one {}other {# gehiago}}",
+ "hints.profiles.followers_may_be_missing": "Baliteke profil honen jarraitzaile guztiak ez agertzea.",
+ "hints.profiles.follows_may_be_missing": "Baliteke profil honek jarraitzen dituen profil guztiak ez erakustea.",
+ "hints.profiles.posts_may_be_missing": "Baliteke profil honen tut guztiak ez erakustea.",
+ "hints.profiles.see_more_followers": "Ikusi jarraitzaile gehiago {domain}-(e)n",
+ "hints.profiles.see_more_follows": "Ikusi jarraitzaile gehiago {domain}-(e)n",
+ "hints.profiles.see_more_posts": "Ikusi bidalketa gehiago {domain}-(e)n",
+ "hints.threads.replies_may_be_missing": "Baliteke beste zerbitzari batzuen erantzun batzuk ez erakustea.",
+ "hints.threads.see_more": "Ikusi erantzun gehiago {domain}-(e)n",
"home.column_settings.show_reblogs": "Erakutsi bultzadak",
"home.column_settings.show_replies": "Erakutsi erantzunak",
"home.hide_announcements": "Ezkutatu iragarpenak",
@@ -354,12 +368,17 @@
"home.pending_critical_update.link": "Ikusi eguneraketak",
"home.pending_critical_update.title": "Segurtasun eguneraketa kritikoa eskuragarri!",
"home.show_announcements": "Erakutsi iragarpenak",
+ "ignore_notifications_modal.disclaimer": "Mastodonek ezin die jakinarazi erabiltzaileei beraien jakinarazpenei ezikusiarena egingo diezula. Jakinarazpenei ezikusiarena egiteak ez du eragotziko mezuak bidaltzen jarraitzea.",
"ignore_notifications_modal.filter_instead": "Iragazi ez ikusiarena egin beharrean",
+ "ignore_notifications_modal.filter_to_act_users": "Oraindik ere erabiltzaileak onartu, baztertu edo salatu ahal izango dituzu",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "Iragazteak nahaste potentzialak saihesten laguntzen du",
+ "ignore_notifications_modal.filter_to_review_separately": "Banaka berrikus ditzakezu iragazitako jakinarazpenak",
"ignore_notifications_modal.ignore": "Ezikusi jakinarazpenak",
"ignore_notifications_modal.limited_accounts_title": "Moderatutako kontuen jakinarazpenei ez ikusiarena egin?",
"ignore_notifications_modal.new_accounts_title": "Kontu berrien jakinarazpenei ez ikusiarena egin?",
"ignore_notifications_modal.not_followers_title": "Jarraitzen ez zaituzten pertsonen jakinarazpenei ez ikusiarena egin?",
"ignore_notifications_modal.not_following_title": "Jarraitzen ez dituzun pertsonen jakinarazpenei ez ikusiarena egin?",
+ "ignore_notifications_modal.private_mentions_title": "Eskatu gabeko aipamen pribatuen jakinarazpenei ez ikusiarena egin?",
"interaction_modal.description.favourite": "Mastodon kontu batekin bidalketa hau gogoko egin dezakezu, egileari eskertzeko eta gerorako gordetzeko.",
"interaction_modal.description.follow": "Mastodon kontu batekin {name} jarraitu dezakezu bere bidalketak zure hasierako denbora lerroan jasotzeko.",
"interaction_modal.description.reblog": "Mastodon kontu batekin bidalketa hau bultzatu dezakezu, zure jarraitzaileekin partekatzeko.",
@@ -413,13 +432,13 @@
"keyboard_shortcuts.unfocus": "testua konposatzeko area / bilaketatik fokua kentzea",
"keyboard_shortcuts.up": "zerrendan gora mugitzea",
"lightbox.close": "Itxi",
- "lightbox.compress": "Konprimatu irudia ikusteko kaxa",
- "lightbox.expand": "Zabaldu irudia ikusteko kaxa",
"lightbox.next": "Hurrengoa",
"lightbox.previous": "Aurrekoa",
"limited_account_hint.action": "Erakutsi profila hala ere",
"limited_account_hint.title": "Profil hau ezkutatu egin dute {domain} zerbitzariko moderatzaileek.",
"link_preview.author": "Egilea: {name}",
+ "link_preview.more_from_author": "{name} erabiltzaileaz gehiago jakin",
+ "link_preview.shares": "{count, plural, one {{counter} bidalketa} other {{counter} bidalketa}}",
"lists.account.add": "Gehitu zerrendara",
"lists.account.remove": "Kendu zerrendatik",
"lists.delete": "Ezabatu zerrenda",
@@ -436,7 +455,7 @@
"lists.subheading": "Zure zerrendak",
"load_pending": "{count, plural, one {elementu berri #} other {# elementu berri}}",
"loading_indicator.label": "Kargatzen…",
- "media_gallery.toggle_visible": "Txandakatu ikusgaitasuna",
+ "media_gallery.hide": "Ezkutatu",
"moved_to_account_banner.text": "Zure {disabledAccount} kontua desgaituta dago une honetan, {movedToAccount} kontura aldatu zinelako.",
"mute_modal.hide_from_notifications": "Ezkutatu jakinarazpenetatik",
"mute_modal.hide_options": "Ezkutatu aukerak",
@@ -448,6 +467,7 @@
"mute_modal.you_wont_see_mentions": "Ez duzu ikusiko bera aipatzen duen argitalpenik.",
"mute_modal.you_wont_see_posts": "Zure argitalpenak ikus ditzake, baina ez dituzu bereak ikusiko.",
"navigation_bar.about": "Honi buruz",
+ "navigation_bar.administration": "Administrazioa",
"navigation_bar.advanced_interface": "Ireki web interfaze aurreratuan",
"navigation_bar.blocks": "Blokeatutako erabiltzaileak",
"navigation_bar.bookmarks": "Laster-markak",
@@ -464,6 +484,7 @@
"navigation_bar.follows_and_followers": "Jarraitutakoak eta jarraitzaileak",
"navigation_bar.lists": "Zerrendak",
"navigation_bar.logout": "Amaitu saioa",
+ "navigation_bar.moderation": "Moderazioa",
"navigation_bar.mutes": "Mutututako erabiltzaileak",
"navigation_bar.opened_in_classic_interface": "Argitalpenak, kontuak eta beste orri jakin batzuk lehenespenez irekitzen dira web-interfaze klasikoan.",
"navigation_bar.personal": "Pertsonala",
@@ -474,10 +495,18 @@
"navigation_bar.security": "Segurtasuna",
"not_signed_in_indicator.not_signed_in": "Baliabide honetara sarbidea izateko saioa hasi behar duzu.",
"notification.admin.report": "{name} erabiltzaileak {target} salatu du",
+ "notification.admin.report_account": "{name}-(e)k {target}-ren {count, plural, one {bidalketa bat} other {# bidalketa}} salatu zituen {category} delakoagatik",
+ "notification.admin.report_account_other": "{name}-(e)k {target}-ren {count, plural, one {bidalketa bat salatu zuen} other {# bidalketa salatu zituen}}",
+ "notification.admin.report_statuses": "{name}-(e)k {target} salatu zuen {category} delakoagatik",
+ "notification.admin.report_statuses_other": "{name} erabiltzaileak {target} salatu du",
"notification.admin.sign_up": "{name} erabiltzailea erregistratu da",
+ "notification.admin.sign_up.name_and_others": "{name} eta {count, plural, one {erabiltzaile # gehiago} other {# erabiltzaile gehiago}} erregistratu dira",
"notification.favourite": "{name}(e)k zure bidalketa gogoko du",
+ "notification.favourite.name_and_others_with_link": "{name} eta
{count, plural, one {erabiltzaile # gehiagok} other {# erabiltzaile gehiagok}} zure bidalketa gogoko dute",
"notification.follow": "{name}(e)k jarraitzen dizu",
+ "notification.follow.name_and_others": "{name} eta {count, plural, one {erabiltzaile # gehiagok} other {# erabiltzaile gehiagok}} jarraitu dizute",
"notification.follow_request": "{name}(e)k zu jarraitzeko eskaera egin du",
+ "notification.follow_request.name_and_others": "{name} eta {count, plural, one {erabiltzaile # gehiagok} other {# erabiltzaile gehiagok}} zu jarraitzeko eskaera egin dute",
"notification.label.mention": "Aipamena",
"notification.label.private_mention": "Aipamen pribatua",
"notification.label.private_reply": "Erantzun pribatua",
@@ -495,14 +524,26 @@
"notification.own_poll": "Zure inkesta amaitu da",
"notification.poll": "Zuk erantzun duzun inkesta bat bukatu da",
"notification.reblog": "{name}(e)k bultzada eman dio zure bidalketari",
+ "notification.reblog.name_and_others_with_link": "{name} eta
{count, plural, one {erabiltzaile # gehiagok} other {# erabiltzaile gehiagok}} bultzada eman diote zure bidalketari",
"notification.relationships_severance_event": "{name} erabiltzailearekin galdutako konexioak",
"notification.relationships_severance_event.account_suspension": "{from} zerbitzariko administratzaile batek {target} bertan behera utzi du, hau da, ezin izango dituzu jaso hango eguneratzerik edo hangoekin elkarreragin.",
"notification.relationships_severance_event.learn_more": "Informazio gehiago",
"notification.status": "{name} erabiltzaileak bidalketa egin berri du",
"notification.update": "{name} erabiltzaileak bidalketa bat editatu du",
"notification_requests.accept": "Onartu",
+ "notification_requests.accept_multiple": "{count, plural, one {Onartu eskaera…} other {Onartu # eskaerak…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Onartu eskaera} other {Onartu eskaerak}}",
+ "notification_requests.confirm_accept_multiple.title": "Onartu jakinarazpen-eskaerak?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Baztertu eskaera} other {Baztertu eskaerak}}",
+ "notification_requests.confirm_dismiss_multiple.title": "Baztertu jakinarazpen-eskaerak?",
"notification_requests.dismiss": "Baztertu",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Baztertu eskaera…} other {Baztertu # eskaerak…}}",
+ "notification_requests.edit_selection": "Editatu",
+ "notification_requests.exit_selection": "Egina",
+ "notification_requests.explainer_for_limited_account": "Kontu honen jakinarazpenak iragazi egin dira, kontua moderatzaile batek mugatu duelako.",
+ "notification_requests.explainer_for_limited_remote_account": "Kontu horren jakinarazpenak iragazi egin dira kontua edo bere zerbitzaria moderatzaile batek mugatu duelako.",
"notification_requests.maximize": "Maximizatu",
+ "notification_requests.minimize_banner": "Minimizatu iragazitako jakinarazpenen bannerra",
"notification_requests.notifications_from": "{name} erabiltzailearen jakinarazpenak",
"notification_requests.title": "Iragazitako jakinarazpenak",
"notification_requests.view": "Ikusi jakinarazpenak",
@@ -512,8 +553,6 @@
"notifications.column_settings.admin.report": "Txosten berriak:",
"notifications.column_settings.admin.sign_up": "Izen-emate berriak:",
"notifications.column_settings.alert": "Mahaigaineko jakinarazpenak",
- "notifications.column_settings.beta.category": "Ezaugarri esperimentalak",
- "notifications.column_settings.beta.grouping": "Multzokatu jakinarazpenak",
"notifications.column_settings.favourite": "Gogokoak:",
"notifications.column_settings.filter_bar.advanced": "Bistaratu kategoria guztiak",
"notifications.column_settings.filter_bar.category": "Iragazki-barra bizkorra",
@@ -719,8 +758,10 @@
"server_banner.about_active_users": "Azken 30 egunetan zerbitzari hau erabili duen jendea (hilabeteko erabiltzaile aktiboak)",
"server_banner.active_users": "erabiltzaile aktibo",
"server_banner.administered_by": "Administratzailea(k):",
+ "server_banner.is_one_of_many": "{domain} fedibertsoan parte hartzeko erabil dezakezun Mastodonen zerbitzari independenteetako bat da.",
"server_banner.server_stats": "Zerbitzariaren estatistikak:",
"sign_in_banner.create_account": "Sortu kontua",
+ "sign_in_banner.follow_anyone": "Jarraitu edonori fedibertsoan eta ikusi dena ordena kronologikoan. Algoritmorik gabe, iragarki edo titulu gezurtirik gabe.",
"sign_in_banner.mastodon_is": "Mastodon gertatzen ari denari buruz egunean egoteko modurik onena da.",
"sign_in_banner.sign_in": "Hasi saioa",
"sign_in_banner.sso_redirect": "Hasi saioa edo izena eman",
@@ -731,6 +772,7 @@
"status.bookmark": "Laster-marka",
"status.cancel_reblog_private": "Kendu bultzada",
"status.cannot_reblog": "Bidalketa honi ezin zaio bultzada eman",
+ "status.continued_thread": "Harian jarraitu zuen",
"status.copy": "Kopiatu bidalketaren esteka",
"status.delete": "Ezabatu",
"status.detailed_status": "Elkarrizketaren ikuspegi xehetsua",
@@ -739,7 +781,7 @@
"status.edit": "Editatu",
"status.edited": "Azken edizioa: {date}",
"status.edited_x_times": "{count, plural, one {behin} other {{count} aldiz}} editatua",
- "status.embed": "Txertatu",
+ "status.embed": "Lortu txertatzeko kodea",
"status.favourite": "Gogokoa",
"status.favourites": "{count, plural, one {gogoko} other {gogoko}}",
"status.filter": "Iragazi bidalketa hau",
@@ -764,6 +806,7 @@
"status.reblogs.empty": "Inork ez dio bultzada eman bidalketa honi oraindik. Inork egiten badu, hemen agertuko da.",
"status.redraft": "Ezabatu eta berridatzi",
"status.remove_bookmark": "Kendu laster-marka",
+ "status.replied_in_thread": "Harian erantzun zuen",
"status.replied_to": "{name} erabiltzaileari erantzuna",
"status.reply": "Erantzun",
"status.replyAll": "Erantzun harian",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 169c325ad7..fbc65ec207 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -11,6 +11,7 @@
"about.not_available": "این اطّلاعات روی این کارساز موجود نشده.",
"about.powered_by": "رسانهٔ اجتماعی نامتمرکز قدرت گرفته از {mastodon}",
"about.rules": "قوانین کارساز",
+ "account.account_note_header": "یادداشت شخصی",
"account.add_or_remove_from_list": "افزودن یا برداشتن از سیاههها",
"account.badges.bot": "خودکار",
"account.badges.group": "گروه",
@@ -33,7 +34,9 @@
"account.follow_back": "دنبال کردن متقابل",
"account.followers": "پیگیرندگان",
"account.followers.empty": "هنوز کسی پیگیر این کاربر نیست.",
+ "account.followers_counter": "{count, plural, one {{counter} پیگیرنده} other {{counter} پیگیرنده}}",
"account.following": "پی میگیرید",
+ "account.following_counter": "{count, plural, one {{counter} پیگرفته} other {{counter} پیگرفته}}",
"account.follows.empty": "این کاربر هنوز پیگیر کسی نیست.",
"account.go_to_profile": "رفتن به نمایه",
"account.hide_reblogs": "نهفتن تقویتهای @{name}",
@@ -59,6 +62,7 @@
"account.requested_follow": "{name} درخواست پیگیریتان را داد",
"account.share": "همرسانی نمایهٔ @{name}",
"account.show_reblogs": "نمایش تقویتهای @{name}",
+ "account.statuses_counter": "{count, plural, one {{counter} فرسته} other {{counter} فرسته}}",
"account.unblock": "رفع مسدودیت @{name}",
"account.unblock_domain": "رفع مسدودیت دامنهٔ {domain}",
"account.unblock_short": "رفع مسدودیت",
@@ -86,9 +90,14 @@
"audio.hide": "نهفتن صدا",
"block_modal.show_less": "نمایش کمتر",
"block_modal.show_more": "نمایش بیشتر",
+ "block_modal.they_cant_mention": "نمیتوانند نامتان را برده یا پیتان بگیرند.",
+ "block_modal.they_cant_see_posts": "نمیتوانند فرستههایتان را دیده و فرستههایشان را نمیبینید.",
+ "block_modal.they_will_know": "میتوانند ببینند که مسدود شدهاند.",
"block_modal.title": "انسداد کاربر؟",
"block_modal.you_wont_see_mentions": "فرستههایی که از اون نام برده را نخواهید دید.",
"boost_modal.combo": "دکمهٔ {combo} را بزنید تا دیگر این را نبینید",
+ "boost_modal.reblog": "تقویت فرسته؟",
+ "boost_modal.undo_reblog": "ناتقویت فرسته؟",
"bundle_column_error.copy_stacktrace": "رونوشت از گزارش خطا",
"bundle_column_error.error.body": "صفحهٔ درخواستی نتوانست پرداخت شود. ممکن است به خاطر اشکالی در کدمان یا مشکل سازگاری مرورگر باشد.",
"bundle_column_error.error.title": "وای، نه!",
@@ -184,6 +193,8 @@
"confirmations.unfollow.confirm": "پینگرفتن",
"confirmations.unfollow.message": "مطمئنید که میخواهید به پیگیری از {name} پایان دهید؟",
"confirmations.unfollow.title": "ناپیگیری کاربر؟",
+ "content_warning.hide": "نهفتن فرسته",
+ "content_warning.show": "نمایش به هر روی",
"conversation.delete": "حذف گفتگو",
"conversation.mark_as_read": "علامتگذاری به عنوان خوانده شده",
"conversation.open": "دیدن گفتگو",
@@ -204,9 +215,24 @@
"dismissable_banner.explore_tags": "هماکنون این برچسبها بین افراد این کارساز و دیگر کارسازهای شبکهٔ نامتمرکز داغ شدهاند.",
"dismissable_banner.public_timeline": "اینها جدیدترین فرستههای عمومی از افرادی روی وب اجتماعیند که اعضای {domain} پی میگیرندشان.",
"domain_block_modal.block": "انسداد کارساز",
+ "domain_block_modal.block_account_instead": "انسداد @{name} به جایش",
+ "domain_block_modal.they_can_interact_with_old_posts": "افزارد روی این کراساز میتوانند با فرستههای قدیمیتان تعامل داشته باشند.",
+ "domain_block_modal.they_cant_follow": "هیچکسی از این کارساز نمیتواند پیتان بگیرد.",
+ "domain_block_modal.they_wont_know": "نخواهند دانست که مسدود شدهاند.",
"domain_block_modal.title": "انسداد دامنه؟",
+ "domain_block_modal.you_will_lose_followers": "همهٔ پیگیرندگانتان از این کارساز برداشته خواهند شد.",
+ "domain_block_modal.you_wont_see_posts": "فرستهها یا آگاهیها از کاربران روی این کارساز را نخواهید دید.",
"domain_pill.server": "کارساز",
+ "domain_pill.their_handle": "شناسهاش:",
+ "domain_pill.their_server": "خانهٔ رقمیش. جایی که همهٔ فرستههایش میزیند.",
+ "domain_pill.their_username": "شناسهٔ یکتایش در کارسازش. ممکن است کاربرانی با نام کاربری مشابه روی کارسازهای مختلف باشند.",
"domain_pill.username": "نام کاربری",
+ "domain_pill.whats_in_a_handle": "شناسه چیست؟",
+ "domain_pill.who_they_are": "از آنجا که شناسهها کیستی و کجایی افراد را میگویند، میتوانید با افرادی در سراسر وب اجتماعی
بنسازههای قدرت گرفته از اکتیویتی پاپ تعامل داشته باشید.",
+ "domain_pill.who_you_are": "از آنجا که شناسهها کیستی و کجاییتان را میگویند، افراد میتوانند از سراسر وب اجتماعی
بنسازههای قدرت گرفته از اکتیویتی پاپ با شما تعامل داشته باشند.",
+ "domain_pill.your_handle": "شناسهتان:",
+ "domain_pill.your_server": "خانهٔ رقمیتان. جایی که همهٔ فرستههایتان میزیند. دوستش ندارید؟ در هر زمان کارسازتان را جابهجا کرده و پیگیرندگانتان را نیز بیاورید.",
+ "domain_pill.your_username": "شناسهٔ یکتایتان روی این کارساز. ممکن است کاربرانی با نام کاربری مشابه روی کارسازهای دیگر باشند.",
"embed.instructions": "جاسازی این فرسته روی پایگاهتان با رونوشت کردن کد زیر.",
"embed.preview": "این گونه دیده خواهد شد:",
"emoji_button.activity": "فعالیت",
@@ -273,6 +299,9 @@
"filter_modal.select_filter.subtitle": "استفاده از یک دستهً موجود یا ایجاد دستهای جدید",
"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.title": "آگاهیهای پالوده",
"firehose.all": "همه",
"firehose.local": "این کارساز",
"firehose.remote": "دیگر کارسازها",
@@ -281,6 +310,8 @@
"follow_requests.unlocked_explanation": "با این که حسابتان قفل نیست، کارکنان {domain} فکر کردند که ممکن است بخواهید درخواستها از این حسابها را به صورت دستی بازبینی کنید.",
"follow_suggestions.curated_suggestion": "گزینش سردبیر",
"follow_suggestions.dismiss": "دیگر نشان داده نشود",
+ "follow_suggestions.featured_longer": "دستچین شده به دست گروه {domain}",
+ "follow_suggestions.friends_of_friends_longer": "محبوب بین کسانی که پیگرفتهاید",
"follow_suggestions.hints.featured": "این نمایه به دست گروه {domain} دستچین شده.",
"follow_suggestions.hints.friends_of_friends": "این نمایه بین کسانی که پی میگیرید محبوب است.",
"follow_suggestions.hints.most_followed": "این نمایه روی {domain} بسیار پیگرفته شده.",
@@ -288,6 +319,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "این نمایه شبیه نمایههاییست که اخیراً پیگرفتهاید.",
"follow_suggestions.personalized_suggestion": "پیشنهاد شخصی",
"follow_suggestions.popular_suggestion": "پیشنهاد محبوب",
+ "follow_suggestions.popular_suggestion_longer": "محبوب روی {domain}",
+ "follow_suggestions.similar_to_recently_followed_longer": "شبیه نمایههایی که اخیراً پی گرفتهاید",
"follow_suggestions.view_all": "دیدن همه",
"follow_suggestions.who_to_follow": "افرادی برای پیگیری",
"followed_tags": "برچسبهای پیگرفته",
@@ -316,6 +349,14 @@
"hashtag.follow": "پیگرفتن برچسب",
"hashtag.unfollow": "پینگرفتن برچسب",
"hashtags.and_other": "…و {count, plural, other {# بیشتر}}",
+ "hints.profiles.followers_may_be_missing": "شاید پیگیرندگان این نمایه نباشند.",
+ "hints.profiles.follows_may_be_missing": "شاید پیگرفتههای این نمایه نباشند.",
+ "hints.profiles.posts_may_be_missing": "شاید فرستههایی از این نمایه نباشند.",
+ "hints.profiles.see_more_followers": "دیدن پیگیرندگان بیشتر روی {domain}",
+ "hints.profiles.see_more_follows": "دیدن پیگرفتههای بیشتر روی {domain}",
+ "hints.profiles.see_more_posts": "دیدن فرستههای بیشتر روی {domain}",
+ "hints.threads.replies_may_be_missing": "شاید پاسخها از دیگر کارسازها نباشند.",
+ "hints.threads.see_more": "دیدن پاسخهای بیشتر روی {domain}",
"home.column_settings.show_reblogs": "نمایش تقویتها",
"home.column_settings.show_replies": "نمایش پاسخها",
"home.hide_announcements": "نهفتن اعلامیهها",
@@ -323,6 +364,11 @@
"home.pending_critical_update.link": "دیدن بهروز رسانیها",
"home.pending_critical_update.title": "بهروز رسانی امنیتی بحرانی موجود است!",
"home.show_announcements": "نمایش اعلامیهها",
+ "ignore_notifications_modal.ignore": "چشمپوشی از آگاهیها",
+ "ignore_notifications_modal.limited_accounts_title": "چشمپوشی از آگاهیهای حسابهای نظارت شده؟",
+ "ignore_notifications_modal.new_accounts_title": "چشمپوشی از آگاهیهای حسابهای جدید؟",
+ "ignore_notifications_modal.not_followers_title": "چشمپوشی از آگاهیهای افرادی که پیتان نمیگیرند؟",
+ "ignore_notifications_modal.not_following_title": "چشمپوشی از آگاهیهای افرادی که پیشان نمیگیرید؟",
"interaction_modal.description.favourite": "با حسابی روی ماستودون میتوانید این فرسته را برگزیده تا نگارنده بداند قدردانش هستید و برای آینده ذخیرهاش میکنید.",
"interaction_modal.description.follow": "با حسابی روی ماستودون میتوانید {name} را برای دریافت فرستههایش در خوراک خانگیتان دنبال کنید.",
"interaction_modal.description.reblog": "با حسابی روی ماستودون میتوانید این فرسته را با پیگیران خودتان همرسانی کنید.",
@@ -376,13 +422,13 @@
"keyboard_shortcuts.unfocus": "برداشتن تمرکز از ناحیهٔ نوشتن یا جستوجو",
"keyboard_shortcuts.up": "بالا بردن در سیاهه",
"lightbox.close": "بستن",
- "lightbox.compress": "فشردهسازی جعبهٔ نمایش تصویر",
- "lightbox.expand": "گسترش جعبهٔ نمایش تصویر",
"lightbox.next": "بعدی",
"lightbox.previous": "قبلی",
"limited_account_hint.action": "به هر روی نمایه نشان داده شود",
"limited_account_hint.title": "این نمایه از سوی ناظمهای {domain} پنهان شده.",
"link_preview.author": "از {name}",
+ "link_preview.more_from_author": "بیشتر از {name}",
+ "link_preview.shares": "{count, plural, one {{counter} فرسته} other {{counter} فرسته}}",
"lists.account.add": "افزودن به سیاهه",
"lists.account.remove": "برداشتن از سیاهه",
"lists.delete": "حذف سیاهه",
@@ -399,11 +445,18 @@
"lists.subheading": "سیاهههایتان",
"load_pending": "{count, plural, one {# مورد جدید} other {# مورد جدید}}",
"loading_indicator.label": "در حال بارگذاری…",
- "media_gallery.toggle_visible": "{number, plural, one {نهفتن تصویر} other {نهفتن تصاویر}}",
+ "media_gallery.hide": "نهفتن",
"moved_to_account_banner.text": "حسابتان {disabledAccount} اکنون از کار افتاده؛ چرا که به {movedToAccount} منتقل شدید.",
+ "mute_modal.hide_from_notifications": "نهفتن از آگاهیها",
+ "mute_modal.hide_options": "گزینههای نهفتن",
+ "mute_modal.indefinite": "تا وقتی ناخموشش کنم",
"mute_modal.show_options": "نمایش گزینهها",
+ "mute_modal.they_wont_know": "نخواهند دانست که خموش شدهاند.",
"mute_modal.title": "خموشی کاربر؟",
+ "mute_modal.you_wont_see_mentions": "فرستههایی که به او اشاره کردهاند را نخواهید دید.",
+ "mute_modal.you_wont_see_posts": "هنوز میتوانند فرستههایتان را ببینند، ولی فرستههایشان را نمیبینید.",
"navigation_bar.about": "درباره",
+ "navigation_bar.administration": "مدیریت",
"navigation_bar.advanced_interface": "بازکردن در رابط کاربری وب پیشرفته",
"navigation_bar.blocks": "کاربران مسدود شده",
"navigation_bar.bookmarks": "نشانکها",
@@ -420,6 +473,7 @@
"navigation_bar.follows_and_followers": "پیگرفتگان و پیگیرندگان",
"navigation_bar.lists": "سیاههها",
"navigation_bar.logout": "خروج",
+ "navigation_bar.moderation": "نظارت",
"navigation_bar.mutes": "کاربران خموشانده",
"navigation_bar.opened_in_classic_interface": "فرستهها، حسابها و دیگر صفحههای خاص به طور پیشگزیده در میانای وب کلاسیک گشوده میشوند.",
"navigation_bar.personal": "شخصی",
@@ -430,26 +484,57 @@
"navigation_bar.security": "امنیت",
"not_signed_in_indicator.not_signed_in": "برای دسترسی به این منبع باید وارد شوید.",
"notification.admin.report": "{name}، {target} را گزارش داد",
+ "notification.admin.report_statuses_other": "{name}، {target} را گزارش داد",
"notification.admin.sign_up": "{name} ثبت نام کرد",
+ "notification.admin.sign_up.name_and_others": "{name} و {count, plural, one {# نفر دیگر} other {# نفر دیگر}} ثبتنام کردند",
"notification.favourite": "{name} فرستهتان را برگزید",
+ "notification.favourite.name_and_others_with_link": "{name} و
{count, plural, one {# نفر دیگر} other {# نفر دیگر}} فرستهتان را برگزیدند",
"notification.follow": "{name} پیگیرتان شد",
+ "notification.follow.name_and_others": "{name} و {count, plural, one {# نفر دیگر} other {# نفر دیگر}} پیتان گرفتند",
"notification.follow_request": "{name} درخواست پیگیریتان را داد",
+ "notification.follow_request.name_and_others": "{name} و {count, plural, one {# نفر دیگر} other {# نفر دیگر}} درخواست پیگیریتان را دادند",
+ "notification.label.mention": "اشاره",
+ "notification.label.private_mention": "اشارهٔ خصوصی",
+ "notification.label.private_reply": "پاسخ خصوصی",
+ "notification.label.reply": "پاسخ",
+ "notification.mention": "اشاره",
"notification.moderation-warning.learn_more": "بیشتر بدانید",
+ "notification.moderation_warning": "هشداری مدیریتی گرفتهاید",
+ "notification.moderation_warning.action_delete_statuses": "برخی از فرستههایتان برداشته شدند.",
+ "notification.moderation_warning.action_disable": "حسابتان از کار افتاد.",
+ "notification.moderation_warning.action_mark_statuses_as_sensitive": "برخی از فرستههایتان به عنوان حسّاس علامت خوردند.",
+ "notification.moderation_warning.action_none": "حسابتان هشداری مدیریتی گرفت.",
+ "notification.moderation_warning.action_sensitive": "فرستههایتان از اکنون به عنوان حسّاس علامت خواهند خورد.",
+ "notification.moderation_warning.action_silence": "حسابتان محدود شده.",
+ "notification.moderation_warning.action_suspend": "حسابتان معلّق شده.",
"notification.own_poll": "نظرسنجیتان پایان یافت",
+ "notification.poll": "نظرسنجیای که در آن رأی دادید به پایان رسید",
"notification.reblog": "{name} فرستهتان را تقویت کرد",
+ "notification.reblog.name_and_others_with_link": "{name} و
{count, plural, one {# نفر دیگر} other {# نفر دیگر}} فرستهتان را تقویت کردند",
+ "notification.relationships_severance_event": "قطع ارتباط با {name}",
"notification.relationships_severance_event.learn_more": "بیشتر بدانید",
"notification.status": "{name} چیزی فرستاد",
"notification.update": "{name} فرستهای را ویرایش کرد",
"notification_requests.accept": "پذیرش",
+ "notification_requests.confirm_accept_multiple.title": "پذیرش درخواستهای آگاهی؟",
+ "notification_requests.confirm_dismiss_multiple.title": "رد کردن درخواستهای آگاهی؟",
"notification_requests.dismiss": "دورانداختن",
+ "notification_requests.edit_selection": "ویرایش",
+ "notification_requests.exit_selection": "انجام شد",
"notification_requests.maximize": "بیشنه",
+ "notification_requests.minimize_banner": "کمینه کردن بیرق آگاهیهای پالوده",
+ "notification_requests.notifications_from": "آگاهیها از {name}",
+ "notification_requests.title": "آگاهیهای پالوده",
+ "notification_requests.view": "دیدن آگاهیها",
"notifications.clear": "پاکسازی آگاهیها",
"notifications.clear_confirmation": "مطمئنید میخواهید همهٔ آگاهیهایتان را برای همیشه پاک کنید؟",
+ "notifications.clear_title": "پاکسازی آگاهیها؟",
"notifications.column_settings.admin.report": "گزارشهای جدید:",
"notifications.column_settings.admin.sign_up": "ثبت نامهای جدید:",
"notifications.column_settings.alert": "آگاهیهای میزکار",
- "notifications.column_settings.beta.category": "ویژگیهای آزمایشی",
"notifications.column_settings.favourite": "برگزیدهها:",
+ "notifications.column_settings.filter_bar.advanced": "نمایش همۀ دستهها",
+ "notifications.column_settings.filter_bar.category": "نوار پالایش سریع",
"notifications.column_settings.follow": "پیگیرندگان جدید:",
"notifications.column_settings.follow_request": "درخواستهای جدید پیگیری:",
"notifications.column_settings.mention": "اشارهها:",
@@ -475,8 +560,19 @@
"notifications.permission_denied": "آگاهیهای میزکار به دلیل رد کردن درخواست اجازهٔ پیشین مرورگر، در دسترس نیستند",
"notifications.permission_denied_alert": "از آنجا که پیش از این اجازهٔ مرورگر رد شده است، آگاهیهای میزکار نمیتوانند به کار بیفتند",
"notifications.permission_required": "آگاهیهای میزکار در دسترس نیستند زیرا اجازههای لازم، اعطا نشده.",
+ "notifications.policy.accept": "پذیرش",
+ "notifications.policy.accept_hint": "نمایش در آگاهیها",
+ "notifications.policy.drop": "چشمپوشی",
+ "notifications.policy.drop_hint": "فرستادن به هیچ. دیگر هرگز دیده نخواهند شد",
+ "notifications.policy.filter": "پالایش",
+ "notifications.policy.filter_hint": "فرستادن به صندوق آگاهیهای پالوده",
+ "notifications.policy.filter_limited_accounts_hint": "محدود شده به دست ناظمهای کارساز",
+ "notifications.policy.filter_limited_accounts_title": "حسابهای مدیریت شده",
+ "notifications.policy.filter_new_accounts_title": "حسابهای جدید",
"notifications.policy.filter_not_followers_title": "کسانی که شما را دنبال میکنند",
"notifications.policy.filter_not_following_hint": "",
+ "notifications.policy.filter_not_following_title": "کسانی که پی نمیگیرید",
+ "notifications.policy.title": "مدیریت آگاهیها از…",
"notifications_permission_banner.enable": "به کار انداختن آگاهیهای میزکار",
"notifications_permission_banner.how_to_control": "برای دریافت آگاهیها هنگام باز نبودن ماستودون، آگاهیهای میزکار را به کار بیندازید. پس از به کار افتادنشان میتوانید گونههای دقیق برهمکنشهایی که آگاهیهای میزکار تولید میکنند را از {icon} بالا واپایید.",
"notifications_permission_banner.title": "هرگز چیزی را از دست ندهید",
@@ -609,6 +705,7 @@
"report_notification.categories.spam": "هرزنامه",
"report_notification.categories.spam_sentence": "هرزنامه",
"report_notification.categories.violation": "تخطّی از قانون",
+ "report_notification.categories.violation_sentence": "تخطّی از قانون",
"report_notification.open": "گشودن گزارش",
"search.no_recent_searches": "جستوجوی اخیری نیست",
"search.placeholder": "جستوجو",
@@ -647,15 +744,17 @@
"status.bookmark": "نشانک",
"status.cancel_reblog_private": "ناتقویت",
"status.cannot_reblog": "این فرسته قابل تقویت نیست",
+ "status.continued_thread": "رشتهٔ دنباله دار",
"status.copy": "رونوشت از پیوند فرسته",
"status.delete": "حذف",
"status.detailed_status": "نمایش کامل گفتگو",
"status.direct": "اشارهٔ خصوصی به @{name}",
"status.direct_indicator": "اشارهٔ خصوصی",
"status.edit": "ویرایش",
+ "status.edited": "آخرین ویرایش {date}",
"status.edited_x_times": "{count, plural, one {{count} مرتبه} other {{count} مرتبه}} ویرایش شد",
- "status.embed": "جاسازی",
"status.favourite": "برگزیده",
+ "status.favourites": "{count, plural, one {برگزیده} other {برگزیده}}",
"status.filter": "پالایش این فرسته",
"status.history.created": "توسط {name} در {date} ایجاد شد",
"status.history.edited": "توسط {name} در {date} ویرایش شد",
@@ -674,9 +773,11 @@
"status.reblog": "تقویت",
"status.reblog_private": "تقویت برای مخاطبان نخستین",
"status.reblogged_by": "{name} تقویت کرد",
+ "status.reblogs": "{count, plural, one {تقویت} other {تقویت}}",
"status.reblogs.empty": "هنوز هیچ کسی این فرسته را تقویت نکرده است. وقتی کسی چنین کاری کند، اینجا نمایش داده خواهد شد.",
"status.redraft": "حذف و بازنویسی",
"status.remove_bookmark": "برداشتن نشانک",
+ "status.replied_in_thread": "در رشته پاسخ داده",
"status.replied_to": "به {name} پاسخ داد",
"status.reply": "پاسخ",
"status.replyAll": "پاسخ به رشته",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index 10f9d79614..d4adef40f2 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -97,6 +97,8 @@
"block_modal.title": "Estetäänkö käyttäjä?",
"block_modal.you_wont_see_mentions": "Et näe enää julkaisuja, joissa hänet mainitaan.",
"boost_modal.combo": "Ensi kerralla voit ohittaa tämän painamalla {combo}",
+ "boost_modal.reblog": "Tehostetaanko julkaisua?",
+ "boost_modal.undo_reblog": "Perutaanko julkaisun tehostus?",
"bundle_column_error.copy_stacktrace": "Kopioi virheraportti",
"bundle_column_error.error.body": "Pyydettyä sivua ei voitu hahmontaa. Se voi johtua virheestä koodissamme tai selaimen yhteensopivuudessa.",
"bundle_column_error.error.title": "Voi ei!",
@@ -302,7 +304,7 @@
"filter_modal.select_filter.title": "Suodata tämä julkaisu",
"filter_modal.title.status": "Suodata julkaisu",
"filter_warning.matches_filter": "Vastaa suodatinta ”{title}”",
- "filtered_notifications_banner.pending_requests": "{count, plural, =0 {Ei keneltäkään, jonka} one {1 käyttäjältä, jonka} other {# käyttäjältä, jotka}} saatat tuntea",
+ "filtered_notifications_banner.pending_requests": "{count, plural, =0 {Ei keneltäkään, jonka} one {Yhdeltä käyttäjältä, jonka} other {# käyttäjältä, jotka}} saatat tuntea",
"filtered_notifications_banner.title": "Suodatetut ilmoitukset",
"firehose.all": "Kaikki",
"firehose.local": "Tämä palvelin",
@@ -368,7 +370,7 @@
"home.show_announcements": "Näytä tiedotteet",
"ignore_notifications_modal.disclaimer": "Mastodon ei voi ilmoittaa käyttäjille, että olet sivuuttanut heidän ilmoituksensa. Ilmoitusten sivuuttaminen ei lopeta itse viestien lähetystä.",
"ignore_notifications_modal.filter_instead": "Suodata sen sijaan",
- "ignore_notifications_modal.filter_to_act_users": "Voit silti hyväksyä, hylätä tai raportoida käyttäjiä",
+ "ignore_notifications_modal.filter_to_act_users": "Voit kuitenkin yhä hyväksyä, hylätä tai raportoida käyttäjiä",
"ignore_notifications_modal.filter_to_avoid_confusion": "Suodatus auttaa välttämään mahdollisia sekaannuksia",
"ignore_notifications_modal.filter_to_review_separately": "Voit käydä suodatettuja ilmoituksia läpi erikseen",
"ignore_notifications_modal.ignore": "Sivuuta ilmoitukset",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Poistu kirjoitus- tai hakukentästä",
"keyboard_shortcuts.up": "Siirry luettelossa taaksepäin",
"lightbox.close": "Sulje",
- "lightbox.compress": "Tiivis kuvankatselunäkymä",
- "lightbox.expand": "Laajennettu kuvankatselunäkymä",
"lightbox.next": "Seuraava",
"lightbox.previous": "Edellinen",
+ "lightbox.zoom_in": "Zoomaa todelliseen kokoon",
+ "lightbox.zoom_out": "Zoomaa mahtumaan",
"limited_account_hint.action": "Näytä profiili joka tapauksessa",
"limited_account_hint.title": "Palvelimen {domain} moderaattorit ovat piilottaneet tämän profiilin.",
"link_preview.author": "Tehnyt {name}",
@@ -455,7 +457,7 @@
"lists.subheading": "Omat listasi",
"load_pending": "{count, plural, one {# uusi kohde} other {# uutta kohdetta}}",
"loading_indicator.label": "Ladataan…",
- "media_gallery.toggle_visible": "{number, plural, one {Piilota kuva} other {Piilota kuvat}}",
+ "media_gallery.hide": "Piilota",
"moved_to_account_banner.text": "Tilisi {disabledAccount} on tällä hetkellä poissa käytöstä, koska teit siirron tiliin {movedToAccount}.",
"mute_modal.hide_from_notifications": "Piilota ilmoituksista",
"mute_modal.hide_options": "Piilota vaihtoehdot",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Et näe enää julkaisuja, joissa hänet mainitaan.",
"mute_modal.you_wont_see_posts": "Hän voi yhä nähdä julkaisusi, mutta sinä et näe hänen.",
"navigation_bar.about": "Tietoja",
+ "navigation_bar.administration": "Ylläpito",
"navigation_bar.advanced_interface": "Avaa edistyneessä selainkäyttöliittymässä",
"navigation_bar.blocks": "Estetyt käyttäjät",
"navigation_bar.bookmarks": "Kirjanmerkit",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Seuratut ja seuraajat",
"navigation_bar.lists": "Listat",
"navigation_bar.logout": "Kirjaudu ulos",
+ "navigation_bar.moderation": "Moderointi",
"navigation_bar.mutes": "Mykistetyt käyttäjät",
"navigation_bar.opened_in_classic_interface": "Julkaisut, profiilit ja tietyt muut sivut avautuvat oletuksena perinteiseen selainkäyttöliittymään.",
"navigation_bar.personal": "Henkilökohtaiset",
@@ -555,8 +559,6 @@
"notifications.column_settings.admin.report": "Uudet raportit:",
"notifications.column_settings.admin.sign_up": "Uudet rekisteröitymiset:",
"notifications.column_settings.alert": "Työpöytäilmoitukset",
- "notifications.column_settings.beta.category": "Kokeelliset ominaisuudet",
- "notifications.column_settings.beta.grouping": "Ryhmittele ilmoitukset",
"notifications.column_settings.favourite": "Suosikit:",
"notifications.column_settings.filter_bar.advanced": "Näytä kaikki luokat",
"notifications.column_settings.filter_bar.category": "Pikasuodatuspalkki",
@@ -776,6 +778,7 @@
"status.bookmark": "Lisää kirjanmerkki",
"status.cancel_reblog_private": "Peru tehostus",
"status.cannot_reblog": "Tätä julkaisua ei voi tehostaa",
+ "status.continued_thread": "Jatkoi ketjua",
"status.copy": "Kopioi linkki julkaisuun",
"status.delete": "Poista",
"status.detailed_status": "Yksityiskohtainen keskustelunäkymä",
@@ -784,7 +787,7 @@
"status.edit": "Muokkaa",
"status.edited": "Viimeksi muokattu {date}",
"status.edited_x_times": "Muokattu {count, plural, one {{count} kerran} other {{count} kertaa}}",
- "status.embed": "Upota",
+ "status.embed": "Hanki upotuskoodi",
"status.favourite": "Suosikki",
"status.favourites": "{count, plural, one {suosikki} other {suosikkia}}",
"status.filter": "Suodata tämä julkaisu",
@@ -809,6 +812,7 @@
"status.reblogs.empty": "Kukaan ei ole vielä tehostanut tätä julkaisua. Kun joku tekee niin, tulee hän tähän näkyviin.",
"status.redraft": "Poista ja palauta muokattavaksi",
"status.remove_bookmark": "Poista kirjanmerkki",
+ "status.replied_in_thread": "Vastasi ketjuun",
"status.replied_to": "Vastaus käyttäjälle {name}",
"status.reply": "Vastaa",
"status.replyAll": "Vastaa ketjuun",
diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json
index 576cacef4e..9b87f5c8d9 100644
--- a/app/javascript/mastodon/locales/fo.json
+++ b/app/javascript/mastodon/locales/fo.json
@@ -97,6 +97,8 @@
"block_modal.title": "Banna brúkara?",
"block_modal.you_wont_see_mentions": "Tú sært ikki postar, sum nevna tey.",
"boost_modal.combo": "Tú kanst trýsta á {combo} fyri at loypa uppum hetta næstu ferð",
+ "boost_modal.reblog": "Stimbra post?",
+ "boost_modal.undo_reblog": "Strika stimbran av posti?",
"bundle_column_error.copy_stacktrace": "Avrita feilfráboðan",
"bundle_column_error.error.body": "Umbidna síðan kann ikki vísast. Tað kann vera orsakað av einum feili í koduni hjá okkum ella tað kann vera orsakað av kaganum, sum tú brúkar.",
"bundle_column_error.error.title": "Áh, nei!",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Tak skrivi-/leiti-økið úr miðdeplinum",
"keyboard_shortcuts.up": "Flyt upp á listanum",
"lightbox.close": "Lat aftur",
- "lightbox.compress": "Kroyst myndavísikassa saman",
- "lightbox.expand": "Víðka myndavísikassa",
"lightbox.next": "Fram",
"lightbox.previous": "Aftur",
+ "lightbox.zoom_in": "Suma til veruliga stødd",
+ "lightbox.zoom_out": "Suma, so tað passar",
"limited_account_hint.action": "Vís vangamynd kortini",
"limited_account_hint.title": "Hesin vangin er fjaldur av kjakleiðarunum á {domain}.",
"link_preview.author": "Av {name}",
@@ -455,7 +457,7 @@
"lists.subheading": "Tínir listar",
"load_pending": "{count, plural, one {# nýtt evni} other {# nýggj evni}}",
"loading_indicator.label": "Innlesur…",
- "media_gallery.toggle_visible": "{number, plural, one {Fjal mynd} other {Fjal myndir}}",
+ "media_gallery.hide": "Fjal",
"moved_to_account_banner.text": "Konta tín {disabledAccount} er í løtuni óvirkin, tí tú flutti til {movedToAccount}.",
"mute_modal.hide_from_notifications": "Fjal boð",
"mute_modal.hide_options": "Fjal valmøguleikar",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Tú sært ikki postar, sum nevna tey.",
"mute_modal.you_wont_see_posts": "Tey síggja framvegis tínar postar, men tú sært ikki teirra.",
"navigation_bar.about": "Um",
+ "navigation_bar.administration": "Umsiting",
"navigation_bar.advanced_interface": "Lat upp í framkomnum vevmarkamóti",
"navigation_bar.blocks": "Bannaðir brúkarar",
"navigation_bar.bookmarks": "Goymd",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Fylgd og fylgjarar",
"navigation_bar.lists": "Listar",
"navigation_bar.logout": "Rita út",
+ "navigation_bar.moderation": "Umsjón",
"navigation_bar.mutes": "Doyvdir brúkarar",
"navigation_bar.opened_in_classic_interface": "Postar, kontur og aðrar serstakar síður verða - um ikki annað er ásett - latnar upp í klassiska vev-markamótinum.",
"navigation_bar.personal": "Persónligt",
@@ -555,8 +559,6 @@
"notifications.column_settings.admin.report": "Nýggjar fráboðanir:",
"notifications.column_settings.admin.sign_up": "Nýggjar tilmeldingar:",
"notifications.column_settings.alert": "Skriviborðsfráboðanir",
- "notifications.column_settings.beta.category": "Royndarhentleikar",
- "notifications.column_settings.beta.grouping": "Bólkafráboðanir",
"notifications.column_settings.favourite": "Dámdir postar:",
"notifications.column_settings.filter_bar.advanced": "Vís allar bólkar",
"notifications.column_settings.filter_bar.category": "Skjótfilturbjálki",
@@ -776,6 +778,7 @@
"status.bookmark": "Goym",
"status.cancel_reblog_private": "Strika stimbran",
"status.cannot_reblog": "Tað ber ikki til at stimbra hendan postin",
+ "status.continued_thread": "Framhaldandi tráður",
"status.copy": "Kopiera leinki til postin",
"status.delete": "Strika",
"status.detailed_status": "Útgreinað samrøðusýni",
@@ -784,7 +787,7 @@
"status.edit": "Rætta",
"status.edited": "Seinast broytt {date}",
"status.edited_x_times": "Rættað {count, plural, one {{count} ferð} other {{count} ferð}}",
- "status.embed": "Legg inní",
+ "status.embed": "Fá kodu at seta inn",
"status.favourite": "Dámdur postur",
"status.favourites": "{count, plural, one {yndispostur} other {yndispostar}}",
"status.filter": "Filtrera hendan postin",
@@ -809,6 +812,7 @@
"status.reblogs.empty": "Eingin hevur stimbrað hendan postin enn. Tá onkur stimbrar postin, verður hann sjónligur her.",
"status.redraft": "Strika & ger nýggja kladdu",
"status.remove_bookmark": "Gloym",
+ "status.replied_in_thread": "Svaraði í tráðnum",
"status.replied_to": "Svaraði {name}",
"status.reply": "Svara",
"status.replyAll": "Svara tráðnum",
diff --git a/app/javascript/mastodon/locales/fr-CA.json b/app/javascript/mastodon/locales/fr-CA.json
index 667b7013ef..ead016dec2 100644
--- a/app/javascript/mastodon/locales/fr-CA.json
+++ b/app/javascript/mastodon/locales/fr-CA.json
@@ -36,6 +36,7 @@
"account.followers.empty": "Personne ne suit ce compte pour l'instant.",
"account.followers_counter": "{count, plural, one {{counter} abonné·e} other {{counter} abonné·e·s}}",
"account.following": "Abonné·e",
+ "account.following_counter": "{count, plural, one {{counter} abonnement} other {{counter} abonnements}}",
"account.follows.empty": "Ce compte ne suit personne présentement.",
"account.go_to_profile": "Voir ce profil",
"account.hide_reblogs": "Masquer les boosts de @{name}",
@@ -96,6 +97,8 @@
"block_modal.title": "Bloquer l'utilisateur·rice ?",
"block_modal.you_wont_see_mentions": "Vous ne verrez pas les publications qui le mentionne.",
"boost_modal.combo": "Vous pouvez appuyer sur {combo} pour sauter ceci la prochaine fois",
+ "boost_modal.reblog": "Booster le message ?",
+ "boost_modal.undo_reblog": "Annuler le boost du message ?",
"bundle_column_error.copy_stacktrace": "Copier le rapport d'erreur",
"bundle_column_error.error.body": "La page demandée n'a pas pu être affichée. Cela pourrait être dû à un bogue dans notre code, ou à un problème de compatibilité avec le navigateur.",
"bundle_column_error.error.title": "Oh non!",
@@ -161,7 +164,7 @@
"compose_form.publish": "Publier",
"compose_form.publish_form": "Publier",
"compose_form.reply": "Répondre",
- "compose_form.save_changes": "Mis à jour",
+ "compose_form.save_changes": "Mettre à jour",
"compose_form.spoiler.marked": "Enlever l'avertissement de contenu",
"compose_form.spoiler.unmarked": "Ajouter un avertissement de contenu",
"compose_form.spoiler_placeholder": "Avertissement de contenu (optionnel)",
@@ -191,6 +194,8 @@
"confirmations.unfollow.confirm": "Ne plus suivre",
"confirmations.unfollow.message": "Voulez-vous vraiment arrêter de suivre {name}?",
"confirmations.unfollow.title": "Se désabonner de l'utilisateur ?",
+ "content_warning.hide": "Masquer le message",
+ "content_warning.show": "Afficher quand même",
"conversation.delete": "Supprimer cette conversation",
"conversation.mark_as_read": "Marquer comme lu",
"conversation.open": "Afficher cette conversation",
@@ -298,6 +303,8 @@
"filter_modal.select_filter.subtitle": "Utilisez une catégorie existante ou en créer une nouvelle",
"filter_modal.select_filter.title": "Filtrer cette publication",
"filter_modal.title.status": "Filtrer une publication",
+ "filter_warning.matches_filter": "Correspond au filtre « {title} »",
+ "filtered_notifications_banner.pending_requests": "De la part {count, plural, =0 {d’aucune personne} one {d'une personne} other {de # personnes}} que vous pourriez connaître",
"filtered_notifications_banner.title": "Notifications filtrées",
"firehose.all": "Tout",
"firehose.local": "Ce serveur",
@@ -305,8 +312,10 @@
"follow_request.authorize": "Autoriser",
"follow_request.reject": "Rejeter",
"follow_requests.unlocked_explanation": "Même si votre compte n’est pas privé, l’équipe de {domain} a pensé que vous pourriez vouloir peut-être consulter manuellement les demandes d'abonnement de ces comptes.",
- "follow_suggestions.curated_suggestion": "Choix du staff",
+ "follow_suggestions.curated_suggestion": "Sélectionné par l'équipe",
"follow_suggestions.dismiss": "Ne plus afficher",
+ "follow_suggestions.featured_longer": "Sélectionné par l'équipe de {domain}",
+ "follow_suggestions.friends_of_friends_longer": "Populaire dans le cercle des personnes que vous suivez",
"follow_suggestions.hints.featured": "Ce profil a été sélectionné par l'équipe de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Ce profil est populaire parmi les personnes que vous suivez.",
"follow_suggestions.hints.most_followed": "Ce profil est l'un des plus suivis sur {domain}.",
@@ -315,6 +324,7 @@
"follow_suggestions.personalized_suggestion": "Suggestion personnalisée",
"follow_suggestions.popular_suggestion": "Suggestion populaire",
"follow_suggestions.popular_suggestion_longer": "Populaire sur {domain}",
+ "follow_suggestions.similar_to_recently_followed_longer": "Similaire aux profils que vous avez dernièrement suivis",
"follow_suggestions.view_all": "Tout afficher",
"follow_suggestions.who_to_follow": "Qui suivre",
"followed_tags": "Hashtags suivis",
@@ -343,8 +353,14 @@
"hashtag.follow": "Suivre ce hashtag",
"hashtag.unfollow": "Ne plus suivre ce hashtag",
"hashtags.and_other": "…et {count, plural, other {# de plus}}",
+ "hints.profiles.followers_may_be_missing": "Les abonné·e·s à ce profil peuvent être manquant·e·s.",
+ "hints.profiles.follows_may_be_missing": "Les abonnements pour ce profil peuvent être manquants.",
+ "hints.profiles.posts_may_be_missing": "Certains messages de ce profil peuvent être manquants.",
+ "hints.profiles.see_more_followers": "Afficher plus d'abonné·e·s sur {domain}",
+ "hints.profiles.see_more_follows": "Afficher plus d'abonné·e·s sur {domain}",
"hints.profiles.see_more_posts": "Voir plus de messages sur {domain}",
- "hints.threads.see_more": "Voir plus de réponses sur {domain}",
+ "hints.threads.replies_may_be_missing": "Les réponses provenant des autres serveurs pourraient être manquantes.",
+ "hints.threads.see_more": "Afficher plus de réponses sur {domain}",
"home.column_settings.show_reblogs": "Afficher boosts",
"home.column_settings.show_replies": "Afficher réponses",
"home.hide_announcements": "Masquer les annonces",
@@ -352,6 +368,17 @@
"home.pending_critical_update.link": "Voir les mises à jour",
"home.pending_critical_update.title": "Une mise à jour de sécurité critique est disponible !",
"home.show_announcements": "Afficher annonces",
+ "ignore_notifications_modal.disclaimer": "Mastodon ne peut pas indiquer aux utilisateurs que vous avez ignoré leurs notifications. Le fait d'ignorer les notifications n'empêchera pas la transmission des messages eux-mêmes.",
+ "ignore_notifications_modal.filter_instead": "Filtrer plutôt",
+ "ignore_notifications_modal.filter_to_act_users": "Vous serez toujours en mesure d'accepter, de rejeter ou de signaler les utilisateur·rice·s",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "Le filtrage permet d'éviter toute éventuelle confusion",
+ "ignore_notifications_modal.filter_to_review_separately": "Vous pouvez réexaminer les notifications filtrées séparément",
+ "ignore_notifications_modal.ignore": "Ignorer les notifications",
+ "ignore_notifications_modal.limited_accounts_title": "Ignorer les notifications provenant des comptes modérés ?",
+ "ignore_notifications_modal.new_accounts_title": "Ignorer les notifications provenant des nouveaux comptes ?",
+ "ignore_notifications_modal.not_followers_title": "Ignorer les notifications provenant des personnes qui ne vous suivent pas ?",
+ "ignore_notifications_modal.not_following_title": "Ignorer les notifications provenant des personnes que vous ne suivez pas ?",
+ "ignore_notifications_modal.private_mentions_title": "Ignorer les notifications issues des mentions privées non sollicitées ?",
"interaction_modal.description.favourite": "Avec un compte Mastodon, vous pouvez ajouter cette publication à vos favoris pour informer l'auteur⋅rice que vous l'appréciez et la sauvegarder pour plus tard.",
"interaction_modal.description.follow": "Avec un compte Mastodon, vous pouvez suivre {name} et recevoir leurs publications dans votre fil d'accueil.",
"interaction_modal.description.reblog": "Avec un compte Mastodon, vous pouvez booster cette publication pour la partager avec vos propres abonné·e·s.",
@@ -405,13 +432,12 @@
"keyboard_shortcuts.unfocus": "Ne plus se concentrer sur la zone de rédaction/barre de recherche",
"keyboard_shortcuts.up": "Monter dans la liste",
"lightbox.close": "Fermer",
- "lightbox.compress": "Compresser la fenêtre de visualisation d'images",
- "lightbox.expand": "Agrandir la fenêtre de visualisation d'images",
"lightbox.next": "Suivant",
"lightbox.previous": "Précédent",
"limited_account_hint.action": "Afficher le profil quand même",
"limited_account_hint.title": "Ce profil a été masqué par la modération de {domain}.",
"link_preview.author": "Par {name}",
+ "link_preview.more_from_author": "Plus via {name}",
"link_preview.shares": "{count, plural, one {{counter} message} other {{counter} messages}}",
"lists.account.add": "Ajouter à une liste",
"lists.account.remove": "Retirer d'une liste",
@@ -429,7 +455,7 @@
"lists.subheading": "Vos listes",
"load_pending": "{count, plural, one {# nouvel élément} other {# nouveaux éléments}}",
"loading_indicator.label": "Chargement…",
- "media_gallery.toggle_visible": "{number, plural, one {Cacher l’image} other {Cacher les images}}",
+ "media_gallery.hide": "Masquer",
"moved_to_account_banner.text": "Votre compte {disabledAccount} est actuellement désactivé parce que vous avez déménagé sur {movedToAccount}.",
"mute_modal.hide_from_notifications": "Cacher des notifications",
"mute_modal.hide_options": "Masquer les options",
@@ -441,6 +467,7 @@
"mute_modal.you_wont_see_mentions": "Vous ne verrez pas les publications qui le mentionne.",
"mute_modal.you_wont_see_posts": "Il peut toujours voir vos publications, mais vous ne verrez pas les siennes.",
"navigation_bar.about": "À propos",
+ "navigation_bar.administration": "Administration",
"navigation_bar.advanced_interface": "Ouvrir dans l’interface avancée",
"navigation_bar.blocks": "Comptes bloqués",
"navigation_bar.bookmarks": "Signets",
@@ -457,6 +484,7 @@
"navigation_bar.follows_and_followers": "Abonnements et abonnés",
"navigation_bar.lists": "Listes",
"navigation_bar.logout": "Se déconnecter",
+ "navigation_bar.moderation": "Modération",
"navigation_bar.mutes": "Utilisateurs masqués",
"navigation_bar.opened_in_classic_interface": "Les messages, les comptes et les pages spécifiques sont ouvertes dans l’interface classique.",
"navigation_bar.personal": "Personnel",
@@ -467,14 +495,23 @@
"navigation_bar.security": "Sécurité",
"not_signed_in_indicator.not_signed_in": "Vous devez vous connecter pour accéder à cette ressource.",
"notification.admin.report": "{name} a signalé {target}",
+ "notification.admin.report_account": "{name} a signalé {count, plural, one {un message} other {# messages}} de {target} pour {category}",
+ "notification.admin.report_account_other": "{name} a signalé {count, plural, one {un message} other {# messages}} depuis {target}",
+ "notification.admin.report_statuses": "{name} a signalé {target} pour {category}",
+ "notification.admin.report_statuses_other": "{name} a signalé {target}",
"notification.admin.sign_up": "{name} s'est inscrit·e",
+ "notification.admin.sign_up.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} se sont inscrit",
"notification.favourite": "{name} a ajouté votre publication à ses favoris",
+ "notification.favourite.name_and_others_with_link": "{name} et
{count, plural, one {# autre} other {# autres}} ont mis votre message en favori",
"notification.follow": "{name} vous suit",
+ "notification.follow.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} se sont abonné à votre compte",
"notification.follow_request": "{name} a demandé à vous suivre",
+ "notification.follow_request.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} ont demandé à vous suivre",
"notification.label.mention": "Mention",
"notification.label.private_mention": "Mention privée",
"notification.label.private_reply": "Répondre en privé",
"notification.label.reply": "Réponse",
+ "notification.mention": "Mention",
"notification.moderation-warning.learn_more": "En savoir plus",
"notification.moderation_warning": "Vous avez reçu un avertissement de modération",
"notification.moderation_warning.action_delete_statuses": "Certains de vos messages ont été supprimés.",
@@ -487,6 +524,7 @@
"notification.own_poll": "Votre sondage est terminé",
"notification.poll": "Un sondage auquel vous avez participé vient de se terminer",
"notification.reblog": "{name} a boosté votre message",
+ "notification.reblog.name_and_others_with_link": "{name} et
{count, plural, one {# autre} other {# autres}} ont boosté votre message",
"notification.relationships_severance_event": "Connexions perdues avec {name}",
"notification.relationships_severance_event.account_suspension": "Un·e administrateur·rice de {from} a suspendu {target}, ce qui signifie que vous ne pourrez plus recevoir de mises à jour ou interagir avec lui.",
"notification.relationships_severance_event.domain_block": "Un·e administrateur·rice de {from} en a bloqué {target}, comprenant {followersCount} de vos abonné·e·s et {followingCount, plural, one {# compte} other {# comptes}} vous suivez.",
@@ -495,11 +533,24 @@
"notification.status": "{name} vient de publier",
"notification.update": "{name} a modifié une publication",
"notification_requests.accept": "Accepter",
+ "notification_requests.accept_multiple": "{count, plural, one {Accepter # requête …} other {Accepter # requêtes …}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Accepter la requête} other {Accepter les requêtes}}",
+ "notification_requests.confirm_accept_multiple.message": "Vous êtes sur le point d'accepter {count, plural, one {une requête de notification} other {# requêtes de notification}}. Êtes-vous sûr de vouloir continuer ?",
+ "notification_requests.confirm_accept_multiple.title": "Accepter les requêtes de notification ?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Ignorer la requête} other {Ignorer les requêtes}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Vous êtes sur le point de rejeter {count, plural, one {une requête de notification} other {# requêtes de notification}}. Vous ne serez plus en mesure d’{count, plural, one {y} other {y}} accéder facilement, ultérieurement. Êtes-vous sûr de vouloir continuer ?",
+ "notification_requests.confirm_dismiss_multiple.title": "Rejeter les requêtes de notification ?",
"notification_requests.dismiss": "Rejeter",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Rejeter # requête …} other {Rejeter # requêtes …}}",
"notification_requests.edit_selection": "Modifier",
"notification_requests.exit_selection": "Fait",
+ "notification_requests.explainer_for_limited_account": "Les notifications en provenance de ce compte ont été filtrées car le compte a été limité par un modérateur.",
+ "notification_requests.explainer_for_limited_remote_account": "Les notifications en provenance de ce compte ont été filtrées car le compte ou le serveur dont il est issu a été limité par un modérateur.",
+ "notification_requests.maximize": "Agrandir",
+ "notification_requests.minimize_banner": "Réduire la bannière des notifications filtrées",
"notification_requests.notifications_from": "Notifications de {name}",
"notification_requests.title": "Notifications filtrées",
+ "notification_requests.view": "Afficher les notifications",
"notifications.clear": "Effacer notifications",
"notifications.clear_confirmation": "Voulez-vous vraiment effacer toutes vos notifications?",
"notifications.clear_title": "Effacer les notifications ?",
@@ -534,9 +585,13 @@
"notifications.permission_denied": "Les notifications de bureau ne sont pas disponibles en raison d'une demande de permission de navigateur précédemment refusée",
"notifications.permission_denied_alert": "Les notifications de bureau ne peuvent pas être activées, car l’autorisation du navigateur a précedemment été refusée",
"notifications.permission_required": "Les notifications de bureau ne sont pas disponibles car l’autorisation requise n’a pas été accordée.",
+ "notifications.policy.accept": "Accepter",
+ "notifications.policy.accept_hint": "Afficher dans les notifications",
"notifications.policy.drop": "Ignorer",
+ "notifications.policy.drop_hint": "Expulser vers le vide, pour ne plus jamais les revoir",
"notifications.policy.filter": "Filtrer",
- "notifications.policy.filter_limited_accounts_hint": "Limité par les modérateur·rice·s du serveur",
+ "notifications.policy.filter_hint": "Envoyer à la boîte de réception des notifications filtrées",
+ "notifications.policy.filter_limited_accounts_hint": "Limités par les modérateur·rice·s du serveur",
"notifications.policy.filter_limited_accounts_title": "Comptes modérés",
"notifications.policy.filter_new_accounts.hint": "Créés au cours des derniers {days, plural, one {un jour} other {# jours}}",
"notifications.policy.filter_new_accounts_title": "Nouveaux comptes",
@@ -544,8 +599,9 @@
"notifications.policy.filter_not_followers_title": "Personnes qui ne vous suivent pas",
"notifications.policy.filter_not_following_hint": "Jusqu'à ce que vous les validiez manuellement",
"notifications.policy.filter_not_following_title": "Personnes que vous ne suivez pas",
- "notifications.policy.filter_private_mentions_hint": "Filtré sauf si c'est en réponse à une mention de vous ou si vous suivez l'expéditeur",
+ "notifications.policy.filter_private_mentions_hint": "Filtrées sauf si c'est en réponse à l'une de vos mentions ou si vous suivez l'expéditeur·ice",
"notifications.policy.filter_private_mentions_title": "Mentions privées non sollicitées",
+ "notifications.policy.title": "Gestion des notifications des …",
"notifications_permission_banner.enable": "Activer les notifications de bureau",
"notifications_permission_banner.how_to_control": "Pour recevoir des notifications lorsque Mastodon n’est pas ouvert, activez les notifications de bureau. Vous pouvez contrôler précisément quels types d’interactions génèrent des notifications de bureau via le bouton {icon} ci-dessus une fois qu’elles sont activées.",
"notifications_permission_banner.title": "Ne rien rater",
@@ -709,6 +765,7 @@
"server_banner.is_one_of_many": "{domain} est l'un des nombreux serveurs Mastodon indépendants que vous pouvez utiliser pour participer au fédiverse.",
"server_banner.server_stats": "Statistiques du serveur:",
"sign_in_banner.create_account": "Créer un compte",
+ "sign_in_banner.follow_anyone": "Suivez n'importe qui à travers le fédivers et affichez tout dans un ordre chronologique. Ni algorithmes, ni publicités, ni appâts à clics en perspective.",
"sign_in_banner.mastodon_is": "Mastodon est le meilleur moyen de suivre ce qui se passe.",
"sign_in_banner.sign_in": "Se connecter",
"sign_in_banner.sso_redirect": "Se connecter ou s’inscrire",
@@ -719,6 +776,7 @@
"status.bookmark": "Ajouter aux signets",
"status.cancel_reblog_private": "Débooster",
"status.cannot_reblog": "Cette publication ne peut pas être boostée",
+ "status.continued_thread": "Suite du fil",
"status.copy": "Copier un lien vers cette publication",
"status.delete": "Supprimer",
"status.detailed_status": "Vue détaillée de la conversation",
@@ -727,7 +785,7 @@
"status.edit": "Modifier",
"status.edited": "Dernière modification le {date}",
"status.edited_x_times": "Modifiée {count, plural, one {{count} fois} other {{count} fois}}",
- "status.embed": "Intégrer",
+ "status.embed": "Obtenir le code d'intégration",
"status.favourite": "Ajouter aux favoris",
"status.favourites": "{count, plural, one {favori} other {favoris}}",
"status.filter": "Filtrer cette publication",
@@ -752,6 +810,7 @@
"status.reblogs.empty": "Personne n’a encore boosté cette publication. Lorsque quelqu’un le fera, elle apparaîtra ici.",
"status.redraft": "Supprimer et réécrire",
"status.remove_bookmark": "Retirer des signets",
+ "status.replied_in_thread": "A répondu dans un fil de discussion",
"status.replied_to": "A répondu à {name}",
"status.reply": "Répondre",
"status.replyAll": "Répondre à cette discussion",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index 11773e38e5..9375eccc6f 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -36,6 +36,7 @@
"account.followers.empty": "Personne ne suit cet·te utilisateur·rice pour l’instant.",
"account.followers_counter": "{count, plural, one {{counter} abonné·e} other {{counter} abonné·e·s}}",
"account.following": "Abonnements",
+ "account.following_counter": "{count, plural, one {{counter} abonnement} other {{counter} abonnements}}",
"account.follows.empty": "Cet·te utilisateur·rice ne suit personne pour l’instant.",
"account.go_to_profile": "Aller au profil",
"account.hide_reblogs": "Masquer les partages de @{name}",
@@ -96,6 +97,8 @@
"block_modal.title": "Bloquer l'utilisateur·rice ?",
"block_modal.you_wont_see_mentions": "Vous ne verrez pas les publications qui le mentionne.",
"boost_modal.combo": "Vous pouvez appuyer sur {combo} pour passer ceci la prochaine fois",
+ "boost_modal.reblog": "Booster le message ?",
+ "boost_modal.undo_reblog": "Annuler le boost du message ?",
"bundle_column_error.copy_stacktrace": "Copier le rapport d'erreur",
"bundle_column_error.error.body": "La page demandée n'a pas pu être affichée. Cela peut être dû à un bogue dans notre code, ou à un problème de compatibilité avec le navigateur.",
"bundle_column_error.error.title": "Oh non !",
@@ -161,7 +164,7 @@
"compose_form.publish": "Publier",
"compose_form.publish_form": "Nouvelle publication",
"compose_form.reply": "Répondre",
- "compose_form.save_changes": "Mis à jour",
+ "compose_form.save_changes": "Mettre à jour",
"compose_form.spoiler.marked": "Enlever l’avertissement de contenu",
"compose_form.spoiler.unmarked": "Ajouter un avertissement de contenu",
"compose_form.spoiler_placeholder": "Avertissement de contenu (optionnel)",
@@ -191,6 +194,8 @@
"confirmations.unfollow.confirm": "Ne plus suivre",
"confirmations.unfollow.message": "Voulez-vous vraiment vous désabonner de {name} ?",
"confirmations.unfollow.title": "Se désabonner de l'utilisateur ?",
+ "content_warning.hide": "Masquer le message",
+ "content_warning.show": "Afficher quand même",
"conversation.delete": "Supprimer la conversation",
"conversation.mark_as_read": "Marquer comme lu",
"conversation.open": "Afficher la conversation",
@@ -209,7 +214,7 @@
"dismissable_banner.explore_links": "On parle actuellement de ces nouvelles sur ce serveur, ainsi que sur d'autres serveurs du réseau décentralisé.",
"dismissable_banner.explore_statuses": "Ces messages venant de tout le web social gagnent en popularité aujourd’hui. Les nouveaux messages avec plus de boosts et de favoris sont classés plus haut.",
"dismissable_banner.explore_tags": "Ces hashtags sont actuellement en train de gagner de l'ampleur parmi les personnes sur les serveurs du réseau décentralisé dont celui-ci.",
- "dismissable_banner.public_timeline": "Ce sont les posts publics les plus récents de personnes sur le web social que les gens sur {domain} suivent.",
+ "dismissable_banner.public_timeline": "Il s'agit des messages publics les plus récents publiés par des gens sur le web social et que les utilisateurs de {domain} suivent.",
"domain_block_modal.block": "Bloquer le serveur",
"domain_block_modal.block_account_instead": "Bloquer @{name} à la place",
"domain_block_modal.they_can_interact_with_old_posts": "Les personnes de ce serveur peuvent interagir avec vos anciennes publications.",
@@ -286,7 +291,7 @@
"filter_modal.added.context_mismatch_title": "Incompatibilité du contexte !",
"filter_modal.added.expired_explanation": "Cette catégorie de filtre a expiré, vous devrez modifier la date d'expiration pour qu'elle soit appliquée.",
"filter_modal.added.expired_title": "Filtre expiré !",
- "filter_modal.added.review_and_configure": "Pour examiner et affiner la configuration de cette catégorie de filtre, allez à {settings_link}.",
+ "filter_modal.added.review_and_configure": "Pour examiner et affiner la configuration de cette catégorie de filtres, allez à {settings_link}.",
"filter_modal.added.review_and_configure_title": "Paramètres du filtre",
"filter_modal.added.settings_link": "page des paramètres",
"filter_modal.added.short_explanation": "Ce message a été ajouté à la catégorie de filtre suivante : {title}.",
@@ -295,9 +300,11 @@
"filter_modal.select_filter.expired": "a expiré",
"filter_modal.select_filter.prompt_new": "Nouvelle catégorie : {name}",
"filter_modal.select_filter.search": "Rechercher ou créer",
- "filter_modal.select_filter.subtitle": "Utilisez une catégorie existante ou en créer une nouvelle",
+ "filter_modal.select_filter.subtitle": "Utilisez une catégorie existante ou créez-en une nouvelle",
"filter_modal.select_filter.title": "Filtrer ce message",
"filter_modal.title.status": "Filtrer un message",
+ "filter_warning.matches_filter": "Correspond au filtre « {title} »",
+ "filtered_notifications_banner.pending_requests": "De la part {count, plural, =0 {d’aucune personne} one {d'une personne} other {de # personnes}} que vous pourriez connaître",
"filtered_notifications_banner.title": "Notifications filtrées",
"firehose.all": "Tout",
"firehose.local": "Ce serveur",
@@ -305,8 +312,10 @@
"follow_request.authorize": "Accepter",
"follow_request.reject": "Rejeter",
"follow_requests.unlocked_explanation": "Même si votre compte n’est pas privé, l’équipe de {domain} a pensé que vous pourriez vouloir consulter manuellement les demandes de suivi de ces comptes.",
- "follow_suggestions.curated_suggestion": "Choix du staff",
+ "follow_suggestions.curated_suggestion": "Sélectionné par l'équipe",
"follow_suggestions.dismiss": "Ne plus afficher",
+ "follow_suggestions.featured_longer": "Sélectionné par l'équipe de {domain}",
+ "follow_suggestions.friends_of_friends_longer": "Populaire dans le cercle des personnes que vous suivez",
"follow_suggestions.hints.featured": "Ce profil a été sélectionné par l'équipe de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Ce profil est populaire parmi les personnes que vous suivez.",
"follow_suggestions.hints.most_followed": "Ce profil est l'un des plus suivis sur {domain}.",
@@ -315,6 +324,7 @@
"follow_suggestions.personalized_suggestion": "Suggestion personnalisée",
"follow_suggestions.popular_suggestion": "Suggestion populaire",
"follow_suggestions.popular_suggestion_longer": "Populaire sur {domain}",
+ "follow_suggestions.similar_to_recently_followed_longer": "Similaire aux profils que vous avez dernièrement suivis",
"follow_suggestions.view_all": "Tout afficher",
"follow_suggestions.who_to_follow": "Qui suivre",
"followed_tags": "Hashtags suivis",
@@ -343,8 +353,14 @@
"hashtag.follow": "Suivre le hashtag",
"hashtag.unfollow": "Ne plus suivre le hashtag",
"hashtags.and_other": "…et {count, plural, other {# de plus}}",
+ "hints.profiles.followers_may_be_missing": "Les abonné·e·s à ce profil peuvent être manquant·e·s.",
+ "hints.profiles.follows_may_be_missing": "Les abonnements pour ce profil peuvent être manquants.",
+ "hints.profiles.posts_may_be_missing": "Certains messages de ce profil peuvent être manquants.",
+ "hints.profiles.see_more_followers": "Afficher plus d'abonné·e·s sur {domain}",
+ "hints.profiles.see_more_follows": "Afficher plus d'abonné·e·s sur {domain}",
"hints.profiles.see_more_posts": "Voir plus de messages sur {domain}",
- "hints.threads.see_more": "Voir plus de réponses sur {domain}",
+ "hints.threads.replies_may_be_missing": "Les réponses provenant des autres serveurs pourraient être manquantes.",
+ "hints.threads.see_more": "Afficher plus de réponses sur {domain}",
"home.column_settings.show_reblogs": "Afficher les partages",
"home.column_settings.show_replies": "Afficher les réponses",
"home.hide_announcements": "Masquer les annonces",
@@ -352,6 +368,17 @@
"home.pending_critical_update.link": "Voir les mises à jour",
"home.pending_critical_update.title": "Une mise à jour de sécurité critique est disponible !",
"home.show_announcements": "Afficher les annonces",
+ "ignore_notifications_modal.disclaimer": "Mastodon ne peut pas indiquer aux utilisateurs que vous avez ignoré leurs notifications. Le fait d'ignorer les notifications n'empêchera pas la transmission des messages eux-mêmes.",
+ "ignore_notifications_modal.filter_instead": "Filtrer plutôt",
+ "ignore_notifications_modal.filter_to_act_users": "Vous serez toujours en mesure d'accepter, de rejeter ou de signaler les utilisateur·rice·s",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "Le filtrage permet d'éviter toute éventuelle confusion",
+ "ignore_notifications_modal.filter_to_review_separately": "Vous pouvez réexaminer les notifications filtrées séparément",
+ "ignore_notifications_modal.ignore": "Ignorer les notifications",
+ "ignore_notifications_modal.limited_accounts_title": "Ignorer les notifications provenant des comptes modérés ?",
+ "ignore_notifications_modal.new_accounts_title": "Ignorer les notifications provenant des nouveaux comptes ?",
+ "ignore_notifications_modal.not_followers_title": "Ignorer les notifications provenant des personnes qui ne vous suivent pas ?",
+ "ignore_notifications_modal.not_following_title": "Ignorer les notifications provenant des personnes que vous ne suivez pas ?",
+ "ignore_notifications_modal.private_mentions_title": "Ignorer les notifications issues des mentions privées non sollicitées ?",
"interaction_modal.description.favourite": "Avec un compte Mastodon, vous pouvez ajouter ce message à vos favoris pour informer l'auteur⋅rice que vous l'appréciez et pour le sauvegarder pour plus tard.",
"interaction_modal.description.follow": "Avec un compte Mastodon, vous pouvez suivre {name} et recevoir leurs posts dans votre fil d'actualité.",
"interaction_modal.description.reblog": "Avec un compte sur Mastodon, vous pouvez partager ce message pour le faire découvrir à vos propres abonné⋅e⋅s.",
@@ -405,13 +432,12 @@
"keyboard_shortcuts.unfocus": "Quitter la zone de rédaction/barre de recherche",
"keyboard_shortcuts.up": "Monter dans la liste",
"lightbox.close": "Fermer",
- "lightbox.compress": "Compresser la fenêtre de visualisation des images",
- "lightbox.expand": "Agrandir la fenêtre de visualisation des images",
"lightbox.next": "Suivant",
"lightbox.previous": "Précédent",
"limited_account_hint.action": "Afficher le profil quand même",
"limited_account_hint.title": "Ce profil a été masqué par la modération de {domain}.",
"link_preview.author": "Par {name}",
+ "link_preview.more_from_author": "Plus via {name}",
"link_preview.shares": "{count, plural, one {{counter} message} other {{counter} messages}}",
"lists.account.add": "Ajouter à la liste",
"lists.account.remove": "Supprimer de la liste",
@@ -429,7 +455,7 @@
"lists.subheading": "Vos listes",
"load_pending": "{count, plural, one {# nouvel élément} other {# nouveaux éléments}}",
"loading_indicator.label": "Chargement…",
- "media_gallery.toggle_visible": "{number, plural, one {Cacher l’image} other {Cacher les images}}",
+ "media_gallery.hide": "Masquer",
"moved_to_account_banner.text": "Votre compte {disabledAccount} est actuellement désactivé parce que vous l'avez déplacé à {movedToAccount}.",
"mute_modal.hide_from_notifications": "Cacher des notifications",
"mute_modal.hide_options": "Masquer les options",
@@ -441,6 +467,7 @@
"mute_modal.you_wont_see_mentions": "Vous ne verrez pas les publications qui le mentionne.",
"mute_modal.you_wont_see_posts": "Il peut toujours voir vos publications, mais vous ne verrez pas les siennes.",
"navigation_bar.about": "À propos",
+ "navigation_bar.administration": "Administration",
"navigation_bar.advanced_interface": "Ouvrir dans l’interface avancée",
"navigation_bar.blocks": "Comptes bloqués",
"navigation_bar.bookmarks": "Marque-pages",
@@ -457,6 +484,7 @@
"navigation_bar.follows_and_followers": "Abonnements et abonnés",
"navigation_bar.lists": "Listes",
"navigation_bar.logout": "Déconnexion",
+ "navigation_bar.moderation": "Modération",
"navigation_bar.mutes": "Comptes masqués",
"navigation_bar.opened_in_classic_interface": "Les messages, les comptes et les pages spécifiques sont ouvertes dans l’interface classique.",
"navigation_bar.personal": "Personnel",
@@ -467,14 +495,23 @@
"navigation_bar.security": "Sécurité",
"not_signed_in_indicator.not_signed_in": "Vous devez vous connecter pour accéder à cette ressource.",
"notification.admin.report": "{name} a signalé {target}",
+ "notification.admin.report_account": "{name} a signalé {count, plural, one {un message} other {# messages}} de {target} pour {category}",
+ "notification.admin.report_account_other": "{name} a signalé {count, plural, one {un message} other {# messages}} depuis {target}",
+ "notification.admin.report_statuses": "{name} a signalé {target} pour {category}",
+ "notification.admin.report_statuses_other": "{name} a signalé {target}",
"notification.admin.sign_up": "{name} s'est inscrit",
+ "notification.admin.sign_up.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} se sont inscrit",
"notification.favourite": "{name} a ajouté votre message à ses favoris",
+ "notification.favourite.name_and_others_with_link": "{name} et
{count, plural, one {# autre} other {# autres}} ont mis votre message en favori",
"notification.follow": "{name} vous suit",
+ "notification.follow.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} se sont abonné à votre compte",
"notification.follow_request": "{name} a demandé à vous suivre",
+ "notification.follow_request.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} ont demandé à vous suivre",
"notification.label.mention": "Mention",
"notification.label.private_mention": "Mention privée",
"notification.label.private_reply": "Répondre en privé",
"notification.label.reply": "Réponse",
+ "notification.mention": "Mention",
"notification.moderation-warning.learn_more": "En savoir plus",
"notification.moderation_warning": "Vous avez reçu un avertissement de modération",
"notification.moderation_warning.action_delete_statuses": "Certains de vos messages ont été supprimés.",
@@ -487,6 +524,7 @@
"notification.own_poll": "Votre sondage est terminé",
"notification.poll": "Un sondage auquel vous avez participé vient de se terminer",
"notification.reblog": "{name} a partagé votre message",
+ "notification.reblog.name_and_others_with_link": "{name} et
{count, plural, one {# autre} other {# autres}} ont boosté votre message",
"notification.relationships_severance_event": "Connexions perdues avec {name}",
"notification.relationships_severance_event.account_suspension": "Un·e administrateur·rice de {from} a suspendu {target}, ce qui signifie que vous ne pourrez plus recevoir de mises à jour ou interagir avec lui.",
"notification.relationships_severance_event.domain_block": "Un·e administrateur·rice de {from} en a bloqué {target}, comprenant {followersCount} de vos abonné·e·s et {followingCount, plural, one {# compte} other {# comptes}} vous suivez.",
@@ -495,11 +533,24 @@
"notification.status": "{name} vient de publier",
"notification.update": "{name} a modifié un message",
"notification_requests.accept": "Accepter",
+ "notification_requests.accept_multiple": "{count, plural, one {Accepter # requête …} other {Accepter # requêtes …}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Accepter la requête} other {Accepter les requêtes}}",
+ "notification_requests.confirm_accept_multiple.message": "Vous êtes sur le point d'accepter {count, plural, one {une requête de notification} other {# requêtes de notification}}. Êtes-vous sûr de vouloir continuer ?",
+ "notification_requests.confirm_accept_multiple.title": "Accepter les requêtes de notification ?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Ignorer la requête} other {Ignorer les requêtes}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Vous êtes sur le point de rejeter {count, plural, one {une requête de notification} other {# requêtes de notification}}. Vous ne serez plus en mesure d’{count, plural, one {y} other {y}} accéder facilement, ultérieurement. Êtes-vous sûr de vouloir continuer ?",
+ "notification_requests.confirm_dismiss_multiple.title": "Rejeter les requêtes de notification ?",
"notification_requests.dismiss": "Rejeter",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Rejeter # requête …} other {Rejeter # requêtes …}}",
"notification_requests.edit_selection": "Modifier",
"notification_requests.exit_selection": "Fait",
+ "notification_requests.explainer_for_limited_account": "Les notifications en provenance de ce compte ont été filtrées car le compte a été limité par un modérateur.",
+ "notification_requests.explainer_for_limited_remote_account": "Les notifications en provenance de ce compte ont été filtrées car le compte ou le serveur dont il est issu a été limité par un modérateur.",
+ "notification_requests.maximize": "Agrandir",
+ "notification_requests.minimize_banner": "Réduire la bannière des notifications filtrées",
"notification_requests.notifications_from": "Notifications de {name}",
"notification_requests.title": "Notifications filtrées",
+ "notification_requests.view": "Afficher les notifications",
"notifications.clear": "Effacer les notifications",
"notifications.clear_confirmation": "Voulez-vous vraiment effacer toutes vos notifications ?",
"notifications.clear_title": "Effacer les notifications ?",
@@ -534,9 +585,13 @@
"notifications.permission_denied": "Impossible d’activer les notifications de bureau car l’autorisation a été refusée.",
"notifications.permission_denied_alert": "Les notifications de bureau ne peuvent pas être activées, car l’autorisation du navigateur a été refusée avant",
"notifications.permission_required": "Les notifications de bureau ne sont pas disponibles car l’autorisation requise n’a pas été accordée.",
+ "notifications.policy.accept": "Accepter",
+ "notifications.policy.accept_hint": "Afficher dans les notifications",
"notifications.policy.drop": "Ignorer",
+ "notifications.policy.drop_hint": "Expulser vers le vide, pour ne plus jamais les revoir",
"notifications.policy.filter": "Filtrer",
- "notifications.policy.filter_limited_accounts_hint": "Limité par les modérateur·rice·s du serveur",
+ "notifications.policy.filter_hint": "Envoyer à la boîte de réception des notifications filtrées",
+ "notifications.policy.filter_limited_accounts_hint": "Limités par les modérateur·rice·s du serveur",
"notifications.policy.filter_limited_accounts_title": "Comptes modérés",
"notifications.policy.filter_new_accounts.hint": "Créés au cours des derniers {days, plural, one {un jour} other {# jours}}",
"notifications.policy.filter_new_accounts_title": "Nouveaux comptes",
@@ -544,8 +599,9 @@
"notifications.policy.filter_not_followers_title": "Personnes qui ne vous suivent pas",
"notifications.policy.filter_not_following_hint": "Jusqu'à ce que vous les validiez manuellement",
"notifications.policy.filter_not_following_title": "Personnes que vous ne suivez pas",
- "notifications.policy.filter_private_mentions_hint": "Filtré sauf si c'est en réponse à une mention de vous ou si vous suivez l'expéditeur",
+ "notifications.policy.filter_private_mentions_hint": "Filtrées sauf si c'est en réponse à l'une de vos mentions ou si vous suivez l'expéditeur·ice",
"notifications.policy.filter_private_mentions_title": "Mentions privées non sollicitées",
+ "notifications.policy.title": "Gestion des notifications des …",
"notifications_permission_banner.enable": "Activer les notifications de bureau",
"notifications_permission_banner.how_to_control": "Pour recevoir des notifications lorsque Mastodon n’est pas ouvert, activez les notifications du bureau. Vous pouvez contrôler précisément quels types d’interactions génèrent des notifications de bureau via le bouton {icon} ci-dessus une fois qu’elles sont activées.",
"notifications_permission_banner.title": "Toujours au courant",
@@ -669,7 +725,7 @@
"report.thanks.title": "Vous ne voulez pas voir cela ?",
"report.thanks.title_actionable": "Merci pour votre signalement, nous allons investiguer.",
"report.unfollow": "Ne plus suivre @{name}",
- "report.unfollow_explanation": "Vous suivez ce compte. Désabonnez-vous pour ne plus en voir les messages sur votre fil principal.",
+ "report.unfollow_explanation": "Vous êtes abonné à ce compte. Pour ne plus voir ses publications dans votre fil principal, retirez-le de votre liste d'abonnements.",
"report_notification.attached_statuses": "{count, plural, one {{count} message lié} other {{count} messages liés}}",
"report_notification.categories.legal": "Légal",
"report_notification.categories.legal_sentence": "contenu illégal",
@@ -709,6 +765,7 @@
"server_banner.is_one_of_many": "{domain} est l'un des nombreux serveurs Mastodon indépendants que vous pouvez utiliser pour participer au fédiverse.",
"server_banner.server_stats": "Statistiques du serveur :",
"sign_in_banner.create_account": "Créer un compte",
+ "sign_in_banner.follow_anyone": "Suivez n'importe qui à travers le fédivers et affichez tout dans un ordre chronologique. Ni algorithmes, ni publicités, ni appâts à clics en perspective.",
"sign_in_banner.mastodon_is": "Mastodon est le meilleur moyen de suivre ce qui se passe.",
"sign_in_banner.sign_in": "Se connecter",
"sign_in_banner.sso_redirect": "Se connecter ou s’inscrire",
@@ -719,6 +776,7 @@
"status.bookmark": "Ajouter aux marque-pages",
"status.cancel_reblog_private": "Annuler le partage",
"status.cannot_reblog": "Ce message ne peut pas être partagé",
+ "status.continued_thread": "Suite du fil",
"status.copy": "Copier le lien vers le message",
"status.delete": "Supprimer",
"status.detailed_status": "Vue détaillée de la conversation",
@@ -727,7 +785,7 @@
"status.edit": "Modifier",
"status.edited": "Dernière modification le {date}",
"status.edited_x_times": "Modifié {count, plural, one {{count} fois} other {{count} fois}}",
- "status.embed": "Intégrer",
+ "status.embed": "Obtenir le code d'intégration",
"status.favourite": "Ajouter aux favoris",
"status.favourites": "{count, plural, one {favori} other {favoris}}",
"status.filter": "Filtrer ce message",
@@ -735,7 +793,7 @@
"status.history.edited": "modifié par {name} {date}",
"status.load_more": "Charger plus",
"status.media.open": "Cliquez pour ouvrir",
- "status.media.show": "Cliquez pour voir",
+ "status.media.show": "Cliquer pour afficher",
"status.media_hidden": "Média caché",
"status.mention": "Mentionner @{name}",
"status.more": "Plus",
@@ -752,6 +810,7 @@
"status.reblogs.empty": "Personne n’a encore partagé ce message. Lorsque quelqu’un le fera, il apparaîtra ici.",
"status.redraft": "Supprimer et réécrire",
"status.remove_bookmark": "Retirer des marque-pages",
+ "status.replied_in_thread": "A répondu dans un fil de discussion",
"status.replied_to": "En réponse à {name}",
"status.reply": "Répondre",
"status.replyAll": "Répondre au fil",
diff --git a/app/javascript/mastodon/locales/fy.json b/app/javascript/mastodon/locales/fy.json
index 0a985a0310..e7723c9533 100644
--- a/app/javascript/mastodon/locales/fy.json
+++ b/app/javascript/mastodon/locales/fy.json
@@ -11,6 +11,7 @@
"about.not_available": "Dizze ynformaasje is troch dizze server net iepenbier makke.",
"about.powered_by": "Desintralisearre sosjale media, mooglik makke troch {mastodon}",
"about.rules": "Serverrigels",
+ "account.account_note_header": "Persoanlike opmerking",
"account.add_or_remove_from_list": "Tafoegje oan of fuortsmite út listen",
"account.badges.bot": "Automatisearre",
"account.badges.group": "Groep",
@@ -96,6 +97,8 @@
"block_modal.title": "Brûker blokkearje?",
"block_modal.you_wont_see_mentions": "Jo sjogge gjin berjochten mear dy’t dizze account fermelde.",
"boost_modal.combo": "Jo kinne op {combo} drukke om dit de folgjende kear oer te slaan",
+ "boost_modal.reblog": "Berjocht booste?",
+ "boost_modal.undo_reblog": "Berjocht net langer booste?",
"bundle_column_error.copy_stacktrace": "Flaterrapport kopiearje",
"bundle_column_error.error.body": "De opfrege side koe net werjûn wurde. It kin wêze troch in flater yn ús koade, of in probleem mei browserkompatibiliteit.",
"bundle_column_error.error.title": "Oh nee!",
@@ -169,21 +172,30 @@
"confirmations.block.confirm": "Blokkearje",
"confirmations.delete.confirm": "Fuortsmite",
"confirmations.delete.message": "Binne jo wis dat jo dit berjocht fuortsmite wolle?",
+ "confirmations.delete.title": "Berjocht fuortsmite?",
"confirmations.delete_list.confirm": "Fuortsmite",
"confirmations.delete_list.message": "Binne jo wis dat jo dizze list foar permanint fuortsmite wolle?",
+ "confirmations.delete_list.title": "List fuortsmite?",
"confirmations.discard_edit_media.confirm": "Fuortsmite",
"confirmations.discard_edit_media.message": "Jo hawwe net-bewarre wizigingen yn de mediabeskriuwing of foarfertoaning, wolle jo dizze dochs fuortsmite?",
"confirmations.edit.confirm": "Bewurkje",
"confirmations.edit.message": "Troch no te bewurkjen sil it berjocht dat jo no oan it skriuwen binne oerskreaun wurde. Wolle jo trochgean?",
+ "confirmations.edit.title": "Berjocht oerskriuwe?",
"confirmations.logout.confirm": "Ofmelde",
"confirmations.logout.message": "Binne jo wis dat jo ôfmelde wolle?",
+ "confirmations.logout.title": "Ofmelde?",
"confirmations.mute.confirm": "Negearje",
"confirmations.redraft.confirm": "Fuortsmite en opnij opstelle",
"confirmations.redraft.message": "Binne jo wis dat jo dit berjocht fuortsmite en opnij opstelle wolle? Favoriten en boosts geane dan ferlern en reaksjes op it oarspronklike berjocht reitsje jo kwyt.",
+ "confirmations.redraft.title": "Berjocht fuortsmite en opnij opstelle?",
"confirmations.reply.confirm": "Reagearje",
"confirmations.reply.message": "Troch no te reagearjen sil it berjocht dat jo no oan it skriuwen binne oerskreaun wurde. Wolle jo trochgean?",
+ "confirmations.reply.title": "Berjocht oerskriuwe?",
"confirmations.unfollow.confirm": "Net mear folgje",
"confirmations.unfollow.message": "Binne jo wis dat jo {name} net mear folgje wolle?",
+ "confirmations.unfollow.title": "Brûker net mear folgje?",
+ "content_warning.hide": "Berjocht ferstopje",
+ "content_warning.show": "Dochs toane",
"conversation.delete": "Petear fuortsmite",
"conversation.mark_as_read": "As lêzen markearje",
"conversation.open": "Petear toane",
@@ -220,7 +232,9 @@
"domain_pill.username": "Brûkersnamme",
"domain_pill.whats_in_a_handle": "Wat is in fediverse-adres?",
"domain_pill.who_they_are": "Omdat jo oan in fediverse-adres sjen kinne hoe’t ien hjit en op hokker server dy sit, kinne jo mei minsken op it troch
ActivityPub oandreaune sosjale web (fediverse) kommunisearje.",
+ "domain_pill.who_you_are": "Omdat jo oan in fediverse-adres sjen kinne hoe’t jo hjitte en op hokker server jo sitte, kinne jo mei minsken op it troch
ActivityPub oandreaune sosjale web (fediverse) kommunisearje.",
"domain_pill.your_handle": "Jo fediverse-adres:",
+ "domain_pill.your_server": "Jo digitale thús, wer't al jo berjochten stean. Is dizze server dochs net nei jo winsk? Dan kinne jo op elk momint nei in oare server ferhúzje en ek jo folgers oerbringe.",
"domain_pill.your_username": "Jo unike identifikaasje-adres op dizze server. It is mooglik dat der brûkers mei deselde brûkersnamme op ferskate servers te finen binne.",
"embed.instructions": "Embed this status on your website by copying the code below.",
"embed.preview": "Sa komt it der út te sjen:",
@@ -258,6 +272,7 @@
"empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
"empty_column.lists": "Jo hawwe noch gjin inkelde list. Wannear’t jo der ien oanmakke hawwe, falt dat hjir te sjen.",
"empty_column.mutes": "Jo hawwe noch gjin brûkers negearre.",
+ "empty_column.notification_requests": "Hielendal leech! Der is hjir neat. Wannear’t jo nije meldingen ûntfange, ferskine dizze hjir neffens jo ynstellingen.",
"empty_column.notifications": "Jo hawwe noch gjin meldingen. Ynteraksjes mei oare minsken sjogge jo hjir.",
"empty_column.public": "Der is hjir neat! Skriuw eat publyklik, of folgje sels brûkers fan oare servers om it hjir te foljen",
"error.unexpected_crash.explanation": "Troch in bug in ús koade of in probleem mei de komptabiliteit fan jo browser, koe dizze side net toand wurde.",
@@ -288,6 +303,8 @@
"filter_modal.select_filter.subtitle": "In besteande kategory brûke of in nije oanmeitsje",
"filter_modal.select_filter.title": "Dit berjocht filterje",
"filter_modal.title.status": "In berjocht filterje",
+ "filter_warning.matches_filter": "Komt oerien mei filter ‘{title}’",
+ "filtered_notifications_banner.pending_requests": "Fan {count, plural, =0 {net ien} one {ien persoan} other {# persoanen}} dy’t jo mooglik kinne",
"filtered_notifications_banner.title": "Filtere meldingen",
"firehose.all": "Alles",
"firehose.local": "Dizze server",
@@ -336,6 +353,14 @@
"hashtag.follow": "Hashtag folgje",
"hashtag.unfollow": "Hashtag ûntfolgje",
"hashtags.and_other": "…en {count, plural, one {}other {# mear}}",
+ "hints.profiles.followers_may_be_missing": "Folgers foar dit profyl kinne ûntbrekke.",
+ "hints.profiles.follows_may_be_missing": "De folgers foar dit profyl kinne ûntbrekke.",
+ "hints.profiles.posts_may_be_missing": "Der ûntbrekke mooglik berjochten fan dit profyl.",
+ "hints.profiles.see_more_followers": "Besjoch mear folgers op {domain}",
+ "hints.profiles.see_more_follows": "Besjoch mear folge accounts op {domain}",
+ "hints.profiles.see_more_posts": "Besjoch mear berjochten op {domain}",
+ "hints.threads.replies_may_be_missing": "Antwurden fan oare servers kinne ûntbrekke.",
+ "hints.threads.see_more": "Besjoch mear reaksjes op {domain}",
"home.column_settings.show_reblogs": "Boosts toane",
"home.column_settings.show_replies": "Reaksjes toane",
"home.hide_announcements": "Meidielingen ferstopje",
@@ -343,6 +368,17 @@
"home.pending_critical_update.link": "Fernijingen besjen",
"home.pending_critical_update.title": "Kritike befeiligingsfernijing beskikber!",
"home.show_announcements": "Meidielingen toane",
+ "ignore_notifications_modal.disclaimer": "Mastodon kin brûkers net ynformearje dat jo harren meldingen negearre hawwe. Meldingen negearje sil net foarkomme dat de berjochten sels ferstjoerd wurde.",
+ "ignore_notifications_modal.filter_instead": "Yn stee derfan filterje",
+ "ignore_notifications_modal.filter_to_act_users": "Jo binne noch hieltyd yn steat om folchfersiken goed- of ôf te karren en om brûkers te rapportearjen",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "Filterjen foarkomt potinsjele betizing",
+ "ignore_notifications_modal.filter_to_review_separately": "Jo kinne filtere meldingen ôfsûnderlik beoardiele",
+ "ignore_notifications_modal.ignore": "Meldingen negearje",
+ "ignore_notifications_modal.limited_accounts_title": "Meldingen fan beheinde accounts negearje?",
+ "ignore_notifications_modal.new_accounts_title": "Meldingen fan nije accounts negearje?",
+ "ignore_notifications_modal.not_followers_title": "Meldingen negearje fan minsken dy’t jo net folgje?",
+ "ignore_notifications_modal.not_following_title": "Meldingen negearje fan minsken dy’t josels net folgje?",
+ "ignore_notifications_modal.private_mentions_title": "Meldingen negearje fan net frege priveeberjochten?",
"interaction_modal.description.favourite": "Jo kinne mei in Mastodon-account dit berjocht as favoryt markearje, om dy brûker witte te litten dat jo it berjocht wurdearje en om it te bewarjen.",
"interaction_modal.description.follow": "Jo kinne mei in Mastodon-account {name} folgje, om sa harren berjochten op jo starttiidline te ûntfangen.",
"interaction_modal.description.reblog": "Jo kinne mei in Mastodon-account dit berjocht booste, om it sa mei jo folgers te dielen.",
@@ -396,8 +432,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "Nei boppe yn list ferpleatse",
"lightbox.close": "Slute",
- "lightbox.compress": "Ofbylding passend werjaan",
- "lightbox.expand": "Ofbylding grut werjaan",
"lightbox.next": "Folgjende",
"lightbox.previous": "Foarige",
"limited_account_hint.action": "Profyl dochs besjen",
@@ -421,7 +455,6 @@
"lists.subheading": "Jo listen",
"load_pending": "{count, plural, one {# nij item} other {# nije items}}",
"loading_indicator.label": "Lade…",
- "media_gallery.toggle_visible": "{number, plural, one {ôfbylding ferstopje} other {ôfbyldingen ferstopje}}",
"moved_to_account_banner.text": "Omdat jo nei {movedToAccount} ferhuze binne is jo account {disabledAccount} op dit stuit útskeakele.",
"mute_modal.hide_from_notifications": "Meldingen ferstopje",
"mute_modal.hide_options": "Opsjes ferstopje",
@@ -433,6 +466,7 @@
"mute_modal.you_wont_see_mentions": "Jo sjogge gjin berjochten mear dy’t dizze account fermelde.",
"mute_modal.you_wont_see_posts": "De persoan kin jo berjochten noch hieltyd sjen, mar jo sjogge harren berjochten net mear.",
"navigation_bar.about": "Oer",
+ "navigation_bar.administration": "Behear",
"navigation_bar.advanced_interface": "Yn avansearre webomjouwing iepenje",
"navigation_bar.blocks": "Blokkearre brûkers",
"navigation_bar.bookmarks": "Blêdwizers",
@@ -449,6 +483,7 @@
"navigation_bar.follows_and_followers": "Folgers en folgjenden",
"navigation_bar.lists": "Listen",
"navigation_bar.logout": "Ofmelde",
+ "navigation_bar.moderation": "Moderaasje",
"navigation_bar.mutes": "Negearre brûkers",
"navigation_bar.opened_in_classic_interface": "Berjochten, accounts en oare spesifike siden, wurde standert iepene yn de klassike webinterface.",
"navigation_bar.personal": "Persoanlik",
@@ -464,9 +499,18 @@
"notification.admin.report_statuses": "{name} rapportearre {target} foar {category}",
"notification.admin.report_statuses_other": "{name} hat {target} rapportearre",
"notification.admin.sign_up": "{name} hat harren registrearre",
+ "notification.admin.sign_up.name_and_others": "{name} en {count, plural, one {# oar} other {# oaren}} hawwe harren registrearre",
"notification.favourite": "{name} hat jo berjocht as favoryt markearre",
+ "notification.favourite.name_and_others_with_link": "{name} en
{count, plural, one {# oar} other {# oaren}} hawwe jo berjocht as favoryt markearre",
"notification.follow": "{name} folget dy",
+ "notification.follow.name_and_others": "{name} en {count, plural, one {# oar} other {# oaren}} hawwe jo folge",
"notification.follow_request": "{name} hat dy in folchfersyk stjoerd",
+ "notification.follow_request.name_and_others": "{name} en {count, plural, one {# oar} other {# oaren}} hawwe frege om jo te folgjen",
+ "notification.label.mention": "Fermelding",
+ "notification.label.private_mention": "Priveeberjocht",
+ "notification.label.private_reply": "Priveereaksje",
+ "notification.label.reply": "Beäntwurdzje",
+ "notification.mention": "Fermelding",
"notification.moderation-warning.learn_more": "Mear ynfo",
"notification.moderation_warning": "Jo hawwe in moderaasje-warskôging ûntfongen",
"notification.moderation_warning.action_delete_statuses": "Guon fan jo berjochten binne fuortsmiten.",
@@ -479,23 +523,42 @@
"notification.own_poll": "Jo poll is beëinige",
"notification.poll": "In enkête dêr’t jo oan meidien hawwe is beëinige",
"notification.reblog": "{name} hat jo berjocht boost",
+ "notification.reblog.name_and_others_with_link": "{name} en
{count, plural, one {# oar} other {# oaren}} hawwe jo berjocht boost",
"notification.relationships_severance_event": "Ferlerne ferbiningen mei {name}",
"notification.relationships_severance_event.account_suspension": "In behearder fan {from} hat {target} útsteld, wat betsjut dat jo gjin updates mear fan harren ûntfange kinne of mei harren kommunisearje kinne.",
"notification.relationships_severance_event.domain_block": "In behearder fan {from} hat {target} blokkearre, ynklusyf {followersCount} fan jo folgers en {followingCount, plural, one {# account} other {# accounts}} dy’t jo folgje.",
"notification.relationships_severance_event.learn_more": "Mear ynfo",
+ "notification.relationships_severance_event.user_domain_block": "Jo hawwe {target} blokkearre, wêrmei’t jo {followersCount} fan jo folgers en {followingCount, plural, one {# account} other {# accounts}} dy’t jo folgje ferlern binne.",
"notification.status": "{name} hat in berjocht pleatst",
"notification.update": "{name} hat in berjocht bewurke",
"notification_requests.accept": "Akseptearje",
+ "notification_requests.accept_multiple": "{count, plural, one {# fersyk akseptearje…} other {# fersiken akseptearje…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Fersyk akseptearje} other {Fersiken akseptearje}}",
+ "notification_requests.confirm_accept_multiple.message": "Jo steane op it punt om {count, plural, one {ien meldingsfersyk} other {# meldingsfersiken}} te akseptearjen. Binne jo wis dat jo trochgean wolle?",
+ "notification_requests.confirm_accept_multiple.title": "Meldingsfersiken akseptearje?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Fersyk ôfwize} other {Fersiken ôfwize}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Jo steane op it punt om {count, plural, one {ien meldingsfersyk} other {# meldingsfersiken}} ôf te wizen. Jo sille net yn steat wêze om {count, plural, one {hier} other {hier}} wer maklik tagong ta te krijen. Wolle jo trochgean?",
+ "notification_requests.confirm_dismiss_multiple.title": "Meldingsfersiken ôfwize?",
"notification_requests.dismiss": "Ofwize",
+ "notification_requests.dismiss_multiple": "{count, plural, one {# fersyk ôfwize…} other {# fersiken ôfwize…}}",
+ "notification_requests.edit_selection": "Bewurkje",
+ "notification_requests.exit_selection": "Klear",
+ "notification_requests.explainer_for_limited_account": "Meldingen fan dizze account binne filtere, omdat dizze account troch in moderator beheind is.",
+ "notification_requests.explainer_for_limited_remote_account": "Meldingen fan dizze account binne filtere, omdat dizze account of harren server troch in moderator beheind is.",
+ "notification_requests.maximize": "Maksimalisearje",
+ "notification_requests.minimize_banner": "Banner mei filtere meldingen minimalisearje",
"notification_requests.notifications_from": "Meldingen fan {name}",
"notification_requests.title": "Filtere meldingen",
+ "notification_requests.view": "Meldingen besjen",
"notifications.clear": "Meldingen wiskje",
"notifications.clear_confirmation": "Binne jo wis dat jo al jo meldingen permanint fuortsmite wolle?",
+ "notifications.clear_title": "Meldingen fuortsmite?",
"notifications.column_settings.admin.report": "Nije rapportaazjes:",
"notifications.column_settings.admin.sign_up": "Nije registraasjes:",
"notifications.column_settings.alert": "Desktopmeldingen",
"notifications.column_settings.favourite": "Favoriten:",
"notifications.column_settings.filter_bar.advanced": "Alle kategoryen toane",
+ "notifications.column_settings.filter_bar.category": "Flugge filterbalke",
"notifications.column_settings.follow": "Nije folgers:",
"notifications.column_settings.follow_request": "Nij folchfersyk:",
"notifications.column_settings.mention": "Fermeldingen:",
@@ -521,6 +584,23 @@
"notifications.permission_denied": "Desktopmeldingen binne net beskikber, omdat in eardere browsertastimming wegere waard",
"notifications.permission_denied_alert": "Desktopmeldingen kinne net ynskeakele wurde, omdat in eardere browsertastimming wegere waard",
"notifications.permission_required": "Desktopmeldingen binne net beskikber, omdat de nedige tastimming net ferliend is.",
+ "notifications.policy.accept": "Akseptearje",
+ "notifications.policy.accept_hint": "Yn meldingen toane",
+ "notifications.policy.drop": "Negearje",
+ "notifications.policy.drop_hint": "Permanint fuortsmite",
+ "notifications.policy.filter": "Filter",
+ "notifications.policy.filter_hint": "Nei filtere ynboks foar meldingen ferstjoere",
+ "notifications.policy.filter_limited_accounts_hint": "Beheind troch servermoderatoren",
+ "notifications.policy.filter_limited_accounts_title": "Moderearre accounts",
+ "notifications.policy.filter_new_accounts.hint": "Yn de ôfrûne {days, plural, one {dei} other {# dagen}} registrearre",
+ "notifications.policy.filter_new_accounts_title": "Nije accounts",
+ "notifications.policy.filter_not_followers_hint": "Ynklusyf minsken dy’t jo koarter as {days, plural, one {dei} other {# dagen}} folgje",
+ "notifications.policy.filter_not_followers_title": "Minsken dy’t jo net folgje",
+ "notifications.policy.filter_not_following_hint": "Oant jo se hânmjittich goedkarre",
+ "notifications.policy.filter_not_following_title": "Minsken dy’t josels net folgje",
+ "notifications.policy.filter_private_mentions_hint": "Unsichtber útsein it in antwurd is op in priveeberjocht fan jo of wannear’t jo de ôfstjoerder folgje",
+ "notifications.policy.filter_private_mentions_title": "Net frege priveeberjochten",
+ "notifications.policy.title": "Meldingen beheare fan…",
"notifications_permission_banner.enable": "Desktopmeldingen ynskeakelje",
"notifications_permission_banner.how_to_control": "Om meldingen te ûntfangen wannear’t Mastodon net iepen stiet. Jo kinne krekt bepale hokker soarte fan ynteraksjes wol of gjin desktopmeldingen jouwe fia de boppesteande {icon} knop.",
"notifications_permission_banner.title": "Mis neat",
@@ -647,6 +727,7 @@
"report.unfollow_explanation": "Jo folgje dizze account. Om harren berjochten net mear op jo starttiidline te sjen, kinne jo dyjinge ûntfolgje.",
"report_notification.attached_statuses": "{count, plural, one {{count} berjocht} other {{count} berjochten}} tafoege",
"report_notification.categories.legal": "Juridysk",
+ "report_notification.categories.legal_sentence": "yllegale ynhâld",
"report_notification.categories.other": "Oars",
"report_notification.categories.other_sentence": "oars",
"report_notification.categories.spam": "Spam",
@@ -680,8 +761,11 @@
"server_banner.about_active_users": "Oantal brûkers yn de ôfrûne 30 dagen (MAU)",
"server_banner.active_users": "warbere brûkers",
"server_banner.administered_by": "Beheard troch:",
+ "server_banner.is_one_of_many": "{domain} is ien fan de protte ôfhinklike Mastodon-servers dy’t jo brûke kinne om diel te nimmen oan de fediverse.",
"server_banner.server_stats": "Serverstatistiken:",
"sign_in_banner.create_account": "Account registrearje",
+ "sign_in_banner.follow_anyone": "Folgje elkenien yn de fediverse en sjoch it allegearre yn gronologyske folchoarder. Gjin algoritmen, advertinsjes of clickbaits.",
+ "sign_in_banner.mastodon_is": "Mastodon is de beste manier om wat der bart by te hâlden.",
"sign_in_banner.sign_in": "Oanmelde",
"sign_in_banner.sso_redirect": "Oanmelde of Registrearje",
"status.admin_account": "Moderaasje-omjouwing fan @{name} iepenje",
@@ -699,7 +783,6 @@
"status.edit": "Bewurkje",
"status.edited": "Lêst bywurke op {date}",
"status.edited_x_times": "{count, plural, one {{count} kear} other {{count} kearen}} bewurke",
- "status.embed": "Ynslute",
"status.favourite": "Favoryt",
"status.favourites": "{count, plural, one {favoryt} other {favoriten}}",
"status.filter": "Dit berjocht filterje",
diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json
index 4407616499..e05adc2732 100644
--- a/app/javascript/mastodon/locales/ga.json
+++ b/app/javascript/mastodon/locales/ga.json
@@ -97,6 +97,8 @@
"block_modal.title": "An bhfuil fonn ort an t-úsáideoir a bhlocáil?",
"block_modal.you_wont_see_mentions": "Ní fheicfidh tú postálacha a luann iad.",
"boost_modal.combo": "Is féidir leat {combo} a bhrú chun é seo a scipeáil an chéad uair eile",
+ "boost_modal.reblog": "An post a threisiú?",
+ "boost_modal.undo_reblog": "An deireadh a chur le postáil?",
"bundle_column_error.copy_stacktrace": "Cóipeáil tuairisc earráide",
"bundle_column_error.error.body": "Ní féidir an leathanach a iarradh a sholáthar. Seans gurb amhlaidh mar gheall ar fhabht sa chód, nó mar gheall ar mhíréireacht leis an mbrabhsálaí.",
"bundle_column_error.error.title": "Ó, níl sé sin go maith!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Ná lean",
"confirmations.unfollow.message": "An bhfuil tú cinnte gur mhaith leat {name} a dhíleanúint?",
"confirmations.unfollow.title": "Dílean an t-úsáideoir?",
+ "content_warning.hide": "Folaigh postáil",
+ "content_warning.show": "Taispeáin ar aon nós",
"conversation.delete": "Scrios comhrá",
"conversation.mark_as_read": "Marcáil mar léite",
"conversation.open": "Féach ar comhrá",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Bain úsáid as catagóir reatha nó cruthaigh ceann nua",
"filter_modal.select_filter.title": "Déan scagadh ar an bpostáil seo",
"filter_modal.title.status": "Déan scagadh ar phostáil",
+ "filter_warning.matches_filter": "Meaitseálann an scagaire “{title}”",
"filtered_notifications_banner.pending_requests": "Ó {count, plural, =0 {duine ar bith} one {duine amháin} two {# daoine} few {# daoine} many {# daoine} other {# daoine}} b’fhéidir go bhfuil aithne agat orthu",
"filtered_notifications_banner.title": "Fógraí scagtha",
"firehose.all": "Gach",
@@ -348,6 +353,14 @@
"hashtag.follow": "Lean haischlib",
"hashtag.unfollow": "Ná lean haischlib",
"hashtags.and_other": "agus {count, plural, one {} two {# níos} few {# níos} many {# níos} other {# níos}}",
+ "hints.profiles.followers_may_be_missing": "Seans go bhfuil leantóirí don phróifíl seo in easnamh.",
+ "hints.profiles.follows_may_be_missing": "Seans go bhfuil na nithe seo a leanas in easnamh ar an bpróifíl seo.",
+ "hints.profiles.posts_may_be_missing": "Seans go bhfuil roinnt postálacha ón bpróifíl seo in easnamh.",
+ "hints.profiles.see_more_followers": "Féach ar a thuilleadh leantóirí ar {domain}",
+ "hints.profiles.see_more_follows": "Féach tuilleadh seo a leanas ar {domain}",
+ "hints.profiles.see_more_posts": "Féach ar a thuilleadh postálacha ar {domain}",
+ "hints.threads.replies_may_be_missing": "Seans go bhfuil freagraí ó fhreastalaithe eile in easnamh.",
+ "hints.threads.see_more": "Féach ar a thuilleadh freagraí ar {domain}",
"home.column_settings.show_reblogs": "Taispeáin moltaí",
"home.column_settings.show_replies": "Taispeán freagraí",
"home.hide_announcements": "Cuir fógraí i bhfolach",
@@ -419,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Unfocus cum textarea/search",
"keyboard_shortcuts.up": "Bog suas ar an liosta",
"lightbox.close": "Dún",
- "lightbox.compress": "Comhbhrúigh an bosca amhairc íomhá",
- "lightbox.expand": "Leathnaigh an bosca amhairc íomhá",
"lightbox.next": "An céad eile",
"lightbox.previous": "Roimhe seo",
+ "lightbox.zoom_in": "Súmáil chuig an méid iarbhír",
+ "lightbox.zoom_out": "Súmáil a d'oirfeadh",
"limited_account_hint.action": "Taispeáin an phróifíl ar aon nós",
"limited_account_hint.title": "Tá an phróifíl seo curtha i bhfolach ag na modhnóra {domain}.",
"link_preview.author": "Le {name}",
@@ -444,7 +457,7 @@
"lists.subheading": "Do liostaí",
"load_pending": "{count, plural, one {# mír nua} two {# mír nua} few {# mír nua} many {# mír nua} other {# mír nua}}",
"loading_indicator.label": "Á lódáil…",
- "media_gallery.toggle_visible": "{number, plural, one {Folaigh íomhá} two {Folaigh íomhánna} few {Folaigh íomhánna} many {Folaigh íomhánna} other {Folaigh íomhánna}}",
+ "media_gallery.hide": "Folaigh",
"moved_to_account_banner.text": "Tá do chuntas {disabledAccount} díchumasaithe faoi láthair toisc gur bhog tú go {movedToAccount}.",
"mute_modal.hide_from_notifications": "Folaigh ó fhógraí",
"mute_modal.hide_options": "Folaigh roghanna",
@@ -456,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Ní fheicfidh tú postálacha a luann iad.",
"mute_modal.you_wont_see_posts": "Is féidir leo do phoist a fheiceáil go fóill, ach ní fheicfidh tú a gcuid postanna.",
"navigation_bar.about": "Maidir le",
+ "navigation_bar.administration": "Riarachán",
"navigation_bar.advanced_interface": "Oscail i gcomhéadan gréasáin chun cinn",
"navigation_bar.blocks": "Cuntais bhactha",
"navigation_bar.bookmarks": "Leabharmharcanna",
@@ -472,6 +486,7 @@
"navigation_bar.follows_and_followers": "Ag leanúint agus do do leanúint",
"navigation_bar.lists": "Liostaí",
"navigation_bar.logout": "Logáil Amach",
+ "navigation_bar.moderation": "Measarthacht",
"navigation_bar.mutes": "Úsáideoirí balbhaithe",
"navigation_bar.opened_in_classic_interface": "Osclaítear poist, cuntais agus leathanaigh shonracha eile de réir réamhshocraithe sa chomhéadan gréasáin clasaiceach.",
"navigation_bar.personal": "Pearsanta",
@@ -487,9 +502,13 @@
"notification.admin.report_statuses": "Thuairiscigh {name} {target} le haghaidh {category}",
"notification.admin.report_statuses_other": "{name} tuairiscithe {target}",
"notification.admin.sign_up": "Chláraigh {name}",
+ "notification.admin.sign_up.name_and_others": "{name} agus {count, plural, one {# duine eile} two {# daoine eile} few {# daoine eile} many {# daoine eile} other {# daoine eile}} a chláraigh",
"notification.favourite": "Is fearr le {name} do phostáil",
+ "notification.favourite.name_and_others_with_link": "{name} agus
{count, plural, one {# duine eile} other {# daoine eile}} thaitin le do phost",
"notification.follow": "Lean {name} thú",
+ "notification.follow.name_and_others": "{name} agus {count, plural, one {# duine eile} other {# daoine eile}} a lean tú",
"notification.follow_request": "D'iarr {name} ort do chuntas a leanúint",
+ "notification.follow_request.name_and_others": "{name} agus {count, plural, one {# duine eile} other {# daoine eile}} iarratas a dhéanamh chun tú a leanúint",
"notification.label.mention": "Luaigh",
"notification.label.private_mention": "Lua príobháideach",
"notification.label.private_reply": "Freagra príobháideach",
@@ -507,6 +526,7 @@
"notification.own_poll": "Tá do suirbhé críochnaithe",
"notification.poll": "Tá deireadh le vótaíocht inar vótáil tú",
"notification.reblog": "Mhol {name} do phostáil",
+ "notification.reblog.name_and_others_with_link": "{name} agus
{count, plural, one {# duine eile} other {# daoine eile}} a chuir borradh faoi do phost",
"notification.relationships_severance_event": "Cailleadh naisc le {name}",
"notification.relationships_severance_event.account_suspension": "Chuir riarthóir ó {from} {target} ar fionraí, rud a chiallaíonn nach féidir leat nuashonruithe a fháil uathu a thuilleadh ná idirghníomhú leo.",
"notification.relationships_severance_event.domain_block": "Chuir riarthóir ó {from} bac ar {target}, lena n-áirítear {followersCount} de do leantóirí agus {followingCount, plural, one {#cuntas} other {#cuntas}} leanann tú.",
@@ -515,7 +535,17 @@
"notification.status": "Phostáil {name} díreach",
"notification.update": "Chuir {name} postáil in eagar",
"notification_requests.accept": "Glac",
+ "notification_requests.accept_multiple": "{count, plural, one {Glac le # iarratas…} other {Glac le # iarratais…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Glac le hIarratas} other {Glac le hIarratais}}",
+ "notification_requests.confirm_accept_multiple.message": "Tá tú ar tí glacadh le {count, plural, one {iarratas fógra amháin} other {# iarratas fógra}}. An bhfuil tú cinnte gur mian leat leanúint ar aghaidh?",
+ "notification_requests.confirm_accept_multiple.title": "Glac le hiarratais ar fhógra?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Dún iarratas} other {Dún iarratais}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Tá tú ar tí iarratas fógra {count, plural, one {a hAon} other {#}} a dhúnadh. Ní bheidh tú in ann {count, plural, one {é} other {iad}} a fháil go héasca arís. An bhfuil tú cinnte gur mian leat leanúint ar aghaidh?",
+ "notification_requests.confirm_dismiss_multiple.title": "An bhfuil fonn ort iarratais ar fhógra a dhíbhe?",
"notification_requests.dismiss": "Díbhe",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Dún # iarratas…} other {Dún # iarratais…}}",
+ "notification_requests.edit_selection": "Cuir in eagar",
+ "notification_requests.exit_selection": "Déanta",
"notification_requests.explainer_for_limited_account": "Scagadh fógraí ón gcuntas seo toisc go bhfuil an cuntas teoranta ag modhnóir.",
"notification_requests.explainer_for_limited_remote_account": "Scagadh fógraí ón gcuntas seo toisc go bhfuil an cuntas nó a fhreastalaí teoranta ag modhnóir.",
"notification_requests.maximize": "Uasmhéadaigh",
@@ -529,8 +559,6 @@
"notifications.column_settings.admin.report": "Tuairiscí nua:",
"notifications.column_settings.admin.sign_up": "Clárúcháin nua:",
"notifications.column_settings.alert": "Fógraí deisce",
- "notifications.column_settings.beta.category": "Gnéithe turgnamhacha",
- "notifications.column_settings.beta.grouping": "Fógraí grúpa",
"notifications.column_settings.favourite": "Ceanáin:",
"notifications.column_settings.filter_bar.advanced": "Taispeáin gach catagóir",
"notifications.column_settings.filter_bar.category": "Barra scagairí tapa",
@@ -750,6 +778,7 @@
"status.bookmark": "Leabharmharcanna",
"status.cancel_reblog_private": "Dímhol",
"status.cannot_reblog": "Ní féidir an phostáil seo a mholadh",
+ "status.continued_thread": "Snáithe ar lean",
"status.copy": "Cóipeáil an nasc chuig an bpostáil",
"status.delete": "Scrios",
"status.detailed_status": "Amharc comhrá mionsonraithe",
@@ -758,7 +787,7 @@
"status.edit": "Cuir in eagar",
"status.edited": "Arna chuir in eagar anuas {date}",
"status.edited_x_times": "Curtha in eagar {count, plural, one {{count} uair amháin} two {{count} uair} few {{count} uair} many {{count} uair} other {{count} uair}}",
- "status.embed": "Leabaigh",
+ "status.embed": "Faigh cód leabú",
"status.favourite": "Is fearr leat",
"status.favourites": "{count, plural, one {a bhfuil grá agat do} two {gráite} few {gráite} many {gráite} other {gráite}}",
"status.filter": "Déan scagadh ar an bpostáil seo",
@@ -783,6 +812,7 @@
"status.reblogs.empty": "Níor mhol éinne an phostáil seo fós. Nuair a mholfaidh duine éigin í, taispeánfar anseo é sin.",
"status.redraft": "Scrios ⁊ athdhréachtaigh",
"status.remove_bookmark": "Bain leabharmharc",
+ "status.replied_in_thread": "D'fhreagair sa snáithe",
"status.replied_to": "D'fhreagair {name}",
"status.reply": "Freagair",
"status.replyAll": "Freagair le snáithe",
diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json
index 8e6260b00f..8f51d43ef8 100644
--- a/app/javascript/mastodon/locales/gd.json
+++ b/app/javascript/mastodon/locales/gd.json
@@ -36,7 +36,7 @@
"account.followers.empty": "Chan eil neach sam bith a’ leantainn air a’ chleachdaiche seo fhathast.",
"account.followers_counter": "{count, plural, one {{counter} neach-leantainn} other {{counter} luchd-leantainn}}",
"account.following": "A’ leantainn",
- "account.following_counter": "{count, plural, one {Tha {counter} a’ leantainn} other {Tha {counter} a’ leantainn}}",
+ "account.following_counter": "{count, plural, one {A’ leantainn {counter}} other {A’ leantainn {counter}}}",
"account.follows.empty": "Chan eil an cleachdaiche seo a’ leantainn neach sam bith fhathast.",
"account.go_to_profile": "Tadhail air a’ phròifil",
"account.hide_reblogs": "Falaich na brosnachaidhean o @{name}",
@@ -97,6 +97,8 @@
"block_modal.title": "A bheil thu airson an cleachdaiche a bhacadh?",
"block_modal.you_wont_see_mentions": "Chan fhaic thu na postaichean a bheir iomradh orra.",
"boost_modal.combo": "Brùth air {combo} nam b’ fheàrr leat leum a ghearradh thar seo an ath-thuras",
+ "boost_modal.reblog": "A bheil thu airson am post a bhrosnachadh?",
+ "boost_modal.undo_reblog": "A bheil thu airson sgur de bhrosnachadh a’ phuist?",
"bundle_column_error.copy_stacktrace": "Dèan lethbhreac de aithris na mearachd",
"bundle_column_error.error.body": "Cha b’ urrainn dhuinn an duilleag a dh’iarr thu a reandaradh. Dh’fhaoidte gu bheil buga sa chòd againn no duilgheadas co-chòrdalachd leis a’ bhrabhsair.",
"bundle_column_error.error.title": "Ìoc!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Na lean tuilleadh",
"confirmations.unfollow.message": "A bheil thu cinnteach nach eil thu airson {name} a leantainn tuilleadh?",
"confirmations.unfollow.title": "A bheil thu airson sgur de leantainn a chleachdaiche?",
+ "content_warning.hide": "Falaich am post",
+ "content_warning.show": "Seall e co-dhiù",
"conversation.delete": "Sguab às an còmhradh",
"conversation.mark_as_read": "Cuir comharra gun deach a leughadh",
"conversation.open": "Seall an còmhradh",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Cleachd roinn-seòrsa a tha ann no cruthaich tè ùr",
"filter_modal.select_filter.title": "Criathraich am post seo",
"filter_modal.title.status": "Criathraich post",
+ "filter_warning.matches_filter": "A’ maidseadh na criathraige “{title}”",
"filtered_notifications_banner.pending_requests": "{count, plural, =0 {Chan eil gin ann} one {O # neach} two {O # neach} few {O # daoine} other {O # duine}} air a bheil thu eòlach ’s dòcha",
"filtered_notifications_banner.title": "Brathan criathraichte",
"firehose.all": "Na h-uile",
@@ -348,6 +353,14 @@
"hashtag.follow": "Lean an taga hais",
"hashtag.unfollow": "Na lean an taga hais tuilleadh",
"hashtags.and_other": "…agus {count, plural, one {# eile} two {# eile} few {# eile} other {# eile}}",
+ "hints.profiles.followers_may_be_missing": "Dh’fhaoidte gu bheil cuid dhen luchd-leantainn na pròifil seo a dhìth.",
+ "hints.profiles.follows_may_be_missing": "Dh’fhaoidte gu bheil cuid a tha a’ phròifil seo a’ leantainn a dhìth.",
+ "hints.profiles.posts_may_be_missing": "Dh’fhaoide gu bheil cuid dhe na postaichean aig a’ phròifil seo a dhìth.",
+ "hints.profiles.see_more_followers": "Faic barrachd luchd-leantainn air {domain}",
+ "hints.profiles.see_more_follows": "Faic barrachd a tha 'gan leantainn air {domain}",
+ "hints.profiles.see_more_posts": "Faic barrachd phostaichean air {domain}",
+ "hints.threads.replies_may_be_missing": "Dh’fhaoidte gu bheil freagairtean o fhrithealaichean eile a dhìth.",
+ "hints.threads.see_more": "Faic barrachd fhreagairtean air {domain}",
"home.column_settings.show_reblogs": "Seall na brosnachaidhean",
"home.column_settings.show_replies": "Seall na freagairtean",
"home.hide_announcements": "Falaich na brathan-fios",
@@ -419,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Thoir am fòcas far raon teacsa an sgrìobhaidh/an luirg",
"keyboard_shortcuts.up": "Gluais suas air an liosta",
"lightbox.close": "Dùin",
- "lightbox.compress": "Co-theannaich bogsa sealladh an deilbh",
- "lightbox.expand": "Leudaich bogsa sealladh an deilbh",
"lightbox.next": "Air adhart",
"lightbox.previous": "Air ais",
+ "lightbox.zoom_in": "Sùm dhan fhìor-mheud",
+ "lightbox.zoom_out": "Sùm fèin-obrachail",
"limited_account_hint.action": "Seall a’ phròifil co-dhiù",
"limited_account_hint.title": "Chaidh a’ phròifil seo fhalach le maoir {domain}.",
"link_preview.author": "Le {name}",
@@ -444,7 +457,7 @@
"lists.subheading": "Na liostaichean agad",
"load_pending": "{count, plural, one {# nì ùr} two {# nì ùr} few {# nithean ùra} other {# nì ùr}}",
"loading_indicator.label": "’Ga luchdadh…",
- "media_gallery.toggle_visible": "{number, plural, 1 {Falaich an dealbh} one {Falaich na dealbhan} two {Falaich na dealbhan} few {Falaich na dealbhan} other {Falaich na dealbhan}}",
+ "media_gallery.hide": "Falaich",
"moved_to_account_banner.text": "Tha an cunntas {disabledAccount} agad à comas on a rinn thu imrich gu {movedToAccount}.",
"mute_modal.hide_from_notifications": "Falaich o na brathan",
"mute_modal.hide_options": "Roghainnean falaich",
@@ -456,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Chan fhaic thu na postaichean a bheir iomradh orra.",
"mute_modal.you_wont_see_posts": "Chì iad na postaichean agad fhathast ach chan fhaic thu na postaichean aca-san.",
"navigation_bar.about": "Mu dhèidhinn",
+ "navigation_bar.administration": "Rianachd",
"navigation_bar.advanced_interface": "Fosgail san eadar-aghaidh-lìn adhartach",
"navigation_bar.blocks": "Cleachdaichean bacte",
"navigation_bar.bookmarks": "Comharran-lìn",
@@ -472,6 +486,7 @@
"navigation_bar.follows_and_followers": "Dàimhean leantainn",
"navigation_bar.lists": "Liostaichean",
"navigation_bar.logout": "Clàraich a-mach",
+ "navigation_bar.moderation": "Maorsainneachd",
"navigation_bar.mutes": "Cleachdaichean mùchte",
"navigation_bar.opened_in_classic_interface": "Thèid postaichean, cunntasan ’s duilleagan sònraichte eile fhosgladh san eadar-aghaidh-lìn chlasaigeach a ghnàth.",
"navigation_bar.personal": "Pearsanta",
@@ -487,9 +502,13 @@
"notification.admin.report_statuses": "Rinn {name} gearan mu {target} air adhbhar {category}",
"notification.admin.report_statuses_other": "Rinn {name} gearan mu {target}",
"notification.admin.sign_up": "Chlàraich {name}",
+ "notification.admin.sign_up.name_and_others": "Chlàraich {name} ’s {count, plural, one {# eile} two {# eile} few {# eile} other {# eile}}",
"notification.favourite": "Is annsa le {name} am post agad",
+ "notification.favourite.name_and_others_with_link": "Is annsa le {name} ’s
{count, plural, one {# eile} two {# eile} few {# eile} other {# eile}} am post agad",
"notification.follow": "Tha {name} ’gad leantainn a-nis",
+ "notification.follow.name_and_others": "Lean {name} ’s {count, plural, one {# eile} two {# eile} few {# eile} other {# eile}} thu",
"notification.follow_request": "Dh’iarr {name} ’gad leantainn",
+ "notification.follow_request.name_and_others": "Dh’iarr {name} ’s {count, plural, one {# eile} two {# eile} few {# eile} other {# eile}} ’gad leantainn",
"notification.label.mention": "Iomradh",
"notification.label.private_mention": "Iomradh prìobhaideach",
"notification.label.private_reply": "Freagairt phrìobhaideach",
@@ -507,6 +526,7 @@
"notification.own_poll": "Thàinig an cunntas-bheachd agad gu crìoch",
"notification.poll": "Thàinig cunntas-bheachd sa bhòt thu gu crìoch",
"notification.reblog": "Bhrosnaich {name} am post agad",
+ "notification.reblog.name_and_others_with_link": "Bhrosnaich {name} ’s
{count, plural, one {# eile} two {# eile} few {# eile} other {# eile}} am post agad",
"notification.relationships_severance_event": "Chaill thu dàimhean le {name}",
"notification.relationships_severance_event.account_suspension": "Chuir rianaire aig {from} {target} à rèim agus is ciall dha sin nach fhaigh thu naidheachdan uapa ’s nach urrainn dhut conaltradh leotha.",
"notification.relationships_severance_event.domain_block": "Bhac rianaire aig {from} {target}, a’ gabhail a-staigh {followersCount} dhen luchd-leantainn agad agus {followingCount, plural, one {# chunntas} two {# chunntas} few {# cunntasan} other {# cunntas}} a tha thu fhèin a’ leantainn.",
@@ -515,7 +535,17 @@
"notification.status": "Phostaich {name} rud",
"notification.update": "Dheasaich {name} post",
"notification_requests.accept": "Gabh ris",
+ "notification_requests.accept_multiple": "{count, plural, one {Gabh ri # iarrtas…} two {Gabh ri # iarrtas…} few {Gabh ri # iarrtasan…} other {Gabh ri # iarrtas…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Gabh ris an t-iarrtas} two {Gabh ris na h-iarrtasan} few {Gabh ris na h-iarrtasan} other {Gabh ris na h-iarrtasan}}",
+ "notification_requests.confirm_accept_multiple.message": "Tha thu gu bhith gabhail ri {count, plural, one {# iarrtas bratha} two {# iarrtas bratha} few {# iarrtasan bratha} other {# iarrtas bratha}} a leigeil seachad. A bheil thu cinnteach gu bheil thu airson leantainn air adhart?",
+ "notification_requests.confirm_accept_multiple.title": "A bheil thu airson gabhail ri iarrtasan bratha?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Leig seachad an t-iarrtas} two {Leig seachad na h-iarrtasan} few {Leig seachad na h-iarrtasan} other {Leig seachad na h-iarrtasan}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Tha thu gu bhith {count, plural, one {# iarrtas bratha} two {# iarrtas bratha} few {# iarrtasan bratha} other {# iarrtas bratha}} a leigeil seachad. Chan fhaigh thu grèim {count, plural, one {air} two {orra} few {orra} other {orra}} a-rithist gun duilgheadas. A bheil thu cinnteach gu bheil thu airson leantainn air adhart?",
+ "notification_requests.confirm_dismiss_multiple.title": "A bheil thu airson iarrtasan bratha a leigeil seachad?",
"notification_requests.dismiss": "Leig seachad",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Leig seachad # iarrtas…} two {Leig seachad # iarrtas…} few {Leig seachad # iarrtasan…} other {Leig seachad # iarrtas…}}",
+ "notification_requests.edit_selection": "Deasaich",
+ "notification_requests.exit_selection": "Deiseil",
"notification_requests.explainer_for_limited_account": "Chaidh na brathan on chunntas seo a chriathradh on a chaidh an cunntas a chuingeachadh le maor.",
"notification_requests.explainer_for_limited_remote_account": "Chaidh na brathan on chunntas seo a chriathradh on a chaidh an cunntas no am frithealaiche aige a chuingeachadh le maor.",
"notification_requests.maximize": "Làn-mheudaich",
@@ -529,8 +559,6 @@
"notifications.column_settings.admin.report": "Gearanan ùra:",
"notifications.column_settings.admin.sign_up": "Clàraidhean ùra:",
"notifications.column_settings.alert": "Brathan deasga",
- "notifications.column_settings.beta.category": "Gleusan deuchainneil",
- "notifications.column_settings.beta.grouping": "Buidhnich na brathan",
"notifications.column_settings.favourite": "Annsachdan:",
"notifications.column_settings.filter_bar.advanced": "Seall a h-uile roinn-seòrsa",
"notifications.column_settings.filter_bar.category": "Bàr-criathraidh luath",
@@ -569,7 +597,7 @@
"notifications.policy.filter_limited_accounts_title": "Cunntasan fo mhaorsainneachd",
"notifications.policy.filter_new_accounts.hint": "A chaidh a chruthachadh o chionn {days, plural, one {# latha} two {# latha} few {# làithean} other {# latha}}",
"notifications.policy.filter_new_accounts_title": "Cunntasan ùra",
- "notifications.policy.filter_not_followers_hint": "A’ gabhail a-staigh an fheadhainn a lean ort nas lugha na {days, plural, one {# latha} two {# latha} few {# làithean} other {# latha}} seo chaidh",
+ "notifications.policy.filter_not_followers_hint": "A’ gabhail a-staigh an fheadhainn a lean thu nas lugha na {days, plural, one {# latha} two {# latha} few {# làithean} other {# latha}} seo chaidh",
"notifications.policy.filter_not_followers_title": "Daoine nach eil gad leantainn",
"notifications.policy.filter_not_following_hint": "Gus an aontaich thu riutha a làimh",
"notifications.policy.filter_not_following_title": "Daoine nach eil thu a’ leantainn",
@@ -750,6 +778,7 @@
"status.bookmark": "Cuir ris na comharran-lìn",
"status.cancel_reblog_private": "Na brosnaich tuilleadh",
"status.cannot_reblog": "Cha ghabh am post seo brosnachadh",
+ "status.continued_thread": "Pàirt de shnàithlean",
"status.copy": "Dèan lethbhreac dhen cheangal dhan phost",
"status.delete": "Sguab às",
"status.detailed_status": "Mion-shealladh a’ chòmhraidh",
@@ -758,7 +787,7 @@
"status.edit": "Deasaich",
"status.edited": "An deasachadh mu dheireadh {date}",
"status.edited_x_times": "Chaidh a dheasachadh {count, plural, one {{count} turas} two {{count} thuras} few {{count} tursan} other {{count} turas}}",
- "status.embed": "Leabaich",
+ "status.embed": "Faigh còd leabachaidh",
"status.favourite": "Cuir ris na h-annsachdan",
"status.favourites": "{count, plural, one {annsachd} two {annsachd} few {annsachdan} other {annsachd}}",
"status.filter": "Criathraich am post seo",
@@ -783,6 +812,7 @@
"status.reblogs.empty": "Chan deach am post seo a bhrosnachadh le duine sam bith fhathast. Nuair a bhrosnaicheas cuideigin e, nochdaidh iad an-seo.",
"status.redraft": "Sguab às ⁊ dèan dreachd ùr",
"status.remove_bookmark": "Thoir an comharra-lìn air falbh",
+ "status.replied_in_thread": "Freagairt do shnàithlean",
"status.replied_to": "Air {name} fhreagairt",
"status.reply": "Freagair",
"status.replyAll": "Freagair dhan t-snàithlean",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index 9da7438da6..f2ea6ee900 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -97,6 +97,8 @@
"block_modal.title": "Bloquear usuaria?",
"block_modal.you_wont_see_mentions": "Non verás publicacións que a mencionen.",
"boost_modal.combo": "Preme {combo} para ignorar isto na seguinte vez",
+ "boost_modal.reblog": "Promover publicación?",
+ "boost_modal.undo_reblog": "Retirar promoción?",
"bundle_column_error.copy_stacktrace": "Copiar informe do erro",
"bundle_column_error.error.body": "Non se puido mostrar a páxina solicitada. Podería deberse a un problema no código, ou incompatiblidade co navegador.",
"bundle_column_error.error.title": "Vaites!",
@@ -221,7 +223,7 @@
"domain_block_modal.title": "Bloquear dominio?",
"domain_block_modal.you_will_lose_followers": "Vanse eliminar todas as túas seguidoras deste servidor.",
"domain_block_modal.you_wont_see_posts": "Non verás publicacións ou notificacións das usuarias deste servidor.",
- "domain_pill.activitypub_lets_connect": "Permíteche conectar e interactuar con persoas non só de Mastodon, se non tamén con outras apps sociais.",
+ "domain_pill.activitypub_lets_connect": "Permíteche conectar e interactuar con persoas non só de Mastodon, se non tamén con outras sociais.",
"domain_pill.activitypub_like_language": "ActivityPub é algo así como o idioma que Mastodon fala con outras redes sociais.",
"domain_pill.server": "Servidor",
"domain_pill.their_handle": "O seu alcume:",
@@ -229,13 +231,13 @@
"domain_pill.their_username": "O seu identificador único no seu servidor. É posible atopar usuarias co mesmo nome de usuaria en diferentes servidores.",
"domain_pill.username": "Nome de usuaria",
"domain_pill.whats_in_a_handle": "As partes do alcume?",
- "domain_pill.who_they_are": "O alcume dinos quen é esa persoa e onde está, para que poidas interactuar con ela en toda a web social de
plataformas ActivityPub.",
- "domain_pill.who_you_are": "Como o teu alcume informa de quen es e onde estás, as persoas poden interactuar contigo desde toda a web social de
plataformas ActivityPub.",
+ "domain_pill.who_they_are": "O alcume dinos quen é esa persoa e onde está, para que poidas interactuar con ela en toda a web social das
plataformas ActivityPub.",
+ "domain_pill.who_you_are": "Como o teu alcume informa de quen es e onde estás, as persoas poden interactuar contigo desde toda a web social das
plataformas ActivityPub.",
"domain_pill.your_handle": "O teu alcume:",
"domain_pill.your_server": "O teu fogar dixital, onde están as túas publicacións. Non é do teu agrado? Podes cambiar de servidor cando queiras levando as túas seguidoras contigo.",
"domain_pill.your_username": "O teu identificador único neste servidor. É posible que atopes usuarias co mesmo nome de usuaria en outros servidores.",
- "embed.instructions": "Engade esta publicación ó teu sitio web copiando o seguinte código.",
- "embed.preview": "Así será mostrado:",
+ "embed.instructions": "Inclúe esta publicación no teu sitio web copiando o seguinte código.",
+ "embed.preview": "Vaise ver así:",
"emoji_button.activity": "Actividade",
"emoji_button.clear": "Limpar",
"emoji_button.custom": "Personalizado",
@@ -270,7 +272,7 @@
"empty_column.list": "Aínda non hai nada nesta listaxe. Cando as usuarias incluídas na listaxe publiquen mensaxes, amosaranse aquí.",
"empty_column.lists": "Aínda non tes listaxes. Cando crees unha, amosarase aquí.",
"empty_column.mutes": "Aínda non silenciaches a ningúnha usuaria.",
- "empty_column.notification_requests": "Todo ben! Nada por aquí. Cando recibas novas notificación aparecerán aquí seguindo o criterio dos teus axustes.",
+ "empty_column.notification_requests": "Todo ben! Nada por aquí. Cando recibas novas notificacións aparecerán aquí seguindo o criterio dos teus axustes.",
"empty_column.notifications": "Aínda non tes notificacións. Aparecerán cando outras persoas interactúen contigo.",
"empty_column.public": "Nada por aquí! Escribe algo de xeito público, ou segue de xeito manual usuarias doutros servidores para ir enchéndoo",
"error.unexpected_crash.explanation": "Debido a un erro no noso código ou a unha compatilidade co teu navegador, esta páxina non pode ser amosada correctamente.",
@@ -313,7 +315,7 @@
"follow_suggestions.curated_suggestion": "Suxestións do Servidor",
"follow_suggestions.dismiss": "Non mostrar máis",
"follow_suggestions.featured_longer": "Elección persoal do equipo de {domain}",
- "follow_suggestions.friends_of_friends_longer": "Popular entre as persoas que sigues",
+ "follow_suggestions.friends_of_friends_longer": "Popular entre as persoas que segues",
"follow_suggestions.hints.featured": "Este perfil foi escollido pola administración de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Este perfil é popular entre as persoas que segues.",
"follow_suggestions.hints.most_followed": "Este perfil é un dos máis seguidos en {domain}.",
@@ -366,13 +368,13 @@
"home.pending_critical_update.link": "Mira as actualizacións",
"home.pending_critical_update.title": "Hai una actualización crítica de seguridade!",
"home.show_announcements": "Amosar anuncios",
- "ignore_notifications_modal.disclaimer": "Mastodon non pode informar ás usuarias se ignoraches as súas notificacións. Ao ignorar as notificacións non evitarás que as mensaxes sexan enviadas igualmente.",
+ "ignore_notifications_modal.disclaimer": "Mastodon non pode informar ás usuarias de que ignoraches as súas notificacións. Ao ignorar as notificacións non evitarás que as mensaxes sexan enviadas igualmente.",
"ignore_notifications_modal.filter_instead": "Filtrar igualmente",
"ignore_notifications_modal.filter_to_act_users": "Poderás seguir aceptando, rexeitando e denunciando usuarias",
"ignore_notifications_modal.filter_to_avoid_confusion": "Ao filtrar axudas a evitar posibles confusións",
- "ignore_notifications_modal.filter_to_review_separately": "Podes revisar as notificacións filtradas por separado",
+ "ignore_notifications_modal.filter_to_review_separately": "Podes revisar por separado as notificacións filtradas",
"ignore_notifications_modal.ignore": "Ignorar notificacións",
- "ignore_notifications_modal.limited_accounts_title": "Ignorar notificacións desde contas moderadas?",
+ "ignore_notifications_modal.limited_accounts_title": "Ignorar notificacións desde contas limitadas?",
"ignore_notifications_modal.new_accounts_title": "Ignorar notificacións desde novas contas?",
"ignore_notifications_modal.not_followers_title": "Ignorar notificacións de persoas que non te seguen?",
"ignore_notifications_modal.not_following_title": "Ignorar notificacións de persoas que non segues?",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Para deixar de destacar a área de escritura/procura",
"keyboard_shortcuts.up": "Para mover cara arriba na listaxe",
"lightbox.close": "Fechar",
- "lightbox.compress": "Comprimir a caixa de vista da imaxe",
- "lightbox.expand": "Estender a caixa de vista da imaxe",
"lightbox.next": "Seguinte",
"lightbox.previous": "Anterior",
+ "lightbox.zoom_in": "Ver tamaño real",
+ "lightbox.zoom_out": "Ver tamaño axustado",
"limited_account_hint.action": "Mostrar perfil igualmente",
"limited_account_hint.title": "Este perfil foi agochado pola moderación de {domain}.",
"link_preview.author": "Por {name}",
@@ -455,18 +457,19 @@
"lists.subheading": "As túas listaxes",
"load_pending": "{count, plural, one {# novo elemento} other {# novos elementos}}",
"loading_indicator.label": "Estase a cargar…",
- "media_gallery.toggle_visible": "Agochar {number, plural, one {imaxe} other {imaxes}}",
+ "media_gallery.hide": "Agochar",
"moved_to_account_banner.text": "A túa conta {disabledAccount} está actualmente desactivada porque movéchela a {movedToAccount}.",
- "mute_modal.hide_from_notifications": "Ocultar nas notificacións",
+ "mute_modal.hide_from_notifications": "Agochar nas notificacións",
"mute_modal.hide_options": "Opcións ao ocultar",
"mute_modal.indefinite": "Ata que as reactive",
"mute_modal.show_options": "Mostrar opcións",
- "mute_modal.they_can_mention_and_follow": "Pódete mencionar e seguirte, pero non o verás.",
+ "mute_modal.they_can_mention_and_follow": "Pódete mencionar e seguirte, pero non a verás.",
"mute_modal.they_wont_know": "Non saberá que a acalaches.",
"mute_modal.title": "Acalar usuaria?",
"mute_modal.you_wont_see_mentions": "Non verás as publicacións que a mencionen.",
"mute_modal.you_wont_see_posts": "Seguirá podendo ler as túas publicacións, pero non verás as súas.",
"navigation_bar.about": "Sobre",
+ "navigation_bar.administration": "Administración",
"navigation_bar.advanced_interface": "Abrir coa interface web avanzada",
"navigation_bar.blocks": "Usuarias bloqueadas",
"navigation_bar.bookmarks": "Marcadores",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Seguindo e seguidoras",
"navigation_bar.lists": "Listaxes",
"navigation_bar.logout": "Pechar sesión",
+ "navigation_bar.moderation": "Moderación",
"navigation_bar.mutes": "Usuarias silenciadas",
"navigation_bar.opened_in_classic_interface": "Publicacións, contas e outras páxinas dedicadas ábrense por defecto na interface web clásica.",
"navigation_bar.personal": "Persoal",
@@ -555,8 +559,6 @@
"notifications.column_settings.admin.report": "Novas denuncias:",
"notifications.column_settings.admin.sign_up": "Novas usuarias:",
"notifications.column_settings.alert": "Notificacións de escritorio",
- "notifications.column_settings.beta.category": "Características experimentais",
- "notifications.column_settings.beta.grouping": "Notificacións de grupo",
"notifications.column_settings.favourite": "Favoritas:",
"notifications.column_settings.filter_bar.advanced": "Mostrar todas as categorías",
"notifications.column_settings.filter_bar.category": "Barra de filtrado rápido",
@@ -637,7 +639,7 @@
"onboarding.steps.publish_status.title": "Escribe a túa primeira publicación",
"onboarding.steps.setup_profile.body": "Ao engadir información ao teu perfil é máis probable que teñas máis interaccións.",
"onboarding.steps.setup_profile.title": "Personaliza o perfil",
- "onboarding.steps.share_profile.body": "Dille ás amizades como poden atoparte en Mastodon!",
+ "onboarding.steps.share_profile.body": "Dille ás amizades como poden atoparte en Mastodon.",
"onboarding.steps.share_profile.title": "Comparte o teu perfil en Mastodon",
"onboarding.tips.2fa": "
Sabes que? Podes protexer a túa conta configurando un segundo factor de autenticación nos axustes. Funciona con calquera app TOTP, non precisas un número de teléfono!",
"onboarding.tips.accounts_from_other_servers": "
Sabes que? Como Mastodon é descentralizado, algúns perfís que atopes estarán en servidores diferentes ao teu. Pero podes interactuar igualmente con eles! O seu servidor é o que ven despois da @ no seu identificador!",
@@ -776,6 +778,7 @@
"status.bookmark": "Marcar",
"status.cancel_reblog_private": "Desfacer compartido",
"status.cannot_reblog": "Esta publicación non pode ser promovida",
+ "status.continued_thread": "Continua co fío",
"status.copy": "Copiar ligazón á publicación",
"status.delete": "Eliminar",
"status.detailed_status": "Vista detallada da conversa",
@@ -784,7 +787,7 @@
"status.edit": "Editar",
"status.edited": "Última edición {date}",
"status.edited_x_times": "Editado {count, plural, one {{count} vez} other {{count} veces}}",
- "status.embed": "Incrustar",
+ "status.embed": "O código a incluír",
"status.favourite": "Favorecer",
"status.favourites": "{count, plural, one {favorecemento} other {favorecementos}}",
"status.filter": "Filtrar esta publicación",
@@ -809,6 +812,7 @@
"status.reblogs.empty": "Aínda ninguén promoveu esta publicación. Cando alguén o faga, amosarase aquí.",
"status.redraft": "Eliminar e reescribir",
"status.remove_bookmark": "Eliminar marcador",
+ "status.replied_in_thread": "Respondeu nun fío",
"status.replied_to": "Respondeu a {name}",
"status.reply": "Responder",
"status.replyAll": "Responder ao tema",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 1d21e3bda7..6503d870e5 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -97,6 +97,8 @@
"block_modal.title": "לחסום משתמש?",
"block_modal.you_wont_see_mentions": "לא תראה הודעות שמאזכרות אותם.",
"boost_modal.combo": "ניתן להקיש {combo} כדי לדלג בפעם הבאה",
+ "boost_modal.reblog": "להדהד הודעה?",
+ "boost_modal.undo_reblog": "להסיר הדהוד?",
"bundle_column_error.copy_stacktrace": "העתקת הודעת שגיאה",
"bundle_column_error.error.body": "הדף המבוקש אינו זמין. זה עשוי להיות באג בקוד או בעייה בתאימות הדפדפן.",
"bundle_column_error.error.title": "הו, לא!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "הפסקת מעקב",
"confirmations.unfollow.message": "להפסיק מעקב אחרי {name}?",
"confirmations.unfollow.title": "לבטל מעקב אחר המשתמש.ת?",
+ "content_warning.hide": "הסתרת חיצרוץ",
+ "content_warning.show": "להציג בכל זאת",
"conversation.delete": "מחיקת שיחה",
"conversation.mark_as_read": "סמן כנקרא",
"conversation.open": "צפו בשיחה",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "שימוש בקטגורייה קיימת או יצירת אחת חדשה",
"filter_modal.select_filter.title": "סינון ההודעה הזו",
"filter_modal.title.status": "סנן הודעה",
+ "filter_warning.matches_filter": "תואם לסנן “{title}”",
"filtered_notifications_banner.pending_requests": "{count, plural,=0 {אין בקשות ממשתמשים }one {בקשה אחת ממישהו/מישהי }two {יש בקשותיים ממשתמשים }other {יש # בקשות ממשתמשים }}שאולי מוכרים לך",
"filtered_notifications_banner.title": "התראות מסוננות",
"firehose.all": "הכל",
@@ -427,10 +432,10 @@
"keyboard_shortcuts.unfocus": "לצאת מתיבת חיבור/חיפוש",
"keyboard_shortcuts.up": "לנוע במעלה הרשימה",
"lightbox.close": "סגירה",
- "lightbox.compress": "דחיסת קופסת צפייה בתמונה",
- "lightbox.expand": "הרחבת קופסת צפייה בתמונה",
"lightbox.next": "הבא",
"lightbox.previous": "הקודם",
+ "lightbox.zoom_in": "הגדלה לגודל מלא",
+ "lightbox.zoom_out": "התאמה לגודל המסך",
"limited_account_hint.action": "הצג חשבון בכל זאת",
"limited_account_hint.title": "פרופיל המשתמש הזה הוסתר על ידי המנחים של {domain}.",
"link_preview.author": "מאת {name}",
@@ -452,7 +457,7 @@
"lists.subheading": "הרשימות שלך",
"load_pending": "{count, plural, one {# פריט חדש} other {# פריטים חדשים}}",
"loading_indicator.label": "בטעינה…",
- "media_gallery.toggle_visible": "{number, plural, one {להסתיר תמונה} two {להסתיר תמונותיים} many {להסתיר תמונות} other {להסתיר תמונות}}",
+ "media_gallery.hide": "להסתיר",
"moved_to_account_banner.text": "חשבונך {disabledAccount} אינו פעיל כרגע עקב מעבר ל{movedToAccount}.",
"mute_modal.hide_from_notifications": "להסתיר מהתראות",
"mute_modal.hide_options": "הסתרת אפשרויות",
@@ -464,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "לא תראה הודעות שמאזכרות אותם.",
"mute_modal.you_wont_see_posts": "הם יכולים לראות את הודעותכם, אבל אתם לא תוכלו לראות את שלהם.",
"navigation_bar.about": "אודות",
+ "navigation_bar.administration": "ניהול",
"navigation_bar.advanced_interface": "פתח במנשק ווב מתקדם",
"navigation_bar.blocks": "משתמשים חסומים",
"navigation_bar.bookmarks": "סימניות",
@@ -480,6 +486,7 @@
"navigation_bar.follows_and_followers": "נעקבים ועוקבים",
"navigation_bar.lists": "רשימות",
"navigation_bar.logout": "התנתקות",
+ "navigation_bar.moderation": "פיקוח",
"navigation_bar.mutes": "משתמשים בהשתקה",
"navigation_bar.opened_in_classic_interface": "הודעות, חשבונות ושאר עמודי רשת יפתחו כברירת מחדל בדפדפן רשת קלאסי.",
"navigation_bar.personal": "אישי",
@@ -552,8 +559,6 @@
"notifications.column_settings.admin.report": "דו\"חות חדשים",
"notifications.column_settings.admin.sign_up": "הרשמות חדשות:",
"notifications.column_settings.alert": "התראות לשולחן העבודה",
- "notifications.column_settings.beta.category": "יכולות ניסיוניות",
- "notifications.column_settings.beta.grouping": "התראות קבוצה",
"notifications.column_settings.favourite": "חיבובים:",
"notifications.column_settings.filter_bar.advanced": "להציג את כל הקטגוריות",
"notifications.column_settings.filter_bar.category": "שורת סינון מהיר",
@@ -773,6 +778,7 @@
"status.bookmark": "סימניה",
"status.cancel_reblog_private": "הסרת הדהוד",
"status.cannot_reblog": "לא ניתן להדהד חצרוץ זה",
+ "status.continued_thread": "שרשור מתמשך",
"status.copy": "העתק/י קישור להודעה זו",
"status.delete": "מחיקה",
"status.detailed_status": "תצוגת שיחה מפורטת",
@@ -781,7 +787,7 @@
"status.edit": "עריכה",
"status.edited": "נערך לאחרונה {date}",
"status.edited_x_times": "נערך {count, plural, one {פעם {count}} other {{count} פעמים}}",
- "status.embed": "הטמעה",
+ "status.embed": "העתקת קוד להטמעה",
"status.favourite": "חיבוב",
"status.favourites": "{count, plural, one {חיבוב אחד} two {זוג חיבובים} other {# חיבובים}}",
"status.filter": "סנן הודעה זו",
@@ -806,6 +812,7 @@
"status.reblogs.empty": "עוד לא הידהדו את ההודעה הזו. כאשר זה יקרה, ההדהודים יופיעו כאן.",
"status.redraft": "מחיקה ועריכה מחדש",
"status.remove_bookmark": "הסרת סימניה",
+ "status.replied_in_thread": "תגובה לשרשור",
"status.replied_to": "בתגובה לחשבון {name}",
"status.reply": "תגובה",
"status.replyAll": "תגובה לשרשור",
diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json
index 0b40251730..4a513c1c07 100644
--- a/app/javascript/mastodon/locales/hi.json
+++ b/app/javascript/mastodon/locales/hi.json
@@ -349,8 +349,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"lightbox.close": "बंद करें",
- "lightbox.compress": "कंप्रेस इमेज व्यू बॉक्स",
- "lightbox.expand": "एक्सपैंड इमेज व्यू बॉक्स",
"lightbox.next": "अगला",
"lightbox.previous": "पिछला",
"limited_account_hint.action": "फिर भी प्रोफाइल दिखाओ",
@@ -367,6 +365,7 @@
"lists.replies_policy.none": "कोई नहीं",
"lists.replies_policy.title": "इसके जवाब दिखाएं:",
"lists.subheading": "आपकी सूचियाँ",
+ "media_gallery.hide": "छिपाएं",
"navigation_bar.about": "विवरण",
"navigation_bar.blocks": "ब्लॉक्ड यूज़र्स",
"navigation_bar.bookmarks": "पुस्तकचिह्न:",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index 0b42c49338..26c527f2fe 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -310,7 +310,6 @@
"lists.replies_policy.none": "Nitko",
"lists.search": "Traži među praćenim ljudima",
"lists.subheading": "Vaše liste",
- "media_gallery.toggle_visible": "Sakrij {number, plural, one {sliku} other {slike}}",
"navigation_bar.about": "O aplikaciji",
"navigation_bar.advanced_interface": "Otvori u naprednom web sučelju",
"navigation_bar.blocks": "Blokirani korisnici",
@@ -458,7 +457,6 @@
"status.delete": "Obriši",
"status.edit": "Uredi",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "Umetni",
"status.filter": "Filtriraj ovu objavu",
"status.history.created": "Kreirao/la {name} prije {date}",
"status.history.edited": "Uredio/la {name} prije {date}",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index b76b2e92cd..cb3517e3a3 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -97,6 +97,8 @@
"block_modal.title": "Letiltsuk a felhasználót?",
"block_modal.you_wont_see_mentions": "Nem látsz majd őt említő bejegyzéseket.",
"boost_modal.combo": "Hogy átugord ezt következő alkalommal, használd {combo}",
+ "boost_modal.reblog": "Bejegyzés megtolása?",
+ "boost_modal.undo_reblog": "Megtolás visszavonása?",
"bundle_column_error.copy_stacktrace": "Hibajelentés másolása",
"bundle_column_error.error.body": "A kért lap nem jeleníthető meg. Ez lehet, hogy kódhiba, vagy böngészőkompatibitási hiba.",
"bundle_column_error.error.title": "Jaj ne!",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Szerkesztés/keresés fókuszból való kivétele",
"keyboard_shortcuts.up": "Mozgás felfelé a listában",
"lightbox.close": "Bezárás",
- "lightbox.compress": "Képnéző doboz összezárása",
- "lightbox.expand": "Képnéző doboz kinyitása",
"lightbox.next": "Következő",
"lightbox.previous": "Előző",
+ "lightbox.zoom_in": "Nagyítás a tényleges méretre",
+ "lightbox.zoom_out": "Méretre igazítás",
"limited_account_hint.action": "Profil megjelenítése mindenképpen",
"limited_account_hint.title": "Ezt a profilt {domain} moderátorai elrejtették.",
"link_preview.author": "{name} szerint",
@@ -455,7 +457,7 @@
"lists.subheading": "Saját listák",
"load_pending": "{count, plural, one {# új elem} other {# új elem}}",
"loading_indicator.label": "Betöltés…",
- "media_gallery.toggle_visible": "{number, plural, one {Kép elrejtése} other {Képek elrejtése}}",
+ "media_gallery.hide": "Elrejtés",
"moved_to_account_banner.text": "A(z) {disabledAccount} fiókod jelenleg le van tiltva, mert átköltöztél ide: {movedToAccount}.",
"mute_modal.hide_from_notifications": "Elrejtés az értesítések közül",
"mute_modal.hide_options": "Beállítások elrejtése",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Nem látsz majd őt említő bejegyzéseket.",
"mute_modal.you_wont_see_posts": "Továbbra is látni fogja a bejegyzéseidet, de te nem fogod látni az övéit.",
"navigation_bar.about": "Névjegy",
+ "navigation_bar.administration": "Adminisztráció",
"navigation_bar.advanced_interface": "Megnyitás a speciális webes felületben",
"navigation_bar.blocks": "Letiltott felhasználók",
"navigation_bar.bookmarks": "Könyvjelzők",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Követések és követők",
"navigation_bar.lists": "Listák",
"navigation_bar.logout": "Kijelentkezés",
+ "navigation_bar.moderation": "Moderáció",
"navigation_bar.mutes": "Némított felhasználók",
"navigation_bar.opened_in_classic_interface": "A bejegyzések, fiókok és más speciális oldalak alapértelmezés szerint a klasszikus webes felületen nyílnak meg.",
"navigation_bar.personal": "Személyes",
@@ -555,8 +559,6 @@
"notifications.column_settings.admin.report": "Új jelentések:",
"notifications.column_settings.admin.sign_up": "Új regisztrálók:",
"notifications.column_settings.alert": "Asztali értesítések",
- "notifications.column_settings.beta.category": "Kísérleti funkciók",
- "notifications.column_settings.beta.grouping": "Csoportértesítések",
"notifications.column_settings.favourite": "Kedvencek:",
"notifications.column_settings.filter_bar.advanced": "Minden kategória megjelenítése",
"notifications.column_settings.filter_bar.category": "Gyorsszűrő sáv",
@@ -776,6 +778,7 @@
"status.bookmark": "Könyvjelzőzés",
"status.cancel_reblog_private": "Megtolás visszavonása",
"status.cannot_reblog": "Ezt a bejegyzést nem lehet megtolni",
+ "status.continued_thread": "Folytatott szál",
"status.copy": "Link másolása bejegyzésbe",
"status.delete": "Törlés",
"status.detailed_status": "Részletes beszélgetési nézet",
@@ -784,7 +787,7 @@
"status.edit": "Szerkesztés",
"status.edited": "Utoljára szerkesztve {date}",
"status.edited_x_times": "{count, plural, one {{count} alkalommal} other {{count} alkalommal}} szerkesztve",
- "status.embed": "Beágyazás",
+ "status.embed": "Beágyazási kód lekérése",
"status.favourite": "Kedvenc",
"status.favourites": "{count, plural, one {kedvenc} other {kedvenc}}",
"status.filter": "E bejegyzés szűrése",
@@ -809,6 +812,7 @@
"status.reblogs.empty": "Senki sem tolta még meg ezt a bejegyzést. Ha valaki megteszi, itt fog megjelenni.",
"status.redraft": "Törlés és újraírás",
"status.remove_bookmark": "Könyvjelző eltávolítása",
+ "status.replied_in_thread": "Válaszolva a szálban",
"status.replied_to": "Megválaszolva {name} számára",
"status.reply": "Válasz",
"status.replyAll": "Válasz a beszélgetésre",
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
index 1d82e884ff..9e5ae79045 100644
--- a/app/javascript/mastodon/locales/hy.json
+++ b/app/javascript/mastodon/locales/hy.json
@@ -271,8 +271,6 @@
"keyboard_shortcuts.unfocus": "տեքստի/որոնման տիրոյթից ապասեւեռուելու համար",
"keyboard_shortcuts.up": "ցանկով վերեւ շարժուելու համար",
"lightbox.close": "Փակել",
- "lightbox.compress": "Փակել պատկերի դիտման պատուհանը",
- "lightbox.expand": "Բացել պատկերի դիտման պատուհանը",
"lightbox.next": "Յաջորդ",
"lightbox.previous": "Նախորդ",
"lists.account.add": "Աւելացնել ցանկին",
@@ -289,7 +287,6 @@
"lists.search": "Փնտրել քո հետեւած մարդկանց մէջ",
"lists.subheading": "Քո ցանկերը",
"load_pending": "{count, plural, one {# նոր նիւթ} other {# նոր նիւթ}}",
- "media_gallery.toggle_visible": "Ցուցադրել/թաքցնել",
"navigation_bar.about": "Մասին",
"navigation_bar.blocks": "Արգելափակուած օգտատէրեր",
"navigation_bar.bookmarks": "Էջանիշեր",
@@ -449,7 +446,6 @@
"status.direct_indicator": "Մասնաւոր յիշատակում",
"status.edit": "Խմբագրել",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "Ներդնել",
"status.favourite": "Հավանել",
"status.filter": "Զտել այս գրառումը",
"status.history.created": "{name}-ը ստեղծել է՝ {date}",
diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json
index 2c3b04f998..93bee9ec79 100644
--- a/app/javascript/mastodon/locales/ia.json
+++ b/app/javascript/mastodon/locales/ia.json
@@ -97,6 +97,8 @@
"block_modal.title": "Blocar usator?",
"block_modal.you_wont_see_mentions": "Tu non videra le messages que mentiona iste persona.",
"boost_modal.combo": "Tu pote premer {combo} pro saltar isto le proxime vice",
+ "boost_modal.reblog": "Impulsar le message?",
+ "boost_modal.undo_reblog": "Cessar de impulsar le message?",
"bundle_column_error.copy_stacktrace": "Copiar reporto de error",
"bundle_column_error.error.body": "Le pagina requestate non pote esser visualisate. Pote esser a causa de un defecto in nostre codice o de un problema de compatibilitate del navigator.",
"bundle_column_error.error.title": "Oh, no!",
@@ -178,6 +180,7 @@
"confirmations.discard_edit_media.message": "Tu ha cambiamentos non salvate in le description o previsualisation del objecto multimedial. Abandonar los?",
"confirmations.edit.confirm": "Modificar",
"confirmations.edit.message": "Si tu modifica isto ora, le message in curso de composition essera perdite. Es tu secur de voler continuar?",
+ "confirmations.edit.title": "Superscriber le message?",
"confirmations.logout.confirm": "Clauder session",
"confirmations.logout.message": "Es tu secur que tu vole clauder le session?",
"confirmations.logout.title": "Clauder session?",
@@ -187,9 +190,12 @@
"confirmations.redraft.title": "Deler e rescriber le message?",
"confirmations.reply.confirm": "Responder",
"confirmations.reply.message": "Si tu responde ora, le message in curso de composition essera perdite. Es tu secur de voler continuar?",
+ "confirmations.reply.title": "Superscriber le message?",
"confirmations.unfollow.confirm": "Non plus sequer",
"confirmations.unfollow.message": "Es tu secur que tu vole cessar de sequer {name}?",
"confirmations.unfollow.title": "Cessar de sequer le usator?",
+ "content_warning.hide": "Celar le message",
+ "content_warning.show": "Monstrar in omne caso",
"conversation.delete": "Deler conversation",
"conversation.mark_as_read": "Marcar como legite",
"conversation.open": "Vider conversation",
@@ -297,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Usa un categoria existente o crea un nove",
"filter_modal.select_filter.title": "Filtrar iste message",
"filter_modal.title.status": "Filtrar un message",
+ "filter_warning.matches_filter": "Corresponde al filtro “{title}”",
"filtered_notifications_banner.title": "Notificationes filtrate",
"firehose.all": "Toto",
"firehose.local": "Iste servitor",
@@ -345,6 +352,11 @@
"hashtag.follow": "Sequer hashtag",
"hashtag.unfollow": "Non sequer plus le hashtag",
"hashtags.and_other": "…e {count, plural, one {}other {# plus}}",
+ "hints.profiles.see_more_followers": "Vider plus de sequitores sur {domain}",
+ "hints.profiles.see_more_follows": "Vider plus de sequites sur {domain}",
+ "hints.profiles.see_more_posts": "Vider plus de messages sur {domain}",
+ "hints.threads.replies_may_be_missing": "Responsas de altere servitores pote esser perdite.",
+ "hints.threads.see_more": "Vider plus de responsas sur {domain}",
"home.column_settings.show_reblogs": "Monstrar impulsos",
"home.column_settings.show_replies": "Monstrar responsas",
"home.hide_announcements": "Celar annuncios",
@@ -352,6 +364,12 @@
"home.pending_critical_update.link": "Vider actualisationes",
"home.pending_critical_update.title": "Actualisation de securitate critic disponibile!",
"home.show_announcements": "Monstrar annuncios",
+ "ignore_notifications_modal.ignore": "Ignorar le notificationes",
+ "ignore_notifications_modal.limited_accounts_title": "Ignorar le notificationes de contos moderate?",
+ "ignore_notifications_modal.new_accounts_title": "Ignorar le notificationes de nove contos?",
+ "ignore_notifications_modal.not_followers_title": "Ignorar notificationes de personas qui non te seque?",
+ "ignore_notifications_modal.not_following_title": "Ignorar notificationes de personas que tu non seque?",
+ "ignore_notifications_modal.private_mentions_title": "Ignorar notificationes de mentiones private non requestate?",
"interaction_modal.description.favourite": "Con un conto sur Mastodon, tu pote marcar iste message como favorite pro informar le autor que tu lo apprecia e lo salva pro plus tarde.",
"interaction_modal.description.follow": "Con un conto sur Mastodon, tu pote sequer {name} e reciper su messages in tu fluxo de initio.",
"interaction_modal.description.reblog": "Con un conto sur Mastodon, tu pote impulsar iste message pro condivider lo con tu proprie sequitores.",
@@ -405,8 +423,6 @@
"keyboard_shortcuts.unfocus": "Disfocalisar le area de composition de texto/de recerca",
"keyboard_shortcuts.up": "Displaciar in alto in le lista",
"lightbox.close": "Clauder",
- "lightbox.compress": "Comprimer le quadro de visualisation de imagine",
- "lightbox.expand": "Expander le quadro de visualisation de imagine",
"lightbox.next": "Sequente",
"lightbox.previous": "Precedente",
"limited_account_hint.action": "Monstrar profilo in omne caso",
@@ -430,7 +446,7 @@
"lists.subheading": "Tu listas",
"load_pending": "{count, plural, one {# nove entrata} other {# nove entratas}}",
"loading_indicator.label": "Cargante…",
- "media_gallery.toggle_visible": "{number, plural, one {Celar imagine} other {Celar imagines}}",
+ "media_gallery.hide": "Celar",
"moved_to_account_banner.text": "Tu conto {disabledAccount} es actualmente disactivate perque tu ha cambiate de conto a {movedToAccount}.",
"mute_modal.hide_from_notifications": "Celar in notificationes",
"mute_modal.hide_options": "Celar optiones",
@@ -442,6 +458,7 @@
"mute_modal.you_wont_see_mentions": "Tu non videra le messages que mentiona iste persona.",
"mute_modal.you_wont_see_posts": "Iste persona pote totevia vider tu messages, ma tu non videra le sues.",
"navigation_bar.about": "A proposito",
+ "navigation_bar.administration": "Administration",
"navigation_bar.advanced_interface": "Aperir in le interfacie web avantiate",
"navigation_bar.blocks": "Usatores blocate",
"navigation_bar.bookmarks": "Marcapaginas",
@@ -458,6 +475,7 @@
"navigation_bar.follows_and_followers": "Sequites e sequitores",
"navigation_bar.lists": "Listas",
"navigation_bar.logout": "Clauder session",
+ "navigation_bar.moderation": "Moderation",
"navigation_bar.mutes": "Usatores silentiate",
"navigation_bar.opened_in_classic_interface": "Messages, contos e altere paginas specific es aperite per predefinition in le interfacie web classic.",
"navigation_bar.personal": "Personal",
@@ -468,6 +486,10 @@
"navigation_bar.security": "Securitate",
"not_signed_in_indicator.not_signed_in": "Es necessari aperir session pro acceder a iste ressource.",
"notification.admin.report": "{name} ha reportate {target}",
+ "notification.admin.report_account": "{name} ha reportate {count, plural, one {un message} other {# messages}} de {target} per {category}",
+ "notification.admin.report_account_other": "{name} ha reportate {count, plural, one {un message} other {# messages}} de {target}",
+ "notification.admin.report_statuses": "{name} ha reportate {target} pro {category}",
+ "notification.admin.report_statuses_other": "{name} ha reportate {target}",
"notification.admin.sign_up": "{name} se ha inscribite",
"notification.favourite": "{name} ha marcate tu message como favorite",
"notification.follow": "{name} te ha sequite",
@@ -487,6 +509,7 @@
"notification.moderation_warning.action_silence": "Tu conto ha essite limitate.",
"notification.moderation_warning.action_suspend": "Tu conto ha essite suspendite.",
"notification.own_poll": "Tu sondage ha finite",
+ "notification.poll": "Un sondage in le qual tu ha votate ha finite",
"notification.reblog": "{name} ha impulsate tu message",
"notification.relationships_severance_event": "Connexiones perdite con {name}",
"notification.relationships_severance_event.account_suspension": "Un administrator de {from} ha suspendiute {target}. Isto significa que tu non pote plus reciper actualisationes de iste persona o interager con ille.",
@@ -496,17 +519,20 @@
"notification.status": "{name} ha justo ora publicate",
"notification.update": "{name} ha modificate un message",
"notification_requests.accept": "Acceptar",
+ "notification_requests.confirm_accept_multiple.title": "Acceptar petitiones de notification?",
+ "notification_requests.confirm_dismiss_multiple.title": "Dimitter petitiones de notification?",
"notification_requests.dismiss": "Clauder",
+ "notification_requests.edit_selection": "Modificar",
+ "notification_requests.exit_selection": "Facite",
"notification_requests.notifications_from": "Notificationes de {name}",
"notification_requests.title": "Notificationes filtrate",
+ "notification_requests.view": "Vider notificationes",
"notifications.clear": "Rader notificationes",
"notifications.clear_confirmation": "Es tu secur que tu vole rader permanentemente tote tu notificationes?",
"notifications.clear_title": "Rader le notificationes?",
"notifications.column_settings.admin.report": "Nove reportos:",
"notifications.column_settings.admin.sign_up": "Nove inscriptiones:",
"notifications.column_settings.alert": "Notificationes de scriptorio",
- "notifications.column_settings.beta.category": "Functionalitates experimental",
- "notifications.column_settings.beta.grouping": "Notificationes de gruppo",
"notifications.column_settings.favourite": "Favorites:",
"notifications.column_settings.filter_bar.advanced": "Monstrar tote le categorias",
"notifications.column_settings.filter_bar.category": "Barra de filtro rapide",
@@ -535,6 +561,11 @@
"notifications.permission_denied": "Le notificationes de scriptorio es indisponibile a causa de un requesta anteriormente refusate de permissiones del navigator",
"notifications.permission_denied_alert": "Le notificationes de scriptorio non pote esser activate perque le permission del navigator ha essite refusate anteriormente",
"notifications.permission_required": "Le notificationes de scriptorio es indisponibile perque le permission necessari non ha essite concedite.",
+ "notifications.policy.accept": "Acceptar",
+ "notifications.policy.accept_hint": "Monstrar in le notificationes",
+ "notifications.policy.filter": "Filtrar",
+ "notifications.policy.filter_hint": "Inviar al cassa de notificationes filtrate",
+ "notifications.policy.filter_limited_accounts_title": "Contos moderate",
"notifications.policy.filter_new_accounts.hint": "Create in le ultime {days, plural, one {die} other {# dies}}",
"notifications.policy.filter_new_accounts_title": "Nove contos",
"notifications.policy.filter_not_followers_hint": "Includente le personas que te ha sequite durante minus de {days, plural, one {un die} other {# dies}}",
@@ -543,6 +574,7 @@
"notifications.policy.filter_not_following_title": "Personas que tu non seque",
"notifications.policy.filter_private_mentions_hint": "Filtrate, excepte si es in responsa a tu proprie mention o si tu seque le expeditor",
"notifications.policy.filter_private_mentions_title": "Mentiones private indesirate",
+ "notifications.policy.title": "Gerer notificationes de…",
"notifications_permission_banner.enable": "Activar notificationes de scriptorio",
"notifications_permission_banner.how_to_control": "Pro reciper notificationes quando Mastodon non es aperte, activa le notificationes de scriptorio. Post lor activation, es possibile controlar precisemente qual typos de interaction genera notificationes de scriptorio per medio del button {icon} hic supra.",
"notifications_permission_banner.title": "Non mancar jammais a un cosa",
@@ -595,8 +627,8 @@
"poll.vote": "Votar",
"poll.voted": "Tu ha votate pro iste responsa",
"poll.votes": "{votes, plural, one {# voto} other {# votos}}",
- "poll_button.add_poll": "Adder un inquesta",
- "poll_button.remove_poll": "Remover un inquesta",
+ "poll_button.add_poll": "Adder un sondage",
+ "poll_button.remove_poll": "Remover un sondage",
"privacy.change": "Cambiar le confidentialitate del message",
"privacy.direct.long": "Tote le personas mentionate in le message",
"privacy.direct.short": "Personas specific",
@@ -724,7 +756,6 @@
"status.edit": "Modificar",
"status.edited": "Ultime modification le {date}",
"status.edited_x_times": "Modificate {count, plural, one {{count} vice} other {{count} vices}}",
- "status.embed": "Incastrar",
"status.favourite": "Adder al favorites",
"status.favourites": "{count, plural, one {favorite} other {favorites}}",
"status.filter": "Filtrar iste message",
@@ -749,6 +780,7 @@
"status.reblogs.empty": "Necuno ha ancora impulsate iste message. Quando alcuno lo face, le impulsos apparera hic.",
"status.redraft": "Deler e reconciper",
"status.remove_bookmark": "Remover marcapagina",
+ "status.replied_in_thread": "Respondite in le discussion",
"status.replied_to": "Respondite a {name}",
"status.reply": "Responder",
"status.replyAll": "Responder al discussion",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index b46e259199..b6d01ec996 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -1,7 +1,7 @@
{
"about.blocks": "Server yang dimoderasi",
- "about.contact": "Hubungi:",
- "about.disclaimer": "Mastodon adalah perangkat lunak bebas dan sumber terbuka, dan adalah merek dagang dari Mastodon gGmbH.",
+ "about.contact": "Kontak:",
+ "about.disclaimer": "perangkat lunak sumber terbuperangkat lunak sumber terbukaka184124.",
"about.domain_blocks.no_reason_available": "Alasan tidak tersedia",
"about.domain_blocks.preamble": "Mastodon umumnya mengizinkan Anda untuk melihat konten dan berinteraksi dengan pengguna dari server lain di fediverse. Ini adalah pengecualian yang dibuat untuk beberapa server.",
"about.domain_blocks.silenced.explanation": "Anda secara umum tidak melihat profil dan konten dari server ini, kecuali jika Anda mencarinya atau memilihnya dengan mengikuti secara eksplisit.",
@@ -11,6 +11,7 @@
"about.not_available": "Informasi ini belum tersedia di server ini.",
"about.powered_by": "Media sosial terdesentralisasi diberdayakan oleh {mastodon}",
"about.rules": "Aturan server",
+ "account.account_note_header": "Personal note",
"account.add_or_remove_from_list": "Tambah atau Hapus dari daftar",
"account.badges.bot": "Bot",
"account.badges.group": "Grup",
@@ -33,7 +34,9 @@
"account.follow_back": "Ikuti balik",
"account.followers": "Pengikut",
"account.followers.empty": "Pengguna ini belum ada pengikut.",
+ "account.followers_counter": "{count, plural, other {{counter} followers}}",
"account.following": "Mengikuti",
+ "account.following_counter": "{count, plural, other {{counter} following}}",
"account.follows.empty": "Pengguna ini belum mengikuti siapa pun.",
"account.go_to_profile": "Buka profil",
"account.hide_reblogs": "Sembunyikan boosts dari @{name}",
@@ -59,6 +62,7 @@
"account.requested_follow": "{name} ingin mengikuti Anda",
"account.share": "Bagikan profil @{name}",
"account.show_reblogs": "Tampilkan boost dari @{name}",
+ "account.statuses_counter": "{count, plural, other {{counter} posts}}",
"account.unblock": "Buka blokir @{name}",
"account.unblock_domain": "Buka blokir domain {domain}",
"account.unblock_short": "Buka blokir",
@@ -166,21 +170,30 @@
"confirmations.block.confirm": "Blokir",
"confirmations.delete.confirm": "Hapus",
"confirmations.delete.message": "Apakah Anda yakin untuk menghapus kiriman ini?",
+ "confirmations.delete.title": "Delete post?",
"confirmations.delete_list.confirm": "Hapus",
"confirmations.delete_list.message": "Apakah Anda yakin untuk menghapus daftar ini secara permanen?",
+ "confirmations.delete_list.title": "Delete list?",
"confirmations.discard_edit_media.confirm": "Buang",
"confirmations.discard_edit_media.message": "Anda belum menyimpan perubahan deskripsi atau pratinjau media, buang saja?",
"confirmations.edit.confirm": "Ubah",
"confirmations.edit.message": "Mengubah akan menimpa pesan yang sedang anda tulis. Apakah anda yakin ingin melanjutkan?",
+ "confirmations.edit.title": "Overwrite post?",
"confirmations.logout.confirm": "Keluar",
"confirmations.logout.message": "Apakah Anda yakin ingin keluar?",
+ "confirmations.logout.title": "Log out?",
"confirmations.mute.confirm": "Bisukan",
"confirmations.redraft.confirm": "Hapus dan susun ulang",
"confirmations.redraft.message": "Apakah anda yakin ingin menghapus postingan ini dan menyusun ulang postingan ini? Favorit dan peningkatan akan hilang, dan balasan ke postingan asli tidak akan terhubung ke postingan manapun.",
+ "confirmations.redraft.title": "Delete & redraft post?",
"confirmations.reply.confirm": "Balas",
"confirmations.reply.message": "Membalas sekarang akan menimpa pesan yang sedang Anda buat. Anda yakin ingin melanjutkan?",
+ "confirmations.reply.title": "Delete & redraft post?",
"confirmations.unfollow.confirm": "Berhenti mengikuti",
"confirmations.unfollow.message": "Apakah Anda ingin berhenti mengikuti {name}?",
+ "confirmations.unfollow.title": "Unfollow user?",
+ "content_warning.hide": "Hide post",
+ "content_warning.show": "Show anyway",
"conversation.delete": "Hapus percakapan",
"conversation.mark_as_read": "Tandai sudah dibaca",
"conversation.open": "Lihat percakapan",
@@ -217,7 +230,9 @@
"domain_pill.username": "Nama pengguna",
"domain_pill.whats_in_a_handle": "Apa itu nama pengguna?",
"domain_pill.who_they_are": "Karena nama pengguna menunjukkan siapa seseorang dan di mana server mereka berada, anda dapat berinteraksi dengan orang-orang di seluruh web sosial
ActivityPub-powered platforms.",
+ "domain_pill.who_you_are": "
ActivityPub-powered platforms.",
"domain_pill.your_handle": "Nama pengguna anda:",
+ "domain_pill.your_server": "Your digital home, where all of your posts live. Don’t like this one? Transfer servers at any time and bring your followers, too.",
"embed.instructions": "Sematkan kiriman ini di situs web Anda dengan menyalin kode di bawah ini.",
"embed.preview": "Tampilan akan seperti ini nantinya:",
"emoji_button.activity": "Aktivitas",
@@ -366,8 +381,6 @@
"keyboard_shortcuts.unfocus": "untuk tidak fokus pada area teks/pencarian",
"keyboard_shortcuts.up": "untuk memindah ke atas pada daftar",
"lightbox.close": "Tutup",
- "lightbox.compress": "Kompres kotak tampilan gambar",
- "lightbox.expand": "Besarkan kotak tampilan gambar",
"lightbox.next": "Selanjutnya",
"lightbox.previous": "Sebelumnya",
"limited_account_hint.action": "Tetap tampilkan profil",
@@ -388,7 +401,6 @@
"lists.subheading": "Daftar Anda",
"load_pending": "{count, plural, other {# item baru}}",
"loading_indicator.label": "Memuat…",
- "media_gallery.toggle_visible": "Tampil/Sembunyikan",
"moved_to_account_banner.text": "Akun {disabledAccount} Anda kini dinonaktifkan karena Anda pindah ke {movedToAccount}.",
"mute_modal.hide_options": "Sembunyikan opsi",
"mute_modal.title": "Bisukan pengguna?",
@@ -569,7 +581,6 @@
"status.detailed_status": "Tampilan detail percakapan",
"status.edit": "Edit",
"status.edited_x_times": "Diedit {count, plural, other {{count} kali}}",
- "status.embed": "Tanam",
"status.filter": "Saring kiriman ini",
"status.history.created": "{name} membuat {date}",
"status.history.edited": "{name} mengedit {date}",
diff --git a/app/javascript/mastodon/locales/ie.json b/app/javascript/mastodon/locales/ie.json
index 4002767cf9..1439b851d3 100644
--- a/app/javascript/mastodon/locales/ie.json
+++ b/app/javascript/mastodon/locales/ie.json
@@ -396,8 +396,6 @@
"keyboard_shortcuts.unfocus": "Desinfocar text-area de composition/serchar",
"keyboard_shortcuts.up": "Mover ad-supra in li liste",
"lightbox.close": "Cluder",
- "lightbox.compress": "Compresser vise-buxe de image",
- "lightbox.expand": "Expander vise-buxe de image",
"lightbox.next": "Sequent",
"lightbox.previous": "Precedent",
"limited_account_hint.action": "Monstrar profil totvez",
@@ -419,7 +417,6 @@
"lists.subheading": "Tui listes",
"load_pending": "{count, plural, one {# nov element} other {# nov elementes}}",
"loading_indicator.label": "Cargant…",
- "media_gallery.toggle_visible": "{number, plural, one {Celar image} other {Celar images}}",
"moved_to_account_banner.text": "Tui conto {disabledAccount} es actualmen desactivisat pro que tu movet te a {movedToAccount}.",
"mute_modal.hide_from_notifications": "Celar de notificationes",
"mute_modal.hide_options": "Celar optiones",
@@ -699,7 +696,6 @@
"status.edit": "Modificar",
"status.edited": "Ultimmen actualisat ye {date}",
"status.edited_x_times": "Modificat {count, plural, one {{count} vez} other {{count} vezes}}",
- "status.embed": "Inbedar",
"status.favourite": "Favoritisar",
"status.favourites": "{count, plural, one {favorit} other {favorites}}",
"status.filter": "Filtrar ti-ci posta",
diff --git a/app/javascript/mastodon/locales/intl_provider.tsx b/app/javascript/mastodon/locales/intl_provider.tsx
index 68d4fcbd96..94372f95b0 100644
--- a/app/javascript/mastodon/locales/intl_provider.tsx
+++ b/app/javascript/mastodon/locales/intl_provider.tsx
@@ -17,7 +17,7 @@ function onProviderError(error: unknown) {
error &&
typeof error === 'object' &&
error instanceof Error &&
- error.message.match('MISSING_DATA')
+ /MISSING_DATA/.exec(error.message)
) {
console.warn(error.message);
}
diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json
index 1329875185..aa284685e7 100644
--- a/app/javascript/mastodon/locales/io.json
+++ b/app/javascript/mastodon/locales/io.json
@@ -339,8 +339,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"lightbox.close": "Klozar",
- "lightbox.compress": "Kompresez imajvidbuxo",
- "lightbox.expand": "Expansez imajvidbuxo",
"lightbox.next": "Nexta",
"lightbox.previous": "Antea",
"limited_account_hint.action": "Jus montrez profilo",
@@ -362,7 +360,6 @@
"lists.subheading": "Vua listi",
"load_pending": "{count, plural, one {# nova kozo} other {# nova kozi}}",
"loading_indicator.label": "Kargante…",
- "media_gallery.toggle_visible": "Chanjar videbleso",
"moved_to_account_banner.text": "Vua konto {disabledAccount} es nune desaktiva pro ke vu movis a {movedToAccount}.",
"navigation_bar.about": "Pri co",
"navigation_bar.advanced_interface": "Apertez per retintervizajo",
@@ -590,7 +587,6 @@
"status.direct_indicator": "Privata menciono",
"status.edit": "Modifikez",
"status.edited_x_times": "Modifikesis {count, plural, one {{count} foyo} other {{count} foyi}}",
- "status.embed": "Eninsertez",
"status.favourite": "Favorizar",
"status.filter": "Filtragez ca posto",
"status.history.created": "{name} kreis ye {date}",
diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json
index e4e21649cc..5f32b438dd 100644
--- a/app/javascript/mastodon/locales/is.json
+++ b/app/javascript/mastodon/locales/is.json
@@ -97,6 +97,8 @@
"block_modal.title": "Útiloka notanda?",
"block_modal.you_wont_see_mentions": "Þú munt ekki sjá færslur sem minnast á viðkomandi aðila.",
"boost_modal.combo": "Þú getur ýtt á {combo} til að sleppa þessu næst",
+ "boost_modal.reblog": "Endurbirta færslu?",
+ "boost_modal.undo_reblog": "Taka færslu úr endurbirtingu?",
"bundle_column_error.copy_stacktrace": "Afrita villuskýrslu",
"bundle_column_error.error.body": "Umbeðna síðau var ekki hægt að myndgera. Það gæti verið vegna villu í kóðanum okkar eða vandamáls með samhæfni vafra.",
"bundle_column_error.error.title": "Ó-nei!",
@@ -430,13 +432,11 @@
"keyboard_shortcuts.unfocus": "Taka virkni úr textainnsetningarreit eða leit",
"keyboard_shortcuts.up": "Fara ofar í listanum",
"lightbox.close": "Loka",
- "lightbox.compress": "Þjappa myndskoðunarreit",
- "lightbox.expand": "Fletta út myndskoðunarreit",
"lightbox.next": "Næsta",
"lightbox.previous": "Fyrra",
"limited_account_hint.action": "Birta notandasniðið samt",
"limited_account_hint.title": "Þetta notandasnið hefur verið falið af umsjónarmönnum {domain}.",
- "link_preview.author": "Eftir {name}",
+ "link_preview.author": "Frá {name}",
"link_preview.more_from_author": "Meira frá {name}",
"link_preview.shares": "{count, plural, one {{counter} færsla} other {{counter} færslur}}",
"lists.account.add": "Bæta á lista",
@@ -455,7 +455,7 @@
"lists.subheading": "Listarnir þínir",
"load_pending": "{count, plural, one {# nýtt atriði} other {# ný atriði}}",
"loading_indicator.label": "Hleð inn…",
- "media_gallery.toggle_visible": "Víxla sýnileika",
+ "media_gallery.hide": "Fela",
"moved_to_account_banner.text": "Aðgangurinn þinn {disabledAccount} er óvirkur í augnablikinu vegna þess að þú fluttir þig yfir á {movedToAccount}.",
"mute_modal.hide_from_notifications": "Fela úr tilkynningum",
"mute_modal.hide_options": "Fela valkosti",
@@ -467,6 +467,7 @@
"mute_modal.you_wont_see_mentions": "Þú munt ekki sjá færslur sem minnast á viðkomandi aðila.",
"mute_modal.you_wont_see_posts": "Viðkomandi geta áfram séð færslurnar þínar en þú munt ekki sjá færslurnar þeirra.",
"navigation_bar.about": "Um hugbúnaðinn",
+ "navigation_bar.administration": "Stjórnun",
"navigation_bar.advanced_interface": "Opna í ítarlegu vefviðmóti",
"navigation_bar.blocks": "Útilokaðir notendur",
"navigation_bar.bookmarks": "Bókamerki",
@@ -483,6 +484,7 @@
"navigation_bar.follows_and_followers": "Fylgist með og fylgjendur",
"navigation_bar.lists": "Listar",
"navigation_bar.logout": "Útskráning",
+ "navigation_bar.moderation": "Umsjón",
"navigation_bar.mutes": "Þaggaðir notendur",
"navigation_bar.opened_in_classic_interface": "Færslur, notendaaðgangar og aðrar sérhæfðar síður eru sjálfgefið opnaðar í klassíska vefviðmótinu.",
"navigation_bar.personal": "Einka",
@@ -555,8 +557,6 @@
"notifications.column_settings.admin.report": "Nýjar kærur:",
"notifications.column_settings.admin.sign_up": "Nýjar skráningar:",
"notifications.column_settings.alert": "Tilkynningar á skjáborði",
- "notifications.column_settings.beta.category": "Eiginleikar á tilraunastigi",
- "notifications.column_settings.beta.grouping": "Tilkynningar hópa",
"notifications.column_settings.favourite": "Eftirlæti:",
"notifications.column_settings.filter_bar.advanced": "Birta alla flokka",
"notifications.column_settings.filter_bar.category": "Skyndisíustika",
@@ -776,6 +776,7 @@
"status.bookmark": "Bókamerki",
"status.cancel_reblog_private": "Taka úr endurbirtingu",
"status.cannot_reblog": "Þessa færslu er ekki hægt að endurbirta",
+ "status.continued_thread": "Hélt samtali áfram",
"status.copy": "Afrita tengil í færslu",
"status.delete": "Eyða",
"status.detailed_status": "Nákvæm spjallþráðasýn",
@@ -784,7 +785,7 @@
"status.edit": "Breyta",
"status.edited": "Síðast breytt {date}",
"status.edited_x_times": "Breytt {count, plural, one {{count} sinni} other {{count} sinnum}}",
- "status.embed": "Ívefja",
+ "status.embed": "Ná í innfellanlegan kóða",
"status.favourite": "Eftirlæti",
"status.favourites": "{count, plural, one {eftirlæti} other {eftirlæti}}",
"status.filter": "Sía þessa færslu",
@@ -809,6 +810,7 @@
"status.reblogs.empty": "Enginn hefur ennþá endurbirt þessa færslu. Þegar einhver gerir það, mun það birtast hér.",
"status.redraft": "Eyða og endurvinna drög",
"status.remove_bookmark": "Fjarlægja bókamerki",
+ "status.replied_in_thread": "Svaraði í samtali",
"status.replied_to": "Svaraði til {name}",
"status.reply": "Svara",
"status.replyAll": "Svara þræði",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index 8e3082359e..ec26d80be6 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -97,6 +97,8 @@
"block_modal.title": "Bloccare l'utente?",
"block_modal.you_wont_see_mentions": "Non vedrai i post che li menzionano.",
"boost_modal.combo": "Puoi premere {combo} per saltare questo passaggio, la prossima volta",
+ "boost_modal.reblog": "Condividere il post?",
+ "boost_modal.undo_reblog": "Annullare la condivisione del post?",
"bundle_column_error.copy_stacktrace": "Copia rapporto sull'errore",
"bundle_column_error.error.body": "Impossibile rendedrizzare la pagina richiesta. Potrebbe dipendere da un bug nel nostro codice o da un problema di compatibilità di un browser.",
"bundle_column_error.error.title": "Oh, no!",
@@ -125,7 +127,7 @@
"column.firehose": "Feed dal vivo",
"column.follow_requests": "Richieste di seguirti",
"column.home": "Home",
- "column.lists": "Elenchi",
+ "column.lists": "Liste",
"column.mutes": "Utenti silenziati",
"column.notifications": "Notifiche",
"column.pins": "Post fissati",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Rimuove il focus sull'area di composizione testuale/ricerca",
"keyboard_shortcuts.up": "Scorre in su nell'elenco",
"lightbox.close": "Chiudi",
- "lightbox.compress": "Comprimi casella di visualizzazione immagine",
- "lightbox.expand": "Espandi casella di visualizzazione immagine",
"lightbox.next": "Successivo",
"lightbox.previous": "Precedente",
+ "lightbox.zoom_in": "Ingrandisci alla dimensione attuale",
+ "lightbox.zoom_out": "Ingrandisci per adattarsi",
"limited_account_hint.action": "Mostra comunque il profilo",
"limited_account_hint.title": "Questo profilo è stato nascosto dai moderatori di {domain}.",
"link_preview.author": "Di {name}",
@@ -452,10 +454,10 @@
"lists.replies_policy.none": "Nessuno",
"lists.replies_policy.title": "Mostra risposte a:",
"lists.search": "Cerca tra le persone che segui",
- "lists.subheading": "I tuoi elenchi",
+ "lists.subheading": "Le tue liste",
"load_pending": "{count, plural, one {# nuovo oggetto} other {# nuovi oggetti}}",
"loading_indicator.label": "Caricamento…",
- "media_gallery.toggle_visible": "{number, plural, one {Nascondi immagine} other {Nascondi immagini}}",
+ "media_gallery.hide": "Nascondi",
"moved_to_account_banner.text": "Il tuo profilo {disabledAccount} è correntemente disabilitato perché ti sei spostato a {movedToAccount}.",
"mute_modal.hide_from_notifications": "Nascondi dalle notifiche",
"mute_modal.hide_options": "Nascondi le opzioni",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Non vedrai i post che li menzionano.",
"mute_modal.you_wont_see_posts": "Possono ancora vedere i tuoi post, ma tu non vedrai i loro.",
"navigation_bar.about": "Info",
+ "navigation_bar.administration": "Amministrazione",
"navigation_bar.advanced_interface": "Apri nell'interfaccia web avanzata",
"navigation_bar.blocks": "Utenti bloccati",
"navigation_bar.bookmarks": "Segnalibri",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Seguiti e seguaci",
"navigation_bar.lists": "Liste",
"navigation_bar.logout": "Disconnettiti",
+ "navigation_bar.moderation": "Moderazione",
"navigation_bar.mutes": "Utenti silenziati",
"navigation_bar.opened_in_classic_interface": "Post, account e altre pagine specifiche sono aperti per impostazione predefinita nella classica interfaccia web.",
"navigation_bar.personal": "Personale",
@@ -555,8 +559,6 @@
"notifications.column_settings.admin.report": "Nuove segnalazioni:",
"notifications.column_settings.admin.sign_up": "Nuove iscrizioni:",
"notifications.column_settings.alert": "Notifiche desktop",
- "notifications.column_settings.beta.category": "Funzioni sperimentali",
- "notifications.column_settings.beta.grouping": "Notifiche di gruppo",
"notifications.column_settings.favourite": "Preferiti:",
"notifications.column_settings.filter_bar.advanced": "Mostra tutte le categorie",
"notifications.column_settings.filter_bar.category": "Barra del filtro veloce",
@@ -776,6 +778,7 @@
"status.bookmark": "Aggiungi segnalibro",
"status.cancel_reblog_private": "Annulla reblog",
"status.cannot_reblog": "Questo post non può essere condiviso",
+ "status.continued_thread": "Discussione continua",
"status.copy": "Copia link al post",
"status.delete": "Elimina",
"status.detailed_status": "Vista conversazione dettagliata",
@@ -784,7 +787,7 @@
"status.edit": "Modifica",
"status.edited": "Ultima modifica {date}",
"status.edited_x_times": "Modificato {count, plural, one {{count} volta} other {{count} volte}}",
- "status.embed": "Incorpora",
+ "status.embed": "Ottieni codice incorporato",
"status.favourite": "Preferito",
"status.favourites": "{count, plural, one {preferito} other {preferiti}}",
"status.filter": "Filtra questo post",
@@ -809,6 +812,7 @@
"status.reblogs.empty": "Ancora nessuno ha rebloggato questo post. Quando qualcuno lo farà, apparirà qui.",
"status.redraft": "Elimina e riscrivi",
"status.remove_bookmark": "Rimuovi segnalibro",
+ "status.replied_in_thread": "Ha risposto nella discussione",
"status.replied_to": "Risposta a {name}",
"status.reply": "Rispondi",
"status.replyAll": "Rispondi alla conversazione",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index c23c2f87d5..c3ddeed880 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -97,6 +97,8 @@
"block_modal.title": "ユーザーをブロックしますか?",
"block_modal.you_wont_see_mentions": "宛先に相手が入っている投稿も閲覧できなくなります。",
"boost_modal.combo": "次からは{combo}を押せばスキップできます",
+ "boost_modal.reblog": "ブーストしますか?",
+ "boost_modal.undo_reblog": "ブーストを解除しますか?",
"bundle_column_error.copy_stacktrace": "エラーレポートをコピー",
"bundle_column_error.error.body": "要求されたページをレンダリングできませんでした。コードのバグ、またはブラウザの互換性の問題が原因である可能性があります。",
"bundle_column_error.error.title": "おっと!",
@@ -170,21 +172,30 @@
"confirmations.block.confirm": "ブロック",
"confirmations.delete.confirm": "削除",
"confirmations.delete.message": "本当に削除しますか?",
+ "confirmations.delete.title": "投稿を削除しようとしています",
"confirmations.delete_list.confirm": "削除",
"confirmations.delete_list.message": "本当にこのリストを完全に削除しますか?",
+ "confirmations.delete_list.title": "リストを削除しようとしています",
"confirmations.discard_edit_media.confirm": "破棄",
"confirmations.discard_edit_media.message": "メディアの説明またはプレビューに保存されていない変更があります。それでも破棄しますか?",
"confirmations.edit.confirm": "編集",
"confirmations.edit.message": "今編集すると現在作成中のメッセージが上書きされます。本当に実行しますか?",
+ "confirmations.edit.title": "作成中の内容を上書きしようとしています",
"confirmations.logout.confirm": "ログアウト",
"confirmations.logout.message": "本当にログアウトしますか?",
+ "confirmations.logout.title": "ログアウトしようとしています",
"confirmations.mute.confirm": "ミュート",
"confirmations.redraft.confirm": "削除して下書きに戻す",
"confirmations.redraft.message": "投稿を削除して下書きに戻します。この投稿へのお気に入り登録やブーストは失われ、返信は孤立することになります。よろしいですか?",
+ "confirmations.redraft.title": "投稿の削除と下書きの再作成",
"confirmations.reply.confirm": "返信",
"confirmations.reply.message": "今返信すると現在作成中のメッセージが上書きされます。本当に実行しますか?",
+ "confirmations.reply.title": "作成中の内容を上書きしようとしています",
"confirmations.unfollow.confirm": "フォロー解除",
"confirmations.unfollow.message": "本当に{name}さんのフォローを解除しますか?",
+ "confirmations.unfollow.title": "フォローを解除しようとしています",
+ "content_warning.hide": "内容を隠す",
+ "content_warning.show": "承知の上で表示",
"conversation.delete": "会話を削除",
"conversation.mark_as_read": "既読にする",
"conversation.open": "会話を表示",
@@ -292,6 +303,7 @@
"filter_modal.select_filter.subtitle": "既存のカテゴリーを使用するか新規作成します",
"filter_modal.select_filter.title": "この投稿をフィルターする",
"filter_modal.title.status": "投稿をフィルターする",
+ "filter_warning.matches_filter": "フィルター「{title}」に一致する投稿です",
"filtered_notifications_banner.pending_requests": "{count, plural, =0 {すべて完了しました} other {#人の通知がブロックされています}}",
"filtered_notifications_banner.title": "保留中の通知",
"firehose.all": "すべて",
@@ -341,6 +353,14 @@
"hashtag.follow": "ハッシュタグをフォローする",
"hashtag.unfollow": "ハッシュタグのフォローを解除",
"hashtags.and_other": "ほか{count, plural, other {#個}}",
+ "hints.profiles.followers_may_be_missing": "フォロワーの一覧は不正確な場合があります。",
+ "hints.profiles.follows_may_be_missing": "フォローの一覧は不正確な場合があります。",
+ "hints.profiles.posts_may_be_missing": "すべての投稿を表示できていない場合があります。",
+ "hints.profiles.see_more_followers": "{domain} で正確な情報を見る",
+ "hints.profiles.see_more_follows": "{domain} で正確な情報を見る",
+ "hints.profiles.see_more_posts": "{domain} でその他の投稿を見る",
+ "hints.threads.replies_may_be_missing": "リモートの返信は表示されない場合があります。",
+ "hints.threads.see_more": "{domain} でその他の返信を見る",
"home.column_settings.show_reblogs": "ブースト表示",
"home.column_settings.show_replies": "返信表示",
"home.hide_announcements": "お知らせを隠す",
@@ -348,6 +368,17 @@
"home.pending_critical_update.link": "詳細",
"home.pending_critical_update.title": "緊急のセキュリティアップデートがあります",
"home.show_announcements": "お知らせを表示",
+ "ignore_notifications_modal.disclaimer": "通知が無視されていることは通知の送信元の相手には伝わりません。通知が破棄されるのみで、投稿や返信の送信を止めさせる効果はありません。",
+ "ignore_notifications_modal.filter_instead": "「保留」に設定",
+ "ignore_notifications_modal.filter_to_act_users": "保留された通知は「受け入れ」「無視」を選択できます。当該ユーザーの通報も可能です",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "通知の破棄による意図しない混乱を避けるためにも、「保留」設定の使用を検討してください",
+ "ignore_notifications_modal.filter_to_review_separately": "「保留」設定を使用することで、保留された通知を個別に確認できます",
+ "ignore_notifications_modal.ignore": "「無視」に設定",
+ "ignore_notifications_modal.limited_accounts_title": "本当に「モデレーションされたアカウントからの通知」を無視するようにしますか?",
+ "ignore_notifications_modal.new_accounts_title": "本当に「新しいアカウントからの通知」を無視するようにしますか?",
+ "ignore_notifications_modal.not_followers_title": "本当に「フォローされていないアカウントからの通知」を無視するようにしますか?",
+ "ignore_notifications_modal.not_following_title": "本当に「フォローしていないアカウントからの通知」を無視するようにしますか?",
+ "ignore_notifications_modal.private_mentions_title": "本当に「外部からの非公開の返信」を無視するようにしますか?",
"interaction_modal.description.favourite": "Mastodonのアカウントがあれば投稿をお気に入り登録して投稿者に気持ちを伝えたり、あとで見返すことができます。",
"interaction_modal.description.follow": "Mastodonのアカウントで{name}さんをフォローしてホームフィードで投稿を受け取れます。",
"interaction_modal.description.reblog": "Mastodonのアカウントでこの投稿をブーストして自分のフォロワーに共有できます。",
@@ -401,10 +432,10 @@
"keyboard_shortcuts.unfocus": "投稿の入力欄・検索欄から離れる",
"keyboard_shortcuts.up": "カラム内一つ上に移動",
"lightbox.close": "閉じる",
- "lightbox.compress": "画像ビューボックスを閉じる",
- "lightbox.expand": "画像ビューボックスを開く",
"lightbox.next": "次",
"lightbox.previous": "前",
+ "lightbox.zoom_in": "実際のサイズにする",
+ "lightbox.zoom_out": "表示範囲に合わせる",
"limited_account_hint.action": "構わず表示する",
"limited_account_hint.title": "このプロフィールは{domain}のモデレーターによって非表示にされています。",
"link_preview.author": "{name}",
@@ -426,7 +457,7 @@
"lists.subheading": "あなたのリスト",
"load_pending": "{count}件の新着",
"loading_indicator.label": "読み込み中…",
- "media_gallery.toggle_visible": "{number, plural, one {画像を閉じる} other {画像を閉じる}}",
+ "media_gallery.hide": "隠す",
"moved_to_account_banner.text": "あなたのアカウント『{disabledAccount}』は『{movedToAccount}』に移動したため現在無効になっています。",
"mute_modal.hide_from_notifications": "通知をオフにする",
"mute_modal.hide_options": "オプションを閉じる",
@@ -438,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "宛先に相手が入っている投稿も閲覧できなくなります。",
"mute_modal.you_wont_see_posts": "相手はあなたの投稿を今までどおり閲覧できますが、あなたは相手の投稿を閲覧できなくなります。",
"navigation_bar.about": "概要",
+ "navigation_bar.administration": "管理",
"navigation_bar.advanced_interface": "上級者向けUIに戻る",
"navigation_bar.blocks": "ブロックしたユーザー",
"navigation_bar.bookmarks": "ブックマーク",
@@ -454,6 +486,7 @@
"navigation_bar.follows_and_followers": "フォロー・フォロワー",
"navigation_bar.lists": "リスト",
"navigation_bar.logout": "ログアウト",
+ "navigation_bar.moderation": "モデレーション",
"navigation_bar.mutes": "ミュートしたユーザー",
"navigation_bar.opened_in_classic_interface": "投稿やプロフィールを直接開いた場合は一時的に標準UIで表示されます。",
"navigation_bar.personal": "個人用",
@@ -469,9 +502,18 @@
"notification.admin.report_statuses": "{name}さんが{target}さんを「{category}」として通報しました",
"notification.admin.report_statuses_other": "{name}さんが{target}さんを通報しました",
"notification.admin.sign_up": "{name}さんがサインアップしました",
+ "notification.admin.sign_up.name_and_others": "{name}さんほか{count, plural, other {#人}}がサインアップしました",
"notification.favourite": "{name}さんがお気に入りしました",
+ "notification.favourite.name_and_others_with_link": "{name}さん
ほか{count, plural, other {#人}}がお気に入りしました",
"notification.follow": "{name}さんにフォローされました",
+ "notification.follow.name_and_others": "{name}さんほか{count, plural, other {#人}}にフォローされました",
"notification.follow_request": "{name}さんがあなたにフォローリクエストしました",
+ "notification.follow_request.name_and_others": "{name}さんほか{count, plural, other {#人}}があなたにフォローリクエストしました",
+ "notification.label.mention": "メンション",
+ "notification.label.private_mention": "非公開の返信 (メンション)",
+ "notification.label.private_reply": "非公開の返信",
+ "notification.label.reply": "返信",
+ "notification.mention": "メンション",
"notification.moderation-warning.learn_more": "さらに詳しく",
"notification.moderation_warning": "管理者から警告が来ています",
"notification.moderation_warning.action_delete_statuses": "あなたによるいくつかの投稿が削除されました。",
@@ -484,6 +526,7 @@
"notification.own_poll": "アンケートが終了しました",
"notification.poll": "投票したアンケートが終了しました",
"notification.reblog": "{name}さんがあなたの投稿をブーストしました",
+ "notification.reblog.name_and_others_with_link": "{name}さん
ほか{count, plural, other {#人}}にブーストされました",
"notification.relationships_severance_event": "{name} との関係が失われました",
"notification.relationships_severance_event.account_suspension": "{from} の管理者が {target} さんを停止したため、今後このユーザーとの交流や新しい投稿の受け取りができなくなりました。",
"notification.relationships_severance_event.domain_block": "{from} の管理者が {target} をブロックしました。これにより{followersCount}フォロワーと{followingCount, plural, other {#フォロー}}が失われました。",
@@ -492,17 +535,30 @@
"notification.status": "{name}さんが投稿しました",
"notification.update": "{name}さんが投稿を編集しました",
"notification_requests.accept": "受け入れる",
+ "notification_requests.accept_multiple": "{count, plural, other {選択中の#件を受け入れる}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, other {#件のアカウントを受け入れる}}",
+ "notification_requests.confirm_accept_multiple.message": "{count, plural, other {#件のアカウント}}に対して今後通知を受け入れるようにします。よろしいですか?",
+ "notification_requests.confirm_accept_multiple.title": "保留中のアカウントの受け入れ",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, other {#件のアカウントを無視する}}",
+ "notification_requests.confirm_dismiss_multiple.message": "{count, plural, other {#件のアカウント}}からの通知を今後無視するようにします。一度この操作を行った{count, plural, other {アカウント}}とふたたび出会うことは容易ではありません。よろしいですか?",
+ "notification_requests.confirm_dismiss_multiple.title": "保留中のアカウントを無視しようとしています",
"notification_requests.dismiss": "無視",
+ "notification_requests.dismiss_multiple": "{count, plural, other {選択中の#件を無視する}}",
+ "notification_requests.edit_selection": "選択",
+ "notification_requests.exit_selection": "選択の終了",
+ "notification_requests.explainer_for_limited_account": "このアカウントはモデレーターにより制限が課されているため、このアカウントによる通知は保留されています",
+ "notification_requests.explainer_for_limited_remote_account": "このアカウントが所属するサーバーはモデレーターにより制限が課されているため、このアカウントによる通知は保留されています",
+ "notification_requests.maximize": "最大化",
"notification_requests.minimize_banner": "「保留中の通知」のバナーを最小化する",
"notification_requests.notifications_from": "{name}からの通知",
"notification_requests.title": "保留中の通知",
+ "notification_requests.view": "通知を見る",
"notifications.clear": "通知を消去",
"notifications.clear_confirmation": "本当に通知を消去しますか?",
+ "notifications.clear_title": "通知を消去しようとしています",
"notifications.column_settings.admin.report": "新しい通報:",
"notifications.column_settings.admin.sign_up": "新規登録:",
"notifications.column_settings.alert": "デスクトップ通知",
- "notifications.column_settings.beta.category": "実験段階の機能",
- "notifications.column_settings.beta.grouping": "通知をグループにまとめる",
"notifications.column_settings.favourite": "お気に入り:",
"notifications.column_settings.filter_bar.advanced": "すべてのカテゴリを表示",
"notifications.column_settings.filter_bar.category": "クイックフィルターバー:",
@@ -545,7 +601,7 @@
"notifications.policy.filter_not_followers_title": "フォローされていないアカウントからの通知",
"notifications.policy.filter_not_following_hint": "手動で通知を受け入れたアカウントは対象外です",
"notifications.policy.filter_not_following_title": "フォローしていないアカウントからの通知",
- "notifications.policy.filter_private_mentions_hint": "あなたがメンションした相手からの返信、およびフォローしているアカウントからの返信は対象外です",
+ "notifications.policy.filter_private_mentions_hint": "メンションした相手からの返信、およびフォローしているアカウントからの返信は対象外です",
"notifications.policy.filter_private_mentions_title": "外部からの非公開の返信",
"notifications.policy.title": "通知のフィルタリング",
"notifications_permission_banner.enable": "デスクトップ通知を有効にする",
@@ -730,7 +786,7 @@
"status.edit": "編集",
"status.edited": "最終更新日 {date}",
"status.edited_x_times": "{count}回編集",
- "status.embed": "埋め込み",
+ "status.embed": "埋め込みコードを取得",
"status.favourite": "お気に入り",
"status.favourites": "{count, plural, one {お気に入り} other {お気に入り}}",
"status.filter": "この投稿をフィルターする",
diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json
index 5713fe60ee..fc0ed0730d 100644
--- a/app/javascript/mastodon/locales/ka.json
+++ b/app/javascript/mastodon/locales/ka.json
@@ -153,7 +153,6 @@
"lists.new.title_placeholder": "ახალი სიის სათაური",
"lists.search": "ძებნა ადამიანებს შორის რომელთაც მიჰყვებით",
"lists.subheading": "თქვენი სიები",
- "media_gallery.toggle_visible": "ხილვადობის ჩართვა",
"navigation_bar.blocks": "დაბლოკილი მომხმარებლები",
"navigation_bar.community_timeline": "ლოკალური თაიმლაინი",
"navigation_bar.compose": "Compose new toot",
@@ -223,7 +222,6 @@
"status.copy": "Copy link to status",
"status.delete": "წაშლა",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "ჩართვა",
"status.load_more": "მეტის ჩატვირთვა",
"status.media_hidden": "მედია დამალულია",
"status.mention": "ასახელე @{name}",
diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json
index c5c0fa94c1..89f68ab95f 100644
--- a/app/javascript/mastodon/locales/kab.json
+++ b/app/javascript/mastodon/locales/kab.json
@@ -2,12 +2,14 @@
"about.blocks": "Ulac agbur",
"about.contact": "Anermis:",
"about.disclaimer": "Mastodon d aseɣẓan ilelli, d aseɣẓan n uɣbalu yeldin, d tnezzut n Mastodon gGmbH.",
+ "about.domain_blocks.no_reason_available": "Ulac taɣẓint",
"about.domain_blocks.preamble": "Maṣṭudun s umata yeḍmen-ak ad teẓreḍ agbur, ad tesdemreḍ akked yimseqdacen-nniḍen seg yal aqeddac deg fedivers. Ha-tent-an ɣur-k tsuraf i yellan deg uqeddac-agi.",
"about.domain_blocks.silenced.title": "Ɣur-s talast",
"about.domain_blocks.suspended.title": "Yeḥbes",
"about.not_available": "Talɣut-a ur tettwabder ara deg uqeddac-a.",
"about.powered_by": "Azeṭṭa inmetti yettwasɣelsen sɣur {mastodon}",
"about.rules": "Ilugan n uqeddac",
+ "account.account_note_header": "Tamawt tudmawant",
"account.add_or_remove_from_list": "Rnu neɣ kkes seg tebdarin",
"account.badges.bot": "Aṛubut",
"account.badges.group": "Agraw",
@@ -46,6 +48,7 @@
"account.mute_notifications_short": "Susem alɣuten",
"account.mute_short": "Sgugem",
"account.muted": "Yettwasgugem",
+ "account.mutual": "Temṭafarem",
"account.no_bio": "Ulac aglam i d-yettunefken.",
"account.open_original_page": "Ldi asebter anasli",
"account.posts": "Tisuffaɣ",
@@ -62,6 +65,7 @@
"account.unendorse": "Ur ttwellih ara fell-as deg umaɣnu-inek",
"account.unfollow": "Ur ṭṭafaṛ ara",
"account.unmute": "Kkes asgugem ɣef @{name}",
+ "account.unmute_notifications_short": "Serreḥ i yilɣa",
"account.unmute_short": "Kkes asgugem",
"account_note.placeholder": "Ulac iwenniten",
"admin.dashboard.retention.cohort_size": "Iseqdacen imaynuten",
@@ -78,6 +82,7 @@
"block_modal.title": "Sewḥel aseqdac ?",
"block_modal.you_wont_see_mentions": "Ur tezmireḍ ara ad twaliḍ tisuffaɣ anda d-yettwabdar.",
"boost_modal.combo": "Tzemreḍ ad tsiteḍ ɣef {combo} akken ad tzegleḍ aya tikelt i d-iteddun",
+ "boost_modal.reblog": "Zuzer tasuffeɣt?",
"bundle_column_error.copy_stacktrace": "Nɣel tuccḍa n uneqqis",
"bundle_column_error.error.title": "Uh, ala !",
"bundle_column_error.network.title": "Tuccḍa deg uẓeṭṭa",
@@ -152,12 +157,15 @@
"confirmations.edit.message": "Abeddel tura ad d-yaru izen-nni i d-tegreḍ akka tura. Tetḥeqqeḍ tebɣiḍ ad tkemmleḍ?",
"confirmations.logout.confirm": "Ffeɣ",
"confirmations.logout.message": "D tidet tebɣiḍ ad teffɣeḍ?",
+ "confirmations.logout.title": "Tebɣiḍ ad teffɣeḍ ssya?",
"confirmations.mute.confirm": "Sgugem",
"confirmations.redraft.confirm": "Kkes sakin ɛiwed tira",
"confirmations.reply.confirm": "Err",
"confirmations.reply.message": "Tiririt akka tura ad k-degger izen-agi i tettaruḍ. Tebɣiḍ ad tkemmleḍ?",
"confirmations.unfollow.confirm": "Ur ḍḍafaṛ ara",
"confirmations.unfollow.message": "Tetḥeqqeḍ belli tebɣiḍ ur teṭafaṛeḍ ara {name}?",
+ "content_warning.hide": "Ffer tasuffeɣt",
+ "content_warning.show": "Ssken-d akken tebɣu tili",
"conversation.delete": "Kkes adiwenni",
"conversation.mark_as_read": "Creḍ yettwaɣṛa",
"conversation.open": "Ssken adiwenni",
@@ -183,7 +191,7 @@
"domain_pill.server": "Aqeddac",
"domain_pill.username": "Isem n useqdac",
"domain_pill.your_server": "D axxam-inek·inem umḍin, anda i zedɣent akk tsuffaɣ-ik·im. Ur k·m-yeεǧib ara wa? Ssenfel-d iqeddacen melmi i ak·m-yehwa, awi-d daɣen ineḍfaren-ik·im yid-k·m.",
- "embed.instructions": "Ẓẓu addad-agi deg usmel-inek s wenγal n tangalt yellan sdaw-agi.",
+ "embed.instructions": "Ẓẓu addad-agi deg usmel-inek·inem s wenɣal n tangalt yellan sdaw-agi.",
"embed.preview": "Akka ara d-iban:",
"emoji_button.activity": "Aqeddic",
"emoji_button.clear": "Sfeḍ",
@@ -325,8 +333,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "i tulin ɣer d asawen n tebdart",
"lightbox.close": "Mdel",
- "lightbox.compress": "Ḥemmeẓ tamnaḍt n uskan n tugna",
- "lightbox.expand": "Simeɣer tamnaḍt n uskan n tugna",
"lightbox.next": "Ɣer zdat",
"lightbox.previous": "Ɣer deffir",
"limited_account_hint.action": "Wali amaɣnu akken yebɣu yili",
@@ -349,7 +355,7 @@
"lists.subheading": "Tibdarin-ik·im",
"load_pending": "{count, plural, one {# n uferdis amaynut} other {# n yiferdisen imaynuten}}",
"loading_indicator.label": "Yessalay-d …",
- "media_gallery.toggle_visible": "{number, plural, one {Ffer tugna} other {Ffer tugniwin}}",
+ "media_gallery.hide": "Seggelmes",
"mute_modal.hide_from_notifications": "Ffer-it deg ulɣuten",
"mute_modal.hide_options": "Ffer tinefrunin",
"mute_modal.indefinite": "Alamma ssnesreɣ asgugem fell-as",
@@ -360,6 +366,7 @@
"mute_modal.you_wont_see_mentions": "Ur tezmireḍ ara ad twaliḍ tisuffaɣ anda d-yettwabdar.",
"mute_modal.you_wont_see_posts": "Yezmer ad yettwali tisuffaɣ-ik·im, maca ur tettwaliḍ ara tidak-is.",
"navigation_bar.about": "Ɣef",
+ "navigation_bar.administration": "Tadbelt",
"navigation_bar.advanced_interface": "Ldi deg ugrudem n web leqqayen",
"navigation_bar.blocks": "Iseqdacen yettusḥebsen",
"navigation_bar.bookmarks": "Ticraḍ",
@@ -390,6 +397,7 @@
"notification.favourite": "{name} yesmenyaf addad-ik·im",
"notification.follow": "iṭṭafar-ik·em-id {name}",
"notification.follow_request": "{name} yessuter-d ad k·m-yeḍfeṛ",
+ "notification.label.mention": "Abdar",
"notification.label.private_mention": "Abdar uslig",
"notification.label.private_reply": "Tiririt tusligt",
"notification.label.reply": "Tiririt",
@@ -402,12 +410,13 @@
"notification.status": "{name} akken i d-yessufeɣ",
"notification_requests.accept": "Qbel",
"notification_requests.dismiss": "Agi",
+ "notification_requests.edit_selection": "Ẓreg",
+ "notification_requests.exit_selection": "Immed",
"notification_requests.notifications_from": "Alɣuten sɣur {name}",
"notifications.clear": "Sfeḍ alɣuten",
"notifications.clear_confirmation": "Tebɣiḍ s tidet ad tekkseḍ akk alɣuten-inek·em i lebda?",
"notifications.column_settings.admin.report": "Ineqqisen imaynuten:",
"notifications.column_settings.alert": "Alɣuten n tnarit",
- "notifications.column_settings.beta.grouping": "Segrew alɣuten",
"notifications.column_settings.favourite": "Imenyafen:",
"notifications.column_settings.filter_bar.advanced": "Sken-d akk taggayin",
"notifications.column_settings.filter_bar.category": "Iri n usizdeg uzrib",
@@ -580,7 +589,7 @@
"status.direct_indicator": "Abdar uslig",
"status.edit": "Ẓreg",
"status.edited_x_times": "Tettwaẓreg {count, plural, one {{count} n tikkelt} other {{count} n tikkal}}",
- "status.embed": "Seddu",
+ "status.embed": "Awi-d tangalt n weslaɣ",
"status.favourite": "Amenyaf",
"status.favourites": "{count, plural, one {n usmenyaf} other {n ismenyafen}}",
"status.filter": "Sizdeg tassufeɣt-a",
diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json
index 85b2fdc005..f146fc652d 100644
--- a/app/javascript/mastodon/locales/kk.json
+++ b/app/javascript/mastodon/locales/kk.json
@@ -222,7 +222,6 @@
"lists.search": "Сіз іздеген адамдар арасында іздеу",
"lists.subheading": "Тізімдеріңіз",
"load_pending": "{count, plural, one {# жаңа нәрсе} other {# жаңа нәрсе}}",
- "media_gallery.toggle_visible": "Көрінуді қосу",
"navigation_bar.blocks": "Бұғатталғандар",
"navigation_bar.bookmarks": "Бетбелгілер",
"navigation_bar.community_timeline": "Жергілікті желі",
@@ -316,7 +315,6 @@
"status.delete": "Өшіру",
"status.detailed_status": "Толық пікірталас көрінісі",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "Embеd",
"status.load_more": "Тағы әкел",
"status.media_hidden": "Жабық медиа",
"status.mention": "Аталым @{name}",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index a5711c81cd..06ee33e2dc 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -34,9 +34,9 @@
"account.follow_back": "맞팔로우 하기",
"account.followers": "팔로워",
"account.followers.empty": "아직 아무도 이 사용자를 팔로우하고 있지 않습니다.",
- "account.followers_counter": "{count, plural, other {{counter} 팔로워}}",
+ "account.followers_counter": "{count, plural, other {팔로워 {counter}명}}",
"account.following": "팔로잉",
- "account.following_counter": "{count, plural, other {{counter} 팔로잉}}",
+ "account.following_counter": "{count, plural, other {팔로잉 {counter}명}}",
"account.follows.empty": "이 사용자는 아직 아무도 팔로우하고 있지 않습니다.",
"account.go_to_profile": "프로필로 이동",
"account.hide_reblogs": "@{name}의 부스트를 숨기기",
@@ -62,7 +62,7 @@
"account.requested_follow": "{name} 님이 팔로우 요청을 보냈습니다",
"account.share": "@{name}의 프로필 공유",
"account.show_reblogs": "@{name}의 부스트 보기",
- "account.statuses_counter": "{count, plural, other {{counter} 게시물}}",
+ "account.statuses_counter": "{count, plural, other {게시물 {counter}개}}",
"account.unblock": "차단 해제",
"account.unblock_domain": "도메인 {domain} 차단 해제",
"account.unblock_short": "차단 해제",
@@ -97,6 +97,8 @@
"block_modal.title": "사용자를 차단할까요?",
"block_modal.you_wont_see_mentions": "그를 멘션하는 게시물을 더는 보지 않습니다.",
"boost_modal.combo": "다음엔 {combo}를 눌러서 이 과정을 건너뛸 수 있습니다",
+ "boost_modal.reblog": "게시물을 부스트할까요?",
+ "boost_modal.undo_reblog": "게시물을 부스트 취소할까요?",
"bundle_column_error.copy_stacktrace": "에러 리포트 복사하기",
"bundle_column_error.error.body": "요청한 페이지를 렌더링 할 수 없습니다. 저희의 코드에 버그가 있거나, 브라우저 호환성 문제일 수 있습니다.",
"bundle_column_error.error.title": "으악, 안돼!",
@@ -154,7 +156,7 @@
"compose_form.placeholder": "지금 무슨 생각을 하고 있나요?",
"compose_form.poll.duration": "투표 기간",
"compose_form.poll.multiple": "다중 선택",
- "compose_form.poll.option_placeholder": "{option}번째 항목",
+ "compose_form.poll.option_placeholder": "{number}번째 옵션",
"compose_form.poll.single": "단일 선택",
"compose_form.poll.switch_to_multiple": "다중 선택이 가능한 투표로 변경",
"compose_form.poll.switch_to_single": "단일 선택 투표로 변경",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "팔로우 해제",
"confirmations.unfollow.message": "정말로 {name} 님을 팔로우 해제하시겠습니까?",
"confirmations.unfollow.title": "사용자를 언팔로우 할까요?",
+ "content_warning.hide": "게시물 숨기기",
+ "content_warning.show": "무시하고 보기",
"conversation.delete": "대화 삭제",
"conversation.mark_as_read": "읽은 상태로 표시",
"conversation.open": "대화 보기",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "기존의 카테고리를 사용하거나 새로 하나를 만듧니다",
"filter_modal.select_filter.title": "이 게시물을 필터",
"filter_modal.title.status": "게시물 필터",
+ "filter_warning.matches_filter": "\"{title}\" 필터에 걸림",
"filtered_notifications_banner.pending_requests": "알 수도 있는 {count, plural, =0 {0 명} one {한 명} other {# 명}}의 사람들로부터",
"filtered_notifications_banner.title": "걸러진 알림",
"firehose.all": "모두",
@@ -342,12 +347,12 @@
"hashtag.column_settings.tag_mode.any": "어느것이든",
"hashtag.column_settings.tag_mode.none": "이것들을 제외하고",
"hashtag.column_settings.tag_toggle": "추가 해시태그를 이 컬럼에 추가합니다",
- "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.follow": "팔로우",
- "hashtag.unfollow": "팔로우 해제",
- "hashtags.and_other": "…그리고 {count, plural,other {# 개 더}}",
+ "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.follow": "해시태그 팔로우",
+ "hashtag.unfollow": "해시태그 팔로우 해제",
+ "hashtags.and_other": "…및 {count, plural,other {#개}}",
"hints.profiles.followers_may_be_missing": "이 프로필의 팔로워 목록은 일부 누락되었을 수 있습니다.",
"hints.profiles.follows_may_be_missing": "이 프로필의 팔로우 목록은 일부 누락되었을 수 있습니다.",
"hints.profiles.posts_may_be_missing": "이 프로필의 게시물은 일부 누락되었을 수 있습니다.",
@@ -427,10 +432,10 @@
"keyboard_shortcuts.unfocus": "작성창에서 포커스 해제",
"keyboard_shortcuts.up": "리스트에서 위로 이동",
"lightbox.close": "닫기",
- "lightbox.compress": "이미지 박스 압축",
- "lightbox.expand": "이미지 박스 확장",
"lightbox.next": "다음",
"lightbox.previous": "이전",
+ "lightbox.zoom_in": "실제 크기에 맞춰 보기",
+ "lightbox.zoom_out": "화면 크기에 맞춰 보기",
"limited_account_hint.action": "그래도 프로필 보기",
"limited_account_hint.title": "이 프로필은 {domain}의 중재자에 의해 숨겨진 상태입니다.",
"link_preview.author": "{name}",
@@ -452,7 +457,7 @@
"lists.subheading": "리스트",
"load_pending": "{count, plural, other {#}} 개의 새 항목",
"loading_indicator.label": "불러오는 중...",
- "media_gallery.toggle_visible": "이미지 숨기기",
+ "media_gallery.hide": "숨기기",
"moved_to_account_banner.text": "당신의 계정 {disabledAccount}는 {movedToAccount}로 이동하였기 때문에 현재 비활성화 상태입니다.",
"mute_modal.hide_from_notifications": "알림에서 숨기기",
"mute_modal.hide_options": "옵션 숨기기",
@@ -464,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "그를 멘션하는 게시물을 더는 보지 않게 됩니다.",
"mute_modal.you_wont_see_posts": "내가 작성한 게시물을 볼 수는 있지만, 나는 그가 작성한 것을 보지 않게 됩니다.",
"navigation_bar.about": "정보",
+ "navigation_bar.administration": "관리",
"navigation_bar.advanced_interface": "고급 웹 인터페이스에서 열기",
"navigation_bar.blocks": "차단한 사용자",
"navigation_bar.bookmarks": "북마크",
@@ -480,6 +486,7 @@
"navigation_bar.follows_and_followers": "팔로우와 팔로워",
"navigation_bar.lists": "리스트",
"navigation_bar.logout": "로그아웃",
+ "navigation_bar.moderation": "중재",
"navigation_bar.mutes": "뮤트한 사용자",
"navigation_bar.opened_in_classic_interface": "게시물, 계정, 기타 특정 페이지들은 기본적으로 기존 웹 인터페이스로 열리게 됩니다.",
"navigation_bar.personal": "개인용",
@@ -495,9 +502,13 @@
"notification.admin.report_statuses": "{name} 님이 {target}을 {category}로 신고했습니다",
"notification.admin.report_statuses_other": "{name} 님이 {target}을 신고했습니다",
"notification.admin.sign_up": "{name} 님이 가입했습니다",
+ "notification.admin.sign_up.name_and_others": "{name} 외 {count, plural, other {# 명}}이 가입했습니다",
"notification.favourite": "{name} 님이 내 게시물을 좋아합니다",
+ "notification.favourite.name_and_others_with_link": "{name} 외
{count, plural, other {# 명}}이 내 게시물을 좋아합니다",
"notification.follow": "{name} 님이 나를 팔로우했습니다",
+ "notification.follow.name_and_others": "{name} 외 {count, plural, other {# 명}}이 날 팔로우 했습니다",
"notification.follow_request": "{name} 님이 팔로우 요청을 보냈습니다",
+ "notification.follow_request.name_and_others": "{name} 외 {count, plural, other {# 명}}이 나에게 팔로우 요청을 보냈습니다",
"notification.label.mention": "멘션",
"notification.label.private_mention": "개인 멘션",
"notification.label.private_reply": "개인 답글",
@@ -515,6 +526,7 @@
"notification.own_poll": "설문을 마침",
"notification.poll": "참여한 투표가 끝났습니다",
"notification.reblog": "{name} 님이 부스트했습니다",
+ "notification.reblog.name_and_others_with_link": "{name} 외
{count, plural, other {# 명}}이 내 게시물을 부스트했습니다",
"notification.relationships_severance_event": "{name} 님과의 연결이 끊어졌습니다",
"notification.relationships_severance_event.account_suspension": "{from}의 관리자가 {target}를 정지시켰기 때문에 그들과 더이상 상호작용 할 수 없고 정보를 받아볼 수 없습니다.",
"notification.relationships_severance_event.domain_block": "{from}의 관리자가 {target}를 차단하였고 여기에는 나의 {followersCount} 명의 팔로워와 {followingCount, plural, other {#}} 명의 팔로우가 포함되었습니다.",
@@ -547,8 +559,6 @@
"notifications.column_settings.admin.report": "새 신고:",
"notifications.column_settings.admin.sign_up": "새로운 가입:",
"notifications.column_settings.alert": "데스크탑 알림",
- "notifications.column_settings.beta.category": "실험적인 기능",
- "notifications.column_settings.beta.grouping": "알림 그룹화",
"notifications.column_settings.favourite": "좋아요:",
"notifications.column_settings.filter_bar.advanced": "모든 범주 표시",
"notifications.column_settings.filter_bar.category": "빠른 필터 막대",
@@ -593,7 +603,7 @@
"notifications.policy.filter_not_following_title": "내가 팔로우하지 않는 사람들",
"notifications.policy.filter_private_mentions_hint": "내가 한 멘션에 단 답글이거나 내가 발신자를 팔로우 한 것이 아닌 이상 걸러집니다",
"notifications.policy.filter_private_mentions_title": "청하지 않은 개인적인 멘션",
- "notifications.policy.title": "…의 알림 설정",
+ "notifications.policy.title": "알림 조건 설정",
"notifications_permission_banner.enable": "데스크탑 알림 활성화",
"notifications_permission_banner.how_to_control": "마스토돈이 열려 있지 않을 때에도 알림을 받으려면, 데스크탑 알림을 활성화 하세요. 당신은 어떤 종류의 반응이 데스크탑 알림을 발생할 지를 {icon} 버튼을 통해 세세하게 설정할 수 있습니다.",
"notifications_permission_banner.title": "아무것도 놓치지 마세요",
@@ -768,6 +778,7 @@
"status.bookmark": "북마크",
"status.cancel_reblog_private": "부스트 취소",
"status.cannot_reblog": "이 게시물은 부스트 할 수 없습니다",
+ "status.continued_thread": "이어지는 글타래",
"status.copy": "게시물 링크 복사",
"status.delete": "삭제",
"status.detailed_status": "대화 자세히 보기",
@@ -776,7 +787,7 @@
"status.edit": "수정",
"status.edited": "{date}에 마지막으로 편집됨",
"status.edited_x_times": "{count, plural, other {{count}}} 번 수정됨",
- "status.embed": "임베드",
+ "status.embed": "임베드 코드 받기",
"status.favourite": "좋아요",
"status.favourites": "{count, plural, other {좋아요}}",
"status.filter": "이 게시물을 필터",
@@ -801,6 +812,7 @@
"status.reblogs.empty": "아직 아무도 이 게시물을 부스트하지 않았습니다. 부스트 한 사람들이 여기에 표시 됩니다.",
"status.redraft": "지우고 다시 쓰기",
"status.remove_bookmark": "북마크 삭제",
+ "status.replied_in_thread": "글타래에 답장",
"status.replied_to": "{name} 님에게",
"status.reply": "답장",
"status.replyAll": "글타래에 답장",
@@ -848,7 +860,7 @@
"upload_modal.description_placeholder": "다람쥐 헌 쳇바퀴 타고파",
"upload_modal.detect_text": "사진에서 문자 탐색",
"upload_modal.edit_media": "미디어 수정",
- "upload_modal.hint": "미리보기를 클릭하거나 드래그 해서 포컬 포인트를 맞추세요. 이 점은 썸네일에 항상 보여질 부분을 나타냅니다.",
+ "upload_modal.hint": "미리보기를 클릭하거나 드래그 해서 초점을 맞추세요. 이 점은 썸네일에서 항상 보여질 부분을 나타냅니다.",
"upload_modal.preparing_ocr": "OCR 준비 중…",
"upload_modal.preview_label": "미리보기 ({ratio})",
"upload_progress.label": "업로드 중...",
diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json
index 73cfa69f42..86ecf98446 100644
--- a/app/javascript/mastodon/locales/ku.json
+++ b/app/javascript/mastodon/locales/ku.json
@@ -293,8 +293,6 @@
"keyboard_shortcuts.unfocus": "Bal nede cîhê nivîsê /lêgerînê",
"keyboard_shortcuts.up": "Di lîsteyê de rake jor",
"lightbox.close": "Bigire",
- "lightbox.compress": "Qutîya wêneya nîşan dike bitepisîne",
- "lightbox.expand": "Qutîya wêneya nîşan dike fireh bike",
"lightbox.next": "Pêş",
"lightbox.previous": "Paş",
"limited_account_hint.action": "Bi heman awayî profîlê nîşan bide",
@@ -313,7 +311,6 @@
"lists.search": "Di navbera kesên ku te dişopînin bigere",
"lists.subheading": "Lîsteyên te",
"load_pending": "{count, plural, one {# hêmaneke nû} other {#hêmaneke nû}}",
- "media_gallery.toggle_visible": "{number, plural, one {Wêneyê veşêre} other {Wêneyan veşêre}}",
"moved_to_account_banner.text": "Ajimêrê te {disabledAccount} niha neçalak e ji ber ku te bar kir bo {movedToAccount}.",
"navigation_bar.about": "Derbar",
"navigation_bar.blocks": "Bikarhênerên astengkirî",
@@ -499,7 +496,6 @@
"status.direct_indicator": "Qalkirinê taybet",
"status.edit": "Serrast bike",
"status.edited_x_times": "{count, plural, one {{count} car} other {{count} car}} hate serrastkirin",
- "status.embed": "Bi cih bike",
"status.filter": "Vê şandiyê parzûn bike",
"status.history.created": "{name} {date} afirand",
"status.history.edited": "{name} {date} serrast kir",
diff --git a/app/javascript/mastodon/locales/kw.json b/app/javascript/mastodon/locales/kw.json
index 0d60d09e30..cef24aa3b7 100644
--- a/app/javascript/mastodon/locales/kw.json
+++ b/app/javascript/mastodon/locales/kw.json
@@ -195,8 +195,6 @@
"keyboard_shortcuts.unfocus": "Anfogella tekstva gomposya/hwilas",
"keyboard_shortcuts.up": "Movya war-vann y'n rol",
"lightbox.close": "Degea",
- "lightbox.compress": "Kula kist a weles aven",
- "lightbox.expand": "Efani kist a weles aven",
"lightbox.next": "Nessa",
"lightbox.previous": "Kynsa",
"lists.account.add": "Keworra dhe rol",
@@ -213,7 +211,6 @@
"lists.search": "Hwilas yn-mysk tus a holyewgh",
"lists.subheading": "Agas rolyow",
"load_pending": "{count, plural, one {# daklennowydh} other {# a daklennow nowydh}}",
- "media_gallery.toggle_visible": "Hide {number, plural, one {aven} other {aven}}",
"navigation_bar.blocks": "Devnydhyoryon lettys",
"navigation_bar.bookmarks": "Folennosow",
"navigation_bar.community_timeline": "Amserlin leel",
@@ -318,7 +315,6 @@
"status.delete": "Dilea",
"status.detailed_status": "Gwel kesklapp a-vanyl",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "Staga",
"status.load_more": "Karga moy",
"status.media_hidden": "Myski kudhys",
"status.mention": "Meneges @{name}",
diff --git a/app/javascript/mastodon/locales/la.json b/app/javascript/mastodon/locales/la.json
index 5ef238a2bd..d894cc01c6 100644
--- a/app/javascript/mastodon/locales/la.json
+++ b/app/javascript/mastodon/locales/la.json
@@ -24,6 +24,7 @@
"announcement.announcement": "Proclamatio",
"attachments_list.unprocessed": "(immūtātus)",
"block_modal.you_wont_see_mentions": "Nuntios quibus eos commemorant non videbis.",
+ "boost_modal.combo": "Potes premēre {combo} ut hoc iterum transilīre",
"bundle_column_error.error.title": "Eheu!",
"bundle_column_error.retry": "Retemptare",
"bundle_column_error.routing.title": "CCCCIIII",
@@ -72,7 +73,10 @@
"empty_column.account_timeline": "Hic nulla contributa!",
"empty_column.account_unavailable": "Notio non impetrabilis",
"empty_column.blocks": "Nondum quemquam usorem obsēcāvisti.",
+ "empty_column.bookmarked_statuses": "Nūllae adhuc postēs notātī habēs. Ubi unum notāverīs, hic apparebit.",
"empty_column.direct": "Nōn habēs adhūc ullo mentionēs prīvātās. Cum ūnam mīseris aut accipis, hīc apparēbit.",
+ "empty_column.favourited_statuses": "Nūllae adhuc postēs praeferendī habēs. Ubi unum praeferās, hic apparebit.",
+ "empty_column.follow_requests": "Nūllae adhuc petitionēs sequendi habēs. Ubi unum accipīs, hic apparebit.",
"empty_column.followed_tags": "Nōn adhūc aliquem hastāginem secūtus es. Cum id fēceris, hic ostendētur.",
"empty_column.home": "Tua linea temporum domesticus vacua est! Sequere plures personas ut eam compleas.",
"empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
@@ -84,12 +88,19 @@
"firehose.all": "Omnis",
"footer.about": "De",
"generic.saved": "Servavit",
+ "hashtag.column_header.tag_mode.none": "sine {additional}",
"hashtag.column_settings.tag_mode.all": "Haec omnia",
"hashtag.column_settings.tag_toggle": "Include additional tags in this column",
"hashtag.counter_by_accounts": "{count, plural, one {{counter} particeps} other {{counter} participēs}}",
"hashtag.counter_by_uses": "{count, plural, one {{counter} nuntius} other {{counter} nuntii}}",
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} nuntius} other {{counter} nuntii}} hodie",
"hashtags.and_other": "…et {count, plural, other {# plus}}",
+ "ignore_notifications_modal.filter_to_act_users": "Adhuc poteris accipere, reicere, vel referre usores",
+ "ignore_notifications_modal.filter_to_review_separately": "Percolantur notificatiōnes separātim recensere potes",
+ "interaction_modal.description.favourite": "Cum accūntū in Mastodon, hanc postem praeferre potes ut auctōrī indicēs tē eam aestimāre et ad posterius servēs.",
+ "interaction_modal.description.follow": "Cum accūntū in Mastodon, {name} sequī potes ut eōrum postēs in tēlā domī tuā recipiās.",
+ "interaction_modal.description.reply": "Mastodon de Ratione, huic nuntio respondere potes.",
+ "interaction_modal.sign_in": "Ad hōc servientem nōn dēlūxī. Ubi accūntum tuum hospitātum est?",
"intervals.full.days": "{number, plural, one {# die} other {# dies}}",
"intervals.full.hours": "{number, plural, one {# hora} other {# horae}}",
"intervals.full.minutes": "{number, plural, one {# minutum} other {# minuta}}",
@@ -130,7 +141,6 @@
"lists.new.create": "Addere tabella",
"lists.subheading": "Tuae tabulae",
"load_pending": "{count, plural, one {# novum item} other {# nova itema}}",
- "media_gallery.toggle_visible": "{number, plural, one {Cēla imaginem} other {Cēla imagines}}",
"moved_to_account_banner.text": "Tua ratione {disabledAccount} interdum reposita est, quod ad {movedToAccount} migrāvisti.",
"mute_modal.you_wont_see_mentions": "Non videbis nuntios quī eōs commemorant.",
"navigation_bar.about": "De",
@@ -155,6 +165,8 @@
"notification.status": "{name} nuper publicavit",
"notification.update": "{name} nuntium correxit",
"notification_requests.accept": "Accipe",
+ "notification_requests.confirm_accept_multiple.message": "Tu es accepturus {count, plural, one {una notitia petitionem} other {# notitia petitiones}}. Certus esne procedere vis?",
+ "notification_requests.confirm_dismiss_multiple.message": "Tu {count, plural, one {unam petitionem notificationis} other {# petitiones notificationum}} abrogāre prōximum es. {count, plural, one {Illa} other {Eae}} facile accessū nōn erit. Certus es tē procedere velle?",
"notifications.filter.all": "Omnia",
"notifications.filter.polls": "Eventus electionis",
"notifications.group": "Notificātiōnēs",
@@ -163,6 +175,8 @@
"onboarding.follows.lead": "Tua domus feed est principalis via Mastodon experīrī. Quō plūrēs persōnas sequeris, eō actīvior et interessantior erit. Ad tē incipiendum, ecce quaedam suāsiones:",
"onboarding.follows.title": "Popular on Mastodon",
"onboarding.profile.display_name_hint": "Tuum nomen completum aut tuum nomen ludens…",
+ "onboarding.profile.lead": "Hoc semper postea in ratiōnibus complērī potest, ubi etiam plūrēs optiōnēs personalizātiōnis praesto sunt.",
+ "onboarding.profile.note_hint": "Alios hominēs vel #hashtags @nōmināre potes…",
"onboarding.start.lead": "Nunc pars es Mastodonis, singularis, socialis medii platformae decentralis ubi—non algorismus—tuam ipsius experientiam curas. Incipiāmus in nova hac socialis regione:",
"onboarding.start.skip": "Want to skip right ahead?",
"onboarding.start.title": "Perfecisti eam!",
@@ -206,8 +220,11 @@
"report.mute_explanation": "Non videbis eōrum nuntiōs. Possunt adhuc tē sequī et tuōs nuntiōs vidēre, nec sciēbunt sē tacitōs esse.",
"report.next": "Secundum",
"report.placeholder": "Commentāriī adiūnctī",
+ "report.reasons.legal_description": "Putās id legem tuae aut servientis patriae violāre.",
+ "report.reasons.violation_description": "Scis quod certa praecepta frangit",
"report.submit": "Mittere",
"report.target": "Report {target}",
+ "report.unfollow_explanation": "Tu hanc rationem secutus es. Non videre stationes suas in domo tua amplius pascere, eas sequere.",
"report_notification.attached_statuses": "{count, plural, one {{count} nuntius} other {{count} nuntii}} attachiatus",
"report_notification.categories.other": "Altera",
"search.placeholder": "Quaerere",
diff --git a/app/javascript/mastodon/locales/lad.json b/app/javascript/mastodon/locales/lad.json
index 48aeec0795..43da2ea16f 100644
--- a/app/javascript/mastodon/locales/lad.json
+++ b/app/javascript/mastodon/locales/lad.json
@@ -34,7 +34,9 @@
"account.follow_back": "Sige tamyen",
"account.followers": "Suivantes",
"account.followers.empty": "Por agora dingun no sige a este utilizador.",
+ "account.followers_counter": "{count, plural, one {{counter} suivante} other {{counter} suivantes}}",
"account.following": "Sigiendo",
+ "account.following_counter": "{count, plural, other {Sigiendo a {counter}}}",
"account.follows.empty": "Este utilizador ainda no sige a dingun.",
"account.go_to_profile": "Va al profil",
"account.hide_reblogs": "Eskonde repartajasyones de @{name}",
@@ -60,6 +62,7 @@
"account.requested_follow": "{name} tiene solisitado segirte",
"account.share": "Partaja el profil de @{name}",
"account.show_reblogs": "Amostra repartajasyones de @{name}",
+ "account.statuses_counter": "{count, plural, one {{counter} publikasyon} other {{counter} publikasyones}}",
"account.unblock": "Dezbloka a @{name}",
"account.unblock_domain": "Dezbloka domeno {domain}",
"account.unblock_short": "Dezbloka",
@@ -92,6 +95,7 @@
"block_modal.title": "Bloka utilizador?",
"block_modal.you_wont_see_mentions": "No veras publikasyones ke lo enmentan.",
"boost_modal.combo": "Puedes klikar {combo} para ometer esto la proksima vez",
+ "boost_modal.reblog": "Repartajar puvlikasyon?",
"bundle_column_error.copy_stacktrace": "Kopia el raporto de yerro",
"bundle_column_error.error.body": "La pajina solisitada no pudo ser renderada. Podria ser por un yerro en muestro kodiche o un problem de kompatibilita kon el navigador.",
"bundle_column_error.error.title": "Atyo, no!",
@@ -185,6 +189,8 @@
"confirmations.unfollow.confirm": "Desige",
"confirmations.unfollow.message": "Estas siguro ke keres deshar de segir a {name}?",
"confirmations.unfollow.title": "Desige utilizador?",
+ "content_warning.hide": "Eskonde puvlikasyon",
+ "content_warning.show": "Amostra entanto",
"conversation.delete": "Efasa konversasyon",
"conversation.mark_as_read": "Marka komo meldado",
"conversation.open": "Ve konversasyon",
@@ -390,8 +396,6 @@
"keyboard_shortcuts.unfocus": "No enfoka en el area de eskrivir/bushkeda",
"keyboard_shortcuts.up": "Move verso arriva en la lista",
"lightbox.close": "Serra",
- "lightbox.compress": "Kompresa kuadro de imaje",
- "lightbox.expand": "Espande kuadro de imaje",
"lightbox.next": "Sigiente",
"lightbox.previous": "Anterior",
"limited_account_hint.action": "Amostra el profil entanto",
@@ -415,7 +419,7 @@
"lists.subheading": "Tus listas",
"load_pending": "{count, plural, one {# muevo elemento} other {# muevos elementos}}",
"loading_indicator.label": "Eskargando…",
- "media_gallery.toggle_visible": "{number, plural, one {Eskonde imaje} other {Eskonde imajes}}",
+ "media_gallery.hide": "Eskonde",
"moved_to_account_banner.text": "Tu kuento {disabledAccount} esta aktualmente inkapasitado porke transferates a {movedToAccount}.",
"mute_modal.hide_from_notifications": "Eskonde de avizos",
"mute_modal.hide_options": "Eskonde opsyones",
@@ -425,6 +429,7 @@
"mute_modal.title": "Silensiar utilizador?",
"mute_modal.you_wont_see_mentions": "No veras publikasyones ke lo enmentan.",
"navigation_bar.about": "Sovre mozotros",
+ "navigation_bar.administration": "Administrasyon",
"navigation_bar.advanced_interface": "Avre en la enterfaz avanzada",
"navigation_bar.blocks": "Utilizadores blokados",
"navigation_bar.bookmarks": "Markadores",
@@ -441,6 +446,7 @@
"navigation_bar.follows_and_followers": "Segidos i suivantes",
"navigation_bar.lists": "Listas",
"navigation_bar.logout": "Salir",
+ "navigation_bar.moderation": "Moderasyon",
"navigation_bar.mutes": "Utilizadores silensiados",
"navigation_bar.opened_in_classic_interface": "Publikasyones, kuentos i otras pajinas espesifikas se avren kon preferensyas predeterminadas en la enterfaz web klasika.",
"navigation_bar.personal": "Personal",
@@ -475,6 +481,8 @@
"notification.update": "{name} edito una publikasyon",
"notification_requests.accept": "Acheta",
"notification_requests.dismiss": "Kita",
+ "notification_requests.edit_selection": "Edita",
+ "notification_requests.exit_selection": "Fecho",
"notification_requests.notifications_from": "Avizos de {name}",
"notification_requests.title": "Avizos filtrados",
"notification_requests.view": "Amostra avizos",
@@ -484,7 +492,6 @@
"notifications.column_settings.admin.report": "Muveos raportos:",
"notifications.column_settings.admin.sign_up": "Muevas enrejistrasyones:",
"notifications.column_settings.alert": "Avizos de ensimameza",
- "notifications.column_settings.beta.category": "Funksyones eksperimentalas",
"notifications.column_settings.favourite": "Te plazen:",
"notifications.column_settings.filter_bar.advanced": "Amostra todas las kategorias",
"notifications.column_settings.filter_bar.category": "Vara de filtrado rapido",
@@ -701,7 +708,6 @@
"status.edit": "Edita",
"status.edited": "Ultima edisyon: {date}",
"status.edited_x_times": "Editado {count, plural, one {{count} vez} other {{count} vezes}}",
- "status.embed": "Inkrusta",
"status.favourite": "Te plaze",
"status.filter": "Filtra esta publikasyon",
"status.history.created": "{name} kriyo {date}",
diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json
index 027326f9cb..632c33129a 100644
--- a/app/javascript/mastodon/locales/lt.json
+++ b/app/javascript/mastodon/locales/lt.json
@@ -97,6 +97,8 @@
"block_modal.title": "Blokuoti naudotoją?",
"block_modal.you_wont_see_mentions": "Nematysi įrašus, kuriuose jie paminimi.",
"boost_modal.combo": "Galima paspausti {combo}, kad praleisti tai kitą kartą",
+ "boost_modal.reblog": "Pasidalinti įrašą?",
+ "boost_modal.undo_reblog": "Panaikinti pasidalintą įrašą?",
"bundle_column_error.copy_stacktrace": "Kopijuoti klaidos ataskaitą",
"bundle_column_error.error.body": "Paprašytos puslapio nepavyko atvaizduoti. Tai gali būti dėl mūsų kodo klaidos arba naršyklės suderinamumo problemos.",
"bundle_column_error.error.title": "O, ne!",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Nebefokusuoti rengykles teksto sritį / paiešką",
"keyboard_shortcuts.up": "Perkelti į viršų sąraše",
"lightbox.close": "Uždaryti",
- "lightbox.compress": "Suspausti vaizdo peržiūros langelį",
- "lightbox.expand": "Išplėsti vaizdo peržiūros langelį",
"lightbox.next": "Kitas",
"lightbox.previous": "Ankstesnis",
+ "lightbox.zoom_in": "Padidink iki tikrojo dydžio",
+ "lightbox.zoom_out": "Padidink, kad tilptų",
"limited_account_hint.action": "Vis tiek rodyti profilį",
"limited_account_hint.title": "Šį profilį paslėpė {domain} prižiūrėtojai.",
"link_preview.author": "Sukūrė {name}",
@@ -455,7 +457,7 @@
"lists.subheading": "Tavo sąrašai",
"load_pending": "{count, plural, one {# naujas elementas} few {# nauji elementai} many {# naujo elemento} other {# naujų elementų}}",
"loading_indicator.label": "Kraunama…",
- "media_gallery.toggle_visible": "{number, plural, one {Slėpti vaizdą} few {Slėpti vaizdus} many {Slėpti vaizdo} other {Slėpti vaizdų}}",
+ "media_gallery.hide": "Slėpti",
"moved_to_account_banner.text": "Tavo paskyra {disabledAccount} šiuo metu išjungta, nes persikėlei į {movedToAccount}.",
"mute_modal.hide_from_notifications": "Slėpti nuo pranešimų",
"mute_modal.hide_options": "Slėpti parinktis",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Nematysi įrašus, kuriuose jie paminimi.",
"mute_modal.you_wont_see_posts": "Jie vis tiek gali matyti tavo įrašus, bet tu nematysi jų.",
"navigation_bar.about": "Apie",
+ "navigation_bar.administration": "Administravimas",
"navigation_bar.advanced_interface": "Atidaryti išplėstinę žiniatinklio sąsają",
"navigation_bar.blocks": "Užblokuoti naudotojai",
"navigation_bar.bookmarks": "Žymės",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Sekimai ir sekėjai",
"navigation_bar.lists": "Sąrašai",
"navigation_bar.logout": "Atsijungti",
+ "navigation_bar.moderation": "Prižiūrėjimas",
"navigation_bar.mutes": "Nutildyti naudotojai",
"navigation_bar.opened_in_classic_interface": "Įrašai, paskyros ir kiti konkretūs puslapiai pagal numatytuosius nustatymus atidaromi klasikinėje žiniatinklio sąsajoje.",
"navigation_bar.personal": "Asmeninis",
@@ -548,8 +552,6 @@
"notifications.column_settings.admin.report": "Naujos ataskaitos:",
"notifications.column_settings.admin.sign_up": "Naujos registracijos:",
"notifications.column_settings.alert": "Darbalaukio pranešimai",
- "notifications.column_settings.beta.category": "Eksperimentinės funkcijos",
- "notifications.column_settings.beta.grouping": "Grupuoti pranešimus",
"notifications.column_settings.favourite": "Mėgstami:",
"notifications.column_settings.filter_bar.advanced": "Rodyti visas kategorijas",
"notifications.column_settings.filter_bar.category": "Spartaus filtro juosta",
@@ -631,7 +633,7 @@
"onboarding.steps.share_profile.title": "Bendrink savo Mastodon profilį",
"onboarding.tips.2fa": "
Ar žinojai? Savo paskyrą gali apsaugoti nustatant dviejų veiksnių tapatybės nustatymą paskyros nustatymuose. Jis veikia su bet kuria pasirinkta TOTP programėle, telefono numeris nebūtinas.",
"onboarding.tips.accounts_from_other_servers": "
Ar žinojai? Kadangi Mastodon decentralizuotas, kai kurie profiliai, su kuriais susidursi, bus talpinami ne tavo, o kituose serveriuose. Ir vis tiek galėsi su jais sklandžiai bendrauti! Jų serveris yra antroje naudotojo vardo pusėje.",
- "onboarding.tips.migration": "
Ar žinojai? Jei manai, kad {domain} serveris ateityje tau netiks, gali persikelti į kitą Mastodon serverį neprarandant savo sekėjų. Gali net talpinti savo paties serverį.",
+ "onboarding.tips.migration": "
Ar žinojai? Jei manai, kad {domain} serveris ateityje tau netiks, gali persikelti į kitą „Mastodon“ serverį neprarandant savo sekėjų. Gali net talpinti savo paties serverį!",
"onboarding.tips.verification": "
Ar žinojai? Savo paskyrą gali patvirtinti pateikęs (-usi) nuorodą į Mastodon profilį savo interneto svetainėje ir pridėjęs (-usi) svetainę prie savo profilio. Nereikia jokių mokesčių ar dokumentų.",
"password_confirmation.exceeds_maxlength": "Slaptažodžio patvirtinimas viršija maksimalų slaptažodžio ilgį.",
"password_confirmation.mismatching": "Slaptažodžio patvirtinimas nesutampa.",
@@ -766,6 +768,7 @@
"status.bookmark": "Pridėti į žymės",
"status.cancel_reblog_private": "Nebepakelti",
"status.cannot_reblog": "Šis įrašas negali būti pakeltas.",
+ "status.continued_thread": "Tęsiama gijoje",
"status.copy": "Kopijuoti nuorodą į įrašą",
"status.delete": "Ištrinti",
"status.detailed_status": "Išsami pokalbio peržiūra",
@@ -774,7 +777,6 @@
"status.edit": "Redaguoti",
"status.edited": "Paskutinį kartą redaguota {date}",
"status.edited_x_times": "Redaguota {count, plural, one {{count} kartą} few {{count} kartus} many {{count} karto} other {{count} kartų}}",
- "status.embed": "Įterpti",
"status.favourite": "Pamėgti",
"status.favourites": "{count, plural, one {mėgstamas} few {mėgstamai} many {mėgstamų} other {mėgstamų}}",
"status.filter": "Filtruoti šį įrašą",
@@ -798,6 +800,7 @@
"status.reblogs.empty": "Šio įrašo dar niekas nepakėlė. Kai kas nors tai padarys, jie bus rodomi čia.",
"status.redraft": "Ištrinti ir parengti iš naujo",
"status.remove_bookmark": "Pašalinti žymę",
+ "status.replied_in_thread": "Atsakyta gijoje",
"status.replied_to": "Atsakyta į {name}",
"status.reply": "Atsakyti",
"status.replyAll": "Atsakyti į giją",
diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json
index 6cd15afbec..43fa8369f4 100644
--- a/app/javascript/mastodon/locales/lv.json
+++ b/app/javascript/mastodon/locales/lv.json
@@ -11,6 +11,7 @@
"about.not_available": "Šī informācija nav padarīta pieejama šajā serverī.",
"about.powered_by": "Decentralizētu sociālo tīklu nodrošina {mastodon}",
"about.rules": "Servera noteikumi",
+ "account.account_note_header": "Personīga piezīme",
"account.add_or_remove_from_list": "Pievienot vai Noņemt no sarakstiem",
"account.badges.bot": "Automatizēts",
"account.badges.group": "Grupa",
@@ -90,7 +91,10 @@
"block_modal.show_more": "Parādīt mazāk",
"block_modal.they_cant_mention": "Nevar Tevi pieminēt vai sekot Tev.",
"block_modal.they_cant_see_posts": "Nevar redzēt Tavus ierakstus, un Tu neredzēsi lietotāja.",
+ "block_modal.title": "Bloķēt lietotāju?",
"boost_modal.combo": "Nospied {combo}, lai nākamreiz šo izlaistu",
+ "boost_modal.reblog": "Pastiprināt ierakstu?",
+ "boost_modal.undo_reblog": "Atcelt ieraksta pastiprināšanu?",
"bundle_column_error.copy_stacktrace": "Kopēt kļūdu ziņojumu",
"bundle_column_error.error.body": "Pieprasīto lapu nevarēja atveidot. Tas varētu būt saistīts ar kļūdu mūsu kodā, vai tā ir pārlūkprogrammas saderības problēma.",
"bundle_column_error.error.title": "Ak vai!",
@@ -152,6 +156,7 @@
"compose_form.poll.single": "Jāizvēlas viens",
"compose_form.poll.switch_to_multiple": "Mainīt aptaujas veidu, lai atļautu vairākas izvēles",
"compose_form.poll.switch_to_single": "Mainīt aptaujas veidu, lai atļautu vienu izvēli",
+ "compose_form.poll.type": "Stils",
"compose_form.publish": "Iesūtīt",
"compose_form.publish_form": "Jauns ieraksts",
"compose_form.reply": "Atbildēt",
@@ -163,21 +168,30 @@
"confirmations.block.confirm": "Bloķēt",
"confirmations.delete.confirm": "Dzēst",
"confirmations.delete.message": "Vai tiešām vēlies dzēst šo ierakstu?",
+ "confirmations.delete.title": "Izdzēst ierakstu?",
"confirmations.delete_list.confirm": "Dzēst",
"confirmations.delete_list.message": "Vai tiešām neatgriezeniski izdzēst šo sarakstu?",
+ "confirmations.delete_list.title": "Izdzēst sarakstu?",
"confirmations.discard_edit_media.confirm": "Atmest",
"confirmations.discard_edit_media.message": "Ir nesaglabātas izmaiņas informācijas nesēja aprakstā vai priekšskatījumā. Vēlies tās atmest tik un tā?",
"confirmations.edit.confirm": "Labot",
"confirmations.edit.message": "Labošana pārrakstīs ziņojumu, kas šobrīd tiek sastādīts. Vai tiešām turpināt?",
+ "confirmations.edit.title": "Pārrakstīt ierakstu?",
"confirmations.logout.confirm": "Iziet",
"confirmations.logout.message": "Vai tiešām vēlies izrakstīties?",
+ "confirmations.logout.title": "Atteikties?",
"confirmations.mute.confirm": "Apklusināt",
"confirmations.redraft.confirm": "Dzēst un pārrakstīt",
"confirmations.redraft.message": "Vai tiešām vēlies dzēst šo ziņu un no jauna noformēt to? Izlase un pastiprinājumi tiks zaudēti, un atbildes uz sākotnējo ziņu tiks atstātas bez autoratlīdzības.",
+ "confirmations.redraft.title": "Dzēst un rakstīt vēlreiz?",
"confirmations.reply.confirm": "Atbildēt",
"confirmations.reply.message": "Tūlītēja atbildēšana pārrakstīs pašlaik sastādīto ziņu. Vai tiešām turpināt?",
+ "confirmations.reply.title": "Pārrakstīt ierakstu?",
"confirmations.unfollow.confirm": "Pārstāt sekot",
"confirmations.unfollow.message": "Vai tiešam vairs nevēlies sekot lietotājam {name}?",
+ "confirmations.unfollow.title": "Pārtraukt sekošanu lietotājam?",
+ "content_warning.hide": "Paslēpt ierakstu",
+ "content_warning.show": "Tomēr rādīt",
"conversation.delete": "Dzēst sarunu",
"conversation.mark_as_read": "Atzīmēt kā izlasītu",
"conversation.open": "Skatīt sarunu",
@@ -197,7 +211,11 @@
"dismissable_banner.explore_statuses": "Šie ir ieraksti, kas šodien gūst arvien lielāku ievērību visā sociālajā tīklā. Augstāk tiek kārtoti jaunāki ieraksti, kuri tiek vairāk pastiprināti un ievietoti izlasēs.",
"dismissable_banner.explore_tags": "Šie tēmturi šobrīd kļūst arvien populārāki cilvēku vidū šajā un citos decentralizētā tīkla serveros.",
"dismissable_banner.public_timeline": "Šie ir jaunākie publiskie ieraksti no lietotājiem sociālajā tīmeklī, kuriem {domain} seko cilvēki.",
+ "domain_block_modal.block": "Bloķēt serveri",
"domain_block_modal.they_cant_follow": "Neviens šajā serverī nevar Tev sekot.",
+ "domain_block_modal.they_wont_know": "Viņi nezinās, ka tikuši bloķēti.",
+ "domain_block_modal.title": "Bloķēt domēnu?",
+ "domain_block_modal.you_will_lose_followers": "Tiks noņemti visi tavi sekotāji no šī servera.",
"domain_pill.server": "Serveris",
"domain_pill.username": "Lietotājvārds",
"embed.instructions": "Iestrādā šo ziņu savā mājaslapā, kopējot zemāk redzamo kodu.",
@@ -266,6 +284,7 @@
"filter_modal.select_filter.subtitle": "Izmanto esošu kategoriju vai izveido jaunu",
"filter_modal.select_filter.title": "Filtrēt šo ziņu",
"filter_modal.title.status": "Filtrēt ziņu",
+ "filter_warning.matches_filter": "Atbilst filtram “{title}”",
"firehose.all": "Visi",
"firehose.local": "Šis serveris",
"firehose.remote": "Citi serveri",
@@ -274,6 +293,7 @@
"follow_requests.unlocked_explanation": "Lai gan Tavs konts nav slēgts, {domain} darbinieki iedomājās, ka Tu varētu vēlēties pašrocīgi pārskatīt sekošanas pieprasījumus no šiem kontiem.",
"follow_suggestions.curated_suggestion": "Darbinieku izvēle",
"follow_suggestions.dismiss": "Vairs nerādīt",
+ "follow_suggestions.friends_of_friends_longer": "Populārs to cilvēku vidū, kuriem tu seko",
"follow_suggestions.personalized_suggestion": "Pielāgots ieteikums",
"follow_suggestions.similar_to_recently_followed_longer": "Līdzīgi profieliem, kuriem nesen sāki sekot",
"follow_suggestions.view_all": "Skatīt visu",
@@ -304,6 +324,7 @@
"hashtag.follow": "Sekot tēmturim",
"hashtag.unfollow": "Pārstāt sekot tēmturim",
"hashtags.and_other": "… un {count, plural, other {vēl #}}",
+ "hints.threads.replies_may_be_missing": "Var trūkt atbildes no citiem serveriem.",
"home.column_settings.show_reblogs": "Rādīt pastiprinātos ierakstus",
"home.column_settings.show_replies": "Rādīt atbildes",
"home.hide_announcements": "Slēpt paziņojumus",
@@ -364,8 +385,6 @@
"keyboard_shortcuts.unfocus": "Atfokusēt veidojamā teksta/meklēšanas lauku",
"keyboard_shortcuts.up": "Pārvietoties augšup sarakstā",
"lightbox.close": "Aizvērt",
- "lightbox.compress": "Saspiest attēla skata lodziņu",
- "lightbox.expand": "Izvērst attēla skata lodziņu",
"lightbox.next": "Tālāk",
"lightbox.previous": "Iepriekšējais",
"limited_account_hint.action": "Tik un tā rādīt profilu",
@@ -388,7 +407,7 @@
"lists.subheading": "Tavi saraksti",
"load_pending": "{count, plural, one {# jauna lieta} other {# jaunas lietas}}",
"loading_indicator.label": "Ielādē…",
- "media_gallery.toggle_visible": "{number, plural, one {Slēpt attēlu} other {Slēpt attēlus}}",
+ "media_gallery.hide": "Paslēpt",
"moved_to_account_banner.text": "Tavs konts {disabledAccount} pašlaik ir atspējots, jo Tu pārcēlies uz kontu {movedToAccount}.",
"mute_modal.hide_from_notifications": "Paslēpt paziņojumos",
"mute_modal.hide_options": "Paslēpt iespējas",
@@ -650,7 +669,6 @@
"status.edit": "Labot",
"status.edited": "Pēdējoreiz labots {date}",
"status.edited_x_times": "Labots {count, plural, zero {{count} reižu} one {{count} reizi} other {{count} reizes}}",
- "status.embed": "Iegult",
"status.favourite": "Izlasē",
"status.favourites": "{count, plural, zero {izlasēs} one {izlasē} other {izlasēs}}",
"status.filter": "Filtrē šo ziņu",
diff --git a/app/javascript/mastodon/locales/ml.json b/app/javascript/mastodon/locales/ml.json
index 48ea29f983..5ed6f219db 100644
--- a/app/javascript/mastodon/locales/ml.json
+++ b/app/javascript/mastodon/locales/ml.json
@@ -308,7 +308,6 @@
"status.delete": "മായ്ക്കുക",
"status.detailed_status": "വിശദമായ സംഭാഷണ കാഴ്ച",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "ഉൾച്ചേർക്കുക",
"status.load_more": "കൂടുതൽ ലോഡു ചെയ്യുക",
"status.media_hidden": "മീഡിയ മറച്ചു",
"status.mention": "@{name} സൂചിപ്പിക്കുക",
diff --git a/app/javascript/mastodon/locales/mr.json b/app/javascript/mastodon/locales/mr.json
index 47c3a55e55..aa8169616e 100644
--- a/app/javascript/mastodon/locales/mr.json
+++ b/app/javascript/mastodon/locales/mr.json
@@ -169,8 +169,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"lightbox.close": "बंद करा",
- "lightbox.compress": "प्रतिमा दृश्य बॉक्स कॉम्प्रेस करा",
- "lightbox.expand": "प्रतिमा दृश्य बॉक्स विस्तृत करा",
"lightbox.next": "पुढे",
"lightbox.previous": "मागील",
"limited_account_hint.action": "तरीही प्रोफाइल दाखवा",
diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json
index c9f8b7a274..cbd57ab356 100644
--- a/app/javascript/mastodon/locales/ms.json
+++ b/app/javascript/mastodon/locales/ms.json
@@ -11,6 +11,7 @@
"about.not_available": "Maklumat ini belum tersedia pada pelayan ini.",
"about.powered_by": "Media sosial terpencar yang dikuasakan oleh {mastodon}",
"about.rules": "Peraturan pelayan",
+ "account.account_note_header": "Personal note",
"account.add_or_remove_from_list": "Tambah atau Buang dari senarai",
"account.badges.bot": "Bot",
"account.badges.group": "Kumpulan",
@@ -33,6 +34,7 @@
"account.follow_back": "Ikut balik",
"account.followers": "Pengikut",
"account.followers.empty": "Belum ada yang mengikuti pengguna ini.",
+ "account.followers_counter": "{count, plural, one {{counter} Diikuti} other {{counter} Diikuti}}",
"account.following": "Mengikuti",
"account.follows.empty": "Pengguna ini belum mengikuti sesiapa.",
"account.go_to_profile": "Pergi ke profil",
@@ -358,8 +360,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "Pindah ke atas dalam senarai",
"lightbox.close": "Tutup",
- "lightbox.compress": "Kecilkan kotak paparan imej",
- "lightbox.expand": "Besarkan kotak paparan imej",
"lightbox.next": "Seterusnya",
"lightbox.previous": "Sebelumnya",
"limited_account_hint.action": "Paparkan profil",
@@ -381,7 +381,6 @@
"lists.subheading": "Senarai anda",
"load_pending": "{count, plural, one {# item baharu} other {# item baharu}}",
"loading_indicator.label": "Memuatkan…",
- "media_gallery.toggle_visible": "{number, plural, other {Sembunyikan imej}}",
"moved_to_account_banner.text": "Akaun anda {disabledAccount} kini dinyahdayakan kerana anda berpindah ke {movedToAccount}.",
"navigation_bar.about": "Perihal",
"navigation_bar.advanced_interface": "Buka dalam antara muka web lanjutan",
@@ -612,7 +611,6 @@
"status.direct_indicator": "Sebutan peribadi",
"status.edit": "Sunting",
"status.edited_x_times": "Disunting {count, plural, other {{count} kali}}",
- "status.embed": "Benaman",
"status.favourite": "Kegemaran",
"status.filter": "Tapiskan hantaran ini",
"status.history.created": "{name} mencipta pada {date}",
diff --git a/app/javascript/mastodon/locales/my.json b/app/javascript/mastodon/locales/my.json
index b042ebbcce..c97de73335 100644
--- a/app/javascript/mastodon/locales/my.json
+++ b/app/javascript/mastodon/locales/my.json
@@ -339,8 +339,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"lightbox.close": "ပိတ်ပါ",
- "lightbox.compress": "ရုပ်ပုံမြင်ကွင်းအကွက်ကို ချုံ့ပါ",
- "lightbox.expand": "ပုံကိုဖွင့်ပါ",
"lightbox.next": "ရှေ့သို့",
"lightbox.previous": "ရှေ့သို့",
"limited_account_hint.action": "ဘာပဲဖြစ်ဖြစ် ပရိုဖိုင်ကို ပြပါ",
@@ -362,7 +360,6 @@
"lists.subheading": "သင့်၏စာရင်းများ",
"load_pending": "{count, plural, one {# new item} other {# new items}}",
"loading_indicator.label": "လုပ်ဆောင်နေသည်…",
- "media_gallery.toggle_visible": "{number, plural, one {Hide image} other {Hide images}}",
"moved_to_account_banner.text": "{movedToAccount} အကောင့်သို့ပြောင်းလဲထားသဖြင့် {disabledAccount} အကောင့်မှာပိတ်ထားသည်",
"navigation_bar.about": "အကြောင်း",
"navigation_bar.advanced_interface": "အဆင့်မြင့်ဝဘ်ပုံစံ ဖွင့်ပါ",
@@ -590,7 +587,6 @@
"status.direct_indicator": "သီးသန့်ဖော်ပြခြင်း။",
"status.edit": "ပြင်ဆင်ရန်",
"status.edited_x_times": "{count, plural, one {{count} time} other {{count} times}} ပြင်ဆင်ခဲ့သည်",
- "status.embed": "Embed",
"status.favourite": "Favorite",
"status.filter": "ဤပို့စ်ကို စစ်ထုတ်ပါ",
"status.history.created": "{name} က {date} က ဖန်တီးခဲ့သည်",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index b15c09fead..f5f4a0a137 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -97,6 +97,8 @@
"block_modal.title": "Gebruiker blokkeren?",
"block_modal.you_wont_see_mentions": "Je ziet geen berichten meer die dit account vermelden.",
"boost_modal.combo": "Je kunt {combo} klikken om dit de volgende keer over te slaan",
+ "boost_modal.reblog": "Bericht boosten?",
+ "boost_modal.undo_reblog": "Bericht niet langer boosten?",
"bundle_column_error.copy_stacktrace": "Foutrapportage kopiëren",
"bundle_column_error.error.body": "De opgevraagde pagina kon niet worden weergegeven. Dit kan het gevolg zijn van een fout in onze broncode, of van een compatibiliteitsprobleem met je webbrowser.",
"bundle_column_error.error.title": "O nee!",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Tekst- en zoekveld ontfocussen",
"keyboard_shortcuts.up": "Naar boven in de lijst bewegen",
"lightbox.close": "Sluiten",
- "lightbox.compress": "Afbeelding passend weergeven",
- "lightbox.expand": "Afbeelding groot weergeven",
"lightbox.next": "Volgende",
"lightbox.previous": "Vorige",
+ "lightbox.zoom_in": "Oorspronkelijke grootte weergeven",
+ "lightbox.zoom_out": "Passend weergeven",
"limited_account_hint.action": "Alsnog het profiel tonen",
"limited_account_hint.title": "Dit profiel is door de moderatoren van {domain} verborgen.",
"link_preview.author": "Door {name}",
@@ -455,7 +457,7 @@
"lists.subheading": "Jouw lijsten",
"load_pending": "{count, plural, one {# nieuw item} other {# nieuwe items}}",
"loading_indicator.label": "Laden…",
- "media_gallery.toggle_visible": "{number, plural, one {afbeelding verbergen} other {afbeeldingen verbergen}}",
+ "media_gallery.hide": "Verbergen",
"moved_to_account_banner.text": "Omdat je naar {movedToAccount} bent verhuisd is jouw account {disabledAccount} momenteel uitgeschakeld.",
"mute_modal.hide_from_notifications": "Onder meldingen verbergen",
"mute_modal.hide_options": "Opties verbergen",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Je ziet geen berichten meer die dit account vermelden.",
"mute_modal.you_wont_see_posts": "De persoon kan nog steeds jouw berichten zien, maar diens berichten zie je niet meer.",
"navigation_bar.about": "Over",
+ "navigation_bar.administration": "Beheer",
"navigation_bar.advanced_interface": "In geavanceerde webinterface openen",
"navigation_bar.blocks": "Geblokkeerde gebruikers",
"navigation_bar.bookmarks": "Bladwijzers",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Volgers en gevolgde accounts",
"navigation_bar.lists": "Lijsten",
"navigation_bar.logout": "Uitloggen",
+ "navigation_bar.moderation": "Moderatie",
"navigation_bar.mutes": "Genegeerde gebruikers",
"navigation_bar.opened_in_classic_interface": "Berichten, accounts en andere specifieke pagina’s, worden standaard geopend in de klassieke webinterface.",
"navigation_bar.personal": "Persoonlijk",
@@ -555,8 +559,6 @@
"notifications.column_settings.admin.report": "Nieuwe rapportages:",
"notifications.column_settings.admin.sign_up": "Nieuwe registraties:",
"notifications.column_settings.alert": "Desktopmeldingen",
- "notifications.column_settings.beta.category": "Experimentele functies",
- "notifications.column_settings.beta.grouping": "Gegroepeerde meldingen",
"notifications.column_settings.favourite": "Favorieten:",
"notifications.column_settings.filter_bar.advanced": "Alle categorieën tonen",
"notifications.column_settings.filter_bar.category": "Snelle filterbalk",
@@ -776,6 +778,7 @@
"status.bookmark": "Bladwijzer toevoegen",
"status.cancel_reblog_private": "Niet langer boosten",
"status.cannot_reblog": "Dit bericht kan niet geboost worden",
+ "status.continued_thread": "Vervolgt het gesprek",
"status.copy": "Link naar bericht kopiëren",
"status.delete": "Verwijderen",
"status.detailed_status": "Uitgebreide gespreksweergave",
@@ -784,7 +787,7 @@
"status.edit": "Bewerken",
"status.edited": "Laatste bewerking op {date}",
"status.edited_x_times": "{count, plural, one {{count} keer} other {{count} keer}} bewerkt",
- "status.embed": "Embedden",
+ "status.embed": "Embed-code verkrijgen",
"status.favourite": "Favoriet",
"status.favourites": "{count, plural, one {favoriet} other {favorieten}}",
"status.filter": "Dit bericht filteren",
@@ -809,6 +812,7 @@
"status.reblogs.empty": "Niemand heeft dit bericht nog geboost. Wanneer iemand dit doet, valt dat hier te zien.",
"status.redraft": "Verwijderen en herschrijven",
"status.remove_bookmark": "Bladwijzer verwijderen",
+ "status.replied_in_thread": "Reageerde in gesprek",
"status.replied_to": "Reageerde op {name}",
"status.reply": "Reageren",
"status.replyAll": "Op iedereen reageren",
diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json
index dd9fa5fd92..702154927d 100644
--- a/app/javascript/mastodon/locales/nn.json
+++ b/app/javascript/mastodon/locales/nn.json
@@ -97,6 +97,8 @@
"block_modal.title": "Blokker brukaren?",
"block_modal.you_wont_see_mentions": "Du ser ikkje innlegg som nemner dei.",
"boost_modal.combo": "Du kan trykkja {combo} for å hoppa over dette neste gong",
+ "boost_modal.reblog": "Framhev innlegget?",
+ "boost_modal.undo_reblog": "Fjern framhevinga?",
"bundle_column_error.copy_stacktrace": "Kopier feilrapport",
"bundle_column_error.error.body": "Den etterspurde sida kan ikke hentast fram. Det kan skuldast ein feil i koden vår eller eit kompatibilitetsproblem.",
"bundle_column_error.error.title": "Ånei!",
@@ -193,6 +195,7 @@
"confirmations.unfollow.message": "Er du sikker på at du vil slutta å fylgja {name}?",
"confirmations.unfollow.title": "Slutt å fylgja brukaren?",
"content_warning.hide": "Gøym innlegg",
+ "content_warning.show": "Vis likevel",
"conversation.delete": "Slett samtale",
"conversation.mark_as_read": "Marker som lesen",
"conversation.open": "Sjå samtale",
@@ -300,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Bruk ein eksisterande kategori eller opprett ein ny",
"filter_modal.select_filter.title": "Filtrer dette innlegget",
"filter_modal.title.status": "Filtrer eit innlegg",
+ "filter_warning.matches_filter": "Passar med filteret «{title}»",
"filtered_notifications_banner.pending_requests": "Frå {count, plural, =0 {ingen} one {éin person} other {# personar}} du kanskje kjenner",
"filtered_notifications_banner.title": "Filtrerte varslingar",
"firehose.all": "Alle",
@@ -349,6 +353,14 @@
"hashtag.follow": "Fylg emneknagg",
"hashtag.unfollow": "Slutt å fylgje emneknaggen",
"hashtags.and_other": "…og {count, plural, one {}other {# fleire}}",
+ "hints.profiles.followers_may_be_missing": "Kven som fylgjer denne profilen manglar kanskje.",
+ "hints.profiles.follows_may_be_missing": "Kven denne profilen fylgjer manglar kanskje.",
+ "hints.profiles.posts_may_be_missing": "Nokre innlegg frå denne profilen manglar kanskje.",
+ "hints.profiles.see_more_followers": "Sjå fleire fylgjarar på {domain}",
+ "hints.profiles.see_more_follows": "Sjå fleire fylgjer på {domain}",
+ "hints.profiles.see_more_posts": "Sjå fleire innlegg på {domain}",
+ "hints.threads.replies_may_be_missing": "Svar frå andre tenarar manglar kanskje.",
+ "hints.threads.see_more": "Sjå fleire svar på {domain}",
"home.column_settings.show_reblogs": "Vis framhevingar",
"home.column_settings.show_replies": "Vis svar",
"home.hide_announcements": "Skjul kunngjeringar",
@@ -420,10 +432,10 @@
"keyboard_shortcuts.unfocus": "for å fokusere vekk skrive-/søkefeltet",
"keyboard_shortcuts.up": "Flytt opp på lista",
"lightbox.close": "Lukk",
- "lightbox.compress": "Komprimer biletvisningsboksen",
- "lightbox.expand": "Utvid biletvisningsboksen",
"lightbox.next": "Neste",
"lightbox.previous": "Førre",
+ "lightbox.zoom_in": "Zoom til faktisk storleik",
+ "lightbox.zoom_out": "Vis heile",
"limited_account_hint.action": "Vis profilen likevel",
"limited_account_hint.title": "Denne profilen er skjult av moderatorane på {domain}.",
"link_preview.author": "Av {name}",
@@ -445,7 +457,7 @@
"lists.subheading": "Listene dine",
"load_pending": "{count, plural, one {# nytt element} other {# nye element}}",
"loading_indicator.label": "Lastar…",
- "media_gallery.toggle_visible": "{number, plural, one {Skjul bilete} other {Skjul bilete}}",
+ "media_gallery.hide": "Gøym",
"moved_to_account_banner.text": "Kontoen din, {disabledAccount} er for tida deaktivert fordi du har flytta til {movedToAccount}.",
"mute_modal.hide_from_notifications": "Ikkje vis varslingar",
"mute_modal.hide_options": "Gøym val",
@@ -457,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Du vil ikkje sjå innlegg som nemner dei.",
"mute_modal.you_wont_see_posts": "Dei kan framleis sjå innlegga dine, men du vil ikkje sjå deira.",
"navigation_bar.about": "Om",
+ "navigation_bar.administration": "Administrasjon",
"navigation_bar.advanced_interface": "Opne i avansert nettgrensesnitt",
"navigation_bar.blocks": "Blokkerte brukarar",
"navigation_bar.bookmarks": "Bokmerke",
@@ -473,6 +486,7 @@
"navigation_bar.follows_and_followers": "Fylgje og fylgjarar",
"navigation_bar.lists": "Lister",
"navigation_bar.logout": "Logg ut",
+ "navigation_bar.moderation": "Moderering",
"navigation_bar.mutes": "Målbundne brukarar",
"navigation_bar.opened_in_classic_interface": "Innlegg, kontoar, og enkelte andre sider blir opna som standard i det klassiske webgrensesnittet.",
"navigation_bar.personal": "Personleg",
@@ -488,9 +502,13 @@
"notification.admin.report_statuses": "{name} rapporterte {target} for {category}",
"notification.admin.report_statuses_other": "{name} rapporterte {target}",
"notification.admin.sign_up": "{name} er registrert",
+ "notification.admin.sign_up.name_and_others": "{name} og {count, plural, one {# annan} other {# andre}} vart med",
"notification.favourite": "{name} markerte innlegget ditt som favoritt",
+ "notification.favourite.name_and_others_with_link": "{name} og
{count, plural, one {# annan} other {# andre}} favorittmerka innlegget ditt",
"notification.follow": "{name} fylgde deg",
+ "notification.follow.name_and_others": "{name} og {count, plural, one {# annan} other {# andre}} fylgde deg",
"notification.follow_request": "{name} har bedt om å fylgja deg",
+ "notification.follow_request.name_and_others": "{name} og {count, plural, one {# annan} other {# andre}} har spurt om å fylgja deg",
"notification.label.mention": "Omtale",
"notification.label.private_mention": "Privat omtale",
"notification.label.private_reply": "Privat svar",
@@ -508,6 +526,7 @@
"notification.own_poll": "Rundspørjinga di er ferdig",
"notification.poll": "Ei rundspørjing du røysta i er ferdig",
"notification.reblog": "{name} framheva innlegget ditt",
+ "notification.reblog.name_and_others_with_link": "{name} og
{count, plural, one {# annan} other {# andre}} framheva innlegget ditt",
"notification.relationships_severance_event": "Tapte samband med {name}",
"notification.relationships_severance_event.account_suspension": "Ein administrator på {from} har utvist {target}, som tyder at du ikkje lenger får oppdateringar frå dei eller kan samhandla med dei.",
"notification.relationships_severance_event.domain_block": "Ein administrator på {from} har blokkert {target}, inkludert {followersCount} av fylgjarane dine og {followingCount, plural, one {# konto} other {# kontoar}} du fylgjer.",
@@ -516,7 +535,17 @@
"notification.status": "{name} la nettopp ut",
"notification.update": "{name} redigerte eit innlegg",
"notification_requests.accept": "Godkjenn",
+ "notification_requests.accept_multiple": "{count, plural, one {Godta # førespurnad…} other {Godta # førespurnader…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Godta førespurnad} other {Godta førespurnader}}",
+ "notification_requests.confirm_accept_multiple.message": "Du er i ferd med å godta {count, plural, one {ein førespurnad om varsling} other {# førespurnader om varsling}}. Er du sikker på at du vil halda fram?",
+ "notification_requests.confirm_accept_multiple.title": "Godta førespurnader om varsling?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Avvis førespurnad} other {Avvis førespurnader}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Du er i ferd med å avvisa {count, plural, one {ein førespurnad om varsel} other {# førespurnader om varsel}}. Det blir ikkje lett å få tilgang til {count, plural, one {han} other {dei}} att. Er du sikker på at du vil halda fram?",
+ "notification_requests.confirm_dismiss_multiple.title": "Avvis førespurnader om varsel?",
"notification_requests.dismiss": "Avvis",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Avvis # førespurnad…} other {Avvis # førespurnader…}}",
+ "notification_requests.edit_selection": "Rediger",
+ "notification_requests.exit_selection": "Ferdig",
"notification_requests.explainer_for_limited_account": "Varsla frå denne kontoen er filtrerte ut fordi ein moderator har avgrensa kontoen.",
"notification_requests.explainer_for_limited_remote_account": "Varla frå denne kontoen er filtrerte ut fordi ein moderator har avgrensa kontoen eller tenaren.",
"notification_requests.maximize": "Maksimer",
@@ -530,8 +559,6 @@
"notifications.column_settings.admin.report": "Nye rapportar:",
"notifications.column_settings.admin.sign_up": "Nyleg registrerte:",
"notifications.column_settings.alert": "Skrivebordsvarsel",
- "notifications.column_settings.beta.category": "Eksperimentelle funksjonar",
- "notifications.column_settings.beta.grouping": "Grupper varslingar",
"notifications.column_settings.favourite": "Favorittar:",
"notifications.column_settings.filter_bar.advanced": "Vis alle kategoriar",
"notifications.column_settings.filter_bar.category": "Snøggfilterline",
@@ -751,6 +778,7 @@
"status.bookmark": "Set bokmerke",
"status.cancel_reblog_private": "Opphev framheving",
"status.cannot_reblog": "Du kan ikkje framheva dette innlegget",
+ "status.continued_thread": "Framhald til tråden",
"status.copy": "Kopier lenke til status",
"status.delete": "Slett",
"status.detailed_status": "Detaljert samtalevisning",
@@ -759,7 +787,7 @@
"status.edit": "Rediger",
"status.edited": "Sist endra {date}",
"status.edited_x_times": "Redigert {count, plural, one {{count} gong} other {{count} gonger}}",
- "status.embed": "Bygg inn",
+ "status.embed": "Få innbyggingskode",
"status.favourite": "Favoritt",
"status.favourites": "{count, plural, one {favoritt} other {favorittar}}",
"status.filter": "Filtrer dette innlegget",
@@ -784,6 +812,7 @@
"status.reblogs.empty": "Ingen har framheva dette tutet enno. Om nokon gjer, så dukkar det opp her.",
"status.redraft": "Slett & skriv på nytt",
"status.remove_bookmark": "Fjern bokmerke",
+ "status.replied_in_thread": "Svara i tråden",
"status.replied_to": "Svarte {name}",
"status.reply": "Svar",
"status.replyAll": "Svar til tråd",
diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json
index a3780de550..1d0294cd7c 100644
--- a/app/javascript/mastodon/locales/no.json
+++ b/app/javascript/mastodon/locales/no.json
@@ -11,6 +11,7 @@
"about.not_available": "Denne informasjonen er ikke gjort tilgjengelig på denne tjeneren.",
"about.powered_by": "Desentraliserte sosiale medier drevet av {mastodon}",
"about.rules": "Regler for serveren",
+ "account.account_note_header": "Personlig notat",
"account.add_or_remove_from_list": "Legg til eller fjern fra lister",
"account.badges.bot": "Automatisert",
"account.badges.group": "Gruppe",
@@ -33,7 +34,9 @@
"account.follow_back": "Følg tilbake",
"account.followers": "Følgere",
"account.followers.empty": "Ingen følger denne brukeren ennå.",
+ "account.followers_counter": "{count, plural, one {{counter} følger} other {{counter} følgere}}",
"account.following": "Følger",
+ "account.following_counter": "{count, plural, one {{counter} som følges} other {{counter} som følges}}",
"account.follows.empty": "Denne brukeren følger ikke noen enda.",
"account.go_to_profile": "Gå til profil",
"account.hide_reblogs": "Skjul fremhevinger fra @{name}",
@@ -59,6 +62,7 @@
"account.requested_follow": "{name} har bedt om å få følge deg",
"account.share": "Del @{name} sin profil",
"account.show_reblogs": "Vis fremhevinger fra @{name}",
+ "account.statuses_counter": "{count, plural, one {{counter} innlegg} other {{counter} innlegg}}",
"account.unblock": "Opphev blokkering av @{name}",
"account.unblock_domain": "Opphev blokkering av {domain}",
"account.unblock_short": "Opphev blokkering",
@@ -84,7 +88,17 @@
"announcement.announcement": "Kunngjøring",
"attachments_list.unprocessed": "(ubehandlet)",
"audio.hide": "Skjul lyd",
+ "block_modal.remote_users_caveat": "Vi vil be serveren {domain} om å respektere din beslutning. Det er imidlertid ingen garanti at det blir overholdt, siden noen servere kan håndtere blokkeringer på forskjellig vis. Offentlige innlegg kan fortsatt være synlige for ikke-innloggede brukere.",
+ "block_modal.show_less": "Vis mindre",
+ "block_modal.show_more": "Vis mer",
+ "block_modal.they_cant_mention": "De kan ikke nevne eller følge deg.",
+ "block_modal.they_cant_see_posts": "De kan ikke se dine innlegg og du kommer ikke til å se deres.",
+ "block_modal.they_will_know": "De kan se at de er blitt blokkert.",
+ "block_modal.title": "Blokker bruker?",
+ "block_modal.you_wont_see_mentions": "Du kommer ikke til å se innlegg som nevner dem.",
"boost_modal.combo": "You kan trykke {combo} for å hoppe over dette neste gang",
+ "boost_modal.reblog": "Fremhev innlegg?",
+ "boost_modal.undo_reblog": "Fjern fremheving?",
"bundle_column_error.copy_stacktrace": "Kopier feilrapport",
"bundle_column_error.error.body": "Den forespurte siden kan ikke gjengis. Den kan skyldes en feil i vår kode eller et kompatibilitetsproblem med nettleseren.",
"bundle_column_error.error.title": "Å nei!",
@@ -158,21 +172,30 @@
"confirmations.block.confirm": "Blokkèr",
"confirmations.delete.confirm": "Slett",
"confirmations.delete.message": "Er du sikker på at du vil slette dette innlegget?",
+ "confirmations.delete.title": "Slett innlegg?",
"confirmations.delete_list.confirm": "Slett",
"confirmations.delete_list.message": "Er du sikker på at du vil slette denne listen permanent?",
+ "confirmations.delete_list.title": "Slett liste?",
"confirmations.discard_edit_media.confirm": "Forkast",
"confirmations.discard_edit_media.message": "Du har ulagrede endringer i mediebeskrivelsen eller i forhåndsvisning, forkast dem likevel?",
"confirmations.edit.confirm": "Redigér",
"confirmations.edit.message": "Å redigere nå vil overskrive meldingen du skriver for øyeblikket. Er du sikker på at du vil fortsette?",
+ "confirmations.edit.title": "Overskriv innlegg?",
"confirmations.logout.confirm": "Logg ut",
"confirmations.logout.message": "Er du sikker på at du vil logge ut?",
+ "confirmations.logout.title": "Logg ut?",
"confirmations.mute.confirm": "Demp",
"confirmations.redraft.confirm": "Slett og skriv på nytt",
"confirmations.redraft.message": "Er du sikker på at du vil slette dette innlegget og lagre det på nytt? Favoritter og fremhevinger vil gå tapt, og svar til det originale innlegget vil bli foreldreløse.",
+ "confirmations.redraft.title": "Slett og skriv på nytt?",
"confirmations.reply.confirm": "Svar",
"confirmations.reply.message": "Å svare nå vil overskrive meldingen du skriver for øyeblikket. Er du sikker på at du vil fortsette?",
+ "confirmations.reply.title": "Overskriv innlegg?",
"confirmations.unfollow.confirm": "Slutt å følge",
"confirmations.unfollow.message": "Er du sikker på at du vil slutte å følge {name}?",
+ "confirmations.unfollow.title": "Slutt å følge bruker?",
+ "content_warning.hide": "Skjul innlegg",
+ "content_warning.show": "Vis likevel",
"conversation.delete": "Slett samtalen",
"conversation.mark_as_read": "Marker som lest",
"conversation.open": "Vis samtale",
@@ -192,6 +215,27 @@
"dismissable_banner.explore_statuses": "Disse innleggene fra denne og andre servere i det desentraliserte nettverket får økt oppmerksomhet på denne serveren akkurat nå. Nyere innlegg med flere fremhevinger og favoritter er rangert høyere.",
"dismissable_banner.explore_tags": "Disse emneknaggene snakker folk om akkurat nå, på denne og andre servere i det desentraliserte nettverket.",
"dismissable_banner.public_timeline": "Dette er de siste offentlige innleggene fra mennesker på det sosiale nettet som folk på {domain} følger.",
+ "domain_block_modal.block": "Blokker server",
+ "domain_block_modal.block_account_instead": "Blokker @{name} i stedet",
+ "domain_block_modal.they_can_interact_with_old_posts": "Personer fra denne serveren kan samhandle med dine gamle innlegg.",
+ "domain_block_modal.they_cant_follow": "Ingen fra denne serveren kan følge deg.",
+ "domain_block_modal.they_wont_know": "De kommer ikke til å få vite at du har valgt å blokkere dem.",
+ "domain_block_modal.title": "Blokker domenet?",
+ "domain_block_modal.you_will_lose_followers": "Alle dine følgere fra denne serveren vil bli fjernet.",
+ "domain_block_modal.you_wont_see_posts": "Du vil ikke se innlegg eller få varsler fra brukere på denne serveren.",
+ "domain_pill.activitypub_lets_connect": "Den lar deg koble til og samhandle med folk ikke bare på Mastodon, men også på tvers av forskjellige sosiale apper.",
+ "domain_pill.activitypub_like_language": "ActivityPub er liksom språket Mastodon snakker med andre sosiale nettverk.",
+ "domain_pill.server": "Server",
+ "domain_pill.their_handle": "Deres håndtak:",
+ "domain_pill.their_server": "Deres digitale hjem, hvor alle innleggene deres bor.",
+ "domain_pill.their_username": "Deres unike identifikator på serveren sin. Det er mulig å finne brukere med samme brukernavn på forskjellige servere.",
+ "domain_pill.username": "Brukernavn",
+ "domain_pill.whats_in_a_handle": "Hva er et håndtak?",
+ "domain_pill.who_they_are": "Siden håndtakene sier hvem noen er og hvor de er, kan du samhandle med folk på tvers av det sosiale nettverket bestående av
plattformer som støtter ActivityPub.",
+ "domain_pill.who_you_are": "Fordi ditt håndtak sier hvem du er og hvor du er, kan folk kommunisere med deg på tvers av
plattformer som støtter ActivityPub.",
+ "domain_pill.your_handle": "Din håndtak:",
+ "domain_pill.your_server": "Ditt digitale hjem, hvor alle dine innlegg bor. Liker du ikke denne? Flytt till en annen server når som helst og ta med følgerne dine.",
+ "domain_pill.your_username": "Din unike identifikator på denne serveren. Det er mulig å finne brukere med samme brukernavn på forskjellige servere.",
"embed.instructions": "Kopier koden under for å bygge inn denne statusen på hjemmesiden din.",
"embed.preview": "Slik kommer det til å se ut:",
"emoji_button.activity": "Aktivitet",
@@ -228,6 +272,7 @@
"empty_column.list": "Det er ingenting i denne listen ennå. Når medlemmene av denne listen legger ut nye statuser vil de dukke opp her.",
"empty_column.lists": "Du har ingen lister enda. Når du lager en, vil den dukke opp her.",
"empty_column.mutes": "Du har ikke dempet noen brukere enda.",
+ "empty_column.notification_requests": "Alt klart! Det er ingenting her. Når du mottar nye varsler, vises de her i henhold til dine innstillinger.",
"empty_column.notifications": "Du har ingen varsler ennå. Kommuniser med andre for å begynne samtalen.",
"empty_column.public": "Det er ingenting her! Skriv noe offentlig, eller følg brukere manuelt fra andre instanser for å fylle den opp",
"error.unexpected_crash.explanation": "På grunn av en bug i koden vår eller et nettleserkompatibilitetsproblem, kunne denne siden ikke vises riktig.",
@@ -258,13 +303,30 @@
"filter_modal.select_filter.subtitle": "Bruk en eksisterende kategori eller opprett en ny",
"filter_modal.select_filter.title": "Filtrer dette innlegget",
"filter_modal.title.status": "Filtrer et innlegg",
+ "filter_warning.matches_filter": "Passer med filteret «{title}»",
+ "filtered_notifications_banner.pending_requests": "Fra {count, plural, =0 {ingen} one {en person} other {# folk}} du kanskje kjenner",
+ "filtered_notifications_banner.title": "Filtrerte varsler",
"firehose.all": "Alt",
"firehose.local": "Denne serveren",
"firehose.remote": "Andre servere",
"follow_request.authorize": "Autoriser",
"follow_request.reject": "Avvis",
"follow_requests.unlocked_explanation": "Selv om kontoen din ikke er låst, tror {domain} ansatte at du kanskje vil gjennomgå forespørsler fra disse kontoene manuelt.",
+ "follow_suggestions.curated_suggestion": "Utvalgt av staben",
+ "follow_suggestions.dismiss": "Ikke vis igjen",
+ "follow_suggestions.featured_longer": "Håndplukket av {domain}-teamet",
+ "follow_suggestions.friends_of_friends_longer": "Populært blant personer du følger",
+ "follow_suggestions.hints.featured": "Denne profilen er håndplukket av {domain}-teamet.",
+ "follow_suggestions.hints.friends_of_friends": "Denne profilen er populær blant de du følger.",
+ "follow_suggestions.hints.most_followed": "Denne profilen er en av de på {domain} som har flest følgere.",
+ "follow_suggestions.hints.most_interactions": "Denne profilen fått mye oppmerksomhet i det siste på {domain}.",
+ "follow_suggestions.hints.similar_to_recently_followed": "Denne profilen ligner på profilene du nylig har fulgt.",
+ "follow_suggestions.personalized_suggestion": "Personlig forslag",
+ "follow_suggestions.popular_suggestion": "Populært forslag",
+ "follow_suggestions.popular_suggestion_longer": "Populært på {domain}",
+ "follow_suggestions.similar_to_recently_followed_longer": "Likner på profiler du nylig har fulgt",
"follow_suggestions.view_all": "Vis alle",
+ "follow_suggestions.who_to_follow": "Hvem du kan følge",
"followed_tags": "Fulgte emneknagger",
"footer.about": "Om",
"footer.directory": "Profilkatalog",
@@ -291,6 +353,14 @@
"hashtag.follow": "Følg emneknagg",
"hashtag.unfollow": "Slutt å følge emneknagg",
"hashtags.and_other": "…og {count, plural, one{en til} other {# til}}",
+ "hints.profiles.followers_may_be_missing": "Følgere for denne profilen mangler kanskje.",
+ "hints.profiles.follows_may_be_missing": "Hvem denne profilen følger mangler kanskje.",
+ "hints.profiles.posts_may_be_missing": "Det kan hende at noen av innleggene til denne profilen mangler.",
+ "hints.profiles.see_more_followers": "Se flere følgere på {domain}",
+ "hints.profiles.see_more_follows": "Se flere som følger på {domain}",
+ "hints.profiles.see_more_posts": "Se flere innlegg på {domain}",
+ "hints.threads.replies_may_be_missing": "Svar fra andre servere mangler kanskje.",
+ "hints.threads.see_more": "Se flere svar på {domain}",
"home.column_settings.show_reblogs": "Vis fremhevinger",
"home.column_settings.show_replies": "Vis svar",
"home.hide_announcements": "Skjul kunngjøring",
@@ -298,6 +368,17 @@
"home.pending_critical_update.link": "Se oppdateringer",
"home.pending_critical_update.title": "Kritisk sikkerhetsoppdatering er tilgjengelig!",
"home.show_announcements": "Vis kunngjøring",
+ "ignore_notifications_modal.disclaimer": "Mastodon kan ikke informere brukere at du har ignorert deres varsler. Å ignorere varsler vil ikke stoppe meldinger selv fra å bli sendt.",
+ "ignore_notifications_modal.filter_instead": "Filtrer i stedet",
+ "ignore_notifications_modal.filter_to_act_users": "Du kan fremdeles akseptere, avvise eller rapportere brukere",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "Filtrering bidrar til å unngå potensiell forvirring",
+ "ignore_notifications_modal.filter_to_review_separately": "Du kan gjennomgå filtrerte varsler for seg",
+ "ignore_notifications_modal.ignore": "Overse varsler",
+ "ignore_notifications_modal.limited_accounts_title": "Overse varsler fra modererte kontoer?",
+ "ignore_notifications_modal.new_accounts_title": "Overse varsler fra nye kontoer?",
+ "ignore_notifications_modal.not_followers_title": "Overse varsler fra folk som ikke følger deg?",
+ "ignore_notifications_modal.not_following_title": "Overse varsler fra folk du ikke følger?",
+ "ignore_notifications_modal.private_mentions_title": "Overse varsler fra uoppfordrede private omtaler?",
"interaction_modal.description.favourite": "Med en konto på Mastodon, kan du favorittmarkere dette innlegget for å la forfatteren vite at du satte pris på det, og lagre innlegget til senere.",
"interaction_modal.description.follow": "Med en konto på Mastodon, kan du følge {name} for å få innleggene deres i tidslinjen din.",
"interaction_modal.description.reblog": "Med en konto på Mastodon, kan du fremheve dette innlegget for å dele det med dine egne følgere.",
@@ -351,13 +432,13 @@
"keyboard_shortcuts.unfocus": "Fjern fokus fra komponerings-/søkefeltet",
"keyboard_shortcuts.up": "Flytt oppover i listen",
"lightbox.close": "Lukk",
- "lightbox.compress": "Komprimer bildevisningsboks",
- "lightbox.expand": "Ekspander bildevisning boks",
"lightbox.next": "Neste",
"lightbox.previous": "Forrige",
"limited_account_hint.action": "Vis profil likevel",
"limited_account_hint.title": "Denne profilen har blitt skjult av moderatorene til {domain}.",
"link_preview.author": "Av {name}",
+ "link_preview.more_from_author": "Mer fra {name}",
+ "link_preview.shares": "{count, plural, one {{counter} innlegg} other {{counter} innlegg}}",
"lists.account.add": "Legg til i listen",
"lists.account.remove": "Fjern fra listen",
"lists.delete": "Slett listen",
@@ -374,9 +455,18 @@
"lists.subheading": "Dine lister",
"load_pending": "{count, plural,one {# ny gjenstand} other {# nye gjenstander}}",
"loading_indicator.label": "Laster…",
- "media_gallery.toggle_visible": "Veksle synlighet",
"moved_to_account_banner.text": "Din konto {disabledAccount} er for øyeblikket deaktivert fordi du flyttet til {movedToAccount}.",
+ "mute_modal.hide_from_notifications": "Ikke varsle",
+ "mute_modal.hide_options": "Skjul alternativer",
+ "mute_modal.indefinite": "Til jeg opphever dempingen",
+ "mute_modal.show_options": "Vis alternativer",
+ "mute_modal.they_can_mention_and_follow": "De kan nevne og følge deg, men du kommer ikke til å se dem.",
+ "mute_modal.they_wont_know": "De kommer ikke til å få vite at du har valgt å skjule dem.",
+ "mute_modal.title": "Demp bruker?",
+ "mute_modal.you_wont_see_mentions": "Du kommer ikke til å se innlegg som nevner dem.",
+ "mute_modal.you_wont_see_posts": "De kan fremdeles se dine innlegg, men du kommer ikke til å se deres.",
"navigation_bar.about": "Om",
+ "navigation_bar.administration": "Administrasjon",
"navigation_bar.advanced_interface": "Åpne i det avanserte nettgrensesnittet",
"navigation_bar.blocks": "Blokkerte brukere",
"navigation_bar.bookmarks": "Bokmerker",
@@ -393,6 +483,7 @@
"navigation_bar.follows_and_followers": "Følginger og følgere",
"navigation_bar.lists": "Lister",
"navigation_bar.logout": "Logg ut",
+ "navigation_bar.moderation": "Moderering",
"navigation_bar.mutes": "Dempede brukere",
"navigation_bar.opened_in_classic_interface": "Innlegg, kontoer og andre spesifikke sider åpnes som standard i det klassiske webgrensesnittet.",
"navigation_bar.personal": "Personlig",
@@ -403,6 +494,7 @@
"navigation_bar.security": "Sikkerhet",
"not_signed_in_indicator.not_signed_in": "Du må logge inn for å få tilgang til denne ressursen.",
"notification.admin.report": "{name} rapporterte {target}",
+ "notification.admin.report_account": "{name} rapporterte {count, plural, one {et innlegg} other {# innlegg}} fra {target} for {category}",
"notification.admin.sign_up": "{name} registrerte seg",
"notification.favourite": "{name} favorittmarkerte innlegget ditt",
"notification.follow": "{name} fulgte deg",
@@ -417,6 +509,8 @@
"notifications.column_settings.admin.sign_up": "Nye registreringer:",
"notifications.column_settings.alert": "Skrivebordsvarslinger",
"notifications.column_settings.favourite": "Favoritter:",
+ "notifications.column_settings.filter_bar.advanced": "Vis alle kategorier",
+ "notifications.column_settings.filter_bar.category": "Hurtigfiltreringslinje",
"notifications.column_settings.follow": "Nye følgere:",
"notifications.column_settings.follow_request": "Nye følgerforespørsler:",
"notifications.column_settings.mention": "Nevnt:",
@@ -442,6 +536,23 @@
"notifications.permission_denied": "Skrivebordsvarsler er ikke tilgjengelige på grunn av tidligere nektet nettlesertillatelser",
"notifications.permission_denied_alert": "Skrivebordsvarsler kan ikke aktiveres, ettersom lesertillatelse har blitt nektet før",
"notifications.permission_required": "Skrivebordsvarsler er utilgjengelige fordi nødvendige rettigheter ikke er gitt.",
+ "notifications.policy.accept": "Godta",
+ "notifications.policy.accept_hint": "Vis i varsler",
+ "notifications.policy.drop": "Overse",
+ "notifications.policy.drop_hint": "Send til avgrunnen, for aldri å bli sett igjen",
+ "notifications.policy.filter": "Filter",
+ "notifications.policy.filter_hint": "Send til filtrert varslingsinnboks",
+ "notifications.policy.filter_limited_accounts_hint": "Begrenset av serverens moderatorer",
+ "notifications.policy.filter_limited_accounts_title": "Modererte kontoer",
+ "notifications.policy.filter_new_accounts.hint": "Opprettet {days, plural, one {den siste dagen} other {i de siste # dagene}}",
+ "notifications.policy.filter_new_accounts_title": "Nye kontoer",
+ "notifications.policy.filter_not_followers_hint": "Inkludert personer som har fulgt deg mindre enn {days, plural, one {en dag} other {# dager}}",
+ "notifications.policy.filter_not_followers_title": "Personer som ikke følger deg",
+ "notifications.policy.filter_not_following_hint": "Inntil du manuelt godkjenner dem",
+ "notifications.policy.filter_not_following_title": "Personer du ikke følger",
+ "notifications.policy.filter_private_mentions_hint": "Filtrert med mindre det er et svar som omtaler deg, eller hvis du følger avsenderen",
+ "notifications.policy.filter_private_mentions_title": "Uoppfordrede private omtaler",
+ "notifications.policy.title": "Behandle varsler fra…",
"notifications_permission_banner.enable": "Skru på skrivebordsvarsler",
"notifications_permission_banner.how_to_control": "For å motta varsler når Mastodon ikke er åpne, aktiver desktop varsler. Du kan kontrollere nøyaktig hvilke typer interaksjoner genererer skrivebordsvarsler gjennom {icon} -knappen ovenfor når de er aktivert.",
"notifications_permission_banner.title": "Aldri gå glipp av noe",
@@ -602,7 +713,7 @@
"sign_in_banner.sso_redirect": "Logg inn eller registrer deg",
"status.admin_account": "Åpne moderatorgrensesnittet for @{name}",
"status.admin_domain": "Åpne moderatorgrensesnittet for {domain}",
- "status.admin_status": "Åpne denne statusen i moderatorgrensesnittet",
+ "status.admin_status": "Åpne dette innlegget i moderatorgrensesnittet",
"status.block": "Blokker @{name}",
"status.bookmark": "Bokmerke",
"status.cancel_reblog_private": "Fjern fremheving",
@@ -614,7 +725,6 @@
"status.direct_indicator": "Privat omtale",
"status.edit": "Rediger",
"status.edited_x_times": "Redigert {count, plural,one {{count} gang} other {{count} ganger}}",
- "status.embed": "Bygge inn",
"status.favourite": "Favoritt",
"status.filter": "Filtrer dette innlegget",
"status.history.created": "{name} opprettet {date}",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index a4e552ba45..9dbd123c9b 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -297,8 +297,6 @@
"keyboard_shortcuts.unfocus": "quitar lo camp tèxte/de recèrca",
"keyboard_shortcuts.up": "far montar dins la lista",
"lightbox.close": "Tampar",
- "lightbox.compress": "Fenèstra de visualizacion dels imatges compressats",
- "lightbox.expand": "Espandir la fenèstra de visualizacion d’imatge",
"lightbox.next": "Seguent",
"lightbox.previous": "Precedent",
"limited_account_hint.action": "Afichar lo perfil de tota manièra",
@@ -319,7 +317,6 @@
"lists.subheading": "Vòstras listas",
"load_pending": "{count, plural, one {# nòu element} other {# nòu elements}}",
"loading_indicator.label": "Cargament…",
- "media_gallery.toggle_visible": "Modificar la visibilitat",
"navigation_bar.about": "A prepaus",
"navigation_bar.advanced_interface": "Dobrir l’interfàcia web avançada",
"navigation_bar.blocks": "Personas blocadas",
@@ -506,7 +503,6 @@
"status.direct_indicator": "Mencion privada",
"status.edit": "Modificar",
"status.edited_x_times": "Modificat {count, plural, un {{count} còp} other {{count} còps}}",
- "status.embed": "Embarcar",
"status.favourite": "Apondre als favorits",
"status.filter": "Filtrar aquesta publicacion",
"status.history.created": "{name} o creèt lo {date}",
diff --git a/app/javascript/mastodon/locales/pa.json b/app/javascript/mastodon/locales/pa.json
index a71c01b3c1..5da88ff08f 100644
--- a/app/javascript/mastodon/locales/pa.json
+++ b/app/javascript/mastodon/locales/pa.json
@@ -320,7 +320,6 @@
"status.delete": "ਹਟਾਓ",
"status.edit": "ਸੋਧ",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "ਮੜ੍ਹੋ",
"status.favourite": "ਪਸੰਦ",
"status.history.created": "{name} ਨੇ {date} ਨੂੰ ਬਣਾਇਆ",
"status.history.edited": "{name} ਨੇ {date} ਨੂੰ ਸੋਧਿਆ",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index 2a4c5d6e44..a4ee25250a 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -97,6 +97,8 @@
"block_modal.title": "Zablokować użytkownika?",
"block_modal.you_wont_see_mentions": "Nie zobaczysz wpisów, które wspominają tego użytkownika.",
"boost_modal.combo": "Naciśnij {combo}, aby pominąć to następnym razem",
+ "boost_modal.reblog": "Podbić wpis?",
+ "boost_modal.undo_reblog": "Cofnąć podbicie?",
"bundle_column_error.copy_stacktrace": "Skopiuj raport o błędzie",
"bundle_column_error.error.body": "Nie można zrenderować żądanej strony. Może to być spowodowane błędem w naszym kodzie lub problemami z kompatybilnością przeglądarki.",
"bundle_column_error.error.title": "O nie!",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "aby opuścić pole wyszukiwania/pisania",
"keyboard_shortcuts.up": "aby przejść na górę listy",
"lightbox.close": "Zamknij",
- "lightbox.compress": "Zmniejsz pole widoku obrazu",
- "lightbox.expand": "Rozwiń pole widoku obrazu",
"lightbox.next": "Następne",
"lightbox.previous": "Poprzednie",
+ "lightbox.zoom_in": "Rozmiar rzeczywisty",
+ "lightbox.zoom_out": "Dopasuj",
"limited_account_hint.action": "Pokaż profil mimo to",
"limited_account_hint.title": "Ten profil został ukryty przez moderatorów {domain}.",
"link_preview.author": "{name}",
@@ -455,7 +457,7 @@
"lists.subheading": "Twoje listy",
"load_pending": "{count, plural, one {# nowa pozycja} other {nowe pozycje}}",
"loading_indicator.label": "Ładowanie…",
- "media_gallery.toggle_visible": "Przełącz widoczność",
+ "media_gallery.hide": "Ukryj",
"moved_to_account_banner.text": "Twoje konto {disabledAccount} jest obecnie wyłączone, ponieważ zostało przeniesione na {movedToAccount}.",
"mute_modal.hide_from_notifications": "Ukryj z powiadomień",
"mute_modal.hide_options": "Ukryj opcje",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Nie zobaczysz wpisów, które wspominają tego użytkownika.",
"mute_modal.you_wont_see_posts": "Użytkownik dalej będzie widzieć Twoje posty, ale Ty nie będziesz widzieć jego.",
"navigation_bar.about": "O serwerze",
+ "navigation_bar.administration": "Administracja",
"navigation_bar.advanced_interface": "Otwórz w zaawansowanym interfejsie użytkownika",
"navigation_bar.blocks": "Zablokowani użytkownicy",
"navigation_bar.bookmarks": "Zakładki",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "Obserwowani i obserwujący",
"navigation_bar.lists": "Listy",
"navigation_bar.logout": "Wyloguj",
+ "navigation_bar.moderation": "Moderacja",
"navigation_bar.mutes": "Wyciszeni użytkownicy",
"navigation_bar.opened_in_classic_interface": "Posty, konta i inne konkretne strony są otwierane domyślnie w klasycznym interfejsie sieciowym.",
"navigation_bar.personal": "Osobiste",
@@ -527,6 +531,7 @@
"notification.relationships_severance_event.account_suspension": "Administrator z {from} zawiesił {target}, więc nie dostaniesz wieści ani nie wejdziesz w interakcje z użytkownikami z tego serwera.",
"notification.relationships_severance_event.domain_block": "Administrator z {from} zablokował {target}, w tym {followersCount} z Twoich obserwujących i {followingCount, plural, one {# konto} other {# konta}} które obserwujesz.",
"notification.relationships_severance_event.learn_more": "Dowiedz się więcej",
+ "notification.relationships_severance_event.user_domain_block": "Zablokowałeś {target}, w tym {followersCount} z Twoich obserwujących i {followingCount, plural, one {# konto} other {# konta}} które obserwujesz.",
"notification.status": "{name} opublikował(a) nowy wpis",
"notification.update": "{name} edytował(a) post",
"notification_requests.accept": "Akceptuj",
@@ -554,8 +559,6 @@
"notifications.column_settings.admin.report": "Nowe zgłoszenia:",
"notifications.column_settings.admin.sign_up": "Nowe rejestracje:",
"notifications.column_settings.alert": "Powiadomienia na pulpicie",
- "notifications.column_settings.beta.category": "Funkcje eksperymentalne",
- "notifications.column_settings.beta.grouping": "Powiadomienia grupowe",
"notifications.column_settings.favourite": "Ulubione:",
"notifications.column_settings.filter_bar.advanced": "Wyświetl wszystkie kategorie",
"notifications.column_settings.filter_bar.category": "Szybkie filtrowanie",
@@ -775,6 +778,7 @@
"status.bookmark": "Dodaj zakładkę",
"status.cancel_reblog_private": "Cofnij podbicie",
"status.cannot_reblog": "Ten wpis nie może zostać podbity",
+ "status.continued_thread": "Ciąg dalszy wątku",
"status.copy": "Skopiuj odnośnik do wpisu",
"status.delete": "Usuń",
"status.detailed_status": "Szczegółowy widok konwersacji",
@@ -783,7 +787,7 @@
"status.edit": "Edytuj",
"status.edited": "Ostatnio edytowane {date}",
"status.edited_x_times": "Edytowano {count, plural, one {{count} raz} other {{count} razy}}",
- "status.embed": "Osadź",
+ "status.embed": "Kod osadzenia",
"status.favourite": "Dodaj do ulubionych",
"status.favourites": "{count, plural, one {polubienie} few {polubienia} other {polubień}}",
"status.filter": "Filtruj ten wpis",
@@ -808,6 +812,7 @@
"status.reblogs.empty": "Nikt nie podbił jeszcze tego wpisu. Gdy ktoś to zrobi, pojawi się tutaj.",
"status.redraft": "Usuń i przeredaguj",
"status.remove_bookmark": "Usuń zakładkę",
+ "status.replied_in_thread": "Odpowiedź w wątku",
"status.replied_to": "Odpowiedź do wpisu użytkownika {name}",
"status.reply": "Odpowiedz",
"status.replyAll": "Odpowiedz na wątek",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index 14957c16d4..1eca63ac15 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -11,6 +11,7 @@
"about.not_available": "Esta informação não foi disponibilizada neste servidor.",
"about.powered_by": "Redes sociais descentralizadas alimentadas por {mastodon}",
"about.rules": "Regras do servidor",
+ "account.account_note_header": "Nota pessoal",
"account.add_or_remove_from_list": "Adicionar ou remover de listas",
"account.badges.bot": "Robô",
"account.badges.group": "Grupo",
@@ -61,6 +62,7 @@
"account.requested_follow": "{name} quer te seguir",
"account.share": "Compartilhar perfil de @{name}",
"account.show_reblogs": "Mostrar boosts de @{name}",
+ "account.statuses_counter": "{count, plural, one {{counter} publicação} other {{counter} publicações}}",
"account.unblock": "Desbloquear @{name}",
"account.unblock_domain": "Desbloquear domínio {domain}",
"account.unblock_short": "Desbloquear",
@@ -95,6 +97,8 @@
"block_modal.title": "Bloquear usuário?",
"block_modal.you_wont_see_mentions": "Você não verá publicações que os mencionem.",
"boost_modal.combo": "Pressione {combo} para pular isso na próxima vez",
+ "boost_modal.reblog": "Impulsionar a publicação?",
+ "boost_modal.undo_reblog": "Retirar o impulsionamento do post?",
"bundle_column_error.copy_stacktrace": "Copiar relatório do erro",
"bundle_column_error.error.body": "A página solicitada não pôde ser renderizada. Pode ser devido a um erro no nosso código, ou um problema de compatibilidade do seu navegador.",
"bundle_column_error.error.title": "Ah, não!",
@@ -190,6 +194,8 @@
"confirmations.unfollow.confirm": "Deixar de seguir",
"confirmations.unfollow.message": "Você tem certeza de que deseja deixar de seguir {name}?",
"confirmations.unfollow.title": "Deixar de seguir o usuário?",
+ "content_warning.hide": "Ocultar post",
+ "content_warning.show": "Mostrar mesmo assim",
"conversation.delete": "Excluir conversa",
"conversation.mark_as_read": "Marcar como lida",
"conversation.open": "Ver conversa",
@@ -297,6 +303,8 @@
"filter_modal.select_filter.subtitle": "Use uma categoria existente ou crie uma nova",
"filter_modal.select_filter.title": "Filtrar esta publicação",
"filter_modal.title.status": "Filtrar uma publicação",
+ "filter_warning.matches_filter": "Correspondente ao filtro “{title}”",
+ "filtered_notifications_banner.pending_requests": "Por {count, plural, =0 {no one} one {one person} other {# people}} que você talvez conheça",
"filtered_notifications_banner.title": "Notificações filtradas",
"firehose.all": "Tudo",
"firehose.local": "Este servidor",
@@ -345,6 +353,14 @@
"hashtag.follow": "Seguir hashtag",
"hashtag.unfollow": "Parar de seguir hashtag",
"hashtags.and_other": "…e {count, plural, one {}other {outros #}}",
+ "hints.profiles.followers_may_be_missing": "Os seguidores deste perfil podem estar faltando.",
+ "hints.profiles.follows_may_be_missing": "Os seguidores deste perfil podem estar faltando.",
+ "hints.profiles.posts_may_be_missing": "É possível que algumas publicações deste perfil estejam faltando.",
+ "hints.profiles.see_more_followers": "Ver mais seguidores no {domain}",
+ "hints.profiles.see_more_follows": "Ver mais seguidores no {domain}",
+ "hints.profiles.see_more_posts": "Ver mais publicações em {domain}",
+ "hints.threads.replies_may_be_missing": "Respostas de outros servidores podem estar faltando.",
+ "hints.threads.see_more": "Ver mais respostas no {domain}",
"home.column_settings.show_reblogs": "Mostrar boosts",
"home.column_settings.show_replies": "Mostrar respostas",
"home.hide_announcements": "Ocultar comunicados",
@@ -352,6 +368,13 @@
"home.pending_critical_update.link": "Ver atualizações",
"home.pending_critical_update.title": "Atualização de segurança crítica disponível!",
"home.show_announcements": "Mostrar comunicados",
+ "ignore_notifications_modal.disclaimer": "O Mastodon não pode informar aos usuários que você ignorou suas notificações. Ignorar notificações não impedirá que as próprias mensagens sejam enviadas.",
+ "ignore_notifications_modal.filter_instead": "Filtrar em vez disso",
+ "ignore_notifications_modal.filter_to_act_users": "Você ainda conseguirá aceitar, rejeitar ou denunciar usuários",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "A filtragem ajuda a evitar confusão potencial",
+ "ignore_notifications_modal.filter_to_review_separately": "Você pode rever notificações filtradas separadamente",
+ "ignore_notifications_modal.ignore": "Ignorar notificações",
+ "ignore_notifications_modal.limited_accounts_title": "Ignorar notificações de contas moderadas?",
"ignore_notifications_modal.new_accounts_title": "Ignorar notificações de novas contas?",
"ignore_notifications_modal.not_followers_title": "Ignorar notificações de pessoas que não seguem você?",
"ignore_notifications_modal.not_following_title": "Ignorar notificações de pessoas que você não segue?",
@@ -409,10 +432,9 @@
"keyboard_shortcuts.unfocus": "desfocar de tudo",
"keyboard_shortcuts.up": "mover para cima",
"lightbox.close": "Fechar",
- "lightbox.compress": "Fechar imagem",
- "lightbox.expand": "Abrir imagem",
"lightbox.next": "Próximo",
"lightbox.previous": "Anterior",
+ "lightbox.zoom_in": "Voltar para o tamanho real",
"limited_account_hint.action": "Exibir perfil mesmo assim",
"limited_account_hint.title": "Este perfil foi ocultado pelos moderadores do {domain}.",
"link_preview.author": "Por {name}",
@@ -434,7 +456,7 @@
"lists.subheading": "Suas listas",
"load_pending": "{count, plural, one {# novo item} other {# novos items}}",
"loading_indicator.label": "Carregando…",
- "media_gallery.toggle_visible": "{number, plural, one {Ocultar mídia} other {Ocultar mídias}}",
+ "media_gallery.hide": "Ocultar",
"moved_to_account_banner.text": "Sua conta {disabledAccount} está desativada porque você a moveu para {movedToAccount}.",
"mute_modal.hide_from_notifications": "Ocultar das notificações",
"mute_modal.hide_options": "Ocultar opções",
@@ -446,6 +468,7 @@
"mute_modal.you_wont_see_mentions": "Você não verá publicações que os mencionem.",
"mute_modal.you_wont_see_posts": "Eles ainda poderão ver suas publicações, mas você não verá as deles.",
"navigation_bar.about": "Sobre",
+ "navigation_bar.administration": "Administração",
"navigation_bar.advanced_interface": "Ativar na interface web avançada",
"navigation_bar.blocks": "Usuários bloqueados",
"navigation_bar.bookmarks": "Salvos",
@@ -462,6 +485,7 @@
"navigation_bar.follows_and_followers": "Segue e seguidores",
"navigation_bar.lists": "Listas",
"navigation_bar.logout": "Sair",
+ "navigation_bar.moderation": "Moderação",
"navigation_bar.mutes": "Usuários silenciados",
"navigation_bar.opened_in_classic_interface": "Publicações, contas e outras páginas específicas são abertas por padrão na interface 'web' clássica.",
"navigation_bar.personal": "Pessoal",
@@ -472,10 +496,23 @@
"navigation_bar.security": "Segurança",
"not_signed_in_indicator.not_signed_in": "Você precisa se autenticar para acessar este recurso.",
"notification.admin.report": "{name} denunciou {target}",
+ "notification.admin.report_account": "{name} reportou {count, plural, one {Um post} other {# posts}} de {target} para {category}",
+ "notification.admin.report_account_other": "{name} reportou {count, plural, one {Um post} other {# posts}} de {target}",
+ "notification.admin.report_statuses": "{name} Reportou {target} para {category}",
+ "notification.admin.report_statuses_other": "{name} denunciou {target}",
"notification.admin.sign_up": "{name} se inscreveu",
+ "notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# other} other {# outros}}",
"notification.favourite": "{name} favoritou sua publicação",
+ "notification.favourite.name_and_others_with_link": "{name} e
{count, plural, one {# outro} other {# others}} favoritaram a publicação",
"notification.follow": "{name} te seguiu",
+ "notification.follow.name_and_others": "{name} e {count, plural, one {# other} other {# outros}} seguiu você",
"notification.follow_request": "{name} quer te seguir",
+ "notification.follow_request.name_and_others": "{name} e {count, plural, one {# other} other {# outros}} pediu para seguir você",
+ "notification.label.mention": "Menção",
+ "notification.label.private_mention": "Menção privada",
+ "notification.label.private_reply": "Resposta privada",
+ "notification.label.reply": "Resposta",
+ "notification.mention": "Menção",
"notification.moderation-warning.learn_more": "Aprender mais",
"notification.moderation_warning": "Você recebeu um aviso de moderação",
"notification.moderation_warning.action_delete_statuses": "Algumas das suas publicações foram removidas.",
@@ -486,7 +523,9 @@
"notification.moderation_warning.action_silence": "Sua conta foi limitada.",
"notification.moderation_warning.action_suspend": "Sua conta foi suspensa.",
"notification.own_poll": "Sua enquete terminou",
+ "notification.poll": "Uma enquete que você votou terminou",
"notification.reblog": "{name} deu boost no teu toot",
+ "notification.reblog.name_and_others_with_link": "{name} e
{count, plural, one {# outra} other {# outras}} impulsionaram a publicação",
"notification.relationships_severance_event": "Conexões perdidas com {name}",
"notification.relationships_severance_event.account_suspension": "Um administrador de {from} suspendeu {target}, o que significa que você não pode mais receber atualizações deles ou interagir com eles.",
"notification.relationships_severance_event.domain_block": "An admin from {from} has blocked {target}, including {followersCount} of your followers and {followingCount, plural, one {# account} other {# accounts}} you follow.",
@@ -495,10 +534,24 @@
"notification.status": "{name} acabou de tootar",
"notification.update": "{name} editou uma publicação",
"notification_requests.accept": "Aceitar",
+ "notification_requests.accept_multiple": "{count, plural, one {Aceite # pedido…} other {Aceite # pedidos…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Aceite # pedido} other {Aceite # pedidos}}",
+ "notification_requests.confirm_accept_multiple.message": "Você está prestes a aceitar {count, plural, one {um pedido de notificação} other {# pedidos de notificação}}. Tem certeza de que deseja continuar?",
+ "notification_requests.confirm_accept_multiple.title": "Aceitar solicitações de notificação?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Dispensar pedido} other {Dispensar pedidos}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Você está prestes a descartar {count, plural, one {um pedido de notificação} other {# pedidos de notificação}}. Você não será capaz de acessar facilmente{count, plural, one {} other {}} novamente. Tem certeza de que deseja continuar?",
+ "notification_requests.confirm_dismiss_multiple.title": "Descartar solicitações de notificação?",
"notification_requests.dismiss": "Rejeitar",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Dispensar # pedido…} other {Dispensar # pedidos…}}",
+ "notification_requests.edit_selection": "Editar",
+ "notification_requests.exit_selection": "Concluído",
+ "notification_requests.explainer_for_limited_account": "As notificações desta conta foram filtradas porque a conta foi limitada por um moderador.",
+ "notification_requests.explainer_for_limited_remote_account": "As notificações desta conta foram filtradas porque a conta ou o seu servidor foi limitado por um moderador.",
"notification_requests.maximize": "Maximizar",
+ "notification_requests.minimize_banner": "Minimizar banner de notificações filtradas",
"notification_requests.notifications_from": "Notificações de {name}",
"notification_requests.title": "Notificações filtradas",
+ "notification_requests.view": "Ver notificações",
"notifications.clear": "Limpar notificações",
"notifications.clear_confirmation": "Você tem certeza de que deseja limpar todas as suas notificações?",
"notifications.clear_title": "Limpar notificações?",
@@ -536,6 +589,11 @@
"notifications.policy.accept": "Aceitar",
"notifications.policy.accept_hint": "Mostrar nas notificações",
"notifications.policy.drop": "Ignorar",
+ "notifications.policy.drop_hint": "Envie para o void, para nunca mais ser visto novamente",
+ "notifications.policy.filter": "Filtrar",
+ "notifications.policy.filter_hint": "Enviar para caixa de notificações filtradas",
+ "notifications.policy.filter_limited_accounts_hint": "Limitado pelos moderadores do servidor",
+ "notifications.policy.filter_limited_accounts_title": "Contas moderadas",
"notifications.policy.filter_new_accounts.hint": "Created within the past {days, plural, one {one day} other {# days}}",
"notifications.policy.filter_new_accounts_title": "Novas contas",
"notifications.policy.filter_not_followers_hint": "Including people who have been following you fewer than {days, plural, one {one day} other {# days}}",
@@ -544,6 +602,7 @@
"notifications.policy.filter_not_following_title": "Pessoas que você não segue",
"notifications.policy.filter_private_mentions_hint": "Filtrado, a menos que respondido em sua própria menção ou se você segue o remetente",
"notifications.policy.filter_private_mentions_title": "Menções privadas não solicitadas",
+ "notifications.policy.title": "Gerenciar notificações de…",
"notifications_permission_banner.enable": "Ativar notificações no computador",
"notifications_permission_banner.how_to_control": "Para receber notificações quando o Mastodon não estiver aberto, ative as notificações no computador. Você pode controlar precisamente quais tipos de interações geram notificações no computador através do botão {icon}.",
"notifications_permission_banner.title": "Nunca perca nada",
@@ -670,9 +729,13 @@
"report.unfollow_explanation": "Você está seguindo esta conta. Para não ver as publicações dela em sua página inicial, deixe de segui-la.",
"report_notification.attached_statuses": "{count, plural, one {{count} publicação anexada} other {{count} publicações anexadas}}",
"report_notification.categories.legal": "Legal",
+ "report_notification.categories.legal_sentence": "conteúdo ilegal",
"report_notification.categories.other": "Outro",
+ "report_notification.categories.other_sentence": "outro",
"report_notification.categories.spam": "Spam",
+ "report_notification.categories.spam_sentence": "spam",
"report_notification.categories.violation": "Violação de regra",
+ "report_notification.categories.violation_sentence": "violação de regra",
"report_notification.open": "Abrir denúncia",
"search.no_recent_searches": "Nenhuma busca recente",
"search.placeholder": "Pesquisar",
@@ -714,6 +777,7 @@
"status.bookmark": "Salvar",
"status.cancel_reblog_private": "Desfazer boost",
"status.cannot_reblog": "Este toot não pode receber boost",
+ "status.continued_thread": "Continuação da conversa",
"status.copy": "Copiar link",
"status.delete": "Excluir",
"status.detailed_status": "Visão detalhada da conversa",
@@ -722,7 +786,7 @@
"status.edit": "Editar",
"status.edited": "Última edição em {date}",
"status.edited_x_times": "Editado {count, plural, one {{count} hora} other {{count} vezes}}",
- "status.embed": "Incorporar",
+ "status.embed": "Obter código de incorporação",
"status.favourite": "Favorita",
"status.favourites": "{count, plural, one {favorite} other {favorites}}",
"status.filter": "Filtrar esta publicação",
@@ -747,6 +811,7 @@
"status.reblogs.empty": "Nada aqui. Quando alguém der boost, o usuário aparecerá aqui.",
"status.redraft": "Excluir e rascunhar",
"status.remove_bookmark": "Remover do Salvos",
+ "status.replied_in_thread": "Respondido na discussão",
"status.replied_to": "Em resposta a {name}",
"status.reply": "Responder",
"status.replyAll": "Responder a conversa",
diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json
index e2414963c5..80f5f9f138 100644
--- a/app/javascript/mastodon/locales/pt-PT.json
+++ b/app/javascript/mastodon/locales/pt-PT.json
@@ -43,7 +43,7 @@
"account.in_memoriam": "Em Memória.",
"account.joined_short": "Juntou-se a",
"account.languages": "Alterar línguas subscritas",
- "account.link_verified_on": "A posse desta ligação foi verificada em {date}",
+ "account.link_verified_on": "O proprietário desta hiperligação foi verificado em {date}",
"account.locked_info": "Esta conta é privada. O proprietário revê manualmente quem o pode seguir.",
"account.media": "Média",
"account.mention": "Mencionar @{name}",
@@ -97,6 +97,8 @@
"block_modal.title": "Bloquear utilizador?",
"block_modal.you_wont_see_mentions": "Não verá publicações que os mencionem.",
"boost_modal.combo": "Pode clicar {combo} para não voltar a ver",
+ "boost_modal.reblog": "Impulsionar a publicação?",
+ "boost_modal.undo_reblog": "Retirar post?",
"bundle_column_error.copy_stacktrace": "Copiar relatório de erros",
"bundle_column_error.error.body": "A página solicitada não pôde ser sintetizada. Isto pode ser devido a uma falha no nosso código ou a um problema de compatibilidade com o navegador.",
"bundle_column_error.error.title": "Ó, não!",
@@ -152,15 +154,15 @@
"compose_form.lock_disclaimer": "A sua conta não é {locked}. Qualquer pessoa pode segui-lo e ver as publicações direcionadas apenas a seguidores.",
"compose_form.lock_disclaimer.lock": "fechada",
"compose_form.placeholder": "Em que está a pensar?",
- "compose_form.poll.duration": "Duração do inquérito",
+ "compose_form.poll.duration": "Duração da sondagem",
"compose_form.poll.multiple": "Escolha múltipla",
"compose_form.poll.option_placeholder": "Opção {number}",
"compose_form.poll.single": "Escolha uma",
- "compose_form.poll.switch_to_multiple": "Alterar o inquérito para permitir várias respostas",
- "compose_form.poll.switch_to_single": "Alterar o inquérito para permitir uma única resposta",
+ "compose_form.poll.switch_to_multiple": "Alterar a sondagem para permitir várias respostas",
+ "compose_form.poll.switch_to_single": "Alterar a sondagem para permitir uma única resposta",
"compose_form.poll.type": "Estilo",
"compose_form.publish": "Publicar",
- "compose_form.publish_form": "Publicar",
+ "compose_form.publish_form": "Nova publicação",
"compose_form.reply": "Responder",
"compose_form.save_changes": "Atualizar",
"compose_form.spoiler.marked": "Texto escondido atrás de aviso",
@@ -187,11 +189,13 @@
"confirmations.redraft.message": "Tem a certeza de que quer eliminar e reescrever esta publicação? Os favoritos e partilhas perder-se-ão e as respostas à publicação original ficarão órfãs.",
"confirmations.redraft.title": "Eliminar e reescrever publicação?",
"confirmations.reply.confirm": "Responder",
- "confirmations.reply.message": "Responder agora irá reescrever a mensagem que está a compor actualmente. Tem a certeza que quer continuar?",
+ "confirmations.reply.message": "Se responder agora, a mensagem que está a escrever será substituída. Tem a certeza que pretende continuar?",
"confirmations.reply.title": "Sobrescrever publicação?",
"confirmations.unfollow.confirm": "Deixar de seguir",
"confirmations.unfollow.message": "De certeza que queres deixar de seguir {name}?",
"confirmations.unfollow.title": "Deixar de seguir utilizador?",
+ "content_warning.hide": "Ocultar publicação",
+ "content_warning.show": "Mostrar mesmo assim",
"conversation.delete": "Eliminar conversa",
"conversation.mark_as_read": "Marcar como lida",
"conversation.open": "Ver conversa",
@@ -202,14 +206,14 @@
"directory.federated": "Do fediverso conhecido",
"directory.local": "Apenas de {domain}",
"directory.new_arrivals": "Recém chegados",
- "directory.recently_active": "Com actividade recente",
+ "directory.recently_active": "Recentemente ativo",
"disabled_account_banner.account_settings": "Definições da conta",
"disabled_account_banner.text": "A sua conta {disabledAccount} está presentemente desativada.",
"dismissable_banner.community_timeline": "Estas são as publicações públicas mais recentes de pessoas cujas contas são hospedadas por {domain}.",
"dismissable_banner.dismiss": "Descartar",
"dismissable_banner.explore_links": "Essas histórias de notícias estão, no momento, a ser faladas por pessoas neste e noutros servidores da rede descentralizada.",
"dismissable_banner.explore_statuses": "Estas são publicações de toda a rede social que estão a ganhar popularidade atualmente. As mensagens mais recentes com mais partilhas e favoritos obtêm uma classificação mais elevada.",
- "dismissable_banner.explore_tags": "Estas #etiquetas estão presentemente a ganhar atenção entre as pessoas neste e noutros servidores da rede descentralizada.",
+ "dismissable_banner.explore_tags": "Estas são hashtags que estão a ganhar força na rede social atualmente. As hashtags que são utilizadas por mais pessoas diferentes têm uma classificação mais elevada.",
"dismissable_banner.public_timeline": "Estas são as publicações públicas mais recentes de pessoas na rede social que as pessoas em {domain} seguem.",
"domain_block_modal.block": "Bloquear servidor",
"domain_block_modal.block_account_instead": "Bloquear @{name} em alternativa",
@@ -234,7 +238,7 @@
"domain_pill.your_username": "O seu identificador único neste servidor. É possível encontrar utilizadores com o mesmo nome de utilizador em diferentes servidores.",
"embed.instructions": "Incorpore esta publicação no seu site copiando o código abaixo.",
"embed.preview": "Podes ver aqui como irá ficar:",
- "emoji_button.activity": "Actividade",
+ "emoji_button.activity": "Atividade",
"emoji_button.clear": "Limpar",
"emoji_button.custom": "Personalizar",
"emoji_button.flags": "Bandeiras",
@@ -242,7 +246,7 @@
"emoji_button.label": "Inserir Emoji",
"emoji_button.nature": "Natureza",
"emoji_button.not_found": "Nenhum emoji correspondente encontrado",
- "emoji_button.objects": "Objectos",
+ "emoji_button.objects": "Objetos",
"emoji_button.people": "Pessoas",
"emoji_button.recent": "Utilizados regularmente",
"emoji_button.search": "Pesquisar...",
@@ -254,27 +258,27 @@
"empty_column.account_timeline": "Sem publicações por aqui!",
"empty_column.account_unavailable": "Perfil indisponível",
"empty_column.blocks": "Ainda não bloqueaste qualquer utilizador.",
- "empty_column.bookmarked_statuses": "Ainda não adicionou nenhuma publicação aos itens salvos. Quando adicionar, eles serão exibidos aqui.",
+ "empty_column.bookmarked_statuses": "Ainda não tem nenhuma publicação marcada. Quando marcar uma, ela aparecerá aqui.",
"empty_column.community": "A cronologia local está vazia. Escreve algo público para começar!",
"empty_column.direct": "Ainda não tem qualquer menção privada. Quando enviar ou receber uma, ela irá aparecer aqui.",
"empty_column.domain_blocks": "Ainda não há qualquer domínio escondido.",
- "empty_column.explore_statuses": "Nada está em alta no momento. Volte mais tarde!",
+ "empty_column.explore_statuses": "Nada é tendência neste momento. Volte mais tarde!",
"empty_column.favourited_statuses": "Ainda não assinalou qualquer publicação como favorita. Quando o fizer, aparecerá aqui.",
"empty_column.favourites": "Ainda ninguém assinalou esta publicação como favorita. Quando alguém o fizer, aparecerá aqui.",
"empty_column.follow_requests": "Ainda não tens nenhum pedido de seguidor. Quando receberes algum, ele irá aparecer aqui.",
"empty_column.followed_tags": "Ainda não segue nenhuma hashtag. Quando o fizer, ela aparecerá aqui.",
"empty_column.hashtag": "Não foram encontradas publicações com essa #etiqueta.",
- "empty_column.home": "Ainda não segues qualquer utilizador. Visita {public} ou utiliza a pesquisa para procurar outros utilizadores.",
+ "empty_column.home": "A sua linha cronológica inicial está vazia! Siga mais pessoas para a preencher.",
"empty_column.list": "Ainda não existem publicações nesta lista. Quando membros desta lista fizerem novas publicações, elas aparecerão aqui.",
"empty_column.lists": "Ainda não tem qualquer lista. Quando criar uma, ela irá aparecer aqui.",
"empty_column.mutes": "Ainda não silenciaste qualquer utilizador.",
"empty_column.notification_requests": "Tudo limpo! Não há nada aqui. Quando você receber novas notificações, elas aparecerão aqui conforme as suas configurações.",
"empty_column.notifications": "Não tens notificações. Interage com outros utilizadores para iniciar uma conversa.",
"empty_column.public": "Não há nada aqui! Escreve algo publicamente ou segue outros utilizadores para veres aqui os conteúdos públicos",
- "error.unexpected_crash.explanation": "Devido a um erro no nosso código ou a uma compatilidade com o seu navegador, esta página não pôde ser apresentada correctamente.",
+ "error.unexpected_crash.explanation": "Devido a um erro no nosso código ou a um problema de compatibilidade do navegador, esta página não pôde ser apresentada corretamente.",
"error.unexpected_crash.explanation_addons": "Esta página não pôde ser exibida corretamente. Este erro provavelmente é causado por um complemento do navegador ou ferramentas de tradução automática.",
"error.unexpected_crash.next_steps": "Tente atualizar a página. Se isso não ajudar, pode usar o Mastodon através de um navegador diferente ou uma aplicação nativa.",
- "error.unexpected_crash.next_steps_addons": "Tente desabilitá-los e atualizar a página. Se isso não ajudar, você ainda poderá usar o Mastodon por meio de um navegador diferente ou de um aplicativo nativo.",
+ "error.unexpected_crash.next_steps_addons": "Tente desativá-los e atualizar a página. Se isso não ajudar, poderá ainda ser possível utilizar o Mastodon através de um navegador diferente ou de uma aplicação nativa.",
"errors.unexpected_crash.copy_stacktrace": "Copiar a stacktrace para o clipboard",
"errors.unexpected_crash.report_issue": "Reportar problema",
"explore.search_results": "Resultados da pesquisa",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Utilize uma categoria existente ou crie uma nova",
"filter_modal.select_filter.title": "Filtrar esta publicação",
"filter_modal.title.status": "Filtrar uma publicação",
+ "filter_warning.matches_filter": "Corresponde ao filtro “{title}”",
"filtered_notifications_banner.pending_requests": "De {count, plural, =0 {ninguém} one {uma pessoa} other {# pessoas}} que pode conhecer",
"filtered_notifications_banner.title": "Notificações filtradas",
"firehose.all": "Todas",
@@ -348,6 +353,14 @@
"hashtag.follow": "Seguir #etiqueta",
"hashtag.unfollow": "Deixar de seguir #etiqueta",
"hashtags.and_other": "…e {count, plural, other {mais #}}",
+ "hints.profiles.followers_may_be_missing": "Podem faltar seguidores neste perfil.",
+ "hints.profiles.follows_may_be_missing": "O número de perfis seguidos por este perfil pode faltar.",
+ "hints.profiles.posts_may_be_missing": "Podem faltar algumas publicações deste perfil.",
+ "hints.profiles.see_more_followers": "Ver mais seguidores no {domain}",
+ "hints.profiles.see_more_follows": "Veja mais perfis seguidos em {domain}",
+ "hints.profiles.see_more_posts": "Ver mais publicações em {domain}",
+ "hints.threads.replies_may_be_missing": "As respostas de outros servidores podem estar a faltar.",
+ "hints.threads.see_more": "Veja mais respostas em {domain}",
"home.column_settings.show_reblogs": "Mostrar impulsos",
"home.column_settings.show_replies": "Mostrar respostas",
"home.hide_announcements": "Ocultar comunicações",
@@ -355,6 +368,17 @@
"home.pending_critical_update.link": "Ver atualizações",
"home.pending_critical_update.title": "Atualização de segurança crítica disponível!",
"home.show_announcements": "Exibir comunicações",
+ "ignore_notifications_modal.disclaimer": "O Mastodon não pode informar utilizadores que ignoraste as notificações deles. Ignorar notificações não irá parar as mensagens serem enviadas.",
+ "ignore_notifications_modal.filter_instead": "Filtrar em vez disso",
+ "ignore_notifications_modal.filter_to_act_users": "Ainda poderá aceitar, rejeitar, ou reportar utilizadores",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "A filtragem ajuda a evitar potenciais equívocos",
+ "ignore_notifications_modal.filter_to_review_separately": "Pode rever as notificações filtradas separadamente",
+ "ignore_notifications_modal.ignore": "Ignorar notificações",
+ "ignore_notifications_modal.limited_accounts_title": "Ignorar notificações de contas moderadas?",
+ "ignore_notifications_modal.new_accounts_title": "Ignorar notificações de contas novas?",
+ "ignore_notifications_modal.not_followers_title": "Ignorar notificações de pessoas que não o seguem?",
+ "ignore_notifications_modal.not_following_title": "Ignorar notificações de pessoas que não segue?",
+ "ignore_notifications_modal.private_mentions_title": "Ignorar notificações de Menções Privadas não solicitadas?",
"interaction_modal.description.favourite": "Com uma conta no Mastodon, pode adicionar assinalar esta publicação como favorita para que o autor saiba que gostou e guardá-la para mais tarde.",
"interaction_modal.description.follow": "Com uma conta no Mastodon, pode seguir {name} para receber as suas publicações na sua página inicial.",
"interaction_modal.description.reblog": "Com uma conta no Mastodon, pode impulsionar esta publicação para compartilhá-lo com os seus seguidores.",
@@ -395,7 +419,7 @@
"keyboard_shortcuts.my_profile": "para abrir o teu perfil",
"keyboard_shortcuts.notifications": "para abrir a coluna das notificações",
"keyboard_shortcuts.open_media": "para abrir media",
- "keyboard_shortcuts.pinned": "para abrir a lista dos toots fixados",
+ "keyboard_shortcuts.pinned": "Abrir lista de publicações fixadas",
"keyboard_shortcuts.profile": "para abrir o perfil do autor",
"keyboard_shortcuts.reply": "para responder",
"keyboard_shortcuts.requests": "para abrir a lista dos pedidos de seguidor",
@@ -408,8 +432,6 @@
"keyboard_shortcuts.unfocus": "para remover o foco da área de texto/pesquisa",
"keyboard_shortcuts.up": "para mover para cima na lista",
"lightbox.close": "Fechar",
- "lightbox.compress": "Compactar caixa de visualização de imagem",
- "lightbox.expand": "Expandir caixa de visualização de imagem",
"lightbox.next": "Próximo",
"lightbox.previous": "Anterior",
"limited_account_hint.action": "Exibir perfil mesmo assim",
@@ -433,7 +455,7 @@
"lists.subheading": "As tuas listas",
"load_pending": "{count, plural, one {# novo item} other {# novos itens}}",
"loading_indicator.label": "A carregar…",
- "media_gallery.toggle_visible": "Alternar visibilidade",
+ "media_gallery.hide": "Esconder",
"moved_to_account_banner.text": "A sua conta {disabledAccount} está, no momento, desativada, porque você migrou para {movedToAccount}.",
"mute_modal.hide_from_notifications": "Ocultar das notificações",
"mute_modal.hide_options": "Ocultar opções",
@@ -445,6 +467,7 @@
"mute_modal.you_wont_see_mentions": "Não verá publicações que os mencionem.",
"mute_modal.you_wont_see_posts": "Eles podem continuar a ver as suas publicações, mas você não verá as deles.",
"navigation_bar.about": "Sobre",
+ "navigation_bar.administration": "Administração",
"navigation_bar.advanced_interface": "Abrir na interface web avançada",
"navigation_bar.blocks": "Utilizadores bloqueados",
"navigation_bar.bookmarks": "Marcadores",
@@ -461,10 +484,11 @@
"navigation_bar.follows_and_followers": "Seguindo e seguidores",
"navigation_bar.lists": "Listas",
"navigation_bar.logout": "Sair",
+ "navigation_bar.moderation": "Moderação",
"navigation_bar.mutes": "Utilizadores silenciados",
"navigation_bar.opened_in_classic_interface": "Por norma, publicações, contas, e outras páginas específicas são abertas na interface web clássica.",
"navigation_bar.personal": "Pessoal",
- "navigation_bar.pins": "Toots afixados",
+ "navigation_bar.pins": "Publicações fixadas",
"navigation_bar.preferences": "Preferências",
"navigation_bar.public_timeline": "Cronologia federada",
"navigation_bar.search": "Pesquisar",
@@ -476,9 +500,13 @@
"notification.admin.report_statuses": "{name} denunicou {target} por {category}",
"notification.admin.report_statuses_other": "{name} denunciou {target}",
"notification.admin.sign_up": "{name} inscreveu-se",
+ "notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# outro} other {# outros}} inscreveram-se",
"notification.favourite": "{name} assinalou a sua publicação como favorita",
+ "notification.favourite.name_and_others_with_link": "{name} e
{count, plural, one {# outro} other {# outros}} assinalou a sua publicação como favorita",
"notification.follow": "{name} começou a seguir-te",
+ "notification.follow.name_and_others": "{name} e {count, plural, one {# outro} other {# outros}} começaram a segui-lo",
"notification.follow_request": "{name} pediu para segui-lo",
+ "notification.follow_request.name_and_others": "{name} e {count, plural, one {# outro} other {# outros}} pediram para segui-lo",
"notification.label.mention": "Menção",
"notification.label.private_mention": "Menção privada",
"notification.label.private_reply": "Resposta privada",
@@ -493,9 +521,10 @@
"notification.moderation_warning.action_sensitive": "As suas publicações serão, a partir de agora, assinaladas como sensíveis.",
"notification.moderation_warning.action_silence": "A sua conta foi limitada.",
"notification.moderation_warning.action_suspend": "A sua conta foi suspensa.",
- "notification.own_poll": "A sua votação terminou",
- "notification.poll": "Uma votação em que participaste chegou ao fim",
+ "notification.own_poll": "A sua sondagem terminou",
+ "notification.poll": "Terminou uma sondagem em que votou",
"notification.reblog": "{name} reforçou a tua publicação",
+ "notification.reblog.name_and_others_with_link": "{name} e
{count, plural, one {# outro} other {# outros}} reforçaram a sua publicação",
"notification.relationships_severance_event": "Perdeu as ligações com {name}",
"notification.relationships_severance_event.account_suspension": "Um administrador de {from} suspendeu {target}, o que significa que já não pode receber atualizações dele ou interagir com ele.",
"notification.relationships_severance_event.domain_block": "Um administrador de {from} bloqueou {target}, incluindo {followersCount} dos seus seguidores e {followingCount, plural, one {# conta} other {# contas}} que segue.",
@@ -504,28 +533,37 @@
"notification.status": "{name} acabou de publicar",
"notification.update": "{name} editou uma publicação",
"notification_requests.accept": "Aceitar",
+ "notification_requests.accept_multiple": "{count, plural, one {Aceitar # pedidos…} other {Aceitar # pedidos…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Aceitar pedido} other {Aceitar pedidos}}",
+ "notification_requests.confirm_accept_multiple.message": "Está prestes a aceitar {count, plural, one {um pedido de notificação} other {# pedidos de notificação}}. Tem a certeza de que pretende continuar?",
+ "notification_requests.confirm_accept_multiple.title": "Aceitar pedidos de notificação?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Rejeitar pedido} other {Rejeitar pedidos}}",
+ "notification_requests.confirm_dismiss_multiple.message": "Está prestes a rejeitar {count, plural, one {um pedido de notificação} other {# pedidos de notificação}}. Não será fácil voltar a {count, plural, one {aceder-lhe} other {aceder-lhes}}. Tem a certeza de que pretende continuar?",
+ "notification_requests.confirm_dismiss_multiple.title": "Rejeitar pedidos de notificação?",
"notification_requests.dismiss": "Descartar",
+ "notification_requests.dismiss_multiple": "{count, plural, one {Rejeitar # pedido…} other {Rejeitar # pedidos…}}",
+ "notification_requests.edit_selection": "Editar",
+ "notification_requests.exit_selection": "Concluído",
"notification_requests.explainer_for_limited_account": "As notificações desta conta foram filtradas porque a conta foi limitada por um moderador.",
"notification_requests.explainer_for_limited_remote_account": "As notificações desta conta foram filtradas porque a conta ou o seu servidor foram limitados por um moderador.",
"notification_requests.maximize": "Maximizar",
"notification_requests.minimize_banner": "Minimizar o cabeçalho das notificações filtradas",
"notification_requests.notifications_from": "Notificações de {name}",
"notification_requests.title": "Notificações filtradas",
+ "notification_requests.view": "Ver notificações",
"notifications.clear": "Limpar notificações",
"notifications.clear_confirmation": "Queres mesmo limpar todas as notificações?",
"notifications.clear_title": "Limpar notificações?",
"notifications.column_settings.admin.report": "Novas denúncias:",
"notifications.column_settings.admin.sign_up": "Novas inscrições:",
"notifications.column_settings.alert": "Notificações no ambiente de trabalho",
- "notifications.column_settings.beta.category": "Funcionalidades experimentais",
- "notifications.column_settings.beta.grouping": "Agrupar notificações",
"notifications.column_settings.favourite": "Favoritos:",
"notifications.column_settings.filter_bar.advanced": "Mostrar todas as categorias",
"notifications.column_settings.filter_bar.category": "Barra de filtros rápidos",
"notifications.column_settings.follow": "Novos seguidores:",
"notifications.column_settings.follow_request": "Novos pedidos de seguidor:",
"notifications.column_settings.mention": "Menções:",
- "notifications.column_settings.poll": "Resultados do inquérito:",
+ "notifications.column_settings.poll": "Resultados da sondagem:",
"notifications.column_settings.push": "Notificações Push",
"notifications.column_settings.reblog": "Reforços:",
"notifications.column_settings.show": "Mostrar na coluna",
@@ -539,7 +577,7 @@
"notifications.filter.favourites": "Favoritos",
"notifications.filter.follows": "Seguidores",
"notifications.filter.mentions": "Menções",
- "notifications.filter.polls": "Resultados do inquérito",
+ "notifications.filter.polls": "Resultados da sondagem",
"notifications.filter.statuses": "Atualizações de pessoas que você segue",
"notifications.grant_permission": "Conceder permissão.",
"notifications.group": "{count} notificações",
@@ -547,6 +585,12 @@
"notifications.permission_denied": "Notificações no ambiente de trabalho não estão disponíveis porque a permissão, solicitada pelo navegador, foi recusada anteriormente",
"notifications.permission_denied_alert": "Notificações no ambiente de trabalho não podem ser ativadas, pois a permissão do navegador foi recusada anteriormente",
"notifications.permission_required": "Notificações no ambiente de trabalho não estão disponíveis porque a permissão necessária não foi concedida.",
+ "notifications.policy.accept": "Aceitar",
+ "notifications.policy.accept_hint": "Mostrar nas notificações",
+ "notifications.policy.drop": "Ignorar",
+ "notifications.policy.drop_hint": "Enviar para o vazio, para nunca mais ser visto",
+ "notifications.policy.filter": "Filtrar",
+ "notifications.policy.filter_hint": "Enviar para a caixa de notificações filtradas",
"notifications.policy.filter_limited_accounts_hint": "Limitado pelos moderadores do servidor",
"notifications.policy.filter_limited_accounts_title": "Contas moderadas",
"notifications.policy.filter_new_accounts.hint": "Criada nos últimos {days, plural, one {um dia} other {# dias}}",
@@ -557,12 +601,13 @@
"notifications.policy.filter_not_following_title": "Pessoas que você não segue",
"notifications.policy.filter_private_mentions_hint": "Filtrado, a menos que seja em resposta à sua própria menção ou se você seguir o remetente",
"notifications.policy.filter_private_mentions_title": "Menções privadas não solicitadas",
+ "notifications.policy.title": "Gerir notificações de…",
"notifications_permission_banner.enable": "Ativar notificações no ambiente de trabalho",
"notifications_permission_banner.how_to_control": "Para receber notificações quando o Mastodon não estiver aberto, ative as notificações no ambiente de trabalho. Depois da sua ativação, pode controlar precisamente quais tipos de interações geram notificações, através do botão {icon} acima.",
"notifications_permission_banner.title": "Nunca perca nada",
"onboarding.action.back": "Voltar atrás",
"onboarding.actions.back": "Voltar atrás",
- "onboarding.actions.go_to_explore": "Veja as tendências atuais",
+ "onboarding.actions.go_to_explore": "Ver tendências atuais",
"onboarding.actions.go_to_home": "Ir para a sua página inicial",
"onboarding.compose.template": "Olá #Mastodon!",
"onboarding.follows.empty": "Infelizmente, não é possível mostrar resultados neste momento. Pode tentar utilizar a pesquisa ou navegar na página \"Explorar\" para encontrar pessoas para seguir ou tentar novamente mais tarde.",
@@ -588,7 +633,7 @@
"onboarding.start.title": "Conseguiu!",
"onboarding.steps.follow_people.body": "Seguir pessoas interessantes é o propósito do Mastodon. ",
"onboarding.steps.follow_people.title": "Personalize o seu feed",
- "onboarding.steps.publish_status.body": "Diga olá ao mundo com texto, fotos, vídeos ou votos {emoji}",
+ "onboarding.steps.publish_status.body": "Diga olá ao mundo com texto, fotos, vídeos ou sondagens {emoji}",
"onboarding.steps.publish_status.title": "Faça a sua primeira publicação",
"onboarding.steps.setup_profile.body": "Promova as suas interações para ter um perfil preenchido. ",
"onboarding.steps.setup_profile.title": "Personalize o seu perfil",
@@ -597,19 +642,19 @@
"onboarding.tips.2fa": "
Sabia? Pode proteger a sua conta ativando a autenticação em duas etapas nas configurações de conta. Funciona com qualquer aplicativo TOTP à sua escolha, sem necessitar de um número de telefone!",
"onboarding.tips.accounts_from_other_servers": "
Sabia? Como o Mastodon é descentralizado, alguns perfis que encontra estarão hospedados noutros servidores que não os seus. E ainda assim pode interagir com eles perfeitamente! O servidor deles está na segunda metade do nome de utilizador!",
"onboarding.tips.migration": "
Sabia? Se sentir que o {domain} não é um bom servidor para si, no futuro pode mudar para outro servidor Mastodon sem perder os seus seguidores. Pode até mesmo hospedar o seu próprio servidor!",
- "onboarding.tips.verification": "
Sabia que? Pode fazer a verificação do seu site, adicionando o link do seu perfil à primeira página do seu site, como também pode adicionar o seu site ao seu perfil? Sem taxas ou documentos!",
+ "onboarding.tips.verification": "
Sabia que? Pode verificar a sua conta colocando uma hiperligação para o seu perfil Mastodon no seu próprio site e adicionando o site ao seu perfil. Sem taxas ou documentos!",
"password_confirmation.exceeds_maxlength": "A confirmação da palavra-passe excedeu o tamanho máximo ",
"password_confirmation.mismatching": "A confirmação da palavra-passe não corresponde",
"picture_in_picture.restore": "Colocá-lo de volta",
"poll.closed": "Fechado",
- "poll.refresh": "Recarregar",
+ "poll.refresh": "Atualizar",
"poll.reveal": "Ver resultados",
"poll.total_people": "{count, plural, one {# pessoa} other {# pessoas}}",
"poll.total_votes": "{count, plural, one {# voto} other {# votos}}",
"poll.vote": "Votar",
- "poll.voted": "Votaste nesta resposta",
+ "poll.voted": "Votou nesta resposta",
"poll.votes": "{votes, plural, one {# voto } other {# votos}}",
- "poll_button.add_poll": "Adicionar votação",
+ "poll_button.add_poll": "Adicionar uma sondagem",
"poll_button.remove_poll": "Remover sondagem",
"privacy.change": "Ajustar a privacidade da publicação",
"privacy.direct.long": "Todos os mencionados na publicação",
@@ -624,7 +669,7 @@
"privacy_policy.last_updated": "Última atualização em {date}",
"privacy_policy.title": "Política de privacidade",
"recommended": "Recomendado",
- "refresh": "Actualizar",
+ "refresh": "Atualizar",
"regeneration_indicator.label": "A carregar…",
"regeneration_indicator.sublabel": "A tua página inicial está a ser preparada!",
"relative_time.days": "{number}d",
@@ -666,7 +711,7 @@
"report.reasons.other": "É outra coisa",
"report.reasons.other_description": "O problema não se encaixa nas outras categorias",
"report.reasons.spam": "É spam",
- "report.reasons.spam_description": "Hiperligações maliciosas, contactos falsos, ou respostas repetitivas",
+ "report.reasons.spam_description": "Hiperligações maliciosas, contactos falsos ou respostas repetitivas",
"report.reasons.violation": "Viola as regras do servidor",
"report.reasons.violation_description": "Está ciente de que infringe regras específicas",
"report.rules.subtitle": "Selecione tudo o que se aplicar",
@@ -722,8 +767,8 @@
"sign_in_banner.create_account": "Criar conta",
"sign_in_banner.follow_anyone": "Siga alguém no fediverso e veja tudo em ordem cronológica. Sem algoritmos, anúncios ou clickbait à vista.",
"sign_in_banner.mastodon_is": "O Mastodon é a melhor maneira de acompanhar o que está a acontecer.",
- "sign_in_banner.sign_in": "Iniciar Sessão",
- "sign_in_banner.sso_redirect": "Inicie Sessão ou Registe-se",
+ "sign_in_banner.sign_in": "Iniciar sessão",
+ "sign_in_banner.sso_redirect": "Inicie sessão ou registe-se",
"status.admin_account": "Abrir a interface de moderação para @{name}",
"status.admin_domain": "Abrir interface de moderação para {domain}",
"status.admin_status": "Abrir esta publicação na interface de moderação",
@@ -731,7 +776,8 @@
"status.bookmark": "Guardar nos marcadores",
"status.cancel_reblog_private": "Deixar de reforçar",
"status.cannot_reblog": "Não é possível partilhar esta publicação",
- "status.copy": "Copiar ligação para a publicação",
+ "status.continued_thread": "Continuação da conserva",
+ "status.copy": "Copiar hiperligação para a publicação",
"status.delete": "Eliminar",
"status.detailed_status": "Vista pormenorizada da conversa",
"status.direct": "Mencionar @{name} em privado",
@@ -739,7 +785,7 @@
"status.edit": "Editar",
"status.edited": "Última edição em {date}",
"status.edited_x_times": "Editado {count, plural,one {{count} vez} other {{count} vezes}}",
- "status.embed": "Embutir",
+ "status.embed": "Obter código de incorporação",
"status.favourite": "Assinalar como favorito",
"status.favourites": "{count, plural, one {favorito} other {favoritos}}",
"status.filter": "Filtrar esta publicação",
@@ -764,6 +810,7 @@
"status.reblogs.empty": "Ainda ninguém reforçou esta publicação. Quando alguém o fizer, ele irá aparecer aqui.",
"status.redraft": "Apagar & reescrever",
"status.remove_bookmark": "Retirar dos marcadores",
+ "status.replied_in_thread": "Responder na conversa",
"status.replied_to": "Respondeu a {name}",
"status.reply": "Responder",
"status.replyAll": "Responder à conversa",
@@ -790,15 +837,15 @@
"time_remaining.moments": "Momentos restantes",
"time_remaining.seconds": "{número, plural, um {# second} outro {# seconds}} faltam",
"trends.counter_by_accounts": "{count, plural, one {{counter} pessoa} other {{counter} pessoas}} {days, plural, one {no último dia} other {nos últimos {days} dias}}",
- "trends.trending_now": "Em alta neste momento",
+ "trends.trending_now": "Tendências atuais",
"ui.beforeunload": "O teu rascunho será perdido se abandonares o Mastodon.",
"units.short.billion": "{count}MM",
"units.short.million": "{count}M",
"units.short.thousand": "{count}m",
- "upload_area.title": "Arraste e solte para enviar",
- "upload_button.label": "Juntar imagens, um vídeo, ou um ficheiro de som",
- "upload_error.limit": "Limite máximo do ficheiro a carregar excedido.",
- "upload_error.poll": "O carregamento de ficheiros não é permitido em sondagens.",
+ "upload_area.title": "Arrastar e largar para enviar",
+ "upload_button.label": "Adicionar imagens, um vídeo ou um ficheiro de som",
+ "upload_error.limit": "Limite de envio de ficheiros excedido.",
+ "upload_error.poll": "Não é permitido o envio de ficheiros em sondagens.",
"upload_form.audio_description": "Descreva para pessoas com diminuição da acuidade auditiva",
"upload_form.description": "Descreva para pessoas com diminuição da acuidade visual",
"upload_form.edit": "Editar",
@@ -809,7 +856,7 @@
"upload_modal.applying": "A aplicar…",
"upload_modal.choose_image": "Escolher imagem",
"upload_modal.description_placeholder": "Grave e cabisbaixo, o filho justo zelava pela querida mãe doente",
- "upload_modal.detect_text": "Detectar texto na imagem",
+ "upload_modal.detect_text": "Detetar texto na imagem",
"upload_modal.edit_media": "Editar media",
"upload_modal.hint": "Clique ou arraste o círculo na pré-visualização para escolher o ponto focal que será sempre visível em todas as miniaturas.",
"upload_modal.preparing_ocr": "A preparar o reconhecimento de caracteres (OCR)…",
diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json
index 5b1901fbe0..a61f4b0d4f 100644
--- a/app/javascript/mastodon/locales/ro.json
+++ b/app/javascript/mastodon/locales/ro.json
@@ -334,8 +334,6 @@
"keyboard_shortcuts.unfocus": "Părăsește zona de text/bara de căutare",
"keyboard_shortcuts.up": "Urcă în listă",
"lightbox.close": "Închide",
- "lightbox.compress": "Închide panoul de vizualizare a imaginilor",
- "lightbox.expand": "Deschide panoul de vizualizare a imaginilor",
"lightbox.next": "Înainte",
"lightbox.previous": "Înapoi",
"limited_account_hint.action": "Afișează profilul oricum",
@@ -355,7 +353,6 @@
"lists.search": "Caută printre persoanele la care ești abonat",
"lists.subheading": "Listele tale",
"load_pending": "{count, plural, one {# element nou} other {# elemente noi}}",
- "media_gallery.toggle_visible": "{number, plural, one {Ascunde imaginea} other {Ascunde imaginile}}",
"moved_to_account_banner.text": "Contul tău {disabledAccount} este în acest moment dezactivat deoarece te-ai mutat la {movedToAccount}.",
"navigation_bar.about": "Despre",
"navigation_bar.advanced_interface": "Deschide în interfața web avansată",
@@ -557,7 +554,6 @@
"status.direct_indicator": "Mențiune privată",
"status.edit": "Modifică",
"status.edited_x_times": "Modificată {count, plural, one {o dată} few {de {count} ori} other {de {count} de ori}}",
- "status.embed": "Înglobează",
"status.filter": "Filtrează această postare",
"status.history.created": "creată de {name} pe {date}",
"status.history.edited": "modificată de {name} pe {date}",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index 94f82e422d..1366114929 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -34,7 +34,9 @@
"account.follow_back": "Подписаться в ответ",
"account.followers": "Подписчики",
"account.followers.empty": "На этого пользователя пока никто не подписан.",
+ "account.followers_counter": "{count, plural, one {{counter} последователя} other {{counter} последователей}}",
"account.following": "Подписки",
+ "account.following_counter": "{count, plural, one {{counter} последующий} other {{counter} последующие}}",
"account.follows.empty": "Этот пользователь пока ни на кого не подписался.",
"account.go_to_profile": "Перейти к профилю",
"account.hide_reblogs": "Скрыть продвижения от @{name}",
@@ -48,7 +50,7 @@
"account.moved_to": "У {name} теперь новый аккаунт:",
"account.mute": "Игнорировать @{name}",
"account.mute_notifications_short": "Отключить уведомления",
- "account.mute_short": "Немой",
+ "account.mute_short": "Приглушить",
"account.muted": "Игнорируется",
"account.mutual": "Взаимно",
"account.no_bio": "Описание не предоставлено.",
@@ -94,6 +96,8 @@
"block_modal.title": "Заблокировать пользователя?",
"block_modal.you_wont_see_mentions": "Вы не увидите записи, которые упоминают его.",
"boost_modal.combo": "{combo}, чтобы пропустить это в следующий раз",
+ "boost_modal.reblog": "Повысить пост?",
+ "boost_modal.undo_reblog": "Разгрузить пост?",
"bundle_column_error.copy_stacktrace": "Скопировать отчет об ошибке",
"bundle_column_error.error.body": "Запрошенная страница не может быть отображена. Это может быть вызвано ошибкой в нашем коде или проблемой совместимости браузера.",
"bundle_column_error.error.title": "О нет!",
@@ -189,6 +193,8 @@
"confirmations.unfollow.confirm": "Отписаться",
"confirmations.unfollow.message": "Вы уверены, что хотите отписаться от {name}?",
"confirmations.unfollow.title": "Отписаться?",
+ "content_warning.hide": "Скрыть пост",
+ "content_warning.show": "Всё равно показать",
"conversation.delete": "Удалить беседу",
"conversation.mark_as_read": "Отметить как прочитанное",
"conversation.open": "Просмотр беседы",
@@ -296,6 +302,8 @@
"filter_modal.select_filter.subtitle": "Используйте существующую категорию или создайте новую",
"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.title": "Отфильтрованные уведомления",
"firehose.all": "Все",
"firehose.local": "Текущий сервер",
@@ -344,6 +352,14 @@
"hashtag.follow": "Подписаться на новые посты",
"hashtag.unfollow": "Отписаться",
"hashtags.and_other": "...и {count, plural, other {# ещё}}",
+ "hints.profiles.followers_may_be_missing": "Последователи для этого профиля могут отсутствовать.",
+ "hints.profiles.follows_may_be_missing": "Фолловеры для этого профиля могут отсутствовать.",
+ "hints.profiles.posts_may_be_missing": "Некоторые сообщения из этого профиля могут отсутствовать.",
+ "hints.profiles.see_more_followers": "Посмотреть больше подписчиков на {domain}",
+ "hints.profiles.see_more_follows": "Смотрите другие материалы по теме {domain}",
+ "hints.profiles.see_more_posts": "Посмотреть другие сообщения на {domain}",
+ "hints.threads.replies_may_be_missing": "Ответы с других серверов могут отсутствовать.",
+ "hints.threads.see_more": "Посмотреть другие ответы на {domain}",
"home.column_settings.show_reblogs": "Показывать продвижения",
"home.column_settings.show_replies": "Показывать ответы",
"home.hide_announcements": "Скрыть объявления",
@@ -351,7 +367,17 @@
"home.pending_critical_update.link": "Посмотреть обновления",
"home.pending_critical_update.title": "Доступно критическое обновление безопасности!",
"home.show_announcements": "Показать объявления",
+ "ignore_notifications_modal.disclaimer": "Mastodon не может сообщить пользователям, что вы проигнорировали их уведомления. Игнорирование уведомлений не остановит отправку самих сообщений.",
+ "ignore_notifications_modal.filter_instead": "Фильтр вместо",
"ignore_notifications_modal.filter_to_act_users": "Вы и далее сможете принять, отвергнуть и жаловаться на пользователей",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "Фильтрация помогает избежать потенциальной путаницы",
+ "ignore_notifications_modal.filter_to_review_separately": "Вы можете просматривать отфильтрованные уведомления отдельно",
+ "ignore_notifications_modal.ignore": "Игнорировать уведомления",
+ "ignore_notifications_modal.limited_accounts_title": "Игнорировать уведомления от модерируемых аккаунтов?",
+ "ignore_notifications_modal.new_accounts_title": "Игнорировать уведомления от новых аккаунтов?",
+ "ignore_notifications_modal.not_followers_title": "Игнорировать уведомления от людей, которые не следят за вами?",
+ "ignore_notifications_modal.not_following_title": "Игнорировать уведомления от людей, за которыми вы не следите?",
+ "ignore_notifications_modal.private_mentions_title": "Игнорировать уведомления о нежелательных личных сообщениях?",
"interaction_modal.description.favourite": "С учётной записью Mastodon, вы можете добавить этот пост в избранное, чтобы сохранить его на будущее и дать автору знать, что пост вам понравился.",
"interaction_modal.description.follow": "С учётной записью Mastodon вы можете подписаться на {name}, чтобы получать их посты в своей домашней ленте.",
"interaction_modal.description.reblog": "С учётной записью Mastodon, вы можете продвинуть этот пост, чтобы поделиться им со своими подписчиками.",
@@ -405,8 +431,6 @@
"keyboard_shortcuts.unfocus": "убрать фокус с поля ввода/поиска",
"keyboard_shortcuts.up": "вверх по списку",
"lightbox.close": "Закрыть",
- "lightbox.compress": "Сжать окно просмотра изображений",
- "lightbox.expand": "Развернуть окно просмотра изображений",
"lightbox.next": "Далее",
"lightbox.previous": "Назад",
"limited_account_hint.action": "Все равно показать профиль",
@@ -430,7 +454,7 @@
"lists.subheading": "Ваши списки",
"load_pending": "{count, plural, one {# новый элемент} few {# новых элемента} other {# новых элементов}}",
"loading_indicator.label": "Загрузка…",
- "media_gallery.toggle_visible": "Показать/скрыть {number, plural, =1 {изображение} other {изображения}}",
+ "media_gallery.hide": "Скрыть",
"moved_to_account_banner.text": "Ваша учетная запись {disabledAccount} в настоящее время заморожена, потому что вы переехали на {movedToAccount}.",
"mute_modal.hide_from_notifications": "Скрыть из уведомлений",
"mute_modal.hide_options": "Скрыть параметры",
@@ -442,6 +466,7 @@
"mute_modal.you_wont_see_mentions": "Вы не увидите постов, которые их упоминают.",
"mute_modal.you_wont_see_posts": "Они по-прежнему смогут видеть ваши посты, но вы не сможете видеть их посты.",
"navigation_bar.about": "О проекте",
+ "navigation_bar.administration": "Администрация",
"navigation_bar.advanced_interface": "Включить многоколоночный интерфейс",
"navigation_bar.blocks": "Заблокированные пользователи",
"navigation_bar.bookmarks": "Закладки",
@@ -458,6 +483,7 @@
"navigation_bar.follows_and_followers": "Подписки и подписчики",
"navigation_bar.lists": "Списки",
"navigation_bar.logout": "Выйти",
+ "navigation_bar.moderation": "Модерация",
"navigation_bar.mutes": "Игнорируемые пользователи",
"navigation_bar.opened_in_classic_interface": "Сообщения, учётные записи и другие специфические страницы по умолчанию открываются в классическом веб-интерфейсе.",
"navigation_bar.personal": "Личное",
@@ -468,10 +494,22 @@
"navigation_bar.security": "Безопасность",
"not_signed_in_indicator.not_signed_in": "Вам нужно войти, чтобы иметь доступ к этому ресурсу.",
"notification.admin.report": "{name} сообщил о {target}",
+ "notification.admin.report_account": "{name} сообщил {count, plural, one {один пост} other {# постов}} от {target} для {category}",
+ "notification.admin.report_account_other": "{name} сообщил {count, plural, one {одно сообщение} other {# сообщений}} от {target}",
+ "notification.admin.report_statuses": "{name} сообщил {target} для {category}",
+ "notification.admin.report_statuses_other": "{name} сообщает {target}",
"notification.admin.sign_up": "{name} зарегистрирован",
+ "notification.admin.sign_up.name_and_others": "{name} и {count, plural, one {# другой} other {# другие}} подписались",
"notification.favourite": "{name} добавил(а) ваш пост в избранное",
+ "notification.favourite.name_and_others_with_link": "{name} и
{count, plural, one {# другие} other {# другие}} отдали предпочтение вашему посту",
"notification.follow": "{name} подписался (-лась) на вас",
"notification.follow_request": "{name} отправил запрос на подписку",
+ "notification.follow_request.name_and_others": "{name} и {count, plural, one {# другие} other {# другие}} последовали за тобой",
+ "notification.label.mention": "Упоминание",
+ "notification.label.private_mention": "Частное упоминание",
+ "notification.label.private_reply": "Частный ответ",
+ "notification.label.reply": "Ответить",
+ "notification.mention": "Упоминание",
"notification.moderation-warning.learn_more": "Узнать больше",
"notification.moderation_warning": "Вы получили предупреждение от модерации",
"notification.moderation_warning.action_delete_statuses": "Некоторые из ваших публикаций были удалены.",
@@ -482,7 +520,9 @@
"notification.moderation_warning.action_silence": "Ваша учётная запись была ограничена.",
"notification.moderation_warning.action_suspend": "Действие вашей учётной записи приостановлено.",
"notification.own_poll": "Ваш опрос закончился",
+ "notification.poll": "Голосование, в котором вы приняли участие, завершилось",
"notification.reblog": "{name} продвинул(а) ваш пост",
+ "notification.reblog.name_and_others_with_link": "{name} и
{count, plural, one {# other} other {# others}} увеличили ваш пост",
"notification.relationships_severance_event": "Потеряно соединение с {name}",
"notification.relationships_severance_event.account_suspension": "Администратор {from} заблокировал {target}, что означает, что вы больше не сможете получать обновления от них или взаймодествовать с ними.",
"notification.relationships_severance_event.domain_block": "Администратор {from} заблокировал {target} включая {followersCount} ваших подписчиков и {followingCount, plural, one {# аккаунт} few {# аккаунта} other {# аккаунтов}}, на которые вы подписаны.",
@@ -491,17 +531,25 @@
"notification.status": "{name} только что запостил",
"notification.update": "{name} изменил(а) пост",
"notification_requests.accept": "Принять",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Принять запрос} other {Принять запросы}}",
+ "notification_requests.confirm_accept_multiple.title": "Принимать запросы на уведомления?",
+ "notification_requests.confirm_dismiss_multiple.title": "Отклонять запросы на уведомления?",
"notification_requests.dismiss": "Отклонить",
+ "notification_requests.edit_selection": "Редактировать",
+ "notification_requests.exit_selection": "Готово",
+ "notification_requests.explainer_for_limited_account": "Уведомления от этой учетной записи были отфильтрованы, поскольку учетная запись была ограничена модератором.",
+ "notification_requests.explainer_for_limited_remote_account": "Уведомления от этой учетной записи были отфильтрованы, поскольку учетная запись или ее сервер были ограничены модератором.",
"notification_requests.maximize": "Развернуть",
+ "notification_requests.minimize_banner": "Минимизация баннера отфильтрованных уведомлений",
"notification_requests.notifications_from": "Уведомления от {name}",
"notification_requests.title": "Отфильтрованные уведомления",
+ "notification_requests.view": "Просмотр уведомлений",
"notifications.clear": "Очистить уведомления",
"notifications.clear_confirmation": "Вы уверены, что хотите очистить все уведомления?",
"notifications.clear_title": "Сбросить уведомления?",
"notifications.column_settings.admin.report": "Новые жалобы:",
"notifications.column_settings.admin.sign_up": "Новые регистрации:",
"notifications.column_settings.alert": "Уведомления на рабочем столе",
- "notifications.column_settings.beta.category": "Экспериментальные функции",
"notifications.column_settings.favourite": "Избранные:",
"notifications.column_settings.filter_bar.advanced": "Отображать все категории",
"notifications.column_settings.filter_bar.category": "Панель сортировки",
@@ -530,7 +578,14 @@
"notifications.permission_denied": "Уведомления на рабочем столе недоступны, так как вы запретили их отправку в браузере. Проверьте настройки для сайта, чтобы включить их обратно.",
"notifications.permission_denied_alert": "Уведомления на рабочем столе недоступны, так как вы ранее отклонили запрос на их отправку.",
"notifications.permission_required": "Чтобы включить уведомления на рабочем столе, необходимо разрешить их в браузере.",
+ "notifications.policy.accept": "Принять",
+ "notifications.policy.accept_hint": "Показать в уведомлениях",
"notifications.policy.drop": "Игнорируем",
+ "notifications.policy.drop_hint": "Отправить в пустоту, чтобы никогда больше не увидеть",
+ "notifications.policy.filter": "Фильтр",
+ "notifications.policy.filter_hint": "Отправка в папку фильтрованных уведомлений",
+ "notifications.policy.filter_limited_accounts_hint": "Ограничено модераторами сервера",
+ "notifications.policy.filter_limited_accounts_title": "Модерируемые аккаунты",
"notifications.policy.filter_new_accounts.hint": "Создано в течение последних {days, plural, one {один день} few {# дней} many {# дней} other {# дня}}",
"notifications.policy.filter_new_accounts_title": "Новые учётные записи",
"notifications.policy.filter_not_followers_title": "Люди, не подписанные на вас",
@@ -538,6 +593,7 @@
"notifications.policy.filter_not_following_title": "Люди, на которых вы не подписаны",
"notifications.policy.filter_private_mentions_hint": "Фильтруется, если только это не ответ на ваше собственное упоминание или если вы подписаны на отправителя",
"notifications.policy.filter_private_mentions_title": "Нежелательные личные упоминания",
+ "notifications.policy.title": "………Управлять уведомлениями от…",
"notifications_permission_banner.enable": "Включить уведомления",
"notifications_permission_banner.how_to_control": "Получайте уведомления даже когда Mastodon закрыт, включив уведомления на рабочем столе. А чтобы лишний шум не отвлекал, вы можете настроить какие уведомления вы хотите получать, нажав на кнопку {icon} выше.",
"notifications_permission_banner.title": "Будьте в курсе происходящего",
@@ -666,6 +722,7 @@
"report_notification.categories.legal": "Правовая информация",
"report_notification.categories.legal_sentence": "срамной контент",
"report_notification.categories.other": "Прочее",
+ "report_notification.categories.other_sentence": "другое",
"report_notification.categories.spam": "Спам",
"report_notification.categories.spam_sentence": "спам",
"report_notification.categories.violation": "Нарушение правил",
@@ -696,8 +753,11 @@
"server_banner.about_active_users": "Люди, заходившие на этот сервер за последние 30 дней (ежемесячные активные пользователи)",
"server_banner.active_users": "активные пользователи",
"server_banner.administered_by": "Управляется:",
+ "server_banner.is_one_of_many": "{domain} - это один из многих независимых серверов Mastodon, которые вы можете использовать для участия в fediverse.",
"server_banner.server_stats": "Статистика сервера:",
"sign_in_banner.create_account": "Создать учётную запись",
+ "sign_in_banner.follow_anyone": "Следите за любым человеком в федеральной вселенной и смотрите все в хронологическом порядке. Никаких алгоритмов, рекламы или клик бейта.",
+ "sign_in_banner.mastodon_is": "Mastodon - лучший способ быть в курсе всего происходящего.",
"sign_in_banner.sign_in": "Войти",
"sign_in_banner.sso_redirect": "Войдите или Зарегистрируйтесь",
"status.admin_account": "Открыть интерфейс модератора для @{name}",
@@ -707,6 +767,7 @@
"status.bookmark": "Сохранить в закладки",
"status.cancel_reblog_private": "Не продвигать",
"status.cannot_reblog": "Этот пост не может быть продвинут",
+ "status.continued_thread": "Продолжение темы",
"status.copy": "Скопировать ссылку на пост",
"status.delete": "Удалить",
"status.detailed_status": "Подробный просмотр обсуждения",
@@ -715,7 +776,7 @@
"status.edit": "Изменить",
"status.edited": "Дата последнего изменения: {date}",
"status.edited_x_times": "{count, plural, one {{count} изменение} many {{count} изменений} other {{count} изменения}}",
- "status.embed": "Встроить на свой сайт",
+ "status.embed": "Получить код для встраивания",
"status.favourite": "Избранное",
"status.filter": "Фильтровать этот пост",
"status.history.created": "{name} создал {date}",
@@ -738,6 +799,7 @@
"status.reblogs.empty": "Никто ещё не продвинул этот пост. Как только кто-то это сделает, они появятся здесь.",
"status.redraft": "Создать заново",
"status.remove_bookmark": "Убрать из закладок",
+ "status.replied_in_thread": "Ответил в теме",
"status.replied_to": "Ответил(а) {name}",
"status.reply": "Ответить",
"status.replyAll": "Ответить всем",
diff --git a/app/javascript/mastodon/locales/ry.json b/app/javascript/mastodon/locales/ry.json
index b33b95fe51..02d1c005cf 100644
--- a/app/javascript/mastodon/locales/ry.json
+++ b/app/javascript/mastodon/locales/ry.json
@@ -148,6 +148,11 @@
"compose_form.publish_form": "Нова публикація",
"compose_form.reply": "Удповідь",
"compose_form.save_changes": "Усокотити",
+ "confirmations.logout.confirm": "Уйти гет",
+ "confirmations.logout.message": "Бизувні сьте ож хочете уйти?",
+ "confirmations.logout.title": "Уйти гет?",
+ "confirmations.mute.confirm": "Стишити",
+ "confirmations.reply.confirm": "Удповісти",
"copypaste.copy_to_clipboard": "Копіровати у памнять",
"directory.recently_active": "Недавно актівні",
"disabled_account_banner.account_settings": "Штімованя акаунта",
diff --git a/app/javascript/mastodon/locales/sa.json b/app/javascript/mastodon/locales/sa.json
index 6ca4eafe19..2d48f688d5 100644
--- a/app/javascript/mastodon/locales/sa.json
+++ b/app/javascript/mastodon/locales/sa.json
@@ -299,8 +299,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"lightbox.close": "पिधीयताम्",
- "lightbox.compress": "सङ्कुच चित्रप्रदर्शनपेटकम्",
- "lightbox.expand": "चित्रप्रदर्शनपेटकं विस्तारय",
"lightbox.next": "परः",
"lightbox.previous": "पूर्वः",
"limited_account_hint.action": "प्रोफैलं दर्शय कथञ्चित्",
@@ -319,7 +317,6 @@
"lists.search": "त्वया अनुसारितजनेषु अन्विष्य",
"lists.subheading": "तव सूचयः",
"load_pending": "{count, plural, one {# नूतनवस्तु} other {# नूतनवस्तूनि}}",
- "media_gallery.toggle_visible": "{number, plural, one {चित्रं प्रच्छादय} other {चित्राणि प्रच्छादय}}",
"moved_to_account_banner.text": "तव एकौण्ट् {disabledAccount} अधुना निष्कृतो यतोहि {movedToAccount} अस्मिन्त्वमसार्षीः।",
"navigation_bar.about": "विषये",
"navigation_bar.blocks": "निषिद्धभोक्तारः",
@@ -504,7 +501,6 @@
"status.detailed_status": "विस्तृतसंभाषणदृश्यम्",
"status.edit": "सम्पादय",
"status.edited_x_times": "Edited {count, plural, one {{count} वारम्} other {{count} वारम्}}",
- "status.embed": "निहितम्",
"status.filter": "पत्रमिदं फिल्तरं कुरु",
"status.history.created": "{name} असृजत् {date}",
"status.history.edited": "{name} समपादयत् {date}",
diff --git a/app/javascript/mastodon/locales/sc.json b/app/javascript/mastodon/locales/sc.json
index 461383191e..bb7d062b95 100644
--- a/app/javascript/mastodon/locales/sc.json
+++ b/app/javascript/mastodon/locales/sc.json
@@ -350,8 +350,6 @@
"keyboard_shortcuts.unfocus": "Essi de s'àrea de cumpositzione de testu o de chirca",
"keyboard_shortcuts.up": "Move in susu in sa lista",
"lightbox.close": "Serra",
- "lightbox.compress": "Cumprime sa casella de visualizatzione de is immàgines",
- "lightbox.expand": "Ismànnia sa casella de visualizatzione de is immàgines",
"lightbox.next": "Imbeniente",
"lightbox.previous": "Pretzedente",
"limited_account_hint.title": "Custu profilu est istadu cuadu dae sa moderatzione de {domain}.",
@@ -370,7 +368,6 @@
"lists.subheading": "Is listas tuas",
"load_pending": "{count, plural, one {# elementu nou} other {# elementos noos}}",
"loading_indicator.label": "Carrighende…",
- "media_gallery.toggle_visible": "Cua {number, plural, one {immàgine} other {immàgines}}",
"navigation_bar.about": "Informatziones",
"navigation_bar.blocks": "Persones blocadas",
"navigation_bar.bookmarks": "Sinnalibros",
@@ -422,8 +419,6 @@
"notifications.clear_confirmation": "Seguru chi boles isboidare in manera permanente totu is notìficas tuas?",
"notifications.column_settings.admin.report": "Informes noos:",
"notifications.column_settings.alert": "Notìficas de iscrivania",
- "notifications.column_settings.beta.category": "Funtzionalidades isperimentales",
- "notifications.column_settings.beta.grouping": "Notìficas de grupu",
"notifications.column_settings.favourite": "Preferidos:",
"notifications.column_settings.filter_bar.advanced": "Ammustra totu is categorias",
"notifications.column_settings.filter_bar.category": "Barra de filtru lestru",
@@ -546,7 +541,6 @@
"status.detailed_status": "Visualizatzione de detàlliu de arresonada",
"status.edit": "Modìfica",
"status.edited_x_times": "Modificadu {count, plural, one {{count} # borta} other {{count} bortas}}",
- "status.embed": "Afissa",
"status.favourites": "{count, plural, one {preferidu} other {preferidos}}",
"status.load_more": "Càrriga·nde àteros",
"status.media_hidden": "Elementos multimediales cuados",
diff --git a/app/javascript/mastodon/locales/sco.json b/app/javascript/mastodon/locales/sco.json
index e8ae521ae5..c14f1cc51a 100644
--- a/app/javascript/mastodon/locales/sco.json
+++ b/app/javascript/mastodon/locales/sco.json
@@ -284,8 +284,6 @@
"keyboard_shortcuts.unfocus": "Unfocus scrieve textarea/seirch",
"keyboard_shortcuts.up": "Muive up in the list",
"lightbox.close": "Shut",
- "lightbox.compress": "Compress image view box",
- "lightbox.expand": "Expand image view box",
"lightbox.next": "Neist",
"lightbox.previous": "Last ane",
"limited_account_hint.action": "Shaw profile onieweys",
@@ -304,7 +302,6 @@
"lists.search": "Seirch amang the fowk ye ken",
"lists.subheading": "Yer lists",
"load_pending": "{count, plural, one {# new item} other {# new items}}",
- "media_gallery.toggle_visible": "{number, plural, one {Hide image} other {Hide images}}",
"moved_to_account_banner.text": "Yer accoont {disabledAccount} is disabilt the noo acause ye flittit tae {movedToAccount}.",
"navigation_bar.about": "Aboot",
"navigation_bar.blocks": "Dingied uisers",
@@ -475,7 +472,6 @@
"status.detailed_status": "Detailt conversation view",
"status.edit": "Edit",
"status.edited_x_times": "Editit {count, plural, one {{count} time} other {{count} times}}",
- "status.embed": "Embed",
"status.filter": "Filter this post",
"status.history.created": "{name} creatit {date}",
"status.history.edited": "{name} editit {date}",
diff --git a/app/javascript/mastodon/locales/si.json b/app/javascript/mastodon/locales/si.json
index a9288fd104..93ce9dd7e2 100644
--- a/app/javascript/mastodon/locales/si.json
+++ b/app/javascript/mastodon/locales/si.json
@@ -415,7 +415,6 @@
"status.detailed_status": "විස්තරාත්මක සංවාද දැක්ම",
"status.edit": "සංස්කරණය",
"status.edited_x_times": "සංශෝධිතයි {count, plural, one {වාර {count}} other {වාර {count}}}",
- "status.embed": "කාවැද්දූ",
"status.filter": "මෙම ලිපිය පෙරන්න",
"status.history.created": "{name} නිර්මාණය {date}",
"status.history.edited": "{name} සංස්කරණය {date}",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index dfb1309ddf..c989a7314c 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -92,6 +92,7 @@
"block_modal.title": "Blokovať užívateľa?",
"block_modal.you_wont_see_mentions": "Neuvidíš príspevky, ktoré ich spomínajú.",
"boost_modal.combo": "Nabudúce môžete preskočiť stlačením {combo}",
+ "boost_modal.reblog": "Vyzdvihnúť príspevok?",
"bundle_column_error.copy_stacktrace": "Kopírovať chybovú hlášku",
"bundle_column_error.error.body": "Požadovanú stránku nebolo možné vykresliť. Môže to byť spôsobené chybou v našom kóde alebo problémom s kompatibilitou prehliadača.",
"bundle_column_error.error.title": "Ale nie!",
@@ -187,6 +188,8 @@
"confirmations.unfollow.confirm": "Prestať sledovať",
"confirmations.unfollow.message": "Určite chcete prestať sledovať {name}?",
"confirmations.unfollow.title": "Prestať sledovať užívateľa?",
+ "content_warning.hide": "Skryť príspevok",
+ "content_warning.show": "Aj tak zobraziť",
"conversation.delete": "Vymazať konverzáciu",
"conversation.mark_as_read": "Označiť ako prečítanú",
"conversation.open": "Zobraziť konverzáciu",
@@ -285,6 +288,7 @@
"filter_modal.select_filter.subtitle": "Použite existujúcu kategóriu alebo vytvorte novú",
"filter_modal.select_filter.title": "Filtrovanie tohto príspevku",
"filter_modal.title.status": "Filtrovanie príspevku",
+ "filter_warning.matches_filter": "Zhody triedenia “{title}”",
"filtered_notifications_banner.title": "Filtrované oznámenia",
"firehose.all": "Všetko",
"firehose.local": "Tento server",
@@ -392,8 +396,6 @@
"keyboard_shortcuts.unfocus": "Odísť z textového poľa",
"keyboard_shortcuts.up": "Posunúť sa vyššie v zozname",
"lightbox.close": "Zatvoriť",
- "lightbox.compress": "Zmenšiť náhľad obrázku",
- "lightbox.expand": "Rozšíriť náhľad obrázku",
"lightbox.next": "Ďalej",
"lightbox.previous": "Späť",
"limited_account_hint.action": "Aj tak zobraziť profil",
@@ -416,7 +418,6 @@
"lists.subheading": "Vaše zoznamy",
"load_pending": "{count, plural, one {# nová položka} few {# nové položky} many {# nových položiek} other {# nových položiek}}",
"loading_indicator.label": "Načítavanie…",
- "media_gallery.toggle_visible": "{number, plural, one {Skryť obrázok} other {Skryť obrázky}}",
"moved_to_account_banner.text": "Váš účet {disabledAccount} je momentálne deaktivovaný, pretože ste sa presunuli na {movedToAccount}.",
"mute_modal.hide_from_notifications": "Ukryť z upozornení",
"mute_modal.hide_options": "Skryť možnosti",
@@ -424,6 +425,7 @@
"mute_modal.show_options": "Zobraziť možnosti",
"mute_modal.title": "Stíšiť užívateľa?",
"navigation_bar.about": "O tomto serveri",
+ "navigation_bar.administration": "Spravovanie",
"navigation_bar.advanced_interface": "Otvoriť v pokročilom webovom rozhraní",
"navigation_bar.blocks": "Blokované účty",
"navigation_bar.bookmarks": "Záložky",
@@ -440,6 +442,7 @@
"navigation_bar.follows_and_followers": "Sledovania a sledovatelia",
"navigation_bar.lists": "Zoznamy",
"navigation_bar.logout": "Odhlásiť sa",
+ "navigation_bar.moderation": "Moderovanie",
"navigation_bar.mutes": "Stíšené účty",
"navigation_bar.opened_in_classic_interface": "Príspevky, účty a iné špeciálne stránky sú predvolene otvárané v klasickom webovom rozhraní.",
"navigation_bar.personal": "Osobné",
@@ -474,8 +477,11 @@
"notification.update": "{name} upravuje príspevok",
"notification_requests.accept": "Prijať",
"notification_requests.dismiss": "Zamietnuť",
+ "notification_requests.edit_selection": "Uprav",
+ "notification_requests.exit_selection": "Hotovo",
"notification_requests.notifications_from": "Oboznámenia od {name}",
"notification_requests.title": "Filtrované oboznámenia",
+ "notification_requests.view": "Zobraz upozornenia",
"notifications.clear": "Vyčistiť upozornenia",
"notifications.clear_confirmation": "Určite chcete nenávratne odstrániť všetky svoje upozornenia?",
"notifications.clear_title": "Vyčistiť upozornenia?",
@@ -509,6 +515,9 @@
"notifications.permission_denied": "Upozornenia na ploche sú nedostupné pre už skôr zamietnutú požiadavku prehliadača",
"notifications.permission_denied_alert": "Upozornenia na ploche nemôžu byť zapnuté, pretože požiadavka prehliadača bola už skôr zamietnutá",
"notifications.permission_required": "Upozornenia na ploche sú nedostupné, pretože neboli udelené potrebné povolenia.",
+ "notifications.policy.drop": "Ignoruj",
+ "notifications.policy.filter": "Triediť",
+ "notifications.policy.filter_limited_accounts_title": "Moderované účty",
"notifications.policy.filter_new_accounts_title": "Nové účty",
"notifications.policy.filter_not_followers_title": "Ľudia, ktorí ťa nenasledujú",
"notifications.policy.filter_not_following_title": "Ľudia, ktorých nenasleduješ",
@@ -691,7 +700,6 @@
"status.edit": "Upraviť",
"status.edited": "Naposledy upravený {date}",
"status.edited_x_times": "Upravený {count, plural, other {{count}×}}",
- "status.embed": "Vložiť",
"status.favourite": "Ohviezdičkované",
"status.filter": "Filtrovanie tohto príspevku",
"status.history.created": "Vytvorené účtom {name} {date}",
diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json
index 6e8ac52df3..43042ca998 100644
--- a/app/javascript/mastodon/locales/sl.json
+++ b/app/javascript/mastodon/locales/sl.json
@@ -412,8 +412,6 @@
"keyboard_shortcuts.unfocus": "Odstrani pozornost z območja za sestavljanje besedila/iskanje",
"keyboard_shortcuts.up": "Premakni navzgor po seznamu",
"lightbox.close": "Zapri",
- "lightbox.compress": "Strni ogledno polje slike",
- "lightbox.expand": "Razširi ogledno polje slike",
"lightbox.next": "Naslednji",
"lightbox.previous": "Prejšnji",
"limited_account_hint.action": "Vseeno pokaži profil",
@@ -437,7 +435,6 @@
"lists.subheading": "Vaši seznami",
"load_pending": "{count, plural, one {# nov element} two {# nova elementa} few {# novi elementi} other {# novih elementov}}",
"loading_indicator.label": "Nalaganje …",
- "media_gallery.toggle_visible": "{number, plural,one {Skrij sliko} two {Skrij sliki} other {Skrij slike}}",
"moved_to_account_banner.text": "Vaš račun {disabledAccount} je trenutno onemogočen, ker ste se prestavili na {movedToAccount}.",
"mute_modal.hide_from_notifications": "Skrijte se pred obvestili",
"mute_modal.hide_options": "Skrij možnosti",
@@ -521,8 +518,6 @@
"notifications.column_settings.admin.report": "Nove prijave:",
"notifications.column_settings.admin.sign_up": "Novi vpisi:",
"notifications.column_settings.alert": "Namizna obvestila",
- "notifications.column_settings.beta.category": "Poskusne funkcionalnosti",
- "notifications.column_settings.beta.grouping": "Skupine obvestil",
"notifications.column_settings.favourite": "Priljubljeni:",
"notifications.column_settings.filter_bar.advanced": "Prikaži vse kategorije",
"notifications.column_settings.filter_bar.category": "Vrstica za hitro filtriranje",
@@ -747,7 +742,6 @@
"status.edit": "Uredi",
"status.edited": "Zadnje urejanje {date}",
"status.edited_x_times": "Urejeno {count, plural, one {#-krat} two {#-krat} few {#-krat} other {#-krat}}",
- "status.embed": "Vdelaj",
"status.favourite": "Priljubljen_a",
"status.favourites": "{count, plural, one {priljubitev} two {priljubitvi} few {priljubitve} other {priljubitev}}",
"status.filter": "Filtriraj to objavo",
diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json
index 39abd13d95..c5e42aae77 100644
--- a/app/javascript/mastodon/locales/sq.json
+++ b/app/javascript/mastodon/locales/sq.json
@@ -97,6 +97,8 @@
"block_modal.title": "Të bllokohet përdoruesi?",
"block_modal.you_wont_see_mentions": "S’do të shihni postimet ku përmenden.",
"boost_modal.combo": "Që kjo të anashkalohet herës tjetër, mund të shtypni {combo}",
+ "boost_modal.reblog": "Përforcim postimi?",
+ "boost_modal.undo_reblog": "Të hiqet përforcim për postimin?",
"bundle_column_error.copy_stacktrace": "Kopjo raportim gabimi",
"bundle_column_error.error.body": "Faqja e kërkuar s’u vizatua dot. Kjo mund të vijë nga një e metë në kodin tonë, ose nga një problem përputhshmërie i shfletuesit.",
"bundle_column_error.error.title": "Oh, mos!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Resht së ndjekuri",
"confirmations.unfollow.message": "Jeni i sigurt se doni të mos ndiqet më {name}?",
"confirmations.unfollow.title": "Të ndalet ndjekja e përdoruesit?",
+ "content_warning.hide": "Fshihe postimin",
+ "content_warning.show": "Shfaqe, sido qoftë",
"conversation.delete": "Fshije bisedën",
"conversation.mark_as_read": "Vëri shenjë si të lexuar",
"conversation.open": "Shfaq bisedën",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Përdorni një kategori ekzistuese, ose krijoni një të re",
"filter_modal.select_filter.title": "Filtroje këtë postim",
"filter_modal.title.status": "Filtroni një postim",
+ "filter_warning.matches_filter": "Ka përkim me filtrin “{title}”",
"filtered_notifications_banner.pending_requests": "Nga {count, plural, =0 {askush} one {një person} other {# vetë}} që mund të njihni",
"filtered_notifications_banner.title": "Njoftime të filtruar",
"firehose.all": "Krejt",
@@ -427,8 +432,6 @@
"keyboard_shortcuts.unfocus": "Për heqjen e fokusit nga fusha e hartimit të mesazheve apo kërkimeve",
"keyboard_shortcuts.up": "Për ngjitje sipër nëpër listë",
"lightbox.close": "Mbylle",
- "lightbox.compress": "Ngjeshe kuadratin e parjes së figurave",
- "lightbox.expand": "Zgjeroje kuadratin e parjes së figurave",
"lightbox.next": "Pasuesja",
"lightbox.previous": "E mëparshmja",
"limited_account_hint.action": "Shfaqe profilin sido qoftë",
@@ -452,7 +455,7 @@
"lists.subheading": "Listat tuaja",
"load_pending": "{count, plural,one {# objekt i ri }other {# objekte të rinj }}",
"loading_indicator.label": "Po ngarkohet…",
- "media_gallery.toggle_visible": "Fshihni {number, plural, one {figurë} other {figura}}",
+ "media_gallery.hide": "Fshihe",
"moved_to_account_banner.text": "Llogaria juaj {disabledAccount} aktualisht është e çaktivizuar, ngaqë kaluat te {movedToAccount}.",
"mute_modal.hide_from_notifications": "Fshihe prej njoftimeve",
"mute_modal.hide_options": "Fshihi mundësitë",
@@ -464,6 +467,7 @@
"mute_modal.you_wont_see_mentions": "S’do të shihni postime ku përmenden.",
"mute_modal.you_wont_see_posts": "Ata munden ende të shohin postimet tuaja, por ju s’do të shihni të tyret.",
"navigation_bar.about": "Mbi",
+ "navigation_bar.administration": "Administrim",
"navigation_bar.advanced_interface": "Hape në ndërfaqe web të thelluar",
"navigation_bar.blocks": "Përdorues të bllokuar",
"navigation_bar.bookmarks": "Faqerojtës",
@@ -480,6 +484,7 @@
"navigation_bar.follows_and_followers": "Ndjekje dhe ndjekës",
"navigation_bar.lists": "Lista",
"navigation_bar.logout": "Dalje",
+ "navigation_bar.moderation": "Moderim",
"navigation_bar.mutes": "Përdorues të heshtuar",
"navigation_bar.opened_in_classic_interface": "Postime, llogari dhe të tjera faqe specifike, si parazgjedhje, hapen në ndërfaqe klasike web.",
"navigation_bar.personal": "Personale",
@@ -552,8 +557,6 @@
"notifications.column_settings.admin.report": "Raportime të reja:",
"notifications.column_settings.admin.sign_up": "Regjistrime të reja:",
"notifications.column_settings.alert": "Njoftime desktopi",
- "notifications.column_settings.beta.category": "Veçori eksperimentale",
- "notifications.column_settings.beta.grouping": "Njoftime grupi",
"notifications.column_settings.favourite": "Të parapëlqyer:",
"notifications.column_settings.filter_bar.advanced": "Shfaq krejt kategoritë",
"notifications.column_settings.filter_bar.category": "Shtyllë filtrimesh të shpejta",
@@ -773,6 +776,7 @@
"status.bookmark": "Faqeruaje",
"status.cancel_reblog_private": "Shpërforcojeni",
"status.cannot_reblog": "Ky postim s’mund të përforcohet",
+ "status.continued_thread": "Vazhdoi rrjedhën",
"status.copy": "Kopjoje lidhjen për te mesazhi",
"status.delete": "Fshije",
"status.detailed_status": "Pamje e hollësishme bisede",
@@ -781,7 +785,7 @@
"status.edit": "Përpunojeni",
"status.edited": "Përpunuar së fundi më {date}",
"status.edited_x_times": "Përpunuar {count, plural, one {{count} herë} other {{count} herë}}",
- "status.embed": "Trupëzim",
+ "status.embed": "Merrni kod trupëzimi",
"status.favourite": "I vini shenjë si të parapëlqyer",
"status.favourites": "{count, plural, one {i parapëlqyer} other {të parapëlqyer}}",
"status.filter": "Filtroje këtë postim",
@@ -806,6 +810,7 @@
"status.reblogs.empty": "Këtë mesazh s’e ka përforcuar njeri deri tani. Kur ta bëjë dikush, kjo do të duket këtu.",
"status.redraft": "Fshijeni & rihartojeni",
"status.remove_bookmark": "Hiqe faqerojtësin",
+ "status.replied_in_thread": "U përgjigj te rrjedha",
"status.replied_to": "Iu përgjigj {name}",
"status.reply": "Përgjigjuni",
"status.replyAll": "Përgjigjuni rrjedhës",
diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json
index d550f6517c..e701da6078 100644
--- a/app/javascript/mastodon/locales/sr-Latn.json
+++ b/app/javascript/mastodon/locales/sr-Latn.json
@@ -399,8 +399,6 @@
"keyboard_shortcuts.unfocus": "Ukloni fokus sa polja za unos teksta/pretrage",
"keyboard_shortcuts.up": "Premesti nagore u listi",
"lightbox.close": "Zatvori",
- "lightbox.compress": "Komprimuj okvir za prikaz slike",
- "lightbox.expand": "Proširi okvir za prikaz slike",
"lightbox.next": "Sledeće",
"lightbox.previous": "Prethodno",
"limited_account_hint.action": "Ipak prikaži profil",
@@ -424,7 +422,6 @@
"lists.subheading": "Vaše liste",
"load_pending": "{count, plural, one {# nova stavka} few {# nove stavke} other {# novih stavki}}",
"loading_indicator.label": "Učitavanje…",
- "media_gallery.toggle_visible": "{number, plural, one {Sakrij sliku} few {Sakrij slike} other {Sakrij slike}}",
"moved_to_account_banner.text": "Vaš nalog {disabledAccount} je trenutno onemogućen jer ste prešli na {movedToAccount}.",
"mute_modal.hide_from_notifications": "Sakrij iz obaveštenja",
"mute_modal.hide_options": "Sakrij opcije",
@@ -707,7 +704,6 @@
"status.edit": "Uredi",
"status.edited": "Poslednje uređivanje {date}",
"status.edited_x_times": "Uređeno {count, plural, one {{count} put} other {{count} puta}}",
- "status.embed": "Ugradi",
"status.favourite": "Omiljeno",
"status.favourites": "{count, plural, one {# omiljeno} few {# omiljena} other {# omiljenih}}",
"status.filter": "Filtriraj ovu objavu",
diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json
index f608d46a20..fd13c4ee5c 100644
--- a/app/javascript/mastodon/locales/sr.json
+++ b/app/javascript/mastodon/locales/sr.json
@@ -399,8 +399,6 @@
"keyboard_shortcuts.unfocus": "Уклони фокус са поља за унос текста/претраге",
"keyboard_shortcuts.up": "Премести нагоре у листи",
"lightbox.close": "Затвори",
- "lightbox.compress": "Компримуј оквир за приказ слике",
- "lightbox.expand": "Прошири оквир за приказ слике",
"lightbox.next": "Следеће",
"lightbox.previous": "Претходно",
"limited_account_hint.action": "Ипак прикажи профил",
@@ -424,7 +422,6 @@
"lists.subheading": "Ваше листе",
"load_pending": "{count, plural, one {# нова ставка} few {# нове ставке} other {# нових ставки}}",
"loading_indicator.label": "Учитавање…",
- "media_gallery.toggle_visible": "{number, plural, one {Сакриј слику} few {Сакриј слике} other {Сакриј слике}}",
"moved_to_account_banner.text": "Ваш налог {disabledAccount} је тренутно онемогућен јер сте прешли на {movedToAccount}.",
"mute_modal.hide_from_notifications": "Сакриј из обавештења",
"mute_modal.hide_options": "Сакриј опције",
@@ -707,7 +704,6 @@
"status.edit": "Уреди",
"status.edited": "Последње уређивање {date}",
"status.edited_x_times": "Уређено {count, plural, one {{count} пут} other {{count} пута}}",
- "status.embed": "Угради",
"status.favourite": "Омиљено",
"status.favourites": "{count, plural, one {# омиљено} few {# омиљена} other {# омиљених}}",
"status.filter": "Филтрирај ову објаву",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index a4a30fbbc5..6bb0b1424a 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -192,6 +192,8 @@
"confirmations.unfollow.confirm": "Avfölj",
"confirmations.unfollow.message": "Är du säker på att du vill avfölja {name}?",
"confirmations.unfollow.title": "Avfölj %s?",
+ "content_warning.hide": "Dölj inlägg",
+ "content_warning.show": "Visa ändå",
"conversation.delete": "Radera konversation",
"conversation.mark_as_read": "Markera som läst",
"conversation.open": "Visa konversation",
@@ -427,8 +429,6 @@
"keyboard_shortcuts.unfocus": "för att avfokusera skrivfält/sökfält",
"keyboard_shortcuts.up": "för att flytta uppåt i listan",
"lightbox.close": "Stäng",
- "lightbox.compress": "Komprimera bildvyrutan",
- "lightbox.expand": "Utöka bildvyrutan",
"lightbox.next": "Nästa",
"lightbox.previous": "Tidigare",
"limited_account_hint.action": "Visa profil ändå",
@@ -452,7 +452,7 @@
"lists.subheading": "Dina listor",
"load_pending": "{count, plural, one {# nytt objekt} other {# nya objekt}}",
"loading_indicator.label": "Laddar…",
- "media_gallery.toggle_visible": "Växla synlighet",
+ "media_gallery.hide": "Dölj",
"moved_to_account_banner.text": "Ditt konto {disabledAccount} är för närvarande inaktiverat eftersom du flyttat till {movedToAccount}.",
"mute_modal.hide_from_notifications": "Dölj från aviseringslistan",
"mute_modal.hide_options": "Dölj alternativ",
@@ -552,8 +552,6 @@
"notifications.column_settings.admin.report": "Nya rapporter:",
"notifications.column_settings.admin.sign_up": "Nya registreringar:",
"notifications.column_settings.alert": "Skrivbordsaviseringar",
- "notifications.column_settings.beta.category": "Experimentella funktioner",
- "notifications.column_settings.beta.grouping": "Gruppera notifikationer",
"notifications.column_settings.favourite": "Favoriter:",
"notifications.column_settings.filter_bar.advanced": "Visa alla kategorier",
"notifications.column_settings.filter_bar.category": "Snabbfilter",
@@ -781,7 +779,7 @@
"status.edit": "Redigera",
"status.edited": "Senast ändrad {date}",
"status.edited_x_times": "Redigerad {count, plural, one {{count} gång} other {{count} gånger}}",
- "status.embed": "Bädda in",
+ "status.embed": "Hämta kod för inbäddning",
"status.favourite": "Favoritmarkera",
"status.favourites": "{count, plural, one {favorit} other {favoriter}}",
"status.filter": "Filtrera detta inlägg",
diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json
index 4bded45679..87d6660f05 100644
--- a/app/javascript/mastodon/locales/ta.json
+++ b/app/javascript/mastodon/locales/ta.json
@@ -252,7 +252,6 @@
"lists.search": "நீங்கள் பின்தொடரும் நபர்கள் மத்தியில் தேடுதல்",
"lists.subheading": "உங்கள் பட்டியல்கள்",
"load_pending": "{count, plural,one {# புதியது}other {# புதியவை}}",
- "media_gallery.toggle_visible": "நிலைமாற்று தெரியும்",
"navigation_bar.blocks": "தடுக்கப்பட்ட பயனர்கள்",
"navigation_bar.bookmarks": "அடையாளக்குறிகள்",
"navigation_bar.community_timeline": "உள்ளூர் காலக்கெடு",
@@ -346,7 +345,6 @@
"status.delete": "நீக்கு",
"status.detailed_status": "விரிவான உரையாடல் காட்சி",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "கிடத்து",
"status.load_more": "அதிகமாய் ஏற்று",
"status.media_hidden": "மீடியா மறைக்கப்பட்டது",
"status.mention": "குறிப்பிடு @{name}",
diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json
index 52cb612d86..40fbd7f7bd 100644
--- a/app/javascript/mastodon/locales/te.json
+++ b/app/javascript/mastodon/locales/te.json
@@ -167,7 +167,6 @@
"lists.new.title_placeholder": "కొత్త జాబితా శీర్షిక",
"lists.search": "మీరు అనుసరించే వ్యక్తులలో శోధించండి",
"lists.subheading": "మీ జాబితాలు",
- "media_gallery.toggle_visible": "దృశ్యమానతను టోగుల్ చేయండి",
"navigation_bar.blocks": "బ్లాక్ చేయబడిన వినియోగదారులు",
"navigation_bar.community_timeline": "స్థానిక కాలక్రమం",
"navigation_bar.compose": "కొత్త టూట్ను రాయండి",
@@ -246,7 +245,6 @@
"status.delete": "తొలగించు",
"status.detailed_status": "వివరణాత్మక సంభాషణ వీక్షణ",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "ఎంబెడ్",
"status.load_more": "మరిన్ని లోడ్ చేయి",
"status.media_hidden": "మీడియా దాచబడింది",
"status.mention": "@{name}ను ప్రస్తావించు",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index 9dbaa5a6cb..d446cacb92 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -97,6 +97,8 @@
"block_modal.title": "ปิดกั้นผู้ใช้?",
"block_modal.you_wont_see_mentions": "คุณจะไม่เห็นโพสต์ที่กล่าวถึงเขา",
"boost_modal.combo": "คุณสามารถกด {combo} เพื่อข้ามสิ่งนี้ในครั้งถัดไป",
+ "boost_modal.reblog": "ดันโพสต์?",
+ "boost_modal.undo_reblog": "เลิกดันโพสต์?",
"bundle_column_error.copy_stacktrace": "คัดลอกรายงานข้อผิดพลาด",
"bundle_column_error.error.body": "ไม่สามารถแสดงผลหน้าที่ขอ ข้อผิดพลาดอาจเป็นเพราะข้อบกพร่องในโค้ดของเรา หรือปัญหาความเข้ากันได้ของเบราว์เซอร์",
"bundle_column_error.error.title": "โอ้ ไม่!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "เลิกติดตาม",
"confirmations.unfollow.message": "คุณแน่ใจหรือไม่ว่าต้องการเลิกติดตาม {name}?",
"confirmations.unfollow.title": "เลิกติดตามผู้ใช้?",
+ "content_warning.hide": "ซ่อนโพสต์",
+ "content_warning.show": "แสดงต่อไป",
"conversation.delete": "ลบการสนทนา",
"conversation.mark_as_read": "ทำเครื่องหมายว่าอ่านแล้ว",
"conversation.open": "ดูการสนทนา",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "ใช้หมวดหมู่ที่มีอยู่หรือสร้างหมวดหมู่ใหม่",
"filter_modal.select_filter.title": "กรองโพสต์นี้",
"filter_modal.title.status": "กรองโพสต์",
+ "filter_warning.matches_filter": "ตรงกับตัวกรอง “{title}”",
"filtered_notifications_banner.pending_requests": "จาก {count, plural, =0 {ไม่มีใคร} other {# คน}} ที่คุณอาจรู้จัก",
"filtered_notifications_banner.title": "การแจ้งเตือนที่กรองอยู่",
"firehose.all": "ทั้งหมด",
@@ -348,6 +353,14 @@
"hashtag.follow": "ติดตามแฮชแท็ก",
"hashtag.unfollow": "เลิกติดตามแฮชแท็ก",
"hashtags.and_other": "…และอีก {count, plural, other {# เพิ่มเติม}}",
+ "hints.profiles.followers_may_be_missing": "ผู้ติดตามสำหรับโปรไฟล์นี้อาจขาดหายไป",
+ "hints.profiles.follows_may_be_missing": "การติดตามสำหรับโปรไฟล์นี้อาจขาดหายไป",
+ "hints.profiles.posts_may_be_missing": "โพสต์บางส่วนจากโปรไฟล์นี้อาจขาดหายไป",
+ "hints.profiles.see_more_followers": "ดูผู้ติดตามเพิ่มเติมใน {domain}",
+ "hints.profiles.see_more_follows": "ดูการติดตามเพิ่มเติมใน {domain}",
+ "hints.profiles.see_more_posts": "ดูโพสต์เพิ่มเติมใน {domain}",
+ "hints.threads.replies_may_be_missing": "การตอบกลับจากเซิร์ฟเวอร์อื่น ๆ อาจขาดหายไป",
+ "hints.threads.see_more": "ดูการตอบกลับเพิ่มเติมใน {domain}",
"home.column_settings.show_reblogs": "แสดงการดัน",
"home.column_settings.show_replies": "แสดงการตอบกลับ",
"home.hide_announcements": "ซ่อนประกาศ",
@@ -355,8 +368,11 @@
"home.pending_critical_update.link": "ดูการอัปเดต",
"home.pending_critical_update.title": "มีการอัปเดตความปลอดภัยสำคัญพร้อมใช้งาน!",
"home.show_announcements": "แสดงประกาศ",
+ "ignore_notifications_modal.disclaimer": "Mastodon ไม่สามารถแจ้งผู้ใช้ว่าคุณได้เพิกเฉยการแจ้งเตือนของเขา การเพิกเฉยการแจ้งเตือนจะไม่หยุดการส่งข้อความนั้นเอง",
"ignore_notifications_modal.filter_instead": "กรองแทน",
"ignore_notifications_modal.filter_to_act_users": "คุณจะยังสามารถยอมรับ ปฏิเสธ หรือรายงานผู้ใช้",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "การกรองช่วยหลีกเลี่ยงความสับสนที่อาจเกิดขึ้น",
+ "ignore_notifications_modal.filter_to_review_separately": "คุณสามารถตรวจทานการแจ้งเตือนที่กรองอยู่แยกต่างหาก",
"ignore_notifications_modal.ignore": "เพิกเฉยการแจ้งเตือน",
"ignore_notifications_modal.limited_accounts_title": "เพิกเฉยการแจ้งเตือนจากบัญชีที่ได้รับการกลั่นกรอง?",
"ignore_notifications_modal.new_accounts_title": "เพิกเฉยการแจ้งเตือนจากบัญชีใหม่?",
@@ -416,8 +432,6 @@
"keyboard_shortcuts.unfocus": "เลิกโฟกัสพื้นที่เขียนข้อความ/การค้นหา",
"keyboard_shortcuts.up": "ย้ายขึ้นในรายการ",
"lightbox.close": "ปิด",
- "lightbox.compress": "บีบอัดกล่องดูภาพ",
- "lightbox.expand": "ขยายกล่องดูภาพ",
"lightbox.next": "ถัดไป",
"lightbox.previous": "ก่อนหน้า",
"limited_account_hint.action": "แสดงโปรไฟล์ต่อไป",
@@ -441,7 +455,7 @@
"lists.subheading": "รายการของคุณ",
"load_pending": "{count, plural, other {# รายการใหม่}}",
"loading_indicator.label": "กำลังโหลด…",
- "media_gallery.toggle_visible": "{number, plural, other {ซ่อนภาพ}}",
+ "media_gallery.hide": "ซ่อน",
"moved_to_account_banner.text": "มีการปิดใช้งานบัญชีของคุณ {disabledAccount} ในปัจจุบันเนื่องจากคุณได้ย้ายไปยัง {movedToAccount}",
"mute_modal.hide_from_notifications": "ซ่อนจากการแจ้งเตือน",
"mute_modal.hide_options": "ซ่อนตัวเลือก",
@@ -453,6 +467,7 @@
"mute_modal.you_wont_see_mentions": "คุณจะไม่เห็นโพสต์ที่กล่าวถึงเขา",
"mute_modal.you_wont_see_posts": "เขายังคงสามารถเห็นโพสต์ของคุณ แต่คุณจะไม่เห็นโพสต์ของเขา",
"navigation_bar.about": "เกี่ยวกับ",
+ "navigation_bar.administration": "การดูแล",
"navigation_bar.advanced_interface": "เปิดในส่วนติดต่อเว็บขั้นสูง",
"navigation_bar.blocks": "ผู้ใช้ที่ปิดกั้นอยู่",
"navigation_bar.bookmarks": "ที่คั่นหน้า",
@@ -469,6 +484,7 @@
"navigation_bar.follows_and_followers": "การติดตามและผู้ติดตาม",
"navigation_bar.lists": "รายการ",
"navigation_bar.logout": "ออกจากระบบ",
+ "navigation_bar.moderation": "การกลั่นกรอง",
"navigation_bar.mutes": "ผู้ใช้ที่ซ่อนอยู่",
"navigation_bar.opened_in_classic_interface": "จะเปิดโพสต์, บัญชี และหน้าที่เฉพาะเจาะจงอื่น ๆ เป็นค่าเริ่มต้นในส่วนติดต่อเว็บแบบคลาสสิก",
"navigation_bar.personal": "ส่วนบุคคล",
@@ -484,9 +500,13 @@
"notification.admin.report_statuses": "{name} ได้รายงาน {target} สำหรับ {category}",
"notification.admin.report_statuses_other": "{name} ได้รายงาน {target}",
"notification.admin.sign_up": "{name} ได้ลงทะเบียน",
+ "notification.admin.sign_up.name_and_others": "{name} และ {count, plural, other {# อื่น ๆ}} ได้ลงทะเบียน",
"notification.favourite": "{name} ได้ชื่นชอบโพสต์ของคุณ",
+ "notification.favourite.name_and_others_with_link": "{name} และ
{count, plural, other {# อื่น ๆ}} ได้ชื่นชอบโพสต์ของคุณ",
"notification.follow": "{name} ได้ติดตามคุณ",
+ "notification.follow.name_and_others": "{name} และ {count, plural, other {# อื่น ๆ}} ได้ติดตามคุณ",
"notification.follow_request": "{name} ได้ขอติดตามคุณ",
+ "notification.follow_request.name_and_others": "{name} และ {count, plural, other {# อื่น ๆ}} ได้ขอติดตามคุณ",
"notification.label.mention": "การกล่าวถึง",
"notification.label.private_mention": "การกล่าวถึงแบบส่วนตัว",
"notification.label.private_reply": "การตอบกลับแบบส่วนตัว",
@@ -504,6 +524,7 @@
"notification.own_poll": "การสำรวจความคิดเห็นของคุณได้สิ้นสุดแล้ว",
"notification.poll": "การสำรวจความคิดเห็นที่คุณได้ลงคะแนนได้สิ้นสุดแล้ว",
"notification.reblog": "{name} ได้ดันโพสต์ของคุณ",
+ "notification.reblog.name_and_others_with_link": "{name} และ
{count, plural, other {# อื่น ๆ}} ได้ดันโพสต์ของคุณ",
"notification.relationships_severance_event": "สูญเสียการเชื่อมต่อกับ {name}",
"notification.relationships_severance_event.account_suspension": "ผู้ดูแลจาก {from} ได้ระงับ {target} ซึ่งหมายความว่าคุณจะไม่สามารถรับการอัปเดตจากเขาหรือโต้ตอบกับเขาได้อีกต่อไป",
"notification.relationships_severance_event.domain_block": "ผู้ดูแลจาก {from} ได้ปิดกั้น {target} รวมถึง {followersCount} ผู้ติดตามของคุณและ {followingCount, plural, other {# บัญชี}}ที่คุณติดตาม",
@@ -512,7 +533,21 @@
"notification.status": "{name} เพิ่งโพสต์",
"notification.update": "{name} ได้แก้ไขโพสต์",
"notification_requests.accept": "ยอมรับ",
+ "notification_requests.accept_multiple": "{count, plural, other {ยอมรับ # คำขอ…}}",
+ "notification_requests.confirm_accept_multiple.button": "{count, plural, other {ยอมรับคำขอ}}",
+ "notification_requests.confirm_accept_multiple.message": "คุณกำลังจะยอมรับ {count, plural, other {# คำขอการแจ้งเตือน}} คุณแน่ใจหรือไม่ว่าต้องการดำเนินการต่อ?",
+ "notification_requests.confirm_accept_multiple.title": "ยอมรับคำขอการแจ้งเตือน?",
+ "notification_requests.confirm_dismiss_multiple.button": "{count, plural, other {ปิดคำขอ}}",
+ "notification_requests.confirm_dismiss_multiple.message": "คุณกำลังจะปิด {count, plural, other {# คำขอการแจ้งเตือน}} คุณจะไม่สามารถเข้าถึง{count, plural, other {การแจ้งเตือน}}ได้อย่างง่ายดายอีกครั้ง คุณแน่ใจหรือไม่ว่าต้องการดำเนินการต่อ?",
+ "notification_requests.confirm_dismiss_multiple.title": "ปิดคำขอการแจ้งเตือน?",
"notification_requests.dismiss": "ปิด",
+ "notification_requests.dismiss_multiple": "{count, plural, other {ปิด # คำขอ…}}",
+ "notification_requests.edit_selection": "แก้ไข",
+ "notification_requests.exit_selection": "เสร็จสิ้น",
+ "notification_requests.explainer_for_limited_account": "มีการกรองการแจ้งเตือนจากบัญชีนี้เนื่องจากมีการจำกัดบัญชีโดยผู้กลั่นกรอง",
+ "notification_requests.explainer_for_limited_remote_account": "มีการกรองการแจ้งเตือนจากบัญชีนี้เนื่องจากมีการจำกัดบัญชีหรือเซิร์ฟเวอร์ของบัญชีโดยผู้กลั่นกรอง",
+ "notification_requests.maximize": "ขยายใหญ่สุด",
+ "notification_requests.minimize_banner": "ย่อแบนเนอร์การแจ้งเตือนที่กรองอยู่ให้เล็กสุด",
"notification_requests.notifications_from": "การแจ้งเตือนจาก {name}",
"notification_requests.title": "การแจ้งเตือนที่กรองอยู่",
"notification_requests.view": "ดูการแจ้งเตือน",
@@ -522,8 +557,6 @@
"notifications.column_settings.admin.report": "รายงานใหม่:",
"notifications.column_settings.admin.sign_up": "การลงทะเบียนใหม่:",
"notifications.column_settings.alert": "การแจ้งเตือนบนเดสก์ท็อป",
- "notifications.column_settings.beta.category": "คุณลักษณะการทดลอง",
- "notifications.column_settings.beta.grouping": "การแจ้งเตือนกลุ่ม",
"notifications.column_settings.favourite": "รายการโปรด:",
"notifications.column_settings.filter_bar.advanced": "แสดงหมวดหมู่ทั้งหมด",
"notifications.column_settings.filter_bar.category": "แถบตัวกรองด่วน",
@@ -555,8 +588,10 @@
"notifications.policy.accept": "ยอมรับ",
"notifications.policy.accept_hint": "แสดงในการแจ้งเตือน",
"notifications.policy.drop": "เพิกเฉย",
+ "notifications.policy.drop_hint": "ละทิ้งอย่างถาวร ไม่ให้เห็นอีกเลย",
"notifications.policy.filter": "กรอง",
"notifications.policy.filter_hint": "ส่งไปยังกล่องขาเข้าการแจ้งเตือนที่กรองอยู่",
+ "notifications.policy.filter_limited_accounts_hint": "จำกัดโดยผู้กลั่นกรองเซิร์ฟเวอร์",
"notifications.policy.filter_limited_accounts_title": "บัญชีที่ได้รับการกลั่นกรอง",
"notifications.policy.filter_new_accounts.hint": "สร้างขึ้นภายใน {days, plural, other {# วัน}}ที่ผ่านมา",
"notifications.policy.filter_new_accounts_title": "บัญชีใหม่",
@@ -606,7 +641,7 @@
"onboarding.steps.share_profile.title": "แชร์โปรไฟล์ Mastodon ของคุณ",
"onboarding.tips.2fa": "
คุณทราบหรือไม่? คุณสามารถรักษาความปลอดภัยบัญชีของคุณได้โดยตั้งค่าการรับรองความถูกต้องด้วยสองปัจจัยในการตั้งค่าบัญชีของคุณ การรับรองความถูกต้องด้วยสองปัจจัยทำงานร่วมกับแอป TOTP ใด ๆ ที่คุณเลือก ไม่จำเป็นต้องมีหมายเลขโทรศัพท์!",
"onboarding.tips.accounts_from_other_servers": "
คุณทราบหรือไม่? เนื่องจาก Mastodon เป็นแบบกระจายศูนย์ โปรไฟล์บางส่วนที่คุณเจอจะได้รับการโฮสต์ในเซิร์ฟเวอร์อื่น ๆ ที่ไม่ใช่ของคุณ และคุณยังสามารถโต้ตอบกับเขาได้อย่างไร้รอยต่อ! เซิร์ฟเวอร์ของเขาอยู่ในครึ่งหลังของชื่อผู้ใช้ของเขา!",
- "onboarding.tips.migration": "
คุณทราบหรือไม่? หากคุณรู้สึกว่า {domain} ไม่ใช่ตัวเลือกเซิร์ฟเวอร์ที่ยอดเยี่ยมสำหรับคุณในอนาคต คุณสามารถย้ายไปยังเซิร์ฟเวอร์ Mastodon อื่นได้โดยไม่สูญเสียผู้ติดตามของคุณ คุณยังสามารถโฮสต์เซิร์ฟเวอร์ของคุณเอง!",
+ "onboarding.tips.migration": "
คุณทราบหรือไม่? หากคุณรู้สึกว่า {domain} ไม่ใช่ตัวเลือกเซิร์ฟเวอร์ที่ยอดเยี่ยมสำหรับคุณในอนาคต คุณสามารถย้ายไปยังเซิร์ฟเวอร์ Mastodon อื่นได้โดยไม่สูญเสียผู้ติดตามของคุณ คุณยังสามารถโฮสต์เซิร์ฟเวอร์ของคุณเองได้อีกด้วย!",
"onboarding.tips.verification": "
คุณทราบหรือไม่? คุณสามารถยืนยันบัญชีของคุณได้โดยใส่ลิงก์ไปยังโปรไฟล์ Mastodon ของคุณในเว็บไซต์ของคุณเองและเพิ่มเว็บไซต์ไปยังโปรไฟล์ของคุณ ไม่จำเป็นต้องมีค่าธรรมเนียมหรือเอกสาร!",
"password_confirmation.exceeds_maxlength": "การยืนยันรหัสผ่านเกินความยาวรหัสผ่านสูงสุดแล้ว",
"password_confirmation.mismatching": "การยืนยันรหัสผ่านไม่ตรงกัน",
@@ -741,6 +776,7 @@
"status.bookmark": "เพิ่มที่คั่นหน้า",
"status.cancel_reblog_private": "เลิกดัน",
"status.cannot_reblog": "ไม่สามารถดันโพสต์นี้",
+ "status.continued_thread": "กระทู้ต่อเนื่อง",
"status.copy": "คัดลอกลิงก์ไปยังโพสต์",
"status.delete": "ลบ",
"status.detailed_status": "มุมมองการสนทนาโดยละเอียด",
@@ -749,7 +785,7 @@
"status.edit": "แก้ไข",
"status.edited": "แก้ไขล่าสุดเมื่อ {date}",
"status.edited_x_times": "แก้ไข {count, plural, other {{count} ครั้ง}}",
- "status.embed": "ฝัง",
+ "status.embed": "รับโค้ดฝังตัว",
"status.favourite": "ชื่นชอบ",
"status.favourites": "{count, plural, other {รายการโปรด}}",
"status.filter": "กรองโพสต์นี้",
@@ -774,6 +810,7 @@
"status.reblogs.empty": "ยังไม่มีใครดันโพสต์นี้ เมื่อใครสักคนดัน เขาจะปรากฏที่นี่",
"status.redraft": "ลบแล้วร่างใหม่",
"status.remove_bookmark": "เอาที่คั่นหน้าออก",
+ "status.replied_in_thread": "ตอบกลับในกระทู้",
"status.replied_to": "ตอบกลับ {name}",
"status.reply": "ตอบกลับ",
"status.replyAll": "ตอบกลับกระทู้",
diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json
index 19e33233c0..9f20388182 100644
--- a/app/javascript/mastodon/locales/tok.json
+++ b/app/javascript/mastodon/locales/tok.json
@@ -252,8 +252,6 @@
"keyboard_shortcuts.toot": "o toki",
"keyboard_shortcuts.up": "o tawa sewi lon lipu",
"lightbox.close": "o pini",
- "lightbox.compress": "o lili e sitelen",
- "lightbox.expand": "o suli e sitelen",
"lightbox.next": "sinpin",
"lightbox.previous": "monsi",
"link_preview.author": "tan {name}",
@@ -270,7 +268,6 @@
"lists.subheading": "kulupu lipu sina",
"load_pending": "{count, plural, other {ijo sin #}}",
"loading_indicator.label": "ni li kama…",
- "media_gallery.toggle_visible": "{number, plural, other {o len e sitelen}}",
"mute_modal.title": "sina wile ala wile kute e jan ni?",
"navigation_bar.about": "sona",
"navigation_bar.blocks": "jan weka",
@@ -360,7 +357,6 @@
"status.cancel_reblog_private": "o pini e pana",
"status.delete": "o weka",
"status.edit": "o ante",
- "status.embed": "ni o lon insa pi lipu ante",
"status.favourite": "o sitelen pona",
"status.history.created": "{name} li pali e ni lon {date}",
"status.history.edited": "{name} li ante lon {date}",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index 23a25a7299..bdb2de0ef1 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -97,6 +97,8 @@
"block_modal.title": "Kullanıcıyı engelle?",
"block_modal.you_wont_see_mentions": "Onlardan bahseden gönderiler göremezsiniz.",
"boost_modal.combo": "Bir daha ki sefere {combo} tuşuna basabilirsin",
+ "boost_modal.reblog": "Gönderiyi yeniden paylaş?",
+ "boost_modal.undo_reblog": "Gönderinin yeniden paylaşımını geri al?",
"bundle_column_error.copy_stacktrace": "Hata raporunu kopyala",
"bundle_column_error.error.body": "İstenen sayfa gösterilemiyor. Bu durum kodumuzdaki bir hatadan veya tarayıcı uyum sorunundan kaynaklanıyor olabilir.",
"bundle_column_error.error.title": "Ah, hayır!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Takibi bırak",
"confirmations.unfollow.message": "{name} adlı kullanıcıyı takibi bırakmak istediğinden emin misin?",
"confirmations.unfollow.title": "Kullanıcıyı takipten çık?",
+ "content_warning.hide": "Gönderiyi gizle",
+ "content_warning.show": "Yine de göster",
"conversation.delete": "Sohbeti sil",
"conversation.mark_as_read": "Okundu olarak işaretle",
"conversation.open": "Sohbeti görüntüle",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Mevcut bir kategoriyi kullan veya yeni bir tane oluştur",
"filter_modal.select_filter.title": "Bu gönderiyi süzgeçle",
"filter_modal.title.status": "Bir gönderi süzgeçle",
+ "filter_warning.matches_filter": "“{title}” filtresiyle eşleşiyor",
"filtered_notifications_banner.pending_requests": "Bildiğiniz {count, plural, =0 {hiç kimseden} one {bir kişiden} other {# kişiden}}",
"filtered_notifications_banner.title": "Filtrelenmiş bildirimler",
"firehose.all": "Tümü",
@@ -427,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Aramada bir gönderiye odaklanmamak için",
"keyboard_shortcuts.up": "Listede yukarıya çıkmak için",
"lightbox.close": "Kapat",
- "lightbox.compress": "Resim görüntüleme kutusunu sıkıştır",
- "lightbox.expand": "Resim görüntüleme kutusunu genişlet",
"lightbox.next": "Sonraki",
"lightbox.previous": "Önceki",
+ "lightbox.zoom_in": "Özgün boyuta dön",
+ "lightbox.zoom_out": "Sığacak şekilde boyutla",
"limited_account_hint.action": "Yine de profili göster",
"limited_account_hint.title": "Bu profil {domain} moderatörleri tarafından gizlendi.",
"link_preview.author": "Yazar: {name}",
@@ -452,7 +457,7 @@
"lists.subheading": "Listeleriniz",
"load_pending": "{count, plural, one {# yeni öğe} other {# yeni öğe}}",
"loading_indicator.label": "Yükleniyor…",
- "media_gallery.toggle_visible": "{number, plural, one {Resmi} other {Resimleri}} gizle",
+ "media_gallery.hide": "Gizle",
"moved_to_account_banner.text": "{disabledAccount} hesabınız, {movedToAccount} hesabına taşıdığınız için şu an devre dışı.",
"mute_modal.hide_from_notifications": "Bildirimlerde gizle",
"mute_modal.hide_options": "Seçenekleri gizle",
@@ -464,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Onlardan bahseden gönderiler göremezsiniz.",
"mute_modal.you_wont_see_posts": "Onlar sizin gönderilerinizi görmeye devam edebilir, ancak siz onlarınkini göremezsiniz.",
"navigation_bar.about": "Hakkında",
+ "navigation_bar.administration": "Yönetim",
"navigation_bar.advanced_interface": "Gelişmiş web arayüzünde aç",
"navigation_bar.blocks": "Engellenen kullanıcılar",
"navigation_bar.bookmarks": "Yer İşaretleri",
@@ -480,6 +486,7 @@
"navigation_bar.follows_and_followers": "Takip edilenler ve takipçiler",
"navigation_bar.lists": "Listeler",
"navigation_bar.logout": "Oturumu kapat",
+ "navigation_bar.moderation": "Moderasyon",
"navigation_bar.mutes": "Sessize alınmış kullanıcılar",
"navigation_bar.opened_in_classic_interface": "Gönderiler, hesaplar ve diğer belirli sayfalar klasik web arayüzünde varsayılan olarak açılıyorlar.",
"navigation_bar.personal": "Kişisel",
@@ -552,8 +559,6 @@
"notifications.column_settings.admin.report": "Yeni bildirimler:",
"notifications.column_settings.admin.sign_up": "Yeni kayıtlar:",
"notifications.column_settings.alert": "Masaüstü bildirimleri",
- "notifications.column_settings.beta.category": "Deneysel özellikler",
- "notifications.column_settings.beta.grouping": "Grup bildirimleri",
"notifications.column_settings.favourite": "Favorilerin:",
"notifications.column_settings.filter_bar.advanced": "Tüm kategorileri görüntüle",
"notifications.column_settings.filter_bar.category": "Hızlı filtre çubuğu",
@@ -773,6 +778,7 @@
"status.bookmark": "Yer işareti ekle",
"status.cancel_reblog_private": "Yeniden paylaşımı geri al",
"status.cannot_reblog": "Bu gönderi yeniden paylaşılamaz",
+ "status.continued_thread": "Devam eden akış",
"status.copy": "Gönderi bağlantısını kopyala",
"status.delete": "Sil",
"status.detailed_status": "Ayrıntılı sohbet görünümü",
@@ -781,7 +787,7 @@
"status.edit": "Düzenle",
"status.edited": "Son düzenleme {date}",
"status.edited_x_times": "{count, plural, one {{count} kez} other {{count} kez}} düzenlendi",
- "status.embed": "Gömülü",
+ "status.embed": "Gömme kodunu al",
"status.favourite": "Favori",
"status.favourites": "{count, plural, one {beğeni} other {beğeni}}",
"status.filter": "Bu gönderiyi süzgeçle",
@@ -806,6 +812,7 @@
"status.reblogs.empty": "Henüz hiç kimse bu gönderiyi yeniden paylaşmadı. Herhangi bir kullanıcı yeniden paylaştığında burada görüntülenecek.",
"status.redraft": "Sil,Düzenle ve Yeniden paylaş",
"status.remove_bookmark": "Yer işaretini kaldır",
+ "status.replied_in_thread": "Akışta yanıtlandı",
"status.replied_to": "{name} kullanıcısına yanıt verdi",
"status.reply": "Yanıtla",
"status.replyAll": "Konuyu yanıtla",
diff --git a/app/javascript/mastodon/locales/tt.json b/app/javascript/mastodon/locales/tt.json
index 1439e2ef58..08bb7979a1 100644
--- a/app/javascript/mastodon/locales/tt.json
+++ b/app/javascript/mastodon/locales/tt.json
@@ -271,8 +271,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"lightbox.close": "Ябу",
- "lightbox.compress": "Кысылган рәсемне карау тәрәзәсе",
- "lightbox.expand": "Рәсемне карау тәрәзәсен ачыгыз",
"lightbox.next": "Киләсе",
"lightbox.previous": "Алдагы",
"limited_account_hint.action": "Барыбер профильне күрсәтергә",
@@ -410,7 +408,6 @@
"status.direct_indicator": "Хосусый искә алу",
"status.edit": "Үзгәртү",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
- "status.embed": "Веб-биткә кертү",
"status.history.created": "{name} ясалды {date}",
"status.history.edited": "{name} төзәтте {date}",
"status.load_more": "Күбрәк йөкләү",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index 7f8b33594d..3bf8d00248 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -97,6 +97,8 @@
"block_modal.title": "Заблокувати користувача?",
"block_modal.you_wont_see_mentions": "Ви не бачитимете дописів, де їх згадано.",
"boost_modal.combo": "Ви можете натиснути {combo}, щоби пропустити це наступного разу",
+ "boost_modal.reblog": "Поширити допис?",
+ "boost_modal.undo_reblog": "Скасувати поширення?",
"bundle_column_error.copy_stacktrace": "Копіювати звіт про помилку",
"bundle_column_error.error.body": "Неможливо показати запитану сторінку. Це може бути спричинено помилкою у нашому коді, або через проблему сумісності з браузером.",
"bundle_column_error.error.title": "О, ні!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Відписатися",
"confirmations.unfollow.message": "Ви впевнені, що хочете відписатися від {name}?",
"confirmations.unfollow.title": "Відписатися від користувача?",
+ "content_warning.hide": "Сховати допис",
+ "content_warning.show": "Усе одно показати",
"conversation.delete": "Видалити бесіду",
"conversation.mark_as_read": "Позначити як прочитане",
"conversation.open": "Переглянути бесіду",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Використати наявну категорію або створити нову",
"filter_modal.select_filter.title": "Фільтрувати цей допис",
"filter_modal.title.status": "Фільтрувати допис",
+ "filter_warning.matches_filter": "Збігається з фільтром “{title}”",
"filtered_notifications_banner.pending_requests": "Від {count, plural, =0 {жодної особи} one {однієї особи} few {# осіб} many {# осіб} other {# особи}}, котрих ви можете знати",
"filtered_notifications_banner.title": "Відфільтровані сповіщення",
"firehose.all": "Всі",
@@ -427,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Розфокусуватися з нового допису чи пошуку",
"keyboard_shortcuts.up": "Рухатися вгору списком",
"lightbox.close": "Закрити",
- "lightbox.compress": "Стиснути поле перегляду зображень",
- "lightbox.expand": "Розгорнути поле перегляду зображень",
"lightbox.next": "Далі",
"lightbox.previous": "Назад",
+ "lightbox.zoom_in": "Масштаб за реальним розміром",
+ "lightbox.zoom_out": "Збільшити відповідно до розміру",
"limited_account_hint.action": "Усе одно показати профіль",
"limited_account_hint.title": "Цей профіль сховали модератори {domain}.",
"link_preview.author": "Від {name}",
@@ -452,7 +457,7 @@
"lists.subheading": "Ваші списки",
"load_pending": "{count, plural, one {# новий елемент} other {# нових елементів}}",
"loading_indicator.label": "Завантаження…",
- "media_gallery.toggle_visible": "{number, plural, one {Приховати зображення} other {Приховати зображення}}",
+ "media_gallery.hide": "Сховати",
"moved_to_account_banner.text": "Ваш обліковий запис {disabledAccount} наразі вимкнений, оскільки вас перенесено до {movedToAccount}.",
"mute_modal.hide_from_notifications": "Сховати зі сповіщень",
"mute_modal.hide_options": "Сховати опції",
@@ -464,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "Ви не бачитимете дописів, де їх згадано.",
"mute_modal.you_wont_see_posts": "Вони все ще можуть бачити ваші дописи, але ви не бачитимете їхніх.",
"navigation_bar.about": "Про застосунок",
+ "navigation_bar.administration": "Адміністрування",
"navigation_bar.advanced_interface": "Відкрити в розширеному вебінтерфейсі",
"navigation_bar.blocks": "Заблоковані користувачі",
"navigation_bar.bookmarks": "Закладки",
@@ -480,6 +486,7 @@
"navigation_bar.follows_and_followers": "Підписки та підписники",
"navigation_bar.lists": "Списки",
"navigation_bar.logout": "Вийти",
+ "navigation_bar.moderation": "Модерування",
"navigation_bar.mutes": "Приховані користувачі",
"navigation_bar.opened_in_classic_interface": "Дописи, облікові записи та інші специфічні сторінки усталено відкриваються в класичному вебінтерфейсі.",
"navigation_bar.personal": "Особисте",
@@ -507,13 +514,13 @@
"notification.label.private_reply": "Приватна відповідь",
"notification.label.reply": "Відповідь",
"notification.mention": "Згадка",
- "notification.moderation-warning.learn_more": "Дізнатися більше",
+ "notification.moderation-warning.learn_more": "Докладніше",
"notification.moderation_warning": "Ви отримали попередження модерації",
- "notification.moderation_warning.action_delete_statuses": "Деякі з ваших дописів було видалено.",
+ "notification.moderation_warning.action_delete_statuses": "Деякі з ваших дописів було вилучено.",
"notification.moderation_warning.action_disable": "Ваш обліковий запис було вимкнено.",
- "notification.moderation_warning.action_mark_statuses_as_sensitive": "Деякі з ваших дописів були позначені як чутливі.",
+ "notification.moderation_warning.action_mark_statuses_as_sensitive": "Деякі з ваших дописів були позначені делікатними.",
"notification.moderation_warning.action_none": "Ваш обліковий запис отримав попередження модерації.",
- "notification.moderation_warning.action_sensitive": "Відтепер ваші дописи будуть позначені як чутливі.",
+ "notification.moderation_warning.action_sensitive": "Відтепер ваші дописи будуть позначені делікатними.",
"notification.moderation_warning.action_silence": "Ваш обліковий запис було обмежено.",
"notification.moderation_warning.action_suspend": "Ваш обліковий запис було заблоковано.",
"notification.own_poll": "Ваше опитування завершилося",
@@ -552,8 +559,6 @@
"notifications.column_settings.admin.report": "Нові скарги:",
"notifications.column_settings.admin.sign_up": "Нові реєстрації:",
"notifications.column_settings.alert": "Сповіщення стільниці",
- "notifications.column_settings.beta.category": "Експериментальні функції",
- "notifications.column_settings.beta.grouping": "Групові сповіщення",
"notifications.column_settings.favourite": "Уподобане:",
"notifications.column_settings.filter_bar.advanced": "Показати всі категорії",
"notifications.column_settings.filter_bar.category": "Панель швидкого фільтра",
@@ -773,6 +778,7 @@
"status.bookmark": "Додати до закладок",
"status.cancel_reblog_private": "Скасувати поширення",
"status.cannot_reblog": "Цей допис не може бути поширений",
+ "status.continued_thread": "Продовження у потоці",
"status.copy": "Копіювати посилання на допис",
"status.delete": "Видалити",
"status.detailed_status": "Детальний вигляд бесіди",
@@ -781,7 +787,7 @@
"status.edit": "Редагувати",
"status.edited": "Востаннє змінено {date}",
"status.edited_x_times": "Відредаговано {count, plural, one {{count} раз} few {{count} рази} many {{counter} разів} other {{counter} разів}}",
- "status.embed": "Вбудувати",
+ "status.embed": "Отримати код вставки",
"status.favourite": "Уподобане",
"status.favourites": "{count, plural, one {вподобання} few {вподобання} many {вподобань} other {вподобання}}",
"status.filter": "Фільтрувати цей допис",
@@ -806,6 +812,7 @@
"status.reblogs.empty": "Ніхто ще не поширив цей допис. Коли хтось це зроблять, вони будуть зображені тут.",
"status.redraft": "Видалити та виправити",
"status.remove_bookmark": "Видалити закладку",
+ "status.replied_in_thread": "Відповідь у потоці",
"status.replied_to": "Відповідь для {name}",
"status.reply": "Відповісти",
"status.replyAll": "Відповісти на ланцюжок",
diff --git a/app/javascript/mastodon/locales/uz.json b/app/javascript/mastodon/locales/uz.json
index 048f8e7757..6dae368ffc 100644
--- a/app/javascript/mastodon/locales/uz.json
+++ b/app/javascript/mastodon/locales/uz.json
@@ -299,7 +299,6 @@
"lists.search": "Siz kuzatadigan odamlar orasidan qidiring",
"lists.subheading": "Sizning ro'yxatlaringiz",
"load_pending": "{count, plural, one {# yangi element} other {# yangi elementlar}}",
- "media_gallery.toggle_visible": "{number, plural, one {Rasmni yashirish} other {Rasmlarni yashirish}}",
"moved_to_account_banner.text": "{movedToAccount} hisobiga koʻchganingiz uchun {disabledAccount} hisobingiz hozirda oʻchirib qoʻyilgan.",
"navigation_bar.about": "Haqida",
"navigation_bar.blocks": "Bloklangan foydalanuvchilar",
diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json
index a0c28db77e..04b73e78fa 100644
--- a/app/javascript/mastodon/locales/vi.json
+++ b/app/javascript/mastodon/locales/vi.json
@@ -3,7 +3,7 @@
"about.contact": "Liên lạc:",
"about.disclaimer": "Mastodon là phần mềm tự do nguồn mở của Mastodon gGmbH.",
"about.domain_blocks.no_reason_available": "Lý do không được cung cấp",
- "about.domain_blocks.preamble": "Mastodon cho phép bạn tương tác nội dung và giao tiếp với mọi người từ bất kỳ máy chủ nào khác trong mạng liên hợp. Còn máy chủ này có những ngoại lệ riêng.",
+ "about.domain_blocks.preamble": "Mastodon cho phép bạn đọc nội dung và giao tiếp với mọi người từ bất kỳ máy chủ nào. Còn đây là những ngoại lệ trên máy chủ này.",
"about.domain_blocks.silenced.explanation": "Nói chung, bạn sẽ không thấy người và nội dung từ máy chủ này, trừ khi bạn tự tìm kiếm hoặc tự theo dõi.",
"about.domain_blocks.silenced.title": "Hạn chế",
"about.domain_blocks.suspended.explanation": "Dữ liệu từ máy chủ này sẽ không được xử lý, lưu trữ hoặc trao đổi. Mọi tương tác hoặc giao tiếp với người từ máy chủ này đều bị cấm.",
@@ -34,9 +34,9 @@
"account.follow_back": "Theo dõi lại",
"account.followers": "Người theo dõi",
"account.followers.empty": "Chưa có người theo dõi nào.",
- "account.followers_counter": "{count, plural, other {{counter} người theo dõi}}",
+ "account.followers_counter": "{count, plural, other {{counter} Người theo dõi}}",
"account.following": "Đang theo dõi",
- "account.following_counter": "{count, plural, other {{counter} đang theo dõi}}",
+ "account.following_counter": "{count, plural, other {{counter} Đang theo dõi}}",
"account.follows.empty": "Người này chưa theo dõi ai.",
"account.go_to_profile": "Xem hồ sơ",
"account.hide_reblogs": "Ẩn tút @{name} đăng lại",
@@ -56,13 +56,13 @@
"account.no_bio": "Chưa có miêu tả.",
"account.open_original_page": "Mở trang gốc",
"account.posts": "Tút",
- "account.posts_with_replies": "Lượt trả lời",
+ "account.posts_with_replies": "Trả lời",
"account.report": "Báo cáo @{name}",
"account.requested": "Đang chờ chấp thuận. Nhấp vào đây để hủy yêu cầu theo dõi",
"account.requested_follow": "{name} yêu cầu theo dõi bạn",
"account.share": "Chia sẻ @{name}",
"account.show_reblogs": "Hiện tút do @{name} đăng lại",
- "account.statuses_counter": "{count, plural, other {{counter} tút}}",
+ "account.statuses_counter": "{count, plural, other {{counter} Tút}}",
"account.unblock": "Bỏ chặn @{name}",
"account.unblock_domain": "Bỏ ẩn {domain}",
"account.unblock_short": "Bỏ chặn",
@@ -76,7 +76,7 @@
"admin.dashboard.monthly_retention": "Tỉ lệ người dùng ở lại sau khi đăng ký",
"admin.dashboard.retention.average": "Trung bình",
"admin.dashboard.retention.cohort": "Tháng đăng ký",
- "admin.dashboard.retention.cohort_size": "Người mới",
+ "admin.dashboard.retention.cohort_size": "Số người",
"admin.impact_report.instance_accounts": "Hồ sơ tài khoản này sẽ xóa",
"admin.impact_report.instance_followers": "Người theo dõi của thành viên máy chủ sẽ mất",
"admin.impact_report.instance_follows": "Người theo dõi người dùng của họ sẽ mất",
@@ -97,6 +97,8 @@
"block_modal.title": "Chặn người này?",
"block_modal.you_wont_see_mentions": "Bạn sẽ không nhìn thấy tút có nhắc đến họ.",
"boost_modal.combo": "Nhấn {combo} để bỏ qua bước này",
+ "boost_modal.reblog": "Đăng lại?",
+ "boost_modal.undo_reblog": "Hủy đăng lại?",
"bundle_column_error.copy_stacktrace": "Sao chép báo lỗi",
"bundle_column_error.error.body": "Không thể hiện trang này. Đây có thể là một lỗi trong mã lập trình của chúng tôi, hoặc là vấn đề tương thích của trình duyệt.",
"bundle_column_error.error.title": "Ôi không!",
@@ -116,15 +118,15 @@
"closed_registrations_modal.title": "Đăng ký Mastodon",
"column.about": "Giới thiệu",
"column.blocks": "Người đã chặn",
- "column.bookmarks": "Đã lưu",
+ "column.bookmarks": "Những tút đã lưu",
"column.community": "Máy chủ này",
"column.direct": "Nhắn riêng",
"column.directory": "Tìm người cùng sở thích",
"column.domain_blocks": "Máy chủ đã chặn",
- "column.favourites": "Lượt thích",
+ "column.favourites": "Những tút đã thích",
"column.firehose": "Bảng tin",
"column.follow_requests": "Yêu cầu theo dõi",
- "column.home": "Trang chính",
+ "column.home": "Trang chủ",
"column.lists": "Danh sách",
"column.mutes": "Người đã ẩn",
"column.notifications": "Thông báo",
@@ -143,7 +145,7 @@
"community.column_settings.remote_only": "Chỉ người ở máy chủ khác",
"compose.language.change": "Chọn ngôn ngữ tút",
"compose.language.search": "Tìm ngôn ngữ...",
- "compose.published.body": "Đã đăng.",
+ "compose.published.body": "Tút đã được đăng.",
"compose.published.open": "Xem lại",
"compose.saved.body": "Đã lưu tút.",
"compose_form.direct_message_warning_learn_more": "Tìm hiểu thêm",
@@ -152,8 +154,8 @@
"compose_form.lock_disclaimer": "Tài khoản của bạn không {locked}. Bất cứ ai cũng có thể theo dõi và xem tút riêng tư của bạn.",
"compose_form.lock_disclaimer.lock": "khóa",
"compose_form.placeholder": "Bạn đang nghĩ gì?",
- "compose_form.poll.duration": "Hết hạn vào",
- "compose_form.poll.multiple": "Nhiều lựa chọn",
+ "compose_form.poll.duration": "Hết hạn sau",
+ "compose_form.poll.multiple": "Chọn nhiều",
"compose_form.poll.option_placeholder": "Lựa chọn {number}",
"compose_form.poll.single": "Chọn một",
"compose_form.poll.switch_to_multiple": "Có thể chọn nhiều lựa chọn",
@@ -168,30 +170,32 @@
"compose_form.spoiler_placeholder": "Nội dung ẩn (tùy chọn)",
"confirmation_modal.cancel": "Hủy bỏ",
"confirmations.block.confirm": "Chặn",
- "confirmations.delete.confirm": "Xóa bỏ",
- "confirmations.delete.message": "Bạn thật sự muốn xóa tút này?",
- "confirmations.delete.title": "Xóa tút?",
- "confirmations.delete_list.confirm": "Xóa bỏ",
- "confirmations.delete_list.message": "Bạn thật sự muốn xóa vĩnh viễn danh sách này?",
- "confirmations.delete_list.title": "Xóa danh sách?",
+ "confirmations.delete.confirm": "Vẫn xóa",
+ "confirmations.delete.message": "Bạn có chắc muốn xóa tút này?",
+ "confirmations.delete.title": "Xóa tút",
+ "confirmations.delete_list.confirm": "Vẫn xóa",
+ "confirmations.delete_list.message": "Bạn có chắc muốn xóa vĩnh viễn danh sách này?",
+ "confirmations.delete_list.title": "Xóa danh sách",
"confirmations.discard_edit_media.confirm": "Bỏ qua",
"confirmations.discard_edit_media.message": "Bạn chưa lưu thay đổi đối với phần mô tả hoặc bản xem trước của media, vẫn bỏ luôn?",
"confirmations.edit.confirm": "Sửa",
"confirmations.edit.message": "Nội dung tút cũ sẽ bị ghi đè, bạn có tiếp tục?",
- "confirmations.edit.title": "Viết đè lên tút cũ?",
+ "confirmations.edit.title": "Ghi đè lên tút cũ",
"confirmations.logout.confirm": "Đăng xuất",
- "confirmations.logout.message": "Bạn có thật sự muốn thoát?",
- "confirmations.logout.title": "Đăng xuất?",
+ "confirmations.logout.message": "Bạn có chắc muốn thoát?",
+ "confirmations.logout.title": "Đăng xuất",
"confirmations.mute.confirm": "Ẩn",
"confirmations.redraft.confirm": "Xóa & viết lại",
- "confirmations.redraft.message": "Bạn thật sự muốn xóa tút và viết lại? Điều này sẽ xóa mất những lượt thích và đăng lại của tút, cũng như những trả lời sẽ không còn nội dung gốc.",
- "confirmations.redraft.title": "Xóa & viết lại?",
+ "confirmations.redraft.message": "Điều này sẽ khiến những lượt thích và đăng lại của tút bị mất, cũng như những trả lời sẽ không còn nội dung gốc.",
+ "confirmations.redraft.title": "Xóa & viết lại",
"confirmations.reply.confirm": "Trả lời",
"confirmations.reply.message": "Nội dung bạn đang soạn thảo sẽ bị ghi đè, bạn có tiếp tục?",
- "confirmations.reply.title": "Viết đè lên tút cũ?",
+ "confirmations.reply.title": "Ghi đè lên tút cũ",
"confirmations.unfollow.confirm": "Bỏ theo dõi",
- "confirmations.unfollow.message": "Bạn thật sự muốn bỏ theo dõi {name}?",
- "confirmations.unfollow.title": "Bỏ theo dõi?",
+ "confirmations.unfollow.message": "Bạn có chắc muốn bỏ theo dõi {name}?",
+ "confirmations.unfollow.title": "Bỏ theo dõi",
+ "content_warning.hide": "Ẩn lại",
+ "content_warning.show": "Nhấn để xem",
"conversation.delete": "Xóa tin nhắn này",
"conversation.mark_as_read": "Đánh dấu là đã đọc",
"conversation.open": "Xem toàn bộ tin nhắn",
@@ -223,15 +227,15 @@
"domain_pill.activitypub_like_language": "ActivityPub giống như ngôn ngữ Mastodon giao tiếp với các mạng xã hội khác.",
"domain_pill.server": "Máy chủ",
"domain_pill.their_handle": "Địa chỉ Mastodon:",
- "domain_pill.their_server": "Ngôi nhà kỹ thuật số, nơi lưu giữ tút của ai đó.",
- "domain_pill.their_username": "Danh tính duy nhất của họ trên máy chủ này. Có thể có tên người dùng giống nhau trên các máy chủ khác.",
+ "domain_pill.their_server": "Nơi lưu trữ tút của người này.",
+ "domain_pill.their_username": "Độc nhất trên máy chủ này. Những máy chủ khác có thể cũng có tên người dùng giống vậy.",
"domain_pill.username": "Tên người dùng",
"domain_pill.whats_in_a_handle": "Địa chỉ Mastodon là gì?",
"domain_pill.who_they_are": "Vì địa chỉ Mastodon cho biết một người là ai và họ ở đâu, nên bạn có thể tương tác với mọi người trên các nền tảng có
hỗ trợ ActivityPub.",
"domain_pill.who_you_are": "Vì địa chỉ Mastodon cho biết bạn là ai và bạn ở đâu, nên bạn có thể tương tác với mọi người trên các nền tảng có
hỗ trợ ActivityPub.",
"domain_pill.your_handle": "Địa chỉ Mastodon của bạn:",
- "domain_pill.your_server": "Ngôi nhà kỹ thuật số, nơi lưu giữ tút của bạn. Không thích ở đây? Chuyển sang máy chủ khác và mang theo người theo dõi của bạn.",
- "domain_pill.your_username": "Danh tính duy nhất của bạn trên máy chủ này. Có thể có tên người dùng giống bạn trên các máy chủ khác.",
+ "domain_pill.your_server": "Nơi lưu trữ tút của bạn. Không thích ở đây? Chuyển sang máy chủ khác và giữ nguyên người theo dõi của bạn.",
+ "domain_pill.your_username": "Chỉ riêng bạn trên máy chủ này. Những máy chủ khác có thể cũng có tên người dùng giống vậy.",
"embed.instructions": "Sao chép đoạn mã dưới đây và chèn vào trang web của bạn.",
"embed.preview": "Nó sẽ hiển thị như vầy:",
"emoji_button.activity": "Hoạt động",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "Sử dụng một danh mục hiện có hoặc tạo một danh mục mới",
"filter_modal.select_filter.title": "Lọc tút này",
"filter_modal.title.status": "Lọc một tút",
+ "filter_warning.matches_filter": "Khớp bộ lọc “{title}”",
"filtered_notifications_banner.pending_requests": "Từ {count, plural, =0 {không ai} other {# người}} bạn có thể biết",
"filtered_notifications_banner.title": "Thông báo đã lọc",
"firehose.all": "Toàn bộ",
@@ -317,7 +322,7 @@
"follow_suggestions.hints.most_interactions": "Người này đang thu hút sự chú ý trên {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Người này có nét giống những người mà bạn theo dõi gần đây.",
"follow_suggestions.personalized_suggestion": "Gợi ý cá nhân hóa",
- "follow_suggestions.popular_suggestion": "Những người nổi tiếng",
+ "follow_suggestions.popular_suggestion": "Người nổi tiếng",
"follow_suggestions.popular_suggestion_longer": "Nổi tiếng trên {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Tương tự những người mà bạn theo dõi gần đây",
"follow_suggestions.view_all": "Xem tất cả",
@@ -354,7 +359,7 @@
"hints.profiles.see_more_followers": "Xem thêm người theo dõi ở {domain}",
"hints.profiles.see_more_follows": "Xem thêm người mà người này theo dõi ở {domain}",
"hints.profiles.see_more_posts": "Xem thêm tút ở {domain}",
- "hints.threads.replies_may_be_missing": "Lượt trả lời trên máy chủ khác có thể không đầy đủ.",
+ "hints.threads.replies_may_be_missing": "Lượt trả lời từ máy chủ khác có thể không đầy đủ.",
"hints.threads.see_more": "Xem thêm ở {domain}",
"home.column_settings.show_reblogs": "Hiện những lượt đăng lại",
"home.column_settings.show_replies": "Hiện những tút dạng trả lời",
@@ -363,8 +368,17 @@
"home.pending_critical_update.link": "Xem bản cập nhật",
"home.pending_critical_update.title": "Có bản cập nhật bảo mật quan trọng!",
"home.show_announcements": "Xem thông báo máy chủ",
+ "ignore_notifications_modal.disclaimer": "Mastodon sẽ không thông báo cho người dùng rằng bạn đã bỏ qua thông báo của họ. Họ sẽ vẫn có thể tương tác với bạn.",
+ "ignore_notifications_modal.filter_instead": "Lọc thay thế",
"ignore_notifications_modal.filter_to_act_users": "Bạn vẫn có thể chấp nhận, từ chối hoặc báo cáo người khác",
- "ignore_notifications_modal.filter_to_review_separately": "Bạn có thể xem lại các thông báo đã lọc riêng biệt",
+ "ignore_notifications_modal.filter_to_avoid_confusion": "Lọc giúp tránh nhầm lẫn tiềm ẩn",
+ "ignore_notifications_modal.filter_to_review_separately": "Bạn có thể xem lại riêng các thông báo đã lọc",
+ "ignore_notifications_modal.ignore": "Bỏ qua thông báo",
+ "ignore_notifications_modal.limited_accounts_title": "Bỏ qua thông báo từ các tài khoản bị kiểm duyệt?",
+ "ignore_notifications_modal.new_accounts_title": "Bỏ qua thông báo từ các tài khoản mới đăng ký?",
+ "ignore_notifications_modal.not_followers_title": "Bỏ qua thông báo từ những người chưa theo dõi bạn?",
+ "ignore_notifications_modal.not_following_title": "Bỏ qua thông báo từ những người bạn không theo dõi?",
+ "ignore_notifications_modal.private_mentions_title": "Bỏ qua thông báo từ những lượt Nhắn Riêng không mong muốn?",
"interaction_modal.description.favourite": "Với tài khoản Mastodon, bạn có thể cho người đăng biết bạn thích tút này và lưu lại tút.",
"interaction_modal.description.follow": "Với tài khoản Mastodon, bạn có thể theo dõi {name} để tút của họ hiện trên bảng tin của mình.",
"interaction_modal.description.reblog": "Với tài khoản Mastodon, bạn có thể đăng lại tút này để chia sẻ nó với những người đang theo dõi bạn.",
@@ -418,12 +432,12 @@
"keyboard_shortcuts.unfocus": "đưa con trỏ ra khỏi ô soạn thảo hoặc ô tìm kiếm",
"keyboard_shortcuts.up": "di chuyển lên trên danh sách",
"lightbox.close": "Đóng",
- "lightbox.compress": "Thu nhỏ hình",
- "lightbox.expand": "Phóng to hình",
"lightbox.next": "Tiếp",
"lightbox.previous": "Trước",
+ "lightbox.zoom_in": "Kích cỡ gốc",
+ "lightbox.zoom_out": "Vừa màn hình",
"limited_account_hint.action": "Vẫn cứ xem",
- "limited_account_hint.title": "Người này đã bị ẩn bởi quản trị viên của {domain}.",
+ "limited_account_hint.title": "Người này đã bị ẩn bởi quản trị viên {domain}.",
"link_preview.author": "Bởi {name}",
"link_preview.more_from_author": "Thêm từ {name}",
"link_preview.shares": "{count, plural, other {{counter} lượt chia sẻ}}",
@@ -443,7 +457,7 @@
"lists.subheading": "Danh sách của bạn",
"load_pending": "{count, plural, one {# tút mới} other {# tút mới}}",
"loading_indicator.label": "Đang tải…",
- "media_gallery.toggle_visible": "{number, plural, other {Ẩn hình ảnh}}",
+ "media_gallery.hide": "Ẩn",
"moved_to_account_banner.text": "Tài khoản {disabledAccount} của bạn hiện không khả dụng vì bạn đã chuyển sang {movedToAccount}.",
"mute_modal.hide_from_notifications": "Ẩn thông báo",
"mute_modal.hide_options": "Tùy chọn ẩn",
@@ -455,22 +469,24 @@
"mute_modal.you_wont_see_mentions": "Bạn sẽ không nhìn thấy tút có nhắc đến họ.",
"mute_modal.you_wont_see_posts": "Bạn sẽ không nhìn thấy tút của họ.",
"navigation_bar.about": "Giới thiệu",
+ "navigation_bar.administration": "Quản trị",
"navigation_bar.advanced_interface": "Dùng bố cục nhiều cột",
"navigation_bar.blocks": "Người đã chặn",
- "navigation_bar.bookmarks": "Đã lưu",
+ "navigation_bar.bookmarks": "Tút lưu",
"navigation_bar.community_timeline": "Cộng đồng",
"navigation_bar.compose": "Soạn tút mới",
"navigation_bar.direct": "Nhắn riêng",
"navigation_bar.discover": "Khám phá",
"navigation_bar.domain_blocks": "Máy chủ đã ẩn",
"navigation_bar.explore": "Xu hướng",
- "navigation_bar.favourites": "Lượt thích",
- "navigation_bar.filters": "Bộ lọc từ ngữ",
+ "navigation_bar.favourites": "Tút thích",
+ "navigation_bar.filters": "Từ khóa đã lọc",
"navigation_bar.follow_requests": "Yêu cầu theo dõi",
"navigation_bar.followed_tags": "Hashtag theo dõi",
"navigation_bar.follows_and_followers": "Quan hệ",
"navigation_bar.lists": "Danh sách",
"navigation_bar.logout": "Đăng xuất",
+ "navigation_bar.moderation": "Kiểm duyệt",
"navigation_bar.mutes": "Người đã ẩn",
"navigation_bar.opened_in_classic_interface": "Tút, tài khoản và các trang cụ thể khác được mở theo mặc định trong giao diện web cổ điển.",
"navigation_bar.personal": "Cá nhân",
@@ -517,7 +533,7 @@
"notification.relationships_severance_event.learn_more": "Tìm hiểu thêm",
"notification.relationships_severance_event.user_domain_block": "Bạn đã chặn {target}, xóa {followersCount} người theo dõi bạn và {followingCount, plural, other {# người}} theo dõi bạn.",
"notification.status": "{name} đăng tút mới",
- "notification.update": "{name} đã sửa tút",
+ "notification.update": "{name} cập nhật tút",
"notification_requests.accept": "Chấp nhận",
"notification_requests.accept_multiple": "{count, plural, other {Duyệt # yêu cầu…}}",
"notification_requests.confirm_accept_multiple.button": "{count, plural, other {Yêu cầu cần duyệt}}",
@@ -536,14 +552,13 @@
"notification_requests.minimize_banner": "Tinh giản banner lọc thông báo",
"notification_requests.notifications_from": "Thông báo từ {name}",
"notification_requests.title": "Thông báo đã lọc",
+ "notification_requests.view": "Hiện thông báo",
"notifications.clear": "Xóa hết thông báo",
- "notifications.clear_confirmation": "Bạn thật sự muốn xóa vĩnh viễn tất cả thông báo của mình?",
- "notifications.clear_title": "Xóa hết thông báo?",
+ "notifications.clear_confirmation": "Bạn có chắc muốn xóa vĩnh viễn tất cả thông báo của mình?",
+ "notifications.clear_title": "Xóa toàn bộ thông báo",
"notifications.column_settings.admin.report": "Báo cáo mới:",
"notifications.column_settings.admin.sign_up": "Người mới tham gia:",
"notifications.column_settings.alert": "Báo trên máy tính",
- "notifications.column_settings.beta.category": "Tính năng thử nghiệm",
- "notifications.column_settings.beta.grouping": "Gộp thông báo theo loại",
"notifications.column_settings.favourite": "Lượt thích:",
"notifications.column_settings.filter_bar.advanced": "Toàn bộ",
"notifications.column_settings.filter_bar.category": "Thanh lọc nhanh",
@@ -572,6 +587,12 @@
"notifications.permission_denied": "Trình duyệt không cho phép hiển thị thông báo trên màn hình.",
"notifications.permission_denied_alert": "Không thể bật thông báo trên màn hình bởi vì trình duyệt đã cấm trước đó",
"notifications.permission_required": "Không hiện thông báo trên màn hình bởi vì chưa cho phép.",
+ "notifications.policy.accept": "Có",
+ "notifications.policy.accept_hint": "Hiện trong thông báo",
+ "notifications.policy.drop": "Không",
+ "notifications.policy.drop_hint": "Loại bỏ vĩnh viễn",
+ "notifications.policy.filter": "Lọc",
+ "notifications.policy.filter_hint": "Cho vào mục thông báo bị lọc",
"notifications.policy.filter_limited_accounts_hint": "Chỉ dành cho kiểm duyệt viên",
"notifications.policy.filter_limited_accounts_title": "Kiểm duyệt tài khoản",
"notifications.policy.filter_new_accounts.hint": "Đã tạo trong vòng {days, plural, other {# ngày}}",
@@ -580,8 +601,9 @@
"notifications.policy.filter_not_followers_title": "Những người không theo dõi bạn",
"notifications.policy.filter_not_following_hint": "Cho tới khi bạn duyệt họ",
"notifications.policy.filter_not_following_title": "Những người bạn không theo dõi",
- "notifications.policy.filter_private_mentions_hint": "Được lọc trừ khi nó trả lời lượt nhắc từ bạn hoặc nếu bạn theo dõi người gửi",
- "notifications.policy.filter_private_mentions_title": "Lượt nhắc riêng tư không được yêu cầu",
+ "notifications.policy.filter_private_mentions_hint": "Trừ khi nó trả lời lượt nhắc từ bạn hoặc nếu bạn có theo dõi người gửi",
+ "notifications.policy.filter_private_mentions_title": "Lượt nhắn riêng không mong muốn",
+ "notifications.policy.title": "Quản lý thông báo từ…",
"notifications_permission_banner.enable": "Cho phép thông báo trên màn hình",
"notifications_permission_banner.how_to_control": "Hãy bật thông báo trên màn hình để không bỏ lỡ những thông báo từ Mastodon. Một khi đã bật, bạn có thể lựa chọn từng loại thông báo khác nhau thông qua {icon} nút bên dưới.",
"notifications_permission_banner.title": "Không bỏ lỡ điều thú vị nào",
@@ -599,7 +621,7 @@
"onboarding.profile.display_name_hint": "Tên đầy đủ hoặc biệt danh đều được…",
"onboarding.profile.lead": "Bạn có thể cài đặt lại trong phần cài đặt, nơi thậm chí còn có nhiều tùy chọn hơn.",
"onboarding.profile.note": "Giới thiệu",
- "onboarding.profile.note_hint": "Bạn có thể @nhắnriêng ai đó hoặc #hashtags…",
+ "onboarding.profile.note_hint": "Bạn có thể @aiđó hoặc #hashtags…",
"onboarding.profile.save_and_continue": "Lưu và tiếp tục",
"onboarding.profile.title": "Thiết lập hồ sơ",
"onboarding.profile.upload_avatar": "Tải lên ảnh đại diện",
@@ -635,7 +657,7 @@
"poll.voted": "Bạn đã bình chọn rồi",
"poll.votes": "{votes, plural, other {# lượt bình chọn}}",
"poll_button.add_poll": "Tạo bình chọn",
- "poll_button.remove_poll": "Hủy cuộc bình chọn",
+ "poll_button.remove_poll": "Xóa bình chọn",
"privacy.change": "Chọn kiểu tút",
"privacy.direct.long": "Những người được nhắc trong tút",
"privacy.direct.short": "Người cụ thể",
@@ -691,7 +713,7 @@
"report.reasons.other": "Một lý do khác",
"report.reasons.other_description": "Vấn đề không nằm trong những mục trên",
"report.reasons.spam": "Đây là spam",
- "report.reasons.spam_description": "Liên kết độc hại, tạo tương tác giả hoặc trả lời lặp đi lặp lại",
+ "report.reasons.spam_description": "Liên kết độc hại, giả tương tác hoặc trả lời lặp đi lặp lại",
"report.reasons.violation": "Vi phạm nội quy máy chủ",
"report.reasons.violation_description": "Bạn nhận thấy nó vi phạm nội quy máy chủ",
"report.rules.subtitle": "Chọn tất cả những gì phù hợp",
@@ -716,7 +738,7 @@
"report_notification.categories.violation": "Vi phạm nội quy",
"report_notification.categories.violation_sentence": "vi phạm nội quy",
"report_notification.open": "Mở báo cáo",
- "search.no_recent_searches": "Không có tìm kiếm gần đây",
+ "search.no_recent_searches": "Gần đây chưa tìm gì",
"search.placeholder": "Tìm kiếm",
"search.quick_action.account_search": "Người có tên {x}",
"search.quick_action.go_to_account": "Xem trang {x}",
@@ -726,12 +748,12 @@
"search.search_or_paste": "Tìm kiếm hoặc nhập URL",
"search_popout.full_text_search_disabled_message": "Không khả dụng trên {domain}.",
"search_popout.full_text_search_logged_out_message": "Cần đăng nhập trước.",
- "search_popout.language_code": "Mã ngôn ngữ ISO",
- "search_popout.options": "Tùy chọn tìm kiếm",
+ "search_popout.language_code": "mã ngôn ngữ ISO",
+ "search_popout.options": "Tìm nâng cao",
"search_popout.quick_actions": "Thao tác nhanh",
- "search_popout.recent": "Tìm kiếm gần đây",
+ "search_popout.recent": "Bạn đã tìm",
"search_popout.specific_date": "ngày cụ thể",
- "search_popout.user": "mọi người",
+ "search_popout.user": "địa chỉ Mastodon",
"search_results.accounts": "Mọi người",
"search_results.all": "Toàn bộ",
"search_results.hashtags": "Hashtag",
@@ -756,6 +778,7 @@
"status.bookmark": "Lưu",
"status.cancel_reblog_private": "Hủy đăng lại",
"status.cannot_reblog": "Không thể đăng lại tút này",
+ "status.continued_thread": "Tiếp tục trong chủ đề",
"status.copy": "Sao chép URL",
"status.delete": "Xóa",
"status.detailed_status": "Xem chi tiết thêm",
@@ -766,7 +789,7 @@
"status.edited_x_times": "Đã sửa {count, plural, other {{count} lần}}",
"status.embed": "Nhúng",
"status.favourite": "Thích",
- "status.favourites": "{count, plural, other {lượt thích}}",
+ "status.favourites": "{count, plural, other {thích}}",
"status.filter": "Lọc tút này",
"status.history.created": "{name} đăng {date}",
"status.history.edited": "{name} đã sửa {date}",
@@ -789,6 +812,7 @@
"status.reblogs.empty": "Tút này chưa có ai đăng lại. Nếu có, nó sẽ hiển thị ở đây.",
"status.redraft": "Xóa và viết lại",
"status.remove_bookmark": "Bỏ lưu",
+ "status.replied_in_thread": "Trả lời trong chủ đề",
"status.replied_to": "Trả lời {name}",
"status.reply": "Trả lời",
"status.replyAll": "Trả lời",
diff --git a/app/javascript/mastodon/locales/zgh.json b/app/javascript/mastodon/locales/zgh.json
index d9367520e8..2fe63fe83c 100644
--- a/app/javascript/mastodon/locales/zgh.json
+++ b/app/javascript/mastodon/locales/zgh.json
@@ -118,7 +118,6 @@
"lists.replies_policy.title": "ⵙⴽⵏ ⵜⵉⵔⴰⵔⵉⵏ ⵉ:",
"lists.subheading": "ⵜⵉⵍⴳⴰⵎⵉⵏ ⵏⵏⴽ",
"load_pending": "{count, plural, one {# ⵓⴼⵔⴷⵉⵙ ⴰⵎⴰⵢⵏⵓ} other {# ⵉⴼⵔⴷⴰⵙ ⵉⵎⴰⵢⵏⵓⵜⵏ}}",
- "media_gallery.toggle_visible": "ⴼⴼⵔ {number, plural, one {ⵜⴰⵡⵍⴰⴼⵜ} other {ⵜⵉⵡⵍⴰⴼⵉⵏ}}",
"navigation_bar.compose": "Compose new toot",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.follow_requests": "ⵜⵓⵜⵔⴰⵡⵉⵏ ⵏ ⵓⴹⴼⴰⵕ",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index 44608c6071..a7cd089948 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -94,9 +94,11 @@
"block_modal.they_cant_mention": "他们不能提及或关注你。",
"block_modal.they_cant_see_posts": "他们看不到你的嘟文,你也看不到他们的嘟文。",
"block_modal.they_will_know": "他们将能看到他们被屏蔽。",
- "block_modal.title": "屏蔽该用户?",
- "block_modal.you_wont_see_mentions": "你将无法看到提及他们的嘟文。",
+ "block_modal.title": "是否屏蔽该用户?",
+ "block_modal.you_wont_see_mentions": "你将不会看到提及他们的嘟文。",
"boost_modal.combo": "下次按住 {combo} 即可跳过此提示",
+ "boost_modal.reblog": "是否转嘟?",
+ "boost_modal.undo_reblog": "是否取消转嘟?",
"bundle_column_error.copy_stacktrace": "复制错误报告",
"bundle_column_error.error.body": "请求的页面无法渲染,可能是代码出现错误或浏览器存在兼容性问题。",
"bundle_column_error.error.title": "糟糕!",
@@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "取消关注",
"confirmations.unfollow.message": "你确定要取消关注 {name} 吗?",
"confirmations.unfollow.title": "是否取消关注用户?",
+ "content_warning.hide": "隐藏嘟文",
+ "content_warning.show": "仍然显示",
"conversation.delete": "删除对话",
"conversation.mark_as_read": "标记为已读",
"conversation.open": "查看对话",
@@ -299,6 +303,7 @@
"filter_modal.select_filter.subtitle": "使用一个已存在类别,或创建一个新类别",
"filter_modal.select_filter.title": "过滤此嘟文",
"filter_modal.title.status": "过滤一条嘟文",
+ "filter_warning.matches_filter": "命中过滤规则 “{title}”",
"filtered_notifications_banner.pending_requests": "来自你可能认识的 {count, plural, =0 {0 个人} other {# 个人}}",
"filtered_notifications_banner.title": "通知(已过滤)",
"firehose.all": "全部",
@@ -312,10 +317,10 @@
"follow_suggestions.featured_longer": "由 {domain} 管理团队精选",
"follow_suggestions.friends_of_friends_longer": "在你关注的人中很受欢迎",
"follow_suggestions.hints.featured": "该用户已被 {domain} 管理团队精选。",
- "follow_suggestions.hints.friends_of_friends": "该用户在您关注的人中很受欢迎。",
+ "follow_suggestions.hints.friends_of_friends": "该用户在你关注的人中很受欢迎。",
"follow_suggestions.hints.most_followed": "该用户是 {domain} 上关注度最高的用户之一。",
"follow_suggestions.hints.most_interactions": "该用户最近在 {domain} 上获得了很多关注。",
- "follow_suggestions.hints.similar_to_recently_followed": "该用户与您最近关注的用户类似。",
+ "follow_suggestions.hints.similar_to_recently_followed": "该用户与你最近关注的用户类似。",
"follow_suggestions.personalized_suggestion": "个性化建议",
"follow_suggestions.popular_suggestion": "热门建议",
"follow_suggestions.popular_suggestion_longer": "在 {domain} 上很受欢迎",
@@ -359,7 +364,7 @@
"home.column_settings.show_reblogs": "显示转嘟",
"home.column_settings.show_replies": "显示回复",
"home.hide_announcements": "隐藏公告",
- "home.pending_critical_update.body": "请尽快更新您的 Mastodon 服务器!",
+ "home.pending_critical_update.body": "请尽快更新你的 Mastodon 服务器!",
"home.pending_critical_update.link": "查看更新",
"home.pending_critical_update.title": "紧急安全更新可用!",
"home.show_announcements": "显示公告",
@@ -427,10 +432,10 @@
"keyboard_shortcuts.unfocus": "取消输入/搜索",
"keyboard_shortcuts.up": "在列表中让光标上移",
"lightbox.close": "关闭",
- "lightbox.compress": "返回图片全览",
- "lightbox.expand": "放大查看图片",
"lightbox.next": "下一个",
"lightbox.previous": "上一个",
+ "lightbox.zoom_in": "缩放为实际大小",
+ "lightbox.zoom_out": "缩放到适合窗口大小",
"limited_account_hint.action": "仍要显示个人资料",
"limited_account_hint.title": "此账号资料已被 {domain} 管理员隐藏。",
"link_preview.author": "由 {name}",
@@ -452,7 +457,7 @@
"lists.subheading": "你的列表",
"load_pending": "{count} 项",
"loading_indicator.label": "加载中…",
- "media_gallery.toggle_visible": "{number, plural, other {隐藏图像}}",
+ "media_gallery.hide": "隐藏",
"moved_to_account_banner.text": "您的账号 {disabledAccount} 已禁用,因为您已迁移到 {movedToAccount}。",
"mute_modal.hide_from_notifications": "从通知中隐藏",
"mute_modal.hide_options": "隐藏选项",
@@ -464,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "你看不到提及他们的嘟文。",
"mute_modal.you_wont_see_posts": "他们可以看到你的嘟文,但是你看不到他们的。",
"navigation_bar.about": "关于",
+ "navigation_bar.administration": "管理",
"navigation_bar.advanced_interface": "在高级网页界面中打开",
"navigation_bar.blocks": "已屏蔽的用户",
"navigation_bar.bookmarks": "书签",
@@ -480,6 +486,7 @@
"navigation_bar.follows_and_followers": "关注和粉丝",
"navigation_bar.lists": "列表",
"navigation_bar.logout": "退出登录",
+ "navigation_bar.moderation": "运营",
"navigation_bar.mutes": "已隐藏的用户",
"navigation_bar.opened_in_classic_interface": "嘟文、账户和其他特定页面默认在经典网页界面中打开。",
"navigation_bar.personal": "个人",
@@ -552,8 +559,6 @@
"notifications.column_settings.admin.report": "新举报:",
"notifications.column_settings.admin.sign_up": "新注册:",
"notifications.column_settings.alert": "桌面通知",
- "notifications.column_settings.beta.category": "实验性功能",
- "notifications.column_settings.beta.grouping": "通知分组",
"notifications.column_settings.favourite": "喜欢:",
"notifications.column_settings.filter_bar.advanced": "显示所有类别",
"notifications.column_settings.filter_bar.category": "快速筛选栏",
@@ -611,12 +616,12 @@
"onboarding.follows.lead": "你管理你自己的家庭饲料。你关注的人越多,它将越活跃和有趣。 这些配置文件可能是一个很好的起点——你可以随时取消关注它们!",
"onboarding.follows.title": "定制您的主页动态",
"onboarding.profile.discoverable": "让我的资料卡可被他人发现",
- "onboarding.profile.discoverable_hint": "当您选择在 Mastodon 上启用发现功能时,你的嘟文可能会出现在搜索结果和热门中,你的账户可能会被推荐给与你兴趣相似的人。",
+ "onboarding.profile.discoverable_hint": "当你选择在 Mastodon 上启用发现功能时,你的嘟文可能会出现在搜索结果和热门中,你的账户可能会被推荐给与你兴趣相似的人。",
"onboarding.profile.display_name": "昵称",
- "onboarding.profile.display_name_hint": "您的全名或昵称…",
- "onboarding.profile.lead": "您可以稍后在设置中完成此操作,设置中有更多的自定义选项。",
+ "onboarding.profile.display_name_hint": "你的全名或昵称…",
+ "onboarding.profile.lead": "你可以稍后在设置中完成此操作,设置中有更多的自定义选项。",
"onboarding.profile.note": "简介",
- "onboarding.profile.note_hint": "您可以提及 @其他人 或 #标签…",
+ "onboarding.profile.note_hint": "你可以提及 @其他人 或 #标签…",
"onboarding.profile.save_and_continue": "保存并继续",
"onboarding.profile.title": "设置个人资料",
"onboarding.profile.upload_avatar": "上传头像",
@@ -625,7 +630,7 @@
"onboarding.share.message": "我是来自 #Mastodon 的 {username}!请在 {url} 关注我。",
"onboarding.share.next_steps": "可能的下一步:",
"onboarding.share.title": "分享你的个人资料",
- "onboarding.start.lead": "您新的 Mastodon 帐户已准备好。下面是如何最大限度地利用它:",
+ "onboarding.start.lead": "你的新 Mastodon 帐户已准备好。下面是如何最大限度地利用它:",
"onboarding.start.skip": "想要在前面跳过吗?",
"onboarding.start.title": "你已经成功了!",
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
@@ -637,7 +642,7 @@
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!",
"onboarding.steps.share_profile.title": "分享你的个人资料",
"onboarding.tips.2fa": "
你知道吗?你可以在账户设置中配置双因素认证来保护账户安全。可以使用你选择的任何 TOTP 应用,无需电话号码!",
- "onboarding.tips.accounts_from_other_servers": "
您知道吗? 既然Mastodon是去中心化的,您所看到的一些账户将被托管在您以外的服务器上。 但你可以无缝地与他们交互!他们的服务器在他们的用户名的后半部分!",
+ "onboarding.tips.accounts_from_other_servers": "
你知道吗? 既然Mastodon是去中心化的,你所看到的一些账户将被托管在你以外的服务器上。 但你可以无缝地与他们交互!他们的服务器在他们的用户名的后半部分!",
"onboarding.tips.migration": "
您知道吗? 如果你觉得你喜欢 {domain} 不是您未来的一个伟大的服务器选择。 您可以移动到另一个 Mastodon 服务器而不失去您的关注者。 您甚至可以主持您自己的服务器!",
"onboarding.tips.verification": "
您知道吗? 您可以通过在自己的网站上放置一个链接到您的 Mastodon 个人资料并将网站添加到您的个人资料来验证您的帐户。 无需收费或文书工作!",
"password_confirmation.exceeds_maxlength": "密码确认超过最大密码长度",
@@ -773,6 +778,7 @@
"status.bookmark": "添加到书签",
"status.cancel_reblog_private": "取消转贴",
"status.cannot_reblog": "这条嘟文不允许被转嘟",
+ "status.continued_thread": "继续线程",
"status.copy": "复制嘟文链接",
"status.delete": "删除",
"status.detailed_status": "详细的对话视图",
@@ -781,7 +787,7 @@
"status.edit": "编辑",
"status.edited": "最近编辑于 {date}",
"status.edited_x_times": "共编辑 {count, plural, one {{count} 次} other {{count} 次}}",
- "status.embed": "嵌入",
+ "status.embed": "获取嵌入代码",
"status.favourite": "喜欢",
"status.favourites": "{count, plural, other {次喜欢}}",
"status.filter": "过滤此嘟文",
@@ -806,6 +812,7 @@
"status.reblogs.empty": "没有人转嘟过此条嘟文。如果有人转嘟了,就会显示在这里。",
"status.redraft": "删除并重新编辑",
"status.remove_bookmark": "移除书签",
+ "status.replied_in_thread": "已在线程中回复",
"status.replied_to": "回复给 {name}",
"status.reply": "回复",
"status.replyAll": "回复所有人",
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index 8543090b9a..22f51a8413 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -398,8 +398,6 @@
"keyboard_shortcuts.unfocus": "把標示移離文字輸入和搜索",
"keyboard_shortcuts.up": "在列表往上移動",
"lightbox.close": "關閉",
- "lightbox.compress": "縮小檢視",
- "lightbox.expand": "擴大檢視",
"lightbox.next": "下一頁",
"lightbox.previous": "上一頁",
"limited_account_hint.action": "一律顯示個人檔案",
@@ -421,7 +419,6 @@
"lists.subheading": "列表",
"load_pending": "{count, plural, other {# 個新項目}}",
"loading_indicator.label": "載入中…",
- "media_gallery.toggle_visible": "隱藏圖片",
"moved_to_account_banner.text": "您的帳號 {disabledAccount} 目前已停用,因為您已搬家至 {movedToAccount}。",
"mute_modal.hide_from_notifications": "隱藏通知",
"mute_modal.hide_options": "隱藏選項",
@@ -700,7 +697,6 @@
"status.edit": "編輯",
"status.edited": "最後編輯於 {date}",
"status.edited_x_times": "Edited {count, plural, one {{count} 次} other {{count} 次}}",
- "status.embed": "嵌入",
"status.favourite": "最愛",
"status.favourites": "{count, plural, one {則最愛} other {則最愛}}",
"status.filter": "篩選此帖文",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 107267b5e5..7f2caeaf4b 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -21,7 +21,7 @@
"account.blocked": "已封鎖",
"account.cancel_follow_request": "收回跟隨請求",
"account.copy": "複製個人檔案連結",
- "account.direct": "私訊 @{name}",
+ "account.direct": " @{name}",
"account.disable_notifications": "取消來自 @{name} 嘟文的通知",
"account.domain_blocked": "已封鎖網域",
"account.edit_profile": "編輯個人檔案",
@@ -97,6 +97,8 @@
"block_modal.title": "是否封鎖該使用者?",
"block_modal.you_wont_see_mentions": "您不會見到提及他們的嘟文。",
"boost_modal.combo": "下次您可以按 {combo} 跳過",
+ "boost_modal.reblog": "是否要轉嘟?",
+ "boost_modal.undo_reblog": "是否要取消轉嘟?",
"bundle_column_error.copy_stacktrace": "複製錯誤報告",
"bundle_column_error.error.body": "無法繪製請求的頁面。這可能是因為我們程式碼中的臭蟲或是瀏覽器的相容問題。",
"bundle_column_error.error.title": "糟糕!",
@@ -430,10 +432,10 @@
"keyboard_shortcuts.unfocus": "跳離文字撰寫區塊或搜尋框",
"keyboard_shortcuts.up": "向上移動",
"lightbox.close": "關閉",
- "lightbox.compress": "折疊圖片檢視框",
- "lightbox.expand": "展開圖片檢視框",
"lightbox.next": "下一步",
"lightbox.previous": "上一步",
+ "lightbox.zoom_in": "縮放至實際大小",
+ "lightbox.zoom_out": "縮放至合適大小",
"limited_account_hint.action": "一律顯示個人檔案",
"limited_account_hint.title": "此個人檔案已被 {domain} 的管理員隱藏。",
"link_preview.author": "來自 {name}",
@@ -455,7 +457,7 @@
"lists.subheading": "您的列表",
"load_pending": "{count, plural, one {# 個新項目} other {# 個新項目}}",
"loading_indicator.label": "正在載入...",
- "media_gallery.toggle_visible": "切換可見性",
+ "media_gallery.hide": "隱藏",
"moved_to_account_banner.text": "您的帳號 {disabledAccount} 目前已停用,因為您已搬家至 {movedToAccount}。",
"mute_modal.hide_from_notifications": "於推播通知中隱藏",
"mute_modal.hide_options": "隱藏選項",
@@ -467,6 +469,7 @@
"mute_modal.you_wont_see_mentions": "您不會見到提及他們的嘟文。",
"mute_modal.you_wont_see_posts": "他們仍可讀取您的嘟文,但您不會見到他們的。",
"navigation_bar.about": "關於",
+ "navigation_bar.administration": "管理介面",
"navigation_bar.advanced_interface": "以進階網頁介面開啟",
"navigation_bar.blocks": "已封鎖的使用者",
"navigation_bar.bookmarks": "書籤",
@@ -483,6 +486,7 @@
"navigation_bar.follows_and_followers": "跟隨中與跟隨者",
"navigation_bar.lists": "列表",
"navigation_bar.logout": "登出",
+ "navigation_bar.moderation": "站務",
"navigation_bar.mutes": "已靜音的使用者",
"navigation_bar.opened_in_classic_interface": "預設於經典網頁介面中開啟嘟文、帳號與其他特定頁面。",
"navigation_bar.personal": "個人",
@@ -555,8 +559,6 @@
"notifications.column_settings.admin.report": "新檢舉報告:",
"notifications.column_settings.admin.sign_up": "新註冊帳號:",
"notifications.column_settings.alert": "桌面通知",
- "notifications.column_settings.beta.category": "實驗性功能",
- "notifications.column_settings.beta.grouping": "分組通知",
"notifications.column_settings.favourite": "最愛:",
"notifications.column_settings.filter_bar.advanced": "顯示所有分類",
"notifications.column_settings.filter_bar.category": "快速過濾器",
@@ -776,6 +778,7 @@
"status.bookmark": "書籤",
"status.cancel_reblog_private": "取消轉嘟",
"status.cannot_reblog": "這則嘟文無法被轉嘟",
+ "status.continued_thread": "接續討論串",
"status.copy": "複製嘟文連結",
"status.delete": "刪除",
"status.detailed_status": "詳細的對話內容",
@@ -784,7 +787,7 @@
"status.edit": "編輯",
"status.edited": "上次編輯於 {date}",
"status.edited_x_times": "已編輯 {count, plural, one {{count} 次} other {{count} 次}}",
- "status.embed": "內嵌嘟文",
+ "status.embed": "取得嵌入程式碼",
"status.favourite": "最愛",
"status.favourites": "{count, plural, other {# 則最愛}}",
"status.filter": "過濾此嘟文",
@@ -809,6 +812,7 @@
"status.reblogs.empty": "還沒有人轉嘟過這則嘟文。當有人轉嘟時,它將於此顯示。",
"status.redraft": "刪除並重新編輯",
"status.remove_bookmark": "移除書籤",
+ "status.replied_in_thread": "於討論串中回覆",
"status.replied_to": "回覆 {name}",
"status.reply": "回覆",
"status.replyAll": "回覆討論串",
diff --git a/app/javascript/mastodon/models/notification_request.ts b/app/javascript/mastodon/models/notification_request.ts
new file mode 100644
index 0000000000..bd98d213d4
--- /dev/null
+++ b/app/javascript/mastodon/models/notification_request.ts
@@ -0,0 +1,19 @@
+import type { ApiNotificationRequestJSON } from 'mastodon/api_types/notifications';
+
+export interface NotificationRequest
+ extends Omit
{
+ account_id: string;
+ notifications_count: number;
+}
+
+export function createNotificationRequestFromJSON(
+ requestJSON: ApiNotificationRequestJSON,
+): NotificationRequest {
+ const { account, notifications_count, ...request } = requestJSON;
+
+ return {
+ account_id: account.id,
+ notifications_count: +notifications_count,
+ ...request,
+ };
+}
diff --git a/app/javascript/mastodon/permissions.ts b/app/javascript/mastodon/permissions.ts
index b583535c00..8f015610ea 100644
--- a/app/javascript/mastodon/permissions.ts
+++ b/app/javascript/mastodon/permissions.ts
@@ -1,4 +1,23 @@
export const PERMISSION_INVITE_USERS = 0x0000000000010000;
export const PERMISSION_MANAGE_USERS = 0x0000000000000400;
export const PERMISSION_MANAGE_FEDERATION = 0x0000000000000020;
+
export const PERMISSION_MANAGE_REPORTS = 0x0000000000000010;
+export const PERMISSION_VIEW_DASHBOARD = 0x0000000000000008;
+
+// These helpers don't quite align with the names/categories in UserRole,
+// but are likely "good enough" for the use cases at present.
+//
+// See: https://docs.joinmastodon.org/entities/Role/#permission-flags
+
+export function canViewAdminDashboard(permissions: number) {
+ return (
+ (permissions & PERMISSION_VIEW_DASHBOARD) === PERMISSION_VIEW_DASHBOARD
+ );
+}
+
+export function canManageReports(permissions: number) {
+ return (
+ (permissions & PERMISSION_MANAGE_REPORTS) === PERMISSION_MANAGE_REPORTS
+ );
+}
diff --git a/app/javascript/mastodon/reducers/accounts_map.js b/app/javascript/mastodon/reducers/accounts_map.js
index 9053dcc9c0..d1229169cc 100644
--- a/app/javascript/mastodon/reducers/accounts_map.js
+++ b/app/javascript/mastodon/reducers/accounts_map.js
@@ -4,11 +4,10 @@ import { ACCOUNT_LOOKUP_FAIL } from '../actions/accounts';
import { importAccounts } from '../actions/accounts_typed';
import { domain } from '../initial_state';
-export const normalizeForLookup = str => {
- str = str.toLowerCase();
- const trailingIndex = str.indexOf(`@${domain.toLowerCase()}`);
- return (trailingIndex > 0) ? str.slice(0, trailingIndex) : str;
-};
+const pattern = new RegExp(`@${domain}$`, 'gi');
+
+export const normalizeForLookup = str =>
+ str.toLowerCase().replace(pattern, '');
const initialState = ImmutableMap();
diff --git a/app/javascript/mastodon/reducers/notification_groups.ts b/app/javascript/mastodon/reducers/notification_groups.ts
index b3535d7b67..f3c83ccd8d 100644
--- a/app/javascript/mastodon/reducers/notification_groups.ts
+++ b/app/javascript/mastodon/reducers/notification_groups.ts
@@ -248,8 +248,9 @@ function processNewNotification(
}
function trimNotifications(state: NotificationGroupsState) {
- if (state.scrolledToTop) {
+ if (state.scrolledToTop && state.groups.length > NOTIFICATIONS_TRIM_LIMIT) {
state.groups.splice(NOTIFICATIONS_TRIM_LIMIT);
+ ensureTrailingGap(state.groups);
}
}
@@ -400,6 +401,28 @@ function ensureLeadingGap(
}
}
+// Ensure the groups list ends with a gap suitable for loading more, mutating it to append one if needed
+function ensureTrailingGap(
+ groups: NotificationGroupsState['groups'],
+): NotificationGap {
+ const groupOrGap = groups.at(-1);
+
+ if (groupOrGap?.type === 'gap') {
+ // We're expecting older notifications, so discard sinceId if it's set
+ groupOrGap.sinceId = undefined;
+
+ return groupOrGap;
+ } else {
+ const gap: NotificationGap = {
+ type: 'gap',
+ maxId: groupOrGap?.page_min_id,
+ };
+
+ groups.push(gap);
+ return gap;
+ }
+}
+
export const notificationGroupsReducer = createReducer(
initialState,
(builder) => {
diff --git a/app/javascript/mastodon/reducers/notification_policy.ts b/app/javascript/mastodon/reducers/notification_policy.ts
index ed912dde5d..a883f9c1ee 100644
--- a/app/javascript/mastodon/reducers/notification_policy.ts
+++ b/app/javascript/mastodon/reducers/notification_policy.ts
@@ -2,7 +2,7 @@ import { createReducer, isAnyOf } from '@reduxjs/toolkit';
import {
fetchNotificationPolicy,
- decreasePendingNotificationsCount,
+ decreasePendingRequestsCount,
updateNotificationsPolicy,
} from 'mastodon/actions/notification_policies';
import type { NotificationPolicy } from 'mastodon/models/notification_policy';
@@ -10,10 +10,9 @@ import type { NotificationPolicy } from 'mastodon/models/notification_policy';
export const notificationPolicyReducer =
createReducer(null, (builder) => {
builder
- .addCase(decreasePendingNotificationsCount, (state, action) => {
+ .addCase(decreasePendingRequestsCount, (state, action) => {
if (state) {
- state.summary.pending_notifications_count -= action.payload;
- state.summary.pending_requests_count -= 1;
+ state.summary.pending_requests_count -= action.payload;
}
})
.addMatcher(
diff --git a/app/javascript/mastodon/reducers/notification_requests.js b/app/javascript/mastodon/reducers/notification_requests.js
deleted file mode 100644
index f73c641965..0000000000
--- a/app/javascript/mastodon/reducers/notification_requests.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
-
-import { blockAccountSuccess, muteAccountSuccess } from 'mastodon/actions/accounts';
-import {
- NOTIFICATION_REQUESTS_EXPAND_REQUEST,
- NOTIFICATION_REQUESTS_EXPAND_SUCCESS,
- NOTIFICATION_REQUESTS_EXPAND_FAIL,
- NOTIFICATION_REQUESTS_FETCH_REQUEST,
- NOTIFICATION_REQUESTS_FETCH_SUCCESS,
- NOTIFICATION_REQUESTS_FETCH_FAIL,
- NOTIFICATION_REQUEST_FETCH_REQUEST,
- NOTIFICATION_REQUEST_FETCH_SUCCESS,
- NOTIFICATION_REQUEST_FETCH_FAIL,
- NOTIFICATION_REQUEST_ACCEPT_REQUEST,
- NOTIFICATION_REQUEST_DISMISS_REQUEST,
- NOTIFICATION_REQUESTS_ACCEPT_REQUEST,
- NOTIFICATION_REQUESTS_DISMISS_REQUEST,
- NOTIFICATIONS_FOR_REQUEST_FETCH_REQUEST,
- NOTIFICATIONS_FOR_REQUEST_FETCH_SUCCESS,
- NOTIFICATIONS_FOR_REQUEST_FETCH_FAIL,
- NOTIFICATIONS_FOR_REQUEST_EXPAND_REQUEST,
- NOTIFICATIONS_FOR_REQUEST_EXPAND_SUCCESS,
- NOTIFICATIONS_FOR_REQUEST_EXPAND_FAIL,
-} from 'mastodon/actions/notifications';
-
-import { notificationToMap } from './notifications';
-
-const initialState = ImmutableMap({
- items: ImmutableList(),
- isLoading: false,
- next: null,
- current: ImmutableMap({
- isLoading: false,
- item: null,
- removed: false,
- notifications: ImmutableMap({
- items: ImmutableList(),
- isLoading: false,
- next: null,
- }),
- }),
-});
-
-const normalizeRequest = request => fromJS({
- ...request,
- account: request.account.id,
-});
-
-const removeRequest = (state, id) => {
- if (state.getIn(['current', 'item', 'id']) === id) {
- state = state.setIn(['current', 'removed'], true);
- }
-
- return state.update('items', list => list.filterNot(item => item.get('id') === id));
-};
-
-const removeRequestByAccount = (state, account_id) => {
- if (state.getIn(['current', 'item', 'account']) === account_id) {
- state = state.setIn(['current', 'removed'], true);
- }
-
- return state.update('items', list => list.filterNot(item => item.get('account') === account_id));
-};
-
-export const notificationRequestsReducer = (state = initialState, action) => {
- switch(action.type) {
- case NOTIFICATION_REQUESTS_FETCH_SUCCESS:
- return state.withMutations(map => {
- map.update('items', list => ImmutableList(action.requests.map(normalizeRequest)).concat(list));
- map.set('isLoading', false);
- map.update('next', next => next ?? action.next);
- });
- case NOTIFICATION_REQUESTS_EXPAND_SUCCESS:
- return state.withMutations(map => {
- map.update('items', list => list.concat(ImmutableList(action.requests.map(normalizeRequest))));
- map.set('isLoading', false);
- map.set('next', action.next);
- });
- case NOTIFICATION_REQUESTS_EXPAND_REQUEST:
- case NOTIFICATION_REQUESTS_FETCH_REQUEST:
- return state.set('isLoading', true);
- case NOTIFICATION_REQUESTS_EXPAND_FAIL:
- case NOTIFICATION_REQUESTS_FETCH_FAIL:
- return state.set('isLoading', false);
- case NOTIFICATION_REQUEST_ACCEPT_REQUEST:
- case NOTIFICATION_REQUEST_DISMISS_REQUEST:
- return removeRequest(state, action.id);
- case NOTIFICATION_REQUESTS_ACCEPT_REQUEST:
- case NOTIFICATION_REQUESTS_DISMISS_REQUEST:
- return action.ids.reduce((state, id) => removeRequest(state, id), state);
- case blockAccountSuccess.type:
- return removeRequestByAccount(state, action.payload.relationship.id);
- case muteAccountSuccess.type:
- return action.payload.relationship.muting_notifications ? removeRequestByAccount(state, action.payload.relationship.id) : state;
- case NOTIFICATION_REQUEST_FETCH_REQUEST:
- return state.set('current', initialState.get('current').set('isLoading', true));
- case NOTIFICATION_REQUEST_FETCH_SUCCESS:
- return state.update('current', map => map.set('isLoading', false).set('item', normalizeRequest(action.request)));
- case NOTIFICATION_REQUEST_FETCH_FAIL:
- return state.update('current', map => map.set('isLoading', false));
- case NOTIFICATIONS_FOR_REQUEST_FETCH_REQUEST:
- case NOTIFICATIONS_FOR_REQUEST_EXPAND_REQUEST:
- return state.setIn(['current', 'notifications', 'isLoading'], true);
- case NOTIFICATIONS_FOR_REQUEST_FETCH_SUCCESS:
- return state.updateIn(['current', 'notifications'], map => map.set('isLoading', false).update('items', list => ImmutableList(action.notifications.map(notificationToMap)).concat(list)).update('next', next => next ?? action.next));
- case NOTIFICATIONS_FOR_REQUEST_EXPAND_SUCCESS:
- return state.updateIn(['current', 'notifications'], map => map.set('isLoading', false).update('items', list => list.concat(ImmutableList(action.notifications.map(notificationToMap)))).set('next', action.next));
- case NOTIFICATIONS_FOR_REQUEST_FETCH_FAIL:
- case NOTIFICATIONS_FOR_REQUEST_EXPAND_FAIL:
- return state.setIn(['current', 'notifications', 'isLoading'], false);
- default:
- return state;
- }
-};
diff --git a/app/javascript/mastodon/reducers/notification_requests.ts b/app/javascript/mastodon/reducers/notification_requests.ts
new file mode 100644
index 0000000000..1ca92d9990
--- /dev/null
+++ b/app/javascript/mastodon/reducers/notification_requests.ts
@@ -0,0 +1,182 @@
+import { createReducer, isAnyOf } from '@reduxjs/toolkit';
+
+import {
+ blockAccountSuccess,
+ muteAccountSuccess,
+} from 'mastodon/actions/accounts';
+import {
+ fetchNotificationRequests,
+ expandNotificationRequests,
+ fetchNotificationRequest,
+ fetchNotificationsForRequest,
+ expandNotificationsForRequest,
+ acceptNotificationRequest,
+ dismissNotificationRequest,
+ acceptNotificationRequests,
+ dismissNotificationRequests,
+} from 'mastodon/actions/notification_requests';
+import type { NotificationRequest } from 'mastodon/models/notification_request';
+import { createNotificationRequestFromJSON } from 'mastodon/models/notification_request';
+
+import { notificationToMap } from './notifications';
+
+interface NotificationsListState {
+ items: unknown[]; // TODO
+ isLoading: boolean;
+ next: string | null;
+}
+
+interface CurrentNotificationRequestState {
+ item: NotificationRequest | null;
+ isLoading: boolean;
+ removed: boolean;
+ notifications: NotificationsListState;
+}
+
+interface NotificationRequestsState {
+ items: NotificationRequest[];
+ isLoading: boolean;
+ next: string | null;
+ current: CurrentNotificationRequestState;
+}
+
+const initialState: NotificationRequestsState = {
+ items: [],
+ isLoading: false,
+ next: null,
+ current: {
+ item: null,
+ isLoading: false,
+ removed: false,
+ notifications: {
+ isLoading: false,
+ items: [],
+ next: null,
+ },
+ },
+};
+
+const removeRequest = (state: NotificationRequestsState, id: string) => {
+ if (state.current.item?.id === id) {
+ state.current.removed = true;
+ }
+
+ state.items = state.items.filter((item) => item.id !== id);
+};
+
+const removeRequestByAccount = (
+ state: NotificationRequestsState,
+ account_id: string,
+) => {
+ if (state.current.item?.account_id === account_id) {
+ state.current.removed = true;
+ }
+
+ state.items = state.items.filter((item) => item.account_id !== account_id);
+};
+
+export const notificationRequestsReducer =
+ createReducer(initialState, (builder) => {
+ builder
+ .addCase(fetchNotificationRequests.fulfilled, (state, action) => {
+ state.items = action.payload.requests
+ .map(createNotificationRequestFromJSON)
+ .concat(state.items);
+ state.isLoading = false;
+ state.next ??= action.payload.next ?? null;
+ })
+ .addCase(expandNotificationRequests.fulfilled, (state, action) => {
+ state.items = state.items.concat(
+ action.payload.requests.map(createNotificationRequestFromJSON),
+ );
+ state.isLoading = false;
+ state.next = action.payload.next ?? null;
+ })
+ .addCase(blockAccountSuccess, (state, action) => {
+ removeRequestByAccount(state, action.payload.relationship.id);
+ })
+ .addCase(muteAccountSuccess, (state, action) => {
+ if (action.payload.relationship.muting_notifications)
+ removeRequestByAccount(state, action.payload.relationship.id);
+ })
+ .addCase(fetchNotificationRequest.pending, (state) => {
+ state.current = { ...initialState.current, isLoading: true };
+ })
+ .addCase(fetchNotificationRequest.rejected, (state) => {
+ state.current.isLoading = false;
+ })
+ .addCase(fetchNotificationRequest.fulfilled, (state, action) => {
+ state.current.isLoading = false;
+ state.current.item = createNotificationRequestFromJSON(action.payload);
+ })
+ .addCase(fetchNotificationsForRequest.fulfilled, (state, action) => {
+ state.current.notifications.isLoading = false;
+ state.current.notifications.items.unshift(
+ ...action.payload.notifications.map(notificationToMap),
+ );
+ state.current.notifications.next ??= action.payload.next ?? null;
+ })
+ .addCase(expandNotificationsForRequest.fulfilled, (state, action) => {
+ state.current.notifications.isLoading = false;
+ state.current.notifications.items.push(
+ ...action.payload.notifications.map(notificationToMap),
+ );
+ state.current.notifications.next = action.payload.next ?? null;
+ })
+ .addMatcher(
+ isAnyOf(
+ fetchNotificationRequests.pending,
+ expandNotificationRequests.pending,
+ ),
+ (state) => {
+ state.isLoading = true;
+ },
+ )
+ .addMatcher(
+ isAnyOf(
+ fetchNotificationRequests.rejected,
+ expandNotificationRequests.rejected,
+ ),
+ (state) => {
+ state.isLoading = false;
+ },
+ )
+ .addMatcher(
+ isAnyOf(
+ acceptNotificationRequest.pending,
+ dismissNotificationRequest.pending,
+ ),
+ (state, action) => {
+ removeRequest(state, action.meta.arg.id);
+ },
+ )
+ .addMatcher(
+ isAnyOf(
+ acceptNotificationRequests.pending,
+ dismissNotificationRequests.pending,
+ ),
+ (state, action) => {
+ action.meta.arg.ids.forEach((id) => {
+ removeRequest(state, id);
+ });
+ },
+ )
+ .addMatcher(
+ isAnyOf(
+ fetchNotificationsForRequest.pending,
+ expandNotificationsForRequest.pending,
+ ),
+ (state) => {
+ state.current.notifications.isLoading = true;
+ },
+ )
+ .addMatcher(
+ isAnyOf(
+ fetchNotificationsForRequest.rejected,
+ expandNotificationsForRequest.rejected,
+ ),
+ (state) => {
+ state.current.notifications.isLoading = false;
+ },
+ );
+ });
diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js
index f7b61f7467..8944555eb9 100644
--- a/app/javascript/mastodon/reducers/settings.js
+++ b/app/javascript/mastodon/reducers/settings.js
@@ -1,8 +1,8 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { COLUMN_ADD, COLUMN_REMOVE, COLUMN_MOVE, COLUMN_PARAMS_CHANGE } from '../actions/columns';
+import { COMPOSE_LANGUAGE_CHANGE } from '../actions/compose';
import { EMOJI_USE } from '../actions/emojis';
-import { LANGUAGE_USE } from '../actions/languages';
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists';
import { NOTIFICATIONS_FILTER_SET } from '../actions/notifications';
import { SETTING_CHANGE, SETTING_SAVE } from '../actions/settings';
@@ -178,7 +178,7 @@ export default function settings(state = initialState, action) {
return changeColumnParams(state, action.uuid, action.path, action.value);
case EMOJI_USE:
return updateFrequentEmojis(state, action.emoji);
- case LANGUAGE_USE:
+ case COMPOSE_LANGUAGE_CHANGE:
return updateFrequentLanguages(state, action.language);
case SETTING_SAVE:
return state.set('saved', true);
diff --git a/app/javascript/mastodon/scroll.ts b/app/javascript/mastodon/scroll.ts
index 35e13a4527..0756edb4ce 100644
--- a/app/javascript/mastodon/scroll.ts
+++ b/app/javascript/mastodon/scroll.ts
@@ -38,13 +38,20 @@ const scroll = (
const isScrollBehaviorSupported =
'scrollBehavior' in document.documentElement.style;
-export const scrollRight = (node: Element, position: number) => {
- if (isScrollBehaviorSupported)
- node.scrollTo({ left: position, behavior: 'smooth' });
- else scroll(node, 'scrollLeft', position);
-};
+export const scrollRight = (node: Element, position: number) =>
+ requestIdleCallback(() => {
+ if (isScrollBehaviorSupported) {
+ node.scrollTo({ left: position, behavior: 'smooth' });
+ } else {
+ scroll(node, 'scrollLeft', position);
+ }
+ });
-export const scrollTop = (node: Element) => {
- if (isScrollBehaviorSupported) node.scrollTo({ top: 0, behavior: 'smooth' });
- else scroll(node, 'scrollTop', 0);
-};
+export const scrollTop = (node: Element) =>
+ requestIdleCallback(() => {
+ if (isScrollBehaviorSupported) {
+ node.scrollTo({ top: 0, behavior: 'smooth' });
+ } else {
+ scroll(node, 'scrollTop', 0);
+ }
+ });
diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js
index bd9b53919c..10e1b167ca 100644
--- a/app/javascript/mastodon/selectors/index.js
+++ b/app/javascript/mastodon/selectors/index.js
@@ -7,14 +7,16 @@ import { me } from '../initial_state';
export { makeGetAccount } from "./accounts";
-const getFilters = (state, { contextType }) => {
- if (!contextType) return null;
+const getFilters = createSelector([state => state.get('filters'), (_, { contextType }) => contextType], (filters, contextType) => {
+ if (!contextType) {
+ return null;
+ }
- const serverSideType = toServerSideType(contextType);
const now = new Date();
+ const serverSideType = toServerSideType(contextType);
- return state.get('filters').filter((filter) => filter.get('context').includes(serverSideType) && (filter.get('expires_at') === null || filter.get('expires_at') > now));
-};
+ return filters.filter(filter => filter.get('context').includes(serverSideType) && (filter.get('expires_at') === null || filter.get('expires_at') > now));
+});
export const makeGetStatus = () => {
return createSelector(
@@ -73,10 +75,21 @@ const ALERT_DEFAULTS = {
style: false,
};
-export const getAlerts = createSelector(state => state.get('alerts'), alerts =>
+const formatIfNeeded = (intl, message, values) => {
+ if (typeof message === 'object') {
+ return intl.formatMessage(message, values);
+ }
+
+ return message;
+};
+
+export const getAlerts = createSelector([state => state.get('alerts'), (_, { intl }) => intl], (alerts, intl) =>
alerts.map(item => ({
...ALERT_DEFAULTS,
...item,
+ action: formatIfNeeded(intl, item.action, item.values),
+ title: formatIfNeeded(intl, item.title, item.values),
+ message: formatIfNeeded(intl, item.message, item.values),
})).toArray());
export const makeGetNotification = () => createSelector([
diff --git a/app/javascript/mastodon/selectors/settings.ts b/app/javascript/mastodon/selectors/settings.ts
index 93276c6692..e722ad0911 100644
--- a/app/javascript/mastodon/selectors/settings.ts
+++ b/app/javascript/mastodon/selectors/settings.ts
@@ -1,17 +1,27 @@
+import { createSelector } from '@reduxjs/toolkit';
+
import type { RootState } from 'mastodon/store';
/* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */
// state.settings is not yet typed, so we disable some ESLint checks for those selectors
-export const selectSettingsNotificationsShows = (state: RootState) =>
- state.settings.getIn(['notifications', 'shows']).toJS() as Record<
- string,
- boolean
- >;
+export const selectSettingsNotificationsShows = createSelector(
+ [
+ (state) =>
+ state.settings.getIn(['notifications', 'shows']) as Immutable.Map<
+ string,
+ boolean
+ >,
+ ],
+ (shows) => shows.toJS() as Record,
+);
-export const selectSettingsNotificationsExcludedTypes = (state: RootState) =>
- Object.entries(selectSettingsNotificationsShows(state))
- .filter(([_type, enabled]) => !enabled)
- .map(([type, _enabled]) => type);
+export const selectSettingsNotificationsExcludedTypes = createSelector(
+ [selectSettingsNotificationsShows],
+ (shows) =>
+ Object.entries(shows)
+ .filter(([_type, enabled]) => !enabled)
+ .map(([type, _enabled]) => type),
+);
export const selectSettingsNotificationsQuickFilterShow = (state: RootState) =>
state.settings.getIn(['notifications', 'quickFilter', 'show']) as boolean;
diff --git a/app/javascript/mastodon/settings.js b/app/javascript/mastodon/settings.js
index f31aee0afc..f4883dc406 100644
--- a/app/javascript/mastodon/settings.js
+++ b/app/javascript/mastodon/settings.js
@@ -14,7 +14,7 @@ export default class Settings {
const encodedData = JSON.stringify(data);
localStorage.setItem(key, encodedData);
return data;
- } catch (e) {
+ } catch {
return null;
}
}
@@ -24,7 +24,7 @@ export default class Settings {
try {
const rawData = localStorage.getItem(key);
return JSON.parse(rawData);
- } catch (e) {
+ } catch {
return null;
}
}
@@ -35,7 +35,8 @@ export default class Settings {
const key = this.generateKey(id);
try {
localStorage.removeItem(key);
- } catch (e) {
+ } catch {
+ // ignore if the key is not found
}
}
return data;
diff --git a/app/javascript/mastodon/store/middlewares/errors.ts b/app/javascript/mastodon/store/middlewares/errors.ts
index e77cec34ed..3ad3844d5b 100644
--- a/app/javascript/mastodon/store/middlewares/errors.ts
+++ b/app/javascript/mastodon/store/middlewares/errors.ts
@@ -30,7 +30,7 @@ function isActionWithmaybeAlertParams(
return isAction(action);
}
-// eslint-disable-next-line @typescript-eslint/ban-types -- we need to use `{}` here to ensure the dispatch types can be merged
+// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- we need to use `{}` here to ensure the dispatch types can be merged
export const errorsMiddleware: Middleware<{}, RootState> =
({ dispatch }) =>
(next) =>
diff --git a/app/javascript/mastodon/store/middlewares/loading_bar.ts b/app/javascript/mastodon/store/middlewares/loading_bar.ts
index d259be899b..33d99f9852 100644
--- a/app/javascript/mastodon/store/middlewares/loading_bar.ts
+++ b/app/javascript/mastodon/store/middlewares/loading_bar.ts
@@ -48,8 +48,9 @@ export const loadingBarMiddleware = (
let isRejected = false;
if (
- isAsyncThunkAction(action)
- // TODO: once we get the first use-case for it, add a check for skipLoading
+ isAsyncThunkAction(action) &&
+ 'useLoadingBar' in action.meta &&
+ action.meta.useLoadingBar
) {
if (isThunkActionPending(action)) isPending = true;
else if (isThunkActionFulfilled(action)) isFulfilled = true;
diff --git a/app/javascript/mastodon/store/middlewares/sounds.ts b/app/javascript/mastodon/store/middlewares/sounds.ts
index 91407b1ec0..bb3a4aa474 100644
--- a/app/javascript/mastodon/store/middlewares/sounds.ts
+++ b/app/javascript/mastodon/store/middlewares/sounds.ts
@@ -51,7 +51,7 @@ const play = (audio: HTMLAudioElement) => {
};
export const soundsMiddleware = (): Middleware<
- // eslint-disable-next-line @typescript-eslint/ban-types -- we need to use `{}` here to ensure the dispatch types can be merged
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- we need to use `{}` here to ensure the dispatch types can be merged
{},
RootState
> => {
diff --git a/app/javascript/mastodon/store/typed_functions.ts b/app/javascript/mastodon/store/typed_functions.ts
index cd0f95cef9..9fcc90c61b 100644
--- a/app/javascript/mastodon/store/typed_functions.ts
+++ b/app/javascript/mastodon/store/typed_functions.ts
@@ -15,7 +15,7 @@ export interface AsyncThunkRejectValue {
}
interface AppMeta {
- skipLoading?: boolean;
+ useLoadingBar?: boolean;
}
export const createAppAsyncThunk = createAsyncThunk.withTypes<{
@@ -33,8 +33,12 @@ interface AppThunkConfig {
}
type AppThunkApi = Pick, 'getState' | 'dispatch'>;
-interface AppThunkOptions {
- skipLoading?: boolean;
+interface AppThunkOptions {
+ useLoadingBar?: boolean;
+ condition?: (
+ arg: Arg,
+ { getState }: { getState: AppThunkApi['getState'] },
+ ) => boolean;
}
const createBaseAsyncThunk = createAsyncThunk.withTypes();
@@ -42,7 +46,7 @@ const createBaseAsyncThunk = createAsyncThunk.withTypes();
export function createThunk(
name: string,
creator: (arg: Arg, api: AppThunkApi) => Returned | Promise,
- options: AppThunkOptions = {},
+ options: AppThunkOptions = {},
) {
return createBaseAsyncThunk(
name,
@@ -54,17 +58,23 @@ export function createThunk(
const result = await creator(arg, { dispatch, getState });
return fulfillWithValue(result, {
- skipLoading: options.skipLoading,
+ useLoadingBar: options.useLoadingBar,
});
} catch (error) {
- return rejectWithValue({ error }, { skipLoading: true });
+ return rejectWithValue(
+ { error },
+ {
+ useLoadingBar: options.useLoadingBar,
+ },
+ );
}
},
{
getPendingMeta() {
- if (options.skipLoading) return { skipLoading: true };
+ if (options.useLoadingBar) return { useLoadingBar: true };
return {};
},
+ condition: options.condition,
},
);
}
@@ -91,7 +101,7 @@ type ArgsType = Record | undefined;
export function createDataLoadingThunk(
name: string,
loadData: (args: Args) => Promise,
- thunkOptions?: AppThunkOptions,
+ thunkOptions?: AppThunkOptions,
): ReturnType>;
// Overload when the `onData` method returns discardLoadDataInPayload, then the payload is empty
@@ -99,17 +109,19 @@ export function createDataLoadingThunk(
name: string,
loadData: LoadData,
onDataOrThunkOptions?:
- | AppThunkOptions
+ | AppThunkOptions
| OnData,
- thunkOptions?: AppThunkOptions,
+ thunkOptions?: AppThunkOptions,
): ReturnType>;
// Overload when the `onData` method returns nothing, then the mayload is the `onData` result
export function createDataLoadingThunk(
name: string,
loadData: LoadData,
- onDataOrThunkOptions?: AppThunkOptions | OnData,
- thunkOptions?: AppThunkOptions,
+ onDataOrThunkOptions?:
+ | AppThunkOptions
+ | OnData,
+ thunkOptions?: AppThunkOptions,
): ReturnType>;
// Overload when there is an `onData` method returning something
@@ -121,9 +133,9 @@ export function createDataLoadingThunk<
name: string,
loadData: LoadData,
onDataOrThunkOptions?:
- | AppThunkOptions
+ | AppThunkOptions
| OnData,
- thunkOptions?: AppThunkOptions,
+ thunkOptions?: AppThunkOptions,
): ReturnType>;
/**
@@ -148,7 +160,8 @@ export function createDataLoadingThunk<
* You can also omit this parameter and pass `thunkOptions` directly
* @param maybeThunkOptions
* Additional Mastodon specific options for the thunk. Currently supports:
- * - `skipLoading` to avoid showing the loading bar when the request is in progress
+ * - `useLoadingBar` to display a loading bar while this action is pending. Defaults to true.
+ * - `condition` is passed to `createAsyncThunk` (https://redux-toolkit.js.org/api/createAsyncThunk#canceling-before-execution)
* @returns The created thunk
*/
export function createDataLoadingThunk<
@@ -159,12 +172,12 @@ export function createDataLoadingThunk<
name: string,
loadData: LoadData,
onDataOrThunkOptions?:
- | AppThunkOptions
+ | AppThunkOptions
| OnData,
- maybeThunkOptions?: AppThunkOptions,
+ maybeThunkOptions?: AppThunkOptions,
) {
let onData: OnData | undefined;
- let thunkOptions: AppThunkOptions | undefined;
+ let thunkOptions: AppThunkOptions | undefined;
if (typeof onDataOrThunkOptions === 'function') onData = onDataOrThunkOptions;
else if (typeof onDataOrThunkOptions === 'object')
@@ -198,6 +211,9 @@ export function createDataLoadingThunk<
return undefined as Returned;
else return result;
},
- thunkOptions,
+ {
+ useLoadingBar: thunkOptions?.useLoadingBar ?? true,
+ condition: thunkOptions?.condition,
+ },
);
}
diff --git a/app/javascript/mastodon/stream.js b/app/javascript/mastodon/stream.js
index 40d69136a8..59b2fd7582 100644
--- a/app/javascript/mastodon/stream.js
+++ b/app/javascript/mastodon/stream.js
@@ -209,7 +209,6 @@ const KNOWN_EVENT_TYPES = [
'notification',
'conversation',
'filters_changed',
- 'encrypted_message',
'announcement',
'announcement.delete',
'announcement.reaction',
diff --git a/app/javascript/mastodon/test_helpers.tsx b/app/javascript/mastodon/test_helpers.tsx
index f405090730..8a6f5a3377 100644
--- a/app/javascript/mastodon/test_helpers.tsx
+++ b/app/javascript/mastodon/test_helpers.tsx
@@ -8,6 +8,14 @@ import { render as rtlRender } from '@testing-library/react';
import { IdentityContext } from './identity_context';
+beforeEach(() => {
+ global.requestIdleCallback = jest
+ .fn()
+ .mockImplementation((fn: () => void) => {
+ fn();
+ });
+});
+
function render(
ui: React.ReactElement,
{
diff --git a/app/javascript/mastodon/utils/debounce.ts b/app/javascript/mastodon/utils/debounce.ts
new file mode 100644
index 0000000000..224a538984
--- /dev/null
+++ b/app/javascript/mastodon/utils/debounce.ts
@@ -0,0 +1,23 @@
+import { debounce } from 'lodash';
+
+import type { AppDispatch } from 'mastodon/store';
+
+export const debounceWithDispatchAndArguments = (
+ fn: (dispatch: AppDispatch, ...args: T[]) => void,
+ { delay = 100 },
+) => {
+ let argumentBuffer: T[] = [];
+ let dispatchBuffer: AppDispatch;
+
+ const wrapped = debounce(() => {
+ const tmpBuffer = argumentBuffer;
+ argumentBuffer = [];
+ fn(dispatchBuffer, ...tmpBuffer);
+ }, delay);
+
+ return (dispatch: AppDispatch, ...args: T[]) => {
+ dispatchBuffer = dispatch;
+ argumentBuffer.push(...args);
+ wrapped();
+ };
+};
diff --git a/app/javascript/material-icons/400-24px/fit_screen-fill.svg b/app/javascript/material-icons/400-24px/fit_screen-fill.svg
new file mode 100644
index 0000000000..a2ed8ca581
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/fit_screen-fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/fit_screen.svg b/app/javascript/material-icons/400-24px/fit_screen.svg
new file mode 100644
index 0000000000..d8d06f6e8b
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/fit_screen.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/styles/application.scss b/app/javascript/styles/application.scss
index 0dd573da9b..465b748078 100644
--- a/app/javascript/styles/application.scss
+++ b/app/javascript/styles/application.scss
@@ -11,7 +11,6 @@
@import 'mastodon/widgets';
@import 'mastodon/forms';
@import 'mastodon/accounts';
-@import 'mastodon/statuses';
@import 'mastodon/components';
@import 'mastodon/polls';
@import 'mastodon/modal';
diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss
index 1df556b42a..45da56994c 100644
--- a/app/javascript/styles/mastodon-light/diff.scss
+++ b/app/javascript/styles/mastodon-light/diff.scss
@@ -147,28 +147,6 @@
border-top-color: lighten($ui-base-color, 4%);
}
-// Change the background colors of modals
-.actions-modal,
-.boost-modal,
-.confirmation-modal,
-.mute-modal,
-.block-modal,
-.report-modal,
-.report-dialog-modal,
-.embed-modal,
-.error-modal,
-.onboarding-modal,
-.compare-history-modal,
-.report-modal__comment .setting-text__wrapper,
-.report-modal__comment .setting-text,
-.announcements,
-.picture-in-picture__header,
-.picture-in-picture__footer,
-.reactions-bar__item {
- background: $white;
- border: 1px solid var(--background-border-color);
-}
-
.reactions-bar__item:hover,
.reactions-bar__item:focus,
.reactions-bar__item:active {
@@ -198,14 +176,6 @@
color: $white;
}
-.report-modal__comment {
- border-right-color: lighten($ui-base-color, 8%);
-}
-
-.report-modal__container {
- border-top-color: lighten($ui-base-color, 8%);
-}
-
.column-settings__hashtags .column-select__option {
color: $white;
}
diff --git a/app/javascript/styles/mastodon-light/variables.scss b/app/javascript/styles/mastodon-light/variables.scss
index 76ede26233..76bdc4022e 100644
--- a/app/javascript/styles/mastodon-light/variables.scss
+++ b/app/javascript/styles/mastodon-light/variables.scss
@@ -1,3 +1,5 @@
+@use 'sass:color';
+
// Dependent colors
$black: #000000;
$white: #ffffff;
@@ -47,11 +49,19 @@ $account-background-color: $white !default;
// Invert darkened and lightened colors
@function darken($color, $amount) {
- @return hsl(hue($color), saturation($color), lightness($color) + $amount);
+ @return hsl(
+ hue($color),
+ color.channel($color, 'saturation', $space: hsl),
+ color.channel($color, 'lightness', $space: hsl) + $amount
+ );
}
@function lighten($color, $amount) {
- @return hsl(hue($color), saturation($color), lightness($color) - $amount);
+ @return hsl(
+ hue($color),
+ color.channel($color, 'saturation', $space: hsl),
+ color.channel($color, 'lightness', $space: hsl) - $amount
+ );
}
$emojis-requiring-inversion: 'chains';
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 7b272497d7..1bc172f440 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -93,7 +93,7 @@
&:disabled,
&.disabled {
background-color: $ui-primary-color;
- cursor: default;
+ cursor: not-allowed;
}
&.copyable {
@@ -299,6 +299,10 @@
}
}
+ &--with-counter {
+ padding-inline-end: 4px;
+ }
+
&__counter {
display: block;
width: auto;
@@ -1466,6 +1470,15 @@ body > [data-popper-placement] {
}
}
+ &__action-bar__button-wrapper {
+ flex-basis: 0;
+ flex-grow: 1;
+
+ &:last-child {
+ flex-grow: 0;
+ }
+ }
+
&--first-in-thread {
border-top: 1px solid var(--background-border-color);
}
@@ -1612,15 +1625,29 @@ body > [data-popper-placement] {
.status__prepend {
padding: 16px;
padding-bottom: 0;
- display: inline-flex;
- gap: 10px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
font-size: 15px;
line-height: 22px;
font-weight: 500;
color: $dark-text-color;
- .status__display-name strong {
- color: $dark-text-color;
+ &__icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex: 0 0 auto;
+
+ .icon {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ a {
+ color: inherit;
+ text-decoration: none;
}
> span {
@@ -1631,7 +1658,8 @@ body > [data-popper-placement] {
}
.status__wrapper-direct,
-.notification-ungrouped--direct {
+.notification-ungrouped--direct,
+.notification-group--direct {
background: rgba($ui-highlight-color, 0.05);
&:focus {
@@ -1677,18 +1705,6 @@ body > [data-popper-placement] {
padding: 16px;
border-top: 1px solid var(--background-border-color);
- &--flex {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
- align-items: flex-start;
-
- .status__content,
- .detailed-status__meta {
- flex: 100%;
- }
- }
-
.status__content {
font-size: 19px;
line-height: 24px;
@@ -1723,6 +1739,29 @@ body > [data-popper-placement] {
margin-bottom: 0;
}
}
+
+ .logo {
+ width: 40px;
+ height: 40px;
+ color: $dark-text-color;
+ }
+}
+
+.embed {
+ position: relative;
+
+ &__overlay {
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ }
+
+ .detailed-status {
+ border-top: 0;
+ }
}
.scrollable > div:first-child .detailed-status {
@@ -2021,13 +2060,14 @@ body > [data-popper-placement] {
display: block;
position: relative;
border-radius: var(--avatar-border-radius);
+ background-color: var(--surface-background-color);
img {
- display: block;
width: 100%;
height: 100%;
object-fit: cover;
border-radius: var(--avatar-border-radius);
+ display: inline-block; // to not show broken images
}
&-inline {
@@ -2696,7 +2736,7 @@ a.account__display-name {
&__main {
box-sizing: border-box;
width: 100%;
- flex: 0 0 auto;
+ flex: 0 1 auto;
display: flex;
flex-direction: column;
@@ -2803,7 +2843,7 @@ $ui-header-logo-wordmark-width: 99px;
}
.column {
- width: 350px;
+ width: 400px;
position: relative;
box-sizing: border-box;
display: flex;
@@ -2836,7 +2876,7 @@ $ui-header-logo-wordmark-width: 99px;
}
.drawer {
- width: 300px;
+ width: 350px;
box-sizing: border-box;
display: flex;
flex-direction: column;
@@ -3910,8 +3950,8 @@ $ui-header-logo-wordmark-width: 99px;
}
&__wrapper {
- background: $white;
- border: 1px solid $ui-secondary-color;
+ background: $ui-base-color;
+ border: 1px solid var(--background-border-color);
margin-bottom: 10px;
border-radius: 4px;
@@ -4718,22 +4758,14 @@ a.status-card {
position: absolute;
z-index: 100;
- &--minified {
- display: block;
- inset-inline-start: 4px;
- top: 4px;
- width: auto;
- height: auto;
+ &--hidden {
+ display: none;
}
&--click-thru {
pointer-events: none;
}
- &--hidden {
- display: none;
- }
-
&__overlay {
display: flex;
align-items: center;
@@ -4745,19 +4777,20 @@ a.status-card {
margin: 0;
border: 0;
color: $white;
+ line-height: 20px;
+ font-size: 14px;
&__label {
background-color: rgba($black, 0.45);
backdrop-filter: blur(10px) saturate(180%) contrast(75%) brightness(70%);
- border-radius: 6px;
- padding: 10px 15px;
+ border-radius: 8px;
+ padding: 12px 16px;
display: flex;
align-items: center;
justify-content: center;
- gap: 8px;
+ gap: 4px;
flex-direction: column;
- font-weight: 500;
- font-size: 14px;
+ font-weight: 600;
}
&__action {
@@ -5763,19 +5796,34 @@ a.status-card {
height: 100%;
position: relative;
- &__close,
- &__zoom-button {
- color: rgba($white, 0.7);
+ &__buttons {
+ position: absolute;
+ inset-inline-end: 8px;
+ top: 8px;
+ z-index: 100;
+ display: flex;
+ gap: 8px;
+ align-items: center;
- &:hover,
- &:focus,
- &:active {
- color: $white;
- background-color: rgba($white, 0.15);
- }
+ .icon-button {
+ color: rgba($white, 0.7);
+ padding: 8px;
- &:focus {
- background-color: rgba($white, 0.3);
+ .icon {
+ width: 24px;
+ height: 24px;
+ }
+
+ &:hover,
+ &:focus,
+ &:active {
+ color: $white;
+ background-color: rgba($white, 0.15);
+ }
+
+ &:focus {
+ background-color: rgba($white, 0.3);
+ }
}
}
}
@@ -5936,28 +5984,6 @@ a.status-card {
}
}
-.media-modal__close {
- position: absolute;
- inset-inline-end: 8px;
- top: 8px;
- z-index: 100;
-}
-
-.media-modal__zoom-button {
- position: absolute;
- inset-inline-end: 64px;
- top: 8px;
- z-index: 100;
- pointer-events: auto;
- transition: opacity 0.3s linear;
- will-change: opacity;
-}
-
-.media-modal__zoom-button--hidden {
- pointer-events: none;
- opacity: 0;
-}
-
.onboarding-modal,
.error-modal,
.embed-modal {
@@ -6161,6 +6187,48 @@ a.status-card {
}
}
+ &__status {
+ border: 1px solid var(--modal-border-color);
+ border-radius: 8px;
+ padding: 8px;
+ cursor: pointer;
+
+ &__account {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ margin-bottom: 8px;
+ color: $dark-text-color;
+
+ bdi {
+ color: inherit;
+ }
+ }
+
+ &__content {
+ display: -webkit-box;
+ font-size: 15px;
+ line-height: 22px;
+ color: $dark-text-color;
+ -webkit-line-clamp: 4;
+ -webkit-box-orient: vertical;
+ max-height: 4 * 22px;
+ overflow: hidden;
+
+ p,
+ a {
+ color: inherit;
+ }
+ }
+
+ .reply-indicator__attachments {
+ margin-top: 0;
+ font-size: 15px;
+ line-height: 22px;
+ color: $dark-text-color;
+ }
+ }
+
&__bullet-points {
display: flex;
flex-direction: column;
@@ -6238,6 +6306,12 @@ a.status-card {
gap: 8px;
justify-content: flex-end;
+ &__hint {
+ font-size: 14px;
+ line-height: 20px;
+ color: $dark-text-color;
+ }
+
.link-button {
padding: 10px 12px;
font-weight: 600;
@@ -6245,18 +6319,80 @@ a.status-card {
}
}
+.dialog-modal {
+ width: 588px;
+ max-height: 80vh;
+ flex-direction: column;
+ background: var(--modal-background-color);
+ backdrop-filter: var(--background-filter);
+ border: 1px solid var(--modal-border-color);
+ border-radius: 16px;
+
+ &__header {
+ border-bottom: 1px solid var(--modal-border-color);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-direction: row-reverse;
+ padding: 12px 24px;
+
+ &__title {
+ font-size: 16px;
+ line-height: 24px;
+ font-weight: 500;
+ letter-spacing: 0.15px;
+ }
+ }
+
+ &__content {
+ font-size: 14px;
+ line-height: 20px;
+ letter-spacing: 0.25px;
+ overflow-y: auto;
+
+ &__form {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ padding: 24px;
+ }
+ }
+
+ .copy-paste-text {
+ margin-bottom: 0;
+ }
+}
+
+.hotkey-combination {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+
+ kbd {
+ padding: 3px 5px;
+ border: 1px solid var(--background-border-color);
+ border-radius: 4px;
+ }
+}
+
.boost-modal,
.report-modal,
.actions-modal,
.compare-history-modal {
- background: lighten($ui-secondary-color, 8%);
- color: $inverted-text-color;
- border-radius: 8px;
+ background: var(--background-color);
+ color: $primary-text-color;
+ border-radius: 4px;
+ border: 1px solid var(--background-border-color);
overflow: hidden;
max-width: 90vw;
width: 480px;
position: relative;
flex-direction: column;
+
+ @media screen and (max-width: $no-columns-breakpoint) {
+ border-bottom: 0;
+ border-radius: 4px 4px 0 0;
+ }
}
.boost-modal__container {
@@ -6295,6 +6431,7 @@ a.status-card {
.report-modal {
width: 90vw;
max-width: 700px;
+ border: 1px solid var(--background-border-color);
}
.report-dialog-modal {
@@ -6395,7 +6532,7 @@ a.status-card {
}
.dialog-option .poll__input {
- border-color: $inverted-text-color;
+ border-color: $darker-text-color;
color: $ui-secondary-color;
display: inline-flex;
align-items: center;
@@ -6409,13 +6546,13 @@ a.status-card {
&:active,
&:focus,
&:hover {
- border-color: lighten($inverted-text-color, 15%);
+ border-color: $valid-value-color;
border-width: 4px;
}
&.active {
- border-color: $inverted-text-color;
- background: $inverted-text-color;
+ border-color: $valid-value-color;
+ background: $valid-value-color;
}
}
@@ -6518,7 +6655,7 @@ a.status-card {
.report-modal__container {
display: flex;
- border-top: 1px solid $ui-secondary-color;
+ border-top: 1px solid var(--background-border-color);
@media screen and (width <= 480px) {
flex-wrap: wrap;
@@ -6576,7 +6713,7 @@ a.status-card {
.report-modal__comment {
padding: 20px;
- border-inline-end: 1px solid $ui-secondary-color;
+ border-inline-end: 1px solid var(--background-border-color);
max-width: 320px;
p {
@@ -6587,7 +6724,7 @@ a.status-card {
.setting-text-label {
display: block;
- color: $inverted-text-color;
+ color: $secondary-text-color;
font-size: 14px;
font-weight: 500;
margin-bottom: 10px;
@@ -6653,7 +6790,7 @@ a.status-card {
li:not(:empty) {
a {
- color: $inverted-text-color;
+ color: $primary-text-color;
display: flex;
padding: 12px 16px;
font-size: 15px;
@@ -6733,7 +6870,7 @@ a.status-card {
.compare-history-modal {
.report-modal__target {
- border-bottom: 1px solid $ui-secondary-color;
+ border-bottom: 1px solid var(--background-border-color);
}
&__container {
@@ -6743,7 +6880,7 @@ a.status-card {
}
.status__content {
- color: $inverted-text-color;
+ color: $secondary-text-color;
font-size: 19px;
line-height: 24px;
@@ -6782,10 +6919,32 @@ a.status-card {
z-index: 9999;
}
+.media-gallery__actions {
+ position: absolute;
+ top: 6px;
+ inset-inline-end: 6px;
+ display: flex;
+ gap: 2px;
+ z-index: 2;
+
+ &__pill {
+ display: block;
+ color: $white;
+ border: 0;
+ background: rgba($black, 0.65);
+ backdrop-filter: blur(10px) saturate(180%) contrast(75%) brightness(70%);
+ padding: 3px 12px;
+ border-radius: 99px;
+ font-size: 14px;
+ font-weight: 700;
+ line-height: 20px;
+ }
+}
+
.media-gallery__item__badges {
position: absolute;
- bottom: 6px;
- inset-inline-start: 6px;
+ bottom: 8px;
+ inset-inline-end: 8px;
display: flex;
gap: 2px;
}
@@ -6798,18 +6957,13 @@ a.status-card {
color: $white;
background: rgba($black, 0.65);
backdrop-filter: blur(10px) saturate(180%) contrast(75%) brightness(70%);
- padding: 2px 6px;
+ padding: 3px 8px;
border-radius: 4px;
- font-size: 11px;
+ font-size: 12px;
font-weight: 700;
z-index: 1;
pointer-events: none;
- line-height: 18px;
-
- .icon {
- width: 15px;
- height: 15px;
- }
+ line-height: 20px;
}
.attachment-list {
@@ -6885,6 +7039,64 @@ a.status-card {
grid-template-columns: 50% 50%;
grid-template-rows: 50% 50%;
gap: 2px;
+
+ &--layout-2 {
+ .media-gallery__item:nth-child(1) {
+ border-end-end-radius: 0;
+ border-start-end-radius: 0;
+ }
+
+ .media-gallery__item:nth-child(2) {
+ border-start-start-radius: 0;
+ border-end-start-radius: 0;
+ }
+ }
+
+ &--layout-3 {
+ .media-gallery__item:nth-child(1) {
+ border-end-end-radius: 0;
+ border-start-end-radius: 0;
+ }
+
+ .media-gallery__item:nth-child(2) {
+ border-start-start-radius: 0;
+ border-end-start-radius: 0;
+ border-end-end-radius: 0;
+ }
+
+ .media-gallery__item:nth-child(3) {
+ border-start-start-radius: 0;
+ border-end-start-radius: 0;
+ border-start-end-radius: 0;
+ }
+ }
+
+ &--layout-4 {
+ .media-gallery__item:nth-child(1) {
+ border-end-end-radius: 0;
+ border-start-end-radius: 0;
+ border-end-start-radius: 0;
+ }
+
+ .media-gallery__item:nth-child(2) {
+ border-start-start-radius: 0;
+ border-end-start-radius: 0;
+ border-end-end-radius: 0;
+ }
+
+ .media-gallery__item:nth-child(3) {
+ border-start-start-radius: 0;
+ border-start-end-radius: 0;
+ border-end-start-radius: 0;
+ border-end-end-radius: 0;
+ }
+
+ .media-gallery__item:nth-child(4) {
+ border-start-start-radius: 0;
+ border-end-start-radius: 0;
+ border-start-end-radius: 0;
+ }
+ }
}
.media-gallery__item {
@@ -7538,7 +7750,7 @@ a.status-card {
}
}
-.radio-button.checked::before {
+.radio-button__input.checked::before {
position: absolute;
left: 2px;
top: 2px;
@@ -7604,69 +7816,6 @@ noscript {
}
}
-.embed-modal {
- width: auto;
- max-width: 80vw;
- max-height: 80vh;
-
- h4 {
- padding: 30px;
- font-weight: 500;
- font-size: 16px;
- text-align: center;
- }
-
- .embed-modal__container {
- padding: 10px;
-
- .hint {
- margin-bottom: 15px;
- }
-
- .embed-modal__html {
- outline: 0;
- box-sizing: border-box;
- display: block;
- width: 100%;
- border: 0;
- padding: 10px;
- font-family: $font-monospace, monospace;
- background: $ui-base-color;
- color: $primary-text-color;
- font-size: 14px;
- margin: 0;
- margin-bottom: 15px;
- border-radius: 4px;
-
- &::-moz-focus-inner {
- border: 0;
- }
-
- &::-moz-focus-inner,
- &:focus,
- &:active {
- outline: 0 !important;
- }
-
- &:focus {
- background: lighten($ui-base-color, 4%);
- }
-
- @media screen and (width <= 600px) {
- font-size: 16px;
- }
- }
-
- .embed-modal__iframe {
- width: 400px;
- max-width: 100%;
- overflow: hidden;
- border: 0;
- border-radius: 4px;
- }
- }
-}
-
.moved-account-banner,
.follow-request-banner,
.account-memorial-banner {
@@ -8480,22 +8629,6 @@ noscript {
word-break: break-word;
}
}
-
- &--unread {
- background: lighten($ui-base-color, 2%);
-
- &:focus {
- background: lighten($ui-base-color, 4%);
- }
-
- .conversation__content__info {
- font-weight: 700;
- }
-
- .conversation__content__relative-time {
- color: $primary-text-color;
- }
- }
}
.announcements {
@@ -8690,7 +8823,8 @@ noscript {
}
.notification,
-.status__wrapper {
+.status__wrapper,
+.conversation {
position: relative;
&.unread {
@@ -10126,6 +10260,7 @@ noscript {
scroll-padding: 16px;
scroll-behavior: smooth;
overflow-x: scroll;
+ scrollbar-width: none;
&__card {
background: var(--background-color);
@@ -10598,6 +10733,7 @@ noscript {
}
.reply-indicator__attachments {
+ margin-top: 0;
font-size: 15px;
line-height: 22px;
color: $dark-text-color;
@@ -10888,6 +11024,7 @@ noscript {
}
.content-warning {
+ box-sizing: border-box;
background: rgba($ui-highlight-color, 0.05);
color: $secondary-text-color;
border-top: 1px solid;
diff --git a/app/javascript/styles/mastodon/dashboard.scss b/app/javascript/styles/mastodon/dashboard.scss
index 1621220ccb..d049b2456c 100644
--- a/app/javascript/styles/mastodon/dashboard.scss
+++ b/app/javascript/styles/mastodon/dashboard.scss
@@ -86,9 +86,7 @@
color: $primary-text-color;
transition: all 100ms ease-in;
font-size: 14px;
- padding: 0 16px;
- line-height: 36px;
- height: 36px;
+ padding: 8px 16px;
text-decoration: none;
margin-bottom: 4px;
diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss
index 926df4e96f..56f7b893f3 100644
--- a/app/javascript/styles/mastodon/forms.scss
+++ b/app/javascript/styles/mastodon/forms.scss
@@ -12,6 +12,41 @@ code {
margin: 50px auto;
}
+.form-section {
+ border-radius: 8px;
+ background: var(--surface-background-color);
+ padding: 24px;
+ margin-bottom: 24px;
+}
+
+.fade-out-top {
+ position: relative;
+ overflow: hidden;
+ height: 160px;
+
+ &::after {
+ content: '';
+ display: block;
+ background: linear-gradient(
+ to bottom,
+ var(--surface-background-color),
+ transparent
+ );
+ position: absolute;
+ top: 0;
+ inset-inline-start: 0;
+ width: 100%;
+ height: 100px;
+ pointer-events: none;
+ }
+
+ & > div {
+ position: absolute;
+ inset-inline-start: 0;
+ bottom: 0;
+ }
+}
+
.indicator-icon {
display: flex;
align-items: center;
diff --git a/app/javascript/styles/mastodon/statuses.scss b/app/javascript/styles/mastodon/statuses.scss
deleted file mode 100644
index b6d4f98cce..0000000000
--- a/app/javascript/styles/mastodon/statuses.scss
+++ /dev/null
@@ -1,152 +0,0 @@
-.activity-stream {
- box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
- border-radius: 4px;
- overflow: hidden;
- margin-bottom: 10px;
-
- &--under-tabs {
- border-radius: 0 0 4px 4px;
- }
-
- @media screen and (max-width: $no-gap-breakpoint) {
- margin-bottom: 0;
- border-radius: 0;
- box-shadow: none;
- }
-
- &--headless {
- border-radius: 0;
- margin: 0;
- box-shadow: none;
-
- .detailed-status,
- .status {
- border-radius: 0 !important;
- }
- }
-
- div[data-component] {
- width: 100%;
- }
-
- .entry {
- background: $ui-base-color;
-
- .detailed-status,
- .status,
- .load-more {
- animation: none;
- }
-
- &:last-child {
- .detailed-status,
- .status,
- .load-more {
- border-bottom: 0;
- border-radius: 0 0 4px 4px;
- }
- }
-
- &:first-child {
- .detailed-status,
- .status,
- .load-more {
- border-radius: 4px 4px 0 0;
- }
-
- &:last-child {
- .detailed-status,
- .status,
- .load-more {
- border-radius: 4px;
- }
- }
- }
-
- @media screen and (width <= 740px) {
- .detailed-status,
- .status,
- .load-more {
- border-radius: 0 !important;
- }
- }
- }
-
- &--highlighted .entry {
- background: lighten($ui-base-color, 8%);
- }
-}
-
-.button.logo-button svg {
- width: 20px;
- height: auto;
- vertical-align: middle;
- margin-inline-end: 5px;
- fill: $primary-text-color;
-
- @media screen and (max-width: $no-gap-breakpoint) {
- display: none;
- }
-}
-
-.embed {
- .status__content[data-spoiler='folded'] {
- .e-content {
- display: none;
- }
-
- p:first-child {
- margin-bottom: 0;
- }
- }
-
- .detailed-status {
- padding: 15px;
-
- .detailed-status__display-avatar .account__avatar {
- width: 48px;
- height: 48px;
- }
- }
-
- .status {
- padding: 15px 15px 15px (48px + 15px * 2);
- min-height: 48px + 2px;
-
- &__avatar {
- inset-inline-start: 15px;
- top: 17px;
-
- .account__avatar {
- width: 48px;
- height: 48px;
- }
- }
-
- &__content {
- padding-top: 5px;
- }
-
- &__prepend {
- margin-inline-start: 48px + 15px * 2;
- padding-top: 15px;
- }
-
- &__prepend-icon-wrapper {
- inset-inline-start: -32px;
- }
-
- .media-gallery,
- &__action-bar,
- .video-player {
- margin-top: 10px;
- }
-
- &__action-bar-button {
- font-size: 18px;
- width: 23.1429px;
- height: 23.1429px;
- line-height: 23.15px;
- }
- }
-}
diff --git a/app/javascript/svg-icons/actual_size.svg b/app/javascript/svg-icons/actual_size.svg
new file mode 100644
index 0000000000..75939cac87
--- /dev/null
+++ b/app/javascript/svg-icons/actual_size.svg
@@ -0,0 +1,4 @@
+
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index f69b68392a..7f9429c5e4 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -8,44 +8,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
dereference_object!
- case @object['type']
- when 'EncryptedMessage'
- create_encrypted_message
- else
- create_status
- end
+ create_status
end
private
- def create_encrypted_message
- return reject_payload! if non_matching_uri_hosts?(@account.uri, object_uri) || @options[:delivered_to_account_id].blank?
-
- target_account = Account.find(@options[:delivered_to_account_id])
- target_device = target_account.devices.find_by(device_id: @object.dig('to', 'deviceId'))
-
- return if target_device.nil?
-
- target_device.encrypted_messages.create!(
- from_account: @account,
- from_device_id: @object.dig('attributedTo', 'deviceId'),
- type: @object['messageType'],
- body: @object['cipherText'],
- digest: @object.dig('digest', 'digestValue'),
- message_franking: message_franking.to_token
- )
- end
-
- def message_franking
- MessageFranking.new(
- hmac: @object.dig('digest', 'digestValue'),
- original_franking: @object['messageFranking'],
- source_account_id: @account.id,
- target_account_id: @options[:delivered_to_account_id],
- timestamp: Time.now.utc
- )
- end
-
def create_status
return reject_payload! if unsupported_object_type? || non_matching_uri_hosts?(@account.uri, object_uri) || tombstone_exists? || !related_to_local_activity?
@@ -375,7 +342,15 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
end
def converted_text
- linkify([@status_parser.title.presence, @status_parser.spoiler_text.presence, @status_parser.url || @status_parser.uri].compact.join("\n\n"))
+ [formatted_title, @status_parser.spoiler_text.presence, formatted_url].compact.join("\n\n")
+ end
+
+ def formatted_title
+ "#{@status_parser.title}
" if @status_parser.title.present?
+ end
+
+ def formatted_url
+ linkify(@status_parser.url || @status_parser.uri)
end
def unsupported_media_type?(mime_type)
diff --git a/app/lib/activitypub/linked_data_signature.rb b/app/lib/activitypub/linked_data_signature.rb
index 9459fdd8b7..c42313b05e 100644
--- a/app/lib/activitypub/linked_data_signature.rb
+++ b/app/lib/activitypub/linked_data_signature.rb
@@ -4,6 +4,7 @@ class ActivityPub::LinkedDataSignature
include JsonLdHelper
CONTEXT = 'https://w3id.org/identity/v1'
+ SIGNATURE_CONTEXT = 'https://w3id.org/security/v1'
def initialize(json)
@json = json.with_indifferent_access
@@ -46,7 +47,13 @@ class ActivityPub::LinkedDataSignature
signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), to_be_signed))
- @json.merge('signature' => options.merge('signatureValue' => signature))
+ # Mastodon's context is either an array or a single URL
+ context_with_security = Array(@json['@context'])
+ context_with_security << 'https://w3id.org/security/v1'
+ context_with_security.uniq!
+ context_with_security = context_with_security.first if context_with_security.size == 1
+
+ @json.merge('signature' => options.merge('signatureValue' => signature), '@context' => context_with_security)
end
private
diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb
index 8643286317..23b44be372 100644
--- a/app/lib/activitypub/tag_manager.rb
+++ b/app/lib/activitypub/tag_manager.rb
@@ -74,6 +74,18 @@ class ActivityPub::TagManager
account_status_replies_url(target.account, target, page_params)
end
+ def likes_uri_for(target)
+ raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local?
+
+ account_status_likes_url(target.account, target)
+ end
+
+ def shares_uri_for(target)
+ raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local?
+
+ account_status_shares_url(target.account, target)
+ end
+
def followers_uri_for(target)
target.local? ? account_followers_url(target) : target.followers_url.presence
end
diff --git a/app/lib/annual_report/archetype.rb b/app/lib/annual_report/archetype.rb
index ea9ef366df..c02b28dfda 100644
--- a/app/lib/annual_report/archetype.rb
+++ b/app/lib/annual_report/archetype.rb
@@ -28,22 +28,18 @@ class AnnualReport::Archetype < AnnualReport::Source
end
def polls_count
- @polls_count ||= base_scope.where.not(poll_id: nil).count
+ @polls_count ||= report_statuses.where.not(poll_id: nil).count
end
def reblogs_count
- @reblogs_count ||= base_scope.where.not(reblog_of_id: nil).count
+ @reblogs_count ||= report_statuses.where.not(reblog_of_id: nil).count
end
def replies_count
- @replies_count ||= base_scope.where.not(in_reply_to_id: nil).where.not(in_reply_to_account_id: @account.id).count
+ @replies_count ||= report_statuses.where.not(in_reply_to_id: nil).where.not(in_reply_to_account_id: @account.id).count
end
def standalone_count
- @standalone_count ||= base_scope.without_replies.without_reblogs.count
- end
-
- def base_scope
- @account.statuses.where(id: year_as_snowflake_range)
+ @standalone_count ||= report_statuses.without_replies.without_reblogs.count
end
end
diff --git a/app/lib/annual_report/commonly_interacted_with_accounts.rb b/app/lib/annual_report/commonly_interacted_with_accounts.rb
index af5e854c22..e7482f0d52 100644
--- a/app/lib/annual_report/commonly_interacted_with_accounts.rb
+++ b/app/lib/annual_report/commonly_interacted_with_accounts.rb
@@ -17,6 +17,6 @@ class AnnualReport::CommonlyInteractedWithAccounts < AnnualReport::Source
private
def commonly_interacted_with_accounts
- @account.statuses.reorder(nil).where(id: year_as_snowflake_range).where.not(in_reply_to_account_id: @account.id).group(:in_reply_to_account_id).having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('in_reply_to_account_id, count(*) AS total'))
+ report_statuses.where.not(in_reply_to_account_id: @account.id).group(:in_reply_to_account_id).having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('in_reply_to_account_id, count(*) AS total'))
end
end
diff --git a/app/lib/annual_report/most_reblogged_accounts.rb b/app/lib/annual_report/most_reblogged_accounts.rb
index e3e8a7c90b..39ed3868ea 100644
--- a/app/lib/annual_report/most_reblogged_accounts.rb
+++ b/app/lib/annual_report/most_reblogged_accounts.rb
@@ -17,6 +17,6 @@ class AnnualReport::MostRebloggedAccounts < AnnualReport::Source
private
def most_reblogged_accounts
- @account.statuses.reorder(nil).where(id: year_as_snowflake_range).where.not(reblog_of_id: nil).joins(reblog: :account).group('accounts.id').having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('accounts.id, count(*) as total'))
+ report_statuses.where.not(reblog_of_id: nil).joins(reblog: :account).group('accounts.id').having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('accounts.id, count(*) as total'))
end
end
diff --git a/app/lib/annual_report/most_used_apps.rb b/app/lib/annual_report/most_used_apps.rb
index 85ff1ff86e..fb1ca1d167 100644
--- a/app/lib/annual_report/most_used_apps.rb
+++ b/app/lib/annual_report/most_used_apps.rb
@@ -17,6 +17,6 @@ class AnnualReport::MostUsedApps < AnnualReport::Source
private
def most_used_apps
- @account.statuses.reorder(nil).where(id: year_as_snowflake_range).joins(:application).group('oauth_applications.name').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('oauth_applications.name, count(*) as total'))
+ report_statuses.joins(:application).group('oauth_applications.name').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('oauth_applications.name, count(*) as total'))
end
end
diff --git a/app/lib/annual_report/percentiles.rb b/app/lib/annual_report/percentiles.rb
index 9fe4698ee5..0251cb66ad 100644
--- a/app/lib/annual_report/percentiles.rb
+++ b/app/lib/annual_report/percentiles.rb
@@ -17,7 +17,7 @@ class AnnualReport::Percentiles < AnnualReport::Source
end
def statuses_created
- @statuses_created ||= @account.statuses.where(id: year_as_snowflake_range).count
+ @statuses_created ||= report_statuses.count
end
def total_with_fewer_followers
diff --git a/app/lib/annual_report/source.rb b/app/lib/annual_report/source.rb
index 1ccb622676..cb9f7b16e3 100644
--- a/app/lib/annual_report/source.rb
+++ b/app/lib/annual_report/source.rb
@@ -10,7 +10,24 @@ class AnnualReport::Source
protected
+ def report_statuses
+ @account
+ .statuses
+ .where(id: year_as_snowflake_range)
+ .reorder(nil)
+ end
+
def year_as_snowflake_range
- (Mastodon::Snowflake.id_at(DateTime.new(year, 1, 1))..Mastodon::Snowflake.id_at(DateTime.new(year, 12, 31)))
+ (beginning_snowflake_id..ending_snowflake_id)
+ end
+
+ private
+
+ def beginning_snowflake_id
+ Mastodon::Snowflake.id_at DateTime.new(year).beginning_of_year
+ end
+
+ def ending_snowflake_id
+ Mastodon::Snowflake.id_at DateTime.new(year).end_of_year
end
end
diff --git a/app/lib/annual_report/time_series.rb b/app/lib/annual_report/time_series.rb
index a144bac0d1..65a188eda7 100644
--- a/app/lib/annual_report/time_series.rb
+++ b/app/lib/annual_report/time_series.rb
@@ -17,7 +17,7 @@ class AnnualReport::TimeSeries < AnnualReport::Source
private
def statuses_per_month
- @statuses_per_month ||= @account.statuses.reorder(nil).where(id: year_as_snowflake_range).group(:period).pluck(Arel.sql("date_part('month', created_at)::int AS period, count(*)")).to_h
+ @statuses_per_month ||= report_statuses.group(:period).pluck(Arel.sql("date_part('month', created_at)::int AS period, count(*)")).to_h
end
def following_per_month
diff --git a/app/lib/annual_report/top_hashtags.rb b/app/lib/annual_report/top_hashtags.rb
index 488dacb1b4..32bd10d698 100644
--- a/app/lib/annual_report/top_hashtags.rb
+++ b/app/lib/annual_report/top_hashtags.rb
@@ -17,6 +17,6 @@ class AnnualReport::TopHashtags < AnnualReport::Source
private
def top_hashtags
- Tag.joins(:statuses).where(statuses: { id: @account.statuses.where(id: year_as_snowflake_range).reorder(nil).select(:id) }).group(:id).having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('COALESCE(tags.display_name, tags.name), count(*) AS total'))
+ Tag.joins(:statuses).where(statuses: { id: report_statuses.select(:id) }).group(:id).having('count(*) > 1').order(total: :desc).limit(SET_SIZE).pluck(Arel.sql('COALESCE(tags.display_name, tags.name), count(*) AS total'))
end
end
diff --git a/app/lib/annual_report/top_statuses.rb b/app/lib/annual_report/top_statuses.rb
index 1ab1709523..c5abeaa58d 100644
--- a/app/lib/annual_report/top_statuses.rb
+++ b/app/lib/annual_report/top_statuses.rb
@@ -16,6 +16,6 @@ class AnnualReport::TopStatuses < AnnualReport::Source
end
def base_scope
- @account.statuses.public_visibility.joins(:status_stat).where(id: year_as_snowflake_range).reorder(nil)
+ report_statuses.public_visibility.joins(:status_stat)
end
end
diff --git a/app/lib/annual_report/type_distribution.rb b/app/lib/annual_report/type_distribution.rb
index fc12a6f1f4..fe38d8a8a2 100644
--- a/app/lib/annual_report/type_distribution.rb
+++ b/app/lib/annual_report/type_distribution.rb
@@ -4,17 +4,11 @@ class AnnualReport::TypeDistribution < AnnualReport::Source
def generate
{
type_distribution: {
- total: base_scope.count,
- reblogs: base_scope.where.not(reblog_of_id: nil).count,
- replies: base_scope.where.not(in_reply_to_id: nil).where.not(in_reply_to_account_id: @account.id).count,
- standalone: base_scope.without_replies.without_reblogs.count,
+ total: report_statuses.count,
+ reblogs: report_statuses.where.not(reblog_of_id: nil).count,
+ replies: report_statuses.where.not(in_reply_to_id: nil).where.not(in_reply_to_account_id: @account.id).count,
+ standalone: report_statuses.without_replies.without_reblogs.count,
},
}
end
-
- private
-
- def base_scope
- @account.statuses.where(id: year_as_snowflake_range)
- end
end
diff --git a/app/lib/content_security_policy.rb b/app/lib/content_security_policy.rb
index 9dbcb35636..a6901a6757 100644
--- a/app/lib/content_security_policy.rb
+++ b/app/lib/content_security_policy.rb
@@ -13,6 +13,22 @@ class ContentSecurityPolicy
[assets_host, cdn_host_value, paperclip_root_url].concat(extra_data_hosts).compact
end
+ def sso_host
+ return unless ENV['ONE_CLICK_SSO_LOGIN'] == 'true' && ENV['OMNIAUTH_ONLY'] == 'true' && Devise.omniauth_providers.length == 1
+
+ provider = Devise.omniauth_configs[Devise.omniauth_providers[0]]
+ @sso_host ||= begin
+ case provider.provider
+ when :cas
+ provider.cas_url
+ when :saml
+ provider.options[:idp_sso_target_url]
+ when :openid_connect
+ provider.options.dig(:client_options, :authorization_endpoint) || OpenIDConnect::Discovery::Provider::Config.discover!(provider.options[:issuer]).authorization_endpoint
+ end
+ end
+ end
+
private
def extra_data_hosts
diff --git a/app/lib/emoji_formatter.rb b/app/lib/emoji_formatter.rb
index 2a3683c499..5f1a4651f7 100644
--- a/app/lib/emoji_formatter.rb
+++ b/app/lib/emoji_formatter.rb
@@ -24,7 +24,7 @@ class EmojiFormatter
def to_s
return html if custom_emojis.empty? || html.blank?
- tree = Nokogiri::HTML.fragment(html)
+ tree = Nokogiri::HTML5.fragment(html)
tree.xpath('./text()|.//text()[not(ancestor[@class="invisible"])]').to_a.each do |node|
i = -1
inside_shortname = false
@@ -43,8 +43,8 @@ class EmojiFormatter
next unless (char_after.nil? || !DISALLOWED_BOUNDING_REGEX.match?(char_after)) && (emoji = emoji_map[shortcode])
- result << Nokogiri::XML::Text.new(text[last_index..shortname_start_index - 1], tree.document) if shortname_start_index.positive?
- result << Nokogiri::HTML.fragment(tag_for_emoji(shortcode, emoji))
+ result << tree.document.create_text_node(text[last_index..shortname_start_index - 1]) if shortname_start_index.positive?
+ result << tree.document.fragment(tag_for_emoji(shortcode, emoji))
last_index = i + 1
elsif text[i] == ':' && (i.zero? || !DISALLOWED_BOUNDING_REGEX.match?(text[i - 1]))
@@ -53,7 +53,7 @@ class EmojiFormatter
end
end
- result << Nokogiri::XML::Text.new(text[last_index..], tree.document)
+ result << tree.document.create_text_node(text[last_index..])
node.replace(result)
end
diff --git a/app/lib/entity_cache.rb b/app/lib/entity_cache.rb
index 80b0046eea..e647dcab7f 100644
--- a/app/lib/entity_cache.rb
+++ b/app/lib/entity_cache.rb
@@ -27,7 +27,7 @@ class EntityCache
end
unless uncached_ids.empty?
- uncached = CustomEmoji.where(shortcode: shortcodes, domain: domain, disabled: false).index_by(&:shortcode)
+ uncached = CustomEmoji.enabled.where(shortcode: shortcodes, domain: domain).index_by(&:shortcode)
uncached.each_value { |item| Rails.cache.write(to_key(:emoji, item.shortcode, domain), item, expires_in: MAX_EXPIRATION) }
end
diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb
index 5a1710c52d..3c278b37d8 100644
--- a/app/lib/feed_manager.rb
+++ b/app/lib/feed_manager.rb
@@ -618,7 +618,7 @@ class FeedManager
arr = crutches[:active_mentions][s.id] || []
arr.push(s.account_id)
- if s.reblog?
+ if s.reblog? && s.reblog.present?
arr.push(s.reblog.account_id)
arr.concat(crutches[:active_mentions][s.reblog_of_id] || [])
end
diff --git a/app/lib/inline_renderer.rb b/app/lib/inline_renderer.rb
index 0aebb13fce..af967ac215 100644
--- a/app/lib/inline_renderer.rb
+++ b/app/lib/inline_renderer.rb
@@ -20,8 +20,6 @@ class InlineRenderer
serializer = REST::AnnouncementSerializer
when :reaction
serializer = REST::ReactionSerializer
- when :encrypted_message
- serializer = REST::EncryptedMessageSerializer
else
return
end
diff --git a/app/lib/link_details_extractor.rb b/app/lib/link_details_extractor.rb
index bd78aef7a9..e4e815c38d 100644
--- a/app/lib/link_details_extractor.rb
+++ b/app/lib/link_details_extractor.rb
@@ -157,11 +157,11 @@ class LinkDetailsExtractor
end
def title
- html_entities_decode(structured_data&.headline || opengraph_tag('og:title') || document.xpath('//title').map(&:content).first)&.strip
+ html_entities.decode(structured_data&.headline || opengraph_tag('og:title') || document.xpath('//title').map(&:content).first)&.strip
end
def description
- html_entities_decode(structured_data&.description || opengraph_tag('og:description') || meta_tag('description'))
+ html_entities.decode(structured_data&.description || opengraph_tag('og:description') || meta_tag('description'))
end
def published_at
@@ -181,7 +181,7 @@ class LinkDetailsExtractor
end
def provider_name
- html_entities_decode(structured_data&.publisher_name || opengraph_tag('og:site_name'))
+ html_entities.decode(structured_data&.publisher_name || opengraph_tag('og:site_name'))
end
def provider_url
@@ -189,7 +189,7 @@ class LinkDetailsExtractor
end
def author_name
- html_entities_decode(structured_data&.author_name || opengraph_tag('og:author') || opengraph_tag('og:author:username'))
+ html_entities.decode(structured_data&.author_name || opengraph_tag('og:author') || opengraph_tag('og:author:username'))
end
def author_url
@@ -225,7 +225,7 @@ class LinkDetailsExtractor
end
def valid_url_or_nil(str, same_origin_only: false)
- return if str.blank? || str == 'null'
+ return if str.blank? || str == 'null' || str == 'undefined'
url = @original_url + Addressable::URI.parse(str)
@@ -258,7 +258,7 @@ class LinkDetailsExtractor
next if json_ld.blank?
- structured_data = StructuredData.new(html_entities_decode(json_ld))
+ structured_data = StructuredData.new(html_entities.decode(json_ld))
next unless structured_data.valid?
@@ -274,11 +274,20 @@ class LinkDetailsExtractor
end
def detect_encoding_and_parse_document
- [detect_encoding, nil, header_encoding].uniq.each do |encoding|
- document = Nokogiri::HTML(@html, nil, encoding)
- return document if document.to_s.valid_encoding?
+ html = nil
+ encoding = nil
+
+ [detect_encoding, header_encoding].compact.each do |enc|
+ html = @html.dup.force_encoding(enc)
+ if html.valid_encoding?
+ encoding = enc
+ break
+ end
end
- Nokogiri::HTML(@html, nil, 'UTF-8')
+
+ html = @html unless encoding
+
+ Nokogiri::HTML5(html, nil, encoding)
end
def detect_encoding
@@ -299,15 +308,6 @@ class LinkDetailsExtractor
end
end
- def html_entities_decode(string)
- return if string.nil?
-
- unicode_string = string.to_s.encode('UTF-8')
- raise EncodingError, 'cannot convert string to valid UTF-8' unless unicode_string.valid_encoding?
-
- html_entities.decode(unicode_string)
- end
-
def html_entities
@html_entities ||= HTMLEntities.new(:expanded)
end
diff --git a/app/lib/permalink_redirector.rb b/app/lib/permalink_redirector.rb
index f551f69db8..142a05d10d 100644
--- a/app/lib/permalink_redirector.rb
+++ b/app/lib/permalink_redirector.rb
@@ -83,6 +83,6 @@ class PermalinkRedirector
end
def path_segments
- @path_segments ||= @path.delete_prefix('/deck').delete_prefix('/').split('/')
+ @path_segments ||= @path.split('?')[0].delete_prefix('/deck').delete_prefix('/').split('/')
end
end
diff --git a/app/lib/plain_text_formatter.rb b/app/lib/plain_text_formatter.rb
index d1ff6808b2..f960ba7acc 100644
--- a/app/lib/plain_text_formatter.rb
+++ b/app/lib/plain_text_formatter.rb
@@ -16,7 +16,7 @@ class PlainTextFormatter
if local?
text
else
- node = Nokogiri::HTML.fragment(insert_newlines)
+ node = Nokogiri::HTML5.fragment(insert_newlines)
# Elements that are entirely removed with our Sanitize config
node.xpath('.//iframe|.//math|.//noembed|.//noframes|.//noscript|.//plaintext|.//script|.//style|.//svg|.//xmp').remove
node.text.chomp
diff --git a/app/lib/redis_configuration.rb b/app/lib/redis_connection.rb
similarity index 65%
rename from app/lib/redis_configuration.rb
rename to app/lib/redis_connection.rb
index fb1249640f..24e376e6a5 100644
--- a/app/lib/redis_configuration.rb
+++ b/app/lib/redis_connection.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class RedisConfiguration
+class RedisConnection
class << self
def establish_pool(new_pool_size)
@pool&.shutdown(&:close)
@@ -22,33 +22,24 @@ class RedisConfiguration
end
end
+ attr_reader :config
+
+ def initialize
+ @config = REDIS_CONFIGURATION.base
+ end
+
def connection
- if namespace?
+ namespace = config[:namespace]
+ if namespace.present?
Redis::Namespace.new(namespace, redis: raw_connection)
else
raw_connection
end
end
- def namespace?
- namespace.present?
- end
-
- def namespace
- ENV.fetch('REDIS_NAMESPACE', nil)
- end
-
- def url
- ENV['REDIS_URL']
- end
-
- def redis_driver
- ENV.fetch('REDIS_DRIVER', 'hiredis') == 'ruby' ? :ruby : :hiredis
- end
-
private
def raw_connection
- Redis.new(url: url, driver: redis_driver)
+ Redis.new(**config)
end
end
diff --git a/app/lib/request.rb b/app/lib/request.rb
index ab42e82300..d7da9fe63c 100644
--- a/app/lib/request.rb
+++ b/app/lib/request.rb
@@ -77,7 +77,7 @@ class Request
@url = Addressable::URI.parse(url).normalize
@http_client = options.delete(:http_client)
@allow_local = options.delete(:allow_local)
- @full_path = options.delete(:with_query_string)
+ @full_path = !options.delete(:omit_query_string)
@options = options.merge(socket_class: use_proxy? || @allow_local ? ProxySocket : Socket)
@options = @options.merge(timeout_class: PerOperationWithDeadline, timeout_options: TIMEOUT)
@options = @options.merge(proxy_url) if use_proxy?
diff --git a/app/lib/search_query_transformer.rb b/app/lib/search_query_transformer.rb
index 606819ed40..1306ed12ed 100644
--- a/app/lib/search_query_transformer.rb
+++ b/app/lib/search_query_transformer.rb
@@ -168,15 +168,15 @@ class SearchQueryTransformer < Parslet::Transform
when 'before'
@filter = :created_at
@type = :range
- @term = { lt: term, time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' }
+ @term = { lt: TermValidator.validate_date!(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' }
when 'after'
@filter = :created_at
@type = :range
- @term = { gt: term, time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' }
+ @term = { gt: TermValidator.validate_date!(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' }
when 'during'
@filter = :created_at
@type = :range
- @term = { gte: term, lte: term, time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' }
+ @term = { gte: TermValidator.validate_date!(term), lte: TermValidator.validate_date!(term), time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' }
when 'in'
@operator = :flag
@term = term
@@ -224,6 +224,17 @@ class SearchQueryTransformer < Parslet::Transform
end
end
+ class TermValidator
+ STRICT_DATE_REGEX = /\A\d{4}-\d{2}-\d{2}\z/ # yyyy-MM-dd
+ EPOCH_MILLIS_REGEX = /\A\d{1,19}\z/
+
+ def self.validate_date!(value)
+ return value if value.match?(STRICT_DATE_REGEX) || value.match?(EPOCH_MILLIS_REGEX)
+
+ raise Mastodon::FilterValidationError, "Invalid date #{value}"
+ end
+ end
+
rule(clause: subtree(:clause)) do
prefix = clause[:prefix][:term].to_s.downcase if clause[:prefix]
operator = clause[:operator]&.to_s
diff --git a/app/lib/vacuum/system_keys_vacuum.rb b/app/lib/vacuum/system_keys_vacuum.rb
deleted file mode 100644
index ceee2fd164..0000000000
--- a/app/lib/vacuum/system_keys_vacuum.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class Vacuum::SystemKeysVacuum
- def perform
- vacuum_expired_system_keys!
- end
-
- private
-
- def vacuum_expired_system_keys!
- SystemKey.expired.delete_all
- end
-end
diff --git a/app/mailers/admin_mailer.rb b/app/mailers/admin_mailer.rb
index 8dd7b6e59f..fffbbb3c6d 100644
--- a/app/mailers/admin_mailer.rb
+++ b/app/mailers/admin_mailer.rb
@@ -9,6 +9,8 @@ class AdminMailer < ApplicationMailer
before_action :process_params
before_action :set_instance
+ after_action :set_important_headers!, only: :new_critical_software_updates
+
default to: -> { @me.user_email }
def new_report(report)
@@ -56,10 +58,6 @@ class AdminMailer < ApplicationMailer
def new_critical_software_updates
@software_updates = SoftwareUpdate.where(urgent: true).to_a.sort_by(&:gem_version)
- headers['Priority'] = 'urgent'
- headers['X-Priority'] = '1'
- headers['Importance'] = 'high'
-
locale_for_account(@me) do
mail subject: default_i18n_subject(instance: @instance)
end
@@ -80,4 +78,12 @@ class AdminMailer < ApplicationMailer
def set_instance
@instance = Rails.configuration.x.local_domain
end
+
+ def set_important_headers!
+ headers(
+ 'Importance' => 'high',
+ 'Priority' => 'urgent',
+ 'X-Priority' => '1'
+ )
+ end
end
diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb
index 3312183d47..9a209aa77b 100644
--- a/app/mailers/application_mailer.rb
+++ b/app/mailers/application_mailer.rb
@@ -12,12 +12,14 @@ class ApplicationMailer < ActionMailer::Base
protected
def locale_for_account(account, &block)
- I18n.with_locale(account.user_locale || I18n.locale || I18n.default_locale, &block)
+ I18n.with_locale(account.user_locale || I18n.default_locale, &block)
end
def set_autoreply_headers!
- headers['Precedence'] = 'list'
- headers['X-Auto-Response-Suppress'] = 'All'
- headers['Auto-Submitted'] = 'auto-generated'
+ headers(
+ 'Auto-Submitted' => 'auto-generated',
+ 'Precedence' => 'list',
+ 'X-Auto-Response-Suppress' => 'All'
+ )
end
end
diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb
index f011b266f7..cbc3c1ce51 100644
--- a/app/mailers/notification_mailer.rb
+++ b/app/mailers/notification_mailer.rb
@@ -6,36 +6,37 @@ class NotificationMailer < ApplicationMailer
:routing
before_action :process_params
- before_action :set_status, only: [:mention, :favourite, :reaction, :reblog]
- before_action :set_account, only: [:follow, :favourite, :reaction, :reblog, :follow_request]
+ with_options only: %i(mention favourite reblog) do
+ before_action :set_status
+ after_action :thread_by_conversation!
+ end
+ before_action :set_account, only: [:follow, :favourite, :reblog, :follow_request]
after_action :set_list_headers!
+ before_deliver :verify_functional_user
+
default to: -> { email_address_with_name(@user.email, @me.username) }
layout 'mailer'
def mention
- return unless @user.functional? && @status.present?
+ return if @status.blank?
locale_for_account(@me) do
- thread_by_conversation(@status.conversation)
mail subject: default_i18n_subject(name: @status.account.acct)
end
end
def follow
- return unless @user.functional?
-
locale_for_account(@me) do
mail subject: default_i18n_subject(name: @account.acct)
end
end
def favourite
- return unless @user.functional? && @status.present?
+ return if @status.blank?
locale_for_account(@me) do
- thread_by_conversation(@status.conversation)
mail subject: default_i18n_subject(name: @account.acct)
end
end
@@ -50,17 +51,14 @@ class NotificationMailer < ApplicationMailer
end
def reblog
- return unless @user.functional? && @status.present?
+ return if @status.blank?
locale_for_account(@me) do
- thread_by_conversation(@status.conversation)
mail subject: default_i18n_subject(name: @account.acct)
end
end
def follow_request
- return unless @user.functional?
-
locale_for_account(@me) do
mail subject: default_i18n_subject(name: @account.acct)
end
@@ -84,18 +82,26 @@ class NotificationMailer < ApplicationMailer
@account = @notification.from_account
end
- def set_list_headers!
- headers['List-ID'] = "<#{@type}.#{@me.username}.#{Rails.configuration.x.local_domain}>"
- headers['List-Unsubscribe'] = "<#{@unsubscribe_url}>"
- headers['List-Unsubscribe-Post'] = 'List-Unsubscribe=One-Click'
+ def verify_functional_user
+ throw(:abort) unless @user.functional?
end
- def thread_by_conversation(conversation)
- return if conversation.nil?
+ def set_list_headers!
+ headers(
+ 'List-ID' => "<#{@type}.#{@me.username}.#{Rails.configuration.x.local_domain}>",
+ 'List-Unsubscribe-Post' => 'List-Unsubscribe=One-Click',
+ 'List-Unsubscribe' => "<#{@unsubscribe_url}>"
+ )
+ end
- msg_id = ""
+ def thread_by_conversation!
+ return if @status.conversation.nil?
- headers['In-Reply-To'] = msg_id
- headers['References'] = msg_id
+ conversation_message_id = ""
+
+ headers(
+ 'In-Reply-To' => conversation_message_id,
+ 'References' => conversation_message_id
+ )
end
end
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index 81a2c0c6d0..5c9e5c96d9 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -33,7 +33,7 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
- I18n.with_locale(locale) do
+ I18n.with_locale(locale(use_current_locale: true)) do
mail subject: default_devise_subject
end
end
@@ -43,7 +43,7 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
- I18n.with_locale(locale) do
+ I18n.with_locale(locale(use_current_locale: true)) do
mail subject: default_devise_subject
end
end
@@ -53,7 +53,7 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
- I18n.with_locale(locale) do
+ I18n.with_locale(locale(use_current_locale: true)) do
mail subject: default_devise_subject
end
end
@@ -63,7 +63,7 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
- I18n.with_locale(locale) do
+ I18n.with_locale(locale(use_current_locale: true)) do
mail subject: default_devise_subject
end
end
@@ -73,7 +73,7 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
- I18n.with_locale(locale) do
+ I18n.with_locale(locale(use_current_locale: true)) do
mail subject: default_devise_subject
end
end
@@ -83,7 +83,7 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
- I18n.with_locale(locale) do
+ I18n.with_locale(locale(use_current_locale: true)) do
mail subject: default_devise_subject
end
end
@@ -93,7 +93,7 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
- I18n.with_locale(locale) do
+ I18n.with_locale(locale(use_current_locale: true)) do
mail subject: default_devise_subject
end
end
@@ -103,7 +103,7 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
- I18n.with_locale(locale) do
+ I18n.with_locale(locale(use_current_locale: true)) do
mail subject: default_devise_subject
end
end
@@ -114,7 +114,7 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
- I18n.with_locale(locale) do
+ I18n.with_locale(locale(use_current_locale: true)) do
mail subject: I18n.t('devise.mailer.webauthn_credential.added.subject')
end
end
@@ -125,7 +125,7 @@ class UserMailer < Devise::Mailer
return unless @resource.active_for_authentication?
- I18n.with_locale(locale) do
+ I18n.with_locale(locale(use_current_locale: true)) do
mail subject: I18n.t('devise.mailer.webauthn_credential.deleted.subject')
end
end
@@ -219,7 +219,7 @@ class UserMailer < Devise::Mailer
@instance = Rails.configuration.x.local_domain
end
- def locale
- @resource.locale.presence || I18n.locale || I18n.default_locale
+ def locale(use_current_locale: false)
+ @resource.locale.presence || (use_current_locale && I18n.locale) || I18n.default_locale
end
end
diff --git a/app/models/account.rb b/app/models/account.rb
index 5ccedc0a89..a9c9d91c89 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -44,22 +44,23 @@
# hide_collections :boolean
# avatar_storage_schema_version :integer
# header_storage_schema_version :integer
-# devices_url :string
# suspension_origin :integer
# sensitized_at :datetime
# trendable :boolean
# reviewed_at :datetime
# requested_review_at :datetime
# indexable :boolean default(FALSE), not null
+# attribution_domains :string default([]), is an Array
#
class Account < ApplicationRecord
self.ignored_columns += %w(
- subscription_expires_at
- secret
+ devices_url
+ hub_url
remote_url
salmon_url
- hub_url
+ secret
+ subscription_expires_at
trust_level
)
@@ -75,6 +76,8 @@ class Account < ApplicationRecord
DISPLAY_NAME_LENGTH_LIMIT = (ENV['MAX_DISPLAY_NAME_CHARS'] || 30).to_i
NOTE_LENGTH_LIMIT = (ENV['MAX_BIO_CHARS'] || 500).to_i
+ AUTOMATED_ACTOR_TYPES = %w(Application Service).freeze
+
include Attachmentable # Load prior to Avatar & Header concerns
include Account::Associations
@@ -86,9 +89,11 @@ class Account < ApplicationRecord
include Account::Merging
include Account::Search
include Account::StatusesSearch
+ include Account::AttributionDomains
include DomainMaterializable
include DomainNormalizable
include Paginable
+ include Reviewable
enum :protocol, { ostatus: 0, activitypub: 1 }
enum :suspension_origin, { local: 0, remote: 1 }, prefix: true
@@ -108,10 +113,12 @@ class Account < ApplicationRecord
validates :display_name, length: { maximum: DISPLAY_NAME_LENGTH_LIMIT }, if: -> { local? && will_save_change_to_display_name? }
validates :note, note_length: { maximum: NOTE_LENGTH_LIMIT }, if: -> { local? && will_save_change_to_note? }
validates :fields, length: { maximum: DEFAULT_FIELDS_SIZE }, if: -> { local? && will_save_change_to_fields? }
- validates :uri, absence: true, if: :local?, on: :create
- validates :inbox_url, absence: true, if: :local?, on: :create
- validates :shared_inbox_url, absence: true, if: :local?, on: :create
- validates :followers_url, absence: true, if: :local?, on: :create
+ with_options on: :create do
+ validates :uri, absence: true, if: :local?
+ validates :inbox_url, absence: true, if: :local?
+ validates :shared_inbox_url, absence: true, if: :local?
+ validates :followers_url, absence: true, if: :local?
+ end
normalizes :username, with: ->(username) { username.squish }
@@ -126,7 +133,8 @@ class Account < ApplicationRecord
scope :without_silenced, -> { where(silenced_at: nil) }
scope :without_instance_actor, -> { where.not(id: INSTANCE_ACTOR_ID) }
scope :recent, -> { reorder(id: :desc) }
- scope :bots, -> { where(actor_type: %w(Application Service)) }
+ scope :bots, -> { where(actor_type: AUTOMATED_ACTOR_TYPES) }
+ scope :non_automated, -> { where.not(actor_type: AUTOMATED_ACTOR_TYPES) }
scope :groups, -> { where(actor_type: 'Group') }
scope :alphabetic, -> { order(domain: :asc, username: :asc) }
scope :matches_uri_prefix, ->(value) { where(arel_table[:uri].matches("#{sanitize_sql_like(value)}/%", false, true)).or(where(uri: value)) }
@@ -145,6 +153,7 @@ class Account < ApplicationRecord
scope :with_username, ->(value) { where arel_table[:username].lower.eq(value.to_s.downcase) }
scope :with_domain, ->(value) { where arel_table[:domain].lower.eq(value&.to_s&.downcase) }
scope :without_memorial, -> { where(memorial: false) }
+ scope :duplicate_uris, -> { select(:uri, Arel.star.count).group(:uri).having(Arel.star.count.gt(1)) }
after_update_commit :trigger_update_webhooks
@@ -181,7 +190,7 @@ class Account < ApplicationRecord
end
def bot?
- %w(Application Service).include? actor_type
+ AUTOMATED_ACTOR_TYPES.include?(actor_type)
end
def instance_actor?
@@ -250,6 +259,10 @@ class Account < ApplicationRecord
suspended_at.present? && !instance_actor?
end
+ def suspended_locally?
+ suspended? && suspension_origin_local?
+ end
+
def suspended_permanently?
suspended? && deletion_request.nil?
end
@@ -421,22 +434,6 @@ class Account < ApplicationRecord
@synchronization_uri_prefix ||= "#{uri[URL_PREFIX_RE]}/"
end
- def requires_review?
- reviewed_at.nil?
- end
-
- def reviewed?
- reviewed_at.present?
- end
-
- def requested_review?
- requested_review_at.present?
- end
-
- def requires_review_notification?
- requires_review? && !requested_review?
- end
-
class << self
def readonly_attributes
super - %w(statuses_count following_count followers_count)
diff --git a/app/models/account/field.rb b/app/models/account/field.rb
index 2bada6954b..bcd89015de 100644
--- a/app/models/account/field.rb
+++ b/app/models/account/field.rb
@@ -73,10 +73,10 @@ class Account::Field < ActiveModelSerializers::Model
end
def extract_url_from_html
- doc = Nokogiri::HTML(value).at_xpath('//body')
+ doc = Nokogiri::HTML5.fragment(value)
return if doc.nil?
- return if doc.children.size > 1
+ return if doc.children.size != 1
element = doc.children.first
diff --git a/app/models/account_migration.rb b/app/models/account_migration.rb
index dc22e32942..7a01e250e2 100644
--- a/app/models/account_migration.rb
+++ b/app/models/account_migration.rb
@@ -31,10 +31,14 @@ class AccountMigration < ApplicationRecord
validate :validate_migration_cooldown
validate :validate_target_account
- scope :within_cooldown, ->(now = Time.now.utc) { where(arel_table[:created_at].gteq(now - COOLDOWN_PERIOD)) }
+ scope :within_cooldown, -> { where(created_at: cooldown_duration_ago..) }
attr_accessor :current_password, :current_username
+ def self.cooldown_duration_ago
+ Time.current - COOLDOWN_PERIOD
+ end
+
def save_with_challenge(current_user)
if current_user.encrypted_password.present?
errors.add(:current_password, :invalid) unless current_user.valid_password?(current_password)
diff --git a/app/models/account_moderation_note.rb b/app/models/account_moderation_note.rb
index 79b8b4d25e..ca7f8e3d5f 100644
--- a/app/models/account_moderation_note.rb
+++ b/app/models/account_moderation_note.rb
@@ -18,7 +18,7 @@ class AccountModerationNote < ApplicationRecord
belongs_to :account
belongs_to :target_account, class_name: 'Account'
- scope :latest, -> { reorder('created_at DESC') }
+ scope :chronological, -> { reorder(id: :asc) }
validates :content, presence: true, length: { maximum: CONTENT_SIZE_LIMIT }
end
diff --git a/app/models/account_statuses_cleanup_policy.rb b/app/models/account_statuses_cleanup_policy.rb
index a102795446..6e998e2dca 100644
--- a/app/models/account_statuses_cleanup_policy.rb
+++ b/app/models/account_statuses_cleanup_policy.rb
@@ -145,19 +145,19 @@ class AccountStatusesCleanupPolicy < ApplicationRecord
end
def without_self_fav_scope
- Status.where('NOT EXISTS (SELECT 1 FROM favourites fav WHERE fav.account_id = statuses.account_id AND fav.status_id = statuses.id)')
+ Status.where.not(self_status_reference_exists(Favourite))
end
def without_self_bookmark_scope
- Status.where('NOT EXISTS (SELECT 1 FROM bookmarks bookmark WHERE bookmark.account_id = statuses.account_id AND bookmark.status_id = statuses.id)')
+ Status.where.not(self_status_reference_exists(Bookmark))
end
def without_pinned_scope
- Status.where('NOT EXISTS (SELECT 1 FROM status_pins pin WHERE pin.account_id = statuses.account_id AND pin.status_id = statuses.id)')
+ Status.where.not(self_status_reference_exists(StatusPin))
end
def without_media_scope
- Status.where('NOT EXISTS (SELECT 1 FROM media_attachments media WHERE media.status_id = statuses.id)')
+ Status.where.not(status_media_reference_exists)
end
def without_poll_scope
@@ -174,4 +174,21 @@ class AccountStatusesCleanupPolicy < ApplicationRecord
def account_statuses
Status.where(account_id: account_id)
end
+
+ def status_media_reference_exists
+ MediaAttachment
+ .where(MediaAttachment.arel_table[:status_id].eq Status.arel_table[:id])
+ .select(1)
+ .arel
+ .exists
+ end
+
+ def self_status_reference_exists(model)
+ model
+ .where(model.arel_table[:account_id].eq Status.arel_table[:account_id])
+ .where(model.arel_table[:status_id].eq Status.arel_table[:id])
+ .select(1)
+ .arel
+ .exists
+ end
end
diff --git a/app/models/admin/account_action.rb b/app/models/admin/account_action.rb
index 3700ce4cd6..7c66b6e646 100644
--- a/app/models/admin/account_action.rb
+++ b/app/models/admin/account_action.rb
@@ -73,6 +73,14 @@ class Admin::AccountAction
end
end
+ def disabled_types_for_account(account)
+ if account.suspended_locally?
+ %w(silence suspend)
+ elsif account.silenced?
+ %w(silence)
+ end
+ end
+
def i18n_scope
:activerecord
end
diff --git a/app/models/announcement_reaction.rb b/app/models/announcement_reaction.rb
index 9881892c4b..f953402b7e 100644
--- a/app/models/announcement_reaction.rb
+++ b/app/models/announcement_reaction.rb
@@ -27,7 +27,7 @@ class AnnouncementReaction < ApplicationRecord
private
def set_custom_emoji
- self.custom_emoji = CustomEmoji.local.find_by(disabled: false, shortcode: name) if name.present?
+ self.custom_emoji = CustomEmoji.local.enabled.find_by(shortcode: name) if name.present?
end
def queue_publish
diff --git a/app/models/concerns/account/associations.rb b/app/models/concerns/account/associations.rb
index 2bfd9fa54a..7cb334ffd0 100644
--- a/app/models/concerns/account/associations.rb
+++ b/app/models/concerns/account/associations.rb
@@ -7,9 +7,6 @@ module Account::Associations
# Local users
has_one :user, inverse_of: :account, dependent: :destroy
- # E2EE
- has_many :devices, dependent: :destroy, inverse_of: :account
-
# Timelines
has_many :statuses, inverse_of: :account, dependent: :destroy
has_many :favourites, inverse_of: :account, dependent: :destroy
diff --git a/app/models/concerns/account/attribution_domains.rb b/app/models/concerns/account/attribution_domains.rb
new file mode 100644
index 0000000000..163c2291fe
--- /dev/null
+++ b/app/models/concerns/account/attribution_domains.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Account::AttributionDomains
+ extend ActiveSupport::Concern
+
+ included do
+ validates :attribution_domains_as_text, domain: { multiline: true }, lines: { maximum: 100 }, if: -> { local? && will_save_change_to_attribution_domains? }
+ end
+
+ def attribution_domains_as_text
+ self[:attribution_domains].join("\n")
+ end
+
+ def attribution_domains_as_text=(str)
+ self[:attribution_domains] = str.split.filter_map do |line|
+ line
+ .strip
+ .delete_prefix('http://')
+ .delete_prefix('https://')
+ .delete_prefix('*.')
+ end
+ end
+
+ def can_be_attributed_from?(domain)
+ segments = domain.split('.')
+ variants = segments.map.with_index { |_, i| segments[i..].join('.') }.to_set
+ self[:attribution_domains].to_set.intersect?(variants)
+ end
+end
diff --git a/app/models/concerns/redisable.rb b/app/models/concerns/redisable.rb
index 0dad3abb2b..01763fa297 100644
--- a/app/models/concerns/redisable.rb
+++ b/app/models/concerns/redisable.rb
@@ -2,10 +2,10 @@
module Redisable
def redis
- Thread.current[:redis] ||= RedisConfiguration.pool.checkout
+ Thread.current[:redis] ||= RedisConnection.pool.checkout
end
def with_redis(&block)
- RedisConfiguration.with(&block)
+ RedisConnection.with(&block)
end
end
diff --git a/app/models/concerns/reviewable.rb b/app/models/concerns/reviewable.rb
new file mode 100644
index 0000000000..d08b473342
--- /dev/null
+++ b/app/models/concerns/reviewable.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Reviewable
+ extend ActiveSupport::Concern
+
+ included do
+ scope :reviewed, -> { where.not(reviewed_at: nil) }
+ scope :unreviewed, -> { where(reviewed_at: nil) }
+ end
+
+ def requires_review?
+ reviewed_at.nil?
+ end
+
+ def reviewed?
+ reviewed_at.present?
+ end
+
+ def requested_review?
+ requested_review_at.present?
+ end
+
+ def requires_review_notification?
+ requires_review? && !requested_review?
+ end
+end
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 7ea50e85d8..df4696c9ce 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -26,6 +26,7 @@ class CustomEmoji < ApplicationRecord
LOCAL_LIMIT = (ENV['MAX_EMOJI_SIZE'] || 256.kilobytes).to_i
LIMIT = [LOCAL_LIMIT, (ENV['MAX_REMOTE_EMOJI_SIZE'] || 256.kilobytes).to_i].max
+ MINIMUM_SHORTCODE_SIZE = 2
SHORTCODE_RE_FRAGMENT = '[a-zA-Z0-9_]{2,}'
@@ -47,13 +48,14 @@ class CustomEmoji < ApplicationRecord
validates_attachment :image, content_type: { content_type: IMAGE_MIME_TYPES }, presence: true
validates_attachment_size :image, less_than: LIMIT, unless: :local?
validates_attachment_size :image, less_than: LOCAL_LIMIT, if: :local?
- validates :shortcode, uniqueness: { scope: :domain }, format: { with: SHORTCODE_ONLY_RE }, length: { minimum: 2 }
+ validates :shortcode, uniqueness: { scope: :domain }, format: { with: SHORTCODE_ONLY_RE }, length: { minimum: MINIMUM_SHORTCODE_SIZE }
scope :local, -> { where(domain: nil) }
scope :remote, -> { where.not(domain: nil) }
+ scope :enabled, -> { where(disabled: false) }
scope :alphabetic, -> { order(domain: :asc, shortcode: :asc) }
scope :by_domain_and_subdomains, ->(domain) { where(domain: domain).or(where(arel_table[:domain].matches("%.#{domain}"))) }
- scope :listed, -> { local.where(disabled: false).where(visible_in_picker: true) }
+ scope :listed, -> { local.enabled.where(visible_in_picker: true) }
remotable_attachment :image, LIMIT
diff --git a/app/models/device.rb b/app/models/device.rb
deleted file mode 100644
index 5dc6cf1e66..0000000000
--- a/app/models/device.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: devices
-#
-# id :bigint(8) not null, primary key
-# access_token_id :bigint(8)
-# account_id :bigint(8)
-# device_id :string default(""), not null
-# name :string default(""), not null
-# fingerprint_key :text default(""), not null
-# identity_key :text default(""), not null
-# created_at :datetime not null
-# updated_at :datetime not null
-#
-
-class Device < ApplicationRecord
- belongs_to :access_token, class_name: 'Doorkeeper::AccessToken'
- belongs_to :account
-
- has_many :one_time_keys, dependent: :destroy, inverse_of: :device
- has_many :encrypted_messages, dependent: :destroy, inverse_of: :device
-
- validates :name, :fingerprint_key, :identity_key, presence: true
- validates :fingerprint_key, :identity_key, ed25519_key: true
-
- before_save :invalidate_associations, if: -> { device_id_changed? || fingerprint_key_changed? || identity_key_changed? }
-
- private
-
- def invalidate_associations
- one_time_keys.destroy_all
- encrypted_messages.destroy_all
- end
-end
diff --git a/app/models/encrypted_message.rb b/app/models/encrypted_message.rb
deleted file mode 100644
index 3e7e95594c..0000000000
--- a/app/models/encrypted_message.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: encrypted_messages
-#
-# id :bigint(8) not null, primary key
-# device_id :bigint(8)
-# from_account_id :bigint(8)
-# from_device_id :string default(""), not null
-# type :integer default(0), not null
-# body :text default(""), not null
-# digest :text default(""), not null
-# message_franking :text default(""), not null
-# created_at :datetime not null
-# updated_at :datetime not null
-#
-
-class EncryptedMessage < ApplicationRecord
- self.inheritance_column = nil
-
- include Paginable
- include Redisable
-
- scope :up_to, ->(id) { where(arel_table[:id].lteq(id)) }
-
- belongs_to :device
- belongs_to :from_account, class_name: 'Account'
-
- around_create Mastodon::Snowflake::Callbacks
-
- after_commit :push_to_streaming_api
-
- private
-
- def push_to_streaming_api
- return if destroyed? || !subscribed_to_timeline?
-
- PushEncryptedMessageWorker.perform_async(id)
- end
-
- def subscribed_to_timeline?
- redis.exists?("subscribed:#{streaming_channel}")
- end
-
- def streaming_channel
- "timeline:#{device.account_id}:#{device.device_id}"
- end
-end
diff --git a/app/models/featured_tag.rb b/app/models/featured_tag.rb
index cdd97205eb..a4e7b7cf6f 100644
--- a/app/models/featured_tag.rb
+++ b/app/models/featured_tag.rb
@@ -45,7 +45,7 @@ class FeaturedTag < ApplicationRecord
end
def decrement(deleted_status_id)
- update(statuses_count: [0, statuses_count - 1].max, last_status_at: visible_tagged_account_statuses.where.not(id: deleted_status_id).select(:created_at).first&.created_at)
+ update(statuses_count: [0, statuses_count - 1].max, last_status_at: visible_tagged_account_statuses.where.not(id: deleted_status_id).pick(:created_at))
end
private
@@ -56,7 +56,7 @@ class FeaturedTag < ApplicationRecord
def reset_data
self.statuses_count = visible_tagged_account_statuses.count
- self.last_status_at = visible_tagged_account_statuses.select(:created_at).first&.created_at
+ self.last_status_at = visible_tagged_account_statuses.pick(:created_at)
end
def validate_featured_tags_limit
diff --git a/app/models/list.rb b/app/models/list.rb
index b45bd057bc..d4915f56fa 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -20,21 +20,23 @@ class List < ApplicationRecord
enum :replies_policy, { list: 0, followed: 1, none: 2 }, prefix: :show
- belongs_to :account, optional: true
+ belongs_to :account
has_many :list_accounts, inverse_of: :list, dependent: :destroy
has_many :accounts, through: :list_accounts
validates :title, presence: true
- validates_each :account_id, on: :create do |record, _attr, value|
- record.errors.add(:base, I18n.t('lists.errors.limit')) if List.where(account_id: value).count >= PER_ACCOUNT_LIMIT
- end
+ validate :validate_account_lists_limit, on: :create
before_destroy :clean_feed_manager
private
+ def validate_account_lists_limit
+ errors.add(:base, I18n.t('lists.errors.limit')) if account.lists.count >= PER_ACCOUNT_LIMIT
+ end
+
def clean_feed_manager
FeedManager.instance.clean_feeds!(:list, [id])
end
diff --git a/app/models/list_account.rb b/app/models/list_account.rb
index e7016f2714..2ff8605717 100644
--- a/app/models/list_account.rb
+++ b/app/models/list_account.rb
@@ -20,13 +20,11 @@ class ListAccount < ApplicationRecord
validates :account_id, uniqueness: { scope: :list_id }
validate :validate_relationship
- before_validation :set_follow
+ before_validation :set_follow, unless: :list_owner_account_is_account?
private
def set_follow
- return if list.account_id == account.id
-
self.follow = Follow.find_by!(account_id: list.account_id, target_account_id: account.id)
rescue ActiveRecord::RecordNotFound
self.follow_request = FollowRequest.find_by!(account_id: list.account_id, target_account_id: account.id)
@@ -39,4 +37,8 @@ class ListAccount < ApplicationRecord
errors.add(:follow, 'mismatched accounts') if follow_id.present? && follow.target_account_id != account_id
errors.add(:follow_request, 'mismatched accounts') if follow_request_id.present? && follow_request.target_account_id != account_id
end
+
+ def list_owner_account_is_account?
+ list.account_id == account_id
+ end
end
diff --git a/app/models/mention.rb b/app/models/mention.rb
index af9bb7378b..a508ed630e 100644
--- a/app/models/mention.rb
+++ b/app/models/mention.rb
@@ -29,8 +29,4 @@ class Mention < ApplicationRecord
to: :account,
prefix: true
)
-
- def active?
- !silent?
- end
end
diff --git a/app/models/message_franking.rb b/app/models/message_franking.rb
deleted file mode 100644
index c72bd1ccac..0000000000
--- a/app/models/message_franking.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class MessageFranking
- attr_reader :hmac, :source_account_id, :target_account_id,
- :timestamp, :original_franking
-
- def initialize(attributes = {})
- @hmac = attributes[:hmac]
- @source_account_id = attributes[:source_account_id]
- @target_account_id = attributes[:target_account_id]
- @timestamp = attributes[:timestamp]
- @original_franking = attributes[:original_franking]
- end
-
- def to_token
- crypt = ActiveSupport::MessageEncryptor.new(SystemKey.current_key, serializer: Oj)
- crypt.encrypt_and_sign(self)
- end
-end
diff --git a/app/models/notification.rb b/app/models/notification.rb
index 49999059ed..4725404b90 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -20,6 +20,7 @@ class Notification < ApplicationRecord
self.inheritance_column = nil
include Paginable
+ include Redisable
LEGACY_TYPE_CLASS_MAP = {
'Mention' => :mention,
@@ -31,6 +32,10 @@ class Notification < ApplicationRecord
'Poll' => :poll,
}.freeze
+ # `set_group_key!` needs to be updated if this list changes
+ GROUPABLE_NOTIFICATION_TYPES = %i(favourite reblog follow).freeze
+ MAXIMUM_GROUP_SPAN_HOURS = 12
+
# Please update app/javascript/api_types/notification.ts if you change this
PROPERTIES = {
mention: {
@@ -129,6 +134,30 @@ class Notification < ApplicationRecord
end
end
+ def set_group_key!
+ return if filtered? || Notification::GROUPABLE_NOTIFICATION_TYPES.exclude?(type)
+
+ type_prefix = case type
+ when :favourite, :reblog
+ [type, target_status&.id].join('-')
+ when :follow
+ type
+ else
+ raise NotImplementedError
+ end
+ redis_key = "notif-group/#{account.id}/#{type_prefix}"
+ hour_bucket = activity.created_at.utc.to_i / 1.hour.to_i
+
+ # Reuse previous group if it does not span too large an amount of time
+ previous_bucket = redis.get(redis_key).to_i
+ hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS
+
+ # We do not concern ourselves with race conditions since we use hour buckets
+ redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i)
+
+ self.group_key = "#{type_prefix}-#{hour_bucket}"
+ end
+
class << self
def browserable(types: [], exclude_types: [], from_account_id: nil, include_filtered: false)
requested_types = if types.empty?
@@ -146,17 +175,40 @@ class Notification < ApplicationRecord
end
end
- def paginate_groups(limit, pagination_order)
+ def paginate_groups(limit, pagination_order, grouped_types: nil)
raise ArgumentError unless %i(asc desc).include?(pagination_order)
query = reorder(id: pagination_order)
+ # Ideally `:types` would be a bind rather than part of the SQL itself, but that does not
+ # seem to be possible to do with Rails, considering that the expression would occur in
+ # multiple places, including in a `select`
+ group_key_sql = begin
+ if grouped_types.present?
+ # Normalize `grouped_types` so the number of different SQL query shapes remains small, and
+ # the queries can be analyzed in monitoring/telemetry tools
+ grouped_types = (grouped_types.map(&:to_sym) & GROUPABLE_NOTIFICATION_TYPES).sort
+
+ sanitize_sql_array([<<~SQL.squish, { types: grouped_types }])
+ COALESCE(
+ CASE
+ WHEN notifications.type IN (:types) THEN notifications.group_key
+ ELSE NULL
+ END,
+ 'ungrouped-' || notifications.id
+ )
+ SQL
+ else
+ "COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)"
+ end
+ end
+
unscoped
.with_recursive(
grouped_notifications: [
# Base case: fetching one notification and annotating it with visited groups
query
- .select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] AS groups")
+ .select('notifications.*', "ARRAY[#{group_key_sql}] AS groups")
.limit(1),
# Recursive case, always yielding at most one annotated notification
unscoped
@@ -171,12 +223,12 @@ class Notification < ApplicationRecord
# Recursive query, using `LATERAL` so we can refer to `wt`
query
.where(pagination_order == :desc ? 'notifications.id < wt.id' : 'notifications.id > wt.id')
- .where.not("COALESCE(notifications.group_key, 'ungrouped-' || notifications.id) = ANY(wt.groups)")
+ .where.not("#{group_key_sql} = ANY(wt.groups)")
.limit(1)
.arel.lateral('notifications'),
]
)
- .select('notifications.*', "array_append(wt.groups, COALESCE(notifications.group_key, 'ungrouped-' || notifications.id))"),
+ .select('notifications.*', "array_append(wt.groups, #{group_key_sql}) AS groups"),
]
)
.from('grouped_notifications AS notifications')
@@ -186,28 +238,28 @@ class Notification < ApplicationRecord
# This returns notifications from the request page, but with at most one notification per group.
# Notifications that have no `group_key` each count as a separate group.
- def paginate_groups_by_max_id(limit, max_id: nil, since_id: nil)
+ def paginate_groups_by_max_id(limit, max_id: nil, since_id: nil, grouped_types: nil)
query = reorder(id: :desc)
query = query.where(id: ...(max_id.to_i)) if max_id.present?
query = query.where(id: (since_id.to_i + 1)...) if since_id.present?
- query.paginate_groups(limit, :desc)
+ query.paginate_groups(limit, :desc, grouped_types: grouped_types)
end
# Differs from :paginate_groups_by_max_id in that it gives the results immediately following min_id,
# whereas since_id gives the items with largest id, but with since_id as a cutoff.
# Results will be in ascending order by id.
- def paginate_groups_by_min_id(limit, max_id: nil, min_id: nil)
+ def paginate_groups_by_min_id(limit, max_id: nil, min_id: nil, grouped_types: nil)
query = reorder(id: :asc)
query = query.where(id: (min_id.to_i + 1)...) if min_id.present?
query = query.where(id: ...(max_id.to_i)) if max_id.present?
- query.paginate_groups(limit, :asc)
+ query.paginate_groups(limit, :asc, grouped_types: grouped_types)
end
def to_a_grouped_paginated_by_id(limit, options = {})
if options[:min_id].present?
- paginate_groups_by_min_id(limit, min_id: options[:min_id], max_id: options[:max_id]).reverse
+ paginate_groups_by_min_id(limit, min_id: options[:min_id], max_id: options[:max_id], grouped_types: options[:grouped_types]).reverse
else
- paginate_groups_by_max_id(limit, max_id: options[:max_id], since_id: options[:since_id]).to_a
+ paginate_groups_by_max_id(limit, max_id: options[:max_id], since_id: options[:since_id], grouped_types: options[:grouped_types]).to_a
end
end
diff --git a/app/models/notification_group.rb b/app/models/notification_group.rb
index 223945f07b..b6aa4d309c 100644
--- a/app/models/notification_group.rb
+++ b/app/models/notification_group.rb
@@ -1,35 +1,49 @@
# frozen_string_literal: true
class NotificationGroup < ActiveModelSerializers::Model
- attributes :group_key, :sample_accounts, :notifications_count, :notification, :most_recent_notification_id
+ attributes :group_key, :sample_accounts, :notifications_count, :notification, :most_recent_notification_id, :pagination_data
# Try to keep this consistent with `app/javascript/mastodon/models/notification_group.ts`
SAMPLE_ACCOUNTS_SIZE = 8
- def self.from_notification(notification, max_id: nil)
- if notification.group_key.present?
- # TODO: caching, and, if caching, preloading
- scope = notification.account.notifications.where(group_key: notification.group_key)
- scope = scope.where(id: ..max_id) if max_id.present?
+ def self.from_notifications(notifications, pagination_range: nil, grouped_types: nil)
+ return [] if notifications.empty?
- # Ideally, we would not load accounts for each notification group
- most_recent_notifications = scope.order(id: :desc).includes(:from_account).take(SAMPLE_ACCOUNTS_SIZE)
- most_recent_id = most_recent_notifications.first.id
- sample_accounts = most_recent_notifications.map(&:from_account)
- notifications_count = scope.count
- else
- most_recent_id = notification.id
- sample_accounts = [notification.from_account]
- notifications_count = 1
+ grouped_types = grouped_types.presence&.map(&:to_sym) || Notification::GROUPABLE_NOTIFICATION_TYPES
+
+ grouped_notifications = notifications.filter { |notification| notification.group_key.present? && grouped_types.include?(notification.type) }
+ group_keys = grouped_notifications.pluck(:group_key)
+
+ groups_data = load_groups_data(notifications.first.account_id, group_keys, pagination_range: pagination_range)
+ accounts_map = Account.where(id: groups_data.values.pluck(1).flatten).index_by(&:id)
+
+ notifications.map do |notification|
+ if notification.group_key.present? && grouped_types.include?(notification.type)
+ most_recent_notification_id, sample_account_ids, count, *raw_pagination_data = groups_data[notification.group_key]
+
+ pagination_data = raw_pagination_data.empty? ? nil : { min_id: raw_pagination_data[0], latest_notification_at: raw_pagination_data[1] }
+
+ NotificationGroup.new(
+ notification: notification,
+ group_key: notification.group_key,
+ sample_accounts: sample_account_ids.map { |id| accounts_map[id] },
+ notifications_count: count,
+ most_recent_notification_id: most_recent_notification_id,
+ pagination_data: pagination_data
+ )
+ else
+ pagination_data = pagination_range.blank? ? nil : { min_id: notification.id, latest_notification_at: notification.created_at }
+
+ NotificationGroup.new(
+ notification: notification,
+ group_key: "ungrouped-#{notification.id}",
+ sample_accounts: [notification.from_account],
+ notifications_count: 1,
+ most_recent_notification_id: notification.id,
+ pagination_data: pagination_data
+ )
+ end
end
-
- NotificationGroup.new(
- notification: notification,
- group_key: notification.group_key || "ungrouped-#{notification.id}",
- sample_accounts: sample_accounts,
- notifications_count: notifications_count,
- most_recent_notification_id: most_recent_id
- )
end
delegate :type,
@@ -38,4 +52,50 @@ class NotificationGroup < ActiveModelSerializers::Model
:account_relationship_severance_event,
:account_warning,
to: :notification, prefix: false
+
+ class << self
+ private
+
+ def load_groups_data(account_id, group_keys, pagination_range: nil)
+ return {} if group_keys.empty?
+
+ if pagination_range.present?
+ binds = [
+ account_id,
+ SAMPLE_ACCOUNTS_SIZE,
+ pagination_range.begin,
+ pagination_range.end,
+ ActiveRecord::Relation::QueryAttribute.new('group_keys', group_keys, ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.new(ActiveModel::Type::String.new)),
+ ]
+
+ ActiveRecord::Base.connection.select_all(<<~SQL.squish, 'grouped_notifications', binds).cast_values.to_h { |k, *values| [k, values] }
+ SELECT
+ groups.group_key,
+ (SELECT id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id <= $4 ORDER BY id DESC LIMIT 1),
+ array(SELECT from_account_id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id <= $4 ORDER BY id DESC LIMIT $2),
+ (SELECT count(*) FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id <= $4) AS notifications_count,
+ (SELECT id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id >= $3 ORDER BY id ASC LIMIT 1) AS min_id,
+ (SELECT created_at FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id <= $4 ORDER BY id DESC LIMIT 1)
+ FROM
+ unnest($5::text[]) AS groups(group_key);
+ SQL
+ else
+ binds = [
+ account_id,
+ SAMPLE_ACCOUNTS_SIZE,
+ ActiveRecord::Relation::QueryAttribute.new('group_keys', group_keys, ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.new(ActiveModel::Type::String.new)),
+ ]
+
+ ActiveRecord::Base.connection.select_all(<<~SQL.squish, 'grouped_notifications', binds).cast_values.to_h { |k, *values| [k, values] }
+ SELECT
+ groups.group_key,
+ (SELECT id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key ORDER BY id DESC LIMIT 1),
+ array(SELECT from_account_id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key ORDER BY id DESC LIMIT $2),
+ (SELECT count(*) FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key) AS notifications_count
+ FROM
+ unnest($3::text[]) AS groups(group_key);
+ SQL
+ end
+ end
+ end
end
diff --git a/app/models/one_time_key.rb b/app/models/one_time_key.rb
deleted file mode 100644
index 23604e2f7d..0000000000
--- a/app/models/one_time_key.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: one_time_keys
-#
-# id :bigint(8) not null, primary key
-# device_id :bigint(8)
-# key_id :string default(""), not null
-# key :text default(""), not null
-# signature :text default(""), not null
-# created_at :datetime not null
-# updated_at :datetime not null
-#
-
-class OneTimeKey < ApplicationRecord
- belongs_to :device
-
- validates :key_id, :key, :signature, presence: true
- validates :key, ed25519_key: true
- validates :signature, ed25519_signature: { message: :key, verify_key: ->(one_time_key) { one_time_key.device.fingerprint_key } }
-end
diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb
index 5a11351e58..7579178f83 100644
--- a/app/models/preview_card.rb
+++ b/app/models/preview_card.rb
@@ -39,7 +39,7 @@ class PreviewCard < ApplicationRecord
include Attachmentable
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze
- LIMIT = 2.megabytes
+ LIMIT = Rails.configuration.x.use_vips ? 8.megabytes : 2.megabytes
BLURHASH_OPTIONS = {
x_comp: 4,
diff --git a/app/models/preview_card_provider.rb b/app/models/preview_card_provider.rb
index 756707e3f1..889176036c 100644
--- a/app/models/preview_card_provider.rb
+++ b/app/models/preview_card_provider.rb
@@ -21,6 +21,7 @@ class PreviewCardProvider < ApplicationRecord
include Paginable
include DomainNormalizable
include Attachmentable
+ include Reviewable
ICON_MIME_TYPES = %w(image/x-icon image/vnd.microsoft.icon image/png).freeze
LIMIT = 1.megabyte
@@ -33,24 +34,6 @@ class PreviewCardProvider < ApplicationRecord
scope :trendable, -> { where(trendable: true) }
scope :not_trendable, -> { where(trendable: false) }
- scope :reviewed, -> { where.not(reviewed_at: nil) }
- scope :pending_review, -> { where(reviewed_at: nil) }
-
- def requires_review?
- reviewed_at.nil?
- end
-
- def reviewed?
- reviewed_at.present?
- end
-
- def requested_review?
- requested_review_at.present?
- end
-
- def requires_review_notification?
- requires_review? && !requested_review?
- end
def self.matching_domain(domain)
segments = domain.split('.')
diff --git a/app/models/report_note.rb b/app/models/report_note.rb
index 7361c97e67..9d3be52594 100644
--- a/app/models/report_note.rb
+++ b/app/models/report_note.rb
@@ -18,7 +18,7 @@ class ReportNote < ApplicationRecord
belongs_to :account
belongs_to :report, inverse_of: :notes, touch: true
- scope :latest, -> { reorder(created_at: :desc) }
+ scope :chronological, -> { reorder(id: :asc) }
validates :content, presence: true, length: { maximum: CONTENT_SIZE_LIMIT }
end
diff --git a/app/models/status.rb b/app/models/status.rb
index b4c488d85f..b31ba628b0 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -54,7 +54,7 @@ class Status < ApplicationRecord
update_index('statuses', :proper)
update_index('public_statuses', :proper)
- enum :visibility, { public: 0, unlisted: 1, private: 2, direct: 3, limited: 4 }, suffix: :visibility
+ enum :visibility, { public: 0, unlisted: 1, private: 2, direct: 3, limited: 4 }, suffix: :visibility, validate: true
belongs_to :application, class_name: 'Doorkeeper::Application', optional: true
diff --git a/app/models/system_key.rb b/app/models/system_key.rb
deleted file mode 100644
index 1be399dd68..0000000000
--- a/app/models/system_key.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: system_keys
-#
-# id :bigint(8) not null, primary key
-# key :binary
-# created_at :datetime not null
-# updated_at :datetime not null
-#
-class SystemKey < ApplicationRecord
- ROTATION_PERIOD = 1.week.freeze
-
- before_validation :set_key
-
- scope :expired, ->(now = Time.now.utc) { where(arel_table[:created_at].lt(now - (ROTATION_PERIOD * 3))) }
-
- class << self
- def current_key
- previous_key = order(id: :asc).last
-
- if previous_key && previous_key.created_at >= ROTATION_PERIOD.ago
- previous_key.key
- else
- create.key
- end
- end
- end
-
- private
-
- def set_key
- return if key.present?
-
- cipher = OpenSSL::Cipher.new('AES-256-GCM')
- cipher.encrypt
-
- self.key = cipher.random_key
- end
-end
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 9006e1f25d..93210eb307 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -21,6 +21,8 @@
class Tag < ApplicationRecord
include Paginable
+ include Reviewable
+
# rubocop:disable Rails/HasAndBelongsToMany
has_and_belongs_to_many :statuses
has_and_belongs_to_many :accounts
@@ -48,8 +50,6 @@ class Tag < ApplicationRecord
validate :validate_name_change, if: -> { !new_record? && name_changed? }
validate :validate_display_name_change, if: -> { !new_record? && display_name_changed? }
- scope :reviewed, -> { where.not(reviewed_at: nil) }
- scope :unreviewed, -> { where(reviewed_at: nil) }
scope :pending_review, -> { unreviewed.where.not(requested_review_at: nil) }
scope :usable, -> { where(usable: [true, nil]) }
scope :not_usable, -> { where(usable: false) }
@@ -97,22 +97,6 @@ class Tag < ApplicationRecord
alias trendable? trendable
- def requires_review?
- reviewed_at.nil?
- end
-
- def reviewed?
- reviewed_at.present?
- end
-
- def requested_review?
- requested_review_at.present?
- end
-
- def requires_review_notification?
- requires_review? && !requested_review?
- end
-
def decaying?
max_score_at && max_score_at >= Trends.tags.options[:max_score_cooldown].ago && max_score_at < 1.day.ago
end
@@ -141,7 +125,7 @@ class Tag < ApplicationRecord
query = Tag.matches_name(stripped_term)
query = query.merge(Tag.listable) if options[:exclude_unlistable]
- query = query.merge(matching_name(stripped_term).or(where.not(reviewed_at: nil))) if options[:exclude_unreviewed]
+ query = query.merge(matching_name(stripped_term).or(reviewed)) if options[:exclude_unreviewed]
query.order(Arel.sql('length(name) ASC, name ASC'))
.limit(limit)
diff --git a/app/models/trends/preview_card_provider_filter.rb b/app/models/trends/preview_card_provider_filter.rb
index 219793f01e..33f4e97912 100644
--- a/app/models/trends/preview_card_provider_filter.rb
+++ b/app/models/trends/preview_card_provider_filter.rb
@@ -41,7 +41,7 @@ class Trends::PreviewCardProviderFilter
when 'rejected'
PreviewCardProvider.not_trendable
when 'pending_review'
- PreviewCardProvider.pending_review
+ PreviewCardProvider.unreviewed
else
raise Mastodon::InvalidParameterError, "Unknown status: #{value}"
end
diff --git a/app/models/user.rb b/app/models/user.rb
index b33d7dcae0..df8444e2d3 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -246,10 +246,6 @@ class User < ApplicationRecord
unconfirmed? || pending?
end
- def inactive_message
- approved? ? super : :pending
- end
-
def approve!
return if approved?
diff --git a/app/presenters/activitypub/activity_presenter.rb b/app/presenters/activitypub/activity_presenter.rb
index 38e8527e8e..994cbeaf48 100644
--- a/app/presenters/activitypub/activity_presenter.rb
+++ b/app/presenters/activitypub/activity_presenter.rb
@@ -26,16 +26,5 @@ class ActivityPub::ActivityPresenter < ActiveModelSerializers::Model
end
end
end
-
- def from_encrypted_message(encrypted_message)
- new.tap do |presenter|
- presenter.id = ActivityPub::TagManager.instance.generate_uri_for(nil)
- presenter.type = 'Create'
- presenter.actor = ActivityPub::TagManager.instance.uri_for(encrypted_message.source_account)
- presenter.published = Time.now.utc
- presenter.to = ActivityPub::TagManager.instance.uri_for(encrypted_message.target_account)
- presenter.virtual_object = encrypted_message
- end
- end
end
end
diff --git a/app/serializers/activitypub/activity_serializer.rb b/app/serializers/activitypub/activity_serializer.rb
index 5bdf53f032..23a5b42bc7 100644
--- a/app/serializers/activitypub/activity_serializer.rb
+++ b/app/serializers/activitypub/activity_serializer.rb
@@ -5,8 +5,6 @@ class ActivityPub::ActivitySerializer < ActivityPub::Serializer
case model.class.name
when 'Status'
ActivityPub::NoteSerializer
- when 'DeliverToDeviceService::EncryptedMessage'
- ActivityPub::EncryptedMessageSerializer
else
super
end
diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb
index 4ab48ff204..f698e758e8 100644
--- a/app/serializers/activitypub/actor_serializer.rb
+++ b/app/serializers/activitypub/actor_serializer.rb
@@ -7,8 +7,8 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
context :security
context_extensions :manually_approves_followers, :featured, :also_known_as,
- :moved_to, :property_value, :discoverable, :olm, :suspended,
- :memorial, :indexable
+ :moved_to, :property_value, :discoverable, :suspended,
+ :memorial, :indexable, :attribution_domains
attributes :id, :type, :following, :followers,
:inbox, :outbox, :featured, :featured_tags,
@@ -21,10 +21,10 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
has_many :virtual_tags, key: :tag
has_many :virtual_attachments, key: :attachment
- attribute :devices, unless: :instance_actor?
attribute :moved_to, if: :moved?
attribute :also_known_as, if: :also_known_as?
attribute :suspended, if: :suspended?
+ attribute :attribution_domains, if: -> { object.attribution_domains.any? }
class EndpointsSerializer < ActivityPub::Serializer
include RoutingHelper
@@ -71,10 +71,6 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
object.instance_actor? ? instance_actor_inbox_url : account_inbox_url(object)
end
- def devices
- account_collection_url(object, :devices)
- end
-
def outbox
object.instance_actor? ? instance_actor_outbox_url : account_outbox_url(object)
end
diff --git a/app/serializers/activitypub/collection_serializer.rb b/app/serializers/activitypub/collection_serializer.rb
index 34026a6b5b..1b410cecae 100644
--- a/app/serializers/activitypub/collection_serializer.rb
+++ b/app/serializers/activitypub/collection_serializer.rb
@@ -14,8 +14,6 @@ class ActivityPub::CollectionSerializer < ActivityPub::Serializer
case model.class.name
when 'Status'
ActivityPub::NoteSerializer
- when 'Device'
- ActivityPub::DeviceSerializer
when 'FeaturedTag'
ActivityPub::HashtagSerializer
when 'ActivityPub::CollectionPresenter'
diff --git a/app/serializers/activitypub/device_serializer.rb b/app/serializers/activitypub/device_serializer.rb
deleted file mode 100644
index 5f0fdc8af9..0000000000
--- a/app/serializers/activitypub/device_serializer.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::DeviceSerializer < ActivityPub::Serializer
- context_extensions :olm
-
- include RoutingHelper
-
- class FingerprintKeySerializer < ActivityPub::Serializer
- attributes :type, :public_key_base64
-
- def type
- 'Ed25519Key'
- end
-
- def public_key_base64
- object.fingerprint_key
- end
- end
-
- class IdentityKeySerializer < ActivityPub::Serializer
- attributes :type, :public_key_base64
-
- def type
- 'Curve25519Key'
- end
-
- def public_key_base64
- object.identity_key
- end
- end
-
- attributes :device_id, :type, :name, :claim
-
- has_one :fingerprint_key, serializer: FingerprintKeySerializer
- has_one :identity_key, serializer: IdentityKeySerializer
-
- def type
- 'Device'
- end
-
- def claim
- account_claim_url(object.account, id: object.device_id)
- end
-
- def fingerprint_key
- object
- end
-
- def identity_key
- object
- end
-end
diff --git a/app/serializers/activitypub/encrypted_message_serializer.rb b/app/serializers/activitypub/encrypted_message_serializer.rb
deleted file mode 100644
index 3c525d23e5..0000000000
--- a/app/serializers/activitypub/encrypted_message_serializer.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::EncryptedMessageSerializer < ActivityPub::Serializer
- context :security
-
- context_extensions :olm
-
- class DeviceSerializer < ActivityPub::Serializer
- attributes :type, :device_id
-
- def type
- 'Device'
- end
-
- def device_id
- object
- end
- end
-
- class DigestSerializer < ActivityPub::Serializer
- attributes :type, :digest_algorithm, :digest_value
-
- def type
- 'Digest'
- end
-
- def digest_algorithm
- 'http://www.w3.org/2000/09/xmldsig#hmac-sha256'
- end
-
- def digest_value
- object
- end
- end
-
- attributes :type, :message_type, :cipher_text, :message_franking
-
- has_one :attributed_to, serializer: DeviceSerializer
- has_one :to, serializer: DeviceSerializer
- has_one :digest, serializer: DigestSerializer
-
- def type
- 'EncryptedMessage'
- end
-
- def attributed_to
- object.source_device.device_id
- end
-
- def to
- object.target_device_id
- end
-
- def message_type
- object.type
- end
-
- def cipher_text
- object.body
- end
-end
diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb
index 52ffaf7170..0d8bac9a09 100644
--- a/app/serializers/activitypub/note_serializer.rb
+++ b/app/serializers/activitypub/note_serializer.rb
@@ -21,6 +21,8 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
has_many :virtual_tags, key: :tag
has_one :replies, serializer: ActivityPub::CollectionSerializer, if: :local?
+ has_one :likes, serializer: ActivityPub::CollectionSerializer, if: :local?
+ has_one :shares, serializer: ActivityPub::CollectionSerializer, if: :local?
has_many :poll_options, key: :one_of, if: :poll_and_not_multiple?
has_many :poll_options, key: :any_of, if: :poll_and_multiple?
@@ -76,6 +78,22 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
)
end
+ def likes
+ ActivityPub::CollectionPresenter.new(
+ id: ActivityPub::TagManager.instance.likes_uri_for(object),
+ type: :unordered,
+ size: object.favourites_count
+ )
+ end
+
+ def shares
+ ActivityPub::CollectionPresenter.new(
+ id: ActivityPub::TagManager.instance.shares_uri_for(object),
+ type: :unordered,
+ size: object.reblogs_count
+ )
+ end
+
def language?
object.language.present?
end
diff --git a/app/serializers/activitypub/one_time_key_serializer.rb b/app/serializers/activitypub/one_time_key_serializer.rb
deleted file mode 100644
index 5932eb5b55..0000000000
--- a/app/serializers/activitypub/one_time_key_serializer.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::OneTimeKeySerializer < ActivityPub::Serializer
- context :security
-
- context_extensions :olm
-
- class SignatureSerializer < ActivityPub::Serializer
- attributes :type, :signature_value
-
- def type
- 'Ed25519Signature'
- end
-
- def signature_value
- object.signature
- end
- end
-
- attributes :key_id, :type, :public_key_base64
-
- has_one :signature, serializer: SignatureSerializer
-
- def type
- 'Curve25519Key'
- end
-
- def public_key_base64
- object.key
- end
-
- def signature
- object
- end
-end
diff --git a/app/serializers/oembed_serializer.rb b/app/serializers/oembed_serializer.rb
index d6261d7242..c87f14f26b 100644
--- a/app/serializers/oembed_serializer.rb
+++ b/app/serializers/oembed_serializer.rb
@@ -1,6 +1,41 @@
# frozen_string_literal: true
class OEmbedSerializer < ActiveModel::Serializer
+ INLINE_STYLES = {
+ blockquote: <<~CSS.squish,
+ background: #FCF8FF;
+ border-radius: 8px;
+ border: 1px solid #C9C4DA;
+ margin: 0;
+ max-width: 540px;
+ min-width: 270px;
+ overflow: hidden;
+ padding: 0;
+ CSS
+ status_link: <<~CSS.squish,
+ align-items: center;
+ color: #1C1A25;
+ display: flex;
+ flex-direction: column;
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', Roboto, sans-serif;
+ font-size: 14px;
+ justify-content: center;
+ letter-spacing: 0.25px;
+ line-height: 20px;
+ padding: 24px;
+ text-decoration: none;
+ CSS
+ div_account: <<~CSS.squish,
+ color: #787588;
+ margin-top: 16px;
+ CSS
+ div_view: <<~CSS.squish,
+ font-weight: 500;
+ CSS
+ }.freeze
+
+ DEFAULT_WIDTH = 400
+
include RoutingHelper
include ActionView::Helpers::TagHelper
@@ -37,23 +72,23 @@ class OEmbedSerializer < ActiveModel::Serializer
end
def html
- attributes = {
- src: embed_short_account_status_url(object.account, object),
- class: 'mastodon-embed',
- style: 'max-width: 100%; border: 0',
- width: width,
- height: height,
- allowfullscreen: true,
- }
-
- content_tag(:iframe, nil, attributes) + content_tag(:script, nil, src: full_asset_url('embed.js', skip_pipeline: true), async: true)
+ <<~HTML.squish
+
+
+
+ Post by @#{object.account.pretty_acct}@#{provider_name}
+ View on Mastodon
+
+
+
+ HTML
end
def width
- instance_options[:width]
+ (instance_options[:width] || DEFAULT_WIDTH).to_i
end
def height
- instance_options[:height]
+ instance_options[:height].presence&.to_i
end
end
diff --git a/app/serializers/rest/encrypted_message_serializer.rb b/app/serializers/rest/encrypted_message_serializer.rb
deleted file mode 100644
index 80c26d060e..0000000000
--- a/app/serializers/rest/encrypted_message_serializer.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class REST::EncryptedMessageSerializer < ActiveModel::Serializer
- attributes :id, :account_id, :device_id,
- :type, :body, :digest, :message_franking,
- :created_at
-
- def id
- object.id.to_s
- end
-
- def account_id
- object.from_account_id.to_s
- end
-
- def device_id
- object.from_device_id
- end
-end
diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb
index 880a182b82..1afbc3e2e7 100644
--- a/app/serializers/rest/instance_serializer.rb
+++ b/app/serializers/rest/instance_serializer.rb
@@ -78,7 +78,7 @@ class REST::InstanceSerializer < ActiveModel::Serializer
},
media_attachments: {
- supported_mime_types: MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES + MediaAttachment::AUDIO_MIME_TYPES,
+ supported_mime_types: MediaAttachment.supported_mime_types,
image_size_limit: MediaAttachment::IMAGE_LIMIT,
image_matrix_limit: Attachmentable::MAX_MATRIX_LIMIT,
video_size_limit: MediaAttachment::VIDEO_LIMIT,
@@ -113,9 +113,7 @@ class REST::InstanceSerializer < ActiveModel::Serializer
end
def api_versions
- {
- mastodon: 1,
- }
+ Mastodon::Version.api_versions
end
private
diff --git a/app/serializers/rest/keys/claim_result_serializer.rb b/app/serializers/rest/keys/claim_result_serializer.rb
deleted file mode 100644
index 145044f557..0000000000
--- a/app/serializers/rest/keys/claim_result_serializer.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class REST::Keys::ClaimResultSerializer < ActiveModel::Serializer
- attributes :account_id, :device_id, :key_id, :key, :signature
-
- def account_id
- object.account.id.to_s
- end
-end
diff --git a/app/serializers/rest/keys/device_serializer.rb b/app/serializers/rest/keys/device_serializer.rb
deleted file mode 100644
index f9b821b79c..0000000000
--- a/app/serializers/rest/keys/device_serializer.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-
-class REST::Keys::DeviceSerializer < ActiveModel::Serializer
- attributes :device_id, :name, :identity_key,
- :fingerprint_key
-end
diff --git a/app/serializers/rest/keys/query_result_serializer.rb b/app/serializers/rest/keys/query_result_serializer.rb
deleted file mode 100644
index 8f8bdde289..0000000000
--- a/app/serializers/rest/keys/query_result_serializer.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class REST::Keys::QueryResultSerializer < ActiveModel::Serializer
- attributes :account_id
-
- has_many :devices, serializer: REST::Keys::DeviceSerializer
-
- def account_id
- object.account.id.to_s
- end
-end
diff --git a/app/serializers/rest/notification_group_serializer.rb b/app/serializers/rest/notification_group_serializer.rb
index 5cdf418218..7842230b6a 100644
--- a/app/serializers/rest/notification_group_serializer.rb
+++ b/app/serializers/rest/notification_group_serializer.rb
@@ -39,21 +39,18 @@ class REST::NotificationGroupSerializer < ActiveModel::Serializer
end
def page_min_id
- range = instance_options[:group_metadata][object.group_key]
- range.present? ? range[:min_id].to_s : object.notification.id.to_s
+ object.pagination_data[:min_id].to_s
end
def page_max_id
- range = instance_options[:group_metadata][object.group_key]
- range.present? ? range[:max_id].to_s : object.notification.id.to_s
+ object.most_recent_notification_id.to_s
end
def latest_page_notification_at
- range = instance_options[:group_metadata][object.group_key]
- range.present? ? range[:latest_notification_at] : object.notification.created_at
+ object.pagination_data[:latest_notification_at]
end
def paginated?
- !instance_options[:group_metadata].nil?
+ object.pagination_data.present?
end
end
diff --git a/app/serializers/rest/v1/instance_serializer.rb b/app/serializers/rest/v1/instance_serializer.rb
index 2a98f0cdeb..92cc71c1ba 100644
--- a/app/serializers/rest/v1/instance_serializer.rb
+++ b/app/serializers/rest/v1/instance_serializer.rb
@@ -83,7 +83,7 @@ class REST::V1::InstanceSerializer < ActiveModel::Serializer
},
media_attachments: {
- supported_mime_types: MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES + MediaAttachment::AUDIO_MIME_TYPES,
+ supported_mime_types: MediaAttachment.supported_mime_types,
image_size_limit: MediaAttachment::IMAGE_LIMIT,
image_matrix_limit: Attachmentable::MAX_MATRIX_LIMIT,
video_size_limit: MediaAttachment::VIDEO_LIMIT,
diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb
index e2ecdef165..46cab6caf9 100644
--- a/app/services/activitypub/fetch_replies_service.rb
+++ b/app/services/activitypub/fetch_replies_service.rb
@@ -49,7 +49,7 @@ class ActivityPub::FetchRepliesService < BaseService
rescue Mastodon::UnexpectedResponseError => e
raise unless e.response && e.response.code == 401 && Addressable::URI.parse(collection_or_uri).query.present?
- fetch_resource_without_id_validation(collection_or_uri, nil, true, request_options: { with_query_string: true })
+ fetch_resource_without_id_validation(collection_or_uri, nil, true, request_options: { omit_query_string: false })
end
end
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index b667e97f4d..a7422b5d02 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -108,7 +108,6 @@ class ActivityPub::ProcessAccountService < BaseService
def set_immediate_attributes!
@account.featured_collection_url = @json['featured'] || ''
- @account.devices_url = @json['devices'] || ''
@account.display_name = @json['name'] || ''
@account.note = @json['summary'] || ''
@account.locked = @json['manuallyApprovesFollowers'] || false
@@ -117,6 +116,7 @@ class ActivityPub::ProcessAccountService < BaseService
@account.discoverable = @json['discoverable'] || false
@account.indexable = @json['indexable'] || false
@account.memorial = @json['memorial'] || false
+ @account.attribution_domains = as_array(@json['attributionDomains'] || []).map { |item| value_or_id(item) }
end
def set_fetchable_key!
diff --git a/app/services/approve_appeal_service.rb b/app/services/approve_appeal_service.rb
index b8a522b2a1..3f8d1e2a3b 100644
--- a/app/services/approve_appeal_service.rb
+++ b/app/services/approve_appeal_service.rb
@@ -53,7 +53,7 @@ class ApproveAppealService < BaseService
def undo_mark_statuses_as_sensitive!
representative_account = Account.representative
- @strike.statuses.includes(:media_attachments).find_each do |status|
+ @strike.statuses.kept.includes(:media_attachments).reorder(nil).find_each do |status|
UpdateStatusService.new.call(status, representative_account.id, sensitive: false) if status.with_media?
end
end
diff --git a/app/services/delete_account_service.rb b/app/services/delete_account_service.rb
index a3d77e54c8..20fcd3032b 100644
--- a/app/services/delete_account_service.rb
+++ b/app/services/delete_account_service.rb
@@ -13,7 +13,6 @@ class DeleteAccountService < BaseService
conversation_mutes
conversations
custom_filters
- devices
domain_blocks
featured_tags
follow_requests
@@ -40,7 +39,6 @@ class DeleteAccountService < BaseService
conversation_mutes
conversations
custom_filters
- devices
domain_blocks
featured_tags
follow_requests
diff --git a/app/services/deliver_to_device_service.rb b/app/services/deliver_to_device_service.rb
deleted file mode 100644
index 71711945c0..0000000000
--- a/app/services/deliver_to_device_service.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-class DeliverToDeviceService < BaseService
- include Payloadable
-
- class EncryptedMessage < ActiveModelSerializers::Model
- attributes :source_account, :target_account, :source_device,
- :target_device_id, :type, :body, :digest,
- :message_franking
- end
-
- def call(source_account, source_device, options = {})
- @source_account = source_account
- @source_device = source_device
- @target_account = Account.find(options[:account_id])
- @target_device_id = options[:device_id]
- @body = options[:body]
- @type = options[:type]
- @hmac = options[:hmac]
-
- set_message_franking!
-
- if @target_account.local?
- deliver_to_local!
- else
- deliver_to_remote!
- end
- end
-
- private
-
- def set_message_franking!
- @message_franking = message_franking.to_token
- end
-
- def deliver_to_local!
- target_device = @target_account.devices.find_by!(device_id: @target_device_id)
-
- target_device.encrypted_messages.create!(
- from_account: @source_account,
- from_device_id: @source_device.device_id,
- type: @type,
- body: @body,
- digest: @hmac,
- message_franking: @message_franking
- )
- end
-
- def deliver_to_remote!
- ActivityPub::DeliveryWorker.perform_async(
- Oj.dump(serialize_payload(ActivityPub::ActivityPresenter.from_encrypted_message(encrypted_message), ActivityPub::ActivitySerializer)),
- @source_account.id,
- @target_account.inbox_url
- )
- end
-
- def message_franking
- MessageFranking.new(
- source_account_id: @source_account.id,
- target_account_id: @target_account.id,
- hmac: @hmac,
- timestamp: Time.now.utc
- )
- end
-
- def encrypted_message
- EncryptedMessage.new(
- source_account: @source_account,
- target_account: @target_account,
- source_device: @source_device,
- target_device_id: @target_device_id,
- type: @type,
- body: @body,
- digest: @hmac,
- message_franking: @message_franking
- )
- end
-end
diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb
index 49b8205574..7662fc1f29 100644
--- a/app/services/fetch_link_card_service.rb
+++ b/app/services/fetch_link_card_service.rb
@@ -29,7 +29,7 @@ class FetchLinkCardService < BaseService
end
attach_card if @card&.persisted?
- rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, EncodingError, ActiveRecord::RecordInvalid => e
+ rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Encoding::UndefinedConversionError, ActiveRecord::RecordInvalid => e
Rails.logger.debug { "Error fetching link #{@original_url}: #{e}" }
nil
end
@@ -80,7 +80,7 @@ class FetchLinkCardService < BaseService
urls = if @status.local?
@status.text.scan(URL_PATTERN).map { |array| Addressable::URI.parse(array[1]).normalize }
else
- document = Nokogiri::HTML(@status.text)
+ document = Nokogiri::HTML5(@status.text)
links = document.css('a')
links.filter_map { |a| Addressable::URI.parse(a['href']) unless skip_link?(a) }.filter_map(&:normalize)
@@ -153,12 +153,13 @@ class FetchLinkCardService < BaseService
return if html.nil?
link_details_extractor = LinkDetailsExtractor.new(@url, @html, @html_charset)
- provider = PreviewCardProvider.matching_domain(Addressable::URI.parse(link_details_extractor.canonical_url).normalized_host)
- linked_account = ResolveAccountService.new.call(link_details_extractor.author_account, suppress_errors: true) if link_details_extractor.author_account.present? && provider&.trendable?
+ domain = Addressable::URI.parse(link_details_extractor.canonical_url).normalized_host
+ provider = PreviewCardProvider.matching_domain(domain)
+ linked_account = ResolveAccountService.new.call(link_details_extractor.author_account, suppress_errors: true) if link_details_extractor.author_account.present?
@card = PreviewCard.find_or_initialize_by(url: link_details_extractor.canonical_url) if link_details_extractor.canonical_url != @card.url
@card.assign_attributes(link_details_extractor.to_preview_card_attributes)
- @card.author_account = linked_account
+ @card.author_account = linked_account if linked_account&.can_be_attributed_from?(domain) || provider&.trendable?
@card.save_with_optional_image! unless @card.title.blank? && @card.html.blank?
end
end
diff --git a/app/services/fetch_oembed_service.rb b/app/services/fetch_oembed_service.rb
index dc84b16b68..c7d4f7e292 100644
--- a/app/services/fetch_oembed_service.rb
+++ b/app/services/fetch_oembed_service.rb
@@ -25,7 +25,7 @@ class FetchOEmbedService
return if html.nil?
@format = @options[:format]
- page = Nokogiri::HTML(html)
+ page = Nokogiri::HTML5(html)
if @format.nil? || @format == :json
@endpoint_url ||= page.at_xpath('//link[@type="application/json+oembed"]|//link[@type="text/json+oembed"]')&.attribute('href')&.value
diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb
index 84c36f6a10..b69015a5e9 100644
--- a/app/services/fetch_resource_service.rb
+++ b/app/services/fetch_resource_service.rb
@@ -73,7 +73,7 @@ class FetchResourceService < BaseService
end
def process_html(response)
- page = Nokogiri::HTML(response.body_with_limit)
+ page = Nokogiri::HTML5(response.body_with_limit)
json_link = page.xpath('//link[@rel="alternate"]').find { |link| ACTIVITY_STREAM_LINK_TYPES.include?(link['type']) }
process(json_link['href'], terminal: true) unless json_link.nil?
diff --git a/app/services/keys/claim_service.rb b/app/services/keys/claim_service.rb
deleted file mode 100644
index ebce9cce7d..0000000000
--- a/app/services/keys/claim_service.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-class Keys::ClaimService < BaseService
- HEADERS = { 'Content-Type' => 'application/activity+json' }.freeze
-
- class Result < ActiveModelSerializers::Model
- attributes :account, :device_id, :key_id,
- :key, :signature
-
- def initialize(account, device_id, key_attributes = {})
- super(
- account: account,
- device_id: device_id,
- key_id: key_attributes[:key_id],
- key: key_attributes[:key],
- signature: key_attributes[:signature],
- )
- end
- end
-
- def call(source_account, target_account_id, device_id)
- @source_account = source_account
- @target_account = Account.find(target_account_id)
- @device_id = device_id
-
- if @target_account.local?
- claim_local_key!
- else
- claim_remote_key!
- end
- rescue ActiveRecord::RecordNotFound
- nil
- end
-
- private
-
- def claim_local_key!
- device = @target_account.devices.find_by(device_id: @device_id)
- key = nil
-
- ApplicationRecord.transaction do
- key = device.one_time_keys.order(Arel.sql('random()')).first!
- key.destroy!
- end
-
- @result = Result.new(@target_account, @device_id, key)
- end
-
- def claim_remote_key!
- query_result = QueryService.new.call(@target_account)
- device = query_result.find(@device_id)
-
- return unless device.present? && device.valid_claim_url?
-
- json = fetch_resource_with_post(device.claim_url)
-
- return unless json.present? && json['publicKeyBase64'].present?
-
- @result = Result.new(@target_account, @device_id, key_id: json['id'], key: json['publicKeyBase64'], signature: json.dig('signature', 'signatureValue'))
- rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error => e
- Rails.logger.debug { "Claiming one-time key for #{@target_account.acct}:#{@device_id} failed: #{e}" }
- nil
- end
-
- def fetch_resource_with_post(uri)
- build_post_request(uri).perform do |response|
- raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response)
-
- body_to_json(response.body_with_limit) if response.code == 200
- end
- end
-
- def build_post_request(uri)
- Request.new(:post, uri).tap do |request|
- request.on_behalf_of(@source_account)
- request.add_headers(HEADERS)
- end
- end
-end
diff --git a/app/services/keys/query_service.rb b/app/services/keys/query_service.rb
deleted file mode 100644
index 33e13293f3..0000000000
--- a/app/services/keys/query_service.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-class Keys::QueryService < BaseService
- include JsonLdHelper
-
- class Result < ActiveModelSerializers::Model
- attributes :account, :devices
-
- def initialize(account, devices)
- super(
- account: account,
- devices: devices || [],
- )
- end
-
- def find(device_id)
- @devices.find { |device| device.device_id == device_id }
- end
- end
-
- class Device < ActiveModelSerializers::Model
- attributes :device_id, :name, :identity_key, :fingerprint_key
-
- def initialize(attributes = {})
- super(
- device_id: attributes[:device_id],
- name: attributes[:name],
- identity_key: attributes[:identity_key],
- fingerprint_key: attributes[:fingerprint_key],
- )
- @claim_url = attributes[:claim_url]
- end
-
- def valid_claim_url?
- return false if @claim_url.blank?
-
- begin
- parsed_url = Addressable::URI.parse(@claim_url).normalize
- rescue Addressable::URI::InvalidURIError
- return false
- end
-
- %w(http https).include?(parsed_url.scheme) && parsed_url.host.present?
- end
- end
-
- def call(account)
- @account = account
-
- if @account.local?
- query_local_devices!
- else
- query_remote_devices!
- end
-
- Result.new(@account, @devices)
- end
-
- private
-
- def query_local_devices!
- @devices = @account.devices.map { |device| Device.new(device) }
- end
-
- def query_remote_devices!
- return if @account.devices_url.blank?
-
- json = fetch_resource(@account.devices_url)
-
- return if json['items'].blank?
-
- @devices = as_array(json['items']).map do |device|
- Device.new(device_id: device['id'], name: device['name'], identity_key: device.dig('identityKey', 'publicKeyBase64'), fingerprint_key: device.dig('fingerprintKey', 'publicKeyBase64'), claim_url: device['claim'])
- end
- rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error => e
- Rails.logger.debug { "Querying devices for #{@account.acct} failed: #{e}" }
- nil
- end
-end
diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb
index 5f488348ec..9aebab787e 100644
--- a/app/services/notify_service.rb
+++ b/app/services/notify_service.rb
@@ -3,8 +3,6 @@
class NotifyService < BaseService
include Redisable
- MAXIMUM_GROUP_SPAN_HOURS = 12
-
# TODO: the severed_relationships type probably warrants email notifications
NON_EMAIL_TYPES = %i(
admin.report
@@ -216,7 +214,7 @@ class NotifyService < BaseService
return if drop?
@notification.filtered = filter?
- @notification.group_key = notification_group_key
+ @notification.set_group_key!
@notification.save!
# It's possible the underlying activity has been deleted
@@ -236,23 +234,6 @@ class NotifyService < BaseService
private
- def notification_group_key
- return nil if @notification.filtered || %i(favourite reaction reblog).exclude?(@notification.type)
-
- type_prefix = "#{@notification.type}-#{@notification.target_status.id}"
- redis_key = "notif-group/#{@recipient.id}/#{type_prefix}"
- hour_bucket = @notification.activity.created_at.utc.to_i / 1.hour.to_i
-
- # Reuse previous group if it does not span too large an amount of time
- previous_bucket = redis.get(redis_key).to_i
- hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS
-
- # We do not concern ourselves with race conditions since we use hour buckets
- redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i)
-
- "#{type_prefix}-#{hour_bucket}"
- end
-
def drop?
DropCondition.new(@notification).drop?
end
diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb
index f67064c9a1..427137545f 100644
--- a/app/services/post_status_service.rb
+++ b/app/services/post_status_service.rb
@@ -150,6 +150,9 @@ class PostStatusService < BaseService
@media = @account.media_attachments.where(status_id: nil).where(id: @options[:media_ids].take(Status::MEDIA_ATTACHMENTS_LIMIT).map(&:to_i))
+ not_found_ids = @options[:media_ids].map(&:to_i) - @media.map(&:id)
+ raise Mastodon::ValidationError, I18n.t('media_attachments.validations.not_found', ids: not_found_ids.join(', ')) if not_found_ids.any?
+
raise Mastodon::ValidationError, I18n.t('media_attachments.validations.images_and_video') if @media.size > 1 && @media.find(&:audio_or_video?)
raise Mastodon::ValidationError, I18n.t('media_attachments.validations.not_ready') if @media.any?(&:not_processed?)
end
diff --git a/app/services/translate_status_service.rb b/app/services/translate_status_service.rb
index 9ad146ae7d..e2e076e21b 100644
--- a/app/services/translate_status_service.rb
+++ b/app/services/translate_status_service.rb
@@ -100,7 +100,7 @@ class TranslateStatusService < BaseService
end
def unwrap_emoji_shortcodes(html)
- fragment = Nokogiri::HTML.fragment(html)
+ fragment = Nokogiri::HTML5.fragment(html)
fragment.css('span[translate="no"]').each do |element|
element.remove_attribute('translate')
element.replace(element.children) if element.attributes.empty?
diff --git a/app/services/update_status_service.rb b/app/services/update_status_service.rb
index 70f5959f21..5ae53751e9 100644
--- a/app/services/update_status_service.rb
+++ b/app/services/update_status_service.rb
@@ -74,6 +74,9 @@ class UpdateStatusService < BaseService
media_attachments = @status.account.media_attachments.where(status_id: [nil, @status.id]).where(scheduled_status_id: nil).where(id: @options[:media_ids].take(Status::MEDIA_ATTACHMENTS_LIMIT).map(&:to_i)).to_a
+ not_found_ids = @options[:media_ids].map(&:to_i) - media_attachments.map(&:id)
+ raise Mastodon::ValidationError, I18n.t('media_attachments.validations.not_found', ids: not_found_ids.join(', ')) if not_found_ids.any?
+
raise Mastodon::ValidationError, I18n.t('media_attachments.validations.images_and_video') if media_attachments.size > 1 && media_attachments.find(&:audio_or_video?)
raise Mastodon::ValidationError, I18n.t('media_attachments.validations.not_ready') if media_attachments.any?(&:not_processed?)
diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb
index b317fc31a8..c4f4191e1f 100644
--- a/app/services/verify_link_service.rb
+++ b/app/services/verify_link_service.rb
@@ -26,7 +26,7 @@ class VerifyLinkService < BaseService
def link_back_present?
return false if @body.blank?
- links = Nokogiri::HTML5(@body).xpath('//a[contains(concat(" ", normalize-space(@rel), " "), " me ")]|//link[contains(concat(" ", normalize-space(@rel), " "), " me ")]')
+ links = Nokogiri::HTML5(@body).css("a[rel~='me'],link[rel~='me']")
if links.any? { |link| link['href']&.downcase == @link_back.downcase }
true
diff --git a/app/validators/domain_validator.rb b/app/validators/domain_validator.rb
index 3a951f9a7e..718fd190f1 100644
--- a/app/validators/domain_validator.rb
+++ b/app/validators/domain_validator.rb
@@ -1,22 +1,29 @@
# frozen_string_literal: true
class DomainValidator < ActiveModel::EachValidator
+ MAX_DOMAIN_LENGTH = 256
+ MIN_LABEL_LENGTH = 1
+ MAX_LABEL_LENGTH = 63
+ ALLOWED_CHARACTERS_RE = /^[a-z0-9\-]+$/i
+
def validate_each(record, attribute, value)
return if value.blank?
- domain = if options[:acct]
- value.split('@').last
- else
- value
- end
+ (options[:multiline] ? value.split : [value]).each do |domain|
+ _, domain = domain.split('@') if options[:acct]
- record.errors.add(attribute, I18n.t('domain_validator.invalid_domain')) unless compliant?(domain)
+ next if domain.blank?
+
+ record.errors.add(attribute, options[:multiline] ? :invalid_domain_on_line : :invalid, value: domain) unless compliant?(domain)
+ end
end
private
def compliant?(value)
- Addressable::URI.new.tap { |uri| uri.host = value }
+ uri = Addressable::URI.new
+ uri.host = value
+ uri.normalized_host.size < MAX_DOMAIN_LENGTH && uri.normalized_host.split('.').all? { |label| label.size.between?(MIN_LABEL_LENGTH, MAX_LABEL_LENGTH) && label =~ ALLOWED_CHARACTERS_RE }
rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
false
end
diff --git a/app/validators/ed25519_key_validator.rb b/app/validators/ed25519_key_validator.rb
deleted file mode 100644
index adf49296b2..0000000000
--- a/app/validators/ed25519_key_validator.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class Ed25519KeyValidator < ActiveModel::EachValidator
- def validate_each(record, attribute, value)
- return if value.blank?
-
- key = Base64.decode64(value)
-
- record.errors.add(attribute, I18n.t('crypto.errors.invalid_key')) unless verified?(key)
- end
-
- private
-
- def verified?(key)
- Ed25519.validate_key_bytes(key)
- rescue ArgumentError
- false
- end
-end
diff --git a/app/validators/ed25519_signature_validator.rb b/app/validators/ed25519_signature_validator.rb
deleted file mode 100644
index 0e74c231ec..0000000000
--- a/app/validators/ed25519_signature_validator.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class Ed25519SignatureValidator < ActiveModel::EachValidator
- def validate_each(record, attribute, value)
- return if value.blank?
-
- verify_key = Ed25519::VerifyKey.new(Base64.decode64(option_to_value(record, :verify_key)))
- signature = Base64.decode64(value)
- message = option_to_value(record, :message)
-
- record.errors.add(attribute, I18n.t('crypto.errors.invalid_signature')) unless verified?(verify_key, signature, message)
- end
-
- private
-
- def verified?(verify_key, signature, message)
- verify_key.verify(signature, message)
- rescue Ed25519::VerifyError, ArgumentError
- false
- end
-
- def option_to_value(record, key)
- if options[key].is_a?(Proc)
- options[key].call(record)
- else
- record.public_send(options[key])
- end
- end
-end
diff --git a/app/validators/lines_validator.rb b/app/validators/lines_validator.rb
new file mode 100644
index 0000000000..27a108bb2c
--- /dev/null
+++ b/app/validators/lines_validator.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class LinesValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ return if value.blank?
+
+ record.errors.add(attribute, :too_many_lines, limit: options[:maximum]) if options[:maximum].present? && value.split.size > options[:maximum]
+ end
+end
diff --git a/app/views/admin/account_actions/new.html.haml b/app/views/admin/account_actions/new.html.haml
index bce1c31760..c4311eba96 100644
--- a/app/views/admin/account_actions/new.html.haml
+++ b/app/views/admin/account_actions/new.html.haml
@@ -1,6 +1,13 @@
- content_for :page_title do
= t('admin.account_actions.title', acct: @account.pretty_acct)
+- if @account.suspended_locally?
+ .flash-message.alert
+ = t('admin.account_actions.already_suspended')
+- elsif @account.silenced?
+ .flash-message.warn
+ = t('admin.account_actions.already_silenced')
+
= simple_form_for @account_action, url: admin_account_action_path(@account.id) do |f|
= f.input :report_id,
as: :hidden
@@ -9,6 +16,7 @@
= f.input :type,
as: :radio_buttons,
collection: Admin::AccountAction.types_for_account(@account),
+ disabled: Admin::AccountAction.disabled_types_for_account(@account),
hint: t('simple_form.hints.admin_account_action.type_html', acct: @account.pretty_acct),
include_blank: false,
label_method: ->(type) { account_action_type_label(type) },
diff --git a/app/views/admin/accounts/_local_account.html.haml b/app/views/admin/accounts/_local_account.html.haml
index 3ad47d8dfb..5357ebcce9 100644
--- a/app/views/admin/accounts/_local_account.html.haml
+++ b/app/views/admin/accounts/_local_account.html.haml
@@ -52,7 +52,7 @@
- if can?(:reset_password, account.user)
%tr
%td
- = table_link_to 'key', t('admin.accounts.reset_password'), admin_account_reset_path(account.id), method: :create, data: { confirm: t('admin.accounts.are_you_sure') }
+ = table_link_to 'key', t('admin.accounts.reset_password'), admin_account_reset_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }
%tr
%th= t('simple_form.labels.defaults.locale')
%td= standard_locale_name(account.user_locale)
diff --git a/app/views/admin/announcements/_announcement.html.haml b/app/views/admin/announcements/_announcement.html.haml
index eac78efb28..8190f87d2f 100644
--- a/app/views/admin/announcements/_announcement.html.haml
+++ b/app/views/admin/announcements/_announcement.html.haml
@@ -1,4 +1,4 @@
-.announcements-list__item
+.announcements-list__item{ id: dom_id(announcement) }
= link_to edit_admin_announcement_path(announcement), class: 'announcements-list__item__title' do
= truncate(announcement.text)
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 8430dd3c4f..27d8f4790b 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -56,19 +56,19 @@
.dashboard__item
= link_to admin_reports_path, class: 'dashboard__quick-access' do
- %span= t('admin.dashboard.pending_reports_html', count: @pending_reports_count)
+ %span= t('admin.dashboard.pending_reports_html', count: @pending_reports_count.value)
= material_symbol 'chevron_right'
= link_to admin_accounts_path(status: 'pending'), class: 'dashboard__quick-access' do
- %span= t('admin.dashboard.pending_users_html', count: @pending_users_count)
+ %span= t('admin.dashboard.pending_users_html', count: @pending_users_count.value)
= material_symbol 'chevron_right'
= link_to admin_trends_tags_path(status: 'pending_review'), class: 'dashboard__quick-access' do
- %span= t('admin.dashboard.pending_tags_html', count: @pending_tags_count)
+ %span= t('admin.dashboard.pending_tags_html', count: @pending_tags_count.value)
= material_symbol 'chevron_right'
= link_to admin_disputes_appeals_path(status: 'pending'), class: 'dashboard__quick-access' do
- %span= t('admin.dashboard.pending_appeals_html', count: @pending_appeals_count)
+ %span= t('admin.dashboard.pending_appeals_html', count: @pending_appeals_count.value)
= material_symbol 'chevron_right'
.dashboard__item
= react_admin_component :dimension,
diff --git a/app/views/admin/reports/_actions.html.haml b/app/views/admin/reports/_actions.html.haml
index 5fb540931b..ef016e949b 100644
--- a/app/views/admin/reports/_actions.html.haml
+++ b/app/views/admin/reports/_actions.html.haml
@@ -17,21 +17,27 @@
.report-actions__item__button
= form.button t('admin.reports.delete_and_resolve'),
name: :delete,
- class: 'button button--destructive'
+ class: 'button button--destructive',
+ disabled: statuses.empty?,
+ title: statuses.empty? ? t('admin.reports.actions_no_posts') : ''
.report-actions__item__description
= t('admin.reports.actions.delete_description_html')
.report-actions__item
.report-actions__item__button
= form.button t('admin.accounts.silence'),
name: :silence,
- class: 'button button--destructive'
+ class: 'button button--destructive',
+ disabled: report.target_account.silenced? || report.target_account.suspended_locally?,
+ title: report.target_account.silenced? ? t('admin.account_actions.already_silenced') : ''
.report-actions__item__description
= t('admin.reports.actions.silence_description_html')
.report-actions__item
.report-actions__item__button
= form.button t('admin.accounts.suspend'),
name: :suspend,
- class: 'button button--destructive'
+ class: 'button button--destructive',
+ disabled: report.target_account.suspended_locally?,
+ title: report.target_account.suspended_locally? ? t('admin.account_actions.already_suspended') : ''
.report-actions__item__description
= t('admin.reports.actions.suspend_description_html')
.report-actions__item
diff --git a/app/views/admin/reports/_status.html.haml b/app/views/admin/reports/_status.html.haml
index 11be38ef84..f4630ed25a 100644
--- a/app/views/admin/reports/_status.html.haml
+++ b/app/views/admin/reports/_status.html.haml
@@ -18,7 +18,7 @@
- if status.application
= status.application.name
·
- = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', target: stream_link_target, rel: 'noopener noreferrer' do
+ = link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__datetime', target: stream_link_target, rel: 'noopener noreferrer' do
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
- if status.edited?
·
@@ -33,7 +33,7 @@
= material_symbol('repeat_active')
= t('statuses.boosted_from_html', acct_link: admin_account_inline_link_to(status.proper.account))
- else
- = fa_visibility_icon(status)
+ = material_symbol visibility_icon(status)
= t("statuses.visibilities.#{status.visibility}")
- if status.proper.sensitive?
·
diff --git a/app/views/admin/trends/links/preview_card_providers/index.html.haml b/app/views/admin/trends/links/preview_card_providers/index.html.haml
index b43b8dfff9..93daf25f31 100644
--- a/app/views/admin/trends/links/preview_card_providers/index.html.haml
+++ b/app/views/admin/trends/links/preview_card_providers/index.html.haml
@@ -12,7 +12,7 @@
%li= filter_link_to t('generic.all'), status: nil
%li= filter_link_to t('admin.trends.approved'), status: 'approved'
%li= filter_link_to t('admin.trends.rejected'), status: 'rejected'
- %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{PreviewCardProvider.pending_review.count})"], ' '), status: 'pending_review'
+ %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{PreviewCardProvider.unreviewed.count})"], ' '), status: 'pending_review'
.back-link
= link_to admin_trends_links_path do
= material_symbol 'chevron_left'
diff --git a/app/views/admin/users/roles/show.html.haml b/app/views/admin/users/roles/show.html.haml
index f26640f2a1..01b3830f4e 100644
--- a/app/views/admin/users/roles/show.html.haml
+++ b/app/views/admin/users/roles/show.html.haml
@@ -7,7 +7,8 @@
collection: UserRole.assignable,
include_blank: I18n.t('admin.accounts.change_role.no_role'),
label_method: :name,
- wrapper: :with_block_label
+ wrapper: :with_block_label,
+ hint: safe_join([I18n.t('simple_form.hints.user.role'), ' ', link_to(I18n.t('admin.accounts.change_role.edit_roles'), admin_roles_path)])
.actions
= f.button :button,
diff --git a/app/views/filters/statuses/_status_filter.html.haml b/app/views/filters/statuses/_status_filter.html.haml
index 31aa9ec237..d0d04638d2 100644
--- a/app/views/filters/statuses/_status_filter.html.haml
+++ b/app/views/filters/statuses/_status_filter.html.haml
@@ -29,7 +29,7 @@
·
= t('statuses.edited_at_html', date: content_tag(:time, l(status.edited_at), datetime: status.edited_at.iso8601, title: l(status.edited_at), class: 'formatted'))
·
- = fa_visibility_icon(status)
+ = material_symbol visibility_icon(status)
= t("statuses.visibilities.#{status.visibility}")
- if status.sensitive?
·
diff --git a/app/views/invites/_invite.html.haml b/app/views/invites/_invite.html.haml
index 94e1a71125..892fdc5a0e 100644
--- a/app/views/invites/_invite.html.haml
+++ b/app/views/invites/_invite.html.haml
@@ -1,4 +1,4 @@
-%tr
+%tr{ id: dom_id(invite) }
%td
.input-copy
.input-copy__wrapper
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index d17ef79459..1b2b23caa7 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -3,6 +3,8 @@
= flavoured_javascript_pack_tag 'public', crossorigin: 'anonymous'
= flavoured_javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'
+- content_for :body_classes, 'admin'
+
- content_for :content do
.admin-wrapper
.sidebar-wrapper
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 1a3a111b33..a76dc75f63 100755
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -21,7 +21,7 @@
%link{ rel: 'mask-icon', href: frontend_asset_path('images/logo-symbol-icon.svg'), color: '#6364FF' }/
%link{ rel: 'manifest', href: manifest_path(format: :json) }/
= theme_color_tags current_theme
- %meta{ name: 'apple-mobile-web-app-capable', content: 'yes' }/
+ %meta{ name: 'mobile-web-app-capable', content: 'yes' }/
%title= html_title
diff --git a/app/views/layouts/embedded.html.haml b/app/views/layouts/embedded.html.haml
index ec583556ce..b194bc07ad 100644
--- a/app/views/layouts/embedded.html.haml
+++ b/app/views/layouts/embedded.html.haml
@@ -15,8 +15,7 @@
= javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
= preload_locale_pack
= render_initial_state
- = flavoured_javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
-
+ = flavoured_javascript_pack_tag 'embed', integrity: true, crossorigin: 'anonymous'
%body.embed
= yield
diff --git a/app/views/layouts/modal.html.haml b/app/views/layouts/modal.html.haml
index 088ba82c1e..9c5975efc9 100644
--- a/app/views/layouts/modal.html.haml
+++ b/app/views/layouts/modal.html.haml
@@ -1,6 +1,8 @@
- content_for :header_tags do
= flavoured_javascript_pack_tag 'public', crossorigin: 'anonymous'
+- content_for :body_classes, 'modal-layout compose-standalone'
+
- content_for :content do
- if user_signed_in? && !@hide_header
.account-header
diff --git a/app/views/media/player.html.haml b/app/views/media/player.html.haml
index c5ba8680a0..e48982a323 100644
--- a/app/views/media/player.html.haml
+++ b/app/views/media/player.html.haml
@@ -2,6 +2,8 @@
= render_initial_state
= flavoured_javascript_pack_tag 'public', crossorigin: 'anonymous'
+- content_for :body_classes, 'player'
+
:ruby
meta = @media_attachment.file.meta || {}
diff --git a/app/views/oauth/authorized_applications/index.html.haml b/app/views/oauth/authorized_applications/index.html.haml
index b6819bbd72..eb544d079b 100644
--- a/app/views/oauth/authorized_applications/index.html.haml
+++ b/app/views/oauth/authorized_applications/index.html.haml
@@ -7,7 +7,7 @@
.applications-list
- @applications.each do |application|
- .applications-list__item
+ .applications-list__item{ id: dom_id(application) }
- if application.website.present?
= link_to application.name, application.website, target: '_blank', rel: 'noopener noreferrer', class: 'announcements-list__item__title'
- else
diff --git a/app/views/redirects/show.html.haml b/app/views/redirects/show.html.haml
index 64436e05d1..aa0db350a8 100644
--- a/app/views/redirects/show.html.haml
+++ b/app/views/redirects/show.html.haml
@@ -2,6 +2,8 @@
%meta{ name: 'robots', content: 'noindex, noarchive' }/
%link{ rel: 'canonical', href: @redirect_path }
+- content_for :body_classes, 'app-body'
+
.redirect
.redirect__logo
= link_to render_logo, root_path
diff --git a/app/views/settings/applications/_fields.html.haml b/app/views/settings/applications/_fields.html.haml
deleted file mode 100644
index d539848952..0000000000
--- a/app/views/settings/applications/_fields.html.haml
+++ /dev/null
@@ -1,36 +0,0 @@
-.fields-group
- = f.input :name,
- label: t('activerecord.attributes.doorkeeper/application.name'),
- wrapper: :with_label
-
-.fields-group
- = f.input :website,
- label: t('activerecord.attributes.doorkeeper/application.website'),
- wrapper: :with_label
-
-.fields-group
- = f.input :redirect_uri,
- label: t('activerecord.attributes.doorkeeper/application.redirect_uri'), hint: t('doorkeeper.applications.help.redirect_uri'),
- required: true,
- wrapper: :with_block_label
-
- %p.hint= t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, Doorkeeper.configuration.native_redirect_uri)).html_safe
-
-.field-group
- .input.with_block_label
- %label= t('activerecord.attributes.doorkeeper/application.scopes')
- %span.hint= t('simple_form.hints.defaults.scopes')
-
- - Doorkeeper.configuration.scopes.group_by { |s| s.split(':').first }.each_value do |value|
- = f.input :scopes,
- as: :check_boxes,
- collection_wrapper_tag: 'ul',
- collection: value.sort,
- hint: false,
- include_blank: false,
- item_wrapper_tag: 'li',
- label_method: ->(scope) { safe_join([content_tag(:samp, scope, class: class_for_scope(scope)), content_tag(:span, t("doorkeeper.scopes.#{scope}"), class: 'hint')]) },
- label: false,
- required: false,
- selected: f.object.scopes.all,
- wrapper: :with_block_label
diff --git a/app/views/settings/applications/_form.html.haml b/app/views/settings/applications/_form.html.haml
new file mode 100644
index 0000000000..66ea8bc12b
--- /dev/null
+++ b/app/views/settings/applications/_form.html.haml
@@ -0,0 +1,36 @@
+.fields-group
+ = form.input :name,
+ label: t('activerecord.attributes.doorkeeper/application.name'),
+ wrapper: :with_label
+
+.fields-group
+ = form.input :website,
+ label: t('activerecord.attributes.doorkeeper/application.website'),
+ wrapper: :with_label
+
+.fields-group
+ = form.input :redirect_uri,
+ label: t('activerecord.attributes.doorkeeper/application.redirect_uri'), hint: t('doorkeeper.applications.help.redirect_uri'),
+ required: true,
+ wrapper: :with_block_label
+
+ %p.hint= t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, Doorkeeper.configuration.native_redirect_uri)).html_safe
+
+.field-group
+ .input.with_block_label
+ %label= t('activerecord.attributes.doorkeeper/application.scopes')
+ %span.hint= t('simple_form.hints.defaults.scopes')
+
+ - Doorkeeper.configuration.scopes.group_by { |s| s.split(':').first }.each_value do |value|
+ = form.input :scopes,
+ as: :check_boxes,
+ collection_wrapper_tag: 'ul',
+ collection: value.sort,
+ hint: false,
+ include_blank: false,
+ item_wrapper_tag: 'li',
+ label_method: ->(scope) { safe_join([content_tag(:samp, scope, class: class_for_scope(scope)), content_tag(:span, t("doorkeeper.scopes.#{scope}"), class: 'hint')]) },
+ label: false,
+ required: false,
+ selected: form.object.scopes.all,
+ wrapper: :with_block_label
diff --git a/app/views/settings/applications/new.html.haml b/app/views/settings/applications/new.html.haml
index aa2281fea1..f6a546e8de 100644
--- a/app/views/settings/applications/new.html.haml
+++ b/app/views/settings/applications/new.html.haml
@@ -1,8 +1,8 @@
- content_for :page_title do
= t('doorkeeper.applications.new.title')
-= simple_form_for @application, url: settings_applications_path do |f|
- = render 'fields', f: f
+= simple_form_for @application, url: settings_applications_path do |form|
+ = render form
.actions
- = f.button :button, t('doorkeeper.applications.buttons.submit'), type: :submit
+ = form.button :button, t('doorkeeper.applications.buttons.submit'), type: :submit
diff --git a/app/views/settings/applications/show.html.haml b/app/views/settings/applications/show.html.haml
index be1d13eae6..19630cf49b 100644
--- a/app/views/settings/applications/show.html.haml
+++ b/app/views/settings/applications/show.html.haml
@@ -23,8 +23,8 @@
%hr/
-= simple_form_for @application, url: settings_application_path(@application), method: :put do |f|
- = render 'fields', f: f
+= simple_form_for @application, url: settings_application_path(@application), method: :put do |form|
+ = render form
.actions
- = f.button :button, t('generic.save_changes'), type: :submit
+ = form.button :button, t('generic.save_changes'), type: :submit
diff --git a/app/views/settings/imports/index.html.haml b/app/views/settings/imports/index.html.haml
index ca815720fd..634631b5aa 100644
--- a/app/views/settings/imports/index.html.haml
+++ b/app/views/settings/imports/index.html.haml
@@ -23,7 +23,7 @@
= f.input :mode,
as: :radio_buttons,
collection_wrapper_tag: 'ul',
- collection: Import::MODES,
+ collection: Form::Import::MODES,
item_wrapper_tag: 'li',
label_method: ->(mode) { safe_join([I18n.t("imports.modes.#{mode}"), content_tag(:span, I18n.t("imports.modes.#{mode}_long"), class: 'hint')]) }
@@ -46,7 +46,7 @@
%th= t('imports.failures')
%tbody
- @recent_imports.each do |import|
- %tr
+ %tr{ id: dom_id(import) }
%td= t("imports.types.#{import.type}")
%td
- if import.state_unconfirmed?
diff --git a/app/views/settings/verifications/show.html.haml b/app/views/settings/verifications/show.html.haml
index 4fb2918018..5318b0767d 100644
--- a/app/views/settings/verifications/show.html.haml
+++ b/app/views/settings/verifications/show.html.haml
@@ -5,7 +5,9 @@
%h2= t('settings.profile')
= render partial: 'settings/shared/profile_navigation'
-.simple_form
+.simple_form.form-section
+ %h3= t('verification.website_verification')
+
%p.lead= t('verification.hint_html')
%h4= t('verification.here_is_how')
@@ -28,3 +30,33 @@
%span.verified-badge
= material_symbol 'check', class: 'verified-badge__mark'
%span= field.value
+
+= simple_form_for @account, url: settings_verification_path, html: { method: :put, class: 'form-section' } do |f|
+ = render 'shared/error_messages', object: @account
+
+ %h3= t('author_attribution.title')
+
+ %p.lead= t('author_attribution.hint_html')
+
+ .fields-row
+ .fields-row__column.fields-row__column-6
+ .fields-group
+ = f.input :attribution_domains_as_text, as: :text, wrapper: :with_block_label, input_html: { placeholder: "example1.com\nexample2.com\nexample3.com", rows: 4 }
+ .fields-row__column.fields-row__column-6
+ .fields-group.fade-out-top
+ %div
+ .status-card.expanded.bottomless
+ .status-card__image
+ = image_tag frontend_asset_url('images/preview.png'), alt: '', class: 'status-card__image-image'
+ .status-card__content
+ %span.status-card__host
+ %span= t('author_attribution.s_blog', name: @account.username)
+ ·
+ %time.time-ago{ datetime: 1.year.ago.to_date.iso8601 }
+ %strong.status-card__title= t('author_attribution.example_title')
+ .more-from-author
+ = logo_as_symbol(:icon)
+ = t('author_attribution.more_from_html', name: link_to(root_url, class: 'story__details__shared__author-link') { image_tag(@account.avatar.url, class: 'account__avatar', width: 16, height: 16, alt: '') + content_tag(:bdi, display_name(@account)) })
+
+ .actions
+ = f.button :button, t('generic.save_changes'), type: :submit
diff --git a/app/views/statuses/_detailed_status.html.haml b/app/views/statuses/_detailed_status.html.haml
deleted file mode 100644
index 6cd240bbbc..0000000000
--- a/app/views/statuses/_detailed_status.html.haml
+++ /dev/null
@@ -1,80 +0,0 @@
-.detailed-status.detailed-status--flex{ class: "detailed-status-#{status.visibility}" }
- .p-author.h-card
- = link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'detailed-status__display-name u-url', target: stream_link_target, rel: 'noopener' do
- .detailed-status__display-avatar
- - if prefers_autoplay?
- = image_tag status.account.avatar_original_url, alt: '', class: 'account__avatar u-photo'
- - else
- = image_tag status.account.avatar_static_url, alt: '', class: 'account__avatar u-photo'
- %span.display-name
- %bdi
- %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: prefers_autoplay?)
- %span.display-name__account
- = acct(status.account)
- = material_symbol('lock') if status.account.locked?
-
- = account_action_button(status.account)
-
- .status__content.emojify{ data: ({ spoiler: current_account&.user&.setting_expand_spoilers ? 'expanded' : 'folded' } if status.spoiler_text?) }<
- - if status.spoiler_text?
- %p<
- %span.p-summary> #{prerender_custom_emojis(h(status.spoiler_text), status.emojis)}
- %button.status__content__spoiler-link= t('statuses.show_more')
- .e-content{ lang: status.language }
- = prerender_custom_emojis(status_content_format(status), status.emojis)
-
- - if status.preloadable_poll
- = render_poll_component(status)
-
- - if !status.ordered_media_attachments.empty?
- - if status.ordered_media_attachments.first.video?
- = render_video_component(status, width: 670, height: 380, detailed: true)
- - elsif status.ordered_media_attachments.first.audio?
- = render_audio_component(status, width: 670, height: 380)
- - else
- = render_media_gallery_component(status, height: 380, standalone: true)
- - elsif status.preview_card
- = render_card_component(status)
-
- .detailed-status__meta
- %data.dt-published{ value: status.created_at.to_time.iso8601 }
- - if status.edited?
- %data.dt-updated{ value: status.edited_at.to_time.iso8601 }
-
- = link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime u-url u-uid', target: stream_link_target, rel: 'noopener noreferrer' do
- %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
- ·
- - if status.edited?
- = t('statuses.edited_at_html', date: content_tag(:time, l(status.edited_at), datetime: status.edited_at.iso8601, title: l(status.edited_at), class: 'formatted'))
- ·
- %span.detailed-status__visibility-icon
- = visibility_icon status
- ·
- - if status.application && status.account.user&.setting_show_application
- - if status.application.website.blank?
- %strong.detailed-status__application= status.application.name
- - else
- = link_to status.application.name, status.application.website, class: 'detailed-status__application', target: '_blank', rel: 'noopener noreferrer'
- ·
- %span.detailed-status__link
- - if status.in_reply_to_id.nil?
- = material_symbol('reply')
- - else
- = material_symbol('reply_all')
- %span.detailed-status__reblogs>= friendly_number_to_human status.replies_count
-
- ·
- - if status.public_visibility? || status.unlisted_visibility?
- %span.detailed-status__link
- = material_symbol('repeat')
- %span.detailed-status__reblogs>= friendly_number_to_human status.reblogs_count
-
- ·
- %span.detailed-status__link
- = material_symbol('star')
- %span.detailed-status__favorites>= friendly_number_to_human status.favourites_count
-
-
- - if user_signed_in?
- ·
- = link_to t('statuses.open_in_web'), web_url("@#{status.account.pretty_acct}/#{status.id}"), class: 'detailed-status__application', target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/statuses/_poll.html.haml b/app/views/statuses/_poll.html.haml
deleted file mode 100644
index 62416a44da..0000000000
--- a/app/views/statuses/_poll.html.haml
+++ /dev/null
@@ -1,36 +0,0 @@
-:ruby
- show_results = (user_signed_in? && poll.voted?(current_account)) || poll.expired?
- total_votes_count = poll.voters_count || poll.votes_count
-
-.poll
- %ul
- - poll.loaded_options.each do |option|
- %li
- - if show_results
- - percent = total_votes_count.positive? ? 100 * option.votes_count / total_votes_count : 0
- %label.poll__option><
- %span.poll__number><
- #{percent.round}%
- %span.poll__option__text
- = prerender_custom_emojis(h(option.title), status.emojis)
-
- %progress{ max: 100, value: [percent, 1].max, 'aria-hidden': 'true' }
- %span.poll__chart
- - else
- %label.poll__option><
- %span.poll__input{ class: poll.multiple? ? 'checkbox' : nil }><
- %span.poll__option__text
- = prerender_custom_emojis(h(option.title), status.emojis)
- .poll__footer
- - unless show_results
- %button.button.button-secondary{ disabled: true }
- = t('statuses.poll.vote')
-
- - if poll.voters_count.nil?
- %span= t('statuses.poll.total_votes', count: poll.votes_count)
- - else
- %span= t('statuses.poll.total_people', count: poll.voters_count)
-
- - unless poll.expires_at.nil?
- ·
- %span= l poll.expires_at
diff --git a/app/views/statuses/_simple_status.html.haml b/app/views/statuses/_simple_status.html.haml
deleted file mode 100644
index 7a731d7cd7..0000000000
--- a/app/views/statuses/_simple_status.html.haml
+++ /dev/null
@@ -1,70 +0,0 @@
-:ruby
- hide_show_thread ||= false
-
-.status{ class: "status-#{status.visibility}" }
- .status__info
- = link_to ActivityPub::TagManager.instance.url_for(status), class: 'status__relative-time u-url u-uid', target: stream_link_target, rel: 'noopener noreferrer' do
- %span.status__visibility-icon><
- = visibility_icon status
- %time.time-ago{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
- - if status.edited?
- %abbr{ title: t('statuses.edited_at_html', date: l(status.edited_at.to_date)) }
- *
- %data.dt-published{ value: status.created_at.to_time.iso8601 }
-
- .p-author.h-card
- = link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener noreferrer' do
- .status__avatar
- %div
- - if prefers_autoplay?
- = image_tag status.account.avatar_original_url, alt: '', class: 'u-photo account__avatar'
- - else
- = image_tag status.account.avatar_static_url, alt: '', class: 'u-photo account__avatar'
- %span.display-name
- %bdi
- %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: prefers_autoplay?)
-
- %span.display-name__account
- = acct(status.account)
- = material_symbol('lock') if status.account.locked?
- .status__content.emojify{ data: ({ spoiler: current_account&.user&.setting_expand_spoilers ? 'expanded' : 'folded' } if status.spoiler_text?) }<
- - if status.spoiler_text?
- %p<
- %span.p-summary> #{prerender_custom_emojis(h(status.spoiler_text), status.emojis)}
- %button.status__content__spoiler-link= t('statuses.show_more')
- .e-content{ lang: status.language }<
- = prerender_custom_emojis(status_content_format(status), status.emojis)
-
- - if status.preloadable_poll
- = render_poll_component(status)
-
- - if !status.ordered_media_attachments.empty?
- - if status.ordered_media_attachments.first.video?
- = render_video_component(status, width: 610, height: 343)
- - elsif status.ordered_media_attachments.first.audio?
- = render_audio_component(status, width: 610, height: 343)
- - else
- = render_media_gallery_component(status, height: 343)
- - elsif status.preview_card
- = render_card_component(status)
-
- - if !status.in_reply_to_id.nil? && status.in_reply_to_account_id == status.account.id && !hide_show_thread
- = link_to ActivityPub::TagManager.instance.url_for(status), class: 'status__content__read-more-button', target: stream_link_target, rel: 'noopener noreferrer' do
- = t 'statuses.show_thread'
-
- .status__action-bar
- %span.status__action-bar-button.icon-button.icon-button--with-counter
- - if status.in_reply_to_id.nil?
- = material_symbol 'reply'
- - else
- = material_symbol 'reply_all'
- %span.icon-button__counter= obscured_counter status.replies_count
- %span.status__action-bar-button.icon-button
- - if status.distributable?
- = material_symbol 'repeat'
- - elsif status.private_visibility? || status.limited_visibility?
- = material_symbol 'lock'
- - else
- = material_symbol 'alternate_email'
- %span.status__action-bar-button.icon-button
- = material_symbol 'star'
diff --git a/app/views/statuses/_status.html.haml b/app/views/statuses/_status.html.haml
deleted file mode 100644
index bf51b5ff7d..0000000000
--- a/app/views/statuses/_status.html.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-.entry
- = render (centered ? 'statuses/detailed_status' : 'statuses/simple_status'), status: status.proper, hide_show_thread: false
diff --git a/app/views/statuses/embed.html.haml b/app/views/statuses/embed.html.haml
index 18d62fd8e3..09d0792ea2 100644
--- a/app/views/statuses/embed.html.haml
+++ b/app/views/statuses/embed.html.haml
@@ -1,2 +1 @@
-.activity-stream.activity-stream--headless
- = render 'status', status: @status, centered: true
+#mastodon-status{ data: { props: Oj.dump(default_props.merge(id: @status.id.to_s)) } }
diff --git a/app/workers/push_encrypted_message_worker.rb b/app/workers/push_encrypted_message_worker.rb
deleted file mode 100644
index 6bee12675b..0000000000
--- a/app/workers/push_encrypted_message_worker.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class PushEncryptedMessageWorker
- include Sidekiq::Worker
- include Redisable
-
- def perform(encrypted_message_id)
- encrypted_message = EncryptedMessage.find(encrypted_message_id)
- message = InlineRenderer.render(encrypted_message, nil, :encrypted_message)
- timeline_id = "timeline:#{encrypted_message.device.account_id}:#{encrypted_message.device.device_id}"
-
- redis.publish(timeline_id, Oj.dump(event: :encrypted_message, payload: message))
- rescue ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/config/application.rb b/config/application.rb
index 3c62a49228..0013c78858 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -101,7 +101,8 @@ module Mastodon
end
config.before_configuration do
- require 'mastodon/redis_config'
+ require 'mastodon/redis_configuration'
+ ::REDIS_CONFIGURATION = Mastodon::RedisConfiguration.new
config.x.use_vips = ENV['MASTODON_USE_LIBVIPS'] == 'true'
diff --git a/config/environments/development.rb b/config/environments/development.rb
index e4da60ac8e..74f0913da2 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -25,7 +25,7 @@ Rails.application.configure do
config.action_controller.perform_caching = true
config.action_controller.enable_fragment_cache_logging = true
- config.cache_store = :redis_cache_store, REDIS_CACHE_PARAMS
+ config.cache_store = :redis_cache_store, REDIS_CONFIGURATION.cache
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}",
}
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 0d00ca7540..4a27310dc0 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -57,7 +57,7 @@ Rails.application.configure do
config.log_tags = [:request_id]
# Use a different cache store in production.
- config.cache_store = :redis_cache_store, REDIS_CACHE_PARAMS
+ config.cache_store = :redis_cache_store, REDIS_CONFIGURATION.cache
# Use a real queuing backend for Active Job (and separate queues per environment).
# config.active_job.queue_adapter = :resque
diff --git a/config/initializers/active_record_encryption.rb b/config/initializers/active_record_encryption.rb
index a83ca80765..b7a874e404 100644
--- a/config/initializers/active_record_encryption.rb
+++ b/config/initializers/active_record_encryption.rb
@@ -38,8 +38,4 @@ Rails.application.configure do
config.active_record.encryption.key_derivation_salt = ENV.fetch('ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT')
config.active_record.encryption.primary_key = ENV.fetch('ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY')
config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true
-
- # TODO: https://github.com/rails/rails/issues/50604#issuecomment-1880990392
- # Remove after updating to Rails 7.1.4
- ActiveRecord::Encryption.configure(**config.active_record.encryption)
end
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
index e43e38786c..9f4a41e3ab 100644
--- a/config/initializers/content_security_policy.rb
+++ b/config/initializers/content_security_policy.rb
@@ -12,24 +12,6 @@ policy = ContentSecurityPolicy.new
assets_host = policy.assets_host
media_hosts = policy.media_hosts
-def sso_host
- return unless ENV['ONE_CLICK_SSO_LOGIN'] == 'true'
- return unless ENV['OMNIAUTH_ONLY'] == 'true'
- return unless Devise.omniauth_providers.length == 1
-
- provider = Devise.omniauth_configs[Devise.omniauth_providers[0]]
- @sso_host ||= begin
- case provider.provider
- when :cas
- provider.cas_url
- when :saml
- provider.options[:idp_sso_target_url]
- when :openid_connect
- provider.options.dig(:client_options, :authorization_endpoint) || OpenIDConnect::Discovery::Provider::Config.discover!(provider.options[:issuer]).authorization_endpoint
- end
- end
-end
-
Rails.application.config.content_security_policy do |p|
p.base_uri :none
p.default_src :none
@@ -38,17 +20,16 @@ Rails.application.config.content_security_policy do |p|
p.img_src :self, :data, :blob, *media_hosts
p.style_src :self, assets_host
p.media_src :self, :data, *media_hosts
- p.frame_src :self, :https
p.manifest_src :self, assets_host
- if sso_host.present?
- p.form_action :self, sso_host
+ if policy.sso_host.present?
+ p.form_action :self, policy.sso_host
else
- p.form_action :self
+ p.form_action :self
end
- p.child_src :self, :blob, assets_host
- p.worker_src :self, :blob, assets_host
+ p.child_src :self, :blob, assets_host
+ p.worker_src :self, :blob, assets_host
if Rails.env.development?
webpacker_public_host = ENV.fetch('WEBPACKER_DEV_SERVER_PUBLIC', Webpacker.config.dev_server[:public])
@@ -56,9 +37,11 @@ Rails.application.config.content_security_policy do |p|
p.connect_src :self, :data, :blob, *media_hosts, Rails.configuration.x.streaming_api_base_url, *front_end_build_urls
p.script_src :self, :unsafe_inline, :unsafe_eval, assets_host
+ p.frame_src :self, :https, :http
else
p.connect_src :self, :data, :blob, *media_hosts, Rails.configuration.x.streaming_api_base_url
p.script_src :self, assets_host, "'wasm-unsafe-eval'"
+ p.frame_src :self, :https
end
end
diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb
index 37a818bf46..c530693a3f 100644
--- a/config/initializers/cors.rb
+++ b/config/initializers/cors.rb
@@ -22,6 +22,7 @@ Rails.application.config.middleware.insert_before 0, Rack::Cors do
expose: %w(Link X-RateLimit-Reset X-RateLimit-Limit X-RateLimit-Remaining X-Request-Id),
methods: %i(post put delete get patch options)
resource '/oauth/token', methods: [:post]
+ resource '/oauth/revoke', methods: [:post]
end
end
end
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index 86fde3cacf..b47e76c08b 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -118,8 +118,7 @@ Doorkeeper.configure do
:'admin:write:domain_blocks',
:'admin:write:ip_blocks',
:'admin:write:email_domain_blocks',
- :'admin:write:canonical_email_blocks',
- :crypto
+ :'admin:write:canonical_email_blocks'
# Change the way client credentials are retrieved from the request object.
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
index ba459e19f2..2b0563f4d3 100644
--- a/config/initializers/inflections.rb
+++ b/config/initializers/inflections.rb
@@ -19,7 +19,6 @@ ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'CLI'
inflect.acronym 'DeepL'
inflect.acronym 'DSL'
- inflect.acronym 'Ed25519'
inflect.acronym 'JsonLd'
inflect.acronym 'OEmbed'
inflect.acronym 'OStatus'
diff --git a/config/initializers/opentelemetry.rb b/config/initializers/opentelemetry.rb
index d121a95a36..8edce03b90 100644
--- a/config/initializers/opentelemetry.rb
+++ b/config/initializers/opentelemetry.rb
@@ -56,12 +56,13 @@ if ENV.keys.any? { |name| name.match?(/OTEL_.*_ENDPOINT/) }
},
})
- prefix = ENV.fetch('OTEL_SERVICE_NAME_PREFIX', 'mastodon')
+ prefix = ENV.fetch('OTEL_SERVICE_NAME_PREFIX', 'mastodon')
+ separator = ENV.fetch('OTEL_SERVICE_NAME_SEPARATOR', '/')
c.service_name = case $PROGRAM_NAME
- when /puma/ then "#{prefix}/web"
+ when /puma/ then "#{prefix}#{separator}web"
else
- "#{prefix}/#{$PROGRAM_NAME.split('/').last}"
+ "#{prefix}#{separator}#{$PROGRAM_NAME.split('/').last}"
end
c.service_version = Mastodon::Version.to_s
end
diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb
index 6b14985ae3..ed16d50a76 100644
--- a/config/initializers/paperclip.rb
+++ b/config/initializers/paperclip.rb
@@ -160,9 +160,10 @@ elsif ENV['AZURE_ENABLED'] == 'true'
)
end
else
+ Rails.configuration.x.file_storage_root_path = ENV.fetch('PAPERCLIP_ROOT_PATH', File.join(':rails_root', 'public', 'system'))
Paperclip::Attachment.default_options.merge!(
storage: :filesystem,
- path: File.join(ENV.fetch('PAPERCLIP_ROOT_PATH', File.join(':rails_root', 'public', 'system')), ':prefix_path:class', ':attachment', ':id_partition', ':style', ':filename'),
+ path: File.join(Rails.configuration.x.file_storage_root_path, ':prefix_path:class', ':attachment', ':id_partition', ':style', ':filename'),
url: ENV.fetch('PAPERCLIP_ROOT_URL', '/system') + "/#{PATH}"
)
end
diff --git a/config/initializers/regexp.rb b/config/initializers/regexp.rb
new file mode 100644
index 0000000000..4e79dc478e
--- /dev/null
+++ b/config/initializers/regexp.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+# 2s is a fairly high default, but that should account for slow servers under load
+Regexp.timeout = ENV.fetch('REGEXP_TIMEOUT', 2).to_f if Regexp.respond_to?(:timeout=)
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 5b2f317bf2..5b281c4339 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -3,7 +3,7 @@
require_relative '../../lib/mastodon/sidekiq_middleware'
Sidekiq.configure_server do |config|
- config.redis = REDIS_SIDEKIQ_PARAMS
+ config.redis = REDIS_CONFIGURATION.sidekiq
# This is used in Kubernetes setups, to signal that the Sidekiq process has started and will begin processing jobs
# This comes from https://github.com/sidekiq/sidekiq/wiki/Kubernetes#sidekiq
@@ -51,7 +51,7 @@ Sidekiq.configure_server do |config|
end
Sidekiq.configure_client do |config|
- config.redis = REDIS_SIDEKIQ_PARAMS
+ config.redis = REDIS_CONFIGURATION.sidekiq
config.client_middleware do |chain|
chain.add SidekiqUniqueJobs::Middleware::Client
diff --git a/config/initializers/stoplight.rb b/config/initializers/stoplight.rb
index 7c13d50637..0ade504f67 100644
--- a/config/initializers/stoplight.rb
+++ b/config/initializers/stoplight.rb
@@ -3,6 +3,6 @@
require 'stoplight'
Rails.application.reloader.to_prepare do
- Stoplight.default_data_store = Stoplight::DataStore::Redis.new(RedisConfiguration.new.connection)
+ Stoplight.default_data_store = Stoplight::DataStore::Redis.new(RedisConnection.new.connection)
Stoplight.default_notifiers = [Stoplight::Notifier::Logger.new(Rails.logger)]
end
diff --git a/config/locales/activerecord.be.yml b/config/locales/activerecord.be.yml
index db6b632dc4..b1495c2855 100644
--- a/config/locales/activerecord.be.yml
+++ b/config/locales/activerecord.be.yml
@@ -15,6 +15,8 @@ be:
user/invite_request:
text: Прычына
errors:
+ messages:
+ too_many_lines: перавышана абмежаванне ў %{limit} радкоў
models:
account:
attributes:
diff --git a/config/locales/activerecord.ca.yml b/config/locales/activerecord.ca.yml
index 021cc38b4f..9fa0f704b0 100644
--- a/config/locales/activerecord.ca.yml
+++ b/config/locales/activerecord.ca.yml
@@ -15,6 +15,12 @@ ca:
user/invite_request:
text: Motiu
errors:
+ attributes:
+ domain:
+ invalid: no és un nom de domini vàlid
+ messages:
+ invalid_domain_on_line: "%{value} no és un nom de domini vàlid"
+ too_many_lines: sobrepassa el límit de %{limit} línies
models:
account:
attributes:
diff --git a/config/locales/activerecord.cy.yml b/config/locales/activerecord.cy.yml
index 73b54d554e..0ad257db50 100644
--- a/config/locales/activerecord.cy.yml
+++ b/config/locales/activerecord.cy.yml
@@ -15,6 +15,12 @@ cy:
user/invite_request:
text: Rheswm
errors:
+ attributes:
+ domain:
+ invalid: "- nid yw'n enw parth dilys"
+ messages:
+ invalid_domain_on_line: Nid yw %{value} yn enw parth dilys
+ too_many_lines: "- dros y terfyn o %{limit} llinell"
models:
account:
attributes:
diff --git a/config/locales/activerecord.da.yml b/config/locales/activerecord.da.yml
index fd94a6cf9a..35151f477d 100644
--- a/config/locales/activerecord.da.yml
+++ b/config/locales/activerecord.da.yml
@@ -15,6 +15,12 @@ da:
user/invite_request:
text: Årsag
errors:
+ attributes:
+ domain:
+ invalid: er ikke et gyldigt domænenavn
+ messages:
+ invalid_domain_on_line: "%{value} er ikke et gyldigt domænenavn"
+ too_many_lines: overstiger grænsen på %{limit} linjer
models:
account:
attributes:
diff --git a/config/locales/activerecord.de.yml b/config/locales/activerecord.de.yml
index ca590bec7d..b4bcd660d8 100644
--- a/config/locales/activerecord.de.yml
+++ b/config/locales/activerecord.de.yml
@@ -15,6 +15,12 @@ de:
user/invite_request:
text: Begründung
errors:
+ attributes:
+ domain:
+ invalid: ist kein gültiger Domain-Name
+ messages:
+ invalid_domain_on_line: "%{value} ist kein gültiger Domain-Name"
+ too_many_lines: übersteigt das Limit von %{limit} Zeilen
models:
account:
attributes:
diff --git a/config/locales/activerecord.el.yml b/config/locales/activerecord.el.yml
index 1c3bcc6ebf..a476221616 100644
--- a/config/locales/activerecord.el.yml
+++ b/config/locales/activerecord.el.yml
@@ -15,6 +15,12 @@ el:
user/invite_request:
text: Αιτιολογία
errors:
+ attributes:
+ domain:
+ invalid: δεν είναι έγκυρο όνομα τομέα
+ messages:
+ invalid_domain_on_line: το %{value} δεν είναι έγκυρο όνομα τομέα
+ too_many_lines: υπερβαίνει το όριο των %{limit} γραμμών
models:
account:
attributes:
diff --git a/config/locales/activerecord.en-GB.yml b/config/locales/activerecord.en-GB.yml
index 2b1cb05a6f..72edf5e02f 100644
--- a/config/locales/activerecord.en-GB.yml
+++ b/config/locales/activerecord.en-GB.yml
@@ -15,6 +15,12 @@ en-GB:
user/invite_request:
text: Reason
errors:
+ attributes:
+ domain:
+ invalid: is not a valid domain name
+ messages:
+ invalid_domain_on_line: "%{value} is not a valid domain name"
+ too_many_lines: is over the limit of %{limit} lines
models:
account:
attributes:
diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml
index a53c7c6e9e..e135856036 100644
--- a/config/locales/activerecord.en.yml
+++ b/config/locales/activerecord.en.yml
@@ -15,6 +15,12 @@ en:
user/invite_request:
text: Reason
errors:
+ attributes:
+ domain:
+ invalid: is not a valid domain name
+ messages:
+ invalid_domain_on_line: "%{value} is not a valid domain name"
+ too_many_lines: is over the limit of %{limit} lines
models:
account:
attributes:
diff --git a/config/locales/activerecord.eo.yml b/config/locales/activerecord.eo.yml
index 99059e3856..f99f726e23 100644
--- a/config/locales/activerecord.eo.yml
+++ b/config/locales/activerecord.eo.yml
@@ -15,6 +15,12 @@ eo:
user/invite_request:
text: Kialo
errors:
+ attributes:
+ domain:
+ invalid: ne estas valida domajna nomo
+ messages:
+ invalid_domain_on_line: "%{value} ne estas valida domajna nomo"
+ too_many_lines: superas la limon de %{limit} linioj
models:
account:
attributes:
diff --git a/config/locales/activerecord.es-AR.yml b/config/locales/activerecord.es-AR.yml
index 71b7f9732d..ba4d148c8b 100644
--- a/config/locales/activerecord.es-AR.yml
+++ b/config/locales/activerecord.es-AR.yml
@@ -15,6 +15,12 @@ es-AR:
user/invite_request:
text: Motivo
errors:
+ attributes:
+ domain:
+ invalid: no es un nombre de dominio válido
+ messages:
+ invalid_domain_on_line: "%{value} no es un nombre de dominio válido"
+ too_many_lines: está por encima del límite de %{limit} líneas
models:
account:
attributes:
diff --git a/config/locales/activerecord.es-MX.yml b/config/locales/activerecord.es-MX.yml
index 882c40ae8d..4d2cba3a27 100644
--- a/config/locales/activerecord.es-MX.yml
+++ b/config/locales/activerecord.es-MX.yml
@@ -15,6 +15,12 @@ es-MX:
user/invite_request:
text: Motivo
errors:
+ attributes:
+ domain:
+ invalid: no es un nombre de dominio válido
+ messages:
+ invalid_domain_on_line: "%{value} no es un nombre de dominio válido"
+ too_many_lines: excede el límite de %{limit} líneas
models:
account:
attributes:
diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml
index 569b783103..16e2c66cbe 100644
--- a/config/locales/activerecord.es.yml
+++ b/config/locales/activerecord.es.yml
@@ -15,6 +15,12 @@ es:
user/invite_request:
text: Razón
errors:
+ attributes:
+ domain:
+ invalid: no es un nombre de dominio válido
+ messages:
+ invalid_domain_on_line: "%{value} no es un nombre de dominio válido"
+ too_many_lines: excede el límite de %{limit} líneas
models:
account:
attributes:
diff --git a/config/locales/activerecord.et.yml b/config/locales/activerecord.et.yml
index 8cabf0e0fe..7af2c362db 100644
--- a/config/locales/activerecord.et.yml
+++ b/config/locales/activerecord.et.yml
@@ -15,6 +15,12 @@ et:
user/invite_request:
text: Põhjus
errors:
+ attributes:
+ domain:
+ invalid: pole kehtiv domeeninimi
+ messages:
+ invalid_domain_on_line: "%{value} ei ole kehtiv domeeninimi"
+ too_many_lines: on üle limiidi %{limit} rida
models:
account:
attributes:
diff --git a/config/locales/activerecord.fi.yml b/config/locales/activerecord.fi.yml
index 9da69b7dbd..b4d91a5f1e 100644
--- a/config/locales/activerecord.fi.yml
+++ b/config/locales/activerecord.fi.yml
@@ -15,6 +15,12 @@ fi:
user/invite_request:
text: Syy
errors:
+ attributes:
+ domain:
+ invalid: ei ole kelvollinen verkkotunnus
+ messages:
+ invalid_domain_on_line: "%{value} ei ole kelvollinen verkkotunnus"
+ too_many_lines: ylittää %{limit} rivin rajan
models:
account:
attributes:
diff --git a/config/locales/activerecord.fo.yml b/config/locales/activerecord.fo.yml
index cf447a9dbc..61b924e5bf 100644
--- a/config/locales/activerecord.fo.yml
+++ b/config/locales/activerecord.fo.yml
@@ -15,6 +15,12 @@ fo:
user/invite_request:
text: Orsøk
errors:
+ attributes:
+ domain:
+ invalid: er ikki eitt virkið økisnavn
+ messages:
+ invalid_domain_on_line: "%{value} er ikki eitt virkið økisnavn"
+ too_many_lines: er longri enn markið á %{limit} reglur
models:
account:
attributes:
diff --git a/config/locales/activerecord.fr-CA.yml b/config/locales/activerecord.fr-CA.yml
index 1a83a0e9e2..8deeeee015 100644
--- a/config/locales/activerecord.fr-CA.yml
+++ b/config/locales/activerecord.fr-CA.yml
@@ -15,6 +15,12 @@ fr-CA:
user/invite_request:
text: Raison
errors:
+ attributes:
+ domain:
+ invalid: n'est pas un nom de domaine valide
+ messages:
+ invalid_domain_on_line: "%{value} n'est pas un nom de domaine valide"
+ too_many_lines: dépasse la limite de %{limit} lignes
models:
account:
attributes:
diff --git a/config/locales/activerecord.fr.yml b/config/locales/activerecord.fr.yml
index 24bb39502b..2f74b16d53 100644
--- a/config/locales/activerecord.fr.yml
+++ b/config/locales/activerecord.fr.yml
@@ -15,6 +15,12 @@ fr:
user/invite_request:
text: Motif
errors:
+ attributes:
+ domain:
+ invalid: n'est pas un nom de domaine valide
+ messages:
+ invalid_domain_on_line: "%{value} n'est pas un nom de domaine valide"
+ too_many_lines: dépasse la limite de %{limit} lignes
models:
account:
attributes:
diff --git a/config/locales/activerecord.ga.yml b/config/locales/activerecord.ga.yml
index 1b61edb2e2..4f83bc40aa 100644
--- a/config/locales/activerecord.ga.yml
+++ b/config/locales/activerecord.ga.yml
@@ -15,6 +15,12 @@ ga:
user/invite_request:
text: Fáth
errors:
+ attributes:
+ domain:
+ invalid: nach ainm fearainn bailí é
+ messages:
+ invalid_domain_on_line: Ní ainm fearainn bailí é %{value}
+ too_many_lines: thar an teorainn de %{limit} línte
models:
account:
attributes:
diff --git a/config/locales/activerecord.gd.yml b/config/locales/activerecord.gd.yml
index 895f035c03..26848e2584 100644
--- a/config/locales/activerecord.gd.yml
+++ b/config/locales/activerecord.gd.yml
@@ -15,6 +15,12 @@ gd:
user/invite_request:
text: Adhbhar
errors:
+ attributes:
+ domain:
+ invalid: "– chan eil seo ’na ainm àrainne dligheach"
+ messages:
+ invalid_domain_on_line: Chan eil %{value} ’na ainm àrainne dligheach
+ too_many_lines: "– tha seo thar crìoch de %{limit} nan loidhnichean"
models:
account:
attributes:
diff --git a/config/locales/activerecord.gl.yml b/config/locales/activerecord.gl.yml
index 477db570e7..961c96edb4 100644
--- a/config/locales/activerecord.gl.yml
+++ b/config/locales/activerecord.gl.yml
@@ -15,6 +15,12 @@ gl:
user/invite_request:
text: Razón
errors:
+ attributes:
+ domain:
+ invalid: non é un nome de dominio válido
+ messages:
+ invalid_domain_on_line: "%{value} non é un nome de dominio válido"
+ too_many_lines: superou o límite de %{limit} liñas
models:
account:
attributes:
diff --git a/config/locales/activerecord.he.yml b/config/locales/activerecord.he.yml
index 211d984863..1729084a4c 100644
--- a/config/locales/activerecord.he.yml
+++ b/config/locales/activerecord.he.yml
@@ -15,6 +15,12 @@ he:
user/invite_request:
text: סיבה
errors:
+ attributes:
+ domain:
+ invalid: אינו שם מתחם קביל
+ messages:
+ invalid_domain_on_line: "%{value} אינו שם מתחם קביל"
+ too_many_lines: מעבר למגבלה של %{limit} שורות
models:
account:
attributes:
diff --git a/config/locales/activerecord.hu.yml b/config/locales/activerecord.hu.yml
index f34ade0440..6e376dd678 100644
--- a/config/locales/activerecord.hu.yml
+++ b/config/locales/activerecord.hu.yml
@@ -15,6 +15,12 @@ hu:
user/invite_request:
text: Indoklás
errors:
+ attributes:
+ domain:
+ invalid: nem egy érvényes domain név
+ messages:
+ invalid_domain_on_line: "%{value} nem egy érvényes domain név"
+ too_many_lines: túllépi a(z) %{limit} soros korlátot
models:
account:
attributes:
diff --git a/config/locales/activerecord.ia.yml b/config/locales/activerecord.ia.yml
index bf1fbc67ef..bccfb96602 100644
--- a/config/locales/activerecord.ia.yml
+++ b/config/locales/activerecord.ia.yml
@@ -15,6 +15,11 @@ ia:
user/invite_request:
text: Motivo
errors:
+ attributes:
+ domain:
+ invalid: non es un nomine de dominio valide
+ messages:
+ invalid_domain_on_line: "%{value} non es un nomine de dominio valide"
models:
account:
attributes:
diff --git a/config/locales/activerecord.is.yml b/config/locales/activerecord.is.yml
index 4423cb6e47..e274cc0a9e 100644
--- a/config/locales/activerecord.is.yml
+++ b/config/locales/activerecord.is.yml
@@ -15,6 +15,12 @@ is:
user/invite_request:
text: Ástæða
errors:
+ attributes:
+ domain:
+ invalid: er ekki leyfilegt nafn á léni
+ messages:
+ invalid_domain_on_line: "%{value} er ekki leyfilegt nafn á léni"
+ too_many_lines: er yfir takmörkum á %{limit} línum
models:
account:
attributes:
diff --git a/config/locales/activerecord.it.yml b/config/locales/activerecord.it.yml
index f23513e34c..3d5be6c258 100644
--- a/config/locales/activerecord.it.yml
+++ b/config/locales/activerecord.it.yml
@@ -15,6 +15,12 @@ it:
user/invite_request:
text: Motivo
errors:
+ attributes:
+ domain:
+ invalid: non è un nome di dominio valido
+ messages:
+ invalid_domain_on_line: "%{value} non è un nome di dominio valido"
+ too_many_lines: è oltre il limite di %{limit} righe
models:
account:
attributes:
diff --git a/config/locales/activerecord.ko.yml b/config/locales/activerecord.ko.yml
index 294d614bca..6d437b72b0 100644
--- a/config/locales/activerecord.ko.yml
+++ b/config/locales/activerecord.ko.yml
@@ -15,6 +15,12 @@ ko:
user/invite_request:
text: 이유
errors:
+ attributes:
+ domain:
+ invalid: 올바른 도메인 네임이 아닙니다
+ messages:
+ invalid_domain_on_line: "%{value}는 올바른 도메인 네임이 아닙니다"
+ too_many_lines: "%{limit}줄 제한을 초과합니다"
models:
account:
attributes:
diff --git a/config/locales/activerecord.lt.yml b/config/locales/activerecord.lt.yml
index cb6e21d8e8..2e4b54c626 100644
--- a/config/locales/activerecord.lt.yml
+++ b/config/locales/activerecord.lt.yml
@@ -15,6 +15,12 @@ lt:
user/invite_request:
text: Priežastis
errors:
+ attributes:
+ domain:
+ invalid: nėra tinkamas domeno vardas.
+ messages:
+ invalid_domain_on_line: "%{value} nėra tinkamas domeno vardas."
+ too_many_lines: yra daugiau nei %{limit} eilučių ribojimą.
models:
account:
attributes:
diff --git a/config/locales/activerecord.lv.yml b/config/locales/activerecord.lv.yml
index 5e41f4630e..b7e2db65e8 100644
--- a/config/locales/activerecord.lv.yml
+++ b/config/locales/activerecord.lv.yml
@@ -15,6 +15,12 @@ lv:
user/invite_request:
text: Iemesls
errors:
+ attributes:
+ domain:
+ invalid: nav derīgs domēna nosaukums
+ messages:
+ invalid_domain_on_line: "%{value} nav derīgs domēna nosaukums"
+ too_many_lines: pārsniedz %{limit} līniju ierobežojumu
models:
account:
attributes:
diff --git a/config/locales/activerecord.nl.yml b/config/locales/activerecord.nl.yml
index ce2c28a810..ee3c8bf260 100644
--- a/config/locales/activerecord.nl.yml
+++ b/config/locales/activerecord.nl.yml
@@ -15,6 +15,12 @@ nl:
user/invite_request:
text: Reden
errors:
+ attributes:
+ domain:
+ invalid: is een ongeldige domeinnaam
+ messages:
+ invalid_domain_on_line: "%{value} is een ongeldige domeinnaam"
+ too_many_lines: overschrijdt de limiet van %{limit} regels
models:
account:
attributes:
diff --git a/config/locales/activerecord.nn.yml b/config/locales/activerecord.nn.yml
index a303af6247..a34cc7cf12 100644
--- a/config/locales/activerecord.nn.yml
+++ b/config/locales/activerecord.nn.yml
@@ -15,6 +15,12 @@ nn:
user/invite_request:
text: Grunn
errors:
+ attributes:
+ domain:
+ invalid: er ikkje eit gyldig domenenamn
+ messages:
+ invalid_domain_on_line: "%{value} er ikkje gyldig i eit domenenamn"
+ too_many_lines: er over grensa på %{limit} liner
models:
account:
attributes:
diff --git a/config/locales/activerecord.pl.yml b/config/locales/activerecord.pl.yml
index 5ae1d3778a..d0e6dda58d 100644
--- a/config/locales/activerecord.pl.yml
+++ b/config/locales/activerecord.pl.yml
@@ -15,6 +15,12 @@ pl:
user/invite_request:
text: Powód
errors:
+ attributes:
+ domain:
+ invalid: nie jest prawidłową nazwą domeny
+ messages:
+ invalid_domain_on_line: "%{value} nie jest prawidłową nazwą domeny"
+ too_many_lines: przekracza limit %{limit} linii
models:
account:
attributes:
diff --git a/config/locales/activerecord.pt-BR.yml b/config/locales/activerecord.pt-BR.yml
index ae78026629..52f2b6ee87 100644
--- a/config/locales/activerecord.pt-BR.yml
+++ b/config/locales/activerecord.pt-BR.yml
@@ -15,6 +15,12 @@ pt-BR:
user/invite_request:
text: Razão
errors:
+ attributes:
+ domain:
+ invalid: não é um nome de domínio válido
+ messages:
+ invalid_domain_on_line: "%{value} não é um nome de domínio válido"
+ too_many_lines: está acima do limite de %{limit} linhas
models:
account:
attributes:
@@ -32,7 +38,7 @@ pt-BR:
import:
attributes:
data:
- malformed: está incorreto
+ malformed: está malformado
status:
attributes:
reblog:
@@ -43,16 +49,16 @@ pt-BR:
blocked: usa provedor de e-mail não permitido
unreachable: parece não existir
role_id:
- elevated: não pode ser maior que seu cargo atual
+ elevated: não pode maior que sua função atual
user_role:
attributes:
permissions_as_keys:
- dangerous: incluir permissões que não são seguras para o cargo base
- elevated: não pode incluir permissões que o seu cargo atual não possui
- own_role: não pode ser alterado com seu cargo atual
+ dangerous: incluir permissões que não são seguras para a função base
+ elevated: não pode incluir permissões que a sua função atual não possui
+ own_role: não pode ser alterado com sua função atual
position:
- elevated: não pode ser maior do que seu cargo atual
- own_role: não pode ser alterado com seu cargo atual
+ elevated: não pode ser maior do que sua função atual
+ own_role: não pode ser alterado com sua função atual
webhook:
attributes:
events:
diff --git a/config/locales/activerecord.pt-PT.yml b/config/locales/activerecord.pt-PT.yml
index ba738741f8..60f3def5d3 100644
--- a/config/locales/activerecord.pt-PT.yml
+++ b/config/locales/activerecord.pt-PT.yml
@@ -6,7 +6,7 @@ pt-PT:
expires_at: Prazo
options: Escolhas
user:
- agreement: Acordo de serviço
+ agreement: Contrato de prestação de serviço
email: Endereço de correio electrónico
locale: Região
password: Palavra-passe
@@ -19,7 +19,7 @@ pt-PT:
account:
attributes:
username:
- invalid: apenas letras, números e underscores
+ invalid: deve conter apenas letras, números e traços inferiores
reserved: está reservado
admin/webhook:
attributes:
@@ -43,15 +43,15 @@ pt-PT:
blocked: usa um fornecedor de e-mail que não é permitido
unreachable: não parece existir
role_id:
- elevated: não pode ser maior que o da sua função atual
+ elevated: não pode ser superior à sua função atual
user_role:
attributes:
permissions_as_keys:
dangerous: incluir permissões que não são seguras para a função base
- elevated: não pode incluir permissões que a sua função atual não possui
+ elevated: não pode incluir permissões que a sua função atual não possua
own_role: não pode ser alterado com a sua função atual
position:
- elevated: não pode ser maior que o da sua função atual
+ elevated: não pode ser superior à sua função atual
own_role: não pode ser alterado com a sua função atual
webhook:
attributes:
diff --git a/config/locales/activerecord.ro.yml b/config/locales/activerecord.ro.yml
index 83c90eda29..1adec0b149 100644
--- a/config/locales/activerecord.ro.yml
+++ b/config/locales/activerecord.ro.yml
@@ -11,15 +11,21 @@ ro:
locale: Localizare
password: Parolă
user/account:
- username: Nume utilizator
+ username: Nume de utilizator
user/invite_request:
text: Motiv
errors:
+ attributes:
+ domain:
+ invalid: nu este un nume de domeniu valid
+ messages:
+ invalid_domain_on_line: "%{value} nu este un nume de domeniu valid"
+ too_many_lines: este peste limita de %{limit} linii
models:
account:
attributes:
username:
- invalid: doar litere, numere și sublinieri
+ invalid: trebuie să conțină numai litere, cifre și bară jos (_)
reserved: este rezervat
admin/webhook:
attributes:
@@ -56,4 +62,4 @@ ro:
webhook:
attributes:
events:
- invalid_permissions: nu poate include evenimente la care nu aveți drepturi
+ invalid_permissions: nu poate include evenimente la care nu aveți dreptul
diff --git a/config/locales/activerecord.ru.yml b/config/locales/activerecord.ru.yml
index 92d85af4d9..203d8e2c34 100644
--- a/config/locales/activerecord.ru.yml
+++ b/config/locales/activerecord.ru.yml
@@ -15,6 +15,12 @@ ru:
user/invite_request:
text: Причина
errors:
+ attributes:
+ domain:
+ invalid: не является действующим доменным именем
+ messages:
+ invalid_domain_on_line: "%{value} Не является действительным доменным именем"
+ too_many_lines: Превышает предел %{limit} строк
models:
account:
attributes:
diff --git a/config/locales/activerecord.sq.yml b/config/locales/activerecord.sq.yml
index 9c548bda04..888a17a1c8 100644
--- a/config/locales/activerecord.sq.yml
+++ b/config/locales/activerecord.sq.yml
@@ -15,6 +15,12 @@ sq:
user/invite_request:
text: Arsye
errors:
+ attributes:
+ domain:
+ invalid: s’është emër i vlefshëm përkatësie
+ messages:
+ invalid_domain_on_line: "%{value} s’është emër i vlefshëm përkatësie"
+ too_many_lines: është tej kufirit prej %{limit} rreshta
models:
account:
attributes:
diff --git a/config/locales/activerecord.sv.yml b/config/locales/activerecord.sv.yml
index a3a45705ec..6ac96d9ea9 100644
--- a/config/locales/activerecord.sv.yml
+++ b/config/locales/activerecord.sv.yml
@@ -15,6 +15,12 @@ sv:
user/invite_request:
text: Anledning
errors:
+ attributes:
+ domain:
+ invalid: är inte ett giltigt domännamn
+ messages:
+ invalid_domain_on_line: "%{value} Är inte ett giltigt domännamn"
+ too_many_lines: överskrider gränsen på %{limit} rader
models:
account:
attributes:
diff --git a/config/locales/activerecord.th.yml b/config/locales/activerecord.th.yml
index 3b4b57a236..e1021b8afa 100644
--- a/config/locales/activerecord.th.yml
+++ b/config/locales/activerecord.th.yml
@@ -15,6 +15,12 @@ th:
user/invite_request:
text: เหตุผล
errors:
+ attributes:
+ domain:
+ invalid: ไม่ใช่ชื่อโดเมนที่ถูกต้อง
+ messages:
+ invalid_domain_on_line: "%{value} ไม่ใช่ชื่อโดเมนที่ถูกต้อง"
+ too_many_lines: เกินขีดจำกัด %{limit} บรรทัด
models:
account:
attributes:
diff --git a/config/locales/activerecord.tr.yml b/config/locales/activerecord.tr.yml
index d2b79d256c..505289470e 100644
--- a/config/locales/activerecord.tr.yml
+++ b/config/locales/activerecord.tr.yml
@@ -15,6 +15,12 @@ tr:
user/invite_request:
text: Gerekçe
errors:
+ attributes:
+ domain:
+ invalid: geçerli bir alan adı değil
+ messages:
+ invalid_domain_on_line: "%{value} geçerli bir alan adı değil"
+ too_many_lines: "%{limit} satır sınırının üzerinde"
models:
account:
attributes:
diff --git a/config/locales/activerecord.uk.yml b/config/locales/activerecord.uk.yml
index f16750acec..c9a4c8e1ec 100644
--- a/config/locales/activerecord.uk.yml
+++ b/config/locales/activerecord.uk.yml
@@ -15,6 +15,12 @@ uk:
user/invite_request:
text: Причина
errors:
+ attributes:
+ domain:
+ invalid: не є дійсним іменем домену
+ messages:
+ invalid_domain_on_line: "%{value} не є дійсним іменем домену"
+ too_many_lines: перевищує ліміт %{limit} рядків
models:
account:
attributes:
diff --git a/config/locales/activerecord.vi.yml b/config/locales/activerecord.vi.yml
index 1b4ad0a4d2..b48510c2e2 100644
--- a/config/locales/activerecord.vi.yml
+++ b/config/locales/activerecord.vi.yml
@@ -15,6 +15,12 @@ vi:
user/invite_request:
text: Lý do
errors:
+ attributes:
+ domain:
+ invalid: không phải là một tên miền hợp lệ
+ messages:
+ invalid_domain_on_line: "%{value} không phải là một tên miền hợp lệ"
+ too_many_lines: vượt quá giới hạn %{limit} dòng
models:
account:
attributes:
diff --git a/config/locales/activerecord.zh-CN.yml b/config/locales/activerecord.zh-CN.yml
index c510a58d14..a4edf294a3 100644
--- a/config/locales/activerecord.zh-CN.yml
+++ b/config/locales/activerecord.zh-CN.yml
@@ -15,6 +15,12 @@ zh-CN:
user/invite_request:
text: 理由
errors:
+ attributes:
+ domain:
+ invalid: 不是有效的域名
+ messages:
+ invalid_domain_on_line: "%{value} 不是有效的域名"
+ too_many_lines: 超出 %{limit} 行的长度限制
models:
account:
attributes:
@@ -56,4 +62,4 @@ zh-CN:
webhook:
attributes:
events:
- invalid_permissions: 不能包含您没有权限的事件
+ invalid_permissions: 不能包含你没有权限的事件
diff --git a/config/locales/activerecord.zh-TW.yml b/config/locales/activerecord.zh-TW.yml
index 24609332cd..7422550660 100644
--- a/config/locales/activerecord.zh-TW.yml
+++ b/config/locales/activerecord.zh-TW.yml
@@ -15,6 +15,12 @@ zh-TW:
user/invite_request:
text: 原因
errors:
+ attributes:
+ domain:
+ invalid: 並非一個有效網域
+ messages:
+ invalid_domain_on_line: "%{value} 並非一個有效網域"
+ too_many_lines: 已超過行數限制 (%{limit} 行)
models:
account:
attributes:
diff --git a/config/locales/af.yml b/config/locales/af.yml
index 648ec6091d..89ede096e2 100644
--- a/config/locales/af.yml
+++ b/config/locales/af.yml
@@ -6,7 +6,6 @@ af:
hosted_on: Mastodon gehuisves op %{domain}
title: Aangaande
accounts:
- follow: Volg
followers:
one: Volgeling
other: Volgelinge
diff --git a/config/locales/an.yml b/config/locales/an.yml
index 9afc9e881d..2f181e0757 100644
--- a/config/locales/an.yml
+++ b/config/locales/an.yml
@@ -7,7 +7,6 @@ an:
hosted_on: Mastodon alochau en %{domain}
title: Sobre
accounts:
- follow: Seguir
followers:
one: Seguidor
other: Seguidores
@@ -954,7 +953,6 @@ an:
crypto:
errors:
invalid_key: no ye una clau Ed25519 u Curve25519 valida
- invalid_signature: no ye una sinyatura Ed25519 valida
date:
formats:
default: "%d %b %Y"
@@ -1017,8 +1015,6 @@ an:
your_appeal_approved: S'aprebó la tuya apelación
your_appeal_pending: Has ninviau una apelación
your_appeal_rejected: La tuya apelación ha estau refusada
- domain_validator:
- invalid_domain: no ye un nombre de dominio valido
errors:
'400': La solicitut que has ninviau no ye valida u yera malformada.
'403': No tiens permiso pa acceder ta esta pachina.
@@ -1412,23 +1408,12 @@ an:
edited_at_html: Editau %{date}
errors:
in_reply_not_found: Lo estau a lo qual intentas responder no existe.
- open_in_web: Ubrir en web
over_character_limit: Limite de caracters de %{max} superau
pin_errors:
direct: Las publicacions que son visibles solo pa los usuarios mencionaus no pueden fixar-se
limit: Ya has fixau lo numero maximo de publicacions
ownership: La publicación d'unatra persona no puede fixar-se
reblog: Un boost no puede fixar-se
- poll:
- total_people:
- one: "%{count} persona"
- other: "%{count} chent"
- total_votes:
- one: "%{count} voto"
- other: "%{count} votos"
- vote: Vota
- show_more: Amostrar mas
- show_thread: Amostrar discusión
title: "%{name}: «%{quote}»"
visibilities:
direct: Directa
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index 18dede8fbf..81705acba0 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -7,7 +7,6 @@ ar:
hosted_on: ماستدون مُستضاف على %{domain}
title: عن
accounts:
- follow: متابَعة
followers:
few: متابِعون
many: متابِعون
@@ -54,6 +53,7 @@ ar:
title: تعديل عنوان البريد الإلكتروني الخاص بـ %{username}
change_role:
changed_msg: تم تغيير بنجاح!
+ edit_roles: إدارة أدوار المستخدمين
label: تغيير الدور
no_role: بلا دور
title: تغيير دور %{username}
@@ -286,6 +286,7 @@ ar:
filter_by_action: تصفية بحسب الإجراء
filter_by_user: تصفية حسب المستخدم
title: سِجلّ التفتيش و المعاينة
+ unavailable_instance: "(اسم النطاق غير متوفر)"
announcements:
destroyed_msg: تم حذف الإعلان بنجاح!
edit:
@@ -905,6 +906,7 @@ ar:
moderation:
title: الحالة
newest: الأحدث
+ reset: إعادة التعيين
review: حالة المراجعة
search: البحث
title: الوسوم
@@ -984,12 +986,14 @@ ar:
other: مستخدَم من قِبل %{count} شخص خلال الأسبوع الماضي
two: مستخدَم من قِبل %{count} شخصين خلال الأسبوع الماضي
zero: مستخدَم من قِبل %{count} شخص خلال الأسبوع الماضي
+ title: التوصيات والرائجة
trending: المتداولة
warning_presets:
add_new: إضافة واحد جديد
delete: حذف
edit_preset: تعديل نموذج التحذير
empty: لم تحدد أي إعدادات تحذير مسبقة بعد.
+ title: نماذج التحذير
webhooks:
add_new: إضافة نقطة نهاية
delete: حذف
@@ -1139,8 +1143,10 @@ ar:
security: الأمان
set_new_password: إدخال كلمة مرور جديدة
setup:
+ email_below_hint_html: قم بفحص مجلد البريد المزعج الخاص بك، أو قم بطلب آخر. يمكنك تصحيح عنوان بريدك الإلكتروني إن كان خاطئا.
email_settings_hint_html: انقر على الرابط الذي أرسلناه لك للتحقق من %{email}. سننتظر هنا.
link_not_received: ألم تحصل على رابط؟
+ new_confirmation_instructions_sent: سوف تتلقى رسالة بريد إلكتروني جديدة مع رابط التأكيد في غضون بضع دقائق!
title: تحقَّق من بريدك الوارِد
sign_in:
preamble_html: قم بتسجيل الدخول باستخدام بيانات الاعتماد الخاصة بك على %{domain}. إن استُضيف حسابك على خادم مختلف عن هذا الخادم، لن تتمكن من الولوج هنا.
@@ -1151,12 +1157,19 @@ ar:
title: دعنا نجهّز %{domain}.
status:
account_status: حالة الحساب
+ confirming: في انتظار اكتمال تأكيد البريد الإلكتروني.
functional: حسابك يعمل بشكل كامل.
+ pending: إن طلبك قيد المراجعة من قبل فريقنا. قد يستغرق هذا بعض الوقت. سوف تتلقى بريدا إلكترونيا إذا تمت الموافقة على طلبك.
redirecting_to: حسابك غير نشط لأنه تم تحويله حاليا إلى %{acct}.
self_destruct: نظرًا لإغلاق %{domain}، ستحصل فقط على وصول محدود إلى حسابك.
view_strikes: عرض العقوبات السابقة المُطَبَّقة ضد حسابك
too_fast: تم إرسال النموذج بسرعة كبيرة، حاول مرة أخرى.
use_security_key: استخدام مفتاح الأمان
+ author_attribution:
+ example_title: عينة نص
+ more_from_html: المزيد من %{name}
+ s_blog: مدونة %{name}
+ title: إسناد المؤلف
challenge:
confirm: واصل
hint_html: "توصية: لن نطلب منك ثانية كلمتك السرية في غضون الساعة اللاحقة."
@@ -1165,7 +1178,6 @@ ar:
crypto:
errors:
invalid_key: ليس بمفتاح Ed25519 أو Curve25519 صالح
- invalid_signature: ليس بتوقيع Ed25519 صالح
date:
formats:
default: "%d %b %Y"
@@ -1194,6 +1206,9 @@ ar:
before: 'يرجى قراءة هذه الملاحظات بتأنّي قبل المواصلة:'
caches: قد يبقى المحتوى الذي تم تخزينه مؤقتًا مِن طرف الخوادم الأخرى
data_removal: سوف تُحذَف منشوراتك والبيانات الأخرى نهائيا
+ email_change_html: بإمكانك تغيير عنوان بريدك الإلكتروني دون أن يُحذف حسابك
+ email_contact_html: إن لم تتلقّ أي شيء ، يمكنك مراسلة %{email} لطلب المساعدة
+ email_reconfirmation_html: إن لم تتلقّ الرسالة الإلكترونية للتأكيد ، بإمكانك إعادة طلبها ثانيةً
irreversible: لن يكون بإمكانك استرجاع أو إعادة تنشيط حسابك
more_details_html: للمزيد مِن التفاصيل ، يرجى الإطلاع على سياسة الخصوصية.
username_available: سيصبح اسم مستخدمك متوفرا ثانية
@@ -1228,8 +1243,6 @@ ar:
your_appeal_approved: تمت الموافقة على طعنك
your_appeal_pending: لقد قمت بتقديم طعن
your_appeal_rejected: تم رفض طعنك
- domain_validator:
- invalid_domain: ليس بإسم نطاق صالح
edit_profile:
basic_information: معلومات أساسية
hint_html: "قم بتخصيص ما سيراه الناس في ملفك الشخصي العام وبجوار منشوراتك. من المرجح أن يتابعك أشخاص آخرون ويتفاعلون معك إن كان لديك صفحة شخصية مملوء وصورة."
@@ -1446,7 +1459,7 @@ ar:
two: "%{count} استخدامات"
zero: "%{count} استخدامات"
max_uses_prompt: بلا حدود
- prompt: توليد و مشاركة روابط للسماح للآخَرين بالنفاذ إلى مثيل الخادم هذا
+ prompt: توليد و مشاركة روابط للسماح للآخَرين النفاذ إلى هذا الخادم
table:
expires_at: تنتهي مدة صلاحيتها في
uses: عدد الاستخدامات
@@ -1458,6 +1471,7 @@ ar:
authentication_methods:
otp: تطبيق المصادقة الثنائية
password: كلمة المرور
+ sign_in_token: رمز الأمان للبريد الإلكتروني
webauthn: مفاتيح الأمان
description_html: إذا رأيت النشاط الذي لا تتعرف عليه، فكر في تغيير كلمة المرور الخاصة بك وتفعيل المصادقة ذات العاملين.
empty: لا يوجد سجل مصادقة متاح
@@ -1551,6 +1565,7 @@ ar:
update:
subject: قام %{name} بتحرير منشور
notifications:
+ administration_emails: إشعارات البريد الإلكتروني الإدارية
email_events_hint: 'اختر الأحداث التي تريد أن تصِلَك اشعارات عنها:'
number:
human:
@@ -1761,31 +1776,12 @@ ar:
edited_at_html: عُدّل في %{date}
errors:
in_reply_not_found: إنّ المنشور الذي تحاول الرد عليه غير موجود على ما يبدو.
- open_in_web: افتح في الويب
over_character_limit: تم تجاوز حد الـ %{max} حرف المسموح بها
pin_errors:
direct: لا يمكن تثبيت المنشورات التي يراها فقط المتسخدمون المشار إليهم
limit: لقد بلغت الحد الأقصى للمنشورات المثبتة
ownership: لا يمكن تثبيت منشور نشره شخص آخر
reblog: لا يمكن تثبيت إعادة نشر
- poll:
- total_people:
- few: "%{count} أشخاص"
- many: "%{count} أشخاص"
- one: "%{count} شخص واحد"
- other: "%{count} شخصا"
- two: "%{count} شخصين"
- zero: "%{count} شخص"
- total_votes:
- few: "%{count} أصوات"
- many: "%{count} أصوات"
- one: صوت واحد %{count}
- other: "%{count} صوتا"
- two: صوتين %{count}
- zero: بدون صوت %{count}
- vote: صوّت
- show_more: أظهر المزيد
- show_thread: اعرض خيط المحادثة
title: '%{name}: "%{quote}"'
visibilities:
direct: مباشرة
@@ -1809,13 +1805,13 @@ ar:
keep_media: الاحتفاظ بالمنشورات ذات وسائط مرفقة
keep_media_hint: لن تُحذف أي من منشوراتك التي تحتوي على وسائط مرفقة
keep_pinned: الاحتفاظ بالمنشورات المثبتة
- keep_pinned_hint: لم تقوم بحذف أي من مشاركتك المثبتة
+ keep_pinned_hint: لن تحذف أي من منشوراتك المثبتة
keep_polls: الاحتفاظ باستطلاعات الرأي
- keep_polls_hint: لم تقم بحذف أي من استطلاعاتك
+ keep_polls_hint: لن يتم حذف أي من استطلاعات الرأي الخاصة بك
keep_self_bookmark: احتفظ بالمنشورات التي أدرجتها في الفواصل المرجعية
- keep_self_bookmark_hint: لم تقم بحذف مشاركاتك الخاصة إذا قمت بوضع علامة مرجعية عليها
+ keep_self_bookmark_hint: لن تحذف منشوراتك الخاصة إذا قمت بوضع علامة مرجعية عليها
keep_self_fav: احتفظ بالمنشورات التي أدرجتها في المفضلة
- keep_self_fav_hint: لم تقم بحذف مشاركاتك الخاصة إذا كنت قد فضلتهم
+ keep_self_fav_hint: لن تحذف منشوراتك الخاصة إذا كنت قد فضلتها
min_age:
'1209600': أسبوعان
'15778476': 6 أشهر
@@ -1826,9 +1822,9 @@ ar:
'63113904': سنتان
'7889238': 3 أشهر
min_age_label: عتبة العمر
- min_favs: إبقاء المشاركات المفضلة أكثر من
+ min_favs: إبقاء المنشورات المفضلة على الأقل
min_favs_hint: لن تُحذف أي من منشوراتك التي تلقّت على الأقل هذا العدد من المفضلات. اتركه فارغاً لحذف المنشورات مهما كان عدد المفضلات التي تلقتها
- min_reblogs: إبقاء المنشورات المعاد نشرها أكثر من
+ min_reblogs: إبقاء المنشورات المعاد نشرها على الأقل
min_reblogs_hint: لن تُحذف أي من منشوراتك التي أعيد مشاركتها أكثر من هذا العدد من المرات. اتركه فارغاً لحذف المنشورات بغض النظر عن عدد إعادات النشر
stream_entries:
sensitive_content: محتوى حساس
@@ -1980,6 +1976,7 @@ ar:
instructions_html: قم بنسخ ولصق التعليمة البرمجية أدناه في شفرة HTML لموقعك الخاص على الويب. ثم أضف عنوان موقع الويب الخاص بك إلى أحد الحقول الإضافية في ملفك التعريفي عبر لسان "تعديل الملف التعريفي" ثم احفظ التغييرات.
verification: التحقق
verified_links: روابطك التي تم التحقق منها
+ website_verification: التحقق من موقع الويب
webauthn_credentials:
add: إضافة مفتاح أمان جديد
create:
diff --git a/config/locales/ast.yml b/config/locales/ast.yml
index 70a0ad3bdd..a7d4a9917e 100644
--- a/config/locales/ast.yml
+++ b/config/locales/ast.yml
@@ -486,7 +486,6 @@ ast:
crypto:
errors:
invalid_key: nun ye una clave ed25519 o curve25519 válida
- invalid_signature: nun ye una clave ed25519 válida
datetime:
distance_in_words:
about_x_hours: "%{count} h"
@@ -800,20 +799,11 @@ ast:
default_language: La mesma que la de la interfaz
errors:
in_reply_not_found: L'artículu al que tentes de responder paez que nun esiste.
- open_in_web: Abrir na web
pin_errors:
direct: Nun se puen fixar los artículos que son visibles namás pa los usuarios mentaos
limit: Yá fixesti'l númberu máximu d'artículos
ownership: Nun se pue fixar l'artículu d'otru perfil
reblog: Nun se pue fixar un artículu compartíu
- poll:
- total_people:
- one: "%{count} persona"
- other: "%{count} persones"
- total_votes:
- one: "%{count} votu"
- other: "%{count} votos"
- show_more: Amosar más
title: "%{name}: «%{quote}»"
visibilities:
direct: Mensaxe direutu
diff --git a/config/locales/be.yml b/config/locales/be.yml
index fbeb55add7..d45f443b75 100644
--- a/config/locales/be.yml
+++ b/config/locales/be.yml
@@ -7,7 +7,6 @@ be:
hosted_on: Mastodon месціцца на %{domain}
title: Пра нас
accounts:
- follow: Падпісацца
followers:
few: Падпісчыка
many: Падпісчыкаў
@@ -1190,7 +1189,6 @@ be:
crypto:
errors:
invalid_key: гэта не сапраўдны Ed25519 або Curve25519 ключ
- invalid_signature: гэта не сапраўдная Ed25519 сігнатура
date:
formats:
default: "%d.%m.%Y"
@@ -1256,8 +1254,6 @@ be:
your_appeal_approved: Ваша абскарджанне было ўхвалена
your_appeal_pending: Вы адправілі апеляцыю
your_appeal_rejected: Ваша абскарджанне было адхілена
- domain_validator:
- invalid_domain: не з'яўляецца сапраўдным даменным імем
edit_profile:
basic_information: Асноўная інфармацыя
hint_html: "Наладзьце тое, што людзі будуць бачыць у вашым профілі і побач з вашымі паведамленнямі. Іншыя людзі з большай верагоднасцю будуць сачыць і ўзаемадзейнічаць з вамі, калі ў вас ёсць запоўнены профіль і фота профілю."
@@ -1780,27 +1776,12 @@ be:
edited_at_html: Адрэдагавана %{date}
errors:
in_reply_not_found: Здаецца, допіс, на які вы спрабуеце адказаць, не існуе.
- open_in_web: Адчыніць у вэб-версіі
over_character_limit: перавышаная колькасць сімвалаў у %{max}
pin_errors:
direct: Допісы, бачныя толькі згаданым карыстальнікам, не могуць быць замацаваныя
limit: Вы ўжо замацавалі максімальную колькасць допісаў
ownership: Немагчыма замацаваць чужы допіс
reblog: Немагчыма замацаваць пашырэнне
- poll:
- total_people:
- few: "%{count} чалавекі"
- many: "%{count} чалавек"
- one: "%{count} чалавек"
- other: "%{count} чалавека"
- total_votes:
- few: "%{count} галасы"
- many: "%{count} галасоў"
- one: "%{count} голас"
- other: "%{count} голасу"
- vote: Прагаласаваць
- show_more: Паказаць больш
- show_thread: Паказаць ланцуг
title: '%{name}: "%{quote}"'
visibilities:
direct: Асабіста
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
index 56ab759174..e2c246827a 100644
--- a/config/locales/bg.yml
+++ b/config/locales/bg.yml
@@ -7,7 +7,6 @@ bg:
hosted_on: Mastodon е разположен на хост %{domain}
title: Относно
accounts:
- follow: Последване
followers:
one: Последовател
other: Последователи
@@ -1116,7 +1115,6 @@ bg:
crypto:
errors:
invalid_key: не е валиден ключ Ed25519 или Curve25519
- invalid_signature: не е валиден подпис Ed25519
date:
formats:
default: "%b %d, %Y"
@@ -1179,8 +1177,6 @@ bg:
your_appeal_approved: Вашето обжалване е одобрено
your_appeal_pending: Подадохте обжалване
your_appeal_rejected: Вашето обжалване е отхвърлено
- domain_validator:
- invalid_domain: не е валидно име на домейн
edit_profile:
basic_information: Основна информация
hint_html: "Персонализирайте какво хората виждат в обществения ви профил и до публикациите ви. Другите хора са по-склонни да ви последват и да взаимодействат с вас, когато имате попълнен профил и снимка на профила."
@@ -1666,23 +1662,12 @@ bg:
edited_at_html: Редактирано на %{date}
errors:
in_reply_not_found: Изглежда, че публикацията, на която се опитвате да отговорите, не съществува.
- open_in_web: Отвори в уеб
over_character_limit: прехвърлен лимит от %{max} символа
pin_errors:
direct: Публикациите, които са видими само за потребители споменати в тях, не могат да бъдат закачани
limit: Вече сте закачили максималния брой публикации
ownership: Публикация на някого другиго не може да бъде закачена
reblog: Раздуване не може да бъде закачано
- poll:
- total_people:
- one: "%{count} човек"
- other: "%{count} души"
- total_votes:
- one: "%{count} глас"
- other: "%{count} гласа"
- vote: Гласуване
- show_more: Покажи повече
- show_thread: Показване на нишката
title: "%{name}: „%{quote}“"
visibilities:
direct: Директно
diff --git a/config/locales/bn.yml b/config/locales/bn.yml
index edbef73ae2..74ff25d754 100644
--- a/config/locales/bn.yml
+++ b/config/locales/bn.yml
@@ -7,7 +7,6 @@ bn:
hosted_on: এই মাস্টাডনটি আছে %{domain} এ
title: পরিচিতি
accounts:
- follow: যুক্ত
followers:
one: যুক্ত আছে
other: যারা যুক্ত হয়েছে
diff --git a/config/locales/br.yml b/config/locales/br.yml
index 4ef8fa1a18..f9fbd34adb 100644
--- a/config/locales/br.yml
+++ b/config/locales/br.yml
@@ -6,7 +6,6 @@ br:
hosted_on: Servijer Mastodon herberc'hiet war %{domain}
title: Diwar-benn
accounts:
- follow: Heuliañ
followers:
few: Heulier·ez
many: Heulier·ez
@@ -519,9 +518,6 @@ br:
two: "%{count} skeudenn"
pin_errors:
ownership: N'hallit ket spilhennañ embannadurioù ar re all
- poll:
- vote: Mouezhiañ
- show_more: Diskouez muioc'h
visibilities:
direct: War-eeun
public: Publik
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index d8de84c283..33a1d4e88f 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -7,7 +7,6 @@ ca:
hosted_on: Mastodon allotjat a %{domain}
title: Quant a
accounts:
- follow: Segueix
followers:
one: Seguidor
other: Seguidors
@@ -25,6 +24,8 @@ ca:
admin:
account_actions:
action: Realitza l'acció
+ already_silenced: Aquest compte ja s'ha limitat.
+ already_suspended: Aquest compte ja s'ha suspès.
title: Fer l'acció de moderació a %{acct}
account_moderation_notes:
create: Crea nota
@@ -46,6 +47,7 @@ ca:
title: Canvia l'adreça electrònica de %{username}
change_role:
changed_msg: Els privilegis del compte s'han canviat correctament!
+ edit_roles: Gestió de rols d'usuari
label: Canvia rol
no_role: Sense rol
title: Canvia el rol per a %{username}
@@ -58,6 +60,7 @@ ca:
demote: Degrada
destroyed_msg: Les dades de %{username} son a la cua per a ser esborrades en breu
disable: Inhabilita
+ disable_sign_in_token_auth: Desactivar l'autenticació de token per correu-e
disable_two_factor_authentication: Desactiva 2FA
disabled: Inhabilitat
display_name: Nom visible
@@ -66,6 +69,7 @@ ca:
email: Adreça electrònica
email_status: Estat de l'adreça electrònica
enable: Habilita
+ enable_sign_in_token_auth: Activar l'autenticació de token per correu-e
enabled: Habilitat
enabled_msg: El compte de %{username} s’ha descongelat amb èxit
followers: Seguidors
@@ -198,8 +202,10 @@ ca:
destroy_user_role: Destrueix Rol
disable_2fa_user: Desactiva 2FA
disable_custom_emoji: Desactiva l'emoji personalitzat
+ disable_sign_in_token_auth_user: Desactivar l'autenticació de token per correu-e per a l'usuari
disable_user: Deshabilita l'usuari
enable_custom_emoji: Activa l'emoji personalitzat
+ enable_sign_in_token_auth_user: Activar l'autenticació de token per correu-e per a l'usuari
enable_user: Activa l'usuari
memorialize_account: Memoritza el compte
promote_user: Promou l'usuari
@@ -234,17 +240,21 @@ ca:
confirm_user_html: "%{name} ha confirmat l'adreça del correu electrònic de l'usuari %{target}"
create_account_warning_html: "%{name} ha enviat un avís a %{target}"
create_announcement_html: "%{name} ha creat un nou anunci %{target}"
+ create_canonical_email_block_html: "%{name} ha blocat l'adreça de correu electrònic amb el hash %{target}"
create_custom_emoji_html: "%{name} ha pujat un emoji nou %{target}"
create_domain_allow_html: "%{name} ha permès la federació amb el domini %{target}"
create_domain_block_html: "%{name} ha bloquejat el domini %{target}"
+ create_email_domain_block_html: "%{name} ha blocat el domini de correu electrònic %{target}"
create_ip_block_html: "%{name} ha creat una regla per a l'IP %{target}"
create_unavailable_domain_html: "%{name} ha aturat el lliurament al domini %{target}"
create_user_role_html: "%{name} ha creat el rol %{target}"
demote_user_html: "%{name} ha degradat l'usuari %{target}"
destroy_announcement_html: "%{name} ha eliminat l'anunci %{target}"
+ destroy_canonical_email_block_html: "%{name} ha desblocat el correu electrònic amb el hash %{target}"
destroy_custom_emoji_html: "%{name} ha esborrat l'emoji %{target}"
destroy_domain_allow_html: "%{name} no permet la federació amb el domini %{target}"
destroy_domain_block_html: "%{name} ha desbloquejat el domini %{target}"
+ destroy_email_domain_block_html: "%{name} ha desblocat el domini de correu electrònic %{target}"
destroy_instance_html: "%{name} ha purgat el domini %{target}"
destroy_ip_block_html: "%{name} ha esborrat la regla per a l'IP %{target}"
destroy_status_html: "%{name} ha eliminat el tut de %{target}"
@@ -252,8 +262,10 @@ ca:
destroy_user_role_html: "%{name} ha esborrat el rol %{target}"
disable_2fa_user_html: "%{name} ha desactivat el requisit de dos factors per a l'usuari %{target}"
disable_custom_emoji_html: "%{name} ha desactivat l'emoji %{target}"
+ disable_sign_in_token_auth_user_html: "%{name} ha desactivat l'autenticació de token per correu-e per a %{target}"
disable_user_html: "%{name} ha desactivat l'accés del usuari %{target}"
enable_custom_emoji_html: "%{name} ha activat l'emoji %{target}"
+ enable_sign_in_token_auth_user_html: "%{name} ha activat l'autenticació de token per correu-e per a %{target}"
enable_user_html: "%{name} ha activat l'accés del usuari %{target}"
memorialize_account_html: "%{name} ha convertit el compte %{target} en una pàgina de memorial"
promote_user_html: "%{name} ha promogut l'usuari %{target}"
@@ -261,6 +273,7 @@ ca:
reject_user_html: "%{name} ha rebutjat el registre de %{target}"
remove_avatar_user_html: "%{name} ha eliminat l'avatar de %{target}"
reopen_report_html: "%{name} ha reobert l'informe %{target}"
+ resend_user_html: "%{name} ha reenviat el correu-e de confirmació per %{target}"
reset_password_user_html: "%{name} ha restablert la contrasenya de l'usuari %{target}"
resolve_report_html: "%{name} ha resolt l'informe %{target}"
sensitive_account_html: "%{name} ha marcat els mèdia de %{target} com a sensibles"
@@ -421,6 +434,7 @@ ca:
attempts_over_week:
one: "%{count} intent en la darrera setmana"
other: "%{count} intents de registre en la darrera setmana"
+ created_msg: S'ha blocat el domini de correu-e
delete: Elimina
dns:
types:
@@ -429,8 +443,11 @@ ca:
new:
create: Afegir un domini
resolve: Resol domini
+ title: Blocar el nou domini de correu-e
+ no_email_domain_block_selected: No s'han canviat els bloqueigs de domini perquè no se n'ha seleccionat cap
not_permitted: No permés
resolved_through_html: Resolt mitjançant %{domain}
+ title: Dominis de correu-e blocats
export_domain_allows:
new:
title: Importa dominis permesos
@@ -584,7 +601,9 @@ ca:
resolve_description_html: No serà presa cap acció contra el compte denunciat, no se'n registrarà res i l'informe es tancarà.
silence_description_html: El compte només serà visible a qui ja el seguia o l'ha cercat manualment, limitant-ne fortament l'abast. Sempre es pot revertir. Es tancaran tots els informes contra aquest compte.
suspend_description_html: Aquest compte i tots els seus continguts seran inaccessibles i finalment eliminats, i interaccionar amb ell no serà possible. Reversible en 30 dies. Tanca tots els informes contra aquest compte.
+ actions_description_html: Decidiu quina acció a prendre per a resoldre aquest informe. Si preneu una acció punitiva contra el compte denunciat, se li enviarà una notificació per correu-e, excepte si se selecciona la categoria Spam.
actions_description_remote_html: Decideix quina acció prendre per a resoldre aquest informe. Això només afectarà com el teu servidor es comunica amb aquest compte remot i en gestiona el contingut.
+ actions_no_posts: Aquest informe no té associada cap publicació a esborrar
add_to_report: Afegir més al informe
already_suspended_badges:
local: Ja és suspès en aquest servidor
@@ -648,6 +667,7 @@ ca:
delete_data_html: Esborra el perfil de @%{acct} i els seus continguts dins de 30 dies des d'ara a no ser que es desactivi la suspensió abans
preview_preamble_html: "@%{acct} rebrà un avís amb el contingut següent:"
record_strike_html: Registra una acció contra @%{acct} per ajudar a escalar-ho en futures violacions des d'aquest compte
+ send_email_html: Envia un avís per correu-e a @%{acct}
warning_placeholder: Opcional raó adicional d'aquesta acció de moderació.
target_origin: Origen del compte denunciat
title: Informes
@@ -687,6 +707,7 @@ ca:
manage_appeals: Gestiona apel·lacions
manage_appeals_description: Permet als usuaris revisar les apel·lacions contra les accions de moderació
manage_blocks: Gestiona blocs
+ manage_blocks_description: Permet als usuaris blocar adreces IP i proveïdors de correu-e
manage_custom_emojis: Gestiona emojis personalitzats
manage_custom_emojis_description: Permet als usuaris gestionar emojis personalitzats al servidor
manage_federation: Gestiona federació
@@ -704,6 +725,7 @@ ca:
manage_taxonomies: Gestionar taxonomies
manage_taxonomies_description: Permet als usuaris revisar el contingut actual i actualitzar la configuració de l'etiqueta
manage_user_access: Gestionar l'accés dels usuaris
+ manage_user_access_description: Permet als usuaris desactivar l'autenticació de dos factors d'altres usuaris, canviar la seva adreça de correu-e i restablir la seva contrasenya
manage_users: Gestionar usuaris
manage_users_description: Permet als usuaris veure els detalls d'altres usuaris i realitzar accions de moderació contra ells
manage_webhooks: Gestionar Webhooks
@@ -1041,7 +1063,9 @@ ca:
guide_link_text: Tothom hi pot contribuir.
sensitive_content: Contingut sensible
application_mailer:
+ notification_preferences: Canviar les preferències de correu-e
salutation: "%{name},"
+ settings: 'Canviar les preferències de correu-e: %{link}'
unsubscribe: Cancel·la la subscripció
view: 'Visualització:'
view_profile: Mostra el perfil
@@ -1061,6 +1085,7 @@ ca:
hint_html: Una cosa més! Necessitem confirmar que ets una persona humana (és així com mantenim a ratlla l'spam). Resolt el CAPTCHA inferior i clica a "Segueix".
title: Revisió de seguretat
confirmations:
+ awaiting_review: S'ha confirmat la vostra adreça-e. El personal de %{domain} revisa ara el registre. Rebreu un correu si s'aprova el compte.
awaiting_review_title: S'està revisant la teva inscripció
clicking_this_link: en clicar aquest enllaç
login_link: inici de sessió
@@ -1068,6 +1093,7 @@ ca:
redirect_to_app_html: Se us hauria d'haver redirigit a l'app %{app_name}. Si això no ha passat, intenteu %{clicking_this_link} o torneu manualment a l'app.
registration_complete: La teva inscripció a %{domain} ja és completa.
welcome_title: Hola, %{name}!
+ wrong_email_hint: Si aquesta adreça de correu-e no és correcta, podeu canviar-la en els ajustos del compte.
delete_account: Elimina el compte
delete_account_html: Si vols suprimir el compte pots fer-ho aquí. Se't demanarà confirmació.
description:
@@ -1110,6 +1136,7 @@ ca:
security: Seguretat
set_new_password: Estableix una contrasenya nova
setup:
+ email_below_hint_html: Verifiqueu la carpeta de correu brossa o demaneu-ne un altre. Podeu corregir l'adreça de correu-e si no és correcta.
email_settings_hint_html: Toca l'enllaç que t'hem enviat per a verificar %{email}. Esperarem aquí mateix.
link_not_received: No has rebut l'enllaç?
new_confirmation_instructions_sent: Rebràs un nou correu amb l'enllaç de confirmació en pocs minuts!
@@ -1123,12 +1150,19 @@ ca:
title: Configurem-te a %{domain}.
status:
account_status: Estat del compte
+ confirming: Esperant que es completi la confirmació del correu-e.
functional: El teu compte està completament operatiu.
redirecting_to: El teu compte és inactiu perquè actualment està redirigint a %{acct}.
self_destruct: Com que %{domain} tanca, només tindreu accés limitat al vostre compte.
view_strikes: Veure accions del passat contra el teu compte
too_fast: Formulari enviat massa ràpid, torna a provar-ho.
use_security_key: Usa clau de seguretat
+ author_attribution:
+ example_title: Text d'exemple
+ hint_html: Controleu com se us acredita quan els enllaços es comparteixen a Mastodon.
+ more_from_html: Més de %{name}
+ s_blog: Blog de %{name}
+ title: Atribució d'autor
challenge:
confirm: Continua
hint_html: "Pista: No et preguntarem un altre cop la teva contrasenya en la pròxima hora."
@@ -1137,7 +1171,6 @@ ca:
crypto:
errors:
invalid_key: no és una clau Ed25519 o Curve25519 vàlida
- invalid_signature: no és una signatura Ed25519 vàlida
date:
formats:
default: "%b %d, %Y"
@@ -1200,8 +1233,6 @@ ca:
your_appeal_approved: La teva apel·lació s'ha aprovat
your_appeal_pending: Has enviat una apel·lació
your_appeal_rejected: La teva apel·lació ha estat rebutjada
- domain_validator:
- invalid_domain: no es un nom de domini vàlid
edit_profile:
basic_information: Informació bàsica
hint_html: "Personalitza el que la gent veu en el teu perfil públic i a prop dels teus tuts.. És més probable que altres persones et segueixin i interaccionin amb tu quan tens emplenat el teu perfil i amb la teva imatge."
@@ -1398,6 +1429,7 @@ ca:
authentication_methods:
otp: aplicació d'autenticació de dos factors
password: contrasenya
+ sign_in_token: codi de seguretat per correu electrònic
webauthn: claus de seguretat
description_html: Si veus activitat que no reconeixes, considera canviar la teva contrasenya i activar l'autenticació de dos factors.
empty: Historial d'autenticació no disponible
@@ -1408,10 +1440,21 @@ ca:
unsubscribe:
action: Sí, canceŀla la subscripció
complete: Subscripció cancel·lada
+ confirmation_html: Segur que vols donar-te de baixa de rebre %{type} de Mastodon a %{domain} a %{email}? Sempre pots subscriure't de nou des de la configuració de les notificacions per correu electrònic.
+ emails:
+ notification_emails:
+ favourite: notificacions dels favorits per correu electrònic
+ follow: notificacions dels seguiments per correu electrònic
+ follow_request: correus electrònics de peticions de seguiment
+ mention: correus electrònics de notificacions de mencions
+ reblog: correus electrònics de notificacions d'impulsos
+ resubscribe_html: Si ets dones de baixa per error pots donar-te d'alta des de la configuració de les notificacions per correu electrònic.
+ success_html: Ja no rebràs %{type} de Mastodon a %{domain} a %{email}.
title: Cancel·la la subscripció
media_attachments:
validations:
images_and_video: No es pot adjuntar un vídeo a una publicació que ja contingui imatges
+ not_found: No s'ha trobat el contingut multimèdia %{ids} o ja s'ha adjuntat a una altra publicació
not_ready: No es poden adjuntar fitxers que no s'hagin acabat de processar. Torna-ho a provar en un moment!
too_many: No es poden adjuntar més de 4 fitxers
migrations:
@@ -1488,6 +1531,8 @@ ca:
update:
subject: "%{name} ha editat una publicació"
notifications:
+ administration_emails: Notificacions per correu-e de l'administrador
+ email_events: Esdeveniments per a notificacions de correu electrònic
email_events_hint: 'Selecciona els esdeveniments per als quals vols rebre notificacions:'
number:
human:
@@ -1646,6 +1691,7 @@ ca:
import: Importació
import_and_export: Importació i exportació
migrate: Migració del compte
+ notifications: Notificacions per correu electrònic
preferences: Preferències
profile: Perfil
relationships: Seguits i seguidors
@@ -1686,23 +1732,12 @@ ca:
edited_at_html: Editat %{date}
errors:
in_reply_not_found: El tut al qual intentes respondre sembla que no existeix.
- open_in_web: Obre en la web
over_character_limit: Límit de caràcters de %{max} superat
pin_errors:
direct: Els tuts que només són visibles per als usuaris mencionats no poden ser fixats
limit: Ja has fixat el màxim nombre de tuts
ownership: No es pot fixar el tut d'algú altre
reblog: No es pot fixar un impuls
- poll:
- total_people:
- one: "%{count} persona"
- other: "%{count} persones"
- total_votes:
- one: "%{count} vot"
- other: "%{count} vots"
- vote: Vota
- show_more: Mostra'n més
- show_thread: Mostra el fil
title: '%{name}: "%{quote}"'
visibilities:
direct: Directe
@@ -1892,6 +1927,7 @@ ca:
invalid_otp_token: El codi de dos factors no és correcte
otp_lost_help_html: Si has perdut l'accés a tots dos pots contactar per %{email}
rate_limited: Excessius intents d'autenticació, torneu-hi més tard.
+ seamless_external_login: Has iniciat sessió via un servei extern. Així, els ajustos de contrasenya i correu electrònic no estan disponibles.
signed_in_as: 'Sessió iniciada com a:'
verification:
extra_instructions_html: Consell: l'enllaç al vostre lloc web pot ser invisible. La part important és rel="me"
que evita que us suplantin la identitat a llocs web amb contingut generat pels usuaris. Fins i tot podeu generar una etiqueta link
a la capçalera de la pàgina en comptes d'una a
, però el codi HTML ha de ser accessible sense requerir executar JavaScript.
@@ -1900,6 +1936,7 @@ ca:
instructions_html: Copieu i enganxeu el següent codi HTML al vostre lloc web. Després, afegiu l'adreça del vostre lloc web dins d'un dels camps extres del vostre perfil i deseu els canvis.
verification: Verificació
verified_links: Els teus enllaços verificats
+ website_verification: Verificació de web
webauthn_credentials:
add: Afegir nova clau de seguretat
create:
diff --git a/config/locales/ckb.yml b/config/locales/ckb.yml
index 15c5690cdd..bc668d2ce4 100644
--- a/config/locales/ckb.yml
+++ b/config/locales/ckb.yml
@@ -7,7 +7,6 @@ ckb:
hosted_on: مەستودۆن میوانداری کراوە لە %{domain}
title: دەربارە
accounts:
- follow: شوێن کەوە
followers:
one: شوێنکەوتوو
other: شوێنکەوتووان
@@ -609,7 +608,6 @@ ckb:
crypto:
errors:
invalid_key: کلیلی باوڕپێکراو Ed25519 یان Curve25519 دروست نییە
- invalid_signature: واژووی Ed25519 بڕوادار نییە
date:
formats:
default: "%b %d, %Y"
@@ -646,8 +644,6 @@ ckb:
strikes:
title_actions:
none: ئاگاداری
- domain_validator:
- invalid_domain: ناوی دۆمەین بڕوادار نییە
errors:
'400': داواکاریەکەی کە پێشکەشت کردووە نادروستە یان نەیپێکا.
'403': تۆ مۆڵەتت نیە بۆ بینینی ئەم لاپەڕەیە.
@@ -940,22 +936,11 @@ ckb:
other: 'هاشتاگەکانی ڕێگەپێنەدراوەی تێدابوو: %{tags}'
errors:
in_reply_not_found: ئەو دۆخەی کە تۆ هەوڵی وەڵامدانەوەی دەدەیت وادەرناکەوێت کە هەبێت.
- open_in_web: کردنەوە لە وێب
over_character_limit: سنووری نووسەی %{max} تێپەڕێنرا
pin_errors:
limit: تۆ پێشتر زۆرترین ژمارەی توتتی چەسپیوەت هەیە
ownership: نووسراوەکانی تر ناتوانرێ بسەلمێت
reblog: بەهێزکردن ناتوانرێت بچەسپێ
- poll:
- total_people:
- one: "%{count} کەس"
- other: "%{count} خەڵک"
- total_votes:
- one: "%{count} دەنگ"
- other: "%{count} دەنگەکان"
- vote: دەنگ
- show_more: زیاتر پیشان بدە
- show_thread: نیشاندانی ڕشتە
visibilities:
private: شوێنکەوتوانی تەنها
private_long: تەنها بۆ شوێنکەوتوانی پیشان بدە
diff --git a/config/locales/co.yml b/config/locales/co.yml
index 5ee69ff8ad..58ddd7d01b 100644
--- a/config/locales/co.yml
+++ b/config/locales/co.yml
@@ -6,7 +6,6 @@ co:
contact_unavailable: Micca dispunibule
hosted_on: Mastodon allughjatu nant’à %{domain}
accounts:
- follow: Siguità
followers:
one: Abbunatu·a
other: Abbunati
@@ -570,7 +569,6 @@ co:
crypto:
errors:
invalid_key: ùn hè micca una chjave Ed25519 o Curve25519 valida
- invalid_signature: ùn hè micca una firma Ed25519 valida
date:
formats:
default: "%d %b %Y"
@@ -603,8 +601,6 @@ co:
more_details_html: Per più di ditagli, videte a pulitica di vita privata.
username_available: U vostru cugnome riduvinterà dispunibule
username_unavailable: U vostru cugnome ùn sarà sempre micca dispunibule
- domain_validator:
- invalid_domain: ùn hè micca un nome di duminiu currettu
errors:
'400': A richiesta mandata ùn era micca valida o curretta.
'403': Ùn site micca auturizatu·a à vede sta pagina.
@@ -924,22 +920,11 @@ co:
other: 'cuntene l’hashtag disattivati: %{tags}'
errors:
in_reply_not_found: U statutu à quellu avete pruvatu di risponde ùn sembra micca esiste.
- open_in_web: Apre nant’à u web
over_character_limit: site sopr’à a limita di %{max} caratteri
pin_errors:
limit: Avete digià puntarulatu u numeru massimale di statuti
ownership: Pudete puntarulà solu unu di i vostri propii statuti
reblog: Ùn pudete micca puntarulà una spartera
- poll:
- total_people:
- one: "%{count} persona"
- other: "%{count} persone"
- total_votes:
- one: "%{count} votu"
- other: "%{count} voti"
- vote: Vutà
- show_more: Vede di più
- show_thread: Vede u filu
title: '%{name}: "%{quote}"'
visibilities:
direct: Direttu
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 98e2c30526..b7fc8ab1b0 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -7,7 +7,6 @@ cs:
hosted_on: Mastodon na doméně %{domain}
title: O aplikaci
accounts:
- follow: Sledovat
followers:
few: Sledující
many: Sledujících
@@ -1150,7 +1149,6 @@ cs:
crypto:
errors:
invalid_key: není platný klíč Ed25519 nebo Curve25519
- invalid_signature: není platný podpis typu Ed25519
date:
formats:
default: "%d. %b %Y"
@@ -1213,8 +1211,6 @@ cs:
your_appeal_approved: Vaše odvolání bylo schváleno
your_appeal_pending: Podali jste odvolání
your_appeal_rejected: Vaše odvolání bylo zamítnuto
- domain_validator:
- invalid_domain: není platné doménové jméno
edit_profile:
basic_information: Základní informace
hint_html: "Nastavte si, co lidé uvidí na vašem veřejném profilu a vedle vašich příspěvků. Ostatní lidé vás budou spíše sledovat a komunikovat s vámi, když budete mít vyplněný profil a profilový obrázek."
@@ -1723,27 +1719,12 @@ cs:
edited_at_html: Upraven %{date}
errors:
in_reply_not_found: Příspěvek, na který se pokoušíte odpovědět, neexistuje.
- open_in_web: Otevřít na webu
over_character_limit: byl překročen limit %{max} znaků
pin_errors:
direct: Příspěvky viditelné pouze zmíněným uživatelům nelze připnout
limit: Už jste si připnuli maximální počet příspěvků
ownership: Nelze připnout příspěvek někoho jiného
reblog: Boosty nelze připnout
- poll:
- total_people:
- few: "%{count} lidé"
- many: "%{count} lidí"
- one: "%{count} člověk"
- other: "%{count} lidí"
- total_votes:
- few: "%{count} hlasy"
- many: "%{count} hlasů"
- one: "%{count} hlas"
- other: "%{count} hlasů"
- vote: Hlasovat
- show_more: Zobrazit více
- show_thread: Zobrazit vlákno
title: "%{name}: „%{quote}“"
visibilities:
direct: Přímé
diff --git a/config/locales/cy.yml b/config/locales/cy.yml
index 73b35bf8bf..c2c193d943 100644
--- a/config/locales/cy.yml
+++ b/config/locales/cy.yml
@@ -7,7 +7,6 @@ cy:
hosted_on: Mastodon wedi ei weinyddu ar %{domain}
title: Ynghylch
accounts:
- follow: Dilyn
followers:
few: Dilynwyr
many: Dilynwyr
@@ -33,6 +32,8 @@ cy:
admin:
account_actions:
action: Cyflawni gweithred
+ already_silenced: Mae'r cyfrif hwn eisoes wedi'i gyfyngu.
+ already_suspended: Mae'r cyfrif hwn eisoes wedi'i atal.
title: Cyflawni gweithred cymedroli ar %{acct}
account_moderation_notes:
create: Gadael nodyn
@@ -54,6 +55,7 @@ cy:
title: Newid e-bost i %{username}
change_role:
changed_msg: Rôl wedi ei newid yn llwyddiannus!
+ edit_roles: Rheoli rolau defnyddwyr
label: Newid rôl
no_role: Dim rôl
title: Newid rôl %{username}
@@ -650,6 +652,7 @@ cy:
suspend_description_html: Bydd y cyfrif a'i holl gynnwys yn anhygyrch ac yn cael ei ddileu yn y pen draw, a bydd rhyngweithio ag ef yn amhosibl. Yn gildroadwy o fewn 30 diwrnod. Yn cau pob adroddiad yn erbyn y cyfrif hwn.
actions_description_html: Penderfynwch pa gamau i'w cymryd i delio gyda'r adroddiad hwn. Os cymerwch gamau cosbi yn erbyn y cyfrif a adroddwyd, bydd hysbysiad e-bost yn cael ei anfon atyn nhw, ac eithrio pan fydd y categori Sbam yn cael ei ddewis.
actions_description_remote_html: Penderfynwch pa gamau i'w cymryd i ddatrys yr adroddiad hwn. Bydd hyn ond yn effeithio ar sut mae'ch gweinydd yn cyfathrebu â'r cyfrif hwn o bell ac yn trin ei gynnwys.
+ actions_no_posts: Nid oes gan yr adroddiad hwn unrhyw bostiadau cysylltiedig i'w dileu
add_to_report: Ychwanegu rhagor i adroddiad
already_suspended_badges:
local: Wedi atal dros dro ar y gweinydd hwn yn barod
@@ -954,6 +957,7 @@ cy:
name: Enw
newest: Mwyaf newydd
oldest: Hynaf
+ open: Gweld yn gyhoeddus
reset: Ailosod
review: Adolygu statws
search: Chwilio
@@ -1228,6 +1232,12 @@ cy:
view_strikes: Gweld rybuddion y gorffennol yn erbyn eich cyfrif
too_fast: Cafodd y ffurflen ei chyflwyno'n rhy gyflym, ceisiwch eto.
use_security_key: Defnyddiwch allwedd diogelwch
+ author_attribution:
+ example_title: Testun enghreifftiol
+ hint_html: Rheolwch sut rydych chi'n cael eich canmol pan fydd dolenni'n cael eu rhannu ar Mastodon.
+ more_from_html: Mwy gan %{name}
+ s_blog: Blog %{name}
+ title: Priodoliad awdur
challenge:
confirm: Parhau
hint_html: "Awgrym: Fyddwn ni ddim yn gofyn i chi am eich cyfrinair eto am yr awr nesaf."
@@ -1236,7 +1246,6 @@ cy:
crypto:
errors:
invalid_key: ddim yn allwedd Ed25519 na Curve25519 dilys
- invalid_signature: ddim yn llofnod Ed25519 dilys
date:
formats:
default: "%b %d %Y"
@@ -1302,8 +1311,6 @@ cy:
your_appeal_approved: Mae eich apêl wedi'i chymeradwyo
your_appeal_pending: Rydych wedi cyflwyno apêl
your_appeal_rejected: Mae eich apêl wedi'i gwrthod
- domain_validator:
- invalid_domain: ddim yn enw parth dilys
edit_profile:
basic_information: Gwybodaeth Sylfaenol
hint_html: "Addaswch yr hyn y mae pobl yn ei weld ar eich proffil cyhoeddus ac wrth ymyl eich postiadau. Mae pobl eraill yn fwy tebygol o'ch dilyn yn ôl a rhyngweithio â chi pan fydd gennych broffil wedi'i lenwi a llun proffil."
@@ -1557,6 +1564,7 @@ cy:
media_attachments:
validations:
images_and_video: Methu atodi fideo i bostiad sydd eisoes yn cynnwys delweddau
+ not_found: Cyfryngau %{ids} heb eu canfod neu wedi'u hatodi i bostiad arall yn barod
not_ready: Methu atodi ffeiliau nad ydynt wedi gorffen prosesu. Ceisiwch eto, cyn hir!
too_many: Methu atodi mwy na 4 ffeil
migrations:
@@ -1850,31 +1858,12 @@ cy:
edited_at_html: Wedi'i olygu %{date}
errors:
in_reply_not_found: Nid yw'n ymddangos bod y postiad rydych chi'n ceisio ei ateb yn bodoli.
- open_in_web: Agor yn y we
over_character_limit: wedi mynd y tu hwnt i'r terfyn nodau o %{max}
pin_errors:
direct: Nid oes modd pinio postiadau sy'n weladwy i ddefnyddwyr a grybwyllwyd yn unig
limit: Rydych chi eisoes wedi pinio uchafswm nifer y postiadau
ownership: Nid oes modd pinio postiad rhywun arall
reblog: Nid oes modd pinio hwb
- poll:
- total_people:
- few: "%{count} person"
- many: "%{count} person"
- one: "%{count} berson"
- other: "%{count} person"
- two: "%{count} person"
- zero: "%{count} o bersonau"
- total_votes:
- few: "%{count} pleidlais"
- many: "%{count} pleidlais"
- one: "%{count} bleidlais"
- other: "%{count} pleidlais"
- two: "%{count} pleidlais"
- zero: "%{count} o bleidleisiau"
- vote: Pleidlais
- show_more: Dangos mwy
- show_thread: Dangos edefyn
title: '%{name}: "%{quote}"'
visibilities:
direct: Uniongyrchol
@@ -2077,6 +2066,7 @@ cy:
instructions_html: Copïwch a gludo'r cod isod i HTML eich gwefan. Yna ychwanegwch gyfeiriad eich gwefan i un o'r meysydd ychwanegol ar eich proffil o'r tab "Golygu proffil" a chadw'r newidiadau.
verification: Dilysu
verified_links: Eich dolenni wedi'u dilysu
+ website_verification: Gwirio gwefan
webauthn_credentials:
add: Ychwanegu allwedd ddiogelwch newydd
create:
diff --git a/config/locales/da.yml b/config/locales/da.yml
index 94f2369f8e..a177b97de7 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -7,7 +7,6 @@ da:
hosted_on: Mastodon hostet på %{domain}
title: Om
accounts:
- follow: Følg
followers:
one: Følger
other: tilhængere
@@ -25,6 +24,8 @@ da:
admin:
account_actions:
action: Udfør handling
+ already_silenced: Denne konto er allerede blevet begrænset.
+ already_suspended: Denne konto er allerede suspenderet.
title: Udfør moderatorhandling på %{acct}
account_moderation_notes:
create: Skriv notat
@@ -46,6 +47,7 @@ da:
title: Skift e-mail for %{username}
change_role:
changed_msg: Rolle ændret!
+ edit_roles: Håndtér brugerroller
label: Ændr rolle
no_role: Ingen rolle
title: Ændr rolle for %{username}
@@ -602,6 +604,7 @@ da:
suspend_description_html: Kontoen inkl. alt indhold utilgængeliggøres og interaktion umuliggøres, og den slettes på et tidspunkt. Kan omgøres inden for 30 dage. Lukker alle indrapporteringer af kontoen.
actions_description_html: Afgør, hvilke foranstaltning, der skal træffes for at løse denne anmeldelse. Ved en straffende foranstaltning mod den anmeldte konto, fremsendes en e-mailnotifikation, undtagen når kategorien Spam er valgt.
actions_description_remote_html: Fastslå en nødvendig handling mhp. at løse denne anmeldelse. Dette vil kun påvirke din servers kommunikation med, og indholdshåndtering for, fjernkontoen.
+ actions_no_posts: Denne anmeldelse har ingen tilknyttede indlæg at slette
add_to_report: Føj mere til anmeldelse
already_suspended_badges:
local: Allerede suspenderet på denne server
@@ -1157,6 +1160,12 @@ da:
view_strikes: Se tidligere anmeldelser af din konto
too_fast: Formularen indsendt for hurtigt, forsøg igen.
use_security_key: Brug sikkerhedsnøgle
+ author_attribution:
+ example_title: Eksempeltekst
+ hint_html: Styrer, hvordan man krediteres, når links deles på Mastodon.
+ more_from_html: Flere fra %{name}
+ s_blog: "%{name}s blog"
+ title: Forfattertilskrivning
challenge:
confirm: Fortsæt
hint_html: "Tip: Du bliver ikke anmodet om din adgangskode igen den næste time."
@@ -1165,7 +1174,6 @@ da:
crypto:
errors:
invalid_key: er ikke en gyldig Ed25519- eller Curve25519-nøgle
- invalid_signature: er ikke en gylidig Ed25519-signatur
date:
formats:
default: "%d. %b %Y"
@@ -1231,8 +1239,6 @@ da:
your_appeal_approved: Din appel er godkendt
your_appeal_pending: Du har indgivet en appel
your_appeal_rejected: Din appel er afvist
- domain_validator:
- invalid_domain: er ikke et gyldigt domænenavn
edit_profile:
basic_information: Oplysninger
hint_html: "Tilpas hvad folk ser på din offentlige profil og ved siden af dine indlæg. Andre personer vil mere sandsynligt følge dig tilbage og interagere med dig, når du har en udfyldt profil og et profilbillede."
@@ -1454,6 +1460,7 @@ da:
media_attachments:
validations:
images_and_video: En video kan ikke vedhæftes et indlæg med billedindhold
+ not_found: Mediet %{ids} ikke fundet eller allerede vedhæftet andet indlæg
not_ready: Filer under behandling kan ikke vedhæftes. Forsøg igen senere!
too_many: Maks. 4 filer kan vedhæftes
migrations:
@@ -1731,23 +1738,12 @@ da:
edited_at_html: Redigeret %{date}
errors:
in_reply_not_found: Indlægget, der forsøges besvaret, ser ikke ud til at eksistere.
- open_in_web: Åbn i webbrowser
over_character_limit: grænsen på %{max} tegn overskredet
pin_errors:
direct: Indlæg, som kun kan ses af omtalte brugere, kan ikke fastgøres
limit: Maksimalt antal indlæg allerede fastgjort
ownership: Andres indlæg kan ikke fastgøres
reblog: Et boost kan ikke fastgøres
- poll:
- total_people:
- one: "%{count} person"
- other: "%{count} personer"
- total_votes:
- one: "%{count} stemme"
- other: "%{count} stemmer"
- vote: Stem
- show_more: Vis flere
- show_thread: Vis tråd
title: '%{name}: "%{quote}"'
visibilities:
direct: Direkte
@@ -1946,6 +1942,7 @@ da:
instructions_html: Kopier og indsæt koden nedenfor i HTML på din hjemmeside. Tilføj derefter adressen på din hjemmeside i et af de ekstra felter på din profil på fanen "Redigér profil" og gem ændringer.
verification: Bekræftelse
verified_links: Dine bekræftede links
+ website_verification: Webstedsbekræftelse
webauthn_credentials:
add: Tilføj ny sikkerhedsnøgle
create:
diff --git a/config/locales/de.yml b/config/locales/de.yml
index a852c736cf..85e24c230e 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -7,7 +7,6 @@ de:
hosted_on: Mastodon, gehostet auf %{domain}
title: Über
accounts:
- follow: Folgen
followers:
one: Follower
other: Follower
@@ -25,6 +24,8 @@ de:
admin:
account_actions:
action: Aktion ausführen
+ already_silenced: Dieses Konto wurde bereits eingeschränkt.
+ already_suspended: Dieses Konto wurde bereits gesperrt.
title: "@%{acct} moderieren"
account_moderation_notes:
create: Notiz abspeichern
@@ -46,6 +47,7 @@ de:
title: E-Mail-Adresse für %{username} ändern
change_role:
changed_msg: Rolle erfolgreich geändert!
+ edit_roles: Rollen verwalten
label: Rolle ändern
no_role: Keine Rolle
title: Rolle für %{username} ändern
@@ -602,6 +604,7 @@ de:
suspend_description_html: Das Konto und alle Inhalte werden unzugänglich und ggf. gelöscht. Eine Interaktion mit dem Konto wird unmöglich. Dies kann innerhalb von 30 Tagen rückgängig gemacht werden. Alle Meldungen zu diesem Konto werden geschlossen.
actions_description_html: Entscheide, welche Maßnahmen du zum Klären dieser Meldung ergreifen möchtest. Wenn du eine Strafmaßnahme gegen das gemeldete Konto ergreifst, wird eine E-Mail-Benachrichtigung an dieses gesendet, außer wenn die Spam-Kategorie ausgewählt ist.
actions_description_remote_html: Entscheide, welche Maßnahmen du zum Klären dieser Meldung ergreifen möchtest. Dies wirkt sich lediglich darauf aus, wie dein Server mit diesem externen Konto kommuniziert und dessen Inhalt handhabt.
+ actions_no_posts: Diese Meldung enthält keine zu löschenden Beiträge
add_to_report: Meldung ergänzen
already_suspended_badges:
local: Auf diesem Server bereits gesperrt
@@ -1157,6 +1160,12 @@ de:
view_strikes: Vorherige Verstöße deines Kontos ansehen
too_fast: Formular zu schnell übermittelt. Bitte versuche es erneut.
use_security_key: Sicherheitsschlüssel verwenden
+ author_attribution:
+ example_title: Beispieltext
+ hint_html: Bestimme, wie du Anerkennungen durch geteilte Links auf Mastodon handhaben möchtest.
+ more_from_html: Mehr von %{name}
+ s_blog: Blog von %{name}
+ title: Anerkennung als Autor*in
challenge:
confirm: Fortfahren
hint_html: "Hinweis: Wir werden dich für die nächste Stunde nicht erneut nach deinem Passwort fragen."
@@ -1165,7 +1174,6 @@ de:
crypto:
errors:
invalid_key: ist kein gültiger Ed25519- oder Curve25519-Schlüssel
- invalid_signature: ist keine gültige Ed25519-Signatur
date:
formats:
default: "%d. %b %Y"
@@ -1231,8 +1239,6 @@ de:
your_appeal_approved: Dein Einspruch wurde angenommen
your_appeal_pending: Du hast Einspruch erhoben
your_appeal_rejected: Dein Einspruch wurde abgelehnt
- domain_validator:
- invalid_domain: ist keine gültige Domain
edit_profile:
basic_information: Allgemeine Informationen
hint_html: "Bestimme, was andere auf deinem öffentlichen Profil und neben deinen Beiträgen sehen können. Wenn du ein Profilbild festlegst und dein Profil vervollständigst, werden andere eher mit dir interagieren und dir folgen."
@@ -1454,6 +1460,7 @@ de:
media_attachments:
validations:
images_and_video: Es kann kein Video an einen Beitrag angehängt werden, der bereits Bilder enthält
+ not_found: Medieninhalt(e) %{ids} nicht gefunden oder bereits an einen anderen Beitrag angehängt
not_ready: Dateien, die noch nicht verarbeitet wurden, können nicht angehängt werden. Versuche es gleich noch einmal!
too_many: Mehr als vier Dateien können nicht angehängt werden
migrations:
@@ -1731,23 +1738,12 @@ de:
edited_at_html: 'Bearbeitet: %{date}'
errors:
in_reply_not_found: Der Beitrag, auf den du antworten möchtest, scheint nicht zu existieren.
- open_in_web: Im Webinterface öffnen
over_character_limit: Begrenzung von %{max} Zeichen überschritten
pin_errors:
direct: Beiträge, die nur für erwähnte Profile sichtbar sind, können nicht angeheftet werden
limit: Du hast bereits die maximale Anzahl an Beiträgen angeheftet
ownership: Du kannst nur eigene Beiträge anheften
reblog: Du kannst keine geteilten Beiträge anheften
- poll:
- total_people:
- one: "%{count} Stimme"
- other: "%{count} Stimmen"
- total_votes:
- one: "%{count} Stimme"
- other: "%{count} Stimmen"
- vote: Abstimmen
- show_more: Mehr anzeigen
- show_thread: Thread anzeigen
title: "%{name}: „%{quote}“"
visibilities:
direct: Direktnachricht
@@ -1946,6 +1942,7 @@ de:
instructions_html: Kopiere den unten stehenden Code und füge ihn in das HTML deiner Website ein. Trage anschließend die Adresse deiner Website in ein Zusatzfeld auf deinem Profil ein und speichere die Änderungen. Die Zusatzfelder befinden sich im Reiter „Profil bearbeiten“.
verification: Verifizierung
verified_links: Deine verifizierten Links
+ website_verification: Website-Verifizierung
webauthn_credentials:
add: Sicherheitsschlüssel hinzufügen
create:
diff --git a/config/locales/devise.eo.yml b/config/locales/devise.eo.yml
index 193fecc757..f0322a60a8 100644
--- a/config/locales/devise.eo.yml
+++ b/config/locales/devise.eo.yml
@@ -48,10 +48,13 @@ eo:
subject: 'Mastodon: Instrukcioj por ŝanĝi pasvorton'
title: Pasvorto restarigita
two_factor_disabled:
+ explanation: Ensalutu nun eblas uzante nur retadreson kaj pasvorton.
subject: 'Mastodon: dufaktora aŭtentigo malebligita'
+ subtitle: Dupaŝa aŭtentigo por via konto estas malŝaltita.
title: 2FA estas malŝaltita
two_factor_enabled:
subject: 'Mastodon: Dufaktora aŭtentigo ebligita'
+ subtitle: Dupaŝa aŭtentigo por via konto estas ŝaltita.
title: 2FA aktivigita
two_factor_recovery_codes_changed:
explanation: La antaŭaj reakiraj kodoj estis nuligitaj kaj novaj estis generitaj.
diff --git a/config/locales/devise.kab.yml b/config/locales/devise.kab.yml
index 20249aae94..32a98a37c3 100644
--- a/config/locales/devise.kab.yml
+++ b/config/locales/devise.kab.yml
@@ -11,9 +11,9 @@ kab:
invalid: Tella tuccḍa deg %{authentication_keys} neγ deg wawal uffir.
last_attempt: Γur-k yiwen n uɛraḍ-nniḍen kan send ad yettucekkel umiḍan-ik.
locked: Amiḍan-ik yettwargel.
- not_found_in_database: Tella tuccḍa deg %{authentication_keys} neγ deg wawal uffir.
+ not_found_in_database: Tella tuccḍa deg %{authentication_keys} neɣ deg wawal uffir.
omniauth_user_creation_failure: Tuccḍa lawan n tmerna n umiḍan i timagit-a.
- pending: Amiḍan-inek mazal-it deg ɛiwed n tmuγli.
+ pending: Amiḍan-inek·inem mazal-it deg ɛiwed n tmuɣli.
timeout: Tiɣimit n tuqqna tezri. Ma ulac aɣilif ɛiwed tuqqna akken ad tkemmleḍ.
unauthenticated: Ilaq ad teqqneḍ neɣ ad tjerrḍeḍ send ad tkemmelḍ.
unconfirmed: Ilaq ad wekdeḍ tansa-inek·inem imayl send ad tkemmelḍ.
diff --git a/config/locales/devise.lv.yml b/config/locales/devise.lv.yml
index 94b4774b60..4470c8109e 100644
--- a/config/locales/devise.lv.yml
+++ b/config/locales/devise.lv.yml
@@ -14,9 +14,9 @@ lv:
not_found_in_database: Nederīga %{authentication_keys} vai parole.
omniauth_user_creation_failure: Kļūda šīs identitātes konta izveidošanā.
pending: Tavs konts joprojām tiek pārskatīts.
- timeout: Tava sesija ir beigusies. Lūdzu, pieraksties vēlreiz, lai turpinātu.
- unauthenticated: Lai turpinātu, tev ir jāpierakstās vai jāreģistrējas.
- unconfirmed: Lai turpinātu, tev ir jāapstiprina savu e-pasta adresi.
+ timeout: Sesijair beigusies. Lūgums vēlreiz pieteikties, lai turpinātu.
+ unauthenticated: Lai turpinātu, jāpiesakās vai jāreģistrējas.
+ unconfirmed: Lai turpinātu, jāapliecina sava e-pasta adrese.
mailer:
confirmation_instructions:
action: Apstiprini savu e-pasta adresi
@@ -108,7 +108,7 @@ lv:
unlocks:
send_instructions: Pēc dažām minūtēm tu saņemsi e-pastu ar norādījumiem, kā atbloķēt savu kontu. Lūdzu, pārbaudi spama mapi, ja neesi saņēmis šo e-pastu.
send_paranoid_instructions: Ja tavs konts eksistē, dažu minūšu laikā tu saņemsi e-pastu ar norādījumiem, kā to atbloķēt. Lūdzu, pārbaudi spama mapi, ja neesi saņēmis šo e-pastu.
- unlocked: Tavs konts ir veiksmīgi atbloķēts. Lūdzu, pieraksties, lai turpinātu.
+ unlocked: Konts tika veiksmīgi atbloķēts. Lūgums pieteikties, lai turpinātu.
errors:
messages:
already_confirmed: jau tika apstiprināts, lūdzu, mēģini pierakstīties
diff --git a/config/locales/devise.pt-BR.yml b/config/locales/devise.pt-BR.yml
index 4a7f346fab..8f504362de 100644
--- a/config/locales/devise.pt-BR.yml
+++ b/config/locales/devise.pt-BR.yml
@@ -14,7 +14,7 @@ pt-BR:
not_found_in_database: "%{authentication_keys} ou senha inválida."
omniauth_user_creation_failure: Erro ao criar uma conta para esta identidade.
pending: Sua conta está sendo revisada.
- timeout: Sua sessão expirou. Por favor, entre novamente para continuar.
+ timeout: Sua sessão expirou. Faça ‘login’ novamente para continuar.
unauthenticated: Você precisa entrar ou criar uma conta antes de continuar.
unconfirmed: Você precisa confirmar o seu endereço de e-mail antes de continuar.
mailer:
@@ -48,12 +48,12 @@ pt-BR:
subject: 'Mastodon: Instruções para alterar senha'
title: Redefinir senha
two_factor_disabled:
- explanation: O ‘login’ agora é possível usando apenas o endereço de e-mail e senha.
+ explanation: O ‘login’ agora é possível usando apenas o endereço eletrônico e senha.
subject: 'Mastodon: Autenticação de dois fatores desativada'
subtitle: A autenticação de dois fatores foi desativada.
title: 2FA desativada
two_factor_enabled:
- explanation: Será necessário um código gerado pelo aplicativo de autenticação para fazer login.
+ explanation: Será necessário um código gerado pelo aplicativo de autenticação TOTP para fazer login.
subject: 'Mastodon: Autenticação de dois fatores ativada'
subtitle: A autenticação de dois fatores foi ativada para sua conta.
title: 2FA ativada
@@ -75,11 +75,11 @@ pt-BR:
title: Uma das suas chaves de segurança foi excluída
webauthn_disabled:
explanation: A autenticação por chaves de segurança foi desativada para sua conta.
- extra: O login agora é possível usando o código gerado por um aplicativo de autenticação de dois fatores.
+ extra: Agora você pode fazer login usando apenas o código gerado pelo aplicativo de autenticação TOTP.
subject: 'Mastodon: Autenticação por chaves de segurança desativada'
title: Chaves de segurança desativadas
webauthn_enabled:
- explanation: Autenticação por chave de segurança foi ativada para sua conta.
+ explanation: A autenticação por chave de segurança foi ativada para sua conta.
extra: Sua chave de segurança agora pode ser usada para ‘login’.
subject: 'Mastodon: Autenticação por chaves de segurança ativada'
title: Chaves de segurança ativadas
diff --git a/config/locales/devise.pt-PT.yml b/config/locales/devise.pt-PT.yml
index c66181fc5b..edfb798509 100644
--- a/config/locales/devise.pt-PT.yml
+++ b/config/locales/devise.pt-PT.yml
@@ -2,117 +2,117 @@
pt-PT:
devise:
confirmations:
- confirmed: O seu endereço correio electrónico foi correctamente confirmado.
- send_instructions: Vais receber um e-mail com as instruções para confirmar o teu endereço de e-mail dentro de alguns minutos. Por favor, verifica a caixa de spam se não recebeu o e-mail.
- send_paranoid_instructions: Se o teu endereço de e-mail já existir na nossa base de dados, vais receber um e-mail com as instruções de confirmação dentro de alguns minutos. Por favor, verifica a caixa de spam se não recebeu o e-mail.
+ confirmed: O seu endereço de e-mail foi corretamente confirmado.
+ send_instructions: Irá receber um e-mail com instruções sobre como confirmar o seu endereço de e-mail dentro de alguns minutos. Verifique a sua pasta de spam se não recebeu este e-mail.
+ send_paranoid_instructions: Se o seu endereço de e-mail existir na nossa base de dados, receberá um e-mail com instruções sobre como confirmar o seu endereço de e-mail dentro de alguns minutos. Verifique a sua pasta de spam se não recebeu este e-mail.
failure:
- already_authenticated: A tua sessão já está aberta.
- inactive: A tua conta ainda não está ativada.
+ already_authenticated: Já tem sessão iniciada.
+ inactive: A sua conta ainda não está ativada.
invalid: "%{authentication_keys} ou palavra-passe inválida."
last_attempt: Tem só mais uma tentativa antes da sua conta ser bloqueada.
- locked: A tua conta está bloqueada.
+ locked: A sua conta está bloqueada.
not_found_in_database: "%{authentication_keys} ou palavra-passe inválida."
omniauth_user_creation_failure: Erro ao criar uma conta para esta identidade.
pending: A sua conta está ainda a aguardar revisão.
- timeout: A tua sessão expirou. Por favor, entra de novo para continuares.
- unauthenticated: Precisas de entrar na tua conta ou de te registares antes de continuar.
- unconfirmed: Tens de confirmar o teu endereço de e-mail antes de continuar.
+ timeout: A sua sessão expirou. Inicie sessão novamente para continuar.
+ unauthenticated: É necessário iniciar sessão ou registar-se antes de continuar.
+ unconfirmed: Tem de confirmar o seu endereço de e-mail antes de continuar.
mailer:
confirmation_instructions:
action: Verificar o endereço de e-mail
action_with_app: Confirmar e regressar a %{app}
- explanation: Criou uma conta em %{host} com este endereço de e-mail. Está a um clique de ativá-la. Se não foi você que fez este registo, por favor ignore esta mensagem.
+ explanation: Foi criada uma conta em %{host} com este endereço de e-mail. Está a um clique de ativá-la. Se não foi você que fez este registo, por favor ignore esta mensagem.
explanation_when_pending: Candidatou-se com um convite para %{host} com este endereço de e-mail. Logo que confirme o seu endereço de e-mail, iremos rever a sua candidatura. Pode iniciar sessão para alterar os seus dados ou eliminar a sua conta, mas não poderá aceder à maioria das funções até que a sua conta seja aprovada. Se a sua inscrição for indeferida, os seus dados serão eliminados, pelo que não será necessária qualquer ação adicional da sua parte. Se não solicitou este convite, queira ignorar este e-mail.
- extra_html: Por favor leia as regras da instância e os nossos termos de serviço.
- subject: 'Mastodon: Instruções de confirmação %{instance}'
+ extra_html: Por favor leia as regras do servidor e os nossos termos de serviço.
+ subject: 'Mastodon: instruções de confirmação para %{instance}'
title: Verificar o endereço de e-mail
email_changed:
explanation: 'O e-mail associado à sua conta será alterado para:'
- extra: Se não alterou o seu e-mail, é possível que alguém tenha conseguido aceder à sua conta. Por favor altere a sua palavra-passe imediatamente ou entra em contacto com um administrador da instância se tiver ficado sem acesso à sua conta.
- subject: 'Mastodon: E-mail alterado'
+ extra: Se não alterou o seu e-mail, é possível que alguém tenha conseguido aceder à sua conta. Por favor altere a sua palavra-passe imediatamente ou entre em contacto com um administrador do servidor se tiver ficado sem acesso à sua conta.
+ subject: 'Mastodon: e-mail alterado'
title: Novo endereço de e-mail
password_change:
- explanation: A palavra-passe da tua conta foi alterada.
- extra: Se não alterou a sua palavra-passe, é possível que alguém tenha conseguido aceder à sua conta. Por favor altere a sua palavra-passe imediatamente ou entre em contacto com um administrador da instância se tiver ficado sem acesso à sua conta.
+ explanation: A palavra-passe da sua conta foi alterada.
+ extra: Se não alterou a sua palavra-passe, é possível que alguém tenha conseguido aceder à sua conta. Por favor altere a sua palavra-passe imediatamente ou entre em contacto com um administrador do servidor se tiver ficado sem acesso à sua conta.
subject: 'Mastodon: palavra-passe alterada'
title: Palavra-passe alterada
reconfirmation_instructions:
explanation: Confirme o seu novo endereço para alterar o e-mail.
- extra: Se esta mudança não foi iniciada por si, queira ignorar este e-mail. O endereço de correio electrónico da sua conta do Mastodon não irá mudar enquanto não aceder à hiperligação acima.
- subject: 'Mastodon: Confirmação de e-mail %{instance}'
+ extra: Se esta alteração não foi iniciada por si, ignore este e-mail. O endereço de e-mail da conta Mastodon não será alterado até aceder à hiperligação acima.
+ subject: 'Mastodon: confirmação de e-mail para %{instance}'
title: Validar o endereço de e-mail
reset_password_instructions:
action: Alterar palavra-passe
- explanation: Pediste a alteração da palavra-passe da tua conta.
- extra: Se não fez este pedido, queira ignorar este e-mail. A sua palavra-passe não irá mudar se não aceder à hiperligação acima e criar uma nova.
- subject: 'Mastodon: Instruções para redefinir a palavra-passe'
+ explanation: Solicitou uma nova palavra-passe para a sua conta.
+ extra: Se não solicitou esta alteração, ignore este e-mail. A sua palavra-passe não será alterada até aceder à hiperligação acima e criar uma nova.
+ subject: 'Mastodon: instruções para redefinir a palavra-passe'
title: Solicitar nova palavra-passe
two_factor_disabled:
- explanation: O acesso agora é possível usando apenas o endereço de correio eletrónico e palavra-passe.
- subject: 'Mastodon: Autenticação de duas etapas desativada'
+ explanation: O início de sessão é agora possível utilizando apenas o endereço de e-mail e a palavra-passe.
+ subject: 'Mastodon: autenticação de duas etapas desativada'
subtitle: A autenticação de dois fatores foi desativada para a sua conta.
title: 2FA desativado
two_factor_enabled:
- explanation: Um token gerado pelo aplicativo TOTP emparelhado será necessário para login.
- subject: 'Mastodon: Autenticação em duas etapas ativada'
- subtitle: A autenticação de dois fatores foi habilitada para sua conta.
+ explanation: Para iniciar sessão, será necessário um token gerado pela aplicação TOTP emparelhada.
+ subject: 'Mastodon: autenticação em duas etapas ativada'
+ subtitle: A autenticação de dois fatores foi ativada para a sua conta.
title: 2FA ativado
two_factor_recovery_codes_changed:
- explanation: Os códigos de recuperação anteriores foram invalidados e novos foram gerados.
- subject: 'Mastodon: Gerados novos códigos de recuperação em duas etapas'
- subtitle: Os códigos de recuperação anteriores foram invalidados e novos foram gerados.
+ explanation: Os códigos de recuperação anteriores foram invalidados e foram gerados novos códigos.
+ subject: 'Mastodon: gerados novos códigos de recuperação em duas etapas'
+ subtitle: Os códigos de recuperação anteriores foram invalidados e foram gerados novos códigos.
title: Códigos de recuperação 2FA alterados
unlock_instructions:
- subject: 'Mastodon: Instruções para desbloquear a tua conta'
+ subject: 'Mastodon: instruções para desbloquear'
webauthn_credential:
added:
explanation: A seguinte chave de segurança foi adicionada à sua conta
- subject: 'Mastodon: Nova chave de segurança'
+ subject: 'Mastodon: nova chave de segurança'
title: Foi adicionada uma nova chave de segurança
deleted:
explanation: A seguinte chave de segurança foi eliminada da sua conta
- subject: 'Mastodon: Chave de segurança eliminada'
+ subject: 'Mastodon: chave de segurança eliminada'
title: Uma das suas chaves de segurança foi eliminada
webauthn_disabled:
explanation: A autenticação com chaves de segurança foi desativada para sua conta.
- extra: O login agora é possível usando apenas o token gerado pelo aplicativo TOTP emparelhado.
- subject: 'Mastodon: Autenticação com chave de segurança desativada'
+ extra: O início de sessão é agora possível utilizando apenas o token gerado pela aplicação TOTP emparelhada.
+ subject: 'Mastodon: autenticação com chave de segurança desativada'
title: Chaves de segurança desativadas
webauthn_enabled:
- explanation: A autenticação da chave de segurança foi habilitada para sua conta.
- extra: Sua chave de segurança agora pode ser usada para login.
- subject: 'Mastodon: Autenticação com chave de segurança ativada'
+ explanation: A autenticação por chave de segurança foi ativada para a sua conta.
+ extra: A sua chave de segurança pode agora ser utilizada para iniciar sessão.
+ subject: 'Mastodon: autenticação com chave de segurança ativada'
title: Chaves de segurança ativadas
omniauth_callbacks:
failure: Não foi possível autenticar %{kind} porque "%{reason}".
success: Autenticado correctamente na conta %{kind}.
passwords:
- no_token: Não pode aceder a esta página se não vier através da ligação enviada por e-mail para alteração da sua palavra-passe. Se de facto usou essa ligação para chegar até aqui, queira garantir de que usou o endereço URL completo.
- send_instructions: Vai receber um e-mail com instruções para alterar a palavra-passe dentro de alguns minutos.
- send_paranoid_instructions: Se o seu endereço de e-mail existir na nossa base de dados, dentro de alguns minutos irá receber uma ligação para recuperar a palavra-passe.
- updated: A tua palavra-passe foi alterada. Estás agora autenticado na tua conta.
+ no_token: Não pode aceder a esta página se não vier através da hiperligação enviada por e-mail para alteração da sua palavra-passe. Se de facto usou essa hiperligação para chegar até aqui, verifique se usou o endereço URL completo.
+ send_instructions: Se o seu endereço de e-mail existir na nossa base de dados, receberá uma hiperligação de recuperação da palavra-passe no seu endereço de e-mail dentro de alguns minutos. Verifique a sua pasta de spam se não recebeu esta mensagem de correio eletrónico.
+ send_paranoid_instructions: Se o seu endereço de e-mail existir na nossa base de dados, receberá uma hiperligação de recuperação da palavra-passe no seu endereço de e-mail dentro de alguns minutos. Verifique a sua pasta de spam se não recebeu esta mensagem de correio eletrónico.
+ updated: A sua palavra-passe foi alterada com sucesso. Está agora autenticado.
updated_not_active: A tua palavra-passe foi alterada.
registrations:
- destroyed: Adeus! A tua conta foi cancelada. Esperamos ver-te em breve.
- signed_up: Seja bem-vindo! A sua conta foi correctamente registada.
- signed_up_but_inactive: A tua conta foi registada. No entanto ainda não está activa.
- signed_up_but_locked: A sua conta foi correctamente registada. Contudo, não pudemos iniciar sessão porque a sua conta está bloqueada.
- signed_up_but_pending: Foi enviada uma hiperligação de confirmação para o seu correio electrónico. Só depois de clicar na hiperligação avaliaremos a sua inscrição. Será notificado caso a sua conta seja aprovada.
- signed_up_but_unconfirmed: Foi enviada uma hiperligação de confirmação para o seu correio electrónico. Queira usar essa hiperligação para activar a sua conta.
- update_needs_confirmation: Solicitou uma alteração da informação da sua conta, mas para tal é necessário confirmá-la. Queira ver o seu correio electrónico e seguir a hiperligação para a confirmar. Se não encontrar essa mensagem, veja se está na pasta de lixo electrónico.
- updated: A sua conta foi correctamente actualizada.
+ destroyed: Adeus! A sua conta foi cancelada com sucesso. Esperamos voltar a vê-lo em breve.
+ signed_up: Bem-vindo! A sua conta foi registada com sucesso.
+ signed_up_but_inactive: Registou-se com sucesso. No entanto, não foi possível iniciar sessão porque a sua conta ainda não está ativada.
+ signed_up_but_locked: Registou-se com sucesso. No entanto, não foi possível iniciar sessão porque a sua conta está bloqueada.
+ signed_up_but_pending: Foi enviada uma mensagem com uma hiperligação de confirmação para o seu endereço de e-mail. Depois de clicar na hiperligação, analisaremos a sua candidatura. Será notificado se for aprovado.
+ signed_up_but_unconfirmed: Foi enviada para o seu endereço de e-mail uma mensagem com uma hiperligação de confirmação. Siga a hiperligação para ativar a sua conta. Verifique a sua pasta de spam se não recebeu esta mensagem de e-mail.
+ update_needs_confirmation: Atualizou a sua conta com sucesso, mas temos de verificar o seu novo endereço de e-mail. Verifique o seu e-mail e siga a hiperligação de confirmação para confirmar o seu novo endereço de e-mail. Verifique a sua pasta de spam se não recebeu esta mensagem de correio eletrónico.
+ updated: A sua conta foi corretamente atualizada.
sessions:
already_signed_out: Sessão encerrada.
signed_in: Sessão iniciada.
signed_out: Sessão encerrada.
unlocks:
- send_instructions: Dentro de alguns momentos, irá receber um e-mail com instruções para desbloquear a sua conta. Consulte a sua pasta de lixo electrónico se não o encontrar.
- send_paranoid_instructions: Se a sua conta existir, dentro de momentos irá receber um e-mail com instruções para a desbloquear. Consulte a sua pasta de lixo electrónico se não o encontrar.
- unlocked: A sua conta foi correctamente desbloqueada. Queira iniciar uma nova sessão para continuar.
+ send_instructions: Receberá um e-mail com instruções sobre como desbloquear a sua conta dentro de alguns minutos. Verifique a sua pasta de spam se não recebeu este e-mail.
+ send_paranoid_instructions: Se a sua conta existir, receberá um e-mail com instruções sobre como a desbloquear dentro de alguns minutos. Verifique a sua pasta de spam se não recebeu este e-mail.
+ unlocked: A sua conta foi desbloqueada com sucesso. Inicie sessão para continuar.
errors:
messages:
already_confirmed: já confirmado, por favor tente iniciar sessão
- confirmation_period_expired: tem de ser confirmado durante %{period}, por favor tenta outra vez
+ confirmation_period_expired: tem de ser confirmado dentro de %{period}, por favor tente outra vez
expired: expirou, por favor tente outra vez
not_found: não encontrado
not_locked: não estava bloqueada
diff --git a/config/locales/devise.ro.yml b/config/locales/devise.ro.yml
index 868bb4b3a1..f570f77e1d 100644
--- a/config/locales/devise.ro.yml
+++ b/config/locales/devise.ro.yml
@@ -2,76 +2,77 @@
ro:
devise:
confirmations:
- confirmed: Adresa ta de e-mail a fost confirmată cu succes.
- send_instructions: Vei primi un e-mail cu instrucțiuni despre cum să confirmi adresa ta de e-mail în câteva minute. Te rugăm să verifici dosarul spam dacă nu ai primit acest e-mail.
- send_paranoid_instructions: Dacă adresa ta de e-mail există în baza noastră de date, în câteva minute vei primi un e-mail cu instrucțiuni pentru confirmarea adresei tale de e-mail. Te rugăm să verifici dosarul spam dacă nu ai primit acest e-mail.
+ confirmed: Adresa dvs. de e-mail a fost confirmată cu succes.
+ send_instructions: Veți primi un e-mail în câteva minute cu instrucțiuni despre cum să vă confirmați adresa de e-mail. Vă rugăm să verificați dosarul spam dacă nu ați primit acest e-mail.
+ send_paranoid_instructions: Dacă adresa dvs. de e-mail există în baza noastră de date, veți primi în câteva minute un e-mail cu instrucțiuni pentru confirmarea adresei de e-mail. Vă rugăm să verificați dosarul spam dacă nu ați primit acest e-mail.
failure:
- already_authenticated: Ești deja conectat.
- inactive: Contul tău nu este încă activat.
+ already_authenticated: Sunteți deja conectat.
+ inactive: Contul dvs. nu este încă activat.
invalid: "%{authentication_keys} sau parolă greșită."
- last_attempt: Mai ai încă o încercare înainte de a bloca contul.
- locked: Contul tău este blocat.
+ last_attempt: Mai aveți o încercare înainte ca contul dvs. să fie blocat.
+ locked: Contul dvs. este blocat.
not_found_in_database: "%{authentication_keys} sau parolă greșită."
- pending: Contul tău este încă în curs de revizuire.
- timeout: Sesiunea ta a expirat. Te rugăm să te conectezi din nou pentru a continua.
- unauthenticated: Trebuie să te conectezi sau să te înregistrezi înainte de a continua.
- unconfirmed: Trebuie să confirmi adresa ta de e-mail înainte de a continua.
+ omniauth_user_creation_failure: Eroare la crearea unui cont pentru această identitate.
+ pending: Contul dvs. este încă în curs de revizuire.
+ timeout: Sesiunea dvs. a expirat. Vă rugăm să vă conectați din nou pentru a continua.
+ unauthenticated: Trebuie să vă conectați sau să vă înregistrați înainte de a continua.
+ unconfirmed: Trebuie să vă confirmați adresa de e-mail înainte de a continua.
mailer:
confirmation_instructions:
- action: Verifică adresa de e-mail
+ action: Verificare adresă de e-mail
action_with_app: Confirmați și reveniți la %{app}
- explanation: Ai creat un cont pe %{host} cu această adresă de e-mail. Ești la un click distanță de a o activa. Dacă nu ai fost tu, ignoră acest e-mail.
- explanation_when_pending: Ai solicitat o invitație către %{host} cu această adresă de e-mail. Odată ce îți confirmi adresa de e-mail, îți vom revizui cererea. Te poți autentifica pentru a-ți schimba detaliile sau pentru a-ți șterge contul, dar nu poți accesa majoritatea funcțiilor până când contul tău nu este aprobat. Dacă cererea ta este respinsă, datele tale vor fi șterse, astfel încât nu va fi necesară nicio altă acțiune din partea ta. Dacă nu ai fost tu, ignoră acest e-mail.
+ explanation: Ați creat un cont pe %{host} cu această adresă de e-mail. Sunteți la un clic distanță de a-l activa. Dacă nu ați fost dvs., vă rugăm să ignorați acest e-mail.
+ explanation_when_pending: Ați aplicat pentru o invitație pentru %{host} cu această adresă de e-mail. Odată ce vă confirmați adresa de e-mail, vă vom examina cererea. Vă puteți autentifica pentru a vă schimba detaliile sau pentru a vă șterge contul, dar nu puteți accesa majoritatea funcțiilor până când contul dvs. nu este aprobat. Dacă cererea dvs. este respinsă, datele dvs. vor fi șterse, astfel încât nu va fi necesară nicio acțiune suplimentară din partea dvs. Dacă nu ați fost dvs., vă rugăm să ignorați acest e-mail.
extra_html: Te rugăm să verifici și regulile serverului și termenii noștri de serviciu.
subject: 'Mastodon: Instrucțiuni de confirmare pentru %{instance}'
- title: Verifică adresa de e-mail
+ title: Verificați adresa de e-mail
email_changed:
- explanation: 'Adresa de e-mail pentru contul tău este schimbată la:'
- extra: Dacă nu v-ați schimbat adresa de e-mail, probabil că cineva a obținut acces la contul dvs. Te rugăm să îți schimbi parola imediat sau să contactezi administratorul serverului dacă nu ai acces la contul tău.
- subject: E-mail schimbat
- title: Noua adresa de e-mail
+ explanation: 'Adresa de e-mail a contului dvs. este schimbată în:'
+ extra: Dacă nu v-ați schimbat adresa de e-mail, probabil că cineva a obținut acces la contul dvs. Vă rugăm să vă schimbați parola imediat sau să contactați administratorul serverului dacă nu aveți acces la contul dvs.
+ subject: 'Mastodon: Adresă de e-mail schimbată'
+ title: Adresă de e-mail nouă
password_change:
- explanation: Parola contului tău a fost schimbată.
- extra: Dacă nu v-ați schimbat parola, este posibil ca cineva să fi obținut acces la contul dvs. Te rugăm să îți schimbi parola imediat sau să contactezi administratorul serverului dacă nu ai acces la contul tău.
- subject: Parolă schimbată
+ explanation: Parola pentru contul dvs. a fost schimbată.
+ extra: Dacă nu v-ați schimbat parola, probabil că cineva a obținut acces la contul dvs. Vă rugăm să vă schimbați parola imediat sau să contactați administratorul serverului dacă nu aveți acces la contul dvs.
+ subject: 'Mastodon: Parolă schimbată'
title: Parolă schimbată
reconfirmation_instructions:
- explanation: Confirmă noua adresă pentru a schimba adresa de e-mail.
+ explanation: Confirmați noua adresă pentru a vă schimba adresa de e-mail.
extra: Dacă această modificare nu a fost inițiată de dvs., vă rugăm să ignorați acest e-mail. Adresa de e-mail pentru contul Mastodon nu se va schimba până când nu accesați link-ul de mai sus.
subject: 'Mastodon: Confirmați e-mailul pentru %{instance}'
- title: Verifică adresa de e-mail
+ title: Verificați adresa de e-mail
reset_password_instructions:
- action: Schimbă parola
+ action: Schimbați parola
explanation: Ați solicitat o nouă parolă pentru contul dvs.
- extra: Dacă nu ați solicitat acest lucru, ignorați acest e-mail. Parola dvs. nu se va schimba până când nu veți accesa link-ul de mai sus și nu veți crea unul nou.
- subject: Instrucțiuni pentru resetarea parolei
+ extra: Dacă nu ați solicitat acest lucru, vă rugăm să ignorați acest e-mail. Parola dvs. nu se va schimba până când nu veți accesa link-ul de mai sus și nu veți crea unul nou.
+ subject: 'Mastodon: Instrucțiuni pentru resetarea parolei'
title: Resetare parolă
two_factor_disabled:
explanation: Conectarea este acum posibilă folosind doar adresa de e-mail și parola.
- subject: Autentificare cu doi factori dezactivată
+ subject: 'Mastodon: Autentificarea cu doi factori dezactivată'
subtitle: Autentificarea cu doi factori pentru contul dvs. a fost dezactivată.
- title: 2FA dezactivat
+ title: A2F dezactivată
two_factor_enabled:
- explanation: Pentru autentificare va fi necesar un token generat de aplicația TOTP asociată.
- subject: Autentificare în doi pași activată
+ explanation: Pentru conectare va fi necesar un token generat de aplicația TOTP asociată.
+ subject: 'Mastodon: Autentificare în doi pași activată'
subtitle: Autentificarea cu doi factori a fost activată pentru contul dvs.
- title: 2FA activat
+ title: A2F activată
two_factor_recovery_codes_changed:
- explanation: Codurile anterioare de recuperare au fost invalidate și unele noi generate.
- subject: Recuperare în doi factori
+ explanation: Codurile de recuperare anterioare au fost invalidate și s-au generat altele noi.
+ subject: 'Mastodon: Coduri de recuperare în doi pași regenerate'
subtitle: Codurile de recuperare anterioare au fost invalidate și s-au generat altele noi.
- title: Coduri de recuperare 2FA modificate
+ title: Codurile de recuperare în doi pași modificate
unlock_instructions:
- subject: Instrucțiuni de deblocare
+ subject: 'Mastodon: Instrucțiuni de deblocare'
webauthn_credential:
added:
- explanation: Următoarea cheie de securitate a fost adăugată în contul tău
+ explanation: Următoarea cheie de securitate a fost adăugată în contul dvs.
subject: 'Mastodon: Noua cheie de securitate'
title: A fost adăugată o nouă cheie de securitate
deleted:
- explanation: Următoarea cheie de securitate a fost ștearsă din contul tău
+ explanation: Următoarea cheie de securitate a fost ștearsă din contul dvs.
subject: 'Mastodon: Cheie de securitate ștearsă'
- title: Una dintre cheile tale de securitate a fost ștearsă
+ title: Una dintre cheile dvs. de securitate a fost ștearsă
webauthn_disabled:
explanation: Autentificarea cu chei de securitate a fost dezactivată pentru contul dvs.
extra: Conectarea este acum posibilă folosind doar token-ul generat de aplicația TOTP asociată.
@@ -80,34 +81,34 @@ ro:
webauthn_enabled:
explanation: Autentificarea cu cheie de securitate a fost activată pentru contul dvs.
extra: Cheia ta de securitate poate fi acum folosită pentru conectare.
- subject: 'Mastodon: Autentificarea cheii de securitate activată'
+ subject: 'Mastodon: Autentificarea prin chei de securitate activată'
title: Chei de securitate activate
omniauth_callbacks:
- failure: Nu te-am putut autentifica de la %{kind} deoarece "%{reason}".
+ failure: Nu v-am putut autentifica de la %{kind} deoarece "%{reason}".
success: Autentificat cu succes din contul %{kind}.
passwords:
- no_token: Nu puteți accesa această pagină fără să veniți dintr-un e-mail de resetare a parolei. Dacă vii dintr-un e-mail de resetare a parolei, te rugăm să te asiguri că ai folosit URL-ul complet furnizat.
- send_instructions: Dacă adresa ta de e-mail există în baza noastră de date, vei primi în câteva minute un link de recuperare a parolei la adresa ta de e-mail. Te rugăm să verifici dosarul spam dacă nu ai primit acest e-mail.
- send_paranoid_instructions: Dacă adresa ta de e-mail există în baza noastră de date, vei primi în câteva minute un link de recuperare a parolei la adresa ta de e-mail. Te rugăm să verifici dosarul spam dacă nu ai primit acest e-mail.
- updated: Parola ta a fost schimbată cu succes. Acum ești conectat.
- updated_not_active: Parola ta a fost schimbată cu succes.
+ no_token: Nu puteți accesa această pagină fără să veniți dintr-un e-mail de resetare a parolei. Dacă veniți dintr-un e-mail de resetare a parolei, vă rugăm asigurați-vă că ați folosit URL-ul complet furnizat.
+ send_instructions: Dacă adresa dvs. de e-mail există în baza noastră de date, veți primi în câteva minute un link de recuperare a parolei la adresa dvs. de e-mail. Vă rugăm să verificați dosarul spam dacă nu ați primit acest e-mail.
+ send_paranoid_instructions: Dacă adresa dvs. de e-mail există în baza noastră de date, veți primi în câteva minute un link de recuperare a parolei la adresa dvs. de e-mail. Vă rugăm să verificați dosarul spam dacă nu ați primit acest e-mail.
+ updated: Parola dvs. a fost schimbată cu succes. Acum sunteți conectat.
+ updated_not_active: Parola dvs. a fost schimbată cu succes.
registrations:
- destroyed: La revedere! Contul tău a fost anulat cu succes. Sperăm să te vedem din nou în curând.
+ destroyed: La revedere! Contul dvs. a fost anulat cu succes. Sperăm să vă vedem din nou în curând.
signed_up: Bine ați venit! V-ați înregistrat cu succes.
signed_up_but_inactive: V-ați înregistrat cu succes. Cu toate acestea, nu vă putem conecta deoarece contul dvs. nu este încă activat.
signed_up_but_locked: V-ați înregistrat cu succes. Cu toate acestea, nu vă putem conecta deoarece contul dvs. este blocat.
- signed_up_but_pending: Un mesaj cu un link de confirmare a fost trimis la adresa ta de e-mail. După ce faceți clic pe link, vă vom revizui cererea. Veți fi notificat dacă este aprobat.
- signed_up_but_unconfirmed: Un mesaj cu un link de confirmare a fost trimis la adresa ta de e-mail. Vă rugăm să urmaţi link-ul pentru a vă activa contul. Vă rugăm să verificaţi folderul spam dacă nu aţi primit acest e-mail.
- update_needs_confirmation: Ți-ai actualizat contul cu succes, dar trebuie să verificăm noua ta adresă de e-mail. Vă rugăm să verificați adresa de e-mail și să urmați link-ul de confirmare pentru a confirma noua dvs. adresă de e-mail. Te rugăm să verifici dosarul spam dacă nu ai primit acest e-mail.
+ signed_up_but_pending: Un mesaj cu un link de confirmare a fost trimis la adresa dvs. de e-mail. După ce faceți clic pe link, vă vom revizui cererea. Veți fi notificat dacă este aprobat.
+ signed_up_but_unconfirmed: Un mesaj cu un link de confirmare a fost trimis la adresa dvs. de e-mail. Vă rugăm să urmați link-ul pentru a vă activa contul. Vă rugăm să verificați folderul spam dacă nu ați primit acest e-mail.
+ update_needs_confirmation: V-ați actualizat contul cu succes, dar trebuie să verificăm noua dvs. adresă de e-mail. Vă rugăm să verificați adresa de e-mail și să urmați link-ul de confirmare pentru a confirma noua dvs. adresă de e-mail. Vă rugăm să verificați dosarul spam dacă nu ați primit acest e-mail.
updated: Contul dvs. a fost actualizat cu succes.
sessions:
already_signed_out: Deconectat cu succes.
signed_in: Conectat cu succes.
signed_out: Deconectat cu succes.
unlocks:
- send_instructions: Veţi primi un e-mail cu instrucţiuni despre cum să vă deblocaţi contul în câteva minute. Te rugăm să verifici dosarul spam dacă nu ai primit acest e-mail.
- send_paranoid_instructions: Dacă contul tău există, vei primi un e-mail cu instrucțiuni pentru cum să-l deblochezi în câteva minute. Te rugăm să verifici dosarul spam dacă nu ai primit acest e-mail.
- unlocked: Contul tău a fost deblocat cu succes. Te rugăm să te autentifici pentru a continua.
+ send_instructions: Veți primi un e-mail cu instrucțiuni despre cum să vă deblocați contul în câteva minute. Vă rugăm să verificați dosarul spam dacă nu ați primit acest e-mail.
+ send_paranoid_instructions: Dacă contul dvs. există, veți primi un e-mail cu instrucțiuni pentru cum să-l deblocați în câteva minute. Vă rugăm să verificați dosarul spam dacă nu ați primit acest e-mail.
+ unlocked: Contul dvs. a fost deblocat cu succes. Vă rugăm să vă autentificați pentru a continua.
errors:
messages:
already_confirmed: a fost deja confirmat, încercați să vă conectați
@@ -118,4 +119,4 @@ ro:
not_saved:
few: "%{count} erori au împiedicat salvarea acestui %{resource}:"
one: 'O eroare a împiedicat salvarea acestui %{resource}:'
- other: "%{count} de erori au împiedicat salvarea acestui %{resource}:"
+ other: "%{count} erori au împiedicat salvarea acestui %{resource}:"
diff --git a/config/locales/devise.zh-CN.yml b/config/locales/devise.zh-CN.yml
index 2a50c131d5..86e78c1b18 100644
--- a/config/locales/devise.zh-CN.yml
+++ b/config/locales/devise.zh-CN.yml
@@ -50,12 +50,12 @@ zh-CN:
two_factor_disabled:
explanation: 目前只能通过邮箱地址和密码登录。
subject: Mastodon:双因素认证已禁用
- subtitle: 您账户的双因素认证已被停用。
+ subtitle: 你账户的双因素认证已被停用。
title: 双因素认证已停用
two_factor_enabled:
explanation: 登录时需要输入先前配对好的TOTP应用生成的令牌。
subject: Mastodon:双因素认证已启用
- subtitle: 您账户的双因素认证已被启用。
+ subtitle: 你账户的双因素认证已被启用。
title: 双因素认证已启用
two_factor_recovery_codes_changed:
explanation: 新恢复码已生成,同时旧恢复码已失效。
@@ -74,13 +74,13 @@ zh-CN:
subject: Mastodon:安全密钥已删除
title: 你的安全密钥之一已被删除
webauthn_disabled:
- explanation: 您账户的安全密钥身份认证已被停用。
+ explanation: 你账户的安全密钥身份认证已被停用。
extra: 目前只能用先前配对的TOTP应用生成的令牌登录。
subject: Mastodon:安全密钥认证已禁用
title: 安全密钥已禁用
webauthn_enabled:
- explanation: 您账户的安全密钥身份认证已被启用。
- extra: 您的安全密钥现在可用于登录。
+ explanation: 你账户的安全密钥身份认证已被启用。
+ extra: 你的安全密钥现在可用于登录。
subject: Mastodon:安全密钥认证已启用
title: 已启用安全密钥
omniauth_callbacks:
diff --git a/config/locales/doorkeeper.af.yml b/config/locales/doorkeeper.af.yml
index 9e05f403f6..d32730468a 100644
--- a/config/locales/doorkeeper.af.yml
+++ b/config/locales/doorkeeper.af.yml
@@ -60,7 +60,6 @@ af:
error:
title: "’n Fout het ingesluip"
new:
- prompt_html: "%{client_name} wil toegang hê tot jou rekening. Dit is ’n derdepartytoepassing. Moet dit nie toelaat as jy dit nie vertrou nie."
review_permissions: Hersien toestemmings
title: Benodig magtiging
show:
diff --git a/config/locales/doorkeeper.an.yml b/config/locales/doorkeeper.an.yml
index 1096d8c8dc..bee55771de 100644
--- a/config/locales/doorkeeper.an.yml
+++ b/config/locales/doorkeeper.an.yml
@@ -60,7 +60,6 @@ an:
error:
title: Ha ocurriu una error
new:
- prompt_html: "%{client_name} deseya permiso pa acceder ta la tuya cuenta. Ye una aplicación de tercers. Si no confías en ella, no habrías d'autorizar-la."
review_permissions: Revisar permisos
title: Se requiere autorización
show:
diff --git a/config/locales/doorkeeper.ar.yml b/config/locales/doorkeeper.ar.yml
index 79e6c60152..8dea8b4894 100644
--- a/config/locales/doorkeeper.ar.yml
+++ b/config/locales/doorkeeper.ar.yml
@@ -60,7 +60,6 @@ ar:
error:
title: حدث هناك خطأ
new:
- prompt_html: يريد %{client_name} الإذن للوصول إلى حسابك. إنه تطبيق طرف ثالث. إذا كنت لا تثق فيه، فلا ينبغي أن تأذن له بذلك.
review_permissions: مراجعة الصلاحيات
title: إذن بالتصريح
show:
diff --git a/config/locales/doorkeeper.ast.yml b/config/locales/doorkeeper.ast.yml
index 0df15a07b6..c9c831f7f5 100644
--- a/config/locales/doorkeeper.ast.yml
+++ b/config/locales/doorkeeper.ast.yml
@@ -41,7 +41,6 @@ ast:
error:
title: Prodúxose un error
new:
- prompt_html: "%{client_name}, que ye una aplicación de terceros, quier tener accesu a la cuenta. Si nun t'enfotes nella, nun habríes autorizala."
review_permissions: Revisión de los permisos
show:
title: Copia esti códigu d'autorización y apiégalu na aplicación.
diff --git a/config/locales/doorkeeper.be.yml b/config/locales/doorkeeper.be.yml
index 75f9930e1a..defe0ddf0d 100644
--- a/config/locales/doorkeeper.be.yml
+++ b/config/locales/doorkeeper.be.yml
@@ -60,7 +60,6 @@ be:
error:
title: Узнікла памылка
new:
- prompt_html: "%{client_name} хацеў бы атрымаць дазвол для доступу да вашага акаунта. Гэта вонкавае прыкладанне. Не давайце дазволу на гэта, калі вы не давяраеце гэтаму прыкладанню. "
review_permissions: Прагледзець дазволы
title: Патрабуецца аўтарызацыя
show:
diff --git a/config/locales/doorkeeper.bg.yml b/config/locales/doorkeeper.bg.yml
index a1ef177854..25dce0ea08 100644
--- a/config/locales/doorkeeper.bg.yml
+++ b/config/locales/doorkeeper.bg.yml
@@ -60,7 +60,6 @@ bg:
error:
title: Възникна грешка
new:
- prompt_html: "%{client_name} иска разрешение да има достъп до акаунта ви. Приложение от трета страна е.Ако не му се доверявате, то може да не го упълномощявате."
review_permissions: Преглед на разрешенията
title: Изисква се упълномощаване
show:
diff --git a/config/locales/doorkeeper.ca.yml b/config/locales/doorkeeper.ca.yml
index 85a09b5b43..590339fe88 100644
--- a/config/locales/doorkeeper.ca.yml
+++ b/config/locales/doorkeeper.ca.yml
@@ -60,7 +60,7 @@ ca:
error:
title: S'ha produït un error
new:
- prompt_html: "%{client_name} vol permís per accedir el teu compte. És una aplicació de tercers. Si no hi confies, no hauries d'autoritzar-la."
+ prompt_html: "%{client_name} demana accés al vostre compte. Només aproveu aquesta petició si reconeixeu i confieu en aquest origen."
review_permissions: Revisa els permisos
title: Cal autorizació
show:
diff --git a/config/locales/doorkeeper.ckb.yml b/config/locales/doorkeeper.ckb.yml
index f952b6eca9..b318bce859 100644
--- a/config/locales/doorkeeper.ckb.yml
+++ b/config/locales/doorkeeper.ckb.yml
@@ -60,7 +60,6 @@ ckb:
error:
title: هەڵەیەک ڕوویدا
new:
- prompt_html: "%{client_name} حەز دەکات مۆڵەت بدرێت بۆ چوونە ناو ئەکاونتەکەت. ئەپڵیکەیشنێکی لایەنی سێیەمە. ئەگەر متمانەت پێی نییە، ئەوا نابێت ڕێگەی پێبدەیت."
review_permissions: پێداچوونەوە بە مۆڵەتەکاندا بکە
title: ڕێپێدان پێویستە
show:
diff --git a/config/locales/doorkeeper.cs.yml b/config/locales/doorkeeper.cs.yml
index 1b98d0f88b..882be66ee0 100644
--- a/config/locales/doorkeeper.cs.yml
+++ b/config/locales/doorkeeper.cs.yml
@@ -60,7 +60,6 @@ cs:
error:
title: Vyskytla se chyba
new:
- prompt_html: "%{client_name} si přeje oprávnění pro přístup k vašemu účtu. Je to aplikace třetí strany. Pokud jí nedůvěřujete, pak byste ji neměli autorizovat."
review_permissions: Zkontrolujte oprávnění
title: Je vyžadována autorizace
show:
diff --git a/config/locales/doorkeeper.cy.yml b/config/locales/doorkeeper.cy.yml
index f15d74d721..80cc022a0b 100644
--- a/config/locales/doorkeeper.cy.yml
+++ b/config/locales/doorkeeper.cy.yml
@@ -60,7 +60,6 @@ cy:
error:
title: Mae rhywbeth wedi mynd o'i le
new:
- prompt_html: Hoffai %{client_name} gael caniatâd i gael mynediad i'ch cyfrif. Mae'n gais trydydd parti. Os nad ydych yn ymddiried ynddo, yna peidiwch a'i awdurdodi.
review_permissions: Adolygu caniatâd
title: Angen awdurdodi
show:
diff --git a/config/locales/doorkeeper.da.yml b/config/locales/doorkeeper.da.yml
index cd11dcf4e3..7ac16e0012 100644
--- a/config/locales/doorkeeper.da.yml
+++ b/config/locales/doorkeeper.da.yml
@@ -60,7 +60,7 @@ da:
error:
title: En fejl opstod
new:
- prompt_html: "%{client_name} ønsker tilladelse til at tilgå din konto. Den er en tredjepartsapplikation. Har du ikke tillid til den, bør den ikke godkendes."
+ prompt_html: "%{client_name} vil ønsker tilladelse til at tilgå din konto. Godkend kun denne anmodning, hvis kilden genkendes, og man stoler på den."
review_permissions: Gennemgå tilladelser
title: Godkendelse kræves
show:
diff --git a/config/locales/doorkeeper.de.yml b/config/locales/doorkeeper.de.yml
index b29d668b2e..6d0e3010af 100644
--- a/config/locales/doorkeeper.de.yml
+++ b/config/locales/doorkeeper.de.yml
@@ -60,7 +60,7 @@ de:
error:
title: Ein Fehler ist aufgetreten
new:
- prompt_html: "%{client_name} möchte auf dein Konto zugreifen. Es handelt sich um eine Software von Dritten. Wenn du der Anwendung nicht vertraust, solltest du ihr keinen Zugriff auf dein Konto geben."
+ prompt_html: "%{client_name} möchte auf dein Konto zugreifen. Du solltest diese Anfrage nur genehmigen, wenn du diese Quelle kennst und ihr vertraust."
review_permissions: Berechtigungen überprüfen
title: Autorisierung erforderlich
show:
diff --git a/config/locales/doorkeeper.el.yml b/config/locales/doorkeeper.el.yml
index 7fcd69c238..59877b6bd0 100644
--- a/config/locales/doorkeeper.el.yml
+++ b/config/locales/doorkeeper.el.yml
@@ -60,7 +60,6 @@ el:
error:
title: Εμφανίστηκε σφάλμα
new:
- prompt_html: Το %{client_name} θα ήθελε άδεια πρόσβασης στο λογαριασμό σου. Είναι μια εφαρμογή τρίτων. Αν δεν το εμπιστεύεσαι, τότε δεν πρέπει να το εγκρίνεις.
review_permissions: Ανασκόπηση δικαιωμάτων
title: Απαιτείται έγκριση
show:
diff --git a/config/locales/doorkeeper.en-GB.yml b/config/locales/doorkeeper.en-GB.yml
index 999284e85f..63a4575e83 100644
--- a/config/locales/doorkeeper.en-GB.yml
+++ b/config/locales/doorkeeper.en-GB.yml
@@ -60,7 +60,7 @@ en-GB:
error:
title: An error has occurred
new:
- prompt_html: "%{client_name} would like permission to access your account. It is a third-party application. If you do not trust it, then you should not authorise it."
+ prompt_html: "%{client_name} would like permission to access your account. Only approve this request if you recognise and trust this source."
review_permissions: Review permissions
title: Authorisation required
show:
diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml
index e28f6a7966..3b3b141afa 100644
--- a/config/locales/doorkeeper.en.yml
+++ b/config/locales/doorkeeper.en.yml
@@ -60,7 +60,7 @@ en:
error:
title: An error has occurred
new:
- prompt_html: "%{client_name} would like permission to access your account. It is a third-party application. If you do not trust it, then you should not authorize it."
+ prompt_html: "%{client_name} would like permission to access your account. Only approve this request if you recognize and trust this source."
review_permissions: Review permissions
title: Authorization required
show:
diff --git a/config/locales/doorkeeper.eo.yml b/config/locales/doorkeeper.eo.yml
index 8bb61c7a49..12e120f8be 100644
--- a/config/locales/doorkeeper.eo.yml
+++ b/config/locales/doorkeeper.eo.yml
@@ -60,7 +60,6 @@ eo:
error:
title: Eraro okazis
new:
- prompt_html: "%{client_name} petas permeson por aliri vian konton. Se vi ne fidas ĝin, ne rajtigu ĝin."
review_permissions: Revizu permesojn
title: Rajtigo bezonata
show:
diff --git a/config/locales/doorkeeper.es-AR.yml b/config/locales/doorkeeper.es-AR.yml
index 91f4191247..804e4a51ed 100644
--- a/config/locales/doorkeeper.es-AR.yml
+++ b/config/locales/doorkeeper.es-AR.yml
@@ -60,7 +60,7 @@ es-AR:
error:
title: Ocurrió un error
new:
- prompt_html: "%{client_name} solicita permiso para acceder a tu cuenta. Es una aplicación de terceros. Si no confiás en ella, no deberías autorizarla."
+ prompt_html: A %{client_name} le gustaría obtener permiso para acceder a tu cuenta. Solo aprueba esta solicitud si reconoces y confías en esta fuente.
review_permissions: Revisar permisos
title: Autorización requerida
show:
diff --git a/config/locales/doorkeeper.es-MX.yml b/config/locales/doorkeeper.es-MX.yml
index b5987676d2..c095777954 100644
--- a/config/locales/doorkeeper.es-MX.yml
+++ b/config/locales/doorkeeper.es-MX.yml
@@ -60,7 +60,7 @@ es-MX:
error:
title: Ha ocurrido un error
new:
- prompt_html: "%{client_name} requiere permiso para acceder a tu cuenta. Es una aplicación de terceros. Si no confías en esta, no deberías autorizarla."
+ prompt_html: A %{client_name} le gustaría obtener permiso para acceder a tu cuenta. Solo aprueba esta solicitud si reconoces y confías en esta fuente.
review_permissions: Revisar permisos
title: Se requiere autorización
show:
@@ -167,7 +167,7 @@ es-MX:
admin:write:reports: realizar acciones de moderación en informes
crypto: usar cifrado de extremo a extremo
follow: seguir, bloquear, desbloquear y dejar de seguir cuentas
- profile: leer sólo la información del perfil de tu cuenta
+ profile: leer solamente la información del perfil de tu cuenta
push: recibir tus notificaciones push
read: leer los datos de tu cuenta
read:accounts: ver información de cuentas
diff --git a/config/locales/doorkeeper.es.yml b/config/locales/doorkeeper.es.yml
index b3c7ccddd4..c26f11a7a1 100644
--- a/config/locales/doorkeeper.es.yml
+++ b/config/locales/doorkeeper.es.yml
@@ -60,7 +60,7 @@ es:
error:
title: Ha ocurrido un error
new:
- prompt_html: "%{client_name} desea permiso para acceder a tu cuenta. Es una aplicación de terceros. Si no confías en ella, no deberías autorizarla."
+ prompt_html: A %{client_name} le gustaría obtener permiso para acceder a tu cuenta. Solo aprueba esta solicitud si reconoces y confías en esta fuente.
review_permissions: Revisar permisos
title: Se requiere autorización
show:
diff --git a/config/locales/doorkeeper.et.yml b/config/locales/doorkeeper.et.yml
index 13d3f40fea..ebfaf5c710 100644
--- a/config/locales/doorkeeper.et.yml
+++ b/config/locales/doorkeeper.et.yml
@@ -60,7 +60,6 @@ et:
error:
title: Ilmnes viga
new:
- prompt_html: "%{client_name} soovib luba kontole juurdepääsuks. See on kolmanda osapoole rakendus. Kui see pole usaldusväärne, siis ei tohiks seda lubada."
review_permissions: Lubade ülevaade
title: Autoriseerimine vajalik
show:
@@ -83,6 +82,7 @@ et:
access_denied: Ressursi omanik või autoriseerimisserver lükkas taotluse tagasi.
credential_flow_not_configured: Resource Owner Password Credentials vool ebaõnnestus, kuna Doorkeeper.configure.resource_owner_from_credentials ei ole seadistatud.
invalid_client: Kliendi autentimine ebaõnnestus. Põhjus kas tundmatu klient, puudulik autentimine või toetamata autentimismeetod.
+ invalid_code_challenge_method: Code challenge meetod peab olema S256,, plain ei ole toetatud.
invalid_grant: Antud autoriseerimisluba on vale, aegunud, tagasi võetud, ei kattu kasutatud ümbersuunamise URLid või oli antud teisele kliendile.
invalid_redirect_uri: Antud ümbersuunamise URL ei ole õige.
invalid_request:
diff --git a/config/locales/doorkeeper.eu.yml b/config/locales/doorkeeper.eu.yml
index e7963672fa..a09fe42f40 100644
--- a/config/locales/doorkeeper.eu.yml
+++ b/config/locales/doorkeeper.eu.yml
@@ -60,7 +60,6 @@ eu:
error:
title: Errore bat gertatu da
new:
- prompt_html: "%{client_name} bezeroak zure kontura sartzeko baimena nahi du. Hirugarrengoen aplikazio bat da. Ez bazara fidatzen, ez zenuke baimendu behar."
review_permissions: Berrikusi baimenak
title: Baimena behar da
show:
diff --git a/config/locales/doorkeeper.fa.yml b/config/locales/doorkeeper.fa.yml
index c56e76e346..4ff03950b5 100644
--- a/config/locales/doorkeeper.fa.yml
+++ b/config/locales/doorkeeper.fa.yml
@@ -60,7 +60,6 @@ fa:
error:
title: خطایی رخ داد
new:
- prompt_html: "%{client_name} خواهان اجازه دسترسی به حساب کاربری شماست. اگر به آن اعتماد ندارید، نباید تاییدش کنید."
review_permissions: بازبینی اجازهها
title: نیاز به اجازه دادن
show:
@@ -83,6 +82,7 @@ fa:
access_denied: صاحب منبع یا کارساز تأیید هویت، درخواست را رد کردند.
credential_flow_not_configured: جریان اعتبارنامهٔ گذرواژهٔ مالک منبع به دلیل پیکربندی نشده بودن Doorkeeper.configure.resource_owner_from_credentials شکست خورد.
invalid_client: تأیید هویت کارخواه به دلیل کارخواه ناشناخته، عدم وجود تأیید هویت کاره یا روش تأیید هویت پشتیبانینشده شکست خورد.
+ invalid_code_challenge_method: روش چالش کدی باید S256 باشد. متن خام پشتیبانی نمیشود.
invalid_grant: اعطای دسترسی فراهم شده نامعتبر، منقضی یا نامطابق با نشانی بازگشت استفادهشده در درخواست تأیید هویت بوده و یا برای کارخواهی دیگر صادر شده است.
invalid_redirect_uri: نشانی بازگشت موجود، معتبر نیست.
invalid_request:
@@ -135,6 +135,7 @@ fa:
media: پیوستهای رسانهای
mutes: خموشها
notifications: آگاهیها
+ profile: نمایهٔ ماستودونتان
push: آگاهیهای ارسالی
reports: گزارشها
search: جستوجو
@@ -165,6 +166,7 @@ fa:
admin:write:reports: انجام کنش مدیریتی روی گزارشها
crypto: از رمزگذاری سرتاسر استفاده کنید
follow: پیگیری، مسدودسازی، لغو مسدودسازی، و لغو پیگیری حسابها
+ profile: فقط خواندن اطّلاعات نمایهٔ حسابتان
push: دریافت آگاهیای ارسالیتان
read: خواندن اطلاعات حساب شما
read:accounts: دیدن اطّلاعات حساب
diff --git a/config/locales/doorkeeper.fi.yml b/config/locales/doorkeeper.fi.yml
index ce8aef4a9f..7d44a6a6b9 100644
--- a/config/locales/doorkeeper.fi.yml
+++ b/config/locales/doorkeeper.fi.yml
@@ -60,7 +60,7 @@ fi:
error:
title: Tapahtui virhe
new:
- prompt_html: "%{client_name} pyytää oikeutta käyttää tiliäsi. Se on kolmannen osapuolen sovellus. Jos et luota siihen, älä valtuuta sitä."
+ prompt_html: "%{client_name} haluaisi käyttöoikeuden tiliisi. Hyväksy tämä pyyntö vain, jos tunnistat lähteen ja luotat siihen."
review_permissions: Tarkista käyttöoikeudet
title: Valtuutus vaaditaan
show:
diff --git a/config/locales/doorkeeper.fo.yml b/config/locales/doorkeeper.fo.yml
index 29f8cd3387..b6c1998b3a 100644
--- a/config/locales/doorkeeper.fo.yml
+++ b/config/locales/doorkeeper.fo.yml
@@ -60,7 +60,7 @@ fo:
error:
title: Ein feilur er íkomin
new:
- prompt_html: "%{client_name} kundi hugsa sær atgongd til tína kontu. Tað er ein triðjaparts-nýtsluskipan. Tú skal ikki geva henni hesa heimld, um tú ikki hevur álit á henni."
+ prompt_html: "%{client_name} kundi hugsað sær atgongd til tína kontu. Góðtak einans hesa umbøn, um tú kennir hesa keldu aftur og hevur álit á henni."
review_permissions: Eftirkanna rættindi
title: Váttan kravd
show:
diff --git a/config/locales/doorkeeper.fr-CA.yml b/config/locales/doorkeeper.fr-CA.yml
index 00df58be79..f3dad084b5 100644
--- a/config/locales/doorkeeper.fr-CA.yml
+++ b/config/locales/doorkeeper.fr-CA.yml
@@ -60,7 +60,6 @@ fr-CA:
error:
title: Une erreur est survenue
new:
- prompt_html: "%{client_name} souhaite accéder à votre compte. Il s'agit d'une application tierce. Si vous ne lui faites pas confiance, vous ne devriez pas l'y autoriser."
review_permissions: Examiner les autorisations
title: Autorisation requise
show:
@@ -83,6 +82,7 @@ fr-CA:
access_denied: Le/la propriétaire de la ressource ou le serveur d’autorisation a refusé la requête.
credential_flow_not_configured: Le flux des identifiants du mot de passe du/de la propriétaire de la ressource a échoué car Doorkeeper.configure.resource_owner_from_credentials n’est pas configuré.
invalid_client: L’authentification du client a échoué à cause d’un client inconnu, d’aucune authentification de client incluse ou d’une méthode d’authentification non prise en charge.
+ invalid_code_challenge_method: La méthode de contrôle du code doit être S256, le mode « en clair » n'est pas pris en charge.
invalid_grant: L’autorisation accordée est invalide, expirée, révoquée, ne concorde pas avec l’URI de redirection utilisée dans la requête d’autorisation, ou a été délivrée à un autre client.
invalid_redirect_uri: L’URI de redirection n’est pas valide.
invalid_request:
diff --git a/config/locales/doorkeeper.fr.yml b/config/locales/doorkeeper.fr.yml
index a5d70030a5..fac58460c6 100644
--- a/config/locales/doorkeeper.fr.yml
+++ b/config/locales/doorkeeper.fr.yml
@@ -25,7 +25,7 @@ fr:
edit: Modifier
submit: Envoyer
confirmations:
- destroy: Voulez-vous vraiment faire ça ?
+ destroy: En êtes-vous sûr ?
edit:
title: Modifier l’application
form:
@@ -60,7 +60,6 @@ fr:
error:
title: Une erreur est survenue
new:
- prompt_html: "%{client_name} souhaite accéder à votre compte. Il s'agit d'une application tierce. Vous ne devriez pas l'y autoriser si vous ne lui faites pas confiance."
review_permissions: Examiner les autorisations
title: Autorisation requise
show:
@@ -69,7 +68,7 @@ fr:
buttons:
revoke: Révoquer
confirmations:
- revoke: Voulez-vous vraiment faire ça ?
+ revoke: En êtes-vous sûr ?
index:
authorized_at: Autorisée le %{date}
description_html: Ces applications peuvent accéder à votre compte via l'API. Si vous voyez ici des applications que vous ne reconnaissez pas ou qui ne fonctionnent pas normalement, vous pouvez en révoquer les accès.
@@ -83,6 +82,7 @@ fr:
access_denied: Le propriétaire de la ressource ou le serveur d’autorisation a refusé la requête.
credential_flow_not_configured: Le flux des identifiants du mot de passe du propriétaire de la ressource a échoué car Doorkeeper.configure.resource_owner_from_credentials n’est pas configuré.
invalid_client: L’authentification du client a échoué à cause d’un client inconnu, d’aucune authentification de client incluse ou d’une méthode d’authentification non prise en charge.
+ invalid_code_challenge_method: La méthode de contrôle du code doit être S256, le mode « en clair » n'est pas pris en charge.
invalid_grant: L’autorisation accordée est invalide, expirée, annulée, ne concorde pas avec l’URL de redirection utilisée dans la requête d’autorisation, ou a été délivrée à un autre client.
invalid_redirect_uri: L’URL de redirection n’est pas valide.
invalid_request:
diff --git a/config/locales/doorkeeper.fy.yml b/config/locales/doorkeeper.fy.yml
index 1cf2d32212..94e67d17a6 100644
--- a/config/locales/doorkeeper.fy.yml
+++ b/config/locales/doorkeeper.fy.yml
@@ -60,7 +60,6 @@ fy:
error:
title: Der is in flater bard
new:
- prompt_html: "%{client_name} hat tastimming nedich om tagong te krijen ta jo account. It giet om in tapassing fan in tredde partij.As jo dit net fertrouwe, moatte jo gjin tastimming jaan."
review_permissions: Tastimmingen beoardiele
title: Autorisaasje fereaske
show:
@@ -83,6 +82,7 @@ fy:
access_denied: De boarne-eigener of autorisaasjeserver hat it fersyk wegere.
credential_flow_not_configured: De wachtwurdgegevens-flow fan de boarne-eigener is mislearre, omdat Doorkeeper.configure.resource_owner_from_credentials net ynsteld is.
invalid_client: Clientferifikaasje is mislearre troch in ûnbekende client, ûntbrekkende client-autentikaasje of in net stipe autentikaasjemetoade.
+ invalid_code_challenge_method: De koadechallengemetoade moat S256 wezen, plain wurdt net stipe.
invalid_grant: De opjûne autorisaasje is ûnjildich, ferrûn, ynlutsen, komt net oerien mei de redirect-URI dy’t opjûn is of útjûn waard oan in oere client.
invalid_redirect_uri: De opjûne redirect-URI is ûnjildich.
invalid_request:
diff --git a/config/locales/doorkeeper.ga.yml b/config/locales/doorkeeper.ga.yml
index 95c3c4d223..27082028c7 100644
--- a/config/locales/doorkeeper.ga.yml
+++ b/config/locales/doorkeeper.ga.yml
@@ -60,7 +60,6 @@ ga:
error:
title: Tharla earráid
new:
- prompt_html: Ba mhaith le %{client_name} cead rochtain a fháil ar do chuntas. Is iarratas tríú páirtí é. Mura bhfuil muinín agat as, níor cheart duit é a údarú.
review_permissions: Ceadanna a athbhreithniú
title: Tá údarú ag teastáil
show:
diff --git a/config/locales/doorkeeper.gd.yml b/config/locales/doorkeeper.gd.yml
index 1db1a90f80..8157a4e5fd 100644
--- a/config/locales/doorkeeper.gd.yml
+++ b/config/locales/doorkeeper.gd.yml
@@ -60,7 +60,7 @@ gd:
error:
title: Thachair mearachd
new:
- prompt_html: Bu mhiann le %{client_name} cead gus an cunntas agad inntrigeadh. Seo aplacaid threas-phàrtaidh. Mur eil earbsa agad ann, na ùghdarraich e.
+ prompt_html: Bu toigh le %{client_name} cead fhaighinn airson an cunntas agad inntrigeadh. Na gabh ris an iarrtas seo ach mas aithne dhut an tùs seo agus earbsa agad ann.
review_permissions: Thoir sùil air na ceadan
title: Tha feum air ùghdarrachadh
show:
diff --git a/config/locales/doorkeeper.gl.yml b/config/locales/doorkeeper.gl.yml
index 2103e50ea1..adee6bd3d3 100644
--- a/config/locales/doorkeeper.gl.yml
+++ b/config/locales/doorkeeper.gl.yml
@@ -60,7 +60,7 @@ gl:
error:
title: Algo fallou
new:
- prompt_html: "%{client_name} solicita permiso para acceder á túa conta. É unha aplicación de terceiros. Se non confías nela, non deberías autorizala."
+ prompt_html: "%{client_name} solicita permiso para acceder á túa conta. Aproba esta solicitude só se recoñeces e confías da súa orixe."
review_permissions: Revisar permisos
title: Autorización necesaria
show:
diff --git a/config/locales/doorkeeper.he.yml b/config/locales/doorkeeper.he.yml
index 16a8fc94cf..a454c779f1 100644
--- a/config/locales/doorkeeper.he.yml
+++ b/config/locales/doorkeeper.he.yml
@@ -60,7 +60,7 @@ he:
error:
title: התרחשה שגיאה
new:
- prompt_html: "%{client_name} מעוניין בהרשאה לגשת לחשבונך. זוהי אפליקציית צד-שלישי. אם יש סיבה לא לבטוח בה, נא לא לאשר."
+ prompt_html: היישום %{client_name} מבקש גישה לחשבונך. אשרו רק אם אתם מזהים את הבקשה וסומכים על מקור הבקשה.
review_permissions: עיון בהרשאות
title: נדרשת הרשאה
show:
diff --git a/config/locales/doorkeeper.hu.yml b/config/locales/doorkeeper.hu.yml
index b3cd00f4be..a13c362173 100644
--- a/config/locales/doorkeeper.hu.yml
+++ b/config/locales/doorkeeper.hu.yml
@@ -60,7 +60,7 @@ hu:
error:
title: Hiba történt
new:
- prompt_html: "%{client_name} szeretné elérni a fiókodat. Ez egy harmadik féltől származó alkalmazás. Ha nem bízol meg benne, ne addj felhatalmazást neki."
+ prompt_html: A(z) %{client_name} engedélyt kér hogy hozzáférjen a fiókodhoz. Csak akkor engedélyezd ezt a kérést, ha felismered és megbízol ebben a forrásban.
review_permissions: Jogosultságok áttekintése
title: Engedélyezés szükséges
show:
diff --git a/config/locales/doorkeeper.ia.yml b/config/locales/doorkeeper.ia.yml
index 985d073ab8..6bf5e38506 100644
--- a/config/locales/doorkeeper.ia.yml
+++ b/config/locales/doorkeeper.ia.yml
@@ -60,7 +60,6 @@ ia:
error:
title: Un error ha occurrite
new:
- prompt_html: "%{client_name} vole haber le permission de acceder a tu conto. Illo es un application tertie. Si tu non confide in illo, alora tu non deberea autorisar lo."
review_permissions: Revider permissiones
title: Autorisation necessari
show:
diff --git a/config/locales/doorkeeper.id.yml b/config/locales/doorkeeper.id.yml
index 3f9a409c21..cccabc0701 100644
--- a/config/locales/doorkeeper.id.yml
+++ b/config/locales/doorkeeper.id.yml
@@ -60,7 +60,6 @@ id:
error:
title: Ada yang error
new:
- prompt_html: "%{client_name} meminta izin untuk mengakses akun Anda. Ini adalah aplikasi pihak ketiga. Jika Anda tidak mempercayainya, Anda boleh tidak mengizinkannya."
review_permissions: Tinjau izin
title: Izin diperlukan
show:
diff --git a/config/locales/doorkeeper.ie.yml b/config/locales/doorkeeper.ie.yml
index 0119f3573f..6d8951b326 100644
--- a/config/locales/doorkeeper.ie.yml
+++ b/config/locales/doorkeeper.ie.yml
@@ -60,7 +60,6 @@ ie:
error:
title: Alquo ha errat
new:
- prompt_html: "%{client_name}, un aplication de triesim partise, vole permission por accesser tui conto. Si tu ne fide it, ne autorisa it."
review_permissions: Inspecter permissiones
title: Autorisation besonat
show:
diff --git a/config/locales/doorkeeper.io.yml b/config/locales/doorkeeper.io.yml
index a71fa95841..0384d968be 100644
--- a/config/locales/doorkeeper.io.yml
+++ b/config/locales/doorkeeper.io.yml
@@ -60,7 +60,6 @@ io:
error:
title: Eroro eventis
new:
- prompt_html: "%{client_name} volas permiso por acesar vua konti. Ol esas externa softwaro. Se vu ne fidas, lore vu debas ne yurizar."
review_permissions: Kontrolez permisi
title: Yurizo bezonesas
show:
diff --git a/config/locales/doorkeeper.is.yml b/config/locales/doorkeeper.is.yml
index 01093f4429..05f2415eea 100644
--- a/config/locales/doorkeeper.is.yml
+++ b/config/locales/doorkeeper.is.yml
@@ -60,7 +60,6 @@ is:
error:
title: Villa kom upp
new:
- prompt_html: "%{client_name} biður um heimild til að fara inn á notandaaðganginn þinn. Þetta er utanaðkomandi hugbúnaður. Ef þú treystir ekki viðkomandi, þá ættir þú ekki að heimila þetta."
review_permissions: Yfirfara heimildir
title: Auðkenning er nauðsynleg
show:
diff --git a/config/locales/doorkeeper.it.yml b/config/locales/doorkeeper.it.yml
index 9654cb2a20..3a24465cdc 100644
--- a/config/locales/doorkeeper.it.yml
+++ b/config/locales/doorkeeper.it.yml
@@ -60,7 +60,7 @@ it:
error:
title: Si è verificato un errore
new:
- prompt_html: "%{client_name} vorrebbe l'autorizzazione ad accedere al tuo profilo. È un'applicazione di terze parti. Se non ti fidi, non dovresti autorizzarla."
+ prompt_html: "%{client_name} vorrebbe il permesso di accedere al tuo account. Approva questa richiesta solo se riconosci e ti fidi di questa fonte."
review_permissions: Revisiona le autorizzazioni
title: Autorizzazione necessaria
show:
diff --git a/config/locales/doorkeeper.ja.yml b/config/locales/doorkeeper.ja.yml
index 26f7ff5635..7cfddf50a1 100644
--- a/config/locales/doorkeeper.ja.yml
+++ b/config/locales/doorkeeper.ja.yml
@@ -60,7 +60,6 @@ ja:
error:
title: エラーが発生しました
new:
- prompt_html: "%{client_name}があなたのアカウントにアクセスする許可を求めています。心当たりが無い場合はアクセス許可しないでください。"
review_permissions: アクセス許可を確認
title: 認証が必要です
show:
@@ -83,6 +82,7 @@ ja:
access_denied: リソースの所有者または認証サーバーが要求を拒否しました。
credential_flow_not_configured: リソース所有者のパスワード Doorkeeper.configure.resource_owner_from_credentials が設定されていないためクレデンシャルフローに失敗しました。
invalid_client: 不明なクライアントであるか、クライアント情報が含まれていない、またはサポートされていない認証方法のため、クライアントの認証に失敗しました。
+ invalid_code_challenge_method: code challenge methodはS256のみが利用可能です。plainはサポートされていません。
invalid_grant: 指定された認証許可は無効であるか、期限切れ、取り消されている、リダイレクトURIの不一致、または別のクライアントに発行されています。
invalid_redirect_uri: 無効なリダイレクトURIが含まれています。
invalid_request:
diff --git a/config/locales/doorkeeper.kab.yml b/config/locales/doorkeeper.kab.yml
index 13d8d93258..fa9e1c540a 100644
--- a/config/locales/doorkeeper.kab.yml
+++ b/config/locales/doorkeeper.kab.yml
@@ -125,10 +125,10 @@ kab:
title: Tlaq tsiregt n OAuth
scopes:
admin:read: ad iɣeṛ akk isefka ɣef uqeddac
- admin:write: ẓreg akk isefka γef uqeddac
- follow: beddel assaγen n umiḍan
- push: ṭṭef-d alɣuten-ik·im yettwademren
- read: γeṛ akk isefka n umiḍan-ik
+ admin:write: ad iẓreg akk isefka ɣef uqeddac
+ follow: ad ibeddel assaɣen n umiḍan
+ push: ad iṭṭef-d alɣuten-ik·im yettwademren
+ read: ad iɣeṛ akk isefka n umiḍan-ik·im
read:accounts: ẓer isallen n yimiḍanen
read:blocks: ẓer imiḍanen i tesḥebseḍ
read:bookmarks: ẓer ticraḍ-ik
@@ -139,10 +139,10 @@ kab:
read:notifications: ad iẓer alɣuten-inek·inem
read:reports: ẓer ineqqisen-ik·im
read:search: anadi deg umkan-ik·im
- read:statuses: ẓer meṛṛa tisuffaɣ
+ read:statuses: ad iẓer meṛṛa tisuffaɣ
write: beddel meṛṛa isefka n umiḍan-ik
write:accounts: ad iẓreg amaɣnu-ik·im
- write:blocks: seḥbes imiḍanen d tγula
+ write:blocks: ad iseḥbes imiḍanen akked tɣula
write:bookmarks: ad yernu tisuffaɣ ɣer ticraḍ
write:filters: ad isnulfu imsizedgen
write:follows: ḍfeṛ imdanen
diff --git a/config/locales/doorkeeper.ko.yml b/config/locales/doorkeeper.ko.yml
index f35333f1df..4dabc19e43 100644
--- a/config/locales/doorkeeper.ko.yml
+++ b/config/locales/doorkeeper.ko.yml
@@ -60,7 +60,6 @@ ko:
error:
title: 오류가 발생하였습니다
new:
- prompt_html: "%{client_name} 제3자 애플리케이션이 귀하의 계정에 접근하기 위한 권한을 요청하고 있습니다. 이 애플리케이션을 신뢰할 수 없다면 이 요청을 승인하지 마십시오."
review_permissions: 권한 검토
title: 승인 필요
show:
diff --git a/config/locales/doorkeeper.ku.yml b/config/locales/doorkeeper.ku.yml
index e3438eb5de..be6f0587c9 100644
--- a/config/locales/doorkeeper.ku.yml
+++ b/config/locales/doorkeeper.ku.yml
@@ -60,7 +60,6 @@ ku:
error:
title: Xeletîyek çêbû
new:
- prompt_html: "%{client_name} mafê dixwaze ku bigihîje ajimêrê te. Ew sepanek aliyê sêyemîn e. Ku tu pê bawer nakî, wê demê divê tu mafê gihiştinê nedî. "
review_permissions: Gihiştinan binirxînin
title: Destûr kirin pêwîst e
show:
diff --git a/config/locales/doorkeeper.lad.yml b/config/locales/doorkeeper.lad.yml
index c335d67fd6..678a53c91d 100644
--- a/config/locales/doorkeeper.lad.yml
+++ b/config/locales/doorkeeper.lad.yml
@@ -60,7 +60,6 @@ lad:
error:
title: Un yerro tiene afitado
new:
- prompt_html: "%{client_name} kere permiso para akseder tu kuento. Es una aplikasyon de terseros. Si no konfias en eya, no deverias autorizarla."
review_permissions: Reviza permisos
title: Autorizasyon rekerida
show:
diff --git a/config/locales/doorkeeper.lt.yml b/config/locales/doorkeeper.lt.yml
index ccdf866848..f957e4157c 100644
--- a/config/locales/doorkeeper.lt.yml
+++ b/config/locales/doorkeeper.lt.yml
@@ -35,24 +35,24 @@ lt:
redirect_uri: Naudok po vieną eilutę kiekvienam URI.
scopes: Atskirk aprėptis tarpais. Palik tuščią, jei nori naudoti numatytąsias aprėtis.
index:
- application: Programėlė
+ application: Programa
callback_url: Atgalinis URL
delete: Ištrinti
- empty: Neturi jokių programėlių.
+ empty: Neturi jokių programų.
name: Pavadinimas
- new: Nauja programėlė
+ new: Nauja programa
scopes: Aprėptys
show: Rodyti
- title: Tavo programėlės
+ title: Tavo programos
new:
- title: Nauja programėlė
+ title: Nauja programa
show:
actions: Veiksmai
- application_id: Kliento raktas
- callback_urls: Atgalinių URL adresų
+ application_id: Kliento programos raktas
+ callback_urls: Atgalinių URL
scopes: Aprėptys
- secret: Kliento paslaptis
- title: 'Programėlė: %{name}'
+ secret: Kliento programos paslaptis
+ title: 'Programa: %{name}'
authorizations:
buttons:
authorize: Leisti
@@ -60,48 +60,48 @@ lt:
error:
title: Įvyko klaida.
new:
- prompt_html: "%{client_name} norėtų gauti leidimą prieigos prie tavo paskyros. Tai trečiosios šalies programėlė. Jei ja nepasitiki, neturėtum leisti."
+ prompt_html: "%{client_name} norėtų gauti leidimą pasiekti tavo paskyrą. Patvirtink šį prašymą tik tada, jei atpažįsti šį šaltinį ir juo pasitiki."
review_permissions: Peržiūrėti leidimus
- title: Reikalingas leidimas
+ title: Privalomas leidimas
show:
- title: Nukopijuok šį tapatybės patvirtinimo kodą ir įklijuok jį į programėlę.
+ title: Nukopijuok šį leidimo kodą ir įklijuok jį į programą.
authorized_applications:
buttons:
revoke: Naikinti
confirmations:
revoke: Ar esi įsitikinęs (-usi)?
index:
- authorized_at: Įgaliota %{date}
- description_html: Tai programėlės, kurios gali pasiekti tavo paskyrą naudojant API. Jei čia yra programėlių, kurių neatpažįsti, arba jei programėlė elgiasi netinkamai, gali panaikinti jos prieigą.
+ authorized_at: Leidžiama %{date}
+ description_html: Tai – programos, kurios gali pasiekti tavo paskyrą naudojant API. Jei čia yra programų, kurių neatpažįsti, arba jei programa elgiasi netinkamai, gali panaikinti jos prieigą.
last_used_at: Paskutinį kartą naudota %{date}
- never_used: Niekada nenaudotas
+ never_used: Niekada nenaudota
scopes: Leidimai
superapp: Vidinis
- title: Tavo leidžiamos programėlės
+ title: Tavo leidžiamos programos
errors:
messages:
- access_denied: Išteklių savininkas (-ė) arba įgaliojimų serveris atmetė užklausą.
+ access_denied: Išteklių savininkas (-ė) arba leidžiamų serveris atmetė užklausą.
credential_flow_not_configured: Išteklių savininko slaptažodžio kredencialų srautas nepavyko, nes Doorkeeper.configure.resource_owner_from_credentials nėra nesukonfigūruotas.
- invalid_client: Kliento tapatybės nustatymas nepavyko dėl nežinomo kliento, neįtraukto kliento tapatybės nustatymo arba nepalaikomo tapatybės nustatymo metodo.
- invalid_code_challenge_method: Kodo iššūkio būdas turi būti S256. Paprastas nepalaikomas.
- invalid_grant: Pateiktas įgaliojimas yra netinkamas, pasibaigęs, panaikintas, neatitinka įgaliojimo užklausoje naudoto nukreipimo URI arba buvo išduotas kitam klientui.
- invalid_redirect_uri: Nukreipimo uri įtrauktas yra netinkamas.
+ invalid_client: Kliento programos tapatybės nustatymas nepavyko dėl nežinomo kliento programos, neįtraukto kliento programos tapatybės nustatymo arba nepalaikomo tapatybės nustatymo metodo.
+ invalid_code_challenge_method: Kodo iššūkio metodas turi būti S256. Paprastas nepalaikomas.
+ invalid_grant: Pateiktas leidimo suteikimas yra netinkamas, nebegaliojantis, panaikintas, neatitinka leidimo užklausoje naudoto nukreipimo URI arba buvo išduotas kitam kliento programui.
+ invalid_redirect_uri: Įtrauktas nukreipimo URI netinkamas.
invalid_request:
missing_param: 'Trūksta privalomo parametro: %{value}.'
- request_not_authorized: Užklausą reikia įgalioti. Reikalingo parametro užklausai įgalioti trūksta arba jis netinkamas.
- unknown: Užklausoje trūksta privalomo parametro, turi nepalaikomą parametro reikšmę arba yra kitaip netinkamai suformuota.
- invalid_resource_owner: Pateikti išteklių savininko įgaliojimai yra netinkami arba išteklių savininko negalima surasti.
+ request_not_authorized: Užklausą reikia leisti. Trūksta privalomo parametro užklausai leisti arba jis netinkamas.
+ unknown: Užklausai trūksta privalomo parametro, įtraukta nepalaikoma parametro reikšmė arba ji yra kitaip netaisyklingas.
+ invalid_resource_owner: Pateikti išteklių savininko kredencialai yra netinkami arba išteklių savininko negalima surasti.
invalid_scope: Užklausos aprėptis yra netinkama, nežinoma arba netaisyklingas.
invalid_token:
- expired: Baigėsi prieigos rakto galiojimas.
+ expired: Prieigos raktas nebegalioja.
revoked: Prieigos raktas buvo panaikintas.
- unknown: Prieigos raktas yra netinkamas.
- resource_owner_authenticator_not_configured: Išteklių savininko suradimas nepavyko dėl to, kad Doorkeeper.configure.resource_owner_authenticator nėra sukonfigūruotas.
- server_error: Įgaliojimų serveris susidūrė su netikėta sąlyga, dėl kurios negalėjo užpildyti užklausos.
+ unknown: Prieigos raktas netinkamas.
+ resource_owner_authenticator_not_configured: Išteklių savininko suradimas nepavyko, nes Doorkeeper.configure.resource_owner_authenticator nėra sukonfigūruotas.
+ server_error: Leidimo serveris susidūrė su netikėta sąlyga, dėl kurios negalėjo užpildyti užklausos.
temporarily_unavailable: Įgaliojimų serveris šiuo metu negali apdoroti užklausos dėl laikinos serverio perkrovos arba techninės priežiūros.
- unauthorized_client: Klientas nėra įgaliotas atlikti šią užklausą šiuo metodu.
- unsupported_grant_type: Įgaliojimų suteikimo tipas nepalaikomas įgaliojimų serveryje.
- unsupported_response_type: Įgaliojimų serveris nepalaiko šio atsako tipo.
+ unauthorized_client: Klientas nėra leidžiamas atlikti šią užklausą šiuo metodu.
+ unsupported_grant_type: Leidimo suteikimo tipas nepalaikomas leidimo serveryje.
+ unsupported_response_type: Leidimo serveris nepalaiko šio atsakymo tipo.
flash:
applications:
create:
@@ -123,7 +123,7 @@ lt:
admin/accounts: Paskyrų administravimas
admin/all: Visi administraciniai funkcijos
admin/reports: Ataskaitų administravimas
- all: Pilna prieiga prie tavo Mastodon paskyros
+ all: Pilna prieiga prie tavo „Mastodon“ paskyros
blocks: Blokavimai
bookmarks: Žymės
conversations: Pokalbiai
@@ -136,7 +136,7 @@ lt:
media: Medijos priedai
mutes: Nutildymai
notifications: Pranešimai
- profile: Tavo Mastodon profilis
+ profile: Tavo „Mastodon“ profilis
push: Tiesioginiai pranešimai
reports: Ataskaitos
search: Paieška
@@ -151,25 +151,25 @@ lt:
scopes:
admin:read: skaityti visus duomenis serveryje
admin:read:accounts: skaityti slaptą visų paskyrų informaciją
- admin:read:canonical_email_blocks: skaityti slaptą visų kanoninių el. laiško blokavimų informaciją
- admin:read:domain_allows: skaityti slaptą visų domeno leidimus informaciją
- admin:read:domain_blocks: skaityti slaptą visų domeno blokavimų informaciją
- admin:read:email_domain_blocks: skaityti slaptą visų el. laiško domeno blokavimų informaciją
+ admin:read:canonical_email_blocks: skaityti slaptą visų kanoninių el. laiškų blokavimų informaciją
+ admin:read:domain_allows: skaityti slaptą visų serverių leidžiamų informaciją
+ admin:read:domain_blocks: skaityti slaptą visų serverių blokavimų informaciją
+ admin:read:email_domain_blocks: skaityti slaptą visų el. laiškų serverių blokavimų informaciją
admin:read:ip_blocks: skaityti slaptą visų IP blokavimų informaciją
admin:read:reports: skaityti slaptą visų ataskaitų ir praneštų paskyrų informaciją
admin:write: modifikuoti visus duomenis serveryje
admin:write:accounts: atlikti paskyrų prižiūrėjimo veiksmus
- admin:write:canonical_email_blocks: atlikti kanoninių el. laiško blokavimų prižiūrėjimo veiksmus
- admin:write:domain_allows: atlikti domeno leidimų prižiūrėjimo veiksmus
- admin:write:domain_blocks: atlikti domeno blokavimų prižiūrėjimo veiksmus
- admin:write:email_domain_blocks: atlikti el. laiško domenų blokavimų prižiūrėjimo veiksmus
+ admin:write:canonical_email_blocks: atlikti kanoninių el. laiškų blokavimų prižiūrėjimo veiksmus
+ admin:write:domain_allows: atlikti serverio leidžiamų prižiūrėjimo veiksmus
+ admin:write:domain_blocks: atlikti serverio blokavimų prižiūrėjimo veiksmus
+ admin:write:email_domain_blocks: atlikti el. laiškų serverių blokavimų prižiūrėjimo veiksmus
admin:write:ip_blocks: atlikti IP blokavimų prižiūrėjimo veiksmus
admin:write:reports: atlikti ataskaitų prižiūrėjimo veiksmus
crypto: naudoti visapusį šifravimą
follow: modifikuoti paskyros sąryšius
profile: skaityti tik tavo paskyros profilio informaciją
push: gauti tiesioginius pranešimus
- read: skaityti visus paskyros duomenis
+ read: skaityti visus tavo paskyros duomenis
read:accounts: matyti paskyrų informaciją
read:blocks: matyti tavo blokavimus
read:bookmarks: matyti tavo žymes
diff --git a/config/locales/doorkeeper.lv.yml b/config/locales/doorkeeper.lv.yml
index 11c5020305..55e288a9d6 100644
--- a/config/locales/doorkeeper.lv.yml
+++ b/config/locales/doorkeeper.lv.yml
@@ -60,7 +60,6 @@ lv:
error:
title: Radās kļūda
new:
- prompt_html: "%{client_name} vēlas saņemt atļauju piekļūt tavam kontam. Tā ir trešās puses lietojumprogramma. Ja tu tam neuzticies, tad nevajadzētu to autorizēt."
review_permissions: Pārskatīt atļaujas
title: Nepieciešama autorizācija
show:
@@ -83,6 +82,7 @@ lv:
access_denied: Resursa īpašnieks vai autorizācijas serveris pieprasījumu noraidīja.
credential_flow_not_configured: Resursa īpašnieka paroles akreditācijas datu plūsma neizdevās, jo Doorkeeper.configure.resource_owner_from_credentials nebija konfigurēts.
invalid_client: Klienta autentifikācija neizdevās nezināma klienta, klienta autentifikācijas vai neatbalstītas autentifikācijas metodes dēļ.
+ invalid_code_challenge_method: Koda izaicinājuma veidam jābūt S256, vienkāršs netiek atbalstīts.
invalid_grant: Sniegtā autorizācijas piekrišana nav derīga, tai ir beidzies derīguma termiņš, tā ir atsaukta, tā neatbilst autorizācijas pieprasījumā izmantotajam novirzīšanas URI vai tika izsniegta citam klientam.
invalid_redirect_uri: Iekļauts novirzīšanas uri nav derīgs.
invalid_request:
diff --git a/config/locales/doorkeeper.ms.yml b/config/locales/doorkeeper.ms.yml
index 32fb0044bb..b52824e8c3 100644
--- a/config/locales/doorkeeper.ms.yml
+++ b/config/locales/doorkeeper.ms.yml
@@ -60,7 +60,6 @@ ms:
error:
title: Ralat telah berlaku
new:
- prompt_html: "%{client_name} ingin mendapatkan kebenaran untuk mengakses akaun anda. Ia adalah aplikasi pihak ketiga. Jika anda tidak mempercayainya, maka anda tidak seharusnya membenarkannya."
review_permissions: Semak kebenaran
title: Kebenaran diperlukan
show:
diff --git a/config/locales/doorkeeper.my.yml b/config/locales/doorkeeper.my.yml
index bce6039eae..0cfe505982 100644
--- a/config/locales/doorkeeper.my.yml
+++ b/config/locales/doorkeeper.my.yml
@@ -60,7 +60,6 @@ my:
error:
title: အမှားအယွင်းတစ်ခု ဖြစ်ပေါ်ခဲ့သည်
new:
- prompt_html: "%{client_name} က သင့်အကောင့်သို့ ဝင်ရောက်ရန် ခွင့်ပြုချက်ရယူလိုပါသည်။ ၎င်းမှာ ပြင်ပကြားခံအက်ပလီကေးရှင်းတစ်ခုဖြစ်သည်။ သင် မယုံကြည်ပါက ၎င်းကိုခွင့်မပြုသင့်ပါ။"
review_permissions: ခွင့်ပြုချက်များကို ပြန်လည်သုံးသပ်ပါ
title: ခွင့်ပြုချက် လိုအပ်သည်
show:
diff --git a/config/locales/doorkeeper.nl.yml b/config/locales/doorkeeper.nl.yml
index 65ef826d38..c6453761f1 100644
--- a/config/locales/doorkeeper.nl.yml
+++ b/config/locales/doorkeeper.nl.yml
@@ -60,7 +60,7 @@ nl:
error:
title: Er is een fout opgetreden
new:
- prompt_html: "%{client_name} heeft toestemming nodig om toegang te krijgen tot jouw account. Het betreft een third-party-toepassing.Als je dit niet vertrouwt, moet je geen toestemming verlenen."
+ prompt_html: "%{client_name} vraagt om toegang tot je account. Keur dit verzoek alleen goed als je deze bron herkent en vertrouwt."
review_permissions: Toestemmingen beoordelen
title: Autorisatie vereist
show:
diff --git a/config/locales/doorkeeper.nn.yml b/config/locales/doorkeeper.nn.yml
index 975ceb43c7..9b9ddba08d 100644
--- a/config/locales/doorkeeper.nn.yml
+++ b/config/locales/doorkeeper.nn.yml
@@ -60,7 +60,7 @@ nn:
error:
title: Ein feil har oppstått
new:
- prompt_html: "%{client_name} ønsker tilgang til kontoen din. Det er ein tredjepartsapplikasjon. Dersom du ikkje stolar på den, bør du ikkje autorisere det."
+ prompt_html: "%{client_name} ynskjer tilgang til kontoen din. Godkjenn dette berre dersom du kjenner att og stolar på %{client_name}."
review_permissions: Sjå gjennom løyve
title: Autorisasjon nødvendig
show:
diff --git a/config/locales/doorkeeper.no.yml b/config/locales/doorkeeper.no.yml
index c432f6645c..7b7b9d6534 100644
--- a/config/locales/doorkeeper.no.yml
+++ b/config/locales/doorkeeper.no.yml
@@ -60,7 +60,6 @@
error:
title: En feil oppstod
new:
- prompt_html: "%{client_name} ønsker tilgang til kontoen din. Det er en tredjeparts applikasjon. Hvis du ikke stoler på den, bør du ikke autorisere den."
review_permissions: Gå gjennom tillatelser
title: Autorisasjon påkrevd
show:
diff --git a/config/locales/doorkeeper.oc.yml b/config/locales/doorkeeper.oc.yml
index 64bc3a43e2..7f1155a839 100644
--- a/config/locales/doorkeeper.oc.yml
+++ b/config/locales/doorkeeper.oc.yml
@@ -60,7 +60,6 @@ oc:
error:
title: I a agut un error
new:
- prompt_html: "%{client_name} volria l’autorizacion d’accedir a vòstre compte. Es una aplicacion tèrça.Se vos fisatz pas a ela, alara deuriatz pas l’autorizacion."
review_permissions: Repassar las autorizacions
title: Cal l’autorizacion
show:
diff --git a/config/locales/doorkeeper.pl.yml b/config/locales/doorkeeper.pl.yml
index bf2da6f808..2ff1bb5f45 100644
--- a/config/locales/doorkeeper.pl.yml
+++ b/config/locales/doorkeeper.pl.yml
@@ -60,7 +60,7 @@ pl:
error:
title: Wystapił błąd
new:
- prompt_html: "%{client_name} chciałby uzyskać pozwolenie na dostęp do Twojego konta. Jest to aplikacja zewnętrzna. Jeśli jej nie ufasz, nie powinno się jej autoryzować."
+ prompt_html: "%{client_name} prosi o dostęp do twojego konta. Tylko zatwierdź tę prośbę, jeżeli ją rozpoznajesz i ufasz."
review_permissions: Sprawdź uprawnienia
title: Wymagana jest autoryzacja
show:
diff --git a/config/locales/doorkeeper.pt-BR.yml b/config/locales/doorkeeper.pt-BR.yml
index 6b076e9081..f7f9dce7ea 100644
--- a/config/locales/doorkeeper.pt-BR.yml
+++ b/config/locales/doorkeeper.pt-BR.yml
@@ -60,8 +60,7 @@ pt-BR:
error:
title: Ocorreu um erro
new:
- prompt_html: O %{client_name} gostaria de ter permissão para acessar sua conta. É uma aplicação de terceiros. Se você não confia, então você não deve autorizá-lo.
- review_permissions: Revisar permissões
+ review_permissions: Rever permissões
title: Autorização necessária
show:
title: Copie este código de autorização e cole no aplicativo.
@@ -72,8 +71,8 @@ pt-BR:
revoke: Você tem certeza?
index:
authorized_at: Autorizado em %{date}
- description_html: Estas são as aplicações que podem acessar sua conta usando a API. Se houver aplicativos que você não reconhece ou com mau funcionamento, você pode revogar seu acesso.
- last_used_at: Última vez usado em %{date}
+ description_html: Estas são as aplicações que podem acessar sua conta usando a API. Se houver aplicações que você não reconhece ou que não funcionem corretamente, você pode revogar os acessos.
+ last_used_at: Usado pela última vez em %{date}
never_used: Nunca usado
scopes: Permissões
superapp: Interno
@@ -83,6 +82,7 @@ pt-BR:
access_denied: O proprietário do recurso ou servidor de autorização recusou a solicitação.
credential_flow_not_configured: Fluxo das Credenciais de Senha do Proprietário do Recurso falhou porque Doorkeeper.configure.resource_owner_from_credentials não foi configurado.
invalid_client: Autenticação do cliente falhou por causa de um cliente desconhecido, nenhum cliente de autenticação foi incluído ou o método de autenticação não é suportado.
+ invalid_code_challenge_method: O método de desafio de código deve ser S256; o método 'plain' não é suportado.
invalid_grant: A garantia de autorização está inválida, expirou ou foi revogada, não é equivalente ao link de redirecionamento usado na solicitação de autorização ou foi emitido por outro cliente.
invalid_redirect_uri: O link de redirecionamento é inválido.
invalid_request:
@@ -114,23 +114,23 @@ pt-BR:
notice: Aplicativo revogado.
grouped_scopes:
access:
- read: Acesso somente para leitura
+ read: Acesso somente leitura
read/write: Acesso de leitura e escrita
- write: Acesso somente para escrita
+ write: Acesso somente escrita
title:
accounts: Contas
admin/accounts: Administração de contas
admin/all: Todas as funções administrativas
- admin/reports: Controle de denúncias
+ admin/reports: Administração de denúncias
all: Acesso total à sua conta Mastodon
blocks: Bloqueios
bookmarks: Salvos
conversations: Conversas
crypto: Criptografia de ponta a ponta
- favourites: Favoritas
+ favourites: Favoritos
filters: Filtros
- follow: Seguidores, Silenciados e Bloqueados
- follows: Seguidores
+ follow: Seguimentos, Silenciamentos e Bloqueios
+ follows: Seguidos
lists: Listas
media: Mídias anexadas
mutes: Silenciados
@@ -151,17 +151,17 @@ pt-BR:
admin:read: ler todos os dados no servidor
admin:read:accounts: ler informações sensíveis de todas as contas
admin:read:canonical_email_blocks: ler informações sensíveis de todos os blocos de e-mail canônicos
- admin:read:domain_allows: ler informações sensíveis de todos os domínios (URL) permitidos
- admin:read:domain_blocks: ler informações sensíveis de todos os domínios (URL) bloqueados
- admin:read:email_domain_blocks: ler informações sensíveis de todos os e-mails de domínios bloqueados
+ admin:read:domain_allows: ler informações sensíveis de todos os domínios permitidos
+ admin:read:domain_blocks: ler informações sensíveis de todos os domínios bloqueados
+ admin:read:email_domain_blocks: ler informações sensíveis de todos os domínios de e-mail bloqueados
admin:read:ip_blocks: ler informações sensíveis de todos os endereços de IP bloqueados
admin:read:reports: ler informações sensíveis de todas as denúncias e contas denunciadas
admin:write: alterar todos os dados no servidor
admin:write:accounts: executar ações de moderação em contas
admin:write:canonical_email_blocks: executar ações de moderação em blocos canônicos de e-mail
- admin:write:domain_allows: executar ações de moderação em domínios (URL) permitidos
- admin:write:domain_blocks: executar ações de moderação em domínios (URL) bloqueados
- admin:write:email_domain_blocks: executar ações de moderação em blocos de e-mail bloqueados
+ admin:write:domain_allows: executar ações de moderação em domínios permitidos
+ admin:write:domain_blocks: executar ações de moderação em domínios bloqueados
+ admin:write:email_domain_blocks: executar ações de moderação em domínios de e-mail bloqueados
admin:write:ip_blocks: executar ações de moderação em IPs bloqueados
admin:write:reports: executar ações de moderação em denúncias
crypto: usar criptografia de ponta-a-ponta
@@ -172,7 +172,7 @@ pt-BR:
read:accounts: ver informações das contas
read:blocks: ver seus bloqueados
read:bookmarks: ver seus salvos
- read:favourites: veja suas favoritas
+ read:favourites: veja seus favoritos
read:filters: ver seus filtros
read:follows: ver quem você segue
read:lists: ver suas listas
diff --git a/config/locales/doorkeeper.pt-PT.yml b/config/locales/doorkeeper.pt-PT.yml
index 30ea62d9eb..e2ac275335 100644
--- a/config/locales/doorkeeper.pt-PT.yml
+++ b/config/locales/doorkeeper.pt-PT.yml
@@ -4,9 +4,9 @@ pt-PT:
attributes:
doorkeeper/application:
name: Nome da aplicação
- redirect_uri: URI de redireccionamento
+ redirect_uri: URI de redirecionamento
scopes: Âmbitos
- website: Página na teia da aplicação
+ website: Site da aplicação
errors:
models:
doorkeeper/application:
@@ -31,11 +31,11 @@ pt-PT:
form:
error: Ups! Verifique que o formulário não tem erros
help:
- native_redirect_uri: Usa %{native_redirect_uri} para testes locais
- redirect_uri: Utiliza uma linha por URI
- scopes: Separe as esferas de acção com espaços. Deixe em branco para usar autorizações predefinidas.
+ native_redirect_uri: Usar %{native_redirect_uri} para testes locais
+ redirect_uri: Usar uma linha por URI
+ scopes: Separe os âmbitos de aplicação com espaços. Deixe em branco para utilizar os âmbitos de aplicação predefinidos.
index:
- application: Aplicações
+ application: Aplicação
callback_url: URL de retorno
delete: Eliminar
empty: Não tem aplicações.
@@ -48,31 +48,30 @@ pt-PT:
title: Nova aplicação
show:
actions: Ações
- application_id: Id de Aplicação
- callback_urls: Callback urls
- scopes: Autorizações
+ application_id: Chave da aplicação
+ callback_urls: URLs de retorno
+ scopes: Âmbitos
secret: Segredo
title: 'Aplicação: %{name}'
authorizations:
buttons:
- authorize: Autorize
- deny: Não autorize
+ authorize: Autorizar
+ deny: Negar
error:
title: Ocorreu um erro
new:
- prompt_html: "%{client_name} pretende ter permissão para aceder à sua conta. É uma aplicação de terceiros. Se não confia nesta aplicação, então não deve autorizá-la."
review_permissions: Rever permissões
- title: Autorização é necessária
+ title: Autorização necessária
show:
- title: Copiar o código desta autorização e colar na aplicação.
+ title: Copie este código de autorização e cole-o na aplicação.
authorized_applications:
buttons:
revoke: Revogar
confirmations:
- revoke: Tens a certeza?
+ revoke: Tem a certeza?
index:
authorized_at: Autorizado em %{date}
- description_html: Estas são aplicações que podem aceder à sua conta utilizando a API. Se encontrar aqui aplicativos que não reconhece, ou um aplicativo está com mau funcionamento, pode revogar o seu acesso.
+ description_html: Estas são as aplicações que podem aceder à sua conta utilizando a API. Se houver aplicações que não reconhece aqui, ou se uma aplicação estiver a comportar-se mal, pode revogar o seu acesso.
last_used_at: Última utilização em %{date}
never_used: Nunca utilizado
scopes: Permissões
@@ -81,15 +80,15 @@ pt-PT:
errors:
messages:
access_denied: O proprietário do recurso ou servidor de autorização negou o pedido.
- credential_flow_not_configured: As credenciais da palavra-passe do proprietário do recurso falhou devido a que Doorkeeper.configure.resource_owner_from_credentials não foram configuradas.
- invalid_client: Autenticação do cliente falhou por causa de um cliente desconhecido, nenhum cliente de autenticação incluído ou método de autenticação não suportado.
+ credential_flow_not_configured: Falha no fluxo de credenciais da palavra-passe do proprietário do recurso porque Doorkeeper.configure.resource_owner_from_credentials não está configurado.
+ invalid_client: A autenticação do cliente falhou devido a cliente desconhecido, sem autenticação de cliente incluída ou método de autenticação não suportado.
invalid_code_challenge_method: O método de validação do código tem de ser S256, o método simples não é suportado.
invalid_grant: A concessão de autorização fornecida é inválida, expirou, foi revogada, não corresponde à URI de redirecionamento usada no pedido de autorização ou foi emitida para outro cliente.
invalid_redirect_uri: A URI de redirecionamento incluída não é válida.
invalid_request:
missing_param: 'Parâmetro requerido em falta: %{value}.'
- request_not_authorized: O pedido precisa ser autorizado. O parâmetro requerido para autorização da solicitação está ausente ou é inválido.
- unknown: A solicitação não possui um parâmetro requerido, inclui um valor de parâmetro não suportado ou tem outro tipo de formato incorreto.
+ request_not_authorized: O pedido tem de ser autorizado. O parâmetro necessário para autorizar o pedido está em falta ou é inválido.
+ unknown: O pedido não tem um parâmetro obrigatório, inclui um valor de parâmetro não suportado ou está mal formado.
invalid_resource_owner: As credenciais do proprietário do recurso não são válidas ou o proprietário do recurso não pode ser encontrado
invalid_scope: O âmbito solicitado é inválido, desconhecido ou tem um formato incorreto.
invalid_token:
@@ -98,7 +97,7 @@ pt-PT:
unknown: O token de acesso é inválido
resource_owner_authenticator_not_configured: A procura pelo proprietário do recurso falhou porque Doorkeeper.configure.resource_owner_authenticator não foi configurado.
server_error: O servidor de autorização encontrou uma condição inesperada que impediu o cumprimento do pedido .
- temporarily_unavailable: O servidor de autorização não é capaz de lidar com o pedido devido a uma sobrecarga ou mantenimento do servidor.
+ temporarily_unavailable: O servidor de autorização não pode atualmente tratar o pedido devido a uma sobrecarga temporária ou à manutenção do servidor.
unauthorized_client: O cliente não está autorizado a realizar esta solicitação usando este método.
unsupported_grant_type: O tipo de concessão de autorização não é suportado pelo servidor de autorização.
unsupported_response_type: O servidor de autorização não suporta este tipo de resposta.
@@ -125,12 +124,12 @@ pt-PT:
admin/reports: Administração de denúncias
all: Acesso total à sua conta Mastodon
blocks: Bloqueios
- bookmarks: Itens Salvos
+ bookmarks: Marcadores
conversations: Conversas
- crypto: Encriptação ponta-a-ponta
+ crypto: Encriptação ponta a ponta
favourites: Favoritos
filters: Filtros
- follow: A seguir, a silenciar, e a bloquear
+ follow: A seguir, a silenciar e a bloquear
follows: Seguidores
lists: Listas
media: Anexos de media
@@ -139,7 +138,7 @@ pt-PT:
profile: O seu perfil Mastodon
push: Notificações push
reports: Denúncias
- search: Pesquisa
+ search: Pesquisar
statuses: Publicações
layouts:
admin:
@@ -165,14 +164,14 @@ pt-PT:
admin:write:email_domain_blocks: executar ações de moderação no bloqueio de domínios de e-mail
admin:write:ip_blocks: executar ações de moderação no bloqueio de IPs
admin:write:reports: executar ações de moderação em denúncias
- crypto: usa encriptação ponta-a-ponta
- follow: siga, bloqueie, desbloqueie, e deixa de seguir contas
- profile: apenas ler as informações do perfil da sua conta
+ crypto: usar encriptação ponta a ponta
+ follow: alterar relações de conta
+ profile: ler apenas as informações do perfil da sua conta
push: receber as suas notificações push
- read: tenha acesso aos dados da tua conta
+ read: ler todos os dados da sua conta
read:accounts: ver as informações da conta
read:blocks: ver os seus bloqueios
- read:bookmarks: ver os seus favoritos
+ read:bookmarks: ver os seus marcadores
read:favourites: ver os seus favoritos
read:filters: ver os seus filtros
read:follows: ver quem você segue
@@ -181,18 +180,18 @@ pt-PT:
read:notifications: ver as suas notificações
read:reports: ver as suas denúncias
read:search: pesquisar em seu nome
- read:statuses: ver todos os estados
- write: publique por ti
- write:accounts: modificar o seu perfil
+ read:statuses: ver todas as publicações
+ write: alterar todos os dados da sua conta
+ write:accounts: alterar o seu perfil
write:blocks: bloquear contas e domínios
- write:bookmarks: estado dos favoritos
+ write:bookmarks: marcar publicações
write:conversations: silenciar e eliminar conversas
- write:favourites: assinalar como favoritas
+ write:favourites: favoritar publicações
write:filters: criar filtros
write:follows: seguir pessoas
write:lists: criar listas
- write:media: carregar arquivos de media
+ write:media: enviar ficheiros de media
write:mutes: silenciar pessoas e conversas
write:notifications: limpar as suas notificações
write:reports: denunciar outras pessoas
- write:statuses: publicar estado
+ write:statuses: publicar publicações
diff --git a/config/locales/doorkeeper.ro.yml b/config/locales/doorkeeper.ro.yml
index fa28373521..9c02501eff 100644
--- a/config/locales/doorkeeper.ro.yml
+++ b/config/locales/doorkeeper.ro.yml
@@ -3,10 +3,10 @@ ro:
activerecord:
attributes:
doorkeeper/application:
- name: Numele aplicației
+ name: Nume aplicație
redirect_uri: URI de redirecționare
scopes: Domenii
- website: Pagina web a aplicației
+ website: Website aplicație
errors:
models:
doorkeeper/application:
@@ -19,60 +19,59 @@ ro:
doorkeeper:
applications:
buttons:
- authorize: Autorizează
- cancel: Anulează
- destroy: Distruge
- edit: Editează
- submit: Trimite
+ authorize: Autorizare
+ cancel: Anulare
+ destroy: Distrugere
+ edit: Editare
+ submit: Trimitere
confirmations:
- destroy: Ești sigur?
+ destroy: Sunteți sigur?
edit:
- title: Editați aplicația
+ title: Editare aplicație
form:
error: Ups! Verificați formularul pentru posibile erori
help:
native_redirect_uri: Utilizați %{native_redirect_uri} pentru teste locale
- redirect_uri: Folosește câte o linie per URI
+ redirect_uri: Folosiți câte o linie per URI
scopes: Separați domeniile cu spații. Lăsați necompletat pentru a utiliza domeniile implicite.
index:
application: Aplicație
- callback_url: URL pentru callback
- delete: Șterge
+ callback_url: Callback URL
+ delete: Ștergere
empty: Nu aveți aplicații.
name: Nume
new: Aplicație nouă
scopes: Domenii
- show: Arată
- title: Aplicațiile tale
+ show: Afișare
+ title: Aplicațiile dvs.
new:
title: Aplicație nouă
show:
actions: Acțiuni
application_id: Cheie client
- callback_urls: URL-uri de callback
+ callback_urls: Callback URL-uri
scopes: Domenii
- secret: Codul secret al clientului
+ secret: Secretul clientului
title: 'Aplicație: %{name}'
authorizations:
buttons:
- authorize: Autorizează
- deny: Interzice
+ authorize: Autorizare
+ deny: Refuzare
error:
title: A apărut o eroare
new:
- prompt_html: "%{client_name} dorește să îți acceseze contul. Este o aplicație terță. Dacă nu aveți încredere în ea, atunci nu ar trebui să o autorizați."
- review_permissions: Revizuiește permisiunile
+ review_permissions: Revizuiți permisiunile
title: Autorizare necesară
show:
title: Copiați acest cod de autorizare și lipiți-l în aplicație.
authorized_applications:
buttons:
- revoke: Revocați
+ revoke: Revocare
confirmations:
- revoke: Ești sigur?
+ revoke: Sunteți sigur?
index:
authorized_at: Autorizat pe %{date}
- description_html: Acestea sunt aplicațiile care vă pot accesa contul folosind API. Dacă există aplicații pe care nu le recunoașteți, sau o aplicație se comportă necorespunzător, puteți revoca accesul.
+ description_html: Acestea sunt aplicațiile care vă pot accesa contul folosind API-ul. Dacă există aplicații pe care nu le recunoașteți, sau o aplicație se comportă necorespunzător, puteți revoca accesul.
last_used_at: Utilizat ultima dată pe %{date}
never_used: Nu a fost folosit niciodată
scopes: Permisiuni
@@ -86,9 +85,9 @@ ro:
invalid_grant: Acordarea autorizației furnizată este invalidă, expirată, revocată, nu corespunde URI-ului de redirecționare folosit în cererea de autorizare, sau a fost eliberat altui client.
invalid_redirect_uri: Uri-ul de redirecționare inclus nu este valid.
invalid_request:
- missing_param: 'Lipseste parametrul necesar: %{value}.'
+ missing_param: 'Lipsește parametrul necesar: %{value}.'
request_not_authorized: Solicitarea trebuie să fie autorizată. Parametrul necesar pentru solicitarea de autorizare lipsește sau este invalid.
- unknown: Solicitarea nu are un parametru necesar, include un parametru nesuportat sau este dealtfel formatat incorect.
+ unknown: Solicitarea nu are un parametru necesar, include un parametru nesuportat sau este formatat incorect.
invalid_resource_owner: Acreditările proprietarului de resurse nu sunt valide sau proprietarul de resurse nu poate fi găsit
invalid_scope: Domeniul de aplicare solicitat este invalid, necunoscut sau incorect.
invalid_token:
@@ -137,12 +136,12 @@ ro:
notifications: Notificări
push: Notificări push
reports: Rapoarte
- search: Caută
+ search: Căutare
statuses: Postări
layouts:
admin:
nav:
- applications: Aplicaţii
+ applications: Aplicații
oauth2_provider: Furnizor OAuth2
application:
title: Este necesară autorizarea OAuth
@@ -160,7 +159,7 @@ ro:
read:accounts: vede informațiile privind conturile
read:blocks: vede blocurile tale
read:bookmarks: vede marcajele tale
- read:favourites: vezi favoritele tale
+ read:favourites: vede favoritele tale
read:filters: vede filtrele tale
read:follows: vede urmăririle tale
read:lists: vede listele tale
@@ -168,7 +167,7 @@ ro:
read:notifications: vede notificările tale
read:reports: vede raportările tale
read:search: caută în numele tău
- read:statuses: vede toate stările
+ read:statuses: vede toate postările
write: modifică toate datele contului tău
write:accounts: modifică profilul tău
write:blocks: blochează conturile și domeniile
diff --git a/config/locales/doorkeeper.ru.yml b/config/locales/doorkeeper.ru.yml
index 12b7e7e87e..1dcb2093d5 100644
--- a/config/locales/doorkeeper.ru.yml
+++ b/config/locales/doorkeeper.ru.yml
@@ -60,7 +60,6 @@ ru:
error:
title: Произошла ошибка
new:
- prompt_html: "%{client_name} хочет получить доступ к вашему аккаунту. Это стороннее приложение. Если вы ему не доверяете, не разрешайте доступ."
review_permissions: Просмотр разрешений
title: Требуется авторизация
show:
diff --git a/config/locales/doorkeeper.sco.yml b/config/locales/doorkeeper.sco.yml
index 70341c3c69..6e54c53ca5 100644
--- a/config/locales/doorkeeper.sco.yml
+++ b/config/locales/doorkeeper.sco.yml
@@ -60,7 +60,6 @@ sco:
error:
title: A error haes occurrt
new:
- prompt_html: "%{client_name} wad like permission fir tae access yer accoont. It is a third-party application. Gin ye dinnae trust it, then ye shuidnae authorize it."
review_permissions: Luik ower permissions
title: Authorization requirt
show:
diff --git a/config/locales/doorkeeper.si.yml b/config/locales/doorkeeper.si.yml
index d3550cf598..43a109b194 100644
--- a/config/locales/doorkeeper.si.yml
+++ b/config/locales/doorkeeper.si.yml
@@ -60,7 +60,6 @@ si:
error:
title: දෝෂයක් සිදු වී ඇත
new:
- prompt_html: "%{client_name} ඔබගේ ගිණුමට ප්රවේශ වීමට අවසර ලබා ගැනීමට කැමති වේ. එය තෙවන පාර්ශවීය යෙදුමකි. ඔබ එය විශ්වාස නොකරන්නේ නම්, ඔබ එයට අවසර නොදිය යුතුය."
review_permissions: අවසර සමාලෝචනය
title: බලය පැවරීමේ අවශ්ය
show:
diff --git a/config/locales/doorkeeper.sk.yml b/config/locales/doorkeeper.sk.yml
index face9db966..774a2648f9 100644
--- a/config/locales/doorkeeper.sk.yml
+++ b/config/locales/doorkeeper.sk.yml
@@ -60,7 +60,6 @@ sk:
error:
title: Nastala chyba
new:
- prompt_html: "%{client_name} žiada o povolenie na prístup k vášmu účtu. Ide o aplikáciu tretej strany. Ak jej nedôverujete, nemali by ste ju povoliť."
review_permissions: Preskúmať povolenia
title: Je potrebné schválenie
show:
diff --git a/config/locales/doorkeeper.sl.yml b/config/locales/doorkeeper.sl.yml
index f6f64fc87f..3f36c73756 100644
--- a/config/locales/doorkeeper.sl.yml
+++ b/config/locales/doorkeeper.sl.yml
@@ -60,7 +60,6 @@ sl:
error:
title: Prišlo je do napake
new:
- prompt_html: "%{client_name} želi dovoljenje za dostop do vašega računa. Gre za zunanji program. Če mu ne zaupate, mu ne dodelite teh pravic."
review_permissions: Preglej dovoljenja
title: Potrebna je odobritev
show:
diff --git a/config/locales/doorkeeper.sq.yml b/config/locales/doorkeeper.sq.yml
index 651f90b3b4..1fd9000aa2 100644
--- a/config/locales/doorkeeper.sq.yml
+++ b/config/locales/doorkeeper.sq.yml
@@ -60,7 +60,6 @@ sq:
error:
title: Ndodhi një gabim
new:
- prompt_html: "%{client_name} do të donte leje të hyjë në llogarinë tuaj. Është një aplikacion palësh të treta. Nëse s’i zini besë, atëherë s’duhet ta autorizoni."
review_permissions: Shqyrtoni leje
title: Lypset autorizim
show:
diff --git a/config/locales/doorkeeper.sr-Latn.yml b/config/locales/doorkeeper.sr-Latn.yml
index 89e84344fd..bce2b1c083 100644
--- a/config/locales/doorkeeper.sr-Latn.yml
+++ b/config/locales/doorkeeper.sr-Latn.yml
@@ -60,7 +60,6 @@ sr-Latn:
error:
title: Dogodila se greška
new:
- prompt_html: "%{client_name} želi dozvolu za pristup tvom nalogu. U pitanju je aplikacija treće strane. Ako smatraš da nije pouzdana, ne bi trebalo da je ovlastiš."
review_permissions: Pregledaj dozvole
title: Potrebna autorizacija
show:
diff --git a/config/locales/doorkeeper.sr.yml b/config/locales/doorkeeper.sr.yml
index 63b9404784..b6ab6e61c0 100644
--- a/config/locales/doorkeeper.sr.yml
+++ b/config/locales/doorkeeper.sr.yml
@@ -60,7 +60,6 @@ sr:
error:
title: Догодила се грешка
new:
- prompt_html: "%{client_name} жели дозволу за приступ твом налогу. У питању је апликација треће стране. Ако сматраш да није поуздана, не би требало да је овластиш."
review_permissions: Прегледај дозволе
title: Потребна ауторизација
show:
diff --git a/config/locales/doorkeeper.sv.yml b/config/locales/doorkeeper.sv.yml
index 83927d1097..9f646fd3e4 100644
--- a/config/locales/doorkeeper.sv.yml
+++ b/config/locales/doorkeeper.sv.yml
@@ -60,7 +60,6 @@ sv:
error:
title: Ett fel har uppstått
new:
- prompt_html: "%{client_name} vill ha behörighet att komma åt ditt konto. Det är en applikation från tredje part. Du bör endast godkänna den om du litar på den."
review_permissions: Granska behörigheter
title: Godkännande krävs
show:
diff --git a/config/locales/doorkeeper.th.yml b/config/locales/doorkeeper.th.yml
index 3735386ba3..e7ed0ba8a3 100644
--- a/config/locales/doorkeeper.th.yml
+++ b/config/locales/doorkeeper.th.yml
@@ -60,7 +60,6 @@ th:
error:
title: เกิดข้อผิดพลาด
new:
- prompt_html: "%{client_name} ต้องการสิทธิอนุญาตเพื่อเข้าถึงบัญชีของคุณ แอปพลิเคชันเป็นแอปพลิเคชันจากบุคคลที่สาม หากคุณไม่เชื่อถือแอปพลิเคชัน คุณไม่ควรอนุญาตแอปพลิเคชัน"
review_permissions: ตรวจทานสิทธิอนุญาต
title: ต้องการการอนุญาต
show:
diff --git a/config/locales/doorkeeper.tr.yml b/config/locales/doorkeeper.tr.yml
index 41996d9603..f7f67564d2 100644
--- a/config/locales/doorkeeper.tr.yml
+++ b/config/locales/doorkeeper.tr.yml
@@ -60,7 +60,7 @@ tr:
error:
title: Bir hata oluştu
new:
- prompt_html: "%{client_name} hesabınıza erişme izni istiyor. Bu üçüncü taraf bir uygulamadır. Eğer güvenmiyorsanız, izin vermemelisiniz."
+ prompt_html: "%{client_name} hesabınıze erişmek için izin istiyor. Bu isteği sadece bu kaynağı tanıyor ve güveniyorsanız onaylayın."
review_permissions: İzinleri incele
title: İzin gerekli
show:
diff --git a/config/locales/doorkeeper.uk.yml b/config/locales/doorkeeper.uk.yml
index 55b91fd69d..1e18eaef9a 100644
--- a/config/locales/doorkeeper.uk.yml
+++ b/config/locales/doorkeeper.uk.yml
@@ -60,7 +60,7 @@ uk:
error:
title: Сталася помилка
new:
- prompt_html: "%{client_name} хоче отримати доступ до вашого облікового запису. Це сторонній застосунок. Якщо ви йому не довіряєте, не варто авторизувати його."
+ prompt_html: "%{client_name} хоче отримати дозвіл на доступ до вашого облікового запису. Схвалюйте цей запит, якщо ви впізнаєте це джерело і довіряєте йому."
review_permissions: Переглянути дозволи
title: Необхідна авторизація
show:
diff --git a/config/locales/doorkeeper.vi.yml b/config/locales/doorkeeper.vi.yml
index 5837961737..6687c0339d 100644
--- a/config/locales/doorkeeper.vi.yml
+++ b/config/locales/doorkeeper.vi.yml
@@ -60,7 +60,7 @@ vi:
error:
title: Một lỗi đã xảy ra
new:
- prompt_html: "%{client_name} yêu cầu truy cập tài khoản của bạn. Đây là ứng dụng của bên thứ ba. Nếu không tin tưởng, đừng cho phép nó."
+ prompt_html: "%{client_name} cần được bạn cho phép truy cập vào tài khoản. Cho phép nếu bạn tin tưởng ứng dụng này."
review_permissions: Quyền truy cập
title: Yêu cầu truy cập
show:
@@ -71,7 +71,7 @@ vi:
confirmations:
revoke: Bạn có chắc không?
index:
- authorized_at: Cho phép %{date}
+ authorized_at: Cho phép vào %{date}
description_html: Đây là những ứng dụng có thể truy cập tài khoản của bạn bằng API. Nếu có ứng dụng bạn không nhận ra ở đây hoặc ứng dụng hoạt động sai, bạn có thể thu hồi quyền truy cập của ứng dụng đó.
last_used_at: Dùng lần cuối %{date}
never_used: Chưa dùng
@@ -151,7 +151,7 @@ vi:
scopes:
admin:read: đọc mọi dữ liệu trên máy chủ
admin:read:accounts: đọc thông tin nhạy cảm của tất cả các tài khoản
- admin:read:canonical_email_blocks: đọc thông tin nhạy cảm của tất cả các khối email chuẩn
+ admin:read:canonical_email_blocks: đọc thông tin nhạy cảm của tất cả khối email chuẩn
admin:read:domain_allows: đọc thông tin nhạy cảm của tất cả các tên miền cho phép
admin:read:domain_blocks: đọc thông tin nhạy cảm của tất cả các tên miền chặn
admin:read:email_domain_blocks: đọc thông tin nhạy cảm của tất cả các miền email chặn
diff --git a/config/locales/doorkeeper.zh-CN.yml b/config/locales/doorkeeper.zh-CN.yml
index ee8c0cf13a..46253d01b3 100644
--- a/config/locales/doorkeeper.zh-CN.yml
+++ b/config/locales/doorkeeper.zh-CN.yml
@@ -60,7 +60,7 @@ zh-CN:
error:
title: 发生错误
new:
- prompt_html: "%{client_name} 希望得到访问你账号的许可。这是一个第三方应用。如果你不信任它,那么你不应该授权它。"
+ prompt_html: "%{client_name} 请求获得访问您账户的权限。 请在确保自己了解并信任此来源后再批准该请求。"
review_permissions: 检查权限
title: 需要授权
show:
diff --git a/config/locales/doorkeeper.zh-HK.yml b/config/locales/doorkeeper.zh-HK.yml
index 79629b12fe..4450cfc1a4 100644
--- a/config/locales/doorkeeper.zh-HK.yml
+++ b/config/locales/doorkeeper.zh-HK.yml
@@ -60,7 +60,6 @@ zh-HK:
error:
title: 發生錯誤
new:
- prompt_html: "%{client_name} 想得到存取你帳號的權限。這是一個第三方應用程式。如果你不信任它,請勿授權。"
review_permissions: 檢視權限
title: 需要用戶授權
show:
diff --git a/config/locales/doorkeeper.zh-TW.yml b/config/locales/doorkeeper.zh-TW.yml
index 2759f0a3d2..5af93e1e07 100644
--- a/config/locales/doorkeeper.zh-TW.yml
+++ b/config/locales/doorkeeper.zh-TW.yml
@@ -60,7 +60,7 @@ zh-TW:
error:
title: 發生錯誤
new:
- prompt_html: "%{client_name} 欲請求存取您帳號之權限。這是一個第三方應用程式。若您不信任該應用程式,請不要授權。"
+ prompt_html: "%{client_name} 想要請求存取您帳號之權限。請僅於您所識別且信任此來源時允許請求。"
review_permissions: 檢視權限
title: 需要授權
show:
diff --git a/config/locales/el.yml b/config/locales/el.yml
index 6b1d8bc0e5..c119beec17 100644
--- a/config/locales/el.yml
+++ b/config/locales/el.yml
@@ -7,7 +7,6 @@ el:
hosted_on: Το Mastodon φιλοξενείται στο %{domain}
title: Σχετικά
accounts:
- follow: Ακολούθησε
followers:
one: Ακόλουθος
other: Ακόλουθοι
@@ -25,6 +24,8 @@ el:
admin:
account_actions:
action: Εκτέλεση ενέργειας
+ already_silenced: Αυτός ο λογαριασμός έχει ήδη περιοριστεί.
+ already_suspended: Αυτός ο λογαριασμός έχει ήδη ανασταλεί.
title: Εκτέλεση ενέργειας συντονισμού στον %{acct}
account_moderation_notes:
create: Άφησε σημείωση
@@ -46,6 +47,7 @@ el:
title: Αλλαγή email για %{username}
change_role:
changed_msg: Ο ρόλος άλλαξε επιτυχώς!
+ edit_roles: Διαχείριση ρόλων χρήστη
label: Αλλαγή ρόλου
no_role: Κανένας ρόλος
title: Αλλαγή ρόλου για %{username}
@@ -1129,7 +1131,6 @@ el:
crypto:
errors:
invalid_key: δεν είναι έγκυρο κλειδί Ed25519 ή Curve25519
- invalid_signature: δεν είναι έγκυρη υπογραφή Ed25519
date:
formats:
default: "%b %d, %Y"
@@ -1192,8 +1193,6 @@ el:
your_appeal_approved: Η έφεση σου έχει εγκριθεί
your_appeal_pending: Υπέβαλλες έφεση
your_appeal_rejected: Η έφεση σου απορρίφθηκε
- domain_validator:
- invalid_domain: δεν είναι έγκυρο όνομα τομέα
edit_profile:
basic_information: Βασικές πληροφορίες
hint_html: "Τροποποίησε τί βλέπουν άτομα στο δημόσιο προφίλ σου και δίπλα στις αναρτήσεις σου. Είναι πιο πιθανό κάποιος να σε ακολουθήσει πίσω και να αλληλεπιδράσουν μαζί σου αν έχεις ολοκληρωμένο προφίλ και εικόνα προφίλ."
@@ -1638,23 +1637,12 @@ el:
edited_at_html: Επεξεργάστηκε στις %{date}
errors:
in_reply_not_found: Η ανάρτηση στην οποία προσπαθείς να απαντήσεις δεν φαίνεται να υπάρχει.
- open_in_web: Άνοιγμα στο διαδίκτυο
over_character_limit: υπέρβαση μέγιστου ορίου %{max} χαρακτήρων
pin_errors:
direct: Αναρτήσεις που είναι ορατές μόνο στους αναφερόμενους χρήστες δεν μπορούν να καρφιτσωθούν
limit: Έχεις ήδη καρφιτσώσει το μέγιστο αριθμό επιτρεπτών αναρτήσεων
ownership: Δεν μπορείς να καρφιτσώσεις ανάρτηση κάποιου άλλου
reblog: Οι ενισχύσεις δεν καρφιτσώνονται
- poll:
- total_people:
- one: "%{count} άτομο"
- other: "%{count} άτομα"
- total_votes:
- one: "%{count} ψήφος"
- other: "%{count} ψήφοι"
- vote: Ψήφισε
- show_more: Δείξε περισσότερα
- show_thread: Εμφάνιση νήματος
title: '%{name}: "%{quote}"'
visibilities:
direct: Άμεση
diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml
index 61dd5d9b38..577978ce88 100644
--- a/config/locales/en-GB.yml
+++ b/config/locales/en-GB.yml
@@ -7,7 +7,6 @@ en-GB:
hosted_on: Mastodon hosted on %{domain}
title: About
accounts:
- follow: Follow
followers:
one: Follower
other: Followers
@@ -25,12 +24,15 @@ en-GB:
admin:
account_actions:
action: Perform action
+ already_silenced: This account has already been limited.
+ already_suspended: This account has already been suspended.
title: Perform moderation action on %{acct}
account_moderation_notes:
create: Leave note
created_msg: Moderation note successfully created!
destroyed_msg: Moderation note successfully destroyed!
accounts:
+ add_email_domain_block: Block email domain
approve: Approve
approved_msg: Successfully approved %{username}'s sign-up application
are_you_sure: Are you sure?
@@ -45,6 +47,7 @@ en-GB:
title: Change email for %{username}
change_role:
changed_msg: Role successfully changed!
+ edit_roles: Manage user roles
label: Change role
no_role: No role
title: Change role for %{username}
@@ -57,6 +60,7 @@ en-GB:
demote: Demote
destroyed_msg: "%{username}'s data is now queued to be deleted imminently"
disable: Freeze
+ disable_sign_in_token_auth: Disable email token authentication
disable_two_factor_authentication: Disable 2FA
disabled: Frozen
display_name: Display name
@@ -65,6 +69,7 @@ en-GB:
email: Email
email_status: Email status
enable: Unfreeze
+ enable_sign_in_token_auth: Enable email token authentication
enabled: Enabled
enabled_msg: Successfully unfroze %{username}'s account
followers: Followers
@@ -129,6 +134,7 @@ en-GB:
resubscribe: Resubscribe
role: Role
search: Search
+ search_same_email_domain: Other users with the same email domain
search_same_ip: Other users with the same IP
security: Security
security_measures:
@@ -169,21 +175,26 @@ en-GB:
approve_appeal: Approve Appeal
approve_user: Approve User
assigned_to_self_report: Assign Report
+ change_email_user: Change Email for User
change_role_user: Change Role of User
confirm_user: Confirm User
create_account_warning: Create Warning
create_announcement: Create Announcement
+ create_canonical_email_block: Create Email Block
create_custom_emoji: Create Custom Emoji
create_domain_allow: Create Domain Allow
create_domain_block: Create Domain Block
+ create_email_domain_block: Create Email Domain Block
create_ip_block: Create IP rule
create_unavailable_domain: Create Unavailable Domain
create_user_role: Create Role
demote_user: Demote User
destroy_announcement: Delete Announcement
+ destroy_canonical_email_block: Delete Email Block
destroy_custom_emoji: Delete Custom Emoji
destroy_domain_allow: Delete Domain Allow
destroy_domain_block: Delete Domain Block
+ destroy_email_domain_block: Delete Email Domain Block
destroy_instance: Purge Domain
destroy_ip_block: Delete IP rule
destroy_status: Delete Post
@@ -191,8 +202,10 @@ en-GB:
destroy_user_role: Destroy Role
disable_2fa_user: Disable 2FA
disable_custom_emoji: Disable Custom Emoji
+ disable_sign_in_token_auth_user: Disable Email Token Authentication for User
disable_user: Disable User
enable_custom_emoji: Enable Custom Emoji
+ enable_sign_in_token_auth_user: Enable Email Token Authentication for User
enable_user: Enable User
memorialize_account: Memorialise Account
promote_user: Promote User
@@ -222,20 +235,26 @@ en-GB:
approve_appeal_html: "%{name} approved moderation decision appeal from %{target}"
approve_user_html: "%{name} approved sign-up from %{target}"
assigned_to_self_report_html: "%{name} assigned report %{target} to themselves"
+ change_email_user_html: "%{name} changed the email address of user %{target}"
change_role_user_html: "%{name} changed role of %{target}"
+ confirm_user_html: "%{name} confirmed email address of user %{target}"
create_account_warning_html: "%{name} sent a warning to %{target}"
create_announcement_html: "%{name} created new announcement %{target}"
+ create_canonical_email_block_html: "%{name} blocked email with the hash %{target}"
create_custom_emoji_html: "%{name} uploaded new emoji %{target}"
create_domain_allow_html: "%{name} allowed federation with domain %{target}"
create_domain_block_html: "%{name} blocked domain %{target}"
+ create_email_domain_block_html: "%{name} blocked email domain %{target}"
create_ip_block_html: "%{name} created rule for IP %{target}"
create_unavailable_domain_html: "%{name} stopped delivery to domain %{target}"
create_user_role_html: "%{name} created %{target} role"
demote_user_html: "%{name} demoted user %{target}"
destroy_announcement_html: "%{name} deleted announcement %{target}"
+ destroy_canonical_email_block_html: "%{name} unblocked email with the hash %{target}"
destroy_custom_emoji_html: "%{name} deleted emoji %{target}"
destroy_domain_allow_html: "%{name} disallowed federation with domain %{target}"
destroy_domain_block_html: "%{name} unblocked domain %{target}"
+ destroy_email_domain_block_html: "%{name} unblocked email domain %{target}"
destroy_instance_html: "%{name} purged domain %{target}"
destroy_ip_block_html: "%{name} deleted rule for IP %{target}"
destroy_status_html: "%{name} removed post by %{target}"
@@ -243,8 +262,10 @@ en-GB:
destroy_user_role_html: "%{name} deleted %{target} role"
disable_2fa_user_html: "%{name} disabled two factor requirement for user %{target}"
disable_custom_emoji_html: "%{name} disabled emoji %{target}"
+ disable_sign_in_token_auth_user_html: "%{name} disabled email token authentication for %{target}"
disable_user_html: "%{name} disabled login for user %{target}"
enable_custom_emoji_html: "%{name} enabled emoji %{target}"
+ enable_sign_in_token_auth_user_html: "%{name} enabled email token authentication for %{target}"
enable_user_html: "%{name} enabled login for user %{target}"
memorialize_account_html: "%{name} turned %{target}'s account into a memoriam page"
promote_user_html: "%{name} promoted user %{target}"
@@ -252,6 +273,7 @@ en-GB:
reject_user_html: "%{name} rejected sign-up from %{target}"
remove_avatar_user_html: "%{name} removed %{target}'s avatar"
reopen_report_html: "%{name} reopened report %{target}"
+ resend_user_html: "%{name} resent confirmation email for %{target}"
reset_password_user_html: "%{name} reset password of user %{target}"
resolve_report_html: "%{name} resolved report %{target}"
sensitive_account_html: "%{name} marked %{target}'s media as sensitive"
@@ -412,6 +434,7 @@ en-GB:
attempts_over_week:
one: "%{count} attempt over the last week"
other: "%{count} sign-up attempts over the last week"
+ created_msg: Successfully blocked email domain
delete: Delete
dns:
types:
@@ -420,8 +443,12 @@ en-GB:
new:
create: Add domain
resolve: Resolve domain
+ title: Block new email domain
+ no_email_domain_block_selected: No email domain blocks were changed as none were selected
not_permitted: Not permitted
+ resolved_dns_records_hint_html: The domain name resolves to the following MX domains, which are ultimately responsible for accepting email. Blocking an MX domain will block sign-ups from any email address which uses the same MX domain, even if the visible domain name is different. Be careful not to block major email providers.
resolved_through_html: Resolved through %{domain}
+ title: Blocked email domains
export_domain_allows:
new:
title: Import domain allows
@@ -575,7 +602,9 @@ en-GB:
resolve_description_html: No action will be taken against the reported account, no strike recorded, and the report will be closed.
silence_description_html: The account will be visible only to those who already follow it or manually look it up, severely limiting its reach. Can always be reverted. Closes all reports against this account.
suspend_description_html: The account and all its contents will be inaccessible and eventually deleted, and interacting with it will be impossible. Reversible within 30 days. Closes all reports against this account.
+ actions_description_html: Decide which action to take to resolve this report. If you take a punitive action against the reported account, an email notification will be sent to them, except when the Spam category is selected.
actions_description_remote_html: Decide which action to take to resolve this report. This will only affect how your server communicates with this remote account and handle its content.
+ actions_no_posts: This report doesn't have any associated posts to delete
add_to_report: Add more to report
already_suspended_badges:
local: Already suspended on this server
@@ -639,6 +668,7 @@ en-GB:
delete_data_html: Delete @%{acct}'s profile and contents 30 days from now unless they get unsuspended in the meantime
preview_preamble_html: "@%{acct} will receive a warning with the following contents:"
record_strike_html: Record a strike against @%{acct} to help you escalate on future violations from this account
+ send_email_html: Send @%{acct} a warning email
warning_placeholder: Optional additional reasoning for the moderation action.
target_origin: Origin of reported account
title: Reports
@@ -678,6 +708,7 @@ en-GB:
manage_appeals: Manage Appeals
manage_appeals_description: Allows users to review appeals against moderation actions
manage_blocks: Manage Blocks
+ manage_blocks_description: Allows users to block email providers and IP addresses
manage_custom_emojis: Manage Custom Emojis
manage_custom_emojis_description: Allows users to manage custom emojis on the server
manage_federation: Manage Federation
@@ -695,6 +726,7 @@ en-GB:
manage_taxonomies: Manage Taxonomies
manage_taxonomies_description: Allows users to review trending content and update hashtag settings
manage_user_access: Manage User Access
+ manage_user_access_description: Allows users to disable other users' two-factor authentication, change their email address, and reset their password
manage_users: Manage Users
manage_users_description: Allows users to view other users' details and perform moderation actions against them
manage_webhooks: Manage Webhooks
@@ -769,6 +801,7 @@ en-GB:
destroyed_msg: Site upload successfully deleted!
software_updates:
critical_update: Critical — please update quickly
+ description: It is recommended to keep your Mastodon installation up to date to benefit from the latest fixes and features. Moreover, it is sometimes critical to update Mastodon in a timely manner to avoid security issues. For these reasons, Mastodon checks for updates every 30 minutes, and will notify you according to your email notification preferences.
documentation_link: Learn more
release_notes: Release notes
title: Available updates
@@ -855,16 +888,39 @@ en-GB:
action: Check here for more information
message_html: "Your object storage is misconfigured. The privacy of your users is at risk."
tags:
+ moderation:
+ not_trendable: Not trendable
+ not_usable: Not usable
+ pending_review: Pending review
+ review_requested: Review requested
+ reviewed: Reviewed
+ title: Status
+ trendable: Trendable
+ unreviewed: Unreviewed
+ usable: Usable
+ name: Name
+ newest: Newest
+ oldest: Oldest
+ open: View Publicly
+ reset: Reset
review: Review status
+ search: Search
+ title: Hashtags
updated_msg: Hashtag settings updated successfully
title: Administration
trends:
allow: Allow
approved: Approved
+ confirm_allow: Are you sure you want to allow selected tags?
+ confirm_disallow: Are you sure you want to disallow selected tags?
disallow: Disallow
links:
allow: Allow link
allow_provider: Allow publisher
+ confirm_allow: Are you sure you want to allow selected links?
+ confirm_allow_provider: Are you sure you want to allow selected providers?
+ confirm_disallow: Are you sure you want to disallow selected links?
+ confirm_disallow_provider: Are you sure you want to disallow selected providers?
description_html: These are links that are currently being shared a lot by accounts that your server sees posts from. It can help your users find out what's going on in the world. No links are displayed publicly until you approve the publisher. You can also allow or reject individual links.
disallow: Disallow link
disallow_provider: Disallow publisher
@@ -888,6 +944,10 @@ en-GB:
statuses:
allow: Allow post
allow_account: Allow author
+ confirm_allow: Are you sure you want to allow selected statuses?
+ confirm_allow_account: Are you sure you want to allow selected accounts?
+ confirm_disallow: Are you sure you want to disallow selected statuses?
+ confirm_disallow_account: Are you sure you want to disallow selected accounts?
description_html: These are posts that your server knows about that are currently being shared and favourited a lot at the moment. It can help your new and returning users to find more people to follow. No posts are displayed publicly until you approve the author, and the author allows their account to be suggested to others. You can also allow or reject individual posts.
disallow: Disallow post
disallow_account: Disallow author
@@ -920,6 +980,7 @@ en-GB:
used_by_over_week:
one: Used by one person over the last week
other: Used by %{count} people over the last week
+ title: Recommendations & Trends
trending: Trending
warning_presets:
add_new: Add new
@@ -1004,7 +1065,9 @@ en-GB:
guide_link_text: Everyone can contribute.
sensitive_content: Sensitive content
application_mailer:
+ notification_preferences: Change email preferences
salutation: "%{name},"
+ settings: 'Change email preferences: %{link}'
unsubscribe: Unsubscribe
view: 'View:'
view_profile: View profile
@@ -1024,6 +1087,7 @@ en-GB:
hint_html: Just one more thing! We need to confirm you're a human (this is so we can keep the spam out!). Solve the CAPTCHA below and click "Continue".
title: Security check
confirmations:
+ awaiting_review: Your email address is confirmed! The %{domain} staff is now reviewing your registration. You will receive an email if they approve your account!
awaiting_review_title: Your registration is being reviewed
clicking_this_link: clicking this link
login_link: log in
@@ -1031,6 +1095,7 @@ en-GB:
redirect_to_app_html: You should have been redirected to the %{app_name} app. If that did not happen, try %{clicking_this_link} or manually return to the app.
registration_complete: Your registration on %{domain} is now complete!
welcome_title: Welcome, %{name}!
+ wrong_email_hint: If that email address is not correct, you can change it in account settings.
delete_account: Delete account
delete_account_html: If you wish to delete your account, you can proceed here. You will be asked for confirmation.
description:
@@ -1051,6 +1116,7 @@ en-GB:
or_log_in_with: Or log in with
privacy_policy_agreement_html: I have read and agree to the privacy policy
progress:
+ confirm: Confirm email
details: Your details
review: Our review
rules: Accept rules
@@ -1072,8 +1138,10 @@ en-GB:
security: Security
set_new_password: Set new password
setup:
+ email_below_hint_html: Check your spam folder, or request another one. You can correct your email address if it's wrong.
email_settings_hint_html: Click the link we sent you to verify %{email}. We'll wait right here.
link_not_received: Didn't get a link?
+ new_confirmation_instructions_sent: You will receive a new email with the confirmation link in a few minutes!
title: Check your inbox
sign_in:
preamble_html: Log in with your %{domain} credentials. If your account is hosted on a different server, you will not be able to log in here.
@@ -1084,12 +1152,20 @@ en-GB:
title: Let's get you set up on %{domain}.
status:
account_status: Account status
+ confirming: Waiting for email confirmation to be completed.
functional: Your account is fully operational.
+ pending: Your application is pending review by our staff. This may take some time. You will receive an email if your application is approved.
redirecting_to: Your account is inactive because it is currently redirecting to %{acct}.
self_destruct: As %{domain} is closing down, you will only get limited access to your account.
view_strikes: View past strikes against your account
too_fast: Form submitted too fast, try again.
use_security_key: Use security key
+ author_attribution:
+ example_title: Sample text
+ hint_html: Control how you're credited when links are shared on Mastodon.
+ more_from_html: More from %{name}
+ s_blog: "%{name}'s Blog"
+ title: Author attribution
challenge:
confirm: Continue
hint_html: "Tip: We won't ask you for your password again for the next hour."
@@ -1098,7 +1174,6 @@ en-GB:
crypto:
errors:
invalid_key: is not a valid Ed25519 or Curve25519 key
- invalid_signature: is not a valid Ed25519 signature
date:
formats:
default: "%b %d, %Y"
@@ -1127,6 +1202,9 @@ en-GB:
before: 'Before proceeding, please read these notes carefully:'
caches: Content that has been cached by other servers may persist
data_removal: Your posts and other data will be permanently removed
+ email_change_html: You can change your email address without deleting your account
+ email_contact_html: If it still doesn't arrive, you can email %{email} for help
+ email_reconfirmation_html: If you are not receiving the confirmation email, you can request it again
irreversible: You will not be able to restore or reactivate your account
more_details_html: For more details, see the privacy policy.
username_available: Your username will become available again
@@ -1161,8 +1239,6 @@ en-GB:
your_appeal_approved: Your appeal has been approved
your_appeal_pending: You have submitted an appeal
your_appeal_rejected: Your appeal has been rejected
- domain_validator:
- invalid_domain: is not a valid domain name
edit_profile:
basic_information: Basic information
hint_html: "Customise what people see on your public profile and next to your posts. Other people are more likely to follow you back and interact with you when you have a filled out profile and a profile picture."
@@ -1359,6 +1435,7 @@ en-GB:
authentication_methods:
otp: two-factor authentication app
password: password
+ sign_in_token: email security code
webauthn: security keys
description_html: If you see activity that you don't recognise, consider changing your password and enabling two-factor authentication.
empty: No authentication history available
@@ -1369,10 +1446,21 @@ en-GB:
unsubscribe:
action: Yes, unsubscribe
complete: Unsubscribed
+ confirmation_html: Are you sure you want to unsubscribe from receiving %{type} for Mastodon on %{domain} to your email at %{email}? You can always re-subscribe from your email notification settings.
+ emails:
+ notification_emails:
+ favourite: favourite notification emails
+ follow: follow notification emails
+ follow_request: follow request emails
+ mention: mention notification emails
+ reblog: boost notification emails
+ resubscribe_html: If you've unsubscribed by mistake, you can re-subscribe from your email notification settings.
+ success_html: You'll no longer receive %{type} for Mastodon on %{domain} to your email at %{email}.
title: Unsubscribe
media_attachments:
validations:
images_and_video: Cannot attach a video to a post that already contains images
+ not_found: Media %{ids} not found or already attached to another post
not_ready: Cannot attach files that have not finished processing. Try again in a moment!
too_many: Cannot attach more than 4 files
migrations:
@@ -1449,6 +1537,8 @@ en-GB:
update:
subject: "%{name} edited a post"
notifications:
+ administration_emails: Admin email notifications
+ email_events: Events for email notifications
email_events_hint: 'Select events that you want to receive notifications for:'
number:
human:
@@ -1607,6 +1697,7 @@ en-GB:
import: Import
import_and_export: Import and export
migrate: Account migration
+ notifications: Email notifications
preferences: Preferences
profile: Profile
relationships: Follows and followers
@@ -1647,23 +1738,12 @@ en-GB:
edited_at_html: Edited %{date}
errors:
in_reply_not_found: The post you are trying to reply to does not appear to exist.
- open_in_web: Open in web
over_character_limit: character limit of %{max} exceeded
pin_errors:
direct: Posts that are only visible to mentioned users cannot be pinned
limit: You have already pinned the maximum number of posts
ownership: Someone else's post cannot be pinned
reblog: A boost cannot be pinned
- poll:
- total_people:
- one: "%{count} person"
- other: "%{count} people"
- total_votes:
- one: "%{count} vote"
- other: "%{count} votes"
- vote: Vote
- show_more: Show more
- show_thread: Show thread
title: '%{name}: "%{quote}"'
visibilities:
direct: Direct
@@ -1853,6 +1933,7 @@ en-GB:
invalid_otp_token: Invalid two-factor code
otp_lost_help_html: If you lost access to both, you may get in touch with %{email}
rate_limited: Too many authentication attempts, try again later.
+ seamless_external_login: You are logged in via an external service, so password and email settings are not available.
signed_in_as: 'Logged in as:'
verification:
extra_instructions_html: Tip: The link on your website can be invisible. The important part is rel="me"
which prevents impersonation on websites with user-generated content. You can even use a link
tag in the header of the page instead of a
, but the HTML must be accessible without executing JavaScript.
@@ -1861,6 +1942,7 @@ en-GB:
instructions_html: Copy and paste the code below into the HTML of your website. Then add the address of your website into one of the extra fields on your profile from the "Edit profile" tab and save changes.
verification: Verification
verified_links: Your verified links
+ website_verification: Website verification
webauthn_credentials:
add: Add new security key
create:
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 99dcb657f4..625f53f2e5 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -7,7 +7,6 @@ en:
hosted_on: Mastodon hosted on %{domain}
title: About
accounts:
- follow: Follow
followers:
one: Follower
other: Followers
@@ -25,6 +24,8 @@ en:
admin:
account_actions:
action: Perform action
+ already_silenced: This account has already been limited.
+ already_suspended: This account has already been suspended.
title: Perform moderation action on %{acct}
account_moderation_notes:
create: Leave note
@@ -46,6 +47,7 @@ en:
title: Change email for %{username}
change_role:
changed_msg: Role successfully changed!
+ edit_roles: Manage user roles
label: Change role
no_role: No role
title: Change role for %{username}
@@ -602,6 +604,7 @@ en:
suspend_description_html: The account and all its contents will be inaccessible and eventually deleted, and interacting with it will be impossible. Reversible within 30 days. Closes all reports against this account.
actions_description_html: Decide which action to take to resolve this report. If you take a punitive action against the reported account, an email notification will be sent to them, except when the Spam category is selected.
actions_description_remote_html: Decide which action to take to resolve this report. This will only affect how your server communicates with this remote account and handle its content.
+ actions_no_posts: This report doesn't have any associated posts to delete
add_to_report: Add more to report
already_suspended_badges:
local: Already suspended on this server
@@ -1157,6 +1160,12 @@ en:
view_strikes: View past strikes against your account
too_fast: Form submitted too fast, try again.
use_security_key: Use security key
+ author_attribution:
+ example_title: Sample text
+ hint_html: Control how you're credited when links are shared on Mastodon.
+ more_from_html: More from %{name}
+ s_blog: "%{name}'s Blog"
+ title: Author attribution
challenge:
confirm: Continue
hint_html: "Tip: We won't ask you for your password again for the next hour."
@@ -1165,7 +1174,6 @@ en:
crypto:
errors:
invalid_key: is not a valid Ed25519 or Curve25519 key
- invalid_signature: is not a valid Ed25519 signature
date:
formats:
default: "%b %d, %Y"
@@ -1231,8 +1239,6 @@ en:
your_appeal_approved: Your appeal has been approved
your_appeal_pending: You have submitted an appeal
your_appeal_rejected: Your appeal has been rejected
- domain_validator:
- invalid_domain: is not a valid domain name
edit_profile:
basic_information: Basic information
hint_html: "Customize what people see on your public profile and next to your posts. Other people are more likely to follow you back and interact with you when you have a filled out profile and a profile picture."
@@ -1454,6 +1460,7 @@ en:
media_attachments:
validations:
images_and_video: Cannot attach a video to a post that already contains images
+ not_found: Media %{ids} not found or already attached to another post
not_ready: Cannot attach files that have not finished processing. Try again in a moment!
too_many: Cannot attach more than 4 files
migrations:
@@ -1732,23 +1739,12 @@ en:
edited_at_html: Edited %{date}
errors:
in_reply_not_found: The post you are trying to reply to does not appear to exist.
- open_in_web: Open in web
over_character_limit: character limit of %{max} exceeded
pin_errors:
direct: Posts that are only visible to mentioned users cannot be pinned
limit: You have already pinned the maximum number of posts
ownership: Someone else's post cannot be pinned
reblog: A boost cannot be pinned
- poll:
- total_people:
- one: "%{count} person"
- other: "%{count} people"
- total_votes:
- one: "%{count} vote"
- other: "%{count} votes"
- vote: Vote
- show_more: Show more
- show_thread: Show thread
title: '%{name}: "%{quote}"'
visibilities:
direct: Direct
@@ -1947,6 +1943,7 @@ en:
instructions_html: Copy and paste the code below into the HTML of your website. Then add the address of your website into one of the extra fields on your profile from the "Edit profile" tab and save changes.
verification: Verification
verified_links: Your verified links
+ website_verification: Website verification
webauthn_credentials:
add: Add new security key
create:
diff --git a/config/locales/eo.yml b/config/locales/eo.yml
index 85aa3a1f31..2d03ce08a7 100644
--- a/config/locales/eo.yml
+++ b/config/locales/eo.yml
@@ -7,7 +7,6 @@ eo:
hosted_on: "%{domain} estas nodo de Mastodon"
title: Pri
accounts:
- follow: Sekvi
followers:
one: Sekvanto
other: Sekvantoj
@@ -25,12 +24,15 @@ eo:
admin:
account_actions:
action: Plenumi agon
+ already_silenced: Ĉi tiu konto jam estis limigita.
+ already_suspended: Ĉi tiu konto jam estis suspendita.
title: Plenumi kontrolan agon al %{acct}
account_moderation_notes:
create: Lasi noton
created_msg: Noto de moderigado sukcese kreita!
destroyed_msg: Noto de moderigado sukcese detruita!
accounts:
+ add_email_domain_block: Bloki retpoŝtan domajnon
approve: Aprobi
approved_msg: Sukcese aprobis aliĝ-peton de %{username}
are_you_sure: Ĉu vi certas?
@@ -45,6 +47,7 @@ eo:
title: Ŝanĝi retadreson por %{username}
change_role:
changed_msg: Rolo sukcese ŝanĝita!
+ edit_roles: Administri uzantrolojn
label: Ŝanĝi rolon
no_role: Neniu rolo
title: Ŝanĝi rolon por %{username}
@@ -818,16 +821,27 @@ eo:
action: Klaku ĉi tie por pliaj informoj
message_html: "Via objektostokado estas misagordita. La privateco de viaj uzantoj estas en risko."
tags:
+ moderation:
+ title: Stato
+ name: Nomo
+ newest: Plej novaj
+ oldest: Plej malnovaj
review: La statuso de la recenzo
+ search: Serĉi
+ title: Kradvortoj
updated_msg: Kradvorto agordoj ĝisdatigis sukcese
title: Administrado
trends:
allow: Permesi
approved: Aprobita
+ confirm_allow: Ĉu vi certas, ke vi volas permesi elektitajn etikedojn?
+ confirm_disallow: Ĉu vi certas, ke vi volas malpermesi elektitajn etikedojn?
disallow: Malpermesi
links:
allow: Permesi ligilon
allow_provider: Permesi publikiganto
+ confirm_allow: Ĉu vi certas, ke vi volas permesi elektitajn ligilojn?
+ confirm_disallow: Ĉu vi certas, ke vi volas malpermesi elektitajn ligilojn?
description_html: Ĉioj estas ligiloj kiuj nun diskonitajs multe de kontoj kiujn via servilo vidas. Ligiloj ne montritas publike se vi ne aprobis la publikiganton.
disallow: Malpermesi ligilon
disallow_provider: Malpermesi publikiganton
@@ -851,6 +865,8 @@ eo:
statuses:
allow: Permesi afiŝon
allow_account: Permesi aŭtoron
+ confirm_allow_account: Ĉu vi certas, ke vi volas permesi elektitajn kontojn?
+ confirm_disallow_account: Ĉu vi certas, ke vi volas malpermesi elektitajn kontojn?
description_html: Oni multe diskonigas kaj stelumas ĉi tiujn mesaĝojn nuntempe laŭ via servilo. Tio povas helpi novajn kaj revenantajn uzantojn trovi pli da homoj por sekvi. Mesaĝo estas montrita publike nur se vi aprobis la aŭtoron kaj se la aŭtoro aprobis ke ties konto estu proponita al aliaj. Vi ankaŭ povas permesi aŭ malakcepti specifajn mesaĝojn.
disallow: Malpermesi afiŝon
disallow_account: Malpermesi aŭtoron
@@ -929,6 +945,8 @@ eo:
body: "%{reporter} signalis %{target}"
body_remote: Iu de %{domain} signalis %{target}
subject: Nova signalo por %{instance} (#%{id})
+ new_software_updates:
+ body: Novaj versioj de Mastodon estis publikigitaj, vi eble volas ĝisdatigi!
new_trends:
body: 'La eroj bezonas kontrolon antau ol ili povas montritas publike:'
new_trending_links:
@@ -1034,6 +1052,9 @@ eo:
view_strikes: Vidi antauaj admonoj kontra via konto
too_fast: Formularo sendita tro rapide, klopodu denove.
use_security_key: Uzi sekurecan ŝlosilon
+ author_attribution:
+ more_from_html: Pli de %{name}
+ s_blog: Blogo de %{name}
challenge:
confirm: Daŭrigi
hint_html: "Konsileto: Ni ne demandos pri via pasvorto ĝis 1 horo."
@@ -1042,7 +1063,6 @@ eo:
crypto:
errors:
invalid_key: 올바른 Ed25519 혹은 Curve25519 키가 아닙니다
- invalid_signature: 올바른 Ed25519 시그니처가 아닙니다
date:
formats:
default: "%Y-%b-%d"
@@ -1105,8 +1125,6 @@ eo:
your_appeal_approved: Via apelacio aprobitas
your_appeal_pending: Vi sendis apelacion
your_appeal_rejected: Via apelacio malakceptitas
- domain_validator:
- invalid_domain: ne estas valida domajna nomo
edit_profile:
basic_information: Baza informo
other: Alia
@@ -1235,6 +1253,7 @@ eo:
states:
finished: Finita
unconfirmed: Nekonfirmita
+ status: Stato
success: Viaj datumoj estis sukcese alŝutitaj kaj estos traktitaj kiel planite
titles:
following: Importado de sekvaj kontoj
@@ -1555,23 +1574,12 @@ eo:
edited_at_html: Redaktis je %{date}
errors:
in_reply_not_found: Mesaĝo kiun vi provas respondi ŝajnas ne ekzisti.
- open_in_web: Malfermi retumile
over_character_limit: limo de %{max} signoj transpasita
pin_errors:
direct: Mesaĝoj kiu videbla nun al la uzantoj ne povas alpinglitis
limit: Vi jam atingis la maksimuman nombron de alpinglitaj mesaĝoj
ownership: Mesaĝo de iu alia ne povas esti alpinglita
reblog: Diskonigo ne povas esti alpinglita
- poll:
- total_people:
- one: "%{count} persono"
- other: "%{count} personoj"
- total_votes:
- one: "%{count} voĉdono"
- other: "%{count} voĉdonoj"
- vote: Voĉdoni
- show_more: Montri pli
- show_thread: Montri la mesaĝaron
title: "%{name}: “%{quote}”"
visibilities:
direct: Rekta
@@ -1704,7 +1712,13 @@ eo:
silence: Konto limigita
suspend: Konto suspendita
welcome:
+ apps_step: Elŝutu niajn oficialajn aplikaĵojn.
+ apps_title: Aplikaĵoj de Mastodon
+ edit_profile_action: Agordi
+ edit_profile_title: Agordi vian profilon
explanation: Jen kelkaj konsiloj por helpi vin komenci
+ feature_action: Lerni pli
+ follow_action: Sekvi
subject: Bonvenon en Mastodon
title: Bonvenon, %{name}!
users:
diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml
index 21836e79f1..9f1dc46c9d 100644
--- a/config/locales/es-AR.yml
+++ b/config/locales/es-AR.yml
@@ -7,7 +7,6 @@ es-AR:
hosted_on: Mastodon alojado en %{domain}
title: Información
accounts:
- follow: Seguir
followers:
one: Seguidor
other: Seguidores
@@ -25,6 +24,8 @@ es-AR:
admin:
account_actions:
action: Ejecutar acción
+ already_silenced: Esta cuenta ya fue limitada.
+ already_suspended: Esta cuenta ya ha sido suspendida.
title: Ejecutar acción de moderación en %{acct}
account_moderation_notes:
create: Dejar nota
@@ -46,6 +47,7 @@ es-AR:
title: Cambiar correo electrónico para %{username}
change_role:
changed_msg: "¡Rol cambiado exitosamente!"
+ edit_roles: Administrar roles de usuario
label: Cambiar rol
no_role: Sin rol
title: Cambiar rol para %{username}
@@ -602,6 +604,7 @@ es-AR:
suspend_description_html: La cuenta y todos sus contenidos serán inaccesibles y finalmente eliminados, e interactuar con ella será imposible. Revertible en 30 días. Esto cierra todas las denuncias contra esta cuenta.
actions_description_html: Decidí qué medidas tomar para resolver esta denuncia. Si tomás una acción punitiva contra la cuenta denunciada, se le enviará a dicha cuenta una notificación por correo electrónico, excepto cuando se seleccione la categoría Spam.
actions_description_remote_html: Decidí qué medidas tomar para resolver esta denuncia. Esto sólo afectará la forma en que tu servidor se comunica con esta cuenta remota y maneja su contenido.
+ actions_no_posts: Esta denuncia no tiene ningún mensaje asociado para eliminar
add_to_report: Agregar más a la denuncia
already_suspended_badges:
local: Ya suspendido en este servidor
@@ -898,6 +901,7 @@ es-AR:
name: Nombre
newest: Lo más reciente
oldest: Lo más antiguo
+ open: Ver públicamente
reset: Restablecer
review: Estado de revisión
search: Buscar
@@ -1156,6 +1160,12 @@ es-AR:
view_strikes: Ver incumplimientos pasados contra tu cuenta
too_fast: Formulario enviado demasiado rápido, probá de nuevo.
use_security_key: Usar la llave de seguridad
+ author_attribution:
+ example_title: Texto de ejemplo
+ hint_html: Controlá cómo se te da crédito cuando los enlaces son compartidos en Mastodon.
+ more_from_html: Más de %{name}
+ s_blog: Blog de %{name}
+ title: Atribución del autor
challenge:
confirm: Continuar
hint_html: "Dato: No volveremos a preguntarte por la contraseña durante la siguiente hora."
@@ -1164,7 +1174,6 @@ es-AR:
crypto:
errors:
invalid_key: no es una clave Ed25519 o Curve25519 válida
- invalid_signature: no es una firma Ed25519 válida
date:
formats:
default: "%d de %b de %Y"
@@ -1230,8 +1239,6 @@ es-AR:
your_appeal_approved: Se aprobó tu apelación
your_appeal_pending: Enviaste una apelación
your_appeal_rejected: Se rechazó tu apelación
- domain_validator:
- invalid_domain: no es un nombre de dominio válido
edit_profile:
basic_information: Información básica
hint_html: "Personalizá lo que la gente ve en tu perfil público y junto a tus publicaciones. Es más probable que otras personas te sigan e interactúen con vos cuando tengas un perfil completo y una foto de perfil."
@@ -1453,6 +1460,7 @@ es-AR:
media_attachments:
validations:
images_and_video: No se puede adjuntar un video a un mensaje que ya contenga imágenes
+ not_found: Medios %{ids} no encontrados o ya adjuntados a otro mensaje
not_ready: No se pueden adjuntar archivos que no se han terminado de procesar. ¡Intentá de nuevo en un rato!
too_many: No se pueden adjuntar más de 4 archivos
migrations:
@@ -1730,23 +1738,12 @@ es-AR:
edited_at_html: Editado el %{date}
errors:
in_reply_not_found: El mensaje al que intentás responder no existe.
- open_in_web: Abrir en la web
over_character_limit: se excedió el límite de %{max} caracteres
pin_errors:
direct: Los mensajes que sólo son visibles para los usuarios mencionados no pueden ser fijados
limit: Ya fijaste el número máximo de mensajes
ownership: No se puede fijar el mensaje de otra cuenta
reblog: No se puede fijar una adhesión
- poll:
- total_people:
- one: "%{count} persona"
- other: "%{count} personas"
- total_votes:
- one: "%{count} voto"
- other: "%{count} votos"
- vote: Votar
- show_more: Mostrar más
- show_thread: Mostrar hilo
title: '%{name}: "%{quote}"'
visibilities:
direct: Directo
@@ -1945,6 +1942,7 @@ es-AR:
instructions_html: Copiá y pegá el siguiente código en el HTML de tu sitio web. Luego, agregá la dirección de tu sitio web en uno de los campos extras de tu perfil desde la pestaña "Editar perfil" y guardá los cambios.
verification: Verificación
verified_links: Tus enlaces verificados
+ website_verification: Verificación del sitio web
webauthn_credentials:
add: Agregar nueva llave de seguridad
create:
diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml
index 61f4a6c167..0325757dca 100644
--- a/config/locales/es-MX.yml
+++ b/config/locales/es-MX.yml
@@ -7,7 +7,6 @@ es-MX:
hosted_on: Mastodon alojado en %{domain}
title: Acerca de
accounts:
- follow: Seguir
followers:
one: Seguidor
other: Seguidores
@@ -25,6 +24,8 @@ es-MX:
admin:
account_actions:
action: Realizar acción
+ already_silenced: Esta cuenta ya ha sido limitada.
+ already_suspended: Esta cuenta ya ha sido suspendida.
title: Moderar %{acct}
account_moderation_notes:
create: Crear
@@ -46,6 +47,7 @@ es-MX:
title: Cambiar el correo electrónico de %{username}
change_role:
changed_msg: Rol cambiado exitosamente!
+ edit_roles: Administrar roles de usuario
label: Cambiar de rol
no_role: Sin rol
title: Cambiar el rol para %{username}
@@ -173,7 +175,7 @@ es-MX:
approve_appeal: Aprobar apelación
approve_user: Aprobar Usuario
assigned_to_self_report: Asignar Reporte
- change_email_user: Cambiar Correo Electrónico del Usuario
+ change_email_user: Cambiar correo electrónico por usuario
change_role_user: Cambiar rol del usuario
confirm_user: Confirmar Usuario
create_account_warning: Crear Advertencia
@@ -200,10 +202,10 @@ es-MX:
destroy_user_role: Destruir Rol
disable_2fa_user: Deshabilitar 2FA
disable_custom_emoji: Deshabilitar Emoji Personalizado
- disable_sign_in_token_auth_user: Deshabilitar la Autenticación por Token de Correo Electrónico para el Usuario
+ disable_sign_in_token_auth_user: Deshabilitar la autenticación por token de correo electrónico para el usuario
disable_user: Deshabilitar Usuario
enable_custom_emoji: Habilitar Emoji Personalizado
- enable_sign_in_token_auth_user: Habilitar la Autenticación por Token de Correo Electrónico para el Usuario
+ enable_sign_in_token_auth_user: Habilitar la autenticación por token de correo electrónico para el usuario
enable_user: Habilitar Usuario
memorialize_account: Transformar en Cuenta Conmemorativa
promote_user: Promover Usuario
@@ -602,6 +604,7 @@ es-MX:
suspend_description_html: La cuenta y todos sus contenidos serán inaccesibles y eventualmente eliminados, e interactuar con ella será imposible. Reversible durante 30 días. Cierra todos los reportes contra esta cuenta.
actions_description_html: Decide qué medidas tomar para resolver esta denuncia. Si tomas una acción punitiva contra la cuenta denunciada, se le enviará a dicha cuenta una notificación por correo electrónico, excepto cuando se seleccione la categoría Spam.
actions_description_remote_html: Decide qué medidas tomar para resolver este reporte. Esto solo afectará a la forma en que tu servidor se comunica con esta cuenta remota y gestiona su contenido.
+ actions_no_posts: Este informe no tiene ningún mensaje asociado para eliminar
add_to_report: Añadir más al reporte
already_suspended_badges:
local: Ya suspendido en este servidor
@@ -758,7 +761,7 @@ es-MX:
desc_html: Esto se basa en scripts externos de hCaptcha, que pueden suponer una preocupación de seguridad y privacidad. Además, esto puede volver el proceso de registro significativamente menos accesible para algunas personas (especialmente con discapacidades). Por estas razones, por favor, considera medidas alternativas como el registro por aprobación manual o con invitación.
title: Solicita a los nuevos usuarios que resuelvan un CAPTCHA para confirmar su cuenta
content_retention:
- danger_zone: Zona peligrosa
+ danger_zone: Zona de peligro
preamble: Controlar cómo el contenido generado por el usuario se almacena en Mastodon.
title: Retención de contenido
default_noindex:
@@ -893,11 +896,12 @@ es-MX:
reviewed: Revisada
title: Estado
trendable: Puede ser tendencia
- unreviewed: Sin revisar
+ unreviewed: No revisado
usable: Disponible
name: Nombre
newest: Más reciente
oldest: Menos reciente
+ open: Ver públicamente
reset: Reiniciar
review: Estado de revisión
search: Buscar
@@ -907,8 +911,8 @@ es-MX:
trends:
allow: Permitir
approved: Aprobado
- confirm_allow: "¿Estás seguro de que deseas permitir la etiqueta seleccionada?"
- confirm_disallow: "¿Estás seguro de que deseas restringir la etiqueta seleccionada?"
+ confirm_allow: "¿Estás seguro de que deseas permitir las etiquetas seleccionadas?"
+ confirm_disallow: "¿Estás seguro de que deseas restringir las etiquetas seleccionadas?"
disallow: Rechazar
links:
allow: Permitir enlace
@@ -940,9 +944,9 @@ es-MX:
statuses:
allow: Permitir publicación
allow_account: Permitir autor
- confirm_allow: "¿Estás seguro de que deseas permitir los estados seleccionados?"
+ confirm_allow: "¿Estás seguro de que deseas permitir las publicaciones seleccionadas?"
confirm_allow_account: "¿Estás seguro de que deseas permitir las cuentas seleccionadas?"
- confirm_disallow: "¿Estás seguro de que deseas restringir los estados seleccionados?"
+ confirm_disallow: "¿Estás seguro de que deseas restringir las publicaciones seleccionadas?"
confirm_disallow_account: "¿Estás seguro de que deseas restringir las cuentas seleccionadas?"
description_html: Estos son publicaciones que su servidor conoce que están siendo compartidas y marcadas como favoritas mucho en este momento. Pueden ayudar a tus usuarios nuevos y retornantes a encontrar más gente a la que seguir. No hay mensajes que se muestren públicamente hasta que apruebes el autor y el autor permita que su cuenta sea sugerida a otros. También puedes permitir o rechazar mensajes individuales.
disallow: Rechazar publicación
@@ -976,7 +980,7 @@ es-MX:
used_by_over_week:
one: Usada por una persona durante la última semana
other: Usada por %{count} personas durante la última semana
- title: Recomendaciones y tendencias
+ title: Recomendaciones y Tendencias
trending: En tendencia
warning_presets:
add_new: Añadir nuevo
@@ -1148,7 +1152,7 @@ es-MX:
title: Crear cuenta de Mastodon en %{domain}.
status:
account_status: Estado de la cuenta
- confirming: Esperando confirmación de correo electrónico.
+ confirming: Esperando a que se complete la confirmación por correo electrónico.
functional: Tu cuenta está completamente operativa.
pending: Tu solicitud está pendiente de revisión por nuestro personal. Eso puede tardar un tiempo. Recibirás un correo electrónico cuando tu solicitud sea aprobada.
redirecting_to: Tu cuenta se encuentra inactiva porque está siendo redirigida a %{acct}.
@@ -1156,6 +1160,12 @@ es-MX:
view_strikes: Ver amonestaciones pasadas contra tu cuenta
too_fast: Formulario enviado demasiado rápido, inténtelo de nuevo.
use_security_key: Usar la clave de seguridad
+ author_attribution:
+ example_title: Texto de ejemplo
+ hint_html: Controla cómo se te dará atribución cuando se compartan enlaces en Mastodon.
+ more_from_html: Más de %{name}
+ s_blog: Blog de %{name}
+ title: Atribución del autor
challenge:
confirm: Continuar
hint_html: "Tip: No volveremos a preguntarte por la contraseña durante la siguiente hora."
@@ -1164,7 +1174,6 @@ es-MX:
crypto:
errors:
invalid_key: no es una clave Ed25519 o Curve25519 válida
- invalid_signature: no es una firma Ed25519 válida
date:
formats:
default: "%d %b %Y"
@@ -1194,7 +1203,7 @@ es-MX:
caches: El contenido que ha sido almacenado en caché por otros servidores puede persistir
data_removal: Tus publicaciones y el resto de datos se eliminarán definitivamente
email_change_html: Puedes cambiar tu dirección de correo electrónico sin eliminar tu cuenta
- email_contact_html: Si aún no te ha llegado, puedes escribir a %{email} para pedir ayuda
+ email_contact_html: Si todavía no te ha llegado, puedes escribir a %{email} para pedir ayuda
email_reconfirmation_html: Si no te ha llegado el correo de confirmación, puedes volver a solicitarlo
irreversible: No podrás restaurar ni reactivar tu cuenta
more_details_html: Para más detalles, ver la política de privacidad.
@@ -1230,8 +1239,6 @@ es-MX:
your_appeal_approved: Se aprobó tu apelación
your_appeal_pending: Has enviado una apelación
your_appeal_rejected: Tu apelación ha sido rechazada
- domain_validator:
- invalid_domain: no es un nombre de dominio válido
edit_profile:
basic_information: Información básica
hint_html: "Personaliza lo que la gente ve en tu perfil público junto a tus publicaciones. Es más probable que otras personas te sigan e interactúen contigo cuando completes tu perfil y agregues una foto."
@@ -1453,6 +1460,7 @@ es-MX:
media_attachments:
validations:
images_and_video: No se puede adjuntar un video a un estado que ya contenga imágenes
+ not_found: Archivos multimedia %{ids} no encontrados, o ya se encuentran adjuntos a otra publicación
not_ready: No se pueden adjuntar archivos que no se han terminado de procesar. ¡Inténtalo de nuevo en un momento!
too_many: No se pueden adjuntar más de 4 archivos
migrations:
@@ -1529,7 +1537,7 @@ es-MX:
update:
subject: "%{name} editó una publicación"
notifications:
- administration_emails: Notificaciones administrativas por correo
+ administration_emails: Notificaciones de administración por correo electrónico
email_events: Eventos para notificaciones por correo electrónico
email_events_hint: 'Selecciona los eventos para los que deseas recibir notificaciones:'
number:
@@ -1730,23 +1738,12 @@ es-MX:
edited_at_html: Editado %{date}
errors:
in_reply_not_found: El estado al que intentas responder no existe.
- open_in_web: Abrir en web
over_character_limit: Límite de caracteres de %{max} superado
pin_errors:
direct: Las publicaciones que son visibles solo para los usuarios mencionados no pueden fijarse
limit: Ya has fijado el número máximo de publicaciones
ownership: El toot de alguien más no puede fijarse
reblog: Un boost no puede fijarse
- poll:
- total_people:
- one: persona %{count}
- other: "%{count} gente"
- total_votes:
- one: "%{count} voto"
- other: "%{count} votos"
- vote: Vota
- show_more: Mostrar más
- show_thread: Mostrar discusión
title: "%{name}: «%{quote}»"
visibilities:
direct: Directa
@@ -1945,6 +1942,7 @@ es-MX:
instructions_html: Copia y pega el siguiente código en el HTML de tu sitio web. A continuación, añade la dirección de su sitio web en uno de los campos extra de tu perfil desde la pestaña "Editar perfil" y guarda los cambios.
verification: Verificación
verified_links: Tus links verificados
+ website_verification: Verificación del sitio web
webauthn_credentials:
add: Agregar nueva clave de seguridad
create:
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 883a953717..2815ada779 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -7,7 +7,6 @@ es:
hosted_on: Mastodon alojado en %{domain}
title: Acerca de
accounts:
- follow: Seguir
followers:
one: Seguidor
other: Seguidores
@@ -25,6 +24,8 @@ es:
admin:
account_actions:
action: Realizar acción
+ already_silenced: Esta cuenta ya ha sido limitada.
+ already_suspended: Esta cuenta ya ha sido suspendida.
title: Moderar %{acct}
account_moderation_notes:
create: Crear
@@ -46,6 +47,7 @@ es:
title: Cambiar el correo electrónico de %{username}
change_role:
changed_msg: "¡Rol cambiado con éxito!"
+ edit_roles: Administrar roles de usuario
label: Cambiar rol
no_role: Sin rol
title: Cambiar rol para %{username}
@@ -602,6 +604,7 @@ es:
suspend_description_html: La cuenta y todos sus contenidos serán inaccesibles y finalmente eliminados, e interactuar con ella será imposible. Reversible durante 30 días. Cierra todos los informes contra esta cuenta.
actions_description_html: Decide qué medidas tomar para resolver esta denuncia. Si tomas una acción punitiva contra la cuenta denunciada, se le enviará a dicha cuenta una notificación por correo electrónico, excepto cuando se seleccione la categoría Spam.
actions_description_remote_html: Decide qué medidas tomar para resolver este informe. Esto solo afectará a la forma en que tu servidor se comunica con esta cuenta remota y gestiona su contenido.
+ actions_no_posts: Este informe no tiene ningún mensaje asociado para eliminar
add_to_report: Añadir más al reporte
already_suspended_badges:
local: Ya suspendido en este servidor
@@ -898,6 +901,7 @@ es:
name: Nombre
newest: Más reciente
oldest: Menos reciente
+ open: Ver públicamente
reset: Reiniciar
review: Estado de revisión
search: Buscar
@@ -907,8 +911,8 @@ es:
trends:
allow: Permitir
approved: Aprobadas
- confirm_allow: "¿Estás seguro de que deseas permitir la etiqueta seleccionada?"
- confirm_disallow: "¿Estás seguro de que deseas restringir la etiqueta seleccionada?"
+ confirm_allow: "¿Estás seguro de que deseas permitir las etiquetas seleccionadas?"
+ confirm_disallow: "¿Estás seguro de que deseas restringir las etiquetas seleccionadas?"
disallow: No permitir
links:
allow: Permitir enlace
@@ -976,7 +980,7 @@ es:
used_by_over_week:
one: Usada por una persona durante la última semana
other: Usada por %{count} personas durante la última semana
- title: Recomendaciones y tendencias
+ title: Recomendaciones y Tendencias
trending: En tendencia
warning_presets:
add_new: Añadir nuevo
@@ -1090,7 +1094,7 @@ es:
proceed_to_login_html: Ahora puedes proceder a %{login_link}.
redirect_to_app_html: Serás redirigido a la aplicación %{app_name}. Si esto no sucede, prueba %{clicking_this_link} o regresa manualmente a la aplicación.
registration_complete: "¡Has completado tu registro en %{domain}!"
- welcome_title: "¡Bienvenido, %{name}!"
+ welcome_title: "¡Te damos la bienvenida, %{name}!"
wrong_email_hint: Si esa dirección de correo electrónico no es correcta, puedes cambiarla en la configuración de la cuenta.
delete_account: Borrar cuenta
delete_account_html: Si desea eliminar su cuenta, puede proceder aquí. Será pedido de una confirmación.
@@ -1156,6 +1160,12 @@ es:
view_strikes: Ver amonestaciones pasadas contra tu cuenta
too_fast: Formulario enviado demasiado rápido, inténtelo de nuevo.
use_security_key: Usar la clave de seguridad
+ author_attribution:
+ example_title: Texto de ejemplo
+ hint_html: Controla cómo se te dará atribución cuando se compartan enlaces en Mastodon.
+ more_from_html: Más de %{name}
+ s_blog: Blog de %{name}
+ title: Atribución del autor
challenge:
confirm: Continuar
hint_html: "Tip: No volveremos a preguntarte por la contraseña durante la siguiente hora."
@@ -1164,7 +1174,6 @@ es:
crypto:
errors:
invalid_key: no es una clave Ed25519 o Curve25519 válida
- invalid_signature: no es una firma Ed25519 válida
date:
formats:
default: "%d %b %Y"
@@ -1230,8 +1239,6 @@ es:
your_appeal_approved: Se aprobó tu apelación
your_appeal_pending: Has enviado una apelación
your_appeal_rejected: Tu apelación ha sido rechazada
- domain_validator:
- invalid_domain: no es un nombre de dominio válido
edit_profile:
basic_information: Información básica
hint_html: "Personaliza lo que la gente ve en tu perfil público junto a tus publicaciones. Es más probable que otras personas te sigan e interactúen contigo cuando completas tu perfil y foto."
@@ -1453,6 +1460,7 @@ es:
media_attachments:
validations:
images_and_video: No se puede adjuntar un video a unapublicación que ya contenga imágenes
+ not_found: Archivos multimedia %{ids} no encontrados, o ya se encuentran adjuntos a otra publicación
not_ready: No se pueden adjuntar archivos que no se han terminado de procesar. ¡Inténtalo de nuevo en un momento!
too_many: No se pueden adjuntar más de 4 archivos
migrations:
@@ -1730,23 +1738,12 @@ es:
edited_at_html: Editado %{date}
errors:
in_reply_not_found: La publicación a la que intentas responder no existe.
- open_in_web: Abrir en web
over_character_limit: Límite de caracteres de %{max} superado
pin_errors:
direct: Las publicaciones que son visibles solo para los usuarios mencionados no pueden fijarse
limit: Ya has fijado el número máximo de publicaciones
ownership: La publicación de otra persona no puede fijarse
reblog: Un boost no puede fijarse
- poll:
- total_people:
- one: "%{count} persona"
- other: "%{count} personas"
- total_votes:
- one: "%{count} voto"
- other: "%{count} votos"
- vote: Vota
- show_more: Mostrar más
- show_thread: Mostrar discusión
title: "%{name}: «%{quote}»"
visibilities:
direct: Directa
@@ -1912,7 +1909,7 @@ es:
follow_action: Seguir
follow_step: Seguir a personas interesantes es de lo que trata Mastodon.
follow_title: Personaliza tu línea de inicio
- follows_subtitle: Seguir cuentas conocidas
+ follows_subtitle: Sigue a cuentas conocidas
follows_title: A quién seguir
follows_view_more: Ver más personas para seguir
hashtags_recent_count:
@@ -1945,6 +1942,7 @@ es:
instructions_html: Copia y pega el siguiente código en el HTML de tu sitio web. A continuación, añade la dirección de su sitio web en uno de los campos extra de tu perfil desde la pestaña "Editar perfil" y guarda los cambios.
verification: Verificación
verified_links: Tus enlaces verificados
+ website_verification: Verificación del sitio web
webauthn_credentials:
add: Agregar nueva clave de seguridad
create:
diff --git a/config/locales/et.yml b/config/locales/et.yml
index 547cc8a643..60f98a471e 100644
--- a/config/locales/et.yml
+++ b/config/locales/et.yml
@@ -7,7 +7,6 @@ et:
hosted_on: Mastodon majutatud %{domain}-is
title: Teave
accounts:
- follow: Jälgi
followers:
one: Jälgija
other: Jälgijaid
@@ -25,12 +24,15 @@ et:
admin:
account_actions:
action: Täida tegevus
+ already_silenced: See konto on juba piiratud.
+ already_suspended: See konto on juba peatatud.
title: Rakenda moderaatori tegevus kasutajale %{acct}
account_moderation_notes:
create: Jäta teade
created_msg: Modereerimisteade edukalt koostatud!
destroyed_msg: Modereerimisteade edukalt kustutatud!
accounts:
+ add_email_domain_block: Blokeeri e-posti domeen
approve: Võta vastu
approved_msg: Kasutaja %{username} liitumisavaldus rahuldatud
are_you_sure: Oled kindel?
@@ -45,6 +47,7 @@ et:
title: Muuda e-postiaadressi kasutajale %{username}
change_role:
changed_msg: Roll on muudetud!
+ edit_roles: Halda kasutaja rolle
label: Muuda rolli
no_role: Roll puudub
title: "%{username} rolli muutmine"
@@ -57,6 +60,7 @@ et:
demote: Alanda
destroyed_msg: "%{username} andmed on nüüd lõpliku kustutamise ootel"
disable: Lukusta
+ disable_sign_in_token_auth: E-posti võtme abil autentimise väljalülitamine
disable_two_factor_authentication: Keela 2FA
disabled: Keelatud
display_name: Kuvanimi
@@ -65,6 +69,7 @@ et:
email: E-post
email_status: E-posti olek
enable: Luba
+ enable_sign_in_token_auth: Luba e-posti võtme abil autentimine
enabled: Lubatud
enabled_msg: Kasutaja %{username} konto taastatud
followers: Jälgijad
@@ -129,6 +134,7 @@ et:
resubscribe: Telli taas
role: Roll
search: Otsi
+ search_same_email_domain: Muud kasutajad sama e-posti domeeniga
search_same_ip: Teised kasutajad, kellel on sama IP
security: Turvalisus
security_measures:
@@ -169,21 +175,26 @@ et:
approve_appeal: Rahulda vaidlustus
approve_user: Kinnita kasutaja
assigned_to_self_report: Määras Teavituse
+ change_email_user: Muuda kasutaja e-posti
change_role_user: Muuda kasutaja rolli
confirm_user: Kasutaja kinnitatud
create_account_warning: Lisas hoiatuse
create_announcement: Lisas teadaande
+ create_canonical_email_block: Loo e-posti blokeering
create_custom_emoji: Lisas kohandatud emotikoni
create_domain_allow: Lisas lubatud domeeni
create_domain_block: Domeeni blokeerimine
+ create_email_domain_block: Loo e-posti domeeni blokeering
create_ip_block: IP-reegli lisamine
create_unavailable_domain: Kättesaamatu domeeni lisamine
create_user_role: Loo roll
demote_user: Alandas kasutaja
destroy_announcement: Eemaldas teadaande
+ destroy_canonical_email_block: Kustuta e-posti blokeering
destroy_custom_emoji: Eemaldas kohandatud emotikoni
destroy_domain_allow: Eemaldas lubatud domeeni
destroy_domain_block: Domeeniblokeeringu eemaldamine
+ destroy_email_domain_block: Kustuta e-posti domeeni blokeering
destroy_instance: Domeeni kustutamine
destroy_ip_block: IP-reegli kustutamine
destroy_status: Kustuta postitus
@@ -191,8 +202,10 @@ et:
destroy_user_role: Rolli kustutamine
disable_2fa_user: Keela 2FA
disable_custom_emoji: Keelas kohandatud emotikoni
+ disable_sign_in_token_auth_user: Keela e-posti võtme abil autentimine kasutajale
disable_user: Keelas kasutaja
enable_custom_emoji: Lubas kohandatud emotikoni
+ enable_sign_in_token_auth_user: Luba e-posti võtme abil autentimine kasutajale
enable_user: Lubas kasutaja
memorialize_account: Igaveselt lahkunuks märkimine
promote_user: Edendas kasutaja
@@ -215,26 +228,33 @@ et:
update_custom_emoji: Uuendas kohandatud emotikoni
update_domain_block: Uuenda domeenipiirangut
update_ip_block: IP-reegli uuendamine
+ update_report: Uuendamise raport
update_status: Uuenda postitust
update_user_role: Uuenda rolli
actions:
approve_appeal_html: "%{name} kiitis heaks modereerimise otsuse vaidlustuse %{target} poolt"
approve_user_html: "%{name} kiitis heaks registreerimise %{target} poolt"
assigned_to_self_report_html: "%{name} määras raporti %{target} endale"
+ change_email_user_html: "%{name} muutis kasutaja %{target} e-postiaadressi"
change_role_user_html: "%{name} muutis %{target} rolli"
+ confirm_user_html: "%{name} kinnitas kasutaja %{target} e-postiaadressi"
create_account_warning_html: "%{name} saatis %{target} hoiatuse"
create_announcement_html: "%{name} lõi uue teate %{target}"
+ create_canonical_email_block_html: "%{name} blokeeris e-posti räsiga %{target}"
create_custom_emoji_html: "%{name} laadis üles uue emotikoni %{target}"
create_domain_allow_html: "%{name} lubas föderatsiooni domeeniga %{target}"
create_domain_block_html: "%{name} keelas domeeni %{target}"
+ create_email_domain_block_html: "%{name} blokeeris e-posti domeeni %{target}"
create_ip_block_html: "%{name} lõi IP-aadressile %{target} reegli"
create_unavailable_domain_html: "%{name} lõpetas edastamise domeeni %{target}"
create_user_role_html: "%{name} lõi rolli %{target}"
demote_user_html: "%{name} alandas kasutajat %{target}"
destroy_announcement_html: "%{name} kustutas teadaande %{target}"
+ destroy_canonical_email_block_html: "%{name} eemaldas blokeeringu e-postilt räsiga %{target}"
destroy_custom_emoji_html: "%{name} kustutas emotikoni %{target}"
destroy_domain_allow_html: "%{name} keelas föderatsiooni domeeniga %{target}"
destroy_domain_block_html: "%{name} lubas domeeni %{target}"
+ destroy_email_domain_block_html: "%{name} eemaldas blokeeringu e-posti domeenilt %{target}"
destroy_instance_html: "%{name} kustutas domeeni %{target}"
destroy_ip_block_html: "%{name} kustutas IP-aadressi %{target} reegli"
destroy_status_html: "%{name} kustutas %{target} postituse"
@@ -242,8 +262,10 @@ et:
destroy_user_role_html: "%{name} kustutas %{target} rolli"
disable_2fa_user_html: "%{name} eemaldas kasutaja %{target} kahe etapise nõude"
disable_custom_emoji_html: "%{name} keelas emotikooni %{target}"
+ disable_sign_in_token_auth_user_html: "%{name} keelas e-posti võtme abil autentimise %{target} jaoks"
disable_user_html: "%{name} keelas %{target} sisenemise"
enable_custom_emoji_html: "%{name} lubas emotikooni %{target}"
+ enable_sign_in_token_auth_user_html: "%{name} lubas e-posti võtme abil autentimise %{target} jaoks"
enable_user_html: "%{name} lubas %{target} sisenemise"
memorialize_account_html: "%{name} märkis %{target} igaveselt lahkunuks"
promote_user_html: "%{name} ülendas kasutajat %{target}"
@@ -251,6 +273,7 @@ et:
reject_user_html: "%{name} lükkas %{target} liitumissoovi tagasi"
remove_avatar_user_html: "%{name} eemaldas %{target} avatari"
reopen_report_html: "%{name} taasavas raporti %{target}"
+ resend_user_html: "%{name} lähtestas %{target} kinnituskirja e-posti"
reset_password_user_html: "%{name} lähtestas %{target} salasõna"
resolve_report_html: "%{name} lahendas raporti %{target}"
sensitive_account_html: "%{name} märkis %{target} meedia kui tundlik sisu"
@@ -411,6 +434,7 @@ et:
attempts_over_week:
one: "%{count} katse viimase nädala kestel"
other: "%{count} liitumiskatset viimase nädala kestel"
+ created_msg: E-posti domeen edukalt blokeeritud
delete: Kustuta
dns:
types:
@@ -419,8 +443,12 @@ et:
new:
create: Lisa domeen
resolve: Domeeni lahendamine
+ title: Blokeeri uus e-posti domeen
+ no_email_domain_block_selected: Ühtegi e-posti domeeni blokeeringut ei muudetud, kuna ühtegi ei valitud
not_permitted: Ei ole lubatud
+ resolved_dns_records_hint_html: Domeeninimi lahendatakse järgmistele MX-domeenidele, mis on lõppkokkuvõttes vastutavad e-kirjade vastuvõtmise eest. MX-domeeni blokeerimine blokeerib registreerimise mis tahes e-posti aadressilt, mis kasutab sama MX-domeeni, isegi kui nähtav domeeninimi on erinev. Ole ettevaatlik, et mitte blokeerida peamisi e-posti teenusepakkujaid.
resolved_through_html: Lahendatud %{domain} kaudu
+ title: Blokeeritud e-posti domeenid
export_domain_allows:
new:
title: Lubatud domeenide import
@@ -445,6 +473,9 @@ et:
title: Jälgimissoovitused
unsuppress: Taasta jälgimissoovitused
instances:
+ audit_log:
+ title: Viimatised auditi logid
+ view_all: Vaata täielikke auditi logisid
availability:
description_html:
one: Kui domeenile edastamine nurjub %{count} päeval, siis ei tehta enam edastamiskatseid, välja arvatud juhul, kui domeenilt võetakse vastu saadetis.
@@ -571,7 +602,9 @@ et:
resolve_description_html: Raporteeritud konto suhtes ei võeta midagi ette, juhtumit ei registreerita ja raport suletakse.
silence_description_html: Konto saab olema nähtav ainult senistele jälgijatele või otsestele pöördujatele, mõjutates avalikku levi. On tagasipööratav. Sulgeb kõik konto suhtes esitatud raportid.
suspend_description_html: See konto ja kogu selle sisu muutub kättesaamatuks ning kustub lõpuks ja igasugune suhtlus sellega muutub võimatuks. Tagasipööratav 30 päeva jooksul. Lõpetab kõik selle konto kohta esitatud kaebused.
+ actions_description_html: Otsusta, milliseid meetmeid selle raporti lahendamiseks võtta. Kui võtad raporteeritud konto suhtes karistusmeetme, saadetakse talle e-posti teade, välja arvatud juhul, kui valid kategooria Rämps.
actions_description_remote_html: Otsusta, mida teha selle raporti lahendamiseks. See mõjutab ainult seda, kuidas Sinu server selle kaugkontoga suhtleb ning selle sisu käsitleb.
+ actions_no_posts: Selle raportiga pole seotud ühtegi postitust, mida kustutada
add_to_report: Lisa raportile juurde
already_suspended_badges:
local: Juba kustutamisel selles serveris
@@ -612,6 +645,7 @@ et:
report: 'Teavitus #%{id}'
reported_account: Teavitatud kontost
reported_by: Teavitaja
+ reported_with_application: Raporteeritud rakendusega
resolved: Lahendatud
resolved_msg: Teavituse lahendamine õnnestus!
skip_to_actions: Otsuste juurde
@@ -634,6 +668,7 @@ et:
delete_data_html: Kustuta tänasest 30 päeva pärast kasutaja @%{acct} profiil ja sisu, kui vahepeal tema kontot ei taastata
preview_preamble_html: "@%{acct} saab järgmise sisuga hoiatuse:"
record_strike_html: Salvesta @%{acct} kohta juhtum, et aidata selle konto tulevaste rikkumiste puhul reageerida
+ send_email_html: Saada hoiatuskiri @%{acct}
warning_placeholder: Valikuline täiendav põhjendus modereerimisele.
target_origin: Raporteeritud konto päritolu
title: Teavitused
@@ -673,6 +708,7 @@ et:
manage_appeals: Vaidlustuste haldamine
manage_appeals_description: Lubab kasutajail läbi vaadata modereerimisotsuste vaidlustusi
manage_blocks: Keeldude haldamine
+ manage_blocks_description: Lubab kasutajatel blokeerida e-posti teenusepakkujaid ja IP-aadresse
manage_custom_emojis: Halda isetehtud emotikone
manage_custom_emojis_description: Lubab kasutajatel hallata serveris isetehtud emotikone
manage_federation: Halda födereerumist
@@ -690,6 +726,7 @@ et:
manage_taxonomies: Halda taksonoomiaid
manage_taxonomies_description: Luba kasutajatel populaarset sisu üle vaadata ning uuendada siltide sätteid
manage_user_access: Halda kasutajate ligipääsu
+ manage_user_access_description: Võimaldab kasutajatel keelata teiste kasutajate kaheastmelise autentimise, muuta oma e-posti aadressi ja lähtestada oma parooli
manage_users: Kasutajate haldamine
manage_users_description: Lubab kasutajail näha teiste kasutajate üksikasju ja teha nende suhtes modereerimisotsuseid
manage_webhooks: Halda webhook'e
@@ -764,6 +801,7 @@ et:
destroyed_msg: Üleslaetud fail edukalt kustutatud!
software_updates:
critical_update: Kriitiline — uuenda kiiresti
+ description: Soovitatav on hoida oma Mastodoni paigaldus ajakohasena, et saada kasu viimastest parandustest ja funktsioonidest. Lisaks sellele on mõnikord oluline Mastodoni õigeaegne uuendamine, et vältida turvaprobleeme. Neil põhjustel kontrollib Mastodon uuendusi iga 30 minuti järel ja teavitab vastavalt sinu e-posti teavitamise eelistustele.
documentation_link: Vaata lisa
release_notes: Väljalaskemärkused
title: Saadaval uuendused
@@ -850,16 +888,39 @@ et:
action: Klõpsa lisainfo saamiseks siia
message_html: "Objektihoidla on valesti seadistatud. Kasutajate privaatsus on ohustatud."
tags:
+ moderation:
+ not_trendable: Pole trendis
+ not_usable: Pole kasutatav
+ pending_review: Ootab läbivaatust
+ review_requested: Taodeldud läbivaatust
+ reviewed: Läbivaadatud
+ title: Olek
+ trendable: Trendil
+ unreviewed: Läbivaatamata
+ usable: Kasutatav
+ name: Nimi
+ newest: Uusim
+ oldest: Vanim
+ open: Vaata avalikult
+ reset: Lähtesta
review: Vaata olek üle
+ search: Otsi
+ title: Märksõnad
updated_msg: Sildi sätted edukalt uuendatud
title: Administreerimine
trends:
allow: Luba
approved: Kinnitatud
+ confirm_allow: Oled kindel, et soovid valitud sildid lubada?
+ confirm_disallow: Oled kindel, et soovid valitud sildid keelata?
disallow: Keela
links:
allow: Luba viit
allow_provider: Luba autor
+ confirm_allow: Oled kindel, et soovid valitud lingid lubada?
+ confirm_allow_provider: Oled kindel, et soovid valitud teenusepakkujad lubada?
+ confirm_disallow: Oled kindel, et soovid valitud lingid keelata?
+ confirm_disallow_provider: Oled kindel, et soovid valitud teenusepakkujad keelata?
description_html: Need on lingid, mida jagavad praegu paljud kontod, mille postitusi server näeb. See võib aidata kasutajatel teada saada, mis maailmas toimub. Ühtegi linki ei kuvata avalikult enne, kui avaldaja on heakskiidetud. Samuti saab üksikuid linke lubada või tagasi lükata.
disallow: Keela viit
disallow_provider: Keela autor
@@ -883,6 +944,10 @@ et:
statuses:
allow: Luba postitada
allow_account: Luba autor
+ confirm_allow: Oled kindel, et soovid valitud olekud lubada?
+ confirm_allow_account: Oled kindel, et soovid valitud kontod lubada?
+ confirm_disallow: Oled kindel, et soovid valitud olekud lubada?
+ confirm_disallow_account: Oled kindel, et soovid valitud kontod keelata?
description_html: Need on postitused, millest server teab ja mida praegu jagatakse ja mis on hetkel paljude lemmikud. See võib aidata uutel ja naasvatel kasutajatel leida rohkem inimesi, keda jälgida. Ühtegi postitust ei kuvata avalikult enne, kui autor on heaks kiidetud ja autor lubab oma kontot teistele soovitada. Samuti saab üksikuid postitusi lubada või tagasi lükata.
disallow: Ära luba postitada
disallow_account: Keela autor
@@ -915,6 +980,7 @@ et:
used_by_over_week:
one: Kasutatud ühe kasutaja pool viimase nädala jooksul
other: Kasutatud %{count} kasutaja poolt viimase nädala jooksul
+ title: Soovitused ja trendid
trending: Trendid
warning_presets:
add_new: Lisa uus
@@ -999,7 +1065,9 @@ et:
guide_link_text: Panustada võib igaüks!
sensitive_content: Tundlik sisu
application_mailer:
+ notification_preferences: Muuda e-posti eelistusi
salutation: "%{name}!"
+ settings: 'Muuda e-posti eelistusi: %{link}'
unsubscribe: Loobu tellimisest
view: 'Vaade:'
view_profile: Vaata profiili
@@ -1008,10 +1076,10 @@ et:
created: Rakenduse loomine õnnestus
destroyed: Rakenduse kustutamine õnnestus
logout: Logi välja
- regenerate_token: Loo uus access token
- token_regenerated: Access tokeni loomine õnnestus
+ regenerate_token: Loo uus ligipääsuvõti
+ token_regenerated: Ligipääsuvõtme loomine õnnestus
warning: Ole nende andmetega ettevaatlikud. Ära jaga neid kellegagi!
- your_token: Su juurdepääsutunnus
+ your_token: Su juurdepääsuvõti
auth:
apply_for_account: Konto taotluse esitamine
captcha_confirmation:
@@ -1019,6 +1087,7 @@ et:
hint_html: Üks asi veel! Me peame veenduma, et oled inimene (et me saaksime spämmi väljaspoole jätta!). Lahenda allpool olev CAPTCHA ja klõpsa "Jätka".
title: Turvalisuse kontroll
confirmations:
+ awaiting_review: Sinu e-posti aadress on kinnitatud! %{domain} meeskond vaatab praegu sinu registreeringut läbi. Saad e-kirja, kui nad konto heaks kiidavad!
awaiting_review_title: Su registreeringut vaadatakse läbi
clicking_this_link: klõpsates seda linki
login_link: logi sisse
@@ -1026,6 +1095,7 @@ et:
redirect_to_app_html: Sind oleks pidanud suunatama rakendusse %{app_name}. Kui seda ei juhtunud, proovi %{clicking_this_link} või naase käsitsi rakendusse.
registration_complete: Sinu registreering domeenil %{domain} on nüüd valmis!
welcome_title: Tere tulemast, %{name}!
+ wrong_email_hint: Kui see e-postiaadress pole korrektne, saad seda muuta konto seadetes.
delete_account: Konto kustutamine
delete_account_html: Kui soovid oma konto kustutada, siis jätka siit. Pead kustutamise eraldi kinnitama.
description:
@@ -1046,6 +1116,7 @@ et:
or_log_in_with: Või logi sisse koos
privacy_policy_agreement_html: Olen tutvunud isikuandmete kaitse põhimõtetega ja nõustun nendega
progress:
+ confirm: E-posti kinnitamine
details: Sinu üksikasjad
review: Meie ülevaatamine
rules: Nõustu reeglitega
@@ -1067,8 +1138,10 @@ et:
security: Turvalisus
set_new_password: Uue salasõna määramine
setup:
+ email_below_hint_html: Kontrolli rämpsposti kausta või taotle uut. Saad oma e-posti aadressi parandada, kui see on vale.
email_settings_hint_html: Klõpsa linki, mis saadeti sulle, et kinnitada %{email}. Seni me ootame.
link_not_received: Kas ei saanud linki?
+ new_confirmation_instructions_sent: Saad mõne minuti pärast uue kinnituslingiga e-kirja!
title: Kontrolli sisendkasti
sign_in:
preamble_html: Logi sisse oma %{domain} volitustega. Kui konto asub teises serveris, ei saa siin sisse logida.
@@ -1079,12 +1152,20 @@ et:
title: Loo konto serverisse %{domain}.
status:
account_status: Konto olek
+ confirming: E-posti kinnitamise ootamine.
functional: Konto on täies mahus kasutatav.
+ pending: Sinu taotlus ootab meie meeskonna läbivaatamist. See võib võtta aega. Kui taotlus on heaks kiidetud, saadetakse sulle e-kiri.
redirecting_to: See konto pole aktiivne, sest on suunatud aadressile %{acct}.
self_destruct: Kuna %{domain} on sulgemisel, saad oma kontole vaid piiratud ligipääsu.
view_strikes: Vaata enda eelnevaid juhtumeid
too_fast: Vorm esitatud liiga kiirelt, proovi uuesti.
use_security_key: Kasuta turvavõtit
+ author_attribution:
+ example_title: Näidistekst
+ hint_html: Määra, kuidas sind krediteeritakse, kui linke Mastodonis jagatakse.
+ more_from_html: Rohkem kasutajalt %{name}
+ s_blog: Kasutaja %{name} blogi
+ title: Autori tunnustamine
challenge:
confirm: Jätka
hint_html: "Nõuanne: Me ei küsi salasõna uuesti järgmise tunni jooksul."
@@ -1093,7 +1174,6 @@ et:
crypto:
errors:
invalid_key: ei ole õige Ed25519 ega Curve25519 võti
- invalid_signature: ei ole õige Ed25519 allkiri
date:
formats:
default: "%d. %b %Y"
@@ -1122,6 +1202,9 @@ et:
before: 'Veendu, et saad aru, mida toob plaanitav muudatus kaasa:'
caches: Teiste serverite poolt talletatud sisu võib jääda kättesaadavaks
data_removal: Sinu postitused ning kontoandmed kustutatakse jäädavalt
+ email_change_html: Saad muuta oma e-postiaadressi ilma oma kontot kustutamata
+ email_contact_html: Kui see ikkagi ei saabu, võid abi saamiseks kirjutada %{email}
+ email_reconfirmation_html: Kui sa ei saa kinnituskirja, saad taotleda seda uuesti
irreversible: Kustutatud kontot ei saa taastada ega uuesti aktiveerida
more_details_html: Konto kustutamise kohta loe täpsemalt isikuandmete kaitse põhimõtetest.
username_available: Kasutajanimi muutub uuesti kasutatavaks
@@ -1156,8 +1239,6 @@ et:
your_appeal_approved: Su vaidlustus on heakskiidetud
your_appeal_pending: Vaidlustus on esitatud
your_appeal_rejected: Vaidlustus on tagasi lükatud
- domain_validator:
- invalid_domain: ei ole sobiv domeeni nimi
edit_profile:
basic_information: Põhiinfo
hint_html: "Kohanda, mida inimesed näevad su avalikul profiilil ja postituste kõrval. Inimesed alustavad tõenäolisemalt sinu jälgimist ja interakteeruvad sinuga, kui sul on täidetud profiil ja profiilipilt."
@@ -1354,6 +1435,7 @@ et:
authentication_methods:
otp: kaheastmelise autentimise rakendus
password: salasõna
+ sign_in_token: e-posti turvvakood
webauthn: turvavõtmed
description_html: Kui paistab tundmatuid tegevusi, tuleks vahetada salasõna ja aktiveerida kaheastmeline autentimine.
empty: Autentimisajalugu pole saadaval
@@ -1364,10 +1446,21 @@ et:
unsubscribe:
action: Jah, lõpeta tellimine
complete: Tellimine lõpetatud
+ confirmation_html: Kas oled kindel, et soovid loobuda %{type} tellimisest oma e-postiaadressile %{email} Mastodonist kohas %{domain}? Saad alati uuesti tellida oma e-posti teavituste seadetest.
+ emails:
+ notification_emails:
+ favourite: lemmikuks märkimise teavituskirjade
+ follow: jälgimiste teavituskirjade
+ follow_request: jälgimistaotluste teavituskirjade
+ mention: mainimiste teavituskirjade
+ reblog: jagamiste teavituskirjade
+ resubscribe_html: Kui loobusid tellimisest ekslikult, saad uuesti tellida oma e-posti teavituste seadetest.
+ success_html: Sa ei saa enam %{type} teateid oma e-postile %{email} Mastodonist kohas %{domain}.
title: Loobu tellimisest
media_attachments:
validations:
images_and_video: Ei saa lisada video postitusele, milles on juba pildid
+ not_found: Meedia %{ids} pole leitav või juba teisele postitusele lisatud
not_ready: Ei saa lisada faile, mida hetkel töödeldakse. Proovi uuesti mõne hetke pärast!
too_many: Ei saa lisada rohkem, kui 4 faili
migrations:
@@ -1444,6 +1537,8 @@ et:
update:
subject: "%{name} muutis postitust"
notifications:
+ administration_emails: Admini e-postiteated
+ email_events: Sündmused e-postiteavituste jaoks
email_events_hint: 'Vali sündmused, mille kohta soovid teavitusi:'
number:
human:
@@ -1602,6 +1697,7 @@ et:
import: Impordi
import_and_export: Import / eksport
migrate: Konto kolimine
+ notifications: E-postiteated
preferences: Eelistused
profile: Profiil
relationships: Jälgitud ja jälgijad
@@ -1642,23 +1738,12 @@ et:
edited_at_html: Muudetud %{date}
errors:
in_reply_not_found: Postitus, millele üritad vastata, ei näi enam eksisteerivat.
- open_in_web: Ava veebis
over_character_limit: tähtmärkide limiit %{max} ületatud
pin_errors:
direct: Ei saa kinnitada postitusi, mis on nähtavad vaid mainitud kasutajatele
limit: Kinnitatud on juba maksimaalne arv postitusi
ownership: Kellegi teise postitust ei saa kinnitada
reblog: Jagamist ei saa kinnitada
- poll:
- total_people:
- one: "%{count} inimene"
- other: "%{count} inimest"
- total_votes:
- one: "%{count} hääl"
- other: "%{count} häält"
- vote: Hääleta
- show_more: Näita rohkem
- show_thread: Kuva lõim
title: '%{name}: "%{quote}"'
visibilities:
direct: Otsene
@@ -1850,6 +1935,7 @@ et:
invalid_otp_token: Vale kaheastmeline võti
otp_lost_help_html: Kui kaotasid ligipääsu mõlemale, saad võtta ühendust %{email}-iga
rate_limited: Liiga palju autentimise katseid, proovi hiljem uuesti.
+ seamless_external_login: Oled sisse logitud välise teenuse kaudu. Nii pole salasõna ja e-posti seaded saadaval.
signed_in_as: 'Sisse logitud kasutajana:'
verification:
extra_instructions_html: Soovitus: Sinu kodulehel olev link võib olla nähtamatu. Oluline osa on rel="me"
, mis väldib kasutaja loodud sisuga lehtedel libaisikustamist. Sa saad isegi kasutada lehe HEADER osas silti link
sildi a
asemel, kuid HTML peab olema kättesaadav ilma JavaScripti käivitamata.
@@ -1858,6 +1944,7 @@ et:
instructions_html: Kopeeri ja kleebi allpool olev kood oma lehe HTML lähtekoodi. Seejärel lisa oma kodulehe aadress profiili "Muuda profiili" taabi ühte lisavälja ning salvesta muudatused.
verification: Kinnitamine
verified_links: Sinu kontrollitud lingid
+ website_verification: Veebilehe kontrollimine
webauthn_credentials:
add: Uue turvavõtme lisamine
create:
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
index 5e7d4a7f05..7c7f995a71 100644
--- a/config/locales/eu.yml
+++ b/config/locales/eu.yml
@@ -7,7 +7,6 @@ eu:
hosted_on: Mastodon %{domain} domeinuan ostatatua
title: Honi buruz
accounts:
- follow: Jarraitu
followers:
one: Jarraitzaile
other: jarraitzaile
@@ -1092,7 +1091,6 @@ eu:
crypto:
errors:
invalid_key: ez da baliozko Ed25519 edo Curve25519 gakoa
- invalid_signature: ez da baliozko Ed25519 sinadura
date:
formats:
default: "%Y(e)ko %b %d"
@@ -1155,8 +1153,6 @@ eu:
your_appeal_approved: Zure apelazioa onartu da
your_appeal_pending: Apelazio bat bidali duzu
your_appeal_rejected: Zure apelazioa baztertu da
- domain_validator:
- invalid_domain: ez da domeinu izen baliogarria
edit_profile:
basic_information: Oinarrizko informazioa
hint_html: "Pertsonalizatu jendeak zer ikusi dezakeen zure profil publikoan eta zure bidalketen baitan. Segur aski, jende gehiagok jarraituko dizu eta interakzio gehiago izango dituzu profila osatuta baduzu, profil irudia eta guzti."
@@ -1641,23 +1637,12 @@ eu:
edited_at_html: Editatua %{date}
errors:
in_reply_not_found: Erantzuten saiatu zaren bidalketa antza ez da existitzen.
- open_in_web: Ireki web-ean
over_character_limit: "%{max}eko karaktere muga gaindituta"
pin_errors:
direct: Aipatutako erabiltzaileentzat soilik ikusgai dauden bidalketak ezin dira finkatu
limit: Gehienez finkatu daitekeen bidalketa kopurua finkatu duzu jada
ownership: Ezin duzu beste norbaiten bidalketa bat finkatu
reblog: Bultzada bat ezin da finkatu
- poll:
- total_people:
- one: pertsona %{count}
- other: "%{count} pertsona"
- total_votes:
- one: Boto %{count}
- other: "%{count} boto"
- vote: Bozkatu
- show_more: Erakutsi gehiago
- show_thread: Erakutsi haria
title: '%{name}: "%{quote}"'
visibilities:
direct: Zuzena
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index 42782da204..c2c22af4c4 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -7,7 +7,6 @@ fa:
hosted_on: ماستودون، میزبانیشده روی %{domain}
title: درباره
accounts:
- follow: پیگیری
followers:
one: پیگیر
other: پیگیر
@@ -25,12 +24,15 @@ fa:
admin:
account_actions:
action: انجامِ کنش
+ already_silenced: این جساب از پیش محدود شده.
+ already_suspended: این جساب از پیش معلّق شده.
title: انجام کنش مدیریتی روی %{acct}
account_moderation_notes:
create: افزودن یادداشت
created_msg: یادداشت مدیر با موفقیت ساخته شد!
destroyed_msg: یادداشت نظارتی با موفقیت نابود شد!
accounts:
+ add_email_domain_block: انسداد دامنهٔ رایانامه
approve: پذیرفتن
approved_msg: کارهٔ ثبتنام %{username} با موفقیت تأیید شد
are_you_sure: مطمئنید؟
@@ -45,6 +47,7 @@ fa:
title: تغییر رایانامه برای %{username}
change_role:
changed_msg: نقش با موفقیت تغییر کرد!
+ edit_roles: مدیریت نقشهای کاربر
label: تغییر نقش
no_role: بدون نقش
title: تغییر نقش برای %{username}
@@ -57,6 +60,7 @@ fa:
demote: تنزلدادن
destroyed_msg: دادههای %{username} در صف حدف قرار گرفتند
disable: از کار انداختن
+ disable_sign_in_token_auth: از کار انداختن تأیید هویت ژتون رایانامهای
disable_two_factor_authentication: از کار انداختن ورود دومرحلهای
disabled: از کار افتاده
display_name: نام نمایشی
@@ -65,6 +69,7 @@ fa:
email: رایانامه
email_status: وضعیت رایانامه
enable: به کار انداختن
+ enable_sign_in_token_auth: به کار انداختن تأیید هویت ژتون رایانامهای
enabled: به کار افتاده
enabled_msg: حساب %{username} با موفقیت به کار انداخته شد
followers: پیگیران
@@ -129,6 +134,7 @@ fa:
resubscribe: اشتراک دوباره
role: نقش
search: جستوجو
+ search_same_email_domain: دیگر کاربران با دامنهٔ رایانامهٔ یکسان
search_same_ip: دیگر کاربران با IP یکسان
security: امنیت
security_measures:
@@ -169,13 +175,16 @@ fa:
approve_appeal: پذیرش درخواست تجدیدنظر
approve_user: تایید کاربر
assigned_to_self_report: واگذاری گزارش
+ change_email_user: تغییر رایانامه برای کاربر
change_role_user: تغیر نقش کاربر
confirm_user: تأیید کاربر
create_account_warning: ایجاد هشدار
create_announcement: ایجاد اعلامیه
+ create_canonical_email_block: ایجاد انسداد رایانامه
create_custom_emoji: ایجاد اموجی سفارشی
create_domain_allow: ایجاد اجازهٔ دامنه
create_domain_block: ایجاد انسداد دامنه
+ create_email_domain_block: ایجاد انسداد دامنهٔ رایانامه
create_ip_block: ایجاد قاعدهٔ آیپی
create_unavailable_domain: ایجاد دامنهٔ ناموجود
create_user_role: ایجاد نقش
@@ -215,6 +224,7 @@ fa:
update_custom_emoji: بهروز رسانی اموجی سفارشی
update_domain_block: بهروزرسانی مسدودسازی دامنه
update_ip_block: بروزرسانی قاعدهٔ آیپی
+ update_report: بهروز رسانی گزارش
update_status: بهروز رسانی وضعیت
update_user_role: به روزرسانی نقش
actions:
@@ -251,6 +261,7 @@ fa:
reject_user_html: "%{name} ثبت نام %{target} را رد کرد"
remove_avatar_user_html: "%{name} تصویر نمایهٔ %{target} را حذف کرد"
reopen_report_html: "%{name} گزارش %{target} را دوباره به جریان انداخت"
+ resend_user_html: "%{name} رایانامهٔ تأیید برای %{target} را دوباره فرستاد"
reset_password_user_html: "%{name} گذرواژه کاربر %{target} را بازنشاند"
resolve_report_html: "%{name} گزارش %{target} را رفع کرد"
sensitive_account_html: "%{name} رسانهٔ %{target} را به عنوان حساس علامتگذاری کرد"
@@ -265,6 +276,7 @@ fa:
update_custom_emoji_html: "%{name} شکلک %{target} را بهروز کرد"
update_domain_block_html: "%{name} مسدودسازی دامنه را برای %{target} بهروزرسانی کرد"
update_ip_block_html: "%{name} قانون آیپی %{target} را تغییر داد"
+ update_report_html: "%{name} گزارش %{target} را بهروز کرد"
update_status_html: "%{name} نوشتهٔ %{target} را بهروز کرد"
update_user_role_html: "%{name} نقش %{target} را تغییر داد"
deleted_account: حساب حذف شد
@@ -272,6 +284,7 @@ fa:
filter_by_action: پالایش بر اساس کنش
filter_by_user: پالایش بر اساس کاربر
title: سیاههٔ بازرسی
+ unavailable_instance: "(نام دامنه ناموجود)"
announcements:
destroyed_msg: اعلامیه با موفقیت حذف شد!
edit:
@@ -406,6 +419,7 @@ fa:
attempts_over_week:
one: "%{count} تلاش در هفتهٔ گذشته"
other: "%{count} تلاش ورود در هفتهٔ گذشته"
+ created_msg: دامنهٔ رایانامه با موفقیت مسدود شد
delete: پاککردن
dns:
types:
@@ -414,7 +428,10 @@ fa:
new:
create: ساختن مسدودسازی
resolve: حل و فصل دامنه
+ title: مسدودسازی دامنهٔ رایانامهٔ جدید
+ no_email_domain_block_selected: هیچ انسداد دامنهٔ رایانامهای تغییر نکرد زیرا هیچکدامشان انتخاب نشده بودند
not_permitted: مجاز نیست
+ title: دامنههای رایانامهٔ مسدود شده
export_domain_allows:
new:
title: درونریزی اجازههای دامنه
@@ -587,6 +604,7 @@ fa:
target_origin: خاستگاه حساب گزارششده
title: گزارشها
unassign: پسگرفتن مسئولیت
+ unknown_action_msg: 'کنش ناشناخته: %{action}'
unresolved: حلنشده
updated_at: بهروز شد
view_profile: دیدن نمایه
@@ -626,6 +644,7 @@ fa:
manage_taxonomies: مدیریت طیقهبندیها
manage_user_access: مدیریت دسترسی کاربران
manage_users: مدیریت کاربران
+ manage_webhooks: مدیریت قلّابهای وب
view_dashboard: دیدن داشبورد
view_dashboard_description: اجازه به کاربران برای دسترسی به داشتبورد و سنجههای مختلف
view_devops: دواپس
@@ -644,6 +663,8 @@ fa:
appearance:
preamble: سفارشیسازی رابطس وب ماستودون.
title: ظاهر
+ branding:
+ title: ویژندگی
default_noindex:
title: درخواست خروج از اندیسگذاری پیشگزیدهٔ موتور جستوجو
discovery:
@@ -744,6 +765,16 @@ fa:
action: برای اطّلاعات بیشتر اینجا را بررسی کنید
message_html: "ذخیرهسازتان بد پیکربندی شده. محرمانگی کاربرانتان در خطر است."
tags:
+ moderation:
+ not_trendable: غیر قابل داغ شدن
+ not_usable: غير قابل استفاده
+ pending_review: بازبینی منتظر
+ review_requested: بازبینی درخواست شده
+ reviewed: بازبینی شده
+ title: وضعیت
+ trendable: قابل داغ شدن
+ unreviewed: بررسی نشده
+ usable: قابل استفاده
review: وضعیت بازبینی
updated_msg: تنظیمات برچسبها با موفقیت بهروز شد
title: مدیریت
@@ -754,15 +785,25 @@ fa:
links:
allow: اجازه به پیوند
allow_provider: اجازه به ناشر
+ confirm_disallow: مطمئنید که می خواهید پیوندهای گزیده را ممنوع کنید؟
+ confirm_disallow_provider: مطمئنید که می خواهید فراهم کنندههای گزیده را ممنوع کنید؟
disallow: اجازه ندادن به پیوند
disallow_provider: اجازه ندادن به ناشر
no_link_selected: هیچ پیوندی تغییر نکرد زیرا هیچکدام از آنها انتخاب نشده بودند
+ publishers:
+ no_publisher_selected: هیچ ناشری تغییر نکرد زیرا هیچکدام از آنها انتخاب نشده بودند
title: پیوندهای داغ
+ not_allowed_to_trend: اجازهٔ داغ شدن ندارد
pending_review: بازبینی منتظر
preview_card_providers:
title: ناشران
rejected: رد شده
statuses:
+ allow: اجازه به فرسته
+ allow_account: اجازه به نگارنده
+ disallow: ممنوع کردن فرسته
+ disallow_account: ممنوع کردن نگارنده
+ no_status_selected: هیچ فرستهٔ داغی تغییری نکرد زیرا هیچکدام از آنها انتخاب نشده بودند
title: فرستههای داغ
tags:
current_score: امتیاز کنونی %{score}
@@ -846,7 +887,9 @@ fa:
guide_link_text: همه میتوانند کمک کنند.
sensitive_content: محتوای حساس
application_mailer:
+ notification_preferences: تغییر ترجیحات رایانامه
salutation: "%{name}،"
+ settings: 'تغییر ترجیحات رایانامه: %{link}'
unsubscribe: لغو اشتراک
view: 'نمایش:'
view_profile: دیدن نمایه
@@ -864,6 +907,7 @@ fa:
captcha_confirmation:
title: بررسی های امنیتی
confirmations:
+ awaiting_review_title: ثبتنامتان دارد بررسی میشود
login_link: ورود
welcome_title: خوش آمدید، %{name}!
delete_account: پاککردن حساب
@@ -915,6 +959,10 @@ fa:
view_strikes: دیدن شکایتهای گذشته از حسابتان
too_fast: فرم با سرعت بسیار زیادی فرستاده شد، دوباره تلاش کنید.
use_security_key: استفاده از کلید امنیتی
+ author_attribution:
+ example_title: متن نمونه
+ more_from_html: بیشتر از %{name}
+ s_blog: بلاگ %{name}
challenge:
confirm: ادامه
hint_html: "نکته: ما در یک ساعت آینده گذرواژهتان را از شما نخواهیم پرسید."
@@ -923,7 +971,6 @@ fa:
crypto:
errors:
invalid_key: یک کلید معتبر Ed25519 یا Curve25519 نیست
- invalid_signature: یک امضای معتبر Ed25519 نیست
date:
formats:
default: "%d %b %Y"
@@ -986,8 +1033,6 @@ fa:
your_appeal_approved: درخواست تجدیدنظرتان پذیرفته شد
your_appeal_pending: شما یک درخواست تجدیدنظر فرستادید
your_appeal_rejected: درخواست تجدیدنظرتان رد شد
- domain_validator:
- invalid_domain: نام دامین معتبر نیست
edit_profile:
basic_information: اطلاعات پایه
hint_html: "شخصیسازی آن چه مردم روی نمایهٔ عمومیتان و کنار فرستههایتان میبینند. هنگامی که نمایهای کامل و یک تصویر نمایه داشته باشید، احتمال پیگیری متقابل و تعامل با شما بیشتر است."
@@ -1082,6 +1127,9 @@ fa:
none: هیچکدام
order_by: مرتبسازی
save_changes: ذخیرهٔ تغییرات
+ select_all_matching_items:
+ one: گزینش %{count} مورد مطابق با جستوجویتان.
+ other: گزینش %{count} مورد مطابق با جستوجویتان.
today: امروز
validation_errors:
one: یک چیزی هنوز درست نیست! لطفاً خطاهای زیر را ببینید
@@ -1090,6 +1138,7 @@ fa:
errors:
over_rows_processing_limit: دارای بیش از %{count} ردیف
too_large: حجم فایل خیلی بزرگ است
+ failures: شکستها
imported: وارد شد
modes:
merge: ادغام
@@ -1106,11 +1155,23 @@ fa:
status: وضعیت
success: دادههای شما با موفقیت بارگذاری شد و به زودی پردازش میشود
time_started: آغاز شده در
+ titles:
+ blocking: درون ریختن حسابهای مسدود
+ bookmarks: درون ریختن نشانکها
+ domain_blocking: درون ریختن دامنههای مسدود
+ following: درون ریختن حسابهای پیگرفته
+ lists: درون ریختن سیاههها
+ muting: درون ریختن حسابهای خموش
+ type: گونهٔ درونریزی
+ type_groups:
+ constructive: پیگیریها و نشانکها
+ destructive: انسدادها و خموشیها
types:
blocking: سیاههٔ انسداد
bookmarks: نشانکها
domain_blocking: سیاههٔ انسداد دامنه
following: سیاههٔ پیگیری
+ lists: سیاههها
muting: سیاههٔ خموشی
upload: بارگذاری
invites:
@@ -1143,6 +1204,7 @@ fa:
authentication_methods:
otp: کارهٔ تأیید هویت دوعاملی
password: گذرواژه
+ sign_in_token: کد امنیتی رایانامهای
webauthn: کلیدهای امنیتی
description_html: اگر فعالیتی میبینید که تشخیصش نمیدهید، تغییر گذرواژه و به کار انداختن تأیید هویت دوعاملی را در نظر داشته باشید.
empty: هیچ تاریخچهای از تأییدهویت موجود نیست
@@ -1318,6 +1380,8 @@ fa:
over_daily_limit: شما از حد مجاز %{limit} فرسته زمانبندیشده در آن روز فراتر رفتهاید
over_total_limit: شما از حد مجاز %{limit} فرسته زمانبندیشده فراتر رفتهاید
too_soon: زمان تعیینشده باید در آینده باشد
+ self_destruct:
+ title: این کارساز دارد بسته میشود
sessions:
activity: آخرین فعالیت
browser: مرورگر
@@ -1342,6 +1406,7 @@ fa:
unknown_browser: مرورگر ناشناخته
weibo: وبیو
current_session: نشست فعلی
+ date: تاریخ
description: "%{browser} روی %{platform}"
explanation: مرورگرهای زیر هماینک به حساب شما وارد شدهاند.
ip: آیپی
@@ -1378,6 +1443,7 @@ fa:
import: درونریزی
import_and_export: درونریزی و برونبری
migrate: انتقال حساب
+ notifications: آگاهیهای رایانامهای
preferences: ترجیحات
profile: نمایه
relationships: پیگیریها و پیگیران
@@ -1385,6 +1451,9 @@ fa:
strikes: شکایتهای مدیریتی
two_factor_authentication: ورود دومرحلهای
webauthn_authentication: کلیدهای امنیتی
+ severed_relationships:
+ download: بارگیری (%{count})
+ type: رویداد
statuses:
attached:
audio:
@@ -1406,23 +1475,12 @@ fa:
edited_at_html: ویراسته در %{date}
errors:
in_reply_not_found: به نظر نمیرسد وضعیتی که میخواهید به آن پاسخ دهید، وجود داشته باشد.
- open_in_web: گشودن در وب
over_character_limit: از حد مجاز %{max} حرف فراتر رفتید
pin_errors:
direct: فرستههایی که فقط برای کاربران اشاره شده نمایانند نمیتوانند سنجاق شوند
limit: از این بیشتر نمیشود نوشتههای ثابت داشت
ownership: نوشتههای دیگران را نمیتوان ثابت کرد
reblog: تقویت نمیتواند سنجاق شود
- poll:
- total_people:
- one: "%{count} نفر"
- other: "%{count} نفر"
- total_votes:
- one: "%{count} رأی"
- other: "%{count} رأی"
- vote: رأی
- show_more: نمایش
- show_thread: نمایش رشته
title: "%{name}: «%{quote}»"
visibilities:
direct: مستقیم
@@ -1534,7 +1592,16 @@ fa:
silence: حساب محدود شده است
suspend: حساب معلق شده است
welcome:
+ apps_android_action: گرفتن از پلی گوگل
+ apps_ios_action: بارگیری روی فروشگاه کاره
+ apps_step: بارگیری کارهٔ رسمیمان.
+ apps_title: کارههای ماستودون
+ edit_profile_action: شخصی سازی
explanation: نکتههایی که برای آغاز کار به شما کمک میکنند
+ follow_action: پیگیری
+ post_action: ایجاد
+ share_action: همرسانی
+ sign_in_action: ورود
subject: به ماستودون خوش آمدید
title: خوش آمدید، کاربر %{name}!
users:
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index 95190d8846..5df82bff9f 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -7,7 +7,6 @@ fi:
hosted_on: Mastodon palvelimella %{domain}
title: Tietoja
accounts:
- follow: Seuraa
followers:
one: seuraaja
other: seuraajaa
@@ -25,6 +24,8 @@ fi:
admin:
account_actions:
action: Suorita toimi
+ already_silenced: Tätä tiliä on jo rajoitettu.
+ already_suspended: Tämä tili on jo jäädytetty.
title: Suorita moderointitoimi käyttäjälle %{acct}
account_moderation_notes:
create: Jätä muistiinpano
@@ -46,6 +47,7 @@ fi:
title: Vaihda käyttäjän %{username} sähköposti-osoite
change_role:
changed_msg: Roolin vaihto onnistui!
+ edit_roles: Hallinnoi käyttäjien rooleja
label: Vaihda rooli
no_role: Ei roolia
title: Vaihda käyttäjän %{username} rooli
@@ -442,9 +444,9 @@ fi:
create: Lisää verkkotunnus
resolve: Selvitä verkkotunnus
title: Estä uusi sähköpostiverkkotunnus
- no_email_domain_block_selected: Sähköpostin verkkotunnuksia ei muutettu, koska yhtään ei ollut valittuna
+ no_email_domain_block_selected: Sähköpostiverkkotunnusten estoja ei muutettu, koska yhtäkään ei ollut valittuna
not_permitted: Ei sallittu
- resolved_dns_records_hint_html: Verkkotunnuksen nimi määräytyy seuraaviin MX-verkkotunnuksiin, jotka ovat viime kädessä vastuussa sähköpostin vastaanottamisesta. MX-verkkotunnuksen estäminen estää rekisteröitymisen mistä tahansa sähköpostiosoitteesta, joka käyttää samaa MX-verkkotunnusta, vaikka näkyvä verkkotunnuksen nimi olisikin erilainen. Varo estämästä suuria sähköpostin palveluntarjoajia.
+ resolved_dns_records_hint_html: Verkkotunnusnimi kytkeytyy seuraaviin MX-verkkotunnuksiin, jotka ovat viime kädessä vastuussa sähköpostin vastaanottamisesta. MX-verkkotunnuksen estäminen estää rekisteröitymisen mistä tahansa sähköpostiosoitteesta, joka käyttää samaa MX-verkkotunnusta, vaikka näkyvä verkkotunnuksen nimi olisikin erilainen. Varo estämästä suuria sähköpostipalvelujen tarjoajia.
resolved_through_html: Ratkaistu verkkotunnuksen %{domain} kautta
title: Estetyt sähköpostiverkkotunnukset
export_domain_allows:
@@ -600,8 +602,9 @@ fi:
resolve_description_html: Ilmoitettua tiliä kohtaan ei ryhdytä toimiin, varoitusta ei kirjata ja raportti suljetaan.
silence_description_html: Tili näkyy vain niille, jotka jo seuraavat sitä tai etsivät sen manuaalisesti, mikä rajoittaa merkittävästi sen tavoitettavuutta. Voidaan perua milloin vain. Sulkee kaikki tiliin kohdistuvat raportit.
suspend_description_html: Tili ja mikään sen sisältö eivät ole käytettävissä, ja lopulta ne poistetaan ja vuorovaikutus tilin kanssa on mahdotonta. Peruttavissa 30 päivän ajan. Sulkee kaikki tiliin kohdistuvat raportit.
- actions_description_html: Päätä, mihin toimiin ryhdyt tämän raportin ratkaisemiseksi. Jos ryhdyt rangaistustoimeen ilmoitettua tiliä kohtaan, hänelle lähetetään sähköposti-ilmoitus, paitsi jos Roskaposti-luokka on valittuna.
+ actions_description_html: Päätä, mihin toimiin ryhdyt tämän raportin ratkaisemiseksi. Jos ryhdyt rangaistustoimeen raportoitua tiliä kohtaan, hänelle lähetetään sähköpostitse ilmoitus asiasta, paitsi jos valittuna on Roskaposti-luokka.
actions_description_remote_html: Päätä, mihin toimiin ryhdyt tämän raportin ratkaisemiseksi. Tämä vaikuttaa vain siihen, miten sinun palvelimesi viestii tämän etätilin kanssa ja käsittelee sen sisältöä.
+ actions_no_posts: Tähän raporttiin ei liity poistettavia julkaisuja
add_to_report: Lisää raporttiin
already_suspended_badges:
local: Jäädytetty jo tällä palvelimella
@@ -1135,7 +1138,7 @@ fi:
security: Turvallisuus
set_new_password: Aseta uusi salasana
setup:
- email_below_hint_html: Tarkista roskapostikansiosi tai pyydä uusi viesti. Voit korjata sähköpostiosoitteesi, jos se oli väärin.
+ email_below_hint_html: Tarkista roskapostikansiosi tai pyydä uusi viesti. Voit korjata sähköpostiosoitteesi tarvittaessa.
email_settings_hint_html: Napsauta lähettämäämme linkkiä vahvistaaksesi osoitteen %{email}. Odotamme täällä.
link_not_received: Etkö saanut linkkiä?
new_confirmation_instructions_sent: Saat pian uuden vahvistuslinkin sisältävän sähköpostiviestin!
@@ -1157,6 +1160,12 @@ fi:
view_strikes: Näytä aiemmat tiliäsi koskevat varoitukset
too_fast: Lomake lähetettiin liian nopeasti, yritä uudelleen.
use_security_key: Käytä suojausavainta
+ author_attribution:
+ example_title: Esimerkkiteksti
+ hint_html: Määrää, kuinka tulet tunnustetuksi, kun Mastodonissa jaetaan linkkejä.
+ more_from_html: Lisää tekijältä %{name}
+ s_blog: Käyttäjän %{name} blogi
+ title: Tekijän tunnustus
challenge:
confirm: Jatka
hint_html: "Vihje: Emme pyydä sinulta salasanaa uudelleen seuraavan tunnin aikana."
@@ -1165,7 +1174,6 @@ fi:
crypto:
errors:
invalid_key: ei ole kelvollinen Ed25519- tai Curve25519-avain
- invalid_signature: ei ole kelvollinen Ed25519-allekirjoitus
date:
formats:
default: "%b %d, %Y"
@@ -1195,8 +1203,8 @@ fi:
caches: Muiden palvelinten välimuistiinsa tallentamaa sisältöä voi säilyä
data_removal: Julkaisusi ja muut tietosi poistetaan pysyvästi
email_change_html: Voit muuttaa sähköpostiosoitettasi poistamatta tiliäsi
- email_contact_html: Jos ei saavu perille, voit pyytää apua sähköpostilla %{email}
- email_reconfirmation_html: Jos et saa vahvistuksen sähköpostia, niin voit pyytää sitä uudelleen
+ email_contact_html: Jos viesti ei vieläkään saavu perille, voit pyytää apua sähköpostitse osoitteella %{email}
+ email_reconfirmation_html: Jos et saa vahvistussähköpostiviestiä, voit pyytää sitä uudelleen
irreversible: Et voi palauttaa tiliäsi etkä aktivoida sitä uudelleen
more_details_html: Tarkempia tietoja saat tietosuojakäytännöstämme.
username_available: Käyttäjänimesi tulee saataville uudelleen
@@ -1231,8 +1239,6 @@ fi:
your_appeal_approved: Valituksesi on hyväksytty
your_appeal_pending: Olet lähettänyt valituksen
your_appeal_rejected: Valituksesi on hylätty
- domain_validator:
- invalid_domain: ei ole kelvollinen verkkotunnus
edit_profile:
basic_information: Perustiedot
hint_html: "Mukauta, mitä ihmiset näkevät julkisessa profiilissasi ja julkaisujesi vieressä. Sinua seurataan takaisin ja kanssasi ollaan vuorovaikutuksessa todennäköisemmin, kun sinulla on täytetty profiili ja profiilikuva."
@@ -1454,6 +1460,7 @@ fi:
media_attachments:
validations:
images_and_video: Videota ei voi liittää tilapäivitykseen, jossa on jo kuvia
+ not_found: Mediaa %{ids} ei löytynyt, tai se on jo liitetty toiseen julkaisuun
not_ready: Ei voi liittää tiedostoja, joiden käsittely on kesken. Yritä hetken kuluttua uudelleen!
too_many: Tiedostoja voi liittää enintään 4
migrations:
@@ -1731,23 +1738,12 @@ fi:
edited_at_html: Muokattu %{date}
errors:
in_reply_not_found: Julkaisua, johon yrität vastata, ei näytä olevan olemassa.
- open_in_web: Avaa selaimessa
over_character_limit: merkkimäärän rajoitus %{max} ylitetty
pin_errors:
direct: Vain mainituille käyttäjille näkyviä julkaisuja ei voi kiinnittää
limit: Olet jo kiinnittänyt enimmäismäärän julkaisuja
ownership: Muiden julkaisuja ei voi kiinnittää
reblog: Tehostusta ei voi kiinnittää
- poll:
- total_people:
- one: "%{count} käyttäjä"
- other: "%{count} käyttäjää"
- total_votes:
- one: "%{count} ääni"
- other: "%{count} ääntä"
- vote: Äänestä
- show_more: Näytä lisää
- show_thread: Näytä ketju
title: "%{name}: ”%{quote}”"
visibilities:
direct: Suoraan
@@ -1946,6 +1942,7 @@ fi:
instructions_html: Kopioi ja liitä seuraava koodi verkkosivustosi HTML-lähdekoodiin. Lisää sitten verkkosivustosi osoite johonkin profiilisi lisäkentistä ”Muokkaa profiilia” -välilehdellä ja tallenna muutokset.
verification: Vahvistus
verified_links: Vahvistetut linkkisi
+ website_verification: Verkkosivuston vahvistus
webauthn_credentials:
add: Lisää uusi suojausavain
create:
diff --git a/config/locales/fo.yml b/config/locales/fo.yml
index b2309694b1..ce21aa3be7 100644
--- a/config/locales/fo.yml
+++ b/config/locales/fo.yml
@@ -7,7 +7,6 @@ fo:
hosted_on: Mastodon hýst á %{domain}
title: Um
accounts:
- follow: Fylg
followers:
one: Fylgjari
other: Fylgjarar
@@ -25,6 +24,8 @@ fo:
admin:
account_actions:
action: Frem atgerð
+ already_silenced: Hendan kontan er longu avmarkað.
+ already_suspended: Hendan kontan er longu ógildað.
title: Frem umsjónaratgerð á %{acct}
account_moderation_notes:
create: Skriva umsjónarviðmerking
@@ -46,6 +47,7 @@ fo:
title: Broyt teldupostin hjá %{username}
change_role:
changed_msg: Leiklutur broyttur!
+ edit_roles: Stýr brúkaraleiklutir
label: Broyt leiklut
no_role: Eingin leiklutur
title: Broyt leiklut hjá %{username}
@@ -602,6 +604,7 @@ fo:
suspend_description_html: Kontan og alt innihald hjá kontuni gerast óatkomulig og við tíðini strikaði, og tað verður ógjørligt at samvirka við henni. Kann angrast innan 30 dagar. Lukkar allar rapporteringar av hesi kontuni.
actions_description_html: Ger av hvør atgerð skal takast fyri at avgreiða hesa meldingina. Revsitiltøk móti meldaðu kontuni føra við sær, at ein teldupostfráboðan verður send teimum, undantikið tá Ruskpostur verður valdur.
actions_description_remote_html: Tak avgerð um hvat skal gerast fyri at avgreiða hesa rapporteringina. Hetta fer einans at ávirka, hvussu tín ambætari samskiftir við hesa fjarkontuna og hvussu hann handfer tilfar frá henni.
+ actions_no_posts: Hendan fráboðanin hevur ongar viðkomandi postar at strika
add_to_report: Legg meira afturat meldingini
already_suspended_badges:
local: Longu gjørt óvirkin á hesum ambætaranum
@@ -1157,6 +1160,12 @@ fo:
view_strikes: Vís eldri atsóknir móti tíni kontu
too_fast: Oyðublaðið innsent ov skjótt, royn aftur.
use_security_key: Brúka trygdarlykil
+ author_attribution:
+ example_title: Tekstadømi
+ hint_html: Kanna, hvussu tú verður viðurkend/ur, tá ið onnur deila slóðir á Mastodon.
+ more_from_html: Meiri frá %{name}
+ s_blog: Bloggurin hjá %{name}
+ title: Ískoyti høvundans
challenge:
confirm: Hald á
hint_html: "Góð ráð: vit spyrja teg ikki aftur um loyniorðið næsta tíman."
@@ -1165,7 +1174,6 @@ fo:
crypto:
errors:
invalid_key: er ikki ein gildur Ed25519 ella Curve25519 lykil
- invalid_signature: er ikki ein gildug Ed25519 undirskrift
date:
formats:
default: "%b %d, %Y"
@@ -1231,8 +1239,6 @@ fo:
your_appeal_approved: Kæra tín er góðkend
your_appeal_pending: Tú hevur kært
your_appeal_rejected: Kæra tín er vrakað
- domain_validator:
- invalid_domain: er ikki eitt loyvt økisnavn
edit_profile:
basic_information: Grundleggjandi upplýsingar
hint_html: "Tillaga tað, sum fólk síggja á tínum almenna vanga og við síðna av tínum postum. Sannlíkindini fyri, at onnur fylgja tær og virka saman við tær eru størri, tá tú hevur fylt út vangan og eina vangamynd."
@@ -1454,6 +1460,7 @@ fo:
media_attachments:
validations:
images_and_video: Kann ikki viðfesta sjónfílu til ein post, sum longu inniheldur myndir
+ not_found: Miðilin %{ids} ikki funnin ella longu knýttur at øðrum posti
not_ready: Kann ikki viðfesta fílur, sum ikki eru liðugt viðgjørdar. Roynd aftur um eina løtu!
too_many: Kann ikki viðfest fleiri enn 4 fílur
migrations:
@@ -1731,23 +1738,12 @@ fo:
edited_at_html: Rættað %{date}
errors:
in_reply_not_found: Posturin, sum tú roynir at svara, sýnist ikki at finnast.
- open_in_web: Lat upp á vevinum
over_character_limit: mesta tal av teknum, %{max}, rokkið
pin_errors:
direct: Postar, sum einans eru sjónligir hjá nevndum brúkarum, kunnu ikki festast
limit: Tú hevur longu fest loyvda talið av postum
ownership: Postar hjá øðrum kunnu ikki festast
reblog: Ein stimbran kann ikki festast
- poll:
- total_people:
- one: "%{count} fólk"
- other: "%{count} fólk"
- total_votes:
- one: "%{count} atkvøða"
- other: "%{count} atkvøður"
- vote: Atkvøð
- show_more: Vís meira
- show_thread: Vís tráð
title: '%{name}: "%{quote}"'
visibilities:
direct: Beinleiðis
@@ -1916,6 +1912,9 @@ fo:
follows_subtitle: Fylg vælkendar kontur
follows_title: Hvørji tú átti at fylgt
follows_view_more: Sí fleiri fólk at fylgja
+ hashtags_recent_count:
+ one: "%{people} fólk seinastu 2 dagarnar"
+ other: "%{people} fólk seinastu 2 dagarnar"
hashtags_subtitle: Kanna rákið seinastu 2 dagarnar
hashtags_title: Vælumtókt frámerki
hashtags_view_more: Sí fleiri vælumtókt frámerki
@@ -1943,6 +1942,7 @@ fo:
instructions_html: Avrita og innset koduna niðanfyri inn í HTML'ið á heimasíðuni hjá tær. Legg síðani adressuna á heimasíðuni hjá tær inn á eitt av eyka teigunum á vanganum hjá tær umvegis "Rætta vanga" teigin og goym broytingar.
verification: Váttan
verified_links: Tíni váttaðu leinki
+ website_verification: Heimasíðuváttan
webauthn_credentials:
add: Legg nýggjan trygdarlykil afturat
create:
diff --git a/config/locales/fr-CA.yml b/config/locales/fr-CA.yml
index 4542b24858..3f9252ffab 100644
--- a/config/locales/fr-CA.yml
+++ b/config/locales/fr-CA.yml
@@ -7,7 +7,6 @@ fr-CA:
hosted_on: Serveur Mastodon hébergé sur %{domain}
title: À propos
accounts:
- follow: Suivre
followers:
one: Abonné·e
other: Abonné·e·s
@@ -25,12 +24,15 @@ fr-CA:
admin:
account_actions:
action: Effectuer l'action
+ already_silenced: Ce compte a déjà été limité.
+ already_suspended: Ce compte est déjà suspendu.
title: Effectuer une action de modération sur %{acct}
account_moderation_notes:
create: Laisser une remarque
created_msg: Note de modération créée avec succès !
destroyed_msg: Note de modération supprimée avec succès !
accounts:
+ add_email_domain_block: Bloquer le domaine de messagerie
approve: Approuver
approved_msg: La demande d’inscription de %{username} a été approuvée avec succès
are_you_sure: Voulez-vous vraiment faire ça ?
@@ -45,6 +47,7 @@ fr-CA:
title: Modifier le courriel pour %{username}
change_role:
changed_msg: Rôle modifié avec succès !
+ edit_roles: Gérer les rôles d'utilisateur·ices
label: Modifier le rôle
no_role: Aucun rôle
title: Modifier le rôle de %{username}
@@ -57,6 +60,7 @@ fr-CA:
demote: Rétrograder
destroyed_msg: Les données de %{username} sont maintenant en file d’attente pour être supprimées imminemment
disable: Geler
+ disable_sign_in_token_auth: Désactiver le jeton d'authentification par e-mail
disable_two_factor_authentication: Désactiver l’authentification à deux facteurs
disabled: Gelé
display_name: Nom affiché
@@ -65,6 +69,7 @@ fr-CA:
email: Courriel
email_status: État du courriel
enable: Dégeler
+ enable_sign_in_token_auth: Activer le jeton d'authentification par e-mail
enabled: Activé
enabled_msg: Le compte de %{username} a été dégelé avec succès
followers: Abonné·e·s
@@ -129,6 +134,7 @@ fr-CA:
resubscribe: Se réabonner
role: Rôle
search: Rechercher
+ search_same_email_domain: Autres utilisateur·rice·s ayant le même domaine de messagerie
search_same_ip: Autres utilisateur·rice·s avec la même IP
security: Sécurité
security_measures:
@@ -169,21 +175,26 @@ fr-CA:
approve_appeal: Approuver l'appel
approve_user: Approuver l’utilisateur
assigned_to_self_report: Affecter le signalement
+ change_email_user: Modification de l’adresse de messagerie électronique pour l'utilisateur·ce
change_role_user: Changer le rôle de l’utilisateur·rice
confirm_user: Confirmer l’utilisateur
create_account_warning: Créer une alerte
create_announcement: Créer une annonce
+ create_canonical_email_block: Création d'un blocage de courrier électronique
create_custom_emoji: Créer des émojis personnalisés
create_domain_allow: Créer un domaine autorisé
create_domain_block: Créer un blocage de domaine
+ create_email_domain_block: Création d'un blocage de domaine de courrier électronique
create_ip_block: Créer une règle IP
create_unavailable_domain: Créer un domaine indisponible
create_user_role: Créer le rôle
demote_user: Rétrograder l’utilisateur·ice
destroy_announcement: Supprimer l’annonce
+ destroy_canonical_email_block: Supprimer le blocage de courriel
destroy_custom_emoji: Supprimer des émojis personnalisés
destroy_domain_allow: Supprimer le domaine autorisé
destroy_domain_block: Supprimer le blocage de domaine
+ destroy_email_domain_block: Supprimer le blocage de domaine de courriel
destroy_instance: Purge du domaine
destroy_ip_block: Supprimer la règle IP
destroy_status: Supprimer le message
@@ -191,8 +202,10 @@ fr-CA:
destroy_user_role: Détruire le rôle
disable_2fa_user: Désactiver l’A2F
disable_custom_emoji: Désactiver les émojis personnalisés
+ disable_sign_in_token_auth_user: Désactiver le jeton d'authentification par e-mail pour l'utilisateur
disable_user: Désactiver le compte
enable_custom_emoji: Activer les émojis personnalisées
+ enable_sign_in_token_auth_user: Activer le jeton d'authentification par e-mail pour l'utilisateur
enable_user: Activer l’utilisateur
memorialize_account: Ériger en mémorial
promote_user: Promouvoir l’utilisateur
@@ -215,26 +228,33 @@ fr-CA:
update_custom_emoji: Mettre à jour les émojis personnalisés
update_domain_block: Mettre à jour le blocage de domaine
update_ip_block: Mettre à jour la règle IP
+ update_report: Mettre à jour le rapport
update_status: Mettre à jour le message
update_user_role: Mettre à jour le rôle
actions:
approve_appeal_html: "%{name} a approuvé l'appel de la décision de modération émis par %{target}"
approve_user_html: "%{name} a approuvé l’inscription de %{target}"
assigned_to_self_report_html: "%{name} s’est assigné·e le signalement de %{target}"
+ change_email_user_html: "%{name} a changé l'adresse e-mail de l'utilisateur \n%{target}"
change_role_user_html: "%{name} a changé le rôle de %{target}"
+ confirm_user_html: "%{name} a confirmé l'adresse e-mail de l'utilisateur %{target}"
create_account_warning_html: "%{name} a envoyé un avertissement à %{target}"
create_announcement_html: "%{name} a créé une nouvelle annonce %{target}"
+ create_canonical_email_block_html: "%{name} a bloqué l'adresse email avec le hachage %{target}"
create_custom_emoji_html: "%{name} a téléversé un nouvel émoji %{target}"
create_domain_allow_html: "%{name} a autorisé la fédération avec le domaine %{target}"
create_domain_block_html: "%{name} a bloqué le domaine %{target}"
+ create_email_domain_block_html: "%{name} a bloqué le domaine d'e-mail %{target}"
create_ip_block_html: "%{name} a créé une règle pour l'IP %{target}"
create_unavailable_domain_html: "%{name} a arrêté la livraison vers le domaine %{target}"
create_user_role_html: "%{name} a créé le rôle %{target}"
demote_user_html: "%{name} a rétrogradé l'utilisateur·rice %{target}"
destroy_announcement_html: "%{name} a supprimé l'annonce %{target}"
+ destroy_canonical_email_block_html: "%{name} a débloqué l'adresse email avec le hachage %{target}"
destroy_custom_emoji_html: "%{name} a supprimé l'émoji %{target}"
destroy_domain_allow_html: "%{name} a rejeté la fédération avec le domaine %{target}"
destroy_domain_block_html: "%{name} a débloqué le domaine %{target}"
+ destroy_email_domain_block_html: "%{name} a débloqué le domaine d'e-mail %{target}"
destroy_instance_html: "%{name} a purgé le domaine %{target}"
destroy_ip_block_html: "%{name} a supprimé la règle pour l'IP %{target}"
destroy_status_html: "%{name} a supprimé le message de %{target}"
@@ -251,6 +271,7 @@ fr-CA:
reject_user_html: "%{name} a rejeté l’inscription de %{target}"
remove_avatar_user_html: "%{name} a supprimé l'avatar de %{target}"
reopen_report_html: "%{name} a rouvert le signalement %{target}"
+ resend_user_html: "%{name} a renvoyé l'e-mail de confirmation pour %{target}"
reset_password_user_html: "%{name} a réinitialisé le mot de passe de l'utilisateur·rice %{target}"
resolve_report_html: "%{name} a résolu le signalement %{target}"
sensitive_account_html: "%{name} a marqué le média de %{target} comme sensible"
@@ -265,6 +286,7 @@ fr-CA:
update_custom_emoji_html: "%{name} a mis à jour l'émoji %{target}"
update_domain_block_html: "%{name} a mis à jour le blocage de domaine pour %{target}"
update_ip_block_html: "%{name} a modifié la règle pour l'IP %{target}"
+ update_report_html: "%{name} a mis à jour le rapport de signalement %{target}"
update_status_html: "%{name} a mis à jour le message de %{target}"
update_user_role_html: "%{name} a changé le rôle %{target}"
deleted_account: compte supprimé
@@ -272,6 +294,7 @@ fr-CA:
filter_by_action: Filtrer par action
filter_by_user: Filtrer par utilisateur·ice
title: Journal d’audit
+ unavailable_instance: "(nom de domaine indisponible)"
announcements:
destroyed_msg: Annonce supprimée avec succès !
edit:
@@ -409,6 +432,7 @@ fr-CA:
attempts_over_week:
one: "%{count} tentative au cours de la dernière semaine"
other: "%{count} tentatives au cours de la dernière semaine"
+ created_msg: Domaine d'e-mail bloqué avec succès
delete: Supprimer
dns:
types:
@@ -417,8 +441,15 @@ fr-CA:
new:
create: Créer le blocage
resolve: Résoudre le domaine
+ title: Blocage d'un nouveau domaine de messagerie électronique
+ no_email_domain_block_selected: Aucun blocage de domaine de messagerie n'a été modifié comme aucun n'a été sélectionné
not_permitted: Non autorisé
+ resolved_dns_records_hint_html: |-
+ Le nom de domaine se réfère aux domaines MX suivants, qui sont à leur tour responsables de la réception des courriels.
+
+ Le blocage d'un domaine MX empêchera l'inscription depuis toute adresse électronique ayant recours au même domaine MX, et ce même si le nom de domaine visible est différent. Veillez à ne pas bloquer les principaux fournisseurs de services de messagerie.
resolved_through_html: Résolu par %{domain}
+ title: Domaines de messagerie électronique bloqués
export_domain_allows:
new:
title: Importer les autorisations de domaine
@@ -443,6 +474,9 @@ fr-CA:
title: Recommandations d'abonnement
unsuppress: Rétablir les recommandations d'abonnement
instances:
+ audit_log:
+ title: Journaux d'audit récents
+ view_all: Voir les journaux d'audit complets
availability:
description_html:
one: Si la livraison au domaine échoue pendant %{count} jour, aucune autre tentative de livraison ne sera faite à moins qu'une livraison depuis le domaine ne soit reçue.
@@ -569,7 +603,9 @@ fr-CA:
resolve_description_html: Aucune mesure ne sera prise contre le compte signalé, aucune sanction ne sera enregistrée et le sigalement sera clôturé.
silence_description_html: Le compte ne sera visible que par ceux qui le suivent déjà ou qui le recherchent manuellement, ce qui limite fortement sa portée. Cette action peut toujours être annulée. Cloture tous les signalements concernant ce compte.
suspend_description_html: Le compte et tous ses contenus seront inaccessibles et finalement supprimés, et il sera impossible d'interagir avec lui. Réversible dans les 30 jours. Cloture tous les signalements concernant ce compte.
+ actions_description_html: Décidez de l'action à entreprendre pour résoudre ce signalement. Si vous prenez une mesure punitive à l'encontre du compte signalé, une notification par courrier électronique lui sera envoyée, excepté lorsque la catégorie Spam est sélectionnée.
actions_description_remote_html: Décidez des mesures à prendre pour résoudre ce signalement. Cela n'affectera que la manière dont votre serveur communique avec ce compte distant et traite son contenu.
+ actions_no_posts: Ce signalement n'a pas de messages qui lui sont associés et qui devraient être supprimés
add_to_report: Ajouter davantage au rapport
already_suspended_badges:
local: Déjà suspendu sur ce serveur
@@ -610,6 +646,7 @@ fr-CA:
report: 'Signalement #%{id}'
reported_account: Compte signalé
reported_by: Signalé par
+ reported_with_application: Signalé avec l'application
resolved: Résolus
resolved_msg: Signalement résolu avec succès !
skip_to_actions: Passer aux actions
@@ -632,6 +669,7 @@ fr-CA:
delete_data_html: effacer le profil de @%{acct} et ses contenus dans 30 jours, à moins que la suspension du compte ne soit annulée entre temps
preview_preamble_html: "@%{acct} recevra un avertissement contenant les éléments suivants :"
record_strike_html: enregistrer une sanction contre @%{acct} pour vous aider à prendre des mesures supplémentaires en cas d'infractions futures de ce compte
+ send_email_html: Envoyer un courriel d'avertissement à @%{acct}
warning_placeholder: Arguments supplémentaires pour l'action de modération (facultatif).
target_origin: Origine du compte signalé
title: Signalements
@@ -671,6 +709,7 @@ fr-CA:
manage_appeals: Gérer les contestations
manage_appeals_description: Permet aux utilisateur⋅rice⋅s d'examiner les appels contre les actions de modération
manage_blocks: Gérer les blocages
+ manage_blocks_description: Permet aux utilisateur⋅rice⋅s de bloquer des fournisseurs de courriel et des adresses IP
manage_custom_emojis: Gérer les émojis personnalisés
manage_custom_emojis_description: Permet aux utilisateur⋅rice⋅s de gérer les émoticônes personnalisées sur le serveur
manage_federation: Gérer de la féderation
@@ -688,6 +727,7 @@ fr-CA:
manage_taxonomies: Gérer les taxonomies
manage_taxonomies_description: Permet aux utilisateur⋅rice⋅s d'examiner les contenus tendance et de mettre à jour les paramètres des hashtags
manage_user_access: Gérer l'accès utilisateur
+ manage_user_access_description: Permet aux utilisateur·rice·s de désactiver l'authentification à deux facteurs des autres utilisateur·rice·s, de modifier leur adresse électronique et de réinitialiser leur mot de passe
manage_users: Gérer les utilisateur·rice·s
manage_users_description: Permet aux utilisateur⋅rice⋅s de voir les détails des autres utilisateur⋅rice⋅s et d'effectuer des actions de modération en conséquence
manage_webhooks: Gérer les points d’ancrage web
@@ -722,6 +762,7 @@ fr-CA:
desc_html: Ceci se base sur des scripts externes de hCaptcha, ce qui peut engendrer des soucis de sécurité et de confidentialité. De plus, cela peut rendre l'inscription beaucoup moins accessible pour certaines personnes (surtout les personnes handicapées). Pour ces raisons, veuillez envisager des mesures alternatives telles que l'inscription par acceptation ou par invitation.
title: Obliger les nouveaux utilisateurs à résoudre un CAPTCHA pour vérifier leur compte
content_retention:
+ danger_zone: Zone de danger
preamble: Contrôle comment le contenu créé par les utilisateurs est enregistré et stocké dans Mastodon.
title: Rétention du contenu
default_noindex:
@@ -761,6 +802,7 @@ fr-CA:
destroyed_msg: Téléversement sur le site supprimé avec succès !
software_updates:
critical_update: Critique — veuillez mettre à jour au plus vite
+ description: Il est recommandé de maintenir votre installation de Mastodon à jour afin de bénéficier des derniers correctifs et fonctionnalités. Par ailleurs, il est parfois critique de mettre à jour Mastodon en temps voulu de manière à éviter les incidents relatifs à la sécurité. Pour ces raisons, Mastodon examine la disponibilté des mises à jour toutes les 30 minutes, et vous en avisera en fonction de vos préférences de notification par messagerie électronique.
documentation_link: En savoir plus
release_notes: Notes de mises à jour
title: Mises à jour disponibles
@@ -847,7 +889,21 @@ fr-CA:
action: Pour plus d'informations, cliquez ici
message_html: "Votre serveur web est mal configuré. La confidentialité de vos utilisateurs est en péril."
tags:
+ moderation:
+ not_trendable: Ne peut être en tendance
+ not_usable: Non utilisable
+ pending_review: En attente de traitement
+ review_requested: Révision requise
+ reviewed: Traité
+ title: État
+ trendable: Peut s'afficher dans les tendances
+ unreviewed: Non traité
+ usable: Utilisable
name: Nom
+ newest: Plus récents
+ oldest: Plus anciens
+ open: Afficher publiquement
+ reset: Réinitialiser
review: État du traitement
search: Recherche
title: Hashtags
@@ -856,10 +912,16 @@ fr-CA:
trends:
allow: Autoriser
approved: Approuvé
+ confirm_allow: Êtes-vous sûr de vouloir autoriser les hashtags sélectionnés ?
+ confirm_disallow: Êtes-vous sûr de vouloir interdire les hashtags sélectionnés ?
disallow: Interdire
links:
allow: Autoriser le lien
allow_provider: Autoriser l'éditeur
+ confirm_allow: Êtes-vous sûr de vouloir autoriser les liens sélectionnés ?
+ confirm_allow_provider: Êtes-vous sûr de vouloir autoriser les fournisseurs sélectionnés ?
+ confirm_disallow: Êtes-vous sûr de vouloir interdire les liens sélectionnés ?
+ confirm_disallow_provider: Êtes-vous sûr de vouloir interdire les fournisseurs sélectionnés ?
description_html: Ces liens sont actuellement énormément partagés par des comptes dont votre serveur voit les messages. Cela peut aider vos utilisateur⋅rice⋅s à découvrir ce qu'il se passe dans le monde. Aucun lien n'est publiquement affiché tant que vous n'avez pas approuvé le compte qui le publie. Vous pouvez également autoriser ou rejeter les liens individuellement.
disallow: Interdire le lien
disallow_provider: Interdire l'éditeur
@@ -883,6 +945,10 @@ fr-CA:
statuses:
allow: Autoriser le message
allow_account: Autoriser l'auteur·rice
+ confirm_allow: Êtes-vous sûr de vouloir autoriser les statuts sélectionnés ?
+ confirm_allow_account: Êtes-vous sûr de vouloir autoriser les comptes sélectionnés ?
+ confirm_disallow: Êtes-vous sûr de vouloir rejeter les statuts sélectionnés ?
+ confirm_disallow_account: Êtes-vous sûr de vouloir rejeter les comptes sélectionnés ?
description_html: Voici les messages dont votre serveur a connaissance qui sont beaucoup partagés et mis en favoris en ce moment. Cela peut aider vos utilisateur⋅rice⋅s, néophytes comme aguerri⋅e⋅s, à trouver plus de comptes à suivre. Aucun message n'est publiquement affiché tant que vous n'en avez pas approuvé l'auteur⋅rice, et seulement si icellui permet que son compte soit suggéré aux autres. Vous pouvez également autoriser ou rejeter les messages individuellement.
disallow: Proscrire le message
disallow_account: Proscrire l'auteur·rice
@@ -1000,7 +1066,9 @@ fr-CA:
guide_link_text: Tout le monde peut y contribuer.
sensitive_content: Contenu sensible
application_mailer:
+ notification_preferences: Modification des préférences de la messagerie
salutation: "%{name},"
+ settings: 'Modifier les préférences de la messagerie : %{link}'
unsubscribe: Se désabonner
view: 'Voir :'
view_profile: Voir le profil
@@ -1020,6 +1088,7 @@ fr-CA:
hint_html: Juste une autre chose! Nous avons besoin de confirmer que vous êtes un humain (pour que nous puissions empêcher les spams!). Résolvez le CAPTCHA ci-dessous et cliquez sur "Continuer".
title: Vérification de sécurité
confirmations:
+ awaiting_review: Votre adresse de messagerie est confirmée ! L'équipe de %{domain} est en train d'examiner votre inscription. Vous recevrez un e-mail si votre compte est approuvé !
awaiting_review_title: Votre inscription est en cours de validation
clicking_this_link: cliquer sur ce lien
login_link: vous connecter
@@ -1027,6 +1096,7 @@ fr-CA:
redirect_to_app_html: Vous auriez dû être redirigé vers l’application %{app_name}. Si cela ne s’est pas produit, essayez de %{clicking_this_link} ou de revenir manuellement à l’application.
registration_complete: Votre inscription sur %{domain} est désormais terminée !
welcome_title: Bienvenue, %{name} !
+ wrong_email_hint: Si cette adresse de messagerie est incorrecte, vous pouvez la modifier dans vos paramètres de compte.
delete_account: Supprimer le compte
delete_account_html: Si vous désirez supprimer votre compte, vous pouvez cliquer ici. Il vous sera demandé de confirmer cette action.
description:
@@ -1047,6 +1117,7 @@ fr-CA:
or_log_in_with: Ou authentifiez-vous avec
privacy_policy_agreement_html: J’ai lu et j’accepte la politique de confidentialité
progress:
+ confirm: Confirmation de l'adresse mail
details: Vos infos
review: Notre avis
rules: Accepter les règles
@@ -1068,6 +1139,7 @@ fr-CA:
security: Sécurité
set_new_password: Définir le nouveau mot de passe
setup:
+ email_below_hint_html: Consultez votre dossier de courrier indésirable ou demandez-en un autre. Vous pouvez corriger votre adresse e-mail si elle est incorrecte.
email_settings_hint_html: Cliquez sur le lien que nous vous avons envoyé pour vérifier %{email}. Nous vous attendrons ici.
link_not_received: Vous n'avez pas reçu de lien?
new_confirmation_instructions_sent: Vous allez recevoir un nouvel e-mail avec le lien de confirmation dans quelques minutes !
@@ -1081,6 +1153,7 @@ fr-CA:
title: Mettons les choses en place pour %{domain}.
status:
account_status: État du compte
+ confirming: En attente de la confirmation par courrier électronique.
functional: Votre compte est entièrement opérationnel.
pending: Votre demande est en attente d’examen par notre équipe. Cela peut prendre un certain temps. Vous recevrez un e-mail si votre demande est approuvée.
redirecting_to: Votre compte est inactif car il est actuellement redirigé vers %{acct}.
@@ -1088,6 +1161,12 @@ fr-CA:
view_strikes: Voir les sanctions précédemment appliquées à votre compte
too_fast: Formulaire envoyé trop rapidement, veuillez réessayer.
use_security_key: Utiliser la clé de sécurité
+ author_attribution:
+ example_title: Exemple de texte
+ hint_html: Déterminez la façon dont vous êtes crédité lorsque des liens sont partagés sur Mastodon.
+ more_from_html: Plus via %{name}
+ s_blog: Blog de %{name}
+ title: Attribution de l'auteur·e
challenge:
confirm: Continuer
hint_html: "Astuce : Nous ne vous demanderons plus votre mot de passe pour la prochaine heure."
@@ -1096,7 +1175,6 @@ fr-CA:
crypto:
errors:
invalid_key: n’est pas une clé Ed25519 ou Curve25519 valide
- invalid_signature: n’est pas une signature Ed25519 valide
date:
formats:
default: "%d %b %Y"
@@ -1126,6 +1204,8 @@ fr-CA:
caches: Le contenu mis en cache par d'autres serveurs peut persister
data_removal: Vos messages et autres données seront définitivement supprimés
email_change_html: Vous pouvez modifier votre adresse e-mail sans supprimer votre compte
+ email_contact_html: S'il ne vous est toujours pas parvenu, vous pouvez envoyer un message à %{email} pour obtenir de l'aide
+ email_reconfirmation_html: Dans le cas où vous n'auriez pas reçu l'email de confirmation, vous pouvez en réclamer un nouveau
irreversible: Vous ne pourrez pas restaurer ou réactiver votre compte
more_details_html: Pour plus de détails, voir la politique de confidentialité.
username_available: Votre nom d’utilisateur·rice sera à nouveau disponible
@@ -1160,8 +1240,6 @@ fr-CA:
your_appeal_approved: Votre appel a été approuvé
your_appeal_pending: Vous avez soumis un appel
your_appeal_rejected: Votre appel a été rejeté
- domain_validator:
- invalid_domain: n’est pas un nom de domaine valide
edit_profile:
basic_information: Informations de base
hint_html: "Personnalisez ce que les gens voient sur votre profil public et à côté de vos messages. Les autres personnes seront plus susceptibles de vous suivre et d’interagir avec vous lorsque vous avez un profil complet et une photo."
@@ -1369,10 +1447,20 @@ fr-CA:
unsubscribe:
action: Oui, me désabonner
complete: Désabonné·e
+ emails:
+ notification_emails:
+ favourite: e-mails de notifications de favoris
+ follow: e-mails de notifications d’abonnements
+ follow_request: e-mails de demandes d’abonnements
+ mention: e-mails de notifications de mentions
+ reblog: e-mails de notifications de partages
+ resubscribe_html: Si vous vous êtes désinscrit par erreur, vous pouvez vous réinscrire à partir de vos paramètres de notification par e-mail.
+ success_html: Vous ne recevrez plus de %{type} pour Mastodon sur %{domain} à votre adresse e-mail à %{email}.
title: Se désabonner
media_attachments:
validations:
images_and_video: Impossible de joindre une vidéo à un message contenant déjà des images
+ not_found: Média %{ids} introuvable ou déjà attaché à un autre message
not_ready: Impossible de joindre les fichiers en cours de traitement. Réessayez dans un instant !
too_many: Impossible de joindre plus de 4 fichiers
migrations:
@@ -1650,23 +1738,12 @@ fr-CA:
edited_at_html: Édité le %{date}
errors:
in_reply_not_found: Le message auquel vous essayez de répondre ne semble pas exister.
- open_in_web: Ouvrir sur le web
over_character_limit: limite de %{max} caractères dépassée
pin_errors:
direct: Les messages qui ne sont visibles que pour les utilisateur·rice·s mentionné·e·s ne peuvent pas être épinglés
limit: Vous avez déjà épinglé le nombre maximum de messages
ownership: Vous ne pouvez pas épingler un message ne vous appartenant pas
reblog: Un partage ne peut pas être épinglé
- poll:
- total_people:
- one: "%{count} personne"
- other: "%{count} personnes"
- total_votes:
- one: "%{count} vote"
- other: "%{count} votes"
- vote: Voter
- show_more: Déplier
- show_thread: Afficher le fil de discussion
title: "%{name} : « %{quote} »"
visibilities:
direct: Direct
@@ -1856,6 +1933,7 @@ fr-CA:
invalid_otp_token: Le code d’authentification à deux facteurs est invalide
otp_lost_help_html: Si vous perdez accès aux deux, vous pouvez contacter %{email}
rate_limited: Trop de tentatives d'authentification, réessayez plus tard.
+ seamless_external_login: Vous êtes connectés sur un service externe, de fait les paramètres de mot de passe et d'e-mail ne sont pas disponibles.
signed_in_as: 'Connecté·e en tant que :'
verification:
extra_instructions_html: Astuce: Le lien sur votre site Web peut être invisible. La partie importante est rel="me"
qui évite d’autres liens provenant de contenu générés par des utilisateurs tiers d'être pris en compte. Vous pouvez même utiliser une balise link
dans l’en-tête de la page au lieu de a
, mais le HTML doit être accessible sans avoir besoin d’exécuter du JavaScript.
@@ -1864,6 +1942,7 @@ fr-CA:
instructions_html: Copiez et collez le code ci-dessous dans le code HTML de votre site web. Ajoutez ensuite l’adresse de votre site dans l’un des champs supplémentaires de votre profil à partir de l‘onglet "Modifier le profil" et enregistrez les modifications.
verification: Vérification
verified_links: Vos liens vérifiés
+ website_verification: Vérification du site web
webauthn_credentials:
add: Ajouter une nouvelle clé de sécurité
create:
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 38c9ca299a..cb76ae2243 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -7,7 +7,6 @@ fr:
hosted_on: Serveur Mastodon hébergé sur %{domain}
title: À propos
accounts:
- follow: Suivre
followers:
one: Abonné·e
other: Abonné·e·s
@@ -25,12 +24,15 @@ fr:
admin:
account_actions:
action: Effectuer l'action
+ already_silenced: Ce compte a déjà été limité.
+ already_suspended: Ce compte est déjà suspendu.
title: Effectuer une action de modération sur %{acct}
account_moderation_notes:
create: Laisser une remarque
created_msg: Note de modération créée avec succès !
destroyed_msg: Note de modération supprimée avec succès !
accounts:
+ add_email_domain_block: Bloquer le domaine de messagerie
approve: Approuver
approved_msg: La demande d’inscription de %{username} a été approuvée avec succès
are_you_sure: Voulez-vous vraiment faire ça ?
@@ -45,6 +47,7 @@ fr:
title: Modifier l’adresse de courriel pour %{username}
change_role:
changed_msg: Rôle modifié avec succès !
+ edit_roles: Gérer les rôles d'utilisateur·ices
label: Modifier le rôle
no_role: Aucun rôle
title: Modifier le rôle de %{username}
@@ -57,6 +60,7 @@ fr:
demote: Rétrograder
destroyed_msg: Les données de %{username} sont maintenant en file d’attente pour être supprimées imminemment
disable: Geler
+ disable_sign_in_token_auth: Désactiver le jeton d'authentification par e-mail
disable_two_factor_authentication: Désactiver l’authentification à deux facteurs
disabled: Gelé
display_name: Nom affiché
@@ -65,6 +69,7 @@ fr:
email: Adresse de courriel
email_status: État du courriel
enable: Dégeler
+ enable_sign_in_token_auth: Activer le jeton d'authentification par e-mail
enabled: Activé
enabled_msg: Le compte de %{username} a été dégelé avec succès
followers: Abonné·e·s
@@ -129,6 +134,7 @@ fr:
resubscribe: Se réabonner
role: Rôle
search: Rechercher
+ search_same_email_domain: Autres utilisateur·rice·s ayant le même domaine de messagerie
search_same_ip: Autres utilisateur·rice·s avec la même IP
security: Sécurité
security_measures:
@@ -169,21 +175,26 @@ fr:
approve_appeal: Approuver l'appel
approve_user: Approuver le compte
assigned_to_self_report: Affecter le signalement
+ change_email_user: Modification de l’adresse de messagerie électronique pour l'utilisateur·ce
change_role_user: Changer le rôle du compte
confirm_user: Confirmer le compte
create_account_warning: Créer une alerte
create_announcement: Créer une annonce
+ create_canonical_email_block: Création d'un blocage de courrier électronique
create_custom_emoji: Créer des émojis personnalisés
create_domain_allow: Créer un domaine autorisé
create_domain_block: Créer un blocage de domaine
+ create_email_domain_block: Création d'un blocage de domaine de courrier électronique
create_ip_block: Créer une règle IP
create_unavailable_domain: Créer un domaine indisponible
create_user_role: Créer le rôle
demote_user: Rétrograder l’utilisateur·ice
destroy_announcement: Supprimer l’annonce
+ destroy_canonical_email_block: Supprimer le blocage de courriel
destroy_custom_emoji: Supprimer des émojis personnalisés
destroy_domain_allow: Supprimer le domaine autorisé
destroy_domain_block: Supprimer le blocage de domaine
+ destroy_email_domain_block: Supprimer le blocage de domaine de courriel
destroy_instance: Purge du domaine
destroy_ip_block: Supprimer la règle IP
destroy_status: Supprimer le message
@@ -191,8 +202,10 @@ fr:
destroy_user_role: Détruire le rôle
disable_2fa_user: Désactiver l’A2F
disable_custom_emoji: Désactiver les émojis personnalisés
+ disable_sign_in_token_auth_user: Désactiver le jeton d'authentification par e-mail pour l'utilisateur
disable_user: Désactiver le compte
enable_custom_emoji: Activer les émojis personnalisées
+ enable_sign_in_token_auth_user: Activer le jeton d'authentification par e-mail pour l'utilisateur
enable_user: Activer le compte
memorialize_account: Ériger en mémorial
promote_user: Promouvoir le compte
@@ -215,26 +228,33 @@ fr:
update_custom_emoji: Mettre à jour les émojis personnalisés
update_domain_block: Mettre à jour le blocage de domaine
update_ip_block: Mettre à jour la règle IP
+ update_report: Mettre à jour le rapport
update_status: Mettre à jour le message
update_user_role: Mettre à jour le rôle
actions:
approve_appeal_html: "%{name} a approuvé l'appel de la décision de modération émis par %{target}"
approve_user_html: "%{name} a approuvé l’inscription de %{target}"
assigned_to_self_report_html: "%{name} s’est assigné·e le signalement de %{target}"
+ change_email_user_html: "%{name} a changé l'adresse e-mail de l'utilisateur \n%{target}"
change_role_user_html: "%{name} a changé le rôle de %{target}"
+ confirm_user_html: "%{name} a confirmé l'adresse e-mail de l'utilisateur %{target}"
create_account_warning_html: "%{name} a envoyé un avertissement à %{target}"
create_announcement_html: "%{name} a créé une nouvelle annonce %{target}"
+ create_canonical_email_block_html: "%{name} a bloqué l'adresse email avec le hachage %{target}"
create_custom_emoji_html: "%{name} a téléversé un nouvel émoji %{target}"
create_domain_allow_html: "%{name} a autorisé la fédération avec le domaine %{target}"
create_domain_block_html: "%{name} a bloqué le domaine %{target}"
+ create_email_domain_block_html: "%{name} a bloqué le domaine d'e-mail %{target}"
create_ip_block_html: "%{name} a créé une règle pour l'IP %{target}"
create_unavailable_domain_html: "%{name} a arrêté la livraison vers le domaine %{target}"
create_user_role_html: "%{name} a créé le rôle %{target}"
demote_user_html: "%{name} a rétrogradé l'utilisateur·rice %{target}"
destroy_announcement_html: "%{name} a supprimé l'annonce %{target}"
+ destroy_canonical_email_block_html: "%{name} a débloqué l'adresse email avec le hachage %{target}"
destroy_custom_emoji_html: "%{name} a supprimé l'émoji %{target}"
destroy_domain_allow_html: "%{name} a rejeté la fédération avec le domaine %{target}"
destroy_domain_block_html: "%{name} a débloqué le domaine %{target}"
+ destroy_email_domain_block_html: "%{name} a débloqué le domaine d'e-mail %{target}"
destroy_instance_html: "%{name} a purgé le domaine %{target}"
destroy_ip_block_html: "%{name} a supprimé la règle pour l'IP %{target}"
destroy_status_html: "%{name} a supprimé le message de %{target}"
@@ -251,6 +271,7 @@ fr:
reject_user_html: "%{name} a rejeté l’inscription de %{target}"
remove_avatar_user_html: "%{name} a supprimé l'avatar de %{target}"
reopen_report_html: "%{name} a rouvert le signalement %{target}"
+ resend_user_html: "%{name} a renvoyé l'e-mail de confirmation pour %{target}"
reset_password_user_html: "%{name} a réinitialisé le mot de passe de l'utilisateur·rice %{target}"
resolve_report_html: "%{name} a résolu le signalement %{target}"
sensitive_account_html: "%{name} a marqué le média de %{target} comme sensible"
@@ -265,6 +286,7 @@ fr:
update_custom_emoji_html: "%{name} a mis à jour l'émoji %{target}"
update_domain_block_html: "%{name} a mis à jour le blocage de domaine pour %{target}"
update_ip_block_html: "%{name} a modifié la règle pour l'IP %{target}"
+ update_report_html: "%{name} a mis à jour le rapport de signalement %{target}"
update_status_html: "%{name} a mis à jour le message de %{target}"
update_user_role_html: "%{name} a changé le rôle %{target}"
deleted_account: compte supprimé
@@ -272,6 +294,7 @@ fr:
filter_by_action: Filtrer par action
filter_by_user: Filtrer par utilisateur·ice
title: Journal d’audit
+ unavailable_instance: "(nom de domaine indisponible)"
announcements:
destroyed_msg: Annonce supprimée avec succès !
edit:
@@ -409,6 +432,7 @@ fr:
attempts_over_week:
one: "%{count} tentative au cours de la dernière semaine"
other: "%{count} tentatives au cours de la dernière semaine"
+ created_msg: Domaine d'e-mail bloqué avec succès
delete: Supprimer
dns:
types:
@@ -417,15 +441,22 @@ fr:
new:
create: Créer le blocage
resolve: Résoudre le domaine
+ title: Blocage d'un nouveau domaine de messagerie électronique
+ no_email_domain_block_selected: Aucun blocage de domaine de messagerie n'a été modifié comme aucun n'a été sélectionné
not_permitted: Non autorisé
+ resolved_dns_records_hint_html: |-
+ Le nom de domaine se réfère aux domaines MX suivants, qui sont à leur tour responsables de la réception des courriels.
+
+ Le blocage d'un domaine MX empêchera l'inscription depuis toute adresse électronique ayant recours au même domaine MX, et ce même si le nom de domaine visible est différent. Veillez à ne pas bloquer les principaux fournisseurs de services de messagerie.
resolved_through_html: Résolu par %{domain}
+ title: Domaines de messagerie électronique bloqués
export_domain_allows:
new:
title: Importer les autorisations de domaine
no_file: Aucun fichier sélectionné
export_domain_blocks:
import:
- description_html: Vous êtes sur le point d'importer une liste de bloqueurs de domaine. Veuillez examiner cette liste très attentivement, surtout si vous ne l'avez pas créée vous-même.
+ description_html: Vous êtes sur le point d'importer une liste de blocage de domaines. Veuillez examiner cette liste très attentivement, surtout si vous ne l'avez pas créée vous-même.
existing_relationships_warning: Relations d'abonnement existantes
private_comment_description_html: 'Pour vous aider à savoir d''où proviennent les blocages importés, ceux-ci seront créés avec le commentaire privé suivant : %{comment}
'
private_comment_template: Importé depuis %{source} le %{date}
@@ -443,6 +474,9 @@ fr:
title: Recommandations d'abonnement
unsuppress: Rétablir les recommandations d'abonnement
instances:
+ audit_log:
+ title: Journaux d'audit récents
+ view_all: Voir les journaux d'audit complets
availability:
description_html:
one: Si la livraison au domaine échoue pendant %{count} jour, aucune autre tentative de livraison ne sera faite à moins qu'une livraison depuis le domaine ne soit reçue.
@@ -569,12 +603,14 @@ fr:
resolve_description_html: Aucune mesure ne sera prise contre le compte signalé, aucune sanction ne sera enregistrée et le sigalement sera clôturé.
silence_description_html: Le compte ne sera visible que par ceux qui le suivent déjà ou qui le recherchent manuellement, ce qui limite fortement sa portée. Cette action peut toujours être annulée. Cloture tous les signalements concernant ce compte.
suspend_description_html: Le compte et tous ses contenus seront inaccessibles et finalement supprimés, et il sera impossible d'interagir avec lui. Réversible dans les 30 jours. Cloture tous les signalements concernant ce compte.
+ actions_description_html: Décidez de l'action à entreprendre pour résoudre ce signalement. Si vous prenez une mesure punitive à l'encontre du compte signalé, une notification par courrier électronique lui sera envoyée, excepté lorsque la catégorie Spam est sélectionnée.
actions_description_remote_html: Décidez des mesures à prendre pour résoudre ce signalement. Cela n'affectera que la manière dont votre serveur communique avec ce compte distant et traite son contenu.
+ actions_no_posts: Ce signalement n'a pas de messages qui lui sont associés et qui devraient être supprimés
add_to_report: Ajouter davantage au rapport
already_suspended_badges:
local: Déjà suspendu sur ce serveur
remote: Déjà suspendu sur le serveur distant
- are_you_sure: Voulez-vous vraiment faire ça ?
+ are_you_sure: En êtes-vous sûr ?
assign_to_self: Me l’assigner
assigned: Modérateur assigné
by_target_domain: Domaine du compte signalé
@@ -610,6 +646,7 @@ fr:
report: 'Signalement #%{id}'
reported_account: Compte signalé
reported_by: Signalé par
+ reported_with_application: Signalé avec l'application
resolved: Résolus
resolved_msg: Signalement résolu avec succès !
skip_to_actions: Passer aux actions
@@ -632,6 +669,7 @@ fr:
delete_data_html: effacer le profil de @%{acct} et ses contenus dans 30 jours, à moins que la suspension du compte ne soit annulée entre temps
preview_preamble_html: "@%{acct} recevra un avertissement contenant les éléments suivants :"
record_strike_html: enregistrer une sanction contre @%{acct} pour vous aider à prendre des mesures supplémentaires en cas d'infractions futures de ce compte
+ send_email_html: Envoyer un courriel d'avertissement à @%{acct}
warning_placeholder: Arguments supplémentaires pour l'action de modération (facultatif).
target_origin: Origine du compte signalé
title: Signalements
@@ -671,6 +709,7 @@ fr:
manage_appeals: Gérer les contestations
manage_appeals_description: Permet aux utilisateur⋅rice⋅s d'examiner les appels contre les actions de modération
manage_blocks: Gérer les blocages
+ manage_blocks_description: Permet aux utilisateur⋅rice⋅s de bloquer des fournisseurs de courriel et des adresses IP
manage_custom_emojis: Gérer les émojis personnalisés
manage_custom_emojis_description: Permet aux utilisateur⋅rice⋅s de gérer les émoticônes personnalisées sur le serveur
manage_federation: Gérer de la féderation
@@ -688,6 +727,7 @@ fr:
manage_taxonomies: Gérer les taxonomies
manage_taxonomies_description: Permet aux utilisateur⋅rice⋅s d'examiner les contenus tendance et de mettre à jour les paramètres des hashtags
manage_user_access: Gérer l'accès utilisateur
+ manage_user_access_description: Permet aux utilisateur·rice·s de désactiver l'authentification à deux facteurs des autres utilisateur·rice·s, de modifier leur adresse électronique et de réinitialiser leur mot de passe
manage_users: Gérer les utilisateur·rice·s
manage_users_description: Permet aux utilisateur⋅rice⋅s de voir les détails des autres utilisateur⋅rice⋅s et d'effectuer des actions de modération en conséquence
manage_webhooks: Gérer les points d’ancrage web
@@ -722,6 +762,7 @@ fr:
desc_html: Ceci se base sur des scripts externes venant de hCaptcha, ce qui peut engendrer des soucis de sécurité et de confidentialité. De plus, cela peut rendre l'inscription beaucoup moins accessible pour certaines personnes (comme les personnes handicapées). Pour ces raisons, veuillez envisager des mesures alternatives telles que l'inscription sur acceptation ou invitation.
title: Exiger que les nouveaux utilisateurs résolvent un CAPTCHA pour confirmer leur compte
content_retention:
+ danger_zone: Zone de danger
preamble: Contrôle comment le contenu créé par les utilisateurs est enregistré et stocké dans Mastodon.
title: Rétention du contenu
default_noindex:
@@ -761,6 +802,7 @@ fr:
destroyed_msg: Téléversement sur le site supprimé avec succès !
software_updates:
critical_update: Critique — veuillez mettre à jour au plus vite
+ description: Il est recommandé de maintenir votre installation de Mastodon à jour afin de bénéficier des derniers correctifs et fonctionnalités. Par ailleurs, il est parfois critique de mettre à jour Mastodon en temps voulu de manière à éviter les incidents relatifs à la sécurité. Pour ces raisons, Mastodon examine la disponibilté des mises à jour toutes les 30 minutes, et vous en avisera en fonction de vos préférences de notification par messagerie électronique.
documentation_link: En savoir plus
release_notes: Notes de mises à jour
title: Mises à jour disponibles
@@ -847,7 +889,21 @@ fr:
action: Pour plus d'informations, cliquez ici
message_html: "Votre serveur web est mal configuré. La confidentialité de vos utilisateurs est en péril."
tags:
+ moderation:
+ not_trendable: Ne peut être en tendance
+ not_usable: Non utilisable
+ pending_review: En attente de traitement
+ review_requested: Révision requise
+ reviewed: Traité
+ title: État
+ trendable: Peut s'afficher dans les tendances
+ unreviewed: Non traité
+ usable: Utilisable
name: Nom
+ newest: Plus récents
+ oldest: Plus anciens
+ open: Afficher publiquement
+ reset: Réinitialiser
review: État du traitement
search: Recherche
title: Hashtags
@@ -856,10 +912,16 @@ fr:
trends:
allow: Autoriser
approved: Approuvé
+ confirm_allow: Êtes-vous sûr de vouloir autoriser les hashtags sélectionnés ?
+ confirm_disallow: Êtes-vous sûr de vouloir interdire les hashtags sélectionnés ?
disallow: Interdire
links:
allow: Autoriser le lien
allow_provider: Autoriser l'éditeur
+ confirm_allow: Êtes-vous sûr de vouloir autoriser les liens sélectionnés ?
+ confirm_allow_provider: Êtes-vous sûr de vouloir autoriser les fournisseurs sélectionnés ?
+ confirm_disallow: Êtes-vous sûr de vouloir interdire les liens sélectionnés ?
+ confirm_disallow_provider: Êtes-vous sûr de vouloir interdire les fournisseurs sélectionnés ?
description_html: Ces liens sont actuellement énormément partagés par des comptes dont votre serveur voit les messages. Cela peut aider vos utilisateur⋅rice⋅s à découvrir ce qu'il se passe dans le monde. Aucun lien n'est publiquement affiché tant que vous n'avez pas approuvé le compte qui le publie. Vous pouvez également autoriser ou rejeter les liens individuellement.
disallow: Interdire le lien
disallow_provider: Interdire l'éditeur
@@ -883,6 +945,10 @@ fr:
statuses:
allow: Autoriser le message
allow_account: Autoriser l'auteur·rice
+ confirm_allow: Êtes-vous sûr de vouloir autoriser les statuts sélectionnés ?
+ confirm_allow_account: Êtes-vous sûr de vouloir autoriser les comptes sélectionnés ?
+ confirm_disallow: Êtes-vous sûr de vouloir rejeter les statuts sélectionnés ?
+ confirm_disallow_account: Êtes-vous sûr de vouloir rejeter les comptes sélectionnés ?
description_html: Voici les messages dont votre serveur a connaissance qui sont beaucoup partagés et mis en favoris en ce moment. Cela peut aider vos utilisateur⋅rice⋅s, néophytes comme aguerri⋅e⋅s, à trouver plus de comptes à suivre. Aucun message n'est publiquement affiché tant que vous n'en avez pas approuvé l'auteur⋅rice, et seulement si icellui permet que son compte soit suggéré aux autres. Vous pouvez également autoriser ou rejeter les messages individuellement.
disallow: Proscrire le message
disallow_account: Proscrire l'auteur·rice
@@ -1000,7 +1066,9 @@ fr:
guide_link_text: Tout le monde peut y contribuer.
sensitive_content: Contenu sensible
application_mailer:
+ notification_preferences: Modification des préférences de la messagerie
salutation: "%{name},"
+ settings: 'Modifier les préférences de la messagerie : %{link}'
unsubscribe: Se désabonner
view: 'Voir :'
view_profile: Voir le profil
@@ -1020,6 +1088,7 @@ fr:
hint_html: Encore une chose ! Nous avons besoin de confirmer que vous êtes un humain (c'est pour que nous puissions empêcher les spams !). Résolvez le CAPTCHA ci-dessous et cliquez sur "Continuer".
title: Vérification de sécurité
confirmations:
+ awaiting_review: Votre adresse de messagerie est confirmée ! L'équipe de %{domain} est en train d'examiner votre inscription. Vous recevrez un e-mail si votre compte est approuvé !
awaiting_review_title: Votre inscription est en cours de validation
clicking_this_link: cliquer sur ce lien
login_link: vous connecter
@@ -1027,6 +1096,7 @@ fr:
redirect_to_app_html: Vous auriez dû être redirigé vers l’application %{app_name}. Si cela ne s’est pas produit, essayez de %{clicking_this_link} ou de revenir manuellement à l’application.
registration_complete: Votre inscription sur %{domain} est désormais terminée !
welcome_title: Bienvenue, %{name} !
+ wrong_email_hint: Si cette adresse de messagerie est incorrecte, vous pouvez la modifier dans vos paramètres de compte.
delete_account: Supprimer le compte
delete_account_html: Si vous désirez supprimer votre compte, vous pouvez cliquer ici. Il vous sera demandé de confirmer cette action.
description:
@@ -1047,6 +1117,7 @@ fr:
or_log_in_with: Ou authentifiez-vous avec
privacy_policy_agreement_html: J’ai lu et j’accepte la politique de confidentialité
progress:
+ confirm: Confirmation de l'adresse mail
details: Vos infos
review: Notre avis
rules: Accepter les règles
@@ -1068,6 +1139,7 @@ fr:
security: Sécurité
set_new_password: Définir le nouveau mot de passe
setup:
+ email_below_hint_html: Consultez votre dossier de courrier indésirable ou demandez-en un autre. Vous pouvez corriger votre adresse e-mail si elle est incorrecte.
email_settings_hint_html: Cliquez sur le lien que nous vous avons envoyé pour vérifier l’adresse %{email}. Nous vous attendons ici.
link_not_received: Vous n'avez pas reçu de lien ?
new_confirmation_instructions_sent: Vous allez recevoir un nouvel e-mail avec le lien de confirmation dans quelques minutes !
@@ -1081,6 +1153,7 @@ fr:
title: Mettons les choses en place pour %{domain}.
status:
account_status: État du compte
+ confirming: En attente de la confirmation par courrier électronique.
functional: Votre compte est entièrement opérationnel.
pending: Votre demande est en attente d’examen par notre équipe. Cela peut prendre un certain temps. Vous recevrez un e-mail si votre demande est approuvée.
redirecting_to: Votre compte est inactif car il est actuellement redirigé vers %{acct}.
@@ -1088,6 +1161,12 @@ fr:
view_strikes: Voir les sanctions précédemment appliquées à votre compte
too_fast: Formulaire envoyé trop rapidement, veuillez réessayer.
use_security_key: Utiliser la clé de sécurité
+ author_attribution:
+ example_title: Exemple de texte
+ hint_html: Déterminez la façon dont vous êtes crédité lorsque des liens sont partagés sur Mastodon.
+ more_from_html: Plus via %{name}
+ s_blog: Blog de %{name}
+ title: Attribution de l'auteur·e
challenge:
confirm: Continuer
hint_html: "Astuce : Nous ne vous demanderons plus votre mot de passe pour la prochaine heure."
@@ -1096,7 +1175,6 @@ fr:
crypto:
errors:
invalid_key: n’est pas une clé Ed25519 ou Curve25519 valide
- invalid_signature: n’est pas une signature Ed25519 valide
date:
formats:
default: "%d %b %Y"
@@ -1126,6 +1204,8 @@ fr:
caches: Le contenu mis en cache par d'autres serveurs peut persister
data_removal: Vos messages et autres données seront définitivement supprimés
email_change_html: Vous pouvez modifier votre adresse e-mail sans supprimer votre compte
+ email_contact_html: S'il ne vous est toujours pas parvenu, vous pouvez envoyer un message à %{email} pour obtenir de l'aide
+ email_reconfirmation_html: Dans le cas où vous n'auriez pas reçu l'email de confirmation, vous pouvez en réclamer un nouveau
irreversible: Vous ne pourrez pas restaurer ou réactiver votre compte
more_details_html: Pour plus de détails, voir la politique de confidentialité.
username_available: Votre nom d’utilisateur·rice sera à nouveau disponible
@@ -1160,8 +1240,6 @@ fr:
your_appeal_approved: Votre appel a été approuvé
your_appeal_pending: Vous avez soumis un appel
your_appeal_rejected: Votre appel a été rejeté
- domain_validator:
- invalid_domain: n’est pas un nom de domaine valide
edit_profile:
basic_information: Informations de base
hint_html: "Personnalisez ce que les gens voient sur votre profil public et à côté de vos messages. Les autres personnes seront plus susceptibles de vous suivre et d’interagir avec vous lorsque vous avez un profil complet et une photo."
@@ -1203,7 +1281,7 @@ fr:
add_new: Ajouter un nouveau hashtag
errors:
limit: Vous avez déjà mis en avant le nombre maximum de hashtags
- hint_html: "Que sont les hashtags mis en avant ? Ils sont affichés en évidence sur votre profil public et permettent aux gens de parcourir vos messages publics qui utilisent ces hashtags. Ils sont un excellent outil pour garder la trace d’activités créatrices ou de projets de long terme."
+ hint_html: "Mettez en évidence vos hashtags les plus importants sur votre profil. Un outil idéal pour suivre vos travaux créatifs et vos projets à long terme, les hashtags mis en avant sont affichés bien en évidence sur votre profil et permettent un accès rapide à vos propres publications."
filters:
contexts:
account: Profils
@@ -1369,10 +1447,20 @@ fr:
unsubscribe:
action: Oui, se désinscrire
complete: Désinscrit
+ emails:
+ notification_emails:
+ favourite: e-mails de notifications de favoris
+ follow: e-mails de notifications d’abonnements
+ follow_request: e-mails de demandes d’abonnements
+ mention: e-mails de notifications de mentions
+ reblog: e-mails de notifications de partages
+ resubscribe_html: Si vous vous êtes désinscrit par erreur, vous pouvez vous réinscrire à partir de vos paramètres de notification par e-mail.
+ success_html: Vous ne recevrez plus de %{type} pour Mastodon sur %{domain} à votre adresse e-mail à %{email}.
title: Se désinscrire
media_attachments:
validations:
images_and_video: Impossible de joindre une vidéo à un message contenant déjà des images
+ not_found: Média %{ids} introuvable ou déjà attaché à un autre message
not_ready: Impossible de joindre les fichiers en cours de traitement. Réessayez dans un instant !
too_many: Impossible de joindre plus de 4 fichiers
migrations:
@@ -1650,23 +1738,12 @@ fr:
edited_at_html: Modifié le %{date}
errors:
in_reply_not_found: Le message auquel vous essayez de répondre ne semble pas exister.
- open_in_web: Ouvrir sur le web
over_character_limit: limite de %{max} caractères dépassée
pin_errors:
direct: Les messages qui ne sont visibles que pour les utilisateur·rice·s mentionné·e·s ne peuvent pas être épinglés
limit: Vous avez déjà épinglé le nombre maximum de messages
ownership: Vous ne pouvez pas épingler un message ne vous appartenant pas
reblog: Un partage ne peut pas être épinglé
- poll:
- total_people:
- one: "%{count} personne"
- other: "%{count} personnes"
- total_votes:
- one: "%{count} vote"
- other: "%{count} votes"
- vote: Voter
- show_more: Déplier
- show_thread: Afficher le fil de discussion
title: "%{name} : « %{quote} »"
visibilities:
direct: Direct
@@ -1856,6 +1933,7 @@ fr:
invalid_otp_token: Le code d’authentification à deux facteurs est invalide
otp_lost_help_html: Si vous perdez accès aux deux, vous pouvez contacter %{email}
rate_limited: Trop de tentatives d'authentification, réessayez plus tard.
+ seamless_external_login: Vous êtes connectés sur un service externe, de fait les paramètres de mot de passe et d'e-mail ne sont pas disponibles.
signed_in_as: 'Connecté·e en tant que :'
verification:
extra_instructions_html: Astuce : Le lien sur votre site Web peut être invisible. La partie importante est rel="me"
qui évite que soient pris en compte d’autres liens provenant de contenu générés par des utilisateurs tiers. Vous pouvez même utiliser une balise link
dans l’en-tête de la page au lieu de a
, mais le HTML doit être accessible sans avoir besoin d’exécuter du JavaScript.
@@ -1864,6 +1942,7 @@ fr:
instructions_html: Copiez et collez le code ci-dessous dans le code HTML de votre site web. Ajoutez ensuite l’adresse de votre site dans l’un des champs supplémentaires de votre profil à partir de l‘onglet « Modifier le profil » et enregistrez les modifications.
verification: Vérification
verified_links: Vos liens vérifiés
+ website_verification: Vérification du site web
webauthn_credentials:
add: Ajouter une nouvelle clé de sécurité
create:
diff --git a/config/locales/fy.yml b/config/locales/fy.yml
index 62889c0b28..8b854494d4 100644
--- a/config/locales/fy.yml
+++ b/config/locales/fy.yml
@@ -7,7 +7,6 @@ fy:
hosted_on: Mastodon op %{domain}
title: Oer
accounts:
- follow: Folgje
followers:
one: Folger
other: Folgers
@@ -31,6 +30,7 @@ fy:
created_msg: Oanmeitsjen fan opmerking foar moderatoaren slagge!
destroyed_msg: Fuortsmiten fan opmerking foar moderatoaren slagge!
accounts:
+ add_email_domain_block: E-maildomein blokkearje
approve: Goedkarre
approved_msg: It goedkarren fan de account fan %{username} is slagge
are_you_sure: Binne jo wis?
@@ -57,6 +57,7 @@ fy:
demote: Degradearje
destroyed_msg: It fuortsmiten fan de gegevens fan %{username} stiet no yn de wachtrige
disable: Befrieze
+ disable_sign_in_token_auth: Ferifikaasje mei in tagongskoade fia e-mail útskeakelje
disable_two_factor_authentication: 2FA útskeakelje
disabled: Beferzen
display_name: Werjeftenamme
@@ -65,6 +66,7 @@ fy:
email: E-mailadres
email_status: E-mailsteat
enable: Untteie
+ enable_sign_in_token_auth: Ferifikaasje mei in tagongskoade fia e-mail ynskeakelje
enabled: Ynskeakele
enabled_msg: It ûntteie fan de account fan %{username} is slagge
followers: Folgers
@@ -129,6 +131,7 @@ fy:
resubscribe: Opnij abonnearje
role: Rol
search: Sykje
+ search_same_email_domain: Oare brûkers mei itselde e-maildomein
search_same_ip: Oare brûkers mei itselde IP-adres
security: Befeiliging
security_measures:
@@ -169,21 +172,26 @@ fy:
approve_appeal: Beswier goedkarre
approve_user: Brûker goedkarre
assigned_to_self_report: Rapportaazje tawize
+ change_email_user: E-mailadres fan brûker wizigje
change_role_user: Brûkersrol wizigje
confirm_user: Brûker befêstigje
create_account_warning: Warskôging oanmeitsje
create_announcement: Meidieling oanmeitsje
+ create_canonical_email_block: E-mailblokkade oanmeitsje
create_custom_emoji: Lokale emoji oanmeitsje
create_domain_allow: Domeingoedkarring oanmeitsje
create_domain_block: Domeinblokkade oanmeitsje
+ create_email_domain_block: E-maildomeinblokkade oanmeitsje
create_ip_block: IP-rigel oanmeitsje
create_unavailable_domain: Net beskikber domein oanmeitsje
create_user_role: Rol oanmeitsje
demote_user: Brûker degradearje
destroy_announcement: Meidieling fuortsmite
+ destroy_canonical_email_block: E-mailblokkade fuortsmite
destroy_custom_emoji: Lokale emoji fuortsmite
destroy_domain_allow: Domeingoedkarring fuortsmite
destroy_domain_block: Domeinblokkade fuortsmite
+ destroy_email_domain_block: E-maildomeinblokkade fuortsmite
destroy_instance: Domein folslein fuortsmite
destroy_ip_block: IP-rigel fuortsmite
destroy_status: Toot fuortsmite
@@ -191,8 +199,10 @@ fy:
destroy_user_role: Rol permanint fuortsmite
disable_2fa_user: Twa-stapsferifikaasje útskeakelje
disable_custom_emoji: Lokale emoji útskeakelje
+ disable_sign_in_token_auth_user: Ferifikaasje mei in tagongskoade fia e-mail foar de brûker útskeakelje
disable_user: Brûker útskeakelje
enable_custom_emoji: Lokale emoji ynskeakelje
+ enable_sign_in_token_auth_user: Ferifikaasje mei in tagongskoade fia e-mail foar de brûker ynskeakelje
enable_user: Brûker ynskeakelje
memorialize_account: De account yn in Yn memoriam wizigje
promote_user: Brûker promovearje
@@ -222,20 +232,26 @@ fy:
approve_appeal_html: "%{name} hat it beswier tsjin de moderaasjemaatregel fan %{target} goedkard"
approve_user_html: "%{name} hat de registraasje fan %{target} goedkard"
assigned_to_self_report_html: "%{name} hat rapportaazje %{target} oan harrensels tawiisd"
+ change_email_user_html: "%{name} hat it e-mailadres fan brûker %{target} wizige"
change_role_user_html: "%{name} hat de rol fan %{target} wizige"
+ confirm_user_html: E-mailadres fan brûker %{target} is troch %{name} befêstige
create_account_warning_html: "%{name} hat in warskôging nei %{target} ferstjoerd"
create_announcement_html: "%{name} hat de nije meidieling %{target} oanmakke"
+ create_canonical_email_block_html: "%{name} hat it e-mailberjocht mei de hash %{target} blokkearre"
create_custom_emoji_html: Nije emoji %{target} is troch %{name} opladen
create_domain_allow_html: "%{name} hat de federaasje mei it domein %{target} goedkard"
create_domain_block_html: Domein %{target} is troch %{name} blokkearre
+ create_email_domain_block_html: "%{name} hat it e-maildomein %{target} blokkearre"
create_ip_block_html: "%{name} hat de rigel foar IP %{target} oanmakke"
create_unavailable_domain_html: "%{name} hat de besoarging foar domein %{target} beëinige"
create_user_role_html: "%{name} hat de rol %{target} oanmakke"
demote_user_html: Brûker %{target} is troch %{name} degradearre
destroy_announcement_html: "%{name} hat de meidieling %{target} fuortsmiten"
+ destroy_canonical_email_block_html: "%{name} hat it e-mailberjocht mei de hash %{target} deblokkearre"
destroy_custom_emoji_html: Emoji %{target} is troch %{name} fuortsmiten
destroy_domain_allow_html: "%{name} hat de federaasje mei it domein %{target} ôfkard"
destroy_domain_block_html: Domein %{target} is troch %{name} deblokkearre
+ destroy_email_domain_block_html: "%{name} hat it e-maildomein %{target} deblokkearre"
destroy_instance_html: "%{name} hat it domein %{target} folslein fuortsmiten"
destroy_ip_block_html: "%{name} hat de rigel foar IP %{target} fuortsmiten"
destroy_status_html: Berjocht fan %{target} is troch %{name} fuortsmiten
@@ -243,8 +259,10 @@ fy:
destroy_user_role_html: "%{name} hat de rol %{target} fuortsmiten"
disable_2fa_user_html: De fereaske twa-stapsferifikaasje foar %{target} is troch %{name} útskeakele
disable_custom_emoji_html: Emoji %{target} is troch %{name} útskeakele
+ disable_sign_in_token_auth_user_html: "%{name} hat ferifikaasje mei in tagongskoade fia e-mail útskeakele foar %{target}"
disable_user_html: Oanmelden foar %{target} is troch %{name} útskeakele
enable_custom_emoji_html: Emoji %{target} is troch %{name} ynskeakele
+ enable_sign_in_token_auth_user_html: "%{name} hat ferifikaasje mei in tagongskoade fia e-mail ynskeakele foar %{target}"
enable_user_html: Oanmelden foar %{target} is troch %{name} ynskeakele
memorialize_account_html: De account %{target} is troch %{name} yn in Yn memoriam wizige
promote_user_html: Brûker %{target} is troch %{name} promovearre
@@ -252,6 +270,7 @@ fy:
reject_user_html: "%{name} hat de registraasje fan %{target} ôfwêzen"
remove_avatar_user_html: "%{name} hat de profylfoto fan %{target} fuortsmiten"
reopen_report_html: "%{name} hat rapportaazje %{target} opnij iepene"
+ resend_user_html: "%{name} hat it befêstigings-e-mailberjocht foar %{target} opnij ferstjoerd"
reset_password_user_html: Wachtwurd fan brûker %{target} is troch %{name} opnij ynsteld
resolve_report_html: "%{name} hat rapportaazje %{target} oplost"
sensitive_account_html: "%{name} markearre de media fan %{target} as gefoelich"
@@ -412,6 +431,7 @@ fy:
attempts_over_week:
one: "%{count} registraasjebesykjen yn de ôfrûne wike"
other: "%{count} registraasjebesykjen yn de ôfrûne wike"
+ created_msg: E-maildomein blokkearjen slagge
delete: Fuortsmite
dns:
types:
@@ -420,8 +440,12 @@ fy:
new:
create: Domein tafoegje
resolve: Domein opsykje
+ title: Nije e-maildomein blokkearje
+ no_email_domain_block_selected: Der binne gjin e-maildomeinblokkaden wizige, omdat der gjin ien selektearre waard
not_permitted: Net tastien
+ resolved_dns_records_hint_html: De domeinnamme slacht op de folgjende MX-domeinen dy’t úteinlik ferantwurdlik binne foar it akseptearjen fan e-mail. It blokkearjen fan in MX-domein blokkearret oanmeldingen fan elk e-mailadres dat itselde MX-domein brûkt, sels as de sichtbere domeinnamme oars is. Pas op dat jo gjin grutte e-mailproviders blokkearje.
resolved_through_html: Blokkearre fia %{domain}
+ title: Blokkearre e-maildomeinen
export_domain_allows:
new:
title: Tastiene domeinen ymportearje
@@ -575,6 +599,7 @@ fy:
resolve_description_html: Der wurdt tsjin it rapportearre account gjin maatregel nommen, gjin oertrêding registrearre en de rapportaazje wurdt markearre as oplost.
silence_description_html: De account sil allinnich sichtber wêze foar dyjinge dy’t it al folgje of it hânmjittich opsykje, wêrtroch it berik earnstich beheind wurdt. Kin altyd weromdraaid wurde. Dit slút alle rapportaazjes oer dizze account.
suspend_description_html: De account en alle ynhâld sil net tagonklik wêze en úteinlik fuortsmiten wurde, en ynteraksje hjirmei sil net mooglik wêze. Binnen 30 dagen werom te draaien. Dit slút alle rapportaazjes oer dizze account.
+ actions_description_html: Beslis hokker maatregel nommen wurde moat om dizze rapportaazje op te lossen. Wannear’t jo in (straf)maatregel tsjin it rapportearre account nimme, kriget de account in e-mailmelding, behalve wannear’t de spam-kategory keazen is.
actions_description_remote_html: Beslút hokker aksje nommen wurde moat om dizze rapportaazje ôf te hanneljen. Dit hat allinnich ynfloed op hoe’t jo server kommunisearret mei dizze eksterne account en omgiet mei de ynhâld.
add_to_report: Mear oan de rapportaazje tafoegje
already_suspended_badges:
@@ -639,6 +664,7 @@ fy:
delete_data_html: It profyl en de ynhâld fan @%{acct} wurde nei 30 dagen fan no ôf fuortsmiten, útsein as de account yn de tuskentiid net mear blokkearre wurdt
preview_preamble_html: "@%{acct} sil in warskôging ûntfange mei de folgjende ynhâld:"
record_strike_html: In ban tsjin @%{acct} ynstelle, om jo te helpen by takomstige skeiningen fan dizze acount te eskalearjen
+ send_email_html: Stjoer @%{acct} in warskôgings-e-mailberjocht
warning_placeholder: Ekstra opsjonele reden foar de moderaasje-aksje.
target_origin: Orizjineel fan rapportearre account
title: Rapportaazjes
@@ -678,6 +704,7 @@ fy:
manage_appeals: Beswieren beheare
manage_appeals_description: Stiet brûkers ta om beswieren tsjin moderaasjemaatregelen te beoardielen
manage_blocks: Blokkaden beheare
+ manage_blocks_description: Stiet brûkers ta om e-mailproviders en IP-adressen te blokkearjen
manage_custom_emojis: Lokale emoji’s beheare
manage_custom_emojis_description: Stiet brûkers ta om lokale emoji’s op de server te behearen
manage_federation: Federaasje beheare
@@ -695,6 +722,7 @@ fy:
manage_taxonomies: Trends en hashtags beheare
manage_taxonomies_description: Stiet brûkers ta om trending ynhâld te besjen en om hashtagynstellingen by te wurkjen
manage_user_access: Brûkerstagong beheare
+ manage_user_access_description: Stiet brûkers ta om twa-stapsferifikaasje fan oare brûkers út te skeakeljen, om harren e-mailadres te wizigjen en om harren wachtwurd opnij yn te stellen
manage_users: Brûkers beheare
manage_users_description: Stiet brûkers ta om brûkersdetails fan oaren te besjen en moderaasjemaatregelen tsjin harren te nimmen
manage_webhooks: Webhooks beheare
@@ -769,6 +797,7 @@ fy:
destroyed_msg: Fuortsmiten website-oplaad slagge!
software_updates:
critical_update: Krityk — fernij sa gau as mooglik
+ description: It wurdt oanrekommandearre om jo Mastodon-ynstallaasje by-de-tiid te hâlden om gebrûk meitsje te kinnen fan de nijste oplossingen en funksjes. Boppe dat is it somtiden krúsjaal om Mastodon tidich by te wurkjen om feiligheidsproblemen foar te kommen. Om dizze redenen kontrolearret Mastodon elke 30 minuten fernijingen en bringt jo hjirfan op de hichte neffens jo foarkarren foar e-mailmeldingen.
documentation_link: Mear ynfo
release_notes: Utjefte-opmerkingen
title: Beskikbere fernijingen
@@ -855,16 +884,39 @@ fy:
action: Klik hjir foar mear ynformaasje
message_html: "Jo objektûnthâld is ferkeard konfigurearre. De privacy fan jo brûkers is yn gefaar."
tags:
+ moderation:
+ not_trendable: Net trendber
+ not_usable: Net brûkber
+ pending_review: Moat noch beoardiele wurde
+ review_requested: Beoardieling oanfrege
+ reviewed: Beoardiele
+ title: Status
+ trendable: Trendber
+ unreviewed: Net beoardiele
+ usable: Brûkber
+ name: Namme
+ newest: Nijste
+ oldest: Aldste
+ open: Yn it iepenbier besjen
+ reset: Opnij ynstelle
review: Steat beoardiele
+ search: Sykje
+ title: Hashtags
updated_msg: Hashtagynstellingen mei sukses bywurke
title: Behear
trends:
allow: Tastean
approved: Goedkarre
+ confirm_allow: Binne jo wis dat jo de selektearre hashtags tastean wolle?
+ confirm_disallow: Binne jo wis dat jo de selektearre hashtags ôfkarre wolle?
disallow: Ofkarre
links:
allow: Keppeling goedkarre
allow_provider: Auteur goedkarre
+ confirm_allow: Binne jo wis dat jo de selektearre keppelingen tastean wolle?
+ confirm_allow_provider: Binne jo wis dat jo de selektearre websites tastean wolle?
+ confirm_disallow: Binne jo wis dat jo de selektearre keppelingen ôfkarre wolle?
+ confirm_disallow_provider: Binne jo wis dat jo de selektearre providers ôfkarre wolle?
description_html: Dit binne keppelingen dy’t op dit stuit in protte dield wurde troch accounts wêr’t jo server berjochten fan ûntfangt. Hjirtroch kinne jo brûkers sjen wat der yn de wrâld oan de hân is. Der wurde gjin keppelingen werjûn oant jo de website goedkard hawwe. Jo kinne ek yndividuele keppelingen goed- of ôfkarre.
disallow: Keppeling ôfkarre
disallow_provider: Website ôfkarre
@@ -888,6 +940,10 @@ fy:
statuses:
allow: Berjocht goedkarre
allow_account: Account goedkarre
+ confirm_allow: Binne jo wis dat jo de selektearre statussen ofkarre wolle?
+ confirm_allow_account: Binne jo wis dat jo de selektearre accounts tastean wolle?
+ confirm_disallow: Binne jo wis dat jo de selektearre statussen ôfkarre wolle?
+ confirm_disallow_account: Binne jo wis dat jo de selektearre accounts ôfkarre wolle?
description_html: Dit binne berjochten dy’t op jo server bekend binne en dy’t op dit stuit in protte dield wurde en as favoryt markearre wurde. Hjirmei kinne nije en weromkearende brûkers mear minsken fine om te folgjen. Der wurde gjin berjochten yn it iepenbier werjûn oant de account troch jo goedkard is en de brûker tastiet dat harren account oan oaren oanrekommandearre wurdt. Jo kinne ek yndividuele berjochten goed- of ôfkarre.
disallow: Berjocht ôfkarre
disallow_account: Account ôfkarre
@@ -920,6 +976,7 @@ fy:
used_by_over_week:
one: Dizze wike troch ien persoan brûkt
other: Dizze wike troch %{count} persoanen brûkt
+ title: Oanrekommandaasjes & trends
trending: Trending
warning_presets:
add_new: Nije tafoegje
@@ -1004,7 +1061,9 @@ fy:
guide_link_text: Elkenien kin bydrage.
sensitive_content: Gefoelige ynhâld
application_mailer:
+ notification_preferences: E-mailynstellingen wizigje
salutation: "%{name},"
+ settings: 'E-mailfoarkarren wizigje: %{link}'
unsubscribe: Ofmelde
view: 'Besjoch:'
view_profile: Profyl besjen
@@ -1024,6 +1083,7 @@ fy:
hint_html: Noch ien ding! Jo moatte befêstigje dat jo in minske binne (dit is om de spam bûten de doar te hâlden!). Los de ûndersteande CAPTCHA op en klik op ‘Trochgean’.
title: Befeiligingskontrôle
confirmations:
+ awaiting_review: Jo e-mailadres is befêstige! De %{domain}-meiwurkers binne no dwaande mei it besjen fan jo registraasje. Jo ûntfange in e-mailberjocht as de jo account goedkarre!
awaiting_review_title: Jo registraasje wurdt beoardield
clicking_this_link: klik op dizze keppeling
login_link: oanmelde
@@ -1031,6 +1091,7 @@ fy:
redirect_to_app_html: Jo soene omlaad wêze moatte nei de %{app_name} app. As dat net bard is, probearje dan %{clicking_this_link} of kear hânmjittich werom nei de app.
registration_complete: Jo registraasje op %{domain} is no foltôge!
welcome_title: Wolkom, %{name}!
+ wrong_email_hint: As it e-mailadres net korrekt is, kinne jo dat wizigje yn de accountynstellingen.
delete_account: Account fuortsmite
delete_account_html: Wannear’t jo jo account graach fuortsmite wolle, kinne jo dat hjir dwaan. Wy freegje jo dêr om in befêstiging.
description:
@@ -1051,6 +1112,7 @@ fy:
or_log_in_with: Of oanmelde mei
privacy_policy_agreement_html: Ik haw it privacybelied lêzen en gean dêrmei akkoard
progress:
+ confirm: E-mailadres werhelje
details: Jo gegevens
review: Us beoardieling
rules: Regels akseptearje
@@ -1072,8 +1134,10 @@ fy:
security: Befeiliging
set_new_password: Nij wachtwurd ynstelle
setup:
+ email_below_hint_html: Kontrolearje jo map Net-winske, of freegje in nije befêstigingskeppeling oan. Jo kinne jo e-mailadres wizigje as it ferkeard is.
email_settings_hint_html: Klik op de keppeling dy’t wy jo stjoerd hawwe om %{email} te ferifiearjen. Wy wachtsje wol even.
link_not_received: Gjin keppeling krigen?
+ new_confirmation_instructions_sent: Jo ûntfange binnen inkelde minuten in nij e-mailberjocht mei de befêstigingskeppeling!
title: Kontrolearje jo Postfek YN
sign_in:
preamble_html: Meld jo oan mei de oanmeldgegevens fan %{domain}. As jo account op in oare server stiet, kinne jo hjir net oanmelde.
@@ -1084,7 +1148,9 @@ fy:
title: Litte wy jo account op %{domain} ynstelle.
status:
account_status: Accountsteat
+ confirming: Oan it wachtsjen oant it e-mailadres befêstige is.
functional: Jo account kin folslein brûkt wurde.
+ pending: Jo oanfraach moat noch beoardiele wurde troch ien fan ús meiwurkers. Dit kin miskien efkes duorje. Jo ûntfangt in e-mailberjocht wannear’t jo oanfraach goedkard is.
redirecting_to: Jo account is ynaktyf, omdat it op dit stuit trochferwezen wurdt nei %{acct}.
self_destruct: Omdat %{domain} sluten sil, krije jo mar beheind tagong ta jo account.
view_strikes: Besjoch de earder troch moderatoaren fêststelde skeiningen dy’t jo makke hawwe
@@ -1098,7 +1164,6 @@ fy:
crypto:
errors:
invalid_key: is gjin jildige Ed25519- of Curve25519-kaai
- invalid_signature: is gjin jildige Ed25519-hantekening
date:
formats:
default: "%d %b %Y"
@@ -1127,6 +1192,9 @@ fy:
before: 'Lês dizze tekst soarchfâldich eardat jo troch gean:'
caches: Berjochten en media dy’t op oare servers bewarre binne kinne dêr efterbliuwe
data_removal: Jo berjochten en oare gegevens wurde permanint fuortmiten
+ email_change_html: Jo kinne jo e-mailadres wizigje sûnder dat jo jo account fuort hoege te smiten
+ email_contact_html: Wannear’t it noch hieltyd net oankomt, kinne jo foar help in e-mailberjocht stjoere nei %{email}
+ email_reconfirmation_html: Wannear’t jo it befêstigings-e-mailberjocht net ûntfongen hawwe, kinne jo dizze opnij oanfreegje
irreversible: Jo sille net yn steat wêze om jo account te werstellen of te de-aktivearjen
more_details_html: Sjoch it privacybelied foar mear ynformaasje.
username_available: Jo brûkersnamme sil wer beskikber komme
@@ -1161,8 +1229,6 @@ fy:
your_appeal_approved: Jo beswier is goedkard
your_appeal_pending: Jo hawwe in beswier yntsjinne
your_appeal_rejected: Jo beswier is ôfwêzen
- domain_validator:
- invalid_domain: is in ûnjildige domeinnamme
edit_profile:
basic_information: Algemiene ynformaasje
hint_html: "Pas oan wat minsken op jo iepenbiere profyl en njonken jo berjochten sjogge. Oare minsken sille jo earder folgje en mei jo kommunisearje wannear’t jo profyl ynfolle is en jo in profylfoto hawwe."
@@ -1359,6 +1425,7 @@ fy:
authentication_methods:
otp: twa-stapsferifikaasje-app
password: wachtwurd
+ sign_in_token: befeiligingskoade fia e-mailberjocht
webauthn: befeiligingskaaien
description_html: Wannear’t jo aktiviteit sjogge dy’t jo net werkenne, tink dan nei om jo wachtwurd te wizigjen en twa-stapsferifikaasje yn te skeakeljen.
empty: Gjin oanmeldskiednis beskikber
@@ -1369,10 +1436,21 @@ fy:
unsubscribe:
action: Ja, ôfmelde
complete: Ofmelden
+ confirmation_html: Binne jo wis dat jo jo ôfmelde wolle foar it ûntfangen fan %{type} fan Mastodon op %{domain} op jo e-mailadres %{email}? Jo kinne jo altyd opnij abonnearje yn jo ynstellingen foar e-mailmeldingen.
+ emails:
+ notification_emails:
+ favourite: e-mailmeldingen foar favoriten
+ follow: e-mailmeldingen foar nije folgers
+ follow_request: e-mailmeldingen foar folchfersiken
+ mention: e-mailmeldingen foar fermeldingen
+ reblog: e-mailmeldingen foar boosts
+ resubscribe_html: As jo jo mei fersin ôfmeld hawwe, kinne jo jo opnij abonnearje yn jo ynstellingen foar e-mailmeldingen.
+ success_html: Jo ûntfange net langer %{type} fan Mastodon op %{domain} op jo e-mailadres %{email}.
title: Ofmelde
media_attachments:
validations:
images_and_video: In fideo kin net oan in berjocht mei ôfbyldingen keppele wurde
+ not_found: Media %{ids} net fûn of al tafoege oan in oar berjocht
not_ready: Kin gjin bestannen tafoegje dy’t noch net ferwurke binne. Probearje it letter opnij!
too_many: Der kinne net mear as 4 ôfbyldingen tafoege wurde
migrations:
@@ -1449,6 +1527,8 @@ fy:
update:
subject: "%{name} hat in berjocht bewurke"
notifications:
+ administration_emails: E-mailmeldingen behearder
+ email_events: E-mailmeldingen foar eveneminten
email_events_hint: 'Selektearje eveneminten wêrfoar’t jo meldingen ûntfange wolle:'
number:
human:
@@ -1607,6 +1687,7 @@ fy:
import: Ymportearje
import_and_export: Ymportearje en eksportearje
migrate: Accountmigraasje
+ notifications: E-mailmeldingen
preferences: Ynstellingen
profile: Profyl
relationships: Folgers en folgjenden
@@ -1647,23 +1728,12 @@ fy:
edited_at_html: Bewurke op %{date}
errors:
in_reply_not_found: It berjocht wêrop jo probearje te reagearjen liket net te bestean.
- open_in_web: Yn de webapp iepenje
over_character_limit: Oer de limyt fan %{max} tekens
pin_errors:
direct: Berjochten dy’t allinnich sichtber binne foar fermelde brûkers kinne net fêstset wurde
limit: Jo hawwe it maksimaal tal berjochten al fêstmakke
ownership: In berjocht fan in oar kin net fêstmakke wurde
reblog: In boost kin net fêstset wurde
- poll:
- total_people:
- one: "%{count} persoan"
- other: "%{count} persoanen"
- total_votes:
- one: "%{count} stim"
- other: "%{count} stimmen"
- vote: Stimme
- show_more: Mear toane
- show_thread: Petear toane
title: '%{name}: "%{quote}"'
visibilities:
direct: Direkt
@@ -1853,6 +1923,7 @@ fy:
invalid_otp_token: Unjildige twa-stapstagongskoade
otp_lost_help_html: As jo tagong ta beide kwytrekke binne, nim dan kontakt op fia %{email}
rate_limited: Te folle autentikaasjebesykjen, probearje it letter opnij.
+ seamless_external_login: Jo binne oanmeld fia in eksterne tsjinst, dêrom binne wachtwurden en e-mailynstellingen net beskikber.
signed_in_as: 'Oanmeld as:'
verification:
extra_instructions_html: Tip: De keppeling op jo website kin ûnsichtber wêze. It wichtige part is rel="me"
dat ympersonaasje op websites mei user-generated ynhâld foarkomt. Jo kinne sels in link
-label brûke yn de header fan de side yn stee fan a
, mar de HTML moat ek sûnder JavaScript tagonklik wêze.
diff --git a/config/locales/ga.yml b/config/locales/ga.yml
index 9d4d281f4f..a6369354cd 100644
--- a/config/locales/ga.yml
+++ b/config/locales/ga.yml
@@ -7,7 +7,6 @@ ga:
hosted_on: Mastodon arna óstáil ar %{domain}
title: Maidir le
accounts:
- follow: Lean
followers:
few: Leantóirí
many: Leantóirí
@@ -31,6 +30,8 @@ ga:
admin:
account_actions:
action: Déan gníomh
+ already_silenced: Tá teorainn leis an gcuntas seo cheana féin.
+ already_suspended: Tá an cuntas seo curtha ar fionraí cheana féin.
title: Dean gníomh modhnóireachta ar %{acct}
account_moderation_notes:
create: Fág nóta
@@ -52,6 +53,7 @@ ga:
title: Athraigh ríomhphost do %{username}
change_role:
changed_msg: Athraíodh ról go rathúil!
+ edit_roles: Bainistigh róil úsáideora
label: Athraigh ról
no_role: Gan ról
title: Athraigh ról do %{username}
@@ -638,6 +640,7 @@ ga:
suspend_description_html: Beidh an cuntas agus a bhfuil ann go léir dorochtana agus scriosfar iad ar deireadh, agus beidh sé dodhéanta idirghníomhú leis. Inchúlaithe laistigh de 30 lá. Dúnann sé gach tuairisc i gcoinne an chuntais seo.
actions_description_html: Déan cinneadh ar an ngníomh atá le déanamh chun an tuarascáil seo a réiteach. Má dhéanann tú beart pionósach in aghaidh an chuntais tuairiscithe, seolfar fógra ríomhphoist chucu, ach amháin nuair a roghnaítear an chatagóir Turscar.
actions_description_remote_html: Déan cinneadh ar an ngníomh atá le déanamh chun an tuarascáil seo a réiteach. Ní bheidh tionchar aige seo ach ar an gcaoi a ndéanann do fhreastalaí cumarsáid leis an gcianchuntas seo agus a láimhseálann sé a ábhar.
+ actions_no_posts: Níl aon phostáil ghaolmhar ag an tuarascáil seo le scriosadh
add_to_report: Cuir tuilleadh leis an tuairisc
already_suspended_badges:
local: Ar fionraí cheana féin ar an bhfreastalaí seo
@@ -940,6 +943,7 @@ ga:
name: Ainm
newest: Is nuaí
oldest: Is sine
+ open: Amharc go Poiblí
reset: Athshocraigh
review: Stádas athbhreithnithe
search: Cuardach
@@ -1210,6 +1214,12 @@ ga:
view_strikes: Féach ar stailceanna san am atá caite i gcoinne do chuntais
too_fast: Cuireadh an fhoirm isteach róthapa, triail arís.
use_security_key: Úsáid eochair shlándála
+ author_attribution:
+ example_title: Téacs samplach
+ hint_html: Rialú conas a chuirtear chun sochair tú nuair a roinntear naisc ar Mastodon.
+ more_from_html: Tuilleadh ó %{name}
+ s_blog: Blag %{name}
+ title: Leithdháil an údair
challenge:
confirm: Lean ar aghaidh
hint_html: "Leid: Ní iarrfaimid do phasfhocal ort arís go ceann uair an chloig eile."
@@ -1218,7 +1228,6 @@ ga:
crypto:
errors:
invalid_key: nach eochair bhailí Ed25519 nó Curve25519 í
- invalid_signature: nach síniú bailí Ed25519 é
date:
formats:
default: "%b %d, %Y"
@@ -1284,8 +1293,6 @@ ga:
your_appeal_approved: Tá d’achomharc ceadaithe
your_appeal_pending: Chuir tú achomharc isteach
your_appeal_rejected: Diúltaíodh do d'achomharc
- domain_validator:
- invalid_domain: nach ainm fearainn bailí é
edit_profile:
basic_information: Eolas bunúsach
hint_html: "Saincheap a bhfeiceann daoine ar do phróifíl phoiblí agus in aice le do phostálacha. Is dóichí go leanfaidh daoine eile ar ais tú agus go n-idirghníomhóidh siad leat nuair a bhíonn próifíl líonta agus pictiúr próifíle agat."
@@ -1531,6 +1538,7 @@ ga:
media_attachments:
validations:
images_and_video: Ní féidir físeán a cheangal le postáil a bhfuil íomhánna ann cheana féin
+ not_found: Meán %{ids} gan aimsiú nó ceangailte le postáil eile cheana
not_ready: Ní féidir comhaid nach bhfuil próiseáil críochnaithe acu a cheangal. Bain triail eile as i gceann nóiméad!
too_many: Ní féidir níos mó ná 4 chomhad a cheangal
migrations:
@@ -1820,29 +1828,12 @@ ga:
edited_at_html: "%{date} curtha in eagar"
errors:
in_reply_not_found: Is cosúil nach ann don phostáil a bhfuil tú ag iarraidh freagra a thabhairt air.
- open_in_web: Oscail i ngréasán
over_character_limit: teorainn carachtar %{max} sáraithe
pin_errors:
direct: Ní féidir postálacha nach bhfuil le feiceáil ach ag úsáideoirí luaite a phinnáil
limit: Tá uaslíon na bpostálacha pinn agat cheana féin
ownership: Ní féidir postáil duine éigin eile a phionnáil
reblog: Ní féidir treisiú a phinnáil
- poll:
- total_people:
- few: "%{count} daoine"
- many: "%{count} daoine"
- one: "%{count} duine"
- other: "%{count} daoine"
- two: "%{count} daoine"
- total_votes:
- few: "%{count} vótaí"
- many: "%{count} vótaí"
- one: "%{count} vóta"
- other: "%{count} vótaí"
- two: "%{count} vótaí"
- vote: Vótáil
- show_more: Taispeáin níos mó
- show_thread: Taispeáin snáithe
title: '%{name}: "%{quote}"'
visibilities:
direct: Díreach
@@ -2044,6 +2035,7 @@ ga:
instructions_html: Cóipeáil agus greamaigh an cód thíos isteach i HTML do shuíomh Gréasáin. Ansin cuir seoladh do shuíomh Gréasáin isteach i gceann de na réimsí breise ar do phróifíl ón gcluaisín "Cuir próifíl in eagar" agus sábháil athruithe.
verification: Fíorú
verified_links: Do naisc fhíoraithe
+ website_verification: Fíorú láithreán gréasáin
webauthn_credentials:
add: Cuir eochair shlándála nua leis
create:
diff --git a/config/locales/gd.yml b/config/locales/gd.yml
index 9592a86c65..b5cbc4a73e 100644
--- a/config/locales/gd.yml
+++ b/config/locales/gd.yml
@@ -7,7 +7,6 @@ gd:
hosted_on: Mastodon ’ga òstadh air %{domain}
title: Mu dhèidhinn
accounts:
- follow: Lean
followers:
few: Luchd-leantainn
one: Neach-leantainn
@@ -29,6 +28,8 @@ gd:
admin:
account_actions:
action: Gabh an gnìomh
+ already_silenced: Chaidh an cunntas seo a chuingeachadh mu thràth.
+ already_suspended: Chaidh an cunntas seo a chur à rèim mu thràth.
title: Gabh gnìomh maorsainneachd air %{acct}
account_moderation_notes:
create: Fàg nòta
@@ -50,6 +51,7 @@ gd:
title: Atharraich am post-d airson %{username}
change_role:
changed_msg: Chaidh an dreuchd atharrachadh!
+ edit_roles: Stiùirich dreuchdan nan cleachdaichean
label: Atharraich an dreuchd
no_role: Gun dreuchd
title: Atharraich an dreuchd aig %{username}
@@ -626,6 +628,7 @@ gd:
suspend_description_html: Cha ghabh an cunntas seo agus an t-susbaint gu leòr aige inntrigeadh gus an dèid a sguabadh às air deireadh na sgeòil agus cha ghabh eadar-ghabhail a dhèanamh leis. Gabhaidh seo a neo-dhèanamh am broinn 30 latha. Dùinidh seo gach gearan mun chunntas seo.
actions_description_html: Cuir romhad dè nì thu airson an gearan seo fhuasgladh. Ma chuireas tu peanas air a’ chunntas le gearan air, gheibh iad brath air a’ phost-d mura tagh thu an roinn-seòrsa Spama.
actions_description_remote_html: Cuir romhad dè an gnìomh a ghabhas tu airson an gearan seo fhuasgladh. Cha bheir seo buaidh ach air mar a làimhsicheas am frithealaiche agadsa an cunntas cèin seo is mar a nì e conaltradh leis.
+ actions_no_posts: Chan eil post ri sguabadh às ris a’ ghearan seo
add_to_report: Cuir barrachd ris a’ ghearan
already_suspended_badges:
local: Chaidh an cur à rèim air an fhrithealaiche seo mu thràth
@@ -926,6 +929,7 @@ gd:
name: Ainm
newest: As ùire
oldest: As sine
+ open: Seall gu poblach
reset: Ath-shuidhich
review: Dèan lèirmheas air an staid
search: Lorg
@@ -1192,6 +1196,12 @@ gd:
view_strikes: Seall na rabhaidhean a fhuair an cunntas agad roimhe
too_fast: Chaidh am foirm a chur a-null ro luath, feuch ris a-rithist.
use_security_key: Cleachd iuchair tèarainteachd
+ author_attribution:
+ example_title: Ball-sampaill teacsa
+ hint_html: Stùirich mar a thèid iomradh a thoirt ort nuair a thèid ceangal a cho-roinneadh air Mastodon.
+ more_from_html: Barrachd o %{name}
+ s_blog: Bloga aig %{name}
+ title: Aithris air an ùghdar
challenge:
confirm: Lean air adhart
hint_html: "Gliocas: Chan iarr sinn am facal-faire agad ort a-rithist fad uair a thìde."
@@ -1200,7 +1210,6 @@ gd:
crypto:
errors:
invalid_key: "– chan e iuchair Ed25519 no Curve25519 dhligheach a th’ ann"
- invalid_signature: "– chan e soidhneadh Ed25519 dligheach a th’ ann"
date:
formats:
default: "%d %b %Y"
@@ -1266,8 +1275,6 @@ gd:
your_appeal_approved: Chaidh aontachadh ris an ath-thagradh agad
your_appeal_pending: Chuir thu ath-thagradh a-null
your_appeal_rejected: Chaidh an t-ath-thagradh agad a dhiùltadh
- domain_validator:
- invalid_domain: "– chan eil seo ’na ainm àrainne dligheach"
edit_profile:
basic_information: Fiosrachadh bunasach
hint_html: "Gnàthaich na chithear air a’ phròifil phoblach agad is ri taobh nam postaichean agad. Bidh càch nas buailtiche do leantainn agus conaltradh leat nuair a bhios tu air a’ phròifil agad a lìonadh agus dealbh rithe."
@@ -1505,6 +1512,7 @@ gd:
media_attachments:
validations:
images_and_video: Chan urrainn dhut video a cheangal ri post sa bheil dealbh mu thràth
+ not_found: Cha deach na meadhanan %{ids} a lorg no chaidh an ceangal ri post eile mu thràth
not_ready: Chan urrainn dhuinn faidhlichean a cheangal ris nach eil air am pròiseasadh fhathast. Feuch ris a-rithist an ceann greis!
too_many: Chan urrainn dhut barrachd air 4 faidhlichean a ceangal ris
migrations:
@@ -1790,27 +1798,12 @@ gd:
edited_at_html: Air a dheasachadh %{date}
errors:
in_reply_not_found: Tha coltas nach eil am post dhan a tha thu airson freagairt ann.
- open_in_web: Fosgail air an lìon
over_character_limit: chaidh thu thar crìoch charactaran de %{max}
pin_errors:
direct: Chan urrainn dhut post a phrìneachadh nach fhaic ach na cleachdaichean le iomradh orra
limit: Tha an àireamh as motha de phostaichean prìnichte agad a tha ceadaichte
ownership: Chan urrainn dhut post càich a phrìneachadh
reblog: Chan urrainn dhut brosnachadh a phrìneachadh
- poll:
- total_people:
- few: "%{count} daoine"
- one: "%{count} neach"
- other: "%{count} duine"
- two: "%{count} neach"
- total_votes:
- few: "%{count} bhòtaichean"
- one: "%{count} bhòt"
- other: "%{count} bhòt"
- two: "%{count} bhòt"
- vote: Bhòt
- show_more: Seall barrachd dheth
- show_thread: Seall an snàithlean
title: "%{name}: “%{quote}”"
visibilities:
direct: Dìreach
@@ -2011,6 +2004,7 @@ gd:
instructions_html: Dèan lethbhreac dhen chòd gu h-ìosal is cuir a-steach ann an HTML na làraich-lìn agad e. An uairsin, cuir seòladh na làraich-lìn agad ri fear dhe na raointean a bharrachd air a’ phròifil agad o thaba “Deasaich a’ phròifil” agus sàbhail na h-atharraichean.
verification: Dearbhadh
verified_links: Na ceanglaichean dearbhte agad
+ website_verification: Dearbhadh làraich-lìn
webauthn_credentials:
add: Cuir iuchair tèarainteachd ùr ris
create:
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index 71df4c8d93..9813514a7b 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -7,7 +7,6 @@ gl:
hosted_on: Mastodon aloxado en %{domain}
title: Sobre
accounts:
- follow: Seguir
followers:
one: Seguidora
other: Seguidoras
@@ -25,6 +24,8 @@ gl:
admin:
account_actions:
action: Executar acción
+ already_silenced: A conta xa está limitada
+ already_suspended: Esta conta xa está suspendida.
title: Executar acción de moderación a %{acct}
account_moderation_notes:
create: Deixar nota
@@ -46,6 +47,7 @@ gl:
title: Mudar email de %{username}
change_role:
changed_msg: Rol mudado correctamente!
+ edit_roles: Xestionar roles de usuarias
label: Cambiar rol
no_role: Sen rol
title: Cambiar o rol de %{username}
@@ -343,7 +345,7 @@ gl:
title: Emoticonas personalizadas
uncategorized: Sen categoría
unlist: Non listar
- unlisted: Sen listar
+ unlisted: Fóra das listas
update_failed_msg: Non foi posíbel actualizar a emoticona
updated_msg: Actualizouse a emoticona de xeito correcto!
upload: Subir
@@ -602,6 +604,7 @@ gl:
suspend_description_html: A conta e todo o seu contido non serán accesible e finalmente eliminaranse, será imposible interactuar con ela. A decisión é reversible durante 30 días. Isto pecha tódalas denuncias sobre esta conta.
actions_description_html: Decide a acción a tomar para resolver esta denuncia. Se tomas accións punitivas contra a conta denunciada enviaraselle un correo, excepto se está indicada a categoría Spam.
actions_description_remote_html: Decide a acción a tomar para resolver a denuncia. Isto só lle afecta ao xeito en que o teu servidor se comunica con esta conta remota e xestiona o seu contido.
+ actions_no_posts: Esta denuncia non ten publicacións asociadas para eliminar
add_to_report: Engadir máis á denuncia
already_suspended_badges:
local: Xa está suspendida neste servidor
@@ -1157,6 +1160,12 @@ gl:
view_strikes: Ver avisos anteriores respecto da túa conta
too_fast: Formulario enviado demasiado rápido, inténtao outra vez.
use_security_key: Usa chave de seguridade
+ author_attribution:
+ example_title: Texto de mostra
+ hint_html: Controla o xeito en que te acreditan cando se comparten ligazóns en Mastodon.
+ more_from_html: Máis de %{name}
+ s_blog: Blog de %{name}
+ title: Atribución da autoría
challenge:
confirm: Continuar
hint_html: "Nota: Non che pediremos o contrasinal na seguinte hora."
@@ -1165,7 +1174,6 @@ gl:
crypto:
errors:
invalid_key: non é unha chave Ed25519 ou Curve25519 válida
- invalid_signature: non é unha sinatura Ed25519 válida
date:
formats:
default: "%d %b, %Y"
@@ -1231,8 +1239,6 @@ gl:
your_appeal_approved: A apelación foi aprobada
your_appeal_pending: Enviaches unha apelación
your_appeal_rejected: A apelación foi rexeitada
- domain_validator:
- invalid_domain: non é un nome de dominio válido
edit_profile:
basic_information: Información básica
hint_html: "Personaliza o que van ver no teu perfil público e ao lado das túas publicacións. As outras persoas estarán máis animadas a seguirte e interactuar contigo se engades algún dato sobre ti así como unha imaxe de perfil."
@@ -1454,6 +1460,7 @@ gl:
media_attachments:
validations:
images_and_video: Non podes anexar un vídeo a unha publicación que xa contén imaxes
+ not_found: Non se atopou o multimedia %{ids} ou xa é adxunto noutra publicación
not_ready: Non se poden anexar ficheiros que aínda se están a procesar. Agarda un intre!
too_many: Non pode anexar máis de 4 ficheiros
migrations:
@@ -1731,23 +1738,12 @@ gl:
edited_at_html: Editado %{date}
errors:
in_reply_not_found: A publicación á que tentas responder semella que non existe.
- open_in_web: Abrir na web
over_character_limit: Excedeu o límite de caracteres %{max}
pin_errors:
direct: As publicacións que só son visibles para as usuarias mencionadas non se poden fixar
limit: Xa fixaches o número máximo permitido de publicacións
ownership: Non podes fixar a publicación doutra usuaria
reblog: Non se poden fixar as mensaxes promovidas
- poll:
- total_people:
- one: "%{count} persoa"
- other: "%{count} persoas"
- total_votes:
- one: "%{count} voto"
- other: "%{count} votos"
- vote: Votar
- show_more: Mostrar máis
- show_thread: Amosar fío
title: '%{name}: "%{quote}"'
visibilities:
direct: Directa
@@ -1755,7 +1751,7 @@ gl:
private_long: Mostrar só as seguidoras
public: Público
public_long: Visible para calquera
- unlisted: Sen listar
+ unlisted: Fóra das listas
unlisted_long: Visible para calquera, pero non en cronoloxías públicas
statuses_cleanup:
enabled: Borrar automáticamente publicacións antigas
@@ -1849,7 +1845,7 @@ gl:
failed_2fa:
details: 'Detalles do intento de acceso:'
explanation: Alguén intentou acceder á túa conta mais fíxoo cun segundo factor de autenticación non válido.
- further_actions_html: Se non foches ti, recomendámosche %{action} inmediatamente xa que a conta podería estar en risco.
+ further_actions_html: Se non foches ti, recomendámosche %{action} inmediatamente porque a conta podería estar en risco.
subject: Fallo co segundo factor de autenticación
title: Fallou o segundo factor de autenticación
suspicious_sign_in:
@@ -1946,6 +1942,7 @@ gl:
instructions_html: Copia e pega o código inferior no HTML do teu sitio web. Despois engade o enderezo da túa web nun dos campos de datos extra do teu perfil dispoñibles na lapela "Editar perfil" e garda os cambios.
verification: Validación
verified_links: As túas ligazóns verificadas
+ website_verification: Verificación do sitio web
webauthn_credentials:
add: Engadir nova chave de seguridade
create:
diff --git a/config/locales/he.yml b/config/locales/he.yml
index 72b4156dbf..13a1f6f05d 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -7,7 +7,6 @@ he:
hosted_on: מסטודון שיושב בכתובת %{domain}
title: אודות
accounts:
- follow: לעקוב
followers:
many: עוקבים
one: עוקב
@@ -29,6 +28,8 @@ he:
admin:
account_actions:
action: בצע/י פעולה
+ already_silenced: חשבון זה הוגבל זה מכבר.
+ already_suspended: חשבון זה הושעה.
title: ביצוע פעולות הנהלה על %{acct}
account_moderation_notes:
create: ליצור
@@ -50,6 +51,7 @@ he:
title: שינוי כתובת דוא"ל עבור המשתמש.ת %{username}
change_role:
changed_msg: התפקיד שונה בהצלחה!
+ edit_roles: נהל תפקידי משתמש
label: שינוי תפקיד
no_role: ללא תפקיד
title: שינוי תפקיד עבור %{username}
@@ -626,6 +628,7 @@ he:
suspend_description_html: חשבון זה על כל תכניו יחסמו וברבות הימים ימחקו, כל פעילות מולו לא תתאפשר. הפעולה ניתנת לביטול תוך 30 ימים, והיא תסגור כל דיווח התלוי ועומד נגד החשבון.
actions_description_html: בחר/י איזו פעולה לבצע על מנת לפתור את הדו"ח. אם תופעל פעולת ענישה כנגד החשבון המדווח, הודעת דוא"ל תשלח אליהם, אלא אם נבחרה קטגוריית הספאם.
actions_description_remote_html: בחרו איזו פעולה לבצע כדי לפתור את הדיווח שהוגש. פעולה זו תשפיע רק על התקשורת מול השרת שלך עם החשבון המרוחק ותוכנו.
+ actions_no_posts: דווח זה לא כולל הודעות למחיקה
add_to_report: הוספת פרטים לדיווח
already_suspended_badges:
local: כבר הודח בשרת זה
@@ -1193,6 +1196,12 @@ he:
view_strikes: צפיה בעברות קודמות שנרשמו נגד חשבונך
too_fast: הטופס הוגש מהר מדי, נסה/י שוב.
use_security_key: שימוש במפתח אבטחה
+ author_attribution:
+ example_title: טקסט לדוגמה
+ hint_html: בחירה איך תקבלו קרדיטציה כאשר קישורים משותפים דרך מסטודון.
+ more_from_html: עוד מאת %{name}
+ s_blog: הבלוג של %{name}
+ title: ייחוס למפרסם
challenge:
confirm: המשך
hint_html: "טיפ: לא נבקש את סיסמתך שוב בשעה הקרובה."
@@ -1201,7 +1210,6 @@ he:
crypto:
errors:
invalid_key: זהו לא מפתח Ed25519 או Curve25519 קביל
- invalid_signature: היא לא חתימת Ed25519 קבילה
date:
formats:
default: "%b %d, %Y"
@@ -1267,8 +1275,6 @@ he:
your_appeal_approved: ערעורך התקבל
your_appeal_pending: הגשת ערעור
your_appeal_rejected: ערעורך נדחה
- domain_validator:
- invalid_domain: הוא לא שם דומיין קביל
edit_profile:
basic_information: מידע בסיסי
hint_html: "התאמה אישית של מה שיראו אחרים בפרופיל הציבורי שלך וליד הודעותיך. אחרים עשויים יותר להחזיר עוקב וליצור אתך שיחה אם הפרופיל והתמונה יהיו מלאים."
@@ -1506,6 +1512,7 @@ he:
media_attachments:
validations:
images_and_video: לא ניתן להוסיף וידאו להודעה שכבר מכילה תמונות
+ not_found: קובץ %{ids} לא נמצא, או שהוצמד כבר להודעה אחרת
not_ready: לא ניתן להצמיד קבצים שהעלאתם לא הסתיימה. נסה/י שוב בעוד רגע!
too_many: לא ניתן להוסיף יותר מארבעה קבצים
migrations:
@@ -1791,27 +1798,12 @@ he:
edited_at_html: נערך ב-%{date}
errors:
in_reply_not_found: נראה שההודעה שאת/ה מנסה להגיב לה לא קיימת.
- open_in_web: פתח ברשת
over_character_limit: חריגה מגבול התווים של %{max}
pin_errors:
direct: לא ניתן לקבע הודעות שנראותן מוגבלת למכותבים בלבד
limit: הגעת למספר המירבי של ההודעות המוצמדות
ownership: הודעות של אחרים לא יכולות להיות מוצמדות
reblog: אין אפשרות להצמיד הדהודים
- poll:
- total_people:
- many: "%{count} אנשים"
- one: איש/ה %{count}
- other: "%{count} אנשים"
- two: "%{count} אנשים"
- total_votes:
- many: "%{count} קולות"
- one: קול %{count}
- other: "%{count} קולות"
- two: "%{count} קולות"
- vote: הצבעה
- show_more: עוד
- show_thread: הצג שרשור
title: '%{name}: "%{quote}"'
visibilities:
direct: ישיר
@@ -2012,6 +2004,7 @@ he:
instructions_html: יש להדביק את הקוד שלמטה אל האתר שלך. ואז להוסיף את כתובת האתר לאחד השדות הנוספים בפרופיל מתוך טאב "עריכת פרופיל" ולשמור את השינויים.
verification: אימות
verified_links: קישוריך המאומתים
+ website_verification: אימות אתר רשת
webauthn_credentials:
add: הוספת מפתח אבטחה חדש
create:
diff --git a/config/locales/hi.yml b/config/locales/hi.yml
index 60b500c7ec..37df2afe1a 100644
--- a/config/locales/hi.yml
+++ b/config/locales/hi.yml
@@ -5,7 +5,6 @@ hi:
contact_unavailable: लागू नहीं है
title: के बारे में
accounts:
- follow: अनुसरे
following: फ़ॉलो कर रहे हैं
instance_actor_flash: यह खाता आभासी है जो सर्वर को दिखाने के लिये है और ये किसी व्यक्तिका प्रतिनिधित्व नहि करता। यह सिर्फ देखरेख के हेतु से कार्यरत है और इसको निलंबित करने कि आवश्यकता नहि है।
last_active: आखिरि बार इस वक्त सक्रिय थे
diff --git a/config/locales/hr.yml b/config/locales/hr.yml
index 6a67ea0129..7dacf20077 100644
--- a/config/locales/hr.yml
+++ b/config/locales/hr.yml
@@ -5,7 +5,6 @@ hr:
contact_missing: Nije postavljeno
title: O aplikaciji
accounts:
- follow: Prati
following: Praćenih
last_active: posljednja aktivnost
nothing_here: Ovdje nema ničeg!
@@ -215,20 +214,7 @@ hr:
statuses_cleanup: Automatsko brisanje postova
two_factor_authentication: Dvofaktorska autentifikacija
statuses:
- open_in_web: Otvori na webu
over_character_limit: prijeđeno je ograničenje od %{max} znakova
- poll:
- total_people:
- few: "%{count} osobe"
- one: "%{count} osoba"
- other: "%{count} ljudi"
- total_votes:
- few: "%{count} glasa"
- one: "%{count} glas"
- other: "%{count} glasova"
- vote: Glasaj
- show_more: Prikaži više
- show_thread: Prikaži nit
visibilities:
private: Samo pratitelji
public: Javno
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index cdddc79b0e..9767c48834 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -7,7 +7,6 @@ hu:
hosted_on: "%{domain} Mastodon-kiszolgáló"
title: Névjegy
accounts:
- follow: Követés
followers:
one: Követő
other: Követő
@@ -25,6 +24,8 @@ hu:
admin:
account_actions:
action: Művelet végrehajtása
+ already_silenced: Ezt a fiókot már korlátozták.
+ already_suspended: Ezt a fiókot már felfüggesztették.
title: 'Moderálási művelet végrehajtása ezen: %{acct}'
account_moderation_notes:
create: Megjegyzés hagyása
@@ -46,6 +47,7 @@ hu:
title: "%{username} e-mail-címének megváltoztatása"
change_role:
changed_msg: A szerep sikeresen megváltoztatva!
+ edit_roles: Felhasználói szerepkörök kezelése
label: Szerep megváltoztatása
no_role: Nincs szerep
title: "%{username} szerepének megváltoztatása"
@@ -602,6 +604,7 @@ hu:
suspend_description_html: A fiók és minden tartalma elérhetetlenné válik és végül törlésre kerül. A fiókkal kapcsolatbalépni lehetetlen lesz. Ez a művelet 30 napig visszafordítható. A fiók ellen indított minden bejelentést lezárunk.
actions_description_html: Döntsd el, mit csináljunk, hogy megoldjuk ezt a bejelentést. Ha valamilyen büntető intézkedést hozol a bejelentett fiók ellen, küldünk neki egy figyelmeztetést e-mailben, kivéve ha a Spam kategóriát választod.
actions_description_remote_html: Döntsd el, mit tegyünk a bejelentés lezárásának érdekében. Ez csak azt befolyásolja, hogy a saját kiszolgálód hogyan kommunikál ezzel a távoli fiókkal és hogyan kezeli annak tartalmait.
+ actions_no_posts: Ennek a bejelentésnek nincs egyetlen törölhető, társított bejegyzése sem
add_to_report: Továbbiak hozzáadása a bejelentéshez
already_suspended_badges:
local: Már felfüggesztették ezen a szerveren
@@ -1157,6 +1160,12 @@ hu:
view_strikes: Fiókod ellen felrótt korábbi vétségek megtekintése
too_fast: Túl gyorsan küldted el az űrlapot, próbáld később.
use_security_key: Biztonsági kulcs használata
+ author_attribution:
+ example_title: Mintaszöveg
+ hint_html: Szabályozd, hogyan hivatkoznak rád, amikor linket osztanak meg Mastodonon.
+ more_from_html: 'Több tőle: %{name}'
+ s_blog: "%{name} blogja"
+ title: Szerző forrásmegjelölése
challenge:
confirm: Folytatás
hint_html: "Hasznos: Nem fogjuk megint a jelszavadat kérdezni a következő órában."
@@ -1165,7 +1174,6 @@ hu:
crypto:
errors:
invalid_key: érvénytelen Ed25519 vagy Curve25519 kulcs
- invalid_signature: érvénytelen Ed25519 aláírás
date:
formats:
default: "%Y. %b %d."
@@ -1231,8 +1239,6 @@ hu:
your_appeal_approved: A fellebbezésedet jóváhagyták
your_appeal_pending: Beküldtél egy fellebbezést
your_appeal_rejected: A fellebbezésedet visszautasították
- domain_validator:
- invalid_domain: nem egy valódi domain név
edit_profile:
basic_information: Általános információk
hint_html: "Tedd egyedivé, mi látnak mások a profilodon és a bejegyzéseid mellett. Mások nagyobb eséllyel követnek vissza és lépnek veled kapcsolatba, ha van kitöltött profilod és profilképed."
@@ -1454,6 +1460,7 @@ hu:
media_attachments:
validations:
images_and_video: Nem csatolhatsz videót olyan bejegyzéshez, amelyhez már csatoltál képet
+ not_found: A(z) %{ids} média nem található, vagy már egy másik bejegyzéshez lett csatolva
not_ready: Nem lehet olyan fájlt csatolni, melynek még nem fejeződött be a feldolgozása. Próbáld kicsit később!
too_many: Maximum négy fájlt csatolhatsz
migrations:
@@ -1731,23 +1738,12 @@ hu:
edited_at_html: 'Szerkesztve: %{date}'
errors:
in_reply_not_found: Már nem létezik az a bejegyzés, melyre válaszolni szeretnél.
- open_in_web: Megnyitás a weben
over_character_limit: túllépted a maximális %{max} karakteres keretet
pin_errors:
direct: A csak a megemlített felhasználók számára látható bejegyzések nem tűzhetők ki
limit: Elérted a kitűzhető bejegyzések maximális számát
ownership: Nem tűzheted ki valaki más bejegyzését
reblog: Megtolt bejegyzést nem tudsz kitűzni
- poll:
- total_people:
- one: "%{count} személy"
- other: "%{count} személy"
- total_votes:
- one: "%{count} szavazat"
- other: "%{count} szavazat"
- vote: Szavazás
- show_more: Több megjelenítése
- show_thread: Szál mutatása
title: "%{name}: „%{quote}”"
visibilities:
direct: Közvetlen
@@ -1944,8 +1940,9 @@ hu:
here_is_how: Itt van, hogyan kell
hint_html: "A személyazonosságod ellenőrizhetősége a Mastodonon mindenki számára elérhető. Ez nyílt webes szabványok alapján, most és mindörökké szabadon és ingyenesen történik. Ehhez csak egy saját weboldalra van szükséged, mely alapján mások felismernek téged. Ha a profilodról erre a weboldalra hivatkozol, mi ellenőrizzük, hogy erről az oldalról visszahivatkozol-e a profilodra, és siker esetén erről vizuális jelzést is adunk a profilodon."
instructions_html: Az alábbi kódot másold be a weboldalad HTML kódjába. Ezután add hozzá a weboldalad címét a profilod egyik extra mezőjéhez a "Profil szerkesztése" fülön és mentsd a változásokat.
- verification: Hitelesítés
+ verification: Ellenőrzés
verified_links: Ellenőrzött hivatkozásaid
+ website_verification: Weboldal ellenőrzése
webauthn_credentials:
add: Biztonsági kulcs hozzáadása
create:
diff --git a/config/locales/hy.yml b/config/locales/hy.yml
index dfb280ac48..1fda020c07 100644
--- a/config/locales/hy.yml
+++ b/config/locales/hy.yml
@@ -7,7 +7,6 @@ hy:
hosted_on: Մաստոդոնը տեղակայուած է %{domain}ում
title: Մասին
accounts:
- follow: Հետևել
followers:
one: Հետեւորդ
other: Հետևորդներ
@@ -496,7 +495,6 @@ hy:
crypto:
errors:
invalid_key: անվաւեր Ed25519 կամ Curve25519 բանալի
- invalid_signature: անվաւեր Ed25519 բանալի
date:
formats:
default: "%b %d, %Y"
@@ -523,8 +521,6 @@ hy:
success_msg: Հաշիւդ բարեյաջող ջնջուեց
warning:
username_available: Քո օգտանունը կրկին հասանելի կը դառնայ
- domain_validator:
- invalid_domain: անվաւէր տիրոյթի անուն
errors:
'404': Էջը, որը փնտրում ես գոյութիւն չունի։
'429': Չափազանց շատ հարցումներ
@@ -784,18 +780,7 @@ hy:
other: "%{count} վիդեո"
content_warning: Նախազգուշացում։ %{warning}
edited_at_html: Խմբագրուած՝ %{date}
- open_in_web: Բացել վէբում
over_character_limit: "%{max} նիշի սահմանը գերազանցուած է"
- poll:
- total_people:
- one: "%{count} մարդ"
- other: "%{count} մարդիկ"
- total_votes:
- one: "%{count} ձայն"
- other: "%{count} ձայներ"
- vote: Քուէարկել
- show_more: Աւելին
- show_thread: Բացել շղթան
title: '%{name}: "%{quote}"'
visibilities:
direct: Հասցէագրուած
diff --git a/config/locales/ia.yml b/config/locales/ia.yml
index 698c7c49e1..6632af061e 100644
--- a/config/locales/ia.yml
+++ b/config/locales/ia.yml
@@ -7,7 +7,6 @@ ia:
hosted_on: Mastodon albergate sur %{domain}
title: A proposito
accounts:
- follow: Sequer
followers:
one: Sequitor
other: Sequitores
@@ -25,12 +24,15 @@ ia:
admin:
account_actions:
action: Exequer action
+ already_silenced: Iste conto jam ha essite limitate.
+ already_suspended: Iste conto jam ha essite suspendite.
title: Exequer action de moderation sur %{acct}
account_moderation_notes:
create: Lassar un nota
created_msg: Nota de moderation create con successo!
destroyed_msg: Nota de moderation destruite con successo!
accounts:
+ add_email_domain_block: Blocar dominio de e-mail
approve: Approbar
approved_msg: Demanda de inscription de %{username} approbate con successo
are_you_sure: Es tu secur?
@@ -45,6 +47,7 @@ ia:
title: Cambiar e-mail pro %{username}
change_role:
changed_msg: Rolo cambiate con successo!
+ edit_roles: Gerer le regulas de usator
label: Cambiar rolo
no_role: Necun rolo
title: Cambiar rolo pro %{username}
@@ -57,6 +60,7 @@ ia:
demote: Degradar
destroyed_msg: Le datos de %{username} es ora in cauda pro lor imminente deletion
disable: Gelar
+ disable_sign_in_token_auth: Disactivar le authentication per token in e-mail
disable_two_factor_authentication: Disactivar A2F
disabled: Gelate
display_name: Nomine a monstrar
@@ -65,6 +69,7 @@ ia:
email: E-mail
email_status: Stato de e-mail
enable: Disgelar
+ enable_sign_in_token_auth: Activar le authentication per token in e-mail
enabled: Activate
enabled_msg: Conto de %{username} disgelate con successo
followers: Sequitores
@@ -129,6 +134,7 @@ ia:
resubscribe: Resubscriber
role: Rolo
search: Cercar
+ search_same_email_domain: Altere usatores con le mesme dominio de e-mail
search_same_ip: Altere usatores con le mesme IP
security: Securitate
security_measures:
@@ -169,21 +175,26 @@ ia:
approve_appeal: Approbar appello
approve_user: Approbar usator
assigned_to_self_report: Assignar reporto
+ change_email_user: Cambiar e-mail pro le usator
change_role_user: Cambiar le rolo del usator
confirm_user: Confirmar le usator
create_account_warning: Crear un advertimento
create_announcement: Crear annuncio
+ create_canonical_email_block: Crear blocada de e-mail
create_custom_emoji: Crear emoji personalisate
create_domain_allow: Crear permisso de dominio
create_domain_block: Crear blocada de dominio
+ create_email_domain_block: Crear blocada de dominio de e-mail
create_ip_block: Crear un regula IP
create_unavailable_domain: Crear dominio indisponibile
create_user_role: Crear un rolo
demote_user: Degradar usator
destroy_announcement: Deler annuncio
+ destroy_canonical_email_block: Deler blocada de e-mail
destroy_custom_emoji: Deler emoji personalisate
destroy_domain_allow: Deler permisso de dominio
destroy_domain_block: Deler blocada de dominio
+ destroy_email_domain_block: Deler blocada de dominio de e-mail
destroy_instance: Purgar dominio
destroy_ip_block: Deler le regula IP
destroy_status: Deler message
@@ -191,8 +202,10 @@ ia:
destroy_user_role: Destruer rolo
disable_2fa_user: Disactivar A2F
disable_custom_emoji: Disactivar emoji personalisate
+ disable_sign_in_token_auth_user: Disactivar le authentication per token de e-mail pro le usator
disable_user: Disactivar le usator
enable_custom_emoji: Activar emoji personalisate
+ enable_sign_in_token_auth_user: Activar le authentication per token de e-mail pro le usator
enable_user: Activar le usator
memorialize_account: Converter conto in memorial
promote_user: Promover usator
@@ -222,20 +235,26 @@ ia:
approve_appeal_html: "%{name} approbava appello del decision de moderation de %{target}"
approve_user_html: "%{name} approbava inscription de %{target}"
assigned_to_self_report_html: "%{name} assignava reporto %{target} a se mesme"
+ change_email_user_html: "%{name} cambiava le adresse de e-mail address del usator %{target}"
change_role_user_html: "%{name} cambiava rolo de %{target}"
+ confirm_user_html: "%{name} confirmava le adresse de e-mail del. usator %{target}"
create_account_warning_html: "%{name} inviava un advertimento a %{target}"
create_announcement_html: "%{name} creava un nove annuncio %{target}"
+ create_canonical_email_block_html: "%{name} blocava le e-mail con le hash %{target}"
create_custom_emoji_html: "%{name} incargava le nove emoji %{target}"
create_domain_allow_html: "%{name} permitteva federation con dominio %{target}"
create_domain_block_html: "%{name} blocava dominio %{target}"
+ create_email_domain_block_html: "%{name} blocava le dominio de e-mail %{target}"
create_ip_block_html: "%{name} creava regula pro IP %{target}"
create_unavailable_domain_html: "%{name} stoppava livration al dominio %{target}"
create_user_role_html: "%{name} creava rolo de %{target}"
demote_user_html: "%{name} degradava usator %{target}"
destroy_announcement_html: "%{name} deleva annuncio %{target}"
+ destroy_canonical_email_block_html: "%{name} disblocava le e-mail con le hash %{target}"
destroy_custom_emoji_html: "%{name} deleva emoji %{target}"
destroy_domain_allow_html: "%{name} impediva le federation con dominio %{target}"
destroy_domain_block_html: "%{name} disblocava dominio %{target}"
+ destroy_email_domain_block_html: "%{name} disblocava le dominio de e-mail %{target}"
destroy_instance_html: "%{name} purgava le dominio %{target}"
destroy_ip_block_html: "%{name} deleva le regula pro IP %{target}"
destroy_status_html: "%{name} removeva un message de %{target}"
@@ -243,8 +262,10 @@ ia:
destroy_user_role_html: "%{name} deleva le rolo %{target}"
disable_2fa_user_html: "%{name} disactivava le authentication a duo factores pro le usator %{target}"
disable_custom_emoji_html: "%{name} disactivava le emoji %{target}"
+ disable_sign_in_token_auth_user_html: "%{name} disactivava le authentication per token de e-mail pro %{target}"
disable_user_html: "%{name} disactivava le apertura de session pro le usator %{target}"
enable_custom_emoji_html: "%{name} activava le emoji %{target}"
+ enable_sign_in_token_auth_user_html: "%{name} activava le authentication per token de e-mail pro %{target}"
enable_user_html: "%{name} activava le apertura de session pro le usator %{target}"
memorialize_account_html: "%{name} converteva le conto de %{target} in un pagina commemorative"
promote_user_html: "%{name} promoveva le usator %{target}"
@@ -252,6 +273,7 @@ ia:
reject_user_html: "%{name} refusava le inscription de %{target}"
remove_avatar_user_html: "%{name} removeva le avatar de %{target}"
reopen_report_html: "%{name} reaperiva le reporto %{target}"
+ resend_user_html: "%{name} reinviava le e-mail de confirmation pro %{target}"
reset_password_user_html: "%{name} reinitialisava le contrasigno del usator %{target}"
resolve_report_html: "%{name} resolveva le reporto %{target}"
sensitive_account_html: "%{name} marcava le multimedia de %{target} como sensibile"
@@ -412,6 +434,7 @@ ia:
attempts_over_week:
one: "%{count} tentativa de inscription in le ultime septimana"
other: "%{count} tentativas de inscription in le ultime septimana"
+ created_msg: Le dominio de e-mail ha essite blocate con successo
delete: Deler
dns:
types:
@@ -420,8 +443,12 @@ ia:
new:
create: Adder un dominio
resolve: Resolver dominio
+ title: Blocar un nove dominio de e-mail
+ no_email_domain_block_selected: Necun blocadas de dominio de e-mail ha essite cambiate perque necun ha essite seligite
not_permitted: Non permittite
+ resolved_dns_records_hint_html: Le nomine de dominio se resolve al sequente dominios MX, le quales ha le ultime responsibilitate pro le reception de e-mail. Blocar un dominio MX blocara le inscriptiones de qualcunque adresse de e-mail que usa le mesme dominio MX, mesmo si le nomine de dominio visibile es differente. Presta attention a evitar de blocar le grande fornitores de e-mail.
resolved_through_html: Resolvite per %{domain}
+ title: Dominios de e-mail blocate
export_domain_allows:
new:
title: Importar permissiones de dominio
@@ -636,6 +663,7 @@ ia:
delete_data_html: Deler le profilo e contento de @%{acct} in 30 dies excepte si le suspension es disfacite intertanto
preview_preamble_html: "@%{acct} recipera un advertimento con le sequente contento:"
record_strike_html: Registra un sanction contra @%{acct} pro adjutar te a prender mesuras adequate in caso de futur violationes committite desde iste conto
+ send_email_html: Inviar un e-mail de advertimento a @%{acct}
warning_placeholder: Motivation supplementari facultative pro le action de moderation.
target_origin: Origine del conto reportate
title: Reportos
@@ -675,6 +703,7 @@ ia:
manage_appeals: Gerer appellos
manage_appeals_description: Permitte que usatores revide appellos contra actiones de moderation
manage_blocks: Gerer blocadas
+ manage_blocks_description: Permitter que usatores bloca le fornitores de e-mail e le adresses IP
manage_custom_emojis: Gerer emojis personalisate
manage_custom_emojis_description: Permitte que usatores gere emojis personalisate sur le servitor
manage_federation: Gerer federation
@@ -692,6 +721,7 @@ ia:
manage_taxonomies: Gerer taxonomias
manage_taxonomies_description: Permitte que usatores revide contento in tendentias e actualisa le parametros de hashtag
manage_user_access: Gerer le accesso de usatores
+ manage_user_access_description: Permitte que usatores disactiva le authentication bifactorial de altere usatores, cambia lor adresses de e-mail, e reinitialisa lor contrasigno
manage_users: Gerer usatores
manage_users_description: Permitte que usatores vide le detalios de altere usatores e exeque actiones de moderation contra illes
manage_webhooks: Gerer Webhooks
@@ -766,6 +796,7 @@ ia:
destroyed_msg: Le file incargate al sito ha essite delite!
software_updates:
critical_update: Critic – per favor, actualisa rapidemente
+ description: Il es recommendate mantener tu installation de Mastodon actualisate pro beneficiar del ultime reparationes e functiones. In ultra, de tempore a tempore, il es de importantia critic actualisar Mastodon in tempore utile pro evitar problemas de securitate. Pro iste rationes, Mastodon verifica le presentia de actualisationes cata 30 minutas, e te notificara secundo tu preferentias de notification in e-mail.
documentation_link: Pro saper plus
release_notes: Notas de version
title: Actualisationes disponibile
@@ -853,6 +884,7 @@ ia:
message_html: "Tu immagazinage de objectos es mal configurate. Le confidentialitate de tu usatores es in risco."
tags:
moderation:
+ not_trendable: Non pro tendentia
pending_review: Attende revision
title: Stato
name: Nomine
@@ -868,10 +900,15 @@ ia:
allow: Permitter
approved: Approbate
confirm_allow: Es tu secur que tu vole permitter le etiquettas seligite?
+ confirm_disallow: Es tu secur que tu vole cessar de permitter le etiquettas seligite?
disallow: Refusar
links:
allow: Permitter ligamine
allow_provider: Autorisar le publicator
+ confirm_allow: Es tu secur que tu vole permitter le ligamines seligite?
+ confirm_allow_provider: Es tu secur que tu vole permitter le fornitores seligite?
+ confirm_disallow: Es tu secur que tu vole cessar de permitter le ligamines seligite?
+ confirm_disallow_provider: Es tu secur que tu vole cessar de permitter le fornitores seligite?
description_html: Istes es ligamines que es actualmente compartite multo per contos del quales tu servitor recipe messages. Illos pote adjutar tu usatores a discoperir lo que eveni in le mundo. Necun ligamine es monstrate publicamente usque tu autorisa le publicator. Tu pote tamben permitter o rejectar ligamines singule.
disallow: Prohibir le ligamine
disallow_provider: Prohibir le publicator
@@ -895,6 +932,8 @@ ia:
statuses:
allow: Permitter message
allow_account: Permitter autor
+ confirm_allow_account: Es tu secur que tu vole permitter le contos seligite?
+ confirm_disallow_account: Es tu secur que tu vole cessar de permitter le contos seligite?
description_html: Istes es le messages cognoscite sur tu servitor que al momento es multo compartite e marcate como favorite. Illos pote adjutar tu usatores nove e reveniente a trovar plus personas a sequer. Necun message es monstrate publicamente usque tu approba le autor, a condition que le autor permitte que su conto es suggerite a alteres. Tu pote tamben permitter o rejectar messages singule.
disallow: Non permitter message
disallow_account: Non permitter autor
@@ -927,6 +966,7 @@ ia:
used_by_over_week:
one: Usate per un persona in le ultime septimana
other: Usate per %{count} personas in le ultime septimana
+ title: Recommendationes e tendentias
trending: In tendentia
warning_presets:
add_new: Adder nove
@@ -1011,7 +1051,9 @@ ia:
guide_link_text: Totes pote contribuer.
sensitive_content: Contento sensibile
application_mailer:
+ notification_preferences: Cambiar preferentias de e-mail
salutation: "%{name},"
+ settings: 'Cambiar preferentias de e-mail: %{link}'
unsubscribe: Desubscriber
view: 'Visita:'
view_profile: Vider profilo
@@ -1031,6 +1073,7 @@ ia:
hint_html: Solo un altere cosa! Nos debe confirmar que tu es un humano (de sorta que nos pote mantener le spam foras!). Solve le CAPTCHA infra e clicca sur "Continuar".
title: Controlo de securitate
confirmations:
+ awaiting_review: Tu adresse de e-mail es confirmate! Le personal de %{domain} ora revide tu registration. Tu recipera un e-mail si illes approba tu conto!
awaiting_review_title: Tu inscription es in curso de revision
clicking_this_link: cliccar sur iste ligamine
login_link: aperir session
@@ -1038,6 +1081,7 @@ ia:
redirect_to_app_html: Tu deberea haber essite redirigite al app %{app_name}. Si isto non ha evenite, tenta %{clicking_this_link} o retornar manualmente al app.
registration_complete: Tu inscription sur %{domain} es ora concludite!
welcome_title: Benvenite, %{name}!
+ wrong_email_hint: Si ille adresse de e-mail non es correcte, tu pote cambiar lo in le parametros del conto.
delete_account: Deler le conto
delete_account_html: Si tu vole deler tu conto, tu pote facer lo hic. Te essera demandate un confirmation.
description:
@@ -1058,6 +1102,7 @@ ia:
or_log_in_with: O aperi session con
privacy_policy_agreement_html: Io ha legite e accepta le politica de confidentialitate
progress:
+ confirm: Confirmar e-mail
details: Tu detalios
review: Nostre revision
rules: Accepta le regulas
@@ -1079,8 +1124,10 @@ ia:
security: Securitate
set_new_password: Definir un nove contrasigno
setup:
+ email_below_hint_html: Consulta tu dossier de spam, o requesta un altere ligamine de confirmation. Tu pote corriger tu adresse de e-mail si illo es errate.
email_settings_hint_html: Clicca sur le ligamine que nos te ha inviate pro verificar %{email}. Nos te attendera hic.
link_not_received: Necun ligamine recipite?
+ new_confirmation_instructions_sent: Tu recipera un nove e-mail con le ligamine de confirmation in poc minutas!
title: Consulta tu cassa de entrata
sign_in:
preamble_html: Aperi session con tu credentiales de %{domain}. Si tu conto es albergate sur un altere servitor, tu non potera aperir session hic.
@@ -1091,12 +1138,18 @@ ia:
title: Lassa nos installar tu conto sur %{domain}.
status:
account_status: Stato del conto
+ confirming: Attendente le termination del confirmation del adresse de e-mail.
functional: Tu conto es completemente operative.
+ pending: Tu demanda attende le revision per nostre personal. Isto pote prender alcun tempore. Tu recipera un e-mail si tu demanda es approbate.
redirecting_to: Tu conto es inactive perque illo actualmente redirige a %{acct}.
self_destruct: Perque %{domain} va clauder, tu solo habera accesso limitate a tu conto.
view_strikes: Examinar le sanctiones passate contra tu conto
too_fast: Formulario inviate troppo rapidemente. Tenta lo de novo.
use_security_key: Usar clave de securitate
+ author_attribution:
+ example_title: Texto de exemplo
+ more_from_html: Plus de %{name}
+ s_blog: Blog de %{name}
challenge:
confirm: Continuar
hint_html: "Consilio: Nos non te demandara tu contrasigno de novo in le proxime hora."
@@ -1105,7 +1158,6 @@ ia:
crypto:
errors:
invalid_key: non es un clave Ed25519 o Curve25519 valide
- invalid_signature: non es un signatura Ed25519 valide
date:
formats:
default: "%d %b %Y"
@@ -1134,6 +1186,9 @@ ia:
before: 'Ante de continuar, per favor lege attentemente iste notas:'
caches: Le contento que altere servitores ha immagazinate in cache pote persister
data_removal: Tu messages e altere datos essera removite permanentemente
+ email_change_html: Tu pote cambiar tu adresse de e-mail sin deler tu conto
+ email_contact_html: Si illo ancora non arriva, tu pote inviar e-mail a %{email} pro peter adjuta
+ email_reconfirmation_html: Si tu non recipe le e-mail de confirmation, tu pote politica de confidentialitate.
username_available: Tu nomine de usator essera disponibile novemente
@@ -1168,8 +1223,6 @@ ia:
your_appeal_approved: Tu appello ha essite approbate
your_appeal_pending: Tu ha submittite un appello
your_appeal_rejected: Tu appello ha essite rejectate
- domain_validator:
- invalid_domain: non es un nomine de dominio valide
edit_profile:
basic_information: Information basic
hint_html: "Personalisa lo que le personas vide sur tu profilo public e presso tu messages. Il es plus probabile que altere personas te seque e interage con te quando tu ha un profilo complete e un photo."
@@ -1377,6 +1430,16 @@ ia:
unsubscribe:
action: Si, desubscriber
complete: Desubscribite
+ confirmation_html: Es tu secur de voler cancellar le subscription al %{type} de Mastodon sur %{domain} pro tu adresse de e-mail %{email}? Tu pote sempre resubscriber te a partir del parametros de notification in e-mail.
+ emails:
+ notification_emails:
+ favourite: notificationes de favorites in e-mail
+ follow: notificationes de sequimento in e-mail
+ follow_request: requestas de sequimento in e-mail
+ mention: notificationes de mentiones in e-mail
+ reblog: notificationes de impulsos in e-mail
+ resubscribe_html: Si tu ha cancellate le subscription in error, tu pote resubscriber te a partir del parametros de notification in e-mail.
+ success_html: Tu non recipera plus %{type} pro Mastodon sur %{domain} a tu adresse de e-mail %{email}.
title: Desubcriber
media_attachments:
validations:
@@ -1457,6 +1520,8 @@ ia:
update:
subject: "%{name} ha modificate un message"
notifications:
+ administration_emails: Notificationes per e-mail pro administratores
+ email_events: Eventos pro notificationes per e-mail
email_events_hint: 'Selige eventos pro le quales tu vole reciper notificationes:'
number:
human:
@@ -1615,6 +1680,7 @@ ia:
import: Importar
import_and_export: Importar e exportar
migrate: Migration de conto
+ notifications: Notificationes per e-mail
preferences: Preferentias
profile: Profilo public
relationships: Sequites e sequitores
@@ -1655,23 +1721,12 @@ ia:
edited_at_html: Modificate le %{date}
errors:
in_reply_not_found: Le message a que tu tenta responder non pare exister.
- open_in_web: Aperir sur le web
over_character_limit: limite de characteres de %{max} excedite
pin_errors:
direct: Messages que es solo visibile a usatores mentionate non pote esser appunctate
limit: Tu ha jam appunctate le maxime numero de messages
ownership: Le message de alcuno altere non pote esser appunctate
reblog: Un impulso non pote esser affixate
- poll:
- total_people:
- one: "%{count} persona"
- other: "%{count} personas"
- total_votes:
- one: "%{count} voto"
- other: "%{count} votos"
- vote: Votar
- show_more: Monstrar plus
- show_thread: Monstrar discussion
title: "%{name}: “%{quote}”"
visibilities:
direct: Directe
@@ -1861,6 +1916,7 @@ ia:
invalid_otp_token: Codice de duo factores non valide
otp_lost_help_html: Si tu ha perdite le accesso a ambes, tu pote contactar %{email}
rate_limited: Troppo de tentativas de authentication. Per favor reessaya plus tarde.
+ seamless_external_login: Tu ha aperite session per medio de un servicio externe. Le parametros de contrasigno e de e-mail es dunque indisponibile.
signed_in_as: 'Session aperite como:'
verification:
extra_instructions_html: Consilio: Le ligamine sur tu sito web pote esser invisibile. Le parte importante es rel="me"
que impedi le usurpation de identitate sur sitos web con contento generate per usatores. Tu pote mesmo usar un etiquetta link
in le capite del pagina in vice de a
, ma le codice HTML debe esser accessibile sin executar JavaScript.
@@ -1869,6 +1925,7 @@ ia:
instructions_html: Copia e colla le codice hic infra in le HTML de tu sito web. Alora adde le adresse de tu sito web in un del campos supplementari sur tu profilo desde le scheda “Modificar profilo” e salva le cambiamentos.
verification: Verification
verified_links: Tu ligamines verificate
+ website_verification: Verification de sito web
webauthn_credentials:
add: Adder un nove clave de securitate
create:
diff --git a/config/locales/id.yml b/config/locales/id.yml
index 73b4218397..96a5022a7c 100644
--- a/config/locales/id.yml
+++ b/config/locales/id.yml
@@ -7,7 +7,6 @@ id:
hosted_on: Mastodon dihosting di %{domain}
title: Tentang
accounts:
- follow: Ikuti
followers:
other: Pengikut
following: Mengikuti
@@ -937,7 +936,6 @@ id:
crypto:
errors:
invalid_key: bukan kunci Ed25519 atau Curve25519 yang valid
- invalid_signature: bukan tanda tangan Ed25519 yang valid
date:
formats:
default: "%d %b %Y"
@@ -1000,8 +998,6 @@ id:
your_appeal_approved: Banding Anda disetujui
your_appeal_pending: Anda telah mengirim banding
your_appeal_rejected: Banding Anda ditolak
- domain_validator:
- invalid_domain: bukan nama domain yang valid
errors:
'400': Permintaan yang dikirim tidak valid atau cacat.
'403': Anda tidak mempunyai izin untuk melihat halaman ini.
@@ -1380,21 +1376,12 @@ id:
edited_at_html: Diedit %{date}
errors:
in_reply_not_found: Status yang ingin Anda balas sudah tidak ada.
- open_in_web: Buka di web
over_character_limit: melebihi %{max} karakter
pin_errors:
direct: Kiriman yang hanya terlihat oleh pengguna yang disebutkan tidak dapat disematkan
limit: Anda sudah mencapai jumlah maksimum kiriman yang dapat disematkan
ownership: Kiriman orang lain tidak bisa disematkan
reblog: Boost tidak bisa disematkan
- poll:
- total_people:
- other: "%{count} orang"
- total_votes:
- other: "%{count} memilih"
- vote: Pilih
- show_more: Tampilkan selengkapnya
- show_thread: Tampilkan utas
title: '%{name}: "%{quote}"'
visibilities:
direct: Langsung
diff --git a/config/locales/ie.yml b/config/locales/ie.yml
index 4ee869d92f..513a8eda7e 100644
--- a/config/locales/ie.yml
+++ b/config/locales/ie.yml
@@ -7,7 +7,6 @@ ie:
hosted_on: Mastodon logiat che %{domain}
title: Pri
accounts:
- follow: Sequer
followers:
one: Sequitor
other: Sequitores
@@ -1090,7 +1089,6 @@ ie:
crypto:
errors:
invalid_key: ne es un valid clave Ed25519 o Curve25519
- invalid_signature: ne es un valid signatura Ed25519
date:
formats:
default: "%d.%m.%Y"
@@ -1153,8 +1151,6 @@ ie:
your_appeal_approved: Tui apelle ha esset aprobat
your_appeal_pending: Tu ha fat un apelle
your_appeal_rejected: Tui apelle ha esset rejectet
- domain_validator:
- invalid_domain: ne es un valid dominia-nómine
edit_profile:
basic_information: Basic information
hint_html: "Customisa ti quel gente vide sur tui public profil e apu tui postas. Altri persones es plu probabil sequer te e interacter con te si tu have un detalliat profil e un profil-image."
@@ -1639,23 +1635,12 @@ ie:
edited_at_html: Modificat ye %{date}
errors:
in_reply_not_found: Li posta a quel tu prova responder ne sembla exister.
- open_in_web: Aperter in web
over_character_limit: límite de carácteres de %{max} transpassat
pin_errors:
direct: On ne posse pinglar postas queles es visibil solmen a mentionat usatores
limit: Tu ja ha pinglat li maxim númere de postas
ownership: On ne posse pinglar li posta de un altri person
reblog: On ne posse pinglar un boost
- poll:
- total_people:
- one: "%{count} person"
- other: "%{count} persones"
- total_votes:
- one: "%{count} vote"
- other: "%{count} votes"
- vote: Votar
- show_more: Monstrar plu
- show_thread: Monstrar fil
title: "%{name}: «%{quote}»"
visibilities:
direct: Direct
diff --git a/config/locales/io.yml b/config/locales/io.yml
index a1d268b9fa..97cc417df0 100644
--- a/config/locales/io.yml
+++ b/config/locales/io.yml
@@ -7,7 +7,6 @@ io:
hosted_on: Mastodon hostigesas che %{domain}
title: Pri co
accounts:
- follow: Sequar
followers:
one: Sequanto
other: Sequanti
@@ -1065,7 +1064,6 @@ io:
crypto:
errors:
invalid_key: ne esas valida klefo Ed25519 o Curve25519
- invalid_signature: ne esas valida parafo Ed25519
date:
formats:
default: "%d %b, %Y"
@@ -1128,8 +1126,6 @@ io:
your_appeal_approved: Vua konto aprobesis
your_appeal_pending: Vu sendis apelo
your_appeal_rejected: Vua apelo refuzesis
- domain_validator:
- invalid_domain: ne esas valida domennomo
edit_profile:
basic_information: Fundamentala informo
other: Altra
@@ -1592,23 +1588,12 @@ io:
edited_at_html: Modifikesis ye %{date}
errors:
in_reply_not_found: Posto quon vu probas respondar semblas ne existas.
- open_in_web: Apertar retnavigile
over_character_limit: limito de %{max} signi ecesita
pin_errors:
direct: Posti quo povas videsar nur mencionita uzanti ne povas pinglagesar
limit: Vu ja pinglagis maxima posti
ownership: Posto di altra persono ne povas pinglagesar
reblog: Repeto ne povas pinglizesar
- poll:
- total_people:
- one: "%{count} persono"
- other: "%{count} personi"
- total_votes:
- one: "%{count} voto"
- other: "%{count} voti"
- vote: Votez
- show_more: Montrar plue
- show_thread: Montrez postaro
title: '%{name}: "%{quote}"'
visibilities:
direct: Direta
diff --git a/config/locales/is.yml b/config/locales/is.yml
index 41347d44bb..590805ad30 100644
--- a/config/locales/is.yml
+++ b/config/locales/is.yml
@@ -7,7 +7,6 @@ is:
hosted_on: Mastodon hýst á %{domain}
title: Um hugbúnaðinn
accounts:
- follow: Fylgjast með
followers:
one: fylgjandi
other: fylgjendur
@@ -25,6 +24,8 @@ is:
admin:
account_actions:
action: Framkvæma aðgerð
+ already_silenced: Þessi aðgangur hefur þegar verið takmarkaður.
+ already_suspended: Þessi aðgangur hefur þegar verið settur í frysti.
title: Framkvæma umsjónaraðgerð á %{acct}
account_moderation_notes:
create: Skilja eftir minnispunkt
@@ -46,6 +47,7 @@ is:
title: Breyta tölvupóstfangi fyrir %{username}
change_role:
changed_msg: Tókst að breyta hlutverki!
+ edit_roles: Sýsla með hlutverk notenda
label: Breyta hlutverki
no_role: Ekkert hlutverk
title: Breyta hlutverki fyrir %{username}
@@ -602,6 +604,7 @@ is:
suspend_description_html: Notandaaðgangurinn og allt efni á honum mun verða óaðgengilegt og á endanum eytt út og samskipti við aðganginn verða ekki möguleg. Hægt að afturkalla innan 30 daga. Lokar öllum kærum gagnvart þessum aðgangi.
actions_description_html: Ákveddu til hvaða aðgerða eigi að taka til að leysa þessa kæru. Ef þú ákveður að refsa kærða notandaaðgangnum, verður viðkomandi send tilkynning í tölvupósti, nema ef flokkurinn Ruslpóstur sé valinn.
actions_description_remote_html: Ákveddu til hvaða aðgerða eigi að taka til að leysa þessa kæru. Þetta mun aðeins hafa áhrif á hvernig netþjónninn þinn meðhöndlar þennan fjartengda aðgang og efnið á honum.
+ actions_no_posts: Þessi kæra er ekki með neinar tengdar færslur til að eyða
add_to_report: Bæta fleiru í kæru
already_suspended_badges:
local: Þegar frystur á þessum netþjóni
@@ -1161,6 +1164,12 @@ is:
view_strikes: Skoða fyrri bönn notandaaðgangsins þíns
too_fast: Innfyllingarform sent inn of hratt, prófaðu aftur.
use_security_key: Nota öryggislykil
+ author_attribution:
+ example_title: Sýnitexti
+ hint_html: Stýrðu hvernig framlög þín birtast þegar tenglum er deilt á Mastodon.
+ more_from_html: Meira frá %{name}
+ s_blog: Bloggsvæði hjá %{name}
+ title: Framlag höfundar
challenge:
confirm: Halda áfram
hint_html: "Ábending: Við munum ekki spyrja þig um lykilorðið aftur næstu klukkustundina."
@@ -1169,7 +1178,6 @@ is:
crypto:
errors:
invalid_key: er ekki gildur Ed25519 eða Curve25519-lykill
- invalid_signature: er ekki gild Ed25519 undirritun
date:
formats:
default: "%d. %b, %Y"
@@ -1235,8 +1243,6 @@ is:
your_appeal_approved: Áfrýjun þín hefur verið samþykkt
your_appeal_pending: Þú hefur sent inn áfrýjun
your_appeal_rejected: Áfrýjun þinni hefur verið hafnað
- domain_validator:
- invalid_domain: er ekki leyfilegt nafn á léni
edit_profile:
basic_information: Grunnupplýsingar
hint_html: "Sérsníddu hvað fólk sér á opinbera notandasniðinu þínu og næst færslunum þínum. Annað fólk er líklegra til að fylgjast með þér og eiga í samskiptum við þig ef þú fyllir út notandasniðið og setur auðkennismynd."
@@ -1458,6 +1464,7 @@ is:
media_attachments:
validations:
images_and_video: Ekki er hægt að hengja myndskeið við færslu sem þegar inniheldur myndir
+ not_found: Myndefnið %{ids} fannst ekki eða er þegar hengt við aðra færslu
not_ready: Ekki er hægt að hengja við skrár sem ekki er búið að vinna til fulls. Prófaðu aftur eftir augnablik!
too_many: Ekki er hægt að hengja við fleiri en 4 skrár
migrations:
@@ -1735,23 +1742,12 @@ is:
edited_at_html: Breytt %{date}
errors:
in_reply_not_found: Færslan sem þú ert að reyna að svara að er líklega ekki til.
- open_in_web: Opna í vafra
over_character_limit: hámarksfjölda stafa (%{max}) náð
pin_errors:
direct: Ekki er hægt að festa færslur sem einungis eru sýnilegar þeim notendum sem minnst er á
limit: Þú hefur þegar fest leyfilegan hámarksfjölda færslna
ownership: Færslur frá einhverjum öðrum er ekki hægt að festa
reblog: Ekki er hægt að festa endurbirtingu
- poll:
- total_people:
- one: "%{count} aðili"
- other: "%{count} aðilar"
- total_votes:
- one: "%{count} atkvæði"
- other: "%{count} atkvæði"
- vote: Greiða atkvæði
- show_more: Sýna meira
- show_thread: Birta þráð
title: "%{name}: „%{quote}‟"
visibilities:
direct: Beint
@@ -1950,6 +1946,7 @@ is:
instructions_html: Afritaðu og límdu kóðann hér fyrir neðan inn í HTML-kóða vefsvæðisins þíns. Bættu síðan slóð vefsvæðisins þíns inn í einn af auka-reitunum í flipanum "Breyta notandasniði" og vistaðu síðan breytingarnar.
verification: Sannprófun
verified_links: Staðfestu tenglarnir þínir
+ website_verification: Staðfesting vefsvæðis
webauthn_credentials:
add: Bæta við nýjum öryggislykli
create:
diff --git a/config/locales/it.yml b/config/locales/it.yml
index bc60b6ea50..fe6fec17d7 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -7,7 +7,6 @@ it:
hosted_on: Mastodon ospitato su %{domain}
title: Info
accounts:
- follow: Segui
followers:
one: Seguace
other: Seguaci
@@ -25,6 +24,8 @@ it:
admin:
account_actions:
action: Esegui azione
+ already_silenced: Questo account è già stato limitato.
+ already_suspended: Questo account è già stato sospeso.
title: Esegui l'azione di moderazione su %{acct}
account_moderation_notes:
create: Lascia una nota
@@ -46,6 +47,7 @@ it:
title: Cambia l'email per %{username}
change_role:
changed_msg: Ruolo modificato correttamente!
+ edit_roles: Gestisci i ruoli utente
label: Cambia il ruolo
no_role: Nessun ruolo
title: Cambia il ruolo per %{username}
@@ -602,6 +604,7 @@ it:
suspend_description_html: L'account e tutti i suoi contenuti saranno inaccessibili ed eventualmente cancellati, e interagire con esso sarà impossibile. Reversibile entro 30 giorni. Chiude tutte le segnalazioni contro questo account.
actions_description_html: Decidi quale azione intraprendere per risolvere questa segnalazione. Se intraprendi un'azione punitiva nei confronti dell'account segnalato, gli verrà inviata una notifica via e-mail, tranne quando è selezionata la categoria Spam.
actions_description_remote_html: Decide quali azioni intraprendere per risolvere la relazione. Questo influenzerà solo come il tuo server comunica con questo account remoto e ne gestisce il contenuto.
+ actions_no_posts: Questa segnalazione non ha alcun post associato da eliminare
add_to_report: Aggiungi altro al report
already_suspended_badges:
local: Già sospeso su questo server
@@ -1159,6 +1162,12 @@ it:
view_strikes: Visualizza le sanzioni precedenti prese nei confronti del tuo account
too_fast: Modulo inviato troppo velocemente, riprova.
use_security_key: Usa la chiave di sicurezza
+ author_attribution:
+ example_title: Testo di esempio
+ hint_html: Controlla come sei viene accreditato quando i link sono condivisi su Mastodon.
+ more_from_html: Altro da %{name}
+ s_blog: Blog di %{name}
+ title: Attribuzione autore
challenge:
confirm: Continua
hint_html: "Suggerimento: Non ti chiederemo di nuovo la tua password per la prossima ora."
@@ -1167,7 +1176,6 @@ it:
crypto:
errors:
invalid_key: non è una chiave Ed25519 o Curve25519 valida
- invalid_signature: non è una firma Ed25519 valida
date:
formats:
default: "%d %b %Y"
@@ -1233,8 +1241,6 @@ it:
your_appeal_approved: Il tuo appello è stato approvato
your_appeal_pending: Hai presentato un appello
your_appeal_rejected: Il tuo appello è stato respinto
- domain_validator:
- invalid_domain: non è un nome di dominio valido
edit_profile:
basic_information: Informazioni di base
hint_html: "Personalizza ciò che le persone vedono sul tuo profilo pubblico e accanto ai tuoi post. È più probabile che altre persone ti seguano e interagiscano con te quando hai un profilo compilato e un'immagine del profilo."
@@ -1456,6 +1462,7 @@ it:
media_attachments:
validations:
images_and_video: Impossibile allegare video a un post che contiene già immagini
+ not_found: Media %{ids} non trovato o già collegato a un altro post
not_ready: Impossibile allegare file per cui l'elaborazione non è finita. Riprova tra poco!
too_many: Impossibile allegare più di 4 file
migrations:
@@ -1733,23 +1740,12 @@ it:
edited_at_html: Modificato il %{date}
errors:
in_reply_not_found: Il post a cui stai tentando di rispondere non sembra esistere.
- open_in_web: Apri sul Web
over_character_limit: Limite caratteri superato di %{max}
pin_errors:
direct: I messaggi visibili solo agli utenti citati non possono essere fissati in cima
limit: Hai già fissato in cima il massimo numero di post
ownership: Non puoi fissare in cima un post di qualcun altro
reblog: Un toot condiviso non può essere fissato in cima
- poll:
- total_people:
- one: "%{count} persona"
- other: "%{count} persone"
- total_votes:
- one: "%{count} voto"
- other: "%{count} voti"
- vote: Vota
- show_more: Mostra di più
- show_thread: Mostra thread
title: '%{name}: "%{quote}"'
visibilities:
direct: Diretto
@@ -1948,6 +1944,7 @@ it:
instructions_html: Copia e incolla il codice qui sotto nell'HTML del tuo sito web. Quindi, aggiungi l'indirizzo del tuo sito web in uno dei campi aggiuntivi del tuo profilo dalla scheda "Modifica profilo" e salva le modifiche.
verification: Verifica
verified_links: I tuoi collegamenti verificati
+ website_verification: Verifica del sito web
webauthn_credentials:
add: Aggiungi una nuova chiave di sicurezza
create:
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index a6b4822c58..cdc1fd18a8 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -7,7 +7,6 @@ ja:
hosted_on: Mastodon hosted on %{domain}
title: このサーバーについて
accounts:
- follow: フォロー
followers:
other: フォロワー
following: フォロー中
@@ -23,12 +22,15 @@ ja:
admin:
account_actions:
action: アクションを実行
+ already_silenced: すでに制限されているアカウントです。
+ already_suspended: すでに停止されているアカウントです。
title: "%{acct}さんに対してアクションを実行"
account_moderation_notes:
create: 書き込む
created_msg: モデレーションメモを書き込みました!
destroyed_msg: モデレーションメモを削除しました!
accounts:
+ add_email_domain_block: メールのドメインをブロック
approve: 承認
approved_msg: "%{username}さんの登録申請を承認しました"
are_you_sure: 本当に実行しますか?
@@ -55,6 +57,7 @@ ja:
demote: 降格
destroyed_msg: "%{username}さんのデータは完全に削除されるよう登録されました"
disable: 無効化
+ disable_sign_in_token_auth: メールトークン認証を無効化
disable_two_factor_authentication: 二要素認証を無効にする
disabled: 無効
display_name: 表示名
@@ -63,6 +66,7 @@ ja:
email: メールアドレス
email_status: メールアドレスの状態
enable: 有効化
+ enable_sign_in_token_auth: メールトークン認証を有効化
enabled: 有効
enabled_msg: "%{username}の無効化を解除しました"
followers: フォロワー数
@@ -126,6 +130,7 @@ ja:
resubscribe: 再講読
role: ロール
search: 検索
+ search_same_email_domain: 同じメールドメインを持つ他のユーザ
search_same_ip: 同じIPのユーザーを検索
security: 認証方法
security_measures:
@@ -166,21 +171,26 @@ ja:
approve_appeal: 抗議を承認
approve_user: ユーザーの承認
assigned_to_self_report: 通報の担当者に設定
+ change_email_user: ユーザーのメールアドレスの変更
change_role_user: ユーザーのロールを変更
confirm_user: ユーザーの確認
create_account_warning: 警告を作成
create_announcement: お知らせを作成
+ create_canonical_email_block: メールアドレスブロックの作成
create_custom_emoji: カスタム絵文字を作成
create_domain_allow: 連合を許可
create_domain_block: ドメインブロックを作成
+ create_email_domain_block: メールドメインブロックを作成
create_ip_block: IPルールを作成
create_unavailable_domain: 配送できないドメインを作成
create_user_role: ロールを作成
demote_user: ユーザーを降格
destroy_announcement: お知らせを削除
+ destroy_canonical_email_block: メールアドレスブロックの削除
destroy_custom_emoji: カスタム絵文字を削除
destroy_domain_allow: 連合許可を外す
destroy_domain_block: ドメインブロックを削除
+ destroy_email_domain_block: メールドメインブロックを削除
destroy_instance: ドメインをブロックする
destroy_ip_block: IPルールを削除
destroy_status: 投稿を削除
@@ -188,8 +198,10 @@ ja:
destroy_user_role: ロールを削除
disable_2fa_user: 二要素認証を無効化
disable_custom_emoji: カスタム絵文字を無効化
+ disable_sign_in_token_auth_user: ユーザのメールトークン認証を無効化
disable_user: ユーザーを無効化
enable_custom_emoji: カスタム絵文字を有効化
+ enable_sign_in_token_auth_user: ユーザのメールトークン認証を有効化
enable_user: ユーザーを有効化
memorialize_account: 追悼アカウント化
promote_user: ユーザーを昇格
@@ -219,20 +231,26 @@ ja:
approve_appeal_html: "%{name}さんが%{target}さんからの抗議を承認しました"
approve_user_html: "%{name}さんが%{target}さんからの登録を承認しました"
assigned_to_self_report_html: "%{name}さんが通報 %{target}を自身の担当に割り当てました"
+ change_email_user_html: "%{name}さんが%{target}さんのメールアドレスを変更しました"
change_role_user_html: "%{name}さんが%{target}さんのロールを変更しました"
+ confirm_user_html: "%{name}さんが%{target}さんのメールアドレスを確認済みにしました"
create_account_warning_html: "%{name}さんが%{target}さんに警告メールを送信しました"
create_announcement_html: "%{name}さんが新しいお知らせ %{target}を作成しました"
+ create_canonical_email_block_html: "%{name}さんがメールアドレス (ハッシュ値: %{target}) をブロックしました"
create_custom_emoji_html: "%{name}さんがカスタム絵文字 %{target}を追加しました"
create_domain_allow_html: "%{name}さんが%{target}の連合を許可しました"
create_domain_block_html: "%{name}さんがドメイン %{target}をブロックしました"
+ create_email_domain_block_html: "%{name}さんがメールドメイン %{target} をブロックしました"
create_ip_block_html: "%{name}さんがIP %{target}のルールを作成しました"
create_unavailable_domain_html: "%{name}がドメイン %{target}への配送を停止しました"
create_user_role_html: "%{name}さんがロール『%{target}』を作成しました"
demote_user_html: "%{name}さんが%{target}さんを降格しました"
destroy_announcement_html: "%{name}さんがお知らせ %{target}を削除しました"
+ destroy_canonical_email_block_html: "%{name}さんがメールアドレス (ハッシュ値: %{target}) のブロックを外しました"
destroy_custom_emoji_html: "%{name}さんがカスタム絵文字『%{target}』を削除しました"
destroy_domain_allow_html: "%{name}さんが%{target}の連合許可を外しました"
destroy_domain_block_html: "%{name}さんがドメイン %{target}のブロックを外しました"
+ destroy_email_domain_block_html: "%{name} がメールドメイン %{target} のブロックを外しました"
destroy_instance_html: "%{name}さんがドメイン %{target}をブロックしました"
destroy_ip_block_html: "%{name}さんが IP %{target}のルールを削除しました"
destroy_status_html: "%{name}さんが%{target}さんの投稿を削除しました"
@@ -240,8 +258,10 @@ ja:
destroy_user_role_html: "%{name}さんがロール『%{target}』を削除しました"
disable_2fa_user_html: "%{name}さんが%{target}さんの二要素認証を無効化しました"
disable_custom_emoji_html: "%{name}さんがカスタム絵文字 %{target}を無効化しました"
+ disable_sign_in_token_auth_user_html: "%{name} が %{target} のメールトークン認証を無効化しました"
disable_user_html: "%{name}さんが%{target}さんのログインを無効化しました"
enable_custom_emoji_html: "%{name}さんがカスタム絵文字 %{target}を有効化しました"
+ enable_sign_in_token_auth_user_html: "%{name} が %{target} のメールトークン認証を有効化しました"
enable_user_html: "%{name}さんが%{target}さんのログインを有効化しました"
memorialize_account_html: "%{name}さんが%{target}さんを追悼アカウントページに登録しました"
promote_user_html: "%{name}さんが%{target}さんを昇格しました"
@@ -249,6 +269,7 @@ ja:
reject_user_html: "%{name}さんが%{target}さんからの登録を拒否しました"
remove_avatar_user_html: "%{name}さんが%{target}さんのアイコンを削除しました"
reopen_report_html: "%{name}さんが通報 %{target}を未解決に戻しました"
+ resend_user_html: "%{name}さんが %{target} の確認メールを再送信しました"
reset_password_user_html: "%{name}さんが%{target}さんのパスワードをリセットしました"
resolve_report_html: "%{name}さんが通報 %{target}を解決済みにしました"
sensitive_account_html: "%{name}さんが%{target}さんのメディアを閲覧注意にマークしました"
@@ -404,6 +425,7 @@ ja:
allow_registrations_with_approval: 承認制での新規登録を可能にする
attempts_over_week:
other: 先週は%{count}回サインアップが試みられました
+ created_msg: メールドメインブロックを追加しました
delete: 消去
dns:
types:
@@ -412,8 +434,12 @@ ja:
new:
create: ドメインを追加
resolve: ドメイン解決
+ title: 新規メールドメインブロック
+ no_email_domain_block_selected: 変更対象のメールドメインブロックを選択してください
not_permitted: 権限がありません
+ resolved_dns_records_hint_html: 入力されたドメイン名のMXレコードから以下のドメインが解決されました。MXレコードが指すドメインはメールの送受信において重要な役割をもっています。MXレコードのドメインをブロックすると、見た目のドメインが異なるメールアドレスからの登録であっても、そのドメイン名から解決されるMXレコードのドメインが同じ場合はブロックの対象になります。大手のメールプロバイダをブロックしないように注意してください。
resolved_through_html: "%{domain}を通して解決しました"
+ title: メールドメインブロック
export_domain_allows:
new:
title: ドメイン許可をインポート
@@ -438,6 +464,9 @@ ja:
title: おすすめフォロー
unsuppress: おすすめフォローを復元
instances:
+ audit_log:
+ title: 最近の監査ログ
+ view_all: 全ての監査ログを閲覧
availability:
description_html:
other: ドメインへの配信が %{count} 日失敗した場合、そのドメインからの配信を受信しない限り、それ以上の配信を行いません。
@@ -560,7 +589,9 @@ ja:
resolve_description_html: 報告されたアカウントに対していかなる措置も取られず、ストライクも記録されず、報告は終了します。
silence_description_html: このアカウントは、すでにフォローしている人、または手動で検索した人にしか見えないため、リーチが極端に制限されます。いつでも元に戻すことができます。このアカウントに対するすべての通報をクローズします。
suspend_description_html: アカウントとそのすべての内容にアクセスできなくなり、最終的に削除され、やり取りは不可能になります。 30日以内であれば元に戻すことができます。このアカウントに対するすべての通報をクローズします。
+ actions_description_html: このレポートへのアクションを決定してください。アカウントへ懲罰的な措置を取った場合、Spanカテゴリが選択されている場合を除き、メール通知が送信されます。
actions_description_remote_html: この通報を解決するためのアクションを選択してください。これはあなたのサーバーがこのリモートアカウントと通信し、そのコンテンツを処理する時のみ影響します。
+ actions_no_posts: 削除対象となる投稿がレポートに含まれていません
add_to_report: 通報にさらに追加
already_suspended_badges:
local: このサーバーで停止済み
@@ -624,6 +655,7 @@ ja:
delete_data_html: 停止が解除されないまま30日経過すると、@%{acct}さんのプロフィールとコンテンツは削除されます
preview_preamble_html: "@%{acct}さんに次の内容の警告を通知します:"
record_strike_html: 今後、@%{acct}さんが違反行為をしたときにエスカレーションできるように、このアカウントに対するストライクを記録します
+ send_email_html: "@%{acct}さんに警告メールを送信します"
warning_placeholder: アクションを行使する追加の理由(オプション)
target_origin: 報告されたアカウントの起源
title: 通報
@@ -661,6 +693,7 @@ ja:
manage_appeals: 抗議の管理
manage_appeals_description: ユーザーはモデレーションアクションに対する抗議を確認できます
manage_blocks: ブロックの管理
+ manage_blocks_description: メールプロバイダとIPアドレスのブロックを許可
manage_custom_emojis: カスタム絵文字を管理
manage_custom_emojis_description: ユーザーがサーバー上のカスタム絵文字を管理できるようにします
manage_federation: 連合の管理
@@ -678,6 +711,7 @@ ja:
manage_taxonomies: 分類の管理
manage_taxonomies_description: トレンドコンテンツの確認とハッシュタグの設定の更新
manage_user_access: アクセス権を管理
+ manage_user_access_description: 他のユーザの二段階認証の無効化、メールアドレスの変更、パスワードリセットを許可
manage_users: ユーザーの管理
manage_users_description: 他のユーザーの詳細情報を閲覧し、モデレーションを行うことができます。
manage_webhooks: Webhookの管理
@@ -752,6 +786,7 @@ ja:
destroyed_msg: ファイルを削除しました!
software_updates:
critical_update: "※緊急 (速やかに適用してください)"
+ description: Mastodonサーバーはいつでも最新の状態を保ち、新しい機能や修正を利用できるようにしておくことをおすすめします。またセキュリティの問題が発生した場合は、速やかにMastodonをアップデートすることが大切です。Mastodonは30分おきにアップデートを確認し、通知設定に応じて新しいアップデートをメールで通知します。
documentation_link: もっと見る
release_notes: リリースノート
title: 利用可能なアップデート
@@ -838,16 +873,39 @@ ja:
action: ここを開いて詳細を確認してください
message_html: "オブジェクトストレージが正しく設定されていません。ユーザーのプライバシーが危険な状態になっています。"
tags:
+ moderation:
+ not_trendable: トレンド不許可
+ not_usable: 使用不可
+ pending_review: 審査を保留中
+ review_requested: 審査待ち
+ reviewed: 審査済
+ title: ステータス
+ trendable: トレンド許可済
+ unreviewed: 未審査
+ usable: 使用可能
+ name: タグ名
+ newest: 新しい順
+ oldest: 古い順
+ open: タグ検索を見る
+ reset: リセット
review: 審査状況
+ search: 検索
+ title: ハッシュタグ
updated_msg: ハッシュタグ設定が更新されました
title: 管理
trends:
allow: 許可
approved: 承認
+ confirm_allow: 本当に選択されたタグを許可しますか?
+ confirm_disallow: 本当に選択されたタグを禁止しますか?
disallow: 拒否
links:
allow: リンクの許可
allow_provider: 発行者の承認
+ confirm_allow: 本当に選択されたリンクを許可しますか?
+ confirm_allow_provider: 本当に選択されたプロバイダを許可しますか?
+ confirm_disallow: 本当に選択されたリンクを禁止しますか?
+ confirm_disallow_provider: 本当に選択されたプロバイダを禁止しますか?
description_html: これらは、多くのユーザーに共有されているリンクです。あなたのユーザーが世の中の動きを知るのに役立ちます。あなたが公開者を承認するまで、リンクは一般に表示されません。また、個別のリンクの許可・拒否も可能です。
disallow: リンクの拒否
disallow_provider: 発行者の拒否
@@ -870,6 +928,10 @@ ja:
statuses:
allow: 掲載を許可
allow_account: 投稿者を許可
+ confirm_allow: 本当に選択されたトゥートを許可しますか?
+ confirm_allow_account: 本当に選択されたアカウントを許可しますか?
+ confirm_disallow: 本当に選択されたトゥートを禁止しますか?
+ confirm_disallow_account: 本当に選択されたアカウントを禁止しますか?
description_html: これらは、このサーバーが知っている、たくさんシェアされ、お気に入り登録されている投稿です。新しいユーザーや久しぶりにアクセスするユーザーがフォローする人を探すのに役立ちます。あなたが投稿者を承認し、投稿者が許可するまで、表示されることはありません。また、個別の投稿を許可または拒否することもできます。
disallow: 掲載を拒否
disallow_account: 投稿者を拒否
@@ -900,6 +962,7 @@ ja:
usage_comparison: 今日は%{today}回、昨日は%{yesterday}回使用されました。
used_by_over_week:
other: 週間%{count}人に使用されました
+ title: おすすめとトレンド
trending: トレンド
warning_presets:
add_new: 追加
@@ -983,7 +1046,9 @@ ja:
guide_link_text: 誰でも参加することができます。
sensitive_content: 閲覧注意コンテンツ
application_mailer:
+ notification_preferences: メール設定の変更
salutation: "%{name}さん"
+ settings: 'メール設定の変更: %{link}'
unsubscribe: 購読解除
view: 'リンク:'
view_profile: プロフィールを表示
@@ -1003,6 +1068,7 @@ ja:
hint_html: もう一つだけ!あなたが人間であることを確認する必要があります(スパムを防ぐためです!)。 以下のCAPTCHAを解き、「続ける」をクリックします。
title: セキュリティチェック
confirmations:
+ awaiting_review: メールアドレスが確認できました。%{domain} のスタッフからの審査をお待ちください。承認された場合、メールにより連絡します。
awaiting_review_title: 登録の審査待ちです
clicking_this_link: このリンクを押す
login_link: ログイン
@@ -1010,6 +1076,7 @@ ja:
redirect_to_app_html: 自動的に%{app_name}に戻らなかった場合、%{clicking_this_link}か、手動でアプリを切り替えてください。
registration_complete: "%{domain} へのアカウント登録が完了しました。"
welcome_title: ようこそ、%{name}さん!
+ wrong_email_hint: メールアドレスが正しくない場合は、アカウント設定画面で変更できます。
delete_account: アカウントの削除
delete_account_html: アカウントを削除したい場合、こちらから手続きが行えます。削除する前に、確認画面があります。
description:
@@ -1030,6 +1097,7 @@ ja:
or_log_in_with: または次のサービスでログイン
privacy_policy_agreement_html: プライバシーポリシーを読み、同意します
progress:
+ confirm: メールアドレスの確認
details: ユーザー情報
review: 承認
rules: ルール
@@ -1051,8 +1119,10 @@ ja:
security: セキュリティ
set_new_password: 新しいパスワード
setup:
+ email_below_hint_html: 確認メールが迷惑メールフォルダに振り分けられていないか確認してください。メールアドレスを間違えた場合は、ここでメールアドレスの変更と確認メールの再送ができます。
email_settings_hint_html: メールに記載のリンクを開いて %{email} を確認してください。
link_not_received: 確認メールを受信できない場合は
+ new_confirmation_instructions_sent: 確認用のリンクを記載した新しいメールを送信しました
title: 確認メールを送信しました
sign_in:
preamble_html: "%{domain} の資格情報でサインインします。 あなたのアカウントが別のサーバーでホストされている場合は、ここでログインすることはできません。"
@@ -1063,7 +1133,9 @@ ja:
title: さあ %{domain} でセットアップしましょう.
status:
account_status: アカウントの状態
+ confirming: メールアドレスの確認が完了するのを待っています。
functional: アカウントは完全に機能しています。
+ pending: あなたの申請は現在サーバー管理者による審査待ちです。これにはしばらくかかります。申請が承認されるとメールが届きます。
redirecting_to: アカウントは%{acct}に引っ越し設定されているため非アクティブになっています。
self_destruct: "%{domain} は閉鎖されるため、今後このアカウントでは限られた操作しかできません。"
view_strikes: 過去のストライクを表示
@@ -1077,7 +1149,6 @@ ja:
crypto:
errors:
invalid_key: 有効なEd25519またはCurve25519キーではありません
- invalid_signature: 有効なEd25519署名ではありません
date:
formats:
default: "%Y年%m月%d日"
@@ -1106,6 +1177,9 @@ ja:
before: '続行する前に、次の点を再度確認してください:'
caches: 他のサーバーにコンテンツのキャッシュがずっと残る場合があります
data_removal: あなたの投稿やその他のデータはこのサーバーから完全に削除されます
+ email_change_html: アカウントを削除しなくてもメールアドレスを変更できます
+ email_contact_html: それでも届かない場合、%{email}までメールで問い合わせてください
+ email_reconfirmation_html: 確認メールが届かない場合はこちらから確認メールを再送してみてください
irreversible: 削除操作の撤回やアカウントの復活はできません
more_details_html: 詳しくはプライバシーポリシーをご覧ください。
username_available: あなたのユーザー名は再利用できるようになります
@@ -1140,8 +1214,6 @@ ja:
your_appeal_approved: 申し立てが承認されました
your_appeal_pending: 申し立てを送信しました
your_appeal_rejected: 申し立ては拒否されました
- domain_validator:
- invalid_domain: は無効なドメイン名です
edit_profile:
basic_information: 基本情報
hint_html: "アカウントのトップページや投稿の隣に表示される公開情報です。プロフィールとアイコンを設定することで、ほかのユーザーは親しみやすく、またフォローしやすくなります。"
@@ -1330,6 +1402,7 @@ ja:
authentication_methods:
otp: 二要素認証アプリ
password: パスワード
+ sign_in_token: メール認証
webauthn: セキュリティキー
description_html: 認識できないアクティビティが表示された場合は、パスワードの変更と二要素認証の有効化を検討してください。
empty: 利用可能な認証履歴がありません
@@ -1340,10 +1413,21 @@ ja:
unsubscribe:
action: 購読を解除する
complete: 購読を解除しました
+ confirmation_html: Mastodon (%{domain}) による %{email} 宛の「%{type}」の配信を停止します。再度必要になった場合はメール通知の設定からいつでも再開できます。
+ emails:
+ notification_emails:
+ favourite: お気に入りの通知メール
+ follow: フォローの通知メール
+ follow_request: フォローリクエストの通知メール
+ mention: 返信の通知メール
+ reblog: ブーストの通知メール
+ resubscribe_html: 誤って解除した場合はメール通知の設定から再購読できます。
+ success_html: Mastodon (%{domain}) から %{email} への「%{type}」の配信が停止されました。
title: 購読の解除
media_attachments:
validations:
images_and_video: 既に画像が追加されているため、動画を追加することはできません
+ not_found: メディア (%{ids}) が存在しないか、すでに添付して投稿されています
not_ready: ファイルのアップロードに失敗しました。しばらくしてからもう一度お試しください!
too_many: 追加できるファイルは4つまでです
migrations:
@@ -1420,6 +1504,8 @@ ja:
update:
subject: "%{name}さんが投稿を更新しました"
notifications:
+ administration_emails: 管理にかかわるメール通知
+ email_events: メールによる通知
email_events_hint: '受信する通知を選択:'
number:
human:
@@ -1578,6 +1664,7 @@ ja:
import: データのインポート
import_and_export: インポート・エクスポート
migrate: アカウントの引っ越し
+ notifications: メール通知
preferences: ユーザー設定
profile: プロフィール
relationships: フォロー・フォロワー
@@ -1614,21 +1701,12 @@ ja:
edited_at_html: "%{date} 編集済み"
errors:
in_reply_not_found: あなたが返信しようとしている投稿は存在しないようです。
- open_in_web: Webで開く
over_character_limit: 上限は%{max}文字です
pin_errors:
direct: 返信したユーザーのみに表示される投稿はピン留めできません
limit: 固定できる投稿数の上限に達しました
ownership: 他人の投稿を固定することはできません
reblog: ブーストを固定することはできません
- poll:
- total_people:
- other: "%{count}人"
- total_votes:
- other: "%{count}票"
- vote: 投票
- show_more: もっと見る
- show_thread: スレッドを表示
title: '%{name}: "%{quote}"'
visibilities:
direct: ダイレクト
@@ -1817,6 +1895,7 @@ ja:
invalid_otp_token: 二要素認証コードが間違っています
otp_lost_help_html: どちらも使用できない場合、%{email}に連絡を取ると解決できるかもしれません
rate_limited: 認証に失敗した回数が多すぎます。時間をおいてからログインしてください。
+ seamless_external_login: あなたは外部サービスを介してログインしているため、パスワードとメールアドレスの設定は利用できません。
signed_in_as: '下記でログイン中:'
verification:
extra_instructions_html: ワンポイント: webサイト上のプロフィールへのリンクは表示上見えなくてもかまいません。重要な部分は rel="me"
で、これはユーザーが自由にリンクを作成可能なサイトを悪用してなりすまされるのを防ぐための情報です。a
タグを配置する代わりに link
タグをHTMLヘッダーに挿入することでも認証が可能です。ただし、HTMLにはJavaScriptを使わなくてもアクセスできるようにしてください。
diff --git a/config/locales/ka.yml b/config/locales/ka.yml
index 97b56ea35c..5769375078 100644
--- a/config/locales/ka.yml
+++ b/config/locales/ka.yml
@@ -6,7 +6,6 @@ ka:
contact_unavailable: მიუწ.
hosted_on: მასტოდონს მასპინძლობს %{domain}
accounts:
- follow: გაყევი
following: მიჰყვება
nothing_here: აქ არაფერია!
pin_errors:
@@ -430,13 +429,11 @@ ka:
disallowed_hashtags:
one: 'მოიცავდა აკრძალულ ჰეშტეგს: %{tags}'
other: 'მოიცავს აკრძალულ ჰეშტეგს: %{tags}'
- open_in_web: ვებში გახნსა
over_character_limit: ნიშნების ლიმიტი გადასცდა %{max}-ს
pin_errors:
limit: ტუტების მაქსიმალური რაოდენობა უკვე აპინეთ
ownership: სხვისი ტუტი ვერ აიპინება
reblog: ბუსტი ვერ აიპინება
- show_more: მეტის ჩვენება
visibilities:
private: მხოლოდ-მიმდევრები
private_long: აჩვენე მხოლოდ მიმდევრებს
diff --git a/config/locales/kab.yml b/config/locales/kab.yml
index 3aed6c55e7..88193f8434 100644
--- a/config/locales/kab.yml
+++ b/config/locales/kab.yml
@@ -7,7 +7,6 @@ kab:
hosted_on: Maṣṭudun yersen deg %{domain}
title: Ɣef
accounts:
- follow: Ḍfeṛ
followers:
one: Umeḍfaṛ
other: Imeḍfaṛen
@@ -223,8 +222,8 @@ kab:
shortcode: Tangalt tawezlant
title: Imujiten udmawanen
uncategorized: War-taggayt
- unlist: Kkes seg wumuγ
- unlisted: Yettwakkes seg wumuγ
+ unlist: Kkes seg wumuɣ
+ unlisted: Yettwakkes seg wumuɣ
update_failed_msg: Ur izmir ara ad-issali umuji-a
upload: Sali
dashboard:
@@ -704,14 +703,15 @@ kab:
prev: Win iɛeddan
preferences:
other: Wiyaḍ
+ posting_defaults: Iɣewwaṛen n usuffeɣ imezwura
privacy:
privacy: Tabaḍnit
search: Anadi
privacy_policy:
title: Tasertit tabaḍnit
redirects:
- prompt: Ma tumneḍ aseɣwen-a, sit fell-as akken ad tkemmleḍ.
- title: Aql-ik·em ad teffɣeḍ seg %{instance}.
+ prompt: Ma tumneḍ asaɣ-a, sit fell-as akken ad tkemmleḍ.
+ title: Ad teffɣeḍ seg %{instance}.
relationships:
activity: Armud n umiḍan
followers: Imeḍfaṛen
@@ -780,6 +780,7 @@ kab:
import: Kter
import_and_export: Taktert d usifeḍ
migrate: Tunigin n umiḍan
+ notifications: Alɣuten s imayl
preferences: Imenyafen
profile: Ameɣnu
relationships: Imeḍfaṛen akked wid i teṭṭafaṛeḍ
@@ -798,17 +799,6 @@ kab:
one: "%{count} n tbidyutt"
other: "%{count} n tbidyutin"
edited_at_html: Tettwaẓreg ass n %{date}
- open_in_web: Ldi deg Web
- poll:
- total_people:
- one: "%{count} n wemdan"
- other: "%{count} n yemdanen"
- total_votes:
- one: "%{count} n wedɣar"
- other: "%{count} n yedɣaren"
- vote: Dɣeṛ
- show_more: Ssken-d ugar
- show_thread: Ssken-d lxiḍ
title: '%{name} : "%{quote}"'
visibilities:
direct: Usrid
diff --git a/config/locales/kk.yml b/config/locales/kk.yml
index 065cd801f7..67969d4d69 100644
--- a/config/locales/kk.yml
+++ b/config/locales/kk.yml
@@ -6,7 +6,6 @@ kk:
contact_unavailable: Белгісіз
hosted_on: Mastodon орнатылған %{domain} доменінде
accounts:
- follow: Жазылу
followers:
one: Оқырман
other: Оқырман
@@ -385,8 +384,6 @@ kk:
more_details_html: Қосымша мәліметтер алу үшін құпиялылық саясатын қараңыз.
username_available: Аккаунтыңыз қайтадан қолжетімді болады
username_unavailable: Логиніңіз қолжетімді болмайды
- domain_validator:
- invalid_domain: жарамды домен атауы емес
errors:
'400': Сіз жіберген сұрау жарамсыз немесе дұрыс емес.
'403': Бұны көру үшін сізде рұқсат жоқ.
@@ -649,22 +646,11 @@ kk:
disallowed_hashtags:
one: 'рұқсат етілмеген хэштег: %{tags}'
other: 'рұқсат етілмеген хэштегтер: %{tags}'
- open_in_web: Вебте ашу
over_character_limit: "%{max} максимум таңбадан асып кетті"
pin_errors:
limit: Жабыстырылатын жазба саны максимумынан асты
ownership: Біреудің жазбасы жабыстырылмайды
reblog: Бөлісілген жазба жабыстырылмайды
- poll:
- total_people:
- one: "%{count} адам"
- other: "%{count} адам"
- total_votes:
- one: "%{count} дауыс"
- other: "%{count} дауыс"
- vote: Дауыс беру
- show_more: Тағы әкел
- show_thread: Тақырыпты көрсет
visibilities:
private: Тек оқырмандарға
private_long: Тек оқырмандарға ғана көрінеді
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index d4a44e516d..df1851a9ef 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -7,7 +7,6 @@ ko:
hosted_on: "%{domain}에서 호스팅 되는 마스토돈"
title: 정보
accounts:
- follow: 팔로우
followers:
other: 팔로워
following: 팔로잉
@@ -23,6 +22,8 @@ ko:
admin:
account_actions:
action: 조치 취하기
+ already_silenced: 이 계정은 이미 제한되었습니다.
+ already_suspended: 이 계정은 이미 정지되었습니다.
title: "%{acct} 계정에 중재 취하기"
account_moderation_notes:
create: 참고사항 남기기
@@ -44,6 +45,7 @@ ko:
title: "%{username}의 이메일 바꾸기"
change_role:
changed_msg: 역할이 성공적으로 변경되었습니다!
+ edit_roles: 사용자 역할 관리
label: 역할 변경
no_role: 역할 없음
title: "%{username}의 역할 변경"
@@ -592,6 +594,7 @@ ko:
suspend_description_html: 이 계정과 이 계정의 콘텐츠들은 접근 불가능해지고 삭제될 것이며, 상호작용은 불가능해집니다. 30일 이내에 되돌릴 수 있습니다. 이 계정에 대한 모든 신고를 닫습니다.
actions_description_html: 이 신고를 해결하기 위해 취해야 할 조치를 지정해주세요. 신고된 계정에 대해 처벌 조치를 취하면, 스팸 카테고리가 선택된 경우를 제외하고 해당 계정으로 이메일 알림이 전송됩니다.
actions_description_remote_html: 이 신고를 해결하기 위해 실행할 행동을 결정하세요. 이 결정은 이 원격 계정과 그 콘텐츠를 다루는 방식에 대해 이 서버에서만 영향을 끼칩니다
+ actions_no_posts: 이 신고는 삭제할 관련 게시물이 없습니다
add_to_report: 신고에 더 추가하기
already_suspended_badges:
local: 이 서버에서 이미 정지되었습니다
@@ -830,7 +833,7 @@ ko:
sensitive: "%{name} 님이 %{target}의 계정을 민감함으로 표시했습니다"
silence: "%{name} 님이 %{target}의 계정을 제한시켰습니다"
suspend: "%{name} 님이 %{target}의 계정을 정지시켰습니다"
- appeal_approved: 이의제기됨
+ appeal_approved: 이의 받아들여짐
appeal_pending: 이의제기 대기중
appeal_rejected: 이의 제기 거절됨
system_checks:
@@ -886,6 +889,7 @@ ko:
name: 이름
newest: 최신
oldest: 오래된 순
+ open: 공개시점으로 보기
reset: 초기화
review: 심사 상태
search: 검색
@@ -1140,6 +1144,12 @@ ko:
view_strikes: 내 계정에 대한 과거 중재 기록 보기
too_fast: 너무 빠르게 양식이 제출되었습니다, 다시 시도하세요.
use_security_key: 보안 키 사용
+ author_attribution:
+ example_title: 예시 텍스트
+ hint_html: 링크가 마스토돈에 공유될 때 내가 어떻게 표시될 지를 제어합니다.
+ more_from_html: "%{name}의 게시물 더 보기"
+ s_blog: "%{name}의 블로그"
+ title: 작성자 기여
challenge:
confirm: 계속
hint_html: "팁: 한 시간 동안 다시 암호를 묻지 않을 것입니다."
@@ -1148,7 +1158,6 @@ ko:
crypto:
errors:
invalid_key: 유효하지 않은 Ed25519 또는 Curve25519 키
- invalid_signature: 유효하지 않은 Ed25519 서명
date:
formats:
default: "%Y-%m-%d"
@@ -1214,8 +1223,6 @@ ko:
your_appeal_approved: 소명이 받아들여졌습니다
your_appeal_pending: 소명을 제출했습니다
your_appeal_rejected: 소명이 기각되었습니다
- domain_validator:
- invalid_domain: 올바른 도메인 네임이 아닙니다
edit_profile:
basic_information: 기본 정보
hint_html: "사람들이 공개 프로필을 보고서 게시물을 볼 때를 위한 프로필을 꾸밉니다. 프로필과 프로필 사진을 채우면 다른 사람들이 나를 팔로우하고 나와 교류할 기회가 더 많아집니다."
@@ -1429,6 +1436,7 @@ ko:
media_attachments:
validations:
images_and_video: 이미 사진이 첨부된 게시물엔 동영상을 첨부할 수 없습니다.
+ not_found: 미디어 %{ids}는 찾을 수 없거나 이미 다른 게시물에 첨부되었습니다
not_ready: 처리가 끝나지 않은 파일은 첨부할 수 없습니다. 잠시 후에 다시 시도해 주세요!
too_many: 최대 4개까지 첨부할 수 있습니다
migrations:
@@ -1702,21 +1710,12 @@ ko:
edited_at_html: "%{date}에 편집됨"
errors:
in_reply_not_found: 답장하려는 게시물이 존재하지 않습니다.
- open_in_web: Web으로 열기
over_character_limit: 최대 %{max}자까지 입력할 수 있습니다
pin_errors:
direct: 멘션된 사용자들에게만 보이는 게시물은 고정될 수 없습니다
limit: 이미 너무 많은 게시물을 고정했습니다
ownership: 다른 사람의 게시물은 고정될 수 없습니다
reblog: 부스트는 고정될 수 없습니다
- poll:
- total_people:
- other: "%{count}명"
- total_votes:
- other: "%{count} 명 투표함"
- vote: 투표
- show_more: 더 보기
- show_thread: 글타래 보기
title: '%{name}: "%{quote}"'
visibilities:
direct: 다이렉트
@@ -1914,6 +1913,7 @@ ko:
instructions_html: 웹사이트에 아래 코드를 복사해 붙여 넣으세요. 그리고 "프로필 수정" 탭에서 그 웹사이트 주소를 프로필의 추가 필드 중 하나에 넣고 변경사항을 저장하세요.
verification: 검증
verified_links: 인증된 링크들
+ website_verification: 웹사이트 인증
webauthn_credentials:
add: 보안 키 추가
create:
diff --git a/config/locales/ku.yml b/config/locales/ku.yml
index cbb6b76406..08843f645e 100644
--- a/config/locales/ku.yml
+++ b/config/locales/ku.yml
@@ -7,7 +7,6 @@ ku:
hosted_on: Mastodon li ser %{domain} tê pêşkêşkirin
title: Derbar
accounts:
- follow: Bişopîne
followers:
one: Şopîner
other: Şopîner
@@ -951,7 +950,6 @@ ku:
crypto:
errors:
invalid_key: ed25519 ne derbasdare ne jî Curve25519 kilîta
- invalid_signature: Ed25519 ne îmzeyek derbasdar e
date:
formats:
default: "%b%d%Y"
@@ -1014,8 +1012,6 @@ ku:
your_appeal_approved: Îtîraza te hate pejirandin
your_appeal_pending: Te îtîrazek şand
your_appeal_rejected: Îtîraza te nehate pejirandin
- domain_validator:
- invalid_domain: ne naveke navper a derbasdar e
errors:
'400': Daxwaza ku te şand nederbasdar an çewt bû.
'403': Ji bo dîtina vê rûpelê mafê te nîn e.
@@ -1406,23 +1402,12 @@ ku:
edited_at_html: Di %{date} de hate serrastkirin
errors:
in_reply_not_found: Ew şandiya ku tu dikî nakî bersivê bide xuya nake an jî hatiye jêbirin.
- open_in_web: Di tevnê de veke
over_character_limit: sînorê karakterê %{max} derbas kir
pin_errors:
direct: Şandiyên ku tenê ji bikarhênerên qalkirî re têne xuyangkirin, nayê derzîkirin
limit: Jixwe te mezintirîn hejmara şandîyên xwe derzî kir
ownership: Şandiya kesekî din nay derzî kirin
reblog: Ev şandî nayê derzî kirin
- poll:
- total_people:
- one: "%{count} kes"
- other: "%{count} kes"
- total_votes:
- one: "%{count} deng"
- other: "%{count} deng"
- vote: Deng bide
- show_more: Bêtir nîşan bide
- show_thread: Mijarê nîşan bide
title: "%{name}%{quote}"
visibilities:
direct: Rasterast
diff --git a/config/locales/la.yml b/config/locales/la.yml
index d3733df934..cc92bf6d28 100644
--- a/config/locales/la.yml
+++ b/config/locales/la.yml
@@ -7,7 +7,6 @@ la:
hosted_on: Mastodon in %{domain} hospitātum
title: De
accounts:
- follow: Sequere
followers:
one: Sectātor
other: Sectātōrēs
diff --git a/config/locales/lad.yml b/config/locales/lad.yml
index 40be2627da..4136877ede 100644
--- a/config/locales/lad.yml
+++ b/config/locales/lad.yml
@@ -7,7 +7,6 @@ lad:
hosted_on: Mastodon balabayado en %{domain}
title: Sovre mozotros
accounts:
- follow: Sige
followers:
one: Suivante
other: Suivantes
@@ -25,6 +24,7 @@ lad:
admin:
account_actions:
action: Realiza aksion
+ already_suspended: Este kuento ya tiene sido suspendido.
title: Modera %{acct}
account_moderation_notes:
create: Kriya nota
@@ -440,8 +440,11 @@ lad:
create: Adjusta domeno
resolve: Rezolve domeno
title: Bloka muevo domeno de posta
+ no_email_domain_block_selected: No se tienen trokado blokos de domeno porke dinguno a sido eskojido
not_permitted: Sin permiso
+ resolved_dns_records_hint_html: El nombre de domeno rezolve los sigientes domenos MX, los kualos son responsavles en ultima instansya de achetar la posta elektronika. Blokar un domeno MX blokara los rejistros de kualkier adreso de posta elektronika ke utilize el mezmo domeno MX, inkluzo si el nombre de domeno vizivle es desferente. Tenga kudiado de no blokar los prinsipales domenos de posta elektronika.
resolved_through_html: Rezolvido por %{domain}
+ title: Domenos de posta blokados
export_domain_allows:
new:
title: Importa permisos de domeno
@@ -871,8 +874,12 @@ lad:
message_html: "Tu magazinaje de objektos es mal konfigurado. La privasita de tus utilizadores esta en riziko."
tags:
moderation:
+ pending_review: Revizion esta asperando
title: Estado
+ usable: Uzavle
name: Nombre
+ newest: Mas muevos
+ oldest: Mas viejos
reset: Reinisya
review: Estado de revizion
search: Bushka
@@ -1024,7 +1031,9 @@ lad:
guide_link_text: Todos pueden kontribuir.
sensitive_content: Kontenido sensivle
application_mailer:
+ notification_preferences: Troka preferensyas de posta
salutation: "%{name},"
+ settings: 'Troka preferensyas de posta: %{link}'
unsubscribe: Dezabona
view: 'Mira:'
view_profile: Ve profil
@@ -1044,6 +1053,7 @@ lad:
hint_html: Una koza mas! Tenemos ke konfirmar ke eres umano (para evitar spam!). Rezolve el CAPTCHA abasho i klika "Kontinua".
title: Kontrolo de sigurita
confirmations:
+ awaiting_review: Tu adreso de posta tiene sido konfirmado! La taifa de %{domain} esta revizando tu enrejistrasyon. Risiviras un meil si acheten tu kuento!
awaiting_review_title: Estamos revizando tu enrejistramiento
clicking_this_link: klikando en este atadijo
login_link: konektate kon kuento
@@ -1051,6 +1061,7 @@ lad:
redirect_to_app_html: Seras readresado a la aplikasyon %{app_name}. Si esto no afita, aprova %{clicking_this_link} o regresa manualmente a la aplikasyon.
registration_complete: Tu enrejistrasyon en %{domain} ya esta kompletada!
welcome_title: Bienvenido, %{name}!
+ wrong_email_hint: Si este adreso de posta es inkorekto, puedes trokarlo en las preferensyas del kuento.
delete_account: Efasa kuento
delete_account_html: Si keres supremir tu kuento, puedes ir aki. Seras pedido de una konfirmasyon.
description:
@@ -1093,8 +1104,10 @@ lad:
security: Sigurita
set_new_password: Establese muevo kod
setup:
+ email_below_hint_html: Mira en tu kuti de spam o solisita de muevo. Si el adreso de posta elektronika ke aparese aki es yerrado, puedes trokarlo aki.
email_settings_hint_html: Klika el atadjiko ke te embimos para verifikar %{email}. Asperaremos aki.
link_not_received: No risivites un atadijo?
+ new_confirmation_instructions_sent: Resiviras un muevo mesaj de posta elektronika kon el atadjio de konfirmasyon en unos minutos!
title: Reviza tu kuti de arivo
sign_in:
preamble_html: Konektate kon tus kredensiales de %{domain}. Si tu kuento esta balabayado en otruno servidor, no puedras konektarte aki.
@@ -1106,11 +1119,14 @@ lad:
status:
account_status: Estado del kuento
functional: Tu kuento esta kompletamente funksyonal.
+ pending: Tu solisitasyon esta asperando la revizion por muestros administradores. Esto puede tadrar algun tiempo. Arisiviras una posta elektronika si la solisitasyon sea achetada.
redirecting_to: Tu kuento se topa inaktivo porke esta siendo readresado a %{acct}.
self_destruct: Deke %{domain} va a serrarse, solo tendras akseso limitado a tu kuento.
view_strikes: Ve amonestamientos pasados kontra tu kuento
too_fast: Formulario enviado demaziado rapido, aprovalo de muevo.
use_security_key: Uza la yave de sigurita
+ author_attribution:
+ more_from_html: Mas de %{name}
challenge:
confirm: Kontinua
hint_html: "Konsejo: No retornaremos a demandarte por el kod durante la sigiente ora."
@@ -1119,7 +1135,6 @@ lad:
crypto:
errors:
invalid_key: no es una yave Ed25519 o Curve25519 valida
- invalid_signature: no es una firma Ed25519 valida
date:
formats:
default: "%d %b %Y"
@@ -1148,6 +1163,9 @@ lad:
before: 'Antes de kontinuar, por favor melda kon atensyon las sigientes notas:'
caches: El kontenido ke tiene sido magazinado en kashe por otros sirvidores puede persistir
data_removal: Tus publikasyones i el resto de datos se supremiran definitivamente
+ email_change_html: Puedes trokar tu adreso de posta elektronika sin supremir tu kuento
+ email_contact_html: Si ainda no te tiene parvenido, puedes eskrivir a %{email} para pider ayuda
+ email_reconfirmation_html: Si no te tiene parvenido la posta de konfirmasyon, puedes retornar a solisitarlo
irreversible: No podras restaurar ni reaktivar tu kuento
more_details_html: Para mas detalyos, ver la politika de privasita.
username_available: Tu nombre de utilizador retornara a estar desponivle
@@ -1182,8 +1200,6 @@ lad:
your_appeal_approved: Tu apelasyon fue achetada
your_appeal_pending: Tienes enviado una apelasyon
your_appeal_rejected: Tu apelasyon fue refuzada
- domain_validator:
- invalid_domain: no es un nombre de domeno valido
edit_profile:
basic_information: Enformasyon bazika
hint_html: "Personaliza lo ke la djente ve en tu profil publiko i kon tus publikasyones. Es mas probavle ke otras personas te sigan i enteraktuen kontigo kuando kompletas tu profil i foto."
@@ -1380,6 +1396,7 @@ lad:
authentication_methods:
otp: aplikasyon de autentifikasyon en dos pasos
password: kod
+ sign_in_token: kodiche de sigurita por posta elektronika
webauthn: yaves de sigurita
description_html: Si ves una aktivita ke no rekoneses, konsidera trokar tu kod i kapasitar la autentifikasyon en dos pasos.
empty: No ay estoria de autentifikasyon desponivle
@@ -1390,6 +1407,7 @@ lad:
unsubscribe:
action: Si, dezabona
complete: Dezabonado
+ confirmation_html: Estas siguro de ke ya no keres risivir %{type} de Mastodon en %{domain} a tu posta elektronika %{email}? Syempre podras reabonarte dizde las opsyones de avizos por posta..
emails:
notification_emails:
favourite: avizos de favoritos por posta
@@ -1675,23 +1693,12 @@ lad:
edited_at_html: Editado %{date}
errors:
in_reply_not_found: La publikasion a la ke aprovas arispondir no egziste.
- open_in_web: Avre en web
over_character_limit: limito de karakteres de %{max} superado
pin_errors:
direct: Las publikasyones ke son vizivles solo para los utilizadores enmentados no pueden fiksarse
limit: Ya tienes fiksado el numero maksimo de publikasyones
ownership: La publikasyon de otra persona no puede fiksarse
reblog: No se puede fixar una repartajasyon
- poll:
- total_people:
- one: "%{count} persona"
- other: "%{count} personas"
- total_votes:
- one: "%{count} voto"
- other: "%{count} votos"
- vote: Vota
- show_more: Amostra mas
- show_thread: Amostra diskusyon
title: '%{name}: "%{quote}"'
visibilities:
direct: Direkto
@@ -1875,6 +1882,7 @@ lad:
invalid_otp_token: Kodiche de dos pasos no valido
otp_lost_help_html: Si pedriste akseso a los dos, puedes kontaktarte kon %{email}
rate_limited: Demaziadas provas de autentifikasyon, aprova de muevo dempues.
+ seamless_external_login: Estas konektado por un servisyo eksterno i estonses la konfigurasyon de kod i konto de posta no estan disponivles.
signed_in_as: 'Konektado komo:'
verification:
extra_instructions_html: Konsejo: El atadijo en tu web puede ser invizivle. La parte importante es rel="me"
, ke evita la suplantasyon de identita en sitios kon kontenido jenerado por el utilizador. Puedes inkluzo uzar una etiketa atadijo
en la kavesera de la pajina en vez de a
, ama el HTML deve ser aksesivle sin exekutar JavaScript.
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index fd3dbc00b1..fa07eb6f59 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -7,7 +7,6 @@ lt:
hosted_on: Mastodon talpinamas %{domain}
title: Apie
accounts:
- follow: Sekti
followers:
few: Sekėjai
many: Sekėjo
@@ -29,6 +28,8 @@ lt:
admin:
account_actions:
action: Atlikti veiksmą
+ already_silenced: Ši paskyra jau buvo apribota.
+ already_suspended: Ši paskyra jau sustabdyta.
title: Atlikti prižiūrėjimo veiksmą %{acct}
account_moderation_notes:
create: Palikti pastabą
@@ -49,6 +50,7 @@ lt:
title: Keisti el. paštą %{username}
change_role:
changed_msg: Vaidmuo sėkmingai pakeistas.
+ edit_roles: Tvarkyti naudotojų vaidmenis
label: Keisti vaidmenį
no_role: Jokios vaidmenį
title: Keisti vaidmenį %{username}
@@ -419,9 +421,21 @@ lt:
domain: Domenas
new:
create: Pridėto domeną
+ export_domain_allows:
+ new:
+ title: Importuoti domeno leidžiamus
+ no_file: Nėra pasirinkto failo
export_domain_blocks:
import:
description_html: Netrukus importuosi domenų blokavimų sąrašą. Labai atidžiai peržiūrėk šį sąrašą, ypač jei ne tu jį sudarei.
+ existing_relationships_warning: Esami sekimo sąryšiai
+ private_comment_description_html: 'Kad būtų lengviau atsekti, iš kur importuoti blokavimai, importuoti blokavimai bus kuriami su šiuo privačiu komentaru: %{comment}
'
+ private_comment_template: Importuota iš %{source}, %{date}
+ title: Importuoti domeno blokavimus
+ invalid_domain_block: 'Vienas ar daugiau domenų blokavimų buvo praleisti dėl toliau nurodytos (-ų) klaidos (-ų): %{error}'
+ new:
+ title: Importuoti domeno blokavimus
+ no_file: Nėra pasirinkto failo
follow_recommendations:
language: Kalbui
status: Būsena
@@ -485,6 +499,7 @@ lt:
destroyed_msg: Skundo žinutė sekmingai ištrinta!
reports:
action_taken_by: Veiksmo ėmėsi
+ actions_no_posts: Ši ataskaita neturi jokių susijusių įrašų ištrinti
already_suspended_badges:
local: Jau sustabdytas šiame serveryje
remote: Jau sustabdytas jų serveryje
@@ -582,6 +597,8 @@ lt:
trending: Tendencinga
with_media: Su medija
system_checks:
+ database_schema_check:
+ message_html: Laukiama duomenų bazės perkėlimo. Paleisk juos, kad įsitikintum, jog programa veikia taip, kaip tikimasi.
elasticsearch_health_yellow:
message_html: Elasticsearch klasteris yra nesveikas (geltona būsena), galbūt norėsi išsiaiškinti priežastį
elasticsearch_preset:
@@ -795,6 +812,12 @@ lt:
redirecting_to: Tavo paskyra yra neaktyvi, nes šiuo metu ji nukreipiama į %{acct}.
self_destruct: Kadangi %{domain} uždaromas, turėsi tik ribotą prieigą prie savo paskyros.
view_strikes: Peržiūrėti ankstesnius savo paskyros pažeidimus
+ author_attribution:
+ example_title: Teksto pavyzdys
+ hint_html: Valdyk, kaip esi nurodomas (-a), kai nuorodos bendrinamos platformoje „Mastodon“.
+ more_from_html: Daugiau iš %{name}
+ s_blog: "%{name} tinklaraštis"
+ title: Autoriaus (-ės) atribucija
challenge:
hint_html: "Patarimas: artimiausią valandą daugiau neprašysime tavo slaptažodžio."
datetime:
@@ -836,24 +859,24 @@ lt:
title: Nepavyko saugumo patvirtinimas
'429': Stabdomas
'500':
- content: Atsiprašome, tačiau mūsų pusėje įvyko klaida.
+ content: Atsiprašome, bet kažkas nutiko ne taip mūsų pusėje.
title: Netinkamas puslapis
noscript_html: Kad naudotumėtės Mastodon web aplikacija, prašome įsijungti JavaScript. Alternatyviai, pabandykite viena iš vietinių aplikacijų Mastodon savo platformai.
exports:
archive_takeout:
date: Data
- download: Parsisiųsti archyvą
- hint_html: Jūs galite prašyti savo įrašų bei medijos archyvo. Eksportuota informacija bus ActivityPub formatu, skaitoma suderintų programų. Galite prašyti archyvo, kas 7 dienas.
+ download: Atsisiųsti archyvą
+ hint_html: Gali paprašyti savo įrašų ir įkeltos medijos archyvo. Eksportuoti duomenys bus „ActivityPub“ formatu, kurį galima perskaityti bet kuria suderinama programine įranga. Archyvo galima prašyti kas 7 dienas.
in_progress: Sudaromas archyvas...
request: Prašyti savo archyvo
size: Dydis
- blocks: Jūs blokuojate
+ blocks: Blokuoji
bookmarks: Žymės
csv: CSV
- domain_blocks: Domeno blokai
+ domain_blocks: Domeno blokavimai
lists: Sąrašai
- mutes: Jūs tildote
- storage: Medijos sandėlis
+ mutes: Nutildei
+ storage: Medijos saugykla
featured_tags:
add_new: Pridėti naują
hint_html: "Savo profilyje parodyk svarbiausius saitažodžius. Tai puikus įrankis kūrybiniams darbams ir ilgalaikiams projektams sekti, todėl svarbiausios saitažodžiai rodomi matomoje vietoje profilyje ir leidžia greitai pasiekti tavo paties įrašus."
@@ -893,7 +916,7 @@ lt:
merge_long: Išsaugoti esančius įrašus ir pridėti naujus
overwrite: Perrašyti
overwrite_long: Pakeisti senus įrašus naujais
- preface: Jūs galite importuoti informaciją iš kito serverio, tokią kaip sąrašą žmonių kuriuos sekate.
+ preface: Gali importuoti duomenis, kuriuos eksportavai iš kito serverio, pavyzdžiui, sekamų arba blokuojamų žmonių sąrašą.
success: Jūsų informacija sėkmingai įkelta ir bus apdorota kaip įmanoma greičiau
types:
blocking: Blokuojamų sąrašas
@@ -939,10 +962,13 @@ lt:
media_attachments:
validations:
images_and_video: Negalima pridėti video prie statuso, kuris jau turi nuotrauką
+ not_found: Medija %{ids} nerasta arba jau pridėta prie kito įrašo.
too_many: Negalima pridėti daugiau nei 4 failų
migrations:
acct: Perkelta į
cancel: Atšaukti nukreipimą
+ warning:
+ disabled_account: Po to tavo dabartine paskyra nebus galima naudotis visiškai. Tačiau turėsi prieigą prie duomenų eksporto ir pakartotinio aktyvavimo.
moderation:
title: Prižiūrėjimas
notification_mailer:
@@ -1033,7 +1059,7 @@ lt:
generic: Nežinoma naršyklė
current_session: Dabartinis seansas
date: Data
- description: "%{browser} ant %{platform}"
+ description: "„%{browser}“ per „%{platform}“"
explanation: Čia rodomos web naršyklės prijungtos prie Jūsų Mastodon paskyros.
ip: IP
platforms:
@@ -1067,6 +1093,7 @@ lt:
export: Duomenų eksportas
featured_tags: Rodomi saitažodžiai
import: Importuoti
+ import_and_export: Importas ir eksportas
migrate: Paskyros migracija
notifications: El. laiško pranešimai
preferences: Nuostatos
@@ -1094,16 +1121,11 @@ lt:
other: "%{count} vaizdų"
boosted_from_html: Pakelta iš %{acct_link}
content_warning: 'Turinio įspėjimas: %{warning}'
- open_in_web: Atidaryti naudojan Web
over_character_limit: pasiektas %{max} simbolių limitas
pin_errors:
limit: Jūs jau prisegėte maksimalų toot'ų skaičų
ownership: Kitų vartotojų toot'ai negali būti prisegti
reblog: Pakeltos žinutės negali būti prisegtos
- poll:
- vote: Balsuoti
- show_more: Rodyti daugiau
- show_thread: Rodyti giją
visibilities:
private: Tik sekėjams
private_long: rodyti tik sekėjams
@@ -1113,6 +1135,7 @@ lt:
unlisted_long: matyti gali visi, bet nėra išvardyti į viešąsias laiko skales
statuses_cleanup:
enabled_hint: Automatiškai ištrina įrašus, kai jie pasiekia nustatytą amžiaus ribą, nebent jie atitinka vieną iš toliau nurodytų išimčių
+ interaction_exceptions_explanation: Atkreipk dėmesį, kad negarantuojama, jog įrašai nebus ištrinti, jei jų mėgstamumo ar pasidalinimo riba bus žemesnė, nors vieną kartą ji jau buvo viršyta.
keep_polls_hint: Neištrina jokių tavo apklausų
keep_self_bookmark: Laikyti įrašus, kuriuos pažymėjai
keep_self_bookmark_hint: Neištrina tavo pačių įrašų, jei esi juos pažymėjęs (-usi)
@@ -1223,6 +1246,7 @@ lt:
instructions_html: Nukopijuok ir įklijuok toliau pateiktą kodą į savo svetainės HTML. Tada į vieną iš papildomų profilio laukų skirtuke Redaguoti profilį įrašyk savo svetainės adresą ir išsaugok pakeitimus.
verification: Patvirtinimas
verified_links: Tavo patikrintos nuorodos
+ website_verification: Svetainės patvirtinimas
webauthn_credentials:
add: Pridėti naują saugumo raktą
create:
diff --git a/config/locales/lv.yml b/config/locales/lv.yml
index 43b6995e28..4aeec5ceca 100644
--- a/config/locales/lv.yml
+++ b/config/locales/lv.yml
@@ -1,13 +1,12 @@
---
lv:
about:
- about_mastodon_html: 'Nākotnes sociālais tīkls: bez reklāmām, bez korporatīvās uzraudzības, ētisks dizains un decentralizācija! Pārvaldi savus datus ar Mastodon!'
+ about_mastodon_html: 'Nākotnes sabiedriskais tīkls: bez reklāmām, bez korporatīvās novērošanas, ētiska projektēšana un decentralizēšana. Pārvaldi savus datus ar Mastodon!'
contact_missing: Nav uzstādīts
contact_unavailable: N/A
hosted_on: Mastodon mitināts %{domain}
title: Par
accounts:
- follow: Sekot
followers:
one: Sekotājs
other: Sekotāji
@@ -27,6 +26,8 @@ lv:
admin:
account_actions:
action: Veikt darbību
+ already_silenced: Šis konts jau ir ierobežots.
+ already_suspended: Šis konts jau ir aizturēts.
title: Veikt moderācijas darbību %{acct}
account_moderation_notes:
create: Atstāt piezīmi
@@ -47,6 +48,7 @@ lv:
title: Mainīt e-pastu %{username}
change_role:
changed_msg: Loma veiksmīgi nomainīta!
+ edit_roles: Pārvaldīt lietotāju lomas
label: Mainīt lomu
no_role: Nav lomas
title: Mainīt lomu %{username}
@@ -132,6 +134,7 @@ lv:
resubscribe: Pieteikties vēlreiz
role: Loma
search: Meklēt
+ search_same_email_domain: Citi lietotāji ar tādu pašu e-pasta domēnu
search_same_ip: Citi lietotāji ar tādu pašu IP
security: Drošība
security_measures:
@@ -172,6 +175,7 @@ lv:
approve_appeal: Apstiprināt Apelāciju
approve_user: Apstiprināt lietotāju
assigned_to_self_report: Piešķirt Pārskatu
+ change_email_user: Mainīt lietotāja e-pasta adresi
change_role_user: Mainīt lietotāja lomu
confirm_user: Apstiprināt lietotāju
create_account_warning: Izveidot Brīdinājumu
@@ -218,13 +222,16 @@ lv:
update_custom_emoji: Atjaunināt pielāgoto emocijzīmi
update_domain_block: Atjaunināt Domēna Bloku
update_ip_block: Atjaunināt IP noteikumu
+ update_report: Atjaunināt atskaiti
update_status: Atjaunināt ziņu
update_user_role: Atjaunināt lomu
actions:
approve_appeal_html: "%{name} apstiprināja moderācijas lēmuma apelāciju no %{target}"
approve_user_html: "%{name} apstiprināja reģistrēšanos no %{target}"
assigned_to_self_report_html: "%{name} piešķīra pārskatu %{target} sev"
+ change_email_user_html: "%{name} nomainīja lietotāja %{target} e-pasta adresi"
change_role_user_html: "%{name} nomainīja lomu uz %{target}"
+ confirm_user_html: "%{name} apstiprināja lietotāja %{target} e-pasta adresi"
create_account_warning_html: "%{name} nosūtīja brīdinājumu %{target}"
create_announcement_html: "%{name} izveidoja jaunu paziņojumu %{target}"
create_custom_emoji_html: "%{name} augšupielādēja jaunu emocijzīmi %{target}"
@@ -254,6 +261,7 @@ lv:
reject_user_html: "%{name} noraidīja reģistrēšanos no %{target}"
remove_avatar_user_html: "%{name} noņēma %{target} profila attēlu"
reopen_report_html: "%{name} atkārtoti atvēra ziņojumu %{target}"
+ resend_user_html: "%{name} atkārtoti nosūtīja %{target} apstiprinājuma e-pasta ziņojumu"
reset_password_user_html: "%{name} atiestatīja paroli lietotājam %{target}"
resolve_report_html: "%{name} atrisināja ziņojumu %{target}"
sensitive_account_html: "%{name} atzīmēja %{target} multividi kā sensitīvu"
@@ -268,6 +276,7 @@ lv:
update_custom_emoji_html: "%{name} atjaunināja emocijzīmi %{target}"
update_domain_block_html: "%{name} atjaunināja domēna bloku %{target}"
update_ip_block_html: "%{name} mainīja nosacījumu priekš IP %{target}"
+ update_report_html: "%{name} atjaunināja %{target} pārskatu"
update_status_html: "%{name} atjaunināja ziņu %{target}"
update_user_role_html: "%{name} nomainīja %{target} lomu"
deleted_account: dzēsts konts
@@ -275,6 +284,7 @@ lv:
filter_by_action: Filtrēt pēc darbības
filter_by_user: Filtrēt pēc lietotāja
title: Auditācijas pieraksti
+ unavailable_instance: "(domēna vārds nav pieejams)"
announcements:
destroyed_msg: Paziņojums ir veiksmīgi izdzēsts!
edit:
@@ -451,6 +461,9 @@ lv:
title: Sekošanas ieteikumi
unsuppress: Atjaunot sekošanas rekomendāciju
instances:
+ audit_log:
+ title: Nesenie pārbaudes žurnāli
+ view_all: Skatīt pilnus pārbaudes žurnālus
availability:
description_html:
one: Ja piegāde uz domēnu neizdodas %{count} dienu bez panākumiem, turpmāki piegādes mēģinājumi netiks veikti, ja vien netiks saņemta piegāde no domēna.
@@ -581,7 +594,9 @@ lv:
resolve_description_html: Pret norādīto kontu netiks veiktas nekādas darbības, netiks reģistrēts brīdinājums, un ziņojums tiks slēgts.
silence_description_html: Konts būs redzams tikai tiem, kas tam jau seko vai meklē to manuāli, ievērojami ierobežojot tā sasniedzamību. To vienmēr var atgriezt. Tiek aizvērti visi šī konta pārskati.
suspend_description_html: Konts un viss tā saturs nebūs pieejams un galu galā tiks izdzēsts, un mijiedarbība ar to nebūs iespējama. Atgriežams 30 dienu laikā. Tiek aizvērti visi šī konta pārskati.
+ actions_description_html: Izlem, kādas darbības jāveic, lai atrisinātu šo ziņojumu. Ja tiks pieņemti sodoši mēri pret kontu, par kuru ziņots, tam e-pastā tiks nosūtīts paziņojums, izņemot gadījumus, kad ir atlasīta kategorija Mēstules.
actions_description_remote_html: Izlem, kādas darbības jāveic, lai atrisinātu šo ziņojumu. Tas ietekmēs tikai to, kā tavs serveris sazinās ar šo attālo kontu un apstrādā tā saturu.
+ actions_no_posts: Šim ziņojumam nav saistītu ierakstu, kurus izdzēst
add_to_report: Pievienot varāk paziņošanai
are_you_sure: Vai esi pārliecināts?
assign_to_self: Piešķirt man
@@ -598,6 +613,7 @@ lv:
created_at: Ziņoti
delete_and_resolve: Izdzēst rakstus
forwarded: Pārsūtīti
+ forwarded_replies_explanation: Šis ziņojums ir no attāla lietotāja un par attālu saturu. Tas tika pārvirzīts šeit, jo saturs, par kuru tika ziņots, ir atbilde vienam no šī servera lietotājiem.
forwarded_to: Pārsūtīti %{domain}
mark_as_resolved: Atzīmēt kā atrisinātu
mark_as_sensitive: Atzīmēt kā sensitīvu
@@ -618,6 +634,7 @@ lv:
report: 'Ziņojums #%{id}'
reported_account: Ziņotais konts
reported_by: Ziņoja
+ reported_with_application: Ziņots no lietotnes
resolved: Atrisināts
resolved_msg: Ziņojums veiksmīgi atrisināts!
skip_to_actions: Pāriet uz darbībām
@@ -856,7 +873,19 @@ lv:
action: Pārbaudi šeit, lai iegūtu plašāku informāciju
message_html: "Tava objektu krātuve ir nepareizi konfigurēta. Tavu lietotāju privātums ir apdraudēts."
tags:
+ moderation:
+ not_usable: Nav izmantojams
+ pending_review: Gaida pārskatīšanu
+ review_requested: Pieprasīta pārskatīšana
+ reviewed: Pārskatīts
+ title: Stāvoklis
+ name: Nosaukums
+ newest: Jaunākie
+ oldest: Vecākie
+ reset: Atiestatīt
review: Pārskatīt stāvokli
+ search: Meklēt
+ title: Tēmturi
updated_msg: Tēmtura iestatījumi ir veiksmīgi atjaunināti
title: Administrēšana
trends:
@@ -930,6 +959,7 @@ lv:
delete: Dzēst
edit_preset: Labot iepriekš iestatītus brīdinājumus
empty: Tu vēl neesi definējis iepriekš iestatītos brīdinājumus.
+ title: Brīdinājumu priekšiestatījums
webhooks:
add_new: Pievienot galapunktu
delete: Dzēst
@@ -1005,7 +1035,9 @@ lv:
guide_link_text: Ikviens var piedalīties.
sensitive_content: Sensitīvs saturs
application_mailer:
+ notification_preferences: Mainīt e-pasta uztādījumus
salutation: "%{name},"
+ settings: 'Mainīt e-pasta uztādījumus: %{link}'
unsubscribe: Atcelt abonēšanu
view: 'Skatīt:'
view_profile: Skatīt profilu
@@ -1025,6 +1057,7 @@ lv:
hint_html: Vēl tikai viena lieta! Mums ir jāapstiprina, ka tu esi cilvēks (tas ir tāpēc, lai mēs varētu nepieļaut surogātpasta izsūtīšanu!). Atrisini tālāk norādīto CAPTCHA un noklikšķini uz "Turpināt".
title: Drošības pārbaude
confirmations:
+ awaiting_review: E-pasta adrese ir apstiprināta. %{domain} darbinieki tagad pārskata reģistrāciju. Tiks saņemts e-pasta ziņojums, ja viņi apstiprinās kontu.
awaiting_review_title: Tava reģistrācija tiek izskatīta
clicking_this_link: klikšķinot šo saiti
login_link: pieteikties
@@ -1032,6 +1065,7 @@ lv:
redirect_to_app_html: Tev vajadzētu būt novirzītam uz lietotni %{app_name}. Ja tas nenotika, mēģini %{clicking_this_link} vai manuāli atgriezieties lietotnē.
registration_complete: Tava reģistrācija domēnā %{domain} tagad ir pabeigta!
welcome_title: Laipni lūdzam, %{name}!
+ wrong_email_hint: Ja šī e-pasta adrese nav pareiza, to var mainīt konta iestatījumos.
delete_account: Dzēst kontu
delete_account_html: Ja vēlies dzēst savu kontu, tu vari turpināt šeit. Tev tiks lūgts apstiprinājums.
description:
@@ -1052,6 +1086,7 @@ lv:
or_log_in_with: Vai piesakies ar
privacy_policy_agreement_html: Esmu izlasījis un piekrītu privātuma politikai
progress:
+ confirm: Apstiprināt e-pasta adresi
details: Tavi dati
review: Mūsu apskats
rules: Pieņemt noteikumus
@@ -1073,11 +1108,13 @@ lv:
security: Drošība
set_new_password: Iestatīt jaunu paroli
setup:
+ email_below_hint_html: Jāpārbauda sava surogātpasta mape vai jāpieprasa vēl vienu! Savu e-pasta adresi var labot, ja tā ir nepareiza.
email_settings_hint_html: Noklikšķini uz saites, kuru mēs tev nosūtījām, lai apstiprinātu %{email}. Mēs tepat pagaidīsim.
link_not_received: Vai nesaņēmi sati?
+ new_confirmation_instructions_sent: Pēc dažām minūtēm saņemsi jaunu e-pasta ziņojumu ar apstiprinājuma saiti.
title: Pārbaudi savu iesūtni
sign_in:
- preamble_html: Jāpiesakās ar saviem %{domain} piekļuves datiem. Ja Tavs konts tiek mitināts citā serverī, Tu nevarēsi šeit pieteikties.
+ preamble_html: Jāpiesakās ar saviem %{domain} piekļuves datiem. Ja konts tiek mitināts citā serverī, šeit nevarēs pieteikties.
title: Pierakstīties %{domain}
sign_up:
manual_review: Reģistrācijas domēnā %{domain} manuāli pārbauda mūsu moderatori. Lai palīdzētu mums apstrādāt tavu reģistrāciju, uzraksti mazliet par sevi un to, kāpēc vēlies kontu %{domain}.
@@ -1085,21 +1122,24 @@ lv:
title: Atļauj tevi iestatīt %{domain}.
status:
account_status: Konta statuss
+ confirming: Gaida e-pasta adreses apstiprināšanas pabeigšanu.
functional: Tavs konts ir pilnā darba kārtībā.
redirecting_to: Tavs konts ir neaktīvs, jo pašlaik tas tiek novirzīts uz %{acct}.
self_destruct: Tā kā %{domain} tiek slēgts, tu iegūsi tikai ierobežotu piekļuvi savam kontam.
view_strikes: Skati iepriekšējos brīdinājumus par savu kontu
too_fast: Veidlapa ir iesniegta pārāk ātri, mēģini vēlreiz.
use_security_key: Lietot drošības atslēgu
+ author_attribution:
+ s_blog: "%{name} emuāri"
+ title: Autora attiecinājums
challenge:
confirm: Turpināt
hint_html: "Padoms: Nākamās stundas laikā mēs tev vairs neprasīsim paroli."
invalid_password: Nepareiza parole
- prompt: Lai turpinātu, apstiprini paroli
+ prompt: Lai turpinātu, jāapstiprina parole
crypto:
errors:
invalid_key: nav derīga Ed25519 vai Curve25519 atslēga
- invalid_signature: nav derīgs Ed25519 paraksts
date:
formats:
default: "%b %d, %Y"
@@ -1128,6 +1168,9 @@ lv:
before: 'Pirms turpināšanas lūgums uzmanīgi izlasīt šīs piezīmes:'
caches: Citu serveru kešatmiņā saglabātais saturs var saglabāties
data_removal: Tavas ziņas un citi dati tiks neatgriezeniski noņemti
+ email_change_html: Savu e-pasta adresi var mainīt bez sava konta izdzēšanas
+ email_contact_html: Ja tas joprojām nav saņemts, var nosūtīt e-pastu uz %{email}, lai saņemtu palīdzību
+ email_reconfirmation_html: Ja netiek saņemts apstiprinājuma e-pasta ziņojums, to var pieprasīt vēlreiz
irreversible: Tu nevarēsi atjaunot vai atkārtoti aktivizēt savu kontu
more_details_html: Plašāku informāciju skatīt privātuma politika.
username_available: Tavs lietotājvārds atkal būs pieejams
@@ -1162,8 +1205,6 @@ lv:
your_appeal_approved: Jūsu apelācija ir apstiprināta
your_appeal_pending: Jūs esat iesniedzis apelāciju
your_appeal_rejected: Jūsu apelācija ir noraidīta
- domain_validator:
- invalid_domain: nav derīgs domēna nosaukums
edit_profile:
basic_information: Pamata informācija
hint_html: "Pielāgo, ko cilvēki redz Tavā publiskajā profilā un blakus Taviem ierakstiem. Ir lielāka iespējamība, ka citi clivēki sekos Tev un mijiedarbosies ar Tevi, ja Tev ir aizpildīts profils un profila attēls."
@@ -1349,6 +1390,7 @@ lv:
'86400': 1 diena
expires_in_prompt: Nekad
generate: Ģenerēt uzaicinājuma saiti
+ invalid: Šis uzaicinājums nav derīgs
invited_by: 'Tevi uzaicināja:'
max_uses:
one: 1 lietojums
@@ -1367,6 +1409,7 @@ lv:
authentication_methods:
otp: divpakāpju autentifikācijas lietotne
password: parole
+ sign_in_token: e-pasta drošības kods
webauthn: drošības atslēgas
description_html: Ja pamani darbības, kuras neatpazīsti, jāapsver iespēja nomainīt savu paroli un iespējot divpakāpju autentifikāciju.
empty: Nav pieejama autentifikācijas vēsture
@@ -1647,25 +1690,12 @@ lv:
edited_at_html: Labots %{date}
errors:
in_reply_not_found: Šķiet, ka ziņa, uz kuru tu mēģini atbildēt, nepastāv.
- open_in_web: Atvērt webā
over_character_limit: pārsniegts %{max} rakstzīmju ierobežojums
pin_errors:
direct: Ziņojumus, kas ir redzami tikai minētajiem lietotājiem, nevar piespraust
limit: Tu jau esi piespraudis maksimālo ziņu skaitu
ownership: Kāda cita ierakstu nevar piespraust
reblog: Izceltu ierakstu nevar piespraust
- poll:
- total_people:
- one: "%{count} cilvēks"
- other: "%{count} cilvēki"
- zero: "%{count} cilvēku"
- total_votes:
- one: "%{count} balss"
- other: "%{count} balsis"
- zero: "%{count} balsu"
- vote: Balsu skaits
- show_more: Rādīt vairāk
- show_thread: Rādīt tematu
title: "%{name}: “%{quote}”"
visibilities:
direct: Tiešs
@@ -1805,14 +1835,20 @@ lv:
explanation: Šeit ir daži padomi, kā sākt darbu
feature_action: Uzzināt vairāk
feature_creativity: Mastodon nodrošina skaņas, video un attēlu ierakstus, pieejamības aprakstus, aptaujas, satura brīdinājumus, animētus profila attēlus, pielāgotas emocijzīmes, sīktēlu apgriešanas vadīklas un vēl, lai palīdzētu Tev sevi izpaust tiešsaistē. Vai Tu izplati savu mākslu, mūziku vai aplādes, Mastodon ir šeit ar Tevi.
+ feature_moderation_title: Moderēšana, kādai tai būtu jābūt
follow_action: Sekot
+ follow_step: Sekošana aizraujošiem cilvēkiem ir viss, par ko ir Mastodon.
follow_title: Pielāgo savu mājas barotni
+ follows_subtitle: Seko labi zināmiem kontiem
follows_title: Kam sekot
follows_view_more: Rādīt vairāk cilvēku, kuriem sekot
hashtags_recent_count:
one: "%{people} cilvēks pēdējās 2 dienās"
other: "%{people} cilvēki pēdējās 2 dienās"
zero: "%{people} cilvēku pēdējās divās dienās"
+ hashtags_subtitle: Izpēti, kas pēdējās divās dienāš ir piesasitījis cilvēku uzmanību
+ hashtags_title: Izplatīti tēmturi
+ hashtags_view_more: Skatīt vairāk izplatītu tēmturu
post_action: Rakstīt
post_step: Pasveicini pasauli ar tekstu, fotoattēliem, video vai aptaujām!
post_title: Izveido savu pirmo ierakstu
@@ -1828,6 +1864,7 @@ lv:
invalid_otp_token: Nederīgs divfaktora kods
otp_lost_help_html: Ja esi zaudējis piekļuvi abiem, tu vari sazināties ar %{email}
rate_limited: Pārāk daudz autentifikācijas mēģinājumu, vēlāk jāmēģina vēlreiz.
+ seamless_external_login: Tu esi pieteicies caur ārēju pakalpojumu, tāpēc paroles un e-pasta iestatījumi nav pieejami.
signed_in_as: 'Pieteicies kā:'
verification:
extra_instructions_html: Padoms: saite Tavā vietnē var būt neredzama. Svarīga daļa ir rel="me"
, kas novērš uzdošanos vietnēs ar lietotāju izveidotu saturu. Tu pat vari lapas galvenē izmantot tagu link
, nevis a
, taču HTML ir jābūt pieejamam bez JavaScript izpildīšanas.
@@ -1836,6 +1873,7 @@ lv:
instructions_html: Ievieto starpliktuvē un ielīmē tālāk norādīto kodu savas tīmekļvietnes HTML! Tad pievieno savas tīmekļvietnes adresi vienā no papildu laukiem savā profila cilnē "Labot profilu" un saglabā izmaiņas!
verification: Pārbaude
verified_links: Tavas verifikācijas saites
+ website_verification: Tīmekļvietnes apliecināšana
webauthn_credentials:
add: Pievienot jaunu drošības atslēgu
create:
diff --git a/config/locales/ml.yml b/config/locales/ml.yml
index a4b9391c00..bdc0475a6f 100644
--- a/config/locales/ml.yml
+++ b/config/locales/ml.yml
@@ -4,7 +4,6 @@ ml:
contact_missing: സജ്ജമാക്കിയിട്ടില്ല
contact_unavailable: ലഭ്യമല്ല
accounts:
- follow: പിന്തുടരുക
following: പിന്തുടരുന്നു
last_active: അവസാനം സജീവമായിരുന്നത്
link_verified_on: സന്ധിയുടെ ഉടമസ്ഥാവസ്കാശം %{date} ൽ പരിശോധിക്കപ്പെട്ടു
diff --git a/config/locales/ms.yml b/config/locales/ms.yml
index 28a2993d36..0c0ffb69bf 100644
--- a/config/locales/ms.yml
+++ b/config/locales/ms.yml
@@ -7,7 +7,6 @@ ms:
hosted_on: Mastodon dihoskan di %{domain}
title: Perihal
accounts:
- follow: Ikut
followers:
other: Pengikut
following: Mengikuti
@@ -1052,7 +1051,6 @@ ms:
crypto:
errors:
invalid_key: bukan kunci Ed25519 atau Curve25519 yang sah
- invalid_signature: bukan tandatangan Ed25519 yang sah
date:
formats:
default: "%b %d, %Y"
@@ -1115,8 +1113,6 @@ ms:
your_appeal_approved: Rayuan anda telah diluluskan
your_appeal_pending: Anda telah menghantar rayuan
your_appeal_rejected: Rayuan anda telah ditolak
- domain_validator:
- invalid_domain: bukan nama domain yang sah
edit_profile:
basic_information: Maklumat Asas
hint_html: "Sesuaikan perkara yang orang lihat pada profil awam anda dan di sebelah siaran anda. Orang lain lebih berkemungkinan mengikuti anda kembali dan berinteraksi dengan anda apabila anda mempunyai profil dan gambar profil yang telah diisi."
@@ -1562,21 +1558,12 @@ ms:
edited_at_html: Disunting %{date}
errors:
in_reply_not_found: Pos yang anda cuba balas nampaknya tidak wujud.
- open_in_web: Buka dalam web
over_character_limit: had aksara %{max} melebihi
pin_errors:
direct: Pos yang hanya boleh dilihat oleh pengguna yang disebut tidak boleh disematkan
limit: Anda telah menyematkan bilangan maksimum pos
ownership: Siaran orang lain tidak boleh disematkan
reblog: Rangsangan tidak boleh disematkan
- poll:
- total_people:
- other: "%{count} orang"
- total_votes:
- other: "%{count} undi"
- vote: Undi
- show_more: Tunjuk lebih banyak
- show_thread: Tunjuk bebenang
title: '%{name}: "%{quote}"'
visibilities:
direct: Terus
diff --git a/config/locales/my.yml b/config/locales/my.yml
index 76372ba174..6acaa34cdc 100644
--- a/config/locales/my.yml
+++ b/config/locales/my.yml
@@ -7,7 +7,6 @@ my:
hosted_on: "%{domain} မှ လက်ခံဆောင်ရွက်ထားသော Mastodon"
title: အကြောင်း
accounts:
- follow: စောင့်ကြည့်မယ်
followers:
other: စောင့်ကြည့်သူ
following: စောင့်ကြည့်နေသည်
@@ -1045,7 +1044,6 @@ my:
crypto:
errors:
invalid_key: မှန်ကန်သော Ed25519 သို့မဟုတ် Curve25519 ကီး မဟုတ်ပါ။
- invalid_signature: မှန်ကန်သော Ed25519 လက်မှတ်မဟုတ်ပါ
date:
formats:
default: "%b %d, %Y"
@@ -1108,8 +1106,6 @@ my:
your_appeal_approved: သင့်တင်သွင်းခြင်းကို အတည်ပြုပြီးပါပြီ
your_appeal_pending: အယူခံဝင်ရန် တင်သွင်းထားသည်
your_appeal_rejected: အယူခံဝင်မှုကို ပယ်ချလိုက်သည်
- domain_validator:
- invalid_domain: တရားဝင်ဒိုမိန်းအမည်မဟုတ်ပါ
edit_profile:
basic_information: အခြေခံသတင်းအချက်အလက်
hint_html: "သင်၏ အများမြင်ပရိုဖိုင်နှင့် သင့်ပို့စ်များဘေးရှိ တွေ့မြင်ရသည့်အရာကို စိတ်ကြိုက်ပြင်ဆင်ပါ။ သင့်တွင် ပရိုဖိုင်နှင့် ပရိုဖိုင်ပုံတစ်ခု ဖြည့်သွင်းထားပါက အခြားသူများအနေဖြင့် သင်နှင့် အပြန်အလှန် တုံ့ပြန်နိုင်ခြေပိုများပါသည်။"
@@ -1562,21 +1558,12 @@ my:
edited_at_html: "%{date} ကို ပြင်ဆင်ပြီးပါပြီ"
errors:
in_reply_not_found: သင် စာပြန်နေသည့်ပို့စ်မှာ မရှိတော့ပါ။
- open_in_web: ဝဘ်တွင် ဖွင့်ပါ
over_character_limit: စာလုံးကန့်သတ်ချက် %{max} ကို ကျော်လွန်သွားပါပြီ
pin_errors:
direct: အမည်ဖော်ပြထားသည့် ပို့စ်များကို ပင်တွဲ၍မရပါ
limit: သင်သည် ပို့စ်အရေအတွက်အများဆုံးကို ပင်တွဲထားပြီးဖြစ်သည်
ownership: အခြားသူ၏ပို့စ်ကို ပင်တွဲ၍မရပါ
reblog: Boost လုပ်ထားသောပို့စ်ကို ပင်ထား၍မရပါ
- poll:
- total_people:
- other: "%{count} ယောက်"
- total_votes:
- other: မဲအရေအတွက် %{count} မဲ
- vote: မဲပေးမည်
- show_more: ပိုမိုပြရန်
- show_thread: Thread ကို ပြပါ
title: '%{name}: "%{quote}"'
visibilities:
direct: တိုက်ရိုက်
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index 0c125acd07..afc4652bf6 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -7,7 +7,6 @@ nl:
hosted_on: Mastodon op %{domain}
title: Over
accounts:
- follow: Volgen
followers:
one: Volger
other: Volgers
@@ -25,6 +24,8 @@ nl:
admin:
account_actions:
action: Actie uitvoeren
+ already_silenced: Dit account is al beperkt.
+ already_suspended: Dit account is al geschorst.
title: Moderatiemaatregel tegen %{acct} nemen
account_moderation_notes:
create: Laat een opmerking achter
@@ -46,6 +47,7 @@ nl:
title: E-mailadres wijzigen voor %{username}
change_role:
changed_msg: Rol succesvol veranderd!
+ edit_roles: Gebruikersrollen beheren
label: Rol veranderen
no_role: Geen rol
title: Rol van %{username} veranderen
@@ -505,8 +507,8 @@ nl:
dashboard:
instance_accounts_dimension: Meest door ons gevolgde accounts
instance_accounts_measure: opgeslagen accounts
- instance_followers_measure: daar ons daar gevolgd
- instance_follows_measure: door hun hier gevolgd
+ instance_followers_measure: onze volgens daar
+ instance_follows_measure: hun volgers hier
instance_languages_dimension: Meest actieve talen
instance_media_attachments_measure: opgeslagen mediabestanden
instance_reports_measure: rapportages over hun
@@ -602,6 +604,7 @@ nl:
suspend_description_html: Het account en de inhoud hiervan is niet meer toegankelijk, en het is ook niet meer mogelijk om ermee interactie te hebben. Uiteindelijk wordt het account volledig verwijderd. Dit is omkeerbaar binnen 30 dagen. Dit sluit alle rapporten tegen dit account af.
actions_description_html: Beslis welke maatregel moet worden genomen om deze rapportage op te lossen. Wanneer je een (straf)maatregel tegen het gerapporteerde account neemt, krijgt het account een e-mailmelding, behalve wanneer de spam-categorie is gekozen.
actions_description_remote_html: Beslis welke actie moet worden ondernomen om deze rapportage op te lossen. Dit is alleen van invloed op hoe jouw server met dit externe account communiceert en de inhoud ervan beheert.
+ actions_no_posts: Dit rapport heeft geen bijbehorende berichten om te verwijderen
add_to_report: Meer aan de rapportage toevoegen
already_suspended_badges:
local: Al geschorst op deze server
@@ -898,7 +901,7 @@ nl:
name: Naam
newest: Nieuwste
oldest: Oudste
- open: Openbaar bekijken
+ open: In het openbaar bekijken
reset: Opnieuw
review: Status beoordelen
search: Zoeken
@@ -1157,6 +1160,12 @@ nl:
view_strikes: Bekijk de eerder door moderatoren vastgestelde overtredingen die je hebt gemaakt
too_fast: Formulier is te snel ingediend. Probeer het nogmaals.
use_security_key: Beveiligingssleutel gebruiken
+ author_attribution:
+ example_title: Voorbeeldtekst
+ hint_html: Bepaal hoe we je vermelden, wanneer jouw links op Mastodon worden gedeeld.
+ more_from_html: Meer van %{name}
+ s_blog: De weblog van %{name}
+ title: Auteur-attributie
challenge:
confirm: Doorgaan
hint_html: "Tip: We vragen jou het komende uur niet meer naar jouw wachtwoord."
@@ -1165,7 +1174,6 @@ nl:
crypto:
errors:
invalid_key: is geen geldige Ed25519- of Curve25519-sleutel
- invalid_signature: is geen geldige Ed25519-handtekening
date:
formats:
default: "%d %b %Y"
@@ -1231,8 +1239,6 @@ nl:
your_appeal_approved: Jouw bezwaar is goedgekeurd
your_appeal_pending: Je hebt een bezwaar ingediend
your_appeal_rejected: Jouw bezwaar is afgewezen
- domain_validator:
- invalid_domain: is een ongeldige domeinnaam
edit_profile:
basic_information: Algemene informatie
hint_html: "Wat mensen op jouw openbare profiel en naast je berichten zien aanpassen. Andere mensen gaan je waarschijnlijk eerder volgen en hebben vaker interactie met je, wanneer je profiel is ingevuld en je een profielfoto hebt."
@@ -1454,6 +1460,7 @@ nl:
media_attachments:
validations:
images_and_video: Een video kan niet aan een bericht met afbeeldingen worden gekoppeld
+ not_found: Media %{ids} niet gevonden of al toegevoegd aan een ander bericht
not_ready: Kan geen bestanden toevoegen die nog niet zijn verwerkt. Probeer het later opnieuw!
too_many: Er kunnen niet meer dan 4 afbeeldingen toegevoegd worden
migrations:
@@ -1731,23 +1738,12 @@ nl:
edited_at_html: Bewerkt op %{date}
errors:
in_reply_not_found: Het bericht waarop je probeert te reageren lijkt niet te bestaan.
- open_in_web: In de webapp openen
over_character_limit: Limiet van %{max} tekens overschreden
pin_errors:
direct: Berichten die alleen zichtbaar zijn voor vermelde gebruikers, kunnen niet worden vastgezet
limit: Je hebt het maximaal aantal bericht al vastgemaakt
ownership: Een bericht van iemand anders kan niet worden vastgemaakt
reblog: Een boost kan niet worden vastgezet
- poll:
- total_people:
- one: "%{count} persoon"
- other: "%{count} personen"
- total_votes:
- one: "%{count} stem"
- other: "%{count} stemmen"
- vote: Stemmen
- show_more: Meer tonen
- show_thread: Gesprek tonen
title: '%{name}: "%{quote}"'
visibilities:
direct: Privébericht
@@ -1946,6 +1942,7 @@ nl:
instructions_html: Kopieer en plak de onderstaande code in de HTML van je website. Voeg vervolgens het adres van je website toe aan een van de extra velden op je profiel op het tabblad "Profiel bewerken" en sla de wijzigingen op.
verification: Verificatie
verified_links: Jouw geverifieerde links
+ website_verification: Website-verificatie
webauthn_credentials:
add: Nieuwe beveiligingssleutel toevoegen
create:
diff --git a/config/locales/nn.yml b/config/locales/nn.yml
index a845c1fbb6..dcf571a792 100644
--- a/config/locales/nn.yml
+++ b/config/locales/nn.yml
@@ -7,7 +7,6 @@ nn:
hosted_on: "%{domain} er vert for Mastodon"
title: Om
accounts:
- follow: Fylg
followers:
one: Fylgjar
other: Fylgjarar
@@ -25,6 +24,8 @@ nn:
admin:
account_actions:
action: Utfør
+ already_silenced: Denne kontoen har allereie vorte avgrensa.
+ already_suspended: Denne kontoen er allereie sperra.
title: Utfør moderatorhandling på %{acct}
account_moderation_notes:
create: Legg igjen merknad
@@ -46,6 +47,7 @@ nn:
title: Byt e-post for %{username}
change_role:
changed_msg: Rolle endra!
+ edit_roles: Administrer brukarroller
label: Endre rolle
no_role: Inga rolle
title: Endre rolle for %{username}
@@ -602,6 +604,7 @@ nn:
suspend_description_html: Brukarkontoen og alt innhaldet vil bli utilgjengeleg og til slutt sletta, og det vil vera uråd å samhandla med brukaren. Du kan angra dette innan 30 dagar. Dette avsluttar alle rapportar om kontoen.
actions_description_html: Avgjer kva som skal gjerast med denne rapporteringa. Dersom du utfører straffetiltak mot den rapporterte kontoen, vil dei motta ein e-post – så sant du ikkje har valt kategorien Spam.
actions_description_remote_html: Avgjer kva du vil gjera for å løysa denne rapporten. Dette påverkar berre korleis tenaren din kommuniserer med kontoen på ein annan tenar, og korleis tenaren din handterer innhald derifrå.
+ actions_no_posts: Denne rapporten har ingen tilknytte innlegg å sletta
add_to_report: Legg til i rapporten
already_suspended_badges:
local: Allereie utestengd på denne tenaren
@@ -898,6 +901,7 @@ nn:
name: Namn
newest: Nyaste
oldest: Eldste
+ open: Vis offentleg
reset: Nullstill
review: Sjå gjennom status
search: Søk
@@ -1156,6 +1160,12 @@ nn:
view_strikes: Vis tidligere advarsler mot kontoen din
too_fast: Skjemaet ble sendt inn for raskt, prøv på nytt.
use_security_key: Bruk sikkerhetsnøkkel
+ author_attribution:
+ example_title: Eksempeltekst
+ hint_html: Kontroller korleis du blir kreditert når nokon deler lenker på Mastodon.
+ more_from_html: Meir frå %{name}
+ s_blog: Bloggen til %{name}
+ title: Forfattarkreditering
challenge:
confirm: Hald fram
hint_html: "Tips: Vi skal ikkje spørja deg om passordet ditt igjen i laupet av den neste timen."
@@ -1164,7 +1174,6 @@ nn:
crypto:
errors:
invalid_key: er ikkje ein gild Ed25519 eller Curve25519 nykel
- invalid_signature: er ikkje ein gild Ed25519-signatur
date:
formats:
default: "%d. %b, %Y"
@@ -1230,8 +1239,6 @@ nn:
your_appeal_approved: Din klage har blitt godkjent
your_appeal_pending: Du har levert en klage
your_appeal_rejected: Din klage har blitt avvist
- domain_validator:
- invalid_domain: er ikkje eit gangbart domenenamn
edit_profile:
basic_information: Grunnleggande informasjon
hint_html: "Tilpass kva folk ser på den offentlege profilen din og ved sida av innlegga dine. Andre vil i større grad fylgja og samhandla med deg når du har eit profilbilete og har fyllt ut profilen din."
@@ -1453,6 +1460,7 @@ nn:
media_attachments:
validations:
images_and_video: Kan ikkje leggja ved video til status som allereie inneheld bilete
+ not_found: Media %{ids} vart ikkje funne eller er allereie kopla til eit anna innlegg
not_ready: Kan ikke legge til filer som ikke er ferdigbehandlet. Prøv igjen om et øyeblikk!
too_many: Kan ikkje leggja til meir enn 4 filer
migrations:
@@ -1730,23 +1738,12 @@ nn:
edited_at_html: Redigert %{date}
errors:
in_reply_not_found: Det ser ut til at tutet du freistar å svara ikkje finst.
- open_in_web: Opn på nett
over_character_limit: øvregrensa for teikn, %{max}, er nådd
pin_errors:
direct: Innlegg som bare er synlige for nevnte brukere kan ikke festes
limit: Du har allereie festa så mange tut som det går an å festa
ownership: Du kan ikkje festa andre sine tut
reblog: Ei framheving kan ikkje festast
- poll:
- total_people:
- one: "%{count} person"
- other: "%{count} folk"
- total_votes:
- one: "%{count} røyst"
- other: "%{count} røyster"
- vote: Røyst
- show_more: Vis meir
- show_thread: Vis tråden
title: "%{name}: «%{quote}»"
visibilities:
direct: Direkte
@@ -1945,6 +1942,7 @@ nn:
instructions_html: Kopier og lim inn i koden nedanfor i HTML-koden for nettsida di. Legg deretter adressa til nettsida di til i ei av ekstrafelta på profilen din frå fana "Rediger profil" og lagre endringane.
verification: Stadfesting
verified_links: Dine verifiserte lenker
+ website_verification: Stadfesting av nettside
webauthn_credentials:
add: Legg til ny sikkerhetsnøkkel
create:
diff --git a/config/locales/no.yml b/config/locales/no.yml
index 1087e6485e..1f0b6bacce 100644
--- a/config/locales/no.yml
+++ b/config/locales/no.yml
@@ -7,7 +7,6 @@
hosted_on: Mastodon driftet på %{domain}
title: Om
accounts:
- follow: Følg
followers:
one: Følger
other: Følgere
@@ -31,6 +30,7 @@
created_msg: Moderasjonsnotat laget uten problem!
destroyed_msg: Moderasjonsnotat slettet uten problem!
accounts:
+ add_email_domain_block: Blokker e-postdomenet
approve: Godkjenn
approved_msg: Godkjent %{username} sin registreringsapplikasjon
are_you_sure: Er du sikker?
@@ -1083,7 +1083,6 @@
crypto:
errors:
invalid_key: er ikke en gyldig Ed25519- eller Curve25519-nøkkel
- invalid_signature: er ikke en gyldig Ed25519-signatur
date:
formats:
default: "%d. %b, %Y"
@@ -1146,8 +1145,6 @@
your_appeal_approved: Anken din har blitt godkjent
your_appeal_pending: Du har levert en anke
your_appeal_rejected: Anken din har blitt avvist
- domain_validator:
- invalid_domain: er ikke et gyldig domenenavn
edit_profile:
basic_information: Grunnleggende informasjon
hint_html: "Tilpass hva folk ser på din offentlige profil og ved siden av dine innlegg. Det er mer sannsynlig at andre mennesker følger deg tilbake og samhandler med deg når du har fylt ut en profil og et profilbilde."
@@ -1620,23 +1617,12 @@
edited_at_html: Redigert %{date}
errors:
in_reply_not_found: Posten du prøver å svare ser ikke ut til eksisterer.
- open_in_web: Åpne i nettleser
over_character_limit: grensen på %{max} tegn overskredet
pin_errors:
direct: Innlegg som bare er synlige for nevnte brukere kan ikke festes
limit: Du har allerede festet det maksimale antall innlegg
ownership: Kun egne innlegg kan festes
reblog: En fremheving kan ikke festes
- poll:
- total_people:
- one: "%{count} person"
- other: "%{count} personer"
- total_votes:
- one: "%{count} stemme"
- other: "%{count} stemmer"
- vote: Stem
- show_more: Vis mer
- show_thread: Vis tråden
title: "%{name}: «%{quote}»"
visibilities:
direct: Direkte
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index 8373513c9b..5cdd9240b0 100644
--- a/config/locales/oc.yml
+++ b/config/locales/oc.yml
@@ -7,7 +7,6 @@ oc:
hosted_on: Mastodon albergat sus %{domain}
title: A prepaus
accounts:
- follow: Sègre
followers:
one: Seguidor
other: Seguidors
@@ -538,8 +537,6 @@ oc:
strikes:
title_actions:
none: Avertiment
- domain_validator:
- invalid_domain: es pas un nom de domeni valid
errors:
'403': Avètz pas l’autorizacion de veire aquesta pagina.
'404': La pagina que cercatz existís pas aquí.
@@ -848,22 +845,11 @@ oc:
edited_at_html: Modificat %{date}
errors:
in_reply_not_found: La publicacion que respondètz sembla pas mai exisitir.
- open_in_web: Dobrir sul web
over_character_limit: limit de %{max} caractèrs passat
pin_errors:
limit: Avètz ja lo maximum de tuts penjats
ownership: Se pòt pas penjar lo tut de qualqu’un mai
reblog: Se pòt pas penjar un tut partejat
- poll:
- total_people:
- one: "%{count} persona"
- other: "%{count} personas"
- total_votes:
- one: "%{count} vòte"
- other: "%{count} vòtes"
- vote: Votar
- show_more: Ne veire mai
- show_thread: Mostrar lo fil
title: '%{name} : "%{quote}"'
visibilities:
direct: Dirècte
diff --git a/config/locales/pa.yml b/config/locales/pa.yml
index 7a34358ddb..1899d71008 100644
--- a/config/locales/pa.yml
+++ b/config/locales/pa.yml
@@ -7,7 +7,6 @@ pa:
hosted_on: "%{domain} ਉੱਤੇ ਹੋਸਟ ਕੀਤਾ ਮਸਟਾਡੋਨ"
title: ਇਸ ਬਾਰੇ
accounts:
- follow: ਫ਼ਾਲੋ
following: ਫ਼ਾਲੋ ਕੀਤੇ ਜਾ ਰਹੇ
posts_tab_heading: ਪੋਸਟਾਂ
admin:
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index d79df666e5..314adf885f 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -7,7 +7,6 @@ pl:
hosted_on: Mastodon prowadzony na %{domain}
title: O nas
accounts:
- follow: Obserwuj
followers:
few: śledzących
many: śledzących
@@ -29,6 +28,8 @@ pl:
admin:
account_actions:
action: Wykonaj działanie
+ already_silenced: To konto zostało już ograniczone.
+ already_suspended: To konto zostało już zawieszone.
title: Wykonaj działanie moderacyjne na %{acct}
account_moderation_notes:
create: Pozostaw notatkę
@@ -50,6 +51,7 @@ pl:
title: Zmień adres e-mail dla %{username}
change_role:
changed_msg: Pomyślnie zmieniono rolę!
+ edit_roles: Zarządzaj rolami użytkowników
label: Zmień rolę
no_role: Brak roli
title: Zmień rolę dla %{username}
@@ -626,6 +628,7 @@ pl:
suspend_description_html: Konto i cała jego zawartość będą niedostępne i ostatecznie usunięte, a interakcja z nim będzie niemożliwa. Możliwość odwrócenia w ciągu 30 dni. Zamyka wszelkie zgłoszenia dotyczące tego konta.
actions_description_html: Zdecyduj, jakie działania należy podjąć, aby rozstrzygnąć niniejsze zgłoszenie. Jeśli podejmiesz działania karne przeciwko zgłoszonemu kontowi, zostanie do nich wysłane powiadomienie e-mail, chyba że wybrano kategorię Spam.
actions_description_remote_html: Zdecyduj, jakie działanie należy podjąć, aby rozwiązać to zgłoszenie. Będzie to miało wpływ jedynie na sposób, w jaki Twój serwer komunikuje się z tym kontem zdalnym i obsługuje jego zawartość.
+ actions_no_posts: Ten raport nie ma żadnych powiązanych wpisów do usunięcia
add_to_report: Dodaj więcej do zgłoszenia
already_suspended_badges:
local: Już zawieszono na tym serwerze
@@ -1193,6 +1196,12 @@ pl:
view_strikes: Zobacz dawne ostrzeżenia nałożone na twoje konto
too_fast: Zbyt szybko przesłano formularz, spróbuj ponownie.
use_security_key: Użyj klucza bezpieczeństwa
+ author_attribution:
+ example_title: Przykładowy tekst
+ hint_html: Kontroluj przypisy do twoich wpisów widoczne na Mastodonie.
+ more_from_html: Więcej od %{name}
+ s_blog: Blog %{name}
+ title: Przypis do autora
challenge:
confirm: Kontynuuj
hint_html: "Informacja: Nie będziemy prosić Cię o ponowne podanie hasła przez następną godzinę."
@@ -1201,7 +1210,6 @@ pl:
crypto:
errors:
invalid_key: nie jest prawidłowym kluczem Ed25519 lub Curve25519
- invalid_signature: nie jest prawidłowym podpisem Ed25519
date:
formats:
default: "%d. %b %Y"
@@ -1267,8 +1275,6 @@ pl:
your_appeal_approved: Twoje odwołanie zostało zatwierdzone
your_appeal_pending: Zgłosiłeś odwołanie
your_appeal_rejected: Twoje odwołanie zostało odrzucone
- domain_validator:
- invalid_domain: nie jest prawidłową nazwą domeny
edit_profile:
basic_information: Podstawowe informacje
hint_html: "Dostosuj to, co ludzie widzą na Twoim profilu publicznym i obok Twoich wpisów. Inne osoby są bardziej skłonne obserwować Cię i wchodzić z Tobą w interakcje, gdy masz wypełniony profil i zdjęcie profilowe."
@@ -1506,6 +1512,7 @@ pl:
media_attachments:
validations:
images_and_video: Nie możesz załączyć pliku wideo do wpisu, który zawiera już zdjęcia
+ not_found: Nie znaleziono mediów %{ids}, lub są już dołączone do innego wpisu
not_ready: Nie można załączyć plików których przetwarzanie nie zostało ukończone. Spróbuj ponownie za chwilę!
too_many: Nie możesz załączyć więcej niż 4 plików
migrations:
@@ -1791,27 +1798,12 @@ pl:
edited_at_html: Edytowane %{date}
errors:
in_reply_not_found: Post, na który próbujesz odpowiedzieć, nie istnieje.
- open_in_web: Otwórz w przeglądarce
over_character_limit: limit %{max} znaków przekroczony
pin_errors:
direct: Nie możesz przypiąć wpisu, który jest widoczny tylko dla wspomnianych użytkowników
limit: Przekroczyłeś maksymalną liczbę przypiętych wpisów
ownership: Nie możesz przypiąć cudzego wpisu
reblog: Nie możesz przypiąć podbicia wpisu
- poll:
- total_people:
- few: "%{count} osoby"
- many: "%{count} osób"
- one: "%{count} osoba"
- other: "%{count} osoby"
- total_votes:
- few: "%{count} głosy"
- many: "%{count} głosy"
- one: "%{count} głos"
- other: "%{count} głosy"
- vote: Głosuj
- show_more: Pokaż więcej
- show_thread: Pokaż wątek
title: '%{name}: "%{quote}"'
visibilities:
direct: Bezpośredni
@@ -2012,6 +2004,7 @@ pl:
instructions_html: Skopiuj poniższy kod HTML i wklej go na swoją stronę. Potem dodaj link do twojej strony do jednego z wolnych pól na profilu z zakładki "Edytuj profil".
verification: Weryfikacja
verified_links: Twoje zweryfikowane linki
+ website_verification: Weryfikacja strony internetowej
webauthn_credentials:
add: Dodaj nowy klucz bezpieczeństwa
create:
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index 418d3d059e..7742a80569 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -4,10 +4,9 @@ pt-BR:
about_mastodon_html: 'A rede social do futuro: Sem anúncios, sem vigilância corporativa, com design ético e muita descentralização! Possua seus próprios dados com o Mastodon!'
contact_missing: Não definido
contact_unavailable: Não disponível
- hosted_on: Servidor Mastodon em %{domain}
+ hosted_on: Mastodon hospedado em %{domain}
title: Sobre
accounts:
- follow: Seguir
followers:
one: Seguidor
other: Seguidores
@@ -25,12 +24,15 @@ pt-BR:
admin:
account_actions:
action: Tomar uma atitude
+ already_silenced: Esta conta já foi limitada.
+ already_suspended: Esta conta já foi suspensa.
title: Moderar %{acct}
account_moderation_notes:
create: Deixar nota
created_msg: Nota de moderação criada!
destroyed_msg: Nota de moderação excluída!
accounts:
+ add_email_domain_block: Bloquear domínio de email
approve: Aprovar
approved_msg: O registro de %{username} foi aprovado
are_you_sure: Você tem certeza?
@@ -44,10 +46,11 @@ pt-BR:
submit: Alterar e-mail
title: Alterar e-mail para %{username}
change_role:
- changed_msg: Cargo alterado!
- label: Alterar cargo
- no_role: Sem cargo
- title: Alterar cargo para %{username}
+ changed_msg: Função alterada com sucesso!
+ edit_roles: Gerenciar funções do usuário
+ label: Alterar função
+ no_role: Nenhuma função
+ title: Alterar função para %{username}
confirm: Confirmar
confirmed: Confirmado
confirming: Confirmando
@@ -57,6 +60,7 @@ pt-BR:
demote: Rebaixar
destroyed_msg: Os dados de %{username} estão na fila para serem excluídos em breve
disable: Congelar
+ disable_sign_in_token_auth: Desativar autenticação via token por email
disable_two_factor_authentication: Desativar autenticação de dois fatores
disabled: Congelada
display_name: Nome de exibição
@@ -65,6 +69,7 @@ pt-BR:
email: E-mail
email_status: Estado do e-mail
enable: Descongelar
+ enable_sign_in_token_auth: Ativar autenticação via token por email
enabled: Ativada
enabled_msg: A conta de %{username} foi descongelada
followers: Seguidores
@@ -129,6 +134,7 @@ pt-BR:
resubscribe: Reinscrever-se
role: Cargo
search: Buscar
+ search_same_email_domain: Outros usuários com o mesmo domínio de e-mail
search_same_ip: Outros usuários com o mesmo IP
security: Segurança
security_measures:
@@ -169,21 +175,26 @@ pt-BR:
approve_appeal: Aprovar revisão
approve_user: Aprovar usuário
assigned_to_self_report: Atribuir denúncia
+ change_email_user: Alterar o Email para o usuário
change_role_user: Alterar cargo do usuário
confirm_user: Confirmar usuário
create_account_warning: Criar aviso
create_announcement: Criar anúncio
+ create_canonical_email_block: Criar bloqueio de Email
create_custom_emoji: Criar emoji personalizado
create_domain_allow: Permitir domínio
create_domain_block: Bloquear domínio
+ create_email_domain_block: Criar Bloqueio de Domínio de Email
create_ip_block: Criar regra de IP
create_unavailable_domain: Criar domínio indisponível
create_user_role: Criar cargo
demote_user: Rebaixar usuário
destroy_announcement: Excluir anúncio
+ destroy_canonical_email_block: Deletar bloqueio de Email
destroy_custom_emoji: Excluir emoji personalizado
destroy_domain_allow: Excluir domínio permitido
destroy_domain_block: Desbloquear domínio
+ destroy_email_domain_block: Deletar bloqueio de domínio Email
destroy_instance: Limpar domínio
destroy_ip_block: Excluir regra de IP
destroy_status: Excluir publicação
@@ -191,8 +202,10 @@ pt-BR:
destroy_user_role: Destruir cargo
disable_2fa_user: Desativar autenticação de dois fatores
disable_custom_emoji: Desativar emoji personalizado
+ disable_sign_in_token_auth_user: Desativar autenticação via Token de Email para Usuário
disable_user: Desativar usuário
enable_custom_emoji: Ativar emoji personalizado
+ enable_sign_in_token_auth_user: Ativar autenticação via Token de Email para Usuário
enable_user: Ativar usuário
memorialize_account: Converter conta em memorial
promote_user: Promover usuário
@@ -215,6 +228,7 @@ pt-BR:
update_custom_emoji: Editar Emoji Personalizado
update_domain_block: Atualizar bloqueio de domínio
update_ip_block: Atualizar regra de IP
+ update_report: Atualizar Relatório
update_status: Editar Status
update_user_role: Atualizar cargo
actions:
@@ -223,19 +237,24 @@ pt-BR:
assigned_to_self_report_html: "%{name} atribuiu a denúncia %{target} para si"
change_email_user_html: "%{name} alterou o endereço de e-mail do usuário %{target}"
change_role_user_html: "%{name} alterou o cargo de %{target}"
+ confirm_user_html: "%{name} confirmou o endereço de e-mail do usuário %{target}"
create_account_warning_html: "%{name} enviou um aviso para %{target}"
create_announcement_html: "%{name} criou o novo anúncio %{target}"
+ create_canonical_email_block_html: "%{name} bloqueou o endereço de e-mail com o hash %{target}"
create_custom_emoji_html: "%{name} enviou o novo emoji %{target}"
create_domain_allow_html: "%{name} permitiu federação com domínio %{target}"
create_domain_block_html: "%{name} bloqueou o domínio %{target}"
+ create_email_domain_block_html: "%{name} bloqueou o domínio de e-mail %{target}"
create_ip_block_html: "%{name} criou a regra para o IP %{target}"
create_unavailable_domain_html: "%{name} parou a entrega ao domínio %{target}"
create_user_role_html: "%{name} criou o cargo %{target}"
demote_user_html: "%{name} rebaixou o usuário %{target}"
destroy_announcement_html: "%{name} excluiu o anúncio %{target}"
+ destroy_canonical_email_block_html: "%{name} desbloqueou o endereço e-mail com o hash %{target}"
destroy_custom_emoji_html: "%{name} apagou o emoji %{target}"
destroy_domain_allow_html: "%{name} bloqueou federação com domínio %{target}"
destroy_domain_block_html: "%{name} desbloqueou o domínio %{target}"
+ destroy_email_domain_block_html: "%{name} desbloqueou o domínio de e-mail %{target}"
destroy_instance_html: "%{name} limpou o domínio %{target}"
destroy_ip_block_html: "%{name} excluiu a regra para o IP %{target}"
destroy_status_html: "%{name} removeu a publicação de %{target}"
@@ -243,8 +262,10 @@ pt-BR:
destroy_user_role_html: "%{name} excluiu o cargo %{target}"
disable_2fa_user_html: "%{name} desativou a exigência da autenticação de dois fatores para o usuário %{target}"
disable_custom_emoji_html: "%{name} desativou o emoji %{target}"
+ disable_sign_in_token_auth_user_html: "%{name} desativou a autenticação via token por e-mail para %{target}"
disable_user_html: "%{name} desativou o login para %{target}"
enable_custom_emoji_html: "%{name} ativou o emoji %{target}"
+ enable_sign_in_token_auth_user_html: "%{name} ativou a autenticação via token por e-mail para %{target}"
enable_user_html: "%{name} ativou o login para %{target}"
memorialize_account_html: "%{name} transformou a conta de %{target} em um memorial"
promote_user_html: "%{name} promoveu o usuário %{target}"
@@ -252,6 +273,7 @@ pt-BR:
reject_user_html: "%{name} rejeitou a inscrição de %{target}"
remove_avatar_user_html: "%{name} removeu a imagem de perfil de %{target}"
reopen_report_html: "%{name} reabriu a denúncia %{target}"
+ resend_user_html: "%{name} reenviou um e-mail de confirmação para %{target}"
reset_password_user_html: "%{name} redefiniu a senha de %{target}"
resolve_report_html: "%{name} resolveu a denúncia %{target}"
sensitive_account_html: "%{name} marcou a mídia de %{target} como sensível"
@@ -412,6 +434,7 @@ pt-BR:
attempts_over_week:
one: "%{count} tentativa na última semana"
other: "%{count} tentativas de inscrição na última semana"
+ created_msg: Domínio de e-mail bloqueado com sucesso
delete: Excluir
dns:
types:
@@ -420,8 +443,12 @@ pt-BR:
new:
create: Adicionar domínio
resolve: Resolver domínio
+ title: Bloquear novo domínio de e-mail
+ no_email_domain_block_selected: Nenhum bloco de domínio de email foi alterado, pois, nenhum foi selecionado
not_permitted: Não permitido
+ resolved_dns_records_hint_html: O nome de domínio é associado aos seguintes domínios MX, que são responsáveis por aceitar e-mails. Ao bloquear um domínio MX, você bloqueará as inscrições de qualquer endereço de e-mail que use o mesmo domínio MX, mesmo que o nome de domínio visível seja diferente. Tenha cuidado para não bloquear os principais provedores de e-mail.
resolved_through_html: Resolvido através de %{domain}
+ title: Domínios de e-mail bloqueados
export_domain_allows:
new:
title: Importar domínios permitidos
@@ -446,6 +473,9 @@ pt-BR:
title: Recomendações de contas
unsuppress: Restaurar recomendação de contas
instances:
+ audit_log:
+ title: Logs de auditoria recentes
+ view_all: Ver todos os logs de auditoria
availability:
description_html:
one: Se a entrega ao domínio falhar em %{count} dia sem sucesso, nenhuma tentativa de entrega será feita a menos que uma entrega do domínio seja recebida.
@@ -572,7 +602,9 @@ pt-BR:
resolve_description_html: Nenhuma ação será tomada contra a conta denunciada, nenhuma violação será guardada e a denúncia será encerrada.
silence_description_html: A conta ficará visível apenas para aqueles que já a seguem ou que a procuram manualmente, limitando severamente seu alcance. Pode ser revertido a qualquer momento. Fecha todas as denúncias desta conta.
suspend_description_html: A conta e todo o seu conteúdo ficará inacessível e, eventualmente, excluído e interagir com ela será impossível. Reversível dentro de 30 dias. Encerra todas as denúncias contra esta conta.
+ actions_description_html: Decida qual ação tomar para responder a essa denúncia. Se você tomar uma ação punitiva contra a conta denunciada, uma notificação por e-mail será enviada ao usuário, exceto quando a categoria Spam for selecionada.
actions_description_remote_html: Decida quais medidas tomará para resolver esta denúncia. Isso só afetará como seu servidor se comunica com esta conta remota e manipula seu conteúdo.
+ actions_no_posts: Essa denúncia não tem nenhuma publicação associada para excluir
add_to_report: Adicionar mais à denúncia
already_suspended_badges:
local: Já suspenso neste servidor
@@ -613,6 +645,7 @@ pt-BR:
report: 'Denúncia #%{id}'
reported_account: Conta denunciada
reported_by: Denunciada por
+ reported_with_application: Denunciado pelo aplicativo
resolved: Resolvido
resolved_msg: Denúncia resolvida!
skip_to_actions: Pular para ações
@@ -635,6 +668,7 @@ pt-BR:
delete_data_html: Exclua o perfil e o conteúdo de @%{acct} daqui a 30 dias, a menos que a suspensão seja desfeita nesse meio tempo
preview_preamble_html: "@%{acct} receberá um aviso com o seguinte conteúdo:"
record_strike_html: Registre uma ação contra @%{acct} para te ajudar em futuras violações desta conta
+ send_email_html: Enviar @%{acct} um e-mail de alerta
warning_placeholder: Argumentos adicionais para a ação de moderação.
target_origin: Origem da conta denunciada
title: Denúncias
@@ -674,6 +708,7 @@ pt-BR:
manage_appeals: Gerenciar revisões
manage_appeals_description: Permite aos usuários visualizar as revisões das decisões da moderação
manage_blocks: Gerenciar Bloqueios
+ manage_blocks_description: Permite aos usuários bloquear provedores de e-mail e endereços IP
manage_custom_emojis: Gerenciar Emojis Personalizados
manage_custom_emojis_description: Permite aos usuários gerenciar emojis personalizados no servidor
manage_federation: Gerenciar Federação
@@ -691,6 +726,7 @@ pt-BR:
manage_taxonomies: Gerenciar taxonomias
manage_taxonomies_description: Permite aos usuários rever o conteúdo em alta e atualizar as configurações de hashtag
manage_user_access: Gerenciar Acesso de Usuário
+ manage_user_access_description: Permite aos usuários desativar a autenticação de dois fatores de outros usuários, alterar seu endereço de e-mail e redefinir sua senha
manage_users: Gerenciar usuários
manage_users_description: Permite aos usuários ver os detalhes de outros usuários e executar ações de moderação contra eles
manage_webhooks: Gerenciar Webhooks
@@ -765,6 +801,7 @@ pt-BR:
destroyed_msg: Upload do site excluído com sucesso!
software_updates:
critical_update: Crítico — por favor, atualize rapidamente
+ description: É recomendável que você mantenha a instalação do Mastodon atualizada para se beneficiar das correções e das novas funcionalidades. Além disso, às vezes é imprescindível atualizar o Mastodon rapidamente para evitar problemas de segurança. Por esses motivos, o Mastodon verifica se há atualizações a cada 30 minutos e notificará você de acordo com as suas preferências de notificação por e-mail.
documentation_link: Saiba mais
release_notes: Notas de lançamento
title: Atualizações disponíveis
@@ -851,16 +888,39 @@ pt-BR:
action: Confira aqui para mais informações
message_html: "Seu armazenamento de objetos está mal configurado. A privacidade de seus usuários está em risco."
tags:
+ moderation:
+ not_trendable: Fora de moda
+ not_usable: Não utilizável
+ pending_review: Revisão pendente
+ review_requested: Revisão solicitada
+ reviewed: Revisado
+ title: Status
+ trendable: Tendências
+ unreviewed: Não revisado
+ usable: Utilizável
+ name: Nome
+ newest: Mais recente
+ oldest: Mais antigos
+ open: Visualizar Publicamente
+ reset: Reinicializar
review: Status da revisão
+ search: Buscar
+ title: Hashtags
updated_msg: Configurações de hashtag atualizadas
title: Administração
trends:
allow: Permitir
approved: Aprovado
+ confirm_allow: Você tem certeza que deseja permitir as tags selecionadas?
+ confirm_disallow: Você tem certeza de que deseja vetar as tags selecionadas?
disallow: Impedir
links:
allow: Permitir link
allow_provider: Permitir editor
+ confirm_allow: Tem certeza que deseja permitir os links selecionados?
+ confirm_allow_provider: Tem certeza que deseja permitir os provedores selecionados?
+ confirm_disallow: Tem certeza que deseja vetar os links selecionados?
+ confirm_disallow_provider: Tem certeza que deseja vetar os provedores selecionados?
description_html: Estes são links que estão sendo compartilhados por contas que seu servidor vê. Você pode ajudar seus usuários a descobrir o que está acontecendo no mundo. Nenhum link é exibido publicamente até que você aprove o editor. Você também pode permitir ou rejeitar links individuais.
disallow: Proibir link
disallow_provider: Proibir autor
@@ -884,6 +944,10 @@ pt-BR:
statuses:
allow: Permitir publicação
allow_account: Permitir autor
+ confirm_allow: Tem certeza que deseja permitir os status selecionados?
+ confirm_allow_account: Tem certeza que deseja permitir as contas selecionadas?
+ confirm_disallow: Tem certeza que deseja vetar os status selecionados?
+ confirm_disallow_account: Tem certeza que deseja vetar as contas selecionadas?
description_html: Estes são as publicações que seu servidor sabe que estão sendo muito compartilhadas e favorecidas no momento. Isso pode ajudar seus usuários, novos e atuais, a encontrar mais pessoas para seguir. Nenhuma publicação é exibida publicamente até que você aprove o autor e o autor permitir que sua conta seja sugerida a outros. Você também pode permitir ou rejeitar publicações individuais.
disallow: Proibir publicação
disallow_account: Proibir autor
@@ -916,6 +980,7 @@ pt-BR:
used_by_over_week:
one: Usado por uma pessoa na última semana
other: Usado por %{count} pessoas na última semana
+ title: Recomendações e tendências
trending: Em alta
warning_presets:
add_new: Adicionar novo
@@ -1000,7 +1065,9 @@ pt-BR:
guide_link_text: Todos podem contribuir.
sensitive_content: Conteúdo sensível
application_mailer:
+ notification_preferences: Alterar preferências de e-mail
salutation: "%{name},"
+ settings: 'Alterar preferências de e-mail: %{link}'
unsubscribe: Desinscrever
view: 'Ver:'
view_profile: Ver perfil
@@ -1020,6 +1087,7 @@ pt-BR:
hint_html: Só mais uma coisa! Precisamos confirmar que você é um humano (isso é para que possamos evitar o spam!). Resolva o CAPTCHA abaixo e clique em "Continuar".
title: Verificação de segurança
confirmations:
+ awaiting_review: Seu endereço de e-mail está confirmado! A equipe %{domain} está agora revisando a sua inscrição. Você receberá um e-mail se a sua conta for aprovada!
awaiting_review_title: Seu cadastro está sendo analisado
clicking_this_link: clicar este link
login_link: entrar
@@ -1027,6 +1095,7 @@ pt-BR:
redirect_to_app_html: Você deveria ter sido redirecionado para o aplicativo %{app_name}. Se isso não aconteceu, tente %{clicking_this_link} ou volte manualmente para o aplicativo.
registration_complete: Seu cadastro no %{domain} foi concluído!
welcome_title: Boas vindas, %{name}!
+ wrong_email_hint: Se esse endereço de e-mail não estiver correto, você pode alterá-lo nas configurações da conta.
delete_account: Excluir conta
delete_account_html: Se você deseja excluir sua conta, você pode fazer isso aqui. Uma confirmação será solicitada.
description:
@@ -1047,6 +1116,7 @@ pt-BR:
or_log_in_with: Ou entre com
privacy_policy_agreement_html: Eu li e concordo com a política de privacidade
progress:
+ confirm: Confirmar e-mail
details: Suas informações
review: Nossa avaliação
rules: Aceitar regras
@@ -1068,8 +1138,10 @@ pt-BR:
security: Segurança
set_new_password: Definir uma nova senha
setup:
+ email_below_hint_html: Verifique a sua pasta de spam, ou solicite outra. Você pode corrigir o seu endereço de e-mail se estiver errado.
email_settings_hint_html: Clique no link que te enviamos para verificar %{email}. Esperaremos aqui.
link_not_received: Não recebeu um link?
+ new_confirmation_instructions_sent: Você receberá um novo e-mail com o link de confirmação em alguns minutos!
title: Verifique sua caixa de entrada
sign_in:
preamble_html: Entre com suas credenciais de domínios ( %{domain} ) . Se sua conta estiver hospedada em um servidor diferente, você não deve conseguir acessar este conteúdo.
@@ -1080,12 +1152,20 @@ pt-BR:
title: Então vamos lá criar uma conta em %{domain}.
status:
account_status: Status da conta
+ confirming: Confirmação por e-mail pendente.
functional: Sua conta está totalmente operacional.
+ pending: Sua inscrição está aguardando revisão pela nossa equipe. Isto pode levar algum tempo. Você receberá um e-mail se sua inscrição for aprovada.
redirecting_to: Sua conta está inativa porque atualmente está redirecionando para %{acct}.
self_destruct: Como %{domain} está se encerrando, você só terá acesso limitado à sua conta.
view_strikes: Veja os avisos anteriores em relação à sua conta
too_fast: O formulário foi enviado muito rapidamente, tente novamente.
use_security_key: Usar chave de segurança
+ author_attribution:
+ example_title: Texto de amostra
+ hint_html: Controle como você é creditado quando links são compartilhados no Mastodon.
+ more_from_html: Mais de %{name}
+ s_blog: Blog do %{name}
+ title: Atribuição de autoria
challenge:
confirm: Continuar
hint_html: "Dica: Não pediremos novamente sua senha pela próxima hora."
@@ -1094,7 +1174,6 @@ pt-BR:
crypto:
errors:
invalid_key: não é uma chave Ed25519 ou Curve25519 válida
- invalid_signature: não é uma assinatura Ed25519 válida
date:
formats:
default: "%d %b, %Y"
@@ -1123,6 +1202,9 @@ pt-BR:
before: 'Antes de prosseguir, leia com cuidado:'
caches: Conteúdo que foi armazenado em cache por outros servidores pode continuar a existir
data_removal: Suas publicações e outros dados serão removidos permanentemente
+ email_change_html: Você pode alterar seu endereço de e-mail sem excluir sua conta
+ email_contact_html: Se ainda não chegar, você pode enviar um e-mail para %{email} para obter ajuda
+ email_reconfirmation_html: Se você não recebeu o e-mail de confirmação, você pode solicitá-lo novamente
irreversible: Você não conseguirá restaurar ou reativar a sua conta
more_details_html: Para mais detalhes, consulte a Política de Privacidade.
username_available: Seu nome de usuário ficará disponível novamente
@@ -1157,8 +1239,6 @@ pt-BR:
your_appeal_approved: Sua revisão foi aprovada
your_appeal_pending: Você enviou uma revisão
your_appeal_rejected: Sua revisão foi rejeitada
- domain_validator:
- invalid_domain: não é um nome de domínio válido
edit_profile:
basic_information: Informações básicas
hint_html: "Personalize o que as pessoas veem no seu perfil público e ao lado de suas publicações. É mais provável que outras pessoas o sigam de volta e interajam com você quando você tiver um perfil preenchido e uma foto de perfil."
@@ -1355,6 +1435,7 @@ pt-BR:
authentication_methods:
otp: autenticação de dois fatores
password: senha
+ sign_in_token: código de segurança do e-mail
webauthn: chaves de segurança
description_html: Se você vir atividades suspeitas ou não reconhecidas, considere alterar sua senha e ativar a autenticação de dois fatores.
empty: Sem histórico de autenticação disponível
@@ -1365,10 +1446,21 @@ pt-BR:
unsubscribe:
action: Sim, cancelar subscrição
complete: Desinscrito
+ confirmation_html: Tem certeza que deseja cancelar a assinatura de %{type} para Mastodon no %{domain} para o seu endereço de e-mail %{email}? Você sempre pode se inscrever novamente nas configurações de notificação de email.
+ emails:
+ notification_emails:
+ favourite: emails de notificação favoritos
+ follow: seguir emails de notificação
+ follow_request: emails de seguidores pendentes
+ mention: emails de notificação de menções
+ reblog: emails de notificação de boosts
+ resubscribe_html: Se você cancelou sua inscrição por engano, você pode se inscrever novamente em suas configurações de notificações por e-mail.
+ success_html: Você não mais receberá %{type} no Mastodon em %{domain} ao seu endereço de e-mail %{email}.
title: Cancelar inscrição
media_attachments:
validations:
images_and_video: Não foi possível anexar um vídeo a uma publicação que já contém imagens
+ not_found: Mídia %{ids} não encontrada ou já anexada a outra publicação
not_ready: Não é possível anexar arquivos que não terminaram de ser processados. Tente novamente daqui a pouco!
too_many: Não foi possível anexar mais de 4 imagens
migrations:
@@ -1445,6 +1537,8 @@ pt-BR:
update:
subject: "%{name} editou uma publicação"
notifications:
+ administration_emails: Notificações de e-mail do administrador
+ email_events: Eventos para notificações por e-mail
email_events_hint: 'Selecione os eventos que deseja receber notificações:'
number:
human:
@@ -1603,6 +1697,7 @@ pt-BR:
import: Importar
import_and_export: Importar e exportar
migrate: Migração de conta
+ notifications: Notificações por e-mail
preferences: Preferências
profile: Perfil
relationships: Seguindo e seguidores
@@ -1643,23 +1738,12 @@ pt-BR:
edited_at_html: Editado em %{date}
errors:
in_reply_not_found: A publicação que você quer responder parece não existir.
- open_in_web: Abrir no navegador
over_character_limit: limite de caracteres de %{max} excedido
pin_errors:
direct: Publicações visíveis apenas para usuários mencionados não podem ser fixadas
limit: Você alcançou o número limite de publicações fixadas
ownership: As publicações dos outros não podem ser fixadas
reblog: Um impulso não pode ser fixado
- poll:
- total_people:
- one: "%{count} pessoa"
- other: "%{count} pessoas"
- total_votes:
- one: "%{count} voto"
- other: "%{count} votos"
- vote: Votar
- show_more: Mostrar mais
- show_thread: Mostrar conversa
title: '%{name}: "%{quote}"'
visibilities:
direct: Direto
@@ -1849,6 +1933,7 @@ pt-BR:
invalid_otp_token: Código de dois fatores inválido
otp_lost_help_html: Se você perder o acesso à ambos, você pode entrar em contato com %{email}
rate_limited: Muitas tentativas de autenticação; tente novamente mais tarde.
+ seamless_external_login: Você está logado através de um serviço externo, portanto as configurações de senha e e-mail não estão disponíveis.
signed_in_as: 'Entrou como:'
verification:
extra_instructions_html: Dica: O link do seu site não precisa ser visível. O importante é a parte rel="me"
, que impede a personificação em sites com conteúdo gerado pelo usuário. Você pode até usar uma tag link
no cabeçalho da página ao invés de uma tag a
, mas é importante que o HTML esteja acessível sem executar JavaScript.
@@ -1857,6 +1942,7 @@ pt-BR:
instructions_html: Copie o código abaixo e cole no HTML do seu site. Em seguida, adicione o endereço do seu site em um dos campos extras em seu perfil, na aba "Editar perfil", e salve as alterações.
verification: Verificação
verified_links: Seus links verificados
+ website_verification: Verificação do site
webauthn_credentials:
add: Adicionar nova chave de segurança
create:
diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml
index 262063698b..d6c5c4a6ff 100644
--- a/config/locales/pt-PT.yml
+++ b/config/locales/pt-PT.yml
@@ -4,16 +4,15 @@ pt-PT:
about_mastodon_html: 'A rede social do futuro: sem publicidade, e sem vigilância empresarial; desenho ético, e descentralizado! Tome posse dos seus dados com o Mastodon!'
contact_missing: Por definir
contact_unavailable: n.d.
- hosted_on: Mastodon em %{domain}
- title: Acerca de
+ hosted_on: Mastodon alojado em %{domain}
+ title: Sobre
accounts:
- follow: Seguir
followers:
one: Seguidor
other: Seguidores
following: A seguir
- instance_actor_flash: Esta conta é um actor virtual usado para representar a própria instância e não um utilizador individual. É usada para motivos de federação e não deve ser suspenso.
- last_active: última vez activo
+ instance_actor_flash: Esta conta é um ator virtual utilizado para representar o servidor em si e não um utilizador individual. É utilizada para efeitos de federação e não deve ser suspensa.
+ last_active: última atividade
link_verified_on: A posse desta hiperligação foi verificada em %{date}
nothing_here: Não há nada aqui!
pin_errors:
@@ -25,19 +24,22 @@ pt-PT:
admin:
account_actions:
action: Executar acção
- title: Executar acção de moderação em %{acct}
+ already_silenced: Esta conta já foi limitada.
+ already_suspended: Esta conta já foi suspensa.
+ title: Executar ação de moderação em %{acct}
account_moderation_notes:
create: Deixar uma nota
- created_msg: Nota de moderação correctamente criada!
+ created_msg: Nota de moderação criada com sucesso!
destroyed_msg: Nota de moderação destruída!
accounts:
+ add_email_domain_block: Bloquear domínio de e-mail
approve: Aprovar
- approved_msg: Inscrição de %{username} aprovada correctamente
- are_you_sure: Tens a certeza?
+ approved_msg: Inscrição de %{username} aprovada com sucesso
+ are_you_sure: Tem a certeza?
avatar: Imagem de perfil
by_domain: Domínio
change_email:
- changed_msg: Endereço de correio electrónico alterado!
+ changed_msg: E-mail alterado com sucesso!
current_email: E-mail atual
label: Alterar e-mail
new_email: Novo e-mail
@@ -45,26 +47,29 @@ pt-PT:
title: Alterar e-mail para %{username}
change_role:
changed_msg: Função alterada com sucesso!
+ edit_roles: Gerir funções de utilizador
label: Alterar função
no_role: Nenhuma função
title: Alterar a função de %{username}
confirm: Confirmar
confirmed: Confirmado
confirming: A confirmar
- custom: Personalizar
+ custom: Personalizado
delete: Eliminar dados
deleted: Eliminada
- demote: Despromoveu
+ demote: Despromovida
destroyed_msg: Os dados de %{username} estão agora em fila de espera para serem eliminados de imediato
disable: Congelar
- disable_two_factor_authentication: Desactivar autenticação por dois factores (2FA)
+ disable_sign_in_token_auth: Desativar token de autenticação por e-mail
+ disable_two_factor_authentication: Desativar autenticação por dois fatores (2FA)
disabled: Congelada
display_name: Nome a mostrar
domain: Domínio
edit: Editar
- email: Correio electrónico
+ email: E-mail
email_status: Estado do e-mail
enable: Descongelar
+ enable_sign_in_token_auth: Ativar token de autenticação por e-mail
enabled: Ativado
enabled_msg: Descongelou a conta %{username}
followers: Seguidores
@@ -86,7 +91,7 @@ pt-PT:
memorialized: Em memória
memorialized_msg: Conta %{username} transformada com sucesso em memorial
moderation:
- active: Activo
+ active: Ativo
all: Todos
disabled: Desativado
pending: Pendente
@@ -94,14 +99,14 @@ pt-PT:
suspended: Supensos
title: Moderação
moderation_notes: Notas de moderação
- most_recent_activity: Actividade mais recente
+ most_recent_activity: Atividade mais recente
most_recent_ip: IP mais recente
no_account_selected: Nenhuma conta foi alterada porque nenhuma foi selecionada
no_limits_imposed: Sem limites impostos
no_role_assigned: Nenhuma função atribuída
not_subscribed: Não inscrito
- pending: Pendente de revisão
- perform_full_suspension: Fazer suspensão completa
+ pending: Revisão pendente
+ perform_full_suspension: Suspender
previous_strikes: Reprimendas anteriores
previous_strikes_description_html:
one: Esta conta tem 1 reprimenda.
@@ -109,11 +114,11 @@ pt-PT:
promote: Promover
protocol: Protocolo
public: Público
- push_subscription_expires: A Inscrição PuSH expira
+ push_subscription_expires: A inscrição PuSH expira
redownload: Atualizar perfil
- redownloaded_msg: Perfil de %{username} correctamente actualizado a partir da origem
+ redownloaded_msg: Perfil de %{username} atualizado a partir da origem com sucesso
reject: Rejeitar
- rejected_msg: Inscrição de %{username} correctamente rejeitada
+ rejected_msg: Inscrição de %{username} rejeitada com sucesso
remote_suspension_irreversible: Os dados desta conta foram eliminados irreversivelmente.
remote_suspension_reversible_hint_html: A conta foi suspensa no servidor de origem e os seus dados serão totalmente eliminados em %{date}. Até lá, o servidor de origem poderá recuperar esta conta sem quaisquer efeitos negativos. Se desejar eliminar todos os dados desta conta imediatamente, pode fazê-lo em baixo.
remove_avatar: Remover a imagem de perfil
@@ -122,13 +127,14 @@ pt-PT:
removed_header_msg: Imagem de cabeçalho de %{username} removida
resend_confirmation:
already_confirmed: Este utilizador já está confirmado
- send: Reenviar link de confirmação
- success: Link de confirmação enviado com sucesso!
- reset: Reiniciar
+ send: Reenviar hiperligação de confirmação
+ success: Hiperligação de confirmação enviada com sucesso!
+ reset: Repor
reset_password: Criar nova palavra-passe
resubscribe: Reinscrever
role: Função
search: Pesquisar
+ search_same_email_domain: Outros utilizadores com o mesmo domínio de e-mail
search_same_ip: Outros utilizadores com o mesmo IP
security: Segurança
security_measures:
@@ -136,7 +142,7 @@ pt-PT:
password_and_2fa: Palavra-passe e 2FA
sensitive: Marcar como problemático
sensitized: Marcada como problemática
- shared_inbox_url: URL da caixa de entrada compartilhada
+ shared_inbox_url: URL da caixa de entrada partilhada
show:
created_reports: Denúncias realizadas
targeted_reports: Denunciada por outros
@@ -151,107 +157,123 @@ pt-PT:
suspension_reversible_hint_html: A conta foi suspensa e os dados serão totalmente eliminados em %{date}. Até lá, a conta poderá ser recuperada sem quaisquer efeitos negativos. Se deseja eliminar todos os dados desta conta imediatamente, pode fazê-lo em baixo.
title: Contas
unblock_email: Desbloquear endereço de e-mail
- unblocked_email_msg: Endereço de e-mail de %{username} desbloqueado
- unconfirmed_email: Correio electrónico por confirmar
+ unblocked_email_msg: Endereço de e-mail de %{username} desbloqueado com sucesso
+ unconfirmed_email: E-mail por confirmar
undo_sensitized: Desmarcar como problemático
undo_silenced: Desfazer silenciar
undo_suspension: Desfazer supensão
- unsilenced_msg: Removeu as limitações da conta %{username}
+ unsilenced_msg: Limitações da conta %{username} removidas com sucesso
unsubscribe: Cancelar inscrição
unsuspended_msg: Removeu a suspensão da conta %{username}
username: Nome de utilizador
view_domain: Ver resumo do domínio
warn: Advertir
- web: Teia
+ web: Web
whitelisted: Permitido para a federação
action_logs:
action_types:
approve_appeal: Aprovar recurso
approve_user: Aprovar utilizador
- assigned_to_self_report: Atribuir Denúncia
- change_role_user: Alterar Função do Utilizador
- confirm_user: Confirmar Utilizador
- create_account_warning: Criar Aviso
+ assigned_to_self_report: Atribuir denúncia
+ change_email_user: Alterar e-mail do utilizador
+ change_role_user: Alterar função do utilizador
+ confirm_user: Confirmar utilizador
+ create_account_warning: Criar aviso
create_announcement: Criar comunicado
- create_custom_emoji: Criar Emoji Personalizado
- create_domain_allow: Criar Permissão de Domínio
- create_domain_block: Criar Bloqueio de Domínio
+ create_canonical_email_block: Criar bloqueio de e-mail
+ create_custom_emoji: Criar emoji personalizado
+ create_domain_allow: Criar permissão de domínio
+ create_domain_block: Criar bloqueio de domínio
+ create_email_domain_block: Criar bloqueio de domínio de e-mail
create_ip_block: Criar regra de IP
- create_unavailable_domain: Criar Domínio Indisponível
- create_user_role: Criar Função
- demote_user: Despromover Utilizador
- destroy_announcement: Apagar comunicado
- destroy_custom_emoji: Eliminar Emoji Personalizado
- destroy_domain_allow: Eliminar Permissão de Domínio
- destroy_domain_block: Eliminar Bloqueio de Domínio
- destroy_instance: Purgar Domínio
+ create_unavailable_domain: Criar domínio indisponível
+ create_user_role: Criar função
+ demote_user: Despromover utilizador
+ destroy_announcement: Eliminar comunicado
+ destroy_canonical_email_block: Eliminar bloqueio de e-mail
+ destroy_custom_emoji: Eliminar emoji personalizado
+ destroy_domain_allow: Eliminar permissão de domínio
+ destroy_domain_block: Eliminar bloqueio de domínio
+ destroy_email_domain_block: Eliminar bloqueio de domínio de e-mail
+ destroy_instance: Purgar domínio
destroy_ip_block: Eliminar regra de IP
- destroy_status: Eliminar Publicação
- destroy_unavailable_domain: Eliminar Domínio Indisponível
- destroy_user_role: Eliminar Função
+ destroy_status: Eliminar publicação
+ destroy_unavailable_domain: Eliminar domínio indisponível
+ destroy_user_role: Eliminar função
disable_2fa_user: Desativar 2FA
- disable_custom_emoji: Desativar Emoji Personalizado
- disable_user: Desativar Utilizador
- enable_custom_emoji: Ativar Emoji Personalizado
- enable_user: Ativar Utilizador
- memorialize_account: Tornar conta num memorial
- promote_user: Promover Utilizador
- reject_appeal: Rejeitar Recurso
- reject_user: Rejeitar Utilizador
- remove_avatar_user: Remover Imagem de Perfil
- reopen_report: Reabrir Denúncia
- resend_user: Reenviar E-mail de Confirmação
- reset_password_user: Repor Password
- resolve_report: Resolver Denúncia
+ disable_custom_emoji: Desativar emoji personalizado
+ disable_sign_in_token_auth_user: Desativar token de autenticação por e-mail para o utilizador
+ disable_user: Desativar utilizador
+ enable_custom_emoji: Ativar emoji personalizado
+ enable_sign_in_token_auth_user: Ativar token de autenticação por e-mail para o utilizador
+ enable_user: Ativar utilizador
+ memorialize_account: Transformar conta num memorial
+ promote_user: Promover utilizador
+ reject_appeal: Rejeitar recurso
+ reject_user: Rejeitar utilizador
+ remove_avatar_user: Remover imagem de perfil
+ reopen_report: Reabrir denúncia
+ resend_user: Reenviar e-mail de confirmação
+ reset_password_user: Repor palavra-passe
+ resolve_report: Resolver denúncia
sensitive_account: Marcar a media na sua conta como problemática
silence_account: Limitar conta
suspend_account: Suspender conta
- unassigned_report: Desatribuir Denúncia
+ unassigned_report: Anular atribuição desta denúncia
unblock_email_account: Desbloquear endereço de e-mail
unsensitive_account: Desmarcar a conta como problemática
- unsilence_account: Deixar de Silenciar Conta
- unsuspend_account: Retirar Suspensão à Conta
+ unsilence_account: Deixar de silenciar conta
+ unsuspend_account: Retirar suspensão da conta
update_announcement: Atualizar comunicado
- update_custom_emoji: Atualizar Emoji Personalizado
- update_domain_block: Atualizar Bloqueio de Domínio
+ update_custom_emoji: Atualizar emoji personalizado
+ update_domain_block: Atualizar bloqueio de domínio
update_ip_block: Atualizar regra de IP
- update_report: Atualizar Relatório
- update_status: Atualizar Estado
- update_user_role: Atualizar Função
+ update_report: Atualizar denúncia
+ update_status: Atualizar publicação
+ update_user_role: Atualizar função
actions:
approve_appeal_html: "%{name} aprovou recurso da decisão de moderação de %{target}"
approve_user_html: "%{name} aprovou a inscrição de %{target}"
assigned_to_self_report_html: "%{name} atribuiu a denúncia %{target} a si próprio"
+ change_email_user_html: "%{name} alterou o endereço de e-mail do utilizador %{target}"
change_role_user_html: "%{name} alterou a função de %{target}"
+ confirm_user_html: "%{name} confirmou o endereço de e-mail do utilizador %{target}"
create_account_warning_html: "%{name} enviou um aviso para %{target}"
create_announcement_html: "%{name} criou o novo anúncio %{target}"
- create_custom_emoji_html: "%{name} carregou o novo emoji %{target}"
- create_domain_allow_html: "%{name} habilitou a federação com o domínio %{target}"
+ create_canonical_email_block_html: "%{name} bloqueou o e-mail com a hash %{target}"
+ create_custom_emoji_html: "%{name} enviou o novo emoji %{target}"
+ create_domain_allow_html: "%{name} permitiu a federação com o domínio %{target}"
create_domain_block_html: "%{name} bloqueou o domínio %{target}"
- create_ip_block_html: "%{name} criou regra para o IP %{target}"
- create_unavailable_domain_html: "%{name} parou a entrega ao domínio %{target}"
+ create_email_domain_block_html: "%{name} bloqueou o domínio de e-mail %{target}"
+ create_ip_block_html: "%{name} criou uma regra para o IP %{target}"
+ create_unavailable_domain_html: "%{name} parou as entregas ao domínio %{target}"
create_user_role_html: "%{name} criou a função %{target}"
demote_user_html: "%{name} despromoveu o utilizador %{target}"
destroy_announcement_html: "%{name} eliminou o anúncio %{target}"
+ destroy_canonical_email_block_html: "%{name} desbloqueou o e-mail com a hash %{target}"
destroy_custom_emoji_html: "%{name} eliminou o emoji %{target}"
- destroy_domain_allow_html: "%{name} desabilitou a federação com o domínio %{target}"
+ destroy_domain_allow_html: "%{name} bloqueou a federação com o domínio %{target}"
destroy_domain_block_html: "%{name} desbloqueou o domínio %{target}"
+ destroy_email_domain_block_html: "%{name} desbloqueou o domínio de e-mail %{target}"
destroy_instance_html: "%{name} purgou o domínio %{target}"
- destroy_ip_block_html: "%{name} eliminou regra para o IP %{target}"
+ destroy_ip_block_html: "%{name} eliminou a regra para o IP %{target}"
destroy_status_html: "%{name} removeu a publicação de %{target}"
- destroy_unavailable_domain_html: "%{name} retomou a entrega ao domínio %{target}"
+ destroy_unavailable_domain_html: "%{name} retomou as entregas ao domínio %{target}"
destroy_user_role_html: "%{name} eliminou a função %{target}"
disable_2fa_user_html: "%{name} desativou o requerimento de autenticação em dois passos para o utilizador %{target}"
- disable_custom_emoji_html: "%{name} desabilitou o emoji %{target}"
- disable_user_html: "%{name} desativou o acesso para o utilizador %{target}"
- enable_custom_emoji_html: "%{name} habilitou o emoji %{target}"
- enable_user_html: "%{name} ativou o acesso para o utilizador %{target}"
+ disable_custom_emoji_html: "%{name} desativou o emoji %{target}"
+ disable_sign_in_token_auth_user_html: "%{name} desativou o token de autenticação por e-mail para %{target}"
+ disable_user_html: "%{name} desativou o início de sessão para o utilizador %{target}"
+ enable_custom_emoji_html: "%{name} ativou o emoji %{target}"
+ enable_sign_in_token_auth_user_html: "%{name} ativou o token de autenticação por e-mail para %{target}"
+ enable_user_html: "%{name} ativou o início de sessão para o utilizador %{target}"
memorialize_account_html: "%{name} transformou a conta de %{target} em um memorial"
promote_user_html: "%{name} promoveu o utilizador %{target}"
reject_appeal_html: "%{name} rejeitou recurso da decisão de moderação de %{target}"
reject_user_html: "%{name} rejeitou a inscrição de %{target}"
remove_avatar_user_html: "%{name} removeu a imagem de perfil de %{target}"
reopen_report_html: "%{name} reabriu a denúncia %{target}"
+ resend_user_html: "%{name} reenviou e-mail de confirmação para %{target}"
reset_password_user_html: "%{name} restabeleceu a palavra-passe do utilizador %{target}"
resolve_report_html: "%{name} resolveu a denúncia %{target}"
sensitive_account_html: "%{name} marcou a media de %{target} como sensível"
@@ -276,22 +298,22 @@ pt-PT:
title: Registo de auditoria
unavailable_instance: "(nome de domínio indisponível)"
announcements:
- destroyed_msg: Comunicado correctamente eliminado!
+ destroyed_msg: Comunicado eliminado com sucesso!
edit:
title: Editar comunicado
empty: Nenhum comunicado encontrado.
- live: Em directo
+ live: Em direto
new:
create: Criar comunicado
title: Novo comunicado
publish: Publicar
- published_msg: Comunicado correctamente publicado!
+ published_msg: Comunicado publicado com sucesso!
scheduled_for: Agendado para %{time}
scheduled_msg: Comunicado agendado para publicação!
title: Comunicados
unpublish: Anular publicação
- unpublished_msg: Comunicado correctamente retirado de publicação!
- updated_msg: Comunicado correctamente actualizado!
+ unpublished_msg: Comunicado corretamente retirado de publicação!
+ updated_msg: Comunicado atualizado com sucesso!
critical_update_pending: Atualização crítica pendente
custom_emojis:
assign_category: Atribuir categoria
@@ -319,16 +341,16 @@ pt-PT:
not_permitted: Não está autorizado a executar esta ação
overwrite: Escrever por cima
shortcode: Código de atalho
- shortcode_hint: Pelo menos 2 caracteres, apenas caracteres alfanuméricos e underscores
+ shortcode_hint: Pelo menos 2 caracteres, apenas caracteres alfanuméricos e traços inferiores
title: Emojis personalizados
uncategorized: Não categorizados
unlist: Não listar
unlisted: Não inventariado
update_failed_msg: Não foi possível atualizar esse emoji
- updated_msg: Emoji correctamente actualizado!
+ updated_msg: Emoji atualizado com sucesso!
upload: Enviar
dashboard:
- active_users: utilizadores activos
+ active_users: utilizadores ativos
interactions: interações
media_storage: Armazenamento de media
new_users: novos utilizadores
@@ -350,16 +372,16 @@ pt-PT:
sources: Origem de inscrições
space: Utilização do espaço
title: Painel de controlo
- top_languages: Principais idiomas activos
- top_servers: Servidores mais activos
- website: Página na teia
+ top_languages: Principais idiomas ativos
+ top_servers: Servidores mais ativos
+ website: Website
disputes:
appeals:
empty: Nenhum recurso encontrado.
title: Recursos
domain_allows:
add_new: Permitir federação com o domínio
- created_msg: Permissão correctamente atribuída para federação
+ created_msg: O domínio foi autorizado com êxito para a federação
destroyed_msg: Revogada a permissão de federação para o domínio
export: Exportar
import: Importar
@@ -385,14 +407,14 @@ pt-PT:
import: Importar
new:
create: Criar bloqueio
- hint: O bloqueio por domínio não vai prevenir a criação de contas na base de dados, mas irá retroactiva e automaticamente aplicar certos métodos de moderação nessas contas.
+ hint: O bloqueio do domínio não impedirá a criação de registos de contas na base de dados, mas aplicará retroativamente e automaticamente métodos de moderação específicos a essas contas.
severity:
desc_html: "Limitar tornará as mensagens das contas neste domínio invisíveis a qualquer pessoa que não as esteja a seguir. Suspender removerá do seu servidor todo o conteúdo, media, e dados de perfil das contas deste domínio. Utilize Nenhum se apenas quiser rejeitar ficheiros media."
noop: Nenhum
silence: Limitar
suspend: Suspender
title: Novo bloqueio de domínio
- no_domain_block_selected: Nenhum bloqueio de domínio foi alterado, pois nenhum foi seleccionado
+ no_domain_block_selected: Nenhum bloqueio de domínio foi alterado pois nenhum foi selecionado
not_permitted: Não está autorizado a executar esta ação
obfuscate: Ofuscar nome de domínio
obfuscate_hint: Ofuscar parcialmente o nome de domínio na lista, caso estejam definidas limitações na publicação da lista de domínios
@@ -412,6 +434,7 @@ pt-PT:
attempts_over_week:
one: "%{count} tentativa na última semana"
other: "%{count} tentativas de inscrição na última semana"
+ created_msg: Domínio de e-mail bloqueado com sucesso
delete: Eliminar
dns:
types:
@@ -420,8 +443,12 @@ pt-PT:
new:
create: Adicionar domínio
resolve: Domínio de resolução
+ title: Bloquear novo domínio de e-mail
+ no_email_domain_block_selected: Não foram alterados quaisquer bloqueios de domínios de e-mail, uma vez que nenhum foi selecionado
not_permitted: Não permitido
+ resolved_dns_records_hint_html: O nome de domínio resolve para os seguintes domínios MX, que são, em última análise, responsáveis por aceitar o e-mail. Bloquear um domínio MX irá bloquear as inscrições de qualquer endereço de e-mail que use o mesmo domínio MX, mesmo quando o nome de domínio visível é diferente. Cuidado para não bloquear os principais provedores de e-mail.
resolved_through_html: Resolvido através de %{domain}
+ title: Domínios de e-mail bloqueados
export_domain_allows:
new:
title: Importar permissões de domínio
@@ -527,7 +554,7 @@ pt-PT:
title: Convites
ip_blocks:
add_new: Criar regra
- created_msg: Nova regra de IP correctamente adicionada
+ created_msg: Nova regra de IP corretamente adicionada
delete: Eliminar
expires_in:
'1209600': 2 semanas
@@ -547,15 +574,15 @@ pt-PT:
delete: Eliminar
description_html: Um repetidor de federação é um servidor intermediário que troca grandes volumes de publicações públicas entre instâncias que o subscrevem e publicam. Ele pode ajudar pequenas e medias instâncias a descobrir conteúdo do fediverso que, de outro modo, exigiria que os utilizadores locais seguissem manualmente outras pessoas em instâncias remotas.
disable: Desativar
- disabled: Desactivado
- enable: Activar
+ disabled: Desativado
+ enable: Ativar
enable_hint: Uma vez ativado, a tua instância irá assinar todas as publicações deste repetidor e irá começar a enviar as suas publicações públicas para lá.
enabled: Ativado
inbox_url: URL do repetidor
pending: À espera da aprovação do repetidor
save_and_enable: Guardar e ativar
setup: Configurar uma ligação ao repetidor
- signatures_not_enabled: Os repetidores não funcionarão correctamente enquanto o modo seguro ou o modo de lista branca estiverem activados
+ signatures_not_enabled: Os repetidores não funcionarão corretamente enquanto o modo seguro ou o modo de lista branca estiverem ativados
status: Estado
title: Retransmissores
report_notes:
@@ -575,7 +602,9 @@ pt-PT:
resolve_description_html: Nenhuma ação será tomada contra a conta denunciada, não será registada nenhuma reprimenda, e a denúncia será fechada.
silence_description_html: O perfil será visível apenas para aqueles que já o seguem ou o procurem manualmente, limitando fortemente o seu alcance. Pode sempre ser revertido. Encerrar todas as denúncias contra esta conta.
suspend_description_html: A conta e todo o seu conteúdo ficará inacessível e, eventualmente apagado, pelo que interagir com ela será impossível. Reversível durante 30 dias. Encerra todas as denúncias contra esta conta.
+ actions_description_html: Decida a ação a tomar para resolver esta denúncia. Se decidir por uma ação punitiva contra a conta denunciada, um e-mail de notificação será enviado, excetuando quando selecionada a categoria Spam.
actions_description_remote_html: Decida quais as medidas a tomar para resolver esta denúncia. Isso apenas afetará como o seu servido comunica com esta conta remota e gere o seu conteúdo.
+ actions_no_posts: Este relatório não tem nenhuma publicação associada para eliminar
add_to_report: Adicionar mais à denúncia
already_suspended_badges:
local: Já suspenso neste servidor
@@ -618,27 +647,28 @@ pt-PT:
reported_by: Denunciado por
reported_with_application: Reportado com a aplicação
resolved: Resolvido
- resolved_msg: Denúncia correctamente resolvida!
+ resolved_msg: Denúncia resolvida com sucesso!
skip_to_actions: Passar para as ações
status: Estado
statuses: Conteúdo denunciado
statuses_description_html: O conteúdo ofensivo será citado na comunicação com a conta denunciada
summary:
action_preambles:
- delete_html: 'Você está prestes a remover algumas das publicações de @%{acct}. Isto irá:'
- mark_as_sensitive_html: 'Você está prestes a marcar alguns dos posts de @%{acct}como sensível. Isto irá:'
- silence_html: 'Você está prestes a limitar a conta do @%{acct}. Isto irá:'
- suspend_html: 'Você está prestes a suspender a conta de @%{acct}. Isto irá:'
+ delete_html: 'Está prestes a remover algumas das publicações de @%{acct}. Isto irá:'
+ mark_as_sensitive_html: 'Está prestes a marcar algumas das publicações de @%{acct}como sensível. Isto irá:'
+ silence_html: 'Está prestes a limitar a conta de @%{acct}. Isto irá:'
+ suspend_html: 'Está prestes a suspender a conta de @%{acct}. Isto irá:'
actions:
delete_html: Excluir as publicações ofensivas
mark_as_sensitive_html: Marcar a mídia dos posts ofensivos como sensível
silence_html: Limitar firmemente o alcance de @%{acct}, tornando seus perfis e conteúdos apenas visíveis para pessoas que já os estão seguindo ou olhando manualmente no perfil
- suspend_html: Suspender @%{acct}, tornando seu perfil e conteúdo inacessíveis e impossível de interagir com
+ suspend_html: Suspender @%{acct}, tornando seu perfil e conteúdo inacessíveis e impossível de interagir
close_report: 'Marcar relatório #%{id} como resolvido'
- close_reports_html: Marcar todos os relatórios contra @%{acct} como resolvidos
- delete_data_html: Excluir @%{acct}perfil e conteúdo 30 dias a menos que sejam dessuspensos
+ close_reports_html: Marcar todas as denúncias contra @%{acct} como resolvidas
+ delete_data_html: Eliminar o perfil de @%{acct} e conteúdos daqui a 30 dias, a menos que entretanto sejam suspensos
preview_preamble_html: "@%{acct} receberá um aviso com o seguinte conteúdo:"
- record_strike_html: Registre um ataque contra @%{acct} para ajudá-lo a escalar futuras violações desta conta
+ record_strike_html: Registar um ataque contra @%{acct} para ajudar a escalar futuras violações desta conta
+ send_email_html: Enviar um e-mail de aviso a @%{acct}
warning_placeholder: Argumentos adicionais opcionais para a acção de moderação.
target_origin: Origem da conta denunciada
title: Denúncias
@@ -669,39 +699,41 @@ pt-PT:
privileges:
administrator: Administrador
administrator_description: Utilizadores com esta permissão irão contornar todas as permissões
- delete_user_data: Eliminar Dados de Utilizador
+ delete_user_data: Eliminar dados de utilizador
delete_user_data_description: Permite que os utilizadores eliminem os dados doutros utilizadores sem tempo de espera
- invite_users: Convidar Utilizadores
+ invite_users: Convidar utilizadores
invite_users_description: Permite aos utilizadores convidar pessoas novas para o servidor
manage_announcements: Gerir comunicados
manage_announcements_description: Permite aos utilizadores gerirem os comunicados no servidor
manage_appeals: Gerir apelos
manage_appeals_description: Permite aos utilizadores rever recursos de moderação
- manage_blocks: Gerir Bloqueios
- manage_custom_emojis: Gerir Emojis Personalizados
+ manage_blocks: Gerir bloqueios
+ manage_blocks_description: Permite aos utilizadores bloquear fornecedores de e-mail e endereços IP
+ manage_custom_emojis: Gerir emojis personalizados
manage_custom_emojis_description: Permite aos utilizadores gerirem os emojis personalizados do servidor
- manage_federation: Gerir Federação
+ manage_federation: Gerir federação
manage_federation_description: Permite aos utilizadores bloquear ou permitir federação com outros domínios e controlar a entregabilidade
- manage_invites: Gerir Convites
+ manage_invites: Gerir convites
manage_invites_description: Permite aos utilizadores pesquisarem e desativarem ligações de convite
- manage_reports: Gerir Relatórios
- manage_reports_description: Permite aos utilizadores rever relatórios e executar ações de moderação contra eles
- manage_roles: Gerir Funções
+ manage_reports: Gerir denúncias
+ manage_reports_description: Permite aos utilizadores rever denúncias e executar ações de moderação contra eles
+ manage_roles: Gerir funções
manage_roles_description: Permite aos utilizadores a gestão e atribuição de funções abaixo dos seus
- manage_rules: Gerir Regras
+ manage_rules: Gerir regras
manage_rules_description: Permite aos utilizadores alterar as regras do servidor
- manage_settings: Gerir Configurações
- manage_settings_description: Permite aos utilizadores alterar as configurações do sítio na teia
- manage_taxonomies: Gerir Taxonomias
- manage_taxonomies_description: 'Permite aos utilizadores avaliar o conteúdo em alta e atualizar as configurações de #etiquetas'
- manage_user_access: Gerir Acesso de Utilizador
- manage_users: Gerir Utilizadores
+ manage_settings: Gerir configurações
+ manage_settings_description: Permite aos utilizadores alterar as configurações do site
+ manage_taxonomies: Gerir taxonomias
+ manage_taxonomies_description: Permite aos utilizadores rever o conteúdo em tendência e atualizar as configurações de hashtag
+ manage_user_access: Gerir acesso de utilizador
+ manage_user_access_description: Permite aos utilizadores desativar a autenticação de dois factores de outros utilizadores, alterar o seu e-mail e reiniciar a sua palavra-passe
+ manage_users: Gerir utilizadores
manage_users_description: Permite aos utilizadores ver os detalhes de outros utilizadores e executar ações de moderação contra eles
- manage_webhooks: Gerir Webhooks
+ manage_webhooks: Gerir webhooks
manage_webhooks_description: Permite aos utilizadores configurar webhooks para eventos administrativos
- view_audit_log: Ver Registo de Auditoria
+ view_audit_log: Ver registo de auditoria
view_audit_log_description: Permite aos utilizadores ver um histórico de ações administrativas no servidor
- view_dashboard: Ver Painel de Controlo
+ view_dashboard: Ver painel de controlo
view_dashboard_description: Permite aos utilizadores acederem ao painel de controlo e a várias estatísticas
view_devops: DevOps
view_devops_description: Permite aos utilizadores aceder aos painéis de controlo do Sidekiq e pgHero
@@ -723,14 +755,14 @@ pt-PT:
preamble: Personalize a interface web do Mastodon.
title: Aspeto
branding:
- preamble: A marca do seu servidor diferencia-a doutros servidores na rede. Essa informação pode ser exibida em vários contexos, como a interface na teia do Mastodon, aplicações nativas, visualizações de hiperligações noutros sites, em aplicações de mensagens, etc. Por esta razão, é melhor manter esta informação clara, curta e concisa.
+ preamble: A marca do seu servidor diferencia-a de outros servidores na rede. Essa informação pode ser mostrada em vários ambientes, como a interface web do Mastodon, aplicações nativas, visualizações de hiperligações em outros sites e dentro de aplicações de mensagens, etc. Por esta razão, é melhor manter esta informação clara, curta e concisa.
title: Marca
captcha_enabled:
desc_html: Isto depende de scripts externos da hCaptcha, o que pode ser uma preocupação de segurança e privacidade. Além disso, isto pode tornar o processo de registo menos acessível para algumas pessoas (especialmente as com limitações físicas). Por isso, considere medidas alternativas tais como registo mediante aprovação ou sob convite.
title: Requerer que novos utilizadores resolvam um CAPTCHA para confirmar a sua conta
content_retention:
danger_zone: Zona de perigo
- preamble: Controle como o conteúdo gerado pelos utilizadores é armazenado no Mastodon.
+ preamble: Controle a forma como o conteúdo gerado pelo utilizador é armazenado no Mastodon.
title: Retenção de conteúdo
default_noindex:
desc_html: Afeta todos os utilizadores que não alteraram esta configuração
@@ -743,13 +775,13 @@ pt-PT:
publish_discovered_servers: Publicar servidores descobertos
publish_statistics: Publicar estatísticas
title: Descobrir
- trends: Em alta
+ trends: Tendências
domain_blocks:
all: Para toda a gente
disabled: Para ninguém
users: Para utilizadores locais que se encontrem autenticados
registrations:
- moderation_recommandation: Por favor, certifique-se de que você tem uma equipe de moderação adequada e reativa antes de abrir os registros para todos!
+ moderation_recommandation: Certifique-se de que dispõe de uma equipa de moderação adequada e reativa antes de abrir as inscrições a todos!
preamble: Controle quem pode criar uma conta no seu servidor.
title: Inscrições
registrations_mode:
@@ -757,7 +789,7 @@ pt-PT:
approved: Registo sujeito a aprovação
none: Ninguém se pode registar
open: Qualquer pessoa se pode registar
- warning_hint: Recomendamos o uso de "Aprovação necessária para se cadastrar", a menos que você esteja confiante de que sua equipe de moderação pode lidar com spam e registros maliciosos em tempo hábil.
+ warning_hint: Recomendamos a utilização de “É necessária aprovação para o registo”, a menos que esteja confiante de que a sua equipa de moderação pode tratar o spam e os registos maliciosos de forma atempada.
security:
authorized_fetch: Exigir autenticação de servidores federados
authorized_fetch_hint: Exigir autenticação de servidores federados permite uma aplicação mais rigorosa de bloqueios tanto ao nível do utilizador como do servidor. No entanto, isso é feito à custa de uma diminuição de desempenho, reduz o alcance das suas respostas e pode introduzir problemas de compatibilidade com alguns serviços federados. Além disso, isso não impede os atores mais empenhados de aceder às suas publicações e contas públicas.
@@ -766,9 +798,10 @@ pt-PT:
title: Definições do servidor
site_uploads:
delete: Eliminar arquivo carregado
- destroyed_msg: Envio de sítio na teia correctamente eliminado!
+ destroyed_msg: Envio do site eliminado com sucesso!
software_updates:
critical_update: Crítico — por favor, atualize rapidamente
+ description: Recomenda-se que mantenha a sua instalação do Mastodon atualizada para beneficiar das últimas correções e funcionalidades. Além disso, é por vezes crítico atualizar o Mastodon de forma atempada para evitar problemas de segurança. Por estas razões, o Mastodon verifica se há actualizações a cada 30 minutos e notifica-o de acordo com as suas preferências de notificação por e-mail.
documentation_link: Saber mais
release_notes: Notas de lançamento
title: Atualizações disponíveis
@@ -800,7 +833,7 @@ pt-PT:
reblogs: Re-publicacões
status_changed: Publicação alterada
title: Estado das contas
- trending: Em alta
+ trending: Em tendência
visibility: Visibilidade
with_media: Com media
strikes:
@@ -823,7 +856,7 @@ pt-PT:
elasticsearch_health_yellow:
message_html: O cluster elasticsearch não está de boa saúde (estado amarelo), pode querer investigar o motivo
elasticsearch_index_mismatch:
- message_html: Os mapeamentos elasticsearch estão desatualizados. Por favor, execute tootctl search deploy --only=%{value}
+ message_html: Os mapeamentos de índice Elasticsearch estão desatualizados. Execute tootctl search deploy --only=%{value}
elasticsearch_preset:
action: Ver a documentação
message_html: O seu cluster elasticsearch tem mais de um nó, mas o Mastodon não está configurado para os usar.
@@ -831,9 +864,9 @@ pt-PT:
action: Ver documentação
message_html: O seu cluster elasticsearch tem apenas um nó, ES_PRESET
deve ser configurado para single_node_cluster
.
elasticsearch_reset_chewy:
- message_html: O seu índice de sistema elasticsearch está desatualizado devido a uma mudança de configuração. Por favor, execute tootctl search deploy --reset-chewy
para o atualizar.
+ message_html: O seu índice de sistema Elasticsearch está desatualizado devido a uma mudança de configuração. Execute tootctl search deploy --reset-chewy
para o atualizar.
elasticsearch_running_check:
- message_html: Não foi possível conectar ao Elasticsearch. Por favor, verifique se está em execução, ou desabilite a pesquisa de texto completo
+ message_html: Não foi possível conectar ao Elasticsearch. Verifique se está em execução ou desative a pesquisa de texto completo
elasticsearch_version_check:
message_html: 'Versão de Elasticsearch incompatível: %{value}'
version_comparison: A versão de Elasticsearch %{running_version} está em execução. No entanto, é obrigatória a versão %{required_version}
@@ -868,19 +901,26 @@ pt-PT:
name: Nome
newest: Mais recente
oldest: Mais antiga
+ open: Visualizar Publicamente
reset: Repor
review: Estado da revisão
search: Pesquisar
title: Hashtags
- updated_msg: 'Definições de #etiquetas correctamente actualizadas'
+ updated_msg: 'Definições de #etiquetas atualizadas com sucesso'
title: Administração
trends:
allow: Permitir
approved: Aprovado
+ confirm_allow: Tem a certeza que pretende permitir as etiquetas selecionadas?
+ confirm_disallow: Tem a certeza que pretende rejeitar as etiquetas selecionadas?
disallow: Não permitir
links:
- allow: Permitir ligação
+ allow: Permitir hiperligação
allow_provider: Permitir editor
+ confirm_allow: Tem a certeza que pretende permitir as hiperligações selecionadas?
+ confirm_allow_provider: Tem a certeza que pretende permitir os fornecedores selecionados?
+ confirm_disallow: Tem a certeza que pretende rejeitar as hiperligações selecionadas?
+ confirm_disallow_provider: Tem a certeza que pretende rejeitar os fornecedores selecionados?
description_html: Estas são as ligações que presentemente estão a ser muito partilhadas por contas visíveis pelo seu servidor. Estas podem ajudar os seus utilizador a descobrir o que está a acontecer no mundo. Nenhuma ligação é exibida publicamente até que o editor a aprove. Também pode permitir ou rejeitar ligações em avulso.
disallow: Não permitir ligação
disallow_provider: Não permitir editor
@@ -890,35 +930,39 @@ pt-PT:
shared_by_over_week:
one: Partilhado por uma pessoa na última semana
other: Partilhado por %{count} pessoas na última semana
- title: Ligações em alta
+ title: Hiperligações em tendência
usage_comparison: Partilhado %{today} vezes hoje, em comparação com %{yesterday} ontem
not_allowed_to_trend: Não permitido para tendência
only_allowed: Apenas permitidos
pending_review: Pendente de revisão
preview_card_providers:
- allowed: Ligações deste editor poderão vir a ficar em alta
+ allowed: As hiperligações deste editor podem ser tendência
description_html: Estes são os domínios a partir dos quais ligações são frequentemente partilhadas no seu servidor. As suas ligações não serão colocadas em alta a menos que o seu domínio de origem seja aprovado. A sua aprovação (ou rejeição) estende-se a subdomínios.
- rejected: Ligações deste editor não serão postas em alta
+ rejected: As hiperligações deste editor não podem ser tendência
title: Editores
rejected: Rejeitado
statuses:
allow: Permitir publicação
allow_account: Permitir autor
+ confirm_allow: Tem a certeza que pretende aceitar os estados selecionados?
+ confirm_allow_account: Tem a certeza que pretende aceitar as contas selecionadas?
+ confirm_disallow: Tem a certeza que pretende rejeitar os estados selecionados?
+ confirm_disallow_account: Tem a certeza que pretende rejeitar as contas selecionadas?
description_html: Estas são publicações que o seu servidor conhece e que atualmente estão a ser frequentemente partilhadas e adicionadas aos favoritos. Isto pode ajudar os seus utilizadores, novos e retornados, a encontrar mais pessoas para seguir. Nenhuma publicação será exibida publicamente até que aprove o autor, e o autor permita que a sua conta seja sugerida a outros. Você também pode permitir ou rejeitar publicações individualmente.
disallow: Não permitir publicação
disallow_account: Não permitir autor
- no_status_selected: Nenhuma publicação em alta foi alterada, pois nenhuma foi selecionada
+ no_status_selected: Não foram alteradas quaisquer publicações de tendências, uma vez que nenhuma foi selecionada
not_discoverable: O autor optou por não permitir que a sua conta seja sugerida a outros
shared_by:
one: Partilhado ou adicionado aos marcadores uma vez
other: Partilhado e adicionado aos marcadores %{friendly_count} vezes
- title: Publicações em alta
+ title: Publicações em tendência
tags:
current_score: Pontuação atual %{score}
dashboard:
tag_accounts_measure: utilizadores únicos
tag_languages_dimension: Idiomas mais populares
- tag_servers_dimension: Topo de servidores
+ tag_servers_dimension: Servidores mais populares
tag_servers_measure: servidores diferentes
tag_uses_measure: utilizações totais
description_html: 'Estas são as #etiquetas que aparecem atualmente com frequência em publicações visíveis pelo seu servidor. Isto pode ajudar os seus utilizadores a descobrir o que está ser mais falado no momento. Nenhuma #etiqueta será exibida publicamente até que a aprove.'
@@ -928,15 +972,16 @@ pt-PT:
not_trendable: Não aparecerá nas tendências
not_usable: Não pode ser utilizada
peaked_on_and_decaying: Máximo em %{date}, agora a decair
- title: Etiquetas em alta
- trendable: Pode aparecer em alta
- trending_rank: 'Em alta #%{rank}'
+ title: Etiquetas em tendência
+ trendable: Pode aparecer nas tendências
+ trending_rank: 'Tendência #%{rank}'
usable: Pode ser utilizada
usage_comparison: Utilizada %{today} vezes hoje, em comparação com %{yesterday} ontem
used_by_over_week:
one: Utilizada por uma pessoa na última semana
other: Utilizada por %{count} pessoas na última semana
- trending: Em alta
+ title: Recomendações e tendências
+ trending: Em tendência
warning_presets:
add_new: Adicionar novo
delete: Eliminar
@@ -946,13 +991,13 @@ pt-PT:
webhooks:
add_new: Adicionar endpoint
delete: Eliminar
- description_html: Um webhook possibilita que o Mastodon envie notificações em tempo real de eventos seleccionados, para uma aplicação sua, de modo que esta possa espoletar ações automaticamente.
+ description_html: Um webhook possibilita que o Mastodon envie notificações em tempo real de eventos selecionados, para uma aplicação sua, de modo que esta possa despoletar ações automaticamente.
disable: Desativar
disabled: Desativado
edit: Editar endpoint
empty: Não tem ainda qualquer endpoint de webhook configurado.
enable: Ativar
- enabled: Activo
+ enabled: Ativo
enabled_events:
one: 1 evento ativado
other: "%{count} eventos ativados"
@@ -993,18 +1038,18 @@ pt-PT:
body: Foram lançadas novas versões do Mastodon, talvez queira atualizar!
subject: Estão disponíveis novas versões do Mastodon para %{instance}!
new_trends:
- body: 'Os seguintes itens precisam ser revistos antes de poderem ser exibidos publicamente:'
+ body: 'Os seguintes itens necessitam de uma revisão antes de poderem ser apresentados publicamente:'
new_trending_links:
- title: Ligações em alta
+ title: Hiperligações em tendência
new_trending_statuses:
- title: Publicações em alta
+ title: Publicações em tendência
new_trending_tags:
- title: Etiquetas em alta
+ title: Etiquetas em tendência
subject: Novas tendências para revisão em %{instance}
aliases:
add_new: Criar pseudónimo
created_msg: Criou com sucesso um novo pseudónimo. Pode agora iniciar a migração da conta antiga.
- deleted_msg: O pseudónimo foi correctamente eliminado. Não será mais possível migrar a partir dessa conta.
+ deleted_msg: O pseudónimo foi removido com êxito. Deixará de ser possível passar dessa conta para esta.
empty: Não tem pseudónimos.
hint_html: Se quiser mudar de outra conta para esta, pode criar aqui um pseudónimo, que é necessário antes de poder prosseguir com a migração de seguidores da conta antiga para esta. Esta ação por si só é inofensiva e reversível. A migração da conta é iniciada a partir da conta antiga.
remove: Desvincular pseudónimo
@@ -1020,14 +1065,16 @@ pt-PT:
guide_link_text: Todos podem contribuir.
sensitive_content: Conteúdo problemático
application_mailer:
+ notification_preferences: Alterar preferências de e-mail
salutation: "%{name},"
+ settings: 'Alterar preferências de e-mail: %{link}'
unsubscribe: Cancelar subscrição
view: 'Ver:'
view_profile: Ver perfil
view_status: Ver publicação
applications:
- created: Aplicação correctamente criada
- destroyed: Aplicação correctamente eliminada
+ created: Aplicação criada com sucesso
+ destroyed: Aplicação eliminada com sucesso
logout: Sair
regenerate_token: Regenerar token de acesso
token_regenerated: Token de acesso regenerado com sucesso
@@ -1036,10 +1083,11 @@ pt-PT:
auth:
apply_for_account: Solicitar uma conta
captcha_confirmation:
- help_html: Se tiver problemas a resolver o CAPTCHA, pode entrar em contacto conosco através de %{email} e poderemos ajudá-lo.
+ help_html: Se tiver problemas a resolver o CAPTCHA, pode entrar em contacto connosco através de %{email} e poderemos ajudá-lo.
hint_html: Só mais uma coisa! Precisamos confirmar que você é um humano (isto para que possamos evitar spam!). Resolva o CAPTCHA abaixo e clique em "Continuar".
title: Verificação de segurança
confirmations:
+ awaiting_review: O seu endereço de e-mail está confirmado! A equipa de %{domain} está agora a analisar a sua inscrição. Receberá um e-mail se a sua conta for aprovada!
awaiting_review_title: A sua inscrição está a ser revista
clicking_this_link: clicar nesta hiperligação
login_link: iniciar sessão
@@ -1047,6 +1095,7 @@ pt-PT:
redirect_to_app_html: Devia ter sido reencaminhado para a aplicação %{app_name}. Se isso não aconteceu, tente %{clicking_this_link} ou volte manualmente para a aplicação.
registration_complete: O seu registo sem %{domain} está agora concluído!
welcome_title: Bem-vindo(a), %{name}!
+ wrong_email_hint: Se este endereço de correio eletrónico não estiver correto, pode alterá-lo nas definições de conta.
delete_account: Eliminar conta
delete_account_html: Se deseja eliminar a sua conta, pode continuar aqui. Uma confirmação será solicitada.
description:
@@ -1067,6 +1116,7 @@ pt-PT:
or_log_in_with: Ou iniciar sessão com
privacy_policy_agreement_html: Eu li e concordo com a política de privacidade
progress:
+ confirm: Confirmar e-mail
details: Os seus dados
review: A nossa avaliação
rules: Aceitar regras
@@ -1088,8 +1138,10 @@ pt-PT:
security: Alterar palavra-passe
set_new_password: Editar palavra-passe
setup:
+ email_below_hint_html: Verifique a sua pasta de spam ou solicite outra. Pode corrigir o seu endereço de e-mail se estiver errado.
email_settings_hint_html: Clique no link que enviamos para verificar %{email}. Esperaremos aqui.
link_not_received: Não recebeu um link?
+ new_confirmation_instructions_sent: Irá receber uma nova mensagem de e-mail com a ligação de confirmação dentro de alguns minutos!
title: Verifique a caixa de entrada do seu e-mail
sign_in:
preamble_html: Iniciar sessão com as suas credenciais de %{domain}. Se a sua conta estiver hospedada noutro servidor, não poderá iniciar sessão aqui.
@@ -1100,12 +1152,20 @@ pt-PT:
title: Vamos lá inscrevê-lo em %{domain}.
status:
account_status: Estado da conta
+ confirming: A aguardar a confirmação do e-mail para ser concluída.
functional: A sua conta está totalmente operacional.
+ pending: A sua inscrição está a ser analisada pela nossa equipa. Este processo pode demorar algum tempo. Receberá um e-mail se a sua inscrição for aprovada.
redirecting_to: A sua conta está inativa porque está atualmente a ser redirecionada para %{acct}.
self_destruct: Como %{domain} vai fechar, só terá acesso limitado à sua conta.
view_strikes: Veja as reprimendas anteriores sobre a sua conta
too_fast: Formulário enviado demasiado rapidamente, tente novamente.
use_security_key: Usar chave de segurança
+ author_attribution:
+ example_title: Texto de exemplo
+ hint_html: Controle a forma como é creditado quando as hiperligações são partilhadas no Mastodon.
+ more_from_html: Mais de %{name}
+ s_blog: Blog de %{name}
+ title: Atribuição de autor
challenge:
confirm: Continuar
hint_html: "Dica: Não vamos pedir novamente a sua palavra-passe durante a próxima hora."
@@ -1114,7 +1174,6 @@ pt-PT:
crypto:
errors:
invalid_key: não é uma chave Ed25519 ou Curve25519 válida
- invalid_signature: não é uma assinatura Ed25519 válida
date:
formats:
default: "%d %b %Y"
@@ -1138,11 +1197,14 @@ pt-PT:
confirm_password: Insira sua palavra-passe atual para verificar a sua identidade
confirm_username: Insira seu nome de utilizador para confirmar o procedimento
proceed: Eliminar conta
- success_msg: A sua conta foi correctamente eliminada
+ success_msg: A sua conta foi eliminada com sucesso
warning:
before: 'Antes de continuar, por favor leia cuidadosamente estas notas:'
caches: O conteúdo que foi armazenado em cache por outras instâncias pode perdurar
data_removal: As suas publicações e outros dados serão eliminados permanentemente
+ email_change_html: Pode alterar o seu e-mail sem eliminar a sua conta
+ email_contact_html: Se ainda assim não o recebeu, pode enviar um e-mail para %{email} para obter ajuda
+ email_reconfirmation_html: Se não recebeu a mensagem de e-mail de confirmação, pode solicitá-la novamente
irreversible: Não será possível restaurar ou reativar sua conta
more_details_html: Para mais pormenores, leia a política de privacidade.
username_available: O seu nome de utilizador ficará novamente disponível
@@ -1177,8 +1239,6 @@ pt-PT:
your_appeal_approved: O seu recurso foi deferido
your_appeal_pending: Submeteu um recurso
your_appeal_rejected: O seu recurso foi indeferido
- domain_validator:
- invalid_domain: não é um nome de domínio válido
edit_profile:
basic_information: Informação básica
hint_html: "Personalize o que as pessoas veem no seu perfil público e junto das suas publicações. É mais provável que as outras pessoas o sigam de volta ou interajam consigo se tiver um perfil preenchido e uma imagem de perfil."
@@ -1197,7 +1257,7 @@ pt-PT:
content: Desculpe, mas algo correu mal da nossa parte.
title: Esta página não está correta
'503': A página não pôde ser apresentada devido a uma falha temporária do servidor.
- noscript_html: Para usar a aplicação da teia do Mastodon, por favor active o JavaScript. Em alternativa, experimenta uma das aplicações nativas do Mastodon para a sua plataforma.
+ noscript_html: Para usar a aplicação web do Mastodon, ative o JavaScript. Alternativamente, experimente uma das aplicações nativas para o Mastodon na sua plataforma.
existing_username_validator:
not_found: não foi possível encontrar um utilizador local com esse nome
not_found_multiple: não foi possível encontrar %{usernames}
@@ -1235,7 +1295,7 @@ pt-PT:
statuses_hint_html: Este filtro aplica-se a publicações individuais selecionadas independentemente de estas corresponderem às palavras-chave abaixo. Reveja ou remova publicações do filtro.
title: Editar filtros
errors:
- deprecated_api_multiple_keywords: Estes parâmetros não podem ser alterados a partir desta aplicação porque se aplicam a mais que um filtro de palavra-chave. Use uma aplicação mais recente ou a interface na teia.
+ deprecated_api_multiple_keywords: Estes parâmetros não podem ser alterados a partir desta aplicação porque se aplicam a mais de um filtro de palavra-chave. Use uma aplicação mais recente ou a interface web.
invalid_context: Inválido ou nenhum contexto fornecido
index:
contexts: Filtros em %{contexts}
@@ -1335,11 +1395,11 @@ pt-PT:
muting: Importando contas silenciadas
type: Tipo de importação
type_groups:
- constructive: Seguidores e Marcadores
+ constructive: Seguidores e marcadores
destructive: Bloqueios e silenciamentos
types:
blocking: Lista de bloqueio
- bookmarks: Itens salvos
+ bookmarks: Marcadores
domain_blocking: Lista de domínios bloqueados
following: Lista de pessoas que estás a seguir
lists: Listas
@@ -1375,6 +1435,7 @@ pt-PT:
authentication_methods:
otp: aplicação de autenticação em duas etapas
password: palavra-passe
+ sign_in_token: código de segurança de e-mail
webauthn: chaves de segurança
description_html: Se vê atividade que não reconhece, considere alterar a sua palavra-passe e ativar a autenticação em duas etapas.
empty: Sem histórico de autenticação disponível
@@ -1395,7 +1456,7 @@ pt-PT:
acct: Mudou-se para
cancel: Cancelar redirecionamento
cancel_explanation: Cancelar o redirecionamento irá reativar a sua conta atual, mas não trará de volta os seguidores que foram migrados para essa conta.
- cancelled_msg: Cancelou correctamente o redireccionamento.
+ cancelled_msg: Cancelou corretamente o redirecionamento.
errors:
already_moved: é a mesma conta para a qual já migrou
missing_also_known_as: não é um pseudónimo dessa conta
@@ -1405,13 +1466,13 @@ pt-PT:
followers_count: Seguidores no momento da migração
incoming_migrations: A migrar de uma conta diferente
incoming_migrations_html: Para migrar de outra conta para esta, primeiro você precisa criar um pseudónimo.
- moved_msg: A sua conta está agora a ser redireccionada para %{acct} e os seus seguidores estão a ser transferidos.
+ moved_msg: A sua conta está agora a ser redirecionada para %{acct} e os seus seguidores estão a ser transferidos.
not_redirecting: A sua conta não está atualmente a ser redirecionada para nenhuma outra conta.
on_cooldown: Migrou recentemente a sua conta. Esta função ficará disponível novamente em %{count} dias.
past_migrations: Migrações anteriores
proceed_with_move: Migrar seguidores
- redirected_msg: A sua conta está agora a ser redireccionada para %{acct}.
- redirecting_to: A sua conta está a ser redireccionada para %{acct}.
+ redirected_msg: A sua conta está agora a ser redirecionada para %{acct}.
+ redirecting_to: A sua conta está a ser redirecionada para %{acct}.
set_redirect: Definir redirecionamento
warning:
backreference_required: A nova conta deve primeiro ser configurada para que esta seja referenciada
@@ -1419,7 +1480,7 @@ pt-PT:
cooldown: Após a migração, há um período de tempo de espera durante o qual não poderá voltar a migrar
disabled_account: Posteriormente, a sua conta atual não será totalmente utilizável. No entanto, continuará a ter acesso à exportação de dados, bem como à reativação.
followers: Esta ação irá migrar todos os seguidores da conta atual para a nova conta
- only_redirect_html: Em alternativa, pode apenas colocar um redireccionamento no seu perfil.
+ only_redirect_html: Em alternativa, pode apenas colocar um redirecionamento no seu perfil.
other_data: Nenhum outro dado será migrado automaticamente
redirect: O perfil da sua conta atual será atualizado com um aviso de redirecionamento e será excluído das pesquisas
moderation:
@@ -1546,7 +1607,7 @@ pt-PT:
remove_selected_follows: Deixar de seguir os utilizadores selecionados
status: Estado da conta
remote_follow:
- missing_resource: Não foi possível encontrar o URL de redireccionamento para a sua conta
+ missing_resource: Não foi possível encontrar o URL de redirecionamento para a sua conta
reports:
errors:
invalid_rules: não faz referência a regras válidas
@@ -1639,7 +1700,7 @@ pt-PT:
user_domain_block: Bloqueou %{target_name}
lost_followers: Seguidores perdidos
lost_follows: Pessoas que segue perdidas
- preamble: Pode perder seguidores e pessoas que segue quando bloqueia um domínio ou quando os seus moderadores decidem suspender um servidor remoto. Quando isso acontecer, poderá descarregar listas de relações cessadas, para serem inspeccionadas e possivelmente importadas para outro servidor.
+ preamble: Pode perder seguidores e pessoas que segue quando bloqueia um domínio ou quando os seus moderadores decidem suspender um servidor remoto. Quando isso acontecer, poderá descarregar listas de relações cortadas, para serem inspecionadas e possivelmente importadas para outro servidor.
purged: Informações sobre este servidor foram purgadas pelos administradores do seu servidor.
type: Evento
statuses:
@@ -1663,23 +1724,12 @@ pt-PT:
edited_at_html: Editado em %{date}
errors:
in_reply_not_found: A publicação a que está a tentar responder parece não existir.
- open_in_web: Abrir na Teia
over_character_limit: limite de caracter excedeu %{max}
pin_errors:
direct: Publicações visíveis apenas para utilizadores mencionados não podem ser afixadas
limit: Já afixaste a quantidade máxima de publicações
ownership: Não podem ser afixadas publicações doutras pessoas
reblog: Não pode afixar um reforço
- poll:
- total_people:
- one: "%{count} pessoa"
- other: "%{count} pessoas"
- total_votes:
- one: "%{count} voto"
- other: "%{count} votos"
- vote: Votar
- show_more: Mostrar mais
- show_thread: Mostrar conversa
title: '%{name}: "%{quote}"'
visibilities:
direct: Direto
@@ -1706,8 +1756,8 @@ pt-PT:
keep_pinned_hint: Não apagar nenhuma das suas publicações afixadas
keep_polls: Manter sondagens
keep_polls_hint: Não apaga nenhuma das suas sondagens
- keep_self_bookmark: Manter as publicações que guardou
- keep_self_bookmark_hint: Não apaga as suas próprias publicações se as tiver guardado
+ keep_self_bookmark: Manter as publicações que marcou
+ keep_self_bookmark_hint: Não elimina as suas próprias publicações se as tiver nos marcadores
keep_self_fav: Manter as publicações que marcou
keep_self_fav_hint: Não apaga as suas próprias publicações se as tiver marcado
min_age:
@@ -1825,7 +1875,7 @@ pt-PT:
welcome:
apps_android_action: Baixe no Google Play
apps_ios_action: Baixar na App Store
- apps_step: Baixe nossos aplicativos oficiais.
+ apps_step: Descarregue as nossas aplicações oficiais.
apps_title: Apps Mastodon
checklist_subtitle: 'Vamos começar nesta nova fronteira social:'
checklist_title: Checklist de Boas-vindas
@@ -1834,11 +1884,11 @@ pt-PT:
edit_profile_title: Personalize seu perfil
explanation: Aqui estão algumas dicas para começar
feature_action: Mais informações
- feature_audience: Mastodon oferece uma possibilidade única de gerenciar seu público sem intermediários. O Mastodon implantado em sua própria infraestrutura permite que você siga e seja seguido de qualquer outro servidor Mastodon online e não esteja sob o controle de ninguém além do seu.
+ feature_audience: O Mastodon oferece-lhe uma possibilidade única de gerir a sua audiência sem intermediários. O Mastodon implantado na sua própria infraestrutura permite-lhe seguir e ser seguido a partir de qualquer outro servidor Mastodon online e não está sob o controlo de ninguém a não ser o seu.
feature_audience_title: Construa seu público em confiança
- feature_control: Você sabe melhor o que deseja ver no feed da sua casa. Sem algoritmos ou anúncios para desperdiçar seu tempo. Siga qualquer pessoa em qualquer servidor Mastodon a partir de uma única conta e receba suas postagens em ordem cronológica, deixando seu canto da internet um pouco mais parecido com você.
- feature_control_title: Fique no controle da sua própria linha do tempo
- feature_creativity: Mastodon suporta postagens de áudio, vídeo e imagens, descrições de acessibilidade, enquetes, avisos de conteúdo, avatares animados, emojis personalizados, controle de corte de miniaturas e muito mais, para ajudá-lo a se expressar online. Esteja você publicando sua arte, sua música ou seu podcast, o Mastodon está lá para você.
+ feature_control: Você sabe melhor o que quer ver no seu feed. Não há algoritmos ou anúncios que o façam perder tempo. Siga qualquer pessoa em qualquer servidor Mastodon a partir de uma única conta e receba as suas mensagens por ordem cronológica e torne o seu canto da Internet um pouco mais parecido consigo.
+ feature_control_title: Mantenha o controlo da sua própria cronologia
+ feature_creativity: O Mastodon suporta publicações de áudio, vídeo e imagens, descrições de acessibilidade, sondagens, avisos de conteúdo, avatares animados, emojis personalizados, controlo de corte de miniaturas e muito mais, para o ajudar a expressar-se online. Quer esteja a publicar a sua arte, a sua música ou o seu podcast, o Mastodon está lá para si.
feature_creativity_title: Criatividade inigualável
feature_moderation: Mastodon coloca a tomada de decisões de volta em suas mãos. Cada servidor cria as suas próprias regras e regulamentos, que são aplicados localmente e não de cima para baixo como as redes sociais corporativas, tornando-o mais flexível na resposta às necessidades de diferentes grupos de pessoas. Junte-se a um servidor com as regras com as quais você concorda ou hospede as suas próprias.
feature_moderation_title: Moderando como deve ser
@@ -1852,10 +1902,10 @@ pt-PT:
one: "%{people} pessoa nos últimos 2 dias"
other: "%{people} pessoas nos últimos 2 dias"
hashtags_subtitle: Explore o que está em tendência desde os últimos 2 dias
- hashtags_title: Trending hashtags
- hashtags_view_more: Ver mais hashtags em alta
+ hashtags_title: Etiquetas em tendência
+ hashtags_view_more: Ver mais etiquetas em tendência
post_action: Compor
- post_step: Diga olá para o mundo com texto, fotos, vídeos ou enquetes.
+ post_step: Diga olá para o mundo com texto, fotos, vídeos ou sondagens.
post_title: Faça a sua primeira publicação
share_action: Compartilhar
share_step: Diga aos seus amigos como te encontrar no Mastodon.
@@ -1874,7 +1924,7 @@ pt-PT:
extra_instructions_html: Dica: A ligação no seu site pode ser invisível. A parte importante é rel="me"
que impede a personificação em sites com conteúdo gerado pelo utilizador. Pode até utilizar uma etiqueta link
no cabeçalho da página ao invés de a
, mas o HTML deve ser acessível sem executar JavaScript.
here_is_how: Veja como
hint_html: "Verificar a sua identidade no Mastodon é para todos. Baseado em normas públicas da web, agora e para sempre gratuitas. Tudo o que precisa é de um site pessoal pelo qual as pessoas o reconheçam. Quando coloca no seu perfil uma ligação para esse site, vamos verificar que o site tem uma ligação de volta para o seu perfil e mostrar um indicador visual."
- instructions_html: Copie e cole o código abaixo no HTML do seu site. Em seguida, adicione o endereço do seu site em um dos campos extras no seu perfil, na aba "Editar perfil" e salve as alterações.
+ instructions_html: Copie e cole o código abaixo no HTML do seu site. Em seguida, adicione o endereço do seu site num dos campos extras no seu perfil, na aba "Editar perfil" e guarde as alterações.
verification: Verificação
verified_links: As suas ligações verificadas
webauthn_credentials:
diff --git a/config/locales/ro.yml b/config/locales/ro.yml
index 52982ead2d..d4f202637b 100644
--- a/config/locales/ro.yml
+++ b/config/locales/ro.yml
@@ -7,7 +7,6 @@ ro:
hosted_on: Mastodon găzduit de %{domain}
title: Despre
accounts:
- follow: Urmărește
followers:
few: Urmăritori
one: Urmăritor
@@ -681,24 +680,11 @@ ro:
other: 'conținea aceste hashtag-uri nepermise: %{tags}'
errors:
in_reply_not_found: Postarea la care încercați să răspundeți nu pare să existe.
- open_in_web: Deschide pe web
over_character_limit: s-a depășit limita de caracter %{max}
pin_errors:
limit: Deja ai fixat numărul maxim de postări
ownership: Postarea altcuiva nu poate fi fixată
reblog: Un impuls nu poate fi fixat
- poll:
- total_people:
- few: "%{count} persoane"
- one: "%{count} persoană"
- other: "%{count} de persoane"
- total_votes:
- few: "%{count} voturi"
- one: "%{count} vot"
- other: "%{count} de voturi"
- vote: Votează
- show_more: Arată mai mult
- show_thread: Arată discuția
visibilities:
private: Doar urmăritorii
private_long: Arată doar urmăritorilor
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index b9c582843d..3877727490 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -7,7 +7,6 @@ ru:
hosted_on: Вы получили это сообщение, так как зарегистрированы на %{domain}
title: О проекте
accounts:
- follow: Подписаться
followers:
few: подписчика
many: подписчиков
@@ -29,6 +28,8 @@ ru:
admin:
account_actions:
action: Выполнить действие
+ already_silenced: Эта учетная запись уже ограничена.
+ already_suspended: Действие этой учетной записи уже приостановлено.
title: Произвести модерацию учётной записи %{acct}
account_moderation_notes:
create: Создать
@@ -50,6 +51,7 @@ ru:
title: Сменить e-mail для %{username}
change_role:
changed_msg: Роль успешно изменена!
+ edit_roles: Управление ролями пользователей
label: Изменить роль
no_role: Нет роли
title: Изменить роль %{username}
@@ -62,6 +64,7 @@ ru:
demote: Разжаловать
destroyed_msg: Данные %{username} поставлены в очередь на удаление
disable: Заморозка
+ disable_sign_in_token_auth: Отключите аутентификацию с помощью маркера электронной почты
disable_two_factor_authentication: Отключить 2FA
disabled: Отключено
display_name: Отображаемое имя
@@ -70,6 +73,7 @@ ru:
email: E-mail
email_status: Статус e-mail
enable: Включить
+ enable_sign_in_token_auth: Включите аутентификацию с помощью маркера электронной почты
enabled: Включен
enabled_msg: Учётная запись %{username} успешно разморожена
followers: Подписчики
@@ -136,6 +140,7 @@ ru:
resubscribe: Переподписаться
role: Роль
search: Поиск
+ search_same_email_domain: Другие пользователи с тем же почтовым доменом
search_same_ip: Другие пользователи с таким же IP
security: Безопасность
security_measures:
@@ -181,17 +186,21 @@ ru:
confirm_user: Подтверждение пользователей
create_account_warning: Выдача предупреждения
create_announcement: Создание объявлений
+ create_canonical_email_block: Создать блок электронной почты
create_custom_emoji: Добавление эмодзи
create_domain_allow: Разрешение доменов
create_domain_block: Блокировка доменов
+ create_email_domain_block: Создать блок домена электронной почты
create_ip_block: Создание правил для IP-адресов
create_unavailable_domain: Добавление домена в список недоступных
create_user_role: Создать роль
demote_user: Разжалование пользователей
destroy_announcement: Удаление объявлений
+ destroy_canonical_email_block: Удалить блок электронной почты
destroy_custom_emoji: Удаление эмодзи
destroy_domain_allow: Отзыв разрешений для доменов
destroy_domain_block: Разблокировка доменов
+ destroy_email_domain_block: Удалить блок домена электронной почты
destroy_instance: Очистить домен
destroy_ip_block: Удаление правил для IP-адресов
destroy_status: Удаление постов
@@ -199,8 +208,10 @@ ru:
destroy_user_role: Удалить роль
disable_2fa_user: Отключение 2FA
disable_custom_emoji: Отключение эмодзи
+ disable_sign_in_token_auth_user: Отключить аутентификацию пользователя с помощью токена электронной почты
disable_user: Заморозка пользователей
enable_custom_emoji: Включение эмодзи
+ enable_sign_in_token_auth_user: Включить аутентификацию пользователя с помощью токена электронной почты
enable_user: Разморозка пользователей
memorialize_account: Присвоение пользователям статуса «мемориала»
promote_user: Повышение пользователей
@@ -230,20 +241,26 @@ ru:
approve_appeal_html: "%{name} одобрил апелляцию на умеренное решение от %{target}"
approve_user_html: "%{name} утвердил(а) регистрацию %{target}"
assigned_to_self_report_html: "%{name} назначил(а) себя для решения жалобы %{target}"
+ change_email_user_html: "%{name} изменил адрес электронной почты пользователя %{target}"
change_role_user_html: "%{name} изменил(а) роль %{target}"
+ confirm_user_html: "%{name} подтвержденный адрес электронной почты пользователя %{target}"
create_account_warning_html: "%{name} выдал(а) предупреждение %{target}"
create_announcement_html: "%{name} создал(а) новое объявление %{target}"
+ create_canonical_email_block_html: "%{name} заблокировал письмо с хэшем %{target}"
create_custom_emoji_html: "%{name} загрузил(а) новый эмодзи %{target}"
create_domain_allow_html: "%{name} разрешил(а) федерацию с доменом %{target}"
create_domain_block_html: "%{name} заблокировал(а) домен %{target}"
+ create_email_domain_block_html: "%{name} заблокированный почтовый домен %{target}"
create_ip_block_html: "%{name} создал(а) правило для IP %{target}"
create_unavailable_domain_html: "%{name} приостановил доставку на узел %{target}"
create_user_role_html: "%{name} создал(а) роль %{target}"
demote_user_html: "%{name} разжаловал(а) пользователя %{target}"
destroy_announcement_html: "%{name} удалил(а) объявление %{target}"
+ destroy_canonical_email_block_html: "%{name} разблокированное письмо с хэшем %{target}"
destroy_custom_emoji_html: "%{name} удалил(а) эмодзи %{target}"
destroy_domain_allow_html: "%{name} запретил(а) федерацию с доменом %{target}"
destroy_domain_block_html: "%{name} снял(а) блокировку с домена %{target}"
+ destroy_email_domain_block_html: "%{name} разблокированный почтовый домен %{target}"
destroy_instance_html: "%{name} очистил(а) данные для домена %{target}"
destroy_ip_block_html: "%{name} удалил(а) правило для IP %{target}"
destroy_status_html: "%{name} удалил(а) пост пользователя %{target}"
@@ -251,8 +268,10 @@ ru:
destroy_user_role_html: "%{name} удалил(а) роль %{target}"
disable_2fa_user_html: "%{name} отключил(а) требование двухэтапной авторизации для пользователя %{target}"
disable_custom_emoji_html: "%{name} отключил(а) эмодзи %{target}"
+ disable_sign_in_token_auth_user_html: "%{name} отключил аутентификацию по маркеру электронной почты для %{target}"
disable_user_html: "%{name} заморозил(а) пользователя %{target}"
enable_custom_emoji_html: "%{name} включил(а) эмодзи %{target}"
+ enable_sign_in_token_auth_user_html: "%{name} включил аутентификацию с помощью маркера электронной почты для %{target}"
enable_user_html: "%{name} разморозил(а) пользователя %{target}"
memorialize_account_html: "%{name} перевел(а) учётную запись пользователя %{target} в статус памятника"
promote_user_html: "%{name} повысил(а) пользователя %{target}"
@@ -260,6 +279,7 @@ ru:
reject_user_html: "%{name} отклонил(а) регистрацию %{target}"
remove_avatar_user_html: "%{name} убрал(а) аватарку пользователя %{target}"
reopen_report_html: "%{name} повторно открыл(а) жалобу %{target}"
+ resend_user_html: "%{name} повторно отправил письмо с подтверждением для %{target}"
reset_password_user_html: "%{name} сбросил(а) пароль пользователя %{target}"
resolve_report_html: "%{name} решил(а) жалобу %{target}"
sensitive_account_html: "%{name} установил(а) отметку файлов %{target} как «деликатного характера»"
@@ -274,6 +294,7 @@ ru:
update_custom_emoji_html: "%{name} обновил(а) эмодзи %{target}"
update_domain_block_html: "%{name} обновил(а) блокировку домена для %{target}"
update_ip_block_html: "%{name} изменил(а) правило для IP %{target}"
+ update_report_html: "%{name} обновленный отчет %{target}"
update_status_html: "%{name} изменил(а) пост пользователя %{target}"
update_user_role_html: "%{name} изменил(а) роль %{target}"
deleted_account: удалённая учётная запись
@@ -438,6 +459,8 @@ ru:
new:
create: Создать блокировку
resolve: Проверить домен
+ title: Блокировка нового почтового домена
+ no_email_domain_block_selected: Блоки почтовых доменов не были изменены, так как ни один из них не был выбран
not_permitted: Не разрешено
resolved_through_html: Разрешено через %{domain}
title: Заблокированные e-mail домены
@@ -465,6 +488,9 @@ ru:
title: Рекомендации подписок
unsuppress: Восстановить рекомендацию
instances:
+ audit_log:
+ title: Последние журналы аудита
+ view_all: Просмотр полных журналов аудита
availability:
description_html:
few: Если доставка в домен завершается сбоем %{count} дня, дальнейшие попытки доставки предприниматься не будут, пока не будет получена доставка из домена.
@@ -600,6 +626,7 @@ ru:
silence_description_html: Учетная запись будет видна только тем пользователям, которые уже подписаны на неё, либо открыли его вручную. Это действие можно отменить в любой момент, и отменяет все жалобы против аккаунта.
suspend_description_html: Аккаунт и все его содержимое будут недоступны и в конечном итоге удалены, и взаимодействие с ним будет невозможно. Это действие можно отменить в течение 30 дней. Отменяет все жалобы против этого аккаунта.
actions_description_remote_html: Решите вопрос о том, какие меры необходимо принять для урегулирования этой жалобы. Это повлияет только на то, как ваш сервер взаимодействует с этим удаленным аккаунтом и обрабатывает его содержимое.
+ actions_no_posts: У этого отчета нет связанных с ним сообщений для удаления
add_to_report: Прикрепить ещё
already_suspended_badges:
local: На этом сервере уже забанен
@@ -640,6 +667,7 @@ ru:
report: Жалоба №%{id}
reported_account: Учётная запись нарушителя
reported_by: Отправитель жалобы
+ reported_with_application: Сообщается с приложением
resolved: Решённые
resolved_msg: Жалоба обработана, спасибо!
skip_to_actions: Перейти к действиям
@@ -662,6 +690,7 @@ ru:
delete_data_html: Удалить профиль и контент @%{acct} через 30 дней, если за это время они не будут разблокированы
preview_preamble_html: "@%{acct} получит предупреждение со следующим содержанием:"
record_strike_html: Запишите замечание против @%{acct}, чтобы помочь вам в решении будущих нарушений с этого аккаунта
+ send_email_html: Отправить @%{acct} предупреждающее письмо
warning_placeholder: Необязательное дополнительное обоснование действия модерации.
target_origin: Происхождение объекта жалобы
title: Жалобы
@@ -705,6 +734,7 @@ ru:
manage_appeals: Управление апелляциями
manage_appeals_description: Позволяет пользователям просматривать апелляции на действия модерации
manage_blocks: Управление блоками
+ manage_blocks_description: Позволить пользователям блокировать провайдеров электронной почты и IP-адреса
manage_custom_emojis: Управление смайлами
manage_custom_emojis_description: Позволяет пользователям управлять пользовательскими эмодзи на сервере
manage_federation: Управление Федерацией
@@ -777,6 +807,7 @@ ru:
disabled: Никому
users: Залогиненным локальным пользователям
registrations:
+ moderation_recommandation: Убедитесь, что у вас есть адекватная и оперативная команда модераторов, прежде чем открывать регистрацию для всех желающих!
preamble: Контролируйте, кто может создать учетную запись на вашем сервере.
title: Регистрации
registrations_mode:
@@ -784,6 +815,7 @@ ru:
approved: Для регистрации требуется подтверждение
none: Никто не может регистрироваться
open: Все могут регистрироваться
+ warning_hint: Мы рекомендуем использовать "Требуется одобрение для регистрации", если вы не уверены, что ваша команда модераторов сможет своевременно справиться со спамом и вредоносными регистрациями.
security:
authorized_fetch: Требовать аутентификацию от федеративных серверов
authorized_fetch_hint: Требование аутентификации от федеративных серверов позволяет более строго соблюдать блокировки как на уровне пользователя, так и на уровне сервера. Однако при этом снижается производительность, уменьшается охват ваших ответов и могут возникнуть проблемы совместимости с некоторыми федеративными сервисами. Кроме того, это не помешает специальным исполнителям получать ваши публичные сообщения и учётные записи.
@@ -795,6 +827,7 @@ ru:
destroyed_msg: Файл успешно удалён.
software_updates:
critical_update: Критично — пожалуйста, обновите как можно скорее
+ description: Рекомендуется поддерживать установку Mastodon в актуальном состоянии, чтобы воспользоваться последними исправлениями и функциями. Кроме того, иногда очень важно своевременно обновлять Mastodon, чтобы избежать проблем с безопасностью. По этим причинам Mastodon проверяет наличие обновлений каждые 30 минут и уведомляет вас об этом в соответствии с вашими предпочтениями в отношении уведомлений по электронной почте.
documentation_link: Узнать больше
release_notes: Примечания к выпуску
title: Доступные обновления
@@ -882,17 +915,38 @@ ru:
message_html: "Ваше хранилище объектов неправильно настроено. Безопасность ваших пользователей находится под угрозой"
tags:
moderation:
+ not_trendable: Не в тренде
+ not_usable: Невозможно использовать
+ pending_review: В ожидании обзора
+ review_requested: Обзор запрошен
+ reviewed: Рассмотрено
title: Статус
+ trendable: Трендовый
+ unreviewed: Без рецензии
+ usable: Полезное
+ name: Название
+ newest: Новейший
+ oldest: Старейший
+ open: Посмотреть публично
+ reset: Сброс
review: Состояние проверки
+ search: Поиск
+ title: Хэштеги
updated_msg: Настройки хэштега обновлены
title: Администрирование
trends:
allow: Разрешить
approved: Принятые
+ confirm_allow: Вы уверены, что хотите разрешить выбранные теги?
+ confirm_disallow: Вы уверены, что хотите запретить выбранные теги?
disallow: Отклонить
links:
allow: Разрешить ссылку
allow_provider: Разрешить издание
+ confirm_allow: Вы уверены, что хотите разрешить выбранные ссылки?
+ confirm_allow_provider: Вы уверены, что хотите разрешить выбранных провайдеров?
+ confirm_disallow: Вы уверены, что хотите запретить выбранные ссылки?
+ confirm_disallow_provider: Вы уверены, что хотите запретить выбранных поставщиков?
description_html: Это ссылки, которыми в настоящее время много пользуются аккаунты, с которых ваш сервер видит сообщения. Это может помочь вашим пользователям узнать, что происходит в мире. Никакие ссылки не отображаются публично, пока вы не одобрите издателя. Вы также можете разрешить или отклонить индивидуальные ссылки.
disallow: Запретить ссылку
disallow_provider: Отклонить издание
@@ -918,6 +972,10 @@ ru:
statuses:
allow: Разрешить пост
allow_account: Разрешить автора
+ confirm_allow: Вы уверены, что хотите разрешить выбранные статусы?
+ confirm_allow_account: Вы уверены, что хотите разрешить выбранные учетные записи?
+ confirm_disallow: Вы уверены, что хотите запретить выбранные статусы?
+ confirm_disallow_account: Вы уверены, что хотите запретить выбранные учетные записи?
description_html: Это посты, которыми на вашем сервере в данный момент часто делятся и предпочитают, что может помочь вашим новым и постоянным пользователям найти больше людей, чтобы на них подписаться. Посты не будут отображаться публично, пока вы не одобрите автора, а автор не разрешит предлагать его аккаунт другим. Вы также можете разрешить или отклонить отдельные сообщения.
disallow: Запретить пост
disallow_account: Запретить автора
@@ -954,12 +1012,14 @@ ru:
many: За последнюю неделю использовало %{count} человек
one: За последнюю неделю использовал один человек
other: За последнюю неделю использовал %{count} человек
+ title: Рекомендации и тенденции
trending: Популярное
warning_presets:
add_new: Добавить
delete: Удалить
edit_preset: Удалить шаблон предупреждения
empty: Вы еще не определили пресеты предупреждений.
+ title: Предупреждающие пред установки
webhooks:
add_new: Добавить конечную точку
delete: Удалить
@@ -983,6 +1043,9 @@ ru:
title: Вебхуки
webhook: Вебхук
admin_mailer:
+ auto_close_registrations:
+ body: В связи с отсутствием активности модераторов в последнее время, регистрация на %{instance} была автоматически переведена в режим, требующий ручной проверки, чтобы предотвратить использование %{instance} в качестве платформы для потенциальных плохих игроков. Вы можете в любой момент переключить его обратно на открытые регистрации.
+ subject: Регистрации для %{instance} были автоматически переведены в разряд требующих одобрения
new_appeal:
actions:
delete_statuses: удалить их посты
@@ -1036,7 +1099,9 @@ ru:
guide_link_text: Каждый может внести свой вклад.
sensitive_content: Содержимое деликатного характера
application_mailer:
+ notification_preferences: Изменение предпочтений электронной почты
salutation: "%{name},"
+ settings: 'Измените настройки электронной почты: %{link}'
unsubscribe: Отписаться
view: 'Просмотр:'
view_profile: Просмотреть профиль
@@ -1056,6 +1121,7 @@ ru:
hint_html: Еще одна вещь! Нам нужно подтвердить, что вы человек (так что мы можем держать спам!). Решите капчу ниже и нажмите кнопку «Продолжить».
title: Проверка безопасности
confirmations:
+ awaiting_review: Ваш адрес электронной почты подтвержден! Сотрудники %{domain} сейчас рассматривают вашу регистрацию. Вы получите письмо, если они одобрят вашу учетную запись!
awaiting_review_title: Ваша регистрация проверяется
clicking_this_link: нажатие на эту ссылку
login_link: войти
@@ -1063,6 +1129,7 @@ ru:
redirect_to_app_html: Вы должны были перенаправлены на приложение %{app_name}. Если этого не произошло, попробуйте %{clicking_this_link} или вернитесь к приложению вручную.
registration_complete: Ваша регистрация на %{domain} завершена!
welcome_title: Добро пожаловать, %{name}!
+ wrong_email_hint: Если этот адрес электронной почты неверен, вы можете изменить его в настройках аккаунта.
delete_account: Удалить учётную запись
delete_account_html: Удалить свою учётную запись можно в два счёта здесь, но прежде у вас будет спрошено подтверждение.
description:
@@ -1083,6 +1150,7 @@ ru:
or_log_in_with: Или войти с помощью
privacy_policy_agreement_html: Мной прочитана и принята политика конфиденциальности
progress:
+ confirm: Подтвердите электронную почту
details: Ваши данные
review: Наш обзор
rules: Принять правила
@@ -1104,8 +1172,10 @@ ru:
security: Безопасность
set_new_password: Задать новый пароль
setup:
+ email_below_hint_html: Проверьте папку "Спам" или запросите другую. Вы можете исправить свой адрес электронной почты, если он неправильный.
email_settings_hint_html: Нажмите на ссылку, которую мы отправили вам для проверки %{email}. Мы будем ждать прямо здесь.
link_not_received: Не получили ссылку?
+ new_confirmation_instructions_sent: Через несколько минут вы получите новое письмо со ссылкой для подтверждения!
title: Проверьте свой почтовый ящик
sign_in:
preamble_html: Войдите, используя ваши учётные данные %{domain}. Если ваша учётная запись размещена на другом сервере, вы не сможете здесь войти.
@@ -1116,12 +1186,20 @@ ru:
title: Зарегистрируйтесь в %{domain}.
status:
account_status: Статус учётной записи
+ confirming: Жду подтверждения по электронной почте.
functional: Ваша учётная запись в полном порядке.
+ pending: Ваша заявка находится на рассмотрении у наших сотрудников. Это может занять некоторое время. Вы получите электронное письмо, если ваша заявка будет одобрена.
redirecting_to: Ваша учётная запись деактивированна, потому что вы настроили перенаправление на %{acct}.
self_destruct: Поскольку %{domain} закрывается, вы получите ограниченный доступ к вашей учетной записи.
view_strikes: Просмотр предыдущих замечаний в адрес вашей учетной записи
too_fast: Форма отправлена слишком быстро, попробуйте еще раз.
use_security_key: Использовать ключ безопасности
+ author_attribution:
+ example_title: Образец текста
+ hint_html: Контролируйте, как вы будете отмечены при обмене ссылками на Mastodon.
+ more_from_html: Больше от %{name}
+ s_blog: "%{name}'S Блог"
+ title: Авторская атрибуция
challenge:
confirm: Продолжить
hint_html: "Подсказка: мы не будем спрашивать пароль повторно в течение часа."
@@ -1130,7 +1208,6 @@ ru:
crypto:
errors:
invalid_key: не является допустимым Ed25519 или Curve25519 ключом
- invalid_signature: не является допустимой Ed25519 подписью
date:
formats:
default: "%d %b %Y"
@@ -1159,6 +1236,9 @@ ru:
before: 'Внимательно прочитайте следующую информацию перед началом:'
caches: Некоторые данные, обработанные другими узлами, однако, могут храниться ещё какое-то время
data_removal: Все ваши золотые посты, шикарный профиль и прочие данные будут безвозвратно уничтожены
+ email_change_html: Вы можете изменить свой адрес электронной почты, не удаляя свою учетную запись
+ email_contact_html: Если оно все еще не пришло, вы можете обратиться за помощью по электронной почте %{email}
+ email_reconfirmation_html: Если вы не получили подтверждение по электронной почте, вы можете запросить его снова
irreversible: После удаления восстановить или повторно активировать учётную запись не получится
more_details_html: За всеми подробностями, изучите политику конфиденциальности.
username_available: Ваше имя пользователя снова станет доступным
@@ -1193,8 +1273,6 @@ ru:
your_appeal_approved: Ваша апелляция одобрена
your_appeal_pending: Вы подали апелляцию
your_appeal_rejected: Ваша апелляция отклонена
- domain_validator:
- invalid_domain: не является корректным доменным именем
edit_profile:
basic_information: Основная информация
hint_html: "Настройте то, что люди видят в вашем публичном профиле и рядом с вашими сообщениями. Другие люди с большей вероятностью подпишутся на Вас и будут взаимодействовать с вами, если у Вас заполнен профиль и добавлено изображение."
@@ -1407,6 +1485,7 @@ ru:
authentication_methods:
otp: приложение двухфакторной аутентификации
password: пароль
+ sign_in_token: код безопасности электронной почты
webauthn: ключи безопасности
description_html: Если вы видите неопознанное действие, смените пароль и/или включите двухфакторную авторизацию.
empty: Нет доступной истории входов
@@ -1417,10 +1496,20 @@ ru:
unsubscribe:
action: Да, отписаться
complete: Подписка отменена
+ emails:
+ notification_emails:
+ favourite: любимые электронные письма с уведомлениями
+ follow: Следить за электронными сообщениями
+ follow_request: Письма с просьбой о помощи
+ mention: Упоминание электронных писем с уведомлениями
+ reblog: Уведомления по электронной почте
+ resubscribe_html: Если вы отписались от рассылки по ошибке, вы можете повторно подписаться на рассылку в настройках настроек почтовых уведомлений.
+ success_html: Вы больше не будете получать %{type} для Mastodon на %{domain} на вашу электронную почту %{email}.
title: Отписаться
media_attachments:
validations:
images_and_video: Нельзя добавить видео к посту с изображениями
+ not_found: Медиа %{ids} не найдено или уже прикреплено к другому сообщению
not_ready: Не удаётся прикрепить файлы, обработка которых не завершена. Повторите попытку чуть позже!
too_many: Нельзя добавить более 4 файлов
migrations:
@@ -1497,6 +1586,8 @@ ru:
update:
subject: "%{name} изменил(а) пост"
notifications:
+ administration_emails: Уведомления администратора по электронной почте
+ email_events: События для уведомлений по электронной почте
email_events_hint: 'Выберите события, для которых вы хотели бы получать уведомления:'
number:
human:
@@ -1655,16 +1746,26 @@ ru:
import: Импорт
import_and_export: Импорт и экспорт
migrate: Миграция учётной записи
+ notifications: E-mail уведомление
preferences: Настройки
profile: Профиль
relationships: Подписки и подписчики
+ severed_relationships: Разорванные отношения
statuses_cleanup: Авто-удаление постов
strikes: Замечания модерации
two_factor_authentication: Подтверждение входа
webauthn_authentication: Ключи безопасности
severed_relationships:
+ download: Скачать (%{count})
event_type:
+ account_suspension: Приостановка аккаунта (%{target_name})
+ domain_block: Приостановка сервера (%{target_name})
user_domain_block: Вы заблокировали %{target_name}
+ lost_followers: Потерянные подписчики
+ lost_follows: Потерянный следует
+ preamble: Вы можете потерять подписчиков и последователей, если заблокируете домен или, если ваши модераторы решат приостановить работу удаленного сервера. Когда это произойдет, вы сможете загрузить списки разорванных отношений, чтобы проверить их и, возможно, импортировать на другой сервер.
+ purged: Информация об этом сервере была удалена администраторами вашего сервера.
+ type: Событие
statuses:
attached:
audio:
@@ -1694,27 +1795,12 @@ ru:
edited_at_html: Редактировано %{date}
errors:
in_reply_not_found: Пост, на который вы пытаетесь ответить, не существует или удалён.
- open_in_web: Открыть в веб-версии
over_character_limit: превышен лимит символов (%{max})
pin_errors:
direct: Сообщения, видимые только упомянутым пользователям, не могут быть закреплены
limit: Вы закрепили максимально возможное число постов
ownership: Нельзя закрепить чужой пост
reblog: Нельзя закрепить продвинутый пост
- poll:
- total_people:
- few: "%{count} человека"
- many: "%{count} человек"
- one: "%{count} человек"
- other: "%{count} человек"
- total_votes:
- few: "%{count} голоса"
- many: "%{count} голосов"
- one: "%{count} голос"
- other: "%{count} голосов"
- vote: Голосовать
- show_more: Развернуть
- show_thread: Открыть обсуждение
title: '%{name}: "%{quote}"'
visibilities:
direct: Адресованный
@@ -1770,6 +1856,7 @@ ru:
contrast: Mastodon (высококонтрастная)
default: Mastodon (тёмная)
mastodon-light: Mastodon (светлая)
+ system: Автоматически (используйте системную тему)
time:
formats:
default: "%d %b %Y, %H:%M"
@@ -1858,8 +1945,45 @@ ru:
suspend: Учётная запись заблокирована
welcome:
apps_android_action: Скачать на Google Play
+ apps_ios_action: Скачать в App Store
+ apps_step: Загрузите наши официальные приложения.
+ apps_title: Приложения Mastodon
+ checklist_subtitle: 'Давайте начнем знакомство с этим новым социальным рубежом:'
+ checklist_title: Приветственный контрольный список
+ edit_profile_action: Персонализация
+ edit_profile_step: Усильте взаимодействие, заполнив полный профиль.
+ edit_profile_title: Персонализируйте свой профиль
explanation: Вот несколько советов для новичков
feature_action: Подробнее
+ feature_audience: Mastodon предоставляет вам уникальную возможность управлять своей аудиторией без посредников. Mastodon, развернутый на вашей собственной инфраструктуре, позволяет вам следить и быть преследуемым с любого другого сервера Mastodon в Интернете и не контролируется никем, кроме вас.
+ feature_audience_title: Создайте уверенную аудиторию
+ feature_control: Вы сами знаете, что хотите видеть в своей ленте. Никаких алгоритмов или рекламы, чтобы тратить ваше время. Следите за любым человеком на любом сервере Mastodon с одного аккаунта и получайте его сообщения в хронологическом порядке, а также сделайте свой уголок интернета немного больше похожим на себя.
+ feature_control_title: Контролируйте свой график
+ feature_creativity: Mastodon поддерживает аудио-, видео- и фотопосты, описания доступности, опросы, предупреждения о содержании, анимированные аватары, пользовательские emojis, управление обрезкой миниатюр и многое другое, чтобы помочь вам выразить себя в Интернете. Публикуете ли вы свои работы, музыку или подкаст, Mastodon всегда готов помочь вам.
+ feature_creativity_title: Непревзойденная креативность
+ feature_moderation: Mastodon возвращает принятие решений в ваши руки. Каждый сервер создает свои собственные правила и нормы, которые соблюдаются локально, а не сверху вниз, как в корпоративных социальных сетях, что позволяет наиболее гибко реагировать на потребности различных групп людей. Присоединяйтесь к серверу с правилами, с которыми вы согласны, или создайте свой собственный.
+ feature_moderation_title: Модерирование, каким оно должно быть
+ follow_action: Следуйте за
+ follow_step: Следить за интересными людьми - вот что такое Mastodon.
+ follow_title: Персонализируйте свою домашнюю ленту
+ follows_subtitle: Следите за известными аккаунтами
+ follows_title: За кем следить
+ follows_view_more: Посмотреть больше людей, за которыми стоит следить
+ hashtags_recent_count:
+ few: "%{people} человека за последние 2 дня"
+ many: "%{people} человек за последние 2 дня"
+ one: "%{people} человек за последние 2 дня"
+ other: "%{people} человек за последние 2 дня"
+ hashtags_subtitle: Изучите, что было в тренде за последние 2 дня
+ hashtags_title: Модные хэштеги
+ hashtags_view_more: Посмотреть другие трендовые хэштеги
+ post_action: Составить
+ post_step: Поприветствуйте мир с помощью текста, фотографий, видео или опросов.
+ post_title: Сделайте свой первый пост
+ share_action: Поделиться
+ share_step: Пусть ваши друзья знают, как найти вас на Mastodon.
+ share_title: Поделитесь информацией о компании Mastodon
+ sign_in_action: Зарегистрироваться
subject: Добро пожаловать в Mastodon
title: Добро пожаловать на борт, %{name}!
users:
@@ -1868,6 +1992,7 @@ ru:
invalid_otp_token: Введен неверный код двухфакторной аутентификации
otp_lost_help_html: Если Вы потеряли доступ к обоим, свяжитесь с %{email}
rate_limited: Слишком много попыток аутентификации, повторите попытку позже.
+ seamless_external_login: Вы вошли в систему через внешнюю службу, поэтому настройки пароля и электронной почты недоступны.
signed_in_as: 'Выполнен вход под именем:'
verification:
extra_instructions_html: Подсказка: Ссылка на вашем сайте может быть невидимой. Важной частью является rel="me"
, который предотвращает выдачу себя за другое лицо на сайтах с пользовательским контентом. Вы даже можете использовать тег link
в заголовке страницы вместо a
, но HTML должен быть доступен без выполнения JavaScript.
@@ -1876,6 +2001,7 @@ ru:
instructions_html: Скопируйте и вставьте код ниже в HTML вашего сайта. Затем, добавьте адрес вашего веб сайта в одно из дополнительных полей на вкладке "Редактировать профиль" и сохраните изменения.
verification: Верификация ссылок
verified_links: Ваши ссылки подтверждения
+ website_verification: Проверка веб-сайта
webauthn_credentials:
add: Добавить новый ключ безопасности
create:
diff --git a/config/locales/ry.yml b/config/locales/ry.yml
index e384b7f1b7..dd1b78600c 100644
--- a/config/locales/ry.yml
+++ b/config/locales/ry.yml
@@ -1,7 +1,6 @@
---
ry:
accounts:
- follow: Пудписати ся
following: Пудпискы
posts:
few: Публикації
diff --git a/config/locales/sc.yml b/config/locales/sc.yml
index ee66cef834..780270ddf1 100644
--- a/config/locales/sc.yml
+++ b/config/locales/sc.yml
@@ -7,7 +7,6 @@ sc:
hosted_on: Mastodon allogiadu in %{domain}
title: Informatziones
accounts:
- follow: Sighi
followers:
one: Sighidura
other: Sighiduras
@@ -694,7 +693,6 @@ sc:
crypto:
errors:
invalid_key: no est una crae Ed25519 o Curve25519 vàlida
- invalid_signature: no est una firma Ed25519 vàlida
date:
formats:
default: "%d %b, %Y"
@@ -734,8 +732,6 @@ sc:
title_actions:
delete_statuses: Cantzelladura de publicatziones
none: Atentzione
- domain_validator:
- invalid_domain: no est unu nòmine de domìniu vàlidu
edit_profile:
basic_information: Informatzione bàsica
other: Àteru
@@ -1113,22 +1109,11 @@ sc:
other: 'cuntenet is etichetas non permìtidas: %{tags}'
errors:
in_reply_not_found: Ses chirchende de rispòndere a unu tut chi no esistit prus.
- open_in_web: Aberi in sa web
over_character_limit: lìmite de caràteres de %{max} superadu
pin_errors:
limit: As giai apicadu su nùmeru màssimu de tuts
ownership: Is tuts de àtere non podent èssere apicados
reblog: Is cumpartziduras non podent èssere apicadas
- poll:
- total_people:
- one: "%{count} persone"
- other: "%{count} persones"
- total_votes:
- one: "%{count} votu"
- other: "%{count} votos"
- vote: Vota
- show_more: Ammustra·nde prus
- show_thread: Ammustra su tema
title: '%{name}: "%{quote}"'
visibilities:
direct: Deretu
diff --git a/config/locales/sco.yml b/config/locales/sco.yml
index 4b7b9e56d7..97eaa21ed6 100644
--- a/config/locales/sco.yml
+++ b/config/locales/sco.yml
@@ -7,7 +7,6 @@ sco:
hosted_on: Mastodon hostit on %{domain}
title: Aboot
accounts:
- follow: Follae
followers:
one: Follaer
other: Follaers
@@ -941,7 +940,6 @@ sco:
crypto:
errors:
invalid_key: isnae a valid Ed25519 or Curve25519 key
- invalid_signature: isnae a valid Ed25519 signature
date:
formats:
default: "%b %d, %Y"
@@ -1004,8 +1002,6 @@ sco:
your_appeal_approved: Yer appeal haes been approved
your_appeal_pending: Ye hae submittit a appeal
your_appeal_rejected: Yer appeal haes been rejectit
- domain_validator:
- invalid_domain: isnae a valid domain nemm
errors:
'400': The request thit ye submittit wisnae valid or it wis illformt.
'403': Ye dinnae hae permission fir tae luik at this page.
@@ -1396,23 +1392,12 @@ sco:
edited_at_html: Editit %{date}
errors:
in_reply_not_found: The post thit ye'r trying tae reply tae disnae appear tae exist.
- open_in_web: Open in wab
over_character_limit: chairacter limit o %{max} exceedit
pin_errors:
direct: Posts thit's ainly visible tae menshied uisers cannae be preent
limit: Ye awriddy preent the maximum nummer o posts
ownership: Somebody else's post cannae be preent
reblog: A heeze cannae be preent
- poll:
- total_people:
- one: "%{count} person"
- other: "%{count} fowk"
- total_votes:
- one: "%{count} vote"
- other: "%{count} votes"
- vote: Vote
- show_more: Shaw mair
- show_thread: Shaw threid
title: '%{name}: "%{quote}"'
visibilities:
direct: Direck
diff --git a/config/locales/si.yml b/config/locales/si.yml
index e68da4321a..8460de01da 100644
--- a/config/locales/si.yml
+++ b/config/locales/si.yml
@@ -7,7 +7,6 @@ si:
hosted_on: "%{domain} හරහා සත්කාරකත්වය ලබයි"
title: පිළිබඳව
accounts:
- follow: අනුගමනය
followers:
one: අනුගාමිකයා
other: අනුගාමිකයින්
@@ -830,7 +829,6 @@ si:
crypto:
errors:
invalid_key: වලංගු Ed25519 හෝ Curve25519 යතුරක් නොවේ
- invalid_signature: වලංගු Ed25519 අත්සනක් නොවේ
date:
formats:
default: "%Y %b %d"
@@ -892,8 +890,6 @@ si:
your_appeal_approved: ඔබගේ අභියාචනය අනුමත කර ඇත
your_appeal_pending: ඔබ අභියාචනයක් ඉදිරිපත් කර ඇත
your_appeal_rejected: ඔබගේ අභියාචනය ප්රතික්ෂේප කර ඇත
- domain_validator:
- invalid_domain: වලංගු ඩොමේන් නාමයක් නොවේ
edit_profile:
basic_information: මූලික තොරතුරු
other: වෙනත්
@@ -1269,22 +1265,11 @@ si:
edited_at_html: සංස්කරණය %{date}
errors:
in_reply_not_found: ඔබ පිළිතුරු දීමට තැත් කරන ලිපිය නොපවතින බව පෙනෙයි.
- open_in_web: වෙබයේ විවෘත කරන්න
over_character_limit: අක්ෂර සීමාව %{max} ඉක්මවා ඇත
pin_errors:
direct: සඳහන් කළ අයට පමණක් පෙනෙන ලිපි ඇමිණීමට නොහැකිය
limit: දැනටමත් මුදුනට ඇමිණිමට හැකි ලිපි සීමාවට ළඟා වී ඇත
ownership: වෙනත් අයගේ ලිපි ඇමිණීමට නොහැකිය
- poll:
- total_people:
- one: පුද්ගලයින් %{count}
- other: පුද්ගලයින් %{count}
- total_votes:
- one: ඡන්ද %{count} යි
- other: ඡන්ද %{count} යි
- vote: ඡන්දය
- show_more: තව පෙන්වන්න
- show_thread: නූල් පෙන්වන්න
title: '%{name}: "%{quote}"'
visibilities:
direct: සෘජු
diff --git a/config/locales/simple_form.an.yml b/config/locales/simple_form.an.yml
index 7119aadba2..c59391f552 100644
--- a/config/locales/simple_form.an.yml
+++ b/config/locales/simple_form.an.yml
@@ -108,7 +108,6 @@ an:
name: Nomás se puede cambiar lo cajón d'as letras, per eixemplo, pa que sía mas leyible
user:
chosen_languages: Quan se marca, nomás s'amostrarán las publicacions en os idiomas triaus en as linias de tiempo publicas
- role: Lo rol controla qué permisos tiene la usuaria
user_role:
color: Color que s'utilizará pa lo rol a lo largo d'a interficie d'usuario, como RGB en formato hexadecimal
highlighted: Esto fa que lo rol sía publicament visible
diff --git a/config/locales/simple_form.ar.yml b/config/locales/simple_form.ar.yml
index e552b42b18..b591cdca57 100644
--- a/config/locales/simple_form.ar.yml
+++ b/config/locales/simple_form.ar.yml
@@ -3,6 +3,7 @@ ar:
simple_form:
hints:
account:
+ attribution_domains_as_text: يحمي من الإسناد الزائف.
discoverable: يمكن عرض مشاركاتك العامة وملفك الشخصي أو التوصية به في مختلف مناطق ماستدون ويمكن اقتراح ملفك الشخصي على مستخدمين آخرين.
display_name: اسمك الكامل أو اسمك المرح.
fields: صفحتك الرئيسية، ضمائرك، عمرك، أي شيء تريده.
@@ -130,7 +131,6 @@ ar:
name: يمكنك فقط تغيير غلاف الحروف ، على سبيل المثال ، لجعلها أكثر قابلية للقراءة
user:
chosen_languages: إن تم اختيارها، فلن تظهر على الخيوط العامة إلّا الرسائل المنشورة في تلك اللغات
- role: الوظيفة تتحكم في الصلاحيات التي يملكها المستخدم
user_role:
color: اللون الذي سيتم استخدامه للوظيفه في جميع وحدات واجهة المستخدم، كـ RGB بتنسيق hex
highlighted: وهذا يجعل الوظيفه مرئيا علنا
@@ -206,7 +206,7 @@ ar:
setting_aggregate_reblogs: جمّع المنشورات المعاد نشرها في الخيوط الزمنية
setting_always_send_emails: ارسل إشعارات البريد الإلكتروني دائماً
setting_auto_play_gif: تشغيل تلقائي لِوَسائط جيف المتحركة
- setting_boost_modal: إظهار مربع حوار التأكيد قبل إعادة مشاركة أي منشور
+ setting_boost_modal: إظهار مربع حوار التأكيد قبل إعادة نشر أي منشور
setting_default_language: لغة النشر
setting_default_privacy: خصوصية المنشور
setting_default_sensitive: اعتبر الوسائط دائما كمحتوى حساس
diff --git a/config/locales/simple_form.be.yml b/config/locales/simple_form.be.yml
index a50db22987..db6a94f8eb 100644
--- a/config/locales/simple_form.be.yml
+++ b/config/locales/simple_form.be.yml
@@ -130,7 +130,6 @@ be:
name: Вы можаце змяняць толькі рэгістр літар, напрыклад для таго, каб падвысіць чытабельнасць
user:
chosen_languages: У публічных стужках будуць паказвацца допісы толькі на тых мовах, якія вы пазначыце
- role: Гэтая роля кантралюе дазволы, якія мае карыстальнік
user_role:
color: Колер, які будзе выкарыстоўвацца для гэтай ролі па ўсім UI, у фармаце RGB ці hex
highlighted: Гэта робіць ролю публічна бачнай
diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml
index 333ab25c82..a2cf8e4222 100644
--- a/config/locales/simple_form.bg.yml
+++ b/config/locales/simple_form.bg.yml
@@ -130,7 +130,6 @@ bg:
name: Можете да смените само употребата на големи/малки букви, например, за да е по-четимо
user:
chosen_languages: Само публикации на отметнатите езици ще се показват в публичните часови оси
- role: Ролите управляват какви права има потребителят
user_role:
color: Цветът, използван за ролите в потребителския интерфейс, като RGB в шестнадесетичен формат
highlighted: Това прави ролята обществено видима
diff --git a/config/locales/simple_form.ca.yml b/config/locales/simple_form.ca.yml
index 4daf657234..7b651470bf 100644
--- a/config/locales/simple_form.ca.yml
+++ b/config/locales/simple_form.ca.yml
@@ -3,6 +3,7 @@ ca:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protegeix de falses atribucions.
discoverable: El teu perfil i els teus tuts públics poden aparèixer o ser recomanats en diverses àreas de Mastodon i el teu perfil pot ser suggerit a altres usuaris.
display_name: El teu nom complet o el teu nom divertit.
fields: La teva pàgina d'inici, pronoms, edat, el que vulguis.
@@ -130,7 +131,7 @@ ca:
name: Només pots canviar la caixa de les lletres, per exemple, per fer-la més llegible
user:
chosen_languages: Quan estigui marcat, només es mostraran els tuts de les llengües seleccionades en les línies de temps públiques
- role: El rol controla quines permissions té l'usuari
+ role: El rol controla quins permisos té l'usuari.
user_role:
color: Color que s'usarà per al rol a tota la interfície d'usuari, com a RGB en format hexadecimal
highlighted: Això fa el rol visible públicament
@@ -143,6 +144,7 @@ ca:
url: On els esdeveniments seran enviats
labels:
account:
+ attribution_domains_as_text: Permet només webs específics
discoverable: Permet el perfil i el tuts en els algorismes de descobriment
fields:
name: Etiqueta
diff --git a/config/locales/simple_form.cs.yml b/config/locales/simple_form.cs.yml
index 2fe08e698a..6242b1ca6e 100644
--- a/config/locales/simple_form.cs.yml
+++ b/config/locales/simple_form.cs.yml
@@ -130,7 +130,6 @@ cs:
name: Můžete měnit pouze velikost písmen, například kvůli lepší čitelnosti
user:
chosen_languages: Po zaškrtnutí budou ve veřejných časových osách zobrazeny pouze příspěvky ve zvolených jazycích
- role: Role určuje, která oprávnění má uživatel
user_role:
color: Barva, která má být použita pro roli v celém UI, jako RGB v hex formátu
highlighted: Toto roli učiní veřejně viditelnou
diff --git a/config/locales/simple_form.cy.yml b/config/locales/simple_form.cy.yml
index 22545a776a..56d1f873dc 100644
--- a/config/locales/simple_form.cy.yml
+++ b/config/locales/simple_form.cy.yml
@@ -3,6 +3,7 @@ cy:
simple_form:
hints:
account:
+ attribution_domains_as_text: Yn amddiffyn rhag priodoliadau ffug.
discoverable: Mae'n bosibl y bydd eich postiadau cyhoeddus a'ch proffil yn cael sylw neu'n cael eu hargymell mewn gwahanol feysydd o Mastodon ac efallai y bydd eich proffil yn cael ei awgrymu i ddefnyddwyr eraill.
display_name: Eich enw llawn neu'ch enw hwyl.
fields: Eich tudalen cartref, rhagenwau, oed, neu unrhyw beth.
@@ -130,7 +131,7 @@ cy:
name: Dim ond er mwyn ei gwneud yn fwy darllenadwy y gallwch chi newid y llythrennau, er enghraifft
user:
chosen_languages: Wedi eu dewis, dim ond tŵtiau yn yr ieithoedd hyn bydd yn cael eu harddangos mewn ffrydiau cyhoeddus
- role: Mae'r rôl yn rheoli pa ganiatâd sydd gan y defnyddiwr
+ role: Mae'r rôl yn rheoli pa ganiatâd sydd gan y defnyddiwr.
user_role:
color: Lliw i'w ddefnyddio ar gyfer y rôl drwy'r UI, fel RGB mewn fformat hecs
highlighted: Mae hyn yn gwneud y rôl yn weladwy i'r cyhoedd
@@ -143,6 +144,7 @@ cy:
url: I ble bydd digwyddiadau'n cael eu hanfon
labels:
account:
+ attribution_domains_as_text: Dim ond yn caniatáu gwefannau penodol
discoverable: Proffil nodwedd a phostiadau mewn algorithmau darganfod
fields:
name: Label
diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml
index 5763885ac4..e7b8fe337a 100644
--- a/config/locales/simple_form.da.yml
+++ b/config/locales/simple_form.da.yml
@@ -3,6 +3,7 @@ da:
simple_form:
hints:
account:
+ attribution_domains_as_text: Beskytter mod falske tilskrivninger.
discoverable: Dine offentlige indlæg og profil kan blive fremhævet eller anbefalet i forskellige områder af Mastodon, og profilen kan blive foreslået til andre brugere.
display_name: Dit fulde navn eller dit sjove navn.
fields: Din hjemmeside, dine pronominer, din alder, eller hvad du har lyst til.
@@ -130,7 +131,7 @@ da:
name: Kun bogstavtyper (store/små) kan ændres, eksempelvis for at gøre det mere læsbart
user:
chosen_languages: Når markeret, vil kun indlæg på de valgte sprog fremgå på offentlige tidslinjer
- role: Rollen styrer, hvilke tilladelser brugeren har
+ role: Rollen styrer, hvilke tilladelser brugeren er tildelt.
user_role:
color: Farven, i RGB hex-format, der skal bruges til rollen i hele UI'en
highlighted: Dette gør rollen offentligt synlig
@@ -143,6 +144,7 @@ da:
url: Hvor begivenheder sendes til
labels:
account:
+ attribution_domains_as_text: Tillad kun bestemte websteder
discoverable: Fremhæv profil og indlæg i opdagelsesalgoritmer
fields:
name: Etiket
diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml
index fb7bda9489..f7e55f1a7b 100644
--- a/config/locales/simple_form.de.yml
+++ b/config/locales/simple_form.de.yml
@@ -3,6 +3,7 @@ de:
simple_form:
hints:
account:
+ attribution_domains_as_text: Dadurch können falsche Zuschreibungen unterbunden werden.
discoverable: Deine öffentlichen Beiträge und dein Profil können in verschiedenen Bereichen auf Mastodon angezeigt oder empfohlen werden und dein Profil kann anderen vorgeschlagen werden.
display_name: Dein richtiger Name oder dein Fantasiename.
fields: Deine Website, Pronomen, dein Alter – alles, was du möchtest.
@@ -130,7 +131,7 @@ de:
name: Du kannst nur die Groß- und Kleinschreibung der Buchstaben ändern, um es z. B. lesbarer zu machen
user:
chosen_languages: Wenn du hier eine oder mehrere Sprachen auswählst, werden ausschließlich Beiträge in diesen Sprachen in deinen öffentlichen Timelines angezeigt
- role: Die Rolle legt fest, welche Berechtigungen das Konto hat
+ role: Die Rolle bestimmt, welche Berechtigungen das Konto hat.
user_role:
color: Farbe, die für diese Rolle in der gesamten Benutzerschnittstelle verwendet wird, als RGB im Hexadezimalsystem
highlighted: Dies macht die Rolle öffentlich im Profil sichtbar
@@ -143,6 +144,7 @@ de:
url: Wohin Ereignisse gesendet werden
labels:
account:
+ attribution_domains_as_text: Nur ausgewählte Websites zulassen
discoverable: Profil und Beiträge in Suchalgorithmen berücksichtigen
fields:
name: Beschriftung
diff --git a/config/locales/simple_form.el.yml b/config/locales/simple_form.el.yml
index af93f65fec..d46e764a44 100644
--- a/config/locales/simple_form.el.yml
+++ b/config/locales/simple_form.el.yml
@@ -2,6 +2,15 @@
el:
simple_form:
hints:
+ account:
+ attribution_domains_as_text: Προστατεύει από ψευδείς ιδιότητες.
+ discoverable: Οι δημόσιες δημοσιεύσεις και το προφίλ σου μπορεί να εμφανίζονται ή να συνιστώνται σε διάφορους τομείς του Mastodon και το προφίλ σου μπορεί να προτείνεται σε άλλους χρήστες.
+ display_name: Το πλήρες ή το αστείο σου όνομα.
+ fields: Η αρχική σου σελίδα, αντωνυμίες, ηλικία, ό,τι θες.
+ indexable: Οι δημόσιες δημοσιεύσεις σου μπορεί να εμφανιστούν στα αποτελέσματα αναζήτησης στο Mastodon. Άτομα που έχουν αλληλεπιδράσει με τις δημοσιεύσεις σου μπορεί να είναι σε θέση να τις αναζητήσουν όπως και να 'χει.
+ note: 'Μπορείς να @επισημάνεις άλλα άτομα ή #ετικέτες.'
+ show_collections: Οι χρήστες θα είναι σε θέση να περιηγηθούν στα άτομα που ακολουθείς και στους ακόλουθούς σου. Άτομα που ακολουθείς θα βλέπουν ότι τους ακολουθείς όπως και να 'χει.
+ unlocked: Οι χρήστες θα είναι σε θέση να σε ακολουθήσουν χωρίς να ζητούν έγκριση. Κατάργησε την επιλογή αν θες να αξιολογείς τα αιτήματα ακολούθησης και να επιλέξεις αν θα αποδεχθείς ή απορρίψεις νέους ακόλουθους.
account_alias:
acct: Όρισε το username@domain του λογαριασμού από τον οποίο θέλεις να μετακινηθείς
account_migration:
@@ -31,12 +40,14 @@ el:
text: Μπορείς να κάνετε έφεση σε ένα παράπτωμα μόνο μία φορά
defaults:
autofollow: Όσοι εγγραφούν μέσω της πρόσκλησης θα σε ακολουθούν αυτόματα
+ avatar: WEBP, PNG, GIF ή JPG. Το πολύ %{size}. Θα υποβαθμιστεί σε %{dimensions}px
bot: Ο λογαριασμός αυτός εκτελεί κυρίως αυτοματοποιημένες ενέργειες και ίσως να μην παρακολουθείται
context: Ένα ή περισσότερα πλαίσια στα οποία μπορεί να εφαρμόζεται αυτό το φίλτρο
current_password: Για λόγους ασφαλείας παρακαλώ γράψε τον κωδικό του τρέχοντος λογαριασμού
current_username: Για επιβεβαίωση, παρακαλώ γράψε το όνομα χρήστη του τρέχοντος λογαριασμού
digest: Αποστέλλεται μόνο μετά από μακρά περίοδο αδράνειας και μόνο αν έχεις λάβει προσωπικά μηνύματα κατά την απουσία σου
email: Θα σου σταλεί email επιβεβαίωσης
+ header: WEBP, PNG, GIF ή JPG. Το πολύ %{size}. Θα υποβαθμιστεί σε %{dimensions}px
inbox_url: Αντέγραψε το URL της αρχικής σελίδας του ανταποκριτή που θέλεις να χρησιμοποιήσεις
irreversible: Οι φιλτραρισμένες αναρτήσεις θα εξαφανιστούν αμετάκλητα, ακόμα και αν το φίλτρο αργότερα αφαιρεθεί
locale: Η γλώσσα χρήσης, των email και των ειδοποιήσεων push
@@ -67,10 +78,15 @@ el:
warn: Απόκρυψη φιλτραρισμένου περιεχομένου πίσω από μια προειδοποίηση που αναφέρει τον τίτλο του φίλτρου
form_admin_settings:
activity_api_enabled: Καταμέτρηση τοπικά δημοσιευμένων δημοσιεύσεων, ενεργών χρηστών και νέων εγγραφών σε εβδομαδιαία πακέτα
+ app_icon: WEBP, PNG, GIF ή JPG. Παρακάμπτει το προεπιλεγμένο εικονίδιο εφαρμογής σε κινητές συσκευές με προσαρμοσμένο εικονίδιο.
+ backups_retention_period: Οι χρήστες έχουν τη δυνατότητα να δημιουργήσουν αρχεία των αναρτήσεων τους για να κατεβάσουν αργότερα. Όταν οριστεί μια θετική τιμή, αυτά τα αρχεία θα διαγράφονται αυτόματα από τον αποθηκευτικό σου χώρο μετά τον καθορισμένο αριθμό ημερών.
bootstrap_timeline_accounts: Αυτοί οι λογαριασμοί θα καρφιτσωθούν στην κορυφή των νέων χρηστών που ακολουθούν τις συστάσεις.
closed_registrations_message: Εμφανίζεται όταν κλείνουν οι εγγραφές
+ content_cache_retention_period: Όλες οι αναρτήσεις από άλλους διακομιστές (συμπεριλαμβανομένων των ενισχύσεων και απαντήσεων) θα διαγραφούν μετά τον καθορισμένο αριθμό ημερών, χωρίς να λαμβάνεται υπόψη οποιαδήποτε αλληλεπίδραση τοπικού χρήστη με αυτές τις αναρτήσεις. Αυτό περιλαμβάνει αναρτήσεις όπου ένας τοπικός χρήστης την έχει χαρακτηρίσει ως σελιδοδείκτη ή αγαπημένη. Θα χαθούν επίσης ιδιωτικές αναφορές μεταξύ χρηστών από διαφορετικές οντότητες και θα είναι αδύνατο να αποκατασταθούν. Η χρήση αυτής της ρύθμισης προορίζεται για οντότητες ειδικού σκοπού και χαλάει πολλές προσδοκίες του χρήστη όταν εφαρμόζεται για χρήση γενική σκοπού.
custom_css: Μπορείς να εφαρμόσεις προσαρμοσμένα στυλ στην έκδοση ιστοσελίδας του Mastodon.
+ favicon: WEBP, PNG, GIF ή JPG. Παρακάμπτει το προεπιλεγμένο favicon του Mastodon με ένα προσαρμοσμένο εικονίδιο.
mascot: Παρακάμπτει την εικονογραφία στην προηγμένη διεπαφή ιστού.
+ media_cache_retention_period: Τα αρχεία πολυμέσων από αναρτήσεις που γίνονται από απομακρυσμένους χρήστες αποθηκεύονται προσωρινά στο διακομιστή σου. Όταν οριστεί μια θετική τιμή, τα μέσα θα διαγραφούν μετά τον καθορισμένο αριθμό ημερών. Αν τα δεδομένα πολυμέσων ζητηθούν μετά τη διαγραφή τους, θα γίνει ε, αν το πηγαίο περιεχόμενο είναι ακόμα διαθέσιμο. Λόγω περιορισμών σχετικά με το πόσο συχνά οι κάρτες προεπισκόπησης συνδέσμων συνδέονται σε ιστοσελίδες τρίτων, συνιστάται να ορίσεις αυτή την τιμή σε τουλάχιστον 14 ημέρες ή οι κάρτες προεπισκόπησης συνδέσμων δεν θα ενημερώνονται κατ' απάιτηση πριν από εκείνη την ώρα.
peers_api_enabled: Μια λίστα με ονόματα τομέα που συνάντησε αυτός ο διακομιστής στο fediverse. Δεν περιλαμβάνονται δεδομένα εδώ για το αν συναλλάσσετε με ένα συγκεκριμένο διακομιστή, μόνο ότι ο διακομιστής σας το ξέρει. Χρησιμοποιείται από υπηρεσίες που συλλέγουν στατιστικά στοιχεία για την συναλλαγή με γενική έννοια.
profile_directory: Ο κατάλογος προφίλ παραθέτει όλους τους χρήστες που έχουν επιλέξει να είναι ανακαλύψιμοι.
require_invite_text: 'Όταν η εγγραφή απαιτεί χειροκίνητη έγκριση, κάνε το πεδίο κειμένου: «Γιατί θέλετε να συμμετάσχετε;» υποχρεωτικό αντί για προαιρετικό'
@@ -103,15 +119,19 @@ el:
sign_up_requires_approval: Νέες εγγραφές θα απαιτούν την έγκριση σας
severity: Επιλέξτε τι θα γίνεται με αιτήσεις από αυτήν την διεύθυνση IP
rule:
+ hint: Προαιρετικό. Δώσε περισσότερες λεπτομέρειες σχετικά με τον κανόνα
text: Περιγράψτε έναν κανόνα ή μια απαίτηση για τους χρήστες σε αυτόν τον διακομιστή. Προσπαθήστε να τον κρατήσετε σύντομο και απλό
sessions:
otp: 'Βάλε τον κωδικό δυο παραγόντων (2FA) από την εφαρμογή του τηλεφώνου σου ή χρησιμοποίησε κάποιον από τους κωδικούς ανάκτησης σου:'
webauthn: Αν πρόκειται για ένα κλειδί USB βεβαιωθείτε ότι είναι συνδεδεμένο και αν απαιτείται πατήστε το ελαφρά.
+ settings:
+ indexable: Η σελίδα του προφίλ σου μπορεί να εμφανιστεί στα αποτελέσματα αναζήτησης στο Google, Bing και άλλες.
+ show_application: Θα είσαι πάντα σε θέση να δεις ποια εφαρμογή δημοσίευσε την ανάρτησή σου όπως και να 'χει.
tag:
name: Μπορείς να αλλάξεις μόνο το πλαίσιο των χαρακτήρων, για παράδειγμα για να γίνει περισσότερο ευανάγνωστο
user:
chosen_languages: Όταν ενεργοποιηθεί, στη δημόσια ροή θα εμφανίζονται τουτ μόνο από τις επιλεγμένες γλώσσες
- role: Ο ρόλος ελέγχει ποια δικαιώματα έχει ο χρήστης
+ role: Ο ρόλος ελέγχει ποια δικαιώματα έχει ο χρήστης.
user_role:
color: Το χρώμα που θα χρησιμοποιηθεί για το ρόλο σε ολόκληρη τη διεπαφή, ως RGB σε δεκαεξαδική μορφή
highlighted: Αυτό καθιστά το ρόλο δημόσια ορατό
@@ -120,12 +140,18 @@ el:
position: Ανώτεροι ρόλοι αποφασίζει την επίλυση συγκρούσεων σε ορισμένες περιπτώσεις. Ορισμένες ενέργειες μπορούν να εκτελεστούν μόνο σε ρόλους με χαμηλότερη προτεραιότητα
webhook:
events: Επιλέξτε συμβάντα για αποστολή
+ template: Σύνθεσε το δικό σου JSON payload χρησιμοποιώντας μεταβλητή παρεμβολή. Άφησε κενό για προεπιλογή JSON.
url: Πού θα σταλούν τα γεγονότα
labels:
account:
+ attribution_domains_as_text: Να επιτρέπονται μόνο συγκεκριμένες ιστοσελίδες
+ discoverable: Παροχή προφίλ και αναρτήσεων σε αλγορίθμους ανακάλυψης
fields:
name: Περιγραφή
value: Περιεχόμενο
+ indexable: Συμπερίληψη δημόσιων αναρτήσεων στα αποτελέσματα αναζήτησης
+ show_collections: Εμφάνιση ακολούθων και ακολουθουμένων στο προφίλ
+ unlocked: Αυτόματη αποδοχή νέων ακολούθων
account_alias:
acct: Διακριτικό του παλιού λογαριασμού
account_migration:
@@ -187,6 +213,7 @@ el:
setting_default_privacy: Ιδιωτικότητα δημοσιεύσεων
setting_default_sensitive: Σημείωση όλων των πολυμέσων ως ευαίσθητου περιεχομένου
setting_delete_modal: Επιβεβαίωση πριν τη διαγραφή ενός τουτ
+ setting_disable_hover_cards: Απενεργοποίηση προεπισκόπησης προφίλ κατά την αιώρηση
setting_disable_swiping: Απενεργοποίηση κινήσεων συρσίματος
setting_display_media: Εμφάνιση πολυμέσων
setting_display_media_default: Προκαθορισμένο
@@ -218,10 +245,13 @@ el:
warn: Απόκρυψη με προειδοποίηση
form_admin_settings:
activity_api_enabled: Δημοσίευση συγκεντρωτικών στατιστικών σχετικά με τη δραστηριότητα του χρήστη στο API
+ app_icon: Εικονίδιο εφαρμογής
backups_retention_period: Περίοδος αρχειοθέτησης του χρήστη
bootstrap_timeline_accounts: Πρότεινε πάντα αυτούς τους λογαριασμούς σε νέους χρήστες
closed_registrations_message: Προσαρμοσμένο μήνυμα όταν οι εγγραφές δεν είναι διαθέσιμες
+ content_cache_retention_period: Περίοδος διατήρησης απομακρυσμένου περιεχομένου
custom_css: Προσαρμοσμένο CSS
+ favicon: Favicon
mascot: Προσαρμοσμένη μασκότ (απαρχαιωμένο)
media_cache_retention_period: Περίοδος διατήρησης προσωρινής μνήμης πολυμέσων
peers_api_enabled: Δημοσίευση λίστας των εντοπισμένων διακομιστών στο API
@@ -269,15 +299,27 @@ el:
pending_account: Αποστολή email όταν υπάρχει νέος λογαριασμός για επιθεώρηση
reblog: Αποστολή email όταν κάποιος προωθεί τη δημοσίευση σου
report: Υποβλήθηκε νέα αναφορά
+ software_updates:
+ all: Ειδοποίηση για όλες τις ενημερώσεις
+ critical: Ειδοποίηση μόνο για κρίσιμες ενημερώσεις
+ label: Μια νέα έκδοση του Mastodon είναι διαθέσιμη
+ none: Να μην ειδοποιούμαι ποτέ για ενημερώσεις (δεν συνιστάται)
+ patch: Ειδοποίηση για ενημερώσεις σφαλμάτων
trending_tag: Νέο περιεχόμενο προς τάση απαιτεί αξιολόγηση
rule:
+ hint: Επιπρόσθετες πληροφορίες
text: Κανόνας
+ settings:
+ indexable: Συμπερίληψη σελίδας προφίλ στις μηχανές αναζήτησης
+ show_application: Εμφάνιση από ποια εφαρμογή έστειλες μία ανάρτηση
tag:
listable: Εμφάνιση αυτής της ετικέτας στο δημόσιο κατάλογο
name: Ετικέτα
trendable: Εμφάνιση της ετικέτας στις τάσεις
+ usable: Να επιτρέπεται η τοπική χρήση αυτής της ετικέτας από αναρτήσεις
user:
role: Ρόλος
+ time_zone: Ζώνη ώρας
user_role:
color: Χρώμα εμβλήματος
highlighted: Εμφάνιση ρόλου ως σήμα στα προφίλ χρηστών
@@ -286,9 +328,11 @@ el:
position: Προτεραιότητα
webhook:
events: Ενεργοποιημένα συμβάντα
+ template: Πρότυπο payload
url: Endpoint URL
'no': Όχι
not_recommended: Δεν προτείνεται
+ overridden: Αντικαταστάθηκε
recommended: Προτείνεται
required:
mark: "*"
diff --git a/config/locales/simple_form.en-GB.yml b/config/locales/simple_form.en-GB.yml
index 2f40feb5ed..b802fd532f 100644
--- a/config/locales/simple_form.en-GB.yml
+++ b/config/locales/simple_form.en-GB.yml
@@ -3,6 +3,7 @@ en-GB:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protects from false attributions.
discoverable: Your public posts and profile may be featured or recommended in various areas of Mastodon and your profile may be suggested to other users.
display_name: Your full name or your fun name.
fields: Your homepage, pronouns, age, anything you want.
@@ -130,7 +131,7 @@ en-GB:
name: You can only change the casing of the letters, for example, to make it more readable
user:
chosen_languages: When checked, only posts in selected languages will be displayed in public timelines
- role: The role controls which permissions the user has
+ role: The role controls which permissions the user has.
user_role:
color: Color to be used for the role throughout the UI, as RGB in hex format
highlighted: This makes the role publicly visible
@@ -143,6 +144,7 @@ en-GB:
url: Where events will be sent to
labels:
account:
+ attribution_domains_as_text: Only allow specific websites
discoverable: Feature profile and posts in discovery algorithms
fields:
name: Label
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index fee3a6151a..8f6137c8c1 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -3,6 +3,7 @@ en:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protects from false attributions.
discoverable: Your public posts and profile may be featured or recommended in various areas of Mastodon and your profile may be suggested to other users.
display_name: Your full name or your fun name.
fields: Your homepage, pronouns, age, anything you want.
@@ -130,7 +131,7 @@ en:
name: You can only change the casing of the letters, for example, to make it more readable
user:
chosen_languages: When checked, only posts in selected languages will be displayed in public timelines
- role: The role controls which permissions the user has
+ role: The role controls which permissions the user has.
user_role:
color: Color to be used for the role throughout the UI, as RGB in hex format
highlighted: This makes the role publicly visible
@@ -143,6 +144,7 @@ en:
url: Where events will be sent to
labels:
account:
+ attribution_domains_as_text: Only allow specific websites
discoverable: Feature profile and posts in discovery algorithms
fields:
name: Label
diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml
index 3b51c15908..053816ef88 100644
--- a/config/locales/simple_form.eo.yml
+++ b/config/locales/simple_form.eo.yml
@@ -122,7 +122,6 @@ eo:
name: Vi povas ŝanĝi nur la majuskladon de la literoj, ekzemple, por igi ĝin pli legebla
user:
chosen_languages: Kun tio markita nur mesaĝoj en elektitaj lingvoj aperos en publikaj tempolinioj
- role: La rolregiloj kies permesojn la uzanto havas
user_role:
color: Koloro uzita por la rolo sur la UI, kun RGB-formato
highlighted: Ĉi tio igi la rolon publike videbla
diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml
index e26af5b0c6..d06d09761a 100644
--- a/config/locales/simple_form.es-AR.yml
+++ b/config/locales/simple_form.es-AR.yml
@@ -3,6 +3,7 @@ es-AR:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protege de atribuciones falsas.
discoverable: Tu perfil y publicaciones pueden ser destacadas o recomendadas en varias áreas de Mastodon, y tu perfil puede ser sugerido a otros usuarios.
display_name: Tu nombre completo o tu pseudónimo.
fields: Tu sitio web, pronombres, edad, o lo que quieras.
@@ -130,7 +131,7 @@ es-AR:
name: Sólo podés cambiar la capitalización de las letras, por ejemplo, para que sea más legible
user:
chosen_languages: Cuando estén marcados, sólo se mostrarán los mensajes en los idiomas seleccionados en las líneas temporales públicas
- role: El rol controla qué permisos tiene el usuario
+ role: El rol controla qué permisos tiene el usuario.
user_role:
color: Color que se utilizará para el rol a lo largo de la interface de usuario, como RGB en formato hexadecimal
highlighted: Esto hace que el rol sea públicamente visible
@@ -143,6 +144,7 @@ es-AR:
url: Adónde serán enviados los eventos
labels:
account:
+ attribution_domains_as_text: Solo permitir sitios web específicos
discoverable: Destacar perfil y mensajes en algoritmos de descubrimiento
fields:
name: Nombre de campo
diff --git a/config/locales/simple_form.es-MX.yml b/config/locales/simple_form.es-MX.yml
index 733a5c2769..f2108828d5 100644
--- a/config/locales/simple_form.es-MX.yml
+++ b/config/locales/simple_form.es-MX.yml
@@ -3,6 +3,7 @@ es-MX:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protege frente atribuciones fraudulentas.
discoverable: Tu perfil y las publicaciones públicas pueden ser destacadas o recomendadas en varias áreas de Mastodon y tu perfil puede ser sugerido a otros usuarios.
display_name: Tu nombre completo o tu nick.
fields: Tu página de inicio, pronombres, edad, todo lo que quieras.
@@ -15,12 +16,12 @@ es-MX:
account_migration:
acct: Especifique el nombre de usuario@dominio de la cuenta a la cual desea migrar
account_warning_preset:
- text: Puede usar sintaxis de toots, como URLs, hashtags y menciones
+ text: Puede usar sintaxis de publicaciones, como URLs, etiquetas y menciones
title: Opcional. No visible para el destinatario
admin_account_action:
- include_statuses: El usuario verá qué toots han causado la acción de moderación o advertencia
+ include_statuses: El usuario verá qué publicaciones han causado la acción de moderación o advertencia
send_email_notification: El usuario recibirá una explicación de lo que sucedió con respecto a su cuenta
- text_html: Opcional. Puede usar sintaxis de toots. Puede añadir configuraciones predefinidas de advertencia para ahorrar tiempo
+ text_html: Opcional. Puede usar sintaxis de publicaciones. Puede añadir configuraciones predefinidas de advertencia para ahorrar tiempo
type_html: Elige qué hacer con %{acct}
types:
disable: Evitar que el usuario utilice su cuenta, pero no eliminar ni ocultar sus contenidos.
@@ -34,7 +35,7 @@ es-MX:
ends_at: Opcional. El anuncio desaparecerá automáticamente en este momento
scheduled_at: Dejar en blanco para publicar el anuncio inmediatamente
starts_at: Opcional. En caso de que su anuncio esté vinculado a un intervalo de tiempo específico
- text: Puedes usar la sintaxis toot. Por favor ten en cuenta el espacio que ocupará el anuncio en la pantalla del usuario
+ text: Puedes usar la sintaxis de publicaciones. Por favor ten en cuenta el espacio que ocupará el anuncio en la pantalla del usuario
appeal:
text: Sólo puede apelar una amonestación a la vez
defaults:
@@ -48,12 +49,12 @@ es-MX:
email: Se le enviará un correo de confirmación
header: WEBP, PNG, GIF o JPG. Máximo %{size}. Será escalado a %{dimensions}px
inbox_url: Copia la URL de la página principal del relés que quieres utilizar
- irreversible: Los toots filtrados desaparecerán irreversiblemente, incluso si este filtro es eliminado más adelante
+ irreversible: Las publicaciones filtradas desaparecerán irreversiblemente, incluso si este filtro es eliminado más adelante
locale: El idioma de la interfaz de usuario, correos y notificaciones push
password: Utilice al menos 8 caracteres
- phrase: Se aplicará sin importar las mayúsculas o los avisos de contenido de un toot
+ phrase: Se aplicará sin importar las mayúsculas o los avisos de contenido de una publicación
scopes: Qué APIs de la aplicación tendrán acceso. Si seleccionas el alcance de nivel mas alto, no necesitas seleccionar las individuales.
- setting_aggregate_reblogs: No mostrar nuevos retoots para los toots que han sido recientemente retooteados (sólo afecta a los retoots recibidos recientemente)
+ setting_aggregate_reblogs: No mostrar nuevos impulsos para las publicaciones que han sido recientemente impulsadas (sólo afecta a las publicaciones recibidas recientemente)
setting_always_send_emails: Normalmente las notificaciones por correo electrónico no se enviarán cuando estés usando Mastodon activamente
setting_default_sensitive: El contenido multimedia sensible está oculto por defecto y puede ser mostrado con un click
setting_display_media_default: Ocultar contenido multimedia marcado como sensible
@@ -83,7 +84,7 @@ es-MX:
closed_registrations_message: Mostrado cuando los registros están cerrados
content_cache_retention_period: Todas las publicaciones de otros servidores (incluso impulsos y respuestas) se eliminarán después del número de días especificado, sin tener en cuenta la interacción del usuario local con esos mensajes. Esto incluye mensajes donde un usuario local los ha marcado como marcadores o favoritos. Las menciones privadas entre usuarios de diferentes instancias también se perderán sin posibilidad de recuperación. El uso de esta configuración está destinado a instancias de propósito especial, y rompe muchas expectativas de los usuarios cuando se implementa para un uso de propósito general.
custom_css: Puedes aplicar estilos personalizados a la versión web de Mastodon.
- favicon: WEBP, PNG, GIF o JPG. Reemplaza el favicon predeterminado de Mastodon con un icono personalizado.
+ favicon: WEBP, PNG, GIF o JPG. Reemplaza el icono predeterminado de Mastodon con un icono personalizado.
mascot: Reemplaza la ilustración en la interfaz web avanzada.
media_cache_retention_period: Los archivos multimedia de las publicaciones creadas por usuarios remotos se almacenan en caché en tu servidor. Cuando se establece un valor positivo, estos archivos se eliminarán después del número especificado de días. Si los datos multimedia se solicitan después de eliminarse, se volverán a descargar, si el contenido fuente todavía está disponible. Debido a restricciones en la frecuencia con la que las tarjetas de previsualización de enlaces realizan peticiones a sitios de terceros, se recomienda establecer este valor a al menos 14 días, o las tarjetas de previsualización de enlaces no se actualizarán bajo demanda antes de ese momento.
peers_api_enabled: Una lista de nombres de dominio que este servidor ha encontrado en el fediverso. Aquí no se incluye ningún dato sobre si usted federa con un servidor determinado, sólo que su servidor lo sabe. Esto es utilizado por los servicios que recopilan estadísticas sobre la federación en un sentido general.
@@ -129,8 +130,8 @@ es-MX:
tag:
name: Sólo se puede cambiar el cajón de las letras, por ejemplo, para que sea más legible
user:
- chosen_languages: Cuando se marca, solo se mostrarán los toots en los idiomas seleccionados en los timelines públicos
- role: El rol controla qué permisos tiene el usuario
+ chosen_languages: Cuando se marca, solo se mostrarán las publicaciones en los idiomas seleccionados en las líneas de tiempo públicas
+ role: El rol controla qué permisos tiene el usuario.
user_role:
color: Color que se utilizará para el rol a lo largo de la interfaz de usuario, como RGB en formato hexadecimal
highlighted: Esto hace que el rol sea públicamente visible
@@ -143,6 +144,7 @@ es-MX:
url: Donde los eventos serán enviados
labels:
account:
+ attribution_domains_as_text: Solo permitir sitios web específicos
discoverable: Destacar el perfil y las publicaciones en el algoritmo de descubrimiento
fields:
name: Etiqueta
@@ -158,7 +160,7 @@ es-MX:
text: Texto predefinido
title: Título
admin_account_action:
- include_statuses: Incluir en el correo electrónico a los toots denunciados
+ include_statuses: Incluir en el correo electrónico a las publicaciones denunciadas
send_email_notification: Notificar al usuario por correo electrónico
text: Aviso personalizado
type: Acción
@@ -203,21 +205,21 @@ es-MX:
password: Contraseña
phrase: Palabra clave o frase
setting_advanced_layout: Habilitar interfaz web avanzada
- setting_aggregate_reblogs: Agrupar retoots en las líneas de tiempo
+ setting_aggregate_reblogs: Agrupar impulsos en las líneas de tiempo
setting_always_send_emails: Enviar siempre notificaciones por correo
setting_auto_play_gif: Reproducir automáticamente los GIFs animados
- setting_boost_modal: Mostrar ventana de confirmación antes de un Retoot
+ setting_boost_modal: Mostrar ventana de confirmación antes de impulsar
setting_default_language: Idioma de publicación
setting_default_privacy: Privacidad de publicaciones
setting_default_sensitive: Marcar siempre imágenes como sensibles
- setting_delete_modal: Mostrar diálogo de confirmación antes de borrar un toot
+ setting_delete_modal: Mostrar diálogo de confirmación antes de borrar una publicación
setting_disable_hover_cards: Desactivar vista previa del perfil al pasar el cursor
setting_disable_swiping: Deshabilitar movimientos de deslizamiento
setting_display_media: Visualización multimedia
setting_display_media_default: Por defecto
setting_display_media_hide_all: Ocultar todo
setting_display_media_show_all: Mostrar todo
- setting_expand_spoilers: Siempre expandir los toots marcados con advertencias de contenido
+ setting_expand_spoilers: Siempre expandir las publicaciones marcadas con advertencias de contenido
setting_hide_network: Ocultar tu red
setting_reduce_motion: Reducir el movimiento de las animaciones
setting_system_font_ui: Utilizar la tipografía por defecto del sistema
diff --git a/config/locales/simple_form.es.yml b/config/locales/simple_form.es.yml
index 02f0562d28..b22701aae7 100644
--- a/config/locales/simple_form.es.yml
+++ b/config/locales/simple_form.es.yml
@@ -3,6 +3,7 @@ es:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protege frente atribuciones fraudulentas.
discoverable: Tu perfil y publicaciones públicas pueden ser destacadas o recomendadas en varias áreas de Mastodon y tu perfil puede ser sugerido a otros usuarios.
display_name: Tu nombre completo o tu apodo.
fields: Tu carta de presentación, pronombres, edad, lo que quieras.
@@ -130,7 +131,7 @@ es:
name: Sólo se puede cambiar el cajón de las letras, por ejemplo, para que sea más legible
user:
chosen_languages: Cuando se marca, solo se mostrarán las publicaciones en los idiomas seleccionados en las líneas de tiempo públicas
- role: El rol controla qué permisos tiene el usuario
+ role: El rol controla qué permisos tiene el usuario.
user_role:
color: Color que se utilizará para el rol a lo largo de la interfaz de usuario, como RGB en formato hexadecimal
highlighted: Esto hace que el rol sea públicamente visible
@@ -143,6 +144,7 @@ es:
url: Donde los eventos serán enviados
labels:
account:
+ attribution_domains_as_text: Solo permitir sitios web específicos
discoverable: Destacar perfil y publicaciones en algoritmos de descubrimiento
fields:
name: Etiqueta
diff --git a/config/locales/simple_form.et.yml b/config/locales/simple_form.et.yml
index 74660921d2..8d045cfcfe 100644
--- a/config/locales/simple_form.et.yml
+++ b/config/locales/simple_form.et.yml
@@ -3,6 +3,7 @@ et:
simple_form:
hints:
account:
+ attribution_domains_as_text: Kaitseb valede omistuste eest.
discoverable: Su profiili ja avalikke postitusi võidakse Mastodoni erinevates piirkondades esile tõsta või soovitada ning su profiili soovitada teistele kasutajatele.
display_name: Su täisnimi või naljanimi.
fields: Su koduleht, sugu, vanus. Mistahes, mida soovid.
@@ -130,7 +131,7 @@ et:
name: Saad muuta ainult tähtede suurtähelisust, näiteks selleks, et muuta seda loetavamaks
user:
chosen_languages: Keelte valimisel näidatakse avalikel ajajoontel ainult neis keeltes postitusi
- role: See roll kontrollib, millised õigused kasutajal on
+ role: Rollid määravad, millised õigused kasutajal on.
user_role:
color: Rolli tähistamise värvus üle kasutajaliidese, RGB 16nd-formaadis
highlighted: Teeb rolli avalikult nähtavaks
@@ -143,6 +144,7 @@ et:
url: Kuhu sündmused saadetakse
labels:
account:
+ attribution_domains_as_text: Luba vaid kindlad veebilehed
discoverable: Tõsta postitused ja profiil avastamise algoritmides esile
fields:
name: Nimetus
@@ -211,6 +213,7 @@ et:
setting_default_privacy: Postituse nähtavus
setting_default_sensitive: Alati märgista meedia tundlikuks
setting_delete_modal: Näita kinnitusdialoogi enne postituse kustutamist
+ setting_disable_hover_cards: Keela profiili eelvaade kui hõljutada
setting_disable_swiping: Keela pühkimisliigutused
setting_display_media: Meedia kuvarežiim
setting_display_media_default: Vaikimisi
@@ -242,11 +245,13 @@ et:
warn: Peida hoiatusega
form_admin_settings:
activity_api_enabled: Avalda agregeeritud statistika kasutajaaktiivsuse kohta API-s
+ app_icon: Äpi ikoon
backups_retention_period: Kasutajate arhiivi talletusperiood
bootstrap_timeline_accounts: Alati soovita neid kontosid uutele kasutajatele
closed_registrations_message: Kohandatud teade, kui liitumine pole võimalik
content_cache_retention_period: Kaugsisu säilitamise aeg
custom_css: Kohandatud CSS
+ favicon: Favicon
mascot: Kohandatud maskott (kunagine)
media_cache_retention_period: Meediapuhvri talletusperiood
peers_api_enabled: Avalda avastatud serverite loetelu API kaudu
@@ -311,6 +316,7 @@ et:
listable: Luba sellel sildil ilmuda profiilide kataloogis
name: Silt
trendable: Luba sellel sildil trendida
+ usable: Luba seda märksõna postitustes kasutada lokaalselt
user:
role: Roll
time_zone: Ajavöönd
diff --git a/config/locales/simple_form.eu.yml b/config/locales/simple_form.eu.yml
index c7e2667cad..7647e187ec 100644
--- a/config/locales/simple_form.eu.yml
+++ b/config/locales/simple_form.eu.yml
@@ -130,7 +130,6 @@ eu:
name: Letrak maiuskula/minuskulara aldatu ditzakezu besterik ez, adibidez irakurterrazago egiteko
user:
chosen_languages: Markatzean, hautatutako hizkuntzetan dauden tutak besterik ez dira erakutsiko.
- role: Rolak erabiltzaileak dituen baimenak kontrolatzen ditu
user_role:
color: Rolarentzat erabiltzaile interfazean erabiliko den kolorea, formatu hamaseitarreko RGB bezala
highlighted: Honek rola publikoki ikusgai jartzen du
diff --git a/config/locales/simple_form.fa.yml b/config/locales/simple_form.fa.yml
index 0610f7fced..bbb0523b17 100644
--- a/config/locales/simple_form.fa.yml
+++ b/config/locales/simple_form.fa.yml
@@ -188,6 +188,7 @@ fa:
setting_default_privacy: حریم خصوصی نوشتهها
setting_default_sensitive: همیشه تصاویر را به عنوان حساس علامت بزن
setting_delete_modal: نمایش پیغام تأیید پیش از پاک کردن یک نوشته
+ setting_disable_hover_cards: از کار انداختن پیشنمایش نمایه هنگام رفتن رویش
setting_disable_swiping: از کار انداختن حرکتهای کشیدنی
setting_display_media: نمایش عکس و ویدیو
setting_display_media_default: پیشفرض
@@ -219,6 +220,7 @@ fa:
warn: نهفتن با هشدار
form_admin_settings:
activity_api_enabled: انتشار آمار تجمیعی دربارهٔ فعالیت کاربران در API
+ app_icon: نقشک کاره
backups_retention_period: دورهٔ نگهداری بایگانی کاربری
bootstrap_timeline_accounts: پیشنهاد همیشگی این حسابها به کاربران جدید
closed_registrations_message: پیام سفارشی هنگام در دسترس نبودن ثبتنامها
@@ -278,6 +280,7 @@ fa:
patch: آگاهی برای بهروز رسانیهای رفع اشکال
trending_tag: روند جدیدی نیازمند بازبینی است
rule:
+ hint: اطّلاعات اضافی
text: قانون
settings:
indexable: بودن صفحهٔ نمایه در نتیجههای جستوجو
@@ -286,6 +289,7 @@ fa:
listable: اجازه به این برچسب برای ظاهر شدن در جستوجوها و پیشنهادها
name: برچسب
trendable: بگذارید که این برچسب در موضوعات پرطرفدار دیده شود
+ usable: اجازه به فرستهها برای استفتاده از این برچسب به صورت محلی
user:
role: نقش
time_zone: منطقهٔ زمانی
diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml
index c20ff9fa5f..5c85367dbb 100644
--- a/config/locales/simple_form.fi.yml
+++ b/config/locales/simple_form.fi.yml
@@ -3,6 +3,7 @@ fi:
simple_form:
hints:
account:
+ attribution_domains_as_text: Suojaa vääriltä tunnustuksilta.
discoverable: Julkisia julkaisujasi ja profiiliasi voidaan pitää esillä tai suositella Mastodonin eri alueilla ja profiiliasi voidaan ehdottaa toisille käyttäjille.
display_name: Koko nimesi tai lempinimesi.
fields: Verkkosivustosi, pronominisi, ikäsi ja mitä ikinä haluatkaan ilmoittaa.
@@ -130,7 +131,7 @@ fi:
name: Voit esimerkiksi vaihtaa suur- ja pienaakkosten kesken helppolukuistaaksesi tekstiäsi
user:
chosen_languages: Jos valitset kieliä oheisesta luettelosta, vain niidenkieliset julkaisut näkyvät sinulle julkisilla aikajanoilla
- role: Rooli vaikuttaa käyttäjän käyttöoikeuksiin
+ role: Rooli määrää, millaiset käyttöoikeudet käyttäjällä on.
user_role:
color: Väri, jota käytetään roolille kaikkialla käyttöliittymässä, RGB-heksadesimaalimuodossa
highlighted: Tämä tekee roolista julkisesti näkyvän
@@ -143,6 +144,7 @@ fi:
url: Mihin tapahtumat lähetetään
labels:
account:
+ attribution_domains_as_text: Salli vain tietyt verkkosivustot
discoverable: Pidä profiiliasi ja julkaisujasi esillä löytämisalgoritmeissa
fields:
name: Nimike
diff --git a/config/locales/simple_form.fo.yml b/config/locales/simple_form.fo.yml
index ecd8402680..afcd3b39ac 100644
--- a/config/locales/simple_form.fo.yml
+++ b/config/locales/simple_form.fo.yml
@@ -3,6 +3,7 @@ fo:
simple_form:
hints:
account:
+ attribution_domains_as_text: Verjir fyri følskum ískoytum.
discoverable: Tínir almennu postar og tín vangi kunnu vera drigin fram og viðmæld ymsa staðni í Mastodon og vangin hjá tær kann vera viðmæltur øðrum brúkarum.
display_name: Títt fulla navn og títt stuttliga navn.
fields: Heimasíðan hjá tær, fornøvn, aldur ella hvat tú vil.
@@ -130,7 +131,7 @@ fo:
name: Tú kanst einans broyta millum stórar og smáar stavir, til dømis fyri at gera tað meira lesiligt
user:
chosen_languages: Tá hetta er valt, verða einans postar í valdum málum vístir á almennum tíðarlinjum
- role: Leikluturin stýrir, hvørji loyvir brúkarin hevur
+ role: Leikluturin stýrir hvørji rættindi, brúkarin hevur.
user_role:
color: Litur, sum leikluturin hevur í øllum brúkaramarkamótinum, sum RGB og upplýst sum sekstandatal
highlighted: Hetta ger, at leikluturin er alment sjónligur
@@ -143,6 +144,7 @@ fo:
url: Hvar hendingar verða sendar til
labels:
account:
+ attribution_domains_as_text: Loyv einans ávísum heimasíðum
discoverable: Framheva vanga og postar í uppdagingar-algoritmum
fields:
name: Spjaldur
diff --git a/config/locales/simple_form.fr-CA.yml b/config/locales/simple_form.fr-CA.yml
index 4e67db2db6..90a268f411 100644
--- a/config/locales/simple_form.fr-CA.yml
+++ b/config/locales/simple_form.fr-CA.yml
@@ -3,6 +3,7 @@ fr-CA:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protège contre les fausses attributions.
discoverable: Vos messages publics et votre profil peuvent être mis en avant ou recommandés dans diverses parties de Mastodon et votre profil peut être suggéré à d’autres utilisateurs.
display_name: Votre nom complet ou votre nom cool.
fields: Votre page d'accueil, pronoms, âge, tout ce que vous voulez.
@@ -77,11 +78,15 @@ fr-CA:
warn: Cacher le contenu filtré derrière un avertissement mentionnant le nom du filtre
form_admin_settings:
activity_api_enabled: Nombre de messages publiés localement, de comptes actifs et de nouvelles inscriptions par tranche hebdomadaire
+ app_icon: WEBP, PNG, GIF ou JPG. Remplace la favicon Mastodon par défaut avec une icône personnalisée.
backups_retention_period: Les utilisateur·rice·s ont la possibilité de générer des archives de leurs messages pour les télécharger plus tard. Lorsqu'elles sont définies à une valeur positive, ces archives seront automatiquement supprimées de votre stockage après le nombre de jours spécifié.
bootstrap_timeline_accounts: Ces comptes seront épinglés en tête de liste des recommandations pour les nouveaux utilisateurs.
closed_registrations_message: Affiché lorsque les inscriptions sont fermées
+ content_cache_retention_period: Tous les messages provenant d'autres serveurs (y compris les partages et les réponses) seront supprimés passé le nombre de jours spécifié, sans tenir compte de l'interaction de l'utilisateur·rice local·e avec ces messages. Cela inclut les messages qu'un·e utilisateur·rice aurait marqué comme signets ou comme favoris. Les mentions privées entre utilisateur·rice·s de différentes instances seront également perdues et impossibles à restaurer. L'utilisation de ce paramètre est destinée à des instances spécifiques et contrevient à de nombreuses attentes des utilisateurs lorsqu'elle est appliquée à des fins d'utilisation ordinaires.
custom_css: Vous pouvez appliquer des styles personnalisés sur la version Web de Mastodon.
+ favicon: WEBP, PNG, GIF ou JPG. Remplace la favicon Mastodon par défaut avec une icône personnalisée.
mascot: Remplace l'illustration dans l'interface Web avancée.
+ media_cache_retention_period: Les fichiers médias des messages publiés par des utilisateurs distants sont mis en cache sur votre serveur. Lorsque cette valeur est positive, les médias sont supprimés au terme du nombre de jours spécifié. Si les données des médias sont demandées après leur suppression, elles seront téléchargées à nouveau, dans la mesure où le contenu source est toujours disponible. En raison des restrictions concernant la fréquence à laquelle les cartes de prévisualisation des liens interrogent des sites tiers, il est recommandé de fixer cette valeur à au moins 14 jours, faute de quoi les cartes de prévisualisation des liens ne seront pas mises à jour à la demande avant cette échéance.
peers_api_enabled: Une liste de noms de domaine que ce serveur a rencontrés dans le fédiverse. Aucune donnée indiquant si vous vous fédérez ou non avec un serveur particulier n'est incluse ici, seulement l'information que votre serveur connaît un autre serveur. Cette option est utilisée par les services qui collectent des statistiques sur la fédération en général.
profile_directory: L'annuaire des profils répertorie tous les utilisateurs qui ont opté pour être découverts.
require_invite_text: Lorsque les inscriptions nécessitent une approbation manuelle, rendre le texte de l’invitation "Pourquoi voulez-vous vous inscrire ?" obligatoire plutôt que facultatif
@@ -126,7 +131,7 @@ fr-CA:
name: Vous ne pouvez modifier que la casse des lettres, par exemple, pour le rendre plus lisible
user:
chosen_languages: Lorsque coché, seuls les messages dans les langues sélectionnées seront affichés sur les fils publics
- role: Le rôle définit quelles autorisations a l'utilisateur⋅rice
+ role: Le rôle définit quelles autorisations a l'utilisateur⋅rice.
user_role:
color: Couleur à attribuer au rôle dans l'interface, au format hexadécimal RVB
highlighted: Cela rend le rôle visible publiquement
@@ -139,6 +144,7 @@ fr-CA:
url: Là où les événements seront envoyés
labels:
account:
+ attribution_domains_as_text: Autoriser uniquement des sites Web spécifiques
discoverable: Autoriser des algorithmes de découverte à mettre en avant votre profil et vos messages
fields:
name: Étiquette
diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml
index a9df5375f3..370f5c1e46 100644
--- a/config/locales/simple_form.fr.yml
+++ b/config/locales/simple_form.fr.yml
@@ -3,6 +3,7 @@ fr:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protège contre les fausses attributions.
discoverable: Vos messages publics et votre profil peuvent être mis en avant ou recommandés dans diverses parties de Mastodon et votre profil peut être suggéré à d’autres utilisateurs.
display_name: Votre nom complet ou votre nom rigolo.
fields: Votre page personnelle, vos pronoms, votre âge, ce que vous voulez.
@@ -77,11 +78,15 @@ fr:
warn: Cacher le contenu filtré derrière un avertissement mentionnant le nom du filtre
form_admin_settings:
activity_api_enabled: Nombre de messages publiés localement, de comptes actifs et de nouvelles inscriptions par tranche hebdomadaire
+ app_icon: WEBP, PNG, GIF ou JPG. Remplace la favicon Mastodon par défaut avec une icône personnalisée.
backups_retention_period: Les utilisateur·rice·s ont la possibilité de générer des archives de leurs messages pour les télécharger plus tard. Lorsqu'elles sont définies à une valeur positive, ces archives seront automatiquement supprimées de votre stockage après le nombre de jours spécifié.
bootstrap_timeline_accounts: Ces comptes seront épinglés en tête de liste des recommandations pour les nouveaux utilisateurs.
closed_registrations_message: Affiché lorsque les inscriptions sont fermées
+ content_cache_retention_period: Tous les messages provenant d'autres serveurs (y compris les partages et les réponses) seront supprimés passé le nombre de jours spécifié, sans tenir compte de l'interaction de l'utilisateur·rice local·e avec ces messages. Cela inclut les messages qu'un·e utilisateur·rice aurait marqué comme signets ou comme favoris. Les mentions privées entre utilisateur·rice·s de différentes instances seront également perdues et impossibles à restaurer. L'utilisation de ce paramètre est destinée à des instances spécifiques et contrevient à de nombreuses attentes des utilisateurs lorsqu'elle est appliquée à des fins d'utilisation ordinaires.
custom_css: Vous pouvez appliquer des styles personnalisés sur la version Web de Mastodon.
+ favicon: WEBP, PNG, GIF ou JPG. Remplace la favicon Mastodon par défaut avec une icône personnalisée.
mascot: Remplace l'illustration dans l'interface Web avancée.
+ media_cache_retention_period: Les fichiers médias des messages publiés par des utilisateurs distants sont mis en cache sur votre serveur. Lorsque cette valeur est positive, les médias sont supprimés au terme du nombre de jours spécifié. Si les données des médias sont demandées après leur suppression, elles seront téléchargées à nouveau, dans la mesure où le contenu source est toujours disponible. En raison des restrictions concernant la fréquence à laquelle les cartes de prévisualisation des liens interrogent des sites tiers, il est recommandé de fixer cette valeur à au moins 14 jours, faute de quoi les cartes de prévisualisation des liens ne seront pas mises à jour à la demande avant cette échéance.
peers_api_enabled: Une liste de noms de domaine que ce serveur a rencontrés dans le fédiverse. Aucune donnée indiquant si vous vous fédérez ou non avec un serveur particulier n'est incluse ici, seulement l'information que votre serveur connaît un autre serveur. Cette option est utilisée par les services qui collectent des statistiques sur la fédération en général.
profile_directory: L'annuaire des profils répertorie tous les comptes qui choisi d'être découvrables.
require_invite_text: Lorsque les inscriptions nécessitent une approbation manuelle, rendre le texte de l’invitation "Pourquoi voulez-vous vous inscrire ?" obligatoire plutôt que facultatif
@@ -126,7 +131,7 @@ fr:
name: Vous ne pouvez modifier que la casse des lettres, par exemple, pour le rendre plus lisible
user:
chosen_languages: Lorsque coché, seuls les messages dans les langues sélectionnées seront affichés sur les fils publics
- role: Le rôle définit quelles autorisations a l'utilisateur⋅rice
+ role: Le rôle définit quelles autorisations a l'utilisateur⋅rice.
user_role:
color: Couleur à attribuer au rôle dans l'interface, au format hexadécimal RVB
highlighted: Cela rend le rôle visible publiquement
@@ -139,6 +144,7 @@ fr:
url: Là où les événements seront envoyés
labels:
account:
+ attribution_domains_as_text: Autoriser uniquement des sites Web spécifiques
discoverable: Autoriser des algorithmes de découverte à mettre en avant votre profil et vos messages
fields:
name: Étiquette
diff --git a/config/locales/simple_form.fy.yml b/config/locales/simple_form.fy.yml
index bde97237f6..e7deca9460 100644
--- a/config/locales/simple_form.fy.yml
+++ b/config/locales/simple_form.fy.yml
@@ -130,7 +130,6 @@ fy:
name: Jo kinne elk wurd mei in haadletter begjinne, om sa bygelyks de tekst mear lêsber te meitsjen
user:
chosen_languages: Allinnich berjochten yn de selektearre talen wurde op de iepenbiere tiidline toand
- role: De rol bepaalt hokker rjochten in brûker hat
user_role:
color: Kleur dy’t brûkt wurdt foar de rol yn de UI, as RGB yn heksadesimaal formaat
highlighted: Dit makket de rol iepenbier sichtber
@@ -314,6 +313,7 @@ fy:
listable: Tastean dat dizze hashtag yn sykopdrachten en oanrekommandaasjes te sjen is
name: Hashtag
trendable: Goedkarre dat dizze hashtag ûnder trends te sjen is
+ usable: Berjochten tastean dizze hashtag lokaal te brûken
user:
role: Rol
time_zone: Tiidsône
diff --git a/config/locales/simple_form.ga.yml b/config/locales/simple_form.ga.yml
index 15ea3094b2..772f996ca6 100644
--- a/config/locales/simple_form.ga.yml
+++ b/config/locales/simple_form.ga.yml
@@ -3,6 +3,7 @@ ga:
simple_form:
hints:
account:
+ attribution_domains_as_text: Cosnaíonn sé ó sannadh bréagach.
discoverable: Seans go mbeidh do phostálacha poiblí agus do phróifíl le feiceáil nó molta i réimsí éagsúla de Mastodon agus is féidir do phróifíl a mholadh d’úsáideoirí eile.
display_name: D'ainm iomlán nó d'ainm spraoi.
fields: Do leathanach baile, forainmneacha, aois, rud ar bith is mian leat.
@@ -130,7 +131,7 @@ ga:
name: Ní féidir leat ach cásáil na litreacha a athrú, mar shampla, chun é a dhéanamh níos inléite
user:
chosen_languages: Nuair a dhéantar iad a sheiceáil, ní thaispeánfar ach postálacha i dteangacha roghnaithe in amlínte poiblí
- role: Rialaíonn an ról na ceadanna atá ag an úsáideoir
+ role: Rialaíonn an ról na ceadanna atá ag an úsáideoir.
user_role:
color: Dath le húsáid don ról ar fud an Chomhéadain, mar RGB i bhformáid heicsidheachúlach
highlighted: Déanann sé seo an ról le feiceáil go poiblí
@@ -143,6 +144,7 @@ ga:
url: An áit a seolfar imeachtaí chuig
labels:
account:
+ attribution_domains_as_text: Ná ceadaigh ach láithreáin ghréasáin ar leith
discoverable: Próifíl gné agus postálacha in halgartaim fionnachtana
fields:
name: Lipéad
diff --git a/config/locales/simple_form.gd.yml b/config/locales/simple_form.gd.yml
index 4375feb492..de585c7a21 100644
--- a/config/locales/simple_form.gd.yml
+++ b/config/locales/simple_form.gd.yml
@@ -3,6 +3,7 @@ gd:
simple_form:
hints:
account:
+ attribution_domains_as_text: Dìonadh seo o bhuaidh-aithrisean cearra.
discoverable: Dh’fhaoidte gun dèid na postaichean poblach ’s a’ phròifil agad a bhrosnachadh no a mholadh ann an caochladh roinnean de Mhastodon agus gun dèid a’ phròifil agad a mholadh do chàch.
display_name: D’ ainm slàn no spòrsail.
fields: An duilleag-dhachaigh agad, roimhearan, aois, rud sam bith a thogras tu.
@@ -130,7 +131,7 @@ gd:
name: Mar eisimpleir, ’s urrainn dhut measgachadh de litrichean mòra ’s beaga a chleachdadh ach an gabh a leughadh nas fhasa
user:
chosen_languages: Nuair a bhios cromag ris, cha nochd ach postaichean sna cànain a thagh thu air loidhnichean-ama poblach
- role: Stiùiridh an dreuchd dè na ceadan a bhios aig cleachdaiche
+ role: Stiùiridh an dreuchd dè na ceadan a bhios aig cleachdaiche.
user_role:
color: An datha a bhios air an dreuchd air feadh na h-eadar-aghaidh, ’na RGB san fhòrmat sia-dheicheach
highlighted: Le seo, chithear an dreuchd gu poblach
@@ -143,6 +144,7 @@ gd:
url: Far an dèid na tachartasan a chur
labels:
account:
+ attribution_domains_as_text: Na ceadaich ach làraichean-lìnn sònraichte
discoverable: Brosnaich a’ phròifil is postaichean agad sna h-algairimean rùrachaidh
fields:
name: Leubail
diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml
index aff8a95f0d..cddeae5cee 100644
--- a/config/locales/simple_form.gl.yml
+++ b/config/locales/simple_form.gl.yml
@@ -3,6 +3,7 @@ gl:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protéxete de falsas atribucións.
discoverable: As túas publicacións públicas e perfil poden mostrarse ou recomendarse en varias zonas de Mastodon e o teu perfil ser suxerido a outras usuarias.
display_name: O teu nome completo ou un nome divertido.
fields: Páxina web, pronome, idade, o que ti queiras.
@@ -130,7 +131,7 @@ gl:
name: Só podes cambiar maiús/minúsculas, por exemplo, mellorar a lexibilidade
user:
chosen_languages: Se ten marca, só as publicacións nos idiomas seleccionados serán mostrados en cronoloxías públicas
- role: O control dos roles adxudicados ás usuarias
+ role: Os roles establecen os permisos que ten a usuaria.
user_role:
color: Cor que se usará para o rol a través da IU, como RGB en formato hex
highlighted: Isto fai o rol publicamente visible
@@ -143,6 +144,7 @@ gl:
url: A onde se enviarán os eventos
labels:
account:
+ attribution_domains_as_text: Permitir só os sitios web indicados
discoverable: Perfil destacado e publicacións nos algoritmos de descubrimento
fields:
name: Etiqueta
diff --git a/config/locales/simple_form.he.yml b/config/locales/simple_form.he.yml
index 9e2becc52f..1feebb0d69 100644
--- a/config/locales/simple_form.he.yml
+++ b/config/locales/simple_form.he.yml
@@ -3,6 +3,7 @@ he:
simple_form:
hints:
account:
+ attribution_domains_as_text: הגנה מייחוסים שקריים.
discoverable: הפוסטים והפרופיל שלך עשויים להיות מוצגים או מומלצים באזורים שונים באתר וייתכן שהפרופיל שלך יוצע למשתמשים אחרים.
display_name: שמך המלא או שם הכיף שלך.
fields: עמוד הבית שלך, לשון הפנייה, גיל, וכל מידע אחר לפי העדפתך האישית.
@@ -130,7 +131,7 @@ he:
name: ניתן רק להחליף בין אותיות קטנות וגדולות, למשל כדי לשפר את הקריאות
user:
chosen_languages: אם פעיל, רק הודעות בשפות הנבחרות יוצגו לפידים הפומביים
- role: התפקיד שולט על אילו הרשאות יש למשתמש
+ role: התפקיד שולט על אילו הרשאות יש למשתמש.
user_role:
color: צבע לתפקיד בממשק המשתמש, כ RGB בפורמט הקסדצימלי
highlighted: מאפשר נראות ציבורית של התפקיד
@@ -143,6 +144,7 @@ he:
url: היעד שאליו יישלחו אירועים
labels:
account:
+ attribution_domains_as_text: רק אתרים מסויימים יאושרו
discoverable: הצג משתמש ופוסטים בעמוד התגליות
fields:
name: תווית
diff --git a/config/locales/simple_form.hu.yml b/config/locales/simple_form.hu.yml
index 512e13d3af..383bdd0760 100644
--- a/config/locales/simple_form.hu.yml
+++ b/config/locales/simple_form.hu.yml
@@ -3,6 +3,7 @@ hu:
simple_form:
hints:
account:
+ attribution_domains_as_text: Megvéd a hamis forrásmegjelölésektől.
discoverable: A nyilvános bejegyzéseid és a profilod kiemelhető vagy ajánlható a Mastodon különböző területein, a profilod más felhasználóknak is javasolható.
display_name: Teljes neved vagy vicces neved.
fields: Weboldalad, megszólításaid, korod, bármi, amit szeretnél.
@@ -130,7 +131,7 @@ hu:
name: Csak a kis/nagybetűséget változtathatod meg, pl. hogy olvashatóbb legyen
user:
chosen_languages: Ha aktív, csak a kiválasztott nyelvű bejegyzések jelennek majd meg a nyilvános idővonalon
- role: A szerep szabályozza, hogy a felhasználó milyen jogosultságokkal rendelkezik
+ role: A szerep szabályozza, hogy a felhasználó milyen jogosultságokkal rendelkezik.
user_role:
color: A szerephez használandó szín mindenhol a felhasználói felületen, hexa RGB formátumban
highlighted: Ez nyilvánosan láthatóvá teszi a szerepet
@@ -143,6 +144,7 @@ hu:
url: Ahová az eseményket küldjük
labels:
account:
+ attribution_domains_as_text: Csak meghatározott weboldalak engedélyezése
discoverable: Profil és bejegyzések szerepeltetése a felfedezési algoritmusokban
fields:
name: Címke
diff --git a/config/locales/simple_form.ia.yml b/config/locales/simple_form.ia.yml
index 00226aee90..dc5aad57ae 100644
--- a/config/locales/simple_form.ia.yml
+++ b/config/locales/simple_form.ia.yml
@@ -130,7 +130,6 @@ ia:
name: Tu pote solmente cambiar le litteras inter majusculas e minusculas, per exemplo, pro render lo plus legibile
user:
chosen_languages: Si marcate, solo le messages in le linguas seligite sera monstrate in chronologias public
- role: Le rolo controla que permissos ha le usator
user_role:
color: Color a esser usate pro le rolo in omne parte del UI, como RGB in formato hexadecimal
highlighted: Iste rende le rolo publicamente visibile
@@ -143,6 +142,7 @@ ia:
url: Ubi le eventos essera inviate
labels:
account:
+ attribution_domains_as_text: Solmente permitter sitos web specific
discoverable: Evidentiar le profilo e messages in le algorithmos de discoperta
fields:
name: Etiquetta
@@ -313,6 +313,7 @@ ia:
listable: Permitter a iste hashtag apparer in le recercas e suggestiones
name: Hashtag
trendable: Permitter a iste hashtag de sub tendentias
+ usable: Permitter al messages usar iste hashtag localmente
user:
role: Rolo
time_zone: Fuso horari
diff --git a/config/locales/simple_form.id.yml b/config/locales/simple_form.id.yml
index 99f4372cc1..0bc98874eb 100644
--- a/config/locales/simple_form.id.yml
+++ b/config/locales/simple_form.id.yml
@@ -107,7 +107,6 @@ id:
name: Anda hanya dapat mengubahnya ke huruf kecil/besar, misalnya, agar lebih mudah dibaca
user:
chosen_languages: Ketika dicentang, hanya toot dalam bahasa yang dipilih yang akan ditampilkan di linimasa publik
- role: Peran mengatur izin apa yang dimiliki pengguna
user_role:
color: Warna yang digunakan untuk peran di antarmuka pengguna, sebagai RGB dalam format hex
highlighted: Ini membuat peran terlihat secara publik
diff --git a/config/locales/simple_form.ie.yml b/config/locales/simple_form.ie.yml
index 0828139a43..771e341616 100644
--- a/config/locales/simple_form.ie.yml
+++ b/config/locales/simple_form.ie.yml
@@ -130,7 +130,6 @@ ie:
name: Tu posse changear solmen li minu/majusculitá del lítteres, por exemple, por far it plu leibil
user:
chosen_languages: Quande selectet, solmen postas in ti lingues va esser monstrat in public témpor-lineas
- role: Permissiones de usator decidet per su rol
user_role:
color: Color a usar por li rol tra li UI, quam RGB (rubi-verdi-blu) in formate hex
highlighted: Va far li rol publicmen visibil
diff --git a/config/locales/simple_form.io.yml b/config/locales/simple_form.io.yml
index 4de7475b2e..fe8243b0e9 100644
--- a/config/locales/simple_form.io.yml
+++ b/config/locales/simple_form.io.yml
@@ -122,7 +122,6 @@ io:
name: Vu povas nur chanjar literkaso, por exemplo, por kauzigar lu divenar plu lektebla
user:
chosen_languages: Kande marketigesis, nur posti en selektesis lingui montresos en publika tempolinei
- role: Rolo dominacas permisi quon uzanto havas
user_role:
color: Koloro quo uzesas por rolo en tota UI, quale RGB kun hexformato
highlighted: Co kauzigas rolo divenar publike videbla
diff --git a/config/locales/simple_form.is.yml b/config/locales/simple_form.is.yml
index a7e2083f4d..6f3a4fe8a5 100644
--- a/config/locales/simple_form.is.yml
+++ b/config/locales/simple_form.is.yml
@@ -3,6 +3,7 @@ is:
simple_form:
hints:
account:
+ attribution_domains_as_text: Ver fyrir fölskum tilvísunum í höfunda.
discoverable: Opinberar færslur og notandasnið þitt geta birst eða verið mælt með á hinum ýmsu svæðum í Mastodon auk þess sem hægt er að mæla með þér við aðra notendur.
display_name: Fullt nafn þitt eða eitthvað til gamans.
fields: Heimasíðan þín, fornöfn, aldur eða eitthvað sem þú vilt koma á framfæri.
@@ -130,7 +131,7 @@ is:
name: Þú getur aðeins breytt stafstöði mill há-/lágstafa, til gæmis til að gera þetta læsilegra
user:
chosen_languages: Þegar merkt er við þetta, birtast einungis færslur á völdum tungumálum á opinberum tímalínum
- role: Hlutverk stýrir hvaða heimildir notandinn hefur
+ role: Hlutverk stýrir hvaða heimildir notandinn hefur.
user_role:
color: Litur sem notaður er fyrir hlutverkið allsstaðar í viðmótinu, sem RGB-gildi á hex-sniði
highlighted: Þetta gerir hlutverk sýnilegt opinberlega
@@ -143,6 +144,7 @@ is:
url: Hvert atburðir verða sendir
labels:
account:
+ attribution_domains_as_text: Einungis leyfa tiltekin vefsvæði
discoverable: Hafa notandasnið og færslur með í reikniritum leitar
fields:
name: Skýring
diff --git a/config/locales/simple_form.it.yml b/config/locales/simple_form.it.yml
index ea175e2bf5..7ed4c0d004 100644
--- a/config/locales/simple_form.it.yml
+++ b/config/locales/simple_form.it.yml
@@ -3,6 +3,7 @@ it:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protegge da false attribuzioni.
discoverable: I tuoi post pubblici e il tuo profilo potrebbero essere presenti o consigliati in varie aree di Mastodon e il tuo profilo potrebbe essere suggerito ad altri utenti.
display_name: Il tuo nome completo o il tuo soprannome.
fields: La tua homepage, i pronomi, l'età, tutto quello che vuoi.
@@ -130,7 +131,7 @@ it:
name: Puoi cambiare solo il minuscolo/maiuscolo delle lettere, ad esempio, per renderlo più leggibile
user:
chosen_languages: Quando una o più lingue sono contrassegnate, nelle timeline pubbliche vengono mostrati solo i toot nelle lingue selezionate
- role: Il ruolo controlla quali permessi ha l'utente
+ role: Il ruolo controlla quali permessi ha l'utente.
user_role:
color: Colore da usare per il ruolo in tutta l'UI, come RGB in formato esadecimale
highlighted: Rende il ruolo visibile
@@ -143,6 +144,7 @@ it:
url: Dove gli eventi saranno inviati
labels:
account:
+ attribution_domains_as_text: Consenti solo siti web specifici
discoverable: Include il profilo e i post negli algoritmi di scoperta
fields:
name: Etichetta
diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml
index 7f4a9daeff..2c1bd6a084 100644
--- a/config/locales/simple_form.ja.yml
+++ b/config/locales/simple_form.ja.yml
@@ -130,7 +130,6 @@ ja:
name: 視認性向上などのためにアルファベット大文字小文字の変更のみ行うことができます
user:
chosen_languages: 選択すると、選択した言語の投稿のみが公開タイムラインに表示されるようになります
- role: このロールはユーザーが持つ権限を管理します
user_role:
color: UI 全体でロールの表示に使用される色(16進数RGB形式)
highlighted: これによりロールが公開されます。
@@ -314,6 +313,7 @@ ja:
listable: 検索とディレクトリへの使用を許可する
name: ハッシュタグ
trendable: トレンドへの表示を許可する
+ usable: このサーバーのユーザーがタグをつけて投稿することを許可する
user:
role: ロール
time_zone: タイムゾーン
diff --git a/config/locales/simple_form.kab.yml b/config/locales/simple_form.kab.yml
index 16f4bdd416..f390d42132 100644
--- a/config/locales/simple_form.kab.yml
+++ b/config/locales/simple_form.kab.yml
@@ -20,7 +20,8 @@ kab:
irreversible: Tisuffaɣ i tessazedgeḍ ad ttwakksent i lebda, ula ma tekkseḍ imsizdeg-nni ar zdat
locale: Tutlayt n ugrudem, imaylen d walɣuten yettudemren
password: Seqdec ma drus 8 n yisekkilen
- setting_display_media_default: Ffer teywalt yettwacreḍ d tanafrit
+ setting_always_send_emails: S umata, ilɣa s yimayl ur d-ttwaceyyεen ara mi ara tesseqdaceḍ Mastodon s wudem urmid
+ setting_display_media_default: Ffer imidyaten yettwacreḍ d infariyen
setting_display_media_hide_all: Ffer yal tikkelt akk taywalt
setting_display_media_show_all: Ffer yal tikkelt teywalt yettwacreḍ d tanafrit
username: Tzemreḍ ad tesqedceḍ isekkilen, uṭṭunen akked yijerriden n wadda
@@ -84,13 +85,14 @@ kab:
password: Awal uffir
phrase: Awal n tsarut neɣ tafyirt
setting_advanced_layout: Rmed agrudem n web leqqayen
- setting_default_language: Tutlayt n tira
- setting_default_privacy: Tabaḍnit n tira
+ setting_always_send_emails: Dima ttazen-d ilɣa s yimayl
+ setting_default_language: Tutlayt n usuffeɣ
+ setting_default_privacy: Tabaḍnit n usuffeɣ
setting_display_media: Askanay n imidyaten
setting_display_media_default: Akk-a kan
setting_display_media_hide_all: Ffer-iten akk
setting_display_media_show_all: Sken-iten-id akk
- setting_hide_network: Ffer azetta-k·m
+ setting_hide_network: Ffer azetta-k·m inmetti
setting_theme: Asental n wesmel
setting_use_pending_items: Askar aleɣwayan
sign_in_token_attempt: Tangalt n tɣellist
diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml
index 5fa3aee6c4..a649b4ec5a 100644
--- a/config/locales/simple_form.ko.yml
+++ b/config/locales/simple_form.ko.yml
@@ -3,6 +3,7 @@ ko:
simple_form:
hints:
account:
+ attribution_domains_as_text: 가짜 기여로부터 보호합니다.
discoverable: 내 공개 게시물과 프로필이 마스토돈의 다양한 추천 기능에 나타날 수 있고 프로필이 다른 사용자에게 제안될 수 있습니다
display_name: 진짜 이름 또는 재미난 이름.
fields: 홈페이지, 호칭, 나이, 뭐든지 적고 싶은 것들.
@@ -130,7 +131,7 @@ ko:
name: 읽기 쉽게하기 위한 글자의 대소문자만 변경할 수 있습니다.
user:
chosen_languages: 체크하면, 선택 된 언어로 작성된 게시물들만 공개 타임라인에 보여집니다
- role: 역할은 사용자가 어떤 권한을 가지게 될 지 결정합니다
+ role: 역할은 사용자가 어떤 권한을 가지게 될 지 결정합니다.
user_role:
color: 색상은 사용자 인터페이스에서 역할을 나타내기 위해 사용되며, RGB 16진수 형식입니다
highlighted: 이 역할이 공개적으로 보이도록 설정합니다
@@ -143,6 +144,7 @@ ko:
url: 이벤트가 어디로 전송될 지
labels:
account:
+ attribution_domains_as_text: 특정 웹사이트만 허용하기
discoverable: 발견하기 알고리즘에 프로필과 게시물을 추천하기
fields:
name: 라벨
diff --git a/config/locales/simple_form.ku.yml b/config/locales/simple_form.ku.yml
index 96e047d937..db50384c7e 100644
--- a/config/locales/simple_form.ku.yml
+++ b/config/locales/simple_form.ku.yml
@@ -106,7 +106,6 @@ ku:
name: Tu dikarî tenê mezinahiya tîpan biguherînî bo mînak, da ku ew bêtir were xwendin
user:
chosen_languages: Dema were nîşankirin, tenê parvekirinên bi zimanên hilbijartî dê di rêzikên giştî de werin nîşandan
- role: Rola kîjan mafdayînên bikarhêner heye kontrol dike
user_role:
color: Renga ku were bikaranîn ji bo rola li seranserê navrûya bikarhêneriyê, wekî RGB di forma hex
highlighted: Ev rola xwe ji raya giştî re xuya dike
diff --git a/config/locales/simple_form.lad.yml b/config/locales/simple_form.lad.yml
index f7093ff73b..94e387107a 100644
--- a/config/locales/simple_form.lad.yml
+++ b/config/locales/simple_form.lad.yml
@@ -125,7 +125,7 @@ lad:
name: Solo se puede trokar la kapitalizasyon de las letras, por enshemplo, para ke sea mas meldable
user:
chosen_languages: Kuando se marka, solo se amostraran las publikasyones en las linguas eskojidas en las linyas de tiempo publikas
- role: El rolo kontrola kualos permisos tiene el utilizador
+ role: El rolo kontrola kualos permisos tiene el utilizador.
user_role:
color: Color ke se utilizara para el rolo a lo largo de la enterfaz de utilizador, komo RGB en formato heksadesimal
highlighted: Esto faze ke el rolo sea publikamente visible
@@ -237,6 +237,7 @@ lad:
warn: Eskonde kon una avertensya
form_admin_settings:
activity_api_enabled: Publika estatistikas adjustadas sovre la aktivita del utilizador kon la API
+ app_icon: Ikono de aplikasyon
backups_retention_period: Periodo de retensyon de la dosya de utilizador
bootstrap_timeline_accounts: Rekomenda siempre estos kuentos a muevos utilizadores
closed_registrations_message: Mesaj personalizado kuando las enrejistrasyones no estan desponivles
diff --git a/config/locales/simple_form.lt.yml b/config/locales/simple_form.lt.yml
index 02f0360938..5d3a02993b 100644
--- a/config/locales/simple_form.lt.yml
+++ b/config/locales/simple_form.lt.yml
@@ -3,6 +3,7 @@ lt:
simple_form:
hints:
account:
+ attribution_domains_as_text: Apsaugo nuo klaidingų atributų.
discoverable: Tavo vieši įrašai ir profilis gali būti rodomi arba rekomenduojami įvairiose Mastodon vietose, o profilis gali būti siūlomas kitiems naudotojams.
display_name: Tavo pilnas vardas arba smagus vardas.
fields: Tavo pagrindinis puslapis, įvardžiai, amžius, bet kas, ko tik nori.
@@ -89,6 +90,8 @@ lt:
timeline_preview: Atsijungę lankytojai galės naršyti naujausius viešus įrašus, esančius serveryje.
trends: Trendai rodo, kurios įrašai, saitažodžiai ir naujienų istorijos tavo serveryje sulaukia didžiausio susidomėjimo.
trends_as_landing_page: Rodyti tendencingą turinį atsijungusiems naudotojams ir lankytojams vietoj šio serverio aprašymo. Reikia, kad tendencijos būtų įjungtos.
+ imports:
+ data: CSV failas, eksportuotas iš kito „Mastodon“ serverio.
invite_request:
text: Tai padės mums peržiūrėti tavo paraišką
rule:
@@ -101,9 +104,10 @@ lt:
show_application: Neatsižvelgiant į tai, visada galėsi matyti, kuri programėlė paskelbė tavo įrašą.
user:
chosen_languages: Kai pažymėta, viešose laiko skalėse bus rodomi tik įrašai pasirinktomis kalbomis.
- role: Vaidmuo valdo, kokius leidimus naudotojas (-a) turi
+ role: Vaidmuo valdo, kokius leidimus naudotojas turi.
labels:
account:
+ attribution_domains_as_text: Leisti tik konkrečias svetaines
discoverable: Rekomenduoti profilį ir įrašus į atradimo algoritmus
indexable: Įtraukti viešus įrašus į paieškos rezultatus
show_collections: Rodyti sekimus ir sekėjus profilyje
diff --git a/config/locales/simple_form.lv.yml b/config/locales/simple_form.lv.yml
index eedae998e4..ed27e08bc3 100644
--- a/config/locales/simple_form.lv.yml
+++ b/config/locales/simple_form.lv.yml
@@ -3,6 +3,7 @@ lv:
simple_form:
hints:
account:
+ attribution_domains_as_text: Aizsargā no nepatiesa attiecinājuma.
discoverable: Tavas publiskās ziņas un profils var tikt piedāvāti vai ieteikti dažādās Mastodon vietās, un tavs profils var tikt ieteikts citiem lietotājiem.
display_name: Tavs pilnais vārds vai tavs joku vārds.
fields: Tava mājas lapa, vietniekvārdi, vecums, viss, ko vēlies.
@@ -128,7 +129,7 @@ lv:
name: Tu vari mainīt tikai burtu lielumu, piemēram, lai tie būtu vieglāk lasāmi
user:
chosen_languages: Ja ieķeksēts, publiskos laika grafikos tiks parādītas tikai ziņas noteiktajās valodās
- role: Loma kontrolē, kādas atļaujas ir lietotājam
+ role: Loma nosaka, kādas lietotājam ir atļaujas.
user_role:
color: Krāsa, kas jāizmanto lomai visā lietotāja saskarnē, kā RGB hex formātā
highlighted: Tas padara lomu publiski redzamu
@@ -141,6 +142,7 @@ lv:
url: Kur notikumi tiks nosūtīti
labels:
account:
+ attribution_domains_as_text: Ļaut tikai noteiktas tīmekļvietnes
discoverable: Funkcijas profils un ziņas atklāšanas algoritmos
fields:
name: Marķējums
@@ -209,6 +211,7 @@ lv:
setting_default_privacy: Publicēšanas privātums
setting_default_sensitive: Atļaut atzīmēt multividi kā sensitīvu
setting_delete_modal: Parādīt apstiprinājuma dialogu pirms ziņas dzēšanas
+ setting_disable_hover_cards: Atspējot profila priekšskatījumu pēc kursora novietošanas
setting_disable_swiping: Atspējot vilkšanas kustības
setting_display_media: Multivides rādīšana
setting_display_media_default: Noklusējums
@@ -240,11 +243,13 @@ lv:
warn: Paslēpt ar brīdinājumu
form_admin_settings:
activity_api_enabled: Publicējiet apkopotu statistiku par lietotāju darbībām API
+ app_icon: Lietotnes ikona
backups_retention_period: Lietotāja arhīva glabāšanas periods
bootstrap_timeline_accounts: Vienmēr iesaki šos kontus jaunajiem lietotājiem
closed_registrations_message: Pielāgots ziņojums, ja reģistrēšanās nav pieejama
content_cache_retention_period: Attālā satura paturēšanas laika posms
custom_css: Pielāgots CSS
+ favicon: Favikona
mascot: Pielāgots talismans (mantots)
media_cache_retention_period: Multivides kešatmiņas saglabāšanas periods
peers_api_enabled: Publicēt API atklāto serveru sarakstu
@@ -309,6 +314,7 @@ lv:
listable: Atļaut šim tēmturim parādīties meklējumos un ieteikumos
name: Tēmturis
trendable: Atļaut šim tēmturim parādīties zem tendencēm
+ usable: Ļaut ierakstos vietēji izmantot šo tēmturi
user:
role: Loma
time_zone: Laika josla
diff --git a/config/locales/simple_form.ms.yml b/config/locales/simple_form.ms.yml
index da00e2dc2b..ecc3588d67 100644
--- a/config/locales/simple_form.ms.yml
+++ b/config/locales/simple_form.ms.yml
@@ -122,7 +122,6 @@ ms:
name: Anda hanya boleh menukar selongsong huruf, sebagai contoh, untuk menjadikannya lebih mudah dibaca
user:
chosen_languages: Apabila disemak, hanya siaran dalam bahasa terpilih akan dipaparkan dalam garis masa awam
- role: Peranan mengawal kebenaran yang dimiliki oleh pengguna
user_role:
color: Warna yang akan digunakan untuk peranan ini dalam seluruh UI, sebagai RGB dalam format hex
highlighted: Ini menjadikan peranan ini dipaparkan secara umum
diff --git a/config/locales/simple_form.my.yml b/config/locales/simple_form.my.yml
index a44635edd4..abcb11bdaa 100644
--- a/config/locales/simple_form.my.yml
+++ b/config/locales/simple_form.my.yml
@@ -122,7 +122,6 @@ my:
name: ဥပမာအားဖြင့် စာလုံးများကို ပိုမိုဖတ်ရှုနိုင်စေရန်မှာ သင်သာ ပြောင်းလဲနိုင်သည်။
user:
chosen_languages: အမှန်ခြစ် ရွေးချယ်ထားသော ဘာသာစကားများဖြင့်သာ ပို့စ်များကို အများမြင်စာမျက်နှာတွင် ပြသပါမည်
- role: အသုံးပြုသူ၏ ခွင့်ပြုချက်ကဏ္ဍကို ထိန်းချုပ်ထားသည်
user_role:
color: hex ပုံစံ RGB အဖြစ် UI တစ်လျှောက်လုံး အခန်းကဏ္ဍအတွက် အသုံးပြုရမည့်အရောင်
highlighted: ယင်းက အခန်းကဏ္ဍကို အများမြင်အောင် ဖွင့်ပေးထားသည်။
diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml
index 91ee9bc3e3..7f8aaa01d6 100644
--- a/config/locales/simple_form.nl.yml
+++ b/config/locales/simple_form.nl.yml
@@ -3,6 +3,7 @@ nl:
simple_form:
hints:
account:
+ attribution_domains_as_text: Beschermt tegen onjuiste attributies.
discoverable: Jouw openbare berichten kunnen worden uitgelicht op verschillende plekken binnen Mastodon en jouw account kan worden aanbevolen aan andere gebruikers.
display_name: Jouw volledige naam of een leuke bijnaam.
fields: Jouw website, persoonlijke voornaamwoorden, leeftijd, alles wat je maar kwijt wilt.
@@ -130,7 +131,7 @@ nl:
name: Je kunt elk woord met een hoofdletter beginnen, om zo bijvoorbeeld de tekst leesbaarder te maken
user:
chosen_languages: Alleen berichten in de aangevinkte talen worden op de openbare tijdlijnen getoond
- role: De rol bepaalt welke rechten een gebruiker heeft
+ role: De rol bepaalt welke rechten de gebruiker heeft.
user_role:
color: Kleur die gebruikt wordt voor de rol in de UI, als RGB in hexadecimale formaat
highlighted: Dit maakt de rol openbaar zichtbaar
@@ -143,6 +144,7 @@ nl:
url: Waar gebeurtenissen naartoe worden verzonden
labels:
account:
+ attribution_domains_as_text: Alleen bepaalde websites toestaan
discoverable: Jouw account en berichten laten uitlichten door Mastodon
fields:
name: Label
diff --git a/config/locales/simple_form.nn.yml b/config/locales/simple_form.nn.yml
index c4d4438b94..ddd5ed8995 100644
--- a/config/locales/simple_form.nn.yml
+++ b/config/locales/simple_form.nn.yml
@@ -3,6 +3,7 @@ nn:
simple_form:
hints:
account:
+ attribution_domains_as_text: Vernar mot falske krediteringar.
discoverable: Dei offentlege innlegga dine og profilen din kan dukka opp i tilrådingar på ulike stader på Mastodon, og profilen din kan bli føreslegen for andre folk.
display_name: Ditt fulle namn eller ditt tøysenamn.
fields: Heimesida di, pronomen, alder, eller kva du måtte ynskje.
@@ -130,7 +131,7 @@ nn:
name: Du kan berre endra bruken av store/små bokstavar, t. d. for å gjera det meir leseleg
user:
chosen_languages: Når merka vil berre tuta på dei valde språka synast på offentlege tidsliner
- role: Rolla kontrollerer kva tilgangar brukaren har
+ role: Rolla kontrollerer kva løyve brukaren har.
user_role:
color: Fargen som skal nyttast for denne rolla i heile brukargrensesnittet, som RGB i hex-format
highlighted: Dette gjer rolla synleg offentleg
@@ -143,6 +144,7 @@ nn:
url: Kvar hendingar skal sendast
labels:
account:
+ attribution_domains_as_text: Tillat berre visse nettstader
discoverable: Ta med profilen og innlegga i oppdagingsalgoritmar
fields:
name: Merkelapp
diff --git a/config/locales/simple_form.no.yml b/config/locales/simple_form.no.yml
index 82de0adb7b..73ba17cd4c 100644
--- a/config/locales/simple_form.no.yml
+++ b/config/locales/simple_form.no.yml
@@ -124,7 +124,6 @@
name: Du kan bare forandre bruken av store/små bokstaver, f.eks. for å gjøre det mer lesbart
user:
chosen_languages: Hvis noen av dem er valgt, vil kun innlegg i de valgte språkene bli vist i de offentlige tidslinjene
- role: Rollekontroller som bestemmer rettigheter brukeren har
user_role:
color: Farge som skal brukes for rollen gjennom hele UI, som RGB i hex-format
highlighted: Dette gjør rollen offentlig synlig
diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml
index 1a9051b951..bb404e56c9 100644
--- a/config/locales/simple_form.pl.yml
+++ b/config/locales/simple_form.pl.yml
@@ -3,6 +3,7 @@ pl:
simple_form:
hints:
account:
+ attribution_domains_as_text: Chroni przed fałszywym przypisaniem wpisów.
discoverable: Twój profil i publiczne wpisy mogą być promowane lub polecane na Mastodonie i twój profil może być sugerowany innym użytkownikom.
display_name: Twoje imię lub pseudonim.
fields: Co ci się tylko podoba – twoja strona domowa, zaimki, wiek…
@@ -130,7 +131,7 @@ pl:
name: Możesz zmieniać tylko wielkość liter, np. aby były bardziej widoczne
user:
chosen_languages: Jeżeli zaznaczone, tylko wpisy w wybranych językach będą wyświetlane na publicznych osiach czasu
- role: Rola kontroluje uprawnienia użytkownika
+ role: Rola kontroluje uprawnienia użytkownika.
user_role:
color: Kolor używany dla roli w całym interfejsie użytkownika, wyrażony jako RGB w formacie szesnastkowym
highlighted: To sprawia, że rola jest widoczna publicznie
@@ -143,6 +144,7 @@ pl:
url: Dokąd będą wysłane zdarzenia
labels:
account:
+ attribution_domains_as_text: Zezwól tylko na konkretne strony
discoverable: Udostępniaj profil i wpisy funkcjom odkrywania
fields:
name: Nazwa
diff --git a/config/locales/simple_form.pt-BR.yml b/config/locales/simple_form.pt-BR.yml
index fc3c09cf1d..96bc219e8e 100644
--- a/config/locales/simple_form.pt-BR.yml
+++ b/config/locales/simple_form.pt-BR.yml
@@ -3,6 +3,7 @@ pt-BR:
simple_form:
hints:
account:
+ attribution_domains_as_text: Protege de atribuições falsas.
discoverable: Suas publicações e perfil públicos podem ser destaques ou recomendados em várias áreas de Mastodon, e seu perfil pode ser sugerido a outros usuários.
display_name: Seu nome completo ou apelido.
fields: Sua página inicial, pronomes, idade ou qualquer coisa que quiser.
@@ -130,7 +131,7 @@ pt-BR:
name: Você pode mudar a capitalização das letras, por exemplo, para torná-la mais legível
user:
chosen_languages: Apenas as publicações dos idiomas selecionados serão exibidas nas linhas públicas
- role: O cargo controla quais permissões o usuário tem
+ role: A função controla quais permissões o usuário tem.
user_role:
color: Cor a ser usada para o cargo em toda a interface do usuário, como RGB no formato hexadecimal
highlighted: Isso torna o cargo publicamente visível
@@ -143,6 +144,7 @@ pt-BR:
url: Aonde os eventos serão enviados
labels:
account:
+ attribution_domains_as_text: Permitir apenas sites específicos
discoverable: Destacar perfil e publicações nos algoritmos de descoberta
fields:
name: Rótulo
@@ -211,6 +213,7 @@ pt-BR:
setting_default_privacy: Privacidade dos toots
setting_default_sensitive: Sempre marcar mídia como sensível
setting_delete_modal: Solicitar confirmação antes de excluir toot
+ setting_disable_hover_cards: Desativar visualização de perfil ao passar o mouse por cima
setting_disable_swiping: Desabilitar movimentos deslizantes
setting_display_media: Exibição das mídias
setting_display_media_default: Padrão
@@ -242,11 +245,13 @@ pt-BR:
warn: Ocultar com um aviso
form_admin_settings:
activity_api_enabled: Publicar estatísticas agregadas sobre atividade de usuários na API
+ app_icon: Ícone do aplicativo
backups_retention_period: Período de retenção do arquivo de usuário
bootstrap_timeline_accounts: Sempre recomendar essas contas para novos usuários
closed_registrations_message: Mensagem personalizada quando inscrições não estão disponíveis
content_cache_retention_period: Período de retenção de conteúdo remoto
custom_css: CSS personalizável
+ favicon: Favicon
mascot: Mascote personalizado (legado)
media_cache_retention_period: Período de retenção do cachê de mídia
peers_api_enabled: Publicar lista de instâncias de servidor descobertas na API
@@ -311,6 +316,7 @@ pt-BR:
listable: Permitir que esta hashtag apareça em pesquisas e sugestões
name: Hashtag
trendable: Permitir que esta hashtag fique em alta
+ usable: Permitir que as publicações usem esta hashtag localmente
user:
role: Cargo
time_zone: Fuso horário
diff --git a/config/locales/simple_form.pt-PT.yml b/config/locales/simple_form.pt-PT.yml
index a76076a5cb..3b606df032 100644
--- a/config/locales/simple_form.pt-PT.yml
+++ b/config/locales/simple_form.pt-PT.yml
@@ -52,7 +52,7 @@ pt-PT:
locale: O idioma da interface de utilizador, e-mails e notificações push
password: Use pelo menos 8 caracteres
phrase: Será correspondido independentemente da capitalização ou do aviso de conteúdo duma publicação
- scopes: Quais as API a que será concedido acesso. Se escolher uma abrangência de nível superior, não precisará de as seleccionar individualmente.
+ scopes: Quais as API a que a aplicação terá permissão para aceder. Se selecionar um âmbito de nível superior, não precisa de selecionar âmbitos individuais.
setting_aggregate_reblogs: Não mostrar novos reforços de publicações recentemente reforçadas (só afecta publicações acabadas de reforçar)
setting_always_send_emails: Normalmente as notificações por e-mail não serão enviadas quando estiver a utilizar ativamente o Mastodon
setting_default_sensitive: Media problemática oculta por padrão, pode ser revelada com um clique
@@ -77,11 +77,11 @@ pt-PT:
warn: Ocultar o conteúdo filtrado por trás de um aviso mencionando o título do filtro
form_admin_settings:
activity_api_enabled: Contagem, em blocos semanais, de publicações locais, utilizadores ativos e novos registos
- app_icon: WEBP, PNG, GIF ou JPG. Substitui o ícone padrão do aplicativo em dispositivos móveis por um ícone personalizado.
+ app_icon: WEBP, PNG, GIF ou JPG. Substitui o ícone padrão da aplicação em dispositivos móveis por um ícone personalizado.
backups_retention_period: Os utilizadores têm a possibilidade de gerar arquivos das suas mensagens para descarregar mais tarde. Quando definido para um valor positivo, estes arquivos serão automaticamente eliminados do seu armazenamento após o número de dias especificado.
bootstrap_timeline_accounts: Estas contas serão destacadas no topo das recomendações aos novos utilizadores.
closed_registrations_message: Apresentado quando as inscrições estiverem encerradas
- content_cache_retention_period: Todas as publicações de outros servidores (incluindo boosts e respostas) serão eliminadas após o número de dias especificado, independentemente de qualquer interação do utilizador local com essas publicações. Isto inclui publicações em que um utilizador local as tenha marcado como favoritas ou adicionado aos items salvos. As menções privadas entre utilizadores de instâncias diferentes também se perderão e serão impossíveis de restaurar. A utilização desta definição destina-se a instâncias para fins especiais e quebra muitas expectativas dos utilizadores quando implementada para utilização geral.
+ content_cache_retention_period: Todas as publicações de outros servidores (incluindo boosts e respostas) serão eliminadas após o número de dias especificado, independentemente de qualquer interação do utilizador local com essas publicações. Isto inclui publicações em que um utilizador local as tenha marcado ou favoritado. As menções privadas entre utilizadores de instâncias diferentes também se perderão e serão impossíveis de restaurar. A utilização desta definição destina-se a instâncias para fins especiais e quebra muitas expectativas dos utilizadores quando implementada para utilização geral.
custom_css: Pode aplicar estilos personalizados na versão web do Mastodon.
favicon: WEBP, PNG, GIF ou JPG. Substitui o ícone de favorito padrão do Mastodon por um ícone personalizado.
mascot: Sobrepõe-se à ilustração na interface web avançada.
@@ -99,9 +99,9 @@ pt-PT:
theme: Tema que os visitantes e os novos utilizadores veem.
thumbnail: Uma imagem de cerca de 2:1, apresentada ao lado da informação do seu servidor.
timeline_preview: Os visitantes sem sessão iniciada poderão consultar as publicações públicas mais recentes disponíveis no servidor.
- trendable_by_default: Ignorar a revisão manual do conteúdo em alta. Elementos em avulso poderão ainda assim ser retirados das tendências mesmo após a sua apresentação.
- trends: As publicações em alta mostram quais as publicações, etiquetas e notícias que estão a ganhar destaque no seu servidor.
- trends_as_landing_page: Mostrar conteúdo de tendências para usuários logados e visitantes em vez de uma descrição deste servidor. Requer que as tendências sejam ativadas.
+ trendable_by_default: Ignorar a revisão manual do conteúdo de tendências. Os itens individuais ainda podem ser removidos das tendências após a apresentação.
+ trends: As tendências mostram quais as publicações, etiquetas e notícias que estão a ganhar destaque no seu servidor.
+ trends_as_landing_page: Mostrar conteúdo de tendências a utilizadores e visitantes com sessão terminada em vez de uma descrição deste servidor. Requer que as tendências estejam ativadas.
form_challenge:
current_password: Está a entrar numa área segura
imports:
@@ -129,14 +129,14 @@ pt-PT:
tag:
name: Só pode alterar a capitalização das letras, por exemplo, para torná-las mais legíveis
user:
- chosen_languages: Quando seleccionado, só serão mostradas nas cronologias públicas as publicações nos idiomas escolhidos
- role: A função controla que permissões o utilizador tem
+ chosen_languages: Quando selecionado, só serão mostradas nas cronologias públicas as publicações nos idiomas escolhidos
+ role: A função controla as permissões que o utilizador tem.
user_role:
color: Cor a ser utilizada para a função em toda a interface de utilizador, como RGB no formato hexadecimal
highlighted: Isto torna a função visível publicamente
- name: Nome público do cargo, se este estiver definido para ser apresentada com um emblema
+ name: Nome público da função, se esta estiver definida para ser apresentada com um emblema
permissions_as_keys: Utilizadores com esta função terão acesso a...
- position: Cargos mais altos decidem a resolução de conflitos em certas situações. Certas ações só podem ser executadas em cargos com uma menor prioridade
+ position: Funções mais altas decidem a resolução de conflitos em certas situações. Certas ações só podem ser executadas com certas funções com uma menor prioridade
webhook:
events: Selecione os eventos a enviar
template: Componha o seu próprio conteúdo JSON utilizando a interpolação de variáveis. Deixar em branco para o JSON predefinido.
@@ -222,7 +222,7 @@ pt-PT:
setting_reduce_motion: Reduz movimento em animações
setting_system_font_ui: Usar o tipo de letra padrão do sistema
setting_theme: Tema do sítio
- setting_trends: Mostrar o que está hoje em alta
+ setting_trends: Mostrar as tendências de hoje
setting_unfollow_modal: Solicitar confirmação antes de deixar de seguir alguém
setting_use_blurhash: Mostrar gradientes coloridos para medias ocultas
setting_use_pending_items: Modo lento
@@ -253,7 +253,7 @@ pt-PT:
mascot: Mascote personalizada (legado)
media_cache_retention_period: Período de retenção de ficheiros de media em cache
peers_api_enabled: Publicar lista de servidores descobertos na API
- profile_directory: Habilitar diretório de perfis
+ profile_directory: Ativar o diretório de perfis
registrations_mode: Quem se pode inscrever
require_invite_text: Requerer uma razão para entrar
show_domain_blocks: Mostrar domínios bloqueados
@@ -268,8 +268,8 @@ pt-PT:
theme: Tema predefinido
thumbnail: Miniatura do servidor
timeline_preview: Permitir acesso não autenticado às cronologias públicas
- trendable_by_default: Permitir publicações em alta sem revisão prévia
- trends: Activar publicações em alta
+ trendable_by_default: Permitir tendências sem revisão prévia
+ trends: Ativar tendências
trends_as_landing_page: Usar tendências como página inicial
interactions:
must_be_follower: Bloquear notificações de não-seguidores
@@ -303,7 +303,7 @@ pt-PT:
label: Está disponível uma nova versão do Mastodon
none: Nunca notificar atualizações (não recomendado)
patch: Notificar sobre atualizações de correções de problemas
- trending_tag: Uma nova publicação em alta requer avaliação
+ trending_tag: Uma nova publicação em tendência requer revisão
rule:
hint: Informação Adicional
text: Regra
@@ -313,10 +313,10 @@ pt-PT:
tag:
listable: Permitir que esta etiqueta apareça em pesquisas e no diretório de perfis
name: Etiqueta
- trendable: Permitir que esta etiqueta apareça em alta
+ trendable: Permitir que esta etiqueta apareça nas tendências
usable: Permitir que as publicações usem esta hashtag localmente
user:
- role: Cargo
+ role: Função
time_zone: Fuso horário
user_role:
color: Cor do emblema
diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml
index 0f830174c8..3ff746451b 100644
--- a/config/locales/simple_form.ru.yml
+++ b/config/locales/simple_form.ru.yml
@@ -3,6 +3,7 @@ ru:
simple_form:
hints:
account:
+ attribution_domains_as_text: Защищает от ложных атрибуций.
discoverable: Ваши публичные сообщения и профиль могут быть показаны или рекомендованы в различных разделах Mastodon, и ваш профиль может быть предложен другим пользователям.
display_name: Ваше полное имя или псевдоним.
fields: Ваша домашняя страница, местоимения, возраст - все, что угодно.
@@ -77,11 +78,15 @@ ru:
warn: Скрыть отфильтрованный контент за предупреждением с указанием названия фильтра
form_admin_settings:
activity_api_enabled: Подсчёт количества локальных постов, активных пользователей и новых регистраций на еженедельной основе
+ app_icon: WEBP, PNG, GIF или JPG. Замените значок приложения по умолчанию на мобильных устройствах пользовательским значком.
backups_retention_period: Пользователи могут создавать архивы своих постов, чтобы потом их забрать. Если задать положительное значение, эти архивы автоматически удалятся с вашего хранилища через указанное число дней.
bootstrap_timeline_accounts: Эти аккаунты будут рекомендованы для подписки новым пользователям.
closed_registrations_message: Отображается, когда регистрация закрыта
+ content_cache_retention_period: Все сообщения с других серверов (включая бусты и ответы) будут удалены через указанное количество дней, независимо от того, как локальный пользователь взаимодействовал с этими сообщениями. Это касается и тех сообщений, которые локальный пользователь пометил в закладки или избранное. Приватные упоминания между пользователями из разных инстансов также будут потеряны и не смогут быть восстановлены. Использование этой настройки предназначено для экземпляров специального назначения и нарушает многие ожидания пользователей при использовании в общих целях.
custom_css: Вы можете применять пользовательские стили в веб-версии Mastodon.
+ favicon: WEBP, PNG, GIF или JPG. Заменяет стандартный фавикон Mastodon на собственный значок.
mascot: Заменяет иллюстрацию в расширенном веб-интерфейсе.
+ media_cache_retention_period: Медиафайлы из сообщений, сделанных удаленными пользователями, кэшируются на вашем сервере. При положительном значении медиафайлы будут удалены через указанное количество дней. Если медиаданные будут запрошены после удаления, они будут загружены повторно, если исходный контент все еще доступен. В связи с ограничениями на частоту опроса карточек предварительного просмотра ссылок на сторонних сайтах рекомендуется устанавливать значение не менее 14 дней, иначе карточки предварительного просмотра ссылок не будут обновляться по запросу до этого времени.
peers_api_enabled: Список доменных имен, с которыми сервер столкнулся в fediverse. Здесь нет данных о том, федерировались ли вы с данным сервером, только что ваш сервер знает об этом. Это используется службами, которые собирают статистику по федерации в общем смысле.
profile_directory: В каталоге профилей перечислены все пользователи, которые согласились быть доступными для обнаружения.
require_invite_text: Когда регистрация требует ручного одобрения, сделайте текстовый ввод "Почему вы хотите присоединиться?" обязательным, а не опциональным
@@ -114,6 +119,7 @@ ru:
sign_up_requires_approval: Новые регистрации потребуют вашего одобрения
severity: Выберите, что будет происходить с запросами с этого IP
rule:
+ hint: Необязательно. Предоставьте дополнительные сведения о правиле
text: Опишите правило или требование для пользователей на этом сервере. Постарайтесь сделать его коротким и простым
sessions:
otp: 'Введите код двухфакторной аутентификации, сгенерированный в мобильном приложении, или используйте один из ваших кодов восстановления:'
@@ -125,7 +131,7 @@ ru:
name: Вы можете изменить только регистр букв чтобы, например, сделать тег более читаемым
user:
chosen_languages: Если выбрано, то в публичных лентах будут показаны только посты на выбранных языках.
- role: Роль определяет, какие разрешения есть у пользователя
+ role: Роль определяет, какими правами обладает пользователь.
user_role:
color: Цвет, который будет использоваться для роли в интерфейсе (UI), как RGB в формате HEX
highlighted: Это действие сделает роль публичной
@@ -138,6 +144,7 @@ ru:
url: Куда события будут отправляться
labels:
account:
+ attribution_domains_as_text: Разрешить только определенные сайты
discoverable: Профиль и сообщения в алгоритмах обнаружения
fields:
name: Пункт
@@ -242,6 +249,7 @@ ru:
backups_retention_period: Период хранения архива пользователя
bootstrap_timeline_accounts: Всегда рекомендовать эти учетные записи новым пользователям
closed_registrations_message: Сообщение, когда регистрация недоступна
+ content_cache_retention_period: Период хранения удаленного содержимого
custom_css: Пользовательский CSS
favicon: Favicon
mascot: Пользовательский маскот (устаревшее)
diff --git a/config/locales/simple_form.sco.yml b/config/locales/simple_form.sco.yml
index 9fc6fd57db..2bc4f6a456 100644
--- a/config/locales/simple_form.sco.yml
+++ b/config/locales/simple_form.sco.yml
@@ -104,7 +104,6 @@ sco:
name: Ye kin ainly chynge the case o the letters, fir example, fir tae mak it mair readable
user:
chosen_languages: Whan ticked, ainly posts in selectit leids wull be displayit in public timelines
- role: The role controls whit permissions the uiser haes
user_role:
color: Colour tae be uised fir the role throuoot the UI, as RGB in hex format
highlighted: This maks the role visible publicly
diff --git a/config/locales/simple_form.sl.yml b/config/locales/simple_form.sl.yml
index bb16e56a0c..d1ae553c8c 100644
--- a/config/locales/simple_form.sl.yml
+++ b/config/locales/simple_form.sl.yml
@@ -130,7 +130,6 @@ sl:
name: Spremenite lahko le npr. velikost črk (velike/male), da je bolj berljivo
user:
chosen_languages: Ko je označeno, bodo v javnih časovnicah prikazane samo objave v izbranih jezikih
- role: Vloga nadzira, katere pravice ima uporabnik
user_role:
color: Barva, uporabljena za vlogo po celem up. vmesniku, podana v šestnajstiškem zapisu RGB
highlighted: S tem je vloga javno vidna
diff --git a/config/locales/simple_form.sq.yml b/config/locales/simple_form.sq.yml
index 8b00751d98..169f4a02de 100644
--- a/config/locales/simple_form.sq.yml
+++ b/config/locales/simple_form.sq.yml
@@ -3,6 +3,7 @@ sq:
simple_form:
hints:
account:
+ attribution_domains_as_text: Mbron nga atribuime të rreme.
discoverable: Postimet dhe profili juaj publik mund të shfaqen, ose rekomandohen në zona të ndryshme të Mastodon-it dhe profili juaj mund të sugjerohet përdoruesve të tjerë.
display_name: Emri juaj i plotë, ose emri juaj lojcak.
fields: Faqja juaj hyrëse, përemra, moshë, ç’të keni qejf.
@@ -130,7 +131,7 @@ sq:
name: Mund të ndryshoni shkronjat vetëm nga të mëdha në të vogla ose anasjelltas, për shembull, për t’i bërë më të lexueshme
user:
chosen_languages: Në iu vëntë shenjë, te rrjedha kohore publike do të shfaqen vetëm mesazhe në gjuhët e përzgjedhura
- role: Roli kontrollon cilat leje ka përdoruesi
+ role: Roli kontrollon cilat leje ka përdoruesi.
user_role:
color: Ngjyrë për t’u përdorur për rolin nëpër UI, si RGB në format gjashtëmbëdhjetësh
highlighted: Kjo e bën rolin të dukshëm publikisht
@@ -143,6 +144,7 @@ sq:
url: Ku do të dërgohen aktet
labels:
account:
+ attribution_domains_as_text: Lejo vetëm sajte specifikë
discoverable: Profilin dhe postimet bëji objekt të algoritmeve të zbulimit
fields:
name: Etiketë
diff --git a/config/locales/simple_form.sr-Latn.yml b/config/locales/simple_form.sr-Latn.yml
index 527c5e0a1f..1dec901340 100644
--- a/config/locales/simple_form.sr-Latn.yml
+++ b/config/locales/simple_form.sr-Latn.yml
@@ -130,7 +130,6 @@ sr-Latn:
name: Mogu se samo promeniti mala slova u velika ili obrnuto, na primer, da bi bilo čitljivije
user:
chosen_languages: Kada je označeno, objave u izabranim jezicima će biti prikazane na javnoj vremenskoj liniji
- role: Uloga kontroliše koje dozvole korisnik ima
user_role:
color: Boja koja će se koristiti za ulogu u celom korisničkom okruženju, kao RGB u heksadecimalnom formatu
highlighted: Ovo čini ulogu javno vidljivom
diff --git a/config/locales/simple_form.sr.yml b/config/locales/simple_form.sr.yml
index d541c0b49c..9566e09475 100644
--- a/config/locales/simple_form.sr.yml
+++ b/config/locales/simple_form.sr.yml
@@ -130,7 +130,6 @@ sr:
name: Могу се само променити мала слова у велика или обрнуто, на пример, да би било читљивије
user:
chosen_languages: Када је означено, објаве у изабраним језицима ће бити приказане на јавној временској линији
- role: Улога контролише које дозволе корисник има
user_role:
color: Боја која ће се користити за улогу у целом корисничком окружењу, као RGB у хексадецималном формату
highlighted: Ово чини улогу јавно видљивом
diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml
index 329cabf941..297e96a2bd 100644
--- a/config/locales/simple_form.sv.yml
+++ b/config/locales/simple_form.sv.yml
@@ -130,7 +130,7 @@ sv:
name: Du kan bara ändra skriftläget av bokstäverna, till exempel, för att göra det mer läsbart
user:
chosen_languages: Vid aktivering visas bara inlägg på dina valda språk i offentliga tidslinjer
- role: Rollen bestämmer vilka behörigheter användaren har
+ role: Rollen styr vilka behörigheter användaren har.
user_role:
color: Färgen som ska användas för rollen i användargränssnittet, som RGB i hex-format
highlighted: Detta gör rollen synlig offentligt
diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml
index 8bd782c140..1ecd672a97 100644
--- a/config/locales/simple_form.th.yml
+++ b/config/locales/simple_form.th.yml
@@ -3,6 +3,7 @@ th:
simple_form:
hints:
account:
+ attribution_domains_as_text: ปกป้องจากการระบุแหล่งที่มาที่ผิด
discoverable: อาจแสดงหรือแนะนำโพสต์และโปรไฟล์สาธารณะของคุณในพื้นที่ต่าง ๆ ของ Mastodon และอาจเสนอแนะโปรไฟล์ของคุณให้กับผู้ใช้อื่น ๆ
display_name: ชื่อเต็มของคุณหรือชื่อแบบสนุกสนานของคุณ
fields: หน้าแรก, สรรพนาม, อายุของคุณ สิ่งใดก็ตามที่คุณต้องการ
@@ -143,6 +144,7 @@ th:
url: ที่ซึ่งจะส่งเหตุการณ์ไปยัง
labels:
account:
+ attribution_domains_as_text: อนุญาตเฉพาะเว็บไซต์ที่เฉพาะเจาะจงเท่านั้น
discoverable: แสดงโปรไฟล์และโพสต์ในอัลกอริทึมการค้นพบ
fields:
name: ป้ายชื่อ
diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml
index c62be89b28..d90b97bf9b 100644
--- a/config/locales/simple_form.tr.yml
+++ b/config/locales/simple_form.tr.yml
@@ -3,6 +3,7 @@ tr:
simple_form:
hints:
account:
+ attribution_domains_as_text: Sahte atıflardan korur.
discoverable: Herkese açık gönderileriniz ve profiliniz Mastodon'un çeşitli kısımlarında öne çıkarılabilir veya önerilebilir ve profiliniz başka kullanıcılara önerilebilir.
display_name: Tam adınız veya kullanıcı adınız.
fields: Ana sayfanız, zamirleriniz, yaşınız, istediğiniz herhangi bir şey.
@@ -130,7 +131,7 @@ tr:
name: Harflerin, örneğin daha okunabilir yapmak için, sadece büyük/küçük harf durumlarını değiştirebilirsiniz
user:
chosen_languages: İşaretlendiğinde, yalnızca seçilen dillerdeki gönderiler genel zaman çizelgelerinde görüntülenir
- role: Rol, kullanıcıların sahip olduğu izinleri denetler
+ role: Rol, kullanıcıların sahip olduğu izinleri denetler.
user_role:
color: Arayüz boyunca rol için kullanılacak olan renk, hex biçiminde RGB
highlighted: Bu rolü herkese açık hale getirir
@@ -143,6 +144,7 @@ tr:
url: Olayların gönderileceği yer
labels:
account:
+ attribution_domains_as_text: Yalnızca belirli websitelerine izin ver
discoverable: Profil ve gönderileri keşif algoritmalarında kullan
fields:
name: Etiket
diff --git a/config/locales/simple_form.uk.yml b/config/locales/simple_form.uk.yml
index 1206714869..b584a6cada 100644
--- a/config/locales/simple_form.uk.yml
+++ b/config/locales/simple_form.uk.yml
@@ -3,6 +3,7 @@ uk:
simple_form:
hints:
account:
+ attribution_domains_as_text: Захищає від фальшивих атрибутів.
discoverable: Ваші дописи та профіль можуть бути рекомендовані в різних частинах Mastodon і ваш профіль може бути запропонований іншим користувачам.
display_name: Ваше повне ім'я або ваш псевдонім.
fields: Ваша домашня сторінка, займенники, вік, все, що вам заманеться.
@@ -85,7 +86,7 @@ uk:
custom_css: Ви можете застосувати користувацькі стилі у вебверсії Mastodon.
favicon: WEBP, PNG, GIF або JPG. Замінює стандартну піктограму Mastodon на власну.
mascot: Змінює ілюстрацію в розширеному вебінтерфейсі.
- media_cache_retention_period: Медіафайли з дописів віддалених користувачів кешуються на вашому сервері. Якщо встановлено додатне значення, медіа буде видалено через вказану кількість днів. Якщо медіа-дані будуть запитані після видалення, вони будуть завантажені повторно, якщо вихідний вміст все ще доступний. Через обмеження на частоту опитування карток попереднього перегляду посилань на сторонніх сайтах, рекомендується встановити це значення не менше 14 днів, інакше картки попереднього перегляду посилань не будуть оновлюватися на вимогу раніше цього часу.
+ media_cache_retention_period: Медіафайли з дописів віддалених користувачів кешуються на вашому сервері. Якщо встановлено додатне значення, медіа буде видалено через вказану кількість днів. Якщо медіадані будуть запитані після видалення, вони будуть завантажені повторно, якщо вихідний вміст все ще доступний. Через обмеження на частоту опитування карток попереднього перегляду посилань на сторонніх сайтах, рекомендується встановити це значення не менше 14 днів, інакше картки попереднього перегляду посилань не будуть оновлюватися на вимогу раніше цього часу.
peers_api_enabled: Список доменів імен цього сервера з'явився у федівсесвіті. Сюди не входять дані чи ви пов'язані федерацією з цим сервером, а лише відомості, що вашому серверу відомо про нього. Його використовують служби, які збирають загальну статистику про федерації.
profile_directory: У каталозі профілів перераховані всі користувачі, які погодились бути видимими.
require_invite_text: Якщо реєстрація вимагає власноручного затвердження, зробіть текстове поле «Чому ви хочете приєднатися?» обов'язковим, а не додатковим
@@ -130,7 +131,7 @@ uk:
name: Тут ви можете лише змінювати регістр літер, щоб підвищити читабельність
user:
chosen_languages: У глобальних стрічках будуть показані дописи тільки вибраними мовами
- role: Роль визначає права користувача
+ role: Роль визначає, які права має користувач.
user_role:
color: Колір, який буде використовуватися для ролі у всьому інтерфейсі, як RGB у форматі hex
highlighted: Це робить роль видимою всім
@@ -143,6 +144,7 @@ uk:
url: Куди надсилатимуться події
labels:
account:
+ attribution_domains_as_text: Дозволити лише на певних вебсайтах
discoverable: Функції профілю та дописів у алгоритмах виявлення
fields:
name: Мітка
diff --git a/config/locales/simple_form.vi.yml b/config/locales/simple_form.vi.yml
index 7954bb1e6f..010bb262ad 100644
--- a/config/locales/simple_form.vi.yml
+++ b/config/locales/simple_form.vi.yml
@@ -3,12 +3,13 @@ vi:
simple_form:
hints:
account:
- discoverable: Các tút và hồ sơ công khai của bạn có thể được giới thiệu hoặc đề xuất ở nhiều khu vực khác nhau của Mastodon và hồ sơ của bạn có thể được đề xuất cho những người dùng khác.
+ attribution_domains_as_text: Bảo vệ khỏi những sự gán ghép sai.
+ discoverable: Hồ sơ và tút công khai của bạn được đề xuất cho những người dùng Mastodon khác.
display_name: Tên đầy đủ hoặc biệt danh đều được.
fields: Trang blog của bạn, nghề nghiệp, tuổi hoặc bất cứ thứ gì.
- indexable: Tút công khai của bạn sẽ xuất hiện khi tìm kiếm trên Mastodon. Những người đã tương tác với tút của bạn có thể tìm kiếm chúng.
- note: 'Bạn có thể @nhắnriêng ai đó hoặc #hashtags.'
- show_collections: Mọi người sẽ biết những bạn theo dõi và người theo dõi bạn. Những người bạn theo dõi sẽ vẫn thấy rằng bạn theo dõi họ.
+ indexable: Mọi người có thể tìm kiếm và tương tác với những tút công khai của bạn trên Mastodon.
+ note: 'Bạn có thể @aiđó hoặc #hashtags.'
+ show_collections: Mọi người sẽ biết những bạn theo dõi và người theo dõi bạn.
unlocked: Mọi người sẽ theo dõi bạn mà không cần bạn cho phép.
account_alias:
acct: Nhập tên_người_dùng@máy chủ của tài khoản cũ
@@ -41,7 +42,7 @@ vi:
autofollow: Những người đăng ký sẽ tự động theo dõi bạn
avatar: WEBP, PNG, GIF hoặc JPG, tối đa %{size}. Sẽ bị nén xuống %{dimensions}px
bot: Tài khoản này tự động thực hiện các hành động và không được quản lý bởi người thật
- context: Chọn một hoặc nhiều nơi mà bộ lọc sẽ áp dụng
+ context: Chọn những nơi mà bộ lọc sẽ áp dụng
current_password: Vì mục đích bảo mật, vui lòng nhập mật khẩu của tài khoản hiện tại
current_username: Để xác nhận, vui lòng nhập tên người dùng của tài khoản hiện tại
digest: Chỉ gửi sau một thời gian dài không hoạt động hoặc khi bạn nhận được tin nhắn (trong thời gian vắng mặt)
@@ -50,7 +51,7 @@ vi:
inbox_url: Sao chép URL của máy chủ mà bạn muốn dùng
irreversible: Các tút đã lọc sẽ không thể phục hồi, kể cả sau khi xóa bộ lọc
locale: Ngôn ngữ của giao diện, email và thông báo đẩy
- password: Dùng ít nhất 8 ký tự
+ password: Tối thiểu 8 ký tự
phrase: Sẽ được hiện thị trong văn bản hoặc cảnh báo nội dung của một tút
scopes: Ứng dụng sẽ được phép truy cập những API nào. Nếu bạn chọn quyền cấp cao nhất, không cần chọn quyền nhỏ.
setting_aggregate_reblogs: Nếu một tút đã được đăng lại thì những lượt đăng lại sau sẽ không hiện trên bảng tin nữa
@@ -73,8 +74,8 @@ vi:
filters:
action: Chọn hành động sẽ thực hiện khi một tút khớp với bộ lọc
actions:
- hide: Ẩn hoàn toàn nội dung đã lọc, như thể nó không tồn tại
- warn: Ẩn nội dung đã lọc đằng sau một cảnh báo đề cập đến tiêu đề của bộ lọc
+ hide: Ẩn hoàn toàn, như thể nó không tồn tại
+ warn: Hiện cảnh báo và bộ lọc
form_admin_settings:
activity_api_enabled: Số lượng tút được đăng trong máy chủ, người dùng đang hoạt động và đăng ký mới hàng tuần
app_icon: WEBP, PNG, GIF hoặc JPG. Dùng biểu tượng tùy chỉnh trên thiết bị di động.
@@ -130,7 +131,7 @@ vi:
name: Bạn có thể thay đổi cách viết hoa các chữ cái để giúp nó dễ đọc hơn
user:
chosen_languages: Chỉ hiển thị những tút viết bằng các ngôn ngữ sau
- role: Vai trò kiểm soát những quyền mà người dùng có
+ role: Vai trò kiểm soát những quyền mà người dùng có.
user_role:
color: Màu được sử dụng cho vai trò trong toàn bộ giao diện người dùng, dưới dạng RGB ở định dạng hex
highlighted: Vai trò sẽ hiển thị công khai
@@ -143,6 +144,7 @@ vi:
url: Nơi những sự kiện được gửi đến
labels:
account:
+ attribution_domains_as_text: Chỉ cho phép các website đặc biệt
discoverable: Cho phép khám phá hồ sơ
fields:
name: Nhãn
@@ -212,7 +214,7 @@ vi:
setting_default_sensitive: Đánh dấu media nhạy cảm
setting_delete_modal: Hỏi trước khi xóa tút
setting_disable_hover_cards: Tắt thẻ xem trước hồ sơ
- setting_disable_swiping: Không dùng chuyển động vuốt
+ setting_disable_swiping: Tắt thao tác vuốt
setting_display_media: Media nhạy cảm
setting_display_media_default: Mặc định
setting_display_media_hide_all: Ẩn toàn bộ
@@ -224,7 +226,7 @@ vi:
setting_theme: Giao diện
setting_trends: Hiển thị xu hướng trong ngày
setting_unfollow_modal: Hỏi trước khi bỏ theo dõi ai đó
- setting_use_blurhash: Phủ màu media nhạy cảm
+ setting_use_blurhash: Làm mờ media nhạy cảm
setting_use_pending_items: Không tự động cập nhật bảng tin
severity: Mức độ nghiêm trọng
sign_in_token_attempt: Mã an toàn
@@ -303,13 +305,13 @@ vi:
label: Đã có phiên bản Mastodon mới
none: Không bao giờ thông báo (không đề xuất)
patch: Thông báo bản cập sửa lỗi
- trending_tag: Phê duyệt nội dung nổi bật mới
+ trending_tag: Phê duyệt xu hướng mới
rule:
hint: Thông tin thêm
text: Nội quy
settings:
indexable: Cho phép hiện hồ sơ trong công cụ tìm kiếm
- show_application: Cho phép hiện ứng dụng dùng để đăng tút
+ show_application: Hiện ứng dụng dùng để đăng tút
tag:
listable: Cho phép xuất hiện trong tìm kiếm và đề xuất
name: Hashtag
diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml
index 3f7b8782ee..419cb99abb 100644
--- a/config/locales/simple_form.zh-CN.yml
+++ b/config/locales/simple_form.zh-CN.yml
@@ -3,13 +3,14 @@ zh-CN:
simple_form:
hints:
account:
+ attribution_domains_as_text: 保护作品免受虚假署名。
discoverable: 您的公开嘟文和个人资料可能会在 Mastodon 的多个位置展示,您的个人资料可能会被推荐给其他用户。
- display_name: 您的全名或昵称。
+ display_name: 你的全名或昵称。
fields: 你的主页、人称代词、年龄,以及任何你想要添加的内容。
indexable: 您的公开嘟文会出现在 Mastodon 的搜索结果中。无论是否勾选,与您的嘟文有过交互的人都可能通过搜索找到它们。
- note: '您可以提及 @其他人 或 #标签 。'
+ note: '你可以提及 @其他人 或 #标签 。'
show_collections: 人们将能够浏览您的关注和追随者。您关注的人会看到您关注他们。
- unlocked: 人们将能够在不请求批准的情况下关注您。如果您希望审核关注请求并选择接受或拒绝新的粉丝,请取消勾选此项。
+ unlocked: 人们将能够在不请求批准的情况下关注你。如果你希望审核关注请求并选择接受或拒绝新的粉丝,请取消勾选此项。
account_alias:
acct: 指定你想要迁移过来的原账号:用户名@站点域名
account_migration:
@@ -78,7 +79,7 @@ zh-CN:
form_admin_settings:
activity_api_enabled: 本站每周的嘟文数、活跃用户数和新注册用户数
app_icon: WEBP、PNG、GIF 或 JPG。使用自定义图标覆盖移动设备上的默认应用图标。
- backups_retention_period: 用户可以生成其嘟文存档以供之后下载。当该值被设为正值时,这些存档将在指定的天数后自动从您的存储中删除。
+ backups_retention_period: 用户可以生成其嘟文存档以供之后下载。当该值被设为正值时,这些存档将在指定的天数后自动从你的存储中删除。
bootstrap_timeline_accounts: 这些账号将在新用户关注推荐中置顶。
closed_registrations_message: 在关闭注册时显示
content_cache_retention_period: 来自其它实例的所有嘟文(包括转嘟与回复)都将在指定天数后被删除,不论本实例用户是否与这些嘟文产生过交互。这包括被本实例用户喜欢和收藏的嘟文。实例间用户的私下提及也将丢失并无法恢复。此设置针对的是特殊用途的实例,用于一般用途时会打破许多用户的期望。
@@ -125,12 +126,12 @@ zh-CN:
webauthn: 如果是 USB 密钥,请确保将其插入,如有必要,请点击它。
settings:
indexable: 您的个人资料页面可能会出现在Google、Bing等搜索结果中。
- show_application: 无论如何,您始终可以看到是哪个应用发布了您的嘟文。
+ show_application: 无论如何,你始终可以看到是哪个应用发布了你的嘟文。
tag:
name: 你只能改变字母的大小写,让它更易读
user:
chosen_languages: 仅选中语言的嘟文会出现在公共时间轴上(全不选则显示所有语言的嘟文)
- role: 角色用于控制用户拥有的权限
+ role: 角色用于控制用户拥有的权限。
user_role:
color: 在界面各处用于标记该角色的颜色,以十六进制 RGB 格式表示
highlighted: 使角色公开可见
@@ -143,7 +144,8 @@ zh-CN:
url: 事件将被发往的目的地
labels:
account:
- discoverable: 在发现算法中展示您的个人资料和嘟文
+ attribution_domains_as_text: 仅允许特定网站
+ discoverable: 在发现算法中展示你的个人资料和嘟文
fields:
name: 标签
value: 内容
@@ -309,7 +311,7 @@ zh-CN:
text: 规则
settings:
indexable: 允许搜索引擎索引个人资料页面
- show_application: 显示您发嘟所用的应用
+ show_application: 显示你发嘟所用的应用
tag:
listable: 允许这个话题标签在用户目录中显示
name: 话题标签
diff --git a/config/locales/simple_form.zh-HK.yml b/config/locales/simple_form.zh-HK.yml
index 6a7cd5a247..dd134a58fb 100644
--- a/config/locales/simple_form.zh-HK.yml
+++ b/config/locales/simple_form.zh-HK.yml
@@ -128,7 +128,6 @@ zh-HK:
name: 你只能變更大小寫(以使其更易讀)。
user:
chosen_languages: 只有被選擇的語言會在公開時間軸內顯示
- role: 角色控制使用者擁有的權限
user_role:
color: 介面各處用於角色的顏色,是以十六進制 RGB 格式表示
highlighted: 這使該角色公開可見
diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml
index 05692243ad..a5bc683634 100644
--- a/config/locales/simple_form.zh-TW.yml
+++ b/config/locales/simple_form.zh-TW.yml
@@ -3,6 +3,7 @@ zh-TW:
simple_form:
hints:
account:
+ attribution_domains_as_text: 偽造署名保護。
discoverable: 公開嘟文及個人檔案可能於各 Mastodon 功能中被推薦,並且您的個人檔案可能被推薦至其他使用者。
display_name: 完整名稱或暱稱。
fields: 烘培雞、自我認同代稱、年齡,及任何您想分享的。
@@ -53,7 +54,7 @@ zh-TW:
password: 使用至少 8 個字元
phrase: 無論是嘟文的本文或是內容警告都會被過濾
scopes: 允許使應用程式存取的 API。 若您選擇最高階範圍,則無須選擇個別項目。
- setting_aggregate_reblogs: 請勿顯示最近已被轉嘟之嘟文的最新轉嘟(只影響最新收到的嘟文)
+ setting_aggregate_reblogs: 不顯示最近已被轉嘟之嘟文的最新轉嘟(只影響最新收到的嘟文)
setting_always_send_emails: 一般情況下若您活躍使用 Mastodon ,我們不會寄送電子郵件通知
setting_default_sensitive: 敏感內容媒體預設隱藏,且按一下即可重新顯示
setting_display_media_default: 隱藏標為敏感內容的媒體
@@ -130,7 +131,7 @@ zh-TW:
name: 您只能變更大小寫,例如,以使其更易讀。
user:
chosen_languages: 當選取時,只有選取語言之嘟文會於公開時間軸中顯示
- role: 角色控制使用者有哪些權限
+ role: 角色控制使用者有哪些權限。
user_role:
color: 於整個使用者介面中用於角色的顏色,十六進位格式的 RGB
highlighted: 這將使角色公開可見
@@ -143,6 +144,7 @@ zh-TW:
url: 事件會被傳送至何處
labels:
account:
+ attribution_domains_as_text: 僅允許特定網站
discoverable: 於探索演算法中推薦個人檔案及嘟文
fields:
name: 標籤
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index ac6134caa7..d7eacb6850 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -7,7 +7,6 @@ sk:
hosted_on: Mastodon hostovaný na %{domain}
title: Ohľadom
accounts:
- follow: Nasleduj
followers:
few: Sledovateľov
many: Sledovateľov
@@ -35,6 +34,7 @@ sk:
created_msg: Poznámka moderátora bola úspešne vytvorená!
destroyed_msg: Moderátorska poznámka bola úspešne zmazaná!
accounts:
+ add_email_domain_block: Blokuj emailovú doménu
approve: Schváľ
approved_msg: Úspešne schválená prihláška %{username}
are_you_sure: Si si istý/á?
@@ -170,10 +170,12 @@ sk:
approve_appeal: Schváľ námietku
approve_user: Odobri užívateľa
assigned_to_self_report: Priraď hlásenie
+ change_email_user: Zmeň email pre užívateľa
change_role_user: Zmeň užívateľskú rolu
confirm_user: Potvrď užívateľa
create_account_warning: Vytvor výstrahu
create_announcement: Vytvor oboznámenie
+ create_canonical_email_block: Vytvor blokovanie emailu
create_custom_emoji: Vytvor vlastné emotikony
create_domain_allow: Vytvor povolenie pre doménu
create_domain_block: Vytvor zákaz domény
@@ -224,10 +226,13 @@ sk:
change_role_user_html: "%{name} zmenil/a rolu pre %{target}"
create_account_warning_html: "%{name} poslal/a upozornenie užívateľovi %{target}"
create_announcement_html: "%{name} vytvoril/a nové oboznámenie %{target}"
+ create_canonical_email_block_html: "%{name} zablokoval/a email s hašom %{target}"
create_custom_emoji_html: "%{name} nahral/a novú emotikonu %{target}"
create_domain_allow_html: "%{name} povolil/a federáciu s doménou %{target}"
create_domain_block_html: "%{name} zablokoval/a doménu %{target}"
+ create_email_domain_block_html: "%{name} zablokoval/a emailovú doménu %{target}"
create_ip_block_html: "%{name} vytvoril/a pravidlo pre IP %{target}"
+ create_unavailable_domain_html: "%{name} pozastavil/a doručovanie k doméne %{target}"
create_user_role_html: "%{name} vytvoril/a rolu pre %{target}"
demote_user_html: "%{name} degradoval/a užívateľa %{target}"
destroy_announcement_html: "%{name} vymazal/a oboznámenie %{target}"
@@ -899,8 +904,6 @@ sk:
silence: Obmedzenie účtu
your_appeal_approved: Tvoja námietka bola schválená
your_appeal_pending: Odoslal si námietku
- domain_validator:
- invalid_domain: nieje správny tvar domény
edit_profile:
basic_information: Základné informácie
other: Ostatné
@@ -1255,26 +1258,11 @@ sk:
edited_at_html: Upravené %{date}
errors:
in_reply_not_found: Príspevok, na ktorý sa snažíš odpovedať, pravdepodobne neexistuje.
- open_in_web: Otvor v okne na webe
over_character_limit: limit %{max} znakov bol presiahnutý
pin_errors:
limit: Už si si pripol ten najvyšší možný počet hlášok
ownership: Nieje možné pripnúť hlášku od niekoho iného
reblog: Vyzdvihnutie sa nedá pripnúť
- poll:
- total_people:
- few: "%{count} ľudí"
- many: "%{count} ľudia"
- one: "%{count} človek"
- other: "%{count} ľudí"
- total_votes:
- few: "%{count} hlasov"
- many: "%{count} hlasov"
- one: "%{count} hlas"
- other: "%{count} hlasy"
- vote: Hlasuj
- show_more: Ukáž viac
- show_thread: Ukáž diskusné vlákno
title: '%{name}: „%{quote}"'
visibilities:
direct: Súkromne
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
index 3384049a11..c8e806bf35 100644
--- a/config/locales/sl.yml
+++ b/config/locales/sl.yml
@@ -7,7 +7,6 @@ sl:
hosted_on: Mastodon gostuje na %{domain}
title: O programu
accounts:
- follow: Sledi
followers:
few: Sledilci
one: Sledilec
@@ -1197,7 +1196,6 @@ sl:
crypto:
errors:
invalid_key: ni veljaven ključ Ed25519 ali Curve25519
- invalid_signature: ni veljaven podpis Ed25519
date:
formats:
default: "%d %b %Y"
@@ -1263,8 +1261,6 @@ sl:
your_appeal_approved: Vaša pritožba je bila odobrena
your_appeal_pending: Oddali ste pritožbo
your_appeal_rejected: Vaša pritožba je bila zavržena
- domain_validator:
- invalid_domain: ni veljavno ime domene
edit_profile:
basic_information: Osnovni podatki
hint_html: "Prilagodite, kaj ljudje vidijo na vašem javnem profilu in poleg vaših objav. Drugi vam bodo raje sledili nazaj in z vami klepetali, če boste imeli izpolnjen profil in nastavljeno profilno sliko."
@@ -1787,27 +1783,12 @@ sl:
edited_at_html: Urejeno %{date}
errors:
in_reply_not_found: Objava, na katero želite odgovoriti, ne obstaja.
- open_in_web: Odpri na spletu
over_character_limit: omejitev %{max} znakov je presežena
pin_errors:
direct: Objav, ki so vidne samo omenjenum uporabnikom, ni mogoče pripenjati
limit: Pripeli ste največje število objav
ownership: Objava nekoga drugega ne more biti pripeta
reblog: Izpostavitev ne more biti pripeta
- poll:
- total_people:
- few: "%{count} osebe"
- one: "%{count} Oseba"
- other: "%{count} oseb"
- two: "%{count} osebi"
- total_votes:
- few: "%{count} glasovi"
- one: "%{count} glas"
- other: "%{count} glasov"
- two: "%{count} glasova"
- vote: Glasuj
- show_more: Pokaži več
- show_thread: Pokaži nit
title: "%{name}: »%{quote}«"
visibilities:
direct: Neposredno
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
index ffaa8e00b9..294c8a888f 100644
--- a/config/locales/sq.yml
+++ b/config/locales/sq.yml
@@ -7,7 +7,6 @@ sq:
hosted_on: Server Mastodon i strehuar në %{domain}
title: Mbi
accounts:
- follow: Ndiqeni
followers:
one: Ndjekës
other: Ndjekës
@@ -25,6 +24,8 @@ sq:
admin:
account_actions:
action: Kryeje veprimin
+ already_silenced: Kjo llogari është kufizuar tashmë.
+ already_suspended: Kjo llogari është pezulluar tashmë.
title: Kryeni veprim moderimi te %{acct}
account_moderation_notes:
create: Lini një shënim
@@ -46,6 +47,7 @@ sq:
title: Ndrysho email-in për %{username}
change_role:
changed_msg: Roli u ndryshua me sukses!
+ edit_roles: Administroni role përdoruesish
label: Ndryshoni rol
no_role: Pa rol
title: Ndryshoni rolin për %{username}
@@ -600,6 +602,7 @@ sq:
suspend_description_html: Llogaria dhe krejt lënda e saj s’do të jenë të përdorshme dhe, së fundi, do të fshihen dhe ndërveprimi me te do të jetë i pamundur. E prapakthyeshme brenda 30 ditësh. Mbyll krejt raportimet kundër kësaj llogarie.
actions_description_html: Vendosni cili veprim të kryhet për të zgjidhur këtë raportim. Nëse ndërmerrni një veprim ndëshkues kundër llogarisë së raportuar, atyre do t’u dërgohet një njoftim me email, hiq rastin kur përzgjidhet kategoria I padëshiruar.
actions_description_remote_html: Vendosni cili veprim të ndërmerret për zgjidhjen e këtij raportimi. Kjo do të prekë vetëm mënyrën se si shërbyesi juaj komunikon me këtë llogari të largët dhe se si e trajtojnë lëndën e saj.
+ actions_no_posts: Ky raportim s’ka ndonjë postim të përshoqëruar, për fshirje
add_to_report: Shtoni më tepër te raportimi
already_suspended_badges:
local: Tashmë i pezulluar në këtë shërbyes
@@ -1149,6 +1152,12 @@ sq:
view_strikes: Shihni paralajmërime të dikurshme kundër llogarisë tuaj
too_fast: Formulari u parashtrua shumë shpejt, riprovoni.
use_security_key: Përdor kyç sigurie
+ author_attribution:
+ example_title: Tekst shembull
+ hint_html: Kontrolloni se si vlerësoheni, kur ndahen lidhje me të tjerë në Mastodon.
+ more_from_html: Më tepër nga %{name}
+ s_blog: Blogu i %{name}
+ title: Atribuim autorësh
challenge:
confirm: Vazhdo
hint_html: "Ndihmëz: S’do t’ju pyesim për fjalëkalimin tuaj sërish, për një orë."
@@ -1157,7 +1166,6 @@ sq:
crypto:
errors:
invalid_key: s’është kyç Ed25519 ose Curve25519 i vlefshëm
- invalid_signature: s’është nënshkrim Ed25519 i vlefshëm
date:
formats:
default: "%d %b, %Y"
@@ -1223,8 +1231,6 @@ sq:
your_appeal_approved: Apelimi juaj u miratua
your_appeal_pending: Keni parashtruar një apelim
your_appeal_rejected: Apelimi juaj është hedhur poshtë
- domain_validator:
- invalid_domain: s’është emër i vlefshëm përkatësie
edit_profile:
basic_information: Hollësi elementare
hint_html: "Përshtatni ç’shohin njerëzit në profilin tuaj publik dhe në krah të postimeve tuaja. Personat e tjerë ka më shumë gjasa t’ju ndjekin dhe ndërveprojnë me ju, kur keni të plotësuar profilin dhe një foto profili."
@@ -1446,6 +1452,7 @@ sq:
media_attachments:
validations:
images_and_video: S’mund të bashkëngjitet video te një gjendje që përmban figura tashmë
+ not_found: S’u gjet media %{ids}, ose është bashkëngjitur tashmë një tjetër postimi
not_ready: S’mund të bashkëngjiten kartela që s’kanë përfunduar së përpunuari. Riprovoni pas një çasti!
too_many: S’mund të bashkëngjiten më shumë se 4 kartela
migrations:
@@ -1723,23 +1730,12 @@ sq:
edited_at_html: Përpunuar më %{date}
errors:
in_reply_not_found: Gjendja të cilës po provoni t’i përgjigjeni s’duket se ekziston.
- open_in_web: Hape në internet
over_character_limit: u tejkalua kufi shenjash prej %{max}
pin_errors:
direct: Postimet që janë të dukshme vetëm për përdoruesit e përmendur s’mund të fiksohen
limit: Keni fiksuar tashmë numrin maksimum të mesazheve
ownership: S’mund të fiksohen mesazhet e të tjerëve
reblog: S’mund të fiksohet një përforcim
- poll:
- total_people:
- one: "%{count} person"
- other: "%{count} vetë"
- total_votes:
- one: "%{count} votë"
- other: "%{count} vota"
- vote: Votë
- show_more: Shfaq më tepër
- show_thread: Shfaq rrjedhën
title: '%{name}: "%{quote}"'
visibilities:
direct: I drejtpërdrejtë
@@ -1938,6 +1934,7 @@ sq:
instructions_html: Kopjoni dhe ngjitni në HTML-në e sajtit tuaj kodin më poshtë. Mandej shtoni adresën e sajtit tuaj te një nga fushat shtesë në profilin tuaj, që nga skeda “Përpunoni profil” dhe ruani ndryshimet.
verification: Verifikim
verified_links: Lidhjet tuaja të verifikuara
+ website_verification: Verifikim sajti
webauthn_credentials:
add: Shtoni kyç të ri sigurie
create:
diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml
index dfc8a635c8..bfb52c275b 100644
--- a/config/locales/sr-Latn.yml
+++ b/config/locales/sr-Latn.yml
@@ -7,7 +7,6 @@ sr-Latn:
hosted_on: Mastodon hostovan na %{domain}
title: O instanci
accounts:
- follow: Zaprati
followers:
few: Pratioca
one: Pratilac
@@ -1111,7 +1110,6 @@ sr-Latn:
crypto:
errors:
invalid_key: nije validan Ed25519 ili Curve25519 ključ
- invalid_signature: nije validan Ed25519 potpis
date:
formats:
default: "%d. %b. %Y."
@@ -1174,8 +1172,6 @@ sr-Latn:
your_appeal_approved: Vaša žalba je uvažena
your_appeal_pending: Priložili ste žalbu
your_appeal_rejected: Vaša žalba je odbijena
- domain_validator:
- invalid_domain: nelegitimno ime domena
edit_profile:
basic_information: Osnovne informacije
hint_html: "Prilagodite šta ljudi vide na vašem javnom profilu i pored vaših objava. Veća je verovatnoća da će vas drugi pratiti i komunicirati sa vama kada imate popunjen profil i sliku profila."
@@ -1672,25 +1668,12 @@ sr-Latn:
edited_at_html: Izmenjeno %{date}
errors:
in_reply_not_found: Objava na koju pokušavate da odgovorite naizgled ne postoji.
- open_in_web: Otvori u vebu
over_character_limit: ograničenje od %{max} karaktera prekoračeno
pin_errors:
direct: Objave koje su vidljive samo pomenutim korisnicima ne mogu biti prikačene
limit: Već ste zakačili maksimalan broj objava
ownership: Tuđa objava se ne može zakačiti
reblog: Podrška ne može da se prikači
- poll:
- total_people:
- few: "%{count} osobe"
- one: "%{count} osoba"
- other: "%{count} ljudi"
- total_votes:
- few: "%{count} glasa"
- one: "%{count} glas"
- other: "%{count} glasova"
- vote: Glasajte
- show_more: Prikaži još
- show_thread: Prikaži niz
title: "%{name}: „%{quote}”"
visibilities:
direct: Direktno
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
index 2bbc4ef131..af7e7ab8d6 100644
--- a/config/locales/sr.yml
+++ b/config/locales/sr.yml
@@ -7,7 +7,6 @@ sr:
hosted_on: Mastodon хостован на %{domain}
title: О инстанци
accounts:
- follow: Запрати
followers:
few: Пратиоца
one: Пратилац
@@ -1141,7 +1140,6 @@ sr:
crypto:
errors:
invalid_key: није валидан Ed25519 или Curve25519 кључ
- invalid_signature: није валидан Ed25519 потпис
date:
formats:
default: "%d. %b. %Y."
@@ -1204,8 +1202,6 @@ sr:
your_appeal_approved: Ваша жалба је уважена
your_appeal_pending: Приложили сте жалбу
your_appeal_rejected: Ваша жалба је одбијена
- domain_validator:
- invalid_domain: нелегитимно име домена
edit_profile:
basic_information: Основне информације
hint_html: "Прилагодите шта људи виде на вашем јавном профилу и поред ваших објава. Већа је вероватноћа да ће вас други пратити и комуницирати са вама када имате попуњен профил и слику профила."
@@ -1702,25 +1698,12 @@ sr:
edited_at_html: Уређено %{date}
errors:
in_reply_not_found: Објава на коју покушавате да одговорите наизглед не постоји.
- open_in_web: Отвори у вебу
over_character_limit: ограничење од %{max} карактера прекорачено
pin_errors:
direct: Објаве које су видљиве само поменутим корисницима не могу бити прикачене
limit: Већ сте закачили максималан број објава
ownership: Туђа објава се не може закачити
reblog: Подршка не може да се прикачи
- poll:
- total_people:
- few: "%{count} особе"
- one: "%{count} особа"
- other: "%{count} људи"
- total_votes:
- few: "%{count} гласа"
- one: "%{count} глас"
- other: "%{count} гласова"
- vote: Гласајте
- show_more: Прикажи још
- show_thread: Прикажи низ
title: "%{name}: „%{quote}”"
visibilities:
direct: Директно
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index e47f506e6b..6146cfc8d7 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -7,7 +7,6 @@ sv:
hosted_on: Mastodon-värd på %{domain}
title: Om
accounts:
- follow: Följa
followers:
one: Följare
other: Följare
@@ -25,6 +24,7 @@ sv:
admin:
account_actions:
action: Utför åtgärd
+ already_silenced: Detta konto är redan begränsat.
title: Utför aktivitet för moderering på %{acct}
account_moderation_notes:
create: Lämna kommentar
@@ -46,6 +46,7 @@ sv:
title: Byt e-postadress för %{username}
change_role:
changed_msg: Rollen har ändrats!
+ edit_roles: Hantera användarroller
label: Ändra roll
no_role: Ingen roll
title: Ändra roll för %{username}
@@ -178,17 +179,21 @@ sv:
confirm_user: Bekräfta användare
create_account_warning: Skapa varning
create_announcement: Skapa kungörelse
+ create_canonical_email_block: Skapa E-post block
create_custom_emoji: Skapa egen emoji
create_domain_allow: Skapa tillåten domän
create_domain_block: Skapa blockerad domän
+ create_email_domain_block: Skapa E-post domän block
create_ip_block: Skapa IP-regel
create_unavailable_domain: Skapa otillgänglig domän
create_user_role: Skapa roll
demote_user: Degradera användare
destroy_announcement: Radera kungörelse
+ destroy_canonical_email_block: Ta bort e-post block
destroy_custom_emoji: Radera egen emoji
destroy_domain_allow: Ta bort tillåten domän
destroy_domain_block: Ta bort blockerad domän
+ destroy_email_domain_block: Ta bort E-post domän block
destroy_instance: Rensa domänen
destroy_ip_block: Radera IP-regel
destroy_status: Radera inlägg
@@ -231,19 +236,24 @@ sv:
assigned_to_self_report_html: "%{name} tilldelade rapporten %{target} till sig själva"
change_email_user_html: "%{name} bytte e-postadress för användaren %{target}"
change_role_user_html: "%{name} ändrade roll för %{target}"
+ confirm_user_html: "%{name} bekräftad e-post adress av användare %{target}"
create_account_warning_html: "%{name} skickade en varning till %{target}"
create_announcement_html: "%{name} skapade kungörelsen %{target}"
+ create_canonical_email_block_html: "%{name} blockade e-posten med %{target}"
create_custom_emoji_html: "%{name} laddade upp ny emoji %{target}"
create_domain_allow_html: "%{name} vitlistade domän %{target}"
create_domain_block_html: "%{name} blockerade domänen %{target}"
+ create_email_domain_block_html: "%{name} blockerade e-post domänet%{target}"
create_ip_block_html: "%{name} skapade regel för IP %{target}"
create_unavailable_domain_html: "%{name} stoppade leverans till domänen %{target}"
create_user_role_html: "%{name} skapade rollen %{target}"
demote_user_html: "%{name} nedgraderade användare %{target}"
destroy_announcement_html: "%{name} raderade kungörelsen %{target}"
+ destroy_canonical_email_block_html: "%{name} avblockerade e-post med hash%{target}"
destroy_custom_emoji_html: "%{name} raderade emoji %{target}"
destroy_domain_allow_html: "%{name} raderade domän %{target} från vitlistan"
destroy_domain_block_html: "%{name} avblockerade domänen %{target}"
+ destroy_email_domain_block_html: "%{name} avblockerade e-post domänet %{target}"
destroy_instance_html: "%{name} rensade domän %{target}"
destroy_ip_block_html: "%{name} tog bort regel för IP %{target}"
destroy_status_html: "%{name} tog bort inlägget av %{target}"
@@ -864,7 +874,9 @@ sv:
message_html: "Din objektlagring är felkonfigurerad. Sekretessen för dina användare är i riskzonen."
tags:
moderation:
+ reviewed: Granskat
title: Status
+ trendable:
name: Namn
reset: Återställ
review: Granskningsstatus
@@ -1106,6 +1118,8 @@ sv:
view_strikes: Visa tidigare prickar på ditt konto
too_fast: Formuläret har skickats för snabbt, försök igen.
use_security_key: Använd säkerhetsnyckel
+ author_attribution:
+ example_title: Exempeltext
challenge:
confirm: Fortsätt
hint_html: "Tips: Vi frågar dig inte efter ditt lösenord igen under nästkommande timme."
@@ -1114,7 +1128,6 @@ sv:
crypto:
errors:
invalid_key: är inte en giltig Ed25519 eller Curve25519 nyckel
- invalid_signature: är inte en giltig Ed25519 signatur
date:
formats:
default: "%b %d, %Y"
@@ -1180,8 +1193,6 @@ sv:
your_appeal_approved: Din överklagan har godkänts
your_appeal_pending: Du har lämnat in en överklagan
your_appeal_rejected: Din överklagan har avvisats
- domain_validator:
- invalid_domain: är inte ett giltigt domännamn
edit_profile:
basic_information: Allmän information
hint_html: "Anpassa vad folk ser på din offentliga profil och bredvid dina inlägg. Andra personer är mer benägna att följa dig och interagera med dig när du har en ifylld profil och en profilbild."
@@ -1680,23 +1691,12 @@ sv:
edited_at_html: 'Ändrad: %{date}'
errors:
in_reply_not_found: Inlägget du försöker svara på verkar inte existera.
- open_in_web: Öppna på webben
over_character_limit: teckengräns på %{max} har överskridits
pin_errors:
direct: Inlägg som endast är synliga för nämnda användare kan inte fästas
limit: Du har redan fäst det maximala antalet inlägg
ownership: Någon annans inlägg kan inte fästas
reblog: En boost kan inte fästas
- poll:
- total_people:
- one: "%{count} person"
- other: "%{count} personer"
- total_votes:
- one: "%{count} röst"
- other: "%{count} röster"
- vote: Rösta
- show_more: Visa mer
- show_thread: Visa tråd
title: '%{name}: "%{quote}"'
visibilities:
direct: Direkt
diff --git a/config/locales/ta.yml b/config/locales/ta.yml
index c73148eaca..56b2895c74 100644
--- a/config/locales/ta.yml
+++ b/config/locales/ta.yml
@@ -6,7 +6,6 @@ ta:
contact_unavailable: பொ/இ
hosted_on: மாஸ்டோடாண் %{domain} இனையத்தில் இயங்குகிறது
accounts:
- follow: பின்தொடர்
followers:
one: பின்தொடர்பவர்
other: பின்தொடர்பவர்கள்
@@ -189,7 +188,6 @@ ta:
crypto:
errors:
invalid_key: ஒரு முறையான Ed25519 அல்லது Curve25519 key அல்ல
- invalid_signature: ஒரு முறையான Ed25519 அடையாளம் அல்ல
filters:
index:
empty: தடுப்புகள் ஏதும் இல்லை.
@@ -220,4 +218,3 @@ ta:
other: "%{count} ஒலிகள்"
errors:
in_reply_not_found: நீங்கள் மறுமொழி அளிக்க முயலும் பதிவு இருப்பதுபோல் தெரியவில்லை.
- show_thread: தொடரைக் காட்டு
diff --git a/config/locales/te.yml b/config/locales/te.yml
index a5eb8d7794..84697a4aef 100644
--- a/config/locales/te.yml
+++ b/config/locales/te.yml
@@ -6,7 +6,6 @@ te:
contact_unavailable: వర్తించదు
hosted_on: మాస్టొడాన్ %{domain} లో హోస్టు చేయబడింది
accounts:
- follow: అనుసరించు
followers:
one: అనుచరి
other: అనుచరులు
diff --git a/config/locales/th.yml b/config/locales/th.yml
index efa142fed3..d56385f261 100644
--- a/config/locales/th.yml
+++ b/config/locales/th.yml
@@ -7,7 +7,6 @@ th:
hosted_on: Mastodon ที่โฮสต์ที่ %{domain}
title: เกี่ยวกับ
accounts:
- follow: ติดตาม
followers:
other: ผู้ติดตาม
following: กำลังติดตาม
@@ -23,6 +22,8 @@ th:
admin:
account_actions:
action: ทำการกระทำ
+ already_silenced: มีการจำกัดบัญชีนี้ไปแล้ว
+ already_suspended: มีการระงับบัญชีนี้ไปแล้ว
title: ทำการกระทำการกลั่นกรองต่อ %{acct}
account_moderation_notes:
create: เขียนหมายเหตุ
@@ -44,6 +45,7 @@ th:
title: เปลี่ยนอีเมลสำหรับ %{username}
change_role:
changed_msg: เปลี่ยนบทบาทสำเร็จ!
+ edit_roles: จัดการบทบาทผู้ใช้
label: เปลี่ยนบทบาท
no_role: ไม่มีบทบาท
title: เปลี่ยนบทบาทสำหรับ %{username}
@@ -590,6 +592,7 @@ th:
suspend_description_html: บัญชีและเนื้อหาของบัญชีทั้งหมดจะเข้าถึงไม่ได้และได้รับการลบในที่สุด และการโต้ตอบกับบัญชีจะเป็นไปไม่ได้ แปลงกลับได้ภายใน 30 วัน ปิดรายงานต่อบัญชีนี้ทั้งหมด
actions_description_html: ตัดสินใจว่าการกระทำใดที่จะใช้เพื่อแก้ปัญหารายงานนี้ หากคุณใช้การกระทำที่เป็นการลงโทษต่อบัญชีที่รายงาน จะส่งการแจ้งเตือนอีเมลถึงเขา ยกเว้นเมื่อมีการเลือกหมวดหมู่ สแปม
actions_description_remote_html: ตัดสินใจว่าการกระทำใดที่จะใช้เพื่อแก้ปัญหารายงานนี้ นี่จะมีผลต่อวิธีที่เซิร์ฟเวอร์ ของคุณ สื่อสารกับบัญชีระยะไกลนี้และจัดการเนื้อหาของบัญชีเท่านั้น
+ actions_no_posts: รายงานนี้ไม่มีโพสต์ที่เกี่ยวข้องใด ๆ ให้ลบ
add_to_report: เพิ่มข้อมูลเพิ่มเติมไปยังรายงาน
already_suspended_badges:
local: ระงับในเซิร์ฟเวอร์นี้อยู่แล้ว
@@ -872,16 +875,19 @@ th:
message_html: "ที่เก็บข้อมูลวัตถุของคุณกำหนดค่าไม่ถูกต้อง ความเป็นส่วนตัวของผู้ใช้ของคุณตกอยู่ในความเสี่ยง"
tags:
moderation:
+ not_trendable: ไม่สามารถขึ้นแนวโน้มได้
not_usable: ไม่สามารถใช้งานได้
pending_review: การตรวจทานที่รอดำเนินการ
review_requested: ต้องการการตรวจทาน
reviewed: ตรวจทานแล้ว
title: สถานะ
+ trendable: ขึ้นแนวโน้มได้
unreviewed: ไม่ได้รับการตรวจทาน
usable: ใช้งานได้
name: ชื่อ
newest: ใหม่ที่สุด
oldest: เก่าที่สุด
+ open: ดูแบบสาธารณะ
reset: รีเซ็ต
review: สถานะการตรวจทาน
search: ค้นหา
@@ -1136,6 +1142,12 @@ th:
view_strikes: ดูการดำเนินการที่ผ่านมาต่อบัญชีของคุณ
too_fast: ส่งแบบฟอร์มเร็วเกินไป ลองอีกครั้ง
use_security_key: ใช้กุญแจความปลอดภัย
+ author_attribution:
+ example_title: ข้อความตัวอย่าง
+ hint_html: ควบคุมวิธีที่ให้เครดิตแก่คุณเมื่อมีการแบ่งปันลิงก์ใน Mastodon
+ more_from_html: เพิ่มเติมจาก %{name}
+ s_blog: บล็อกของ %{name}
+ title: การระบุแหล่งที่มาผู้สร้าง
challenge:
confirm: ดำเนินการต่อ
hint_html: "เคล็ดลับ: เราจะไม่ถามรหัสผ่านของคุณกับคุณสำหรับชั่วโมงถัดไป"
@@ -1144,7 +1156,6 @@ th:
crypto:
errors:
invalid_key: ไม่ใช่กุญแจ Ed25519 หรือ Curve25519 ที่ถูกต้อง
- invalid_signature: ไม่ใช่ลายเซ็น Ed25519 ที่ถูกต้อง
date:
formats:
default: "%d %b %Y"
@@ -1210,8 +1221,6 @@ th:
your_appeal_approved: อนุมัติการอุทธรณ์ของคุณแล้ว
your_appeal_pending: คุณได้ส่งการอุทธรณ์
your_appeal_rejected: ปฏิเสธการอุทธรณ์ของคุณแล้ว
- domain_validator:
- invalid_domain: ไม่ใช่ชื่อโดเมนที่ถูกต้อง
edit_profile:
basic_information: ข้อมูลพื้นฐาน
hint_html: "ปรับแต่งสิ่งที่ผู้คนเห็นในโปรไฟล์สาธารณะของคุณและถัดจากโพสต์ของคุณ ผู้คนอื่น ๆ มีแนวโน้มที่จะติดตามคุณกลับและโต้ตอบกับคุณมากขึ้นเมื่อคุณมีโปรไฟล์ที่กรอกแล้วและรูปภาพโปรไฟล์"
@@ -1425,6 +1434,7 @@ th:
media_attachments:
validations:
images_and_video: ไม่สามารถแนบวิดีโอกับโพสต์ที่มีภาพอยู่แล้ว
+ not_found: ไม่พบสื่อ %{ids} หรือได้แนบกับโพสต์อื่นไปแล้ว
not_ready: ไม่สามารถแนบไฟล์ที่ยังประมวลผลไม่เสร็จ ลองอีกครั้งในอีกสักครู่!
too_many: ไม่สามารถแนบมากกว่า 4 ไฟล์
migrations:
@@ -1698,21 +1708,12 @@ th:
edited_at_html: แก้ไขเมื่อ %{date}
errors:
in_reply_not_found: ดูเหมือนว่าจะไม่มีโพสต์ที่คุณกำลังพยายามตอบกลับอยู่
- open_in_web: เปิดในเว็บ
over_character_limit: เกินขีดจำกัดตัวอักษรที่ %{max} แล้ว
pin_errors:
direct: ไม่สามารถปักหมุดโพสต์ที่ปรากฏแก่ผู้ใช้ที่กล่าวถึงเท่านั้น
limit: คุณได้ปักหมุดโพสต์ถึงจำนวนสูงสุดไปแล้ว
ownership: ไม่สามารถปักหมุดโพสต์ของคนอื่น
reblog: ไม่สามารถปักหมุดการดัน
- poll:
- total_people:
- other: "%{count} คน"
- total_votes:
- other: "%{count} การลงคะแนน"
- vote: ลงคะแนน
- show_more: แสดงเพิ่มเติม
- show_thread: แสดงกระทู้
title: '%{name}: "%{quote}"'
visibilities:
direct: โดยตรง
@@ -1904,12 +1905,13 @@ th:
seamless_external_login: คุณได้เข้าสู่ระบบผ่านบริการภายนอก ดังนั้นการตั้งค่ารหัสผ่านและอีเมลจึงไม่พร้อมใช้งาน
signed_in_as: 'ลงชื่อเข้าเป็น:'
verification:
- extra_instructions_html: เคล็ดลับ: ลิงก์ในเว็บไซต์ของคุณสามารถเป็นแบบมองไม่เห็น ส่วนที่สำคัญคือ rel="me"
ซึ่งป้องกันการแอบอ้างในเว็บไซต์ที่มีเนื้อหาที่ผู้ใช้สร้างขึ้น คุณยังสามารถใช้แท็ก link
ในส่วนหัวของหน้าแทนที่จะเป็น a
แต่ HTML ต้องเข้าถึงได้โดยไม่มีการประมวลผล JavaScript
+ extra_instructions_html: เคล็ดลับ: ลิงก์ในเว็บไซต์ของคุณสามารถเป็นแบบมองไม่เห็น ส่วนที่สำคัญคือ rel="me"
ซึ่งป้องกันการแอบอ้างในเว็บไซต์ที่มีเนื้อหาที่ผู้ใช้สร้างขึ้น คุณยังสามารถใช้แท็ก link
ในส่วนหัวของหน้าแทนที่จะเป็น a
ได้อีกด้วย แต่ HTML ต้องเข้าถึงได้โดยไม่มีการประมวลผล JavaScript
here_is_how: นี่คือวิธี
hint_html: "การยืนยันตัวตนของคุณใน Mastodon มีไว้สำหรับทุกคน โดยอิงตามมาตรฐานเว็บแบบเปิด ฟรีตอนนี้และตลอดไป ทั้งหมดที่คุณจำเป็นต้องมีคือเว็บไซต์ส่วนบุคคลที่ผู้คนรู้จักคุณ เมื่อคุณเชื่อมโยงไปยังเว็บไซต์นี้จากโปรไฟล์ของคุณ เราจะตรวจสอบว่าเว็บไซต์เชื่อมโยงกลับไปยังโปรไฟล์ของคุณและแสดงตัวบ่งชี้ที่มองเห็นได้ในโปรไฟล์"
instructions_html: คัดลอกแล้ววางโค้ดด้านล่างลงใน HTML ของเว็บไซต์ของคุณ จากนั้นเพิ่มที่อยู่ของเว็บไซต์ของคุณลงในหนึ่งในช่องพิเศษในโปรไฟล์ของคุณจากแท็บ "แก้ไขโปรไฟล์" และบันทึกการเปลี่ยนแปลง
verification: การตรวจสอบ
verified_links: ลิงก์ที่ยืนยันแล้วของคุณ
+ website_verification: การตรวจสอบเว็บไซต์
webauthn_credentials:
add: เพิ่มกุญแจความปลอดภัยใหม่
create:
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index fc9fde3615..16dd4c899d 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -7,7 +7,6 @@ tr:
hosted_on: Mastodon %{domain} üzerinde barındırılıyor
title: Hakkında
accounts:
- follow: Takip et
followers:
one: Takipçi
other: Takipçiler
@@ -25,6 +24,8 @@ tr:
admin:
account_actions:
action: Eylemi gerçekleştir
+ already_silenced: Bu hesap zaten sınırlanmış.
+ already_suspended: Bu hesap zaten askıya alınmış.
title: "%{acct} üzerinde denetleme eylemi gerçekleştir"
account_moderation_notes:
create: Not bırak
@@ -46,6 +47,7 @@ tr:
title: "%{username} için e-postayı değiştir"
change_role:
changed_msg: Rol başarıyla değiştirildi!
+ edit_roles: Kullanıcı rollerini yönetin
label: Rolü değiştir
no_role: Rol yok
title: "%{username} için rolü değiştir"
@@ -602,6 +604,7 @@ tr:
suspend_description_html: Bu hesap ve tüm içeriği erişilmez olacak ve nihayetinde silinecek ve bu hesapla etkileşim mümkün olmayacaktır. 30 gün içinde geri alınabilir. Bu hesaba yönelik tüm bildiriimleri kapatır.
actions_description_html: Bu bildirimi çözmek için ne yapılması gerektiğine karar verin. Bildirilen hesap için ceza işlemi yaparsanız, İstenmeyen kategorisi seçilmemişse, onlara bir e-posta duyurusu gönderilecektir.
actions_description_remote_html: Bu bildirimi çözmek için hangi eylemi yapmak istediğinize karar verin. Bu yalnızca sizin sunucunuzun bu uzak hesapla nasıl etkileşeğini ve içeriğiyle ne yapacağını etkiler.
+ actions_no_posts: Bu raporun ilişkili olduğu silinecek gönderi yok
add_to_report: Bildirime daha fazlasını ekle
already_suspended_badges:
local: Bu sunucuda zaten askıya alınmış
@@ -1157,6 +1160,12 @@ tr:
view_strikes: Hesabınıza yönelik eski eylemleri görüntüleyin
too_fast: Form çok hızlı gönderildi, tekrar deneyin.
use_security_key: Güvenlik anahtarını kullan
+ author_attribution:
+ example_title: Örnek metin
+ hint_html: Mastodon'da bağlantılar paylaşıldığında nasıl tanınmak istediğinizi denetleyin.
+ more_from_html: "%{name} kişisinden daha fazlası"
+ s_blog: "%{name} kişisinin Günlüğü"
+ title: Yazar atıfı
challenge:
confirm: Devam et
hint_html: "İpucu: Önümüzdeki saat boyunca sana parolanı sormayacağız."
@@ -1165,7 +1174,6 @@ tr:
crypto:
errors:
invalid_key: geçerli bir Ed25519 veya Curve25519 anahtarı değil
- invalid_signature: geçerli bir Ed25519 imzası değil
date:
formats:
default: "%d %b %Y"
@@ -1231,8 +1239,6 @@ tr:
your_appeal_approved: İtirazınız onaylandı
your_appeal_pending: Bir itiraz gönderdiniz
your_appeal_rejected: İtirazınız reddedildi
- domain_validator:
- invalid_domain: geçerli bir alan adı değil
edit_profile:
basic_information: Temel bilgiler
hint_html: "İnsanlara herkese açık profilinizde ve gönderilerinizin yanında ne göstermek istediğinizi düzenleyin. Dolu bir profile ve bir profil resmine sahip olduğunuzda diğer insanlar daha yüksek ihtimalle sizi takip etmek ve sizinle etkileşime geçmek isteyeceklerdir."
@@ -1454,6 +1460,7 @@ tr:
media_attachments:
validations:
images_and_video: Zaten resim içeren bir duruma video eklenemez
+ not_found: "%{ids} medya dosyaları bulunamadı veya başka bir gönderiye zaten eklenmiş"
not_ready: İşlemi tamamlanmamış dosyalar eklenemez. Birazdan tekrar deneyin!
too_many: 4'ten fazla dosya eklenemiyor
migrations:
@@ -1731,23 +1738,12 @@ tr:
edited_at_html: "%{date} tarihinde düzenlendi"
errors:
in_reply_not_found: Yanıtlamaya çalıştığınız durum yok gibi görünüyor.
- open_in_web: Web sayfasında aç
over_character_limit: "%{max} karakter limiti aşıldı"
pin_errors:
direct: Sadece değinilen kullanıcıların görebileceği gönderiler üstte tutulamaz
limit: Halihazırda maksimum sayıda gönderi sabitlediniz
ownership: Başkasının gönderisi sabitlenemez
reblog: Bir gönderi sabitlenemez
- poll:
- total_people:
- one: "%{count} kişi"
- other: "%{count} kişiler"
- total_votes:
- one: "%{count} oy"
- other: "%{count} oylar"
- vote: Oy Ver
- show_more: Daha fazlasını göster
- show_thread: Konuyu göster
title: '%{name}: "%{quote}"'
visibilities:
direct: Doğrudan
@@ -1946,6 +1942,7 @@ tr:
instructions_html: Aşağıdaki kodu kopyalayın ve websitenizin HTML'sine yapıştırın. Daha sonra "Profil Düzenle" sekmesini kullanarak profilinizdeki ek sahalardan birine websitenizin adresini ekleyin ve değişiklikleri kaydedin.
verification: Doğrulama
verified_links: Doğrulanmış bağlantılarınız
+ website_verification: Website doğrulama
webauthn_credentials:
add: Yeni güvenlik anahtarı ekle
create:
diff --git a/config/locales/tt.yml b/config/locales/tt.yml
index 3a0d9d9ce8..7847d636eb 100644
--- a/config/locales/tt.yml
+++ b/config/locales/tt.yml
@@ -4,7 +4,6 @@ tt:
contact_unavailable: Юк
title: Проект турында
accounts:
- follow: Языл
followers:
other: язылучы
following: Язылгансыз
@@ -519,12 +518,6 @@ tt:
video:
other: "%{count} видео"
edited_at_html: "%{date} көнне төзәтте"
- open_in_web: Веб-та ачу
- poll:
- total_people:
- other: "%{count} кеше"
- vote: Тавыш бирү
- show_more: Күбрәк күрсәтү
title: '%{name}: "%{quote}"'
visibilities:
private: Ияртүчеләр генә
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index faff0b4e42..0ef08a1555 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -7,7 +7,6 @@ uk:
hosted_on: Mastodon розміщено на %{domain}
title: Про програму
accounts:
- follow: Підписатися
followers:
few: Підписники
many: Підписників
@@ -29,6 +28,8 @@ uk:
admin:
account_actions:
action: Виконати дію
+ already_silenced: Цей обліковий запис вже обмежено.
+ already_suspended: Цей обліковий запис вже було призупинено.
title: Здійснити модераційну дію над %{acct}
account_moderation_notes:
create: Залишити нотатку
@@ -50,6 +51,7 @@ uk:
title: Змінити адресу електронної пошти для %{username}
change_role:
changed_msg: Роль успішно змінено!
+ edit_roles: Керування ролями
label: Змінити роль
no_role: Немає ролі
title: Змінити роль для %{username}
@@ -626,6 +628,7 @@ uk:
suspend_description_html: Обліковий запис і весь його вміст будуть недоступними й врешті-решт видалені, і взаємодіяти з ним буде неможливо. Відновлення можливе протягом 30 днів. Закриває всі скарги на цей обліковий запис.
actions_description_html: Визначте, які дії слід вжити для розв'язання цієї скарги. Якщо ви оберете каральні дії проти зареєстрованого облікового запису, про них буде надіслано сповіщення електронним листом, крім випадків, коли вибрано категорію Спам.
actions_description_remote_html: Визначте, які дії слід вжити для розв'язання цього звіту. Це вплине тільки на те, як ваш сервер з'єднується з цим віддаленим обліковим записом і обробляє його вміст.
+ actions_no_posts: Ця скарга не має жодних пов'язаних дописів для видалення
add_to_report: Додати ще подробиць до скарги
already_suspended_badges:
local: Вже призупинено на цьому сервері
@@ -786,7 +789,7 @@ uk:
desc_html: Це залежить від зовнішніх скриптів hCaptcha, що може становити загрозу безпеці та приватності. Крім того, це може зробити процес реєстрації значно менш доступним для деяких людей (особливо з обмеженими можливостями). З цих причин, будь ласка, розгляньте альтернативні заходи, такі як реєстрація на основі схвалення або на основі запрошення.
title: Вимагати нових користувачів розв'язувати CAPTCHA для підтвердження облікового запису
content_retention:
- danger_zone: Зони небезпеки
+ danger_zone: Небезпечна зона
preamble: Контролюйте, як зберігаються користувацькі матеріали в Mastodon.
title: Зберігання вмісту
default_noindex:
@@ -1193,6 +1196,12 @@ uk:
view_strikes: Переглянути попередні попередження вашому обліковому запису
too_fast: Форму подано занадто швидко, спробуйте ще раз.
use_security_key: Використовувати ключ безпеки
+ author_attribution:
+ example_title: Зразок тексту
+ hint_html: Контроль авторства поширених посилань на Mastodon.
+ more_from_html: Більше від %{name}
+ s_blog: Блог %{name}
+ title: Атрибути авторства
challenge:
confirm: Далі
hint_html: "Підказка: ми не будемо запитувати ваш пароль впродовж наступної години."
@@ -1201,7 +1210,6 @@ uk:
crypto:
errors:
invalid_key: не є припустимим ключем Ed25519 або Curve25519
- invalid_signature: не є дійсним підписом Ed25519
date:
formats:
default: "%b %d, %Y"
@@ -1267,8 +1275,6 @@ uk:
your_appeal_approved: Вашу апеляцію було схвалено
your_appeal_pending: Ви не подавали апеляцій
your_appeal_rejected: Вашу апеляцію було відхилено
- domain_validator:
- invalid_domain: не є допустимим ім'ям домену
edit_profile:
basic_information: Основна інформація
hint_html: "Налаштуйте те, що люди бачитимуть у вашому загальнодоступному профілі та поруч із вашими дописами. Інші люди з більшою ймовірністю підпишуться на вас та взаємодіятимуть з вами, якщо у вас є заповнений профіль та зображення профілю."
@@ -1506,6 +1512,7 @@ uk:
media_attachments:
validations:
images_and_video: Не можна додати відео до допису з зображеннями
+ not_found: Медіа %{ids} не знайдено або вже прикріплено до іншого допису
not_ready: Не можна прикріпити файли, оброблення яких ще не закінчилося. Спробуйте ще раз через хвилину!
too_many: Не можна додати більше 4 файлів
migrations:
@@ -1791,27 +1798,12 @@ uk:
edited_at_html: Відредаговано %{date}
errors:
in_reply_not_found: Допису, на який ви намагаєтеся відповісти, не існує.
- open_in_web: Відкрити у вебі
over_character_limit: перевищено ліміт символів %{max}
pin_errors:
direct: Не можливо прикріпити дописи, які видимі лише згаданим користувачам
limit: Ви вже закріпили максимальну кількість дописів
ownership: Не можна закріпити чужий допис
reblog: Не можна закріпити просунутий допис
- poll:
- total_people:
- few: "%{count} людей"
- many: "%{count} людей"
- one: "%{count} людина"
- other: "%{count} людей"
- total_votes:
- few: "%{count} голоса"
- many: "%{count} голосів"
- one: "%{count} голос"
- other: "%{count} голоси"
- vote: Проголосувати
- show_more: Розгорнути
- show_thread: Відкрити обговорення
title: '%{name}: "%{quote}"'
visibilities:
direct: Особисто
@@ -2012,6 +2004,7 @@ uk:
instructions_html: Скопіюйте та вставте наведений нижче код у HTML-код вашого сайту. Потім додайте адресу свого сайту в одне з додаткових полів вашого профілю на вкладці «Редагувати профіль» і збережіть зміни.
verification: Підтвердження
verified_links: Ваші підтверджені посилання
+ website_verification: Підтвердження вебсайтів
webauthn_credentials:
add: Додати новий ключ безпеки
create:
diff --git a/config/locales/uz.yml b/config/locales/uz.yml
index 403ffd33cf..9215a0f0e8 100644
--- a/config/locales/uz.yml
+++ b/config/locales/uz.yml
@@ -2,8 +2,6 @@
uz:
about:
title: Haqida
- accounts:
- follow: Obuna bo‘lish
admin:
accounts:
display_name: Ko'rsatiladigan nom
diff --git a/config/locales/vi.yml b/config/locales/vi.yml
index 35b55583a0..d969ad7d4f 100644
--- a/config/locales/vi.yml
+++ b/config/locales/vi.yml
@@ -7,7 +7,6 @@ vi:
hosted_on: "%{domain} vận hành nhờ Mastodon"
title: Giới thiệu
accounts:
- follow: Theo dõi
followers:
other: Người theo dõi
following: Theo dõi
@@ -23,6 +22,8 @@ vi:
admin:
account_actions:
action: Thực hiện hành động
+ already_silenced: Tài khoản này đã bị hạn chế.
+ already_suspended: Tài khoản này đã bị vô hiệu hóa.
title: Áp đặt kiểm duyệt với %{acct}
account_moderation_notes:
create: Thêm lưu ý
@@ -43,7 +44,8 @@ vi:
submit: Thay đổi email
title: Thay đổi email cho %{username}
change_role:
- changed_msg: Vai trò đã thay đổi thành công!
+ changed_msg: Đã cập nhật vai trò!
+ edit_roles: Quản lý vai trò người dùng
label: Đổi vai trò
no_role: Chưa có vai trò
title: Thay đổi vai trò %{username}
@@ -53,7 +55,7 @@ vi:
custom: Tùy chỉnh
delete: Xóa dữ liệu
deleted: Đã xóa
- demote: Xóa vai trò
+ demote: Hạ vai trò
destroyed_msg: Dữ liệu %{username} sẽ được lên lịch xóa ngay bây giờ
disable: Khóa
disable_sign_in_token_auth: Tắt xác minh bằng email
@@ -106,7 +108,7 @@ vi:
previous_strikes: Lịch sử kiểm duyệt
previous_strikes_description_html:
other: Người này bị cảnh cáo %{count} lần.
- promote: Chỉ định vai trò
+ promote: Nâng vai trò
protocol: Giao thức
public: Công khai
push_subscription_expires: Đăng ký PuSH hết hạn
@@ -151,8 +153,8 @@ vi:
suspension_irreversible: Toàn bộ dữ liệu của người này sẽ bị xóa hết. Bạn vẫn có thể ngừng vô hiệu hóa nhưng dữ liệu sẽ không thể phục hồi.
suspension_reversible_hint_html: Mọi dữ liệu của người này sẽ bị xóa sạch vào %{date}. Trước thời hạn này, dữ liệu vẫn có thể phục hồi. Nếu bạn muốn xóa dữ liệu của người này ngay lập tức, hãy tiếp tục.
title: Tài khoản
- unblock_email: Mở khóa địa chỉ email
- unblocked_email_msg: Mở khóa thành công địa chỉ email của %{username}
+ unblock_email: Bỏ chặn địa chỉ email
+ unblocked_email_msg: Đã bỏ chặn địa chỉ email của %{username}
unconfirmed_email: Email chưa được xác minh
undo_sensitized: Đánh dấu bình thường
undo_silenced: Bỏ hạn chế
@@ -168,42 +170,42 @@ vi:
action_logs:
action_types:
approve_appeal: Chấp nhận kháng cáo
- approve_user: Chấp nhận đăng ký
+ approve_user: Duyệt đăng ký
assigned_to_self_report: Tự xử lý báo cáo
change_email_user: Đổi email người dùng
change_role_user: Đổi vai trò
confirm_user: Xác minh
create_account_warning: Cảnh cáo
create_announcement: Tạo thông báo mới
- create_canonical_email_block: Tạo chặn email
+ create_canonical_email_block: Chặn địa chỉ email
create_custom_emoji: Tạo emoji
create_domain_allow: Cho phép máy chủ
create_domain_block: Chặn máy chủ
create_email_domain_block: Tạo chặn tên miền email
- create_ip_block: Tạo chặn IP mới
- create_unavailable_domain: Máy chủ không khả dụng
+ create_ip_block: Chặn IP
+ create_unavailable_domain: Ngừng liên hợp
create_user_role: Tạo vai trò
- demote_user: Xóa vai trò
+ demote_user: Hạ vai trò
destroy_announcement: Xóa thông báo
- destroy_canonical_email_block: Bỏ chặn email
+ destroy_canonical_email_block: Bỏ chặn địa chỉ email
destroy_custom_emoji: Xóa emoji
destroy_domain_allow: Bỏ thanh trừng máy chủ
destroy_domain_block: Bỏ chặn máy chủ
destroy_email_domain_block: Bỏ chặn tên miền email
destroy_instance: Thanh trừng máy chủ
- destroy_ip_block: Xóa IP đã chặn
+ destroy_ip_block: Bỏ chặn IP
destroy_status: Xóa tút
- destroy_unavailable_domain: Xóa máy chủ không khả dụng
+ destroy_unavailable_domain: Tái liên hợp
destroy_user_role: Xóa vai trò
disable_2fa_user: Vô hiệu hóa 2FA
disable_custom_emoji: Vô hiệu hóa emoji
disable_sign_in_token_auth_user: Tắt xác minh bằng email cho người dùng
disable_user: Vô hiệu hóa đăng nhập
- enable_custom_emoji: Cho phép emoji
+ enable_custom_emoji: Duyệt emoji
enable_sign_in_token_auth_user: Bật xác minh bằng email cho người dùng
- enable_user: Bỏ vô hiệu hóa đăng nhập
+ enable_user: Cho phép đăng nhập
memorialize_account: Đánh dấu tưởng niệm
- promote_user: Chỉ định vai trò
+ promote_user: Nâng vai trò
reject_appeal: Từ chối kháng cáo
reject_user: Từ chối đăng ký
remove_avatar_user: Xóa ảnh đại diện
@@ -211,11 +213,11 @@ vi:
resend_user: Gửi lại email xác minh
reset_password_user: Đặt lại mật khẩu
resolve_report: Xử lý báo cáo
- sensitive_account: Áp đặt nhạy cảm
- silence_account: Áp đặt ẩn
- suspend_account: Áp đặt vô hiệu hóa
+ sensitive_account: Gán nhạy cảm
+ silence_account: Gán ẩn
+ suspend_account: Gán vô hiệu hóa
unassigned_report: Báo cáo chưa xử lý
- unblock_email_account: Mở khóa địa chỉ email
+ unblock_email_account: Bỏ chặn địa chỉ email
unsensitive_account: Bỏ nhạy cảm
unsilence_account: Bỏ ẩn
unsuspend_account: Bỏ vô hiệu hóa
@@ -227,7 +229,7 @@ vi:
update_status: Cập nhật tút
update_user_role: Cập nhật vai trò
actions:
- approve_appeal_html: "%{name} đã chấp nhận kháng cáo của %{target}"
+ approve_appeal_html: "%{name} đã duyệt kháng cáo của %{target}"
approve_user_html: "%{name} đã chấp nhận đăng ký từ %{target}"
assigned_to_self_report_html: "%{name} tự xử lý báo cáo %{target}"
change_email_user_html: "%{name} đã thay đổi địa chỉ email của %{target}"
@@ -235,7 +237,7 @@ vi:
confirm_user_html: "%{name} đã xác minh địa chỉ email của %{target}"
create_account_warning_html: "%{name} đã cảnh cáo %{target}"
create_announcement_html: "%{name} tạo thông báo mới %{target}"
- create_canonical_email_block_html: "%{name} đã chặn email với hash %{target}"
+ create_canonical_email_block_html: "%{name} đã chặn địa chỉ email với hash %{target}"
create_custom_emoji_html: "%{name} đã tải lên biểu tượng cảm xúc mới %{target}"
create_domain_allow_html: "%{name} kích hoạt liên hợp với %{target}"
create_domain_block_html: "%{name} chặn máy chủ %{target}"
@@ -243,9 +245,9 @@ vi:
create_ip_block_html: "%{name} đã chặn IP %{target}"
create_unavailable_domain_html: "%{name} ngưng phân phối với máy chủ %{target}"
create_user_role_html: "%{name} đã tạo vai trò %{target}"
- demote_user_html: "%{name} đã xóa vai trò của %{target}"
+ demote_user_html: "%{name} đã hạ vai trò của %{target}"
destroy_announcement_html: "%{name} xóa thông báo %{target}"
- destroy_canonical_email_block_html: "%{name} đã bỏ chặn email với hash %{target}"
+ destroy_canonical_email_block_html: "%{name} đã bỏ chặn địa chỉ email với hash %{target}"
destroy_custom_emoji_html: "%{name} đã xóa emoji %{target}"
destroy_domain_allow_html: "%{name} đã ngừng liên hợp với %{target}"
destroy_domain_block_html: "%{name} bỏ chặn máy chủ %{target}"
@@ -259,11 +261,11 @@ vi:
disable_custom_emoji_html: "%{name} đã ẩn emoji %{target}"
disable_sign_in_token_auth_user_html: "%{name} đã tắt xác minh email của %{target}"
disable_user_html: "%{name} vô hiệu hóa đăng nhập %{target}"
- enable_custom_emoji_html: "%{name} cho phép Emoji %{target}"
+ enable_custom_emoji_html: "%{name} cho phép emoji %{target}"
enable_sign_in_token_auth_user_html: "%{name} đã bật xác minh email của %{target}"
enable_user_html: "%{name} bỏ vô hiệu hóa đăng nhập %{target}"
memorialize_account_html: "%{name} đã biến tài khoản %{target} thành một trang tưởng niệm"
- promote_user_html: "%{name} chỉ định vai trò cho %{target}"
+ promote_user_html: "%{name} đã nâng vai trò của %{target}"
reject_appeal_html: "%{name} đã từ chối kháng cáo của %{target}"
reject_user_html: "%{name} đã từ chối đăng ký từ %{target}"
remove_avatar_user_html: "%{name} đã xóa ảnh đại diện của %{target}"
@@ -275,7 +277,7 @@ vi:
silence_account_html: "%{name} đã ẩn %{target}"
suspend_account_html: "%{name} đã vô hiệu hóa %{target}"
unassigned_report_html: "%{name} đã xử lý báo cáo %{target} chưa xử lí"
- unblock_email_account_html: "%{name} mở khóa địa chỉ email của %{target}"
+ unblock_email_account_html: "%{name} bỏ chặn địa chỉ email của %{target}"
unsensitive_account_html: "%{name} đánh dấu nội dung của %{target} là bình thường"
unsilence_account_html: "%{name} đã bỏ ẩn %{target}"
unsuspend_account_html: "%{name} đã bỏ vô hiệu hóa %{target}"
@@ -285,7 +287,7 @@ vi:
update_ip_block_html: "%{name} cập nhật chặn IP %{target}"
update_report_html: "%{name} cập nhật báo cáo %{target}"
update_status_html: "%{name} cập nhật tút của %{target}"
- update_user_role_html: "%{name} đã thay đổi vai trò %{target}"
+ update_user_role_html: "%{name} đã cập nhật vai trò %{target}"
deleted_account: tài khoản đã xóa
empty: Không tìm thấy bản ghi.
filter_by_action: Theo hành động
@@ -326,7 +328,7 @@ vi:
emoji: Emoji
enable: Cho phép
enabled: Đã cho phép
- enabled_msg: Đã cho phép thành công Emoji này
+ enabled_msg: Đã cho phép emoji này xong
image_hint: PNG hoặc GIF tối đa %{size}
list: Danh sách
listed: Liệt kê
@@ -590,6 +592,7 @@ vi:
suspend_description_html: Tài khoản và tất cả nội dung của nó sẽ không thể truy cập được và cuối cùng sẽ bị xóa, đồng thời không thể tương tác với tài khoản đó. Có thể đảo ngược trong vòng 30 ngày. Đóng tất cả các báo cáo đối với tài khoản này.
actions_description_html: Nếu áp đặt kiểm duyệt, một email thông báo sẽ được gửi cho người này, ngoại trừ Spam.
actions_description_remote_html: Chọn hành động cần thực hiện để xử lý báo cáo này. Điều này sẽ chỉ ảnh hưởng đến cách máy chủ của bạn giao tiếp với tài khoản này và xử lý nội dung của nó.
+ actions_no_posts: Báo cáo này không có tút liên quan để xóa
add_to_report: Bổ sung báo cáo
already_suspended_badges:
local: Đã vô hiệu hóa trên máy chủ này
@@ -689,7 +692,7 @@ vi:
manage_announcements: Quản lý thông báo
manage_announcements_description: Cho phép quản lý thông báo trên máy chủ
manage_appeals: Quản lý kháng cáo
- manage_appeals_description: Cho phép xem xét kháng cáo đối với các hành động kiểm duyệt
+ manage_appeals_description: Cho phép thành viên kháng cáo đối với các hành động kiểm duyệt
manage_blocks: Quản lý chặn
manage_blocks_description: Cho phép người dùng tự chặn các nhà cung cấp email và địa chỉ IP
manage_custom_emojis: Quản lý emoji
@@ -701,7 +704,7 @@ vi:
manage_reports: Quản lý báo cáo
manage_reports_description: Cho phép xem xét các báo cáo và thực hiện hành động kiểm duyệt đối với chúng
manage_roles: Quản lý vai trò
- manage_roles_description: Cho phép quản lý và chỉ định các vai trò nhỏ hơn họ
+ manage_roles_description: Cho phép quản lý và nâng cấp các vai trò nhỏ hơn họ
manage_rules: Quản lý nội quy máy chủ
manage_rules_description: Cho phép thay đổi nội quy máy chủ
manage_settings: Quản lý thiết lập
@@ -795,7 +798,7 @@ vi:
patch: Bản vá - sửa lỗi và dễ dàng áp dụng các thay đổi
version: Phiên bản
statuses:
- account: Tác giả
+ account: Người đăng
application: Ứng dụng
back_to_account: Quay lại trang tài khoản
back_to_report: Quay lại trang báo cáo
@@ -814,7 +817,7 @@ vi:
open: Mở tút
original_status: Tút gốc
reblogs: Lượt đăng lại
- status_changed: Tút đã thay đổi
+ status_changed: Tút đã sửa
title: Toàn bộ tút
trending: Xu hướng
visibility: Hiển thị
@@ -884,6 +887,7 @@ vi:
name: Tên
newest: Mới nhất
oldest: Cũ nhất
+ open: Xem công khai
reset: Đặt lại
review: Phê duyệt
search: Tìm kiếm
@@ -892,7 +896,7 @@ vi:
title: Quản trị
trends:
allow: Cho phép
- approved: Đã cho phép
+ approved: Đã duyệt
confirm_allow: Bạn có chắc muốn cho phép những hashtag đã chọn?
confirm_disallow: Bạn có chắc muốn cấm những hashtag đã chọn?
disallow: Cấm
@@ -911,17 +915,17 @@ vi:
no_publisher_selected: Không có nguồn đăng nào thay đổi vì không có nguồn đăng nào được chọn
shared_by_over_week:
other: "%{count} người chia sẻ tuần rồi"
- title: Tin tức nổi bật
+ title: Xu hướng tin tức
usage_comparison: Chia sẻ %{today} lần hôm nay, so với %{yesterday} lần hôm qua
not_allowed_to_trend: Không được phép thành xu hướng
- only_allowed: Chỉ cho phép
+ only_allowed: Đã cho phép
pending_review: Đang chờ
preview_card_providers:
allowed: Tin tức từ nguồn này có thể lên xu hướng
description_html: Đây là những nguồn mà từ đó các liên kết thường được chia sẻ trên máy chủ của bạn. Các liên kết sẽ không thể lên xu hướng trừ khi bạn cho phép nguồn. Sự cho phép (hoặc cấm) của bạn áp dụng luôn cho các tên miền phụ.
rejected: Tin tức từ nguồn này không thể lên xu hướng
title: Nguồn đăng
- rejected: Đã cấm
+ rejected: Từ chối
statuses:
allow: Cho phép tút
allow_account: Cho phép người đăng
@@ -932,11 +936,11 @@ vi:
description_html: Đây là những tút đang được chia sẻ và yêu thích rất nhiều trên máy chủ của bạn. Nó có thể giúp người mới và người cũ tìm thấy nhiều người hơn để theo dõi. Không có tút nào được hiển thị công khai cho đến khi bạn cho phép người đăng và người cho phép đề xuất tài khoản của họ cho người khác. Bạn cũng có thể cho phép hoặc từ chối từng tút riêng.
disallow: Cấm tút
disallow_account: Cấm người đăng
- no_status_selected: Không có tút xu hướng nào thay đổi vì không có tút nào được chọn
- not_discoverable: Tác giả đã chọn không tham gia mục khám phá
+ no_status_selected: Bạn chưa chọn mục nào
+ not_discoverable: Người đăng đã chọn không tham gia mục khám phá
shared_by:
other: Được thích và đăng lại %{friendly_count} lần
- title: Tút xu hướng
+ title: Xu hướng tút
tags:
current_score: Chỉ số gần đây %{score}
dashboard:
@@ -952,9 +956,9 @@ vi:
not_trendable: Không cho lên xu hướng
not_usable: Không được phép dùng
peaked_on_and_decaying: Đỉnh điểm %{date}, giờ đang giảm
- title: Hashtag nổi bật
+ title: Xu hướng hashtag
trendable: Cho phép lên xu hướng
- trending_rank: 'Nổi bật #%{rank}'
+ trending_rank: 'Xu hướng #%{rank}'
usable: Có thể dùng
usage_comparison: Dùng %{today} lần hôm nay, so với %{yesterday} hôm qua
used_by_over_week:
@@ -1000,7 +1004,7 @@ vi:
silence: hạn chế tài khoản của họ
suspend: vô hiệu hóa tài khoản của họ
body: "%{target} đã khiếu nại vì bị %{action_taken_by} %{type} vào %{date}. Họ cho biết:"
- next_steps: Bạn có thể chấp nhận kháng cáo để hủy kiểm duyệt hoặc bỏ qua.
+ next_steps: Bạn có thể duyệt kháng cáo để hủy kiểm duyệt hoặc bỏ qua.
subject: "%{username} đang khiếu nại quyết định kiểm duyệt trên %{instance}"
new_critical_software_updates:
body: Các phiên bản quan trọng mới của Mastodon đã được phát hành, bạn nên cập nhật càng sớm càng tốt!
@@ -1018,12 +1022,12 @@ vi:
new_trends:
body: 'Các mục sau đây cần được xem xét trước khi chúng hiển thị công khai:'
new_trending_links:
- title: Tin tức nổi bật
+ title: Xu hướng tin tức
new_trending_statuses:
- title: Tút nổi bật
+ title: Xu hướng tút
new_trending_tags:
- title: Hashtag nổi bật
- subject: Nội dung nổi bật chờ duyệt trên %{instance}
+ title: Xu hướng hashtag
+ subject: Xu hướng chờ duyệt trên %{instance}
aliases:
add_new: Kết nối tài khoản
created_msg: Tạo thành công một tên hiển thị mới. Bây giờ bạn có thể bắt đầu di chuyển từ tài khoản cũ.
@@ -1033,7 +1037,7 @@ vi:
remove: Bỏ liên kết bí danh
appearance:
advanced_web_interface: Bố cục
- advanced_web_interface_hint: Bố cục nhiều cột cho phép bạn chuyển bố cục hiển thị thành nhiều cột khác nhau. Thích hợp với màn hình rộng.
+ advanced_web_interface_hint: Chia giao diện thành nhiều cột, phù hợp với màn hình rộng.
animations_and_accessibility: Hiệu ứng
confirmation_dialogs: Hộp thoại xác nhận
discovery: Khám phá
@@ -1138,6 +1142,12 @@ vi:
view_strikes: Xem những lần cảnh cáo cũ
too_fast: Nghi vấn đăng ký spam, xin thử lại.
use_security_key: Dùng khóa bảo mật
+ author_attribution:
+ example_title: Văn bản mẫu
+ hint_html: Kiểm soát cách bạn được ghi nhận khi chia sẻ liên kết trên Mastodon.
+ more_from_html: Thêm từ %{name}
+ s_blog: "%{name}'s Blog"
+ title: Ghi nhận người đăng
challenge:
confirm: Tiếp tục
hint_html: "Mẹo: Chúng tôi sẽ không hỏi lại mật khẩu của bạn sau này."
@@ -1146,7 +1156,6 @@ vi:
crypto:
errors:
invalid_key: không phải là mã khóa Ed25519 hoặc Curve25519 đúng
- invalid_signature: không phải là chữ ký số Ed25519 đúng
date:
formats:
default: "%-d %B, %Y"
@@ -1192,7 +1201,7 @@ vi:
appealed_msg: Khiếu nại của bạn đã được gửi đi. Nếu nó được chấp nhận, bạn sẽ nhận được thông báo.
appeals:
submit: Gửi khiếu nại
- approve_appeal: Chấp nhận kháng cáo
+ approve_appeal: Duyệt kháng cáo
associated_report: Báo cáo đính kèm
created_at: Ngày
description_html: Đây là những cảnh cáo và áp đặt kiểm duyệt đối với bạn bởi đội ngũ %{instance}.
@@ -1212,8 +1221,6 @@ vi:
your_appeal_approved: Khiếu nại của bạn được chấp nhận
your_appeal_pending: Bạn đã gửi một khiếu nại
your_appeal_rejected: Khiếu nại của bạn bị từ chối
- domain_validator:
- invalid_domain: không phải là một tên miền hợp lệ
edit_profile:
basic_information: Thông tin cơ bản
hint_html: "Tùy chỉnh những gì mọi người nhìn thấy trên hồ sơ công khai và bên cạnh tút của bạn. Mọi người sẽ muốn theo dõi và tương tác với bạn hơn nếu bạn có ảnh đại diện và một hồ sơ hoàn chỉnh."
@@ -1255,7 +1262,7 @@ vi:
add_new: Thêm mới
errors:
limit: Bạn đã đạt tới số lượng hashtag tối đa
- hint_html: "Làm nổi bật những hashtag thường dùng. Một công cụ tuyệt vời để theo dõi các tác phẩm sáng tạo và dự án dài hạn của bạn, các hashtag thường dùng sẽ hiển thị nổi bật trên hồ sơ của bạn và cho phép truy cập nhanh vào các tút."
+ hint_html: "Làm nổi bật những hashtag thường dùng. Một công cụ tuyệt vời để theo dõi các tác phẩm sáng tạo và dự án dài hạn của bạn, cũng như giúp truy cập nhanh vào các tút."
filters:
contexts:
account: Trang hồ sơ
@@ -1273,7 +1280,7 @@ vi:
deprecated_api_multiple_keywords: Không thể thay đổi các tham số này từ ứng dụng này vì chúng áp dụng cho nhiều hơn một từ khóa bộ lọc. Sử dụng ứng dụng mới hơn hoặc giao diện web.
invalid_context: Bối cảnh không hợp lệ hoặc không có
index:
- contexts: Bộ lọc %{contexts}
+ contexts: Lọc ở %{contexts}
delete: Xóa bỏ
empty: Chưa có bộ lọc nào.
expires_in: Hết hạn trong %{distance}
@@ -1329,7 +1336,7 @@ vi:
merge: Hợp nhất
merge_long: Giữ hồ sơ hiện có và thêm hồ sơ mới
overwrite: Ghi đè
- overwrite_long: Thay thế các bản ghi hiện tại bằng những cái mới
+ overwrite_long: Thay thế các bản ghi hiện tại bằng các bản ghi mới
overwrite_preambles:
blocking_html: Bạn sắp thay thế danh sách chặn với %{total_items} tài khoản từ %{filename}.
bookmarks_html: Bạn sắp thay thế lượt lưu với %{total_items} tút từ %{filename}.
@@ -1407,7 +1414,7 @@ vi:
description_html: Nếu có lần đăng nhập đáng ngờ, hãy đổi ngay mật khẩu và bật xác minh 2 bước.
empty: Không có lịch sử đăng nhập
failed_sign_in_html: Đăng nhập thất bại bằng %{method} từ %{ip} (%{browser})
- successful_sign_in_html: Đăng nhập thành công bằng %{method} từ %{ip} (%{browser})
+ successful_sign_in_html: Đăng nhập bằng %{method} từ %{ip} (%{browser})
title: Lịch sử đăng nhập
mail_subscriptions:
unsubscribe:
@@ -1427,6 +1434,7 @@ vi:
media_attachments:
validations:
images_and_video: Không thể đính kèm video vào tút đã chứa hình ảnh
+ not_found: Không tìm thấy %{ids} hoặc nó đã bị đính kèm với tút khác
not_ready: Tập tin này vẫn chưa xử lý xong. Hãy thử lại sau!
too_many: Không thể đính kèm hơn 4 tệp
migrations:
@@ -1547,13 +1555,13 @@ vi:
posting_defaults: Mặc định cho tút
public_timelines: Bảng tin
privacy:
- hint_html: "Tùy chỉnh cách mọi người tìm thấy hồ sơ và các tút của bạn. Nhiều tính năng trong Mastodon có thể giúp bạn tiếp cận nhiều đối tượng hơn khi được bật. Hãy xem lại các cài đặt này để đảm bảo chúng phù hợp với bạn."
+ hint_html: "Tùy chỉnh cách mọi người tìm thấy hồ sơ và tút của bạn. Hãy đảm bảo các thiết lập sau phù hợp với bạn."
privacy: Riêng tư
privacy_hint_html: Kiểm soát mức độ chi tiết bạn muốn tiết lộ. Mọi người khám phá các hồ sơ thú vị và các ứng dụng thú vị bằng cách theo dõi những người khác và xem họ đăng từ ứng dụng nào, nhưng có thể bạn muốn ẩn nó đi.
reach: Tiếp cận
reach_hint_html: Kiểm soát cách bạn được khám phá và theo dõi. Bạn có muốn tút của mình xuất hiện trên màn hình Khám phá không? Bạn có muốn người khác nhìn thấy bạn trong các đề xuất theo dõi của họ không? Bạn muốn tự động chấp nhận tất cả những người theo dõi mới hay tự duyệt từng người theo dõi?
search: Tìm kiếm
- search_hint_html: Kiểm soát cách tìm thấy bạn. Bạn có muốn mọi người tìm thấy bạn bằng những gì bạn đã đăng công khai không? Bạn có muốn những người bên ngoài Mastodon tìm thấy hồ sơ của bạn khi tìm kiếm trên web không? Xin lưu ý rằng không thể đảm bảo loại trừ hoàn toàn khỏi tất cả các công cụ tìm kiếm đối với thông tin công khai.
+ search_hint_html: Kiểm soát cách tìm thấy bạn. Bạn có muốn mọi người tìm thấy bạn bằng những gì bạn đã đăng công khai không? Bạn có muốn những người bên ngoài Mastodon tìm thấy hồ sơ của bạn khi tìm kiếm trên web không? Lưu ý là không thể đảm bảo tránh khỏi các công cụ tìm kiếm đối với thông tin công khai.
title: Riêng tư và tiếp cận
privacy_policy:
title: Chính sách bảo mật
@@ -1667,7 +1675,7 @@ vi:
preferences: Chung
profile: Hồ sơ
relationships: Quan hệ
- severed_relationships: Mối quan hệ bị cắt đứt
+ severed_relationships: Quan hệ bị cắt đứt
statuses_cleanup: Tự động xóa tút cũ
strikes: Lần cảnh cáo
two_factor_authentication: Xác minh 2 bước
@@ -1680,7 +1688,7 @@ vi:
user_domain_block: Bạn đã chặn %{target_name}
lost_followers: Mất người theo dõi
lost_follows: Mất người đang theo dõi
- preamble: Bạn có thể mất số lượt theo dõi và người theo dõi khi chặn một máy chủ hoặc khi kiểm duyệt viên của bạn quyết định tạm dừng máy chủ từ xa. Khi điều đó xảy ra, bạn sẽ có thể tải xuống danh sách các mối quan hệ đã bị cắt đứt, để kiểm tra và nhập vào máy chủ khác.
+ preamble: Khi bạn hoặc kiểm duyệt viên máy chủ của bạn chặn một máy chủ, người bạn đang theo dõi và người theo dõi bạn có thể sẽ bị mất. Khi điều đó xảy ra, hãy vào đây tải xuống danh sách các mối quan hệ đã bị cắt đứt, và nhập thủ công.
purged: Thông tin về máy chủ này đã bị quản trị viên máy chủ của bạn xóa sạch.
type: Sự kiện
statuses:
@@ -1700,21 +1708,12 @@ vi:
edited_at_html: Sửa %{date}
errors:
in_reply_not_found: Bạn đang trả lời một tút không còn tồn tại.
- open_in_web: Xem trong web
over_character_limit: vượt quá giới hạn %{max} ký tự
pin_errors:
direct: Không thể ghim những tút nhắn riêng
limit: Bạn đã ghim quá số lượng tút cho phép
ownership: Không thể ghim tút của người khác
reblog: Không thể ghim tút đăng lại
- poll:
- total_people:
- other: "%{count} người bình chọn"
- total_votes:
- other: "%{count} người bình chọn"
- vote: Bình chọn
- show_more: Đọc thêm
- show_thread: Nội dung gốc
title: '%{name}: "%{quote}"'
visibilities:
direct: Nhắn riêng
@@ -1770,7 +1769,7 @@ vi:
contrast: Mastodon (Tương phản)
default: Mastodon (Tối)
mastodon-light: Mastodon (Sáng)
- system: Tự động (chủ đề hệ thống)
+ system: Theo hệ thống
time:
formats:
default: "%-d.%m.%Y %H:%M"
@@ -1833,14 +1832,14 @@ vi:
spam: Spam
violation: Nội dung vi phạm quy tắc cộng đồng
explanation:
- delete_statuses: Vài tút của bạn đã vi phạm nội quy máy chủ và tạm thời bị ẩn bởi kiểm duyệt viên của %{instance}.
+ delete_statuses: Tút của bạn đã vi phạm nội quy máy chủ và tạm thời bị ẩn bởi kiểm duyệt viên của %{instance}.
disable: Bạn không còn có thể sử dụng tài khoản của mình, nhưng hồ sơ của bạn và dữ liệu khác vẫn còn nguyên. Bạn có thể yêu cầu sao lưu dữ liệu của mình, thay đổi cài đặt tài khoản hoặc xóa tài khoản của bạn.
mark_statuses_as_sensitive: Vài tút của bạn đã bị kiểm duyệt viên %{instance} đánh dấu nhạy cảm. Mọi người cần nhấn vào media để xem nó. Bạn có thể tự đánh dấu tài khoản của bạn là nhạy cảm.
sensitive: Từ giờ trở đi, tất cả các media của bạn bạn tải lên sẽ được đánh dấu là nhạy cảm và ẩn đằng sau cảnh báo nhấp chuột.
silence: Bạn vẫn có thể sử dụng tài khoản của mình, nhưng chỉ những người đang theo dõi bạn mới thấy bài đăng của bạn. Bạn cũng bị loại khỏi các tính năng khám phá khác. Tuy nhiên, những người khác vẫn có thể theo dõi bạn.
suspend: Bạn không còn có thể sử dụng tài khoản của bạn, hồ sơ và các dữ liệu khác không còn có thể truy cập được. Trong vòng 30 ngày, bạn vẫn có thể đăng nhập để yêu cầu bản sao dữ liệu của mình cho đến khi dữ liệu bị xóa hoàn toàn, nhưng chúng tôi sẽ giữ lại một số dữ liệu cơ bản để ngăn bạn thoát khỏi việc vô hiệu hóa.
reason: 'Lý do:'
- statuses: 'Tút lưu ý:'
+ statuses: 'Tút vi phạm:'
subject:
delete_statuses: Những tút %{acct} của bạn đã bị xóa bỏ
disable: Tài khoản %{acct} của bạn đã bị vô hiệu hóa
@@ -1906,19 +1905,20 @@ vi:
seamless_external_login: Bạn đã đăng nhập thông qua một dịch vụ bên ngoài, vì vậy mật khẩu và email không khả dụng.
signed_in_as: 'Đăng nhập bằng:'
verification:
- extra_instructions_html: Mẹo: Liên kết trên trang web của bạn có thể ẩn. Phần quan trọng là rel="me"
ngăn chặn việc mạo danh trên các trang web có nội dung do người dùng tạo. Bạn thậm chí có thể sử dụng một thẻ link
trên header của trang thay vì a
, nhưng HTML phải có thể truy cập được mà không cần thực thi JavaScript.
+ extra_instructions_html: Mẹo: Có thể ẩn liên kết trên trang web của bạn. Quan trọng là rel="me"
giúp ngăn chặn việc mạo danh trên các trang web có nội dung do người dùng tạo. Bạn cũng có thể sử dụng một thẻ link
trên header của trang thay vì a
, nhưng HTML phải có thể truy cập được mà không cần thực thi JavaScript.
here_is_how: Cách thực hiện
hint_html: "Xác minh danh tính trên Mastodon là dành cho tất cả mọi người. Dựa trên các tiêu chuẩn web mở, miễn phí bây giờ và mãi mãi. Tất cả những gì bạn cần là một trang web cá nhân để mọi người nhận ra bạn. Khi bạn liên kết đến trang web này từ hồ sơ của mình, chúng tôi sẽ kiểm tra xem trang web đó có liên kết lại với hồ sơ của bạn hay không và hiển thị một chỉ báo trực quan trên đó."
instructions_html: Sao chép và dán mã bên dưới vào mã nguồn trang web của bạn. Sau đó, thêm địa chỉ trang web của bạn vào một trong các trường metadata trên hồ sơ của bạn từ tab "Sửa hồ sơ" và lưu thay đổi.
verification: Xác minh
verified_links: Những liên kết bạn đã xác minh
+ website_verification: Xác minh website
webauthn_credentials:
add: Thêm khóa bảo mật mới
create:
error: Có vấn đề khi thêm khóa bảo mật. Xin thử lại.
success: Đã thêm khóa bảo mật mới thành công.
delete: Xóa
- delete_confirmation: Bạn thật sự muốn xóa khóa bảo mật này?
+ delete_confirmation: Bạn có chắc muốn xóa khóa bảo mật này?
description_html: Nếu bạn kích hoạt khóa bảo mật, bạn sẽ cần dùng một trong những khóa bảo mật đó mỗi khi đăng nhập.
destroy:
error: Có vấn đề khi xóa khóa bảo mật. Xin thử lại.
diff --git a/config/locales/zgh.yml b/config/locales/zgh.yml
index 180fcf2f16..cbd0bc961b 100644
--- a/config/locales/zgh.yml
+++ b/config/locales/zgh.yml
@@ -1,7 +1,6 @@
---
zgh:
accounts:
- follow: ⴹⴼⵕ
followers:
one: ⴰⵎⴹⴼⴰⵕ
other: ⵉⵎⴹⴼⴰⵕⵏ
diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml
index 36b62e535d..8b34da076a 100644
--- a/config/locales/zh-CN.yml
+++ b/config/locales/zh-CN.yml
@@ -7,7 +7,6 @@ zh-CN:
hosted_on: 运行在 %{domain} 上的 Mastodon 实例
title: 关于本站
accounts:
- follow: 关注
followers:
other: 关注者
following: 正在关注
@@ -23,6 +22,8 @@ zh-CN:
admin:
account_actions:
action: 执行操作
+ already_silenced: 此账户已受限。
+ already_suspended: 此帐户已被封禁。
title: 在 %{acct} 上执行管理操作
account_moderation_notes:
create: 新建记录
@@ -44,6 +45,7 @@ zh-CN:
title: 更改 %{username} 的电子邮箱
change_role:
changed_msg: 已成功更改角色!
+ edit_roles: 管理用户角色
label: 更改角色
no_role: 没有角色
title: 更改 %{username} 的角色
@@ -383,9 +385,9 @@ zh-CN:
cancel: 取消
confirm: 封禁
permanent_action: 撤销暂停不会恢复任何数据或关系。
- preamble_html: 您将要暂停 %{domain} 及其子域。
- remove_all_data: 这将从您的实例上删除此域名下账户的所有内容、媒体和个人资料数据。
- stop_communication: 您的实例将停止与这些实例的通信。
+ preamble_html: 你将要暂停 %{domain} 及其子域。
+ remove_all_data: 这将从你的实例上删除此域名下账户的所有内容、媒体和个人资料数据。
+ stop_communication: 你的实例将停止与这些实例的通信。
title: 确认对 %{domain} 的封锁
undo_relationships: 这将解除你的实例与这些实例上账户之间的任何关注。
created_msg: 正在进行域名屏蔽
@@ -590,6 +592,7 @@ zh-CN:
suspend_description_html: 该帐户及其所有内容将无法访问并最终被删除,且无法与该帐户进行互动。 在 30 天内可随时撤销。关闭针对此帐户的所有举报。
actions_description_html: 决定采取何种措施处理此举报。如果对被举报账号采取惩罚性措施,将向其发送一封电子邮件通知。但若选中垃圾信息类别则不会发送通知。
actions_description_remote_html: 决定采取何种行动来解决此举报。 这只会影响您的服务器如何与该远程帐户的通信并处理其内容。
+ actions_no_posts: 该举报没有相关嘟文可供删除
add_to_report: 增加更多举报内容
already_suspended_badges:
local: 已经在此服务器上暂停
@@ -609,7 +612,7 @@ zh-CN:
created_at: 举报时间
delete_and_resolve: 删除嘟文
forwarded: 已转发
- forwarded_replies_explanation: 该举报来自外站用户,涉及外站内容。之所以转发给您,是因为被举报的内容是对您站点一位用户的回复。
+ forwarded_replies_explanation: 该举报来自外站用户,涉及外站内容。之所以转发给你,是因为被举报的内容是对你站点一位用户的回复。
forwarded_to: 转发举报至 %{domain}
mark_as_resolved: 标记为已处理
mark_as_sensitive: 标记为敏感内容
@@ -764,7 +767,7 @@ zh-CN:
disabled: 不对任何人
users: 对本地已登录用户
registrations:
- moderation_recommandation: 在向所有人开放注册之前,请确保您拥有一个人手足够且反应迅速的管理团队!
+ moderation_recommandation: 在向所有人开放注册之前,请确保你拥有一个人手足够且反应迅速的管理团队!
preamble: 控制谁可以在你的服务器上创建账号。
title: 注册
registrations_mode:
@@ -772,7 +775,7 @@ zh-CN:
approved: 注册时需要批准
none: 关闭注册
open: 开放注册
- warning_hint: 我们建议使用“注册必须经过批准”,除非您确信您的管理团队能够及时处理骚扰和恶意注册。
+ warning_hint: 我们建议使用“注册必须经过批准”,除非你确信你的管理团队能够及时处理骚扰和恶意注册。
security:
authorized_fetch: 需要跨站认证
authorized_fetch_hint: 要求外站请求通过验证能够使用户级别与服务器级别的封锁更为严格。然而,这将带来额外的性能负担、减少回复触达范围、并可能导致与一些联邦宇宙服务的兼容性问题。此外,这并不能阻止他人针对性地获取公开嘟文与账户。
@@ -784,7 +787,7 @@ zh-CN:
destroyed_msg: 站点上传的文件已经成功删除!
software_updates:
critical_update: 紧急 — 请尽快更新
- description: 建议你及时更新Mastodon实例,以便获得最新修复和功能。此外,为避免安全问题,有时及时更新Mastodon是至关重要的。出于这些原因,Mastodon每30分钟检查一次更新,并根据您的邮件通知偏好向您发送通知。
+ description: 建议你及时更新Mastodon实例,以便获得最新修复和功能。此外,为避免安全问题,有时及时更新Mastodon是至关重要的。出于这些原因,Mastodon每30分钟检查一次更新,并根据你的邮件通知偏好向你发送通知。
documentation_link: 详细了解
release_notes: 发行说明
title: 可用的更新
@@ -837,17 +840,17 @@ zh-CN:
elasticsearch_health_red:
message_html: Elasticsearch 集群状态不健康(红色),搜索功能不可用
elasticsearch_health_yellow:
- message_html: Elasticsearch 集群不健康(黄色状态),您可能想要调查原因
+ message_html: Elasticsearch 集群不健康(黄色状态),你可能想要调查原因
elasticsearch_index_mismatch:
message_html: Elasticsearch索引映射已过时。请运行tootctl search deploy --only=%{value}
。
elasticsearch_preset:
action: 查看文档
- message_html: 您的Elasticsearch集群有多个节点,但Mastodon未配置好使用它们。
+ message_html: 你的Elasticsearch集群有多个节点,但Mastodon未配置好使用它们。
elasticsearch_preset_single_node:
action: 查看文档
- message_html: 您的Elasticsearch集群只有一个节点,ES_PRESET
应该设置为single_node_cluster
。
+ message_html: 你的Elasticsearch集群只有一个节点,ES_PRESET
应该设置为single_node_cluster
。
elasticsearch_reset_chewy:
- message_html: 您的Elasticsearch系统索引已过时,可能是由于设置更改导致的。请运行tootctl search deploy --reset-chewy
命令来更新它。
+ message_html: 你的Elasticsearch系统索引已过时,可能是由于设置更改导致的。请运行tootctl search deploy --reset-chewy
命令来更新它。
elasticsearch_running_check:
message_html: 无法连接到 Elasticsearch。请检查它是否正在运行,或禁用全文搜索
elasticsearch_version_check:
@@ -884,6 +887,7 @@ zh-CN:
name: 名称
newest: 最新
oldest: 最早
+ open: 以公开身份查看
reset: 重置
review: 审核状态
search: 搜索
@@ -988,7 +992,7 @@ zh-CN:
webhook: Webhook
admin_mailer:
auto_close_registrations:
- body: 由于近期缺乏管理员活动, %{instance} 上的注册已自动切换为需要手动审核,以防止 %{instance} 被潜在的不良行为者用作平台。您可以随时将其切换回开放注册。
+ body: 由于近期缺乏管理员活动, %{instance} 上的注册已自动切换为需要手动审核,以防止 %{instance} 被潜在的不良行为者用作平台。你可以随时将其切换回开放注册。
subject: "%{instance} 的注册已自动切换为需要批准"
new_appeal:
actions:
@@ -1003,7 +1007,7 @@ zh-CN:
next_steps: 你可以批准此申诉并撤销该审核结果,也可以忽略此申诉。
subject: "%{username} 对 %{instance} 的审核结果提出了申诉"
new_critical_software_updates:
- body: 新的紧急更新版本Mastodon已经发布,您可能希望尽快更新!
+ body: 新的紧急更新版本Mastodon已经发布,你可能希望尽快更新!
subject: 适用于 %{instance} 的Mastodon紧急更新已经可用。
new_pending_account:
body: 新账户的详细信息如下。你可以批准或拒绝此申请。
@@ -1013,7 +1017,7 @@ zh-CN:
body_remote: 来自 %{domain} 的用户举报了用户 %{target}
subject: 来自 %{instance} 的用户举报(#%{id})
new_software_updates:
- body: 新的 Mastodon 版本已发布,您可能想要更新!
+ body: 新的 Mastodon 版本已发布,你可能想要更新!
subject: 适用于 %{instance} 的Mastodon版本更新已经可用!
new_trends:
body: 以下项目需要审核才能公开显示:
@@ -1061,18 +1065,18 @@ zh-CN:
auth:
apply_for_account: 申请账号
captcha_confirmation:
- help_html: 如果您在输入验证码时遇到问题,可以通过%{email} 与我们联系,我们将为您提供帮助。
- hint_html: 只剩最后一件事了!我们需要确认您是一个人类(这样我们才能阻止恶意访问!)。请输入下面的验证码,然后点击“继续”。
+ help_html: 如果你在输入验证码时遇到问题,可以通过%{email} 与我们联系,我们将为你提供帮助。
+ hint_html: 只剩最后一件事了!我们需要确认你是一个人类(这样我们才能阻止恶意访问!)。请输入下面的验证码,然后点击“继续”。
title: 安全检查
confirmations:
awaiting_review: 你的邮箱地址已确认!%{domain} 的工作人员正在审核你的注册信息。如果他们批准了你的账户,你将收到一封邮件通知!
- awaiting_review_title: 您的注册申请正在审核中
+ awaiting_review_title: 你的注册申请正在审核中
clicking_this_link: 点击此链接
login_link: 登录
- proceed_to_login_html: 现在您可以继续前往 %{login_link} 。
- redirect_to_app_html: 您应该已被重定向到 %{app_name} 应用程序。如果没有,请尝试 %{clicking_this_link} 或手动返回应用程序。
- registration_complete: 您在 %{domain} 上的注册现已完成!
- welcome_title: 欢迎您,%{name}!
+ proceed_to_login_html: 现在你可以继续前往 %{login_link} 。
+ redirect_to_app_html: 你应该已被重定向到 %{app_name} 应用程序。如果没有,请尝试 %{clicking_this_link} 或手动返回应用程序。
+ registration_complete: 你在 %{domain} 上的注册现已完成!
+ welcome_title: 欢迎你,%{name}!
wrong_email_hint: 如果该邮箱地址不正确,你可以在账户设置中进行更改。
delete_account: 删除帐户
delete_account_html: 如果你想删除你的帐户,请点击这里继续。你需要确认你的操作。
@@ -1110,7 +1114,7 @@ zh-CN:
back: 返回
invited_by: 你可以加入%{domain},这是由于你收到了他人的邀请,邀请来自:
preamble: 这些由 %{domain} 监察员设置和执行。
- preamble_invited: 在您继续之前,请考虑 %{domain} 的管理员设定的基本规则。
+ preamble_invited: 在你继续之前,请考虑 %{domain} 的管理员设定的基本规则。
title: 一些基本规则。
title_invited: 您已经被邀请。
security: 账户安全
@@ -1138,6 +1142,12 @@ zh-CN:
view_strikes: 查看针对你账号的记录
too_fast: 表单提交过快,请重试。
use_security_key: 使用安全密钥
+ author_attribution:
+ example_title: 示例文本
+ hint_html: 控制在 Mastodon 上分享的链接如何显示你的署名。
+ more_from_html: 来自 %{name} 的更多内容
+ s_blog: "%{name} 的博客"
+ title: 作者归属
challenge:
confirm: 继续
hint_html: "注意:接下来一小时内我们不会再次要求你输入密码。"
@@ -1146,7 +1156,6 @@ zh-CN:
crypto:
errors:
invalid_key: 不是有效的 Ed25519 或者 Curve25519 密钥
- invalid_signature: 不是有效的 Ed25519 签名
date:
formats:
default: "%Y年%m月%d日"
@@ -1212,8 +1221,6 @@ zh-CN:
your_appeal_approved: 你的申诉已被批准
your_appeal_pending: 你已提交申诉
your_appeal_rejected: 你的申诉已被驳回
- domain_validator:
- invalid_domain: 不是一个有效的域名
edit_profile:
basic_information: 基本信息
hint_html: "自定义公开资料和嘟文旁边显示的内容。当您填写完整的个人资料并设置了头像时,其他人更有可能关注您并与您互动。"
@@ -1324,26 +1331,26 @@ zh-CN:
too_large: 文件过大
failures: 失败
imported: 已导入
- mismatched_types_warning: 您似乎选择了导入错误的类型,请再次检查。
+ mismatched_types_warning: 你似乎选择了导入错误的类型,请再次检查。
modes:
merge: 合并
merge_long: 保留现有记录并添加新的记录
overwrite: 覆盖
overwrite_long: 将当前记录替换为新记录
overwrite_preambles:
- blocking_html: 您即将使用来自 %{filename} 的最多 %{total_items} 个账户替换您的屏蔽列表。
- bookmarks_html: 您即将使用来自 %{filename} 的 %{total_items} 篇嘟文替换您的书签。
- domain_blocking_html: 您即将使用来自 %{filename} 的最多 %{total_items} 个域名替换您的域名屏蔽列表。
- following_html: 您即将从 %{filename} 关注 %{total_items} 个账户,并停止关注其他任何人。
+ blocking_html: 你即将使用来自 %{filename} 的最多 %{total_items} 个账户替换你的屏蔽列表。
+ bookmarks_html: 你即将使用来自 %{filename} 的 %{total_items} 篇嘟文替换你的书签。
+ domain_blocking_html: 你即将使用来自 %{filename} 的最多 %{total_items} 个域名替换你的域名屏蔽列表。
+ following_html: 你即将从 %{filename} 关注 %{total_items} 个账户,并停止关注其他任何人。
lists_html: 你即将用 %{filename} 的内容替换你的列表。新列表中将添加 %{total_items} 个账户。
- muting_html: 您即将使用来自 %{filename} 的最多 %{total_items} 个账户替换您已隐藏的账户列表。
+ muting_html: 你即将使用来自 %{filename} 的最多 %{total_items} 个账户替换你已隐藏的账户列表。
preambles:
- blocking_html: 您即将从 %{filename} 中封锁多达 %{total_items} 个账户。
- bookmarks_html: 您即将把来自 %{filename} 的 %{total_items} 篇嘟文添加到您的书签中。
- domain_blocking_html: 您即将从 %{filename} 中屏蔽 %{total_items} 个域名。
- following_html: 您即将从 %{filename} 关注最多 %{total_items} 个账户。
+ blocking_html: 你即将从 %{filename} 中封锁多达 %{total_items} 个账户。
+ bookmarks_html: 你即将把来自 %{filename} 的 %{total_items} 篇嘟文添加到你的书签中。
+ domain_blocking_html: 你即将从 %{filename} 中屏蔽 %{total_items} 个域名。
+ following_html: 你即将从 %{filename} 关注最多 %{total_items} 个账户。
lists_html: 你即将从 %{filename} 中添加最多 %{total_items} 个账户到你的列表中。如果没有可用列表,将创建新的列表。
- muting_html: 您即将从 %{filename} 中隐藏 %{total_items} 个账户。
+ muting_html: 你即将从 %{filename} 中隐藏 %{total_items} 个账户。
preface: 你可以在此导入你在其他实例导出的数据,比如你所关注或屏蔽的用户列表。
recent_imports: 最近导入
states:
@@ -1413,7 +1420,7 @@ zh-CN:
unsubscribe:
action: 是,取消订阅
complete: 已取消订阅
- confirmation_html: 你确定要退订来自 %{domain} 上的 Mastodon 的 %{type} 到您的邮箱 %{email} 吗?您可以随时在邮件通知设置中重新订阅。
+ confirmation_html: 你确定要退订来自 %{domain} 上的 Mastodon 的 %{type} 到你的邮箱 %{email} 吗?你可以随时在邮件通知设置中重新订阅。
emails:
notification_emails:
favourite: 嘟文被喜欢邮件通知
@@ -1427,6 +1434,7 @@ zh-CN:
media_attachments:
validations:
images_and_video: 无法在嘟文中同时插入视频和图片
+ not_found: 媒体 %{ids} 未找到,有可能已随附于另一条嘟文。
not_ready: 不能附加还在处理中的文件。请稍后再试!
too_many: 最多只能添加 4 张图片
migrations:
@@ -1539,7 +1547,7 @@ zh-CN:
expired: 投票已经结束
invalid_choice: 被选中的投票选项不存在
over_character_limit: 每条不能超过 %{max} 个字符
- self_vote: 您不能参与自己发起的投票
+ self_vote: 你不能参与自己发起的投票
too_few_options: 至少需要两个选项
too_many_options: 不能超过 %{max} 项
preferences:
@@ -1547,7 +1555,7 @@ zh-CN:
posting_defaults: 发布默认值
public_timelines: 公共时间轴
privacy:
- hint_html: "自定义您希望如何找到您的个人资料和嘟文。启用Mastodon中的各种功能可以帮助您扩大受众范围。请花点时间查看这些设置,确保它们适合您的使用情况。"
+ hint_html: "自定义你希望如何找到你的个人资料和嘟文。启用Mastodon中的各种功能可以帮助你扩大受众范围。请花点时间查看这些设置,确保它们适合你的使用情况。"
privacy: 隐私
privacy_hint_html: 控制你愿意向他人透露多少信息。通过浏览他人的关注列表和查看他们发嘟所用的应用,人们可以发现有趣的用户和酷炫的应用,但你可能更喜欢将其隐藏起来。
reach: 范围
@@ -1562,8 +1570,8 @@ zh-CN:
limit_reached: 互动种类的限制
unrecognized_emoji: 不是一个可识别的表情
redirects:
- prompt: 如果您信任此链接,请单击以继续跳转。
- title: 您正在离开 %{instance} 。
+ prompt: 如果你信任此链接,请单击以继续跳转。
+ title: 你正在离开 %{instance} 。
relationships:
activity: 账号活动
confirm_follow_selected_followers: 您确定想要关注所选的关注者吗?
@@ -1700,21 +1708,12 @@ zh-CN:
edited_at_html: 编辑于 %{date}
errors:
in_reply_not_found: 你回复的嘟文似乎不存在
- open_in_web: 在站内打开
over_character_limit: 超过了 %{max} 字的限制
pin_errors:
direct: 仅对被提及的用户可见的帖子不能被置顶
limit: 你所固定的嘟文数量已达到上限
ownership: 不能置顶别人的嘟文
reblog: 不能置顶转嘟
- poll:
- total_people:
- other: "%{count} 人"
- total_votes:
- other: "%{count} 票"
- vote: 投票
- show_more: 显示更多
- show_thread: 显示全部对话
title: "%{name}:“%{quote}”"
visibilities:
direct: 私信
@@ -1801,22 +1800,22 @@ zh-CN:
action: 账户设置
explanation: 你于 %{appeal_date} 对 %{strike_date} 在你账号上做出的处罚提出的申诉已被批准,你的账号已回到正常状态。
subject: 你于 %{date} 提出的申诉已被批准
- subtitle: 您的账户已再次回到良好状态。
+ subtitle: 你的账户已再次回到良好状态。
title: 申诉已批准
appeal_rejected:
explanation: 你于 %{appeal_date} 对 %{strike_date} 在你账号上做出的处罚提出的申诉已被驳回。
subject: 你于 %{date} 提出的申诉已被驳回
- subtitle: 您的申诉已被驳回。
+ subtitle: 你的申诉已被驳回。
title: 申诉已驳回
backup_ready:
- explanation: 您之前请求为您的 Mastodon 账户创建一份完整的备份。
+ explanation: 你之前请求为你的 Mastodon 账户创建一份完整的备份。
extra: 现在它可以下载了!
subject: 你的存档已经准备完毕
title: 存档导出
failed_2fa:
details: 以下是该次登录尝试的详情:
- explanation: 有人试图登录到您的账户,但提供了无效的辅助认证因子。
- further_actions_html: 如果这不是您所为,您的密码可能已经泄露,建议您立即 %{action} 。
+ explanation: 有人试图登录到你的账户,但提供了无效的辅助认证因子。
+ further_actions_html: 如果这不是你所为,你的密码可能已经泄露,建议你立即 %{action} 。
subject: 辅助认证失败
title: 辅助认证失败
suspicious_sign_in:
@@ -1862,24 +1861,24 @@ zh-CN:
apps_ios_action: 从 App Store 下载
apps_step: 下载我们的官方应用。
apps_title: Mastodon应用
- checklist_subtitle: 让我们带您开启这片社交新天地:
+ checklist_subtitle: 让我们带你开启这片社交新天地:
checklist_title: 欢迎清单
edit_profile_action: 个性化
- edit_profile_step: 完善个人资料,提升您的互动体验。
- edit_profile_title: 个性化您的个人资料
+ edit_profile_step: 完善个人资料,提升你的互动体验。
+ edit_profile_title: 个性化你的个人资料
explanation: 下面是几个小贴士,希望它们能帮到你
feature_action: 了解更多
- feature_audience: Mastodon为您提供了无需中间商即可管理受众的独特可能。Mastodon可被部署在您自己的基础设施上,允许您关注其它任何Mastodon在线服务器的用户,或被任何其他在线 Mastodon 服务器的用户关注,并且不受您之外的任何人控制。
- feature_audience_title: 放手去建立起您的受众
- feature_control: 您最清楚您想在你自己的主页中看到什么动态。没有算法或广告浪费您的时间。您可以用一个账号关注任何 Mastodon 服务器上的任何人,并按时间顺序获得他们发布的嘟文,让您的互联网的角落更合自己的心意。
+ feature_audience: Mastodon为你提供了无需中间商即可管理受众的独特可能。Mastodon可被部署在你自己的基础设施上,允许你关注其它任何Mastodon在线服务器的用户,或被任何其他在线 Mastodon 服务器的用户关注,并且不受你之外的任何人控制。
+ feature_audience_title: 放手去建立起你的受众
+ feature_control: 你最清楚你想在你自己的主页中看到什么动态。没有算法或广告浪费你的时间。你可以用一个账号关注任何 Mastodon 服务器上的任何人,并按时间顺序获得他们发布的嘟文,让你的互联网的角落更合自己的心意。
feature_control_title: 掌控自己的时间线
- feature_creativity: Mastodon支持音频、视频和图片、无障碍描述、投票、内容警告, 动画头像、自定义表情包、缩略图裁剪控制等功能,帮助您在网上尽情表达自己。无论您是要发布您的艺术作品、音乐还是播客,Mastodon 都能为您服务。
+ feature_creativity: Mastodon支持音频、视频和图片、无障碍描述、投票、内容警告, 动画头像、自定义表情包、缩略图裁剪控制等功能,帮助你在网上尽情表达自己。无论你是要发布你的艺术作品、音乐还是播客,Mastodon 都能为你服务。
feature_creativity_title: 无与伦比的创造力
- feature_moderation: Mastodon将决策权交还给您。每个服务器都会创建自己的规则和条例,并在站点内施行,而不是像企业社交媒体那样居高临下,这使得它可以最灵活地响应不同人群的需求。加入一个您认同其规则的服务器,或托管您自己的服务器。
+ feature_moderation: Mastodon将决策权交还给你。每个服务器都会创建自己的规则和条例,并在站点内施行,而不是像企业社交媒体那样居高临下,这使得它可以最灵活地响应不同人群的需求。加入一个你认同其规则的服务器,或托管你自己的服务器。
feature_moderation_title: 管理,本应如此
follow_action: 关注
follow_step: 关注有趣的人,这就是Mastodon的意义所在。
- follow_title: 个性化您的首页动态
+ follow_title: 个性化你的首页动态
follows_subtitle: 关注知名账户
follows_title: 推荐关注
follows_view_more: 查看更多可关注的人
@@ -1890,10 +1889,10 @@ zh-CN:
hashtags_view_more: 查看更多热门话题标签
post_action: 撰写
post_step: 向世界打个招呼吧。
- post_title: 发布您的第一条嘟文
+ post_title: 发布你的第一条嘟文
share_action: 分享
- share_step: 让您的朋友知道如何在Mastodon找到你。
- share_title: 分享您的Mastodon个人资料
+ share_step: 让你的朋友知道如何在Mastodon找到你。
+ share_title: 分享你的Mastodon个人资料
sign_in_action: 登录
subject: 欢迎来到 Mastodon
title: "%{name},欢迎你的加入!"
@@ -1906,12 +1905,13 @@ zh-CN:
seamless_external_login: 你通过外部服务登录,因此密码和邮件设置不可用。
signed_in_as: 当前登录的账户:
verification:
- extra_instructions_html: 提示:您网站上的链接可能是不可见的。重要的部分是 rel="me"
,它可以防止在具有用户生成内容的网站上冒充身份。您甚至可以在页面头部使用 link
标签而不是 a
,但 HTML 必须能够在不执行 JavaScript 的情况下访问。
+ extra_instructions_html: 提示:你网站上的链接可能是不可见的。重要的部分是 rel="me"
,它可以防止在具有用户生成内容的网站上冒充身份。你甚至可以在页面头部使用 link
标签而不是 a
,但 HTML 必须能够在不执行 JavaScript 的情况下访问。
here_is_how: 具体方法如下:
- hint_html: "在Mastodon上验证您的身份对每个人都是必要的。基于开放网络标准,现在和将来永远免费。您只需要一个被人们认可的个人网站。当您在个人资料中链接到这个网站时,我们会检查该网站是否回链到您的资料,并显示一个指示符号。"
- instructions_html: 将下面的代码复制并粘贴到您网站的HTML中。然后在“编辑个人资料”选项卡中的附加字段之一添加您网站的地址,并保存更改。
+ hint_html: "在Mastodon上验证你的身份对每个人都是必要的。基于开放网络标准,现在和将来永远免费。你只需要一个被人们认可的个人网站。当你在个人资料中链接到这个网站时,我们会检查该网站是否回链到你的资料,并显示一个指示符号。"
+ instructions_html: 将下面的代码复制并粘贴到你网站的HTML中。然后在“编辑个人资料”选项卡中的附加字段之一添加你网站的地址,并保存更改。
verification: 验证
- verified_links: 您已验证的链接
+ verified_links: 你已验证的链接
+ website_verification: 网站验证
webauthn_credentials:
add: 添加新的安全密钥
create:
diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml
index 26743d2cb1..598c65d049 100644
--- a/config/locales/zh-HK.yml
+++ b/config/locales/zh-HK.yml
@@ -7,7 +7,6 @@ zh-HK:
hosted_on: 在 %{domain} 運作的 Mastodon 伺服器
title: 關於
accounts:
- follow: 關注
followers:
other: 關注者
following: 正在關注
@@ -1072,7 +1071,6 @@ zh-HK:
crypto:
errors:
invalid_key: 不是一個有效的 Ed25519 或 Curve25519 密鑰
- invalid_signature: 不是一個有效的 Ed25519 簽名
date:
formats:
default: "%Y年%b月%d日"
@@ -1135,8 +1133,6 @@ zh-HK:
your_appeal_approved: 你的申訴已獲批准
your_appeal_pending: 你已提交申訴
your_appeal_rejected: 你的申訴已被駁回
- domain_validator:
- invalid_domain: 不是一個可用域名
edit_profile:
basic_information: 基本資料
hint_html: "自訂你的公開個人檔案和帖文內容。當你有完整的個人檔案和頭像時,其他人更願意追蹤你和與你互動。"
@@ -1609,21 +1605,12 @@ zh-HK:
edited_at_html: 編輯於 %{date}
errors:
in_reply_not_found: 你所回覆的嘟文並不存在。
- open_in_web: 開啟網頁
over_character_limit: 超過了 %{max} 字的限制
pin_errors:
direct: 無法將只有被提及使用者可見的帖文置頂
limit: 你所置頂的文章數量已經達到上限
ownership: 不能置頂他人的文章
reblog: 不能置頂轉推
- poll:
- total_people:
- other: "%{count} 人"
- total_votes:
- other: "%{count} 票"
- vote: 投票
- show_more: 顯示更多
- show_thread: 顯示討論串
title: "%{name}:「%{quote}」"
visibilities:
direct: 私人訊息
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index f85646b5bc..41c4c8a534 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -7,7 +7,6 @@ zh-TW:
hosted_on: 於 %{domain} 託管之 Mastodon 站點
title: 關於本站
accounts:
- follow: 跟隨
followers:
other: 跟隨者
following: 正在跟隨
@@ -23,6 +22,8 @@ zh-TW:
admin:
account_actions:
action: 執行動作
+ already_silenced: 此帳號已被限制。
+ already_suspended: 此帳號已被停權。
title: 對 %{acct} 執行站務動作
account_moderation_notes:
create: 新增站務記錄
@@ -44,6 +45,7 @@ zh-TW:
title: 為 %{username} 變更電子郵件地址
change_role:
changed_msg: 成功修改角色!
+ edit_roles: 管理使用者權限
label: 變更角色
no_role: 沒有角色
title: 為 %{username} 變更角色
@@ -590,6 +592,7 @@ zh-TW:
suspend_description_html: 此帳號及其所有內容將不可被存取並且最終被移除,並且無法與之進行互動。三十天內可以撤銷此動作。關閉所有對此帳號之檢舉報告。
actions_description_html: 決定應對此報告採取何種行動。若您對檢舉之帳號採取懲罰措施,則將對他們發送 e-mail 通知,除非選擇了 垃圾郵件 類別。
actions_description_remote_html: 決定將對此檢舉報告採取何種動作。這將僅作用於您的伺服器與此遠端帳號及其內容之通訊行為。
+ actions_no_posts: 此報告無任何需要刪除之相關嘟文
add_to_report: 加入更多至報告
already_suspended_badges:
local: 已自此伺服器停權
@@ -1141,6 +1144,12 @@ zh-TW:
view_strikes: 檢視針對您帳號過去的警示
too_fast: 送出表單的速度太快跟不上,請稍後再試。
use_security_key: 使用安全金鑰
+ author_attribution:
+ example_title: 範例文字
+ hint_html: 控制如何於 Mastodon 上分享連結時註明您的貢獻。
+ more_from_html: 來自 %{name} 之更多內容
+ s_blog: "%{name} 的部落格"
+ title: 作者署名
challenge:
confirm: 繼續
hint_html: "温馨小提醒: 我們於接下來一小時內不會再要求您輸入密碼。"
@@ -1149,7 +1158,6 @@ zh-TW:
crypto:
errors:
invalid_key: 這不是一把有效的 Ed25519 或 Curve25519 金鑰
- invalid_signature: 這不是有效的 Ed25519 簽章
date:
formats:
default: "%Y年%b月%d日"
@@ -1215,8 +1223,6 @@ zh-TW:
your_appeal_approved: 您的申訴已被批准
your_appeal_pending: 您已遞交申訴
your_appeal_rejected: 您的申訴已被駁回
- domain_validator:
- invalid_domain: 並非一個有效網域
edit_profile:
basic_information: 基本資訊
hint_html: "自訂人們能於您個人檔案及嘟文旁所見之內容。當您完成填寫個人檔案及設定大頭貼後,其他人們比較願意跟隨您並與您互動。"
@@ -1265,7 +1271,7 @@ zh-TW:
home: 首頁時間軸
notifications: 通知
public: 公開時間軸
- thread: 對話
+ thread: 討論串
edit:
add_keyword: 新增關鍵字
keywords: 關鍵字
@@ -1430,6 +1436,7 @@ zh-TW:
media_attachments:
validations:
images_and_video: 無法於已有圖片之嘟文中加入影片
+ not_found: 找不到多媒體 %{ids} 或已附加於另一嘟文中
not_ready: 修但幾勒!不能附加未完成處理的檔案欸,咁按呢?
too_many: 無法加入超過 4 個檔案
migrations:
@@ -1703,21 +1710,12 @@ zh-TW:
edited_at_html: 編輯於 %{date}
errors:
in_reply_not_found: 您嘗試回覆的嘟文看起來不存在。
- open_in_web: 以網頁開啟
over_character_limit: 已超過 %{max} 字的限制
pin_errors:
direct: 無法釘選只有僅提及使用者可見之嘟文
limit: 釘選嘟文的數量已達上限
ownership: 不能釘選他人的嘟文
reblog: 不能釘選轉嘟
- poll:
- total_people:
- other: "%{count} 個人"
- total_votes:
- other: "%{count} 票"
- vote: 投票
- show_more: 顯示更多
- show_thread: 顯示討論串
title: "%{name}:「%{quote}」"
visibilities:
direct: 私訊
@@ -1915,6 +1913,7 @@ zh-TW:
instructions_html: 複製及貼上以下程式碼至您個人網站之 HTML 中。接著透過「編輯個人檔案」將您網站網址加入您個人網站之額外欄位中,並儲存變更。
verification: 驗證連結
verified_links: 已驗證連結
+ website_verification: 網站驗證
webauthn_credentials:
add: 新增安全金鑰
create:
diff --git a/config/routes.rb b/config/routes.rb
index 242ca06262..79b374e413 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -127,6 +127,8 @@ Rails.application.routes.draw do
end
resources :replies, only: [:index], module: :activitypub
+ resources :likes, only: [:index], module: :activitypub
+ resources :shares, only: [:index], module: :activitypub
end
resources :followers, only: [:index], controller: :follower_accounts
@@ -135,7 +137,6 @@ Rails.application.routes.draw do
scope module: :activitypub do
resource :outbox, only: [:show]
resource :inbox, only: [:create]
- resource :claim, only: [:create]
resources :collections, only: [:show]
resource :followers_synchronization, only: [:show]
end
diff --git a/config/routes/api.rb b/config/routes/api.rb
index 7a765492a6..ff195bccb0 100644
--- a/config/routes/api.rb
+++ b/config/routes/api.rb
@@ -74,23 +74,6 @@ namespace :api, format: false do
end
end
- # namespace :crypto do
- # resources :deliveries, only: :create
-
- # namespace :keys do
- # resource :upload, only: [:create]
- # resource :query, only: [:create]
- # resource :claim, only: [:create]
- # resource :count, only: [:show]
- # end
-
- # resources :encrypted_messages, only: [:index] do
- # collection do
- # post :clear
- # end
- # end
- # end
-
resources :conversations, only: [:index, :destroy] do
member do
post :read
@@ -348,10 +331,8 @@ namespace :api, format: false do
namespace :notifications do
resource :policy, only: [:show, :update]
end
- end
- namespace :v2_alpha do
- resources :notifications, only: [:index, :show] do
+ resources :notifications, param: :group_key, only: [:index, :show] do
collection do
post :clear
get :unread_count
@@ -360,6 +341,8 @@ namespace :api, format: false do
member do
post :dismiss
end
+
+ resources :accounts, only: [:index], module: :notifications
end
end
diff --git a/config/routes/settings.rb b/config/routes/settings.rb
index 6f166850ee..d83974071f 100644
--- a/config/routes/settings.rb
+++ b/config/routes/settings.rb
@@ -62,7 +62,7 @@ namespace :settings do
resource :delete, only: [:show, :destroy]
resource :migration, only: [:show, :create]
- resource :verification, only: :show
+ resource :verification, only: [:show, :update]
resource :privacy, only: [:show, :update], controller: 'privacy'
namespace :migration do
diff --git a/config/secrets.yml b/config/secrets.yml
deleted file mode 100644
index 51681d7a5c..0000000000
--- a/config/secrets.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-# Be sure to restart your server when you modify this file.
-
-# Your secret key is used for verifying the integrity of signed cookies.
-# If you change this key, all old signed cookies will become invalid!
-
-# Make sure the secret is at least 30 characters and all random,
-# no regular words or you'll be exposed to dictionary attacks.
-# You can use `rails secret` to generate a secure secret key.
-
-# Make sure the secrets in this file are kept private
-# if you're sharing your code publicly.
-
-development:
- secret_key_base: d4398e4af52f1fc5be5c3c8764e9ecce7beac5462826cb8b649373b2aad5a0f133598ed817c4e9931e943041460d6b6eda40a854e825e1bbd510c4594b1538f2
-
-test:
- secret_key_base: 5be187ddbd651211a906f9aa399f4a148edf6e06b971c7c0b5429b9483df6e21d262cc846447d0f89b89c32d56a99e151039df5dd874ede7f712afbe041a9269
-
-# Do not keep production secrets in the repository,
-# instead read values from the environment.
-production:
- secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
diff --git a/db/migrate/20161122163057_remove_unneeded_indexes.rb b/db/migrate/20161122163057_remove_unneeded_indexes.rb
index 7ed92127d7..2496184703 100644
--- a/db/migrate/20161122163057_remove_unneeded_indexes.rb
+++ b/db/migrate/20161122163057_remove_unneeded_indexes.rb
@@ -2,8 +2,8 @@
class RemoveUnneededIndexes < ActiveRecord::Migration[5.0]
def change
- remove_index :notifications, name: 'index_notifications_on_account_id'
- remove_index :settings, name: 'index_settings_on_target_type_and_target_id'
- remove_index :statuses_tags, name: 'index_statuses_tags_on_tag_id'
+ remove_index :notifications, :account_id, name: 'index_notifications_on_account_id'
+ remove_index :settings, [:target_type, :target_id], name: 'index_settings_on_target_type_and_target_id'
+ remove_index :statuses_tags, :tag_id, name: 'index_statuses_tags_on_tag_id'
end
end
diff --git a/db/migrate/20170920032311_fix_reblogs_in_feeds.rb b/db/migrate/20170920032311_fix_reblogs_in_feeds.rb
index fd6ad39f08..e752915fb9 100644
--- a/db/migrate/20170920032311_fix_reblogs_in_feeds.rb
+++ b/db/migrate/20170920032311_fix_reblogs_in_feeds.rb
@@ -2,7 +2,7 @@
class FixReblogsInFeeds < ActiveRecord::Migration[5.1]
def up
- redis = RedisConfiguration.pool.checkout
+ redis = RedisConnection.pool.checkout
fm = FeedManager.instance
# Old scheme:
diff --git a/db/migrate/20171129172043_add_index_on_stream_entries.rb b/db/migrate/20171129172043_add_index_on_stream_entries.rb
index c959135c22..e861cdc2d1 100644
--- a/db/migrate/20171129172043_add_index_on_stream_entries.rb
+++ b/db/migrate/20171129172043_add_index_on_stream_entries.rb
@@ -5,6 +5,6 @@ class AddIndexOnStreamEntries < ActiveRecord::Migration[5.2]
def change
add_index :stream_entries, [:account_id, :activity_type, :id], algorithm: :concurrently
- remove_index :stream_entries, name: :index_stream_entries_on_account_id
+ remove_index :stream_entries, :account_id, name: :index_stream_entries_on_account_id
end
end
diff --git a/db/migrate/20171212195226_remove_duplicate_indexes_in_lists.rb b/db/migrate/20171212195226_remove_duplicate_indexes_in_lists.rb
index 362b1367df..6f51f0a063 100644
--- a/db/migrate/20171212195226_remove_duplicate_indexes_in_lists.rb
+++ b/db/migrate/20171212195226_remove_duplicate_indexes_in_lists.rb
@@ -2,7 +2,7 @@
class RemoveDuplicateIndexesInLists < ActiveRecord::Migration[5.2]
def change
- remove_index :list_accounts, name: 'index_list_accounts_on_account_id'
- remove_index :list_accounts, name: 'index_list_accounts_on_list_id'
+ remove_index :list_accounts, :account_id, name: 'index_list_accounts_on_account_id'
+ remove_index :list_accounts, :list_id, name: 'index_list_accounts_on_list_id'
end
end
diff --git a/db/migrate/20171226094803_more_faster_index_on_notifications.rb b/db/migrate/20171226094803_more_faster_index_on_notifications.rb
index 429eab96a1..b2fc040e2e 100644
--- a/db/migrate/20171226094803_more_faster_index_on_notifications.rb
+++ b/db/migrate/20171226094803_more_faster_index_on_notifications.rb
@@ -5,6 +5,6 @@ class MoreFasterIndexOnNotifications < ActiveRecord::Migration[5.2]
def change
add_index :notifications, [:account_id, :id], order: { id: :desc }, algorithm: :concurrently
- remove_index :notifications, name: :index_notifications_on_id_and_account_id_and_activity_type
+ remove_index :notifications, [:id, :account_id, :activity_type], name: :index_notifications_on_id_and_account_id_and_activity_type
end
end
diff --git a/db/migrate/20180106000232_add_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb b/db/migrate/20180106000232_add_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb
index 1531c4dd29..4c3a25e838 100644
--- a/db/migrate/20180106000232_add_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb
+++ b/db/migrate/20180106000232_add_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb
@@ -7,6 +7,6 @@ class AddIndexOnStatusesForApiV1AccountsAccountIdStatuses < ActiveRecord::Migrat
safety_assured do
add_index :statuses, [:account_id, :id, :visibility, :updated_at], order: { id: :desc }, algorithm: :concurrently, name: :index_statuses_20180106
end
- remove_index :statuses, name: :index_statuses_on_account_id_id
+ remove_index :statuses, [:account_id, :id], name: :index_statuses_on_account_id_id
end
end
diff --git a/db/migrate/20180617162849_remove_unused_indexes.rb b/db/migrate/20180617162849_remove_unused_indexes.rb
index 14766589fd..cf8faceb3a 100644
--- a/db/migrate/20180617162849_remove_unused_indexes.rb
+++ b/db/migrate/20180617162849_remove_unused_indexes.rb
@@ -2,8 +2,8 @@
class RemoveUnusedIndexes < ActiveRecord::Migration[5.2]
def change
- remove_index :statuses, name: 'index_statuses_on_conversation_id'
- remove_index :users, name: 'index_users_on_filtered_languages'
- remove_index :backups, name: 'index_backups_on_user_id'
+ remove_index :statuses, :conversation_id, name: 'index_statuses_on_conversation_id'
+ remove_index :users, :filtered_languages, name: 'index_users_on_filtered_languages'
+ remove_index :backups, :user_id, name: 'index_backups_on_user_id'
end
end
diff --git a/db/migrate/20200407202420_migrate_unavailable_inboxes.rb b/db/migrate/20200407202420_migrate_unavailable_inboxes.rb
index a79045839b..3caacbe90b 100644
--- a/db/migrate/20200407202420_migrate_unavailable_inboxes.rb
+++ b/db/migrate/20200407202420_migrate_unavailable_inboxes.rb
@@ -4,7 +4,7 @@ class MigrateUnavailableInboxes < ActiveRecord::Migration[5.2]
disable_ddl_transaction!
def up
- redis = RedisConfiguration.pool.checkout
+ redis = RedisConnection.pool.checkout
urls = redis.smembers('unavailable_inboxes')
hosts = urls.filter_map do |url|
diff --git a/db/migrate/20240909014637_add_attribution_domains_to_accounts.rb b/db/migrate/20240909014637_add_attribution_domains_to_accounts.rb
new file mode 100644
index 0000000000..e90f6f1ede
--- /dev/null
+++ b/db/migrate/20240909014637_add_attribution_domains_to_accounts.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddAttributionDomainsToAccounts < ActiveRecord::Migration[7.1]
+ def change
+ add_column :accounts, :attribution_domains, :string, array: true, default: []
+ end
+end
diff --git a/db/post_migrate/20240720140205_drop_end_to_end_message_tables.rb b/db/post_migrate/20240720140205_drop_end_to_end_message_tables.rb
new file mode 100644
index 0000000000..dd5662885c
--- /dev/null
+++ b/db/post_migrate/20240720140205_drop_end_to_end_message_tables.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class DropEndToEndMessageTables < ActiveRecord::Migration[7.1]
+ def up
+ drop_table :system_keys
+ drop_table :one_time_keys
+ drop_table :encrypted_messages
+ drop_table :devices
+ safety_assured { remove_column :accounts, :devices_url }
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
diff --git a/db/post_migrate/20240916190140_remove_crypto_scope_values.rb b/db/post_migrate/20240916190140_remove_crypto_scope_values.rb
new file mode 100644
index 0000000000..8caf5b801d
--- /dev/null
+++ b/db/post_migrate/20240916190140_remove_crypto_scope_values.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class RemoveCryptoScopeValues < ActiveRecord::Migration[7.1]
+ def up
+ applications.in_batches do |records|
+ records.update_all(<<~SQL.squish)
+ scopes = TRIM(REPLACE(scopes, 'crypto', ''))
+ SQL
+ end
+
+ tokens.in_batches do |records|
+ records.update_all(<<~SQL.squish)
+ scopes = TRIM(REPLACE(scopes, 'crypto', ''))
+ SQL
+ end
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+
+ private
+
+ def applications
+ Doorkeeper::Application
+ .where("scopes LIKE '%crypto%'")
+ end
+
+ def tokens
+ Doorkeeper::AccessToken
+ .where("scopes LIKE '%crypto%'")
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 87351374a4..0fc93ee89a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.1].define(version: 2024_08_08_125420) do
+ActiveRecord::Schema[7.1].define(version: 2024_09_16_190140) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -193,13 +193,13 @@ ActiveRecord::Schema[7.1].define(version: 2024_08_08_125420) do
t.boolean "hide_collections"
t.integer "avatar_storage_schema_version"
t.integer "header_storage_schema_version"
- t.string "devices_url"
t.datetime "sensitized_at", precision: nil
t.integer "suspension_origin"
t.boolean "trendable"
t.datetime "reviewed_at", precision: nil
t.datetime "requested_review_at", precision: nil
t.boolean "indexable", default: false, null: false
+ t.string "attribution_domains", default: [], array: true
t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
t.index "lower((username)::text), COALESCE(lower((domain)::text), ''::text)", name: "index_accounts_on_username_and_domain_lower", unique: true
t.index ["domain", "id"], name: "index_accounts_on_domain_and_id"
@@ -411,19 +411,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_08_08_125420) do
t.index ["account_id"], name: "index_custom_filters_on_account_id"
end
- create_table "devices", force: :cascade do |t|
- t.bigint "access_token_id"
- t.bigint "account_id"
- t.string "device_id", default: "", null: false
- t.string "name", default: "", null: false
- t.text "fingerprint_key", default: "", null: false
- t.text "identity_key", default: "", null: false
- t.datetime "created_at", precision: nil, null: false
- t.datetime "updated_at", precision: nil, null: false
- t.index ["access_token_id"], name: "index_devices_on_access_token_id"
- t.index ["account_id"], name: "index_devices_on_account_id"
- end
-
create_table "domain_allows", force: :cascade do |t|
t.string "domain", default: "", null: false
t.datetime "created_at", precision: nil, null: false
@@ -453,20 +440,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_08_08_125420) do
t.index ["domain"], name: "index_email_domain_blocks_on_domain", unique: true
end
- create_table "encrypted_messages", id: :bigint, default: -> { "timestamp_id('encrypted_messages'::text)" }, force: :cascade do |t|
- t.bigint "device_id"
- t.bigint "from_account_id"
- t.string "from_device_id", default: "", null: false
- t.integer "type", default: 0, null: false
- t.text "body", default: "", null: false
- t.text "digest", default: "", null: false
- t.text "message_franking", default: "", null: false
- t.datetime "created_at", precision: nil, null: false
- t.datetime "updated_at", precision: nil, null: false
- t.index ["device_id"], name: "index_encrypted_messages_on_device_id"
- t.index ["from_account_id"], name: "index_encrypted_messages_on_from_account_id"
- end
-
create_table "favourites", force: :cascade do |t|
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
@@ -780,17 +753,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_08_08_125420) do
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
end
- create_table "one_time_keys", force: :cascade do |t|
- t.bigint "device_id"
- t.string "key_id", default: "", null: false
- t.text "key", default: "", null: false
- t.text "signature", default: "", null: false
- t.datetime "created_at", precision: nil, null: false
- t.datetime "updated_at", precision: nil, null: false
- t.index ["device_id"], name: "index_one_time_keys_on_device_id"
- t.index ["key_id"], name: "index_one_time_keys_on_key_id"
- end
-
create_table "pghero_space_stats", force: :cascade do |t|
t.text "database"
t.text "schema"
@@ -1118,12 +1080,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_08_08_125420) do
t.index ["status_id"], name: "index_statuses_tags_on_status_id"
end
- create_table "system_keys", force: :cascade do |t|
- t.binary "key"
- t.datetime "created_at", precision: nil, null: false
- t.datetime "updated_at", precision: nil, null: false
- end
-
create_table "tag_follows", force: :cascade do |t|
t.bigint "tag_id", null: false
t.bigint "account_id", null: false
@@ -1320,11 +1276,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_08_08_125420) do
add_foreign_key "custom_filter_statuses", "custom_filters", on_delete: :cascade
add_foreign_key "custom_filter_statuses", "statuses", on_delete: :cascade
add_foreign_key "custom_filters", "accounts", on_delete: :cascade
- add_foreign_key "devices", "accounts", on_delete: :cascade
- add_foreign_key "devices", "oauth_access_tokens", column: "access_token_id", on_delete: :cascade
add_foreign_key "email_domain_blocks", "email_domain_blocks", column: "parent_id", on_delete: :cascade
- add_foreign_key "encrypted_messages", "accounts", column: "from_account_id", on_delete: :cascade
- add_foreign_key "encrypted_messages", "devices", on_delete: :cascade
add_foreign_key "favourites", "accounts", name: "fk_5eb6c2b873", on_delete: :cascade
add_foreign_key "favourites", "statuses", name: "fk_b0e856845e", on_delete: :cascade
add_foreign_key "featured_tags", "accounts", on_delete: :cascade
@@ -1367,7 +1319,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_08_08_125420) do
add_foreign_key "oauth_access_tokens", "oauth_applications", column: "application_id", name: "fk_f5fc4c1ee3", on_delete: :cascade
add_foreign_key "oauth_access_tokens", "users", column: "resource_owner_id", name: "fk_e84df68546", on_delete: :cascade
add_foreign_key "oauth_applications", "users", column: "owner_id", name: "fk_b0988c7c0a", on_delete: :cascade
- add_foreign_key "one_time_keys", "devices", on_delete: :cascade
add_foreign_key "poll_votes", "accounts", on_delete: :cascade
add_foreign_key "poll_votes", "polls", on_delete: :cascade
add_foreign_key "polls", "accounts", on_delete: :cascade
diff --git a/db/seeds.rb b/db/seeds.rb
index 370790e513..9d25ef0a4e 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
Chewy.strategy(:mastodon) do
- Dir[Rails.root.join('db', 'seeds', '*.rb')].each do |seed|
+ Rails.root.glob('db/seeds/*.rb').each do |seed|
load seed
end
end
diff --git a/docker-compose.yml b/docker-compose.yml
index 05fd9e1887..c4e8cb7374 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -57,8 +57,9 @@ services:
# - '127.0.0.1:9200:9200'
web:
- build: .
- image: ghcr.io/mastodon/mastodon:v4.3.0-beta.1
+ # You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes
+ # build: .
+ image: ghcr.io/mastodon/mastodon:v4.3.0-beta.2
restart: always
env_file: .env.production
command: bundle exec puma -C config/puma.rb
@@ -78,8 +79,11 @@ services:
- ./public/system:/mastodon/public/system
streaming:
- build: .
- image: ghcr.io/mastodon/mastodon-streaming:v4.3.0-beta.1
+ # You can uncomment the following lines if you want to not use the prebuilt image, for example if you have local code changes
+ # build:
+ # dockerfile: ./streaming/Dockerfile
+ # context: .
+ image: ghcr.io/mastodon/mastodon-streaming:v4.3.0-beta.2
restart: always
env_file: .env.production
command: node ./streaming/index.js
@@ -88,7 +92,7 @@ services:
- internal_network
healthcheck:
# prettier-ignore
- test: ['CMD-SHELL', "curl -s --noproxy localhost localhost:4000/api/v1/streaming/health | grep -q 'OK' || exit 1'"]
+ test: ['CMD-SHELL', "curl -s --noproxy localhost localhost:4000/api/v1/streaming/health | grep -q 'OK' || exit 1"]
ports:
- '127.0.0.1:4000:4000'
depends_on:
@@ -97,7 +101,7 @@ services:
sidekiq:
build: .
- image: ghcr.io/mastodon/mastodon:v4.3.0-beta.1
+ image: ghcr.io/mastodon/mastodon:v4.3.0-beta.2
restart: always
env_file: .env.production
command: bundle exec sidekiq
diff --git a/lib/chewy/strategy/mastodon.rb b/lib/chewy/strategy/mastodon.rb
index ee8b921865..a4b655c506 100644
--- a/lib/chewy/strategy/mastodon.rb
+++ b/lib/chewy/strategy/mastodon.rb
@@ -14,7 +14,7 @@ module Chewy
end
def leave
- RedisConfiguration.with do |redis|
+ RedisConnection.with do |redis|
redis.pipelined do |pipeline|
@stash.each do |type, ids|
pipeline.sadd("chewy:queue:#{type.name}", ids)
diff --git a/lib/exceptions.rb b/lib/exceptions.rb
index d3b92f4a09..c2ff162a6e 100644
--- a/lib/exceptions.rb
+++ b/lib/exceptions.rb
@@ -8,6 +8,7 @@ module Mastodon
class LengthValidationError < ValidationError; end
class DimensionsValidationError < ValidationError; end
class StreamValidationError < ValidationError; end
+ class FilterValidationError < ValidationError; end
class RaceConditionError < Error; end
class RateLimitExceededError < Error; end
class SyntaxError < Error; end
diff --git a/lib/mastodon/cli/accounts.rb b/lib/mastodon/cli/accounts.rb
index d3b7ebe580..08a28e5f5c 100644
--- a/lib/mastodon/cli/accounts.rb
+++ b/lib/mastodon/cli/accounts.rb
@@ -252,7 +252,7 @@ module Mastodon::CLI
domain configuration.
LONG_DESC
def fix_duplicates
- Account.remote.select(:uri, 'count(*)').group(:uri).having('count(*) > 1').pluck(:uri).each do |uri|
+ Account.remote.duplicate_uris.pluck(:uri).each do |uri|
say("Duplicates found for #{uri}")
begin
ActivityPub::FetchRemoteAccountService.new.call(uri) unless dry_run?
@@ -502,17 +502,7 @@ module Mastodon::CLI
- not muted/blocked by us
LONG_DESC
def prune
- query = Account.remote.where.not(actor_type: %i(Application Service))
- query = query.where('NOT EXISTS (SELECT 1 FROM mentions WHERE account_id = accounts.id)')
- query = query.where('NOT EXISTS (SELECT 1 FROM favourites WHERE account_id = accounts.id)')
- query = query.where('NOT EXISTS (SELECT 1 FROM statuses WHERE account_id = accounts.id)')
- query = query.where('NOT EXISTS (SELECT 1 FROM follows WHERE account_id = accounts.id OR target_account_id = accounts.id)')
- query = query.where('NOT EXISTS (SELECT 1 FROM blocks WHERE account_id = accounts.id OR target_account_id = accounts.id)')
- query = query.where('NOT EXISTS (SELECT 1 FROM mutes WHERE target_account_id = accounts.id)')
- query = query.where('NOT EXISTS (SELECT 1 FROM reports WHERE target_account_id = accounts.id)')
- query = query.where('NOT EXISTS (SELECT 1 FROM follow_requests WHERE account_id = accounts.id OR target_account_id = accounts.id)')
-
- _, deleted = parallelize_with_progress(query) do |account|
+ _, deleted = parallelize_with_progress(prunable_accounts) do |account|
next if account.bot? || account.group?
next if account.suspended?
next if account.silenced?
@@ -577,6 +567,31 @@ module Mastodon::CLI
private
+ def prunable_accounts
+ Account
+ .remote
+ .non_automated
+ .where.not(referencing_account(Mention, :account_id))
+ .where.not(referencing_account(Favourite, :account_id))
+ .where.not(referencing_account(Status, :account_id))
+ .where.not(referencing_account(Follow, :account_id))
+ .where.not(referencing_account(Follow, :target_account_id))
+ .where.not(referencing_account(Block, :account_id))
+ .where.not(referencing_account(Block, :target_account_id))
+ .where.not(referencing_account(Mute, :target_account_id))
+ .where.not(referencing_account(Report, :target_account_id))
+ .where.not(referencing_account(FollowRequest, :account_id))
+ .where.not(referencing_account(FollowRequest, :target_account_id))
+ end
+
+ def referencing_account(model, attribute)
+ model
+ .where(model.arel_table[attribute].eq Account.arel_table[:id])
+ .select(1)
+ .arel
+ .exists
+ end
+
def report_errors(errors)
message = errors.map do |error|
<<~STRING
diff --git a/lib/mastodon/cli/base.rb b/lib/mastodon/cli/base.rb
index 93dec1fb8f..dfdcec57be 100644
--- a/lib/mastodon/cli/base.rb
+++ b/lib/mastodon/cli/base.rb
@@ -40,7 +40,7 @@ module Mastodon
.dup
.tap { |config| config['pool'] = options[:concurrency] + 1 }
)
- RedisConfiguration.establish_pool(options[:concurrency])
+ RedisConnection.establish_pool(options[:concurrency])
end
end
end
diff --git a/lib/mastodon/cli/media.rb b/lib/mastodon/cli/media.rb
index 123973d195..70c11ee1a1 100644
--- a/lib/mastodon/cli/media.rb
+++ b/lib/mastodon/cli/media.rb
@@ -157,7 +157,7 @@ module Mastodon::CLI
when :filesystem
require 'find'
- root_path = ENV.fetch('PAPERCLIP_ROOT_PATH', File.join(':rails_root', 'public', 'system')).gsub(':rails_root', Rails.root.to_s)
+ root_path = Rails.configuration.x.file_storage_root_path.gsub(':rails_root', Rails.root.to_s)
Find.find(File.join(*[root_path, prefix].compact)) do |path|
next if File.directory?(path)
diff --git a/lib/mastodon/cli/progress_helper.rb b/lib/mastodon/cli/progress_helper.rb
index f22492afcf..5634343796 100644
--- a/lib/mastodon/cli/progress_helper.rb
+++ b/lib/mastodon/cli/progress_helper.rb
@@ -51,7 +51,7 @@ module Mastodon::CLI
result = ActiveRecord::Base.connection_pool.with_connection do
yield(item)
ensure
- RedisConfiguration.pool.checkin if Thread.current[:redis]
+ RedisConnection.pool.checkin if Thread.current[:redis]
Thread.current[:redis] = nil
end
diff --git a/lib/mastodon/rack_middleware.rb b/lib/mastodon/rack_middleware.rb
index 8aa7911fe7..0e452f06d6 100644
--- a/lib/mastodon/rack_middleware.rb
+++ b/lib/mastodon/rack_middleware.rb
@@ -19,7 +19,7 @@ class Mastodon::RackMiddleware
end
def clean_up_redis_socket!
- RedisConfiguration.pool.checkin if Thread.current[:redis]
+ RedisConnection.pool.checkin if Thread.current[:redis]
Thread.current[:redis] = nil
end
diff --git a/lib/mastodon/redis_config.rb b/lib/mastodon/redis_config.rb
deleted file mode 100644
index c858b61a05..0000000000
--- a/lib/mastodon/redis_config.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-def setup_redis_env_url(prefix = nil, defaults = true)
- prefix = "#{prefix.to_s.upcase}_" unless prefix.nil?
- prefix = '' if prefix.nil?
-
- return if ENV["#{prefix}REDIS_URL"].present?
-
- password = ENV.fetch("#{prefix}REDIS_PASSWORD") { '' if defaults }
- host = ENV.fetch("#{prefix}REDIS_HOST") { 'localhost' if defaults }
- port = ENV.fetch("#{prefix}REDIS_PORT") { 6379 if defaults }
- db = ENV.fetch("#{prefix}REDIS_DB") { 0 if defaults }
-
- ENV["#{prefix}REDIS_URL"] = begin
- if [password, host, port, db].all?(&:nil?)
- ENV['REDIS_URL']
- else
- Addressable::URI.parse("redis://#{host}:#{port}/#{db}").tap do |uri|
- uri.password = password if password.present?
- end.normalize.to_str
- end
- end
-end
-
-setup_redis_env_url
-setup_redis_env_url(:cache, false)
-setup_redis_env_url(:sidekiq, false)
-
-namespace = ENV.fetch('REDIS_NAMESPACE', nil)
-cache_namespace = namespace ? "#{namespace}_cache" : 'cache'
-sidekiq_namespace = namespace
-
-redis_driver = ENV.fetch('REDIS_DRIVER', 'hiredis') == 'ruby' ? :ruby : :hiredis
-
-REDIS_CACHE_PARAMS = {
- driver: redis_driver,
- url: ENV['CACHE_REDIS_URL'],
- expires_in: 10.minutes,
- namespace: "#{cache_namespace}:7.1",
- connect_timeout: 5,
- pool: {
- size: Sidekiq.server? ? Sidekiq[:concurrency] : Integer(ENV['MAX_THREADS'] || 5),
- timeout: 5,
- },
-}.freeze
-
-REDIS_SIDEKIQ_PARAMS = {
- driver: redis_driver,
- url: ENV['SIDEKIQ_REDIS_URL'],
- namespace: sidekiq_namespace,
-}.freeze
-
-ENV['REDIS_NAMESPACE'] = "mastodon_test#{ENV['TEST_ENV_NUMBER']}" if Rails.env.test?
diff --git a/lib/mastodon/redis_configuration.rb b/lib/mastodon/redis_configuration.rb
new file mode 100644
index 0000000000..3d739a2ac6
--- /dev/null
+++ b/lib/mastodon/redis_configuration.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+class Mastodon::RedisConfiguration
+ DEFAULTS = {
+ host: 'localhost',
+ port: 6379,
+ db: 0,
+ }.freeze
+
+ def base
+ @base ||= setup_config(prefix: nil, defaults: DEFAULTS)
+ .merge(namespace: base_namespace)
+ end
+
+ def sidekiq
+ @sidekiq ||= setup_config(prefix: 'SIDEKIQ_')
+ .merge(namespace: sidekiq_namespace)
+ end
+
+ def cache
+ @cache ||= setup_config(prefix: 'CACHE_')
+ .merge({
+ namespace: cache_namespace,
+ expires_in: 10.minutes,
+ connect_timeout: 5,
+ pool: {
+ size: Sidekiq.server? ? Sidekiq[:concurrency] : Integer(ENV['MAX_THREADS'] || 5),
+ timeout: 5,
+ },
+ })
+ end
+
+ private
+
+ def driver
+ ENV['REDIS_DRIVER'] == 'ruby' ? :ruby : :hiredis
+ end
+
+ def namespace
+ @namespace ||= ENV.fetch('REDIS_NAMESPACE', nil)
+ end
+
+ def base_namespace
+ return "mastodon_test#{ENV.fetch('TEST_ENV_NUMBER', nil)}" if Rails.env.test?
+
+ namespace
+ end
+
+ def sidekiq_namespace
+ namespace
+ end
+
+ def cache_namespace
+ namespace ? "#{namespace}_cache" : 'cache'
+ end
+
+ def setup_config(prefix: nil, defaults: {})
+ prefix = "#{prefix}REDIS_"
+
+ url = ENV.fetch("#{prefix}URL", nil)
+ user = ENV.fetch("#{prefix}USER", nil)
+ password = ENV.fetch("#{prefix}PASSWORD", nil)
+ host = ENV.fetch("#{prefix}HOST", defaults[:host])
+ port = ENV.fetch("#{prefix}PORT", defaults[:port])
+ db = ENV.fetch("#{prefix}DB", defaults[:db])
+
+ return { url:, driver: } if url
+
+ sentinel_options = setup_sentinels(prefix, default_user: user, default_password: password)
+
+ if sentinel_options.present?
+ host = sentinel_options[:name]
+ port = nil
+ db ||= 0
+ end
+
+ url = construct_uri(host, port, db, user, password)
+
+ if url.present?
+ { url:, driver: }.merge(sentinel_options)
+ else
+ # Fall back to base config, which has defaults for the URL
+ # so this cannot lead to endless recursion.
+ base
+ end
+ end
+
+ def setup_sentinels(prefix, default_user: nil, default_password: nil)
+ name = ENV.fetch("#{prefix}SENTINEL_MASTER", nil)
+ sentinel_port = ENV.fetch("#{prefix}SENTINEL_PORT", 26_379)
+ sentinel_list = ENV.fetch("#{prefix}SENTINELS", nil)
+ sentinel_username = ENV.fetch("#{prefix}SENTINEL_USERNAME", default_user)
+ sentinel_password = ENV.fetch("#{prefix}SENTINEL_PASSWORD", default_password)
+
+ sentinels = parse_sentinels(sentinel_list, default_port: sentinel_port)
+
+ if name.present? && sentinels.present?
+ { name:, sentinels:, sentinel_username:, sentinel_password: }
+ else
+ {}
+ end
+ end
+
+ def construct_uri(host, port, db, user, password)
+ return nil if host.blank?
+
+ Addressable::URI.parse("redis://#{host}:#{port}/#{db}").tap do |uri|
+ uri.user = user if user.present?
+ uri.password = password if password.present?
+ end.normalize.to_str
+ end
+
+ def parse_sentinels(sentinels_string, default_port: 26_379)
+ (sentinels_string || '').split(',').map do |sentinel|
+ host, port = sentinel.split(':')
+ port = (port || default_port).to_i
+ { host: host, port: port }
+ end.presence
+ end
+end
diff --git a/lib/mastodon/sidekiq_middleware.rb b/lib/mastodon/sidekiq_middleware.rb
index c5f4d8da35..8ce1124c69 100644
--- a/lib/mastodon/sidekiq_middleware.rb
+++ b/lib/mastodon/sidekiq_middleware.rb
@@ -53,7 +53,7 @@ class Mastodon::SidekiqMiddleware
end
def clean_up_redis_socket!
- RedisConfiguration.pool.checkin if Thread.current[:redis]
+ RedisConnection.pool.checkin if Thread.current[:redis]
Thread.current[:redis] = nil
end
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index 5fceb46fd3..36a084c052 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -17,7 +17,7 @@ module Mastodon
end
def default_prerelease
- 'beta.1'
+ 'beta.2'
end
def prerelease
@@ -43,6 +43,12 @@ module Mastodon
@gem_version ||= Gem::Version.new(to_s.split('+')[0])
end
+ def api_versions
+ {
+ mastodon: 2,
+ }
+ end
+
def repository
ENV.fetch('GITHUB_REPOSITORY', 'funamitech/mastodon')
end
diff --git a/lib/sanitize_ext/sanitize_config.rb b/lib/sanitize_ext/sanitize_config.rb
index e6ba5ab250..ed244d4a3e 100644
--- a/lib/sanitize_ext/sanitize_config.rb
+++ b/lib/sanitize_ext/sanitize_config.rb
@@ -71,7 +71,7 @@ class Sanitize
:relative
end
- current_node.replace(Nokogiri::XML::Text.new(current_node.text, current_node.document)) unless LINK_PROTOCOLS.include?(scheme)
+ current_node.replace(current_node.document.create_text_node(current_node.text)) unless LINK_PROTOCOLS.include?(scheme)
end
MASTODON_STRICT = freeze_config(
diff --git a/lib/tasks/branding.rake b/lib/tasks/branding.rake
index be72454ce2..1e2af1b446 100644
--- a/lib/tasks/branding.rake
+++ b/lib/tasks/branding.rake
@@ -15,7 +15,7 @@ namespace :branding do
output_dest = Rails.root.join('app', 'javascript', 'images', 'mailer')
# Displayed size is 64px, at 3x it's 192px
- Dir[Rails.root.join('app', 'javascript', 'images', 'icons', '*.svg')].each do |path|
+ Rails.root.glob('app/javascript/images/icons/*.svg').each do |path|
rsvg_convert.run(input: path, size: 192, output: output_dest.join("#{File.basename(path, '.svg')}.png"))
end
diff --git a/lib/tasks/emojis.rake b/lib/tasks/emojis.rake
index e9fea2deea..fb18f21cf5 100644
--- a/lib/tasks/emojis.rake
+++ b/lib/tasks/emojis.rake
@@ -13,7 +13,7 @@ def gen_border(codepoint, color)
view_box[3] += 4
svg['viewBox'] = view_box.join(' ')
end
- g = Nokogiri::XML::Node.new 'g', doc
+ g = doc.create_element('g')
doc.css('svg > *').each do |elem|
border_elem = elem.dup
diff --git a/lib/tasks/icons.rake b/lib/tasks/icons.rake
index 374ea149fe..96e0a14315 100644
--- a/lib/tasks/icons.rake
+++ b/lib/tasks/icons.rake
@@ -20,7 +20,7 @@ end
def find_used_icons
icons_by_weight_and_size = {}
- Dir[Rails.root.join('app', 'javascript', '**', '*.*s*')].map do |path|
+ Rails.root.glob('app/javascript/**/*.*s*').map do |path|
File.open(path, 'r') do |file|
pattern = %r{\Aimport .* from '@/material-icons/(?[0-9]+)-(?[0-9]+)px/(?[^-]*)(?-fill)?.svg\?react';}
file.each_line do |line|
diff --git a/lib/tasks/repo.rake b/lib/tasks/repo.rake
index b90b48934e..539c44273f 100644
--- a/lib/tasks/repo.rake
+++ b/lib/tasks/repo.rake
@@ -98,7 +98,7 @@ namespace :repo do
missing_yaml_files = I18n.available_locales.reject { |locale| Rails.root.join('config', 'locales', "#{locale}.yml").exist? }
missing_json_files = I18n.available_locales.reject { |locale| Rails.root.join('app', 'javascript', 'mastodon', 'locales', "#{locale}.json").exist? }
- locales_in_files = Dir[Rails.root.join('config', 'locales', '*.yml')].map do |path|
+ locales_in_files = Rails.root.glob('config/locales/*.yml').map do |path|
file_name = File.basename(path, '.yml')
file_name.gsub(/\A(doorkeeper|devise|activerecord|simple_form)\./, '').to_sym
end.uniq.compact
diff --git a/package.json b/package.json
index 866a5003e9..b046061da6 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@mastodon/mastodon",
"license": "AGPL-3.0-or-later",
- "packageManager": "yarn@4.4.0",
+ "packageManager": "yarn@4.5.0",
"engines": {
"node": ">=18"
},
@@ -45,7 +45,7 @@
"@formatjs/intl-pluralrules": "^5.2.2",
"@gamestdio/websocket": "^0.3.2",
"@github/webauthn-json": "^2.1.1",
- "@rails/ujs": "7.1.3",
+ "@rails/ujs": "7.1.400",
"@reduxjs/toolkit": "^2.0.1",
"@svgr/webpack": "^5.5.0",
"arrow-key-navigation": "^1.2.0",
@@ -171,16 +171,16 @@
"@types/requestidlecallback": "^0.3.5",
"@types/webpack": "^4.41.33",
"@types/webpack-env": "^1.18.4",
- "@typescript-eslint/eslint-plugin": "^7.0.0",
- "@typescript-eslint/parser": "^7.0.0",
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
+ "@typescript-eslint/parser": "^8.0.0",
"babel-jest": "^29.5.0",
"eslint": "^8.41.0",
"eslint-define-config": "^2.0.0",
"eslint-import-resolver-typescript": "^3.5.5",
"eslint-plugin-formatjs": "^4.10.1",
- "eslint-plugin-import": "~2.29.0",
+ "eslint-plugin-import": "~2.30.0",
"eslint-plugin-jsdoc": "^50.0.0",
- "eslint-plugin-jsx-a11y": "~6.9.0",
+ "eslint-plugin-jsx-a11y": "~6.10.0",
"eslint-plugin-promise": "~7.1.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
diff --git a/public/embed.js b/public/embed.js
index f8e6a22db4..3fb57469a9 100644
--- a/public/embed.js
+++ b/public/embed.js
@@ -1,5 +1,7 @@
// @ts-check
+const allowedPrefixes = (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT' && document.currentScript.dataset.allowedPrefixes) ? document.currentScript.dataset.allowedPrefixes.split(' ') : [];
+
(function () {
'use strict';
@@ -18,45 +20,71 @@
}
};
+ /**
+ * @param {Map} map
+ */
+ var generateId = function (map) {
+ var id = 0, failCount = 0, idBuffer = new Uint32Array(1);
+
+ while (id === 0 || map.has(id)) {
+ id = crypto.getRandomValues(idBuffer)[0];
+ failCount++;
+
+ if (failCount > 100) {
+ // give up and assign (easily guessable) unique number if getRandomValues is broken or no luck
+ id = -(map.size + 1);
+ break;
+ }
+ }
+
+ return id;
+ };
+
ready(function () {
- /** @type {Map} */
- var iframes = new Map();
+ /** @type {Map} */
+ var embeds = new Map();
window.addEventListener('message', function (e) {
var data = e.data || {};
- if (typeof data !== 'object' || data.type !== 'setHeight' || !iframes.has(data.id)) {
+ if (typeof data !== 'object' || data.type !== 'setHeight' || !embeds.has(data.id)) {
return;
}
- var iframe = iframes.get(data.id);
+ var embed = embeds.get(data.id);
- if(!iframe) return;
-
- if ('source' in e && iframe.contentWindow !== e.source) {
- return;
+ if (embed instanceof HTMLIFrameElement) {
+ embed.height = data.height;
}
- iframe.height = data.height;
+ if (embed instanceof HTMLQuoteElement) {
+ var iframe = embed.querySelector('iframe');
+
+ if (!iframe || ('source' in e && iframe.contentWindow !== e.source)) {
+ return;
+ }
+
+ iframe.height = data.height;
+
+ var placeholder = embed.querySelector('a');
+
+ if (!placeholder) return;
+
+ embed.removeChild(placeholder);
+ }
});
+ // Legacy embeds
document.querySelectorAll('iframe.mastodon-embed').forEach(iframe => {
- // select unique id for each iframe
- var id = 0, failCount = 0, idBuffer = new Uint32Array(1);
- while (id === 0 || iframes.has(id)) {
- id = crypto.getRandomValues(idBuffer)[0];
- failCount++;
- if (failCount > 100) {
- // give up and assign (easily guessable) unique number if getRandomValues is broken or no luck
- id = -(iframes.size + 1);
- break;
- }
- }
+ var id = generateId(embeds);
- iframes.set(id, iframe);
+ embeds.set(id, iframe);
- iframe.scrolling = 'no';
+ iframe.allow = 'fullscreen';
+ iframe.sandbox = 'allow-scripts allow-same-origin';
+ iframe.style.border = 0;
iframe.style.overflow = 'hidden';
+ iframe.style.display = 'block';
iframe.onload = function () {
iframe.contentWindow.postMessage({
@@ -65,7 +93,38 @@
}, '*');
};
- iframe.onload();
+ iframe.onload(); // In case the script is executing after the iframe has already loaded
+ });
+
+ // New generation of embeds
+ document.querySelectorAll('blockquote.mastodon-embed').forEach(container => {
+ var id = generateId(embeds);
+
+ embeds.set(id, container);
+
+ var iframe = document.createElement('iframe');
+ var embedUrl = new URL(container.getAttribute('data-embed-url'));
+
+ if (embedUrl.protocol !== 'https:' && embedUrl.protocol !== 'http:') return;
+ if (allowedPrefixes.every((allowedPrefix) => !embedUrl.toString().startsWith(allowedPrefix))) return;
+
+ iframe.src = embedUrl.toString();
+ iframe.width = container.clientWidth;
+ iframe.height = 0;
+ iframe.allow = 'fullscreen';
+ iframe.sandbox = 'allow-scripts allow-same-origin';
+ iframe.style.border = 0;
+ iframe.style.overflow = 'hidden';
+ iframe.style.display = 'block';
+
+ iframe.onload = function () {
+ iframe.contentWindow.postMessage({
+ type: 'setHeight',
+ id: id,
+ }, '*');
+ };
+
+ container.appendChild(iframe);
});
});
})();
diff --git a/spec/chewy/accounts_index_spec.rb b/spec/chewy/accounts_index_spec.rb
index f9c5922c76..f7b5b2e249 100644
--- a/spec/chewy/accounts_index_spec.rb
+++ b/spec/chewy/accounts_index_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe AccountsIndex do
+RSpec.describe AccountsIndex do
describe 'Searching the index' do
before do
mock_elasticsearch_response(described_class, raw_response)
diff --git a/spec/chewy/public_statuses_index_spec.rb b/spec/chewy/public_statuses_index_spec.rb
index 2f93d0ff02..6bc08832f3 100644
--- a/spec/chewy/public_statuses_index_spec.rb
+++ b/spec/chewy/public_statuses_index_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe PublicStatusesIndex do
+RSpec.describe PublicStatusesIndex do
describe 'Searching the index' do
before do
mock_elasticsearch_response(described_class, raw_response)
diff --git a/spec/chewy/statuses_index_spec.rb b/spec/chewy/statuses_index_spec.rb
index 768e9415fc..e3899f3a17 100644
--- a/spec/chewy/statuses_index_spec.rb
+++ b/spec/chewy/statuses_index_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe StatusesIndex do
+RSpec.describe StatusesIndex do
describe 'Searching the index' do
before do
mock_elasticsearch_response(described_class, raw_response)
diff --git a/spec/chewy/tags_index_spec.rb b/spec/chewy/tags_index_spec.rb
index 054589bdfb..6b57da65e4 100644
--- a/spec/chewy/tags_index_spec.rb
+++ b/spec/chewy/tags_index_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe TagsIndex do
+RSpec.describe TagsIndex do
describe 'Searching the index' do
before do
mock_elasticsearch_response(described_class, raw_response)
diff --git a/spec/config/initializers/rack/attack_spec.rb b/spec/config/initializers/rack/attack_spec.rb
index 19de480898..c7af11bea7 100644
--- a/spec/config/initializers/rack/attack_spec.rb
+++ b/spec/config/initializers/rack/attack_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Rack::Attack, type: :request do
+RSpec.describe Rack::Attack, type: :request do
def app
Rails.application
end
diff --git a/spec/controllers/about_controller_spec.rb b/spec/controllers/about_controller_spec.rb
deleted file mode 100644
index 8db6d80b0b..0000000000
--- a/spec/controllers/about_controller_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe AboutController do
- render_views
-
- describe 'GET #show' do
- before do
- get :show
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/activitypub/claims_controller_spec.rb b/spec/controllers/activitypub/claims_controller_spec.rb
deleted file mode 100644
index f00eeb732a..0000000000
--- a/spec/controllers/activitypub/claims_controller_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ActivityPub::ClaimsController do
- let(:account) { Fabricate(:account) }
-
- describe 'POST #create' do
- context 'without signature' do
- before do
- post :create, params: { account_username: account.username }, body: '{}'
- end
-
- it 'returns http not authorized' do
- expect(response).to have_http_status(401)
- end
- end
- end
-end
diff --git a/spec/controllers/activitypub/collections_controller_spec.rb b/spec/controllers/activitypub/collections_controller_spec.rb
index a5718fbd7d..408e0dd2f6 100644
--- a/spec/controllers/activitypub/collections_controller_spec.rb
+++ b/spec/controllers/activitypub/collections_controller_spec.rb
@@ -25,13 +25,13 @@ RSpec.describe ActivityPub::CollectionsController do
context 'without signature' do
let(:remote_account) { nil }
- it_behaves_like 'cacheable response'
-
it 'returns http success and correct media type and correct items' do
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers
expect(response.media_type).to eq 'application/activity+json'
- expect(body_as_json[:orderedItems])
+ expect(response.parsed_body[:orderedItems])
.to be_an(Array)
.and have_attributes(size: 3)
.and include(ActivityPub::TagManager.instance.uri_for(private_pinned))
@@ -64,13 +64,14 @@ RSpec.describe ActivityPub::CollectionsController do
let(:remote_account) { Fabricate(:account, domain: 'example.com') }
context 'when getting a featured resource' do
- it_behaves_like 'cacheable response'
-
it 'returns http success and correct media type and expected items' do
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers
+
expect(response.media_type).to eq 'application/activity+json'
- expect(body_as_json[:orderedItems])
+ expect(response.parsed_body[:orderedItems])
.to be_an(Array)
.and have_attributes(size: 3)
.and include(ActivityPub::TagManager.instance.uri_for(private_pinned))
@@ -93,7 +94,7 @@ RSpec.describe ActivityPub::CollectionsController do
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to include 'private'
- expect(body_as_json[:orderedItems])
+ expect(response.parsed_body[:orderedItems])
.to be_an(Array)
.and be_empty
end
@@ -109,7 +110,7 @@ RSpec.describe ActivityPub::CollectionsController do
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to include 'private'
- expect(body_as_json[:orderedItems])
+ expect(response.parsed_body[:orderedItems])
.to be_an(Array)
.and be_empty
end
diff --git a/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb
index c030078d43..cbd982f18f 100644
--- a/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb
+++ b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb
@@ -34,7 +34,6 @@ RSpec.describe ActivityPub::FollowersSynchronizationsController do
context 'with signature from example.com' do
subject(:response) { get :show, params: { account_username: account.username } }
- let(:body) { body_as_json }
let(:remote_account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/instance') }
it 'returns http success and cache control and activity json types and correct items' do
@@ -42,7 +41,7 @@ RSpec.describe ActivityPub::FollowersSynchronizationsController do
expect(response.headers['Cache-Control']).to eq 'max-age=0, private'
expect(response.media_type).to eq 'application/activity+json'
- expect(body[:orderedItems])
+ expect(response.parsed_body[:orderedItems])
.to be_an(Array)
.and contain_exactly(
follower_example_com_instance_actor.uri,
diff --git a/spec/controllers/activitypub/outboxes_controller_spec.rb b/spec/controllers/activitypub/outboxes_controller_spec.rb
index 3c8e8e399f..ca986dcabb 100644
--- a/spec/controllers/activitypub/outboxes_controller_spec.rb
+++ b/spec/controllers/activitypub/outboxes_controller_spec.rb
@@ -19,19 +19,19 @@ RSpec.describe ActivityPub::OutboxesController do
context 'without signature' do
subject(:response) { get :show, params: { account_username: account.username, page: page } }
- let(:body) { body_as_json }
let(:remote_account) { nil }
context 'with page not requested' do
let(:page) { nil }
- it_behaves_like 'cacheable response'
-
it 'returns http success and correct media type and headers and items count' do
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers
+
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Vary']).to be_nil
- expect(body[:totalItems]).to eq 4
+ expect(response.parsed_body[:totalItems]).to eq 4
end
context 'when account is permanently suspended' do
@@ -59,16 +59,20 @@ RSpec.describe ActivityPub::OutboxesController do
context 'with page requested' do
let(:page) { 'true' }
- it_behaves_like 'cacheable response'
-
it 'returns http success and correct media type and vary header and items' do
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers
+
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Vary']).to include 'Signature'
- expect(body[:orderedItems]).to be_an Array
- expect(body[:orderedItems].size).to eq 2
- expect(body[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true
+ expect(response.parsed_body)
+ .to include(
+ orderedItems: be_an(Array)
+ .and(have_attributes(size: 2))
+ .and(all(satisfy { |item| targets_public_collection?(item) }))
+ )
end
context 'when account is permanently suspended' do
@@ -108,9 +112,12 @@ RSpec.describe ActivityPub::OutboxesController do
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
- expect(body_as_json[:orderedItems]).to be_an Array
- expect(body_as_json[:orderedItems].size).to eq 2
- expect(body_as_json[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true
+ expect(response.parsed_body)
+ .to include(
+ orderedItems: be_an(Array)
+ .and(have_attributes(size: 2))
+ .and(all(satisfy { |item| targets_public_collection?(item) }))
+ )
end
end
@@ -125,9 +132,12 @@ RSpec.describe ActivityPub::OutboxesController do
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
- expect(body_as_json[:orderedItems]).to be_an Array
- expect(body_as_json[:orderedItems].size).to eq 3
- expect(body_as_json[:orderedItems].all? { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) }).to be true
+ expect(response.parsed_body)
+ .to include(
+ orderedItems: be_an(Array)
+ .and(have_attributes(size: 3))
+ .and(all(satisfy { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) }))
+ )
end
end
@@ -142,9 +152,10 @@ RSpec.describe ActivityPub::OutboxesController do
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
- expect(body_as_json[:orderedItems])
- .to be_an(Array)
- .and be_empty
+ expect(response.parsed_body)
+ .to include(
+ orderedItems: be_an(Array).and(be_empty)
+ )
end
end
@@ -159,9 +170,10 @@ RSpec.describe ActivityPub::OutboxesController do
expect(response.media_type).to eq 'application/activity+json'
expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
- expect(body_as_json[:orderedItems])
- .to be_an(Array)
- .and be_empty
+ expect(response.parsed_body)
+ .to include(
+ orderedItems: be_an(Array).and(be_empty)
+ )
end
end
end
diff --git a/spec/controllers/activitypub/replies_controller_spec.rb b/spec/controllers/activitypub/replies_controller_spec.rb
index c556e07270..27821b0d4e 100644
--- a/spec/controllers/activitypub/replies_controller_spec.rb
+++ b/spec/controllers/activitypub/replies_controller_spec.rb
@@ -66,12 +66,13 @@ RSpec.describe ActivityPub::RepliesController do
context 'when status is public' do
let(:parent_visibility) { :public }
- let(:page_json) { body_as_json[:first] }
-
- it_behaves_like 'cacheable response'
+ let(:page_json) { response.parsed_body[:first] }
it 'returns http success and correct media type' do
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers
+
expect(response.media_type).to eq 'application/activity+json'
end
diff --git a/spec/controllers/admin/account_actions_controller_spec.rb b/spec/controllers/admin/account_actions_controller_spec.rb
index b8dae79939..d513b3d4a0 100644
--- a/spec/controllers/admin/account_actions_controller_spec.rb
+++ b/spec/controllers/admin/account_actions_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::AccountActionsController do
+RSpec.describe Admin::AccountActionsController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/accounts_controller_spec.rb b/spec/controllers/admin/accounts_controller_spec.rb
index f241d261b1..a182300106 100644
--- a/spec/controllers/admin/accounts_controller_spec.rb
+++ b/spec/controllers/admin/accounts_controller_spec.rb
@@ -40,20 +40,38 @@ RSpec.describe Admin::AccountsController do
expect(response)
.to have_http_status(200)
- expect(assigns(:accounts))
- .to have_attributes(
- count: eq(1),
- klass: be(Account)
- )
+ expect(accounts_table_rows.size)
+ .to eq(1)
expect(AccountFilter)
.to have_received(:new)
.with(hash_including(params))
end
+
+ def accounts_table_rows
+ response.parsed_body.css('table.accounts-table tr')
+ end
end
describe 'GET #show' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+ describe 'account moderation notes' do
+ let(:account) { Fabricate(:account) }
+
+ it 'includes moderation notes' do
+ note1 = Fabricate(:account_moderation_note, target_account: account)
+ note2 = Fabricate(:account_moderation_note, target_account: account)
+
+ get :show, params: { id: account.id }
+ expect(response).to have_http_status(200)
+
+ moderation_notes = assigns(:moderation_notes).to_a
+
+ expect(moderation_notes.size).to be 2
+ expect(moderation_notes).to eq [note1, note2]
+ end
+ end
+
context 'with a remote account' do
let(:account) { Fabricate(:account, domain: 'example.com') }
diff --git a/spec/controllers/admin/action_logs_controller_spec.rb b/spec/controllers/admin/action_logs_controller_spec.rb
index be4222df08..3daf260672 100644
--- a/spec/controllers/admin/action_logs_controller_spec.rb
+++ b/spec/controllers/admin/action_logs_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::ActionLogsController do
+RSpec.describe Admin::ActionLogsController do
render_views
# Action logs typically cause issues when their targets are not in the database
diff --git a/spec/controllers/admin/announcements_controller_spec.rb b/spec/controllers/admin/announcements_controller_spec.rb
deleted file mode 100644
index c2d3135d92..0000000000
--- a/spec/controllers/admin/announcements_controller_spec.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::AnnouncementsController do
- render_views
-
- let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index
-
- expect(response).to have_http_status(:success)
- end
- end
-
- describe 'GET #new' do
- it 'returns http success and renders new' do
- get :new
-
- expect(response).to have_http_status(:success)
- expect(response).to render_template(:new)
- end
- end
-
- describe 'GET #edit' do
- let(:announcement) { Fabricate(:announcement) }
-
- it 'returns http success and renders edit' do
- get :edit, params: { id: announcement.id }
-
- expect(response).to have_http_status(:success)
- expect(response).to render_template(:edit)
- end
- end
-
- describe 'POST #create' do
- it 'creates a new announcement and redirects' do
- expect do
- post :create, params: { announcement: { text: 'The announcement message.' } }
- end.to change(Announcement, :count).by(1)
-
- expect(response).to redirect_to(admin_announcements_path)
- expect(flash.notice).to match(I18n.t('admin.announcements.published_msg'))
- end
- end
-
- describe 'PUT #update' do
- let(:announcement) { Fabricate(:announcement, text: 'Original text') }
-
- it 'updates an announcement and redirects' do
- put :update, params: { id: announcement.id, announcement: { text: 'Updated text.' } }
-
- expect(response).to redirect_to(admin_announcements_path)
- expect(flash.notice).to match(I18n.t('admin.announcements.updated_msg'))
- end
- end
-
- describe 'DELETE #destroy' do
- let!(:announcement) { Fabricate(:announcement, text: 'Original text') }
-
- it 'destroys an announcement and redirects' do
- expect do
- delete :destroy, params: { id: announcement.id }
- end.to change(Announcement, :count).by(-1)
-
- expect(response).to redirect_to(admin_announcements_path)
- expect(flash.notice).to match(I18n.t('admin.announcements.destroyed_msg'))
- end
- end
-
- describe 'POST #publish' do
- subject { post :publish, params: { id: announcement.id } }
-
- let(:announcement) { Fabricate(:announcement, published_at: nil) }
-
- it 'marks announcement published' do
- subject
-
- expect(announcement.reload).to be_published
- expect(response).to redirect_to admin_announcements_path
- end
- end
-
- describe 'POST #unpublish' do
- subject { post :unpublish, params: { id: announcement.id } }
-
- let(:announcement) { Fabricate(:announcement, published_at: 4.days.ago) }
-
- it 'marks announcement as not published' do
- subject
-
- expect(announcement.reload).to_not be_published
- expect(response).to redirect_to admin_announcements_path
- end
- end
-end
diff --git a/spec/controllers/admin/base_controller_spec.rb b/spec/controllers/admin/base_controller_spec.rb
index 1f1fa8441a..8b8b7fe63d 100644
--- a/spec/controllers/admin/base_controller_spec.rb
+++ b/spec/controllers/admin/base_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::BaseController do
+RSpec.describe Admin::BaseController do
controller do
def success
authorize :dashboard, :index?
diff --git a/spec/controllers/admin/custom_emojis_controller_spec.rb b/spec/controllers/admin/custom_emojis_controller_spec.rb
index 9e732200dd..57c2a6d21b 100644
--- a/spec/controllers/admin/custom_emojis_controller_spec.rb
+++ b/spec/controllers/admin/custom_emojis_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::CustomEmojisController do
+RSpec.describe Admin::CustomEmojisController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/dashboard_controller_spec.rb b/spec/controllers/admin/dashboard_controller_spec.rb
index 25300fdd90..9177be4b6d 100644
--- a/spec/controllers/admin/dashboard_controller_spec.rb
+++ b/spec/controllers/admin/dashboard_controller_spec.rb
@@ -2,23 +2,34 @@
require 'rails_helper'
-describe Admin::DashboardController do
+RSpec.describe Admin::DashboardController do
render_views
describe 'GET #index' do
+ let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Owner')) }
+
before do
- allow(Admin::SystemCheck).to receive(:perform).and_return([
- Admin::SystemCheck::Message.new(:database_schema_check),
- Admin::SystemCheck::Message.new(:rules_check, nil, admin_rules_path),
- Admin::SystemCheck::Message.new(:sidekiq_process_check, 'foo, bar'),
- ])
- sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin'))
+ stub_system_checks
+ Fabricate :software_update
+ sign_in(user)
end
- it 'returns 200' do
+ it 'returns http success and body with system check messages' do
get :index
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and have_attributes(
+ body: include(I18n.t('admin.system_checks.software_version_patch_check.message_html'))
+ )
+ end
+
+ private
+
+ def stub_system_checks
+ stub_const 'Admin::SystemCheck::ACTIVE_CHECKS', [
+ Admin::SystemCheck::SoftwareVersionCheck,
+ ]
end
end
end
diff --git a/spec/controllers/admin/domain_allows_controller_spec.rb b/spec/controllers/admin/domain_allows_controller_spec.rb
index 6f82f322b5..036d229091 100644
--- a/spec/controllers/admin/domain_allows_controller_spec.rb
+++ b/spec/controllers/admin/domain_allows_controller_spec.rb
@@ -13,7 +13,6 @@ RSpec.describe Admin::DomainAllowsController do
it 'assigns a new domain allow' do
get :new
- expect(assigns(:domain_allow)).to be_instance_of(DomainAllow)
expect(response).to have_http_status(200)
end
end
diff --git a/spec/controllers/admin/domain_blocks_controller_spec.rb b/spec/controllers/admin/domain_blocks_controller_spec.rb
index eb2c6265d1..a99ca6c641 100644
--- a/spec/controllers/admin/domain_blocks_controller_spec.rb
+++ b/spec/controllers/admin/domain_blocks_controller_spec.rb
@@ -13,7 +13,6 @@ RSpec.describe Admin::DomainBlocksController do
it 'assigns a new domain block' do
get :new
- expect(assigns(:domain_block)).to be_instance_of(DomainBlock)
expect(response).to have_http_status(200)
end
end
@@ -171,7 +170,6 @@ RSpec.describe Admin::DomainBlocksController do
it 'returns http success' do
get :edit, params: { id: domain_block.id }
- expect(assigns(:domain_block)).to be_instance_of(DomainBlock)
expect(response).to have_http_status(200)
end
end
diff --git a/spec/controllers/admin/export_domain_blocks_controller_spec.rb b/spec/controllers/admin/export_domain_blocks_controller_spec.rb
index bfcccfa06c..564f5a88c5 100644
--- a/spec/controllers/admin/export_domain_blocks_controller_spec.rb
+++ b/spec/controllers/admin/export_domain_blocks_controller_spec.rb
@@ -42,11 +42,8 @@ RSpec.describe Admin::ExportDomainBlocksController do
post :import, params: { admin_import: { data: fixture_file_upload('domain_blocks.csv') } }
end
- it 'renders page with expected domain blocks' do
- expect(assigns(:domain_blocks).map { |block| [block.domain, block.severity.to_sym] }).to contain_exactly(['bad.domain', :silence], ['worse.domain', :suspend], ['reject.media', :noop])
- end
-
- it 'returns http success' do
+ it 'renders page with expected domain blocks and returns http success' do
+ expect(mapped_batch_table_rows).to contain_exactly(['bad.domain', :silence], ['worse.domain', :suspend], ['reject.media', :noop])
expect(response).to have_http_status(200)
end
end
@@ -56,14 +53,19 @@ RSpec.describe Admin::ExportDomainBlocksController do
post :import, params: { admin_import: { data: fixture_file_upload('domain_blocks_list.txt') } }
end
- it 'renders page with expected domain blocks' do
- expect(assigns(:domain_blocks).map { |block| [block.domain, block.severity.to_sym] }).to contain_exactly(['bad.domain', :suspend], ['worse.domain', :suspend], ['reject.media', :suspend])
- end
-
- it 'returns http success' do
+ it 'renders page with expected domain blocks and returns http success' do
+ expect(mapped_batch_table_rows).to contain_exactly(['bad.domain', :suspend], ['worse.domain', :suspend], ['reject.media', :suspend])
expect(response).to have_http_status(200)
end
end
+
+ def mapped_batch_table_rows
+ batch_table_rows.map { |row| [row.at_css('[id$=_domain]')['value'], row.at_css('[id$=_severity]')['value'].to_sym] }
+ end
+
+ def batch_table_rows
+ response.parsed_body.css('body div.batch-table__row')
+ end
end
it 'displays error on no file selected' do
diff --git a/spec/controllers/admin/follow_recommendations_controller_spec.rb b/spec/controllers/admin/follow_recommendations_controller_spec.rb
index f62aa6e4b2..d614f2ef43 100644
--- a/spec/controllers/admin/follow_recommendations_controller_spec.rb
+++ b/spec/controllers/admin/follow_recommendations_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::FollowRecommendationsController do
+RSpec.describe Admin::FollowRecommendationsController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/instances_controller_spec.rb b/spec/controllers/admin/instances_controller_spec.rb
index ca64dd90a0..1e65373e1f 100644
--- a/spec/controllers/admin/instances_controller_spec.rb
+++ b/spec/controllers/admin/instances_controller_spec.rb
@@ -28,12 +28,15 @@ RSpec.describe Admin::InstancesController do
it 'renders instances' do
get :index, params: { page: 2 }
- instances = assigns(:instances).to_a
- expect(instances.size).to eq 1
- expect(instances[0].domain).to eq 'less.popular'
+ expect(instance_directory_links.size).to eq(1)
+ expect(instance_directory_links.first.text.strip).to match('less.popular')
expect(response).to have_http_status(200)
end
+
+ def instance_directory_links
+ response.parsed_body.css('div.directory__tag a')
+ end
end
describe 'GET #show' do
diff --git a/spec/controllers/admin/invites_controller_spec.rb b/spec/controllers/admin/invites_controller_spec.rb
index 71748cbbec..b6471e80b2 100644
--- a/spec/controllers/admin/invites_controller_spec.rb
+++ b/spec/controllers/admin/invites_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::InvitesController do
+RSpec.describe Admin::InvitesController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
@@ -18,7 +18,8 @@ describe Admin::InvitesController do
it 'renders index page' do
expect(subject).to render_template :index
- expect(assigns(:invites)).to include invite
+ expect(response.body)
+ .to include(invite.code)
end
end
diff --git a/spec/controllers/admin/ip_blocks_controller_spec.rb b/spec/controllers/admin/ip_blocks_controller_spec.rb
index 05190f1340..2e32db5a01 100644
--- a/spec/controllers/admin/ip_blocks_controller_spec.rb
+++ b/spec/controllers/admin/ip_blocks_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::IpBlocksController do
+RSpec.describe Admin::IpBlocksController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/relationships_controller_spec.rb b/spec/controllers/admin/relationships_controller_spec.rb
index 1099a37a3b..214be7c7cd 100644
--- a/spec/controllers/admin/relationships_controller_spec.rb
+++ b/spec/controllers/admin/relationships_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::RelationshipsController do
+RSpec.describe Admin::RelationshipsController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/relays_controller_spec.rb b/spec/controllers/admin/relays_controller_spec.rb
index ca351c39b2..c6251a6d76 100644
--- a/spec/controllers/admin/relays_controller_spec.rb
+++ b/spec/controllers/admin/relays_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::RelaysController do
+RSpec.describe Admin::RelaysController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/report_notes_controller_spec.rb b/spec/controllers/admin/report_notes_controller_spec.rb
index 8d5b5c7aec..423a64ebc4 100644
--- a/spec/controllers/admin/report_notes_controller_spec.rb
+++ b/spec/controllers/admin/report_notes_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::ReportNotesController do
+RSpec.describe Admin::ReportNotesController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/reports/actions_controller_spec.rb b/spec/controllers/admin/reports/actions_controller_spec.rb
index 06d4b31f54..6185702c30 100644
--- a/spec/controllers/admin/reports/actions_controller_spec.rb
+++ b/spec/controllers/admin/reports/actions_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Reports::ActionsController do
+RSpec.describe Admin::Reports::ActionsController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/reports_controller_spec.rb b/spec/controllers/admin/reports_controller_spec.rb
index 5849163b5f..1252ceb1f4 100644
--- a/spec/controllers/admin/reports_controller_spec.rb
+++ b/spec/controllers/admin/reports_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::ReportsController do
+RSpec.describe Admin::ReportsController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
@@ -13,39 +13,57 @@ describe Admin::ReportsController do
describe 'GET #index' do
it 'returns http success with no filters' do
- specified = Fabricate(:report, action_taken_at: nil)
- Fabricate(:report, action_taken_at: Time.now.utc)
+ specified = Fabricate(:report, action_taken_at: nil, comment: 'First report')
+ other = Fabricate(:report, action_taken_at: Time.now.utc, comment: 'Second report')
get :index
- reports = assigns(:reports).to_a
- expect(reports.size).to eq 1
- expect(reports[0]).to eq specified
expect(response).to have_http_status(200)
+ expect(response.body)
+ .to include(specified.comment)
+ .and not_include(other.comment)
end
it 'returns http success with resolved filter' do
- specified = Fabricate(:report, action_taken_at: Time.now.utc)
- Fabricate(:report, action_taken_at: nil)
+ specified = Fabricate(:report, action_taken_at: Time.now.utc, comment: 'First report')
+ other = Fabricate(:report, action_taken_at: nil, comment: 'Second report')
get :index, params: { resolved: '1' }
- reports = assigns(:reports).to_a
- expect(reports.size).to eq 1
- expect(reports[0]).to eq specified
-
expect(response).to have_http_status(200)
+ expect(response.body)
+ .to include(specified.comment)
+ .and not_include(other.comment)
end
end
describe 'GET #show' do
it 'renders report' do
- report = Fabricate(:report)
+ report = Fabricate(:report, comment: 'A big problem')
get :show, params: { id: report }
- expect(assigns(:report)).to eq report
expect(response).to have_http_status(200)
+ expect(response.body)
+ .to include(report.comment)
+ end
+
+ describe 'account moderation notes' do
+ let(:report) { Fabricate(:report) }
+
+ it 'includes moderation notes' do
+ note1 = Fabricate(:report_note, report: report)
+ note2 = Fabricate(:report_note, report: report)
+
+ get :show, params: { id: report }
+
+ expect(response).to have_http_status(200)
+
+ report_notes = assigns(:report_notes).to_a
+
+ expect(report_notes.size).to be 2
+ expect(report_notes).to eq [note1, note2]
+ end
end
end
diff --git a/spec/controllers/admin/resets_controller_spec.rb b/spec/controllers/admin/resets_controller_spec.rb
deleted file mode 100644
index 0cbc3b60ab..0000000000
--- a/spec/controllers/admin/resets_controller_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::ResetsController do
- render_views
-
- subject { post :create, params: { account_id: account.id } }
-
- let(:account) { Fabricate(:account) }
-
- before do
- sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user
- end
-
- describe 'POST #create', :inline_jobs do
- it 'redirects to admin accounts page' do
- emails = capture_emails { subject }
-
- expect(emails.size)
- .to eq(2)
- expect(emails).to have_attributes(
- first: have_attributes(
- to: include(account.user.email),
- subject: I18n.t('devise.mailer.password_change.subject')
- ),
- last: have_attributes(
- to: include(account.user.email),
- subject: I18n.t('devise.mailer.reset_password_instructions.subject')
- )
- )
- expect(response).to redirect_to(admin_account_path(account.id))
- end
- end
-end
diff --git a/spec/controllers/admin/roles_controller_spec.rb b/spec/controllers/admin/roles_controller_spec.rb
index 223d0a472a..2c43a0ca87 100644
--- a/spec/controllers/admin/roles_controller_spec.rb
+++ b/spec/controllers/admin/roles_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::RolesController do
+RSpec.describe Admin::RolesController do
render_views
let(:permissions) { UserRole::Flags::NONE }
diff --git a/spec/controllers/admin/rules_controller_spec.rb b/spec/controllers/admin/rules_controller_spec.rb
index 92ffb41567..1b2a2010d0 100644
--- a/spec/controllers/admin/rules_controller_spec.rb
+++ b/spec/controllers/admin/rules_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::RulesController do
+RSpec.describe Admin::RulesController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/settings/about_controller_spec.rb b/spec/controllers/admin/settings/about_controller_spec.rb
deleted file mode 100644
index f322cb4434..0000000000
--- a/spec/controllers/admin/settings/about_controller_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::Settings::AboutController do
- render_views
-
- let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(:success)
- end
- end
-
- describe 'PUT #update' do
- it 'updates the settings' do
- put :update, params: { form_admin_settings: { site_extended_description: 'new site description' } }
-
- expect(response).to redirect_to(admin_settings_about_path)
- end
- end
-end
diff --git a/spec/controllers/admin/settings/appearance_controller_spec.rb b/spec/controllers/admin/settings/appearance_controller_spec.rb
deleted file mode 100644
index ea6f3b7833..0000000000
--- a/spec/controllers/admin/settings/appearance_controller_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::Settings::AppearanceController do
- render_views
-
- let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(:success)
- end
- end
-
- describe 'PUT #update' do
- it 'updates the settings' do
- put :update, params: { form_admin_settings: { custom_css: 'html { display: inline; }' } }
-
- expect(response).to redirect_to(admin_settings_appearance_path)
- end
- end
-end
diff --git a/spec/controllers/admin/settings/branding_controller_spec.rb b/spec/controllers/admin/settings/branding_controller_spec.rb
index e30300b4e4..5e46910cc6 100644
--- a/spec/controllers/admin/settings/branding_controller_spec.rb
+++ b/spec/controllers/admin/settings/branding_controller_spec.rb
@@ -10,14 +10,6 @@ RSpec.describe Admin::Settings::BrandingController do
sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user
end
- describe 'GET #show' do
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(200)
- end
- end
-
describe 'PUT #update' do
it 'cannot create a setting value for a non-admin key' do
expect(Setting.new_setting_key).to be_blank
@@ -27,15 +19,6 @@ RSpec.describe Admin::Settings::BrandingController do
expect(response).to redirect_to(admin_settings_branding_path)
expect(Setting.new_setting_key).to be_nil
end
-
- it 'creates a settings value that didnt exist before for eligible key' do
- expect(Setting.site_short_description).to be_blank
-
- patch :update, params: { form_admin_settings: { site_short_description: 'New key value' } }
-
- expect(response).to redirect_to(admin_settings_branding_path)
- expect(Setting.site_short_description).to eq 'New key value'
- end
end
end
end
diff --git a/spec/controllers/admin/settings/content_retention_controller_spec.rb b/spec/controllers/admin/settings/content_retention_controller_spec.rb
deleted file mode 100644
index fb6a3d2848..0000000000
--- a/spec/controllers/admin/settings/content_retention_controller_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::Settings::ContentRetentionController do
- render_views
-
- let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(:success)
- end
- end
-
- describe 'PUT #update' do
- it 'updates the settings' do
- put :update, params: { form_admin_settings: { media_cache_retention_period: '2' } }
-
- expect(response).to redirect_to(admin_settings_content_retention_path)
- end
- end
-end
diff --git a/spec/controllers/admin/settings/discovery_controller_spec.rb b/spec/controllers/admin/settings/discovery_controller_spec.rb
deleted file mode 100644
index 33109e3c01..0000000000
--- a/spec/controllers/admin/settings/discovery_controller_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::Settings::DiscoveryController do
- render_views
-
- let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(:success)
- end
- end
-
- describe 'PUT #update' do
- it 'updates the settings' do
- put :update, params: { form_admin_settings: { trends: '1' } }
-
- expect(response).to redirect_to(admin_settings_discovery_path)
- end
- end
-end
diff --git a/spec/controllers/admin/settings/registrations_controller_spec.rb b/spec/controllers/admin/settings/registrations_controller_spec.rb
deleted file mode 100644
index e076544603..0000000000
--- a/spec/controllers/admin/settings/registrations_controller_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::Settings::RegistrationsController do
- render_views
-
- let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(:success)
- end
- end
-
- describe 'PUT #update' do
- it 'updates the settings' do
- put :update, params: { form_admin_settings: { registrations_mode: 'open' } }
-
- expect(response).to redirect_to(admin_settings_registrations_path)
- end
- end
-end
diff --git a/spec/controllers/admin/site_uploads_controller_spec.rb b/spec/controllers/admin/site_uploads_controller_spec.rb
index 4ea37f396a..9c65c63b78 100644
--- a/spec/controllers/admin/site_uploads_controller_spec.rb
+++ b/spec/controllers/admin/site_uploads_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SiteUploadsController do
+RSpec.describe Admin::SiteUploadsController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/statuses_controller_spec.rb b/spec/controllers/admin/statuses_controller_spec.rb
index 4ab6d109ef..e6053a6e8a 100644
--- a/spec/controllers/admin/statuses_controller_spec.rb
+++ b/spec/controllers/admin/statuses_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::StatusesController do
+RSpec.describe Admin::StatusesController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/trends/links/preview_card_providers_controller_spec.rb b/spec/controllers/admin/trends/links/preview_card_providers_controller_spec.rb
index 95ed38d6b1..ce62a13db6 100644
--- a/spec/controllers/admin/trends/links/preview_card_providers_controller_spec.rb
+++ b/spec/controllers/admin/trends/links/preview_card_providers_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Trends::Links::PreviewCardProvidersController do
+RSpec.describe Admin::Trends::Links::PreviewCardProvidersController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/trends/links_controller_spec.rb b/spec/controllers/admin/trends/links_controller_spec.rb
index 7c67f5e5aa..984f3007c2 100644
--- a/spec/controllers/admin/trends/links_controller_spec.rb
+++ b/spec/controllers/admin/trends/links_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Trends::LinksController do
+RSpec.describe Admin::Trends::LinksController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/trends/statuses_controller_spec.rb b/spec/controllers/admin/trends/statuses_controller_spec.rb
index b752234d3c..eecf4ab4f2 100644
--- a/spec/controllers/admin/trends/statuses_controller_spec.rb
+++ b/spec/controllers/admin/trends/statuses_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Trends::StatusesController do
+RSpec.describe Admin::Trends::StatusesController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/trends/tags_controller_spec.rb b/spec/controllers/admin/trends/tags_controller_spec.rb
index 4f74a55455..51ad1860c8 100644
--- a/spec/controllers/admin/trends/tags_controller_spec.rb
+++ b/spec/controllers/admin/trends/tags_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Trends::TagsController do
+RSpec.describe Admin::Trends::TagsController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/users/roles_controller_spec.rb b/spec/controllers/admin/users/roles_controller_spec.rb
index 97f69a0b0a..bfc2bb151f 100644
--- a/spec/controllers/admin/users/roles_controller_spec.rb
+++ b/spec/controllers/admin/users/roles_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Users::RolesController do
+RSpec.describe Admin::Users::RolesController do
render_views
let(:current_role) { UserRole.create(name: 'Foo', permissions: UserRole::FLAGS[:manage_roles], position: 10) }
diff --git a/spec/controllers/admin/users/two_factor_authentications_controller_spec.rb b/spec/controllers/admin/users/two_factor_authentications_controller_spec.rb
index eb10d47963..1f0a6ac34d 100644
--- a/spec/controllers/admin/users/two_factor_authentications_controller_spec.rb
+++ b/spec/controllers/admin/users/two_factor_authentications_controller_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'webauthn/fake_client'
-describe Admin::Users::TwoFactorAuthenticationsController do
+RSpec.describe Admin::Users::TwoFactorAuthenticationsController do
render_views
let(:user) { Fabricate(:user) }
diff --git a/spec/controllers/admin/warning_presets_controller_spec.rb b/spec/controllers/admin/warning_presets_controller_spec.rb
index b32a58e990..4171bbad82 100644
--- a/spec/controllers/admin/warning_presets_controller_spec.rb
+++ b/spec/controllers/admin/warning_presets_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::WarningPresetsController do
+RSpec.describe Admin::WarningPresetsController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/webhooks/secrets_controller_spec.rb b/spec/controllers/admin/webhooks/secrets_controller_spec.rb
index 291a10fba5..61ae8cdaa5 100644
--- a/spec/controllers/admin/webhooks/secrets_controller_spec.rb
+++ b/spec/controllers/admin/webhooks/secrets_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Webhooks::SecretsController do
+RSpec.describe Admin::Webhooks::SecretsController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/admin/webhooks_controller_spec.rb b/spec/controllers/admin/webhooks_controller_spec.rb
index 17d8506025..4fe787c26c 100644
--- a/spec/controllers/admin/webhooks_controller_spec.rb
+++ b/spec/controllers/admin/webhooks_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::WebhooksController do
+RSpec.describe Admin::WebhooksController do
render_views
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
diff --git a/spec/controllers/api/base_controller_spec.rb b/spec/controllers/api/base_controller_spec.rb
index 659d55f801..1e0e7c8f4d 100644
--- a/spec/controllers/api/base_controller_spec.rb
+++ b/spec/controllers/api/base_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Api::BaseController do
+RSpec.describe Api::BaseController do
controller do
def success
head 200
diff --git a/spec/controllers/api/oembed_controller_spec.rb b/spec/controllers/api/oembed_controller_spec.rb
deleted file mode 100644
index 5f0ca560d2..0000000000
--- a/spec/controllers/api/oembed_controller_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::OEmbedController do
- render_views
-
- let(:alice) { Fabricate(:account, username: 'alice') }
- let(:status) { Fabricate(:status, text: 'Hello world', account: alice) }
-
- describe 'GET #show' do
- before do
- request.host = Rails.configuration.x.local_domain
- get :show, params: { url: short_account_status_url(alice, status) }, format: :json
- end
-
- it 'returns private cache control headers', :aggregate_failures do
- expect(response).to have_http_status(200)
- expect(response.headers['Cache-Control']).to include('private, no-store')
- end
- end
-end
diff --git a/spec/controllers/api/web/push_subscriptions_controller_spec.rb b/spec/controllers/api/web/push_subscriptions_controller_spec.rb
index 58677841ca..acc0312113 100644
--- a/spec/controllers/api/web/push_subscriptions_controller_spec.rb
+++ b/spec/controllers/api/web/push_subscriptions_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Api::Web::PushSubscriptionsController do
+RSpec.describe Api::Web::PushSubscriptionsController do
render_views
let(:user) { Fabricate(:user) }
diff --git a/spec/controllers/api/web/settings_controller_spec.rb b/spec/controllers/api/web/settings_controller_spec.rb
deleted file mode 100644
index 815da04c47..0000000000
--- a/spec/controllers/api/web/settings_controller_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::Web::SettingsController do
- render_views
-
- let!(:user) { Fabricate(:user) }
-
- describe 'PATCH #update' do
- it 'redirects to about page' do
- sign_in(user)
- patch :update, format: :json, params: { data: { 'onboarded' => true } }
-
- user.reload
- expect(response).to have_http_status(200)
- expect(user_web_setting.data['onboarded']).to eq('true')
- end
-
- def user_web_setting
- Web::Setting.where(user: user).first
- end
- end
-end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 704cc1270e..52d92a2b6c 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ApplicationController do
+RSpec.describe ApplicationController do
controller do
def success
head 200
diff --git a/spec/controllers/auth/challenges_controller_spec.rb b/spec/controllers/auth/challenges_controller_spec.rb
index 32bbedde63..56fdfa61b5 100644
--- a/spec/controllers/auth/challenges_controller_spec.rb
+++ b/spec/controllers/auth/challenges_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Auth::ChallengesController do
+RSpec.describe Auth::ChallengesController do
render_views
let(:password) { 'foobar12345' }
diff --git a/spec/controllers/auth/confirmations_controller_spec.rb b/spec/controllers/auth/confirmations_controller_spec.rb
index 15403e8ea1..a5b212e660 100644
--- a/spec/controllers/auth/confirmations_controller_spec.rb
+++ b/spec/controllers/auth/confirmations_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Auth::ConfirmationsController do
+RSpec.describe Auth::ConfirmationsController do
render_views
describe 'GET #new' do
diff --git a/spec/controllers/auth/passwords_controller_spec.rb b/spec/controllers/auth/passwords_controller_spec.rb
index d70490abcf..9ccbb9e494 100644
--- a/spec/controllers/auth/passwords_controller_spec.rb
+++ b/spec/controllers/auth/passwords_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Auth::PasswordsController do
+RSpec.describe Auth::PasswordsController do
include Devise::Test::ControllerHelpers
describe 'GET #new' do
diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb
index 75ab287652..6118edf4e3 100644
--- a/spec/controllers/auth/registrations_controller_spec.rb
+++ b/spec/controllers/auth/registrations_controller_spec.rb
@@ -342,7 +342,7 @@ RSpec.describe Auth::RegistrationsController do
end
def username_error_text
- Nokogiri::Slop(response.body).css('.user_account_username .error').text
+ response.parsed_body.css('.user_account_username .error').text
end
end
diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb
index 9a94e5e1a1..713ea3ff16 100644
--- a/spec/controllers/auth/sessions_controller_spec.rb
+++ b/spec/controllers/auth/sessions_controller_spec.rb
@@ -402,7 +402,7 @@ RSpec.describe Auth::SessionsController do
end
it 'instructs the browser to redirect to home, logs the user in, and updates the sign count' do
- expect(body_as_json[:redirect_path]).to eq(root_path)
+ expect(response.parsed_body[:redirect_path]).to eq(root_path)
expect(controller.current_user).to eq user
@@ -412,44 +412,4 @@ RSpec.describe Auth::SessionsController do
end
end
end
-
- describe 'GET #webauthn_options' do
- subject { get :webauthn_options, session: { attempt_user_id: user.id } }
-
- let!(:user) do
- Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32))
- end
-
- context 'with WebAuthn and OTP enabled as second factor' do
- let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http'}://#{Rails.configuration.x.web_domain}" }
-
- let(:fake_client) { WebAuthn::FakeClient.new(domain) }
-
- before do
- user.update(webauthn_id: WebAuthn.generate_user_id)
- public_key_credential = WebAuthn::Credential.from_create(fake_client.create)
- user.webauthn_credentials.create(
- nickname: 'SecurityKeyNickname',
- external_id: public_key_credential.id,
- public_key: public_key_credential.public_key,
- sign_count: '1000'
- )
- post :create, params: { user: { email: user.email, password: user.password } }
- end
-
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status 200
- end
- end
-
- context 'when WebAuthn not enabled' do
- it 'returns http unauthorized' do
- subject
-
- expect(response).to have_http_status 401
- end
- end
- end
end
diff --git a/spec/controllers/auth/setup_controller_spec.rb b/spec/controllers/auth/setup_controller_spec.rb
index 75e42aaf96..28b07cb4b2 100644
--- a/spec/controllers/auth/setup_controller_spec.rb
+++ b/spec/controllers/auth/setup_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Auth::SetupController do
+RSpec.describe Auth::SetupController do
render_views
describe 'GET #show' do
diff --git a/spec/controllers/authorize_interactions_controller_spec.rb b/spec/controllers/authorize_interactions_controller_spec.rb
index 5282a196a6..2a0422efa9 100644
--- a/spec/controllers/authorize_interactions_controller_spec.rb
+++ b/spec/controllers/authorize_interactions_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe AuthorizeInteractionsController do
+RSpec.describe AuthorizeInteractionsController do
render_views
describe 'GET #show' do
@@ -46,8 +46,9 @@ describe AuthorizeInteractionsController do
get :show, params: { acct: 'http://example.com' }
- expect(response).to have_http_status(302)
- expect(assigns(:resource)).to eq account
+ expect(response)
+ .to have_http_status(302)
+ .and redirect_to(web_url("@#{account.pretty_acct}"))
end
it 'sets resource from acct uri' do
@@ -58,8 +59,9 @@ describe AuthorizeInteractionsController do
get :show, params: { acct: 'acct:found@hostname' }
- expect(response).to have_http_status(302)
- expect(assigns(:resource)).to eq account
+ expect(response)
+ .to have_http_status(302)
+ .and redirect_to(web_url("@#{account.pretty_acct}"))
end
end
end
diff --git a/spec/controllers/concerns/account_controller_concern_spec.rb b/spec/controllers/concerns/account_controller_concern_spec.rb
index 6eb970dedb..384406a0ea 100644
--- a/spec/controllers/concerns/account_controller_concern_spec.rb
+++ b/spec/controllers/concerns/account_controller_concern_spec.rb
@@ -2,12 +2,12 @@
require 'rails_helper'
-describe AccountControllerConcern do
+RSpec.describe AccountControllerConcern do
controller(ApplicationController) do
include AccountControllerConcern
def success
- head 200
+ render plain: @account.username # rubocop:disable RSpec/InstanceVariable
end
end
@@ -51,19 +51,15 @@ describe AccountControllerConcern do
context 'when account is not suspended' do
let(:account) { Fabricate(:account, username: 'username') }
- it 'assigns @account, returns success, and sets link headers' do
+ it 'Prepares the account, returns success, and sets link headers' do
get 'success', params: { account_username: account.username }
- expect(assigns(:account)).to eq account
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].to_s).to eq(expected_link_headers)
- end
-
- def expected_link_headers
- [
- '; rel="lrdd"; type="application/jrd+json"',
- '; rel="alternate"; type="application/activity+json"',
- ].join(', ')
+ expect(response)
+ .to have_http_status(200)
+ .and have_http_link_header('http://test.host/.well-known/webfinger?resource=acct%3Ausername%40cb6e6126.ngrok.io').for(rel: 'lrdd', type: 'application/jrd+json')
+ .and have_http_link_header('https://cb6e6126.ngrok.io/users/username').for(rel: 'alternate', type: 'application/activity+json')
+ expect(response.body)
+ .to include(account.username)
end
end
end
diff --git a/spec/controllers/concerns/api/error_handling_spec.rb b/spec/controllers/concerns/api/error_handling_spec.rb
index 9b36fc20a3..eff01605d2 100644
--- a/spec/controllers/concerns/api/error_handling_spec.rb
+++ b/spec/controllers/concerns/api/error_handling_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Api::ErrorHandling do
+RSpec.describe Api::ErrorHandling do
before do
stub_const('FakeService', Class.new)
end
diff --git a/spec/controllers/concerns/api/rate_limit_headers_spec.rb b/spec/controllers/concerns/api/rate_limit_headers_spec.rb
index 2050de2aed..6372c94e6c 100644
--- a/spec/controllers/concerns/api/rate_limit_headers_spec.rb
+++ b/spec/controllers/concerns/api/rate_limit_headers_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Api::RateLimitHeaders do
+RSpec.describe Api::RateLimitHeaders do
controller(ApplicationController) do
include Api::RateLimitHeaders
diff --git a/spec/controllers/concerns/localized_spec.rb b/spec/controllers/concerns/localized_spec.rb
index ce31e786f0..b1f805ae50 100644
--- a/spec/controllers/concerns/localized_spec.rb
+++ b/spec/controllers/concerns/localized_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Localized do
+RSpec.describe Localized do
controller(ApplicationController) do
include Localized
diff --git a/spec/controllers/concerns/settings/export_controller_concern_spec.rb b/spec/controllers/concerns/settings/export_controller_concern_spec.rb
index a19af8689a..2c67991e3a 100644
--- a/spec/controllers/concerns/settings/export_controller_concern_spec.rb
+++ b/spec/controllers/concerns/settings/export_controller_concern_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::ExportControllerConcern do
+RSpec.describe Settings::ExportControllerConcern do
controller(ApplicationController) do
include Settings::ExportControllerConcern
diff --git a/spec/controllers/concerns/user_tracking_concern_spec.rb b/spec/controllers/concerns/user_tracking_concern_spec.rb
index f23d482f5f..cc61e285cc 100644
--- a/spec/controllers/concerns/user_tracking_concern_spec.rb
+++ b/spec/controllers/concerns/user_tracking_concern_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe UserTrackingConcern do
+RSpec.describe UserTrackingConcern do
controller(ApplicationController) do
include UserTrackingConcern
diff --git a/spec/controllers/custom_css_controller_spec.rb b/spec/controllers/custom_css_controller_spec.rb
deleted file mode 100644
index 405fa0bcf3..0000000000
--- a/spec/controllers/custom_css_controller_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe CustomCssController do
- render_views
-
- describe 'GET #show' do
- before do
- get :show
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it_behaves_like 'cacheable response'
- end
-end
diff --git a/spec/controllers/emojis_controller_spec.rb b/spec/controllers/emojis_controller_spec.rb
deleted file mode 100644
index dd139de931..0000000000
--- a/spec/controllers/emojis_controller_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe EmojisController do
- render_views
-
- let(:emoji) { Fabricate(:custom_emoji, shortcode: 'coolcat') }
-
- describe 'GET #show' do
- let(:response) { get :show, params: { id: emoji.id, format: :json } }
-
- it 'returns the right response' do
- expect(response).to have_http_status 200
- expect(body_as_json[:name]).to eq ':coolcat:'
- end
- end
-end
diff --git a/spec/controllers/filters/statuses_controller_spec.rb b/spec/controllers/filters/statuses_controller_spec.rb
index 2c80613302..f1fed76fca 100644
--- a/spec/controllers/filters/statuses_controller_spec.rb
+++ b/spec/controllers/filters/statuses_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Filters::StatusesController do
+RSpec.describe Filters::StatusesController do
render_views
describe 'GET #index' do
diff --git a/spec/controllers/filters_controller_spec.rb b/spec/controllers/filters_controller_spec.rb
index 091f714bb3..de043e8ae3 100644
--- a/spec/controllers/filters_controller_spec.rb
+++ b/spec/controllers/filters_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe FiltersController do
+RSpec.describe FiltersController do
render_views
describe 'GET #index' do
diff --git a/spec/controllers/follower_accounts_controller_spec.rb b/spec/controllers/follower_accounts_controller_spec.rb
index dd78c96c05..e14ed00e60 100644
--- a/spec/controllers/follower_accounts_controller_spec.rb
+++ b/spec/controllers/follower_accounts_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe FollowerAccountsController do
+RSpec.describe FollowerAccountsController do
render_views
let(:alice) { Fabricate(:account, username: 'alice') }
@@ -39,8 +39,6 @@ describe FollowerAccountsController do
end
context 'when format is json' do
- subject(:body) { response.parsed_body }
-
let(:response) { get :index, params: { account_username: alice.username, page: page, format: :json } }
context 'with page' do
@@ -48,15 +46,15 @@ describe FollowerAccountsController do
it 'returns followers' do
expect(response).to have_http_status(200)
- expect(body_as_json)
+ expect(response.parsed_body)
.to include(
orderedItems: contain_exactly(
include(follow_from_bob.account.username),
include(follow_from_chris.account.username)
- )
+ ),
+ totalItems: eq(2),
+ partOf: be_present
)
- expect(body['totalItems']).to eq 2
- expect(body['partOf']).to be_present
end
context 'when account is permanently suspended' do
@@ -86,8 +84,11 @@ describe FollowerAccountsController do
it 'returns followers' do
expect(response).to have_http_status(200)
- expect(body['totalItems']).to eq 2
- expect(body['partOf']).to be_blank
+ expect(response.parsed_body)
+ .to include(
+ totalItems: eq(2)
+ )
+ .and not_include(:partOf)
end
context 'when account hides their network' do
@@ -95,15 +96,17 @@ describe FollowerAccountsController do
alice.update(hide_collections: true)
end
- it 'returns followers count' do
- expect(body['totalItems']).to eq 2
- end
-
- it 'does not return items' do
- expect(body['items']).to be_blank
- expect(body['orderedItems']).to be_blank
- expect(body['first']).to be_blank
- expect(body['last']).to be_blank
+ it 'returns followers count but not any items' do
+ expect(response.parsed_body)
+ .to include(
+ totalItems: eq(2)
+ )
+ .and not_include(
+ :items,
+ :orderedItems,
+ :first,
+ :last
+ )
end
end
diff --git a/spec/controllers/following_accounts_controller_spec.rb b/spec/controllers/following_accounts_controller_spec.rb
index 7bb78fb420..fea4d4845c 100644
--- a/spec/controllers/following_accounts_controller_spec.rb
+++ b/spec/controllers/following_accounts_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe FollowingAccountsController do
+RSpec.describe FollowingAccountsController do
render_views
let(:alice) { Fabricate(:account, username: 'alice') }
@@ -39,8 +39,6 @@ describe FollowingAccountsController do
end
context 'when format is json' do
- subject(:body) { response.parsed_body }
-
let(:response) { get :index, params: { account_username: alice.username, page: page, format: :json } }
context 'with page' do
@@ -48,15 +46,15 @@ describe FollowingAccountsController do
it 'returns followers' do
expect(response).to have_http_status(200)
- expect(body_as_json)
+ expect(response.parsed_body)
.to include(
orderedItems: contain_exactly(
include(follow_of_bob.target_account.username),
include(follow_of_chris.target_account.username)
- )
+ ),
+ totalItems: eq(2),
+ partOf: be_present
)
- expect(body['totalItems']).to eq 2
- expect(body['partOf']).to be_present
end
context 'when account is permanently suspended' do
@@ -86,8 +84,11 @@ describe FollowingAccountsController do
it 'returns followers' do
expect(response).to have_http_status(200)
- expect(body['totalItems']).to eq 2
- expect(body['partOf']).to be_blank
+ expect(response.parsed_body)
+ .to include(
+ totalItems: eq(2)
+ )
+ .and not_include(:partOf)
end
context 'when account hides their network' do
@@ -95,15 +96,17 @@ describe FollowingAccountsController do
alice.update(hide_collections: true)
end
- it 'returns followers count' do
- expect(body['totalItems']).to eq 2
- end
-
- it 'does not return items' do
- expect(body['items']).to be_blank
- expect(body['orderedItems']).to be_blank
- expect(body['first']).to be_blank
- expect(body['last']).to be_blank
+ it 'returns followers count but not any items' do
+ expect(response.parsed_body)
+ .to include(
+ totalItems: eq(2)
+ )
+ .and not_include(
+ :items,
+ :orderedItems,
+ :first,
+ :last
+ )
end
end
diff --git a/spec/controllers/health_controller_spec.rb b/spec/controllers/health_controller_spec.rb
deleted file mode 100644
index 282b664199..0000000000
--- a/spec/controllers/health_controller_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe HealthController do
- render_views
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb
deleted file mode 100644
index 50a8aba2d8..0000000000
--- a/spec/controllers/home_controller_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe HomeController do
- render_views
-
- describe 'GET #index' do
- subject { get :index }
-
- context 'when not signed in' do
- it 'returns http success' do
- request.path = '/'
- expect(subject).to have_http_status(:success)
- end
- end
-
- context 'when signed in' do
- let(:user) { Fabricate(:user) }
-
- before do
- sign_in(user)
- end
-
- it 'returns http success' do
- expect(subject).to have_http_status(:success)
- end
- end
- end
-end
diff --git a/spec/controllers/instance_actors_controller_spec.rb b/spec/controllers/instance_actors_controller_spec.rb
deleted file mode 100644
index 42ffb67988..0000000000
--- a/spec/controllers/instance_actors_controller_spec.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe InstanceActorsController do
- describe 'GET #show' do
- context 'with JSON' do
- let(:format) { 'json' }
-
- shared_examples 'shared behavior' do
- before do
- get :show, params: { format: format }
- end
-
- it 'returns http success with correct media type and body' do
- expect(response)
- .to have_http_status(200)
- .and have_attributes(
- media_type: eq('application/activity+json')
- )
-
- expect(body_as_json)
- .to include(:id, :type, :preferredUsername, :inbox, :publicKey, :inbox, :outbox, :url)
- end
-
- it_behaves_like 'cacheable response'
- end
-
- before do
- allow(controller).to receive(:authorized_fetch_mode?).and_return(authorized_fetch_mode)
- end
-
- context 'without authorized fetch mode' do
- let(:authorized_fetch_mode) { false }
-
- it_behaves_like 'shared behavior'
- end
-
- context 'with authorized fetch mode' do
- let(:authorized_fetch_mode) { true }
-
- it_behaves_like 'shared behavior'
- end
-
- context 'with a suspended instance actor' do
- let(:authorized_fetch_mode) { false }
-
- before { Account.representative.update(suspended_at: 10.days.ago) }
-
- it_behaves_like 'shared behavior'
- end
- end
- end
-end
diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb
deleted file mode 100644
index 5221941267..0000000000
--- a/spec/controllers/invites_controller_spec.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe InvitesController do
- render_views
-
- let(:user) { Fabricate(:user) }
-
- before do
- sign_in user
- end
-
- describe 'GET #index' do
- before do
- Fabricate(:invite, user: user)
- end
-
- context 'when everyone can invite' do
- before do
- UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
- get :index
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(:success)
- end
-
- it 'returns private cache control headers' do
- expect(response.headers['Cache-Control']).to include('private, no-store')
- end
- end
-
- context 'when not everyone can invite' do
- before do
- UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
- get :index
- end
-
- it 'returns http forbidden' do
- expect(response).to have_http_status(403)
- end
- end
- end
-
- describe 'POST #create' do
- subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
-
- context 'when everyone can invite' do
- before do
- UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
- end
-
- it 'succeeds to create a invite' do
- expect { subject }.to change(Invite, :count).by(1)
- expect(subject).to redirect_to invites_path
- expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10)
- end
- end
-
- context 'when not everyone can invite' do
- before do
- UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
- end
-
- it 'returns http forbidden' do
- expect(subject).to have_http_status(403)
- end
- end
- end
-
- describe 'DELETE #destroy' do
- subject { delete :destroy, params: { id: invite.id } }
-
- let(:invite) { Fabricate(:invite, user: user, expires_at: nil) }
-
- it 'expires invite and redirects' do
- expect { subject }
- .to(change { invite.reload.expired? }.to(true))
- expect(response)
- .to redirect_to invites_path
- end
- end
-end
diff --git a/spec/controllers/manifests_controller_spec.rb b/spec/controllers/manifests_controller_spec.rb
deleted file mode 100644
index 9279fae024..0000000000
--- a/spec/controllers/manifests_controller_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ManifestsController do
- render_views
-
- describe 'GET #show' do
- before do
- get :show
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it_behaves_like 'cacheable response'
- end
-end
diff --git a/spec/controllers/media_controller_spec.rb b/spec/controllers/media_controller_spec.rb
deleted file mode 100644
index efd15b5b40..0000000000
--- a/spec/controllers/media_controller_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe MediaController do
- render_views
-
- describe '#show' do
- it 'raises when shortcode cant be found' do
- get :show, params: { id: 'missing' }
-
- expect(response).to have_http_status(404)
- end
-
- context 'when the media attachment has a shortcode' do
- it 'redirects to the file url when attached to a status' do
- status = Fabricate(:status)
- media_attachment = Fabricate(:media_attachment, status: status, shortcode: 'OI6IgDzG-nYTqvDQ994')
- get :show, params: { id: media_attachment.to_param }
-
- expect(response).to redirect_to(media_attachment.file.url(:original))
- end
-
- it 'responds with missing when there is not an attached status' do
- media_attachment = Fabricate(:media_attachment, status: nil, shortcode: 'OI6IgDzG-nYTqvDQ994')
- get :show, params: { id: media_attachment.to_param }
-
- expect(response).to have_http_status(404)
- end
-
- it 'raises when not permitted to view' do
- status = Fabricate(:status, visibility: :direct)
- media_attachment = Fabricate(:media_attachment, status: status, shortcode: 'OI6IgDzG-nYTqvDQ994')
- get :show, params: { id: media_attachment.to_param }
-
- expect(response).to have_http_status(404)
- end
- end
-
- context 'when the media attachment has no shortcode' do
- it 'redirects to the file url when attached to a status' do
- status = Fabricate(:status)
- media_attachment = Fabricate(:media_attachment, status: status)
- get :show, params: { id: media_attachment.to_param }
-
- expect(response).to redirect_to(media_attachment.file.url(:original))
- end
-
- it 'responds with missing when there is not an attached status' do
- media_attachment = Fabricate(:media_attachment, status: nil)
- get :show, params: { id: media_attachment.to_param }
-
- expect(response).to have_http_status(404)
- end
-
- it 'raises when not permitted to view' do
- status = Fabricate(:status, visibility: :direct)
- media_attachment = Fabricate(:media_attachment, status: status)
- get :show, params: { id: media_attachment.to_param }
-
- expect(response).to have_http_status(404)
- end
- end
- end
-end
diff --git a/spec/controllers/media_proxy_controller_spec.rb b/spec/controllers/media_proxy_controller_spec.rb
deleted file mode 100644
index 32510cf43d..0000000000
--- a/spec/controllers/media_proxy_controller_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe MediaProxyController do
- render_views
-
- before do
- stub_request(:get, 'http://example.com/attachment.png').to_return(request_fixture('avatar.txt'))
- end
-
- describe '#show' do
- it 'redirects when attached to a status' do
- status = Fabricate(:status)
- media_attachment = Fabricate(:media_attachment, status: status, remote_url: 'http://example.com/attachment.png')
- get :show, params: { id: media_attachment.id }
-
- expect(response).to have_http_status(302)
- end
-
- it 'responds with missing when there is not an attached status' do
- media_attachment = Fabricate(:media_attachment, status: nil, remote_url: 'http://example.com/attachment.png')
- get :show, params: { id: media_attachment.id }
-
- expect(response).to have_http_status(404)
- end
-
- it 'raises when id cant be found' do
- get :show, params: { id: 'missing' }
-
- expect(response).to have_http_status(404)
- end
-
- it 'raises when not permitted to view' do
- status = Fabricate(:status, visibility: :direct)
- media_attachment = Fabricate(:media_attachment, status: status, remote_url: 'http://example.com/attachment.png')
- get :show, params: { id: media_attachment.id }
-
- expect(response).to have_http_status(404)
- end
- end
-end
diff --git a/spec/controllers/oauth/authorizations_controller_spec.rb b/spec/controllers/oauth/authorizations_controller_spec.rb
index 9bb520211c..cfc80b8650 100644
--- a/spec/controllers/oauth/authorizations_controller_spec.rb
+++ b/spec/controllers/oauth/authorizations_controller_spec.rb
@@ -10,13 +10,6 @@ RSpec.describe Oauth::AuthorizationsController do
get :new, params: { client_id: app.uid, response_type: 'code', redirect_uri: 'http://localhost/', scope: 'read' }
end
- shared_examples 'stores location for user' do
- it 'stores location for user' do
- subject
- expect(controller.stored_location_for(:user)).to eq "/oauth/authorize?client_id=#{app.uid}&redirect_uri=http%3A%2F%2Flocalhost%2F&response_type=code&scope=read"
- end
- end
-
context 'when signed in' do
let!(:user) { Fabricate(:user) }
@@ -24,18 +17,17 @@ RSpec.describe Oauth::AuthorizationsController do
sign_in user, scope: :user
end
- it 'returns http success' do
+ it 'returns http success and private cache control headers' do
subject
- expect(response).to have_http_status(200)
- end
- it 'returns private cache control headers' do
- subject
- expect(response.headers['Cache-Control']).to include('private, no-store')
+ expect(response)
+ .to have_http_status(200)
+ expect(response.headers['Cache-Control'])
+ .to include('private, no-store')
+ expect(controller.stored_location_for(:user))
+ .to eq authorize_path_for(app)
end
- include_examples 'stores location for user'
-
context 'when app is already authorized' do
before do
Doorkeeper::AccessToken.find_or_create_for(
@@ -52,10 +44,12 @@ RSpec.describe Oauth::AuthorizationsController do
expect(response).to redirect_to(/\A#{app.redirect_uri}/)
end
- it 'does not redirect to callback with force_login=true' do
- get :new, params: { client_id: app.uid, response_type: 'code', redirect_uri: 'http://localhost/', scope: 'read', force_login: 'true' }
+ context 'with `force_login` param true' do
+ subject do
+ get :new, params: { client_id: app.uid, response_type: 'code', redirect_uri: 'http://localhost/', scope: 'read', force_login: 'true' }
+ end
- expect(response).to have_http_status(:success)
+ it { is_expected.to have_http_status(:success) }
end
end
end
@@ -63,10 +57,16 @@ RSpec.describe Oauth::AuthorizationsController do
context 'when not signed in' do
it 'redirects' do
subject
- expect(response).to redirect_to '/auth/sign_in'
- end
- include_examples 'stores location for user'
+ expect(response)
+ .to redirect_to '/auth/sign_in'
+ expect(controller.stored_location_for(:user))
+ .to eq authorize_path_for(app)
+ end
+ end
+
+ def authorize_path_for(app)
+ "/oauth/authorize?client_id=#{app.uid}&redirect_uri=http%3A%2F%2Flocalhost%2F&response_type=code&scope=read"
end
end
end
diff --git a/spec/controllers/oauth/authorized_applications_controller_spec.rb b/spec/controllers/oauth/authorized_applications_controller_spec.rb
index 3fd9f9499f..1cf0984abe 100644
--- a/spec/controllers/oauth/authorized_applications_controller_spec.rb
+++ b/spec/controllers/oauth/authorized_applications_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Oauth::AuthorizedApplicationsController do
+RSpec.describe Oauth::AuthorizedApplicationsController do
render_views
describe 'GET #index' do
@@ -10,38 +10,31 @@ describe Oauth::AuthorizedApplicationsController do
get :index
end
- shared_examples 'stores location for user' do
- it 'stores location for user' do
- subject
- expect(controller.stored_location_for(:user)).to eq '/oauth/authorized_applications'
- end
- end
-
context 'when signed in' do
before do
sign_in Fabricate(:user), scope: :user
end
- it 'returns http success' do
+ it 'returns http success with private cache control headers' do
subject
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ expect(response.headers['Cache-Control'])
+ .to include('private, no-store')
+ expect(controller.stored_location_for(:user))
+ .to eq '/oauth/authorized_applications'
end
-
- it 'returns private cache control headers' do
- subject
- expect(response.headers['Cache-Control']).to include('private, no-store')
- end
-
- include_examples 'stores location for user'
end
context 'when not signed in' do
it 'redirects' do
subject
- expect(response).to redirect_to '/auth/sign_in'
- end
- include_examples 'stores location for user'
+ expect(response)
+ .to redirect_to '/auth/sign_in'
+ expect(controller.stored_location_for(:user))
+ .to eq '/oauth/authorized_applications'
+ end
end
end
@@ -55,23 +48,19 @@ describe Oauth::AuthorizedApplicationsController do
before do
sign_in user, scope: :user
allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub)
+ end
+
+ it 'revokes access tokens for the application and removes subscriptions and sends kill payload to streaming' do
post :destroy, params: { id: application.id }
- end
- it 'revokes access tokens for the application' do
- expect(Doorkeeper::AccessToken.where(application: application).first.revoked_at).to_not be_nil
- end
-
- it 'removes subscriptions for the application\'s access tokens' do
- expect(Web::PushSubscription.where(user: user).count).to eq 0
- end
-
- it 'removes the web_push_subscription' do
- expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'sends a session kill payload to the streaming server' do
- expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}')
+ expect(Doorkeeper::AccessToken.where(application: application).first.revoked_at)
+ .to_not be_nil
+ expect(Web::PushSubscription.where(user: user).count)
+ .to eq(0)
+ expect { web_push_subscription.reload }
+ .to raise_error(ActiveRecord::RecordNotFound)
+ expect(redis_pipeline_stub)
+ .to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}')
end
end
end
diff --git a/spec/controllers/oauth/tokens_controller_spec.rb b/spec/controllers/oauth/tokens_controller_spec.rb
index dd2d8ca70c..a2eed797e0 100644
--- a/spec/controllers/oauth/tokens_controller_spec.rb
+++ b/spec/controllers/oauth/tokens_controller_spec.rb
@@ -9,20 +9,15 @@ RSpec.describe Oauth::TokensController do
let!(:access_token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: application) }
let!(:web_push_subscription) { Fabricate(:web_push_subscription, user: user, access_token: access_token) }
- before do
+ it 'revokes the token and removes subscriptions' do
post :revoke, params: { client_id: application.uid, token: access_token.token }
- end
- it 'revokes the token' do
- expect(access_token.reload.revoked_at).to_not be_nil
- end
-
- it 'removes web push subscription for token' do
- expect(Web::PushSubscription.where(access_token: access_token).count).to eq 0
- end
-
- it 'removes the web_push_subscription' do
- expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ expect(access_token.reload.revoked_at)
+ .to_not be_nil
+ expect(Web::PushSubscription.where(access_token: access_token).count)
+ .to eq(0)
+ expect { web_push_subscription.reload }
+ .to raise_error(ActiveRecord::RecordNotFound)
end
end
end
diff --git a/spec/controllers/privacy_controller_spec.rb b/spec/controllers/privacy_controller_spec.rb
deleted file mode 100644
index c92c71ea64..0000000000
--- a/spec/controllers/privacy_controller_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe PrivacyController do
- render_views
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/relationships_controller_spec.rb b/spec/controllers/relationships_controller_spec.rb
index 9495fc214f..323fcc995d 100644
--- a/spec/controllers/relationships_controller_spec.rb
+++ b/spec/controllers/relationships_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RelationshipsController do
+RSpec.describe RelationshipsController do
render_views
let(:user) { Fabricate(:user) }
diff --git a/spec/controllers/settings/aliases_controller_spec.rb b/spec/controllers/settings/aliases_controller_spec.rb
index 18e568be0b..4858c15298 100644
--- a/spec/controllers/settings/aliases_controller_spec.rb
+++ b/spec/controllers/settings/aliases_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::AliasesController do
+RSpec.describe Settings::AliasesController do
render_views
let!(:user) { Fabricate(:user) }
diff --git a/spec/controllers/settings/applications_controller_spec.rb b/spec/controllers/settings/applications_controller_spec.rb
deleted file mode 100644
index ce2e0749a7..0000000000
--- a/spec/controllers/settings/applications_controller_spec.rb
+++ /dev/null
@@ -1,178 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::ApplicationsController do
- render_views
-
- let!(:user) { Fabricate(:user) }
- let!(:app) { Fabricate(:application, owner: user) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #index' do
- before do
- Fabricate(:application)
- get :index
- end
-
- it 'returns http success with private cache control headers', :aggregate_failures do
- expect(response).to have_http_status(200)
- expect(response.headers['Cache-Control']).to include('private, no-store')
- end
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show, params: { id: app.id }
- expect(response).to have_http_status(200)
- expect(assigns[:application]).to eql(app)
- end
-
- it 'returns 404 if you dont own app' do
- app.update!(owner: nil)
-
- get :show, params: { id: app.id }
- expect(response).to have_http_status 404
- end
- end
-
- describe 'GET #new' do
- it 'returns http success' do
- get :new
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- context 'when success (passed scopes as a String)' do
- subject do
- post :create, params: {
- doorkeeper_application: {
- name: 'My New App',
- redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
- website: 'http://google.com',
- scopes: 'read write follow',
- },
- }
- end
-
- it 'creates an entry in the database', :aggregate_failures do
- expect { subject }.to change(Doorkeeper::Application, :count)
- expect(response).to redirect_to(settings_applications_path)
- end
- end
-
- context 'when success (passed scopes as an Array)' do
- subject do
- post :create, params: {
- doorkeeper_application: {
- name: 'My New App',
- redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
- website: 'http://google.com',
- scopes: %w(read write follow),
- },
- }
- end
-
- it 'creates an entry in the database', :aggregate_failures do
- expect { subject }.to change(Doorkeeper::Application, :count)
- expect(response).to redirect_to(settings_applications_path)
- end
- end
-
- context 'with failure request' do
- before do
- post :create, params: {
- doorkeeper_application: {
- name: '',
- redirect_uri: '',
- website: '',
- scopes: [],
- },
- }
- end
-
- it 'returns http success and renders form', :aggregate_failures do
- expect(response).to have_http_status(200)
- expect(response).to render_template(:new)
- end
- end
- end
-
- describe 'PATCH #update' do
- context 'when success' do
- subject do
- patch :update, params: {
- id: app.id,
- doorkeeper_application: opts,
- }
- response
- end
-
- let(:opts) do
- {
- website: 'https://foo.bar/',
- }
- end
-
- it 'updates existing application' do
- subject
-
- expect(app.reload.website).to eql(opts[:website])
- expect(response).to redirect_to(settings_application_path(app))
- end
- end
-
- context 'with failure request' do
- before do
- patch :update, params: {
- id: app.id,
- doorkeeper_application: {
- name: '',
- redirect_uri: '',
- website: '',
- scopes: [],
- },
- }
- end
-
- it 'returns http success and renders form', :aggregate_failures do
- expect(response).to have_http_status(200)
- expect(response).to render_template(:show)
- end
- end
- end
-
- describe 'destroy' do
- let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) }
- let!(:access_token) { Fabricate(:accessible_access_token, application: app) }
-
- before do
- allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub)
- post :destroy, params: { id: app.id }
- end
-
- it 'redirects back to applications page removes the app' do
- expect(response).to redirect_to(settings_applications_path)
- expect(Doorkeeper::Application.find_by(id: app.id)).to be_nil
- end
-
- it 'sends a session kill payload to the streaming server' do
- expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}')
- end
- end
-
- describe 'regenerate' do
- let(:token) { user.token_for_app(app) }
-
- it 'creates new token' do
- expect(token).to_not be_nil
- post :regenerate, params: { id: app.id }
-
- expect(user.token_for_app(app)).to_not eql(token)
- end
- end
-end
diff --git a/spec/controllers/settings/deletes_controller_spec.rb b/spec/controllers/settings/deletes_controller_spec.rb
index 3342599bc1..98104b8454 100644
--- a/spec/controllers/settings/deletes_controller_spec.rb
+++ b/spec/controllers/settings/deletes_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::DeletesController do
+RSpec.describe Settings::DeletesController do
render_views
describe 'GET #show' do
diff --git a/spec/controllers/settings/exports/blocked_accounts_controller_spec.rb b/spec/controllers/settings/exports/blocked_accounts_controller_spec.rb
deleted file mode 100644
index 459b278d64..0000000000
--- a/spec/controllers/settings/exports/blocked_accounts_controller_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::Exports::BlockedAccountsController do
- render_views
-
- describe 'GET #index' do
- it 'returns a csv of the blocking accounts' do
- user = Fabricate(:user)
- user.account.block!(Fabricate(:account, username: 'username', domain: 'domain'))
-
- sign_in user, scope: :user
- get :index, format: :csv
-
- expect(response.body).to eq "username@domain\n"
- end
- end
-end
diff --git a/spec/controllers/settings/exports/blocked_domains_controller_spec.rb b/spec/controllers/settings/exports/blocked_domains_controller_spec.rb
deleted file mode 100644
index ac72fd9dd7..0000000000
--- a/spec/controllers/settings/exports/blocked_domains_controller_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::Exports::BlockedDomainsController do
- render_views
-
- describe 'GET #index' do
- it 'returns a csv of the domains' do
- account = Fabricate(:account, domain: 'example.com')
- user = Fabricate(:user, account: account)
- Fabricate(:account_domain_block, domain: 'example.com', account: account)
-
- sign_in user, scope: :user
- get :index, format: :csv
-
- expect(response.body).to eq "example.com\n"
- end
- end
-end
diff --git a/spec/controllers/settings/exports/bookmarks_controller_spec.rb b/spec/controllers/settings/exports/bookmarks_controller_spec.rb
deleted file mode 100644
index 9982eff165..0000000000
--- a/spec/controllers/settings/exports/bookmarks_controller_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::Exports::BookmarksController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:account) { Fabricate(:account, domain: 'foo.bar') }
- let(:status) { Fabricate(:status, account: account, uri: 'https://foo.bar/statuses/1312') }
-
- describe 'GET #index' do
- before do
- user.account.bookmarks.create!(status: status)
- end
-
- it 'returns a csv of the bookmarked toots' do
- sign_in user, scope: :user
- get :index, format: :csv
-
- expect(response.body).to eq "https://foo.bar/statuses/1312\n"
- end
- end
-end
diff --git a/spec/controllers/settings/exports/following_accounts_controller_spec.rb b/spec/controllers/settings/exports/following_accounts_controller_spec.rb
deleted file mode 100644
index 72b0b94e13..0000000000
--- a/spec/controllers/settings/exports/following_accounts_controller_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::Exports::FollowingAccountsController do
- render_views
-
- describe 'GET #index' do
- it 'returns a csv of the following accounts' do
- user = Fabricate(:user)
- user.account.follow!(Fabricate(:account, username: 'username', domain: 'domain'))
-
- sign_in user, scope: :user
- get :index, format: :csv
-
- expect(response.body).to eq "Account address,Show boosts,Notify on new posts,Languages\nusername@domain,true,false,\n"
- end
- end
-end
diff --git a/spec/controllers/settings/exports/lists_controller_spec.rb b/spec/controllers/settings/exports/lists_controller_spec.rb
deleted file mode 100644
index 29623ba499..0000000000
--- a/spec/controllers/settings/exports/lists_controller_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::Exports::ListsController do
- render_views
-
- describe 'GET #index' do
- it 'returns a csv of the domains' do
- account = Fabricate(:account)
- user = Fabricate(:user, account: account)
- list = Fabricate(:list, account: account, title: 'The List')
- Fabricate(:list_account, list: list, account: account)
-
- sign_in user, scope: :user
- get :index, format: :csv
-
- expect(response.body).to match 'The List'
- end
- end
-end
diff --git a/spec/controllers/settings/exports/muted_accounts_controller_spec.rb b/spec/controllers/settings/exports/muted_accounts_controller_spec.rb
deleted file mode 100644
index b4170cb160..0000000000
--- a/spec/controllers/settings/exports/muted_accounts_controller_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::Exports::MutedAccountsController do
- render_views
-
- describe 'GET #index' do
- it 'returns a csv of the muting accounts' do
- user = Fabricate(:user)
- user.account.mute!(Fabricate(:account, username: 'username', domain: 'domain'))
-
- sign_in user, scope: :user
- get :index, format: :csv
-
- expect(response.body).to eq "Account address,Hide notifications\nusername@domain,true\n"
- end
- end
-end
diff --git a/spec/controllers/settings/exports_controller_spec.rb b/spec/controllers/settings/exports_controller_spec.rb
deleted file mode 100644
index 3399f78ac5..0000000000
--- a/spec/controllers/settings/exports_controller_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::ExportsController do
- render_views
-
- describe 'GET #show' do
- context 'when signed in' do
- let(:user) { Fabricate(:user) }
-
- before do
- sign_in user, scope: :user
- get :show
- end
-
- it 'returns http success with private cache control headers', :aggregate_failures do
- expect(response).to have_http_status(200)
- expect(response.headers['Cache-Control']).to include('private, no-store')
- end
- end
-
- context 'when not signed in' do
- it 'redirects' do
- get :show
- expect(response).to redirect_to '/auth/sign_in'
- end
- end
- end
-
- describe 'POST #create' do
- before do
- sign_in Fabricate(:user), scope: :user
- end
-
- it 'redirects to settings_export_path' do
- post :create
- expect(response).to redirect_to(settings_export_path)
- end
-
- it 'queues BackupWorker job by 1' do
- expect do
- post :create
- end.to change(BackupWorker.jobs, :size).by(1)
- end
- end
-end
diff --git a/spec/controllers/settings/featured_tags_controller_spec.rb b/spec/controllers/settings/featured_tags_controller_spec.rb
index 4e1dd52945..f414e818f5 100644
--- a/spec/controllers/settings/featured_tags_controller_spec.rb
+++ b/spec/controllers/settings/featured_tags_controller_spec.rb
@@ -2,19 +2,13 @@
require 'rails_helper'
-describe Settings::FeaturedTagsController do
+RSpec.describe Settings::FeaturedTagsController do
render_views
- shared_examples 'authenticate user' do
- it 'redirects to sign_in page' do
- expect(subject).to redirect_to new_user_session_path
- end
- end
-
context 'when user is not signed in' do
subject { post :create }
- it_behaves_like 'authenticate user'
+ it { is_expected.to redirect_to new_user_session_path }
end
context 'when user is signed in' do
diff --git a/spec/controllers/settings/imports_controller_spec.rb b/spec/controllers/settings/imports_controller_spec.rb
index 89ec39e54d..219b882e6d 100644
--- a/spec/controllers/settings/imports_controller_spec.rb
+++ b/spec/controllers/settings/imports_controller_spec.rb
@@ -21,9 +21,10 @@ RSpec.describe Settings::ImportsController do
it 'assigns the expected imports', :aggregate_failures do
expect(response).to have_http_status(200)
- expect(assigns(:recent_imports)).to eq [import]
- expect(assigns(:recent_imports)).to_not include(other_import)
expect(response.headers['Cache-Control']).to include('private, no-store')
+ expect(response.body)
+ .to include("bulk_import_#{import.id}")
+ .and not_include("bulk_import_#{other_import.id}")
end
end
@@ -261,7 +262,8 @@ RSpec.describe Settings::ImportsController do
it 'does not creates an unconfirmed bulk_import', :aggregate_failures do
expect { subject }.to_not(change { user.account.bulk_imports.count })
- expect(assigns(:import).errors).to_not be_empty
+ expect(response.body)
+ .to include('field_with_errors')
end
end
diff --git a/spec/controllers/settings/login_activities_controller_spec.rb b/spec/controllers/settings/login_activities_controller_spec.rb
index 294bf85c97..3447620abb 100644
--- a/spec/controllers/settings/login_activities_controller_spec.rb
+++ b/spec/controllers/settings/login_activities_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::LoginActivitiesController do
+RSpec.describe Settings::LoginActivitiesController do
render_views
let!(:user) { Fabricate(:user) }
diff --git a/spec/controllers/settings/migration/redirects_controller_spec.rb b/spec/controllers/settings/migration/redirects_controller_spec.rb
index b909a02668..d853fe8ae6 100644
--- a/spec/controllers/settings/migration/redirects_controller_spec.rb
+++ b/spec/controllers/settings/migration/redirects_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::Migration::RedirectsController do
+RSpec.describe Settings::Migration::RedirectsController do
render_views
let!(:user) { Fabricate(:user, password: 'testtest') }
diff --git a/spec/controllers/settings/migrations_controller_spec.rb b/spec/controllers/settings/migrations_controller_spec.rb
index f3340574d0..dca4c925fd 100644
--- a/spec/controllers/settings/migrations_controller_spec.rb
+++ b/spec/controllers/settings/migrations_controller_spec.rb
@@ -2,20 +2,14 @@
require 'rails_helper'
-describe Settings::MigrationsController do
+RSpec.describe Settings::MigrationsController do
render_views
- shared_examples 'authenticate user' do
- it 'redirects to sign_in page' do
- expect(subject).to redirect_to new_user_session_path
- end
- end
-
describe 'GET #show' do
context 'when user is not sign in' do
subject { get :show }
- it_behaves_like 'authenticate user'
+ it { is_expected.to redirect_to new_user_session_path }
end
context 'when user is sign in' do
@@ -49,7 +43,7 @@ describe Settings::MigrationsController do
context 'when user is not sign in' do
subject { post :create }
- it_behaves_like 'authenticate user'
+ it { is_expected.to redirect_to new_user_session_path }
end
context 'when user is signed in' do
diff --git a/spec/controllers/settings/pictures_controller_spec.rb b/spec/controllers/settings/pictures_controller_spec.rb
index 705878f03d..683d231ed1 100644
--- a/spec/controllers/settings/pictures_controller_spec.rb
+++ b/spec/controllers/settings/pictures_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::PicturesController do
+RSpec.describe Settings::PicturesController do
render_views
let!(:user) { Fabricate(:user) }
diff --git a/spec/controllers/settings/preferences/appearance_controller_spec.rb b/spec/controllers/settings/preferences/appearance_controller_spec.rb
index c59d315104..ede00699a2 100644
--- a/spec/controllers/settings/preferences/appearance_controller_spec.rb
+++ b/spec/controllers/settings/preferences/appearance_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::Preferences::AppearanceController do
+RSpec.describe Settings::Preferences::AppearanceController do
render_views
let!(:user) { Fabricate(:user) }
diff --git a/spec/controllers/settings/preferences/base_controller_spec.rb b/spec/controllers/settings/preferences/base_controller_spec.rb
index 53b3a461ed..75fc999a48 100644
--- a/spec/controllers/settings/preferences/base_controller_spec.rb
+++ b/spec/controllers/settings/preferences/base_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::Preferences::BaseController do
+RSpec.describe Settings::Preferences::BaseController do
describe 'after_update_redirect_path' do
it 'raises error when called' do
expect { described_class.new.send(:after_update_redirect_path) }.to raise_error(/Override/)
diff --git a/spec/controllers/settings/preferences/notifications_controller_spec.rb b/spec/controllers/settings/preferences/notifications_controller_spec.rb
index e0f0bc55a7..edfdea50e0 100644
--- a/spec/controllers/settings/preferences/notifications_controller_spec.rb
+++ b/spec/controllers/settings/preferences/notifications_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::Preferences::NotificationsController do
+RSpec.describe Settings::Preferences::NotificationsController do
render_views
let(:user) { Fabricate(:user) }
diff --git a/spec/controllers/settings/preferences/other_controller_spec.rb b/spec/controllers/settings/preferences/other_controller_spec.rb
index 61a94a4142..117fdeea7c 100644
--- a/spec/controllers/settings/preferences/other_controller_spec.rb
+++ b/spec/controllers/settings/preferences/other_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::Preferences::OtherController do
+RSpec.describe Settings::Preferences::OtherController do
render_views
let(:user) { Fabricate(:user, chosen_languages: []) }
diff --git a/spec/controllers/settings/sessions_controller_spec.rb b/spec/controllers/settings/sessions_controller_spec.rb
index a4248e1bde..c098af7485 100644
--- a/spec/controllers/settings/sessions_controller_spec.rb
+++ b/spec/controllers/settings/sessions_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::SessionsController do
+RSpec.describe Settings::SessionsController do
render_views
let(:user) { Fabricate(:user) }
diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
index 1b3b0cb0ae..34eaacdf49 100644
--- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
+++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
@@ -2,18 +2,23 @@
require 'rails_helper'
-describe Settings::TwoFactorAuthentication::ConfirmationsController do
+RSpec.describe Settings::TwoFactorAuthentication::ConfirmationsController do
render_views
shared_examples 'renders :new' do
it 'renders the new view' do
subject
- expect(assigns(:confirmation)).to be_instance_of Form::TwoFactorConfirmation
- expect(assigns(:provision_url)).to eq 'otpauth://totp/cb6e6126.ngrok.io:local-part%40domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io'
- expect(assigns(:qrcode)).to be_instance_of RQRCode::QRCode
expect(response).to have_http_status(200)
expect(response).to render_template(:new)
+ expect(response.body)
+ .to include(qr_code_markup)
+ end
+
+ def qr_code_markup
+ RQRCode::QRCode.new(
+ 'otpauth://totp/cb6e6126.ngrok.io:local-part%40domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io'
+ ).as_svg(padding: 0, module_size: 4)
end
end
@@ -61,10 +66,10 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do
expect { post_create_with_options }
.to change { user.reload.otp_secret }.to 'thisisasecretforthespecofnewview'
- expect(assigns(:recovery_codes)).to eq otp_backup_codes
expect(flash[:notice]).to eq 'Two-factor authentication successfully enabled'
expect(response).to have_http_status(200)
expect(response).to render_template('settings/two_factor_authentication/recovery_codes/index')
+ expect(response.body).to include(*otp_backup_codes)
end
end
diff --git a/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb
index 007df87d95..a03c4a4adb 100644
--- a/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb
+++ b/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::TwoFactorAuthentication::OtpAuthenticationController do
+RSpec.describe Settings::TwoFactorAuthentication::OtpAuthenticationController do
render_views
let(:user) { Fabricate(:user) }
diff --git a/spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb
index 28a40e138c..0defc52cde 100644
--- a/spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb
+++ b/spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::TwoFactorAuthentication::RecoveryCodesController do
+RSpec.describe Settings::TwoFactorAuthentication::RecoveryCodesController do
render_views
describe 'POST #create' do
@@ -15,10 +15,11 @@ describe Settings::TwoFactorAuthentication::RecoveryCodesController do
sign_in user, scope: :user
post :create, session: { challenge_passed_at: Time.now.utc }
- expect(assigns(:recovery_codes)).to eq otp_backup_codes
expect(flash[:notice]).to eq 'Recovery codes successfully regenerated'
expect(response).to have_http_status(200)
expect(response).to render_template(:index)
+ expect(response.body)
+ .to include(*otp_backup_codes)
end
it 'redirects when not signed in' do
diff --git a/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb
index 41a3ba5eb5..cccf3c51d3 100644
--- a/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb
+++ b/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'webauthn/fake_client'
-describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
+RSpec.describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
render_views
let(:user) { Fabricate(:user) }
diff --git a/spec/controllers/settings/two_factor_authentication_methods_controller_spec.rb b/spec/controllers/settings/two_factor_authentication_methods_controller_spec.rb
index de0d28463b..c55f113d4d 100644
--- a/spec/controllers/settings/two_factor_authentication_methods_controller_spec.rb
+++ b/spec/controllers/settings/two_factor_authentication_methods_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Settings::TwoFactorAuthenticationMethodsController do
+RSpec.describe Settings::TwoFactorAuthenticationMethodsController do
render_views
context 'when not signed in' do
diff --git a/spec/controllers/shares_controller_spec.rb b/spec/controllers/shares_controller_spec.rb
deleted file mode 100644
index 5dcc46e47a..0000000000
--- a/spec/controllers/shares_controller_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe SharesController do
- render_views
-
- let(:user) { Fabricate(:user) }
-
- before { sign_in user }
-
- describe 'GET #show' do
- subject(:body_classes) { assigns(:body_classes) }
-
- before { get :show, params: { title: 'test title', text: 'test text', url: 'url1 url2' } }
-
- it 'returns http success' do
- expect(response).to have_http_status 200
- expect(body_classes).to eq 'modal-layout compose-standalone'
- end
- end
-end
diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb
index fe40ee6de1..d9702251f4 100644
--- a/spec/controllers/statuses_controller_spec.rb
+++ b/spec/controllers/statuses_controller_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe StatusesController do
+RSpec.describe StatusesController do
render_views
describe 'GET #show' do
@@ -63,7 +63,7 @@ describe StatusesController do
expect(response.headers).to include(
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('public'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
expect(response.body).to include status.text
end
@@ -72,17 +72,16 @@ describe StatusesController do
context 'with JSON' do
let(:format) { 'json' }
- it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
-
it 'renders ActivityPub Note object successfully', :aggregate_failures do
expect(response)
.to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
+
expect(response.headers).to include(
- 'Vary' => 'Accept, Accept-Language, Cookie',
'Content-Type' => include('application/activity+json'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
- expect(body_as_json)
+ expect(response.parsed_body)
.to include(content: include(status.text))
end
end
@@ -169,7 +168,7 @@ describe StatusesController do
expect(response.headers).to include(
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
expect(response.body).to include status.text
end
@@ -185,9 +184,9 @@ describe StatusesController do
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
'Content-Type' => include('application/activity+json'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
- expect(body_as_json)
+ expect(response.parsed_body)
.to include(content: include(status.text))
end
end
@@ -213,7 +212,7 @@ describe StatusesController do
expect(response.headers).to include(
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
expect(response.body).to include status.text
end
@@ -229,9 +228,9 @@ describe StatusesController do
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
'Content-Type' => include('application/activity+json'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
- expect(body_as_json)
+ expect(response.parsed_body)
.to include(content: include(status.text))
end
end
@@ -279,7 +278,7 @@ describe StatusesController do
expect(response.headers).to include(
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
expect(response.body).to include status.text
end
@@ -295,9 +294,9 @@ describe StatusesController do
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
'Content-Type' => include('application/activity+json'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
- expect(body_as_json)
+ expect(response.parsed_body)
.to include(content: include(status.text))
end
end
@@ -371,7 +370,7 @@ describe StatusesController do
expect(response.headers).to include(
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
expect(response.body).to include status.text
end
@@ -380,17 +379,15 @@ describe StatusesController do
context 'with JSON' do
let(:format) { 'json' }
- it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
-
it 'renders ActivityPub Note object successfully', :aggregate_failures do
expect(response)
.to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
expect(response.headers).to include(
- 'Vary' => 'Accept, Accept-Language, Cookie',
'Content-Type' => include('application/activity+json'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
- expect(body_as_json)
+ expect(response.parsed_body)
.to include(content: include(status.text))
end
end
@@ -415,7 +412,7 @@ describe StatusesController do
expect(response.headers).to include(
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
expect(response.body).to include status.text
end
@@ -431,10 +428,10 @@ describe StatusesController do
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
'Content-Type' => include('application/activity+json'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
- expect(body_as_json)
+ expect(response.parsed_body)
.to include(content: include(status.text))
end
end
@@ -482,7 +479,7 @@ describe StatusesController do
expect(response.headers).to include(
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
expect(response.body).to include status.text
end
@@ -498,9 +495,9 @@ describe StatusesController do
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('private'),
'Content-Type' => include('application/activity+json'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
- expect(body_as_json)
+ expect(response.parsed_body)
.to include(content: include(status.text))
end
end
@@ -782,9 +779,8 @@ describe StatusesController do
expect(response.headers).to include(
'Vary' => 'Accept, Accept-Language, Cookie',
'Cache-Control' => include('public'),
- 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
+ 'Link' => include('activity+json')
)
- expect(response.body).to include status.text
end
end
diff --git a/spec/controllers/tags_controller_spec.rb b/spec/controllers/tags_controller_spec.rb
deleted file mode 100644
index 2bb0c8de3b..0000000000
--- a/spec/controllers/tags_controller_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe TagsController do
- render_views
-
- describe 'GET #show' do
- let(:format) { 'html' }
- let(:tag) { Fabricate(:tag, name: 'test') }
- let(:tag_name) { tag&.name }
-
- before do
- get :show, params: { id: tag_name, format: format }
- end
-
- context 'when tag exists' do
- context 'when requested as HTML' do
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
- end
-
- context 'when requested as JSON' do
- let(:format) { 'json' }
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
- end
- end
-
- context 'when tag does not exist' do
- let(:tag_name) { 'hoge' }
-
- it 'returns http not found' do
- expect(response).to have_http_status(404)
- end
- end
- end
-end
diff --git a/spec/fabrication/fabricators_spec.rb b/spec/fabrication/fabricators_spec.rb
index 2cf45041a4..f7bb504543 100644
--- a/spec/fabrication/fabricators_spec.rb
+++ b/spec/fabrication/fabricators_spec.rb
@@ -5,7 +5,7 @@ require 'rails_helper'
Fabrication.manager.load_definitions if Fabrication.manager.empty?
Fabrication.manager.schematics.map(&:first).each do |factory_name|
- describe "The #{factory_name} factory" do
+ RSpec.describe "The #{factory_name} factory" do
it 'is able to create valid records' do
records = Fabricate.times(2, factory_name) # Create multiple of each to uncover uniqueness issues
expect(records).to all(be_valid)
diff --git a/spec/fabricators/account_moderation_note_fabricator.rb b/spec/fabricators/account_moderation_note_fabricator.rb
index 05a687bf4e..1ded862638 100644
--- a/spec/fabricators/account_moderation_note_fabricator.rb
+++ b/spec/fabricators/account_moderation_note_fabricator.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
Fabricator(:account_moderation_note) do
- content 'MyText'
+ content { Faker::Lorem.sentences }
account { Fabricate.build(:account) }
target_account { Fabricate.build(:account) }
end
diff --git a/spec/fabricators/device_fabricator.rb b/spec/fabricators/device_fabricator.rb
deleted file mode 100644
index 37a2e8977d..0000000000
--- a/spec/fabricators/device_fabricator.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-Fabricator(:device) do
- access_token { Fabricate.build(:access_token) }
- account { Fabricate.build(:account) }
- device_id { Faker::Number.number(digits: 5) }
- name { Faker::App.name }
- fingerprint_key { Base64.strict_encode64(Ed25519::SigningKey.generate.verify_key.to_bytes) }
- identity_key { Base64.strict_encode64(Ed25519::SigningKey.generate.verify_key.to_bytes) }
-end
diff --git a/spec/fabricators/encrypted_message_fabricator.rb b/spec/fabricators/encrypted_message_fabricator.rb
deleted file mode 100644
index 349b659c2f..0000000000
--- a/spec/fabricators/encrypted_message_fabricator.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-Fabricator(:encrypted_message) do
- device { Fabricate.build(:device) }
- from_account { Fabricate.build(:account) }
- from_device_id { Faker::Number.number(digits: 5) }
-end
diff --git a/spec/fabricators/generated_annual_report_fabricator.rb b/spec/fabricators/generated_annual_report_fabricator.rb
new file mode 100644
index 0000000000..462d0cf4bc
--- /dev/null
+++ b/spec/fabricators/generated_annual_report_fabricator.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+Fabricator(:generated_annual_report) do
+ account { Fabricate.build(:account) }
+ data { { test: :data } }
+ schema_version { AnnualReport::SCHEMA }
+ year { sequence(:year) { |i| 2000 + i } }
+end
diff --git a/spec/fabricators/list_account_fabricator.rb b/spec/fabricators/list_account_fabricator.rb
index 00dde83cdf..fe5a471209 100644
--- a/spec/fabricators/list_account_fabricator.rb
+++ b/spec/fabricators/list_account_fabricator.rb
@@ -2,6 +2,8 @@
Fabricator(:list_account) do
list
- account
- before_create { |list_account, _| list_account.list.account.follow!(account) }
+
+ initialize_with do
+ resolved_class.new(list: list, account: list.account)
+ end
end
diff --git a/spec/fabricators/one_time_key_fabricator.rb b/spec/fabricators/one_time_key_fabricator.rb
deleted file mode 100644
index 505282e05d..0000000000
--- a/spec/fabricators/one_time_key_fabricator.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-Fabricator(:one_time_key) do
- device { Fabricate.build(:device) }
- key_id { Faker::Alphanumeric.alphanumeric(number: 10) }
- key { Base64.strict_encode64(Ed25519::SigningKey.generate.verify_key.to_bytes) }
-
- signature do |attrs|
- signing_key = Ed25519::SigningKey.generate
- attrs[:device].update(fingerprint_key: Base64.strict_encode64(signing_key.verify_key.to_bytes))
- Base64.strict_encode64(signing_key.sign(attrs[:key]))
- end
-end
diff --git a/spec/fabricators/report_note_fabricator.rb b/spec/fabricators/report_note_fabricator.rb
index 080fad51ac..a5e9cc9009 100644
--- a/spec/fabricators/report_note_fabricator.rb
+++ b/spec/fabricators/report_note_fabricator.rb
@@ -3,5 +3,5 @@
Fabricator(:report_note) do
report { Fabricate.build(:report) }
account { Fabricate.build(:account) }
- content 'Test Content'
+ content { Faker::Lorem.sentences }
end
diff --git a/spec/fabricators/system_key_fabricator.rb b/spec/fabricators/system_key_fabricator.rb
deleted file mode 100644
index bcb3bd5577..0000000000
--- a/spec/fabricators/system_key_fabricator.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# frozen_string_literal: true
-
-Fabricator(:system_key)
diff --git a/spec/generators/post_deployment_migration_generator_spec.rb b/spec/generators/post_deployment_migration_generator_spec.rb
index 55e70a7917..1aa8e0915c 100644
--- a/spec/generators/post_deployment_migration_generator_spec.rb
+++ b/spec/generators/post_deployment_migration_generator_spec.rb
@@ -6,7 +6,7 @@ require 'rails/generators/testing/assertions'
require 'generators/post_deployment_migration/post_deployment_migration_generator'
-describe PostDeploymentMigrationGenerator, type: :generator do
+RSpec.describe PostDeploymentMigrationGenerator, type: :generator do
include Rails::Generators::Testing::Behavior
include Rails::Generators::Testing::Assertions
include FileUtils
diff --git a/spec/helpers/admin/dashboard_helper_spec.rb b/spec/helpers/admin/dashboard_helper_spec.rb
index 59062e4839..9c674fb4b9 100644
--- a/spec/helpers/admin/dashboard_helper_spec.rb
+++ b/spec/helpers/admin/dashboard_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::DashboardHelper do
+RSpec.describe Admin::DashboardHelper do
describe 'relevant_account_timestamp' do
context 'with an account with older sign in' do
let(:account) { Fabricate(:account) }
diff --git a/spec/helpers/admin/disputes_helper_spec.rb b/spec/helpers/admin/disputes_helper_spec.rb
index 5f9a85df86..a6ac021bd4 100644
--- a/spec/helpers/admin/disputes_helper_spec.rb
+++ b/spec/helpers/admin/disputes_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::DisputesHelper do
+RSpec.describe Admin::DisputesHelper do
describe 'strike_action_label' do
it 'returns html describing the appeal' do
adam = Account.new(username: 'Adam')
diff --git a/spec/helpers/admin/filter_helper_spec.rb b/spec/helpers/admin/filter_helper_spec.rb
index 40ed63239f..d07a6e1bb7 100644
--- a/spec/helpers/admin/filter_helper_spec.rb
+++ b/spec/helpers/admin/filter_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::FilterHelper do
+RSpec.describe Admin::FilterHelper do
it 'Uses filter_link_to to create filter links' do
params = ActionController::Parameters.new(
{ test: 'test' }
diff --git a/spec/helpers/admin/trends/statuses_helper_spec.rb b/spec/helpers/admin/trends/statuses_helper_spec.rb
index 92caae6909..fa5c337e97 100644
--- a/spec/helpers/admin/trends/statuses_helper_spec.rb
+++ b/spec/helpers/admin/trends/statuses_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Trends::StatusesHelper do
+RSpec.describe Admin::Trends::StatusesHelper do
describe '.one_line_preview' do
before do
allow(helper).to receive(:current_user).and_return(Fabricate.build(:user))
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index f37dc480c4..90dc0d36de 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -2,13 +2,23 @@
require 'rails_helper'
-describe ApplicationHelper do
+RSpec.describe ApplicationHelper do
describe 'body_classes' do
context 'with a body class string from a controller' do
before { helper.extend controller_helpers }
it 'uses the controller body classes in the result' do
- expect(helper.body_classes).to match(/modal-layout compose-standalone/)
+ expect(helper.body_classes)
+ .to match(/modal-layout compose-standalone/)
+ .and match(/flavour-glitch/)
+ .and match(/skin-default/)
+ end
+
+ it 'includes values set via content_for' do
+ helper.content_for(:body_classes) { 'admin' }
+
+ expect(helper.body_classes)
+ .to match(/admin/)
end
private
diff --git a/spec/helpers/flashes_helper_spec.rb b/spec/helpers/flashes_helper_spec.rb
index a6a3b062d7..aaef7ab144 100644
--- a/spec/helpers/flashes_helper_spec.rb
+++ b/spec/helpers/flashes_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe FlashesHelper do
+RSpec.describe FlashesHelper do
describe 'user_facing_flashes' do
before do
# rubocop:disable Rails/I18nLocaleTexts
diff --git a/spec/helpers/formatting_helper_spec.rb b/spec/helpers/formatting_helper_spec.rb
index d6e7631f66..136a609b1c 100644
--- a/spec/helpers/formatting_helper_spec.rb
+++ b/spec/helpers/formatting_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe FormattingHelper do
+RSpec.describe FormattingHelper do
include Devise::Test::ControllerHelpers
describe '#rss_status_content_format' do
diff --git a/spec/helpers/instance_helper_spec.rb b/spec/helpers/instance_helper_spec.rb
index 9a2d884158..e7b15e6513 100644
--- a/spec/helpers/instance_helper_spec.rb
+++ b/spec/helpers/instance_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe InstanceHelper do
+RSpec.describe InstanceHelper do
describe 'site_title' do
it 'Uses the Setting.site_title value when it exists' do
Setting.site_title = 'New site title'
diff --git a/spec/helpers/json_ld_helper_spec.rb b/spec/helpers/json_ld_helper_spec.rb
index 4855085027..d76c5167a7 100644
--- a/spec/helpers/json_ld_helper_spec.rb
+++ b/spec/helpers/json_ld_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe JsonLdHelper do
+RSpec.describe JsonLdHelper do
describe '#equals_or_includes?' do
it 'returns true when value equals' do
expect(helper.equals_or_includes?('foo', 'foo')).to be true
@@ -21,6 +21,34 @@ describe JsonLdHelper do
end
end
+ describe '#uri_from_bearcap' do
+ subject { helper.uri_from_bearcap(string) }
+
+ context 'when a bear string has a u param' do
+ let(:string) { 'bear:?t=TOKEN&u=https://example.com/foo' }
+
+ it 'returns the value from the u query param' do
+ expect(subject).to eq('https://example.com/foo')
+ end
+ end
+
+ context 'when a bear string does not have a u param' do
+ let(:string) { 'bear:?t=TOKEN&h=https://example.com/foo' }
+
+ it 'returns nil' do
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'when a non-bear string' do
+ let(:string) { 'http://example.com' }
+
+ it 'returns the string' do
+ expect(subject).to eq('http://example.com')
+ end
+ end
+ end
+
describe '#first_of_value' do
context 'when value.is_a?(Array)' do
it 'returns value.first' do
diff --git a/spec/helpers/languages_helper_spec.rb b/spec/helpers/languages_helper_spec.rb
index 99461b293b..dd9b6004d1 100644
--- a/spec/helpers/languages_helper_spec.rb
+++ b/spec/helpers/languages_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe LanguagesHelper do
+RSpec.describe LanguagesHelper do
describe 'the SUPPORTED_LOCALES constant' do
it 'includes all i18n locales' do
expect(Set.new(described_class::SUPPORTED_LOCALES.keys + described_class::REGIONAL_LOCALE_NAMES.keys)).to include(*I18n.available_locales)
diff --git a/spec/helpers/media_component_helper_spec.rb b/spec/helpers/media_component_helper_spec.rb
index af5d92769c..a44b9b8415 100644
--- a/spec/helpers/media_component_helper_spec.rb
+++ b/spec/helpers/media_component_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe MediaComponentHelper do
+RSpec.describe MediaComponentHelper do
before { helper.extend controller_helpers }
describe 'render_video_component' do
@@ -32,28 +32,6 @@ describe MediaComponentHelper do
end
end
- describe 'render_card_component' do
- let(:status) { Fabricate(:status) }
- let(:result) { helper.render_card_component(status) }
-
- before do
- PreviewCardsStatus.create(status: status, preview_card: Fabricate(:preview_card))
- end
-
- it 'returns the correct react component markup' do
- expect(parsed_html.div['data-component']).to eq('Card')
- end
- end
-
- describe 'render_poll_component' do
- let(:status) { Fabricate(:status, poll: Fabricate(:poll)) }
- let(:result) { helper.render_poll_component(status) }
-
- it 'returns the correct react component markup' do
- expect(parsed_html.div['data-component']).to eq('Poll')
- end
- end
-
private
def parsed_html
diff --git a/spec/helpers/react_component_helper_spec.rb b/spec/helpers/react_component_helper_spec.rb
index 28208b619b..202694fbe4 100644
--- a/spec/helpers/react_component_helper_spec.rb
+++ b/spec/helpers/react_component_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ReactComponentHelper do
+RSpec.describe ReactComponentHelper do
describe 'react_component' do
context 'with no block passed in' do
let(:result) { helper.react_component('name', { one: :two }) }
diff --git a/spec/helpers/settings_helper_spec.rb b/spec/helpers/settings_helper_spec.rb
index ca447d8ce1..ecff2edbfa 100644
--- a/spec/helpers/settings_helper_spec.rb
+++ b/spec/helpers/settings_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe SettingsHelper do
+RSpec.describe SettingsHelper do
describe 'session_device_icon' do
context 'with a mobile device' do
let(:session) { SessionActivation.new(user_agent: 'Mozilla/5.0 (iPhone)') }
diff --git a/spec/helpers/statuses_helper_spec.rb b/spec/helpers/statuses_helper_spec.rb
index ba6fe361d9..edd3e8f2f7 100644
--- a/spec/helpers/statuses_helper_spec.rb
+++ b/spec/helpers/statuses_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe StatusesHelper do
+RSpec.describe StatusesHelper do
describe 'status_text_summary' do
context 'with blank text' do
let(:status) { Status.new(spoiler_text: '') }
@@ -23,20 +23,27 @@ describe StatusesHelper do
end
end
- def status_text_summary(status)
- return if status.spoiler_text.blank?
+ describe '#media_summary' do
+ it 'describes the media on a status' do
+ status = Fabricate :status
+ Fabricate :media_attachment, status: status, type: :video
+ Fabricate :media_attachment, status: status, type: :audio
+ Fabricate :media_attachment, status: status, type: :image
- I18n.t('statuses.content_warning', warning: status.spoiler_text)
+ result = helper.media_summary(status)
+
+ expect(result).to eq('Attached: 1 image · 1 video · 1 audio')
+ end
end
- describe 'fa_visibility_icon' do
+ describe 'visibility_icon' do
context 'with a status that is public' do
let(:status) { Status.new(visibility: 'public') }
it 'returns the correct fa icon' do
- result = helper.fa_visibility_icon(status)
+ result = helper.visibility_icon(status)
- expect(result).to match('material-globe')
+ expect(result).to match('globe')
end
end
@@ -44,9 +51,9 @@ describe StatusesHelper do
let(:status) { Status.new(visibility: 'unlisted') }
it 'returns the correct fa icon' do
- result = helper.fa_visibility_icon(status)
+ result = helper.visibility_icon(status)
- expect(result).to match('material-lock_open')
+ expect(result).to match('lock_open')
end
end
@@ -54,9 +61,9 @@ describe StatusesHelper do
let(:status) { Status.new(visibility: 'private') }
it 'returns the correct fa icon' do
- result = helper.fa_visibility_icon(status)
+ result = helper.visibility_icon(status)
- expect(result).to match('material-lock')
+ expect(result).to match('lock')
end
end
@@ -64,9 +71,9 @@ describe StatusesHelper do
let(:status) { Status.new(visibility: 'direct') }
it 'returns the correct fa icon' do
- result = helper.fa_visibility_icon(status)
+ result = helper.visibility_icon(status)
- expect(result).to match('material-alternate_email')
+ expect(result).to match('alternate_email')
end
end
end
diff --git a/spec/helpers/theme_helper_spec.rb b/spec/helpers/theme_helper_spec.rb
index aae1ae2a3b..83a68f4739 100644
--- a/spec/helpers/theme_helper_spec.rb
+++ b/spec/helpers/theme_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ThemeHelper do
+RSpec.describe ThemeHelper do
describe 'theme_style_tags' do
let(:result) { helper.theme_style_tags(theme) }
diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb
index fbaf672b5a..83ea6566e4 100644
--- a/spec/lib/activitypub/activity/create_spec.rb
+++ b/spec/lib/activitypub/activity/create_spec.rb
@@ -982,64 +982,6 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
- context 'with an encrypted message' do
- subject { described_class.new(json, sender, delivery: true, delivered_to_account_id: recipient.id) }
-
- let(:recipient) { Fabricate(:account) }
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'EncryptedMessage',
- attributedTo: {
- type: 'Device',
- deviceId: '1234',
- },
- to: {
- type: 'Device',
- deviceId: target_device.device_id,
- },
- messageType: 1,
- cipherText: 'Foo',
- messageFranking: 'Baz678',
- digest: {
- digestAlgorithm: 'Bar456',
- digestValue: 'Foo123',
- },
- }
- end
- let(:target_device) { Fabricate(:device, account: recipient) }
-
- before do
- subject.perform
- end
-
- it 'creates an encrypted message' do
- encrypted_message = target_device.encrypted_messages.reload.first
-
- expect(encrypted_message)
- .to be_present
- .and have_attributes(
- from_device_id: eq('1234'),
- from_account: eq(sender),
- type: eq(1),
- body: eq('Foo'),
- digest: eq('Foo123')
- )
- end
-
- it 'creates a message franking' do
- encrypted_message = target_device.encrypted_messages.reload.first
- message_franking = encrypted_message.message_franking
-
- crypt = ActiveSupport::MessageEncryptor.new(SystemKey.current_key, serializer: Oj)
- json = crypt.decrypt_and_verify(message_franking)
-
- expect(json['source_account_id']).to eq sender.id
- expect(json['target_account_id']).to eq recipient.id
- expect(json['original_franking']).to eq 'Baz678'
- end
- end
-
context 'when sender is followed by local users' do
subject { described_class.new(json, sender, delivery: true) }
diff --git a/spec/lib/activitypub/linked_data_signature_spec.rb b/spec/lib/activitypub/linked_data_signature_spec.rb
index 1af45673c0..b1a8dc5c49 100644
--- a/spec/lib/activitypub/linked_data_signature_spec.rb
+++ b/spec/lib/activitypub/linked_data_signature_spec.rb
@@ -95,16 +95,11 @@ RSpec.describe ActivityPub::LinkedDataSignature do
describe '#sign!' do
subject { described_class.new(raw_json).sign!(sender) }
- it 'returns a hash' do
+ it 'returns a hash with a signature, the expected context, and the signature can be verified', :aggregate_failures do
expect(subject).to be_a Hash
- end
-
- it 'contains signature' do
expect(subject['signature']).to be_a Hash
expect(subject['signature']['signatureValue']).to be_present
- end
-
- it 'can be verified again' do
+ expect(Array(subject['@context'])).to include('https://w3id.org/security/v1')
expect(described_class.new(subject).verify_actor!).to eq sender
end
end
diff --git a/spec/lib/admin/metrics/dimension/instance_accounts_dimension_spec.rb b/spec/lib/admin/metrics/dimension/instance_accounts_dimension_spec.rb
index 2b14e6956c..c8683afda9 100644
--- a/spec/lib/admin/metrics/dimension/instance_accounts_dimension_spec.rb
+++ b/spec/lib/admin/metrics/dimension/instance_accounts_dimension_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Dimension::InstanceAccountsDimension do
+RSpec.describe Admin::Metrics::Dimension::InstanceAccountsDimension do
subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/dimension/instance_languages_dimension_spec.rb b/spec/lib/admin/metrics/dimension/instance_languages_dimension_spec.rb
index e4e9fbe2b7..c633041f9d 100644
--- a/spec/lib/admin/metrics/dimension/instance_languages_dimension_spec.rb
+++ b/spec/lib/admin/metrics/dimension/instance_languages_dimension_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Dimension::InstanceLanguagesDimension do
+RSpec.describe Admin::Metrics::Dimension::InstanceLanguagesDimension do
subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/dimension/languages_dimension_spec.rb b/spec/lib/admin/metrics/dimension/languages_dimension_spec.rb
index 9d80970693..801b3d84df 100644
--- a/spec/lib/admin/metrics/dimension/languages_dimension_spec.rb
+++ b/spec/lib/admin/metrics/dimension/languages_dimension_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Dimension::LanguagesDimension do
+RSpec.describe Admin::Metrics::Dimension::LanguagesDimension do
subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/dimension/servers_dimension_spec.rb b/spec/lib/admin/metrics/dimension/servers_dimension_spec.rb
index 5661441d5d..d86ccd099a 100644
--- a/spec/lib/admin/metrics/dimension/servers_dimension_spec.rb
+++ b/spec/lib/admin/metrics/dimension/servers_dimension_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Dimension::ServersDimension do
+RSpec.describe Admin::Metrics::Dimension::ServersDimension do
subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/dimension/software_versions_dimension_spec.rb b/spec/lib/admin/metrics/dimension/software_versions_dimension_spec.rb
index 5d31121ab3..5b0fb902e0 100644
--- a/spec/lib/admin/metrics/dimension/software_versions_dimension_spec.rb
+++ b/spec/lib/admin/metrics/dimension/software_versions_dimension_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Dimension::SoftwareVersionsDimension do
+RSpec.describe Admin::Metrics::Dimension::SoftwareVersionsDimension do
subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/dimension/sources_dimension_spec.rb b/spec/lib/admin/metrics/dimension/sources_dimension_spec.rb
index 5fa5aa8af5..ca7f716afd 100644
--- a/spec/lib/admin/metrics/dimension/sources_dimension_spec.rb
+++ b/spec/lib/admin/metrics/dimension/sources_dimension_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Dimension::SourcesDimension do
+RSpec.describe Admin::Metrics::Dimension::SourcesDimension do
subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/dimension/space_usage_dimension_spec.rb b/spec/lib/admin/metrics/dimension/space_usage_dimension_spec.rb
index 96ff9c66dc..4be5ed30ee 100644
--- a/spec/lib/admin/metrics/dimension/space_usage_dimension_spec.rb
+++ b/spec/lib/admin/metrics/dimension/space_usage_dimension_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Dimension::SpaceUsageDimension do
+RSpec.describe Admin::Metrics::Dimension::SpaceUsageDimension do
subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/dimension/tag_languages_dimension_spec.rb b/spec/lib/admin/metrics/dimension/tag_languages_dimension_spec.rb
index c1dfd0eaf4..166edf92b0 100644
--- a/spec/lib/admin/metrics/dimension/tag_languages_dimension_spec.rb
+++ b/spec/lib/admin/metrics/dimension/tag_languages_dimension_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Dimension::TagLanguagesDimension do
+RSpec.describe Admin::Metrics::Dimension::TagLanguagesDimension do
subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/dimension/tag_servers_dimension_spec.rb b/spec/lib/admin/metrics/dimension/tag_servers_dimension_spec.rb
index 025cf1b7ec..7391b55456 100644
--- a/spec/lib/admin/metrics/dimension/tag_servers_dimension_spec.rb
+++ b/spec/lib/admin/metrics/dimension/tag_servers_dimension_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Dimension::TagServersDimension do
+RSpec.describe Admin::Metrics::Dimension::TagServersDimension do
subject { described_class.new(start_at, end_at, limit, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/dimension_spec.rb b/spec/lib/admin/metrics/dimension_spec.rb
index 109250b72b..0a52d442be 100644
--- a/spec/lib/admin/metrics/dimension_spec.rb
+++ b/spec/lib/admin/metrics/dimension_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Dimension do
+RSpec.describe Admin::Metrics::Dimension do
describe '.retrieve' do
subject { described_class.retrieve(reports, start_at, end_at, 5, params) }
diff --git a/spec/lib/admin/metrics/measure/active_users_measure_spec.rb b/spec/lib/admin/metrics/measure/active_users_measure_spec.rb
index 38ee14075b..653e677354 100644
--- a/spec/lib/admin/metrics/measure/active_users_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/active_users_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::ActiveUsersMeasure do
+RSpec.describe Admin::Metrics::Measure::ActiveUsersMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/measure/instance_accounts_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_accounts_measure_spec.rb
index 0d2ad31c39..f974f2ca46 100644
--- a/spec/lib/admin/metrics/measure/instance_accounts_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/instance_accounts_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::InstanceAccountsMeasure do
+RSpec.describe Admin::Metrics::Measure::InstanceAccountsMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' }
diff --git a/spec/lib/admin/metrics/measure/instance_followers_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_followers_measure_spec.rb
index 27bf30d17d..643249fa4e 100644
--- a/spec/lib/admin/metrics/measure/instance_followers_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/instance_followers_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::InstanceFollowersMeasure do
+RSpec.describe Admin::Metrics::Measure::InstanceFollowersMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' }
diff --git a/spec/lib/admin/metrics/measure/instance_follows_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_follows_measure_spec.rb
index 9961ea56c4..70f5004fef 100644
--- a/spec/lib/admin/metrics/measure/instance_follows_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/instance_follows_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::InstanceFollowsMeasure do
+RSpec.describe Admin::Metrics::Measure::InstanceFollowsMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' }
diff --git a/spec/lib/admin/metrics/measure/instance_media_attachments_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_media_attachments_measure_spec.rb
index 3634450930..11f13b85bc 100644
--- a/spec/lib/admin/metrics/measure/instance_media_attachments_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/instance_media_attachments_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure do
+RSpec.describe Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' }
diff --git a/spec/lib/admin/metrics/measure/instance_reports_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_reports_measure_spec.rb
index ca64049d92..62c9dec464 100644
--- a/spec/lib/admin/metrics/measure/instance_reports_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/instance_reports_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::InstanceReportsMeasure do
+RSpec.describe Admin::Metrics::Measure::InstanceReportsMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' }
diff --git a/spec/lib/admin/metrics/measure/instance_statuses_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_statuses_measure_spec.rb
index ac28658ea0..0fc903a2a8 100644
--- a/spec/lib/admin/metrics/measure/instance_statuses_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/instance_statuses_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::InstanceStatusesMeasure do
+RSpec.describe Admin::Metrics::Measure::InstanceStatusesMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:domain) { 'example.com' }
diff --git a/spec/lib/admin/metrics/measure/interactions_measure_spec.rb b/spec/lib/admin/metrics/measure/interactions_measure_spec.rb
index ed333380cf..edbec2eabf 100644
--- a/spec/lib/admin/metrics/measure/interactions_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/interactions_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::InteractionsMeasure do
+RSpec.describe Admin::Metrics::Measure::InteractionsMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/measure/new_users_measure_spec.rb b/spec/lib/admin/metrics/measure/new_users_measure_spec.rb
index 085acbcede..5c03b67a18 100644
--- a/spec/lib/admin/metrics/measure/new_users_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/new_users_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::NewUsersMeasure do
+RSpec.describe Admin::Metrics::Measure::NewUsersMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/measure/opened_reports_measure_spec.rb b/spec/lib/admin/metrics/measure/opened_reports_measure_spec.rb
index d5ba78527e..f4d3a66454 100644
--- a/spec/lib/admin/metrics/measure/opened_reports_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/opened_reports_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::OpenedReportsMeasure do
+RSpec.describe Admin::Metrics::Measure::OpenedReportsMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/measure/resolved_reports_measure_spec.rb b/spec/lib/admin/metrics/measure/resolved_reports_measure_spec.rb
index f7b497590d..432dbbe796 100644
--- a/spec/lib/admin/metrics/measure/resolved_reports_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/resolved_reports_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::ResolvedReportsMeasure do
+RSpec.describe Admin::Metrics::Measure::ResolvedReportsMeasure do
subject { described_class.new(start_at, end_at, params) }
let(:start_at) { 2.days.ago }
diff --git a/spec/lib/admin/metrics/measure/tag_accounts_measure_spec.rb b/spec/lib/admin/metrics/measure/tag_accounts_measure_spec.rb
index b33ae7bb71..577b1260ff 100644
--- a/spec/lib/admin/metrics/measure/tag_accounts_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/tag_accounts_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::TagAccountsMeasure do
+RSpec.describe Admin::Metrics::Measure::TagAccountsMeasure do
subject { described_class.new(start_at, end_at, params) }
let!(:tag) { Fabricate(:tag) }
diff --git a/spec/lib/admin/metrics/measure/tag_servers_measure_spec.rb b/spec/lib/admin/metrics/measure/tag_servers_measure_spec.rb
index e1e2ced43a..42715e5adc 100644
--- a/spec/lib/admin/metrics/measure/tag_servers_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/tag_servers_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::TagServersMeasure do
+RSpec.describe Admin::Metrics::Measure::TagServersMeasure do
subject { described_class.new(start_at, end_at, params) }
let!(:tag) { Fabricate(:tag) }
diff --git a/spec/lib/admin/metrics/measure/tag_uses_measure_spec.rb b/spec/lib/admin/metrics/measure/tag_uses_measure_spec.rb
index dd66f00de0..b258455dab 100644
--- a/spec/lib/admin/metrics/measure/tag_uses_measure_spec.rb
+++ b/spec/lib/admin/metrics/measure/tag_uses_measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure::TagUsesMeasure do
+RSpec.describe Admin::Metrics::Measure::TagUsesMeasure do
subject { described_class.new(start_at, end_at, params) }
let!(:tag) { Fabricate(:tag) }
diff --git a/spec/lib/admin/metrics/measure_spec.rb b/spec/lib/admin/metrics/measure_spec.rb
index c9809b0f79..49a5aecc61 100644
--- a/spec/lib/admin/metrics/measure_spec.rb
+++ b/spec/lib/admin/metrics/measure_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::Metrics::Measure do
+RSpec.describe Admin::Metrics::Measure do
describe '.retrieve' do
subject { described_class.retrieve(reports, start_at, end_at, params) }
diff --git a/spec/lib/admin/system_check/base_check_spec.rb b/spec/lib/admin/system_check/base_check_spec.rb
index fdd9f6b6c4..769e0e1d18 100644
--- a/spec/lib/admin/system_check/base_check_spec.rb
+++ b/spec/lib/admin/system_check/base_check_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SystemCheck::BaseCheck do
+RSpec.describe Admin::SystemCheck::BaseCheck do
subject(:check) { described_class.new(user) }
let(:user) { Fabricate(:user) }
diff --git a/spec/lib/admin/system_check/database_schema_check_spec.rb b/spec/lib/admin/system_check/database_schema_check_spec.rb
index db1dcb52fa..311d524956 100644
--- a/spec/lib/admin/system_check/database_schema_check_spec.rb
+++ b/spec/lib/admin/system_check/database_schema_check_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SystemCheck::DatabaseSchemaCheck do
+RSpec.describe Admin::SystemCheck::DatabaseSchemaCheck do
subject(:check) { described_class.new(user) }
let(:user) { Fabricate(:user) }
diff --git a/spec/lib/admin/system_check/elasticsearch_check_spec.rb b/spec/lib/admin/system_check/elasticsearch_check_spec.rb
index 8f210579d0..05d204c453 100644
--- a/spec/lib/admin/system_check/elasticsearch_check_spec.rb
+++ b/spec/lib/admin/system_check/elasticsearch_check_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SystemCheck::ElasticsearchCheck do
+RSpec.describe Admin::SystemCheck::ElasticsearchCheck do
subject(:check) { described_class.new(user) }
let(:user) { Fabricate(:user) }
diff --git a/spec/lib/admin/system_check/media_privacy_check_spec.rb b/spec/lib/admin/system_check/media_privacy_check_spec.rb
index 316bf12156..0d5bcdb3e8 100644
--- a/spec/lib/admin/system_check/media_privacy_check_spec.rb
+++ b/spec/lib/admin/system_check/media_privacy_check_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SystemCheck::MediaPrivacyCheck do
+RSpec.describe Admin::SystemCheck::MediaPrivacyCheck do
subject(:check) { described_class.new(user) }
let(:user) { Fabricate(:user) }
diff --git a/spec/lib/admin/system_check/message_spec.rb b/spec/lib/admin/system_check/message_spec.rb
index c0671f3452..81ef4f2f09 100644
--- a/spec/lib/admin/system_check/message_spec.rb
+++ b/spec/lib/admin/system_check/message_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SystemCheck::Message do
+RSpec.describe Admin::SystemCheck::Message do
subject(:check) { described_class.new(:key_value, :value_value, :action_value, :critical_value) }
it 'providers readers when initialized' do
diff --git a/spec/lib/admin/system_check/rules_check_spec.rb b/spec/lib/admin/system_check/rules_check_spec.rb
index fb3293fb2d..32650d9cd8 100644
--- a/spec/lib/admin/system_check/rules_check_spec.rb
+++ b/spec/lib/admin/system_check/rules_check_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SystemCheck::RulesCheck do
+RSpec.describe Admin::SystemCheck::RulesCheck do
subject(:check) { described_class.new(user) }
let(:user) { Fabricate(:user) }
diff --git a/spec/lib/admin/system_check/sidekiq_process_check_spec.rb b/spec/lib/admin/system_check/sidekiq_process_check_spec.rb
index 9bd9daddf6..992fd7aee0 100644
--- a/spec/lib/admin/system_check/sidekiq_process_check_spec.rb
+++ b/spec/lib/admin/system_check/sidekiq_process_check_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SystemCheck::SidekiqProcessCheck do
+RSpec.describe Admin::SystemCheck::SidekiqProcessCheck do
subject(:check) { described_class.new(user) }
let(:user) { Fabricate(:user) }
diff --git a/spec/lib/admin/system_check/software_version_check_spec.rb b/spec/lib/admin/system_check/software_version_check_spec.rb
index de4335fc51..1affaa3a96 100644
--- a/spec/lib/admin/system_check/software_version_check_spec.rb
+++ b/spec/lib/admin/system_check/software_version_check_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SystemCheck::SoftwareVersionCheck do
+RSpec.describe Admin::SystemCheck::SoftwareVersionCheck do
include RoutingHelper
subject(:check) { described_class.new(user) }
diff --git a/spec/lib/admin/system_check_spec.rb b/spec/lib/admin/system_check_spec.rb
index 30048fd3ad..92852ab025 100644
--- a/spec/lib/admin/system_check_spec.rb
+++ b/spec/lib/admin/system_check_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SystemCheck do
+RSpec.describe Admin::SystemCheck do
let(:user) { Fabricate(:user) }
describe 'perform' do
diff --git a/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb b/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb
new file mode 100644
index 0000000000..e99d3cb4a7
--- /dev/null
+++ b/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AnnualReport::CommonlyInteractedWithAccounts do
+ describe '#generate' do
+ subject { described_class.new(account, Time.zone.now.year) }
+
+ context 'with an inactive account' do
+ let(:account) { Fabricate :account }
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ commonly_interacted_with_accounts: be_an(Array).and(be_empty)
+ )
+ end
+ end
+
+ context 'with an active account' do
+ let(:account) { Fabricate :account }
+
+ let(:other_account) { Fabricate :account }
+
+ before do
+ _other = Fabricate :status
+ Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: other_account).id
+ Fabricate :status, account: account, reply: true, in_reply_to_id: Fabricate(:status, account: other_account).id
+ end
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ commonly_interacted_with_accounts: contain_exactly(
+ include(account_id: other_account.id, count: 2)
+ )
+ )
+ end
+ end
+ end
+end
diff --git a/spec/lib/annual_report/most_reblogged_accounts_spec.rb b/spec/lib/annual_report/most_reblogged_accounts_spec.rb
new file mode 100644
index 0000000000..0280ba1992
--- /dev/null
+++ b/spec/lib/annual_report/most_reblogged_accounts_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AnnualReport::MostRebloggedAccounts do
+ describe '#generate' do
+ subject { described_class.new(account, Time.zone.now.year) }
+
+ context 'with an inactive account' do
+ let(:account) { Fabricate :account }
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ most_reblogged_accounts: be_an(Array).and(be_empty)
+ )
+ end
+ end
+
+ context 'with an active account' do
+ let(:account) { Fabricate :account }
+
+ let(:other_account) { Fabricate :account }
+
+ before do
+ _other = Fabricate :status
+ Fabricate :status, account: account, reblog: Fabricate(:status, account: other_account)
+ Fabricate :status, account: account, reblog: Fabricate(:status, account: other_account)
+ end
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ most_reblogged_accounts: contain_exactly(
+ include(account_id: other_account.id, count: 2)
+ )
+ )
+ end
+ end
+ end
+end
diff --git a/spec/lib/annual_report/most_used_apps_spec.rb b/spec/lib/annual_report/most_used_apps_spec.rb
new file mode 100644
index 0000000000..d2fcecc4d8
--- /dev/null
+++ b/spec/lib/annual_report/most_used_apps_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AnnualReport::MostUsedApps do
+ describe '#generate' do
+ subject { described_class.new(account, Time.zone.now.year) }
+
+ context 'with an inactive account' do
+ let(:account) { Fabricate :account }
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ most_used_apps: be_an(Array).and(be_empty)
+ )
+ end
+ end
+
+ context 'with an active account' do
+ let(:account) { Fabricate :account }
+
+ let(:application) { Fabricate :application }
+
+ before do
+ _other = Fabricate :status
+ Fabricate.times 2, :status, account: account, application: application
+ end
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ most_used_apps: contain_exactly(
+ include(name: application.name, count: 2)
+ )
+ )
+ end
+ end
+ end
+end
diff --git a/spec/lib/annual_report/percentiles_spec.rb b/spec/lib/annual_report/percentiles_spec.rb
new file mode 100644
index 0000000000..1d1df3166b
--- /dev/null
+++ b/spec/lib/annual_report/percentiles_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AnnualReport::Percentiles do
+ describe '#generate' do
+ subject { described_class.new(account, Time.zone.now.year) }
+
+ context 'with an inactive account' do
+ let(:account) { Fabricate :account }
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ percentiles: include(
+ followers: 0,
+ statuses: 0
+ )
+ )
+ end
+ end
+
+ context 'with an active account' do
+ let(:account) { Fabricate :account }
+
+ before do
+ Fabricate.times 2, :status # Others as `account`
+ Fabricate.times 2, :follow # Others as `target_account`
+ Fabricate.times 2, :status, account: account
+ Fabricate.times 2, :follow, target_account: account
+ end
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ percentiles: include(
+ followers: 50,
+ statuses: 50
+ )
+ )
+ end
+ end
+ end
+end
diff --git a/spec/lib/annual_report/time_series_spec.rb b/spec/lib/annual_report/time_series_spec.rb
new file mode 100644
index 0000000000..219d6c0834
--- /dev/null
+++ b/spec/lib/annual_report/time_series_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AnnualReport::TimeSeries do
+ describe '#generate' do
+ subject { described_class.new(account, Time.zone.now.year) }
+
+ context 'with an inactive account' do
+ let(:account) { Fabricate :account }
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ time_series: match(
+ include(followers: 0, following: 0, month: 1, statuses: 0)
+ )
+ )
+ end
+ end
+
+ context 'with an active account' do
+ let(:account) { Fabricate :account }
+
+ let(:month_one_date) { DateTime.new(Time.zone.now.year, 1, 1, 12, 12, 12) }
+
+ let(:tag) { Fabricate :tag }
+
+ before do
+ _other = Fabricate :status
+ Fabricate :status, account: account, created_at: month_one_date
+ Fabricate :follow, account: account, created_at: month_one_date
+ Fabricate :follow, target_account: account, created_at: month_one_date
+ end
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ time_series: match(
+ include(followers: 1, following: 1, month: 1, statuses: 1)
+ )
+ )
+ end
+ end
+ end
+end
diff --git a/spec/lib/annual_report/top_hashtags_spec.rb b/spec/lib/annual_report/top_hashtags_spec.rb
new file mode 100644
index 0000000000..58a9152184
--- /dev/null
+++ b/spec/lib/annual_report/top_hashtags_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AnnualReport::TopHashtags do
+ describe '#generate' do
+ subject { described_class.new(account, Time.zone.now.year) }
+
+ context 'with an inactive account' do
+ let(:account) { Fabricate :account }
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ top_hashtags: be_an(Array).and(be_empty)
+ )
+ end
+ end
+
+ context 'with an active account' do
+ let(:account) { Fabricate :account }
+
+ let(:tag) { Fabricate :tag }
+
+ before do
+ _other = Fabricate :status
+ first = Fabricate :status, account: account
+ first.tags << tag
+ last = Fabricate :status, account: account
+ last.tags << tag
+ end
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ top_hashtags: contain_exactly(
+ include(name: tag.name, count: 2)
+ )
+ )
+ end
+ end
+ end
+end
diff --git a/spec/lib/annual_report/top_statuses_spec.rb b/spec/lib/annual_report/top_statuses_spec.rb
new file mode 100644
index 0000000000..b956b03973
--- /dev/null
+++ b/spec/lib/annual_report/top_statuses_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AnnualReport::TopStatuses do
+ describe '#generate' do
+ subject { described_class.new(account, Time.zone.now.year) }
+
+ context 'with an inactive account' do
+ let(:account) { Fabricate :account }
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ top_statuses: include(
+ by_reblogs: be_nil,
+ by_favourites: be_nil,
+ by_replies: be_nil
+ )
+ )
+ end
+ end
+
+ context 'with an active account' do
+ let(:account) { Fabricate :account }
+
+ let(:reblogged_status) { Fabricate :status, account: account }
+ let(:favourited_status) { Fabricate :status, account: account }
+ let(:replied_status) { Fabricate :status, account: account }
+
+ before do
+ _other = Fabricate :status
+ reblogged_status.status_stat.update(reblogs_count: 123)
+ favourited_status.status_stat.update(favourites_count: 123)
+ replied_status.status_stat.update(replies_count: 123)
+ end
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ top_statuses: include(
+ by_reblogs: reblogged_status.id,
+ by_favourites: favourited_status.id,
+ by_replies: replied_status.id
+ )
+ )
+ end
+ end
+ end
+end
diff --git a/spec/lib/annual_report/type_distribution_spec.rb b/spec/lib/annual_report/type_distribution_spec.rb
new file mode 100644
index 0000000000..89a31fb207
--- /dev/null
+++ b/spec/lib/annual_report/type_distribution_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AnnualReport::TypeDistribution do
+ describe '#generate' do
+ subject { described_class.new(account, Time.zone.now.year) }
+
+ context 'with an inactive account' do
+ let(:account) { Fabricate :account }
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ type_distribution: include(
+ total: 0,
+ reblogs: 0,
+ replies: 0,
+ standalone: 0
+ )
+ )
+ end
+ end
+
+ context 'with an active account' do
+ let(:account) { Fabricate :account }
+
+ before do
+ _other = Fabricate :status
+ Fabricate :status, reblog: Fabricate(:status), account: account
+ Fabricate :status, in_reply_to_id: Fabricate(:status).id, account: account, reply: true
+ Fabricate :status, account: account
+ end
+
+ it 'builds a report for an account' do
+ expect(subject.generate)
+ .to include(
+ type_distribution: include(
+ total: 3,
+ reblogs: 1,
+ replies: 1,
+ standalone: 1
+ )
+ )
+ end
+ end
+ end
+end
diff --git a/spec/lib/annual_report_spec.rb b/spec/lib/annual_report_spec.rb
new file mode 100644
index 0000000000..bd4d0f3387
--- /dev/null
+++ b/spec/lib/annual_report_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AnnualReport do
+ describe '#generate' do
+ subject { described_class.new(account, Time.zone.now.year) }
+
+ let(:account) { Fabricate :account }
+
+ it 'builds a report for an account' do
+ expect { subject.generate }
+ .to change(GeneratedAnnualReport, :count).by(1)
+ end
+ end
+end
diff --git a/spec/lib/cache_buster_spec.rb b/spec/lib/cache_buster_spec.rb
index 84085608e8..f7cff9c1c3 100644
--- a/spec/lib/cache_buster_spec.rb
+++ b/spec/lib/cache_buster_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe CacheBuster do
+RSpec.describe CacheBuster do
subject { described_class.new(secret_header: secret_header, secret: secret, http_method: http_method) }
let(:secret_header) { nil }
diff --git a/spec/lib/connection_pool/shared_connection_pool_spec.rb b/spec/lib/connection_pool/shared_connection_pool_spec.rb
index a2fe75f742..2352703b5a 100644
--- a/spec/lib/connection_pool/shared_connection_pool_spec.rb
+++ b/spec/lib/connection_pool/shared_connection_pool_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ConnectionPool::SharedConnectionPool do
+RSpec.describe ConnectionPool::SharedConnectionPool do
subject { described_class.new(size: 5, timeout: 5) { |site| mini_connection_class.new(site) } }
let(:mini_connection_class) do
diff --git a/spec/lib/connection_pool/shared_timed_stack_spec.rb b/spec/lib/connection_pool/shared_timed_stack_spec.rb
index 04d550eec5..7469664ea0 100644
--- a/spec/lib/connection_pool/shared_timed_stack_spec.rb
+++ b/spec/lib/connection_pool/shared_timed_stack_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ConnectionPool::SharedTimedStack do
+RSpec.describe ConnectionPool::SharedTimedStack do
subject { described_class.new(5) { |site| mini_connection_class.new(site) } }
let(:mini_connection_class) do
diff --git a/spec/lib/content_security_policy_spec.rb b/spec/lib/content_security_policy_spec.rb
index 27a3e80257..5ecea60543 100644
--- a/spec/lib/content_security_policy_spec.rb
+++ b/spec/lib/content_security_policy_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ContentSecurityPolicy do
+RSpec.describe ContentSecurityPolicy do
subject { described_class.new }
around do |example|
diff --git a/spec/lib/delivery_failure_tracker_spec.rb b/spec/lib/delivery_failure_tracker_spec.rb
index c8179ebd91..40c8adc4c8 100644
--- a/spec/lib/delivery_failure_tracker_spec.rb
+++ b/spec/lib/delivery_failure_tracker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe DeliveryFailureTracker do
+RSpec.describe DeliveryFailureTracker do
subject { described_class.new('http://example.com/inbox') }
describe '#track_success!' do
diff --git a/spec/lib/extractor_spec.rb b/spec/lib/extractor_spec.rb
index af5c62d4c8..bc3ee8ac49 100644
--- a/spec/lib/extractor_spec.rb
+++ b/spec/lib/extractor_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Extractor do
+RSpec.describe Extractor do
describe 'extract_mentions_or_lists_with_indices' do
it 'returns an empty array if the given string does not have at signs' do
text = 'a string without at signs'
diff --git a/spec/lib/fast_ip_map_spec.rb b/spec/lib/fast_ip_map_spec.rb
index 78b3ddb054..a3a647e3e3 100644
--- a/spec/lib/fast_ip_map_spec.rb
+++ b/spec/lib/fast_ip_map_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe FastIpMap do
+RSpec.describe FastIpMap do
describe '#include?' do
subject { described_class.new([IPAddr.new('20.4.0.0/16'), IPAddr.new('145.22.30.0/24'), IPAddr.new('189.45.86.3')]) }
diff --git a/spec/lib/hashtag_normalizer_spec.rb b/spec/lib/hashtag_normalizer_spec.rb
index fbb9f37c07..796445043a 100644
--- a/spec/lib/hashtag_normalizer_spec.rb
+++ b/spec/lib/hashtag_normalizer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe HashtagNormalizer do
+RSpec.describe HashtagNormalizer do
subject { described_class.new }
describe '#normalize' do
diff --git a/spec/lib/importer/accounts_index_importer_spec.rb b/spec/lib/importer/accounts_index_importer_spec.rb
index 73f9bce399..a5d11c747a 100644
--- a/spec/lib/importer/accounts_index_importer_spec.rb
+++ b/spec/lib/importer/accounts_index_importer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Importer::AccountsIndexImporter do
+RSpec.describe Importer::AccountsIndexImporter do
describe 'import!' do
let(:pool) { Concurrent::FixedThreadPool.new(5) }
let(:importer) { described_class.new(batch_size: 123, executor: pool) }
diff --git a/spec/lib/importer/base_importer_spec.rb b/spec/lib/importer/base_importer_spec.rb
index 78e9a869b8..0d12f975aa 100644
--- a/spec/lib/importer/base_importer_spec.rb
+++ b/spec/lib/importer/base_importer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Importer::BaseImporter do
+RSpec.describe Importer::BaseImporter do
describe 'import!' do
let(:pool) { Concurrent::FixedThreadPool.new(5) }
let(:importer) { described_class.new(batch_size: 123, executor: pool) }
diff --git a/spec/lib/importer/public_statuses_index_importer_spec.rb b/spec/lib/importer/public_statuses_index_importer_spec.rb
index bc7c038a97..2407717409 100644
--- a/spec/lib/importer/public_statuses_index_importer_spec.rb
+++ b/spec/lib/importer/public_statuses_index_importer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Importer::PublicStatusesIndexImporter do
+RSpec.describe Importer::PublicStatusesIndexImporter do
describe 'import!' do
let(:pool) { Concurrent::FixedThreadPool.new(5) }
let(:importer) { described_class.new(batch_size: 123, executor: pool) }
diff --git a/spec/lib/importer/statuses_index_importer_spec.rb b/spec/lib/importer/statuses_index_importer_spec.rb
index d5e1c9f2cb..f6fac3bd67 100644
--- a/spec/lib/importer/statuses_index_importer_spec.rb
+++ b/spec/lib/importer/statuses_index_importer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Importer::StatusesIndexImporter do
+RSpec.describe Importer::StatusesIndexImporter do
describe 'import!' do
let(:pool) { Concurrent::FixedThreadPool.new(5) }
let(:importer) { described_class.new(batch_size: 123, executor: pool) }
diff --git a/spec/lib/importer/tags_index_importer_spec.rb b/spec/lib/importer/tags_index_importer_spec.rb
index 348990c01e..44de9e7c34 100644
--- a/spec/lib/importer/tags_index_importer_spec.rb
+++ b/spec/lib/importer/tags_index_importer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Importer::TagsIndexImporter do
+RSpec.describe Importer::TagsIndexImporter do
describe 'import!' do
let(:pool) { Concurrent::FixedThreadPool.new(5) }
let(:importer) { described_class.new(batch_size: 123, executor: pool) }
diff --git a/spec/lib/link_details_extractor_spec.rb b/spec/lib/link_details_extractor_spec.rb
index b1e5cedced..d8d9db0ad1 100644
--- a/spec/lib/link_details_extractor_spec.rb
+++ b/spec/lib/link_details_extractor_spec.rb
@@ -33,6 +33,14 @@ RSpec.describe LinkDetailsExtractor do
expect(subject.canonical_url).to eq original_url
end
end
+
+ context 'when canonical URL is set to "undefined"' do
+ let(:url) { 'undefined' }
+
+ it 'ignores the canonical URLs' do
+ expect(subject.canonical_url).to eq original_url
+ end
+ end
end
context 'when only basic metadata is present' do
diff --git a/spec/lib/mastodon/cli/accounts_spec.rb b/spec/lib/mastodon/cli/accounts_spec.rb
index 137f85c6ca..f6cc28297a 100644
--- a/spec/lib/mastodon/cli/accounts_spec.rb
+++ b/spec/lib/mastodon/cli/accounts_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/accounts'
-describe Mastodon::CLI::Accounts do
+RSpec.describe Mastodon::CLI::Accounts do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
@@ -613,6 +613,25 @@ describe Mastodon::CLI::Accounts do
end
end
+ describe '#fix_duplicates' do
+ let(:action) { :fix_duplicates }
+ let(:service_double) { instance_double(ActivityPub::FetchRemoteAccountService, call: nil) }
+ let(:uri) { 'https://host.example/same/value' }
+
+ context 'when there are duplicate URI accounts' do
+ before do
+ Fabricate.times(2, :account, domain: 'host.example', uri: uri)
+ allow(ActivityPub::FetchRemoteAccountService).to receive(:new).and_return(service_double)
+ end
+
+ it 'finds the duplicates and calls fetch remote account service' do
+ expect { subject }
+ .to output_results('Duplicates found')
+ expect(service_double).to have_received(:call).with(uri)
+ end
+ end
+ end
+
describe '#backup' do
let(:action) { :backup }
diff --git a/spec/lib/mastodon/cli/cache_spec.rb b/spec/lib/mastodon/cli/cache_spec.rb
index 247a14f9e2..dc571238d2 100644
--- a/spec/lib/mastodon/cli/cache_spec.rb
+++ b/spec/lib/mastodon/cli/cache_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/cache'
-describe Mastodon::CLI::Cache do
+RSpec.describe Mastodon::CLI::Cache do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb b/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb
index 1745ea01bf..faa5ec7cb8 100644
--- a/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb
+++ b/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/canonical_email_blocks'
-describe Mastodon::CLI::CanonicalEmailBlocks do
+RSpec.describe Mastodon::CLI::CanonicalEmailBlocks do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/domains_spec.rb b/spec/lib/mastodon/cli/domains_spec.rb
index 448e6fe42b..d1c26546f0 100644
--- a/spec/lib/mastodon/cli/domains_spec.rb
+++ b/spec/lib/mastodon/cli/domains_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/domains'
-describe Mastodon::CLI::Domains do
+RSpec.describe Mastodon::CLI::Domains do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb
index 55e3da0bb8..a5fbd23e65 100644
--- a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb
+++ b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/email_domain_blocks'
-describe Mastodon::CLI::EmailDomainBlocks do
+RSpec.describe Mastodon::CLI::EmailDomainBlocks do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/emoji_spec.rb b/spec/lib/mastodon/cli/emoji_spec.rb
index d05e972e77..4336db17d3 100644
--- a/spec/lib/mastodon/cli/emoji_spec.rb
+++ b/spec/lib/mastodon/cli/emoji_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/emoji'
-describe Mastodon::CLI::Emoji do
+RSpec.describe Mastodon::CLI::Emoji do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/feeds_spec.rb b/spec/lib/mastodon/cli/feeds_spec.rb
index 420cb3d587..75a8cb3ebc 100644
--- a/spec/lib/mastodon/cli/feeds_spec.rb
+++ b/spec/lib/mastodon/cli/feeds_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/feeds'
-describe Mastodon::CLI::Feeds do
+RSpec.describe Mastodon::CLI::Feeds do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/ip_blocks_spec.rb b/spec/lib/mastodon/cli/ip_blocks_spec.rb
index d44b1b9fe4..68d6b19859 100644
--- a/spec/lib/mastodon/cli/ip_blocks_spec.rb
+++ b/spec/lib/mastodon/cli/ip_blocks_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/ip_blocks'
-describe Mastodon::CLI::IpBlocks do
+RSpec.describe Mastodon::CLI::IpBlocks do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/main_spec.rb b/spec/lib/mastodon/cli/main_spec.rb
index 99d770a81d..a63b798683 100644
--- a/spec/lib/mastodon/cli/main_spec.rb
+++ b/spec/lib/mastodon/cli/main_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/main'
-describe Mastodon::CLI::Main do
+RSpec.describe Mastodon::CLI::Main do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/maintenance_spec.rb b/spec/lib/mastodon/cli/maintenance_spec.rb
index cde25d39ed..6a15677f43 100644
--- a/spec/lib/mastodon/cli/maintenance_spec.rb
+++ b/spec/lib/mastodon/cli/maintenance_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/maintenance'
-describe Mastodon::CLI::Maintenance do
+RSpec.describe Mastodon::CLI::Maintenance do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/media_spec.rb b/spec/lib/mastodon/cli/media_spec.rb
index ecc7101b6c..fa7a3161d0 100644
--- a/spec/lib/mastodon/cli/media_spec.rb
+++ b/spec/lib/mastodon/cli/media_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/media'
-describe Mastodon::CLI::Media do
+RSpec.describe Mastodon::CLI::Media do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/preview_cards_spec.rb b/spec/lib/mastodon/cli/preview_cards_spec.rb
index 951ae3758f..949787a759 100644
--- a/spec/lib/mastodon/cli/preview_cards_spec.rb
+++ b/spec/lib/mastodon/cli/preview_cards_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/preview_cards'
-describe Mastodon::CLI::PreviewCards do
+RSpec.describe Mastodon::CLI::PreviewCards do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/search_spec.rb b/spec/lib/mastodon/cli/search_spec.rb
index ed3789c3e7..8a6c2492aa 100644
--- a/spec/lib/mastodon/cli/search_spec.rb
+++ b/spec/lib/mastodon/cli/search_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/search'
-describe Mastodon::CLI::Search do
+RSpec.describe Mastodon::CLI::Search do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/settings_spec.rb b/spec/lib/mastodon/cli/settings_spec.rb
index e1b353eb90..5565b798ef 100644
--- a/spec/lib/mastodon/cli/settings_spec.rb
+++ b/spec/lib/mastodon/cli/settings_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/settings'
-describe Mastodon::CLI::Settings do
+RSpec.describe Mastodon::CLI::Settings do
it_behaves_like 'CLI Command'
describe 'subcommand "registrations"' do
diff --git a/spec/lib/mastodon/cli/statuses_spec.rb b/spec/lib/mastodon/cli/statuses_spec.rb
index 161b7c02bb..2597ad7f27 100644
--- a/spec/lib/mastodon/cli/statuses_spec.rb
+++ b/spec/lib/mastodon/cli/statuses_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/statuses'
-describe Mastodon::CLI::Statuses do
+RSpec.describe Mastodon::CLI::Statuses do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/cli/upgrade_spec.rb b/spec/lib/mastodon/cli/upgrade_spec.rb
index 6861e04887..6861e1a068 100644
--- a/spec/lib/mastodon/cli/upgrade_spec.rb
+++ b/spec/lib/mastodon/cli/upgrade_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/cli/upgrade'
-describe Mastodon::CLI::Upgrade do
+RSpec.describe Mastodon::CLI::Upgrade do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
diff --git a/spec/lib/mastodon/migration_warning_spec.rb b/spec/lib/mastodon/migration_warning_spec.rb
index 4adf0837ab..d796d1e902 100644
--- a/spec/lib/mastodon/migration_warning_spec.rb
+++ b/spec/lib/mastodon/migration_warning_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'mastodon/migration_warning'
-describe Mastodon::MigrationWarning do
+RSpec.describe Mastodon::MigrationWarning do
describe 'migration_duration_warning' do
before do
allow(migration).to receive(:valid_environment?).and_return(true)
diff --git a/spec/lib/mastodon/redis_configuration_spec.rb b/spec/lib/mastodon/redis_configuration_spec.rb
new file mode 100644
index 0000000000..e36dcfba0a
--- /dev/null
+++ b/spec/lib/mastodon/redis_configuration_spec.rb
@@ -0,0 +1,263 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Mastodon::RedisConfiguration do
+ let(:redis_environment) { described_class.new }
+
+ before do
+ # We use one numbered namespace per parallel test runner
+ # in the test env. This here should test the non-test
+ # behavior, so we disable it temporarily.
+ allow(Rails.env).to receive(:test?).and_return(false)
+ end
+
+ shared_examples 'setting a different driver' do
+ context 'when setting the `REDIS_DRIVER` variable to `ruby`' do
+ around do |example|
+ ClimateControl.modify REDIS_DRIVER: 'ruby' do
+ example.run
+ end
+ end
+
+ it 'sets the driver accordingly' do
+ expect(subject[:driver]).to eq :ruby
+ end
+ end
+ end
+
+ shared_examples 'setting a namespace' do
+ context 'when setting the `REDIS_NAMESPACE` variable' do
+ around do |example|
+ ClimateControl.modify REDIS_NAMESPACE: 'testns' do
+ example.run
+ end
+ end
+
+ it 'uses the value for the namespace' do
+ expect(subject[:namespace]).to eq 'testns'
+ end
+ end
+ end
+
+ shared_examples 'secondary configuration' do |prefix|
+ context "when no `#{prefix}_REDIS_` environment variables are present" do
+ it 'uses the url from the base config' do
+ expect(subject[:url]).to eq 'redis://localhost:6379/0'
+ end
+
+ context 'when the base config uses sentinel' do
+ around do |example|
+ ClimateControl.modify REDIS_SENTINELS: '192.168.0.1:3000,192.168.0.2:4000', REDIS_SENTINEL_MASTER: 'mainsentinel' do
+ example.run
+ end
+ end
+
+ it 'uses the sentinel configuration from base config' do
+ expect(subject[:url]).to eq 'redis://mainsentinel/0'
+ expect(subject[:name]).to eq 'mainsentinel'
+ expect(subject[:sentinels]).to contain_exactly({ host: '192.168.0.1', port: 3000 }, { host: '192.168.0.2', port: 4000 })
+ end
+ end
+ end
+
+ context "when the `#{prefix}_REDIS_URL` environment variable is present" do
+ around do |example|
+ ClimateControl.modify "#{prefix}_REDIS_URL": 'redis::/user@other.example.com/4' do
+ example.run
+ end
+ end
+
+ it 'uses the provided URL' do
+ expect(subject[:url]).to eq 'redis::/user@other.example.com/4'
+ end
+ end
+
+ context 'when giving separate environment variables' do
+ around do |example|
+ ClimateControl.modify "#{prefix}_REDIS_PASSWORD": 'testpass1', "#{prefix}_REDIS_HOST": 'redis2.example.com', "#{prefix}_REDIS_PORT": '3322', "#{prefix}_REDIS_DB": '8' do
+ example.run
+ end
+ end
+
+ it 'constructs the url from them' do
+ expect(subject[:url]).to eq 'redis://:testpass1@redis2.example.com:3322/8'
+ end
+ end
+ end
+
+ shared_examples 'sentinel support' do |prefix = nil|
+ prefix = prefix ? "#{prefix}_" : ''
+
+ context 'when configuring sentinel support' do
+ around do |example|
+ ClimateControl.modify "#{prefix}REDIS_PASSWORD": 'testpass1', "#{prefix}REDIS_HOST": 'redis2.example.com', "#{prefix}REDIS_SENTINELS": '192.168.0.1:3000,192.168.0.2:4000', "#{prefix}REDIS_SENTINEL_MASTER": 'mainsentinel' do
+ example.run
+ end
+ end
+
+ it 'constructs the url using the sentinel master name' do
+ expect(subject[:url]).to eq 'redis://:testpass1@mainsentinel/0'
+ end
+
+ it 'uses the redis password to authenticate with sentinels' do
+ expect(subject[:sentinel_password]).to eq 'testpass1'
+ end
+
+ it 'includes the sentinel master name and list of sentinels' do
+ expect(subject[:name]).to eq 'mainsentinel'
+ expect(subject[:sentinels]).to contain_exactly({ host: '192.168.0.1', port: 3000 }, { host: '192.168.0.2', port: 4000 })
+ end
+
+ context "when giving dedicated credentials in `#{prefix}REDIS_SENTINEL_USERNAME` and `#{prefix}REDIS_SENTINEL_PASSWORD`" do
+ around do |example|
+ ClimateControl.modify "#{prefix}REDIS_SENTINEL_USERNAME": 'sentinel_user', "#{prefix}REDIS_SENTINEL_PASSWORD": 'sentinel_pass1' do
+ example.run
+ end
+ end
+
+ it 'uses the credential to authenticate with sentinels' do
+ expect(subject[:sentinel_username]).to eq 'sentinel_user'
+ expect(subject[:sentinel_password]).to eq 'sentinel_pass1'
+ end
+ end
+ end
+
+ context 'when giving sentinels without port numbers' do
+ context "when no default port is given via `#{prefix}REDIS_SENTINEL_PORT`" do
+ around do |example|
+ ClimateControl.modify "#{prefix}REDIS_SENTINELS": '192.168.0.1,192.168.0.2', "#{prefix}REDIS_SENTINEL_MASTER": 'mainsentinel' do
+ example.run
+ end
+ end
+
+ it 'uses the default sentinel port' do
+ expect(subject[:sentinels]).to contain_exactly({ host: '192.168.0.1', port: 26_379 }, { host: '192.168.0.2', port: 26_379 })
+ end
+ end
+
+ context 'when adding port numbers to some, but not all sentinels' do
+ around do |example|
+ ClimateControl.modify "#{prefix}REDIS_SENTINELS": '192.168.0.1:5678,192.168.0.2', "#{prefix}REDIS_SENTINEL_MASTER": 'mainsentinel' do
+ example.run
+ end
+ end
+
+ it 'uses the given port number when available and the default otherwise' do
+ expect(subject[:sentinels]).to contain_exactly({ host: '192.168.0.1', port: 5678 }, { host: '192.168.0.2', port: 26_379 })
+ end
+ end
+
+ context "when a default port is given via `#{prefix}REDIS_SENTINEL_PORT`" do
+ around do |example|
+ ClimateControl.modify "#{prefix}REDIS_SENTINEL_PORT": '1234', "#{prefix}REDIS_SENTINELS": '192.168.0.1,192.168.0.2', "#{prefix}REDIS_SENTINEL_MASTER": 'mainsentinel' do
+ example.run
+ end
+ end
+
+ it 'uses the given port number' do
+ expect(subject[:sentinels]).to contain_exactly({ host: '192.168.0.1', port: 1234 }, { host: '192.168.0.2', port: 1234 })
+ end
+ end
+ end
+ end
+
+ describe '#base' do
+ subject { redis_environment.base }
+
+ context 'when no `REDIS_` environment variables are present' do
+ it 'uses defaults' do
+ expect(subject).to eq({
+ url: 'redis://localhost:6379/0',
+ driver: :hiredis,
+ namespace: nil,
+ })
+ end
+ end
+
+ context 'when the `REDIS_URL` environment variable is present' do
+ around do |example|
+ ClimateControl.modify REDIS_URL: 'redis::/user@example.com/2' do
+ example.run
+ end
+ end
+
+ it 'uses the provided URL' do
+ expect(subject).to eq({
+ url: 'redis::/user@example.com/2',
+ driver: :hiredis,
+ namespace: nil,
+ })
+ end
+ end
+
+ context 'when giving separate environment variables' do
+ around do |example|
+ ClimateControl.modify REDIS_PASSWORD: 'testpass', REDIS_HOST: 'redis.example.com', REDIS_PORT: '3333', REDIS_DB: '3' do
+ example.run
+ end
+ end
+
+ it 'constructs the url from them' do
+ expect(subject).to eq({
+ url: 'redis://:testpass@redis.example.com:3333/3',
+ driver: :hiredis,
+ namespace: nil,
+ })
+ end
+ end
+
+ include_examples 'setting a different driver'
+ include_examples 'setting a namespace'
+ include_examples 'sentinel support'
+ end
+
+ describe '#sidekiq' do
+ subject { redis_environment.sidekiq }
+
+ include_examples 'secondary configuration', 'SIDEKIQ'
+ include_examples 'setting a different driver'
+ include_examples 'setting a namespace'
+ include_examples 'sentinel support', 'SIDEKIQ'
+ end
+
+ describe '#cache' do
+ subject { redis_environment.cache }
+
+ it 'includes extra configuration' do
+ expect(subject).to eq({
+ url: 'redis://localhost:6379/0',
+ driver: :hiredis,
+ namespace: 'cache',
+ expires_in: 10.minutes,
+ connect_timeout: 5,
+ pool: {
+ size: 5,
+ timeout: 5,
+ },
+ })
+ end
+
+ context 'when `REDIS_NAMESPACE` is not set' do
+ it 'uses the `cache` namespace' do
+ expect(subject[:namespace]).to eq 'cache'
+ end
+ end
+
+ context 'when setting the `REDIS_NAMESPACE` variable' do
+ around do |example|
+ ClimateControl.modify REDIS_NAMESPACE: 'testns' do
+ example.run
+ end
+ end
+
+ it 'attaches the `_cache` postfix to the namespace' do
+ expect(subject[:namespace]).to eq 'testns_cache'
+ end
+ end
+
+ include_examples 'secondary configuration', 'CACHE'
+ include_examples 'setting a different driver'
+ include_examples 'sentinel support', 'CACHE'
+ end
+end
diff --git a/spec/lib/ostatus/tag_manager_spec.rb b/spec/lib/ostatus/tag_manager_spec.rb
index 0e20f26c7c..f808b96289 100644
--- a/spec/lib/ostatus/tag_manager_spec.rb
+++ b/spec/lib/ostatus/tag_manager_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe OStatus::TagManager do
+RSpec.describe OStatus::TagManager do
describe '#unique_tag' do
it 'returns a unique tag' do
expect(described_class.instance.unique_tag(Time.utc(2000), 12, 'Status')).to eq 'tag:cb6e6126.ngrok.io,2000-01-01:objectId=12:objectType=Status'
diff --git a/spec/lib/paperclip/response_with_limit_adapter_spec.rb b/spec/lib/paperclip/response_with_limit_adapter_spec.rb
index baf8bf5bb7..3db52ffa0d 100644
--- a/spec/lib/paperclip/response_with_limit_adapter_spec.rb
+++ b/spec/lib/paperclip/response_with_limit_adapter_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Paperclip::ResponseWithLimitAdapter do
+RSpec.describe Paperclip::ResponseWithLimitAdapter do
subject { described_class.new(response_with_limit) }
before { stub_request(:get, url).to_return(headers: headers, body: body) }
diff --git a/spec/lib/permalink_redirector_spec.rb b/spec/lib/permalink_redirector_spec.rb
index a009136561..5a544c3d38 100644
--- a/spec/lib/permalink_redirector_spec.rb
+++ b/spec/lib/permalink_redirector_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe PermalinkRedirector do
+RSpec.describe PermalinkRedirector do
let(:remote_account) { Fabricate(:account, username: 'alice', domain: 'example.com', url: 'https://example.com/@alice', id: 2) }
describe '#redirect_url' do
@@ -29,5 +29,20 @@ describe PermalinkRedirector do
redirector = described_class.new('@alice/123')
expect(redirector.redirect_path).to eq 'https://example.com/status-123'
end
+
+ it 'returns path for legacy status links with a query param' do
+ redirector = described_class.new('statuses/123?foo=bar')
+ expect(redirector.redirect_path).to eq 'https://example.com/status-123'
+ end
+
+ it 'returns path for pretty status links with a query param' do
+ redirector = described_class.new('@alice/123?foo=bar')
+ expect(redirector.redirect_path).to eq 'https://example.com/status-123'
+ end
+
+ it 'returns path for deck URLs with query params' do
+ redirector = described_class.new('/deck/directory?local=true')
+ expect(redirector.redirect_path).to eq '/directory?local=true'
+ end
end
end
diff --git a/spec/lib/request_pool_spec.rb b/spec/lib/request_pool_spec.rb
index a82eb5a188..2e8c785de8 100644
--- a/spec/lib/request_pool_spec.rb
+++ b/spec/lib/request_pool_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RequestPool do
+RSpec.describe RequestPool do
subject { described_class.new }
describe '#with' do
diff --git a/spec/lib/request_spec.rb b/spec/lib/request_spec.rb
index c99f18838b..c600a48ee2 100644
--- a/spec/lib/request_spec.rb
+++ b/spec/lib/request_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'securerandom'
-describe Request do
+RSpec.describe Request do
subject { described_class.new(:get, 'http://example.com') }
describe '#headers' do
diff --git a/spec/lib/sanitize/config_spec.rb b/spec/lib/sanitize/config_spec.rb
index a1e39153e6..c2008544f5 100644
--- a/spec/lib/sanitize/config_spec.rb
+++ b/spec/lib/sanitize/config_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Sanitize::Config do
+RSpec.describe Sanitize::Config do
shared_examples 'common HTML sanitization' do
it 'keeps h1' do
expect(Sanitize.fragment('Foo
', subject)).to eq 'Foo
'
diff --git a/spec/lib/scope_transformer_spec.rb b/spec/lib/scope_transformer_spec.rb
index 7bc226e94f..f4003352e4 100644
--- a/spec/lib/scope_transformer_spec.rb
+++ b/spec/lib/scope_transformer_spec.rb
@@ -2,21 +2,18 @@
require 'rails_helper'
-describe ScopeTransformer do
+RSpec.describe ScopeTransformer do
describe '#apply' do
subject { described_class.new.apply(ScopeParser.new.parse(input)) }
shared_examples 'a scope' do |namespace, term, access|
- it 'parses the term' do
- expect(subject.term).to eq term
- end
-
- it 'parses the namespace' do
- expect(subject.namespace).to eq namespace
- end
-
- it 'parses the access' do
- expect(subject.access).to eq access
+ it 'parses the attributes' do
+ expect(subject)
+ .to have_attributes(
+ term: term,
+ namespace: namespace,
+ access: access
+ )
end
end
diff --git a/spec/lib/search_query_parser_spec.rb b/spec/lib/search_query_parser_spec.rb
index 66b0e8f9e2..22149b3402 100644
--- a/spec/lib/search_query_parser_spec.rb
+++ b/spec/lib/search_query_parser_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'parslet/rig/rspec'
-describe SearchQueryParser do
+RSpec.describe SearchQueryParser do
let(:parser) { described_class.new }
context 'with term' do
diff --git a/spec/lib/search_query_transformer_spec.rb b/spec/lib/search_query_transformer_spec.rb
index 5817e3d1d2..9399f3503d 100644
--- a/spec/lib/search_query_transformer_spec.rb
+++ b/spec/lib/search_query_transformer_spec.rb
@@ -2,12 +2,43 @@
require 'rails_helper'
-describe SearchQueryTransformer do
+RSpec.describe SearchQueryTransformer do
subject { described_class.new.apply(parser, current_account: account) }
let(:account) { Fabricate(:account) }
let(:parser) { SearchQueryParser.new.parse(query) }
+ shared_examples 'date operator' do |operator|
+ let(:statement_operations) { [] }
+
+ [
+ ['2022-01-01', '2022-01-01'],
+ ['"2022-01-01"', '2022-01-01'],
+ ['12345678', '12345678'],
+ ['"12345678"', '12345678'],
+ ].each do |value, parsed|
+ context "with #{operator}:#{value}" do
+ let(:query) { "#{operator}:#{value}" }
+
+ it 'transforms clauses' do
+ ops = statement_operations.index_with { |_op| parsed }
+
+ expect(subject.send(:must_clauses)).to be_empty
+ expect(subject.send(:must_not_clauses)).to be_empty
+ expect(subject.send(:filter_clauses).map(&:term)).to contain_exactly(**ops, time_zone: 'UTC')
+ end
+ end
+ end
+
+ context "with #{operator}:\"abc\"" do
+ let(:query) { "#{operator}:\"abc\"" }
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(Mastodon::FilterValidationError, 'Invalid date abc')
+ end
+ end
+ end
+
context 'with "hello world"' do
let(:query) { 'hello world' }
@@ -68,13 +99,33 @@ describe SearchQueryTransformer do
end
end
- context 'with \'before:"2022-01-01 23:00"\'' do
- let(:query) { 'before:"2022-01-01 23:00"' }
+ context 'with \'is:"foo bar"\'' do
+ let(:query) { 'is:"foo bar"' }
it 'transforms clauses' do
expect(subject.send(:must_clauses)).to be_empty
expect(subject.send(:must_not_clauses)).to be_empty
- expect(subject.send(:filter_clauses).map(&:term)).to contain_exactly(lt: '2022-01-01 23:00', time_zone: 'UTC')
+ expect(subject.send(:filter_clauses).map(&:term)).to contain_exactly('foo bar')
+ end
+ end
+
+ context 'with date operators' do
+ context 'with "before"' do
+ it_behaves_like 'date operator', 'before' do
+ let(:statement_operations) { [:lt] }
+ end
+ end
+
+ context 'with "after"' do
+ it_behaves_like 'date operator', 'after' do
+ let(:statement_operations) { [:gt] }
+ end
+ end
+
+ context 'with "during"' do
+ it_behaves_like 'date operator', 'during' do
+ let(:statement_operations) { [:gte, :lte] }
+ end
end
end
end
diff --git a/spec/lib/status_cache_hydrator_spec.rb b/spec/lib/status_cache_hydrator_spec.rb
index 5b80ccb970..958e2f62d7 100644
--- a/spec/lib/status_cache_hydrator_spec.rb
+++ b/spec/lib/status_cache_hydrator_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe StatusCacheHydrator do
+RSpec.describe StatusCacheHydrator do
let(:status) { Fabricate(:status) }
let(:account) { Fabricate(:account) }
diff --git a/spec/lib/status_filter_spec.rb b/spec/lib/status_filter_spec.rb
index cf6f3c7959..16c2e84f22 100644
--- a/spec/lib/status_filter_spec.rb
+++ b/spec/lib/status_filter_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe StatusFilter do
+RSpec.describe StatusFilter do
describe '#filtered?' do
let(:status) { Fabricate(:status) }
diff --git a/spec/lib/status_finder_spec.rb b/spec/lib/status_finder_spec.rb
index 53f5039af9..4d1c27afff 100644
--- a/spec/lib/status_finder_spec.rb
+++ b/spec/lib/status_finder_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe StatusFinder do
+RSpec.describe StatusFinder do
include RoutingHelper
describe '#status' do
diff --git a/spec/lib/status_reach_finder_spec.rb b/spec/lib/status_reach_finder_spec.rb
index 7181717dc1..c045980ea9 100644
--- a/spec/lib/status_reach_finder_spec.rb
+++ b/spec/lib/status_reach_finder_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe StatusReachFinder do
+RSpec.describe StatusReachFinder do
describe '#inboxes' do
context 'with a local status' do
subject { described_class.new(status) }
diff --git a/spec/lib/vacuum/system_keys_vacuum_spec.rb b/spec/lib/vacuum/system_keys_vacuum_spec.rb
deleted file mode 100644
index 84cae30411..0000000000
--- a/spec/lib/vacuum/system_keys_vacuum_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Vacuum::SystemKeysVacuum do
- subject { described_class.new }
-
- describe '#perform' do
- let!(:expired_system_key) { Fabricate(:system_key, created_at: (SystemKey::ROTATION_PERIOD * 4).ago) }
- let!(:current_system_key) { Fabricate(:system_key) }
-
- before do
- subject.perform
- end
-
- it 'deletes the expired key' do
- expect { expired_system_key.reload }.to raise_error ActiveRecord::RecordNotFound
- end
-
- it 'does not delete the current key' do
- expect { current_system_key.reload }.to_not raise_error
- end
- end
-end
diff --git a/spec/lib/webfinger_resource_spec.rb b/spec/lib/webfinger_resource_spec.rb
index 442f91aad0..0b86b41c48 100644
--- a/spec/lib/webfinger_resource_spec.rb
+++ b/spec/lib/webfinger_resource_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe WebfingerResource do
+RSpec.describe WebfingerResource do
around do |example|
before_local = Rails.configuration.x.local_domain
before_web = Rails.configuration.x.web_domain
diff --git a/spec/lib/webhooks/payload_renderer_spec.rb b/spec/lib/webhooks/payload_renderer_spec.rb
index 074847c74c..0623edd254 100644
--- a/spec/lib/webhooks/payload_renderer_spec.rb
+++ b/spec/lib/webhooks/payload_renderer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Webhooks::PayloadRenderer do
+RSpec.describe Webhooks::PayloadRenderer do
subject(:renderer) { described_class.new(json) }
let(:event) { Webhooks::EventPresenter.new(type, object) }
diff --git a/spec/locales/i18n_spec.rb b/spec/locales/i18n_spec.rb
index cfce8e2234..8facf6612c 100644
--- a/spec/locales/i18n_spec.rb
+++ b/spec/locales/i18n_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'I18n' do
+RSpec.describe 'I18n' do
describe 'Pluralizing locale translations' do
subject { I18n.t('generic.validation_errors', count: 1) }
diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb
index eab196166d..4c6107d9f7 100644
--- a/spec/mailers/notification_mailer_spec.rb
+++ b/spec/mailers/notification_mailer_spec.rb
@@ -3,43 +3,28 @@
require 'rails_helper'
RSpec.describe NotificationMailer do
+ shared_examples 'delivery to non functional user' do
+ context 'when user is not functional' do
+ before { receiver.update(confirmed_at: nil) }
+
+ it 'does not deliver mail' do
+ emails = capture_emails { mail.deliver_now }
+ expect(emails).to be_empty
+ end
+ end
+ end
+
let(:receiver) { Fabricate(:user, account_attributes: { username: 'alice' }) }
let(:sender) { Fabricate(:account, username: 'bob') }
let(:foreign_status) { Fabricate(:status, account: sender, text: 'The body of the foreign status') }
let(:own_status) { Fabricate(:status, account: receiver.account, text: 'The body of the own status') }
- shared_examples 'standard headers' do |type|
- it 'renders the email' do
- expect(mail)
- .to be_present
- .and(have_header('To', "#{receiver.account.username} <#{receiver.email}>"))
- .and(have_header('List-ID', "<#{type}.alice.cb6e6126.ngrok.io>"))
- .and(have_header('List-Unsubscribe', %r{}))
- .and(have_header('List-Unsubscribe', /&type=#{type}/))
- .and(have_header('List-Unsubscribe-Post', 'List-Unsubscribe=One-Click'))
- .and(deliver_to("#{receiver.account.username} <#{receiver.email}>"))
- .and(deliver_from('notifications@localhost'))
- end
- end
-
- shared_examples 'thread headers' do
- it 'renders the email with conversation thread headers' do
- conversation_header_regex = //
- expect(mail)
- .to be_present
- .and(have_header('In-Reply-To', conversation_header_regex))
- .and(have_header('References', conversation_header_regex))
- end
- end
-
describe 'mention' do
let(:mention) { Mention.create!(account: receiver.account, status: foreign_status) }
let(:notification) { Notification.create!(account: receiver.account, activity: mention) }
let(:mail) { prepared_mailer_for(receiver.account).mention }
include_examples 'localized subject', 'notification_mailer.mention.subject', name: 'bob'
- include_examples 'standard headers', 'mention'
- include_examples 'thread headers'
it 'renders the email' do
expect(mail)
@@ -47,7 +32,11 @@ RSpec.describe NotificationMailer do
.and(have_subject('You were mentioned by bob'))
.and(have_body_text('You were mentioned by bob'))
.and(have_body_text('The body of the foreign status'))
+ .and have_thread_headers
+ .and have_standard_headers('mention').for(receiver)
end
+
+ include_examples 'delivery to non functional user'
end
describe 'follow' do
@@ -56,14 +45,16 @@ RSpec.describe NotificationMailer do
let(:mail) { prepared_mailer_for(receiver.account).follow }
include_examples 'localized subject', 'notification_mailer.follow.subject', name: 'bob'
- include_examples 'standard headers', 'follow'
it 'renders the email' do
expect(mail)
.to be_present
.and(have_subject('bob is now following you'))
.and(have_body_text('bob is now following you'))
+ .and have_standard_headers('follow').for(receiver)
end
+
+ include_examples 'delivery to non functional user'
end
describe 'favourite' do
@@ -72,8 +63,6 @@ RSpec.describe NotificationMailer do
let(:mail) { prepared_mailer_for(own_status.account).favourite }
include_examples 'localized subject', 'notification_mailer.favourite.subject', name: 'bob'
- include_examples 'standard headers', 'favourite'
- include_examples 'thread headers'
it 'renders the email' do
expect(mail)
@@ -81,7 +70,11 @@ RSpec.describe NotificationMailer do
.and(have_subject('bob favorited your post'))
.and(have_body_text('Your post was favorited by bob'))
.and(have_body_text('The body of the own status'))
+ .and have_thread_headers
+ .and have_standard_headers('favourite').for(receiver)
end
+
+ include_examples 'delivery to non functional user'
end
describe 'reblog' do
@@ -90,8 +83,6 @@ RSpec.describe NotificationMailer do
let(:mail) { prepared_mailer_for(own_status.account).reblog }
include_examples 'localized subject', 'notification_mailer.reblog.subject', name: 'bob'
- include_examples 'standard headers', 'reblog'
- include_examples 'thread headers'
it 'renders the email' do
expect(mail)
@@ -99,7 +90,11 @@ RSpec.describe NotificationMailer do
.and(have_subject('bob boosted your post'))
.and(have_body_text('Your post was boosted by bob'))
.and(have_body_text('The body of the own status'))
+ .and have_thread_headers
+ .and have_standard_headers('reblog').for(receiver)
end
+
+ include_examples 'delivery to non functional user'
end
describe 'follow_request' do
@@ -108,14 +103,16 @@ RSpec.describe NotificationMailer do
let(:mail) { prepared_mailer_for(receiver.account).follow_request }
include_examples 'localized subject', 'notification_mailer.follow_request.subject', name: 'bob'
- include_examples 'standard headers', 'follow_request'
it 'renders the email' do
expect(mail)
.to be_present
.and(have_subject('Pending follower: bob'))
.and(have_body_text('bob has requested to follow you'))
+ .and have_standard_headers('follow_request').for(receiver)
end
+
+ include_examples 'delivery to non functional user'
end
private
diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb
index 5a8c293740..0257465817 100644
--- a/spec/mailers/user_mailer_spec.rb
+++ b/spec/mailers/user_mailer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe UserMailer do
+RSpec.describe UserMailer do
let(:receiver) { Fabricate(:user) }
describe '#confirmation_instructions' do
diff --git a/spec/models/account_alias_spec.rb b/spec/models/account_alias_spec.rb
new file mode 100644
index 0000000000..fc8c6bd250
--- /dev/null
+++ b/spec/models/account_alias_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AccountAlias do
+ describe 'Normalizations' do
+ describe 'acct' do
+ it { is_expected.to normalize(:acct).from(' @username@domain ').to('username@domain') }
+ end
+ end
+end
diff --git a/spec/models/account_deletion_request_spec.rb b/spec/models/account_deletion_request_spec.rb
new file mode 100644
index 0000000000..7dbfbed12a
--- /dev/null
+++ b/spec/models/account_deletion_request_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AccountDeletionRequest do
+ describe 'Associations' do
+ it { is_expected.to belong_to(:account).required }
+ end
+
+ describe '#due_at' do
+ before { stub_const 'AccountDeletionRequest::DELAY_TO_DELETION', 1.day }
+
+ it 'returns time from created at with delay added' do
+ account_deletion_request = Fabricate :account_deletion_request, created_at: Date.current.at_midnight
+ expect(account_deletion_request.due_at)
+ .to be_within(0.1).of(Date.tomorrow.at_midnight)
+ end
+ end
+end
diff --git a/spec/models/account_filter_spec.rb b/spec/models/account_filter_spec.rb
index fa47b5954a..5cb7fa92d4 100644
--- a/spec/models/account_filter_spec.rb
+++ b/spec/models/account_filter_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe AccountFilter do
+RSpec.describe AccountFilter do
describe 'with empty params' do
it 'excludes instance actor by default' do
filter = described_class.new({})
diff --git a/spec/models/account_migration_spec.rb b/spec/models/account_migration_spec.rb
index 1f32c6082e..d658915ce3 100644
--- a/spec/models/account_migration_spec.rb
+++ b/spec/models/account_migration_spec.rb
@@ -3,6 +3,12 @@
require 'rails_helper'
RSpec.describe AccountMigration do
+ describe 'Normalizations' do
+ describe 'acct' do
+ it { is_expected.to normalize(:acct).from(' @username@domain ').to('username@domain') }
+ end
+ end
+
describe 'validations' do
subject { described_class.new(account: source_account, acct: target_acct) }
diff --git a/spec/models/account_moderation_note_spec.rb b/spec/models/account_moderation_note_spec.rb
new file mode 100644
index 0000000000..079774c492
--- /dev/null
+++ b/spec/models/account_moderation_note_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AccountModerationNote do
+ describe 'chronological scope' do
+ it 'returns account moderation notes oldest to newest' do
+ account = Fabricate(:account)
+ note1 = Fabricate(:account_moderation_note, target_account: account)
+ note2 = Fabricate(:account_moderation_note, target_account: account)
+
+ expect(account.targeted_moderation_notes.chronological).to eq [note1, note2]
+ end
+ end
+
+ describe 'validations' do
+ it 'is invalid if the content is empty' do
+ report = Fabricate.build(:account_moderation_note, content: '')
+ expect(report.valid?).to be false
+ end
+
+ it 'is invalid if content is longer than character limit' do
+ report = Fabricate.build(:account_moderation_note, content: comment_over_limit)
+ expect(report.valid?).to be false
+ end
+
+ def comment_over_limit
+ Faker::Lorem.paragraph_by_chars(number: described_class::CONTENT_SIZE_LIMIT * 2)
+ end
+ end
+end
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
index 8e5648a0b0..a8f6ed7493 100644
--- a/spec/models/account_spec.rb
+++ b/spec/models/account_spec.rb
@@ -3,15 +3,46 @@
require 'rails_helper'
RSpec.describe Account do
+ include_examples 'Reviewable'
+
context 'with an account record' do
subject { Fabricate(:account) }
let(:bob) { Fabricate(:account, username: 'bob') }
+ describe '#suspended_locally?' do
+ context 'when the account is not suspended' do
+ it 'returns false' do
+ expect(subject.suspended_locally?).to be false
+ end
+ end
+
+ context 'when the account is suspended locally' do
+ before do
+ subject.update!(suspended_at: 1.day.ago, suspension_origin: :local)
+ end
+
+ it 'returns true' do
+ expect(subject.suspended_locally?).to be true
+ end
+ end
+
+ context 'when the account is suspended remotely' do
+ before do
+ subject.update!(suspended_at: 1.day.ago, suspension_origin: :remote)
+ end
+
+ it 'returns false' do
+ expect(subject.suspended_locally?).to be false
+ end
+ end
+ end
+
describe '#suspend!' do
it 'marks the account as suspended and creates a deletion request' do
expect { subject.suspend! }
.to change(subject, :suspended?).from(false).to(true)
+ .and change(subject, :suspended_locally?).from(false).to(true)
.and(change { AccountDeletionRequest.exists?(account: subject) }.from(false).to(true))
end
@@ -721,17 +752,82 @@ RSpec.describe Account do
end
end
- describe 'validations' do
- it 'is invalid without a username' do
- account = Fabricate.build(:account, username: nil)
- account.valid?
- expect(account).to model_have_error_on_field(:username)
+ describe '#prepare_contents' do
+ subject { Fabricate.build :account, domain: domain, note: ' padded note ', display_name: ' padded name ' }
+
+ context 'with local account' do
+ let(:domain) { nil }
+
+ it 'strips values' do
+ expect { subject.valid? }
+ .to change(subject, :note).to('padded note')
+ .and(change(subject, :display_name).to('padded name'))
+ end
end
- it 'squishes the username before validation' do
- account = Fabricate(:account, domain: nil, username: " \u3000bob \t \u00a0 \n ")
- expect(account.username).to eq 'bob'
+ context 'with remote account' do
+ let(:domain) { 'host.example' }
+
+ it 'preserves values' do
+ expect { subject.valid? }
+ .to not_change(subject, :note)
+ .and(not_change(subject, :display_name))
+ end
end
+ end
+
+ describe '#can_be_attributed_from?' do
+ subject { Fabricate(:account, attribution_domains: %w(example.com)) }
+
+ it 'returns true for a matching domain' do
+ expect(subject.can_be_attributed_from?('example.com')).to be true
+ end
+
+ it 'returns true for a subdomain of a domain' do
+ expect(subject.can_be_attributed_from?('foo.example.com')).to be true
+ end
+
+ it 'returns false for a non-matching domain' do
+ expect(subject.can_be_attributed_from?('hoge.com')).to be false
+ end
+ end
+
+ describe '#attribution_domains_as_text=' do
+ subject { Fabricate(:account) }
+
+ it 'sets attribution_domains accordingly' do
+ subject.attribution_domains_as_text = "hoge.com\nexample.com"
+
+ expect(subject.attribution_domains).to contain_exactly('hoge.com', 'example.com')
+ end
+
+ it 'strips leading "*."' do
+ subject.attribution_domains_as_text = "hoge.com\n*.example.com"
+
+ expect(subject.attribution_domains).to contain_exactly('hoge.com', 'example.com')
+ end
+
+ it 'strips the protocol if present' do
+ subject.attribution_domains_as_text = "http://hoge.com\nhttps://example.com"
+
+ expect(subject.attribution_domains).to contain_exactly('hoge.com', 'example.com')
+ end
+
+ it 'strips a combination of leading "*." and protocol' do
+ subject.attribution_domains_as_text = "http://*.hoge.com\nhttps://*.example.com"
+
+ expect(subject.attribution_domains).to contain_exactly('hoge.com', 'example.com')
+ end
+ end
+
+ describe 'Normalizations' do
+ describe 'username' do
+ it { is_expected.to normalize(:username).from(" \u3000bob \t \u00a0 \n ").to('bob') }
+ end
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:username) }
context 'when is local' do
it 'is invalid if the username is not unique in case-insensitive comparison among local accounts' do
diff --git a/spec/models/account_warning_preset_spec.rb b/spec/models/account_warning_preset_spec.rb
index f171df7c97..e7a9855175 100644
--- a/spec/models/account_warning_preset_spec.rb
+++ b/spec/models/account_warning_preset_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe AccountWarningPreset do
+RSpec.describe AccountWarningPreset do
describe 'alphabetical' do
let(:first) { Fabricate(:account_warning_preset, title: 'aaa', text: 'aaa') }
let(:second) { Fabricate(:account_warning_preset, title: 'bbb', text: 'aaa') }
diff --git a/spec/models/account_warning_spec.rb b/spec/models/account_warning_spec.rb
new file mode 100644
index 0000000000..37866ce3da
--- /dev/null
+++ b/spec/models/account_warning_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe AccountWarning do
+ describe 'Normalizations' do
+ describe 'text' do
+ it { is_expected.to normalize(:text).from(nil).to('') }
+ end
+ end
+end
diff --git a/spec/models/admin/appeal_filter_spec.rb b/spec/models/admin/appeal_filter_spec.rb
index e840bc3bc1..8303e58ad6 100644
--- a/spec/models/admin/appeal_filter_spec.rb
+++ b/spec/models/admin/appeal_filter_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::AppealFilter do
+RSpec.describe Admin::AppealFilter do
describe '#results' do
let(:approved_appeal) { Fabricate(:appeal, approved_at: 10.days.ago) }
let(:not_approved_appeal) { Fabricate(:appeal, approved_at: nil) }
diff --git a/spec/models/admin/tag_filter_spec.rb b/spec/models/admin/tag_filter_spec.rb
index 21dc28affb..1baae117b8 100644
--- a/spec/models/admin/tag_filter_spec.rb
+++ b/spec/models/admin/tag_filter_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::TagFilter do
+RSpec.describe Admin::TagFilter do
describe 'with invalid params' do
it 'raises with key error' do
filter = described_class.new(wrong: true)
diff --git a/spec/models/announcement_spec.rb b/spec/models/announcement_spec.rb
index 1e7283ca77..8bd1e74b29 100644
--- a/spec/models/announcement_spec.rb
+++ b/spec/models/announcement_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Announcement do
+RSpec.describe Announcement do
describe 'Scopes' do
context 'with published and unpublished records' do
let!(:published) { Fabricate(:announcement, published: true) }
@@ -64,14 +64,7 @@ describe Announcement do
end
describe 'Validations' do
- describe 'text' do
- it 'validates presence of attribute' do
- record = Fabricate.build(:announcement, text: nil)
-
- expect(record).to_not be_valid
- expect(record.errors[:text]).to be_present
- end
- end
+ it { is_expected.to validate_presence_of(:text) }
describe 'ends_at' do
it 'validates presence when starts_at is present' do
diff --git a/spec/models/appeal_spec.rb b/spec/models/appeal_spec.rb
index 13ca3a2d90..7e324582ed 100644
--- a/spec/models/appeal_spec.rb
+++ b/spec/models/appeal_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Appeal do
+RSpec.describe Appeal do
describe 'Validations' do
it 'validates text length is under limit' do
appeal = Fabricate.build(
diff --git a/spec/models/block_spec.rb b/spec/models/block_spec.rb
index 8249503c59..84f0f318f4 100644
--- a/spec/models/block_spec.rb
+++ b/spec/models/block_spec.rb
@@ -4,17 +4,8 @@ require 'rails_helper'
RSpec.describe Block do
describe 'validations' do
- it 'is invalid without an account' do
- block = Fabricate.build(:block, account: nil)
- block.valid?
- expect(block).to model_have_error_on_field(:account)
- end
-
- it 'is invalid without a target_account' do
- block = Fabricate.build(:block, target_account: nil)
- block.valid?
- expect(block).to model_have_error_on_field(:target_account)
- end
+ it { is_expected.to belong_to(:account).required }
+ it { is_expected.to belong_to(:target_account).required }
end
it 'removes blocking cache after creation' do
diff --git a/spec/models/bookmark_spec.rb b/spec/models/bookmark_spec.rb
new file mode 100644
index 0000000000..e0d91000e7
--- /dev/null
+++ b/spec/models/bookmark_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Bookmark do
+ describe 'Associations' do
+ it { is_expected.to belong_to(:account).required }
+ it { is_expected.to belong_to(:status).required }
+ end
+
+ describe 'Validations' do
+ subject { Fabricate.build :bookmark }
+
+ it { is_expected.to validate_uniqueness_of(:status_id).scoped_to(:account_id) }
+ end
+
+ describe 'Callbacks' do
+ describe 'reblog statuses' do
+ context 'when status is not a reblog' do
+ let(:status) { Fabricate :status }
+
+ it 'keeps status set to assigned value' do
+ bookmark = Fabricate.build :bookmark, status: status
+
+ expect { bookmark.valid? }
+ .to_not change(bookmark, :status)
+ end
+ end
+
+ context 'when status is a reblog' do
+ let(:original) { Fabricate :status }
+ let(:status) { Fabricate :status, reblog: original }
+
+ it 'keeps status set to assigned value' do
+ bookmark = Fabricate.build :bookmark, status: status
+
+ expect { bookmark.valid? }
+ .to change(bookmark, :status).to(original)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/account/counters_spec.rb b/spec/models/concerns/account/counters_spec.rb
index ccac9e95de..bbbaa7d06c 100644
--- a/spec/models/concerns/account/counters_spec.rb
+++ b/spec/models/concerns/account/counters_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Account::Counters do
+RSpec.describe Account::Counters do
let!(:account) { Fabricate(:account) }
describe '#increment_count!' do
diff --git a/spec/models/concerns/account/finder_concern_spec.rb b/spec/models/concerns/account/finder_concern_spec.rb
index ab5149e987..b3fae56dfc 100644
--- a/spec/models/concerns/account/finder_concern_spec.rb
+++ b/spec/models/concerns/account/finder_concern_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Account::FinderConcern do
+RSpec.describe Account::FinderConcern do
describe 'local finders' do
let!(:account) { Fabricate(:account, username: 'Alice') }
diff --git a/spec/models/concerns/account/interactions_spec.rb b/spec/models/concerns/account/interactions_spec.rb
index 798a8672da..68f334cdba 100644
--- a/spec/models/concerns/account/interactions_spec.rb
+++ b/spec/models/concerns/account/interactions_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Account::Interactions do
+RSpec.describe Account::Interactions do
let(:account) { Fabricate(:account, username: 'account') }
let(:account_id) { account.id }
let(:account_ids) { [account_id] }
diff --git a/spec/models/concerns/account/statuses_search_spec.rb b/spec/models/concerns/account/statuses_search_spec.rb
index ab249d62d0..9488d42021 100644
--- a/spec/models/concerns/account/statuses_search_spec.rb
+++ b/spec/models/concerns/account/statuses_search_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Account::StatusesSearch do
+RSpec.describe Account::StatusesSearch do
let(:account) { Fabricate(:account, indexable: indexable) }
before do
diff --git a/spec/models/concerns/status/threading_concern_spec.rb b/spec/models/concerns/status/threading_concern_spec.rb
index 09fb218566..a13487c10a 100644
--- a/spec/models/concerns/status/threading_concern_spec.rb
+++ b/spec/models/concerns/status/threading_concern_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Status::ThreadingConcern do
+RSpec.describe Status::ThreadingConcern do
describe '#ancestors' do
let!(:alice) { Fabricate(:account, username: 'alice') }
let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') }
diff --git a/spec/models/custom_emoji_category_spec.rb b/spec/models/custom_emoji_category_spec.rb
index 30de07bd81..2b414a66ee 100644
--- a/spec/models/custom_emoji_category_spec.rb
+++ b/spec/models/custom_emoji_category_spec.rb
@@ -2,13 +2,8 @@
require 'rails_helper'
-describe CustomEmojiCategory do
+RSpec.describe CustomEmojiCategory do
describe 'validations' do
- it 'validates name presence' do
- record = described_class.new(name: nil)
-
- expect(record).to_not be_valid
- expect(record).to model_have_error_on_field(:name)
- end
+ it { is_expected.to validate_presence_of(:name) }
end
end
diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb
index cb8cb5c11b..f812cf7584 100644
--- a/spec/models/custom_emoji_spec.rb
+++ b/spec/models/custom_emoji_spec.rb
@@ -79,22 +79,18 @@ RSpec.describe CustomEmoji, :attachment_processing do
end
describe 'Normalizations' do
- describe 'downcase domain value' do
- context 'with a mixed case domain value' do
- it 'normalizes the value to downcased' do
- custom_emoji = Fabricate.build(:custom_emoji, domain: 'wWw.MaStOdOn.CoM')
-
- expect(custom_emoji.domain).to eq('www.mastodon.com')
- end
- end
-
- context 'with a nil domain value' do
- it 'leaves the value as nil' do
- custom_emoji = Fabricate.build(:custom_emoji, domain: nil)
-
- expect(custom_emoji.domain).to be_nil
- end
- end
+ describe 'domain' do
+ it { is_expected.to normalize(:domain).from('wWw.MaStOdOn.CoM').to('www.mastodon.com') }
+ it { is_expected.to normalize(:domain).from(nil).to(nil) }
end
end
+
+ describe 'Validations' do
+ subject { Fabricate.build :custom_emoji }
+
+ it { is_expected.to validate_uniqueness_of(:shortcode).scoped_to(:domain) }
+ it { is_expected.to validate_length_of(:shortcode).is_at_least(described_class::MINIMUM_SHORTCODE_SIZE) }
+ it { is_expected.to allow_values('cats').for(:shortcode) }
+ it { is_expected.to_not allow_values('@#$@#$', 'X').for(:shortcode) }
+ end
end
diff --git a/spec/models/custom_filter_spec.rb b/spec/models/custom_filter_spec.rb
index 8ac9dbb896..afbc420241 100644
--- a/spec/models/custom_filter_spec.rb
+++ b/spec/models/custom_filter_spec.rb
@@ -4,19 +4,8 @@ require 'rails_helper'
RSpec.describe CustomFilter do
describe 'Validations' do
- it 'requires presence of title' do
- record = described_class.new(title: '')
- record.valid?
-
- expect(record).to model_have_error_on_field(:title)
- end
-
- it 'requires presence of context' do
- record = described_class.new(context: nil)
- record.valid?
-
- expect(record).to model_have_error_on_field(:context)
- end
+ it { is_expected.to validate_presence_of(:title) }
+ it { is_expected.to validate_presence_of(:context) }
it 'requires non-empty of context' do
record = described_class.new(context: [])
@@ -34,10 +23,8 @@ RSpec.describe CustomFilter do
end
describe 'Normalizations' do
- it 'cleans up context values' do
- record = described_class.new(context: ['home', 'notifications', 'public ', ''])
-
- expect(record.context).to eq(%w(home notifications public))
+ describe 'context' do
+ it { is_expected.to normalize(:context).from(['home', 'notifications', 'public ', '']).to(%w(home notifications public)) }
end
end
end
diff --git a/spec/models/domain_allow_spec.rb b/spec/models/domain_allow_spec.rb
index 12504211a1..d8f438f07e 100644
--- a/spec/models/domain_allow_spec.rb
+++ b/spec/models/domain_allow_spec.rb
@@ -2,13 +2,9 @@
require 'rails_helper'
-describe DomainAllow do
+RSpec.describe DomainAllow do
describe 'Validations' do
- it 'is invalid without a domain' do
- domain_allow = Fabricate.build(:domain_allow, domain: nil)
- domain_allow.valid?
- expect(domain_allow).to model_have_error_on_field(:domain)
- end
+ it { is_expected.to validate_presence_of(:domain) }
it 'is invalid if the same normalized domain already exists' do
_domain_allow = Fabricate(:domain_allow, domain: 'にゃん')
diff --git a/spec/models/domain_block_spec.rb b/spec/models/domain_block_spec.rb
index d595441fd3..8278454cd7 100644
--- a/spec/models/domain_block_spec.rb
+++ b/spec/models/domain_block_spec.rb
@@ -4,11 +4,7 @@ require 'rails_helper'
RSpec.describe DomainBlock do
describe 'validations' do
- it 'is invalid without a domain' do
- domain_block = Fabricate.build(:domain_block, domain: nil)
- domain_block.valid?
- expect(domain_block).to model_have_error_on_field(:domain)
- end
+ it { is_expected.to validate_presence_of(:domain) }
it 'is invalid if the same normalized domain already exists' do
_domain_block = Fabricate(:domain_block, domain: 'にゃん')
diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb
index 75468898d2..06bf07ed78 100644
--- a/spec/models/export_spec.rb
+++ b/spec/models/export_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Export do
+RSpec.describe Export do
let(:account) { Fabricate(:account) }
let(:target_accounts) do
[{}, { username: 'one', domain: 'local.host' }].map(&method(:Fabricate).curry(2).call(:account))
diff --git a/spec/models/extended_description_spec.rb b/spec/models/extended_description_spec.rb
index ecc27c0f6d..368ca33f5b 100644
--- a/spec/models/extended_description_spec.rb
+++ b/spec/models/extended_description_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ExtendedDescription do
+RSpec.describe ExtendedDescription do
describe '.current' do
context 'with the default values' do
it 'makes a new instance' do
diff --git a/spec/models/featured_tag_spec.rb b/spec/models/featured_tag_spec.rb
new file mode 100644
index 0000000000..0f5ead8f97
--- /dev/null
+++ b/spec/models/featured_tag_spec.rb
@@ -0,0 +1,141 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe FeaturedTag do
+ describe 'Normalizations' do
+ describe 'name' do
+ it { is_expected.to normalize(:name).from(' #hashtag ').to('hashtag') }
+ end
+ end
+
+ describe 'Validations' do
+ context 'when account already has a featured tag' do
+ subject { Fabricate.build :featured_tag, account: account }
+
+ before { Fabricate :featured_tag, account: account, name: 'Test' }
+
+ let(:account) { Fabricate :account }
+
+ it { is_expected.to_not allow_value('Test').for(:name) }
+
+ context 'when account has hit limit' do
+ before { stub_const 'FeaturedTag::LIMIT', 1 }
+
+ context 'with a local account' do
+ let(:account) { Fabricate :account, domain: nil }
+
+ it { is_expected.to_not allow_value(account).for(:account).against(:base).with_message(I18n.t('featured_tags.errors.limit')) }
+ end
+
+ context 'with a remote account' do
+ let(:account) { Fabricate :account, domain: 'host.example' }
+
+ it { is_expected.to allow_value(account).for(:account) }
+ end
+ end
+ end
+ end
+
+ describe 'Callback to set the tag' do
+ context 'with no matching tag' do
+ it 'creates a new tag' do
+ expect { Fabricate :featured_tag, name: 'tag' }
+ .to change(Tag, :count).by(1)
+ end
+ end
+
+ context 'with a matching tag' do
+ it 'creates a new tag' do
+ tag = Fabricate :tag, name: 'tag'
+
+ expect { Fabricate :featured_tag, name: 'tag' }
+ .to_not change(Tag, :count)
+
+ expect(described_class.last.tag)
+ .to eq(tag)
+ end
+ end
+ end
+
+ describe 'Callback to set the stats' do
+ context 'when no statuses are relevant' do
+ it 'sets values to nil' do
+ featured_tag = Fabricate :featured_tag
+
+ expect(featured_tag)
+ .to have_attributes(
+ statuses_count: 0,
+ last_status_at: be_nil
+ )
+ end
+ end
+
+ context 'when some statuses are relevant' do
+ it 'sets values to nil' do
+ tag = Fabricate :tag, name: 'test'
+ status = Fabricate :status, visibility: :public, created_at: 10.days.ago
+ status.tags << tag
+
+ featured_tag = Fabricate :featured_tag, name: 'test', account: status.account
+
+ expect(featured_tag)
+ .to have_attributes(
+ statuses_count: 1,
+ last_status_at: be_within(0.1).of(status.created_at)
+ )
+ end
+ end
+ end
+
+ describe '#sign?' do
+ it { is_expected.to be_sign }
+ end
+
+ describe '#display_name' do
+ subject { Fabricate.build :featured_tag, name: name, tag: tag }
+
+ context 'with a name value present' do
+ let(:name) { 'Test' }
+ let(:tag) { nil }
+
+ it 'uses name value' do
+ expect(subject.display_name).to eq('Test')
+ end
+ end
+
+ context 'with a missing name value but a present tag' do
+ let(:name) { nil }
+ let(:tag) { Fabricate.build :tag, name: 'Tester' }
+
+ it 'uses name value' do
+ expect(subject.display_name).to eq('Tester')
+ end
+ end
+ end
+
+ describe '#increment' do
+ it 'increases the count and updates the last_status_at timestamp' do
+ featured_tag = Fabricate :featured_tag
+ timestamp = 5.days.ago
+
+ expect { featured_tag.increment(timestamp) }
+ .to change(featured_tag, :statuses_count).from(0).to(1)
+ .and change(featured_tag, :last_status_at).from(nil).to(be_within(0.1).of(timestamp))
+ end
+ end
+
+ describe '#decrement' do
+ it 'decreases the count and updates the last_status_at timestamp' do
+ tag = Fabricate :tag, name: 'test'
+ status = Fabricate :status, visibility: :public, created_at: 10.days.ago
+ status.tags << tag
+
+ featured_tag = Fabricate :featured_tag, name: 'test', account: status.account
+
+ expect { featured_tag.decrement(status.id) }
+ .to change(featured_tag, :statuses_count).from(1).to(0)
+ .and change(featured_tag, :last_status_at).to(nil)
+ end
+ end
+end
diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb
index 9aa172b2f2..f22bd6ea88 100644
--- a/spec/models/follow_spec.rb
+++ b/spec/models/follow_spec.rb
@@ -9,17 +9,8 @@ RSpec.describe Follow do
describe 'validations' do
subject { described_class.new(account: alice, target_account: bob, rate_limit: true) }
- it 'is invalid without an account' do
- follow = Fabricate.build(:follow, account: nil)
- follow.valid?
- expect(follow).to model_have_error_on_field(:account)
- end
-
- it 'is invalid without a target_account' do
- follow = Fabricate.build(:follow, target_account: nil)
- follow.valid?
- expect(follow).to model_have_error_on_field(:target_account)
- end
+ it { is_expected.to belong_to(:account).required }
+ it { is_expected.to belong_to(:target_account).required }
it 'is invalid if account already follows too many people' do
alice.update(following_count: FollowLimitValidator::LIMIT)
diff --git a/spec/models/form/admin_settings_spec.rb b/spec/models/form/admin_settings_spec.rb
index 0dc2d881ad..6080b9e081 100644
--- a/spec/models/form/admin_settings_spec.rb
+++ b/spec/models/form/admin_settings_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Form::AdminSettings do
+RSpec.describe Form::AdminSettings do
describe 'validations' do
describe 'site_contact_username' do
context 'with no accounts' do
diff --git a/spec/models/form/custom_emoji_batch_spec.rb b/spec/models/form/custom_emoji_batch_spec.rb
index abeada5d50..180c6abd23 100644
--- a/spec/models/form/custom_emoji_batch_spec.rb
+++ b/spec/models/form/custom_emoji_batch_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Form::CustomEmojiBatch do
+RSpec.describe Form::CustomEmojiBatch do
describe '#save' do
subject { described_class.new({ current_account: account }.merge(options)) }
diff --git a/spec/models/form/status_filter_batch_action_spec.rb b/spec/models/form/status_filter_batch_action_spec.rb
index f06a11cc8b..8ea9d7545e 100644
--- a/spec/models/form/status_filter_batch_action_spec.rb
+++ b/spec/models/form/status_filter_batch_action_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Form::StatusFilterBatchAction do
+RSpec.describe Form::StatusFilterBatchAction do
describe '#save!' do
it 'does nothing if status_filter_ids is empty' do
batch_action = described_class.new(status_filter_ids: [])
diff --git a/spec/models/import_spec.rb b/spec/models/import_spec.rb
index 10df5f8c0b..587e0a9d26 100644
--- a/spec/models/import_spec.rb
+++ b/spec/models/import_spec.rb
@@ -3,19 +3,8 @@
require 'rails_helper'
RSpec.describe Import do
- let(:account) { Fabricate(:account) }
- let(:type) { 'following' }
- let(:data) { attachment_fixture('imports.txt') }
-
- describe 'validations' do
- it 'is invalid without an type' do
- import = described_class.create(account: account, data: data)
- expect(import).to model_have_error_on_field(:type)
- end
-
- it 'is invalid without a data' do
- import = described_class.create(account: account, type: type)
- expect(import).to model_have_error_on_field(:data)
- end
+ describe 'Validations' do
+ it { is_expected.to validate_presence_of(:type) }
+ it { is_expected.to validate_presence_of(:data) }
end
end
diff --git a/spec/models/ip_block_spec.rb b/spec/models/ip_block_spec.rb
index 290b99b288..ac9f5db601 100644
--- a/spec/models/ip_block_spec.rb
+++ b/spec/models/ip_block_spec.rb
@@ -2,21 +2,10 @@
require 'rails_helper'
-describe IpBlock do
+RSpec.describe IpBlock do
describe 'validations' do
- it 'validates ip presence', :aggregate_failures do
- ip_block = described_class.new(ip: nil, severity: :no_access)
-
- expect(ip_block).to_not be_valid
- expect(ip_block).to model_have_error_on_field(:ip)
- end
-
- it 'validates severity presence', :aggregate_failures do
- ip_block = described_class.new(ip: '127.0.0.1', severity: nil)
-
- expect(ip_block).to_not be_valid
- expect(ip_block).to model_have_error_on_field(:severity)
- end
+ it { is_expected.to validate_presence_of(:ip) }
+ it { is_expected.to validate_presence_of(:severity) }
it 'validates ip uniqueness', :aggregate_failures do
described_class.create!(ip: '127.0.0.1', severity: :no_access)
diff --git a/spec/models/list_account_spec.rb b/spec/models/list_account_spec.rb
new file mode 100644
index 0000000000..b2ec17a563
--- /dev/null
+++ b/spec/models/list_account_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe ListAccount do
+ describe 'Callbacks to set follows' do
+ context 'when list owner follows account' do
+ let!(:follow) { Fabricate :follow }
+ let(:list) { Fabricate :list, account: follow.account }
+
+ it 'finds and sets the follow with the list account' do
+ list_account = Fabricate :list_account, list: list, account: follow.target_account
+ expect(list_account)
+ .to have_attributes(
+ follow: eq(follow),
+ follow_request: be_nil
+ )
+ end
+ end
+
+ context 'when list owner has a follow request for account' do
+ let!(:follow_request) { Fabricate :follow_request }
+ let(:list) { Fabricate :list, account: follow_request.account }
+
+ it 'finds and sets the follow request with the list account' do
+ list_account = Fabricate :list_account, list: list, account: follow_request.target_account
+ expect(list_account)
+ .to have_attributes(
+ follow: be_nil,
+ follow_request: eq(follow_request)
+ )
+ end
+ end
+
+ context 'when list owner is the account' do
+ it 'does not set follow or follow request' do
+ list_account = Fabricate :list_account
+ expect(list_account)
+ .to have_attributes(
+ follow: be_nil,
+ follow_request: be_nil
+ )
+ end
+ end
+ end
+end
diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb
new file mode 100644
index 0000000000..62a84dfebf
--- /dev/null
+++ b/spec/models/list_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe List do
+ describe 'Validations' do
+ subject { Fabricate.build :list }
+
+ it { is_expected.to validate_presence_of(:title) }
+
+ context 'when account has hit max list limit' do
+ let(:account) { Fabricate :account }
+
+ before { stub_const 'List::PER_ACCOUNT_LIMIT', 0 }
+
+ context 'when creating a new list' do
+ it { is_expected.to_not allow_value(account).for(:account).against(:base).with_message(I18n.t('lists.errors.limit')) }
+ end
+
+ context 'when updating an existing list' do
+ before { subject.save(validate: false) }
+
+ it { is_expected.to allow_value(account).for(:account).against(:base) }
+ end
+ end
+ end
+end
diff --git a/spec/models/marker_spec.rb b/spec/models/marker_spec.rb
index 51dd584388..1da8eb6f43 100644
--- a/spec/models/marker_spec.rb
+++ b/spec/models/marker_spec.rb
@@ -2,15 +2,8 @@
require 'rails_helper'
-describe Marker do
- describe 'validations' do
- describe 'timeline' do
- it 'must be included in valid list' do
- record = described_class.new(timeline: 'not real timeline')
-
- expect(record).to_not be_valid
- expect(record).to model_have_error_on_field(:timeline)
- end
- end
+RSpec.describe Marker do
+ describe 'Validations' do
+ it { is_expected.to validate_inclusion_of(:timeline).in_array(described_class::TIMELINES) }
end
end
diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb
index 50f8d00a54..5f91ae0967 100644
--- a/spec/models/media_attachment_spec.rb
+++ b/spec/models/media_attachment_spec.rb
@@ -257,12 +257,7 @@ RSpec.describe MediaAttachment, :attachment_processing do
end
end
- it 'is invalid without file' do
- media = described_class.new
-
- expect(media.valid?).to be false
- expect(media).to model_have_error_on_field(:file)
- end
+ it { is_expected.to validate_presence_of(:file) }
describe 'size limit validation' do
it 'rejects video files that are too large' do
diff --git a/spec/models/mention_spec.rb b/spec/models/mention_spec.rb
index b241049a54..3a9b9fddf2 100644
--- a/spec/models/mention_spec.rb
+++ b/spec/models/mention_spec.rb
@@ -4,16 +4,7 @@ require 'rails_helper'
RSpec.describe Mention do
describe 'validations' do
- it 'is invalid without an account' do
- mention = Fabricate.build(:mention, account: nil)
- mention.valid?
- expect(mention).to model_have_error_on_field(:account)
- end
-
- it 'is invalid without a status' do
- mention = Fabricate.build(:mention, status: nil)
- mention.valid?
- expect(mention).to model_have_error_on_field(:status)
- end
+ it { is_expected.to belong_to(:account).required }
+ it { is_expected.to belong_to(:status).required }
end
end
diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb
index d498ee02a5..67c85b40f3 100644
--- a/spec/models/notification_spec.rb
+++ b/spec/models/notification_spec.rb
@@ -252,88 +252,83 @@ RSpec.describe Notification do
]
end
- context 'with a preloaded target status' do
- it 'preloads mention' do
- expect(subject[0].type).to eq :mention
- expect(subject[0].association(:mention)).to be_loaded
- expect(subject[0].mention.association(:status)).to be_loaded
+ context 'with a preloaded target status and a cached status' do
+ it 'preloads association records and replaces association records' do
+ expect(subject)
+ .to contain_exactly(
+ mention_attributes,
+ status_attributes,
+ reblog_attributes,
+ follow_attributes,
+ follow_request_attributes,
+ favourite_attributes,
+ poll_attributes
+ )
end
- it 'preloads status' do
- expect(subject[1].type).to eq :status
- expect(subject[1].association(:status)).to be_loaded
+ def mention_attributes
+ have_attributes(
+ type: :mention,
+ target_status: eq(mention.status).and(have_loaded_association(:account)),
+ mention: have_loaded_association(:status)
+ ).and(have_loaded_association(:mention))
end
- it 'preloads reblog' do
- expect(subject[2].type).to eq :reblog
- expect(subject[2].association(:status)).to be_loaded
- expect(subject[2].status.association(:reblog)).to be_loaded
+ def status_attributes
+ have_attributes(
+ type: :status,
+ target_status: eq(status).and(have_loaded_association(:account))
+ ).and(have_loaded_association(:status))
end
- it 'preloads follow as nil' do
- expect(subject[3].type).to eq :follow
- expect(subject[3].target_status).to be_nil
+ def reblog_attributes
+ have_attributes(
+ type: :reblog,
+ status: have_loaded_association(:reblog),
+ target_status: eq(reblog.reblog).and(have_loaded_association(:account))
+ ).and(have_loaded_association(:status))
end
- it 'preloads follow_request as nill' do
- expect(subject[4].type).to eq :follow_request
- expect(subject[4].target_status).to be_nil
+ def follow_attributes
+ have_attributes(
+ type: :follow,
+ target_status: be_nil
+ )
end
- it 'preloads favourite' do
- expect(subject[5].type).to eq :favourite
- expect(subject[5].association(:favourite)).to be_loaded
- expect(subject[5].favourite.association(:status)).to be_loaded
+ def follow_request_attributes
+ have_attributes(
+ type: :follow_request,
+ target_status: be_nil
+ )
end
- it 'preloads poll' do
- expect(subject[6].type).to eq :poll
- expect(subject[6].association(:poll)).to be_loaded
- expect(subject[6].poll.association(:status)).to be_loaded
- end
- end
-
- context 'with a cached status' do
- it 'replaces mention' do
- expect(subject[0].type).to eq :mention
- expect(subject[0].target_status.association(:account)).to be_loaded
- expect(subject[0].target_status).to eq mention.status
+ def favourite_attributes
+ have_attributes(
+ type: :favourite,
+ favourite: have_loaded_association(:status),
+ target_status: eq(favourite.status).and(have_loaded_association(:account))
+ ).and(have_loaded_association(:favourite))
end
- it 'replaces status' do
- expect(subject[1].type).to eq :status
- expect(subject[1].target_status.association(:account)).to be_loaded
- expect(subject[1].target_status).to eq status
- end
-
- it 'replaces reblog' do
- expect(subject[2].type).to eq :reblog
- expect(subject[2].target_status.association(:account)).to be_loaded
- expect(subject[2].target_status).to eq reblog.reblog
- end
-
- it 'replaces follow' do
- expect(subject[3].type).to eq :follow
- expect(subject[3].target_status).to be_nil
- end
-
- it 'replaces follow_request' do
- expect(subject[4].type).to eq :follow_request
- expect(subject[4].target_status).to be_nil
- end
-
- it 'replaces favourite' do
- expect(subject[5].type).to eq :favourite
- expect(subject[5].target_status.association(:account)).to be_loaded
- expect(subject[5].target_status).to eq favourite.status
- end
-
- it 'replaces poll' do
- expect(subject[6].type).to eq :poll
- expect(subject[6].target_status.association(:account)).to be_loaded
- expect(subject[6].target_status).to eq poll.status
+ def poll_attributes
+ have_attributes(
+ type: :poll,
+ poll: have_loaded_association(:status),
+ target_status: eq(poll.status).and(have_loaded_association(:account))
+ ).and(have_loaded_association(:poll))
end
end
end
end
end
+
+RSpec::Matchers.define :have_loaded_association do |association|
+ match do |record|
+ record.association(association).loaded?
+ end
+
+ failure_message do |record|
+ "expected #{record} to have loaded association #{association} but it did not."
+ end
+end
diff --git a/spec/models/one_time_key_spec.rb b/spec/models/one_time_key_spec.rb
deleted file mode 100644
index 6ff7ffc5c1..0000000000
--- a/spec/models/one_time_key_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe OneTimeKey do
- describe 'validations' do
- context 'with an invalid signature' do
- let(:one_time_key) { Fabricate.build(:one_time_key, signature: 'wrong!') }
-
- it 'is invalid' do
- expect(one_time_key).to_not be_valid
- end
- end
-
- context 'with an invalid key' do
- let(:one_time_key) { Fabricate.build(:one_time_key, key: 'wrong!') }
-
- it 'is invalid' do
- expect(one_time_key).to_not be_valid
- end
- end
- end
-end
diff --git a/spec/models/poll_spec.rb b/spec/models/poll_spec.rb
index ebcc459078..736f3615d0 100644
--- a/spec/models/poll_spec.rb
+++ b/spec/models/poll_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Poll do
+RSpec.describe Poll do
describe 'scopes' do
let(:status) { Fabricate(:status) }
let(:attached_poll) { Fabricate(:poll, status: status) }
@@ -32,12 +32,9 @@ describe Poll do
describe 'validations' do
context 'when not valid' do
- let(:poll) { Fabricate.build(:poll, expires_at: nil) }
+ subject { Fabricate.build(:poll) }
- it 'is invalid without an expire date' do
- poll.valid?
- expect(poll).to model_have_error_on_field(:expires_at)
- end
+ it { is_expected.to validate_presence_of(:expires_at) }
end
end
end
diff --git a/spec/models/preview_card_provider_spec.rb b/spec/models/preview_card_provider_spec.rb
index 7425b93946..a3bd4f49ad 100644
--- a/spec/models/preview_card_provider_spec.rb
+++ b/spec/models/preview_card_provider_spec.rb
@@ -2,7 +2,9 @@
require 'rails_helper'
-describe PreviewCardProvider do
+RSpec.describe PreviewCardProvider do
+ include_examples 'Reviewable'
+
describe 'scopes' do
let(:trendable_and_reviewed) { Fabricate(:preview_card_provider, trendable: true, reviewed_at: 5.days.ago) }
let(:not_trendable_and_not_reviewed) { Fabricate(:preview_card_provider, trendable: false, reviewed_at: nil) }
@@ -22,21 +24,5 @@ describe PreviewCardProvider do
expect(results).to eq([not_trendable_and_not_reviewed])
end
end
-
- describe 'reviewed' do
- it 'returns the relevant records' do
- results = described_class.reviewed
-
- expect(results).to eq([trendable_and_reviewed])
- end
- end
-
- describe 'pending_review' do
- it 'returns the relevant records' do
- results = described_class.pending_review
-
- expect(results).to eq([not_trendable_and_not_reviewed])
- end
- end
end
end
diff --git a/spec/models/preview_card_spec.rb b/spec/models/preview_card_spec.rb
index a17c7532e9..c0bc2b6e0e 100644
--- a/spec/models/preview_card_spec.rb
+++ b/spec/models/preview_card_spec.rb
@@ -2,7 +2,13 @@
require 'rails_helper'
-describe PreviewCard do
+RSpec.describe PreviewCard do
+ describe 'file size limit', :attachment_processing do
+ it 'is set differently whether vips is enabled or not' do
+ expect(described_class::LIMIT).to eq(Rails.configuration.x.use_vips ? 8.megabytes : 2.megabytes)
+ end
+ end
+
describe 'validations' do
describe 'urls' do
it 'allows http schemes' do
diff --git a/spec/models/privacy_policy_spec.rb b/spec/models/privacy_policy_spec.rb
index 03bbe7264b..742cac8e18 100644
--- a/spec/models/privacy_policy_spec.rb
+++ b/spec/models/privacy_policy_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe PrivacyPolicy do
+RSpec.describe PrivacyPolicy do
describe '.current' do
context 'with the default values' do
it 'has the privacy text' do
diff --git a/spec/models/relationship_filter_spec.rb b/spec/models/relationship_filter_spec.rb
index fccd42aaad..b56da91f8d 100644
--- a/spec/models/relationship_filter_spec.rb
+++ b/spec/models/relationship_filter_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RelationshipFilter do
+RSpec.describe RelationshipFilter do
let(:account) { Fabricate(:account) }
describe '#results' do
diff --git a/spec/models/relay_spec.rb b/spec/models/relay_spec.rb
new file mode 100644
index 0000000000..4b95c596e4
--- /dev/null
+++ b/spec/models/relay_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Relay do
+ describe 'Normalizations' do
+ describe 'inbox_url' do
+ it { is_expected.to normalize(:inbox_url).from(' http://host.example ').to('http://host.example') }
+ end
+ end
+end
diff --git a/spec/models/report_filter_spec.rb b/spec/models/report_filter_spec.rb
index 6baf0ea421..8668eb3d10 100644
--- a/spec/models/report_filter_spec.rb
+++ b/spec/models/report_filter_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ReportFilter do
+RSpec.describe ReportFilter do
describe 'with empty params' do
it 'defaults to unresolved reports list' do
filter = described_class.new({})
diff --git a/spec/models/report_note_spec.rb b/spec/models/report_note_spec.rb
new file mode 100644
index 0000000000..417971c9a1
--- /dev/null
+++ b/spec/models/report_note_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe ReportNote do
+ describe 'chronological scope' do
+ it 'returns report notes oldest to newest' do
+ report = Fabricate(:report)
+ note1 = Fabricate(:report_note, report: report)
+ note2 = Fabricate(:report_note, report: report)
+
+ expect(report.notes.chronological).to eq [note1, note2]
+ end
+ end
+
+ describe 'validations' do
+ it 'is invalid if the content is empty' do
+ report = Fabricate.build(:report_note, content: '')
+ expect(report.valid?).to be false
+ end
+
+ it 'is invalid if content is longer than character limit' do
+ report = Fabricate.build(:report_note, content: comment_over_limit)
+ expect(report.valid?).to be false
+ end
+
+ def comment_over_limit
+ Faker::Lorem.paragraph_by_chars(number: described_class::CONTENT_SIZE_LIMIT * 2)
+ end
+ end
+end
diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb
index d01d37bd8b..a0e4f6fafd 100644
--- a/spec/models/report_spec.rb
+++ b/spec/models/report_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Report do
+RSpec.describe Report do
describe 'statuses' do
it 'returns the statuses for the report' do
status = Fabricate(:status)
diff --git a/spec/models/rule_spec.rb b/spec/models/rule_spec.rb
index c9b9c55028..375483e0db 100644
--- a/spec/models/rule_spec.rb
+++ b/spec/models/rule_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Rule do
+RSpec.describe Rule do
describe 'scopes' do
describe 'ordered' do
let(:deleted_rule) { Fabricate(:rule, deleted_at: 10.days.ago) }
diff --git a/spec/models/status_edit_spec.rb b/spec/models/status_edit_spec.rb
index 2d33514522..7a469b44dc 100644
--- a/spec/models/status_edit_spec.rb
+++ b/spec/models/status_edit_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe StatusEdit do
+RSpec.describe StatusEdit do
describe '#reblog?' do
it 'returns false' do
record = described_class.new
diff --git a/spec/models/tag_feed_spec.rb b/spec/models/tag_feed_spec.rb
index 82d5af0f02..939b9f3e82 100644
--- a/spec/models/tag_feed_spec.rb
+++ b/spec/models/tag_feed_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe TagFeed do
+RSpec.describe TagFeed do
describe '#get' do
let(:account) { Fabricate(:account) }
let(:tag_cats) { Fabricate(:tag, name: 'cats') }
diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb
index ff0a055113..18dd26be94 100644
--- a/spec/models/tag_spec.rb
+++ b/spec/models/tag_spec.rb
@@ -3,6 +3,8 @@
require 'rails_helper'
RSpec.describe Tag do
+ include_examples 'Reviewable'
+
describe 'validations' do
it 'invalid with #' do
expect(described_class.new(name: '#hello_world')).to_not be_valid
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 0f3e25576e..d28e6658f1 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -4,6 +4,8 @@ require 'rails_helper'
require 'devise_two_factor/spec_helpers'
RSpec.describe User do
+ subject { described_class.new(account: account) }
+
let(:password) { 'abcd1234' }
let(:account) { Fabricate(:account, username: 'alice') }
@@ -32,11 +34,7 @@ RSpec.describe User do
end
describe 'validations' do
- it 'is invalid without an account' do
- user = Fabricate.build(:user, account: nil)
- user.valid?
- expect(user).to model_have_error_on_field(:account)
- end
+ it { is_expected.to belong_to(:account).required }
it 'is invalid without a valid email' do
user = Fabricate.build(:user, email: 'john@')
@@ -59,45 +57,18 @@ RSpec.describe User do
describe 'Normalizations' do
describe 'locale' do
- it 'preserves valid locale' do
- user = Fabricate.build(:user, locale: 'en')
-
- expect(user.locale).to eq('en')
- end
-
- it 'cleans out invalid locale' do
- user = Fabricate.build(:user, locale: 'toto')
-
- expect(user.locale).to be_nil
- end
+ it { is_expected.to_not normalize(:locale).from('en') }
+ it { is_expected.to normalize(:locale).from('toto').to(nil) }
end
describe 'time_zone' do
- it 'preserves valid timezone' do
- user = Fabricate.build(:user, time_zone: 'UTC')
-
- expect(user.time_zone).to eq('UTC')
- end
-
- it 'cleans out invalid timezone' do
- user = Fabricate.build(:user, time_zone: 'toto')
-
- expect(user.time_zone).to be_nil
- end
+ it { is_expected.to_not normalize(:time_zone).from('UTC') }
+ it { is_expected.to normalize(:time_zone).from('toto').to(nil) }
end
- describe 'languages' do
- it 'preserves valid options for languages' do
- user = Fabricate.build(:user, chosen_languages: ['en', 'fr', ''])
-
- expect(user.chosen_languages).to eq(['en', 'fr'])
- end
-
- it 'cleans out empty string from languages' do
- user = Fabricate.build(:user, chosen_languages: [''])
-
- expect(user.chosen_languages).to be_nil
- end
+ describe 'chosen_languages' do
+ it { is_expected.to normalize(:chosen_languages).from(['en', 'fr', '']).to(%w(en fr)) }
+ it { is_expected.to normalize(:chosen_languages).from(['']).to(nil) }
end
end
@@ -463,7 +434,9 @@ RSpec.describe User do
end
describe '#reset_password!' do
- subject(:user) { Fabricate(:user, password: 'foobar12345') }
+ subject(:user) { Fabricate(:user, password: original_password) }
+
+ let(:original_password) { 'foobar12345' }
let!(:session_activation) { Fabricate(:session_activation, user: user) }
let!(:access_token) { Fabricate(:access_token, resource_owner_id: user.id) }
@@ -471,31 +444,40 @@ RSpec.describe User do
let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) }
- before do
- allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub)
- user.reset_password!
+ before { stub_redis }
+
+ it 'changes the password immediately and revokes related access' do
+ expect { user.reset_password! }
+ .to remove_activated_sessions
+ .and remove_active_user_tokens
+ .and remove_user_web_subscriptions
+
+ expect(user)
+ .to_not be_external_or_valid_password(original_password)
+ expect { session_activation.reload }
+ .to raise_error(ActiveRecord::RecordNotFound)
+ expect { web_push_subscription.reload }
+ .to raise_error(ActiveRecord::RecordNotFound)
+ expect(redis_pipeline_stub)
+ .to have_received(:publish).with("timeline:access_token:#{access_token.id}", Oj.dump(event: :kill)).once
end
- it 'changes the password immediately' do
- expect(user.external_or_valid_password?('foobar12345')).to be false
+ def remove_activated_sessions
+ change(user.session_activations, :count).to(0)
end
- it 'deactivates all sessions' do
- expect(user.session_activations.count).to eq 0
- expect { session_activation.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ def remove_active_user_tokens
+ change { Doorkeeper::AccessToken.active_for(user).count }.to(0)
end
- it 'revokes all access tokens' do
- expect(Doorkeeper::AccessToken.active_for(user).count).to eq 0
+ def remove_user_web_subscriptions
+ change { Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count }.to(0)
end
- it 'revokes streaming access for all access tokens' do
- expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", Oj.dump(event: :kill)).once
- end
-
- it 'removes push subscriptions' do
- expect(Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count).to eq 0
- expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ def stub_redis
+ allow(redis)
+ .to receive(:pipelined)
+ .and_yield(redis_pipeline_stub)
end
end
diff --git a/spec/models/webauthn_credential_spec.rb b/spec/models/webauthn_credential_spec.rb
index 23f0229a67..c4105d9150 100644
--- a/spec/models/webauthn_credential_spec.rb
+++ b/spec/models/webauthn_credential_spec.rb
@@ -4,37 +4,10 @@ require 'rails_helper'
RSpec.describe WebauthnCredential do
describe 'validations' do
- it 'is invalid without an external id' do
- webauthn_credential = Fabricate.build(:webauthn_credential, external_id: nil)
-
- webauthn_credential.valid?
-
- expect(webauthn_credential).to model_have_error_on_field(:external_id)
- end
-
- it 'is invalid without a public key' do
- webauthn_credential = Fabricate.build(:webauthn_credential, public_key: nil)
-
- webauthn_credential.valid?
-
- expect(webauthn_credential).to model_have_error_on_field(:public_key)
- end
-
- it 'is invalid without a nickname' do
- webauthn_credential = Fabricate.build(:webauthn_credential, nickname: nil)
-
- webauthn_credential.valid?
-
- expect(webauthn_credential).to model_have_error_on_field(:nickname)
- end
-
- it 'is invalid without a sign_count' do
- webauthn_credential = Fabricate.build(:webauthn_credential, sign_count: nil)
-
- webauthn_credential.valid?
-
- expect(webauthn_credential).to model_have_error_on_field(:sign_count)
- end
+ it { is_expected.to validate_presence_of(:external_id) }
+ it { is_expected.to validate_presence_of(:public_key) }
+ it { is_expected.to validate_presence_of(:nickname) }
+ it { is_expected.to validate_presence_of(:sign_count) }
it 'is invalid if already exist a webauthn credential with the same external id' do
Fabricate(:webauthn_credential, external_id: '_Typ0ygudDnk9YUVWLQayw')
diff --git a/spec/models/webhook_spec.rb b/spec/models/webhook_spec.rb
index effaf92e9c..03ef1dcc68 100644
--- a/spec/models/webhook_spec.rb
+++ b/spec/models/webhook_spec.rb
@@ -6,12 +6,7 @@ RSpec.describe Webhook do
let(:webhook) { Fabricate(:webhook) }
describe 'Validations' do
- it 'requires presence of events' do
- record = described_class.new(events: nil)
- record.valid?
-
- expect(record).to model_have_error_on_field(:events)
- end
+ it { is_expected.to validate_presence_of(:events) }
it 'requires non-empty events value' do
record = described_class.new(events: [])
@@ -29,37 +24,35 @@ RSpec.describe Webhook do
end
describe 'Normalizations' do
- it 'cleans up events values' do
- record = described_class.new(events: ['account.approved', 'account.created ', ''])
-
- expect(record.events).to eq(%w(account.approved account.created))
+ describe 'events' do
+ it { is_expected.to normalize(:events).from(['account.approved', 'account.created ', '']).to(%w(account.approved account.created)) }
end
end
describe '#rotate_secret!' do
it 'changes the secret' do
- previous_value = webhook.secret
- webhook.rotate_secret!
- expect(webhook.secret).to_not be_blank
- expect(webhook.secret).to_not eq previous_value
+ expect { webhook.rotate_secret! }
+ .to change(webhook, :secret)
+ expect(webhook.secret)
+ .to_not be_blank
end
end
describe '#enable!' do
- before do
- webhook.disable!
- end
+ let(:webhook) { Fabricate(:webhook, enabled: false) }
it 'enables the webhook' do
- webhook.enable!
- expect(webhook.enabled?).to be true
+ expect { webhook.enable! }
+ .to change(webhook, :enabled?).to(true)
end
end
describe '#disable!' do
+ let(:webhook) { Fabricate(:webhook, enabled: true) }
+
it 'disables the webhook' do
- webhook.disable!
- expect(webhook.enabled?).to be false
+ expect { webhook.disable! }
+ .to change(webhook, :enabled?).to(false)
end
end
end
diff --git a/spec/policies/account_warning_preset_policy_spec.rb b/spec/policies/account_warning_preset_policy_spec.rb
index 63bf33de24..53e224f19f 100644
--- a/spec/policies/account_warning_preset_policy_spec.rb
+++ b/spec/policies/account_warning_preset_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe AccountWarningPresetPolicy do
+RSpec.describe AccountWarningPresetPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/admin/status_policy_spec.rb b/spec/policies/admin/status_policy_spec.rb
index af9f7716be..07af425516 100644
--- a/spec/policies/admin/status_policy_spec.rb
+++ b/spec/policies/admin/status_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe Admin::StatusPolicy do
+RSpec.describe Admin::StatusPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/announcement_policy_spec.rb b/spec/policies/announcement_policy_spec.rb
index 3d230b3cb4..503ffca6dc 100644
--- a/spec/policies/announcement_policy_spec.rb
+++ b/spec/policies/announcement_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe AnnouncementPolicy do
+RSpec.describe AnnouncementPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/appeal_policy_spec.rb b/spec/policies/appeal_policy_spec.rb
index d7498eb9f0..1bf8ce0a0d 100644
--- a/spec/policies/appeal_policy_spec.rb
+++ b/spec/policies/appeal_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe AppealPolicy do
+RSpec.describe AppealPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/canonical_email_block_policy_spec.rb b/spec/policies/canonical_email_block_policy_spec.rb
index 0e55febfa9..f5029d9e6b 100644
--- a/spec/policies/canonical_email_block_policy_spec.rb
+++ b/spec/policies/canonical_email_block_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe CanonicalEmailBlockPolicy do
+RSpec.describe CanonicalEmailBlockPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/delivery_policy_spec.rb b/spec/policies/delivery_policy_spec.rb
index fbcbf390d7..bb82389eec 100644
--- a/spec/policies/delivery_policy_spec.rb
+++ b/spec/policies/delivery_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe DeliveryPolicy do
+RSpec.describe DeliveryPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/follow_recommendation_policy_spec.rb b/spec/policies/follow_recommendation_policy_spec.rb
index 01f4da0be2..ae74d5c3a8 100644
--- a/spec/policies/follow_recommendation_policy_spec.rb
+++ b/spec/policies/follow_recommendation_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe FollowRecommendationPolicy do
+RSpec.describe FollowRecommendationPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/ip_block_policy_spec.rb b/spec/policies/ip_block_policy_spec.rb
index 3cfa85863c..97bc239e9a 100644
--- a/spec/policies/ip_block_policy_spec.rb
+++ b/spec/policies/ip_block_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe IpBlockPolicy do
+RSpec.describe IpBlockPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/preview_card_policy_spec.rb b/spec/policies/preview_card_policy_spec.rb
index d6675c5b34..a1944303e1 100644
--- a/spec/policies/preview_card_policy_spec.rb
+++ b/spec/policies/preview_card_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe PreviewCardPolicy do
+RSpec.describe PreviewCardPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/preview_card_provider_policy_spec.rb b/spec/policies/preview_card_provider_policy_spec.rb
index 8d3715de95..676039a1b7 100644
--- a/spec/policies/preview_card_provider_policy_spec.rb
+++ b/spec/policies/preview_card_provider_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe PreviewCardProviderPolicy do
+RSpec.describe PreviewCardProviderPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/rule_policy_spec.rb b/spec/policies/rule_policy_spec.rb
index 0e45f6df02..5d435e38c1 100644
--- a/spec/policies/rule_policy_spec.rb
+++ b/spec/policies/rule_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe RulePolicy do
+RSpec.describe RulePolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/policies/webhook_policy_spec.rb b/spec/policies/webhook_policy_spec.rb
index 909311461a..96aaae2c30 100644
--- a/spec/policies/webhook_policy_spec.rb
+++ b/spec/policies/webhook_policy_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
require 'pundit/rspec'
-describe WebhookPolicy do
+RSpec.describe WebhookPolicy do
let(:policy) { described_class }
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
diff --git a/spec/presenters/instance_presenter_spec.rb b/spec/presenters/instance_presenter_spec.rb
index ddf1ad2eb1..9dc9aa8f31 100644
--- a/spec/presenters/instance_presenter_spec.rb
+++ b/spec/presenters/instance_presenter_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe InstancePresenter do
+RSpec.describe InstancePresenter do
let(:instance_presenter) { described_class.new }
describe '#description' do
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
index d4b9bddf93..ee03b49bc6 100644
--- a/spec/rails_helper.rb
+++ b/spec/rails_helper.rb
@@ -21,6 +21,7 @@ unless ENV['DISABLE_SIMPLECOV'] == 'true'
add_group 'Libraries', 'lib'
add_group 'Policies', 'app/policies'
add_group 'Presenters', 'app/presenters'
+ add_group 'Search', 'app/chewy'
add_group 'Serializers', 'app/serializers'
add_group 'Services', 'app/services'
add_group 'Validators', 'app/validators'
@@ -44,7 +45,7 @@ require 'chewy/rspec'
require 'email_spec/rspec'
require 'test_prof/recipes/rspec/before_all'
-Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
+Rails.root.glob('spec/support/**/*.rb').each { |f| require f }
ActiveRecord::Migration.maintain_test_schema!
WebMock.disable_net_connect!(
@@ -55,6 +56,8 @@ Sidekiq.logger = nil
DatabaseCleaner.strategy = [:deletion]
+Chewy.settings[:enabled] = false
+
Devise::Test::ControllerHelpers.module_eval do
alias_method :original_sign_in, :sign_in
@@ -112,6 +115,7 @@ RSpec.configure do |config|
config.include ThreadingHelpers
config.include SignedRequestHelpers, type: :request
config.include CommandLineHelpers, type: :cli
+ config.include SystemHelpers, type: :system
config.around(:each, use_transactional_tests: false) do |example|
self.use_transactional_tests = false
@@ -128,6 +132,12 @@ RSpec.configure do |config|
example.run
end
+ config.around(:each, type: :search) do |example|
+ Chewy.settings[:enabled] = true
+ example.run
+ Chewy.settings[:enabled] = false
+ end
+
config.before :each, type: :cli do
stub_reset_connection_pools
end
@@ -138,10 +148,19 @@ RSpec.configure do |config|
config.before do |example|
unless example.metadata[:attachment_processing]
- allow_any_instance_of(Paperclip::Attachment).to receive(:post_process).and_return(true) # rubocop:disable RSpec/AnyInstance
+ # rubocop:disable RSpec/AnyInstance
+ allow_any_instance_of(Paperclip::Attachment).to receive(:post_process).and_return(true)
+ allow_any_instance_of(Paperclip::MediaTypeSpoofDetector).to receive(:spoofed?).and_return(false)
+ # rubocop:enable RSpec/AnyInstance
end
end
+ config.before :each, type: :request do
+ # Use https and configured hostname in request spec requests
+ integration_session.https!
+ host! Rails.configuration.x.local_domain
+ end
+
config.after do
Rails.cache.clear
redis.del(redis.keys)
@@ -176,5 +195,5 @@ def stub_reset_connection_pools
# TODO: Is there a better way to correctly run specs without stubbing this?
# (Avoids reset_connection_pools! in test env)
allow(ActiveRecord::Base).to receive(:establish_connection)
- allow(RedisConfiguration).to receive(:establish_pool)
+ allow(RedisConnection).to receive(:establish_pool)
end
diff --git a/spec/requests/account_show_page_spec.rb b/spec/requests/account_show_page_spec.rb
index 830d778608..7f3ea2595f 100644
--- a/spec/requests/account_show_page_spec.rb
+++ b/spec/requests/account_show_page_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'The account show page' do
+RSpec.describe 'The account show page' do
it 'has valid opengraph tags' do
alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
_status = Fabricate(:status, account: alice, text: 'Hello World')
@@ -14,18 +14,20 @@ describe 'The account show page' do
expect(head_meta_content('og:title')).to match alice.display_name
expect(head_meta_content('og:type')).to eq 'profile'
expect(head_meta_content('og:image')).to match '.+'
- expect(head_meta_content('og:url')).to match 'http://.+'
+ expect(head_meta_content('og:url')).to eq short_account_url(username: alice.username)
end
def head_link_icons
- head_section.css('link[rel=icon]')
+ response
+ .parsed_body
+ .search('html head link[rel=icon]')
end
def head_meta_content(property)
- head_section.meta("[@property='#{property}']")[:content]
- end
-
- def head_section
- Nokogiri::Slop(response.body).html.head
+ response
+ .parsed_body
+ .search("html head meta[property='#{property}']")
+ .attr('content')
+ .text
end
end
diff --git a/spec/requests/accounts_spec.rb b/spec/requests/accounts_spec.rb
index bf067cdc38..afd9ac80e2 100644
--- a/spec/requests/accounts_spec.rb
+++ b/spec/requests/accounts_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Accounts show response' do
+RSpec.describe 'Accounts show response' do
let(:account) { Fabricate(:account) }
context 'with an unapproved account' do
@@ -46,21 +46,6 @@ describe 'Accounts show response' do
describe 'GET to short username paths' do
context 'with existing statuses' do
- let!(:status) { Fabricate(:status, account: account) }
- let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) }
- let!(:status_self_reply) { Fabricate(:status, account: account, thread: status) }
- let!(:status_media) { Fabricate(:status, account: account) }
- let!(:status_pinned) { Fabricate(:status, account: account) }
- let!(:status_private) { Fabricate(:status, account: account, visibility: :private) }
- let!(:status_direct) { Fabricate(:status, account: account, visibility: :direct) }
- let!(:status_reblog) { Fabricate(:status, account: account, reblog: Fabricate(:status)) }
-
- before do
- status_media.media_attachments << Fabricate(:media_attachment, account: account, type: :image)
- account.pinned_statuses << status_pinned
- account.pinned_statuses << status_private
- end
-
context 'with HTML' do
let(:format) { 'html' }
@@ -69,8 +54,7 @@ describe 'Accounts show response' do
expect(response)
.to have_http_status(200)
.and render_template(:show)
-
- expect(response.headers['Link'].to_s).to include ActivityPub::TagManager.instance.uri_for(account)
+ .and have_http_link_header(ActivityPub::TagManager.instance.uri_for(account)).for(rel: 'alternate')
end
end
@@ -130,15 +114,14 @@ describe 'Accounts show response' do
it 'returns a JSON version of the account', :aggregate_failures do
expect(response)
.to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
.and have_attributes(
media_type: eq('application/activity+json')
)
- expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
+ expect(response.parsed_body).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
end
- it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
-
context 'with authorized fetch mode' do
let(:authorized_fetch_mode) { true }
@@ -165,7 +148,7 @@ describe 'Accounts show response' do
expect(response.headers['Cache-Control']).to include 'private'
- expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
+ expect(response.parsed_body).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
end
end
@@ -179,15 +162,14 @@ describe 'Accounts show response' do
it 'returns a JSON version of the account', :aggregate_failures do
expect(response)
.to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
.and have_attributes(
media_type: eq('application/activity+json')
)
- expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
+ expect(response.parsed_body).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
end
- it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
-
context 'with authorized fetch mode' do
let(:authorized_fetch_mode) { true }
@@ -201,7 +183,7 @@ describe 'Accounts show response' do
expect(response.headers['Cache-Control']).to include 'private'
expect(response.headers['Vary']).to include 'Signature'
- expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
+ expect(response.parsed_body).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
end
end
end
@@ -210,15 +192,30 @@ describe 'Accounts show response' do
context 'with RSS' do
let(:format) { 'rss' }
+ let!(:status) { Fabricate(:status, account: account) }
+ let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) }
+ let!(:status_self_reply) { Fabricate(:status, account: account, thread: status) }
+ let!(:status_media) { Fabricate(:status, account: account) }
+ let!(:status_pinned) { Fabricate(:status, account: account) }
+ let!(:status_private) { Fabricate(:status, account: account, visibility: :private) }
+ let!(:status_direct) { Fabricate(:status, account: account, visibility: :direct) }
+ let!(:status_reblog) { Fabricate(:status, account: account, reblog: Fabricate(:status)) }
+
+ before do
+ status_media.media_attachments << Fabricate(:media_attachment, account: account, type: :image)
+ account.pinned_statuses << status_pinned
+ account.pinned_statuses << status_private
+ end
+
context 'with a normal account in an RSS request' do
before do
get short_account_path(username: account.username, format: format)
end
- it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
-
it 'responds with correct statuses', :aggregate_failures do
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
expect(response.body).to include(status_tag_for(status_media))
expect(response.body).to include(status_tag_for(status_self_reply))
expect(response.body).to include(status_tag_for(status))
@@ -234,10 +231,11 @@ describe 'Accounts show response' do
get short_account_with_replies_path(username: account.username, format: format)
end
- it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
-
it 'responds with correct statuses with replies', :aggregate_failures do
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
+
expect(response.body).to include(status_tag_for(status_media))
expect(response.body).to include(status_tag_for(status_reply))
expect(response.body).to include(status_tag_for(status_self_reply))
@@ -253,10 +251,10 @@ describe 'Accounts show response' do
get short_account_media_path(username: account.username, format: format)
end
- it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
-
it 'responds with correct statuses with media', :aggregate_failures do
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
expect(response.body).to include(status_tag_for(status_media))
expect(response.body).to_not include(status_tag_for(status_direct))
expect(response.body).to_not include(status_tag_for(status_private))
@@ -277,10 +275,11 @@ describe 'Accounts show response' do
get short_account_tag_path(username: account.username, tag: tag, format: format)
end
- it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
-
it 'responds with correct statuses with a tag', :aggregate_failures do
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
+
expect(response.body).to include(status_tag_for(status_tag))
expect(response.body).to_not include(status_tag_for(status_direct))
expect(response.body).to_not include(status_tag_for(status_media))
diff --git a/spec/requests/anonymous_cookies_spec.rb b/spec/requests/anonymous_cookies_spec.rb
index 427f54e449..235dd46a63 100644
--- a/spec/requests/anonymous_cookies_spec.rb
+++ b/spec/requests/anonymous_cookies_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-context 'when visited anonymously' do
+RSpec.describe 'Anonymous visits' do
around do |example|
old = ActionController::Base.allow_forgery_protection
ActionController::Base.allow_forgery_protection = true
diff --git a/spec/requests/api/oembed_spec.rb b/spec/requests/api/oembed_spec.rb
new file mode 100644
index 0000000000..767f20dddf
--- /dev/null
+++ b/spec/requests/api/oembed_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'API OEmbed' do
+ describe 'GET /api/oembed' do
+ before { host! Rails.configuration.x.local_domain }
+
+ context 'when status is public' do
+ let(:status) { Fabricate(:status, visibility: :public) }
+
+ it 'returns success with private cache control headers' do
+ get '/api/oembed', params: { url: short_account_status_url(status.account, status) }
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.headers['Cache-Control'])
+ .to include('private, no-store')
+ end
+ end
+
+ context 'when status is not public' do
+ let(:status) { Fabricate(:status, visibility: :direct) }
+
+ it 'returns not found' do
+ get '/api/oembed', params: { url: short_account_status_url(status.account, status) }
+
+ expect(response)
+ .to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/v1/accounts/credentials_spec.rb b/spec/requests/api/v1/accounts/credentials_spec.rb
index ce5940d468..966d1f598e 100644
--- a/spec/requests/api/v1/accounts/credentials_spec.rb
+++ b/spec/requests/api/v1/accounts/credentials_spec.rb
@@ -20,7 +20,9 @@ RSpec.describe 'credentials API' do
expect(response)
.to have_http_status(200)
- expect(body_as_json).to include({
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to include({
source: hash_including({
discoverable: false,
indexable: false,
@@ -36,8 +38,10 @@ RSpec.describe 'credentials API' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json).to include({
+ expect(response.parsed_body).to include({
locked: true,
})
end
@@ -75,6 +79,8 @@ RSpec.describe 'credentials API' do
it 'returns http success' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -84,6 +90,8 @@ RSpec.describe 'credentials API' do
it 'returns http unprocessable entity' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -92,8 +100,10 @@ RSpec.describe 'credentials API' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json).to include({
+ expect(response.parsed_body).to include({
source: hash_including({
discoverable: true,
indexable: true,
diff --git a/spec/requests/api/v1/accounts/familiar_followers_spec.rb b/spec/requests/api/v1/accounts/familiar_followers_spec.rb
index fdc0a3a932..c698c2d689 100644
--- a/spec/requests/api/v1/accounts/familiar_followers_spec.rb
+++ b/spec/requests/api/v1/accounts/familiar_followers_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Accounts Familiar Followers API' do
+RSpec.describe 'Accounts Familiar Followers API' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:follows' }
@@ -14,6 +14,8 @@ describe 'Accounts Familiar Followers API' do
get '/api/v1/accounts/familiar_followers', params: { account_id: account.id, limit: 2 }, headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'when there are duplicate account IDs in the params' do
@@ -24,7 +26,7 @@ describe 'Accounts Familiar Followers API' do
account_ids = [account_a, account_b, account_b, account_a, account_a].map { |a| a.id.to_s }
get '/api/v1/accounts/familiar_followers', params: { id: account_ids }, headers: headers
- expect(body_as_json.pluck(:id)).to contain_exactly(account_a.id.to_s, account_b.id.to_s)
+ expect(response.parsed_body.pluck(:id)).to contain_exactly(account_a.id.to_s, account_b.id.to_s)
end
end
end
diff --git a/spec/requests/api/v1/accounts/featured_tags_spec.rb b/spec/requests/api/v1/accounts/featured_tags_spec.rb
index bae7d448b6..632db65c44 100644
--- a/spec/requests/api/v1/accounts/featured_tags_spec.rb
+++ b/spec/requests/api/v1/accounts/featured_tags_spec.rb
@@ -23,7 +23,9 @@ RSpec.describe 'account featured tags API' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to contain_exactly(a_hash_including({
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to contain_exactly(a_hash_including({
name: 'bar',
url: "https://cb6e6126.ngrok.io/@#{account.username}/tagged/bar",
}), a_hash_including({
@@ -37,7 +39,9 @@ RSpec.describe 'account featured tags API' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to contain_exactly(a_hash_including({
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to contain_exactly(a_hash_including({
name: 'bar',
url: "https://cb6e6126.ngrok.io/@#{account.pretty_acct}/tagged/bar",
}), a_hash_including({
diff --git a/spec/requests/api/v1/accounts/follower_accounts_spec.rb b/spec/requests/api/v1/accounts/follower_accounts_spec.rb
index 7ff92d6a48..61987fac1c 100644
--- a/spec/requests/api/v1/accounts/follower_accounts_spec.rb
+++ b/spec/requests/api/v1/accounts/follower_accounts_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Accounts FollowerAccounts' do
+RSpec.describe 'API V1 Accounts FollowerAccounts' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:accounts' }
@@ -21,8 +21,13 @@ describe 'API V1 Accounts FollowerAccounts' do
get "/api/v1/accounts/#{account.id}/followers", params: { limit: 2 }, headers: headers
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq 2
- expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: alice.id.to_s),
+ hash_including(id: bob.id.to_s)
+ )
end
it 'does not return blocked users', :aggregate_failures do
@@ -30,8 +35,12 @@ describe 'API V1 Accounts FollowerAccounts' do
get "/api/v1/accounts/#{account.id}/followers", params: { limit: 2 }, headers: headers
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq 1
- expect(body_as_json[0][:id]).to eq alice.id.to_s
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: alice.id.to_s)
+ )
end
context 'when requesting user is blocked' do
@@ -41,7 +50,7 @@ describe 'API V1 Accounts FollowerAccounts' do
it 'hides results' do
get "/api/v1/accounts/#{account.id}/followers", params: { limit: 2 }, headers: headers
- expect(body_as_json.size).to eq 0
+ expect(response.parsed_body.size).to eq 0
end
end
@@ -52,8 +61,11 @@ describe 'API V1 Accounts FollowerAccounts' do
account.mute!(bob)
get "/api/v1/accounts/#{account.id}/followers", params: { limit: 2 }, headers: headers
- expect(body_as_json.size).to eq 2
- expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: alice.id.to_s),
+ hash_including(id: bob.id.to_s)
+ )
end
end
end
diff --git a/spec/requests/api/v1/accounts/following_accounts_spec.rb b/spec/requests/api/v1/accounts/following_accounts_spec.rb
index b343a48654..aae811467d 100644
--- a/spec/requests/api/v1/accounts/following_accounts_spec.rb
+++ b/spec/requests/api/v1/accounts/following_accounts_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Accounts FollowingAccounts' do
+RSpec.describe 'API V1 Accounts FollowingAccounts' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:accounts' }
@@ -21,8 +21,13 @@ describe 'API V1 Accounts FollowingAccounts' do
get "/api/v1/accounts/#{account.id}/following", params: { limit: 2 }, headers: headers
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq 2
- expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: alice.id.to_s),
+ hash_including(id: bob.id.to_s)
+ )
end
it 'does not return blocked users', :aggregate_failures do
@@ -30,8 +35,12 @@ describe 'API V1 Accounts FollowingAccounts' do
get "/api/v1/accounts/#{account.id}/following", params: { limit: 2 }, headers: headers
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq 1
- expect(body_as_json[0][:id]).to eq alice.id.to_s
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: alice.id.to_s)
+ )
end
context 'when requesting user is blocked' do
@@ -41,7 +50,7 @@ describe 'API V1 Accounts FollowingAccounts' do
it 'hides results' do
get "/api/v1/accounts/#{account.id}/following", params: { limit: 2 }, headers: headers
- expect(body_as_json.size).to eq 0
+ expect(response.parsed_body.size).to eq 0
end
end
@@ -52,8 +61,11 @@ describe 'API V1 Accounts FollowingAccounts' do
account.mute!(bob)
get "/api/v1/accounts/#{account.id}/following", params: { limit: 2 }, headers: headers
- expect(body_as_json.size).to eq 2
- expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: alice.id.to_s),
+ hash_including(id: bob.id.to_s)
+ )
end
end
end
diff --git a/spec/requests/api/v1/accounts/identity_proofs_spec.rb b/spec/requests/api/v1/accounts/identity_proofs_spec.rb
index 3727af7e89..ba04ed45b9 100644
--- a/spec/requests/api/v1/accounts/identity_proofs_spec.rb
+++ b/spec/requests/api/v1/accounts/identity_proofs_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Accounts Identity Proofs API' do
+RSpec.describe 'Accounts Identity Proofs API' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:accounts' }
@@ -14,6 +14,8 @@ describe 'Accounts Identity Proofs API' do
get "/api/v1/accounts/#{account.id}/identity_proofs", params: { limit: 2 }, headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/accounts/lists_spec.rb b/spec/requests/api/v1/accounts/lists_spec.rb
index 48c0337e54..cb1ff6b9f2 100644
--- a/spec/requests/api/v1/accounts/lists_spec.rb
+++ b/spec/requests/api/v1/accounts/lists_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Accounts Lists API' do
+RSpec.describe 'Accounts Lists API' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:lists' }
@@ -20,6 +20,8 @@ describe 'Accounts Lists API' do
get "/api/v1/accounts/#{account.id}/lists", headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/accounts/lookup_spec.rb b/spec/requests/api/v1/accounts/lookup_spec.rb
index 4c022c7c13..77c09c0902 100644
--- a/spec/requests/api/v1/accounts/lookup_spec.rb
+++ b/spec/requests/api/v1/accounts/lookup_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Accounts Lookup API' do
+RSpec.describe 'Accounts Lookup API' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:accounts' }
@@ -14,6 +14,8 @@ describe 'Accounts Lookup API' do
get '/api/v1/accounts/lookup', params: { account_id: account.id, acct: account.acct }, headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/accounts/notes_spec.rb b/spec/requests/api/v1/accounts/notes_spec.rb
index 4f3ac68c74..1677ec07e3 100644
--- a/spec/requests/api/v1/accounts/notes_spec.rb
+++ b/spec/requests/api/v1/accounts/notes_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Accounts Notes API' do
+RSpec.describe 'Accounts Notes API' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'write:accounts' }
@@ -22,6 +22,8 @@ describe 'Accounts Notes API' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(AccountNote.find_by(account_id: user.account.id, target_account_id: account.id).comment).to eq comment
end
end
@@ -33,6 +35,8 @@ describe 'Accounts Notes API' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(AccountNote.where(account_id: user.account.id, target_account_id: account.id)).to_not exist
end
end
diff --git a/spec/requests/api/v1/accounts/pins_spec.rb b/spec/requests/api/v1/accounts/pins_spec.rb
index c293715f7e..8ebcb27d28 100644
--- a/spec/requests/api/v1/accounts/pins_spec.rb
+++ b/spec/requests/api/v1/accounts/pins_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Accounts Pins API' do
+RSpec.describe 'Accounts Pins API' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'write:accounts' }
@@ -21,6 +21,8 @@ describe 'Accounts Pins API' do
subject
end.to change { AccountPin.where(account: user.account, target_account: kevin.account).count }.by(1)
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -36,6 +38,8 @@ describe 'Accounts Pins API' do
subject
end.to change { AccountPin.where(account: user.account, target_account: kevin.account).count }.by(-1)
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/accounts/relationships_spec.rb b/spec/requests/api/v1/accounts/relationships_spec.rb
index b06ce0509d..52aeb01328 100644
--- a/spec/requests/api/v1/accounts/relationships_spec.rb
+++ b/spec/requests/api/v1/accounts/relationships_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'GET /api/v1/accounts/relationships' do
+RSpec.describe 'GET /api/v1/accounts/relationships' do
subject do
get '/api/v1/accounts/relationships', headers: headers, params: params
end
@@ -29,7 +29,9 @@ describe 'GET /api/v1/accounts/relationships' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to be_an(Enumerable)
.and contain_exactly(
include(
@@ -50,7 +52,9 @@ describe 'GET /api/v1/accounts/relationships' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to be_an(Enumerable)
.and have_attributes(
size: 2
@@ -70,7 +74,9 @@ describe 'GET /api/v1/accounts/relationships' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to be_an(Enumerable)
.and have_attributes(
size: 3
@@ -89,7 +95,7 @@ describe 'GET /api/v1/accounts/relationships' do
it 'removes duplicate account IDs from params' do
subject
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_an(Enumerable)
.and have_attributes(
size: 2
@@ -141,7 +147,7 @@ describe 'GET /api/v1/accounts/relationships' do
it 'returns JSON with correct data on previously cached requests' do
# Initial request including multiple accounts in params
get '/api/v1/accounts/relationships', headers: headers, params: { id: [simon.id, lewis.id] }
- expect(body_as_json)
+ expect(response.parsed_body)
.to have_attributes(size: 2)
# Subsequent request with different id, should override cache from first request
@@ -149,8 +155,10 @@ describe 'GET /api/v1/accounts/relationships' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_an(Enumerable)
.and have_attributes(
size: 1
@@ -171,8 +179,10 @@ describe 'GET /api/v1/accounts/relationships' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_an(Enumerable)
.and contain_exactly(
include(
diff --git a/spec/requests/api/v1/accounts/search_spec.rb b/spec/requests/api/v1/accounts/search_spec.rb
index 76b32e7b2c..dc24813e73 100644
--- a/spec/requests/api/v1/accounts/search_spec.rb
+++ b/spec/requests/api/v1/accounts/search_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Accounts Search API' do
+RSpec.describe 'Accounts Search API' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:accounts' }
@@ -13,6 +13,8 @@ describe 'Accounts Search API' do
get '/api/v1/accounts/search', params: { q: 'query' }, headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/accounts/statuses_spec.rb b/spec/requests/api/v1/accounts/statuses_spec.rb
index 97cdbe0156..1e21950287 100644
--- a/spec/requests/api/v1/accounts/statuses_spec.rb
+++ b/spec/requests/api/v1/accounts/statuses_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Accounts Statuses' do
+RSpec.describe 'API V1 Accounts Statuses' do
let(:user) { Fabricate(:user) }
let(:scopes) { 'read:statuses' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -19,6 +19,8 @@ describe 'API V1 Accounts Statuses' do
prev: api_v1_account_statuses_url(limit: 1, min_id: status.id),
next: api_v1_account_statuses_url(limit: 1, max_id: status.id)
)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'with only media' do
@@ -26,6 +28,8 @@ describe 'API V1 Accounts Statuses' do
get "/api/v1/accounts/#{user.account.id}/statuses", params: { only_media: true }, headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -41,7 +45,9 @@ describe 'API V1 Accounts Statuses' do
it 'returns posts along with self replies', :aggregate_failures do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to have_attributes(size: 2)
.and contain_exactly(
include(id: status.id.to_s),
@@ -61,6 +67,8 @@ describe 'API V1 Accounts Statuses' do
expect(response)
.to have_http_status(200)
.and include_pagination_headers(prev: api_v1_account_statuses_url(pinned: true, min_id: Status.first.id))
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -79,6 +87,8 @@ describe 'API V1 Accounts Statuses' do
prev: api_v1_account_statuses_url(pinned: true, min_id: Status.first.id),
next: api_v1_account_statuses_url(pinned: true, max_id: Status.first.id)
)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -96,13 +106,15 @@ describe 'API V1 Accounts Statuses' do
get "/api/v1/accounts/#{account.id}/statuses", params: { pinned: true }, headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'when user does not follow account' do
it 'lists the public status only' do
get "/api/v1/accounts/#{account.id}/statuses", params: { pinned: true }, headers: headers
- expect(body_as_json)
+ expect(response.parsed_body)
.to contain_exactly(
a_hash_including(id: status.id.to_s)
)
@@ -117,11 +129,13 @@ describe 'API V1 Accounts Statuses' do
it 'lists both the public and the private statuses' do
get "/api/v1/accounts/#{account.id}/statuses", params: { pinned: true }, headers: headers
- expect(body_as_json)
+ expect(response.parsed_body)
.to contain_exactly(
a_hash_including(id: status.id.to_s),
a_hash_including(id: private_status.id.to_s)
)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/accounts_spec.rb b/spec/requests/api/v1/accounts_spec.rb
index 3d9eb65019..45e66f0744 100644
--- a/spec/requests/api/v1/accounts_spec.rb
+++ b/spec/requests/api/v1/accounts_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe '/api/v1/accounts' do
+RSpec.describe '/api/v1/accounts' do
let(:user) { Fabricate(:user) }
let(:scopes) { '' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -17,7 +17,9 @@ describe '/api/v1/accounts' do
get '/api/v1/accounts', headers: headers, params: { id: [account.id, other_account.id, 123_123] }
expect(response).to have_http_status(200)
- expect(body_as_json).to contain_exactly(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to contain_exactly(
hash_including(id: account.id.to_s),
hash_including(id: other_account.id.to_s)
)
@@ -32,7 +34,9 @@ describe '/api/v1/accounts' do
get "/api/v1/accounts/#{account.id}"
expect(response).to have_http_status(200)
- expect(body_as_json[:id]).to eq(account.id.to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:id]).to eq(account.id.to_s)
end
end
@@ -41,7 +45,9 @@ describe '/api/v1/accounts' do
get '/api/v1/accounts/1'
expect(response).to have_http_status(404)
- expect(body_as_json[:error]).to eq('Record not found')
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:error]).to eq('Record not found')
end
end
@@ -57,7 +63,9 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:id]).to eq(account.id.to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:id]).to eq(account.id.to_s)
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
@@ -80,7 +88,9 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:access_token]).to_not be_blank
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:access_token]).to_not be_blank
user = User.find_by(email: 'hello@world.tld')
expect(user).to_not be_nil
@@ -93,6 +103,8 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -113,11 +125,14 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- json = body_as_json
-
- expect(json[:following]).to be true
- expect(json[:requested]).to be false
+ expect(response.parsed_body)
+ .to include(
+ following: true,
+ requested: false
+ )
expect(user.account.following?(other_account)).to be true
end
@@ -132,11 +147,14 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- json = body_as_json
-
- expect(json[:following]).to be false
- expect(json[:requested]).to be true
+ expect(response.parsed_body)
+ .to include(
+ following: false,
+ requested: true
+ )
expect(user.account.requested?(other_account)).to be true
end
@@ -155,7 +173,7 @@ describe '/api/v1/accounts' do
it 'changes reblogs option' do
post "/api/v1/accounts/#{other_account.id}/follow", headers: headers, params: { reblogs: true }
- expect(body_as_json).to include({
+ expect(response.parsed_body).to include({
following: true,
showing_reblogs: true,
notifying: false,
@@ -165,7 +183,7 @@ describe '/api/v1/accounts' do
it 'changes notify option' do
post "/api/v1/accounts/#{other_account.id}/follow", headers: headers, params: { notify: true }
- expect(body_as_json).to include({
+ expect(response.parsed_body).to include({
following: true,
showing_reblogs: false,
notifying: true,
@@ -175,7 +193,7 @@ describe '/api/v1/accounts' do
it 'changes languages option' do
post "/api/v1/accounts/#{other_account.id}/follow", headers: headers, params: { languages: %w(en es) }
- expect(body_as_json).to include({
+ expect(response.parsed_body).to include({
following: true,
showing_reblogs: false,
notifying: false,
@@ -201,6 +219,8 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.following?(other_account)).to be false
end
@@ -223,6 +243,8 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.followed_by?(other_account)).to be false
end
@@ -245,6 +267,8 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.following?(other_account)).to be false
expect(user.account.blocking?(other_account)).to be true
end
@@ -268,6 +292,8 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.blocking?(other_account)).to be false
end
@@ -290,6 +316,8 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.following?(other_account)).to be true
expect(user.account.muting?(other_account)).to be true
expect(user.account.muting_notifications?(other_account)).to be true
@@ -314,6 +342,8 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.following?(other_account)).to be true
expect(user.account.muting?(other_account)).to be true
expect(user.account.muting_notifications?(other_account)).to be false
@@ -338,6 +368,8 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.following?(other_account)).to be true
expect(user.account.muting?(other_account)).to be true
expect(user.account.muting_notifications?(other_account)).to be true
@@ -362,6 +394,8 @@ describe '/api/v1/accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.muting?(other_account)).to be false
end
diff --git a/spec/requests/api/v1/admin/account_actions_spec.rb b/spec/requests/api/v1/admin/account_actions_spec.rb
index 5bcf809401..4884dba9c7 100644
--- a/spec/requests/api/v1/admin/account_actions_spec.rb
+++ b/spec/requests/api/v1/admin/account_actions_spec.rb
@@ -61,6 +61,8 @@ RSpec.describe 'Account actions' do
it 'disables the target account' do
expect { subject }.to change { target_account.reload.user_disabled? }.from(false).to(true)
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -75,6 +77,8 @@ RSpec.describe 'Account actions' do
it 'marks the target account as sensitive' do
expect { subject }.to change { target_account.reload.sensitized? }.from(false).to(true)
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -89,6 +93,8 @@ RSpec.describe 'Account actions' do
it 'marks the target account as silenced' do
expect { subject }.to change { target_account.reload.silenced? }.from(false).to(true)
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -103,6 +109,8 @@ RSpec.describe 'Account actions' do
it 'marks the target account as suspended' do
expect { subject }.to change { target_account.reload.suspended? }.from(false).to(true)
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -115,6 +123,8 @@ RSpec.describe 'Account actions' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -125,6 +135,8 @@ RSpec.describe 'Account actions' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -135,6 +147,8 @@ RSpec.describe 'Account actions' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/accounts_spec.rb b/spec/requests/api/v1/admin/accounts_spec.rb
index 1615581f0e..6a681f9c5e 100644
--- a/spec/requests/api/v1/admin/accounts_spec.rb
+++ b/spec/requests/api/v1/admin/accounts_spec.rb
@@ -19,7 +19,9 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.pluck(:id)).to match_array(expected_results.map { |a| a.id.to_s })
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.pluck(:id)).to match_array(expected_results.map { |a| a.id.to_s })
end
end
@@ -93,7 +95,9 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.size).to eq(params[:limit])
end
end
end
@@ -112,7 +116,9 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to match(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match(
a_hash_including(id: account.id.to_s, username: account.username, email: account.user.email)
)
end
@@ -122,6 +128,8 @@ RSpec.describe 'Accounts' do
get '/api/v1/admin/accounts/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -145,6 +153,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(account.reload.user_approved?).to be(true)
end
@@ -166,6 +176,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(403)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -174,6 +186,8 @@ RSpec.describe 'Accounts' do
post '/api/v1/admin/accounts/-1/approve', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -193,15 +207,13 @@ RSpec.describe 'Accounts' do
it_behaves_like 'forbidden for wrong scope', 'write write:accounts read admin:read'
it_behaves_like 'forbidden for wrong role', ''
- it 'removes the user successfully', :aggregate_failures do
+ it 'removes the user successfully and logs action', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(User.where(id: account.user.id)).to_not exist
- end
-
- it 'logs action', :aggregate_failures do
- subject
expect(latest_admin_action_log)
.to be_present
@@ -218,6 +230,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(403)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -226,6 +240,8 @@ RSpec.describe 'Accounts' do
post '/api/v1/admin/accounts/-1/reject', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -248,6 +264,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(account.reload.user_disabled?).to be false
end
@@ -256,6 +274,8 @@ RSpec.describe 'Accounts' do
post '/api/v1/admin/accounts/-1/enable', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -279,6 +299,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(account.reload.suspended?).to be false
end
end
@@ -288,6 +310,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(403)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -296,6 +320,8 @@ RSpec.describe 'Accounts' do
post '/api/v1/admin/accounts/-1/unsuspend', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -318,6 +344,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(account.reload.sensitized?).to be false
end
@@ -326,6 +354,8 @@ RSpec.describe 'Accounts' do
post '/api/v1/admin/accounts/-1/unsensitive', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -348,6 +378,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(account.reload.silenced?).to be false
end
@@ -356,6 +388,8 @@ RSpec.describe 'Accounts' do
post '/api/v1/admin/accounts/-1/unsilence', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -380,6 +414,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(Admin::AccountDeletionWorker).to have_received(:perform_async).with(account.id).once
end
end
@@ -397,6 +433,8 @@ RSpec.describe 'Accounts' do
delete '/api/v1/admin/accounts/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb b/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb
index 3f33b50f39..25af0a26af 100644
--- a/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb
+++ b/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb
@@ -20,17 +20,16 @@ RSpec.describe 'Canonical Email Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
context 'when there is no canonical email block' do
it 'returns an empty list' do
subject
- expect(body_as_json).to be_empty
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to be_empty
end
end
@@ -41,7 +40,12 @@ RSpec.describe 'Canonical Email Blocks' do
it 'returns the correct canonical email hashes' do
subject
- expect(body_as_json.pluck(:canonical_email_hash)).to match_array(expected_email_hashes)
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.pluck(:canonical_email_hash))
+ .to match_array(expected_email_hashes)
end
context 'with limit param' do
@@ -50,7 +54,7 @@ RSpec.describe 'Canonical Email Blocks' do
it 'returns only the requested number of canonical email blocks' do
subject
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.parsed_body.size).to eq(params[:limit])
end
end
@@ -62,7 +66,7 @@ RSpec.describe 'Canonical Email Blocks' do
canonical_email_blocks_ids = canonical_email_blocks.pluck(:id).map(&:to_s)
- expect(body_as_json.pluck(:id)).to match_array(canonical_email_blocks_ids[2..])
+ expect(response.parsed_body.pluck(:id)).to match_array(canonical_email_blocks_ids[2..])
end
end
@@ -74,7 +78,7 @@ RSpec.describe 'Canonical Email Blocks' do
canonical_email_blocks_ids = canonical_email_blocks.pluck(:id).map(&:to_s)
- expect(body_as_json.pluck(:id)).to match_array(canonical_email_blocks_ids[..2])
+ expect(response.parsed_body.pluck(:id)).to match_array(canonical_email_blocks_ids[..2])
end
end
end
@@ -96,10 +100,13 @@ RSpec.describe 'Canonical Email Blocks' do
subject
expect(response).to have_http_status(200)
- json = body_as_json
-
- expect(json[:id]).to eq(canonical_email_block.id.to_s)
- expect(json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to include(
+ id: eq(canonical_email_block.id.to_s),
+ canonical_email_hash: eq(canonical_email_block.canonical_email_hash)
+ )
end
end
@@ -108,6 +115,8 @@ RSpec.describe 'Canonical Email Blocks' do
get '/api/v1/admin/canonical_email_blocks/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -130,6 +139,8 @@ RSpec.describe 'Canonical Email Blocks' do
subject
expect(response).to have_http_status(400)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -141,7 +152,9 @@ RSpec.describe 'Canonical Email Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[0][:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.first[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
end
end
@@ -150,7 +163,9 @@ RSpec.describe 'Canonical Email Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to be_empty
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to be_empty
end
end
end
@@ -172,7 +187,9 @@ RSpec.describe 'Canonical Email Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
end
context 'when the required email param is not provided' do
@@ -182,6 +199,8 @@ RSpec.describe 'Canonical Email Blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -192,7 +211,9 @@ RSpec.describe 'Canonical Email Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:canonical_email_hash]).to eq(params[:canonical_email_hash])
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:canonical_email_hash]).to eq(params[:canonical_email_hash])
end
end
@@ -203,7 +224,9 @@ RSpec.describe 'Canonical Email Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
end
end
@@ -216,6 +239,8 @@ RSpec.describe 'Canonical Email Blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -236,6 +261,8 @@ RSpec.describe 'Canonical Email Blocks' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(CanonicalEmailBlock.find_by(id: canonical_email_block.id)).to be_nil
end
@@ -244,6 +271,8 @@ RSpec.describe 'Canonical Email Blocks' do
delete '/api/v1/admin/canonical_email_blocks/0', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/dimensions_spec.rb b/spec/requests/api/v1/admin/dimensions_spec.rb
index 87534a74b8..81fb580ba7 100644
--- a/spec/requests/api/v1/admin/dimensions_spec.rb
+++ b/spec/requests/api/v1/admin/dimensions_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin Dimensions' do
+RSpec.describe 'Admin Dimensions' do
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
@@ -15,6 +15,8 @@ describe 'Admin Dimensions' do
expect(response)
.to have_http_status(403)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -27,7 +29,10 @@ describe 'Admin Dimensions' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
.to be_an(Array)
end
end
diff --git a/spec/requests/api/v1/admin/domain_allows_spec.rb b/spec/requests/api/v1/admin/domain_allows_spec.rb
index b8f0b0055c..fba1eb15d3 100644
--- a/spec/requests/api/v1/admin/domain_allows_spec.rb
+++ b/spec/requests/api/v1/admin/domain_allows_spec.rb
@@ -20,17 +20,15 @@ RSpec.describe 'Domain Allows' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
context 'when there is no allowed domains' do
it 'returns an empty body' do
subject
- expect(body_as_json).to be_empty
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to be_empty
end
end
@@ -49,7 +47,12 @@ RSpec.describe 'Domain Allows' do
it 'returns the correct allowed domains' do
subject
- expect(body_as_json).to match_array(expected_response)
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to match_array(expected_response)
end
context 'with limit param' do
@@ -58,7 +61,7 @@ RSpec.describe 'Domain Allows' do
it 'returns only the requested number of allowed domains' do
subject
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.parsed_body.size).to eq(params[:limit])
end
end
end
@@ -79,7 +82,9 @@ RSpec.describe 'Domain Allows' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:domain]).to eq domain_allow.domain
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:domain]).to eq domain_allow.domain
end
context 'when the requested allowed domain does not exist' do
@@ -87,6 +92,8 @@ RSpec.describe 'Domain Allows' do
get '/api/v1/admin/domain_allows/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -107,7 +114,9 @@ RSpec.describe 'Domain Allows' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:domain]).to eq 'foo.bar.com'
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:domain]).to eq 'foo.bar.com'
expect(DomainAllow.find_by(domain: 'foo.bar.com')).to be_present
end
end
@@ -119,6 +128,8 @@ RSpec.describe 'Domain Allows' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -129,6 +140,8 @@ RSpec.describe 'Domain Allows' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -140,7 +153,7 @@ RSpec.describe 'Domain Allows' do
it 'returns the existing allowed domain name' do
subject
- expect(body_as_json[:domain]).to eq(params[:domain])
+ expect(response.parsed_body[:domain]).to eq(params[:domain])
end
end
end
@@ -160,6 +173,8 @@ RSpec.describe 'Domain Allows' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(DomainAllow.find_by(id: domain_allow.id)).to be_nil
end
@@ -168,6 +183,8 @@ RSpec.describe 'Domain Allows' do
delete '/api/v1/admin/domain_allows/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/domain_blocks_spec.rb b/spec/requests/api/v1/admin/domain_blocks_spec.rb
index 415281a932..029de72fd7 100644
--- a/spec/requests/api/v1/admin/domain_blocks_spec.rb
+++ b/spec/requests/api/v1/admin/domain_blocks_spec.rb
@@ -20,17 +20,16 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
context 'when there are no domain blocks' do
it 'returns an empty list' do
subject
- expect(body_as_json).to be_empty
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to be_empty
end
end
@@ -64,7 +63,12 @@ RSpec.describe 'Domain Blocks' do
it 'returns the expected domain blocks' do
subject
- expect(body_as_json).to match_array(expected_responde)
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to match_array(expected_responde)
end
context 'with limit param' do
@@ -73,7 +77,7 @@ RSpec.describe 'Domain Blocks' do
it 'returns only the requested number of domain blocks' do
subject
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.parsed_body.size).to eq(params[:limit])
end
end
end
@@ -94,19 +98,19 @@ RSpec.describe 'Domain Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to eq(
- {
- id: domain_block.id.to_s,
- domain: domain_block.domain,
- digest: domain_block.domain_digest,
- created_at: domain_block.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ'),
- severity: domain_block.severity.to_s,
- reject_media: domain_block.reject_media,
- reject_reports: domain_block.reject_reports,
- private_comment: domain_block.private_comment,
- public_comment: domain_block.public_comment,
- obfuscate: domain_block.obfuscate,
- }
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match(
+ id: domain_block.id.to_s,
+ domain: domain_block.domain,
+ digest: domain_block.domain_digest,
+ created_at: domain_block.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ'),
+ severity: domain_block.severity.to_s,
+ reject_media: domain_block.reject_media,
+ reject_reports: domain_block.reject_reports,
+ private_comment: domain_block.private_comment,
+ public_comment: domain_block.public_comment,
+ obfuscate: domain_block.obfuscate
)
end
@@ -115,6 +119,8 @@ RSpec.describe 'Domain Blocks' do
get '/api/v1/admin/domain_blocks/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -133,10 +139,10 @@ RSpec.describe 'Domain Blocks' do
it 'creates a domain block with the expected domain name and severity', :aggregate_failures do
subject
- body = body_as_json
-
expect(response).to have_http_status(200)
- expect(body).to match a_hash_including(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match a_hash_including(
{
domain: 'foo.bar.com',
severity: 'silence',
@@ -156,10 +162,10 @@ RSpec.describe 'Domain Blocks' do
it 'creates a domain block with the expected domain name and severity', :aggregate_failures do
subject
- body = body_as_json
-
expect(response).to have_http_status(200)
- expect(body).to match a_hash_including(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match a_hash_including(
{
domain: 'foo.bar.com',
severity: 'suspend',
@@ -179,7 +185,9 @@ RSpec.describe 'Domain Blocks' do
subject
expect(response).to have_http_status(422)
- expect(body_as_json[:existing_domain_block][:domain]).to eq('foo.bar.com')
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:existing_domain_block][:domain]).to eq('foo.bar.com')
end
end
@@ -192,7 +200,9 @@ RSpec.describe 'Domain Blocks' do
subject
expect(response).to have_http_status(422)
- expect(body_as_json[:existing_domain_block][:domain]).to eq('bar.com')
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:existing_domain_block][:domain]).to eq('bar.com')
end
end
@@ -203,6 +213,8 @@ RSpec.describe 'Domain Blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -223,7 +235,9 @@ RSpec.describe 'Domain Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to match a_hash_including(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match a_hash_including(
{
id: domain_block.id.to_s,
domain: domain_block.domain,
@@ -242,6 +256,8 @@ RSpec.describe 'Domain Blocks' do
put '/api/v1/admin/domain_blocks/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -261,6 +277,8 @@ RSpec.describe 'Domain Blocks' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(DomainBlock.find_by(id: domain_block.id)).to be_nil
end
@@ -269,6 +287,8 @@ RSpec.describe 'Domain Blocks' do
delete '/api/v1/admin/domain_blocks/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/email_domain_blocks_spec.rb b/spec/requests/api/v1/admin/email_domain_blocks_spec.rb
index 16656e0202..2788a45a4a 100644
--- a/spec/requests/api/v1/admin/email_domain_blocks_spec.rb
+++ b/spec/requests/api/v1/admin/email_domain_blocks_spec.rb
@@ -21,17 +21,16 @@ RSpec.describe 'Email Domain Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
context 'when there is no email domain block' do
it 'returns an empty list' do
subject
- expect(body_as_json).to be_empty
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to be_empty
end
end
@@ -42,7 +41,12 @@ RSpec.describe 'Email Domain Blocks' do
it 'return the correct blocked email domains' do
subject
- expect(body_as_json.pluck(:domain)).to match_array(blocked_email_domains)
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.pluck(:domain))
+ .to match_array(blocked_email_domains)
end
context 'with limit param' do
@@ -51,7 +55,7 @@ RSpec.describe 'Email Domain Blocks' do
it 'returns only the requested number of email domain blocks' do
subject
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.parsed_body.size).to eq(params[:limit])
end
end
@@ -63,7 +67,7 @@ RSpec.describe 'Email Domain Blocks' do
email_domain_blocks_ids = email_domain_blocks.pluck(:id).map(&:to_s)
- expect(body_as_json.pluck(:id)).to match_array(email_domain_blocks_ids[2..])
+ expect(response.parsed_body.pluck(:id)).to match_array(email_domain_blocks_ids[2..])
end
end
@@ -75,7 +79,7 @@ RSpec.describe 'Email Domain Blocks' do
email_domain_blocks_ids = email_domain_blocks.pluck(:id).map(&:to_s)
- expect(body_as_json.pluck(:id)).to match_array(email_domain_blocks_ids[..2])
+ expect(response.parsed_body.pluck(:id)).to match_array(email_domain_blocks_ids[..2])
end
end
end
@@ -97,7 +101,9 @@ RSpec.describe 'Email Domain Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:domain]).to eq(email_domain_block.domain)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:domain]).to eq(email_domain_block.domain)
end
end
@@ -106,6 +112,8 @@ RSpec.describe 'Email Domain Blocks' do
get '/api/v1/admin/email_domain_blocks/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -125,7 +133,9 @@ RSpec.describe 'Email Domain Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:domain]).to eq(params[:domain])
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:domain]).to eq(params[:domain])
end
context 'when domain param is not provided' do
@@ -135,6 +145,8 @@ RSpec.describe 'Email Domain Blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -145,6 +157,8 @@ RSpec.describe 'Email Domain Blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -157,6 +171,8 @@ RSpec.describe 'Email Domain Blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -176,7 +192,9 @@ RSpec.describe 'Email Domain Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to be_empty
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to be_empty
expect(EmailDomainBlock.find_by(id: email_domain_block.id)).to be_nil
end
@@ -185,6 +203,8 @@ RSpec.describe 'Email Domain Blocks' do
delete '/api/v1/admin/email_domain_blocks/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/ip_blocks_spec.rb b/spec/requests/api/v1/admin/ip_blocks_spec.rb
index 98b954dd49..aa3db33915 100644
--- a/spec/requests/api/v1/admin/ip_blocks_spec.rb
+++ b/spec/requests/api/v1/admin/ip_blocks_spec.rb
@@ -20,17 +20,16 @@ RSpec.describe 'IP Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
context 'when there is no ip block' do
it 'returns an empty body' do
subject
- expect(body_as_json).to be_empty
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to be_empty
end
end
@@ -58,7 +57,12 @@ RSpec.describe 'IP Blocks' do
it 'returns the correct blocked ips' do
subject
- expect(body_as_json).to match_array(expected_response)
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to match_array(expected_response)
end
context 'with limit param' do
@@ -67,7 +71,7 @@ RSpec.describe 'IP Blocks' do
it 'returns only the requested number of ip blocks' do
subject
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.parsed_body.size).to eq(params[:limit])
end
end
end
@@ -88,10 +92,14 @@ RSpec.describe 'IP Blocks' do
subject
expect(response).to have_http_status(200)
- json = body_as_json
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(json[:ip]).to eq("#{ip_block.ip}/#{ip_block.ip.prefix}")
- expect(json[:severity]).to eq(ip_block.severity.to_s)
+ expect(response.parsed_body)
+ .to include(
+ ip: eq("#{ip_block.ip}/#{ip_block.ip.prefix}"),
+ severity: eq(ip_block.severity.to_s)
+ )
end
context 'when ip block does not exist' do
@@ -99,6 +107,8 @@ RSpec.describe 'IP Blocks' do
get '/api/v1/admin/ip_blocks/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -118,11 +128,14 @@ RSpec.describe 'IP Blocks' do
subject
expect(response).to have_http_status(200)
- json = body_as_json
-
- expect(json[:ip]).to eq("#{params[:ip]}/32")
- expect(json[:severity]).to eq(params[:severity])
- expect(json[:comment]).to eq(params[:comment])
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to include(
+ ip: eq("#{params[:ip]}/32"),
+ severity: eq(params[:severity]),
+ comment: eq(params[:comment])
+ )
end
context 'when the required ip param is not provided' do
@@ -132,6 +145,8 @@ RSpec.describe 'IP Blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -142,6 +157,8 @@ RSpec.describe 'IP Blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -154,6 +171,8 @@ RSpec.describe 'IP Blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -164,6 +183,8 @@ RSpec.describe 'IP Blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -182,7 +203,9 @@ RSpec.describe 'IP Blocks' do
.and change_comment_value
expect(response).to have_http_status(200)
- expect(body_as_json).to match(hash_including({
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match(hash_including({
ip: "#{ip_block.ip}/#{ip_block.ip.prefix}",
severity: 'sign_up_requires_approval',
comment: 'Decreasing severity',
@@ -202,6 +225,8 @@ RSpec.describe 'IP Blocks' do
put '/api/v1/admin/ip_blocks/-1', headers: headers, params: params
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -217,7 +242,9 @@ RSpec.describe 'IP Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to be_empty
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to be_empty
expect(IpBlock.find_by(id: ip_block.id)).to be_nil
end
@@ -226,6 +253,8 @@ RSpec.describe 'IP Blocks' do
delete '/api/v1/admin/ip_blocks/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/measures_spec.rb b/spec/requests/api/v1/admin/measures_spec.rb
index 80fed79d9a..519b5cc7b3 100644
--- a/spec/requests/api/v1/admin/measures_spec.rb
+++ b/spec/requests/api/v1/admin/measures_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin Measures' do
+RSpec.describe 'Admin Measures' do
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
@@ -32,6 +32,8 @@ describe 'Admin Measures' do
expect(response)
.to have_http_status(403)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -43,8 +45,10 @@ describe 'Admin Measures' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_an(Array)
end
end
diff --git a/spec/requests/api/v1/admin/reports_spec.rb b/spec/requests/api/v1/admin/reports_spec.rb
index 4b0b7e1713..987f0eda7f 100644
--- a/spec/requests/api/v1/admin/reports_spec.rb
+++ b/spec/requests/api/v1/admin/reports_spec.rb
@@ -19,17 +19,16 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
context 'when there are no reports' do
it 'returns an empty list' do
subject
- expect(body_as_json).to be_empty
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to be_empty
end
end
@@ -64,7 +63,12 @@ RSpec.describe 'Reports' do
it 'returns all unresolved reports' do
subject
- expect(body_as_json).to match_array(expected_response)
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to match_array(expected_response)
end
context 'with resolved param' do
@@ -74,7 +78,7 @@ RSpec.describe 'Reports' do
it 'returns only the resolved reports' do
subject
- expect(body_as_json).to match_array(expected_response)
+ expect(response.parsed_body).to match_array(expected_response)
end
end
@@ -85,7 +89,7 @@ RSpec.describe 'Reports' do
it 'returns all unresolved reports filed by the specified account' do
subject
- expect(body_as_json).to match_array(expected_response)
+ expect(response.parsed_body).to match_array(expected_response)
end
end
@@ -96,7 +100,7 @@ RSpec.describe 'Reports' do
it 'returns all unresolved reports targeting the specified account' do
subject
- expect(body_as_json).to match_array(expected_response)
+ expect(response.parsed_body).to match_array(expected_response)
end
end
@@ -106,7 +110,7 @@ RSpec.describe 'Reports' do
it 'returns only the requested number of reports' do
subject
- expect(body_as_json.size).to eq(1)
+ expect(response.parsed_body.size).to eq(1)
end
end
end
@@ -126,7 +130,9 @@ RSpec.describe 'Reports' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to include(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to include(
{
id: report.id.to_s,
action_taken: report.action_taken?,
@@ -156,10 +162,12 @@ RSpec.describe 'Reports' do
.and create_an_action_log
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
report.reload
- expect(body_as_json).to include(
+ expect(response.parsed_body).to include(
{
id: report.id.to_s,
action_taken: report.action_taken?,
@@ -190,6 +198,8 @@ RSpec.describe 'Reports' do
.to change { report.reload.unresolved? }.from(true).to(false)
.and create_an_action_log
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -208,6 +218,8 @@ RSpec.describe 'Reports' do
.to change { report.reload.unresolved? }.from(false).to(true)
.and create_an_action_log
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -226,6 +238,8 @@ RSpec.describe 'Reports' do
.to change { report.reload.assigned_account_id }.from(nil).to(user.account.id)
.and create_an_action_log
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -244,6 +258,8 @@ RSpec.describe 'Reports' do
.to change { report.reload.assigned_account_id }.from(user.account.id).to(nil)
.and create_an_action_log
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
diff --git a/spec/requests/api/v1/admin/retention_spec.rb b/spec/requests/api/v1/admin/retention_spec.rb
index 9178335ba5..e28bc2a94f 100644
--- a/spec/requests/api/v1/admin/retention_spec.rb
+++ b/spec/requests/api/v1/admin/retention_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin Retention' do
+RSpec.describe 'Admin Retention' do
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
@@ -15,6 +15,8 @@ describe 'Admin Retention' do
expect(response)
.to have_http_status(403)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -26,8 +28,10 @@ describe 'Admin Retention' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_an(Array)
end
end
diff --git a/spec/requests/api/v1/admin/tags_spec.rb b/spec/requests/api/v1/admin/tags_spec.rb
index 031be17f52..3a57432af7 100644
--- a/spec/requests/api/v1/admin/tags_spec.rb
+++ b/spec/requests/api/v1/admin/tags_spec.rb
@@ -20,17 +20,16 @@ RSpec.describe 'Tags' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
context 'when there are no tags' do
it 'returns an empty list' do
subject
- expect(body_as_json).to be_empty
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to be_empty
end
end
@@ -46,8 +45,13 @@ RSpec.describe 'Tags' do
it 'returns the expected tags' do
subject
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
tags.each do |tag|
- expect(body_as_json.find { |item| item[:id] == tag.id.to_s && item[:name] == tag.name }).to_not be_nil
+ expect(response.parsed_body.find { |item| item[:id] == tag.id.to_s && item[:name] == tag.name }).to_not be_nil
end
end
@@ -57,7 +61,7 @@ RSpec.describe 'Tags' do
it 'returns only the requested number of tags' do
subject
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.parsed_body.size).to eq(params[:limit])
end
end
end
@@ -73,17 +77,18 @@ RSpec.describe 'Tags' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
+ it 'returns http success and expected tag content' do
subject
expect(response).to have_http_status(200)
- end
+ expect(response.content_type)
+ .to start_with('application/json')
- it 'returns expected tag content' do
- subject
-
- expect(body_as_json[:id].to_i).to eq(tag.id)
- expect(body_as_json[:name]).to eq(tag.name)
+ expect(response.parsed_body)
+ .to include(
+ id: tag.id.to_s,
+ name: tag.name
+ )
end
context 'when the requested tag does not exist' do
@@ -91,6 +96,8 @@ RSpec.describe 'Tags' do
get '/api/v1/admin/tags/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -107,17 +114,18 @@ RSpec.describe 'Tags' do
it_behaves_like 'forbidden for wrong scope', 'admin:read'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
+ it 'returns http success and updates tag' do
subject
expect(response).to have_http_status(200)
- end
+ expect(response.content_type)
+ .to start_with('application/json')
- it 'returns updated tag' do
- subject
-
- expect(body_as_json[:id].to_i).to eq(tag.id)
- expect(body_as_json[:name]).to eq(tag.name.upcase)
+ expect(response.parsed_body)
+ .to include(
+ id: tag.id.to_s,
+ name: tag.name.upcase
+ )
end
context 'when the updated display name is invalid' do
@@ -127,6 +135,8 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -135,6 +145,8 @@ RSpec.describe 'Tags' do
get '/api/v1/admin/tags/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/trends/links/links_spec.rb b/spec/requests/api/v1/admin/trends/links/links_spec.rb
index 48842828b3..51e800734a 100644
--- a/spec/requests/api/v1/admin/trends/links/links_spec.rb
+++ b/spec/requests/api/v1/admin/trends/links/links_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Links' do
+RSpec.describe 'Links' do
let(:role) { UserRole.find_by(name: 'Admin') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
@@ -18,6 +18,8 @@ describe 'Links' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -36,6 +38,8 @@ describe 'Links' do
.to change_link_trendable_to_true
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expects_correct_link_data
end
@@ -44,7 +48,7 @@ describe 'Links' do
end
def expects_correct_link_data
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(
url: preview_card.url,
title: preview_card.title,
@@ -60,6 +64,8 @@ describe 'Links' do
post '/api/v1/admin/trends/links/-1/approve', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -70,6 +76,8 @@ describe 'Links' do
subject
expect(response).to have_http_status(403)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -89,6 +97,8 @@ describe 'Links' do
.to_not change_link_trendable
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
def change_link_trendable
@@ -98,7 +108,7 @@ describe 'Links' do
it 'returns the link data' do
subject
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(
url: preview_card.url,
title: preview_card.title,
@@ -114,6 +124,8 @@ describe 'Links' do
post '/api/v1/admin/trends/links/-1/reject', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -124,6 +136,8 @@ describe 'Links' do
subject
expect(response).to have_http_status(403)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/trends/links/preview_card_providers_spec.rb b/spec/requests/api/v1/admin/trends/links/preview_card_providers_spec.rb
index 384a305d4a..d46d0ff555 100644
--- a/spec/requests/api/v1/admin/trends/links/preview_card_providers_spec.rb
+++ b/spec/requests/api/v1/admin/trends/links/preview_card_providers_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Admin Trends Links Preview Card Providers' do
+RSpec.describe 'API V1 Admin Trends Links Preview Card Providers' do
let(:role) { UserRole.find_by(name: 'Admin') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
@@ -16,6 +16,8 @@ describe 'API V1 Admin Trends Links Preview Card Providers' do
get '/api/v1/admin/trends/links/publishers', params: { account_id: account.id, limit: 2 }, headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -29,6 +31,8 @@ describe 'API V1 Admin Trends Links Preview Card Providers' do
it 'returns http success' do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -42,6 +46,8 @@ describe 'API V1 Admin Trends Links Preview Card Providers' do
it 'returns http success' do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/trends/statuses_spec.rb b/spec/requests/api/v1/admin/trends/statuses_spec.rb
index 04aa0465f2..c63d8d925c 100644
--- a/spec/requests/api/v1/admin/trends/statuses_spec.rb
+++ b/spec/requests/api/v1/admin/trends/statuses_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Admin Trends Statuses' do
+RSpec.describe 'API V1 Admin Trends Statuses' do
let(:role) { UserRole.find_by(name: 'Admin') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
@@ -16,6 +16,8 @@ describe 'API V1 Admin Trends Statuses' do
get '/api/v1/admin/trends/statuses', params: { account_id: account.id, limit: 2 }, headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -29,6 +31,8 @@ describe 'API V1 Admin Trends Statuses' do
it 'returns http success' do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -42,6 +46,8 @@ describe 'API V1 Admin Trends Statuses' do
it 'returns http success' do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/admin/trends/tags_spec.rb b/spec/requests/api/v1/admin/trends/tags_spec.rb
index b1437dad8d..433cc6c5a6 100644
--- a/spec/requests/api/v1/admin/trends/tags_spec.rb
+++ b/spec/requests/api/v1/admin/trends/tags_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Admin Trends Tags' do
+RSpec.describe 'API V1 Admin Trends Tags' do
let(:role) { UserRole.find_by(name: 'Admin') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
@@ -16,6 +16,8 @@ describe 'API V1 Admin Trends Tags' do
get '/api/v1/admin/trends/tags', params: { account_id: account.id, limit: 2 }, headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -29,6 +31,8 @@ describe 'API V1 Admin Trends Tags' do
it 'returns http success' do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -42,6 +46,8 @@ describe 'API V1 Admin Trends Tags' do
it 'returns http success' do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/announcements/reactions_spec.rb b/spec/requests/api/v1/announcements/reactions_spec.rb
index ffacb2b0af..82154b4a26 100644
--- a/spec/requests/api/v1/announcements/reactions_spec.rb
+++ b/spec/requests/api/v1/announcements/reactions_spec.rb
@@ -15,7 +15,9 @@ RSpec.describe 'API V1 Announcements Reactions' do
it 'returns http unauthorized' do
put "/api/v1/announcements/#{announcement.id}/reactions/#{escaped_emoji}"
- expect(response).to have_http_status 401
+ expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -26,6 +28,8 @@ RSpec.describe 'API V1 Announcements Reactions' do
it 'creates reaction', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(announcement.announcement_reactions.find_by(name: '😂', account: user.account)).to_not be_nil
end
end
@@ -39,7 +43,9 @@ RSpec.describe 'API V1 Announcements Reactions' do
context 'without token' do
it 'returns http unauthorized' do
delete "/api/v1/announcements/#{announcement.id}/reactions/#{escaped_emoji}"
- expect(response).to have_http_status 401
+ expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -50,6 +56,8 @@ RSpec.describe 'API V1 Announcements Reactions' do
it 'creates reaction', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(announcement.announcement_reactions.find_by(name: '😂', account: user.account)).to be_nil
end
end
diff --git a/spec/requests/api/v1/announcements_spec.rb b/spec/requests/api/v1/announcements_spec.rb
index 1624b76012..97a4442aa9 100644
--- a/spec/requests/api/v1/announcements_spec.rb
+++ b/spec/requests/api/v1/announcements_spec.rb
@@ -15,7 +15,9 @@ RSpec.describe 'API V1 Announcements' do
it 'returns http unprocessable entity' do
get '/api/v1/announcements'
- expect(response).to have_http_status 422
+ expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -26,6 +28,8 @@ RSpec.describe 'API V1 Announcements' do
it 'returns http success' do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -35,7 +39,9 @@ RSpec.describe 'API V1 Announcements' do
it 'returns http unauthorized' do
post "/api/v1/announcements/#{announcement.id}/dismiss"
- expect(response).to have_http_status 401
+ expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -48,6 +54,8 @@ RSpec.describe 'API V1 Announcements' do
it 'dismisses announcement', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(announcement.announcement_mutes.find_by(account: user.account)).to_not be_nil
end
end
diff --git a/spec/requests/api/v1/annual_reports_spec.rb b/spec/requests/api/v1/annual_reports_spec.rb
new file mode 100644
index 0000000000..b9831d17e2
--- /dev/null
+++ b/spec/requests/api/v1/annual_reports_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'API V1 Annual Reports' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+
+ describe 'GET /api/v1/annual_reports' do
+ context 'when not authorized' do
+ it 'returns http unauthorized' do
+ get api_v1_annual_reports_path
+
+ expect(response)
+ .to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
+ end
+ end
+
+ context 'with wrong scope' do
+ before do
+ get api_v1_annual_reports_path, headers: headers
+ end
+
+ it_behaves_like 'forbidden for wrong scope', 'write write:accounts'
+ end
+
+ context 'with correct scope' do
+ let(:scopes) { 'read:accounts' }
+
+ it 'returns http success' do
+ get api_v1_annual_reports_path, headers: headers
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
+ .to be_present
+ end
+ end
+ end
+
+ describe 'POST /api/v1/annual_reports/:id/read' do
+ context 'with correct scope' do
+ let(:scopes) { 'write:accounts' }
+
+ it 'returns success and marks the report as read' do
+ annual_report = Fabricate :generated_annual_report, account: user.account
+
+ expect { post read_api_v1_annual_report_path(id: annual_report.year), headers: headers }
+ .to change { annual_report.reload.viewed? }.to(true)
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/v1/apps/credentials_spec.rb b/spec/requests/api/v1/apps/credentials_spec.rb
index 6e6970ce53..8e5fa14b7e 100644
--- a/spec/requests/api/v1/apps/credentials_spec.rb
+++ b/spec/requests/api/v1/apps/credentials_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Credentials' do
+RSpec.describe 'Credentials' do
describe 'GET /api/v1/apps/verify_credentials' do
subject do
get '/api/v1/apps/verify_credentials', headers: headers
@@ -17,8 +17,10 @@ describe 'Credentials' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(
id: token.application.id.to_s,
name: token.application.name,
@@ -36,9 +38,12 @@ describe 'Credentials' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json[:client_id]).to_not be_present
- expect(body_as_json[:client_secret]).to_not be_present
+ expect(response.parsed_body)
+ .to not_include(client_id: be_present)
+ .and not_include(client_secret: be_present)
end
end
@@ -47,16 +52,14 @@ describe 'Credentials' do
let(:token) { Fabricate(:accessible_access_token, application: application) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
- it 'returns http success' do
+ it 'returns http success and returns app information' do
subject
expect(response).to have_http_status(200)
- end
+ expect(response.content_type)
+ .to start_with('application/json')
- it 'returns the app information correctly' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(
id: token.application.id.to_s,
name: token.application.name,
@@ -78,6 +81,8 @@ describe 'Credentials' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -90,12 +95,14 @@ describe 'Credentials' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
it 'returns the error in the json response' do
subject
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(
error: 'The access token was revoked'
)
@@ -108,16 +115,14 @@ describe 'Credentials' do
let(:token) { Fabricate(:accessible_access_token, application: application) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}-invalid" } }
- it 'returns http authorization error' do
+ it 'returns http authorization error with json error' do
subject
expect(response).to have_http_status(401)
- end
+ expect(response.content_type)
+ .to start_with('application/json')
- it 'returns the error in the json response' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(
error: 'The access token is invalid'
)
diff --git a/spec/requests/api/v1/apps_spec.rb b/spec/requests/api/v1/apps_spec.rb
index 1f01bddf3c..cf43e14d62 100644
--- a/spec/requests/api/v1/apps_spec.rb
+++ b/spec/requests/api/v1/apps_spec.rb
@@ -28,6 +28,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
app = Doorkeeper::Application.find_by(name: client_name)
@@ -35,7 +37,7 @@ RSpec.describe 'Apps' do
expect(app.scopes.to_s).to eq scopes
expect(app.redirect_uris).to eq redirect_uris
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(
id: app.id.to_s,
client_id: app.uid,
@@ -59,11 +61,14 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(Doorkeeper::Application.find_by(name: client_name)).to be_present
- body = body_as_json
-
- expect(body[:scopes]).to eq Doorkeeper.config.default_scopes.to_a
+ expect(response.parsed_body)
+ .to include(
+ scopes: Doorkeeper.config.default_scopes.to_a
+ )
end
end
@@ -75,15 +80,18 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
app = Doorkeeper::Application.find_by(name: client_name)
expect(app).to be_present
expect(app.scopes.to_s).to eq 'read'
- body = body_as_json
-
- expect(body[:scopes]).to eq ['read']
+ expect(response.parsed_body)
+ .to include(
+ scopes: %w(read)
+ )
end
end
@@ -94,6 +102,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -104,6 +114,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(Doorkeeper::Application.find_by(name: client_name).scopes.to_s).to eq 'read'
end
end
@@ -115,6 +127,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -125,6 +139,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -135,6 +151,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -146,6 +164,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -156,6 +176,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
app = Doorkeeper::Application.find_by(name: client_name)
@@ -163,10 +185,11 @@ RSpec.describe 'Apps' do
expect(app.redirect_uri).to eq redirect_uris
expect(app.redirect_uris).to eq redirect_uris.split
- body = body_as_json
-
- expect(body[:redirect_uri]).to eq redirect_uris
- expect(body[:redirect_uris]).to eq redirect_uris.split
+ expect(response.parsed_body)
+ .to include(
+ redirect_uri: redirect_uris,
+ redirect_uris: redirect_uris.split
+ )
end
end
@@ -177,6 +200,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
app = Doorkeeper::Application.find_by(name: client_name)
@@ -184,10 +209,11 @@ RSpec.describe 'Apps' do
expect(app.redirect_uri).to eq redirect_uris.join "\n"
expect(app.redirect_uris).to eq redirect_uris
- body = body_as_json
-
- expect(body[:redirect_uri]).to eq redirect_uris.join "\n"
- expect(body[:redirect_uris]).to eq redirect_uris
+ expect(response.parsed_body)
+ .to include(
+ redirect_uri: redirect_uris.join("\n"),
+ redirect_uris: redirect_uris
+ )
end
end
@@ -198,6 +224,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -208,6 +236,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -218,6 +248,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -228,6 +260,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -238,6 +272,8 @@ RSpec.describe 'Apps' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
app = Doorkeeper::Application.find_by(name: client_name)
diff --git a/spec/requests/api/v1/blocks_spec.rb b/spec/requests/api/v1/blocks_spec.rb
index c6c2d56f36..498cf93275 100644
--- a/spec/requests/api/v1/blocks_spec.rb
+++ b/spec/requests/api/v1/blocks_spec.rb
@@ -26,21 +26,20 @@ RSpec.describe 'Blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to match_array(expected_response)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match_array(expected_response)
end
context 'with limit param' do
let(:params) { { limit: 2 } }
- it 'returns only the requested number of blocked accounts' do
- subject
-
- expect(body_as_json.size).to eq(params[:limit])
- end
-
- it 'sets correct link header pagination' do
+ it 'returns only the requested number of blocked accounts and sets link header pagination' do
subject
+ expect(response.parsed_body.size).to eq(params[:limit])
+ expect(response.content_type)
+ .to start_with('application/json')
expect(response)
.to include_pagination_headers(
prev: api_v1_blocks_url(limit: params[:limit], since_id: blocks.last.id),
@@ -55,10 +54,8 @@ RSpec.describe 'Blocks' do
it 'queries the blocks in range according to max_id', :aggregate_failures do
subject
- response_body = body_as_json
-
- expect(response_body.size).to be 1
- expect(response_body[0][:id]).to eq(blocks[0].target_account.id.to_s)
+ expect(response.parsed_body)
+ .to contain_exactly(include(id: blocks.first.target_account.id.to_s))
end
end
@@ -68,10 +65,8 @@ RSpec.describe 'Blocks' do
it 'queries the blocks in range according to since_id', :aggregate_failures do
subject
- response_body = body_as_json
-
- expect(response_body.size).to be 1
- expect(response_body[0][:id]).to eq(blocks[2].target_account.id.to_s)
+ expect(response.parsed_body)
+ .to contain_exactly(include(id: blocks[2].target_account.id.to_s))
end
end
end
diff --git a/spec/requests/api/v1/bookmarks_spec.rb b/spec/requests/api/v1/bookmarks_spec.rb
index dc32820c89..c78e691236 100644
--- a/spec/requests/api/v1/bookmarks_spec.rb
+++ b/spec/requests/api/v1/bookmarks_spec.rb
@@ -24,16 +24,13 @@ RSpec.describe 'Bookmarks' do
it_behaves_like 'forbidden for wrong scope', 'write'
- it 'returns http success' do
+ it 'returns http success and the bookmarked statuses' do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the bookmarked statuses' do
- subject
-
- expect(body_as_json).to match_array(expected_response)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match_array(expected_response)
end
context 'with limit param' do
@@ -42,9 +39,11 @@ RSpec.describe 'Bookmarks' do
it 'paginates correctly', :aggregate_failures do
subject
- expect(body_as_json.size)
+ expect(response.parsed_body.size)
.to eq(params[:limit])
+ expect(response.content_type)
+ .to start_with('application/json')
expect(response)
.to include_pagination_headers(
prev: api_v1_bookmarks_url(limit: params[:limit], min_id: bookmarks.last.id),
@@ -60,6 +59,8 @@ RSpec.describe 'Bookmarks' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/conversations_spec.rb b/spec/requests/api/v1/conversations_spec.rb
index f136e1f4e8..6e2ac1df53 100644
--- a/spec/requests/api/v1/conversations_spec.rb
+++ b/spec/requests/api/v1/conversations_spec.rb
@@ -26,13 +26,15 @@ RSpec.describe 'API V1 Conversations' do
prev: api_v1_conversations_url(limit: 1, min_id: Status.first.id),
next: api_v1_conversations_url(limit: 1, max_id: Status.first.id)
)
+ expect(response.content_type)
+ .to start_with('application/json')
end
it 'returns conversations', :aggregate_failures do
get '/api/v1/conversations', headers: headers
- expect(body_as_json.size).to eq 2
- expect(body_as_json[0][:accounts].size).to eq 1
+ expect(response.parsed_body.size).to eq 2
+ expect(response.parsed_body.first[:accounts].size).to eq 1
end
context 'with since_id' do
@@ -40,7 +42,7 @@ RSpec.describe 'API V1 Conversations' do
it 'returns conversations' do
get '/api/v1/conversations', params: { since_id: Mastodon::Snowflake.id_at(1.hour.ago, with_random: false) }, headers: headers
- expect(body_as_json.size).to eq 2
+ expect(response.parsed_body.size).to eq 2
end
end
@@ -48,7 +50,7 @@ RSpec.describe 'API V1 Conversations' do
it 'returns no conversation' do
get '/api/v1/conversations', params: { since_id: Mastodon::Snowflake.id_at(1.hour.from_now, with_random: false) }, headers: headers
- expect(body_as_json.size).to eq 0
+ expect(response.parsed_body.size).to eq 0
end
end
end
diff --git a/spec/requests/api/v1/csp_spec.rb b/spec/requests/api/v1/csp_spec.rb
index 2db52ac725..5d61d7f3f5 100644
--- a/spec/requests/api/v1/csp_spec.rb
+++ b/spec/requests/api/v1/csp_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API namespace minimal Content-Security-Policy' do
+RSpec.describe 'API namespace minimal Content-Security-Policy' do
before { stub_tests_controller }
after { Rails.application.reload_routes! }
diff --git a/spec/requests/api/v1/custom_emojis_spec.rb b/spec/requests/api/v1/custom_emojis_spec.rb
index 2f0dc72944..e860fbeb17 100644
--- a/spec/requests/api/v1/custom_emojis_spec.rb
+++ b/spec/requests/api/v1/custom_emojis_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Custom Emojis' do
+RSpec.describe 'Custom Emojis' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
@@ -18,8 +18,10 @@ describe 'Custom Emojis' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_present
.and have_attributes(
first: include(shortcode: 'coolcat')
@@ -33,8 +35,10 @@ describe 'Custom Emojis' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_present
.and have_attributes(
first: include(shortcode: 'coolcat')
diff --git a/spec/requests/api/v1/directories_spec.rb b/spec/requests/api/v1/directories_spec.rb
index 0a1864d136..07e65f49b7 100644
--- a/spec/requests/api/v1/directories_spec.rb
+++ b/spec/requests/api/v1/directories_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Directories API' do
+RSpec.describe 'Directories API' do
let(:user) { Fabricate(:user, confirmed_at: nil) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:follows' }
@@ -82,8 +82,13 @@ describe 'Directories API' do
get '/api/v1/directory', headers: headers
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq(2)
- expect(body_as_json.pluck(:id)).to contain_exactly(eligible_remote_account.id.to_s, local_discoverable_account.id.to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: eligible_remote_account.id.to_s),
+ hash_including(id: local_discoverable_account.id.to_s)
+ )
end
end
@@ -101,9 +106,13 @@ describe 'Directories API' do
get '/api/v1/directory', headers: headers, params: { local: '1' }
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq(1)
- expect(body_as_json.first[:id]).to include(local_account.id.to_s)
- expect(response.body).to_not include(remote_account.id.to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: local_account.id.to_s)
+ )
+ .and not_include(remote_account.id.to_s)
end
end
@@ -115,9 +124,13 @@ describe 'Directories API' do
get '/api/v1/directory', headers: headers, params: { order: 'active' }
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq(2)
- expect(body_as_json.first[:id]).to include(new_stat.account_id.to_s)
- expect(body_as_json.second[:id]).to include(old_stat.account_id.to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: new_stat.account_id.to_s),
+ hash_including(id: old_stat.account_id.to_s)
+ )
end
end
@@ -130,9 +143,13 @@ describe 'Directories API' do
get '/api/v1/directory', headers: headers, params: { order: 'new' }
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq(2)
- expect(body_as_json.first[:id]).to include(account_new.id.to_s)
- expect(body_as_json.second[:id]).to include(account_old.id.to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: account_new.id.to_s),
+ hash_including(id: account_old.id.to_s)
+ )
end
end
end
diff --git a/spec/requests/api/v1/domain_blocks_spec.rb b/spec/requests/api/v1/domain_blocks_spec.rb
index 954497ebe1..339f49fe76 100644
--- a/spec/requests/api/v1/domain_blocks_spec.rb
+++ b/spec/requests/api/v1/domain_blocks_spec.rb
@@ -26,7 +26,9 @@ RSpec.describe 'Domain blocks' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to match_array(blocked_domains)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match_array(blocked_domains)
end
context 'with limit param' do
@@ -35,7 +37,7 @@ RSpec.describe 'Domain blocks' do
it 'returns only the requested number of blocked domains' do
subject
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.parsed_body.size).to eq(params[:limit])
end
end
end
@@ -53,6 +55,8 @@ RSpec.describe 'Domain blocks' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.domain_blocking?(params[:domain])).to be(true)
end
@@ -63,6 +67,8 @@ RSpec.describe 'Domain blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -73,6 +79,8 @@ RSpec.describe 'Domain blocks' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -94,6 +102,8 @@ RSpec.describe 'Domain blocks' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.domain_blocking?('example.com')).to be(false)
end
@@ -104,6 +114,8 @@ RSpec.describe 'Domain blocks' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/emails/confirmations_spec.rb b/spec/requests/api/v1/emails/confirmations_spec.rb
index 8f5171ee78..1408ad0506 100644
--- a/spec/requests/api/v1/emails/confirmations_spec.rb
+++ b/spec/requests/api/v1/emails/confirmations_spec.rb
@@ -26,6 +26,8 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(403)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -41,6 +43,8 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(403)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'when user changed e-mail and has not confirmed it' do
@@ -52,6 +56,8 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -61,6 +67,8 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -71,6 +79,8 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.reload.unconfirmed_email).to eq('foo@bar.com')
end
end
@@ -82,6 +92,8 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -94,6 +106,8 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -111,7 +125,9 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to be false
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to be false
end
end
@@ -122,7 +138,9 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to be true
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to be true
end
end
end
@@ -139,7 +157,9 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to be false
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to be false
end
end
@@ -150,7 +170,9 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to be true
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to be true
end
end
end
@@ -162,6 +184,8 @@ RSpec.describe 'Confirmations' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/endorsements_spec.rb b/spec/requests/api/v1/endorsements_spec.rb
index e267f2abd2..730ba6350c 100644
--- a/spec/requests/api/v1/endorsements_spec.rb
+++ b/spec/requests/api/v1/endorsements_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Endorsements' do
+RSpec.describe 'Endorsements' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
@@ -14,6 +14,8 @@ describe 'Endorsements' do
expect(response)
.to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -36,8 +38,10 @@ describe 'Endorsements' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_present
.and have_attributes(
first: include(acct: account_pin.target_account.acct)
@@ -51,8 +55,10 @@ describe 'Endorsements' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to_not be_present
end
end
diff --git a/spec/requests/api/v1/favourites_spec.rb b/spec/requests/api/v1/favourites_spec.rb
index b988ac99db..44d0239556 100644
--- a/spec/requests/api/v1/favourites_spec.rb
+++ b/spec/requests/api/v1/favourites_spec.rb
@@ -24,35 +24,29 @@ RSpec.describe 'Favourites' do
it_behaves_like 'forbidden for wrong scope', 'write'
- it 'returns http success' do
+ it 'returns http success and includes the favourites' do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the favourites' do
- subject
-
- expect(body_as_json).to match_array(expected_response)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match_array(expected_response)
end
context 'with limit param' do
let(:params) { { limit: 1 } }
- it 'returns only the requested number of favourites' do
- subject
-
- expect(body_as_json.size).to eq(params[:limit])
- end
-
- it 'sets the correct pagination headers' do
+ it 'returns only the requested number of favourites and sets pagination headers' do
subject
+ expect(response.parsed_body.size).to eq(params[:limit])
expect(response)
.to include_pagination_headers(
prev: api_v1_favourites_url(limit: params[:limit], min_id: favourites.last.id),
next: api_v1_favourites_url(limit: params[:limit], max_id: favourites.second.id)
)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -63,6 +57,8 @@ RSpec.describe 'Favourites' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/featured_tags/suggestions_spec.rb b/spec/requests/api/v1/featured_tags/suggestions_spec.rb
index 00451540ca..5fbbec5097 100644
--- a/spec/requests/api/v1/featured_tags/suggestions_spec.rb
+++ b/spec/requests/api/v1/featured_tags/suggestions_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Featured Tags Suggestions API' do
+RSpec.describe 'Featured Tags Suggestions API' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:accounts' }
@@ -32,7 +32,9 @@ describe 'Featured Tags Suggestions API' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to contain_exactly(
include(name: used_tag.name)
)
diff --git a/spec/requests/api/v1/featured_tags_spec.rb b/spec/requests/api/v1/featured_tags_spec.rb
index 4b96988704..b9c78cc11b 100644
--- a/spec/requests/api/v1/featured_tags_spec.rb
+++ b/spec/requests/api/v1/featured_tags_spec.rb
@@ -22,6 +22,8 @@ RSpec.describe 'FeaturedTags' do
get '/api/v1/featured_tags'
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -29,6 +31,8 @@ RSpec.describe 'FeaturedTags' do
get '/api/v1/featured_tags', headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'when the requesting user has no featured tag' do
@@ -37,9 +41,7 @@ RSpec.describe 'FeaturedTags' do
it 'returns an empty body' do
get '/api/v1/featured_tags', headers: headers
- body = body_as_json
-
- expect(body).to be_empty
+ expect(response.parsed_body).to be_empty
end
end
@@ -49,10 +51,10 @@ RSpec.describe 'FeaturedTags' do
it 'returns only the featured tags belonging to the requesting user' do
get '/api/v1/featured_tags', headers: headers
- body = body_as_json
- expected_ids = user_featured_tags.pluck(:id).map(&:to_s)
-
- expect(body.pluck(:id)).to match_array(expected_ids)
+ expect(response.parsed_body.pluck(:id))
+ .to match_array(
+ user_featured_tags.pluck(:id).map(&:to_s)
+ )
end
end
end
@@ -60,18 +62,16 @@ RSpec.describe 'FeaturedTags' do
describe 'POST /api/v1/featured_tags' do
let(:params) { { name: 'tag' } }
- it 'returns http success' do
+ it 'returns http success and includes correct tag name' do
post '/api/v1/featured_tags', headers: headers, params: params
expect(response).to have_http_status(200)
- end
-
- it 'returns the correct tag name' do
- post '/api/v1/featured_tags', headers: headers, params: params
-
- body = body_as_json
-
- expect(body[:name]).to eq(params[:name])
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to include(
+ name: params[:name]
+ )
end
it 'creates a new featured tag for the requesting user' do
@@ -95,6 +95,8 @@ RSpec.describe 'FeaturedTags' do
post '/api/v1/featured_tags', params: params
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -103,6 +105,8 @@ RSpec.describe 'FeaturedTags' do
post '/api/v1/featured_tags', headers: headers
expect(response).to have_http_status(400)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -113,6 +117,8 @@ RSpec.describe 'FeaturedTags' do
post '/api/v1/featured_tags', headers: headers, params: params
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -125,6 +131,8 @@ RSpec.describe 'FeaturedTags' do
post '/api/v1/featured_tags', headers: headers, params: params
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -133,25 +141,15 @@ RSpec.describe 'FeaturedTags' do
let!(:featured_tag) { FeaturedTag.create(name: 'tag', account: user.account) }
let(:id) { featured_tag.id }
- it 'returns http success' do
+ it 'returns http success with an empty body and deletes the featured tag', :inline_jobs do
delete "/api/v1/featured_tags/#{id}", headers: headers
expect(response).to have_http_status(200)
- end
-
- it 'returns an empty body' do
- delete "/api/v1/featured_tags/#{id}", headers: headers
-
- body = body_as_json
-
- expect(body).to be_empty
- end
-
- it 'deletes the featured tag', :inline_jobs do
- delete "/api/v1/featured_tags/#{id}", headers: headers
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to be_empty
featured_tag = FeaturedTag.find_by(id: id)
-
expect(featured_tag).to be_nil
end
@@ -168,6 +166,8 @@ RSpec.describe 'FeaturedTags' do
delete "/api/v1/featured_tags/#{id}"
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -176,6 +176,8 @@ RSpec.describe 'FeaturedTags' do
delete '/api/v1/featured_tags/0', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -187,6 +189,8 @@ RSpec.describe 'FeaturedTags' do
delete "/api/v1/featured_tags/#{id}", headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/filters_spec.rb b/spec/requests/api/v1/filters_spec.rb
index deb6e74217..51f03cc04d 100644
--- a/spec/requests/api/v1/filters_spec.rb
+++ b/spec/requests/api/v1/filters_spec.rb
@@ -15,7 +15,9 @@ RSpec.describe 'API V1 Filters' do
it 'returns http success' do
get '/api/v1/filters', headers: headers
expect(response).to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to contain_exactly(
include(id: custom_filter_keyword.id.to_s)
)
@@ -35,6 +37,8 @@ RSpec.describe 'API V1 Filters' do
filter = user.account.custom_filters.first
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]]
expect(filter.context).to eq %w(home)
@@ -50,6 +54,8 @@ RSpec.describe 'API V1 Filters' do
filter = user.account.custom_filters.first
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]]
expect(filter.context).to eq %w(home)
@@ -68,6 +74,8 @@ RSpec.describe 'API V1 Filters' do
get "/api/v1/filters/#{keyword.id}", headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -82,6 +90,8 @@ RSpec.describe 'API V1 Filters' do
it 'updates the filter', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(keyword.reload.phrase).to eq 'updated'
end
end
@@ -97,6 +107,8 @@ RSpec.describe 'API V1 Filters' do
it 'removes the filter', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound
end
end
diff --git a/spec/requests/api/v1/follow_requests_spec.rb b/spec/requests/api/v1/follow_requests_spec.rb
index a8898ccb3e..f0f73d38ad 100644
--- a/spec/requests/api/v1/follow_requests_spec.rb
+++ b/spec/requests/api/v1/follow_requests_spec.rb
@@ -36,7 +36,9 @@ RSpec.describe 'Follow requests' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to match_array(expected_response)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match_array(expected_response)
end
context 'with limit param' do
@@ -45,7 +47,7 @@ RSpec.describe 'Follow requests' do
it 'returns only the requested number of follow requests' do
subject
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.parsed_body.size).to eq(params[:limit])
end
end
end
@@ -66,7 +68,9 @@ RSpec.describe 'Follow requests' do
it 'allows the requesting follower to follow', :aggregate_failures do
expect { subject }.to change { follower.following?(user.account) }.from(false).to(true)
expect(response).to have_http_status(200)
- expect(body_as_json[:followed_by]).to be true
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:followed_by]).to be true
end
end
@@ -87,8 +91,10 @@ RSpec.describe 'Follow requests' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(FollowRequest.where(target_account: user.account, account: follower)).to_not exist
- expect(body_as_json[:followed_by]).to be false
+ expect(response.parsed_body[:followed_by]).to be false
end
end
end
diff --git a/spec/requests/api/v1/followed_tags_spec.rb b/spec/requests/api/v1/followed_tags_spec.rb
index 3d2d82d5db..b0191b523f 100644
--- a/spec/requests/api/v1/followed_tags_spec.rb
+++ b/spec/requests/api/v1/followed_tags_spec.rb
@@ -28,29 +28,24 @@ RSpec.describe 'Followed tags' do
it_behaves_like 'forbidden for wrong scope', 'write write:follows'
- it 'returns http success' do
+ it 'returns http success and includes followed tags' do
subject
expect(response).to have_http_status(:success)
- end
-
- it 'returns the followed tags correctly' do
- subject
-
- expect(body_as_json).to match_array(expected_response)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match_array(expected_response)
end
context 'with limit param' do
let(:params) { { limit: 1 } }
- it 'returns only the requested number of follow tags' do
+ it 'returns only the requested number of follow tags and sets pagination headers' do
subject
- expect(body_as_json.size).to eq(params[:limit])
- end
-
- it 'sets the correct pagination headers' do
- subject
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.size).to eq(params[:limit])
expect(response)
.to include_pagination_headers(
diff --git a/spec/requests/api/v1/instance_spec.rb b/spec/requests/api/v1/instance_spec.rb
index 600584eccb..62c90f55b2 100644
--- a/spec/requests/api/v1/instance_spec.rb
+++ b/spec/requests/api/v1/instance_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Instances' do
+RSpec.describe 'Instances' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
@@ -14,8 +14,10 @@ describe 'Instances' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_present
.and include(title: 'Mastodon Glitch Edition')
end
@@ -27,8 +29,10 @@ describe 'Instances' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_present
.and include(title: 'Mastodon Glitch Edition')
end
diff --git a/spec/requests/api/v1/instances/activity_spec.rb b/spec/requests/api/v1/instances/activity_spec.rb
index 4f2bc91ad6..c2f94cc578 100644
--- a/spec/requests/api/v1/instances/activity_spec.rb
+++ b/spec/requests/api/v1/instances/activity_spec.rb
@@ -13,7 +13,10 @@ RSpec.describe 'Activity' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
.to be_present
.and(be_an(Array))
.and(have_attributes(size: Api::V1::Instances::ActivityController::WEEKS_OF_ACTIVITY))
diff --git a/spec/requests/api/v1/instances/domain_blocks_spec.rb b/spec/requests/api/v1/instances/domain_blocks_spec.rb
index 397ecff084..b214fda73b 100644
--- a/spec/requests/api/v1/instances/domain_blocks_spec.rb
+++ b/spec/requests/api/v1/instances/domain_blocks_spec.rb
@@ -17,7 +17,10 @@ RSpec.describe 'Domain Blocks' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
.to be_present
.and(be_an(Array))
.and(have_attributes(size: 1))
diff --git a/spec/requests/api/v1/instances/extended_descriptions_spec.rb b/spec/requests/api/v1/instances/extended_descriptions_spec.rb
index 64982de686..62a7fff2ec 100644
--- a/spec/requests/api/v1/instances/extended_descriptions_spec.rb
+++ b/spec/requests/api/v1/instances/extended_descriptions_spec.rb
@@ -9,8 +9,10 @@ RSpec.describe 'Extended Descriptions' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_present
.and include(:content)
end
diff --git a/spec/requests/api/v1/instances/languages_spec.rb b/spec/requests/api/v1/instances/languages_spec.rb
index 8ab8bf99ce..3d188d23c0 100644
--- a/spec/requests/api/v1/instances/languages_spec.rb
+++ b/spec/requests/api/v1/instances/languages_spec.rb
@@ -8,12 +8,11 @@ RSpec.describe 'Languages' do
get '/api/v1/instance/languages'
end
- it 'returns http success' do
+ it 'returns http success and includes supported languages' do
expect(response).to have_http_status(200)
- end
-
- it 'returns the supported languages' do
- expect(body_as_json.pluck(:code)).to match_array LanguagesHelper::SUPPORTED_LOCALES.keys.map(&:to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.pluck(:code)).to match_array LanguagesHelper::SUPPORTED_LOCALES.keys.map(&:to_s)
end
end
end
diff --git a/spec/requests/api/v1/instances/peers_spec.rb b/spec/requests/api/v1/instances/peers_spec.rb
index 1a7975f8b7..8ebfc93357 100644
--- a/spec/requests/api/v1/instances/peers_spec.rb
+++ b/spec/requests/api/v1/instances/peers_spec.rb
@@ -12,8 +12,10 @@ RSpec.describe 'Peers' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_an(Array)
end
end
diff --git a/spec/requests/api/v1/instances/privacy_policies_spec.rb b/spec/requests/api/v1/instances/privacy_policies_spec.rb
index 24de98d880..519c2b29d0 100644
--- a/spec/requests/api/v1/instances/privacy_policies_spec.rb
+++ b/spec/requests/api/v1/instances/privacy_policies_spec.rb
@@ -9,8 +9,10 @@ RSpec.describe 'Privacy Policy' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_present
.and include(:content)
end
diff --git a/spec/requests/api/v1/instances/rules_spec.rb b/spec/requests/api/v1/instances/rules_spec.rb
index 65b8d78c7d..b730048863 100644
--- a/spec/requests/api/v1/instances/rules_spec.rb
+++ b/spec/requests/api/v1/instances/rules_spec.rb
@@ -9,8 +9,10 @@ RSpec.describe 'Rules' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_an(Array)
end
end
diff --git a/spec/requests/api/v1/instances/translation_languages_spec.rb b/spec/requests/api/v1/instances/translation_languages_spec.rb
index 0b7dd8314d..fef8700db9 100644
--- a/spec/requests/api/v1/instances/translation_languages_spec.rb
+++ b/spec/requests/api/v1/instances/translation_languages_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Translation Languages' do
+RSpec.describe 'Translation Languages' do
describe 'GET /api/v1/instances/translation_languages' do
context 'when no translation service is configured' do
it 'returns empty language matrix', :aggregate_failures do
@@ -10,8 +10,10 @@ describe 'Translation Languages' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to eq({})
end
end
@@ -24,9 +26,11 @@ describe 'Translation Languages' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
- .to eq({ und: %w(en de), en: ['de'] })
+ expect(response.parsed_body)
+ .to match({ und: %w(en de), en: ['de'] })
end
private
diff --git a/spec/requests/api/v1/lists/accounts_spec.rb b/spec/requests/api/v1/lists/accounts_spec.rb
index de49982351..3911d1f28b 100644
--- a/spec/requests/api/v1/lists/accounts_spec.rb
+++ b/spec/requests/api/v1/lists/accounts_spec.rb
@@ -34,7 +34,9 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to match_array(expected_response)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match_array(expected_response)
end
context 'with limit param' do
@@ -43,7 +45,7 @@ RSpec.describe 'Accounts' do
it 'returns only the requested number of accounts' do
subject
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.parsed_body.size).to eq(params[:limit])
end
end
end
@@ -68,6 +70,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(list.accounts).to include(bob)
end
end
@@ -81,6 +85,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(list.accounts).to include(bob)
end
end
@@ -90,6 +96,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(list.accounts).to_not include(bob)
end
end
@@ -105,6 +113,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -118,6 +128,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -139,16 +151,13 @@ RSpec.describe 'Accounts' do
list.accounts << [bob, peter]
end
- it 'removes the specified account from the list', :aggregate_failures do
+ it 'removes the specified account from the list but keeps other accounts in the list', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(list.accounts).to_not include(bob)
- end
-
- it 'does not remove any other account from the list' do
- subject
-
expect(list.accounts).to include(peter)
end
@@ -159,6 +168,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(list.accounts).to contain_exactly(bob, peter)
end
end
@@ -172,6 +183,8 @@ RSpec.describe 'Accounts' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/lists_spec.rb b/spec/requests/api/v1/lists_spec.rb
index 4635e936f5..20f27a7431 100644
--- a/spec/requests/api/v1/lists_spec.rb
+++ b/spec/requests/api/v1/lists_spec.rb
@@ -43,7 +43,9 @@ RSpec.describe 'Lists' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to match_array(expected_response)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match_array(expected_response)
end
end
@@ -60,7 +62,9 @@ RSpec.describe 'Lists' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to eq({
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match({
id: list.id.to_s,
title: list.title,
replies_policy: list.replies_policy,
@@ -75,6 +79,8 @@ RSpec.describe 'Lists' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -83,6 +89,8 @@ RSpec.describe 'Lists' do
get '/api/v1/lists/-1', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -100,7 +108,9 @@ RSpec.describe 'Lists' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to match(a_hash_including(title: 'my list', replies_policy: 'none', exclusive: true))
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match(a_hash_including(title: 'my list', replies_policy: 'none', exclusive: true))
expect(List.where(account: user.account).count).to eq(1)
end
@@ -111,6 +121,8 @@ RSpec.describe 'Lists' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -121,6 +133,8 @@ RSpec.describe 'Lists' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -142,9 +156,11 @@ RSpec.describe 'Lists' do
.and change_list_exclusive
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
list.reload
- expect(body_as_json).to eq({
+ expect(response.parsed_body).to match({
id: list.id.to_s,
title: list.title,
replies_policy: list.replies_policy,
@@ -169,6 +185,8 @@ RSpec.describe 'Lists' do
put '/api/v1/lists/-1', headers: headers, params: params
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -179,6 +197,8 @@ RSpec.describe 'Lists' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -196,6 +216,8 @@ RSpec.describe 'Lists' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(List.where(id: list.id)).to_not exist
end
@@ -214,6 +236,8 @@ RSpec.describe 'Lists' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/markers_spec.rb b/spec/requests/api/v1/markers_spec.rb
index b04adf2594..d7cd78924b 100644
--- a/spec/requests/api/v1/markers_spec.rb
+++ b/spec/requests/api/v1/markers_spec.rb
@@ -17,13 +17,14 @@ RSpec.describe 'API Markers' do
end
it 'returns markers', :aggregate_failures do
- json = body_as_json
-
expect(response).to have_http_status(200)
- expect(json.key?(:home)).to be true
- expect(json[:home][:last_read_id]).to eq '123'
- expect(json.key?(:notifications)).to be true
- expect(json[:notifications][:last_read_id]).to eq '456'
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to include(
+ home: include(last_read_id: '123'),
+ notifications: include(last_read_id: '456')
+ )
end
end
@@ -35,6 +36,8 @@ RSpec.describe 'API Markers' do
it 'creates a marker', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.markers.first.timeline).to eq 'home'
expect(user.markers.first.last_read_id).to eq 69_420
end
@@ -48,6 +51,8 @@ RSpec.describe 'API Markers' do
it 'updates a marker', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.markers.first.timeline).to eq 'home'
expect(user.markers.first.last_read_id).to eq 70_120
end
@@ -62,7 +67,9 @@ RSpec.describe 'API Markers' do
it 'returns error json' do
expect(response)
.to have_http_status(409)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to include(error: /Conflict during update/)
end
end
diff --git a/spec/requests/api/v1/media_spec.rb b/spec/requests/api/v1/media_spec.rb
index c89c49afdf..d7d0b92f11 100644
--- a/spec/requests/api/v1/media_spec.rb
+++ b/spec/requests/api/v1/media_spec.rb
@@ -17,16 +17,13 @@ RSpec.describe 'Media' do
it_behaves_like 'forbidden for wrong scope', 'read'
- it 'returns http success' do
+ it 'returns http success with media information' do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the media information' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match(
a_hash_including(
id: media.id.to_s,
description: media.description,
@@ -44,6 +41,8 @@ RSpec.describe 'Media' do
subject
expect(response).to have_http_status(206)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -54,6 +53,8 @@ RSpec.describe 'Media' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -64,6 +65,8 @@ RSpec.describe 'Media' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -80,10 +83,12 @@ RSpec.describe 'Media' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(MediaAttachment.first).to be_present
expect(MediaAttachment.first).to have_attached_file(:file)
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(id: MediaAttachment.first.id.to_s, description: params[:description], type: media_type)
)
end
@@ -107,6 +112,8 @@ RSpec.describe 'Media' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -117,6 +124,8 @@ RSpec.describe 'Media' do
subject
expect(response).to have_http_status(500)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -158,6 +167,8 @@ RSpec.describe 'Media' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -176,6 +187,8 @@ RSpec.describe 'Media' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/mutes_spec.rb b/spec/requests/api/v1/mutes_spec.rb
index 019bf16584..61e32cb9ae 100644
--- a/spec/requests/api/v1/mutes_spec.rb
+++ b/spec/requests/api/v1/mutes_spec.rb
@@ -18,32 +18,26 @@ RSpec.describe 'Mutes' do
it_behaves_like 'forbidden for wrong scope', 'write write:mutes'
- it 'returns http success' do
+ it 'returns http success with muted accounts' do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the muted accounts' do
- subject
+ expect(response.content_type)
+ .to start_with('application/json')
muted_accounts = mutes.map(&:target_account)
-
- expect(body_as_json.pluck(:id)).to match_array(muted_accounts.map { |account| account.id.to_s })
+ expect(response.parsed_body.pluck(:id)).to match_array(muted_accounts.map { |account| account.id.to_s })
end
context 'with limit param' do
let(:params) { { limit: 1 } }
- it 'returns only the requested number of muted accounts' do
- subject
-
- expect(body_as_json.size).to eq(params[:limit])
- end
-
- it 'sets the correct pagination headers', :aggregate_failures do
+ it 'returns only the requested number of muted accounts with pagination headers' do
subject
+ expect(response.parsed_body.size).to eq(params[:limit])
+ expect(response.content_type)
+ .to start_with('application/json')
expect(response)
.to include_pagination_headers(
prev: api_v1_mutes_url(limit: params[:limit], since_id: mutes.last.id),
@@ -58,10 +52,8 @@ RSpec.describe 'Mutes' do
it 'queries mutes in range according to max_id', :aggregate_failures do
subject
- body = body_as_json
-
- expect(body.size).to eq 1
- expect(body[0][:id]).to eq mutes[0].target_account_id.to_s
+ expect(response.parsed_body)
+ .to contain_exactly(include(id: mutes.first.target_account_id.to_s))
end
end
@@ -71,10 +63,8 @@ RSpec.describe 'Mutes' do
it 'queries mutes in range according to since_id', :aggregate_failures do
subject
- body = body_as_json
-
- expect(body.size).to eq 1
- expect(body[0][:id]).to eq mutes[1].target_account_id.to_s
+ expect(response.parsed_body)
+ .to contain_exactly(include(id: mutes[1].target_account_id.to_s))
end
end
@@ -85,6 +75,8 @@ RSpec.describe 'Mutes' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/notifications/policies_spec.rb b/spec/requests/api/v1/notifications/policies_spec.rb
index a73d4217be..ac24501526 100644
--- a/spec/requests/api/v1/notifications/policies_spec.rb
+++ b/spec/requests/api/v1/notifications/policies_spec.rb
@@ -26,7 +26,9 @@ RSpec.describe 'Policies' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to include(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to include(
filter_not_following: false,
filter_not_followers: false,
filter_new_accounts: false,
@@ -54,7 +56,9 @@ RSpec.describe 'Policies' do
.to change { NotificationPolicy.find_or_initialize_by(account: user.account).for_not_following.to_sym }.from(:accept).to(:filter)
expect(response).to have_http_status(200)
- expect(body_as_json).to include(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to include(
filter_not_following: true,
filter_not_followers: false,
filter_new_accounts: false,
diff --git a/spec/requests/api/v1/notifications/requests_spec.rb b/spec/requests/api/v1/notifications/requests_spec.rb
index c385fb3499..bee9d3a3da 100644
--- a/spec/requests/api/v1/notifications/requests_spec.rb
+++ b/spec/requests/api/v1/notifications/requests_spec.rb
@@ -26,6 +26,8 @@ RSpec.describe 'Requests' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -39,15 +41,12 @@ RSpec.describe 'Requests' do
it_behaves_like 'forbidden for wrong scope', 'read read:notifications'
- it 'returns http success' do
+ it 'returns http success and creates notification permission' do
subject
expect(response).to have_http_status(200)
- end
-
- it 'creates notification permission' do
- subject
-
+ expect(response.content_type)
+ .to start_with('application/json')
expect(NotificationPermission.find_by(account: notification_request.account, from_account: notification_request.from_account)).to_not be_nil
end
@@ -58,6 +57,8 @@ RSpec.describe 'Requests' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -75,6 +76,8 @@ RSpec.describe 'Requests' do
expect { subject }.to change(NotificationRequest, :count).by(-1)
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'when notification request belongs to someone else' do
@@ -84,6 +87,8 @@ RSpec.describe 'Requests' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -102,6 +107,8 @@ RSpec.describe 'Requests' do
expect(NotificationPermission.find_by(account: notification_request.account, from_account: notification_request.from_account)).to_not be_nil
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -118,6 +125,8 @@ RSpec.describe 'Requests' do
expect { subject }.to change(NotificationRequest, :count).by(-1)
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -133,7 +142,9 @@ RSpec.describe 'Requests' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to eq({ merged: true })
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match({ merged: true })
end
end
@@ -146,7 +157,9 @@ RSpec.describe 'Requests' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to eq({ merged: false })
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match({ merged: false })
end
end
end
diff --git a/spec/requests/api/v1/notifications_spec.rb b/spec/requests/api/v1/notifications_spec.rb
index 84e6db1e51..0e8eb6ad3b 100644
--- a/spec/requests/api/v1/notifications_spec.rb
+++ b/spec/requests/api/v1/notifications_spec.rb
@@ -31,7 +31,9 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:count]).to eq 5
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq 5
end
end
@@ -45,7 +47,9 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:count]).to eq 2
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq 2
end
end
@@ -56,7 +60,9 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:count]).to eq 4
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq 4
end
end
@@ -67,7 +73,9 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:count]).to eq 2
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq 2
end
end
@@ -80,7 +88,9 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:count]).to eq Api::V1::NotificationsController::DEFAULT_NOTIFICATIONS_COUNT_LIMIT
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq Api::V1::NotificationsController::DEFAULT_NOTIFICATIONS_COUNT_LIMIT
end
end
end
@@ -111,9 +121,11 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq 5
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.size).to eq 5
expect(body_json_types).to include('reblog', 'mention', 'favourite', 'follow')
- expect(body_as_json.any? { |x| x[:filtered] }).to be false
+ expect(response.parsed_body.any? { |x| x[:filtered] }).to be false
end
end
@@ -124,9 +136,11 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq 6
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.size).to eq 6
expect(body_json_types).to include('reblog', 'mention', 'favourite', 'follow')
- expect(body_as_json.any? { |x| x[:filtered] }).to be true
+ expect(response.parsed_body.any? { |x| x[:filtered] }).to be true
end
end
@@ -137,11 +151,13 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(body_json_account_ids.uniq).to eq [tom.account.id.to_s]
end
def body_json_account_ids
- body_as_json.map { |x| x[:account][:id] }
+ response.parsed_body.map { |x| x[:account][:id] }
end
end
@@ -152,7 +168,9 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq 0
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.size).to eq 0
end
end
@@ -163,7 +181,9 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.size).to_not eq 0
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.size).to_not eq 0
expect(body_json_types.uniq).to_not include 'mention'
end
end
@@ -175,6 +195,8 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(body_json_types.uniq).to eq ['mention']
end
end
@@ -187,7 +209,7 @@ RSpec.describe 'Notifications' do
notifications = user.account.notifications.browserable.order(id: :asc)
- expect(body_as_json.size)
+ expect(response.parsed_body.size)
.to eq(params[:limit])
expect(response)
@@ -199,7 +221,7 @@ RSpec.describe 'Notifications' do
end
def body_json_types
- body_as_json.pluck(:type)
+ response.parsed_body.pluck(:type)
end
end
@@ -216,6 +238,8 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'when notification belongs to someone else' do
@@ -225,6 +249,8 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -242,6 +268,8 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect { notification.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
@@ -252,6 +280,8 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -272,6 +302,8 @@ RSpec.describe 'Notifications' do
expect(user.account.reload.notifications).to be_empty
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/peers/search_spec.rb b/spec/requests/api/v1/peers/search_spec.rb
index dcdea387a5..afcc141902 100644
--- a/spec/requests/api/v1/peers/search_spec.rb
+++ b/spec/requests/api/v1/peers/search_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API Peers Search' do
+RSpec.describe 'API Peers Search' do
describe 'GET /api/v1/peers/search' do
context 'when peers api is disabled' do
before do
@@ -23,7 +23,9 @@ describe 'API Peers Search' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to be_blank
end
end
@@ -34,7 +36,9 @@ describe 'API Peers Search' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to be_blank
end
end
@@ -49,10 +53,12 @@ describe 'API Peers Search' do
expect(response)
.to have_http_status(200)
- expect(body_as_json.size)
- .to eq(1)
- expect(body_as_json.first)
- .to eq(account.domain)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ eq(account.domain)
+ )
end
end
end
diff --git a/spec/requests/api/v1/polls/votes_spec.rb b/spec/requests/api/v1/polls/votes_spec.rb
index 669f64b6e4..d3f7eb431d 100644
--- a/spec/requests/api/v1/polls/votes_spec.rb
+++ b/spec/requests/api/v1/polls/votes_spec.rb
@@ -18,6 +18,8 @@ RSpec.describe 'API V1 Polls Votes' do
it 'creates a vote', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(vote).to_not be_nil
expect(vote.choice).to eq 1
@@ -30,6 +32,8 @@ RSpec.describe 'API V1 Polls Votes' do
it 'returns http bad request' do
expect(response).to have_http_status(400)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
diff --git a/spec/requests/api/v1/polls_spec.rb b/spec/requests/api/v1/polls_spec.rb
index 1c8a818d59..fd38297931 100644
--- a/spec/requests/api/v1/polls_spec.rb
+++ b/spec/requests/api/v1/polls_spec.rb
@@ -23,7 +23,9 @@ RSpec.describe 'Polls' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to match(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match(
a_hash_including(
id: poll.id.to_s,
voted: false,
@@ -41,6 +43,8 @@ RSpec.describe 'Polls' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/preferences_spec.rb b/spec/requests/api/v1/preferences_spec.rb
index 6f4188c35a..e03b9cf108 100644
--- a/spec/requests/api/v1/preferences_spec.rb
+++ b/spec/requests/api/v1/preferences_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Preferences' do
+RSpec.describe 'Preferences' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
@@ -14,6 +14,8 @@ describe 'Preferences' do
expect(response)
.to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -34,7 +36,10 @@ describe 'Preferences' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
.to be_present
end
end
diff --git a/spec/requests/api/v1/profiles_spec.rb b/spec/requests/api/v1/profiles_spec.rb
index 26a9b848e5..fd3ab4bf58 100644
--- a/spec/requests/api/v1/profiles_spec.rb
+++ b/spec/requests/api/v1/profiles_spec.rb
@@ -28,31 +28,16 @@ RSpec.describe 'Deleting profile images' do
it_behaves_like 'forbidden for wrong scope', 'read'
end
- it 'returns http success' do
+ it 'returns http success and deletes the avatar, preserves the header, queues up distribution' do
delete '/api/v1/profile/avatar', headers: headers
expect(response).to have_http_status(200)
- end
-
- it 'deletes the avatar' do
- delete '/api/v1/profile/avatar', headers: headers
+ expect(response.content_type)
+ .to start_with('application/json')
account.reload
-
expect(account.avatar).to_not exist
- end
-
- it 'does not delete the header' do
- delete '/api/v1/profile/avatar', headers: headers
-
- account.reload
-
expect(account.header).to exist
- end
-
- it 'queues up an account update distribution' do
- delete '/api/v1/profile/avatar', headers: headers
-
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
end
end
@@ -66,31 +51,16 @@ RSpec.describe 'Deleting profile images' do
it_behaves_like 'forbidden for wrong scope', 'read'
end
- it 'returns http success' do
+ it 'returns http success, preserves the avatar, deletes the header, queues up distribution' do
delete '/api/v1/profile/header', headers: headers
expect(response).to have_http_status(200)
- end
-
- it 'does not delete the avatar' do
- delete '/api/v1/profile/header', headers: headers
+ expect(response.content_type)
+ .to start_with('application/json')
account.reload
-
expect(account.avatar).to exist
- end
-
- it 'deletes the header' do
- delete '/api/v1/profile/header', headers: headers
-
- account.reload
-
expect(account.header).to_not exist
- end
-
- it 'queues up an account update distribution' do
- delete '/api/v1/profile/header', headers: headers
-
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
end
end
diff --git a/spec/requests/api/v1/push/subscriptions_spec.rb b/spec/requests/api/v1/push/subscriptions_spec.rb
index 54ef5a13ad..8ad672c95e 100644
--- a/spec/requests/api/v1/push/subscriptions_spec.rb
+++ b/spec/requests/api/v1/push/subscriptions_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Push Subscriptions' do
+RSpec.describe 'API V1 Push Subscriptions' do
let(:user) { Fabricate(:user) }
let(:endpoint) { 'https://fcm.googleapis.com/fcm/send/fiuH06a27qE:APA91bHnSiGcLwdaxdyqVXNDR9w1NlztsHb6lyt5WDKOC_Z_Q8BlFxQoR8tWFSXUIDdkyw0EdvxTu63iqamSaqVSevW5LfoFwojws8XYDXv_NRRLH6vo2CdgiN4jgHv5VLt2A8ah6lUX' }
let(:keys) do
@@ -45,6 +45,8 @@ describe 'API V1 Push Subscriptions' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(endpoint_push_subscriptions.count).to eq(0)
expect(endpoint_push_subscription).to be_nil
end
@@ -65,7 +67,7 @@ describe 'API V1 Push Subscriptions' do
access_token_id: eq(token.id)
)
- expect(body_as_json.with_indifferent_access)
+ expect(response.parsed_body.with_indifferent_access)
.to include(
{ endpoint: create_payload[:subscription][:endpoint], alerts: {}, policy: 'all' }
)
@@ -124,7 +126,7 @@ describe 'API V1 Push Subscriptions' do
)
end
- expect(body_as_json.with_indifferent_access)
+ expect(response.parsed_body.with_indifferent_access)
.to include(
endpoint: create_payload[:subscription][:endpoint],
alerts: alerts_payload[:data][:alerts],
diff --git a/spec/requests/api/v1/reports_spec.rb b/spec/requests/api/v1/reports_spec.rb
index a72d9bbcd8..18b894bf63 100644
--- a/spec/requests/api/v1/reports_spec.rb
+++ b/spec/requests/api/v1/reports_spec.rb
@@ -37,7 +37,9 @@ RSpec.describe 'Reports' do
emails = capture_emails { subject }
expect(response).to have_http_status(200)
- expect(body_as_json).to match(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match(
a_hash_including(
status_ids: [status.id.to_s],
category: category,
@@ -65,6 +67,8 @@ RSpec.describe 'Reports' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
diff --git a/spec/requests/api/v1/scheduled_status_spec.rb b/spec/requests/api/v1/scheduled_status_spec.rb
index f4612410bf..3a1b81ce65 100644
--- a/spec/requests/api/v1/scheduled_status_spec.rb
+++ b/spec/requests/api/v1/scheduled_status_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Scheduled Statuses' do
+RSpec.describe 'Scheduled Statuses' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
@@ -14,6 +14,8 @@ describe 'Scheduled Statuses' do
expect(response)
.to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -33,6 +35,8 @@ describe 'Scheduled Statuses' do
expect(response)
.to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -45,8 +49,10 @@ describe 'Scheduled Statuses' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to_not be_present
end
end
@@ -59,8 +65,10 @@ describe 'Scheduled Statuses' do
expect(response)
.to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json)
+ expect(response.parsed_body)
.to be_present
.and have_attributes(
first: include(id: scheduled_status.id.to_s)
diff --git a/spec/requests/api/v1/statuses/bookmarks_spec.rb b/spec/requests/api/v1/statuses/bookmarks_spec.rb
index d3007740a5..583f5b6a0e 100644
--- a/spec/requests/api/v1/statuses/bookmarks_spec.rb
+++ b/spec/requests/api/v1/statuses/bookmarks_spec.rb
@@ -18,17 +18,15 @@ RSpec.describe 'Bookmarks' do
it_behaves_like 'forbidden for wrong scope', 'read'
context 'with public status' do
- it 'bookmarks the status successfully', :aggregate_failures do
+ it 'bookmarks the status successfully and includes updated json', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.bookmarked?(status)).to be true
- end
- it 'returns json with updated attributes' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(id: status.id.to_s, bookmarked: true)
)
end
@@ -41,6 +39,8 @@ RSpec.describe 'Bookmarks' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -55,6 +55,8 @@ RSpec.describe 'Bookmarks' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.bookmarked?(status)).to be true
end
end
@@ -64,6 +66,8 @@ RSpec.describe 'Bookmarks' do
post '/api/v1/statuses/-1/bookmark', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -74,6 +78,8 @@ RSpec.describe 'Bookmarks' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -93,17 +99,15 @@ RSpec.describe 'Bookmarks' do
Bookmark.find_or_create_by!(account: user.account, status: status)
end
- it 'unbookmarks the status successfully', :aggregate_failures do
+ it 'unbookmarks the status successfully and includes updated json', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.bookmarked?(status)).to be false
- end
- it 'returns json with updated attributes' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(id: status.id.to_s, bookmarked: false)
)
end
@@ -117,17 +121,15 @@ RSpec.describe 'Bookmarks' do
status.account.block!(user.account)
end
- it 'unbookmarks the status successfully', :aggregate_failures do
+ it 'unbookmarks the status successfully and includes updated json', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.bookmarked?(status)).to be false
- end
- it 'returns json with updated attributes' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(id: status.id.to_s, bookmarked: false)
)
end
@@ -138,6 +140,8 @@ RSpec.describe 'Bookmarks' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -149,6 +153,8 @@ RSpec.describe 'Bookmarks' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb b/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb
index 2fd79f424b..441664d099 100644
--- a/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb
+++ b/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb
@@ -33,10 +33,10 @@ RSpec.describe 'API V1 Statuses Favourited by Accounts' do
prev: api_v1_status_favourited_by_index_url(limit: 2, since_id: Favourite.last.id),
next: api_v1_status_favourited_by_index_url(limit: 2, max_id: Favourite.first.id)
)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json.size)
- .to eq(2)
- expect(body_as_json)
+ expect(response.parsed_body)
.to contain_exactly(
include(id: alice.id.to_s),
include(id: bob.id.to_s)
@@ -48,9 +48,10 @@ RSpec.describe 'API V1 Statuses Favourited by Accounts' do
subject
- expect(body_as_json.size)
- .to eq 1
- expect(body_as_json.first[:id]).to eq(alice.id.to_s)
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: alice.id.to_s)
+ )
end
end
end
@@ -72,6 +73,8 @@ RSpec.describe 'API V1 Statuses Favourited by Accounts' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -88,6 +91,8 @@ RSpec.describe 'API V1 Statuses Favourited by Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/statuses/favourites_spec.rb b/spec/requests/api/v1/statuses/favourites_spec.rb
index 22d0e4831f..3d1021e29d 100644
--- a/spec/requests/api/v1/statuses/favourites_spec.rb
+++ b/spec/requests/api/v1/statuses/favourites_spec.rb
@@ -18,17 +18,15 @@ RSpec.describe 'Favourites', :inline_jobs do
it_behaves_like 'forbidden for wrong scope', 'read read:favourites'
context 'with public status' do
- it 'favourites the status successfully', :aggregate_failures do
+ it 'favourites the status successfully and includes updated json', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.favourited?(status)).to be true
- end
- it 'returns json with updated attributes' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(id: status.id.to_s, favourites_count: 1, favourited: true)
)
end
@@ -41,6 +39,8 @@ RSpec.describe 'Favourites', :inline_jobs do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -55,6 +55,8 @@ RSpec.describe 'Favourites', :inline_jobs do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.favourited?(status)).to be true
end
end
@@ -66,6 +68,8 @@ RSpec.describe 'Favourites', :inline_jobs do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -84,18 +88,16 @@ RSpec.describe 'Favourites', :inline_jobs do
FavouriteService.new.call(user.account, status)
end
- it 'unfavourites the status successfully', :aggregate_failures do
+ it 'unfavourites the status successfully and includes updated json', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.favourited?(status)).to be false
- end
- it 'returns json with updated attributes' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(id: status.id.to_s, favourites_count: 0, favourited: false)
)
end
@@ -107,18 +109,16 @@ RSpec.describe 'Favourites', :inline_jobs do
status.account.block!(user.account)
end
- it 'unfavourites the status successfully', :aggregate_failures do
+ it 'unfavourites the status successfully and includes updated json', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.favourited?(status)).to be false
- end
- it 'returns json with updated attributes' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(id: status.id.to_s, favourites_count: 0, favourited: false)
)
end
@@ -129,6 +129,8 @@ RSpec.describe 'Favourites', :inline_jobs do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -139,6 +141,8 @@ RSpec.describe 'Favourites', :inline_jobs do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/statuses/histories_spec.rb b/spec/requests/api/v1/statuses/histories_spec.rb
index b3761ca688..9c7f93d343 100644
--- a/spec/requests/api/v1/statuses/histories_spec.rb
+++ b/spec/requests/api/v1/statuses/histories_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Statuses Histories' do
+RSpec.describe 'API V1 Statuses Histories' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:statuses' }
@@ -18,7 +18,9 @@ describe 'API V1 Statuses Histories' do
it 'returns http success' do
expect(response).to have_http_status(200)
- expect(body_as_json.size).to_not be 0
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.size).to_not be 0
end
end
end
diff --git a/spec/requests/api/v1/statuses/mutes_spec.rb b/spec/requests/api/v1/statuses/mutes_spec.rb
index 72fd7d9d11..55313482d6 100644
--- a/spec/requests/api/v1/statuses/mutes_spec.rb
+++ b/spec/requests/api/v1/statuses/mutes_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Statuses Mutes' do
+RSpec.describe 'API V1 Statuses Mutes' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'write:mutes' }
@@ -18,6 +18,8 @@ describe 'API V1 Statuses Mutes' do
it 'creates a conversation mute', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to_not be_nil
end
end
@@ -32,6 +34,8 @@ describe 'API V1 Statuses Mutes' do
it 'destroys the conversation mute', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to be_nil
end
end
diff --git a/spec/requests/api/v1/statuses/pins_spec.rb b/spec/requests/api/v1/statuses/pins_spec.rb
index db07fa424f..05d8f570cc 100644
--- a/spec/requests/api/v1/statuses/pins_spec.rb
+++ b/spec/requests/api/v1/statuses/pins_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Pins' do
+RSpec.describe 'Pins' do
let(:user) { Fabricate(:user) }
let(:scopes) { 'write:accounts' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -18,17 +18,15 @@ describe 'Pins' do
it_behaves_like 'forbidden for wrong scope', 'read read:accounts'
context 'when the status is public' do
- it 'pins the status successfully', :aggregate_failures do
+ it 'pins the status successfully and returns updated json', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.pinned?(status)).to be true
- end
- it 'return json with updated attributes' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(id: status.id.to_s, pinned: true)
)
end
@@ -41,6 +39,8 @@ describe 'Pins' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.pinned?(status)).to be true
end
end
@@ -52,6 +52,8 @@ describe 'Pins' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -60,6 +62,8 @@ describe 'Pins' do
post '/api/v1/statuses/-1/pin', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -70,6 +74,8 @@ describe 'Pins' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -86,17 +92,15 @@ describe 'Pins' do
Fabricate(:status_pin, status: status, account: user.account)
end
- it 'unpins the status successfully', :aggregate_failures do
+ it 'unpins the status successfully and includes updated json', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(user.account.pinned?(status)).to be false
- end
- it 'return json with updated attributes' do
- subject
-
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
a_hash_including(id: status.id.to_s, pinned: false)
)
end
@@ -107,6 +111,8 @@ describe 'Pins' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -115,6 +121,8 @@ describe 'Pins' do
post '/api/v1/statuses/-1/unpin', headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -125,6 +133,8 @@ describe 'Pins' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb b/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb
index 5fc54042f9..824b5aa275 100644
--- a/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb
+++ b/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb
@@ -32,10 +32,10 @@ RSpec.describe 'API V1 Statuses Reblogged by Accounts' do
prev: api_v1_status_reblogged_by_index_url(limit: 2, since_id: bob.statuses.first.id),
next: api_v1_status_reblogged_by_index_url(limit: 2, max_id: alice.statuses.first.id)
)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json.size)
- .to eq(2)
- expect(body_as_json)
+ expect(response.parsed_body)
.to contain_exactly(
include(id: alice.id.to_s),
include(id: bob.id.to_s)
@@ -47,9 +47,10 @@ RSpec.describe 'API V1 Statuses Reblogged by Accounts' do
subject
- expect(body_as_json.size)
- .to eq 1
- expect(body_as_json.first[:id]).to eq(alice.id.to_s)
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: alice.id.to_s)
+ )
end
end
end
@@ -71,6 +72,8 @@ RSpec.describe 'API V1 Statuses Reblogged by Accounts' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -87,6 +90,8 @@ RSpec.describe 'API V1 Statuses Reblogged by Accounts' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/statuses/reblogs_spec.rb b/spec/requests/api/v1/statuses/reblogs_spec.rb
index 503d804ed0..5e88690074 100644
--- a/spec/requests/api/v1/statuses/reblogs_spec.rb
+++ b/spec/requests/api/v1/statuses/reblogs_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Statuses Reblogs' do
+RSpec.describe 'API V1 Statuses Reblogs' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'write:statuses' }
@@ -19,16 +19,21 @@ describe 'API V1 Statuses Reblogs' do
context 'with public status' do
it 'reblogs the status', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(status.reblogs.count).to eq 1
expect(user.account.reblogged?(status)).to be true
- hash_body = body_as_json
-
- expect(hash_body[:reblog][:id]).to eq status.id.to_s
- expect(hash_body[:reblog][:reblogs_count]).to eq 1
- expect(hash_body[:reblog][:reblogged]).to be true
+ expect(response.parsed_body)
+ .to include(
+ reblog: include(
+ id: status.id.to_s,
+ reblogs_count: 1,
+ reblogged: true
+ )
+ )
end
end
@@ -37,6 +42,8 @@ describe 'API V1 Statuses Reblogs' do
it 'returns http not found' do
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -52,16 +59,19 @@ describe 'API V1 Statuses Reblogs' do
it 'destroys the reblog', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(status.reblogs.count).to eq 0
expect(user.account.reblogged?(status)).to be false
- hash_body = body_as_json
-
- expect(hash_body[:id]).to eq status.id.to_s
- expect(hash_body[:reblogs_count]).to eq 0
- expect(hash_body[:reblogged]).to be false
+ expect(response.parsed_body)
+ .to include(
+ id: status.id.to_s,
+ reblogs_count: 0,
+ reblogged: false
+ )
end
end
@@ -76,16 +86,19 @@ describe 'API V1 Statuses Reblogs' do
it 'destroys the reblog', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(status.reblogs.count).to eq 0
expect(user.account.reblogged?(status)).to be false
- hash_body = body_as_json
-
- expect(hash_body[:id]).to eq status.id.to_s
- expect(hash_body[:reblogs_count]).to eq 0
- expect(hash_body[:reblogged]).to be false
+ expect(response.parsed_body)
+ .to include(
+ id: status.id.to_s,
+ reblogs_count: 0,
+ reblogged: false
+ )
end
end
@@ -98,6 +111,8 @@ describe 'API V1 Statuses Reblogs' do
it 'returns http not found' do
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/statuses/sources_spec.rb b/spec/requests/api/v1/statuses/sources_spec.rb
index c79ec89648..b9c09f6721 100644
--- a/spec/requests/api/v1/statuses/sources_spec.rb
+++ b/spec/requests/api/v1/statuses/sources_spec.rb
@@ -22,7 +22,9 @@ RSpec.describe 'Sources' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to eq({
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match({
id: status.id.to_s,
text: status.text,
spoiler_text: status.spoiler_text,
@@ -38,6 +40,8 @@ RSpec.describe 'Sources' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -52,7 +56,9 @@ RSpec.describe 'Sources' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to eq({
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to match({
id: status.id.to_s,
text: status.text,
spoiler_text: status.spoiler_text,
@@ -68,6 +74,8 @@ RSpec.describe 'Sources' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/statuses/translations_spec.rb b/spec/requests/api/v1/statuses/translations_spec.rb
index e2ab5d0b80..e316bd451b 100644
--- a/spec/requests/api/v1/statuses/translations_spec.rb
+++ b/spec/requests/api/v1/statuses/translations_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Statuses Translations' do
+RSpec.describe 'API V1 Statuses Translations' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:statuses' }
@@ -20,6 +20,8 @@ describe 'API V1 Statuses Translations' do
it 'returns http unprocessable entity' do
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -38,6 +40,8 @@ describe 'API V1 Statuses Translations' do
it 'returns http success' do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/statuses_spec.rb b/spec/requests/api/v1/statuses_spec.rb
index 2f99b35e74..ddf5945d25 100644
--- a/spec/requests/api/v1/statuses_spec.rb
+++ b/spec/requests/api/v1/statuses_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe '/api/v1/statuses' do
+RSpec.describe '/api/v1/statuses' do
context 'with an oauth token' do
let(:user) { Fabricate(:user) }
let(:client_app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
@@ -18,7 +18,9 @@ describe '/api/v1/statuses' do
get '/api/v1/statuses', headers: headers, params: { id: [status.id, other_status.id, 123_123] }
expect(response).to have_http_status(200)
- expect(body_as_json).to contain_exactly(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to contain_exactly(
hash_including(id: status.id.to_s),
hash_including(id: other_status.id.to_s)
)
@@ -39,6 +41,8 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'when post includes filtered terms' do
@@ -52,7 +56,9 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:filtered][0]).to include({
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:filtered][0]).to include({
filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s,
title: 'filter1',
@@ -75,7 +81,9 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:filtered][0]).to include({
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:filtered][0]).to include({
filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s,
title: 'filter1',
@@ -97,7 +105,9 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:reblog][:filtered][0]).to include({
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:reblog][:filtered][0]).to include({
filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s,
title: 'filter1',
@@ -121,6 +131,8 @@ describe '/api/v1/statuses' do
get "/api/v1/statuses/#{status.id}/context", headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -139,6 +151,8 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
expect(response.headers['X-RateLimit-Remaining']).to eq (RateLimiter::FAMILIES[:statuses][:limit] - 1).to_s
end
@@ -154,7 +168,9 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(422)
- expect(body_as_json[:unexpected_accounts].map { |a| a.slice(:id, :acct) }).to eq [{ id: bob.id.to_s, acct: bob.acct }]
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:unexpected_accounts].map { |a| a.slice(:id, :acct) }).to match [{ id: bob.id.to_s, acct: bob.acct }]
end
end
@@ -165,6 +181,8 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
end
end
@@ -179,6 +197,8 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(429)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
expect(response.headers['X-RateLimit-Remaining']).to eq '0'
end
@@ -191,6 +211,8 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -202,6 +224,8 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
it 'creates a scheduled status' do
@@ -215,6 +239,8 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(account.scheduled_statuses).to be_empty
end
end
@@ -235,6 +261,8 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(Status.find_by(id: status.id)).to be_nil
end
end
@@ -253,6 +281,8 @@ describe '/api/v1/statuses' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(status.reload.text).to eq 'I am updated'
end
end
@@ -267,6 +297,8 @@ describe '/api/v1/statuses' do
get "/api/v1/statuses/#{status.id}"
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -279,6 +311,8 @@ describe '/api/v1/statuses' do
get "/api/v1/statuses/#{status.id}/context"
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -291,6 +325,8 @@ describe '/api/v1/statuses' do
get "/api/v1/statuses/#{status.id}"
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -303,6 +339,8 @@ describe '/api/v1/statuses' do
get "/api/v1/statuses/#{status.id}/context"
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/streaming_spec.rb b/spec/requests/api/v1/streaming_spec.rb
index 6b550dfa60..62b43d657a 100644
--- a/spec/requests/api/v1/streaming_spec.rb
+++ b/spec/requests/api/v1/streaming_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Streaming' do
+RSpec.describe 'API V1 Streaming' do
around do |example|
before = Rails.configuration.x.streaming_api_base_url
Rails.configuration.x.streaming_api_base_url = "wss://#{Rails.configuration.x.web_domain}"
@@ -10,14 +10,15 @@ describe 'API V1 Streaming' do
Rails.configuration.x.streaming_api_base_url = before
end
- let(:headers) { { 'Host' => Rails.configuration.x.web_domain } }
-
context 'with streaming api on same host' do
describe 'GET /api/v1/streaming' do
it 'raises ActiveRecord::RecordNotFound' do
- get '/api/v1/streaming', headers: headers
+ integration_session.https!(false)
+ get '/api/v1/streaming'
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/suggestions_spec.rb b/spec/requests/api/v1/suggestions_spec.rb
index dc89613fc5..0a32d8899b 100644
--- a/spec/requests/api/v1/suggestions_spec.rb
+++ b/spec/requests/api/v1/suggestions_spec.rb
@@ -23,19 +23,14 @@ RSpec.describe 'Suggestions' do
it_behaves_like 'forbidden for wrong scope', 'write'
- it 'returns http success' do
+ it 'returns http success with accounts' do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns accounts' do
- subject
-
- body = body_as_json
-
- expect(body.size).to eq 2
- expect(body.pluck(:id)).to match_array([bob, jeff].map { |i| i.id.to_s })
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(include(id: bob.id.to_s), include(id: jeff.id.to_s))
end
context 'with limit param' do
@@ -44,7 +39,7 @@ RSpec.describe 'Suggestions' do
it 'returns only the requested number of accounts' do
subject
- expect(body_as_json.size).to eq 1
+ expect(response.parsed_body.size).to eq 1
end
end
@@ -55,6 +50,8 @@ RSpec.describe 'Suggestions' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -74,15 +71,12 @@ RSpec.describe 'Suggestions' do
it_behaves_like 'forbidden for wrong scope', 'read'
- it 'returns http success' do
+ it 'returns http success and removes suggestion' do
subject
expect(response).to have_http_status(200)
- end
-
- it 'removes the specified suggestion' do
- subject
-
+ expect(response.content_type)
+ .to start_with('application/json')
expect(FollowRecommendationMute.exists?(account: user.account, target_account: jeff)).to be true
end
diff --git a/spec/requests/api/v1/tags_spec.rb b/spec/requests/api/v1/tags_spec.rb
index db74a6f037..f6ff7c614f 100644
--- a/spec/requests/api/v1/tags_spec.rb
+++ b/spec/requests/api/v1/tags_spec.rb
@@ -21,7 +21,9 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:name]).to eq(name)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:name]).to eq(name)
end
end
@@ -32,6 +34,8 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -42,6 +46,8 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -61,6 +67,8 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(:success)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(TagFollow.where(tag: tag, account: user.account)).to exist
end
end
@@ -72,6 +80,8 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(Tag.where(name: name)).to exist
expect(TagFollow.where(tag: Tag.find_by(name: name), account: user.account)).to exist
end
@@ -84,6 +94,8 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -95,6 +107,8 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -117,6 +131,8 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(TagFollow.where(tag: tag, account: user.account)).to_not exist
end
@@ -127,6 +143,8 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -138,6 +156,8 @@ RSpec.describe 'Tags' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/timelines/direct_spec.rb b/spec/requests/api/v1/timelines/direct_spec.rb
index f882e4ccc5..2551060fa9 100644
--- a/spec/requests/api/v1/timelines/direct_spec.rb
+++ b/spec/requests/api/v1/timelines/direct_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Direct Timeline' do
+RSpec.describe 'API V1 Direct Timeline' do
let(:user) { Fabricate(:user) }
let(:scopes) { 'read:statuses' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
diff --git a/spec/requests/api/v1/timelines/home_spec.rb b/spec/requests/api/v1/timelines/home_spec.rb
index 96bd153aff..2023b189ec 100644
--- a/spec/requests/api/v1/timelines/home_spec.rb
+++ b/spec/requests/api/v1/timelines/home_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Home', :inline_jobs do
+RSpec.describe 'Home', :inline_jobs do
let(:user) { Fabricate(:user) }
let(:scopes) { 'read:statuses' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -31,35 +31,31 @@ describe 'Home', :inline_jobs do
PostStatusService.new.call(ana, text: 'New toot from ana.')
end
- it 'returns http success' do
+ it 'returns http success and statuses of followed users' do
subject
expect(response).to have_http_status(200)
- end
+ expect(response.content_type)
+ .to start_with('application/json')
- it 'returns the statuses of followed users' do
- subject
-
- expect(body_as_json.pluck(:id)).to match_array(home_statuses.map { |status| status.id.to_s })
+ expect(response.parsed_body.pluck(:id)).to match_array(home_statuses.map { |status| status.id.to_s })
end
context 'with limit param' do
let(:params) { { limit: 1 } }
- it 'returns only the requested number of statuses' do
+ it 'returns only the requested number of statuses with pagination headers', :aggregate_failures do
subject
- expect(body_as_json.size).to eq(params[:limit])
- end
-
- it 'sets the correct pagination headers', :aggregate_failures do
- subject
+ expect(response.parsed_body.size).to eq(params[:limit])
expect(response)
.to include_pagination_headers(
prev: api_v1_timelines_home_url(limit: params[:limit], min_id: ana.statuses.first.id),
next: api_v1_timelines_home_url(limit: params[:limit], max_id: ana.statuses.first.id)
)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -75,6 +71,8 @@ describe 'Home', :inline_jobs do
subject
expect(response).to have_http_status(206)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -85,6 +83,8 @@ describe 'Home', :inline_jobs do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -94,8 +94,11 @@ describe 'Home', :inline_jobs do
it 'returns http unprocessable entity', :aggregate_failures do
subject
- expect(response).to have_http_status(422)
- expect(response.headers['Link']).to be_nil
+ expect(response)
+ .to have_http_status(422)
+ .and not_have_http_link_header
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v1/timelines/link_spec.rb b/spec/requests/api/v1/timelines/link_spec.rb
index 57969fbd0e..dc4d0d9506 100644
--- a/spec/requests/api/v1/timelines/link_spec.rb
+++ b/spec/requests/api/v1/timelines/link_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Link' do
+RSpec.describe 'Link' do
let(:user) { Fabricate(:user) }
let(:scopes) { 'read:statuses' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -13,7 +13,9 @@ describe 'Link' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.pluck(:id)).to match_array(expected_statuses.map { |status| status.id.to_s })
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.pluck(:id)).to match_array(expected_statuses.map { |status| status.id.to_s })
end
end
@@ -50,6 +52,8 @@ describe 'Link' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -62,6 +66,8 @@ describe 'Link' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -74,6 +80,8 @@ describe 'Link' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -91,6 +99,8 @@ describe 'Link' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -101,6 +111,8 @@ describe 'Link' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -127,15 +139,13 @@ describe 'Link' do
context 'with limit param' do
let(:params) { { limit: 1, url: url } }
- it 'returns only the requested number of statuses', :aggregate_failures do
+ it 'returns only the requested number of statuses with pagination headers', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq(params[:limit])
- end
-
- it 'sets the correct pagination headers', :aggregate_failures do
- subject
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.size).to eq(params[:limit])
expect(response)
.to include_pagination_headers(
diff --git a/spec/requests/api/v1/timelines/list_spec.rb b/spec/requests/api/v1/timelines/list_spec.rb
index 98d2456745..1be754f264 100644
--- a/spec/requests/api/v1/timelines/list_spec.rb
+++ b/spec/requests/api/v1/timelines/list_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API V1 Timelines List' do
+RSpec.describe 'API V1 Timelines List' do
let(:user) { Fabricate(:user) }
let(:scopes) { 'read:statuses' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -23,6 +23,8 @@ describe 'API V1 Timelines List' do
get "/api/v1/timelines/list/#{list.id}", headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -36,6 +38,8 @@ describe 'API V1 Timelines List' do
get "/api/v1/timelines/list/#{list.id}", headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -47,8 +51,9 @@ describe 'API V1 Timelines List' do
it 'returns http unprocessable entity' do
get "/api/v1/timelines/list/#{list.id}", headers: headers
- expect(response).to have_http_status(422)
- expect(response.headers['Link']).to be_nil
+ expect(response)
+ .to have_http_status(422)
+ .and not_have_http_link_header
end
end
end
diff --git a/spec/requests/api/v1/timelines/public_spec.rb b/spec/requests/api/v1/timelines/public_spec.rb
index f17311af9b..83d9039356 100644
--- a/spec/requests/api/v1/timelines/public_spec.rb
+++ b/spec/requests/api/v1/timelines/public_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Public' do
+RSpec.describe 'Public' do
let(:user) { Fabricate(:user) }
let(:scopes) { 'read:statuses' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -13,7 +13,9 @@ describe 'Public' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.pluck(:id)).to match_array(expected_statuses.map { |status| status.id.to_s })
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.pluck(:id)).to match_array(expected_statuses.map { |status| status.id.to_s })
end
end
@@ -81,15 +83,13 @@ describe 'Public' do
context 'with limit param' do
let(:params) { { limit: 1 } }
- it 'returns only the requested number of statuses', :aggregate_failures do
+ it 'returns only the requested number of statuses and sets pagination headers', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.size).to eq(params[:limit])
- end
-
- it 'sets the correct pagination headers', :aggregate_failures do
- subject
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.size).to eq(params[:limit])
expect(response)
.to include_pagination_headers(
@@ -114,6 +114,8 @@ describe 'Public' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -124,6 +126,8 @@ describe 'Public' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
diff --git a/spec/requests/api/v1/timelines/tag_spec.rb b/spec/requests/api/v1/timelines/tag_spec.rb
index 4f2f6e5a18..1d6844364d 100644
--- a/spec/requests/api/v1/timelines/tag_spec.rb
+++ b/spec/requests/api/v1/timelines/tag_spec.rb
@@ -8,15 +8,6 @@ RSpec.describe 'Tag' do
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
- shared_examples 'a successful request to the tag timeline' do
- it 'returns the expected statuses', :aggregate_failures do
- subject
-
- expect(response).to have_http_status(200)
- expect(body_as_json.pluck(:id)).to match_array(expected_statuses.map { |status| status.id.to_s })
- end
- end
-
describe 'GET /api/v1/timelines/tag/:hashtag' do
subject do
get "/api/v1/timelines/tag/#{hashtag}", headers: headers, params: params
@@ -26,8 +17,22 @@ RSpec.describe 'Tag' do
Setting.timeline_preview = true
end
+ shared_examples 'a successful request to the tag timeline' do
+ it 'returns the expected statuses', :aggregate_failures do
+ subject
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.pluck(:id))
+ .to match_array(expected_statuses.map { |status| status.id.to_s })
+ .and not_include(private_status.id)
+ end
+ end
+
let(:account) { Fabricate(:account) }
- let!(:private_status) { PostStatusService.new.call(account, visibility: :private, text: '#life could be a dream') } # rubocop:disable RSpec/LetSetup
+ let!(:private_status) { PostStatusService.new.call(account, visibility: :private, text: '#life could be a dream') }
let!(:life_status) { PostStatusService.new.call(account, text: 'tell me what is my #life without your #love') }
let!(:war_status) { PostStatusService.new.call(user.account, text: '#war, war never changes') }
let!(:love_status) { PostStatusService.new.call(account, text: 'what is #love?') }
@@ -71,7 +76,7 @@ RSpec.describe 'Tag' do
it 'returns only the requested number of statuses' do
subject
- expect(body_as_json.size).to eq(params[:limit])
+ expect(response.parsed_body.size).to eq(params[:limit])
end
it 'sets the correct pagination headers', :aggregate_failures do
@@ -82,6 +87,8 @@ RSpec.describe 'Tag' do
prev: api_v1_timelines_tag_url(limit: params[:limit], min_id: love_status.id),
next: api_v1_timelines_tag_url(limit: params[:limit], max_id: love_status.id)
)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -108,6 +115,8 @@ RSpec.describe 'Tag' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
diff --git a/spec/requests/api/v1/trends/links_spec.rb b/spec/requests/api/v1/trends/links_spec.rb
index 012d035907..b1b77e7fd8 100644
--- a/spec/requests/api/v1/trends/links_spec.rb
+++ b/spec/requests/api/v1/trends/links_spec.rb
@@ -10,7 +10,11 @@ RSpec.describe 'API V1 Trends Links' do
it 'returns http success' do
get '/api/v1/trends/links'
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and not_have_http_link_header
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -22,8 +26,11 @@ RSpec.describe 'API V1 Trends Links' do
stub_const('Api::V1::Trends::LinksController::DEFAULT_LINKS_LIMIT', 2)
get '/api/v1/trends/links'
- expect(response).to have_http_status(200)
- expect(response.headers).to include('Link')
+ expect(response)
+ .to have_http_status(200)
+ .and have_http_link_header(api_v1_trends_links_url(offset: 2)).for(rel: 'next')
+ expect(response.content_type)
+ .to start_with('application/json')
end
def prepare_trends
diff --git a/spec/requests/api/v1/trends/statuses_spec.rb b/spec/requests/api/v1/trends/statuses_spec.rb
index 3b906e8f82..fe00c9c645 100644
--- a/spec/requests/api/v1/trends/statuses_spec.rb
+++ b/spec/requests/api/v1/trends/statuses_spec.rb
@@ -10,7 +10,11 @@ RSpec.describe 'API V1 Trends Statuses' do
it 'returns http success' do
get '/api/v1/trends/statuses'
- expect(response).to have_http_status(200)
+ expect(response)
+ .to have_http_status(200)
+ .and not_have_http_link_header
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -22,8 +26,11 @@ RSpec.describe 'API V1 Trends Statuses' do
stub_const('Api::BaseController::DEFAULT_STATUSES_LIMIT', 2)
get '/api/v1/trends/statuses'
- expect(response).to have_http_status(200)
- expect(response.headers).to include('Link')
+ expect(response)
+ .to have_http_status(200)
+ .and have_http_link_header(api_v1_trends_statuses_url(offset: 2)).for(rel: 'next')
+ expect(response.content_type)
+ .to start_with('application/json')
end
def prepare_trends
diff --git a/spec/requests/api/v1/trends/tags_spec.rb b/spec/requests/api/v1/trends/tags_spec.rb
index 598f4e7752..14ab73fc96 100644
--- a/spec/requests/api/v1/trends/tags_spec.rb
+++ b/spec/requests/api/v1/trends/tags_spec.rb
@@ -10,8 +10,11 @@ RSpec.describe 'API V1 Trends Tags' do
it 'returns http success' do
get '/api/v1/trends/tags'
- expect(response).to have_http_status(200)
- expect(response.headers).to_not include('Link')
+ expect(response)
+ .to have_http_status(200)
+ .and not_have_http_link_header
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -23,8 +26,11 @@ RSpec.describe 'API V1 Trends Tags' do
stub_const('Api::V1::Trends::TagsController::DEFAULT_TAGS_LIMIT', 2)
get '/api/v1/trends/tags'
- expect(response).to have_http_status(200)
- expect(response.headers).to include('Link')
+ expect(response)
+ .to have_http_status(200)
+ .and have_http_link_header(api_v1_trends_tags_url(offset: 2)).for(rel: 'next')
+ expect(response.content_type)
+ .to start_with('application/json')
end
def prepare_trends
diff --git a/spec/requests/api/v2/admin/accounts_spec.rb b/spec/requests/api/v2/admin/accounts_spec.rb
index 8f52c6a613..1d1fda3e67 100644
--- a/spec/requests/api/v2/admin/accounts_spec.rb
+++ b/spec/requests/api/v2/admin/accounts_spec.rb
@@ -34,7 +34,12 @@ RSpec.describe 'API V2 Admin Accounts' do
it 'returns the correct accounts' do
expect(response).to have_http_status(200)
- expect(body_json_ids).to eq([admin_account.id])
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: admin_account.id.to_s)
+ )
end
end
@@ -43,8 +48,13 @@ RSpec.describe 'API V2 Admin Accounts' do
it 'returns the correct accounts' do
expect(response).to have_http_status(200)
- expect(body_json_ids).to include(remote_account.id)
- expect(body_json_ids).to_not include(other_remote_account.id)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: remote_account.id.to_s)
+ )
+ .and not_include(hash_including(id: other_remote_account.id.to_s))
end
end
@@ -53,7 +63,13 @@ RSpec.describe 'API V2 Admin Accounts' do
it 'returns the correct accounts' do
expect(response).to have_http_status(200)
- expect(body_json_ids).to include(suspended_remote.id, suspended_account.id)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: suspended_remote.id.to_s),
+ hash_including(id: suspended_account.id.to_s)
+ )
end
end
@@ -62,7 +78,12 @@ RSpec.describe 'API V2 Admin Accounts' do
it 'returns the correct accounts' do
expect(response).to have_http_status(200)
- expect(body_json_ids).to include(disabled_account.id)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: disabled_account.id.to_s)
+ )
end
end
@@ -71,20 +92,23 @@ RSpec.describe 'API V2 Admin Accounts' do
it 'returns the correct accounts' do
expect(response).to have_http_status(200)
- expect(body_json_ids).to include(pending_account.id)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to contain_exactly(
+ hash_including(id: pending_account.id.to_s)
+ )
end
end
- def body_json_ids
- body_as_json.map { |a| a[:id].to_i }
- end
-
context 'with limit param' do
let(:params) { { limit: 1 } }
it 'sets the correct pagination headers' do
expect(response)
.to include_pagination_headers(next: api_v2_admin_accounts_url(limit: 1, max_id: admin_account.id))
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v2/filters/keywords_spec.rb b/spec/requests/api/v2/filters/keywords_spec.rb
index 55fb2afd95..f0d62e9ecc 100644
--- a/spec/requests/api/v2/filters/keywords_spec.rb
+++ b/spec/requests/api/v2/filters/keywords_spec.rb
@@ -17,7 +17,9 @@ RSpec.describe 'API V2 Filters Keywords' do
it 'returns http success' do
get "/api/v2/filters/#{filter.id}/keywords", headers: headers
expect(response).to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to contain_exactly(
include(id: keyword.id.to_s)
)
@@ -27,6 +29,8 @@ RSpec.describe 'API V2 Filters Keywords' do
it 'returns http not found' do
get "/api/v2/filters/#{other_filter.id}/keywords", headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -41,10 +45,14 @@ RSpec.describe 'API V2 Filters Keywords' do
it 'creates a filter', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- json = body_as_json
- expect(json[:keyword]).to eq 'magic'
- expect(json[:whole_word]).to be false
+ expect(response.parsed_body)
+ .to include(
+ keyword: 'magic',
+ whole_word: false
+ )
filter = user.account.custom_filters.first
expect(filter).to_not be_nil
@@ -56,6 +64,8 @@ RSpec.describe 'API V2 Filters Keywords' do
it 'returns http not found' do
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -70,10 +80,14 @@ RSpec.describe 'API V2 Filters Keywords' do
it 'responds with the keyword', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- json = body_as_json
- expect(json[:keyword]).to eq 'foo'
- expect(json[:whole_word]).to be false
+ expect(response.parsed_body)
+ .to include(
+ keyword: 'foo',
+ whole_word: false
+ )
end
context "when trying to access another user's filter keyword" do
@@ -81,6 +95,8 @@ RSpec.describe 'API V2 Filters Keywords' do
it 'returns http not found' do
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -95,6 +111,8 @@ RSpec.describe 'API V2 Filters Keywords' do
it 'updates the keyword', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(keyword.reload.keyword).to eq 'updated'
end
@@ -104,6 +122,8 @@ RSpec.describe 'API V2 Filters Keywords' do
it 'returns http not found' do
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -118,6 +138,8 @@ RSpec.describe 'API V2 Filters Keywords' do
it 'destroys the keyword', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound
end
@@ -127,6 +149,8 @@ RSpec.describe 'API V2 Filters Keywords' do
it 'returns http not found' do
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v2/filters/statuses_spec.rb b/spec/requests/api/v2/filters/statuses_spec.rb
index 26d2fb00e1..f20a6ae5e6 100644
--- a/spec/requests/api/v2/filters/statuses_spec.rb
+++ b/spec/requests/api/v2/filters/statuses_spec.rb
@@ -17,7 +17,9 @@ RSpec.describe 'API V2 Filters Statuses' do
it 'returns http success' do
get "/api/v2/filters/#{filter.id}/statuses", headers: headers
expect(response).to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
.to contain_exactly(
include(id: status_filter.id.to_s)
)
@@ -27,6 +29,8 @@ RSpec.describe 'API V2 Filters Statuses' do
it 'returns http not found' do
get "/api/v2/filters/#{other_filter.id}/statuses", headers: headers
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -42,9 +46,13 @@ RSpec.describe 'API V2 Filters Statuses' do
it 'creates a filter', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- json = body_as_json
- expect(json[:status_id]).to eq status.id.to_s
+ expect(response.parsed_body)
+ .to include(
+ status_id: status.id.to_s
+ )
filter = user.account.custom_filters.first
expect(filter).to_not be_nil
@@ -56,6 +64,8 @@ RSpec.describe 'API V2 Filters Statuses' do
it 'returns http not found' do
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -70,9 +80,13 @@ RSpec.describe 'API V2 Filters Statuses' do
it 'responds with the filter', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- json = body_as_json
- expect(json[:status_id]).to eq status_filter.status_id.to_s
+ expect(response.parsed_body)
+ .to include(
+ status_id: status_filter.status.id.to_s
+ )
end
context "when trying to access another user's filter keyword" do
@@ -94,6 +108,8 @@ RSpec.describe 'API V2 Filters Statuses' do
it 'destroys the filter', :aggregate_failures do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect { status_filter.reload }.to raise_error ActiveRecord::RecordNotFound
end
@@ -103,6 +119,8 @@ RSpec.describe 'API V2 Filters Statuses' do
it 'returns http not found' do
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v2/filters_spec.rb b/spec/requests/api/v2/filters_spec.rb
index fd0483abbe..3b5c44cefa 100644
--- a/spec/requests/api/v2/filters_spec.rb
+++ b/spec/requests/api/v2/filters_spec.rb
@@ -15,6 +15,8 @@ RSpec.describe 'Filters' do
subject
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -32,7 +34,9 @@ RSpec.describe 'Filters' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.pluck(:id)).to match_array(filters.map { |filter| filter.id.to_s })
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.pluck(:id)).to match_array(filters.map { |filter| filter.id.to_s })
end
end
@@ -49,25 +53,22 @@ RSpec.describe 'Filters' do
context 'with valid params' do
let(:params) { { title: 'magic', context: %w(home), filter_action: 'hide', keywords_attributes: [keyword: 'magic'] } }
- it 'returns http success' do
+ it 'returns http success with a filter with keywords in json and creates a filter', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
+ expect(response.content_type)
+ .to start_with('application/json')
- it 'returns a filter with keywords', :aggregate_failures do
- subject
-
- json = body_as_json
-
- expect(json[:title]).to eq 'magic'
- expect(json[:filter_action]).to eq 'hide'
- expect(json[:context]).to eq ['home']
- expect(json[:keywords].map { |keyword| keyword.slice(:keyword, :whole_word) }).to eq [{ keyword: 'magic', whole_word: true }]
- end
-
- it 'creates a filter', :aggregate_failures do
- subject
+ expect(response.parsed_body)
+ .to include(
+ title: 'magic',
+ filter_action: 'hide',
+ context: %w(home),
+ keywords: contain_exactly(
+ include(keyword: 'magic', whole_word: true)
+ )
+ )
filter = user.account.custom_filters.first
@@ -86,6 +87,8 @@ RSpec.describe 'Filters' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -96,6 +99,8 @@ RSpec.describe 'Filters' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -106,6 +111,8 @@ RSpec.describe 'Filters' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -124,7 +131,12 @@ RSpec.describe 'Filters' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:id]).to eq(filter.id.to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body)
+ .to include(
+ id: filter.id.to_s
+ )
end
context 'when the filter belongs to someone else' do
@@ -134,6 +146,8 @@ RSpec.describe 'Filters' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -160,6 +174,8 @@ RSpec.describe 'Filters' do
filter.reload
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(filter.title).to eq 'updated'
expect(filter.reload.context).to eq %w(home public)
end
@@ -172,6 +188,8 @@ RSpec.describe 'Filters' do
subject
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -183,20 +201,14 @@ RSpec.describe 'Filters' do
allow(redis).to receive_messages(publish: nil)
end
- it 'returns http success' do
+ it 'returns http success and updates keyword and sends a filters_changed event' do
subject
expect(response).to have_http_status(200)
- end
-
- it 'updates the keyword' do
- subject
+ expect(response.content_type)
+ .to start_with('application/json')
expect(keyword.reload.keyword).to eq 'updated'
- end
-
- it 'sends exactly one filters_changed event' do
- subject
expect(redis).to have_received(:publish).with("timeline:#{user.account.id}", Oj.dump(event: :filters_changed)).once
end
@@ -209,6 +221,8 @@ RSpec.describe 'Filters' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -223,14 +237,12 @@ RSpec.describe 'Filters' do
it_behaves_like 'forbidden for wrong scope', 'read read:filters'
it_behaves_like 'unauthorized for invalid token'
- it 'returns http success' do
+ it 'returns http success and removes the filter' do
subject
expect(response).to have_http_status(200)
- end
-
- it 'removes the filter' do
- subject
+ expect(response.content_type)
+ .to start_with('application/json')
expect { filter.reload }.to raise_error ActiveRecord::RecordNotFound
end
@@ -242,6 +254,8 @@ RSpec.describe 'Filters' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v2/instance_spec.rb b/spec/requests/api/v2/instance_spec.rb
index 2b80a4cdf6..85d92f68d0 100644
--- a/spec/requests/api/v2/instance_spec.rb
+++ b/spec/requests/api/v2/instance_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Instances' do
+RSpec.describe 'Instances' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
@@ -15,7 +15,10 @@ describe 'Instances' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
.to be_present
.and include(title: 'Mastodon Glitch Edition')
.and include_api_versions
@@ -30,7 +33,10 @@ describe 'Instances' do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
.to be_present
.and include(title: 'Mastodon Glitch Edition')
.and include_api_versions
diff --git a/spec/requests/api/v2/media_spec.rb b/spec/requests/api/v2/media_spec.rb
index 97540413f1..70e0679f57 100644
--- a/spec/requests/api/v2/media_spec.rb
+++ b/spec/requests/api/v2/media_spec.rb
@@ -21,7 +21,10 @@ RSpec.describe 'Media API', :attachment_processing do
expect(response)
.to have_http_status(200)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
.to be_a(Hash)
end
end
@@ -38,7 +41,10 @@ RSpec.describe 'Media API', :attachment_processing do
expect(response)
.to have_http_status(202)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
.to be_a(Hash)
end
end
@@ -63,7 +69,10 @@ RSpec.describe 'Media API', :attachment_processing do
expect(response)
.to have_http_status(422)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
.to be_a(Hash)
.and include(error: /File type/)
end
@@ -80,7 +89,10 @@ RSpec.describe 'Media API', :attachment_processing do
expect(response)
.to have_http_status(500)
- expect(body_as_json)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ expect(response.parsed_body)
.to be_a(Hash)
.and include(error: /processing/)
end
diff --git a/spec/requests/api/v2/notifications/accounts_spec.rb b/spec/requests/api/v2/notifications/accounts_spec.rb
new file mode 100644
index 0000000000..29880a4c0a
--- /dev/null
+++ b/spec/requests/api/v2/notifications/accounts_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Accounts in grouped notifications' do
+ let(:user) { Fabricate(:user, account_attributes: { username: 'alice' }) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'read:notifications write:notifications' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+
+ describe 'GET /api/v2/notifications/:group_key/accounts', :inline_jobs do
+ subject do
+ get "/api/v2/notifications/#{user.account.notifications.first.group_key}/accounts", headers: headers, params: params
+ end
+
+ let(:params) { {} }
+
+ before do
+ first_status = PostStatusService.new.call(user.account, text: 'Test')
+ FavouriteService.new.call(Fabricate(:account), first_status)
+ FavouriteService.new.call(Fabricate(:account), first_status)
+ ReblogService.new.call(Fabricate(:account), first_status)
+ FollowService.new.call(Fabricate(:account), user.account)
+ FavouriteService.new.call(Fabricate(:account), first_status)
+ end
+
+ it_behaves_like 'forbidden for wrong scope', 'write write:notifications'
+
+ it 'returns a list of accounts' do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ # The group we are interested in is only favorites
+ notifications = user.account.notifications.where(type: 'favourite').reorder(id: :desc)
+ expect(response.parsed_body).to match(
+ [
+ a_hash_including(
+ id: notifications.first.from_account_id.to_s
+ ),
+ a_hash_including(
+ id: notifications.second.from_account_id.to_s
+ ),
+ a_hash_including(
+ id: notifications.third.from_account_id.to_s
+ ),
+ ]
+ )
+ end
+
+ context 'with limit param' do
+ let(:params) { { limit: 2 } }
+
+ it 'returns the requested number of accounts, with pagination headers' do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+
+ # The group we are interested in is only favorites
+ notifications = user.account.notifications.where(type: 'favourite').reorder(id: :desc)
+ expect(response.parsed_body).to match(
+ [
+ a_hash_including(
+ id: notifications.first.from_account_id.to_s
+ ),
+ a_hash_including(
+ id: notifications.second.from_account_id.to_s
+ ),
+ ]
+ )
+
+ expect(response)
+ .to include_pagination_headers(
+ prev: api_v2_notification_accounts_url(limit: params[:limit], min_id: notifications.first.id),
+ next: api_v2_notification_accounts_url(limit: params[:limit], max_id: notifications.second.id)
+ )
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/v2/notifications/policies_spec.rb b/spec/requests/api/v2/notifications/policies_spec.rb
index f9860b5fb4..f080bc730f 100644
--- a/spec/requests/api/v2/notifications/policies_spec.rb
+++ b/spec/requests/api/v2/notifications/policies_spec.rb
@@ -26,7 +26,9 @@ RSpec.describe 'Policies' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json).to include(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to include(
for_not_following: 'accept',
for_not_followers: 'accept',
for_new_accounts: 'accept',
@@ -56,7 +58,9 @@ RSpec.describe 'Policies' do
.and change { NotificationPolicy.find_or_initialize_by(account: user.account).for_limited_accounts.to_sym }.from(:filter).to(:drop)
expect(response).to have_http_status(200)
- expect(body_as_json).to include(
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body).to include(
for_not_following: 'filter',
for_not_followers: 'accept',
for_new_accounts: 'accept',
diff --git a/spec/requests/api/v2_alpha/notifications_spec.rb b/spec/requests/api/v2/notifications_spec.rb
similarity index 55%
rename from spec/requests/api/v2_alpha/notifications_spec.rb
rename to spec/requests/api/v2/notifications_spec.rb
index a613158aa5..ffa0a71c77 100644
--- a/spec/requests/api/v2_alpha/notifications_spec.rb
+++ b/spec/requests/api/v2/notifications_spec.rb
@@ -8,9 +8,9 @@ RSpec.describe 'Notifications' do
let(:scopes) { 'read:notifications write:notifications' }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
- describe 'GET /api/v2_alpha/notifications/unread_count', :inline_jobs do
+ describe 'GET /api/v2/notifications/unread_count', :inline_jobs do
subject do
- get '/api/v2_alpha/notifications/unread_count', headers: headers, params: params
+ get '/api/v2/notifications/unread_count', headers: headers, params: params
end
let(:params) { {} }
@@ -31,7 +31,22 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:count]).to eq 4
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq 4
+ end
+ end
+
+ context 'with grouped_types parameter' do
+ let(:params) { { grouped_types: %w(reblog) } }
+
+ it 'returns expected notifications count' do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq 5
end
end
@@ -45,7 +60,9 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:count]).to eq 2
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq 2
end
end
@@ -56,7 +73,9 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:count]).to eq 3
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq 3
end
end
@@ -67,27 +86,31 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:count]).to eq 2
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq 2
end
end
context 'when there are more notifications than the limit' do
before do
- stub_const('Api::V2Alpha::NotificationsController::DEFAULT_NOTIFICATIONS_COUNT_LIMIT', 2)
+ stub_const('Api::V2::NotificationsController::DEFAULT_NOTIFICATIONS_COUNT_LIMIT', 2)
end
it 'returns a capped value' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:count]).to eq Api::V2Alpha::NotificationsController::DEFAULT_NOTIFICATIONS_COUNT_LIMIT
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:count]).to eq Api::V2::NotificationsController::DEFAULT_NOTIFICATIONS_COUNT_LIMIT
end
end
end
- describe 'GET /api/v2_alpha/notifications', :inline_jobs do
+ describe 'GET /api/v2/notifications', :inline_jobs do
subject do
- get '/api/v2_alpha/notifications', headers: headers, params: params
+ get '/api/v2/notifications', headers: headers, params: params
end
let(:bob) { Fabricate(:user) }
@@ -105,15 +128,66 @@ RSpec.describe 'Notifications' do
it_behaves_like 'forbidden for wrong scope', 'write write:notifications'
+ context 'when there are no notifications' do
+ before do
+ user.account.notifications.destroy_all
+ end
+
+ it 'returns 0 notifications' do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:notification_groups]).to eq []
+ end
+ end
+
context 'with no options' do
it 'returns expected notification types', :aggregate_failures do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(body_json_types).to include('reblog', 'mention', 'favourite', 'follow')
end
end
+ context 'with grouped_types param' do
+ let(:params) { { grouped_types: %w(reblog) } }
+
+ it 'returns everything, but does not group favourites' do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:notification_groups]).to contain_exactly(
+ a_hash_including(
+ type: 'reblog',
+ sample_account_ids: [bob.account_id.to_s]
+ ),
+ a_hash_including(
+ type: 'mention',
+ sample_account_ids: [bob.account_id.to_s]
+ ),
+ a_hash_including(
+ type: 'favourite',
+ sample_account_ids: [bob.account_id.to_s]
+ ),
+ a_hash_including(
+ type: 'favourite',
+ sample_account_ids: [tom.account_id.to_s]
+ ),
+ a_hash_including(
+ type: 'follow',
+ sample_account_ids: [bob.account_id.to_s]
+ )
+ )
+ end
+ end
+
context 'with exclude_types param' do
let(:params) { { exclude_types: %w(mention) } }
@@ -121,7 +195,9 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json.size).to_not eq 0
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body.size).to_not eq 0
expect(body_json_types.uniq).to_not include 'mention'
end
end
@@ -133,8 +209,10 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(body_json_types.uniq).to eq ['mention']
- expect(body_as_json.dig(:notification_groups, 0, :page_min_id)).to_not be_nil
+ expect(response.parsed_body.dig(:notification_groups, 0, :page_min_id)).to_not be_nil
end
end
@@ -145,16 +223,18 @@ RSpec.describe 'Notifications' do
it 'returns the requested number of notifications paginated', :aggregate_failures do
subject
- expect(body_as_json[:notification_groups].size)
+ expect(response.parsed_body[:notification_groups].size)
.to eq(params[:limit])
expect(response)
.to include_pagination_headers(
- prev: api_v2_alpha_notifications_url(limit: params[:limit], min_id: notifications.first.id),
+ prev: api_v2_notifications_url(limit: params[:limit], min_id: notifications.first.id),
# TODO: one downside of the current approach is that we return the first ID matching the group,
# not the last that has been skipped, so pagination is very likely to give overlap
- next: api_v2_alpha_notifications_url(limit: params[:limit], max_id: notifications[3].id)
+ next: api_v2_notifications_url(limit: params[:limit], max_id: notifications[3].id)
)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -165,15 +245,17 @@ RSpec.describe 'Notifications' do
it 'returns the requested number of notifications paginated', :aggregate_failures do
subject
- expect(body_as_json[:notification_groups].size)
+ expect(response.parsed_body[:notification_groups].size)
.to eq(2)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(response)
.to include_pagination_headers(
- prev: api_v2_alpha_notifications_url(limit: params[:limit], min_id: notifications.first.id),
+ prev: api_v2_notifications_url(limit: params[:limit], min_id: notifications.first.id),
# TODO: one downside of the current approach is that we return the first ID matching the group,
# not the last that has been skipped, so pagination is very likely to give overlap
- next: api_v2_alpha_notifications_url(limit: params[:limit], max_id: notifications[1].id)
+ next: api_v2_notifications_url(limit: params[:limit], max_id: notifications[1].id)
)
end
end
@@ -191,10 +273,12 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:partial_accounts].size).to be > 0
- expect(body_as_json[:partial_accounts][0].keys).to contain_exactly(:acct, :avatar, :avatar_static, :bot, :id, :locked, :url)
- expect(body_as_json[:partial_accounts].pluck(:id)).to_not include(recent_account.id.to_s)
- expect(body_as_json[:accounts].pluck(:id)).to include(recent_account.id.to_s)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:partial_accounts].size).to be > 0
+ expect(response.parsed_body[:partial_accounts][0].keys.map(&:to_sym)).to contain_exactly(:acct, :avatar, :avatar_static, :bot, :id, :locked, :url)
+ expect(response.parsed_body[:partial_accounts].pluck(:id)).to_not include(recent_account.id.to_s)
+ expect(response.parsed_body[:accounts].pluck(:id)).to include(recent_account.id.to_s)
end
end
@@ -205,17 +289,19 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(400)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
def body_json_types
- body_as_json[:notification_groups].pluck(:type)
+ response.parsed_body[:notification_groups].pluck(:type)
end
end
- describe 'GET /api/v2_alpha/notifications/:id' do
+ describe 'GET /api/v2/notifications/:id' do
subject do
- get "/api/v2_alpha/notifications/#{notification.group_key}", headers: headers
+ get "/api/v2/notifications/#{notification.group_key}", headers: headers
end
let(:notification) { Fabricate(:notification, account: user.account, group_key: 'foobar') }
@@ -226,6 +312,8 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'when notification belongs to someone else' do
@@ -235,13 +323,15 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
- describe 'POST /api/v2_alpha/notifications/:id/dismiss' do
+ describe 'POST /api/v2/notifications/:id/dismiss' do
subject do
- post "/api/v2_alpha/notifications/#{notification.group_key}/dismiss", headers: headers
+ post "/api/v2/notifications/#{notification.group_key}/dismiss", headers: headers
end
let!(:notification) { Fabricate(:notification, account: user.account, group_key: 'foobar') }
@@ -252,23 +342,28 @@ RSpec.describe 'Notifications' do
subject
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
expect { notification.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
context 'when notification belongs to someone else' do
- let(:notification) { Fabricate(:notification) }
+ let(:notification) { Fabricate(:notification, group_key: 'foobar') }
- it 'returns http not found' do
- subject
+ it 'leaves the notification alone' do
+ expect { subject }
+ .to_not change(Notification, :count)
- expect(response).to have_http_status(404)
+ expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
- describe 'POST /api/v2_alpha/notifications/clear' do
+ describe 'POST /api/v2/notifications/clear' do
subject do
- post '/api/v2_alpha/notifications/clear', headers: headers
+ post '/api/v2/notifications/clear', headers: headers
end
before do
@@ -282,6 +377,8 @@ RSpec.describe 'Notifications' do
expect(user.account.reload.notifications).to be_empty
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/v2/search_spec.rb b/spec/requests/api/v2/search_spec.rb
index 13bcf17984..5a2346dc39 100644
--- a/spec/requests/api/v2/search_spec.rb
+++ b/spec/requests/api/v2/search_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Search API' do
+RSpec.describe 'Search API' do
context 'with token' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -19,6 +19,8 @@ describe 'Search API' do
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'when searching accounts' do
@@ -27,7 +29,7 @@ describe 'Search API' do
it 'returns all matching accounts' do
get '/api/v2/search', headers: headers, params: params
- expect(body_as_json[:accounts].pluck(:id)).to contain_exactly(bob.id.to_s, ana.id.to_s, tom.id.to_s)
+ expect(response.parsed_body[:accounts].pluck(:id)).to contain_exactly(bob.id.to_s, ana.id.to_s, tom.id.to_s)
end
context 'with truthy `resolve`' do
@@ -37,6 +39,8 @@ describe 'Search API' do
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -47,6 +51,8 @@ describe 'Search API' do
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -57,6 +63,8 @@ describe 'Search API' do
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(400)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -67,6 +75,8 @@ describe 'Search API' do
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(400)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -80,7 +90,7 @@ describe 'Search API' do
it 'returns only the followed accounts' do
get '/api/v2/search', headers: headers, params: params
- expect(body_as_json[:accounts].pluck(:id)).to contain_exactly(ana.id.to_s)
+ expect(response.parsed_body[:accounts].pluck(:id)).to contain_exactly(ana.id.to_s)
end
end
end
@@ -92,6 +102,8 @@ describe 'Search API' do
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -102,6 +114,8 @@ describe 'Search API' do
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -118,6 +132,8 @@ describe 'Search API' do
context 'without a `q` param' do
it 'returns http bad_request' do
expect(response).to have_http_status(400)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -126,6 +142,8 @@ describe 'Search API' do
it 'returns http success' do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -134,6 +152,8 @@ describe 'Search API' do
it 'returns http success' do
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
end
context 'with truthy `resolve`' do
@@ -141,6 +161,8 @@ describe 'Search API' do
it 'returns http unauthorized' do
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(response.body).to match('resolve remote resources')
end
end
@@ -150,6 +172,8 @@ describe 'Search API' do
it 'returns http unauthorized' do
expect(response).to have_http_status(401)
+ expect(response.content_type)
+ .to start_with('application/json')
expect(response.body).to match('pagination is not supported')
end
end
diff --git a/spec/requests/api/v2/suggestions_spec.rb b/spec/requests/api/v2/suggestions_spec.rb
index a7d6a0864f..099d9bc3b2 100644
--- a/spec/requests/api/v2/suggestions_spec.rb
+++ b/spec/requests/api/v2/suggestions_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Suggestions API' do
+RSpec.describe 'Suggestions API' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read' }
@@ -21,8 +21,10 @@ describe 'Suggestions API' do
get '/api/v2/suggestions', headers: headers
expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
- expect(body_as_json).to match_array(
+ expect(response.parsed_body).to match_array(
[bob, jeff].map do |account|
hash_including({
source: 'staff',
diff --git a/spec/requests/api/web/embeds_spec.rb b/spec/requests/api/web/embeds_spec.rb
index 0e6195204b..3cc2f977f8 100644
--- a/spec/requests/api/web/embeds_spec.rb
+++ b/spec/requests/api/web/embeds_spec.rb
@@ -18,7 +18,9 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:html]).to be_present
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:html]).to be_present
end
end
@@ -29,6 +31,8 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -42,6 +46,8 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -52,6 +58,8 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -71,7 +79,9 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:html]).to be_present
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:html]).to be_present
end
context 'when the requesting user is blocked' do
@@ -83,6 +93,8 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -98,6 +110,8 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -123,6 +137,8 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -133,7 +149,9 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:html]).to be_present
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:html]).to be_present
end
end
@@ -146,6 +164,8 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
@@ -156,6 +176,8 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
@@ -167,6 +189,8 @@ RSpec.describe '/api/web/embed' do
subject
expect(response).to have_http_status(404)
+ expect(response.content_type)
+ .to start_with('application/json')
end
end
end
diff --git a/spec/requests/api/web/settings_spec.rb b/spec/requests/api/web/settings_spec.rb
new file mode 100644
index 0000000000..3873bc179b
--- /dev/null
+++ b/spec/requests/api/web/settings_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe '/api/web/settings' do
+ describe 'PATCH /api/web/settings' do
+ let(:user) { Fabricate :user }
+
+ context 'when signed in' do
+ before { sign_in(user) }
+
+ it 'updates setting and responds with success' do
+ patch '/api/web/settings', params: { data: { 'onboarded' => true } }
+
+ expect(user_web_setting.data)
+ .to include('onboarded' => 'true')
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ end
+ end
+
+ context 'when not signed in' do
+ it 'responds with unprocessable and does not modify setting' do
+ patch '/api/web/settings', params: { data: { 'onboarded' => true } }
+
+ expect(user_web_setting)
+ .to be_nil
+
+ expect(response)
+ .to have_http_status(422)
+ expect(response.content_type)
+ .to start_with('application/json')
+ end
+ end
+
+ def user_web_setting
+ Web::Setting
+ .where(user: user)
+ .first
+ end
+ end
+end
diff --git a/spec/requests/auth/sessions/security_key_options_spec.rb b/spec/requests/auth/sessions/security_key_options_spec.rb
new file mode 100644
index 0000000000..6246e4beb3
--- /dev/null
+++ b/spec/requests/auth/sessions/security_key_options_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'webauthn/fake_client'
+
+RSpec.describe 'Security Key Options' do
+ describe 'GET /auth/sessions/security_key_options' do
+ let!(:user) do
+ Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32))
+ end
+
+ context 'with WebAuthn and OTP enabled as second factor' do
+ let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http'}://#{Rails.configuration.x.web_domain}" }
+
+ let(:fake_client) { WebAuthn::FakeClient.new(domain) }
+ let(:public_key_credential) { WebAuthn::Credential.from_create(fake_client.create) }
+
+ before do
+ user.update(webauthn_id: WebAuthn.generate_user_id)
+ Fabricate(
+ :webauthn_credential,
+ user_id: user.id,
+ external_id: public_key_credential.id,
+ public_key: public_key_credential.public_key
+ )
+ post '/auth/sign_in', params: { user: { email: user.email, password: user.password } }
+ end
+
+ it 'returns http success' do
+ get '/auth/sessions/security_key_options'
+
+ expect(response)
+ .to have_http_status 200
+ expect(response.content_type)
+ .to start_with('application/json')
+ end
+ end
+
+ context 'when WebAuthn not enabled' do
+ it 'returns http unauthorized' do
+ get '/auth/sessions/security_key_options'
+
+ expect(response)
+ .to have_http_status 401
+ expect(response.content_type)
+ .to start_with('application/json')
+ end
+ end
+ end
+end
diff --git a/spec/requests/backups_spec.rb b/spec/requests/backups_spec.rb
index a6c2efe0db..a8c1124ed2 100644
--- a/spec/requests/backups_spec.rb
+++ b/spec/requests/backups_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Backups' do
+RSpec.describe 'Backups' do
include RoutingHelper
describe 'GET backups#download' do
diff --git a/spec/requests/cache_spec.rb b/spec/requests/cache_spec.rb
index 91e5b022e3..9cce241b38 100644
--- a/spec/requests/cache_spec.rb
+++ b/spec/requests/cache_spec.rb
@@ -118,7 +118,7 @@ module TestEndpoints
end
end
-describe 'Caching behavior' do
+RSpec.describe 'Caching behavior' do
shared_examples 'cachable response' do |http_success: false|
it 'does not set cookies or set public cache control', :aggregate_failures do
expect(response.cookies).to be_empty
diff --git a/spec/requests/catch_all_route_request_spec.rb b/spec/requests/catch_all_route_request_spec.rb
index e600bedfe0..e7ea21524c 100644
--- a/spec/requests/catch_all_route_request_spec.rb
+++ b/spec/requests/catch_all_route_request_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'The catch all route' do
+RSpec.describe 'The catch all route' do
describe 'with a simple value' do
it 'returns a 404 page as html' do
get '/test'
diff --git a/spec/requests/content_security_policy_spec.rb b/spec/requests/content_security_policy_spec.rb
index ba6fe47741..2bbbdd841e 100644
--- a/spec/requests/content_security_policy_spec.rb
+++ b/spec/requests/content_security_policy_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Content-Security-Policy' do
+RSpec.describe 'Content-Security-Policy' do
before { allow(SecureRandom).to receive(:base64).with(16).and_return('ZbA+JmE7+bK8F5qvADZHuQ==') }
it 'sets the expected CSP headers' do
@@ -26,7 +26,7 @@ describe 'Content-Security-Policy' do
connect-src 'self' data: blob: https://cb6e6126.ngrok.io #{Rails.configuration.x.streaming_api_base_url}
default-src 'none'
font-src 'self' https://cb6e6126.ngrok.io
- form-action 'self'
+ form-action 'none'
frame-ancestors 'none'
frame-src 'self' https:
img-src 'self' data: blob: https://cb6e6126.ngrok.io
diff --git a/spec/requests/custom_css_spec.rb b/spec/requests/custom_css_spec.rb
index 5271ed4a5a..a46ebd7281 100644
--- a/spec/requests/custom_css_spec.rb
+++ b/spec/requests/custom_css_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Custom CSS' do
+RSpec.describe 'Custom CSS' do
include RoutingHelper
describe 'GET /custom.css' do
diff --git a/spec/requests/custom_stylesheets_spec.rb b/spec/requests/custom_stylesheets_spec.rb
new file mode 100644
index 0000000000..9c5c058344
--- /dev/null
+++ b/spec/requests/custom_stylesheets_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Custom stylesheets' do
+ describe 'GET /custom.css' do
+ before { get '/custom.css' }
+
+ it 'returns http success' do
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers
+ .and have_attributes(
+ content_type: match('text/css')
+ )
+ end
+ end
+end
diff --git a/spec/requests/disabled_oauth_endpoints_spec.rb b/spec/requests/disabled_oauth_endpoints_spec.rb
index 7c2c09f380..279d2576a3 100644
--- a/spec/requests/disabled_oauth_endpoints_spec.rb
+++ b/spec/requests/disabled_oauth_endpoints_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Disabled OAuth routes' do
+RSpec.describe 'Disabled OAuth routes' do
# These routes are disabled via the doorkeeper configuration for
# `admin_authenticator`, as these routes should only be accessible by server
# administrators. For now, these routes are not properly designed and
diff --git a/spec/requests/emojis_spec.rb b/spec/requests/emojis_spec.rb
new file mode 100644
index 0000000000..644838dc65
--- /dev/null
+++ b/spec/requests/emojis_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Emojis' do
+ describe 'GET /emojis/:id' do
+ let(:emoji) { Fabricate(:custom_emoji, shortcode: 'coolcat') }
+
+ it 'returns http success with correct json' do
+ get "/emojis/#{emoji.id}"
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.parsed_body)
+ .to include(
+ name: ':coolcat:',
+ type: 'Emoji'
+ )
+ end
+ end
+end
diff --git a/spec/requests/health_spec.rb b/spec/requests/health_spec.rb
new file mode 100644
index 0000000000..1d2f96bb3d
--- /dev/null
+++ b/spec/requests/health_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Health check endpoint' do
+ describe 'GET /health' do
+ it 'returns http success when server is functioning' do
+ get '/health'
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.body)
+ .to include('OK')
+ end
+ end
+end
diff --git a/spec/requests/instance_actor_spec.rb b/spec/requests/instance_actor_spec.rb
new file mode 100644
index 0000000000..b4a9b2ce6f
--- /dev/null
+++ b/spec/requests/instance_actor_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Instance actor endpoint' do
+ describe 'GET /actor' do
+ let!(:original_federation_mode) { Rails.configuration.x.limited_federation_mode }
+
+ shared_examples 'instance actor endpoint' do
+ before { get instance_actor_path(format: :json) }
+
+ it 'returns http success with correct media type and body' do
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers
+ expect(response.content_type)
+ .to start_with('application/activity+json')
+ expect(response.parsed_body)
+ .to include(
+ id: instance_actor_url,
+ type: 'Application',
+ preferredUsername: 'mastodon.internal',
+ inbox: instance_actor_inbox_url,
+ outbox: instance_actor_outbox_url,
+ publicKey: include(
+ id: instance_actor_url(anchor: 'main-key')
+ ),
+ url: about_more_url(instance_actor: true)
+ )
+ end
+ end
+
+ context 'with limited federation mode disabled' do
+ before { Rails.configuration.x.limited_federation_mode = false }
+ after { Rails.configuration.x.limited_federation_mode = original_federation_mode }
+
+ it_behaves_like 'instance actor endpoint'
+
+ context 'with a disabled instance actor' do
+ before { disable_instance_actor }
+
+ it_behaves_like 'instance actor endpoint'
+ end
+ end
+
+ context 'with limited federation mode enabled' do
+ before { Rails.configuration.x.limited_federation_mode = true }
+ after { Rails.configuration.x.limited_federation_mode = original_federation_mode }
+
+ it_behaves_like 'instance actor endpoint'
+
+ context 'with a disabled instance actor' do
+ before { disable_instance_actor }
+
+ it_behaves_like 'instance actor endpoint'
+ end
+ end
+
+ def disable_instance_actor
+ Account
+ .representative
+ .update(suspended_at: 10.days.ago)
+ end
+ end
+end
diff --git a/spec/requests/invite_spec.rb b/spec/requests/invite_spec.rb
index c44ef2419c..ba04645389 100644
--- a/spec/requests/invite_spec.rb
+++ b/spec/requests/invite_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'invites' do
+RSpec.describe 'invites' do
let(:invite) { Fabricate(:invite) }
context 'when requesting a JSON document' do
@@ -12,7 +12,7 @@ describe 'invites' do
expect(response).to have_http_status(200)
expect(response.media_type).to eq 'application/json'
- expect(body_as_json[:invite_code]).to eq invite.code
+ expect(response.parsed_body[:invite_code]).to eq invite.code
end
end
diff --git a/spec/requests/invites_spec.rb b/spec/requests/invites_spec.rb
new file mode 100644
index 0000000000..8a5ad2ccd1
--- /dev/null
+++ b/spec/requests/invites_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Invites' do
+ let(:user) { Fabricate(:user) }
+
+ before { sign_in user }
+
+ context 'when not everyone can invite' do
+ before { UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users]) }
+
+ describe 'GET /invites' do
+ it 'returns http forbidden' do
+ get invites_path
+
+ expect(response)
+ .to have_http_status(403)
+ end
+ end
+
+ describe 'POST /invites' do
+ it 'returns http forbidden' do
+ post invites_path, params: { invite: { max_users: '10', expires_in: 1800 } }
+
+ expect(response)
+ .to have_http_status(403)
+ end
+ end
+ end
+end
diff --git a/spec/requests/link_headers_spec.rb b/spec/requests/link_headers_spec.rb
index b822adbfb8..e20f5e79e5 100644
--- a/spec/requests/link_headers_spec.rb
+++ b/spec/requests/link_headers_spec.rb
@@ -2,32 +2,16 @@
require 'rails_helper'
-describe 'Link headers' do
+RSpec.describe 'Link headers' do
describe 'on the account show page' do
let(:account) { Fabricate(:account, username: 'test') }
- before do
+ it 'contains webfinger and activitypub urls in link header' do
get short_account_path(username: account)
- end
- it 'contains webfinger url in link header' do
- link_header = link_header_with_type('application/jrd+json')
-
- expect(link_header.href).to eq 'http://www.example.com/.well-known/webfinger?resource=acct%3Atest%40cb6e6126.ngrok.io'
- expect(link_header.attr_pairs.first).to eq %w(rel lrdd)
- end
-
- it 'contains activitypub url in link header' do
- link_header = link_header_with_type('application/activity+json')
-
- expect(link_header.href).to eq 'https://cb6e6126.ngrok.io/users/test'
- expect(link_header.attr_pairs.first).to eq %w(rel alternate)
- end
-
- def link_header_with_type(type)
- LinkHeader.parse(response.headers['Link'].to_s).links.find do |link|
- link.attr_pairs.any?(['type', type])
- end
+ expect(response)
+ .to have_http_link_header('https://cb6e6126.ngrok.io/.well-known/webfinger?resource=acct%3Atest%40cb6e6126.ngrok.io').for(rel: 'lrdd', type: 'application/jrd+json')
+ .and have_http_link_header('https://cb6e6126.ngrok.io/users/test').for(rel: 'alternate', type: 'application/activity+json')
end
end
end
diff --git a/spec/requests/localization_spec.rb b/spec/requests/localization_spec.rb
index b7fb53ed8d..26fc204ea4 100644
--- a/spec/requests/localization_spec.rb
+++ b/spec/requests/localization_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Localization' do
+RSpec.describe 'Localization' do
around do |example|
I18n.with_locale(I18n.locale) do
example.run
diff --git a/spec/requests/log_out_spec.rb b/spec/requests/log_out_spec.rb
index 62ca1ac547..25291fa796 100644
--- a/spec/requests/log_out_spec.rb
+++ b/spec/requests/log_out_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Log Out' do
+RSpec.describe 'Log Out' do
include RoutingHelper
describe 'DELETE /auth/sign_out' do
@@ -24,7 +24,7 @@ describe 'Log Out' do
expect(response).to have_http_status(200)
expect(response.media_type).to eq 'application/json'
- expect(body_as_json[:redirect_to]).to eq '/auth/sign_in'
+ expect(response.parsed_body[:redirect_to]).to eq '/auth/sign_in'
end
end
end
diff --git a/spec/requests/manifest_spec.rb b/spec/requests/manifest_spec.rb
new file mode 100644
index 0000000000..14ca8c66ee
--- /dev/null
+++ b/spec/requests/manifest_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Manifest' do
+ describe 'GET /manifest' do
+ before { get '/manifest' }
+
+ it 'returns http success' do
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers
+ .and have_attributes(
+ content_type: match('application/json')
+ )
+ expect(response.parsed_body)
+ .to include(
+ id: '/home',
+ name: 'Mastodon Glitch Edition'
+ )
+ end
+ end
+end
diff --git a/spec/requests/media_proxy_spec.rb b/spec/requests/media_proxy_spec.rb
new file mode 100644
index 0000000000..fb4801ee67
--- /dev/null
+++ b/spec/requests/media_proxy_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Media Proxy' do
+ describe 'GET /media_proxy/:id' do
+ before { stub_attachment_request }
+
+ context 'when attached to a status' do
+ let(:status) { Fabricate(:status) }
+ let(:media_attachment) { Fabricate(:media_attachment, status: status, remote_url: 'http://example.com/attachment.png') }
+
+ it 'redirects to correct original url' do
+ get "/media_proxy/#{media_attachment.id}"
+
+ expect(response)
+ .to have_http_status(302)
+ .and redirect_to media_attachment.file.url(:original)
+ end
+
+ it 'redirects to small style url' do
+ get "/media_proxy/#{media_attachment.id}/small"
+
+ expect(response)
+ .to have_http_status(302)
+ .and redirect_to media_attachment.file.url(:small)
+ end
+ end
+
+ context 'when there is not an attached status' do
+ let(:media_attachment) { Fabricate(:media_attachment, status: status, remote_url: 'http://example.com/attachment.png') }
+
+ it 'responds with missing' do
+ get "/media_proxy/#{media_attachment.id}"
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+
+ context 'when id cannot be found' do
+ it 'responds with missing' do
+ get '/media_proxy/missing'
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+
+ context 'when not permitted to view' do
+ let(:status) { Fabricate(:status, visibility: :direct) }
+ let(:media_attachment) { Fabricate(:media_attachment, status: status, remote_url: 'http://example.com/attachment.png') }
+
+ it 'responds with missing' do
+ get "/media_proxy/#{media_attachment.id}"
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+
+ def stub_attachment_request
+ stub_request(
+ :get,
+ 'http://example.com/attachment.png'
+ )
+ .to_return(
+ request_fixture('avatar.txt')
+ )
+ end
+ end
+end
diff --git a/spec/requests/media_spec.rb b/spec/requests/media_spec.rb
new file mode 100644
index 0000000000..a448a87492
--- /dev/null
+++ b/spec/requests/media_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Media' do
+ describe 'GET /media/:id' do
+ context 'when the media attachment does not exist' do
+ it 'responds with not found' do
+ get '/media/missing'
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+
+ context 'when the media attachment has a shortcode' do
+ let(:media_attachment) { Fabricate :media_attachment, status: status, shortcode: 'OI6IgDzG-nYTqvDQ994' }
+
+ context 'when attached to a status' do
+ let(:status) { Fabricate :status }
+
+ it 'redirects to file url' do
+ get medium_path(id: media_attachment.shortcode)
+
+ expect(response)
+ .to redirect_to(media_attachment.file.url(:original))
+ end
+ end
+
+ context 'when not attached to a status' do
+ let(:status) { nil }
+
+ it 'responds with not found' do
+ get medium_path(id: media_attachment.shortcode)
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+
+ context 'when attached to non-public status' do
+ let(:status) { Fabricate :status, visibility: :direct }
+
+ it 'responds with not found' do
+ get medium_path(id: media_attachment.shortcode)
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when the media attachment does not have a shortcode' do
+ let(:media_attachment) { Fabricate :media_attachment, status: status, shortcode: nil }
+
+ context 'when attached to a status' do
+ let(:status) { Fabricate :status }
+
+ it 'redirects to file url' do
+ get medium_path(id: media_attachment.id)
+
+ expect(response)
+ .to redirect_to(media_attachment.file.url(:original))
+ end
+ end
+
+ context 'when not attached to a status' do
+ let(:status) { nil }
+
+ it 'responds with not found' do
+ get medium_path(id: media_attachment.id)
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+
+ context 'when attached to non-public status' do
+ let(:status) { Fabricate :status, visibility: :direct }
+
+ it 'responds with not found' do
+ get medium_path(id: media_attachment.id)
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/oauth/token_spec.rb b/spec/requests/oauth/token_spec.rb
index 39ea9b35ff..18d232e5ab 100644
--- a/spec/requests/oauth/token_spec.rb
+++ b/spec/requests/oauth/token_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe 'Obtaining OAuth Tokens' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:scope]).to eq 'read write'
+ expect(response.parsed_body[:scope]).to eq 'read write'
end
end
@@ -76,7 +76,7 @@ RSpec.describe 'Obtaining OAuth Tokens' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:scope]).to eq('read')
+ expect(response.parsed_body[:scope]).to eq('read')
end
end
@@ -88,7 +88,7 @@ RSpec.describe 'Obtaining OAuth Tokens' do
subject
expect(response).to have_http_status(200)
- expect(body_as_json[:scope]).to eq 'read write'
+ expect(response.parsed_body[:scope]).to eq 'read write'
end
end
diff --git a/spec/requests/omniauth_callbacks_spec.rb b/spec/requests/omniauth_callbacks_spec.rb
index 095535e485..e13a49ec62 100644
--- a/spec/requests/omniauth_callbacks_spec.rb
+++ b/spec/requests/omniauth_callbacks_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'OmniAuth callbacks' do
+RSpec.describe 'OmniAuth callbacks' do
shared_examples 'omniauth provider callbacks' do |provider|
subject { post send :"user_#{provider}_omniauth_callback_path" }
diff --git a/spec/requests/remote_interaction_helper_spec.rb b/spec/requests/remote_interaction_helper_spec.rb
index e6364fe8ce..942f70b9a4 100644
--- a/spec/requests/remote_interaction_helper_spec.rb
+++ b/spec/requests/remote_interaction_helper_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Remote Interaction Helper' do
+RSpec.describe 'Remote Interaction Helper' do
describe 'GET /remote_interaction_helper' do
it 'returns http success' do
get remote_interaction_helper_path
diff --git a/spec/requests/self_destruct_spec.rb b/spec/requests/self_destruct_spec.rb
index f71a2325e2..651a894c89 100644
--- a/spec/requests/self_destruct_spec.rb
+++ b/spec/requests/self_destruct_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Self-destruct mode' do
+RSpec.describe 'Self-destruct mode' do
before do
allow(SelfDestructHelper).to receive(:self_destruct?).and_return(true)
end
diff --git a/spec/requests/settings/applications_spec.rb b/spec/requests/settings/applications_spec.rb
new file mode 100644
index 0000000000..8a5b3de895
--- /dev/null
+++ b/spec/requests/settings/applications_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings / Exports' do
+ let(:user) { Fabricate :user }
+
+ before { sign_in user }
+
+ describe 'GET /settings/application/:id' do
+ context 'when user does not own application' do
+ let(:application) { Fabricate :application }
+
+ it 'returns http missing' do
+ get settings_application_path(application)
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+ end
+
+ describe 'POST /settings/applications' do
+ subject { post '/settings/applications', params: params }
+
+ let(:params) do
+ {
+ doorkeeper_application: {
+ name: 'My New App',
+ redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
+ website: 'http://google.com',
+ scopes: 'read write follow',
+ },
+ }
+ end
+
+ it 'supports passing scope values as string' do
+ expect { subject }
+ .to change(Doorkeeper::Application, :count).by(1)
+ expect(response)
+ .to redirect_to(settings_applications_path)
+ end
+ end
+end
diff --git a/spec/requests/settings/exports/blocked_accounts_spec.rb b/spec/requests/settings/exports/blocked_accounts_spec.rb
new file mode 100644
index 0000000000..9d0768a1e3
--- /dev/null
+++ b/spec/requests/settings/exports/blocked_accounts_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings / Exports / Blocked Accounts' do
+ describe 'GET /settings/exports/blocks' do
+ context 'with a signed in user who has blocked accounts' do
+ let(:user) { Fabricate :user }
+
+ before do
+ Fabricate(
+ :block,
+ account: user.account,
+ target_account: Fabricate(:account, username: 'username', domain: 'domain')
+ )
+ sign_in user
+ end
+
+ it 'returns a CSV with the blocking accounts' do
+ get '/settings/exports/blocks.csv'
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to eq('text/csv')
+ expect(response.body)
+ .to eq(<<~CSV)
+ username@domain
+ CSV
+ end
+ end
+
+ describe 'when signed out' do
+ it 'returns unauthorized' do
+ get '/settings/exports/blocks.csv'
+
+ expect(response)
+ .to have_http_status(401)
+ end
+ end
+ end
+end
diff --git a/spec/requests/settings/exports/blocked_domains_spec.rb b/spec/requests/settings/exports/blocked_domains_spec.rb
new file mode 100644
index 0000000000..838baf8cdb
--- /dev/null
+++ b/spec/requests/settings/exports/blocked_domains_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings / Exports / Blocked Domains' do
+ describe 'GET /settings/exports/domain_blocks' do
+ context 'with a signed in user who has blocked domains' do
+ let(:account) { Fabricate :account, domain: 'example.com' }
+ let(:user) { Fabricate :user, account: account }
+
+ before do
+ Fabricate(:account_domain_block, domain: 'example.com', account: account)
+ sign_in user
+ end
+
+ it 'returns a CSV with the domains' do
+ get '/settings/exports/domain_blocks.csv'
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to eq('text/csv')
+ expect(response.body)
+ .to eq(<<~CSV)
+ example.com
+ CSV
+ end
+ end
+
+ describe 'when signed out' do
+ it 'returns unauthorized' do
+ get '/settings/exports/domain_blocks.csv'
+
+ expect(response)
+ .to have_http_status(401)
+ end
+ end
+ end
+end
diff --git a/spec/requests/settings/exports/bookmarks_spec.rb b/spec/requests/settings/exports/bookmarks_spec.rb
new file mode 100644
index 0000000000..e97f4a84d2
--- /dev/null
+++ b/spec/requests/settings/exports/bookmarks_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings / Exports / Bookmarks' do
+ describe 'GET /settings/exports/bookmarks' do
+ context 'with a signed in user who has bookmarks' do
+ let(:account) { Fabricate(:account, domain: 'foo.bar') }
+ let(:status) { Fabricate(:status, account: account, uri: 'https://foo.bar/statuses/1312') }
+ let(:user) { Fabricate(:user) }
+
+ before do
+ Fabricate(
+ :bookmark,
+ account: user.account,
+ status: status
+ )
+ sign_in user
+ end
+
+ it 'returns a CSV with the bookmarked statuses' do
+ get '/settings/exports/bookmarks.csv'
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to eq('text/csv')
+ expect(response.body)
+ .to eq(<<~CSV)
+ https://foo.bar/statuses/1312
+ CSV
+ end
+ end
+
+ describe 'when signed out' do
+ it 'returns unauthorized' do
+ get '/settings/exports/bookmarks.csv'
+
+ expect(response)
+ .to have_http_status(401)
+ end
+ end
+ end
+end
diff --git a/spec/requests/settings/exports/following_accounts_spec.rb b/spec/requests/settings/exports/following_accounts_spec.rb
new file mode 100644
index 0000000000..c34ec261a6
--- /dev/null
+++ b/spec/requests/settings/exports/following_accounts_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings / Exports / Following Accounts' do
+ describe 'GET /settings/exports/follows' do
+ context 'with a signed in user who is following accounts' do
+ let(:user) { Fabricate :user }
+
+ before do
+ Fabricate(
+ :follow,
+ account: user.account,
+ target_account: Fabricate(:account, username: 'username', domain: 'domain'),
+ languages: ['en']
+ )
+ sign_in user
+ end
+
+ it 'returns a CSV with the accounts' do
+ get '/settings/exports/follows.csv'
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to eq('text/csv')
+ expect(response.body)
+ .to eq(<<~CSV)
+ Account address,Show boosts,Notify on new posts,Languages
+ username@domain,true,false,en
+ CSV
+ end
+ end
+
+ describe 'when signed out' do
+ it 'returns unauthorized' do
+ get '/settings/exports/follows.csv'
+
+ expect(response)
+ .to have_http_status(401)
+ end
+ end
+ end
+end
diff --git a/spec/requests/settings/exports/lists_spec.rb b/spec/requests/settings/exports/lists_spec.rb
new file mode 100644
index 0000000000..4c13225bb9
--- /dev/null
+++ b/spec/requests/settings/exports/lists_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings / Exports / Lists' do
+ describe 'GET /settings/exports/lists' do
+ context 'with a signed in user who has lists' do
+ let(:account) { Fabricate(:account, username: 'test', domain: 'example.com') }
+ let(:list) { Fabricate :list, account: account, title: 'The List' }
+ let(:user) { Fabricate(:user, account: account) }
+
+ before do
+ Fabricate(:list_account, list: list, account: account)
+ sign_in user
+ end
+
+ it 'returns a CSV with the list' do
+ get '/settings/exports/lists.csv'
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to eq('text/csv')
+ expect(response.body)
+ .to eq(<<~CSV)
+ The List,test@example.com
+ CSV
+ end
+ end
+
+ describe 'when signed out' do
+ it 'returns unauthorized' do
+ get '/settings/exports/lists.csv'
+
+ expect(response)
+ .to have_http_status(401)
+ end
+ end
+ end
+end
diff --git a/spec/requests/settings/exports/muted_accounts_spec.rb b/spec/requests/settings/exports/muted_accounts_spec.rb
new file mode 100644
index 0000000000..98ccb3e4a2
--- /dev/null
+++ b/spec/requests/settings/exports/muted_accounts_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings / Exports / Muted Accounts' do
+ describe 'GET /settings/exports/mutes' do
+ context 'with a signed in user who has muted accounts' do
+ let(:user) { Fabricate :user }
+
+ before do
+ Fabricate(
+ :mute,
+ account: user.account,
+ target_account: Fabricate(:account, username: 'username', domain: 'domain')
+ )
+ sign_in user
+ end
+
+ it 'returns a CSV with the muted accounts' do
+ get '/settings/exports/mutes.csv'
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to eq('text/csv')
+ expect(response.body)
+ .to eq(<<~CSV)
+ Account address,Hide notifications
+ username@domain,true
+ CSV
+ end
+ end
+
+ describe 'when signed out' do
+ it 'returns unauthorized' do
+ get '/settings/exports/mutes.csv'
+
+ expect(response)
+ .to have_http_status(401)
+ end
+ end
+ end
+end
diff --git a/spec/requests/settings/exports_spec.rb b/spec/requests/settings/exports_spec.rb
new file mode 100644
index 0000000000..db823ac770
--- /dev/null
+++ b/spec/requests/settings/exports_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings / Exports' do
+ context 'when not signed in' do
+ describe 'GET /settings/export' do
+ it 'redirects to sign in page' do
+ get settings_export_path
+
+ expect(response)
+ .to redirect_to new_user_session_path
+ end
+ end
+
+ describe 'POST /settings/export' do
+ it 'redirects to sign in page' do
+ post settings_export_path
+
+ expect(response)
+ .to redirect_to new_user_session_path
+ end
+ end
+ end
+end
diff --git a/spec/requests/severed_relationships_spec.rb b/spec/requests/severed_relationships_spec.rb
new file mode 100644
index 0000000000..ac98ab8f94
--- /dev/null
+++ b/spec/requests/severed_relationships_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Severed Relationships' do
+ let(:account_rs_event) { Fabricate :account_relationship_severance_event }
+
+ before { sign_in Fabricate(:user) }
+
+ describe 'GET /severed_relationships/:id/following' do
+ it 'returns a CSV file with correct data' do
+ get following_severed_relationship_path(account_rs_event, format: :csv)
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('text/csv')
+ expect(response.headers['Content-Disposition'])
+ .to match(<<~FILENAME.squish)
+ attachment; filename="following-example.com-#{Date.current}.csv"
+ FILENAME
+ expect(response.body)
+ .to include('Account address')
+ end
+ end
+
+ describe 'GET /severed_relationships/:id/followers' do
+ it 'returns a CSV file with correct data' do
+ get followers_severed_relationship_path(account_rs_event, format: :csv)
+
+ expect(response)
+ .to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('text/csv')
+ expect(response.headers['Content-Disposition'])
+ .to match(<<~FILENAME.squish)
+ attachment; filename="followers-example.com-#{Date.current}.csv"
+ FILENAME
+ expect(response.body)
+ .to include('Account address')
+ end
+ end
+end
diff --git a/spec/requests/signature_verification_spec.rb b/spec/requests/signature_verification_spec.rb
index 401828c4a3..128e7c0787 100644
--- a/spec/requests/signature_verification_spec.rb
+++ b/spec/requests/signature_verification_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'signature verification concern' do
+RSpec.describe 'signature verification concern' do
before do
stub_tests_controller
@@ -50,7 +50,7 @@ describe 'signature verification concern' do
get '/activitypub/success'
expect(response).to have_http_status(200)
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: false,
signature_actor_id: nil,
error: 'Request not signed'
@@ -62,7 +62,7 @@ describe 'signature verification concern' do
get '/activitypub/signature_required'
expect(response).to have_http_status(401)
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
error: 'Request not signed'
)
end
@@ -87,7 +87,7 @@ describe 'signature verification concern' do
}
expect(response).to have_http_status(200)
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: actor.id.to_s
)
@@ -109,7 +109,7 @@ describe 'signature verification concern' do
}
expect(response).to have_http_status(200)
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: actor.id.to_s
)
@@ -131,7 +131,7 @@ describe 'signature verification concern' do
}
expect(response).to have_http_status(200)
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: actor.id.to_s
)
@@ -152,7 +152,7 @@ describe 'signature verification concern' do
'Signature' => signature_header,
}
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: nil,
error: anything
@@ -168,7 +168,7 @@ describe 'signature verification concern' do
'Signature' => 'keyId="https://remote.domain/users/bob#main-key",algorithm="rsa-sha256",headers="date host (request-target)",signature="Z8ilar3J7bOwqZkMp7sL8sRs4B1FT+UorbmvWoE+A5UeoOJ3KBcUmbsh+k3wQwbP5gMNUrra9rEWabpasZGphLsbDxfbsWL3Cf0PllAc7c1c7AFEwnewtExI83/qqgEkfWc2z7UDutXc2NfgAx89Ox8DXU/fA2GG0jILjB6UpFyNugkY9rg6oI31UnvfVi3R7sr3/x8Ea3I9thPvqI2byF6cojknSpDAwYzeKdngX3TAQEGzFHz3SDWwyp3jeMWfwvVVbM38FxhvAnSumw7YwWW4L7M7h4M68isLimoT3yfCn2ucBVL5Dz8koBpYf/40w7QidClAwCafZQFC29yDOg=="', # rubocop:disable Layout/LineLength
}
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: nil,
error: anything
@@ -184,7 +184,7 @@ describe 'signature verification concern' do
'Signature' => 'keyId="https://remote.domain/users/bob#main-key",algorithm="rsa-sha256",headers="date host (request-target)",signature="Z8ilar3J7bOwqZkMp7sL8sRs4B1FT+UorbmvWoE+A5UeoOJ3KBcUmbsh+k3wQwbP5gMNUrra9rEWabpasZGphLsbDxfbsWL3Cf0PllAc7c1c7AFEwnewtExI83/qqgEkfWc2z7UDutXc2NfgAx89Ox8DXU/fA2GG0jILjB6UpFyNugkY9rg6oI31UnvfVi3R7sr3/x8Ea3I9thPvqI2byF6cojknSpDAwYzeKdngX3TAQEGzFHz3SDWwyp3jeMWfwvVVbM38FxhvAnSumw7YwWW4L7M7h4M68isLimoT3yfCn2ucBVL5Dz8koBpYf/40w7QidClAwCafZQFC29yDOg=="', # rubocop:disable Layout/LineLength
}
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: nil,
error: anything
@@ -206,7 +206,7 @@ describe 'signature verification concern' do
'Signature' => signature_header,
}
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: nil,
error: 'Invalid Date header: not RFC 2616 compliant date: "wrong date"'
@@ -228,7 +228,7 @@ describe 'signature verification concern' do
'Signature' => signature_header,
}
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: nil,
error: 'Signed request date outside acceptable time window'
@@ -254,7 +254,7 @@ describe 'signature verification concern' do
}
expect(response).to have_http_status(200)
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: actor.id.to_s
)
@@ -278,7 +278,7 @@ describe 'signature verification concern' do
'Signature' => signature_header,
}
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: nil,
error: 'Mastodon requires the Digest header to be signed when doing a POST request'
@@ -303,7 +303,7 @@ describe 'signature verification concern' do
'Signature' => signature_header,
}
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: nil,
error: 'Invalid Digest value. Computed SHA-256 digest: wFNeS+K3n/2TKRMFQ2v4iTFOSj+uwF7P/Lt98xrZ5Ro=; given: ZOyIygCyaOW6GjVnihtTFtIS9PNmskdyMlNKiuyjfzw='
@@ -321,7 +321,7 @@ describe 'signature verification concern' do
}
expect(response).to have_http_status(200)
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: nil,
error: anything
@@ -342,7 +342,7 @@ describe 'signature verification concern' do
'Signature' => 'keyId="https://remote.domain/users/alice#main-key",algorithm="rsa-sha256",headers="date host (request-target)",signature="Z8ilar3J7bOwqZkMp7sL8sRs4B1FT+UorbmvWoE+A5UeoOJ3KBcUmbsh+k3wQwbP5gMNUrra9rEWabpasZGphLsbDxfbsWL3Cf0PllAc7c1c7AFEwnewtExI83/qqgEkfWc2z7UDutXc2NfgAx89Ox8DXU/fA2GG0jILjB6UpFyNugkY9rg6oI31UnvfVi3R7sr3/x8Ea3I9thPvqI2byF6cojknSpDAwYzeKdngX3TAQEGzFHz3SDWwyp3jeMWfwvVVbM38FxhvAnSumw7YwWW4L7M7h4M68isLimoT3yfCn2ucBVL5Dz8koBpYf/40w7QidClAwCafZQFC29yDOg=="', # rubocop:disable Layout/LineLength
}
- expect(body_as_json).to match(
+ expect(response.parsed_body).to match(
signed_request: true,
signature_actor_id: nil,
error: 'Unable to fetch key JSON at https://remote.domain/users/alice#main-key'
diff --git a/spec/requests/tags_spec.rb b/spec/requests/tags_spec.rb
new file mode 100644
index 0000000000..7974a6b152
--- /dev/null
+++ b/spec/requests/tags_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Tags' do
+ describe 'GET /tags/:id' do
+ context 'when tag exists' do
+ let(:tag) { Fabricate :tag }
+
+ context 'with HTML format' do
+ # TODO: Update the have_cacheable_headers matcher to operate on capybara sessions
+ # Remove this example, rely on system spec (which should use matcher)
+ before { get tag_path(tag) }
+
+ it 'returns http success' do
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
+ end
+ end
+
+ context 'with JSON format' do
+ before { get tag_path(tag, format: :json) }
+
+ it 'returns http success' do
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
+ expect(response.content_type)
+ .to start_with('application/activity+json')
+ end
+ end
+
+ context 'with RSS format' do
+ before { get tag_path(tag, format: :rss) }
+
+ it 'returns http success' do
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
+ expect(response.content_type)
+ .to start_with('application/rss+xml')
+ end
+ end
+ end
+
+ context 'when tag does not exist' do
+ before { get tag_path('missing') }
+
+ it 'returns http not found' do
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+ end
+end
diff --git a/spec/requests/well_known/change_password_spec.rb b/spec/requests/well_known/change_password_spec.rb
index 04134b71ff..77fec15412 100644
--- a/spec/requests/well_known/change_password_spec.rb
+++ b/spec/requests/well_known/change_password_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'The /.well-known/change-password request' do
+RSpec.describe 'The /.well-known/change-password request' do
it 'redirects to the change password page' do
get '/.well-known/change-password'
diff --git a/spec/requests/well_known/host_meta_spec.rb b/spec/requests/well_known/host_meta_spec.rb
index ca10a51a01..09f17baa89 100644
--- a/spec/requests/well_known/host_meta_spec.rb
+++ b/spec/requests/well_known/host_meta_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'The /.well-known/host-meta request' do
+RSpec.describe 'The /.well-known/host-meta request' do
it 'returns http success with valid XML response' do
get '/.well-known/host-meta'
diff --git a/spec/requests/well_known/node_info_spec.rb b/spec/requests/well_known/node_info_spec.rb
index 0934b0fde6..3d5afc7e2d 100644
--- a/spec/requests/well_known/node_info_spec.rb
+++ b/spec/requests/well_known/node_info_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'The well-known node-info endpoints' do
+RSpec.describe 'The well-known node-info endpoints' do
describe 'The /.well-known/node-info endpoint' do
it 'returns JSON document pointing to node info' do
get '/.well-known/nodeinfo'
@@ -13,7 +13,7 @@ describe 'The well-known node-info endpoints' do
media_type: 'application/json'
)
- expect(body_as_json).to include(
+ expect(response.parsed_body).to include(
links: be_an(Array).and(
contain_exactly(
include(
@@ -39,7 +39,7 @@ describe 'The well-known node-info endpoints' do
expect(non_matching_hash)
.to_not match_json_schema('nodeinfo_2.0')
- expect(body_as_json)
+ expect(response.parsed_body)
.to match_json_schema('nodeinfo_2.0')
.and include(
version: '2.0',
diff --git a/spec/requests/well_known/oauth_metadata_spec.rb b/spec/requests/well_known/oauth_metadata_spec.rb
index 9d2d202286..9c86dbedfe 100644
--- a/spec/requests/well_known/oauth_metadata_spec.rb
+++ b/spec/requests/well_known/oauth_metadata_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'The /.well-known/oauth-authorization-server request' do
+RSpec.describe 'The /.well-known/oauth-authorization-server request' do
let(:protocol) { ENV.fetch('LOCAL_HTTPS', true) ? :https : :http }
before do
@@ -21,7 +21,7 @@ describe 'The /.well-known/oauth-authorization-server request' do
grant_types_supported = Doorkeeper.configuration.grant_flows.dup
grant_types_supported << 'refresh_token' if Doorkeeper.configuration.refresh_token_enabled?
- expect(body_as_json).to include(
+ expect(response.parsed_body).to include(
issuer: root_url(protocol: protocol),
service_documentation: 'https://docs.joinmastodon.org/',
authorization_endpoint: oauth_authorization_url(protocol: protocol),
diff --git a/spec/requests/well_known/webfinger_spec.rb b/spec/requests/well_known/webfinger_spec.rb
index 0aafdf5624..aeff56aebf 100644
--- a/spec/requests/well_known/webfinger_spec.rb
+++ b/spec/requests/well_known/webfinger_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'The /.well-known/webfinger endpoint' do
+RSpec.describe 'The /.well-known/webfinger endpoint' do
subject(:perform_request!) { get webfinger_url(resource: resource) }
let(:alternate_domains) { [] }
@@ -24,7 +24,7 @@ describe 'The /.well-known/webfinger endpoint' do
expect(response.media_type).to eq 'application/jrd+json'
- expect(body_as_json)
+ expect(response.parsed_body)
.to include(
subject: eq('acct:alice@cb6e6126.ngrok.io'),
aliases: include('https://cb6e6126.ngrok.io/@alice', 'https://cb6e6126.ngrok.io/users/alice')
@@ -129,9 +129,11 @@ describe 'The /.well-known/webfinger endpoint' do
end
it 'returns links for the internal account' do
- json = body_as_json
- expect(json[:subject]).to eq 'acct:mastodon.internal@cb6e6126.ngrok.io'
- expect(json[:aliases]).to eq ['https://cb6e6126.ngrok.io/actor']
+ expect(response.parsed_body)
+ .to include(
+ subject: 'acct:mastodon.internal@cb6e6126.ngrok.io',
+ aliases: ['https://cb6e6126.ngrok.io/actor']
+ )
end
end
@@ -166,10 +168,12 @@ describe 'The /.well-known/webfinger endpoint' do
it 'returns avatar in response' do
perform_request!
- avatar_link = get_avatar_link(body_as_json)
- expect(avatar_link).to_not be_nil
- expect(avatar_link[:type]).to eq alice.avatar.content_type
- expect(avatar_link[:href]).to eq Addressable::URI.new(host: Rails.configuration.x.local_domain, path: alice.avatar.to_s, scheme: 'https').to_s
+ expect(response_avatar_link)
+ .to be_present
+ .and include(
+ type: eq(alice.avatar.content_type),
+ href: eq(Addressable::URI.new(host: Rails.configuration.x.local_domain, path: alice.avatar.to_s, scheme: 'https').to_s)
+ )
end
context 'with limited federation mode' do
@@ -180,8 +184,8 @@ describe 'The /.well-known/webfinger endpoint' do
it 'does not return avatar in response' do
perform_request!
- avatar_link = get_avatar_link(body_as_json)
- expect(avatar_link).to be_nil
+ expect(response_avatar_link)
+ .to be_nil
end
end
@@ -195,8 +199,8 @@ describe 'The /.well-known/webfinger endpoint' do
it 'does not return avatar in response' do
perform_request!
- avatar_link = get_avatar_link(body_as_json)
- expect(avatar_link).to be_nil
+ expect(response_avatar_link)
+ .to be_nil
end
end
end
@@ -210,8 +214,8 @@ describe 'The /.well-known/webfinger endpoint' do
end
it 'does not return avatar in response' do
- avatar_link = get_avatar_link(body_as_json)
- expect(avatar_link).to be_nil
+ expect(response_avatar_link)
+ .to be_nil
end
end
@@ -245,7 +249,9 @@ describe 'The /.well-known/webfinger endpoint' do
private
- def get_avatar_link(json)
- json[:links].find { |link| link[:rel] == 'http://webfinger.net/rel/avatar' }
+ def response_avatar_link
+ response
+ .parsed_body[:links]
+ .find { |link| link[:rel] == 'http://webfinger.net/rel/avatar' }
end
end
diff --git a/spec/routing/accounts_routing_spec.rb b/spec/routing/accounts_routing_spec.rb
index 588855943e..8ff711a681 100644
--- a/spec/routing/accounts_routing_spec.rb
+++ b/spec/routing/accounts_routing_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Routes under accounts/' do
+RSpec.describe 'Routes under accounts/' do
context 'with local username' do
let(:username) { 'alice' }
diff --git a/spec/routing/api_routing_spec.rb b/spec/routing/api_routing_spec.rb
index a822fba4c5..c46fa75d1f 100644
--- a/spec/routing/api_routing_spec.rb
+++ b/spec/routing/api_routing_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'API routes' do
+RSpec.describe 'API routes' do
describe 'Credentials routes' do
it 'routes to verify credentials' do
expect(get('/api/v1/accounts/verify_credentials'))
diff --git a/spec/routing/well_known_routes_spec.rb b/spec/routing/well_known_routes_spec.rb
index 8cf08c13c1..6578e939ae 100644
--- a/spec/routing/well_known_routes_spec.rb
+++ b/spec/routing/well_known_routes_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Well Known routes' do
+RSpec.describe 'Well Known routes' do
describe 'the host-meta route' do
it 'routes to correct place with xml format' do
expect(get('/.well-known/host-meta'))
diff --git a/spec/search/models/concerns/account/search_spec.rb b/spec/search/models/concerns/account/search_spec.rb
index d8d7f355dd..de12161ef9 100644
--- a/spec/search/models/concerns/account/search_spec.rb
+++ b/spec/search/models/concerns/account/search_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Account::Search do
+RSpec.describe Account::Search do
describe 'a non-discoverable account becoming discoverable' do
let(:account) { Account.find_by(username: 'search_test_account_1') }
diff --git a/spec/search/models/concerns/account/statuses_search_spec.rb b/spec/search/models/concerns/account/statuses_search_spec.rb
index b1bf4968ca..bce1aecd75 100644
--- a/spec/search/models/concerns/account/statuses_search_spec.rb
+++ b/spec/search/models/concerns/account/statuses_search_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Account::StatusesSearch, :inline_jobs do
+RSpec.describe Account::StatusesSearch, :inline_jobs do
describe 'a non-indexable account becoming indexable' do
let(:account) { Account.find_by(username: 'search_test_account_1') }
diff --git a/spec/serializers/activitypub/device_serializer_spec.rb b/spec/serializers/activitypub/device_serializer_spec.rb
deleted file mode 100644
index 23f0b24c4e..0000000000
--- a/spec/serializers/activitypub/device_serializer_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ActivityPub::DeviceSerializer do
- let(:serialization) { serialized_record_json(record, described_class) }
- let(:record) { Fabricate(:device) }
-
- describe 'type' do
- it 'returns correct serialized type' do
- expect(serialization['type']).to eq('Device')
- end
- end
-end
diff --git a/spec/serializers/activitypub/note_serializer_spec.rb b/spec/serializers/activitypub/note_serializer_spec.rb
index 338d66b308..285b241ee2 100644
--- a/spec/serializers/activitypub/note_serializer_spec.rb
+++ b/spec/serializers/activitypub/note_serializer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::NoteSerializer do
+RSpec.describe ActivityPub::NoteSerializer do
subject { serialized_record_json(parent, described_class, adapter: ActivityPub::Adapter) }
let!(:account) { Fabricate(:account) }
diff --git a/spec/serializers/activitypub/one_time_key_serializer_spec.rb b/spec/serializers/activitypub/one_time_key_serializer_spec.rb
deleted file mode 100644
index 89efe95c8c..0000000000
--- a/spec/serializers/activitypub/one_time_key_serializer_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ActivityPub::OneTimeKeySerializer do
- let(:serialization) { serialized_record_json(record, described_class) }
- let(:record) { Fabricate(:one_time_key) }
-
- describe 'type' do
- it 'returns correct serialized type' do
- expect(serialization['type']).to eq('Curve25519Key')
- end
- end
-end
diff --git a/spec/serializers/activitypub/undo_like_serializer_spec.rb b/spec/serializers/activitypub/undo_like_serializer_spec.rb
index 3d61e86751..c7190adc1a 100644
--- a/spec/serializers/activitypub/undo_like_serializer_spec.rb
+++ b/spec/serializers/activitypub/undo_like_serializer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::UndoLikeSerializer do
+RSpec.describe ActivityPub::UndoLikeSerializer do
let(:serialization) { serialized_record_json(record, described_class) }
let(:record) { Fabricate(:favourite) }
diff --git a/spec/serializers/activitypub/update_poll_serializer_spec.rb b/spec/serializers/activitypub/update_poll_serializer_spec.rb
index 8ff4fd2701..6a4d8177fc 100644
--- a/spec/serializers/activitypub/update_poll_serializer_spec.rb
+++ b/spec/serializers/activitypub/update_poll_serializer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::UpdatePollSerializer do
+RSpec.describe ActivityPub::UpdatePollSerializer do
subject { serialized_record_json(status, described_class, adapter: ActivityPub::Adapter) }
let(:account) { Fabricate(:account) }
diff --git a/spec/serializers/activitypub/vote_serializer_spec.rb b/spec/serializers/activitypub/vote_serializer_spec.rb
index b7c0b8928b..4e8a2beca3 100644
--- a/spec/serializers/activitypub/vote_serializer_spec.rb
+++ b/spec/serializers/activitypub/vote_serializer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::VoteSerializer do
+RSpec.describe ActivityPub::VoteSerializer do
let(:serialization) { serialized_record_json(record, described_class) }
let(:record) { Fabricate(:poll_vote) }
diff --git a/spec/serializers/rest/account_serializer_spec.rb b/spec/serializers/rest/account_serializer_spec.rb
index 15939e484d..7daa0796a9 100644
--- a/spec/serializers/rest/account_serializer_spec.rb
+++ b/spec/serializers/rest/account_serializer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe REST::AccountSerializer do
+RSpec.describe REST::AccountSerializer do
subject { serialized_record_json(account, described_class) }
let(:role) { Fabricate(:user_role, name: 'Role', highlighted: true) }
diff --git a/spec/serializers/rest/encrypted_message_serializer_spec.rb b/spec/serializers/rest/encrypted_message_serializer_spec.rb
deleted file mode 100644
index 01db1149af..0000000000
--- a/spec/serializers/rest/encrypted_message_serializer_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe REST::EncryptedMessageSerializer do
- let(:serialization) { serialized_record_json(record, described_class) }
- let(:record) { Fabricate(:encrypted_message) }
-
- describe 'account' do
- it 'returns the associated account' do
- expect(serialization['account_id']).to eq(record.from_account.id.to_s)
- end
- end
-end
diff --git a/spec/serializers/rest/instance_serializer_spec.rb b/spec/serializers/rest/instance_serializer_spec.rb
index 39e6b3820b..2d8d14e39a 100644
--- a/spec/serializers/rest/instance_serializer_spec.rb
+++ b/spec/serializers/rest/instance_serializer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe REST::InstanceSerializer do
+RSpec.describe REST::InstanceSerializer do
let(:serialization) { serialized_record_json(record, described_class) }
let(:record) { InstancePresenter.new }
diff --git a/spec/serializers/rest/keys/claim_result_serializer_spec.rb b/spec/serializers/rest/keys/claim_result_serializer_spec.rb
deleted file mode 100644
index 7f7fb850cd..0000000000
--- a/spec/serializers/rest/keys/claim_result_serializer_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe REST::Keys::ClaimResultSerializer do
- let(:serialization) { serialized_record_json(record, described_class) }
- let(:record) { Keys::ClaimService::Result.new(Account.new(id: 123), 456) }
-
- describe 'account' do
- it 'returns the associated account' do
- expect(serialization['account_id']).to eq('123')
- end
- end
-end
diff --git a/spec/serializers/rest/keys/device_serializer_spec.rb b/spec/serializers/rest/keys/device_serializer_spec.rb
deleted file mode 100644
index 28177a3db5..0000000000
--- a/spec/serializers/rest/keys/device_serializer_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe REST::Keys::DeviceSerializer do
- let(:serialization) { serialized_record_json(record, described_class) }
- let(:record) { Device.new(name: 'Device name') }
-
- describe 'name' do
- it 'returns the name' do
- expect(serialization['name']).to eq('Device name')
- end
- end
-end
diff --git a/spec/serializers/rest/keys/query_result_serializer_spec.rb b/spec/serializers/rest/keys/query_result_serializer_spec.rb
deleted file mode 100644
index ef67d70675..0000000000
--- a/spec/serializers/rest/keys/query_result_serializer_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe REST::Keys::QueryResultSerializer do
- let(:serialization) { serialized_record_json(record, described_class) }
- let(:record) { Keys::QueryService::Result.new(Account.new(id: 123), []) }
-
- describe 'account' do
- it 'returns the associated account id' do
- expect(serialization['account_id']).to eq('123')
- end
- end
-end
diff --git a/spec/serializers/rest/suggestion_serializer_spec.rb b/spec/serializers/rest/suggestion_serializer_spec.rb
index b5efba082d..288d1daa23 100644
--- a/spec/serializers/rest/suggestion_serializer_spec.rb
+++ b/spec/serializers/rest/suggestion_serializer_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe REST::SuggestionSerializer do
+RSpec.describe REST::SuggestionSerializer do
let(:serialization) { serialized_record_json(record, described_class) }
let(:record) do
AccountSuggestions::Suggestion.new(
diff --git a/spec/services/account_search_service_spec.rb b/spec/services/account_search_service_spec.rb
index 5ec0885903..7d251641ee 100644
--- a/spec/services/account_search_service_spec.rb
+++ b/spec/services/account_search_service_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe AccountSearchService do
+RSpec.describe AccountSearchService do
describe '#call' do
context 'with a query to ignore' do
it 'returns empty array for missing query' do
diff --git a/spec/services/account_statuses_cleanup_service_spec.rb b/spec/services/account_statuses_cleanup_service_spec.rb
index 403c4632d7..857bd4fda4 100644
--- a/spec/services/account_statuses_cleanup_service_spec.rb
+++ b/spec/services/account_statuses_cleanup_service_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe AccountStatusesCleanupService do
+RSpec.describe AccountStatusesCleanupService do
let(:account) { Fabricate(:account, username: 'alice', domain: nil) }
let(:account_policy) { Fabricate(:account_statuses_cleanup_policy, account: account) }
let!(:unrelated_status) { Fabricate(:status, created_at: 3.years.ago) }
diff --git a/spec/services/activitypub/fetch_remote_status_service_spec.rb b/spec/services/activitypub/fetch_remote_status_service_spec.rb
index 635fcb7976..9d8c6e0e0a 100644
--- a/spec/services/activitypub/fetch_remote_status_service_spec.rb
+++ b/spec/services/activitypub/fetch_remote_status_service_spec.rb
@@ -72,7 +72,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
expect(status).to_not be_nil
expect(status.url).to eq 'https://foo.bar/watch?v=12345'
- expect(strip_tags(status.text)).to eq 'Nyan Cat 10 hours remixhttps://foo.bar/watch?v=12345'
+ expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remix\n\nhttps://foo.bar/watch?v=12345"
end
end
@@ -105,7 +105,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
expect(status).to_not be_nil
expect(status.url).to eq 'https://foo.bar/watch?v=12345'
- expect(strip_tags(status.text)).to eq 'Nyan Cat 10 hours remixhttps://foo.bar/watch?v=12345'
+ expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remix\n\nhttps://foo.bar/watch?v=12345"
end
end
@@ -125,7 +125,58 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
expect(status).to_not be_nil
expect(status.url).to eq 'https://foo.bar/@foo/1234'
- expect(strip_tags(status.text)).to eq "Let's change the worldhttps://foo.bar/@foo/1234"
+ expect(strip_tags(status.text)).to eq "Let's change the world\n\nhttps://foo.bar/@foo/1234"
+ end
+ end
+
+ context 'with Event object that contains a HTML summary' do
+ let(:object) do
+ {
+ '@context': 'https://www.w3.org/ns/activitystreams',
+ id: 'https://foo.bar/@foo/1234',
+ type: 'Event',
+ name: 'Fediverse Birthday Party',
+ startTime: '2024-01-31T20:00:00.000+01:00',
+ location: {
+ type: 'Place',
+ name: 'FooBar – The not converted location',
+ },
+ content: 'The not converted detailed description of the event object.',
+ summary: 'See you at the FooBar!
',
+ attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
+ }
+ end
+
+ it 'creates status' do
+ status = sender.statuses.first
+
+ expect(status).to_not be_nil
+ expect(status.url).to eq 'https://foo.bar/@foo/1234'
+ expect(status.text).to start_with "#{object[:name]}
\n\n#{object[:summary]}\n\n"
+ expect(status.text).to include "href=\"#{object[:id]}\""
+ end
+ end
+
+ context 'with Article object that contains a HTML summary' do
+ let(:object) do
+ {
+ '@context': 'https://www.w3.org/ns/activitystreams',
+ id: 'https://foo.bar/blog/future-of-the-fediverse',
+ type: 'Article',
+ name: 'Future of the Fediverse',
+ content: 'Lorem Ipsum',
+ summary: 'Guest article by John Mastodon
The fediverse is great reading this you will find out why!
',
+ attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
+ }
+ end
+
+ it 'creates status' do
+ status = sender.statuses.first
+
+ expect(status).to_not be_nil
+ expect(status.url).to eq object[:id]
+ expect(status.text).to start_with "#{object[:name]}
\n\n#{object[:summary]}\n\n"
+ expect(status.text).to include "href=\"#{object[:id]}\""
end
end
diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb
index 86314e6b48..e4a36cf182 100644
--- a/spec/services/activitypub/process_account_service_spec.rb
+++ b/spec/services/activitypub/process_account_service_spec.rb
@@ -63,6 +63,26 @@ RSpec.describe ActivityPub::ProcessAccountService do
end
end
+ context 'with attribution domains' do
+ let(:payload) do
+ {
+ id: 'https://foo.test',
+ type: 'Actor',
+ inbox: 'https://foo.test/inbox',
+ attributionDomains: [
+ 'example.com',
+ ],
+ }.with_indifferent_access
+ end
+
+ it 'parses attribution domains' do
+ account = subject.call('alice', 'example.com', payload)
+
+ expect(account.attribution_domains)
+ .to match_array(%w(example.com))
+ end
+ end
+
context 'when account is not suspended' do
subject { described_class.new.call(account.username, account.domain, payload) }
diff --git a/spec/services/approve_appeal_service_spec.rb b/spec/services/approve_appeal_service_spec.rb
index 5707c5d7f4..52e073df0c 100644
--- a/spec/services/approve_appeal_service_spec.rb
+++ b/spec/services/approve_appeal_service_spec.rb
@@ -4,27 +4,55 @@ require 'rails_helper'
RSpec.describe ApproveAppealService do
describe '#call' do
- context 'with an existing appeal' do
- let(:appeal) { Fabricate(:appeal) }
- let(:account) { Fabricate(:account) }
+ let(:appeal) { Fabricate(:appeal) }
+ let(:account) { Fabricate(:account) }
- it 'processes the appeal approval' do
- expect { subject.call(appeal, account) }
- .to mark_overruled
- .and record_approver
+ it 'processes the appeal approval' do
+ expect { subject.call(appeal, account) }
+ .to mark_overruled
+ .and record_approver
+ end
+
+ context 'with an appeal about then-deleted posts marked as sensitive by moderators' do
+ let(:target_account) { Fabricate(:account) }
+ let(:appeal) { Fabricate(:appeal, strike: strike, account: target_account) }
+ let(:deleted_media) { Fabricate(:media_attachment, type: :video, status: Fabricate(:status, account: target_account), account: target_account) }
+ let(:kept_media) { Fabricate(:media_attachment, type: :video, status: Fabricate(:status, account: target_account), account: target_account) }
+ let(:strike) { Fabricate(:account_warning, target_account: target_account, action: :mark_statuses_as_sensitive, status_ids: [deleted_media.status.id, kept_media.status.id]) }
+
+ before do
+ target_account.unsuspend!
+ deleted_media.status.discard!
end
- def mark_overruled
- change(appeal.strike, :overruled_at)
- .from(nil)
- .to(be > 1.minute.ago)
- end
+ it 'approves the appeal, marks the statuses as not sensitive and notifies target account about the approval', :inline_jobs do
+ emails = capture_emails { subject.call(appeal, account) }
- def record_approver
- change(appeal, :approved_by_account)
- .from(nil)
- .to(account)
+ expect(appeal.reload).to be_approved
+ expect(strike.reload).to be_overruled
+
+ expect(kept_media.status.reload).to_not be_sensitive
+
+ expect(emails.size)
+ .to eq(1)
+ expect(emails.first)
+ .to have_attributes(
+ to: contain_exactly(target_account.user.email),
+ subject: eq(I18n.t('user_mailer.appeal_approved.subject', date: I18n.l(appeal.created_at)))
+ )
end
end
+
+ def mark_overruled
+ change(appeal.strike, :overruled_at)
+ .from(nil)
+ .to(be > 1.minute.ago)
+ end
+
+ def record_approver
+ change(appeal, :approved_by_account)
+ .from(nil)
+ .to(account)
+ end
end
end
diff --git a/spec/services/bulk_import_service_spec.rb b/spec/services/bulk_import_service_spec.rb
index e8bec96c85..0197f81a44 100644
--- a/spec/services/bulk_import_service_spec.rb
+++ b/spec/services/bulk_import_service_spec.rb
@@ -274,7 +274,7 @@ RSpec.describe BulkImportService do
let(:rows) do
[
{ 'domain' => 'blocked.com' },
- { 'domain' => 'to_block.com' },
+ { 'domain' => 'to-block.com' },
]
end
@@ -286,7 +286,7 @@ RSpec.describe BulkImportService do
it 'blocks all the new domains' do
subject.call(import)
- expect(account.domain_blocks.pluck(:domain)).to contain_exactly('alreadyblocked.com', 'blocked.com', 'to_block.com')
+ expect(account.domain_blocks.pluck(:domain)).to contain_exactly('alreadyblocked.com', 'blocked.com', 'to-block.com')
end
it 'marks the import as finished' do
@@ -302,7 +302,7 @@ RSpec.describe BulkImportService do
let(:rows) do
[
{ 'domain' => 'blocked.com' },
- { 'domain' => 'to_block.com' },
+ { 'domain' => 'to-block.com' },
]
end
@@ -314,7 +314,7 @@ RSpec.describe BulkImportService do
it 'blocks all the new domains' do
subject.call(import)
- expect(account.domain_blocks.pluck(:domain)).to contain_exactly('blocked.com', 'to_block.com')
+ expect(account.domain_blocks.pluck(:domain)).to contain_exactly('blocked.com', 'to-block.com')
end
it 'marks the import as finished' do
diff --git a/spec/services/fetch_link_card_service_spec.rb b/spec/services/fetch_link_card_service_spec.rb
index 2f64f40558..1d61e33c0b 100644
--- a/spec/services/fetch_link_card_service_spec.rb
+++ b/spec/services/fetch_link_card_service_spec.rb
@@ -192,8 +192,8 @@ RSpec.describe FetchLinkCardService do
context 'when encoding problems appear in title tag' do
let(:status) { Fabricate(:status, text: 'Check out http://example.com/latin1_posing_as_utf8_broken') }
- it 'does not create a preview card' do
- expect(status.preview_card).to be_nil
+ it 'creates a preview card anyway that replaces invalid bytes with U+FFFD (replacement char)' do
+ expect(status.preview_card.title).to eq("Tofu � l'orange")
end
end
end
diff --git a/spec/services/fetch_oembed_service_spec.rb b/spec/services/fetch_oembed_service_spec.rb
index c9f84048b6..52d2b9cf22 100644
--- a/spec/services/fetch_oembed_service_spec.rb
+++ b/spec/services/fetch_oembed_service_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe FetchOEmbedService do
+RSpec.describe FetchOEmbedService do
subject { described_class.new }
before do
diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb
index f21548b5f2..26db398d5e 100644
--- a/spec/services/post_status_service_spec.rb
+++ b/spec/services/post_status_service_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe PostStatusService do
it 'schedules a status for future creation and does not create one immediately' do
media = Fabricate(:media_attachment, account: account)
- status = subject.call(account, text: 'Hi future!', media_ids: [media.id], scheduled_at: future)
+ status = subject.call(account, text: 'Hi future!', media_ids: [media.id.to_s], scheduled_at: future)
expect(status)
.to be_a(ScheduledStatus)
@@ -42,7 +42,7 @@ RSpec.describe PostStatusService do
scheduled_at: eq(future),
params: include(
'text' => eq('Hi future!'),
- 'media_ids' => contain_exactly(media.id)
+ 'media_ids' => contain_exactly(media.id.to_s)
)
)
expect(media.reload.status).to be_nil
@@ -68,7 +68,10 @@ RSpec.describe PostStatusService do
it 'raises invalid record error' do
expect do
subject.call(account, text: 'Hi future!', scheduled_at: invalid_scheduled_time)
- end.to raise_error(ActiveRecord::RecordInvalid)
+ end.to raise_error(
+ ActiveRecord::RecordInvalid,
+ 'Validation failed: Scheduled at The scheduled date must be in the future'
+ )
end
end
end
@@ -123,6 +126,15 @@ RSpec.describe PostStatusService do
expect(status.visibility).to eq 'private'
end
+ it 'raises on an invalid visibility' do
+ expect do
+ create_status_with_options(visibility: :xxx)
+ end.to raise_error(
+ ActiveRecord::RecordInvalid,
+ 'Validation failed: Visibility is not included in the list'
+ )
+ end
+
it 'creates a status with limited visibility for silenced users' do
status = subject.call(Fabricate(:account, silenced: true), text: 'test', visibility: :public)
@@ -219,7 +231,7 @@ RSpec.describe PostStatusService do
status = subject.call(
account,
text: 'test status update',
- media_ids: [media.id]
+ media_ids: [media.id.to_s]
)
expect(media.reload.status).to eq status
@@ -229,13 +241,16 @@ RSpec.describe PostStatusService do
account = Fabricate(:account)
media = Fabricate(:media_attachment, account: Fabricate(:account))
- subject.call(
- account,
- text: 'test status update',
- media_ids: [media.id]
+ expect do
+ subject.call(
+ account,
+ text: 'test status update',
+ media_ids: [media.id.to_s]
+ )
+ end.to raise_error(
+ Mastodon::ValidationError,
+ I18n.t('media_attachments.validations.not_found', ids: media.id)
)
-
- expect(media.reload.status).to be_nil
end
it 'does not allow attaching more files than configured limit' do
@@ -246,7 +261,7 @@ RSpec.describe PostStatusService do
subject.call(
account,
text: 'test status update',
- media_ids: Array.new(2) { Fabricate(:media_attachment, account: account) }.map(&:id)
+ media_ids: Array.new(2) { Fabricate(:media_attachment, account: account) }.map { |m| m.id.to_s }
)
end.to raise_error(
Mastodon::ValidationError,
@@ -268,7 +283,7 @@ RSpec.describe PostStatusService do
media_ids: [
video,
image,
- ].map(&:id)
+ ].map { |m| m.id.to_s }
)
end.to raise_error(
Mastodon::ValidationError,
diff --git a/spec/services/resolve_account_service_spec.rb b/spec/services/resolve_account_service_spec.rb
index e0084a1579..a856e019a7 100644
--- a/spec/services/resolve_account_service_spec.rb
+++ b/spec/services/resolve_account_service_spec.rb
@@ -228,7 +228,7 @@ RSpec.describe ResolveAccountService do
rescue ActiveRecord::RecordNotUnique
fail_occurred = true
ensure
- RedisConfiguration.pool.checkin if Thread.current[:redis]
+ RedisConnection.pool.checkin if Thread.current[:redis]
end
end
diff --git a/spec/services/resolve_url_service_spec.rb b/spec/services/resolve_url_service_spec.rb
index 3d59a55f10..80f2a5a4ba 100644
--- a/spec/services/resolve_url_service_spec.rb
+++ b/spec/services/resolve_url_service_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ResolveURLService do
+RSpec.describe ResolveURLService do
subject { described_class.new }
describe '#call' do
diff --git a/spec/services/search_service_spec.rb b/spec/services/search_service_spec.rb
index 394ee7c3a6..cd4c424630 100644
--- a/spec/services/search_service_spec.rb
+++ b/spec/services/search_service_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe SearchService do
+RSpec.describe SearchService do
subject { described_class.new }
describe '#call' do
diff --git a/spec/services/unblock_domain_service_spec.rb b/spec/services/unblock_domain_service_spec.rb
index 289ddfc218..405fe1cfd2 100644
--- a/spec/services/unblock_domain_service_spec.rb
+++ b/spec/services/unblock_domain_service_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe UnblockDomainService do
+RSpec.describe UnblockDomainService do
subject { described_class.new }
describe 'call' do
diff --git a/spec/services/update_status_service_spec.rb b/spec/services/update_status_service_spec.rb
index 47be53f4fc..de06fb13c6 100644
--- a/spec/services/update_status_service_spec.rb
+++ b/spec/services/update_status_service_spec.rb
@@ -69,7 +69,7 @@ RSpec.describe UpdateStatusService do
before do
status.media_attachments << detached_media_attachment
- subject.call(status, status.account_id, text: 'Foo', media_ids: [attached_media_attachment.id])
+ subject.call(status, status.account_id, text: 'Foo', media_ids: [attached_media_attachment.id.to_s])
end
it 'updates media attachments' do
@@ -95,7 +95,7 @@ RSpec.describe UpdateStatusService do
before do
status.media_attachments << media_attachment
- subject.call(status, status.account_id, text: 'Foo', media_ids: [media_attachment.id], media_attributes: [{ id: media_attachment.id, description: 'New description' }])
+ subject.call(status, status.account_id, text: 'Foo', media_ids: [media_attachment.id.to_s], media_attributes: [{ id: media_attachment.id, description: 'New description' }])
end
it 'does not detach media attachment' do
diff --git a/spec/services/verify_link_service_spec.rb b/spec/services/verify_link_service_spec.rb
index 0ce8c9a904..a4fd19751b 100644
--- a/spec/services/verify_link_service_spec.rb
+++ b/spec/services/verify_link_service_spec.rb
@@ -11,13 +11,14 @@ RSpec.describe VerifyLinkService do
before do
stub_request(:head, 'https://redirect.me/abc').to_return(status: 301, headers: { 'Location' => ActivityPub::TagManager.instance.url_for(account) })
+ stub_request(:head, 'http://unrelated-site.com').to_return(status: 301)
stub_request(:get, 'http://example.com').to_return(status: 200, body: html)
subject.call(field)
end
context 'when a link contains an back' do
let(:html) do
- <<-HTML
+ <<~HTML
Follow me on Mastodon
@@ -30,9 +31,9 @@ RSpec.describe VerifyLinkService do
end
end
- context 'when a link contains an back' do
+ context 'when a link contains an back' do
let(:html) do
- <<-HTML
+ <<~HTML
Follow me on Mastodon
@@ -47,7 +48,7 @@ RSpec.describe VerifyLinkService do
context 'when a link contains a back' do
let(:html) do
- <<-HTML
+ <<~HTML
@@ -62,7 +63,7 @@ RSpec.describe VerifyLinkService do
context 'when a link goes through a redirect back' do
let(:html) do
- <<-HTML
+ <<~HTML
@@ -113,7 +114,7 @@ RSpec.describe VerifyLinkService do
context 'when link has no `href` attribute' do
let(:html) do
- <<-HTML
+ <<~HTML
@@ -128,6 +129,21 @@ RSpec.describe VerifyLinkService do
expect(field.verified?).to be false
end
end
+
+ context 'when a link contains a link to an unexpected URL' do
+ let(:html) do
+ <<~HTML
+
+
+ Follow me on Unrelated Site
+
+ HTML
+ end
+
+ it 'does not mark the field as verified' do
+ expect(field.verified?).to be false
+ end
+ end
end
context 'when given a remote account' do
@@ -141,7 +157,7 @@ RSpec.describe VerifyLinkService do
context 'when a link contains an back' do
let(:html) do
- <<-HTML
+ <<~HTML
Follow me on Mastodon
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 1f9cc40f12..2a27544407 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -6,14 +6,10 @@ RSpec.configure do |config|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
+ config.disable_monkey_patching!
+
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
-
- config.around(:example, :without_verify_partial_doubles) do |example|
- mocks.verify_partial_doubles = false
- example.call
- mocks.verify_partial_doubles = true
- end
end
config.before :suite do
@@ -28,7 +24,7 @@ RSpec.configure do |config|
end
config.after :suite do
- FileUtils.rm_rf(Dir[Rails.root.join('spec', 'test_files')])
+ FileUtils.rm_rf(Rails.root.glob('spec/test_files'))
end
# Use the GitHub Annotations formatter for CI
@@ -38,14 +34,6 @@ RSpec.configure do |config|
end
end
-def body_as_json
- json_str_to_hash(response.body)
-end
-
-def json_str_to_hash(str)
- JSON.parse(str, symbolize_names: true)
-end
-
def serialized_record_json(record, serializer, adapter: nil)
options = { serializer: serializer }
options[:adapter] = adapter if adapter.present?
diff --git a/spec/support/examples/api.rb b/spec/support/examples/api.rb
index d531860abf..ddc61fcbe0 100644
--- a/spec/support/examples/api.rb
+++ b/spec/support/examples/api.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-shared_examples 'forbidden for wrong scope' do |wrong_scope|
+RSpec.shared_examples 'forbidden for wrong scope' do |wrong_scope|
let(:scopes) { wrong_scope }
it 'returns http forbidden' do
@@ -11,7 +11,7 @@ shared_examples 'forbidden for wrong scope' do |wrong_scope|
end
end
-shared_examples 'forbidden for wrong role' do |wrong_role|
+RSpec.shared_examples 'forbidden for wrong role' do |wrong_role|
let(:role) { UserRole.find_by(name: wrong_role) }
it 'returns http forbidden' do
diff --git a/spec/support/examples/cache.rb b/spec/support/examples/cache.rb
deleted file mode 100644
index 60e522f426..0000000000
--- a/spec/support/examples/cache.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-shared_examples 'cacheable response' do |expects_vary: false|
- it 'sets correct cache and vary headers and does not set cookies or session', :aggregate_failures do
- expect(response.cookies).to be_empty
- expect(response.headers['Set-Cookies']).to be_nil
-
- expect(session).to be_empty
-
- expect(response.headers['Vary']).to include(expects_vary) if expects_vary
-
- expect(response.headers['Cache-Control']).to include('public')
- end
-end
diff --git a/spec/support/examples/cli.rb b/spec/support/examples/cli.rb
index 091c842bd1..5f357fc915 100644
--- a/spec/support/examples/cli.rb
+++ b/spec/support/examples/cli.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-shared_examples 'CLI Command' do
+RSpec.shared_examples 'CLI Command' do
it 'configures Thor to exit on failure' do
expect(described_class.exit_on_failure?).to be true
end
diff --git a/spec/support/examples/lib/admin/checks.rb b/spec/support/examples/lib/admin/checks.rb
index b50faa77ba..e8c1336c5f 100644
--- a/spec/support/examples/lib/admin/checks.rb
+++ b/spec/support/examples/lib/admin/checks.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-shared_examples 'a check available to devops users' do
+RSpec.shared_examples 'a check available to devops users' do
describe 'skip?' do
context 'when user can view devops' do
before { allow(user).to receive(:can?).with(:view_devops).and_return(true) }
diff --git a/spec/support/examples/mailers.rb b/spec/support/examples/mailers.rb
index 213e873b4e..c1767dc419 100644
--- a/spec/support/examples/mailers.rb
+++ b/spec/support/examples/mailers.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-shared_examples 'localized subject' do |*args, **kwrest|
+RSpec.shared_examples 'localized subject' do |*args, **kwrest|
it 'renders subject localized for the locale of the receiver' do
locale = :de
receiver.update!(locale: locale)
@@ -12,3 +12,32 @@ shared_examples 'localized subject' do |*args, **kwrest|
expect(mail.subject).to eq I18n.t(*args, **kwrest.merge(locale: I18n.default_locale))
end
end
+
+RSpec::Matchers.define :have_thread_headers do
+ match(notify_expectation_failures: true) do |mail|
+ expect(mail)
+ .to be_present
+ .and(have_header('In-Reply-To', conversation_header_regex))
+ .and(have_header('References', conversation_header_regex))
+ end
+
+ def conversation_header_regex = //
+end
+
+RSpec::Matchers.define :have_standard_headers do |type|
+ chain :for do |user|
+ @user = user
+ end
+
+ match(notify_expectation_failures: true) do |mail|
+ expect(mail)
+ .to be_present
+ .and(have_header('To', "#{@user.account.username} <#{@user.email}>"))
+ .and(have_header('List-ID', "<#{type}.#{@user.account.username}.#{Rails.configuration.x.local_domain}>"))
+ .and(have_header('List-Unsubscribe', %r{}))
+ .and(have_header('List-Unsubscribe', /&type=#{type}/))
+ .and(have_header('List-Unsubscribe-Post', 'List-Unsubscribe=One-Click'))
+ .and(deliver_to("#{@user.account.username} <#{@user.email}>"))
+ .and(deliver_from(Rails.configuration.action_mailer.default_options[:from]))
+ end
+end
diff --git a/spec/support/examples/models/concerns/account_avatar.rb b/spec/support/examples/models/concerns/account_avatar.rb
index ab6020d834..232f51fa3c 100644
--- a/spec/support/examples/models/concerns/account_avatar.rb
+++ b/spec/support/examples/models/concerns/account_avatar.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-shared_examples 'AccountAvatar' do |fabricator|
+RSpec.shared_examples 'AccountAvatar' do |fabricator|
describe 'static avatars', :attachment_processing do
describe 'when GIF' do
it 'creates a png static style' do
diff --git a/spec/support/examples/models/concerns/account_header.rb b/spec/support/examples/models/concerns/account_header.rb
index 43bbdaacf4..af8d22d633 100644
--- a/spec/support/examples/models/concerns/account_header.rb
+++ b/spec/support/examples/models/concerns/account_header.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-shared_examples 'AccountHeader' do |fabricator|
+RSpec.shared_examples 'AccountHeader' do |fabricator|
describe 'base64-encoded files', :attachment_processing do
let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" }
let(:account) { Fabricate(fabricator, header: base64_attachment) }
diff --git a/spec/support/examples/models/concerns/reviewable.rb b/spec/support/examples/models/concerns/reviewable.rb
new file mode 100644
index 0000000000..144019d969
--- /dev/null
+++ b/spec/support/examples/models/concerns/reviewable.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'Reviewable' do
+ subject { described_class.new(reviewed_at: reviewed_at, requested_review_at: requested_review_at) }
+
+ let(:reviewed_at) { nil }
+ let(:requested_review_at) { nil }
+
+ describe 'Scopes' do
+ let!(:reviewed_record) { Fabricate factory_name, reviewed_at: 10.days.ago }
+ let!(:un_reviewed_record) { Fabricate factory_name, reviewed_at: nil }
+
+ describe '.reviewed' do
+ it 'returns reviewed records' do
+ expect(described_class.reviewed)
+ .to include(reviewed_record)
+ .and not_include(un_reviewed_record)
+ end
+ end
+
+ describe '.unreviewed' do
+ it 'returns non reviewed records' do
+ expect(described_class.unreviewed)
+ .to include(un_reviewed_record)
+ .and not_include(reviewed_record)
+ end
+ end
+
+ def factory_name
+ described_class.name.underscore.to_sym
+ end
+ end
+
+ describe '#requires_review?' do
+ it { is_expected.to be_requires_review }
+
+ context 'when reviewed_at is not null' do
+ let(:reviewed_at) { 5.days.ago }
+
+ it { is_expected.to_not be_requires_review }
+ end
+ end
+
+ describe '#reviewed?' do
+ it { is_expected.to_not be_reviewed }
+
+ context 'when reviewed_at is not null' do
+ let(:reviewed_at) { 5.days.ago }
+
+ it { is_expected.to be_reviewed }
+ end
+ end
+
+ describe '#requested_review?' do
+ it { is_expected.to_not be_requested_review }
+
+ context 'when requested_reviewed_at is not null' do
+ let(:requested_review_at) { 5.days.ago }
+
+ it { is_expected.to be_requested_review }
+ end
+ end
+
+ describe '#requires_review_notification?' do
+ it { is_expected.to be_requires_review_notification }
+
+ context 'when reviewed_at is not null' do
+ let(:reviewed_at) { 5.days.ago }
+
+ it { is_expected.to_not be_requires_review_notification }
+ end
+
+ context 'when requested_reviewed_at is not null' do
+ let(:requested_review_at) { 5.days.ago }
+
+ it { is_expected.to_not be_requires_review_notification }
+ end
+ end
+end
diff --git a/spec/support/matchers/api_pagination.rb b/spec/support/matchers/api_pagination.rb
index f7d552b242..1a4f53a84a 100644
--- a/spec/support/matchers/api_pagination.rb
+++ b/spec/support/matchers/api_pagination.rb
@@ -3,7 +3,7 @@
RSpec::Matchers.define :include_pagination_headers do |links|
match do |response|
links.map do |key, value|
- response.headers['Link'].find_link(['rel', key.to_s]).href == value
+ expect(response).to have_http_link_header(value).for(rel: key.to_s)
end.all?
end
diff --git a/spec/support/matchers/cacheable_response.rb b/spec/support/matchers/cacheable_response.rb
new file mode 100644
index 0000000000..e48eb28cc1
--- /dev/null
+++ b/spec/support/matchers/cacheable_response.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :have_cacheable_headers do
+ match do |response|
+ @response = response
+
+ @errors = [].tap do |errors|
+ errors << check_cookies
+ errors << check_cookie_headers
+ errors << check_session
+ errors << check_cache_control
+ errors << check_vary if @expected_vary.present?
+ end
+
+ @errors.compact.empty?
+ end
+
+ chain :with_vary do |string|
+ @expected_vary = string
+ end
+
+ failure_message do
+ <<~ERROR
+ Expected that the response would be cacheable but it was not:
+ - #{@errors.compact.join("\n - ")}
+ ERROR
+ end
+
+ def check_vary
+ "Response `Vary` header does not contain `#{@expected_vary}`" unless @response.headers['Vary'].include?(@expected_vary)
+ end
+
+ def check_cookies
+ 'Reponse cookies are present' unless @response.cookies.empty?
+ end
+
+ def check_cookie_headers
+ 'Response `Set-Cookies` headers are present' if @response.headers['Set-Cookies'].present?
+ end
+
+ def check_session
+ 'The session is not empty' unless session.empty?
+ end
+
+ def check_cache_control
+ 'The `Cache-Control` header does not contain `public`' unless @response.headers['Cache-Control'].include?('public')
+ end
+end
diff --git a/spec/support/matchers/http_link_header.rb b/spec/support/matchers/http_link_header.rb
new file mode 100644
index 0000000000..3e658071c9
--- /dev/null
+++ b/spec/support/matchers/http_link_header.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :have_http_link_header do |href|
+ match do |response|
+ @response = response
+
+ header_link&.href == href
+ end
+
+ match_when_negated do |response|
+ response.headers['Link'].blank?
+ end
+
+ chain :for do |attributes|
+ @attributes = attributes
+ end
+
+ failure_message do |response|
+ "Expected `#{response.headers['Link']}` to include `href` value of `#{href}` for `#{@attributes}` but it did not."
+ end
+
+ failure_message_when_negated do
+ "Expected response not to have a `Link` header but `#{response.headers['Link']}` is present."
+ end
+
+ def header_link
+ LinkHeader
+ .parse(@response.headers['Link'])
+ .find_link(*@attributes.stringify_keys)
+ end
+end
+
+RSpec::Matchers.define_negated_matcher :not_have_http_link_header, :have_http_link_header # Allow chaining
diff --git a/spec/support/matchers/json/match_json_schema.rb b/spec/support/matchers/json/match_json_schema.rb
index b4ced8addb..05dc1ee5a0 100644
--- a/spec/support/matchers/json/match_json_schema.rb
+++ b/spec/support/matchers/json/match_json_schema.rb
@@ -9,7 +9,9 @@ end
RSpec::Matchers.define :match_json_values do |values|
match do |string|
- expect(json_str_to_hash(string))
+ parsed_json = JSON.parse(string, symbolize_names: true)
+
+ expect(parsed_json)
.to include(values)
end
diff --git a/spec/support/matchers/private_cache_control.rb b/spec/support/matchers/private_cache_control.rb
new file mode 100644
index 0000000000..7fcf56be3e
--- /dev/null
+++ b/spec/support/matchers/private_cache_control.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :have_private_cache_control do
+ match do |page|
+ page.response_headers['Cache-Control'] == 'private, no-store'
+ end
+
+ failure_message do |page|
+ <<~ERROR
+ Expected page to have `Cache-Control` header with `private, no-store` but it has:
+ #{page.response_headers['Cache-Control']}
+ ERROR
+ end
+end
diff --git a/spec/support/shoulda_matchers.rb b/spec/support/shoulda_matchers.rb
new file mode 100644
index 0000000000..edcf9dd859
--- /dev/null
+++ b/spec/support/shoulda_matchers.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+Shoulda::Matchers.configure do |config|
+ config.integrate do |with|
+ with.test_framework :rspec
+ with.library :rails
+ end
+end
diff --git a/spec/support/streaming_server_manager.rb b/spec/support/streaming_server_manager.rb
index 376d6b8725..78cadcf6ad 100644
--- a/spec/support/streaming_server_manager.rb
+++ b/spec/support/streaming_server_manager.rb
@@ -17,7 +17,7 @@ class StreamingServerManager
@running_thread = Thread.new do
Open3.popen2e(
{
- 'REDIS_NAMESPACE' => ENV.fetch('REDIS_NAMESPACE'),
+ 'REDIS_NAMESPACE' => REDIS_CONFIGURATION.base[:namespace],
'DB_NAME' => "#{ENV.fetch('DB_NAME', 'mastodon')}_test#{ENV.fetch('TEST_ENV_NUMBER', '')}",
'RAILS_ENV' => ENV.fetch('RAILS_ENV', 'test'),
'NODE_ENV' => ENV.fetch('STREAMING_NODE_ENV', 'development'),
diff --git a/spec/support/system_helpers.rb b/spec/support/system_helpers.rb
new file mode 100644
index 0000000000..4cc1928701
--- /dev/null
+++ b/spec/support/system_helpers.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module SystemHelpers
+ def admin_user
+ Fabricate(:user, role: UserRole.find_by(name: 'Admin'))
+ end
+
+ def submit_button
+ I18n.t('generic.save_changes')
+ end
+
+ def success_message
+ I18n.t('generic.changes_saved_msg')
+ end
+
+ def form_label(key)
+ I18n.t key, scope: 'simple_form.labels'
+ end
+
+ def css_id(record)
+ "##{dom_id(record)}"
+ end
+end
diff --git a/spec/system/about_spec.rb b/spec/system/about_spec.rb
new file mode 100644
index 0000000000..f832802f91
--- /dev/null
+++ b/spec/system/about_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'About page' do
+ it 'visits the about page and renders the web app' do
+ visit about_path
+
+ expect(page)
+ .to have_css('noscript', text: /Mastodon/)
+ end
+end
diff --git a/spec/system/admin/accounts_spec.rb b/spec/system/admin/accounts_spec.rb
index 20813f6be4..c21e01e4f3 100644
--- a/spec/system/admin/accounts_spec.rb
+++ b/spec/system/admin/accounts_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin::Accounts' do
+RSpec.describe 'Admin::Accounts' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
diff --git a/spec/system/admin/announcements_spec.rb b/spec/system/admin/announcements_spec.rb
new file mode 100644
index 0000000000..87b7332639
--- /dev/null
+++ b/spec/system/admin/announcements_spec.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Admin::Announcements' do
+ include ActionView::RecordIdentifier
+
+ describe 'Viewing announcements' do
+ it 'can view a list of existing announcements' do
+ announcement = Fabricate :announcement, text: 'Test Announcement'
+ sign_in admin_user
+ visit admin_announcements_path
+
+ within css_id(announcement) do
+ expect(page)
+ .to have_content(announcement.text)
+ end
+ end
+ end
+
+ describe 'Creating announcements' do
+ it 'create a new announcement' do
+ sign_in admin_user
+ visit new_admin_announcement_path
+
+ fill_in text_label,
+ with: 'Announcement text'
+
+ expect { submit_form }
+ .to change(Announcement, :count).by(1)
+ expect(page)
+ .to have_content(I18n.t('admin.announcements.published_msg'))
+ end
+ end
+
+ describe 'Updating announcements' do
+ it 'updates an existing announcement' do
+ announcement = Fabricate :announcement, text: 'Test Announcement'
+ sign_in admin_user
+ visit admin_announcements_path
+
+ within css_id(announcement) do
+ click_on announcement.text
+ end
+
+ fill_in text_label,
+ with: 'Announcement text'
+ click_on submit_button
+
+ expect(page)
+ .to have_content(I18n.t('admin.announcements.updated_msg'))
+ end
+ end
+
+ describe 'Deleting announcements' do
+ it 'deletes an existing announcement' do
+ announcement = Fabricate :announcement, text: 'Test Announcement'
+ sign_in admin_user
+ visit admin_announcements_path
+
+ expect { delete_announcement(announcement) }
+ .to change(Announcement, :count).by(-1)
+
+ expect(page)
+ .to have_content(I18n.t('admin.announcements.destroyed_msg'))
+ end
+ end
+
+ describe 'Publishing announcements' do
+ it 'publishes an existing announcement' do
+ announcement = Fabricate :announcement, published: false, scheduled_at: 10.days.from_now
+ sign_in admin_user
+ visit admin_announcements_path
+
+ expect { publish_announcement(announcement) }
+ .to change { announcement.reload.published? }.to(true)
+
+ expect(page)
+ .to have_content(I18n.t('admin.announcements.published_msg'))
+ end
+
+ it 'unpublishes an existing announcement' do
+ announcement = Fabricate :announcement, published: true
+ sign_in admin_user
+ visit admin_announcements_path
+
+ expect { unpublish_announcement(announcement) }
+ .to change { announcement.reload.published? }.to(false)
+
+ expect(page)
+ .to have_content(I18n.t('admin.announcements.unpublished_msg'))
+ end
+ end
+
+ private
+
+ def publish_announcement(announcement)
+ within css_id(announcement) do
+ click_on I18n.t('admin.announcements.publish')
+ end
+ end
+
+ def unpublish_announcement(announcement)
+ within css_id(announcement) do
+ click_on I18n.t('admin.announcements.unpublish')
+ end
+ end
+
+ def delete_announcement(announcement)
+ within css_id(announcement) do
+ click_on I18n.t('generic.delete')
+ end
+ end
+
+ def submit_form
+ click_on I18n.t('admin.announcements.new.create')
+ end
+
+ def text_label
+ I18n.t('simple_form.labels.announcement.text')
+ end
+
+ def admin_user
+ Fabricate(:user, role: UserRole.find_by(name: 'Admin'))
+ end
+end
diff --git a/spec/system/admin/custom_emojis_spec.rb b/spec/system/admin/custom_emojis_spec.rb
index 8a8b6efcd1..e47f21f8a9 100644
--- a/spec/system/admin/custom_emojis_spec.rb
+++ b/spec/system/admin/custom_emojis_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin::CustomEmojis' do
+RSpec.describe 'Admin::CustomEmojis' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
diff --git a/spec/system/admin/domain_blocks_spec.rb b/spec/system/admin/domain_blocks_spec.rb
index 99aa7cf1a7..f00d65dfe0 100644
--- a/spec/system/admin/domain_blocks_spec.rb
+++ b/spec/system/admin/domain_blocks_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'blocking domains through the moderation interface' do
+RSpec.describe 'blocking domains through the moderation interface' do
before do
allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user
@@ -91,7 +91,7 @@ describe 'blocking domains through the moderation interface' do
visit edit_admin_domain_block_path(domain_block)
select I18n.t('admin.domain_blocks.new.severity.suspend'), from: 'domain_block_severity'
- click_on I18n.t('generic.save_changes')
+ click_on submit_button
# It doesn't immediately block but presents a confirmation screen
expect(page).to have_title(I18n.t('admin.domain_blocks.confirm_suspension.title', domain: 'example.com'))
diff --git a/spec/system/admin/email_domain_blocks_spec.rb b/spec/system/admin/email_domain_blocks_spec.rb
index 14959cbe74..a90bede827 100644
--- a/spec/system/admin/email_domain_blocks_spec.rb
+++ b/spec/system/admin/email_domain_blocks_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin::EmailDomainBlocks' do
+RSpec.describe 'Admin::EmailDomainBlocks' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
diff --git a/spec/system/admin/ip_blocks_spec.rb b/spec/system/admin/ip_blocks_spec.rb
index c9b16f6f78..9c03520277 100644
--- a/spec/system/admin/ip_blocks_spec.rb
+++ b/spec/system/admin/ip_blocks_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin::IpBlocks' do
+RSpec.describe 'Admin::IpBlocks' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
diff --git a/spec/system/admin/reset_spec.rb b/spec/system/admin/reset_spec.rb
new file mode 100644
index 0000000000..1e787ea110
--- /dev/null
+++ b/spec/system/admin/reset_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Admin::Reset' do
+ it 'Resets password for account user' do
+ account = Fabricate :account
+ sign_in admin_user
+ visit admin_account_path(account.id)
+
+ emails = capture_emails do
+ expect { submit_reset }
+ .to change(Admin::ActionLog.where(target: account.user), :count).by(1)
+ end
+
+ expect(emails.first)
+ .to be_present
+ .and(deliver_to(account.user.email))
+ .and(have_subject(password_change_subject))
+
+ expect(emails.last)
+ .to be_present
+ .and(deliver_to(account.user.email))
+ .and(have_subject(reset_instructions_subject))
+
+ expect(page)
+ .to have_content(account.username)
+ end
+
+ def admin_user
+ Fabricate(:user, role: UserRole.find_by(name: 'Admin'))
+ end
+
+ def submit_reset
+ click_on I18n.t('admin.accounts.reset_password')
+ end
+
+ def password_change_subject
+ I18n.t('devise.mailer.password_change.subject')
+ end
+
+ def reset_instructions_subject
+ I18n.t('devise.mailer.reset_password_instructions.subject')
+ end
+end
diff --git a/spec/system/admin/settings/about_spec.rb b/spec/system/admin/settings/about_spec.rb
new file mode 100644
index 0000000000..c7405a8d5a
--- /dev/null
+++ b/spec/system/admin/settings/about_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Admin::Settings::About' do
+ it 'Saves changes to about settings' do
+ sign_in admin_user
+ visit admin_settings_about_path
+
+ fill_in extended_description_field,
+ with: 'new site description'
+
+ click_on submit_button
+
+ expect(page)
+ .to have_content(success_message)
+ end
+
+ def extended_description_field
+ form_label 'form_admin_settings.site_extended_description'
+ end
+end
diff --git a/spec/system/admin/settings/appearance_spec.rb b/spec/system/admin/settings/appearance_spec.rb
new file mode 100644
index 0000000000..56af58c812
--- /dev/null
+++ b/spec/system/admin/settings/appearance_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Admin::Settings::Appearance' do
+ it 'Saves changes to appearance settings' do
+ sign_in admin_user
+ visit admin_settings_appearance_path
+
+ fill_in custom_css_field,
+ with: 'html { display: inline; }'
+
+ click_on submit_button
+
+ expect(page)
+ .to have_content(success_message)
+ end
+
+ def custom_css_field
+ form_label 'form_admin_settings.custom_css'
+ end
+end
diff --git a/spec/system/admin/settings/branding_spec.rb b/spec/system/admin/settings/branding_spec.rb
new file mode 100644
index 0000000000..5cd9319ce0
--- /dev/null
+++ b/spec/system/admin/settings/branding_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Admin::Settings::Branding' do
+ it 'Saves changes to branding settings' do
+ sign_in admin_user
+ visit admin_settings_branding_path
+
+ fill_in short_description_field,
+ with: 'new key value'
+
+ fill_in site_contact_email_field,
+ with: User.last.email
+
+ fill_in site_contact_username_field,
+ with: Account.last.username
+
+ expect { click_on submit_button }
+ .to change(Setting, :site_short_description).to('new key value')
+
+ expect(page)
+ .to have_content(success_message)
+ end
+
+ def short_description_field
+ form_label 'form_admin_settings.site_short_description'
+ end
+
+ def site_contact_email_field
+ form_label 'form_admin_settings.site_contact_email'
+ end
+
+ def site_contact_username_field
+ form_label 'form_admin_settings.site_contact_username'
+ end
+end
diff --git a/spec/system/admin/settings/content_retention_spec.rb b/spec/system/admin/settings/content_retention_spec.rb
new file mode 100644
index 0000000000..f788f8eea0
--- /dev/null
+++ b/spec/system/admin/settings/content_retention_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Admin::Settings::ContentRetention' do
+ it 'Saves changes to content retention settings' do
+ sign_in admin_user
+ visit admin_settings_content_retention_path
+
+ fill_in media_cache_retention_period_field,
+ with: '2'
+
+ click_on submit_button
+
+ expect(page)
+ .to have_content(success_message)
+ end
+
+ def media_cache_retention_period_field
+ form_label 'form_admin_settings.media_cache_retention_period'
+ end
+end
diff --git a/spec/system/admin/settings/discovery_spec.rb b/spec/system/admin/settings/discovery_spec.rb
new file mode 100644
index 0000000000..f000d18370
--- /dev/null
+++ b/spec/system/admin/settings/discovery_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Admin::Settings::Discovery' do
+ it 'Saves changes to discovery settings' do
+ sign_in admin_user
+ visit admin_settings_discovery_path
+
+ check trends_box
+
+ click_on submit_button
+
+ expect(page)
+ .to have_content(success_message)
+ end
+
+ def trends_box
+ form_label 'form_admin_settings.trends'
+ end
+end
diff --git a/spec/system/admin/settings/registrations_spec.rb b/spec/system/admin/settings/registrations_spec.rb
new file mode 100644
index 0000000000..d026b07c85
--- /dev/null
+++ b/spec/system/admin/settings/registrations_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Admin::Settings::Registrations' do
+ it 'Saves changes to registrations settings' do
+ sign_in admin_user
+ visit admin_settings_registrations_path
+
+ select open_mode_option,
+ from: registrations_mode_field
+
+ click_on submit_button
+
+ expect(page)
+ .to have_content(success_message)
+ end
+
+ def open_mode_option
+ I18n.t('admin.settings.registrations_mode.modes.open')
+ end
+
+ def registrations_mode_field
+ form_label 'form_admin_settings.registrations_mode'
+ end
+end
diff --git a/spec/system/admin/software_updates_spec.rb b/spec/system/admin/software_updates_spec.rb
index 4a635d1a79..77e9f16684 100644
--- a/spec/system/admin/software_updates_spec.rb
+++ b/spec/system/admin/software_updates_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'finding software updates through the admin interface' do
+RSpec.describe 'finding software updates through the admin interface' do
before do
Fabricate(:software_update, version: '99.99.99', type: 'major', urgent: true, release_notes: 'https://github.com/mastodon/mastodon/releases/v99')
diff --git a/spec/system/admin/statuses_spec.rb b/spec/system/admin/statuses_spec.rb
index 531d0de953..bb76a2963d 100644
--- a/spec/system/admin/statuses_spec.rb
+++ b/spec/system/admin/statuses_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin::Statuses' do
+RSpec.describe 'Admin::Statuses' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
diff --git a/spec/system/admin/trends/links/preview_card_providers_spec.rb b/spec/system/admin/trends/links/preview_card_providers_spec.rb
index dca89117b1..16343a6891 100644
--- a/spec/system/admin/trends/links/preview_card_providers_spec.rb
+++ b/spec/system/admin/trends/links/preview_card_providers_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin::Trends::Links::PreviewCardProviders' do
+RSpec.describe 'Admin::Trends::Links::PreviewCardProviders' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
diff --git a/spec/system/admin/trends/links_spec.rb b/spec/system/admin/trends/links_spec.rb
index 99638bc069..7a51c337c9 100644
--- a/spec/system/admin/trends/links_spec.rb
+++ b/spec/system/admin/trends/links_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin::Trends::Links' do
+RSpec.describe 'Admin::Trends::Links' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
diff --git a/spec/system/admin/trends/statuses_spec.rb b/spec/system/admin/trends/statuses_spec.rb
index 779a15d38f..13fc966dfd 100644
--- a/spec/system/admin/trends/statuses_spec.rb
+++ b/spec/system/admin/trends/statuses_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin::Trends::Statuses' do
+RSpec.describe 'Admin::Trends::Statuses' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
diff --git a/spec/system/admin/trends/tags_spec.rb b/spec/system/admin/trends/tags_spec.rb
index 52e49c3a5d..d914badbd4 100644
--- a/spec/system/admin/trends/tags_spec.rb
+++ b/spec/system/admin/trends/tags_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Admin::Trends::Tags' do
+RSpec.describe 'Admin::Trends::Tags' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
diff --git a/spec/system/captcha_spec.rb b/spec/system/captcha_spec.rb
index 06c823adf2..4c0ce02d1b 100644
--- a/spec/system/captcha_spec.rb
+++ b/spec/system/captcha_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'email confirmation flow when captcha is enabled' do
+RSpec.describe 'email confirmation flow when captcha is enabled' do
let(:user) { Fabricate(:user, confirmed_at: nil, confirmation_token: 'foobar', created_by_application: client_app) }
let(:client_app) { nil }
diff --git a/spec/system/filters_spec.rb b/spec/system/filters_spec.rb
index a0cb965a61..64de384c00 100644
--- a/spec/system/filters_spec.rb
+++ b/spec/system/filters_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Filters' do
+RSpec.describe 'Filters' do
let(:user) { Fabricate(:user) }
let(:filter_title) { 'Filter of fun and games' }
@@ -29,7 +29,7 @@ describe 'Filters' do
click_on filter_title
fill_in filter_title_field, with: new_title
- click_on I18n.t('generic.save_changes')
+ click_on submit_button
expect(page).to have_content(new_title)
end
diff --git a/spec/system/home_spec.rb b/spec/system/home_spec.rb
new file mode 100644
index 0000000000..c1ce4e1726
--- /dev/null
+++ b/spec/system/home_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Home page' do
+ context 'when signed in' do
+ before { sign_in Fabricate(:user) }
+
+ it 'visits the homepage and renders the web app' do
+ visit root_path
+
+ expect(page)
+ .to have_css('noscript', text: /Mastodon/)
+ end
+ end
+
+ context 'when not signed in' do
+ it 'visits the homepage and renders the web app' do
+ visit root_path
+
+ expect(page)
+ .to have_css('noscript', text: /Mastodon/)
+ end
+ end
+end
diff --git a/spec/system/invites_spec.rb b/spec/system/invites_spec.rb
new file mode 100644
index 0000000000..c57de871cc
--- /dev/null
+++ b/spec/system/invites_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Invites' do
+ include ActionView::RecordIdentifier
+
+ let(:user) { Fabricate :user }
+
+ before do
+ host! 'localhost:3000' # TODO: Move into before for all system specs?
+ sign_in user
+ end
+
+ describe 'Viewing invites' do
+ it 'Lists existing user invites' do
+ invite = Fabricate :invite, user: user
+
+ visit invites_path
+
+ within css_id(invite) do
+ expect(page)
+ .to have_content(invite.uses)
+ .and have_private_cache_control
+ expect(copyable_field.value)
+ .to eq(public_invite_url(invite_code: invite.code))
+ end
+ end
+ end
+
+ describe 'Creating a new invite' do
+ it 'Saves the invite for the user' do
+ visit invites_path
+
+ fill_invite_form
+
+ expect { submit_form }
+ .to change(user.invites, :count).by(1)
+ end
+ end
+
+ describe 'Deleting an existing invite' do
+ it 'Expires the invite' do
+ invite = Fabricate :invite, user: user
+
+ visit invites_path
+
+ expect { delete_invite(invite) }
+ .to change { invite.reload.expired? }.to(true)
+
+ within css_id(invite) do
+ expect(page).to have_content I18n.t('invites.expired')
+ end
+ end
+ end
+
+ private
+
+ def copyable_field
+ within '.input-copy' do
+ find(:field, type: :text, readonly: true)
+ end
+ end
+
+ def submit_form
+ click_on I18n.t('invites.generate')
+ end
+
+ def delete_invite(invite)
+ within css_id(invite) do
+ click_on I18n.t('invites.delete')
+ end
+ end
+
+ def fill_invite_form
+ select I18n.t('invites.max_uses', count: 100),
+ from: I18n.t('simple_form.labels.defaults.max_uses')
+ select I18n.t("invites.expires_in.#{30.minutes.to_i}"),
+ from: I18n.t('simple_form.labels.defaults.expires_in')
+ check I18n.t('simple_form.labels.defaults.autofollow')
+ end
+end
diff --git a/spec/system/log_in_spec.rb b/spec/system/log_in_spec.rb
index 8a73c42d2e..f8765e8e1c 100644
--- a/spec/system/log_in_spec.rb
+++ b/spec/system/log_in_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Log in' do
+RSpec.describe 'Log in' do
include ProfileStories
subject { page }
diff --git a/spec/system/log_out_spec.rb b/spec/system/log_out_spec.rb
index f50f7c2d18..2e52254ca0 100644
--- a/spec/system/log_out_spec.rb
+++ b/spec/system/log_out_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Log out' do
+RSpec.describe 'Log out' do
include ProfileStories
before do
diff --git a/spec/system/media_spec.rb b/spec/system/media_spec.rb
new file mode 100644
index 0000000000..d014c7e88e
--- /dev/null
+++ b/spec/system/media_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Media' do
+ describe 'Player page' do
+ context 'when signed in' do
+ before { sign_in Fabricate(:user) }
+
+ it 'visits the media player page and renders the media' do
+ status = Fabricate :status
+ media = Fabricate :media_attachment, type: :video
+ status.media_attachments << media
+
+ visit medium_player_path(media)
+
+ expect(page)
+ .to have_css('body', class: 'player')
+ .and have_css('div[data-component="Video"]')
+ end
+ end
+ end
+end
diff --git a/spec/system/new_statuses_spec.rb b/spec/system/new_statuses_spec.rb
index 2f2fcf2248..317508a0bb 100644
--- a/spec/system/new_statuses_spec.rb
+++ b/spec/system/new_statuses_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'NewStatuses', :inline_jobs, :js, :streaming do
+RSpec.describe 'NewStatuses', :inline_jobs, :js, :streaming do
include ProfileStories
subject { page }
diff --git a/spec/system/oauth_spec.rb b/spec/system/oauth_spec.rb
index 5d06f6111c..0f96a59675 100644
--- a/spec/system/oauth_spec.rb
+++ b/spec/system/oauth_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Using OAuth from an external app' do
+RSpec.describe 'Using OAuth from an external app' do
include ProfileStories
subject { visit "/oauth/authorize?#{params.to_query}" }
diff --git a/spec/system/ocr_spec.rb b/spec/system/ocr_spec.rb
index 17d18af158..fc816b6dba 100644
--- a/spec/system/ocr_spec.rb
+++ b/spec/system/ocr_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'OCR', :attachment_processing, :inline_jobs, :js, :streaming do
+RSpec.describe 'OCR', :attachment_processing, :inline_jobs, :js, :streaming do
include ProfileStories
let(:email) { 'test@example.com' }
diff --git a/spec/system/privacy_spec.rb b/spec/system/privacy_spec.rb
new file mode 100644
index 0000000000..631440ebb2
--- /dev/null
+++ b/spec/system/privacy_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Privacy policy page' do
+ it 'visits the privacy policy page and renders the web app' do
+ visit privacy_policy_path
+
+ expect(page)
+ .to have_css('noscript', text: /Mastodon/)
+ end
+end
diff --git a/spec/system/profile_spec.rb b/spec/system/profile_spec.rb
index 2517e823b5..7e3cbfd334 100644
--- a/spec/system/profile_spec.rb
+++ b/spec/system/profile_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Profile' do
+RSpec.describe 'Profile' do
include ProfileStories
subject { page }
diff --git a/spec/system/redirections_spec.rb b/spec/system/redirections_spec.rb
index f73ab58470..eba034326b 100644
--- a/spec/system/redirections_spec.rb
+++ b/spec/system/redirections_spec.rb
@@ -2,31 +2,35 @@
require 'rails_helper'
-describe 'redirection confirmations' do
+RSpec.describe 'redirection confirmations' do
let(:account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/users/foo', url: 'https://example.com/@foo') }
let(:status) { Fabricate(:status, account: account, uri: 'https://example.com/users/foo/statuses/1', url: 'https://example.com/@foo/1') }
- context 'when a logged out user visits a local page for a remote account' do
- it 'shows a confirmation page' do
- visit "/@#{account.pretty_acct}"
+ context 'when logged out' do
+ describe 'a local page for a remote account' do
+ it 'shows a confirmation page with relevant content' do
+ visit "/@#{account.pretty_acct}"
- # It explains about the redirect
- expect(page).to have_content(I18n.t('redirects.title', instance: 'cb6e6126.ngrok.io'))
+ expect(page)
+ .to have_content(redirect_title) # Redirect explanation
+ .and have_link(account.url, href: account.url) # Appropriate account link
+ .and have_css('body', class: 'app-body')
+ end
+ end
- # It features an appropriate link
- expect(page).to have_link(account.url, href: account.url)
+ describe 'a local page for a remote status' do
+ it 'shows a confirmation page with relevant content' do
+ visit "/@#{account.pretty_acct}/#{status.id}"
+
+ expect(page)
+ .to have_content(redirect_title) # Redirect explanation
+ .and have_link(status.url, href: status.url) # Appropriate status link
+ .and have_css('body', class: 'app-body')
+ end
end
end
- context 'when a logged out user visits a local page for a remote status' do
- it 'shows a confirmation page' do
- visit "/@#{account.pretty_acct}/#{status.id}"
-
- # It explains about the redirect
- expect(page).to have_content(I18n.t('redirects.title', instance: 'cb6e6126.ngrok.io'))
-
- # It features an appropriate link
- expect(page).to have_link(status.url, href: status.url)
- end
+ def redirect_title
+ I18n.t('redirects.title', instance: 'cb6e6126.ngrok.io')
end
end
diff --git a/spec/system/report_interface_spec.rb b/spec/system/report_interface_spec.rb
index e6cc3b1b68..257a1cd6fd 100644
--- a/spec/system/report_interface_spec.rb
+++ b/spec/system/report_interface_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'report interface', :attachment_processing, :js, :streaming do
+RSpec.describe 'report interface', :attachment_processing, :js, :streaming do
include ProfileStories
let(:email) { 'admin@example.com' }
diff --git a/spec/system/settings/applications_spec.rb b/spec/system/settings/applications_spec.rb
new file mode 100644
index 0000000000..ee43da3d5d
--- /dev/null
+++ b/spec/system/settings/applications_spec.rb
@@ -0,0 +1,144 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings applications page' do
+ let!(:application) { Fabricate :application, owner: user }
+ let(:user) { Fabricate :user }
+
+ before { sign_in user }
+
+ describe 'Viewing the list of applications' do
+ it 'sees the applications' do
+ visit settings_applications_path
+
+ expect(page)
+ .to have_content(application.name)
+ .and have_private_cache_control
+ end
+ end
+
+ describe 'Viewing a single application' do
+ it 'shows a page with application details' do
+ visit settings_application_path(application)
+
+ expect(page)
+ .to have_content(application.name)
+ end
+ end
+
+ describe 'Creating a new application' do
+ it 'accepts form input to make an application' do
+ visit new_settings_application_path
+
+ fill_in_form
+
+ expect { submit_form }
+ .to change(Doorkeeper::Application, :count).by(1)
+ expect(page)
+ .to have_content(I18n.t('doorkeeper.applications.index.title'))
+ .and have_content('My new app')
+ end
+
+ it 'does not save with invalid form values' do
+ visit new_settings_application_path
+
+ expect { submit_form }
+ .to not_change(Doorkeeper::Application, :count)
+ expect(page)
+ .to have_content("can't be blank")
+ end
+
+ def fill_in_form
+ fill_in form_app_name_label,
+ with: 'My new app'
+ fill_in I18n.t('activerecord.attributes.doorkeeper/application.website'),
+ with: 'http://google.com'
+ fill_in I18n.t('activerecord.attributes.doorkeeper/application.redirect_uri'),
+ with: 'urn:ietf:wg:oauth:2.0:oob'
+
+ check 'read', id: :doorkeeper_application_scopes_read
+ check 'write', id: :doorkeeper_application_scopes_write
+ check 'follow', id: :doorkeeper_application_scopes_follow
+ end
+
+ def submit_form
+ click_on I18n.t('doorkeeper.applications.buttons.submit')
+ end
+ end
+
+ describe 'Updating an application' do
+ it 'successfully updates with valid values' do
+ visit settings_application_path(application)
+
+ fill_in form_app_name_label,
+ with: 'My new app name with a new value'
+ submit_form
+
+ expect(page)
+ .to have_content('My new app name with a new value')
+ end
+
+ it 'does not update with wrong values' do
+ visit settings_application_path(application)
+
+ fill_in form_app_name_label,
+ with: ''
+ submit_form
+
+ expect(page)
+ .to have_content("can't be blank")
+ end
+
+ def submit_form
+ click_on I18n.t('generic.save_changes')
+ end
+ end
+
+ describe 'Destroying an application' do
+ let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) }
+ let!(:access_token) { Fabricate(:accessible_access_token, application: application) }
+
+ before { stub_redis_pipeline }
+
+ it 'destroys the record and tells the broader universe about that' do
+ visit settings_applications_path
+
+ expect { destroy_application }
+ .to change(Doorkeeper::Application, :count).by(-1)
+ expect(page)
+ .to have_no_content(application.name)
+ expect(redis_pipeline_stub)
+ .to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}')
+ end
+
+ def destroy_application
+ click_on I18n.t('doorkeeper.applications.index.delete')
+ end
+
+ def stub_redis_pipeline
+ allow(redis)
+ .to receive(:pipelined)
+ .and_yield(redis_pipeline_stub)
+ end
+ end
+
+ describe 'Regenerating an app token' do
+ it 'updates the app token' do
+ visit settings_application_path(application)
+
+ expect { regenerate_token }
+ .to(change { user.token_for_app(application) })
+ expect(page)
+ .to have_content(I18n.t('applications.token_regenerated'))
+ end
+
+ def regenerate_token
+ click_on I18n.t('applications.regenerate_token')
+ end
+ end
+
+ def form_app_name_label
+ I18n.t('activerecord.attributes.doorkeeper/application.name')
+ end
+end
diff --git a/spec/system/settings/exports_spec.rb b/spec/system/settings/exports_spec.rb
new file mode 100644
index 0000000000..2cc2961a0b
--- /dev/null
+++ b/spec/system/settings/exports_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Export page' do
+ let(:user) { Fabricate :user }
+
+ before { sign_in user }
+
+ describe 'Viewing the export page' do
+ context 'when signed in' do
+ it 'shows the export page', :aggregate_failures do
+ visit settings_export_path
+
+ expect(page)
+ .to have_content(takeout_summary)
+ .and have_private_cache_control
+ end
+ end
+ end
+
+ describe 'Creating a new archive' do
+ it 'queues a worker and redirects' do
+ visit settings_export_path
+
+ expect { request_archive }
+ .to change(BackupWorker.jobs, :size).by(1)
+ expect(page)
+ .to have_content(takeout_summary)
+ end
+
+ def request_archive
+ click_on I18n.t('exports.archive_takeout.request')
+ end
+ end
+
+ def takeout_summary
+ I18n.t('settings.export')
+ end
+end
diff --git a/spec/system/severed_relationships_spec.rb b/spec/system/severed_relationships_spec.rb
index b933398a08..4a7bf3e280 100644
--- a/spec/system/severed_relationships_spec.rb
+++ b/spec/system/severed_relationships_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'Severed relationships page' do
+RSpec.describe 'Severed relationships page' do
include ProfileStories
describe 'GET severed_relationships#index' do
diff --git a/spec/system/share_entrypoint_spec.rb b/spec/system/share_entrypoint_spec.rb
index 5fdbeacefa..7ccfee599a 100644
--- a/spec/system/share_entrypoint_spec.rb
+++ b/spec/system/share_entrypoint_spec.rb
@@ -2,32 +2,45 @@
require 'rails_helper'
-describe 'ShareEntrypoint', :js, :streaming do
+RSpec.describe 'Share page', :js, :streaming do
include ProfileStories
- subject { page }
-
let(:email) { 'test@example.com' }
let(:password) { 'password' }
let(:confirmed_at) { Time.zone.now }
let(:finished_onboarding) { true }
- before do
- as_a_logged_in_user
+ before { as_a_logged_in_user }
+
+ it 'allows posting a new status' do
visit share_path
+
+ expect(page)
+ .to have_css('.modal-layout__mastodon')
+ .and have_css('div#mastodon-compose')
+ .and have_css('.compose-form__submit')
+
+ fill_in_form
+
+ expect(page)
+ .to have_css('.notification-bar-message', text: translations['compose.published.body'])
end
- it 'can be used to post a new status' do
- expect(subject).to have_css('div#mastodon-compose')
- expect(subject).to have_css('.compose-form__submit')
-
- status_text = 'This is a new status!'
-
+ def fill_in_form
within('.compose-form') do
- fill_in "What's on your mind?", with: status_text
- click_on 'Post'
+ fill_in translations['compose_form.placeholder'],
+ with: 'This is a new status!'
+ click_on translations['compose_form.publish']
end
+ end
- expect(subject).to have_css('.notification-bar-message', text: 'Post published.')
+ def translations
+ # TODO: Extract to system spec helper for re-use?
+ JSON.parse(
+ Rails
+ .root
+ .join('app', 'javascript', 'mastodon', 'locales', 'en.json')
+ .read
+ )
end
end
diff --git a/spec/system/tags_spec.rb b/spec/system/tags_spec.rb
new file mode 100644
index 0000000000..f39c6bf0d8
--- /dev/null
+++ b/spec/system/tags_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Tags' do
+ describe 'Viewing a tag' do
+ let(:tag) { Fabricate(:tag, name: 'test') }
+
+ before { sign_in Fabricate(:user) }
+
+ it 'visits the tag page and renders the web app' do
+ visit tag_path(tag)
+
+ expect(page)
+ .to have_css('noscript', text: /Mastodon/)
+ .and have_private_cache_control
+ end
+ end
+end
diff --git a/spec/system/unlogged_spec.rb b/spec/system/unlogged_spec.rb
index 417ccdaeb6..26d1bd4542 100644
--- a/spec/system/unlogged_spec.rb
+++ b/spec/system/unlogged_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'UnloggedBrowsing', :js, :streaming do
+RSpec.describe 'UnloggedBrowsing', :js, :streaming do
subject { page }
before do
diff --git a/spec/validators/domain_validator_spec.rb b/spec/validators/domain_validator_spec.rb
new file mode 100644
index 0000000000..0b4cb0d3f0
--- /dev/null
+++ b/spec/validators/domain_validator_spec.rb
@@ -0,0 +1,125 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe DomainValidator do
+ let(:record) { record_class.new }
+
+ context 'with no options' do
+ let(:record_class) do
+ Class.new do
+ include ActiveModel::Validations
+
+ attr_accessor :domain
+
+ validates :domain, domain: true
+ end
+ end
+
+ describe '#validate_each' do
+ context 'with a nil value' do
+ it 'does not add errors' do
+ record.domain = nil
+
+ expect(record).to be_valid
+ expect(record.errors).to be_empty
+ end
+ end
+
+ context 'with a valid domain' do
+ it 'does not add errors' do
+ record.domain = 'example.com'
+
+ expect(record).to be_valid
+ expect(record.errors).to be_empty
+ end
+ end
+
+ context 'with a domain that is too long' do
+ it 'adds an error' do
+ record.domain = "#{'a' * 300}.com"
+
+ expect(record).to_not be_valid
+ expect(record.errors.where(:domain)).to_not be_empty
+ end
+ end
+
+ context 'with a domain with an empty segment' do
+ it 'adds an error' do
+ record.domain = '.example.com'
+
+ expect(record).to_not be_valid
+ expect(record.errors.where(:domain)).to_not be_empty
+ end
+ end
+
+ context 'with a domain with an invalid character' do
+ it 'adds an error' do
+ record.domain = '*.example.com'
+
+ expect(record).to_not be_valid
+ expect(record.errors.where(:domain)).to_not be_empty
+ end
+ end
+
+ context 'with a domain that would fail parsing' do
+ it 'adds an error' do
+ record.domain = '/'
+
+ expect(record).to_not be_valid
+ expect(record.errors.where(:domain)).to_not be_empty
+ end
+ end
+ end
+ end
+
+ context 'with acct option' do
+ let(:record_class) do
+ Class.new do
+ include ActiveModel::Validations
+
+ attr_accessor :acct
+
+ validates :acct, domain: { acct: true }
+ end
+ end
+
+ describe '#validate_each' do
+ context 'with a nil value' do
+ it 'does not add errors' do
+ record.acct = nil
+
+ expect(record).to be_valid
+ expect(record.errors).to be_empty
+ end
+ end
+
+ context 'with no domain' do
+ it 'does not add errors' do
+ record.acct = 'hoge_123'
+
+ expect(record).to be_valid
+ expect(record.errors).to be_empty
+ end
+ end
+
+ context 'with a valid domain' do
+ it 'does not add errors' do
+ record.acct = 'hoge_123@example.com'
+
+ expect(record).to be_valid
+ expect(record.errors).to be_empty
+ end
+ end
+
+ context 'with an invalid domain' do
+ it 'adds an error' do
+ record.acct = 'hoge_123@.example.com'
+
+ expect(record).to_not be_valid
+ expect(record.errors.where(:acct)).to_not be_empty
+ end
+ end
+ end
+ end
+end
diff --git a/spec/validators/email_mx_validator_spec.rb b/spec/validators/email_mx_validator_spec.rb
index 23a5f768ef..7109c9f4e2 100644
--- a/spec/validators/email_mx_validator_spec.rb
+++ b/spec/validators/email_mx_validator_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe EmailMxValidator do
+RSpec.describe EmailMxValidator do
describe '#validate' do
let(:user) { instance_double(User, email: 'foo@example.com', sign_up_ip: '1.2.3.4', errors: instance_double(ActiveModel::Errors, add: nil)) }
let(:resolv_dns_double) { instance_double(Resolv::DNS) }
diff --git a/spec/validators/existing_username_validator_spec.rb b/spec/validators/existing_username_validator_spec.rb
index 4f1dd55a17..25ecb1fbcd 100644
--- a/spec/validators/existing_username_validator_spec.rb
+++ b/spec/validators/existing_username_validator_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ExistingUsernameValidator do
+RSpec.describe ExistingUsernameValidator do
let(:record_class) do
Class.new do
include ActiveModel::Validations
diff --git a/spec/validators/language_validator_spec.rb b/spec/validators/language_validator_spec.rb
index cb693dcd81..19e55f3467 100644
--- a/spec/validators/language_validator_spec.rb
+++ b/spec/validators/language_validator_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe LanguageValidator do
+RSpec.describe LanguageValidator do
let(:record_class) do
Class.new do
include ActiveModel::Validations
diff --git a/spec/validators/lines_validator_spec.rb b/spec/validators/lines_validator_spec.rb
new file mode 100644
index 0000000000..a80dbbaf3e
--- /dev/null
+++ b/spec/validators/lines_validator_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe LinesValidator do
+ let(:record_class) do
+ Class.new do
+ include ActiveModel::Validations
+
+ attr_accessor :text
+
+ validates :text, lines: { maximum: 5 }
+ end
+ end
+
+ let(:record) { record_class.new }
+
+ describe '#validate_each' do
+ context 'with a nil value' do
+ it 'does not add errors' do
+ record.text = nil
+
+ expect(record).to be_valid
+ expect(record.errors).to be_empty
+ end
+ end
+
+ context 'with lines below the limit' do
+ it 'does not add errors' do
+ record.text = "hoge\n" * 5
+
+ expect(record).to be_valid
+ expect(record.errors).to be_empty
+ end
+ end
+
+ context 'with more lines than limit' do
+ it 'adds an error' do
+ record.text = "hoge\n" * 6
+
+ expect(record).to_not be_valid
+ expect(record.errors.where(:text)).to_not be_empty
+ end
+ end
+ end
+end
diff --git a/spec/validators/note_length_validator_spec.rb b/spec/validators/note_length_validator_spec.rb
index 3bca93a283..3fdb4ae8b9 100644
--- a/spec/validators/note_length_validator_spec.rb
+++ b/spec/validators/note_length_validator_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe NoteLengthValidator do
+RSpec.describe NoteLengthValidator do
subject { described_class.new(attributes: { note: true }, maximum: 500) }
describe '#validate' do
diff --git a/spec/validators/reaction_validator_spec.rb b/spec/validators/reaction_validator_spec.rb
index f99c1cb5f9..c4d4a51779 100644
--- a/spec/validators/reaction_validator_spec.rb
+++ b/spec/validators/reaction_validator_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ReactionValidator do
+RSpec.describe ReactionValidator do
let(:announcement) { Fabricate(:announcement) }
describe '#validate' do
diff --git a/spec/validators/status_length_validator_spec.rb b/spec/validators/status_length_validator_spec.rb
index 249b90f490..ecbfd4ba37 100644
--- a/spec/validators/status_length_validator_spec.rb
+++ b/spec/validators/status_length_validator_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe StatusLengthValidator do
+RSpec.describe StatusLengthValidator do
describe '#validate' do
before { stub_const("#{described_class}::MAX_CHARS", 500) } # Example values below are relative to this baseline
diff --git a/spec/validators/unique_username_validator_spec.rb b/spec/validators/unique_username_validator_spec.rb
index 0d172c8408..037ddadb9f 100644
--- a/spec/validators/unique_username_validator_spec.rb
+++ b/spec/validators/unique_username_validator_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe UniqueUsernameValidator do
+RSpec.describe UniqueUsernameValidator do
describe '#validate' do
context 'when local account' do
it 'does not add errors if username is nil' do
diff --git a/spec/validators/unreserved_username_validator_spec.rb b/spec/validators/unreserved_username_validator_spec.rb
index 0eb5f83683..ad1092109d 100644
--- a/spec/validators/unreserved_username_validator_spec.rb
+++ b/spec/validators/unreserved_username_validator_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe UnreservedUsernameValidator do
+RSpec.describe UnreservedUsernameValidator do
let(:record_class) do
Class.new do
include ActiveModel::Validations
diff --git a/spec/validators/url_validator_spec.rb b/spec/validators/url_validator_spec.rb
index 4f32b7b399..2297dddaa0 100644
--- a/spec/validators/url_validator_spec.rb
+++ b/spec/validators/url_validator_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe URLValidator do
+RSpec.describe URLValidator do
let(:record_class) do
Class.new do
include ActiveModel::Validations
diff --git a/spec/views/admin/trends/links/_preview_card.html.haml_spec.rb b/spec/views/admin/trends/links/_preview_card.html.haml_spec.rb
index 82a1dee6d7..47a8564eff 100644
--- a/spec/views/admin/trends/links/_preview_card.html.haml_spec.rb
+++ b/spec/views/admin/trends/links/_preview_card.html.haml_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe 'admin/trends/links/_preview_card.html.haml' do
+RSpec.describe 'admin/trends/links/_preview_card.html.haml' do
it 'correctly escapes user supplied url values' do
form = instance_double(ActionView::Helpers::FormHelper, check_box: nil)
trend = PreviewCardTrend.new(allowed: false)
diff --git a/spec/views/statuses/show.html.haml_spec.rb b/spec/views/statuses/show.html.haml_spec.rb
index 57032a068f..9e3f4082b5 100644
--- a/spec/views/statuses/show.html.haml_spec.rb
+++ b/spec/views/statuses/show.html.haml_spec.rb
@@ -2,14 +2,13 @@
require 'rails_helper'
-describe 'statuses/show.html.haml', :without_verify_partial_doubles do
+RSpec.describe 'statuses/show.html.haml' do
let(:alice) { Fabricate(:account, username: 'alice', display_name: 'Alice') }
let(:status) { Fabricate(:status, account: alice, text: 'Hello World') }
before do
- allow(view).to receive_messages(api_oembed_url: '', site_title: 'example site', site_hostname: 'example.com', full_asset_url: '//asset.host/image.svg', current_flavour: 'glitch', current_account: nil, single_user_mode?: false)
- allow(view).to receive(:local_time)
- allow(view).to receive(:local_time_ago)
+ view.extend view_helpers
+
assign(:instance_presenter, InstancePresenter.new)
Fabricate(:media_attachment, account: alice, status: status, type: :video)
@@ -40,4 +39,19 @@ describe 'statuses/show.html.haml', :without_verify_partial_doubles do
def header_tags
view.content_for(:header_tags)
end
+
+ def view_helpers
+ Module.new do
+ def api_oembed_url(_) = ''
+ def show_landing_strip? = true
+ def site_title = 'example site'
+ def site_hostname = 'example.com'
+ def full_asset_url(_) = '//asset.host/image.svg'
+ def current_account = nil
+ def current_flavour = 'glitch'
+ def single_user_mode? = false
+ def local_time = nil
+ def local_time_ago = nil
+ end
+ end
end
diff --git a/spec/workers/account_refresh_worker_spec.rb b/spec/workers/account_refresh_worker_spec.rb
index 361d69aa0a..3e88e8db28 100644
--- a/spec/workers/account_refresh_worker_spec.rb
+++ b/spec/workers/account_refresh_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe AccountRefreshWorker do
+RSpec.describe AccountRefreshWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(ResolveAccountService, call: true) }
diff --git a/spec/workers/activitypub/delivery_worker_spec.rb b/spec/workers/activitypub/delivery_worker_spec.rb
index efce610ae4..3dfbef31a4 100644
--- a/spec/workers/activitypub/delivery_worker_spec.rb
+++ b/spec/workers/activitypub/delivery_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::DeliveryWorker do
+RSpec.describe ActivityPub::DeliveryWorker do
include RoutingHelper
subject { described_class.new }
diff --git a/spec/workers/activitypub/distribute_poll_update_worker_spec.rb b/spec/workers/activitypub/distribute_poll_update_worker_spec.rb
index 4427cfdf95..9ff4731f96 100644
--- a/spec/workers/activitypub/distribute_poll_update_worker_spec.rb
+++ b/spec/workers/activitypub/distribute_poll_update_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::DistributePollUpdateWorker do
+RSpec.describe ActivityPub::DistributePollUpdateWorker do
subject { described_class.new }
let(:account) { Fabricate(:account) }
diff --git a/spec/workers/activitypub/distribution_worker_spec.rb b/spec/workers/activitypub/distribution_worker_spec.rb
index 0eb6227859..9e5db53185 100644
--- a/spec/workers/activitypub/distribution_worker_spec.rb
+++ b/spec/workers/activitypub/distribution_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::DistributionWorker do
+RSpec.describe ActivityPub::DistributionWorker do
subject { described_class.new }
let(:status) { Fabricate(:status) }
diff --git a/spec/workers/activitypub/fetch_replies_worker_spec.rb b/spec/workers/activitypub/fetch_replies_worker_spec.rb
index 2d080e286e..56d19705a4 100644
--- a/spec/workers/activitypub/fetch_replies_worker_spec.rb
+++ b/spec/workers/activitypub/fetch_replies_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::FetchRepliesWorker do
+RSpec.describe ActivityPub::FetchRepliesWorker do
subject { described_class.new }
let(:account) { Fabricate(:account, domain: 'example.com') }
diff --git a/spec/workers/activitypub/move_distribution_worker_spec.rb b/spec/workers/activitypub/move_distribution_worker_spec.rb
index c810b33c23..63396834de 100644
--- a/spec/workers/activitypub/move_distribution_worker_spec.rb
+++ b/spec/workers/activitypub/move_distribution_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::MoveDistributionWorker do
+RSpec.describe ActivityPub::MoveDistributionWorker do
subject { described_class.new }
let(:migration) { Fabricate(:account_migration) }
diff --git a/spec/workers/activitypub/post_upgrade_worker_spec.rb b/spec/workers/activitypub/post_upgrade_worker_spec.rb
index 08de150ad9..fe1c5e895e 100644
--- a/spec/workers/activitypub/post_upgrade_worker_spec.rb
+++ b/spec/workers/activitypub/post_upgrade_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::PostUpgradeWorker do
+RSpec.describe ActivityPub::PostUpgradeWorker do
let(:worker) { described_class.new }
describe '#perform' do
diff --git a/spec/workers/activitypub/processing_worker_spec.rb b/spec/workers/activitypub/processing_worker_spec.rb
index 66d1cf4890..c06ba63d39 100644
--- a/spec/workers/activitypub/processing_worker_spec.rb
+++ b/spec/workers/activitypub/processing_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::ProcessingWorker do
+RSpec.describe ActivityPub::ProcessingWorker do
subject { described_class.new }
let(:account) { Fabricate(:account) }
diff --git a/spec/workers/activitypub/status_update_distribution_worker_spec.rb b/spec/workers/activitypub/status_update_distribution_worker_spec.rb
index 66e52c4f28..e9a70d11d1 100644
--- a/spec/workers/activitypub/status_update_distribution_worker_spec.rb
+++ b/spec/workers/activitypub/status_update_distribution_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::StatusUpdateDistributionWorker do
+RSpec.describe ActivityPub::StatusUpdateDistributionWorker do
subject { described_class.new }
let(:status) { Fabricate(:status, text: 'foo') }
diff --git a/spec/workers/activitypub/synchronize_featured_tags_collection_worker_spec.rb b/spec/workers/activitypub/synchronize_featured_tags_collection_worker_spec.rb
index 8cf13cb900..d10ea8a75e 100644
--- a/spec/workers/activitypub/synchronize_featured_tags_collection_worker_spec.rb
+++ b/spec/workers/activitypub/synchronize_featured_tags_collection_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::SynchronizeFeaturedTagsCollectionWorker do
+RSpec.describe ActivityPub::SynchronizeFeaturedTagsCollectionWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(ActivityPub::FetchFeaturedTagsCollectionService, call: true) }
diff --git a/spec/workers/activitypub/update_distribution_worker_spec.rb b/spec/workers/activitypub/update_distribution_worker_spec.rb
index b183a58dfd..7d78606398 100644
--- a/spec/workers/activitypub/update_distribution_worker_spec.rb
+++ b/spec/workers/activitypub/update_distribution_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ActivityPub::UpdateDistributionWorker do
+RSpec.describe ActivityPub::UpdateDistributionWorker do
subject { described_class.new }
let(:account) { Fabricate(:account) }
diff --git a/spec/workers/add_to_public_statuses_index_worker_spec.rb b/spec/workers/add_to_public_statuses_index_worker_spec.rb
index fa15072241..edaec1dd3a 100644
--- a/spec/workers/add_to_public_statuses_index_worker_spec.rb
+++ b/spec/workers/add_to_public_statuses_index_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe AddToPublicStatusesIndexWorker do
+RSpec.describe AddToPublicStatusesIndexWorker do
describe '#perform' do
let(:account) { Fabricate(:account, indexable: indexable) }
let(:account_id) { account.id }
diff --git a/spec/workers/admin/account_deletion_worker_spec.rb b/spec/workers/admin/account_deletion_worker_spec.rb
index 631cab6648..e41b734f21 100644
--- a/spec/workers/admin/account_deletion_worker_spec.rb
+++ b/spec/workers/admin/account_deletion_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::AccountDeletionWorker do
+RSpec.describe Admin::AccountDeletionWorker do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/admin/domain_purge_worker_spec.rb b/spec/workers/admin/domain_purge_worker_spec.rb
index 861fd71a7f..32bdd0868b 100644
--- a/spec/workers/admin/domain_purge_worker_spec.rb
+++ b/spec/workers/admin/domain_purge_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::DomainPurgeWorker do
+RSpec.describe Admin::DomainPurgeWorker do
subject { described_class.new }
describe 'perform' do
diff --git a/spec/workers/admin/suspension_worker_spec.rb b/spec/workers/admin/suspension_worker_spec.rb
index da12037edc..445e0b635e 100644
--- a/spec/workers/admin/suspension_worker_spec.rb
+++ b/spec/workers/admin/suspension_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Admin::SuspensionWorker do
+RSpec.describe Admin::SuspensionWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(SuspendAccountService, call: true) }
diff --git a/spec/workers/after_account_domain_block_worker_spec.rb b/spec/workers/after_account_domain_block_worker_spec.rb
index 54a113a2b3..56f5957ea2 100644
--- a/spec/workers/after_account_domain_block_worker_spec.rb
+++ b/spec/workers/after_account_domain_block_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe AfterAccountDomainBlockWorker do
+RSpec.describe AfterAccountDomainBlockWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(AfterBlockDomainFromAccountService, call: true) }
diff --git a/spec/workers/backup_worker_spec.rb b/spec/workers/backup_worker_spec.rb
index db1b50140b..5d1d91267a 100644
--- a/spec/workers/backup_worker_spec.rb
+++ b/spec/workers/backup_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe BackupWorker do
+RSpec.describe BackupWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(BackupService, call: true) }
diff --git a/spec/workers/bulk_import_worker_spec.rb b/spec/workers/bulk_import_worker_spec.rb
index 91f51fbb42..2d429c880b 100644
--- a/spec/workers/bulk_import_worker_spec.rb
+++ b/spec/workers/bulk_import_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe BulkImportWorker do
+RSpec.describe BulkImportWorker do
subject { described_class.new }
let(:import) { Fabricate(:bulk_import, state: :scheduled) }
diff --git a/spec/workers/cache_buster_worker_spec.rb b/spec/workers/cache_buster_worker_spec.rb
index adeb287fa3..b6948395b8 100644
--- a/spec/workers/cache_buster_worker_spec.rb
+++ b/spec/workers/cache_buster_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe CacheBusterWorker do
+RSpec.describe CacheBusterWorker do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/delete_mute_worker_spec.rb b/spec/workers/delete_mute_worker_spec.rb
index 1fc84491c3..a5d1fe343d 100644
--- a/spec/workers/delete_mute_worker_spec.rb
+++ b/spec/workers/delete_mute_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe DeleteMuteWorker do
+RSpec.describe DeleteMuteWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(UnmuteService, call: true) }
diff --git a/spec/workers/domain_block_worker_spec.rb b/spec/workers/domain_block_worker_spec.rb
index 33c3ca009a..c55aa2c0c3 100644
--- a/spec/workers/domain_block_worker_spec.rb
+++ b/spec/workers/domain_block_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe DomainBlockWorker do
+RSpec.describe DomainBlockWorker do
subject { described_class.new }
describe 'perform' do
diff --git a/spec/workers/domain_clear_media_worker_spec.rb b/spec/workers/domain_clear_media_worker_spec.rb
index 21f8f87b2f..20911007b0 100644
--- a/spec/workers/domain_clear_media_worker_spec.rb
+++ b/spec/workers/domain_clear_media_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe DomainClearMediaWorker do
+RSpec.describe DomainClearMediaWorker do
subject { described_class.new }
describe 'perform' do
diff --git a/spec/workers/feed_insert_worker_spec.rb b/spec/workers/feed_insert_worker_spec.rb
index e9484879ff..92ae304d0e 100644
--- a/spec/workers/feed_insert_worker_spec.rb
+++ b/spec/workers/feed_insert_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe FeedInsertWorker do
+RSpec.describe FeedInsertWorker do
subject { described_class.new }
describe 'perform' do
diff --git a/spec/workers/filtered_notification_cleanup_worker_spec.rb b/spec/workers/filtered_notification_cleanup_worker_spec.rb
index 2636b70ad4..5ecd4291af 100644
--- a/spec/workers/filtered_notification_cleanup_worker_spec.rb
+++ b/spec/workers/filtered_notification_cleanup_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe FilteredNotificationCleanupWorker do
+RSpec.describe FilteredNotificationCleanupWorker do
describe '#perform' do
let(:sender) { Fabricate(:account) }
let(:recipient) { Fabricate(:account) }
diff --git a/spec/workers/generate_annual_report_worker_spec.rb b/spec/workers/generate_annual_report_worker_spec.rb
new file mode 100644
index 0000000000..69b0d4424b
--- /dev/null
+++ b/spec/workers/generate_annual_report_worker_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe GenerateAnnualReportWorker do
+ let(:worker) { described_class.new }
+ let(:account) { Fabricate :account }
+
+ describe '#perform' do
+ it 'generates new report for the account' do
+ expect { worker.perform(account.id, Date.current.year) }
+ .to change(account_reports, :count).by(1)
+ end
+
+ it 'returns true for non-existent record' do
+ result = worker.perform(123_123_123, Date.current.year)
+
+ expect(result).to be(true)
+ end
+
+ def account_reports
+ GeneratedAnnualReport
+ .where(account: account)
+ .where(year: Date.current.year)
+ end
+ end
+end
diff --git a/spec/workers/import/row_worker_spec.rb b/spec/workers/import/row_worker_spec.rb
index 0a71a838fc..edb02cb391 100644
--- a/spec/workers/import/row_worker_spec.rb
+++ b/spec/workers/import/row_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Import::RowWorker do
+RSpec.describe Import::RowWorker do
subject { described_class.new }
let(:row) { Fabricate(:bulk_import_row, bulk_import: import) }
diff --git a/spec/workers/import_worker_spec.rb b/spec/workers/import_worker_spec.rb
index 4095a5d354..1d34aafe86 100644
--- a/spec/workers/import_worker_spec.rb
+++ b/spec/workers/import_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ImportWorker do
+RSpec.describe ImportWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(ImportService, call: true) }
diff --git a/spec/workers/move_worker_spec.rb b/spec/workers/move_worker_spec.rb
index b25992e44b..a24de57e27 100644
--- a/spec/workers/move_worker_spec.rb
+++ b/spec/workers/move_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe MoveWorker do
+RSpec.describe MoveWorker do
subject { described_class.new }
let(:local_follower) { Fabricate(:account, domain: nil) }
diff --git a/spec/workers/poll_expiration_notify_worker_spec.rb b/spec/workers/poll_expiration_notify_worker_spec.rb
index 4bd90270d8..b3ccdd3d77 100644
--- a/spec/workers/poll_expiration_notify_worker_spec.rb
+++ b/spec/workers/poll_expiration_notify_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe PollExpirationNotifyWorker do
+RSpec.describe PollExpirationNotifyWorker do
let(:worker) { described_class.new }
let(:account) { Fabricate(:account, domain: remote? ? 'example.com' : nil) }
let(:status) { Fabricate(:status, account: account) }
diff --git a/spec/workers/post_process_media_worker_spec.rb b/spec/workers/post_process_media_worker_spec.rb
index 1a274623d7..f4b441a920 100644
--- a/spec/workers/post_process_media_worker_spec.rb
+++ b/spec/workers/post_process_media_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe PostProcessMediaWorker, :attachment_processing do
+RSpec.describe PostProcessMediaWorker, :attachment_processing do
let(:worker) { described_class.new }
describe '#perform' do
diff --git a/spec/workers/publish_announcement_reaction_worker_spec.rb b/spec/workers/publish_announcement_reaction_worker_spec.rb
index 91668b5ada..37687ca1a8 100644
--- a/spec/workers/publish_announcement_reaction_worker_spec.rb
+++ b/spec/workers/publish_announcement_reaction_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe PublishAnnouncementReactionWorker do
+RSpec.describe PublishAnnouncementReactionWorker do
let(:worker) { described_class.new }
describe '#perform' do
diff --git a/spec/workers/publish_scheduled_announcement_worker_spec.rb b/spec/workers/publish_scheduled_announcement_worker_spec.rb
index 2e50d4a50d..c4e17903a9 100644
--- a/spec/workers/publish_scheduled_announcement_worker_spec.rb
+++ b/spec/workers/publish_scheduled_announcement_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe PublishScheduledAnnouncementWorker do
+RSpec.describe PublishScheduledAnnouncementWorker do
subject { described_class.new }
let!(:remote_account) { Fabricate(:account, domain: 'domain.com', username: 'foo', uri: 'https://domain.com/users/foo') }
diff --git a/spec/workers/publish_scheduled_status_worker_spec.rb b/spec/workers/publish_scheduled_status_worker_spec.rb
index f8547e6fe2..35e510d253 100644
--- a/spec/workers/publish_scheduled_status_worker_spec.rb
+++ b/spec/workers/publish_scheduled_status_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe PublishScheduledStatusWorker do
+RSpec.describe PublishScheduledStatusWorker do
subject { described_class.new }
let(:scheduled_status) { Fabricate(:scheduled_status, params: { text: 'Hello world, future!' }) }
diff --git a/spec/workers/push_conversation_worker_spec.rb b/spec/workers/push_conversation_worker_spec.rb
index 5fbb4c6853..d651059c9a 100644
--- a/spec/workers/push_conversation_worker_spec.rb
+++ b/spec/workers/push_conversation_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe PushConversationWorker do
+RSpec.describe PushConversationWorker do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/push_encrypted_message_worker_spec.rb b/spec/workers/push_encrypted_message_worker_spec.rb
deleted file mode 100644
index 3cd04ce7b4..0000000000
--- a/spec/workers/push_encrypted_message_worker_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe PushEncryptedMessageWorker do
- let(:worker) { described_class.new }
-
- describe 'perform' do
- it 'runs without error for missing record' do
- expect { worker.perform(nil) }.to_not raise_error
- end
- end
-end
diff --git a/spec/workers/push_update_worker_spec.rb b/spec/workers/push_update_worker_spec.rb
index c8f94fa82a..6206ab5986 100644
--- a/spec/workers/push_update_worker_spec.rb
+++ b/spec/workers/push_update_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe PushUpdateWorker do
+RSpec.describe PushUpdateWorker do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/redownload_avatar_worker_spec.rb b/spec/workers/redownload_avatar_worker_spec.rb
index 6ef320bc4f..6712ce8f40 100644
--- a/spec/workers/redownload_avatar_worker_spec.rb
+++ b/spec/workers/redownload_avatar_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RedownloadAvatarWorker do
+RSpec.describe RedownloadAvatarWorker do
let(:worker) { described_class.new }
describe '#perform' do
diff --git a/spec/workers/redownload_header_worker_spec.rb b/spec/workers/redownload_header_worker_spec.rb
index 746c1a63ff..a57ed31792 100644
--- a/spec/workers/redownload_header_worker_spec.rb
+++ b/spec/workers/redownload_header_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RedownloadHeaderWorker do
+RSpec.describe RedownloadHeaderWorker do
let(:worker) { described_class.new }
describe '#perform' do
diff --git a/spec/workers/redownload_media_worker_spec.rb b/spec/workers/redownload_media_worker_spec.rb
index cd561d148b..adf9a7171c 100644
--- a/spec/workers/redownload_media_worker_spec.rb
+++ b/spec/workers/redownload_media_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RedownloadMediaWorker do
+RSpec.describe RedownloadMediaWorker do
let(:worker) { described_class.new }
describe '#perform' do
diff --git a/spec/workers/refollow_worker_spec.rb b/spec/workers/refollow_worker_spec.rb
index 5718d4db49..30d5327947 100644
--- a/spec/workers/refollow_worker_spec.rb
+++ b/spec/workers/refollow_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RefollowWorker do
+RSpec.describe RefollowWorker do
subject { described_class.new }
let(:account) { Fabricate(:account, domain: 'example.org', protocol: :activitypub) }
diff --git a/spec/workers/regeneration_worker_spec.rb b/spec/workers/regeneration_worker_spec.rb
index 37b0a04c49..980f1d81db 100644
--- a/spec/workers/regeneration_worker_spec.rb
+++ b/spec/workers/regeneration_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RegenerationWorker do
+RSpec.describe RegenerationWorker do
subject { described_class.new }
describe 'perform' do
diff --git a/spec/workers/removal_worker_spec.rb b/spec/workers/removal_worker_spec.rb
index 5071e882b6..784e72441c 100644
--- a/spec/workers/removal_worker_spec.rb
+++ b/spec/workers/removal_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RemovalWorker do
+RSpec.describe RemovalWorker do
let(:worker) { described_class.new }
let(:service) { instance_double(RemoveStatusService, call: true) }
diff --git a/spec/workers/remove_featured_tag_worker_spec.rb b/spec/workers/remove_featured_tag_worker_spec.rb
index a64bd0605f..7866824ee7 100644
--- a/spec/workers/remove_featured_tag_worker_spec.rb
+++ b/spec/workers/remove_featured_tag_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RemoveFeaturedTagWorker do
+RSpec.describe RemoveFeaturedTagWorker do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/remove_from_public_statuses_index_worker_spec.rb b/spec/workers/remove_from_public_statuses_index_worker_spec.rb
index 43ff211eaa..90f05d6a26 100644
--- a/spec/workers/remove_from_public_statuses_index_worker_spec.rb
+++ b/spec/workers/remove_from_public_statuses_index_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe RemoveFromPublicStatusesIndexWorker do
+RSpec.describe RemoveFromPublicStatusesIndexWorker do
describe '#perform' do
let(:account) { Fabricate(:account, indexable: indexable) }
let(:account_id) { account.id }
diff --git a/spec/workers/resolve_account_worker_spec.rb b/spec/workers/resolve_account_worker_spec.rb
index 6f3cff099f..de349adacb 100644
--- a/spec/workers/resolve_account_worker_spec.rb
+++ b/spec/workers/resolve_account_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe ResolveAccountWorker do
+RSpec.describe ResolveAccountWorker do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb b/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb
index 08ebf82785..28a4176193 100644
--- a/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb
+++ b/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::AccountsStatusesCleanupScheduler do
+RSpec.describe Scheduler::AccountsStatusesCleanupScheduler do
subject { described_class.new }
let!(:account_alice) { Fabricate(:account, domain: nil, username: 'alice') }
diff --git a/spec/workers/scheduler/auto_close_registrations_scheduler_spec.rb b/spec/workers/scheduler/auto_close_registrations_scheduler_spec.rb
index c0c50b128d..d9355248ba 100644
--- a/spec/workers/scheduler/auto_close_registrations_scheduler_spec.rb
+++ b/spec/workers/scheduler/auto_close_registrations_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::AutoCloseRegistrationsScheduler do
+RSpec.describe Scheduler::AutoCloseRegistrationsScheduler do
subject { described_class.new }
describe '#perform' do
diff --git a/spec/workers/scheduler/follow_recommendations_scheduler_spec.rb b/spec/workers/scheduler/follow_recommendations_scheduler_spec.rb
index 246012e128..eb9d88e59a 100644
--- a/spec/workers/scheduler/follow_recommendations_scheduler_spec.rb
+++ b/spec/workers/scheduler/follow_recommendations_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::FollowRecommendationsScheduler do
+RSpec.describe Scheduler::FollowRecommendationsScheduler do
let!(:target_accounts) do
Fabricate.times(3, :account) do
statuses(count: 6)
diff --git a/spec/workers/scheduler/indexing_scheduler_spec.rb b/spec/workers/scheduler/indexing_scheduler_spec.rb
index 568f0fc84d..39a88e8063 100644
--- a/spec/workers/scheduler/indexing_scheduler_spec.rb
+++ b/spec/workers/scheduler/indexing_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::IndexingScheduler do
+RSpec.describe Scheduler::IndexingScheduler do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/scheduler/instance_refresh_scheduler_spec.rb b/spec/workers/scheduler/instance_refresh_scheduler_spec.rb
index 8f686a6998..37682ebb8f 100644
--- a/spec/workers/scheduler/instance_refresh_scheduler_spec.rb
+++ b/spec/workers/scheduler/instance_refresh_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::InstanceRefreshScheduler do
+RSpec.describe Scheduler::InstanceRefreshScheduler do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb b/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb
index 50af030117..7071fa6e98 100644
--- a/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb
+++ b/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::IpCleanupScheduler do
+RSpec.describe Scheduler::IpCleanupScheduler do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/scheduler/pghero_scheduler_spec.rb b/spec/workers/scheduler/pghero_scheduler_spec.rb
index e404e5fe47..c99e5bb164 100644
--- a/spec/workers/scheduler/pghero_scheduler_spec.rb
+++ b/spec/workers/scheduler/pghero_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::PgheroScheduler do
+RSpec.describe Scheduler::PgheroScheduler do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/scheduler/scheduled_statuses_scheduler_spec.rb b/spec/workers/scheduler/scheduled_statuses_scheduler_spec.rb
index 13c853c62a..2eeaeffe37 100644
--- a/spec/workers/scheduler/scheduled_statuses_scheduler_spec.rb
+++ b/spec/workers/scheduler/scheduled_statuses_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::ScheduledStatusesScheduler do
+RSpec.describe Scheduler::ScheduledStatusesScheduler do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/scheduler/self_destruct_scheduler_spec.rb b/spec/workers/scheduler/self_destruct_scheduler_spec.rb
index 2bf5783571..a79559efdd 100644
--- a/spec/workers/scheduler/self_destruct_scheduler_spec.rb
+++ b/spec/workers/scheduler/self_destruct_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::SelfDestructScheduler do
+RSpec.describe Scheduler::SelfDestructScheduler do
let(:worker) { described_class.new }
describe '#perform' do
diff --git a/spec/workers/scheduler/software_update_check_scheduler_spec.rb b/spec/workers/scheduler/software_update_check_scheduler_spec.rb
index f596c0a1ec..c88dbfe0af 100644
--- a/spec/workers/scheduler/software_update_check_scheduler_spec.rb
+++ b/spec/workers/scheduler/software_update_check_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::SoftwareUpdateCheckScheduler do
+RSpec.describe Scheduler::SoftwareUpdateCheckScheduler do
subject { described_class.new }
describe 'perform' do
diff --git a/spec/workers/scheduler/suspended_user_cleanup_scheduler_spec.rb b/spec/workers/scheduler/suspended_user_cleanup_scheduler_spec.rb
index 25f0e1fce4..2782848e76 100644
--- a/spec/workers/scheduler/suspended_user_cleanup_scheduler_spec.rb
+++ b/spec/workers/scheduler/suspended_user_cleanup_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::SuspendedUserCleanupScheduler do
+RSpec.describe Scheduler::SuspendedUserCleanupScheduler do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/scheduler/trends/refresh_scheduler_spec.rb b/spec/workers/scheduler/trends/refresh_scheduler_spec.rb
index c0c5f032bf..34bcd8fdd8 100644
--- a/spec/workers/scheduler/trends/refresh_scheduler_spec.rb
+++ b/spec/workers/scheduler/trends/refresh_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::Trends::RefreshScheduler do
+RSpec.describe Scheduler::Trends::RefreshScheduler do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/scheduler/trends/review_notifications_scheduler_spec.rb b/spec/workers/scheduler/trends/review_notifications_scheduler_spec.rb
index cc971c24b4..ec35236172 100644
--- a/spec/workers/scheduler/trends/review_notifications_scheduler_spec.rb
+++ b/spec/workers/scheduler/trends/review_notifications_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::Trends::ReviewNotificationsScheduler do
+RSpec.describe Scheduler::Trends::ReviewNotificationsScheduler do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/scheduler/user_cleanup_scheduler_spec.rb b/spec/workers/scheduler/user_cleanup_scheduler_spec.rb
index 7952f2c146..b1be7c4611 100644
--- a/spec/workers/scheduler/user_cleanup_scheduler_spec.rb
+++ b/spec/workers/scheduler/user_cleanup_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::UserCleanupScheduler do
+RSpec.describe Scheduler::UserCleanupScheduler do
subject { described_class.new }
let!(:new_unconfirmed_user) { Fabricate(:user) }
diff --git a/spec/workers/scheduler/vacuum_scheduler_spec.rb b/spec/workers/scheduler/vacuum_scheduler_spec.rb
index 36ecc93d8e..29a7eeac40 100644
--- a/spec/workers/scheduler/vacuum_scheduler_spec.rb
+++ b/spec/workers/scheduler/vacuum_scheduler_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Scheduler::VacuumScheduler do
+RSpec.describe Scheduler::VacuumScheduler do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/tag_unmerge_worker_spec.rb b/spec/workers/tag_unmerge_worker_spec.rb
index 5d3a12c449..a0e53e36d9 100644
--- a/spec/workers/tag_unmerge_worker_spec.rb
+++ b/spec/workers/tag_unmerge_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe TagUnmergeWorker do
+RSpec.describe TagUnmergeWorker do
subject { described_class.new }
describe 'perform' do
diff --git a/spec/workers/unfilter_notifications_worker_spec.rb b/spec/workers/unfilter_notifications_worker_spec.rb
index 629eb644e4..464a4520ff 100644
--- a/spec/workers/unfilter_notifications_worker_spec.rb
+++ b/spec/workers/unfilter_notifications_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe UnfilterNotificationsWorker do
+RSpec.describe UnfilterNotificationsWorker do
let(:recipient) { Fabricate(:account) }
let(:sender) { Fabricate(:account) }
diff --git a/spec/workers/unfollow_follow_worker_spec.rb b/spec/workers/unfollow_follow_worker_spec.rb
index 8025b88c0c..7b9d49b902 100644
--- a/spec/workers/unfollow_follow_worker_spec.rb
+++ b/spec/workers/unfollow_follow_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe UnfollowFollowWorker do
+RSpec.describe UnfollowFollowWorker do
subject { described_class.new }
let(:local_follower) { Fabricate(:account) }
diff --git a/spec/workers/unpublish_announcement_worker_spec.rb b/spec/workers/unpublish_announcement_worker_spec.rb
index c742c30bce..f4838ac248 100644
--- a/spec/workers/unpublish_announcement_worker_spec.rb
+++ b/spec/workers/unpublish_announcement_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe UnpublishAnnouncementWorker do
+RSpec.describe UnpublishAnnouncementWorker do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/verify_account_links_worker_spec.rb b/spec/workers/verify_account_links_worker_spec.rb
index 227591392c..3f600b8c97 100644
--- a/spec/workers/verify_account_links_worker_spec.rb
+++ b/spec/workers/verify_account_links_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe VerifyAccountLinksWorker do
+RSpec.describe VerifyAccountLinksWorker do
let(:worker) { described_class.new }
describe 'perform' do
diff --git a/spec/workers/web/push_notification_worker_spec.rb b/spec/workers/web/push_notification_worker_spec.rb
index 637206a409..ced21d5bf7 100644
--- a/spec/workers/web/push_notification_worker_spec.rb
+++ b/spec/workers/web/push_notification_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Web::PushNotificationWorker do
+RSpec.describe Web::PushNotificationWorker do
subject { described_class.new }
let(:p256dh) { 'BN4GvZtEZiZuqFxSKVZfSfluwKBD7UxHNBmWkfiZfCtgDE8Bwh-_MtLXbBxTBAWH9r7IPKL0lhdcaqtL1dfxU5E=' }
diff --git a/spec/workers/webhooks/delivery_worker_spec.rb b/spec/workers/webhooks/delivery_worker_spec.rb
index 6a5483d1d4..48fcfc607b 100644
--- a/spec/workers/webhooks/delivery_worker_spec.rb
+++ b/spec/workers/webhooks/delivery_worker_spec.rb
@@ -2,7 +2,7 @@
require 'rails_helper'
-describe Webhooks::DeliveryWorker do
+RSpec.describe Webhooks::DeliveryWorker do
let(:worker) { described_class.new }
describe '#perform' do
diff --git a/streaming/database.js b/streaming/database.js
new file mode 100644
index 0000000000..9f1d742143
--- /dev/null
+++ b/streaming/database.js
@@ -0,0 +1,128 @@
+import pg from 'pg';
+import pgConnectionString from 'pg-connection-string';
+
+import { parseIntFromEnvValue } from './utils.js';
+
+/**
+ * @param {NodeJS.ProcessEnv} env the `process.env` value to read configuration from
+ * @param {string} environment
+ * @returns {pg.PoolConfig} the configuration for the PostgreSQL connection
+ */
+export function configFromEnv(env, environment) {
+ /** @type {Record} */
+ const pgConfigs = {
+ development: {
+ user: env.DB_USER || pg.defaults.user,
+ password: env.DB_PASS || pg.defaults.password,
+ database: env.DB_NAME || 'mastodon_development',
+ host: env.DB_HOST || pg.defaults.host,
+ port: parseIntFromEnvValue(env.DB_PORT, pg.defaults.port ?? 5432, 'DB_PORT')
+ },
+
+ production: {
+ user: env.DB_USER || 'mastodon',
+ password: env.DB_PASS || '',
+ database: env.DB_NAME || 'mastodon_production',
+ host: env.DB_HOST || 'localhost',
+ port: parseIntFromEnvValue(env.DB_PORT, 5432, 'DB_PORT')
+ },
+ };
+
+ /**
+ * @type {pg.PoolConfig}
+ */
+ let baseConfig = {};
+
+ if (env.DATABASE_URL) {
+ const parsedUrl = pgConnectionString.parse(env.DATABASE_URL);
+
+ // The result of dbUrlToConfig from pg-connection-string is not type
+ // compatible with pg.PoolConfig, since parts of the connection URL may be
+ // `null` when pg.PoolConfig expects `undefined`, as such we have to
+ // manually create the baseConfig object from the properties of the
+ // parsedUrl.
+ //
+ // For more information see:
+ // https://github.com/brianc/node-postgres/issues/2280
+ //
+ // FIXME: clean up once brianc/node-postgres#3128 lands
+ if (typeof parsedUrl.password === 'string') baseConfig.password = parsedUrl.password;
+ if (typeof parsedUrl.host === 'string') baseConfig.host = parsedUrl.host;
+ if (typeof parsedUrl.user === 'string') baseConfig.user = parsedUrl.user;
+ if (typeof parsedUrl.port === 'string') {
+ const parsedPort = parseInt(parsedUrl.port, 10);
+ if (isNaN(parsedPort)) {
+ throw new Error('Invalid port specified in DATABASE_URL environment variable');
+ }
+ baseConfig.port = parsedPort;
+ }
+ if (typeof parsedUrl.database === 'string') baseConfig.database = parsedUrl.database;
+ if (typeof parsedUrl.options === 'string') baseConfig.options = parsedUrl.options;
+
+ // The pg-connection-string type definition isn't correct, as parsedUrl.ssl
+ // can absolutely be an Object, this is to work around these incorrect
+ // types, including the casting of parsedUrl.ssl to Record
+ if (typeof parsedUrl.ssl === 'boolean') {
+ baseConfig.ssl = parsedUrl.ssl;
+ } else if (typeof parsedUrl.ssl === 'object' && !Array.isArray(parsedUrl.ssl) && parsedUrl.ssl !== null) {
+ /** @type {Record} */
+ const sslOptions = parsedUrl.ssl;
+ baseConfig.ssl = {};
+
+ baseConfig.ssl.cert = sslOptions.cert;
+ baseConfig.ssl.key = sslOptions.key;
+ baseConfig.ssl.ca = sslOptions.ca;
+ baseConfig.ssl.rejectUnauthorized = sslOptions.rejectUnauthorized;
+ }
+
+ // Support overriding the database password in the connection URL
+ if (!baseConfig.password && env.DB_PASS) {
+ baseConfig.password = env.DB_PASS;
+ }
+ } else if (Object.hasOwn(pgConfigs, environment)) {
+ baseConfig = pgConfigs[environment];
+
+ if (env.DB_SSLMODE) {
+ switch(env.DB_SSLMODE) {
+ case 'disable':
+ case '':
+ baseConfig.ssl = false;
+ break;
+ case 'no-verify':
+ baseConfig.ssl = { rejectUnauthorized: false };
+ break;
+ default:
+ baseConfig.ssl = {};
+ break;
+ }
+ }
+ } else {
+ throw new Error('Unable to resolve postgresql database configuration.');
+ }
+
+ return {
+ ...baseConfig,
+ max: parseIntFromEnvValue(env.DB_POOL, 10, 'DB_POOL'),
+ connectionTimeoutMillis: 15000,
+ // Deliberately set application_name to an empty string to prevent excessive
+ // CPU usage with PG Bouncer. See:
+ // - https://github.com/mastodon/mastodon/pull/23958
+ // - https://github.com/pgbouncer/pgbouncer/issues/349
+ application_name: '',
+ };
+}
+
+let pool;
+/**
+ *
+ * @param {pg.PoolConfig} config
+ * @returns {pg.Pool}
+ */
+export function getPool(config) {
+ if (pool) {
+ return pool;
+ }
+
+ pool = new pg.Pool(config);
+ return pool;
+}
diff --git a/streaming/index.js b/streaming/index.js
index 4419b37c60..d792f95acf 100644
--- a/streaming/index.js
+++ b/streaming/index.js
@@ -8,15 +8,14 @@ import url from 'node:url';
import cors from 'cors';
import dotenv from 'dotenv';
import express from 'express';
-import { Redis } from 'ioredis';
import { JSDOM } from 'jsdom';
-import pg from 'pg';
-import pgConnectionString from 'pg-connection-string';
import { WebSocketServer } from 'ws';
+import * as Database from './database.js';
import { AuthenticationError, RequestError, extractStatusAndMessage as extractErrorStatusAndMessage } from './errors.js';
import { logger, httpLogger, initializeLogLevel, attachWebsocketHttpLogger, createWebsocketLogger } from './logging.js';
import { setupMetrics } from './metrics.js';
+import * as Redis from './redis.js';
import { isTruthy, normalizeHashtag, firstParam } from './utils.js';
const environment = process.env.NODE_ENV || 'development';
@@ -45,26 +44,8 @@ initializeLogLevel(process.env, environment);
* @property {string[]} scopes
* @property {string} accountId
* @property {string[]} chosenLanguages
- * @property {string} deviceId
*/
-/**
- * @param {RedisConfiguration} config
- * @returns {Promise}
- */
-const createRedisClient = async ({ redisParams, redisUrl }) => {
- let client;
-
- if (typeof redisUrl === 'string') {
- client = new Redis(redisUrl, redisParams);
- } else {
- client = new Redis(redisParams);
- }
-
- client.on('error', (err) => logger.error({ err }, 'Redis Client Error!'));
-
- return client;
-};
/**
* Attempts to safely parse a string as JSON, used when both receiving a message
@@ -97,177 +78,6 @@ const parseJSON = (json, req) => {
}
};
-/**
- * Takes an environment variable that should be an integer, attempts to parse
- * it falling back to a default if not set, and handles errors parsing.
- * @param {string|undefined} value
- * @param {number} defaultValue
- * @param {string} variableName
- * @returns {number}
- */
-const parseIntFromEnv = (value, defaultValue, variableName) => {
- if (typeof value === 'string' && value.length > 0) {
- const parsedValue = parseInt(value, 10);
- if (isNaN(parsedValue)) {
- throw new Error(`Invalid ${variableName} environment variable: ${value}`);
- }
- return parsedValue;
- } else {
- return defaultValue;
- }
-};
-
-/**
- * @param {NodeJS.ProcessEnv} env the `process.env` value to read configuration from
- * @returns {pg.PoolConfig} the configuration for the PostgreSQL connection
- */
-const pgConfigFromEnv = (env) => {
- /** @type {Record} */
- const pgConfigs = {
- development: {
- user: env.DB_USER || pg.defaults.user,
- password: env.DB_PASS || pg.defaults.password,
- database: env.DB_NAME || 'mastodon_development',
- host: env.DB_HOST || pg.defaults.host,
- port: parseIntFromEnv(env.DB_PORT, pg.defaults.port ?? 5432, 'DB_PORT')
- },
-
- production: {
- user: env.DB_USER || 'mastodon',
- password: env.DB_PASS || '',
- database: env.DB_NAME || 'mastodon_production',
- host: env.DB_HOST || 'localhost',
- port: parseIntFromEnv(env.DB_PORT, 5432, 'DB_PORT')
- },
- };
-
- /**
- * @type {pg.PoolConfig}
- */
- let baseConfig = {};
-
- if (env.DATABASE_URL) {
- const parsedUrl = pgConnectionString.parse(env.DATABASE_URL);
-
- // The result of dbUrlToConfig from pg-connection-string is not type
- // compatible with pg.PoolConfig, since parts of the connection URL may be
- // `null` when pg.PoolConfig expects `undefined`, as such we have to
- // manually create the baseConfig object from the properties of the
- // parsedUrl.
- //
- // For more information see:
- // https://github.com/brianc/node-postgres/issues/2280
- //
- // FIXME: clean up once brianc/node-postgres#3128 lands
- if (typeof parsedUrl.password === 'string') baseConfig.password = parsedUrl.password;
- if (typeof parsedUrl.host === 'string') baseConfig.host = parsedUrl.host;
- if (typeof parsedUrl.user === 'string') baseConfig.user = parsedUrl.user;
- if (typeof parsedUrl.port === 'string') {
- const parsedPort = parseInt(parsedUrl.port, 10);
- if (isNaN(parsedPort)) {
- throw new Error('Invalid port specified in DATABASE_URL environment variable');
- }
- baseConfig.port = parsedPort;
- }
- if (typeof parsedUrl.database === 'string') baseConfig.database = parsedUrl.database;
- if (typeof parsedUrl.options === 'string') baseConfig.options = parsedUrl.options;
-
- // The pg-connection-string type definition isn't correct, as parsedUrl.ssl
- // can absolutely be an Object, this is to work around these incorrect
- // types, including the casting of parsedUrl.ssl to Record
- if (typeof parsedUrl.ssl === 'boolean') {
- baseConfig.ssl = parsedUrl.ssl;
- } else if (typeof parsedUrl.ssl === 'object' && !Array.isArray(parsedUrl.ssl) && parsedUrl.ssl !== null) {
- /** @type {Record} */
- const sslOptions = parsedUrl.ssl;
- baseConfig.ssl = {};
-
- baseConfig.ssl.cert = sslOptions.cert;
- baseConfig.ssl.key = sslOptions.key;
- baseConfig.ssl.ca = sslOptions.ca;
- baseConfig.ssl.rejectUnauthorized = sslOptions.rejectUnauthorized;
- }
-
- // Support overriding the database password in the connection URL
- if (!baseConfig.password && env.DB_PASS) {
- baseConfig.password = env.DB_PASS;
- }
- } else if (Object.hasOwn(pgConfigs, environment)) {
- baseConfig = pgConfigs[environment];
-
- if (env.DB_SSLMODE) {
- switch(env.DB_SSLMODE) {
- case 'disable':
- case '':
- baseConfig.ssl = false;
- break;
- case 'no-verify':
- baseConfig.ssl = { rejectUnauthorized: false };
- break;
- default:
- baseConfig.ssl = {};
- break;
- }
- }
- } else {
- throw new Error('Unable to resolve postgresql database configuration.');
- }
-
- return {
- ...baseConfig,
- max: parseIntFromEnv(env.DB_POOL, 10, 'DB_POOL'),
- connectionTimeoutMillis: 15000,
- // Deliberately set application_name to an empty string to prevent excessive
- // CPU usage with PG Bouncer. See:
- // - https://github.com/mastodon/mastodon/pull/23958
- // - https://github.com/pgbouncer/pgbouncer/issues/349
- application_name: '',
- };
-};
-
-/**
- * @typedef RedisConfiguration
- * @property {import('ioredis').RedisOptions} redisParams
- * @property {string} redisPrefix
- * @property {string|undefined} redisUrl
- */
-
-/**
- * @param {NodeJS.ProcessEnv} env the `process.env` value to read configuration from
- * @returns {RedisConfiguration} configuration for the Redis connection
- */
-const redisConfigFromEnv = (env) => {
- // ioredis *can* transparently add prefixes for us, but it doesn't *in some cases*,
- // which means we can't use it. But this is something that should be looked into.
- const redisPrefix = env.REDIS_NAMESPACE ? `${env.REDIS_NAMESPACE}:` : '';
-
- let redisPort = parseIntFromEnv(env.REDIS_PORT, 6379, 'REDIS_PORT');
- let redisDatabase = parseIntFromEnv(env.REDIS_DB, 0, 'REDIS_DB');
-
- /** @type {import('ioredis').RedisOptions} */
- const redisParams = {
- host: env.REDIS_HOST || '127.0.0.1',
- port: redisPort,
- // Force support for both IPv6 and IPv4, by default ioredis sets this to 4,
- // only allowing IPv4 connections:
- // https://github.com/redis/ioredis/issues/1576
- family: 0,
- db: redisDatabase,
- password: env.REDIS_PASSWORD || undefined,
- };
-
- // redisParams.path takes precedence over host and port.
- if (env.REDIS_URL && env.REDIS_URL.startsWith('unix://')) {
- redisParams.path = env.REDIS_URL.slice(7);
- }
-
- return {
- redisParams,
- redisPrefix,
- redisUrl: typeof env.REDIS_URL === 'string' ? env.REDIS_URL : undefined,
- };
-};
-
const PUBLIC_CHANNELS = [
'public',
'public:media',
@@ -291,10 +101,44 @@ const CHANNEL_NAMES = [
];
const startServer = async () => {
- const pgPool = new pg.Pool(pgConfigFromEnv(process.env));
+ const pgPool = Database.getPool(Database.configFromEnv(process.env, environment));
+
+ const metrics = setupMetrics(CHANNEL_NAMES, pgPool);
+
+ const redisConfig = Redis.configFromEnv(process.env);
+ const redisClient = Redis.createClient(redisConfig, logger);
const server = http.createServer();
const wss = new WebSocketServer({ noServer: true });
+ /**
+ * Adds a namespace to Redis keys or channel names
+ * Fixes: https://github.com/redis/ioredis/issues/1910
+ * @param {string} keyOrChannel
+ * @returns {string}
+ */
+ function redisNamespaced(keyOrChannel) {
+ if (redisConfig.namespace) {
+ return `${redisConfig.namespace}:${keyOrChannel}`;
+ } else {
+ return keyOrChannel;
+ }
+ }
+
+ /**
+ * Removes the redis namespace from a channel name
+ * @param {string} channel
+ * @returns {string}
+ */
+ function redisUnnamespaced(channel) {
+ if (typeof redisConfig.namespace === "string") {
+ // Note: this removes the configured namespace and the colon that is used
+ // to separate it:
+ return channel.slice(redisConfig.namespace.length + 1);
+ } else {
+ return channel;
+ }
+ }
+
// Set the X-Request-Id header on WebSockets:
wss.on("headers", function onHeaders(headers, req) {
headers.push(`X-Request-Id: ${req.id}`);
@@ -383,20 +227,7 @@ const startServer = async () => {
*/
const subs = {};
- const redisConfig = redisConfigFromEnv(process.env);
- const redisSubscribeClient = await createRedisClient(redisConfig);
- const redisClient = await createRedisClient(redisConfig);
- const { redisPrefix } = redisConfig;
-
- const metrics = setupMetrics(CHANNEL_NAMES, pgPool);
- // TODO: migrate all metrics to metrics.X.method() instead of just X.method()
- const {
- connectedClients,
- connectedChannels,
- redisSubscriptions,
- redisMessagesReceived,
- messagesSent,
- } = metrics;
+ const redisSubscribeClient = Redis.createClient(redisConfig, logger);
// When checking metrics in the browser, the favicon is requested this
// prevents the request from falling through to the API Router, which would
@@ -408,15 +239,7 @@ const startServer = async () => {
res.end('OK');
});
- app.get('/metrics', async (req, res) => {
- try {
- res.set('Content-Type', metrics.register.contentType);
- res.end(await metrics.register.metrics());
- } catch (ex) {
- req.log.error(ex);
- res.status(500).end();
- }
- });
+ app.get('/metrics', metrics.requestHandler);
/**
* @param {string[]} channels
@@ -426,7 +249,7 @@ const startServer = async () => {
const interval = 6 * 60;
const tellSubscribed = () => {
- channels.forEach(channel => redisClient.set(`${redisPrefix}subscribed:${channel}`, '1', 'EX', interval * 3));
+ channels.forEach(channel => redisClient.set(redisNamespaced(`subscribed:${channel}`), '1', 'EX', interval * 3));
};
tellSubscribed();
@@ -443,12 +266,11 @@ const startServer = async () => {
* @param {string} message
*/
const onRedisMessage = (channel, message) => {
- redisMessagesReceived.inc();
-
- const callbacks = subs[channel];
-
- logger.debug(`New message on channel ${redisPrefix}${channel}`);
+ metrics.redisMessagesReceived.inc();
+ logger.debug(`New message on channel ${channel}`);
+ const key = redisUnnamespaced(channel);
+ const callbacks = subs[key];
if (!callbacks) {
return;
}
@@ -477,11 +299,12 @@ const startServer = async () => {
if (subs[channel].length === 0) {
logger.debug(`Subscribe ${channel}`);
- redisSubscribeClient.subscribe(channel, (err, count) => {
+
+ redisSubscribeClient.subscribe(redisNamespaced(channel), (err, count) => {
if (err) {
logger.error(`Error subscribing to ${channel}`);
} else if (typeof count === 'number') {
- redisSubscriptions.set(count);
+ metrics.redisSubscriptions.set(count);
}
});
}
@@ -504,11 +327,13 @@ const startServer = async () => {
if (subs[channel].length === 0) {
logger.debug(`Unsubscribe ${channel}`);
- redisSubscribeClient.unsubscribe(channel, (err, count) => {
+
+ // FIXME: https://github.com/redis/ioredis/issues/1910
+ redisSubscribeClient.unsubscribe(redisNamespaced(channel), (err, count) => {
if (err) {
logger.error(`Error unsubscribing to ${channel}`);
} else if (typeof count === 'number') {
- redisSubscriptions.set(count);
+ metrics.redisSubscriptions.set(count);
}
});
delete subs[channel];
@@ -529,7 +354,7 @@ const startServer = async () => {
* @returns {Promise}
*/
const accountFromToken = async (token, req) => {
- const result = await pgPool.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes, devices.device_id FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id LEFT OUTER JOIN devices ON oauth_access_tokens.id = devices.access_token_id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL LIMIT 1', [token]);
+ const result = await pgPool.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL LIMIT 1', [token]);
if (result.rows.length === 0) {
throw new AuthenticationError('Invalid access token');
@@ -539,14 +364,12 @@ const startServer = async () => {
req.scopes = result.rows[0].scopes.split(' ');
req.accountId = result.rows[0].account_id;
req.chosenLanguages = result.rows[0].chosen_languages;
- req.deviceId = result.rows[0].device_id;
return {
accessTokenId: result.rows[0].id,
scopes: result.rows[0].scopes.split(' '),
accountId: result.rows[0].account_id,
chosenLanguages: result.rows[0].chosen_languages,
- deviceId: result.rows[0].device_id
};
};
@@ -685,16 +508,16 @@ const startServer = async () => {
});
res.on('close', () => {
- unsubscribe(`${redisPrefix}${accessTokenChannelId}`, listener);
- unsubscribe(`${redisPrefix}${systemChannelId}`, listener);
+ unsubscribe(accessTokenChannelId, listener);
+ unsubscribe(systemChannelId, listener);
- connectedChannels.labels({ type: 'eventsource', channel: 'system' }).dec(2);
+ metrics.connectedChannels.labels({ type: 'eventsource', channel: 'system' }).dec(2);
});
- subscribe(`${redisPrefix}${accessTokenChannelId}`, listener);
- subscribe(`${redisPrefix}${systemChannelId}`, listener);
+ subscribe(accessTokenChannelId, listener);
+ subscribe(systemChannelId, listener);
- connectedChannels.labels({ type: 'eventsource', channel: 'system' }).inc(2);
+ metrics.connectedChannels.labels({ type: 'eventsource', channel: 'system' }).inc(2);
};
/**
@@ -791,7 +614,7 @@ const startServer = async () => {
// TODO: Replace "string"-based delete payloads with object payloads:
const encodedPayload = typeof payload === 'object' ? JSON.stringify(payload) : payload;
- messagesSent.labels({ type: destinationType }).inc(1);
+ metrics.messagesSent.labels({ type: destinationType }).inc(1);
log.debug({ event, payload }, `Transmitting ${event} to ${req.accountId}`);
@@ -1016,11 +839,11 @@ const startServer = async () => {
};
channelIds.forEach(id => {
- subscribe(`${redisPrefix}${id}`, listener);
+ subscribe(id, listener);
});
if (typeof attachCloseHandler === 'function') {
- attachCloseHandler(channelIds.map(id => `${redisPrefix}${id}`), listener);
+ attachCloseHandler(channelIds, listener);
}
return listener;
@@ -1034,11 +857,11 @@ const startServer = async () => {
const streamToHttp = (req, res) => {
const channelName = channelNameFromPath(req);
- connectedClients.labels({ type: 'eventsource' }).inc();
+ metrics.connectedClients.labels({ type: 'eventsource' }).inc();
// In theory we'll always have a channel name, but channelNameFromPath can return undefined:
if (typeof channelName === 'string') {
- connectedChannels.labels({ type: 'eventsource', channel: channelName }).inc();
+ metrics.connectedChannels.labels({ type: 'eventsource', channel: channelName }).inc();
}
res.setHeader('Content-Type', 'text/event-stream');
@@ -1054,10 +877,10 @@ const startServer = async () => {
// We decrement these counters here instead of in streamHttpEnd as in that
// method we don't have knowledge of the channel names
- connectedClients.labels({ type: 'eventsource' }).dec();
+ metrics.connectedClients.labels({ type: 'eventsource' }).dec();
// In theory we'll always have a channel name, but channelNameFromPath can return undefined:
if (typeof channelName === 'string') {
- connectedChannels.labels({ type: 'eventsource', channel: channelName }).dec();
+ metrics.connectedChannels.labels({ type: 'eventsource', channel: channelName }).dec();
}
clearInterval(heartbeat);
@@ -1164,10 +987,6 @@ const startServer = async () => {
const channelsForUserStream = req => {
const arr = [`timeline:${req.accountId}`];
- if (isInScope(req, ['crypto']) && req.deviceId) {
- arr.push(`timeline:${req.accountId}:${req.deviceId}`);
- }
-
if (isInScope(req, ['read', 'read:notifications'])) {
arr.push(`timeline:${req.accountId}:notifications`);
}
@@ -1345,7 +1164,7 @@ const startServer = async () => {
const stopHeartbeat = subscriptionHeartbeat(channelIds);
const listener = streamFrom(channelIds, request, logger, onSend, undefined, 'websocket', options.needsFiltering, options.allowLocalOnly);
- connectedChannels.labels({ type: 'websocket', channel: channelName }).inc();
+ metrics.connectedChannels.labels({ type: 'websocket', channel: channelName }).inc();
subscriptions[channelIds.join(';')] = {
channelName,
@@ -1381,10 +1200,10 @@ const startServer = async () => {
}
channelIds.forEach(channelId => {
- unsubscribe(`${redisPrefix}${channelId}`, subscription.listener);
+ unsubscribe(channelId, subscription.listener);
});
- connectedChannels.labels({ type: 'websocket', channel: subscription.channelName }).dec();
+ metrics.connectedChannels.labels({ type: 'websocket', channel: subscription.channelName }).dec();
subscription.stopHeartbeat();
delete subscriptions[channelIds.join(';')];
@@ -1425,8 +1244,8 @@ const startServer = async () => {
},
});
- subscribe(`${redisPrefix}${accessTokenChannelId}`, listener);
- subscribe(`${redisPrefix}${systemChannelId}`, listener);
+ subscribe(accessTokenChannelId, listener);
+ subscribe(systemChannelId, listener);
subscriptions[accessTokenChannelId] = {
channelName: 'system',
@@ -1442,7 +1261,7 @@ const startServer = async () => {
},
};
- connectedChannels.labels({ type: 'websocket', channel: 'system' }).inc(2);
+ metrics.connectedChannels.labels({ type: 'websocket', channel: 'system' }).inc(2);
};
/**
@@ -1454,7 +1273,7 @@ const startServer = async () => {
// Note: url.parse could throw, which would terminate the connection, so we
// increment the connected clients metric straight away when we establish
// the connection, without waiting:
- connectedClients.labels({ type: 'websocket' }).inc();
+ metrics.connectedClients.labels({ type: 'websocket' }).inc();
// Setup connection keep-alive state:
ws.isAlive = true;
@@ -1480,7 +1299,7 @@ const startServer = async () => {
});
// Decrement the metrics for connected clients:
- connectedClients.labels({ type: 'websocket' }).dec();
+ metrics.connectedClients.labels({ type: 'websocket' }).dec();
// We need to unassign the session object as to ensure it correctly gets
// garbage collected, without doing this we could accidentally hold on to
@@ -1576,15 +1395,23 @@ const startServer = async () => {
* @param {function(string): void} [onSuccess]
*/
const attachServerWithConfig = (server, onSuccess) => {
- if (process.env.SOCKET || process.env.PORT && isNaN(+process.env.PORT)) {
- server.listen(process.env.SOCKET || process.env.PORT, () => {
+ if (process.env.SOCKET) {
+ server.listen(process.env.SOCKET, () => {
if (onSuccess) {
fs.chmodSync(server.address(), 0o666);
onSuccess(server.address());
}
});
} else {
- server.listen(+(process.env.PORT || 4000), process.env.BIND || '127.0.0.1', () => {
+ const port = +(process.env.PORT || 4000);
+ let bind = process.env.BIND ?? '127.0.0.1';
+ // Web uses the URI syntax for BIND, which means IPv6 addresses may
+ // be wrapped in square brackets:
+ if (bind.startsWith('[') && bind.endsWith(']')) {
+ bind = bind.slice(1, -1);
+ }
+
+ server.listen(port, bind, () => {
if (onSuccess) {
onSuccess(`${server.address().address}:${server.address().port}`);
}
diff --git a/streaming/metrics.js b/streaming/metrics.js
index a029d778fc..bb6bce3f3c 100644
--- a/streaming/metrics.js
+++ b/streaming/metrics.js
@@ -4,12 +4,12 @@ import metrics from 'prom-client';
/**
* @typedef StreamingMetrics
- * @property {metrics.Registry} register
* @property {metrics.Gauge<"type">} connectedClients
* @property {metrics.Gauge<"type" | "channel">} connectedChannels
* @property {metrics.Gauge} redisSubscriptions
* @property {metrics.Counter} redisMessagesReceived
* @property {metrics.Counter<"type">} messagesSent
+ * @property {import('express').RequestHandler<{}>} requestHandler
*/
/**
@@ -92,8 +92,21 @@ export function setupMetrics(channels, pgPool) {
messagesSent.inc({ type: 'websocket' }, 0);
messagesSent.inc({ type: 'eventsource' }, 0);
+ /**
+ * @type {import('express').RequestHandler<{}>}
+ */
+ const requestHandler = (req, res) => {
+ metrics.register.metrics().then((output) => {
+ res.set('Content-Type', metrics.register.contentType);
+ res.end(output);
+ }).catch((err) => {
+ req.log.error(err, "Error collecting metrics");
+ res.status(500).end();
+ });
+ };
+
return {
- register: metrics.register,
+ requestHandler,
connectedClients,
connectedChannels,
redisSubscriptions,
diff --git a/streaming/package.json b/streaming/package.json
index 4f44927831..d573c9b284 100644
--- a/streaming/package.json
+++ b/streaming/package.json
@@ -1,7 +1,7 @@
{
"name": "@mastodon/streaming",
"license": "AGPL-3.0-or-later",
- "packageManager": "yarn@4.4.0",
+ "packageManager": "yarn@4.5.0",
"engines": {
"node": ">=18"
},
@@ -21,7 +21,7 @@
"dotenv": "^16.0.3",
"express": "^4.18.2",
"ioredis": "^5.3.2",
- "jsdom": "^24.0.0",
+ "jsdom": "^25.0.0",
"pg": "^8.5.0",
"pg-connection-string": "^2.6.0",
"pino": "^9.0.0",
diff --git a/streaming/redis.js b/streaming/redis.js
new file mode 100644
index 0000000000..2a36b89dc5
--- /dev/null
+++ b/streaming/redis.js
@@ -0,0 +1,135 @@
+import { Redis } from 'ioredis';
+
+import { parseIntFromEnvValue } from './utils.js';
+
+/**
+ * @typedef RedisConfiguration
+ * @property {string|undefined} namespace
+ * @property {string|undefined} url
+ * @property {import('ioredis').RedisOptions} options
+ */
+
+/**
+ *
+ * @param {NodeJS.ProcessEnv} env
+ * @returns {boolean}
+ */
+function hasSentinelConfiguration(env) {
+ return (
+ typeof env.REDIS_SENTINELS === 'string' &&
+ env.REDIS_SENTINELS.length > 0 &&
+ typeof env.REDIS_SENTINEL_MASTER === 'string' &&
+ env.REDIS_SENTINEL_MASTER.length > 0
+ );
+}
+
+/**
+ *
+ * @param {NodeJS.ProcessEnv} env
+ * @param {import('ioredis').SentinelConnectionOptions} commonOptions
+ * @returns {import('ioredis').SentinelConnectionOptions}
+ */
+function getSentinelConfiguration(env, commonOptions) {
+ const redisDatabase = parseIntFromEnvValue(env.REDIS_DB, 0, 'REDIS_DB');
+ const sentinelPort = parseIntFromEnvValue(env.REDIS_SENTINEL_PORT, 26379, 'REDIS_SENTINEL_PORT');
+
+ const sentinels = env.REDIS_SENTINELS.split(',').map((sentinel) => {
+ const [host, port] = sentinel.split(':', 2);
+
+ /** @type {import('ioredis').SentinelAddress} */
+ return {
+ host: host,
+ port: port ?? sentinelPort,
+ // Force support for both IPv6 and IPv4, by default ioredis sets this to 4,
+ // only allowing IPv4 connections:
+ // https://github.com/redis/ioredis/issues/1576
+ family: 0
+ };
+ });
+
+ return {
+ db: redisDatabase,
+ name: env.REDIS_SENTINEL_MASTER,
+ username: env.REDIS_USERNAME,
+ password: env.REDIS_PASSWORD,
+ sentinelUsername: env.REDIS_SENTINEL_USERNAME ?? env.REDIS_USERNAME,
+ sentinelPassword: env.REDIS_SENTINEL_PASSWORD ?? env.REDIS_PASSWORD,
+ sentinels,
+ ...commonOptions,
+ };
+}
+
+/**
+ * @param {NodeJS.ProcessEnv} env the `process.env` value to read configuration from
+ * @returns {RedisConfiguration} configuration for the Redis connection
+ */
+export function configFromEnv(env) {
+ const redisNamespace = env.REDIS_NAMESPACE;
+
+ // These options apply for both REDIS_URL based connections and connections
+ // using the other REDIS_* environment variables:
+ const commonOptions = {
+ // Force support for both IPv6 and IPv4, by default ioredis sets this to 4,
+ // only allowing IPv4 connections:
+ // https://github.com/redis/ioredis/issues/1576
+ family: 0
+ // Note: we don't use auto-prefixing of keys since this doesn't apply to
+ // subscribe/unsubscribe which have "channel" instead of "key" arguments
+ };
+
+ // If we receive REDIS_URL, don't continue parsing any other REDIS_*
+ // environment variables:
+ if (typeof env.REDIS_URL === 'string' && env.REDIS_URL.length > 0) {
+ return {
+ url: env.REDIS_URL,
+ options: commonOptions,
+ namespace: redisNamespace
+ };
+ }
+
+ // If we have configuration for Redis Sentinel mode, prefer that:
+ if (hasSentinelConfiguration(env)) {
+ return {
+ options: getSentinelConfiguration(env, commonOptions),
+ namespace: redisNamespace
+ };
+ }
+
+ // Finally, handle all the other REDIS_* environment variables:
+ let redisPort = parseIntFromEnvValue(env.REDIS_PORT, 6379, 'REDIS_PORT');
+ let redisDatabase = parseIntFromEnvValue(env.REDIS_DB, 0, 'REDIS_DB');
+
+ /** @type {import('ioredis').RedisOptions} */
+ const options = {
+ host: env.REDIS_HOST ?? '127.0.0.1',
+ port: redisPort,
+ db: redisDatabase,
+ username: env.REDIS_USERNAME,
+ password: env.REDIS_PASSWORD,
+ ...commonOptions,
+ };
+
+ return {
+ options,
+ namespace: redisNamespace
+ };
+}
+
+/**
+ * @param {RedisConfiguration} config
+ * @param {import('pino').Logger} logger
+ * @returns {Redis}
+ */
+export function createClient({ url, options }, logger) {
+ let client;
+
+ if (typeof url === 'string') {
+ client = new Redis(url, options);
+ } else {
+ client = new Redis(options);
+ }
+
+ client.on('error', (err) => logger.error({ err }, 'Redis Client Error!'));
+
+ return client;
+}
diff --git a/streaming/utils.js b/streaming/utils.js
index 4610bf660d..47c63dd4ca 100644
--- a/streaming/utils.js
+++ b/streaming/utils.js
@@ -59,3 +59,23 @@ export function firstParam(arrayOrString) {
return arrayOrString;
}
}
+
+/**
+ * Takes an environment variable that should be an integer, attempts to parse
+ * it falling back to a default if not set, and handles errors parsing.
+ * @param {string|undefined} value
+ * @param {number} defaultValue
+ * @param {string} variableName
+ * @returns {number}
+ */
+export function parseIntFromEnvValue(value, defaultValue, variableName) {
+ if (typeof value === 'string' && value.length > 0) {
+ const parsedValue = parseInt(value, 10);
+ if (isNaN(parsedValue)) {
+ throw new Error(`Invalid ${variableName} environment variable: ${value}`);
+ }
+ return parsedValue;
+ } else {
+ return defaultValue;
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index 2554ae2bdc..a905bfb958 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1487,11 +1487,11 @@ __metadata:
linkType: hard
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
- version: 7.25.4
- resolution: "@babel/runtime@npm:7.25.4"
+ version: 7.25.6
+ resolution: "@babel/runtime@npm:7.25.6"
dependencies:
regenerator-runtime: "npm:^0.14.0"
- checksum: 10c0/33e937e685f0bfc2d40c219261e2e50d0df7381a6e7cbf56b770e0c5d77cb0c21bf4d97da566cf0164317ed7508e992082c7b6cce7aaa3b17da5794f93fbfb46
+ checksum: 10c0/d6143adf5aa1ce79ed374e33fdfd74fa975055a80bc6e479672ab1eadc4e4bfd7484444e17dd063a1d180e051f3ec62b357c7a2b817e7657687b47313158c3d2
languageName: node
linkType: hard
@@ -1579,7 +1579,7 @@ __metadata:
languageName: node
linkType: hard
-"@csstools/css-parser-algorithms@npm:^3.0.0, @csstools/css-parser-algorithms@npm:^3.0.1":
+"@csstools/css-parser-algorithms@npm:^3.0.1":
version: 3.0.1
resolution: "@csstools/css-parser-algorithms@npm:3.0.1"
peerDependencies:
@@ -1588,14 +1588,14 @@ __metadata:
languageName: node
linkType: hard
-"@csstools/css-tokenizer@npm:^3.0.0, @csstools/css-tokenizer@npm:^3.0.1":
+"@csstools/css-tokenizer@npm:^3.0.1":
version: 3.0.1
resolution: "@csstools/css-tokenizer@npm:3.0.1"
checksum: 10c0/c9ed4373e5731b5375ea9791590081019c04e95f08b46b272977e5e7b8c3d560affc62e82263cb8def1df1e57f0673140e7e16a14a5e7be04e6a234be088d1d3
languageName: node
linkType: hard
-"@csstools/media-query-list-parser@npm:^3.0.0, @csstools/media-query-list-parser@npm:^3.0.1":
+"@csstools/media-query-list-parser@npm:^3.0.1":
version: 3.0.1
resolution: "@csstools/media-query-list-parser@npm:3.0.1"
peerDependencies:
@@ -2330,9 +2330,9 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/intl@npm:2.10.4":
- version: 2.10.4
- resolution: "@formatjs/intl@npm:2.10.4"
+"@formatjs/intl@npm:2.10.5":
+ version: 2.10.5
+ resolution: "@formatjs/intl@npm:2.10.5"
dependencies:
"@formatjs/ecma402-abstract": "npm:2.0.0"
"@formatjs/fast-memoize": "npm:2.2.0"
@@ -2346,7 +2346,7 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10c0/ca7877e962f73f1fe0e358f12d73bdc3ec4006c14ee801e06d9f7aef06bcdcc12355a8f53f32b0e890f829949ded35e825c914ca5f4709eb1e08c2a18c1368c2
+ checksum: 10c0/d00ef00e41200947ed22895b73a0863283de4762ec238b4a81e2252e642e30a309cd9c73174e4917b6c675ab6f148eda5a4e3345c3caeef64e090fc8374d27c4
languageName: node
linkType: hard
@@ -2757,7 +2757,7 @@ __metadata:
"@formatjs/intl-pluralrules": "npm:^5.2.2"
"@gamestdio/websocket": "npm:^0.3.2"
"@github/webauthn-json": "npm:^2.1.1"
- "@rails/ujs": "npm:7.1.3"
+ "@rails/ujs": "npm:7.1.400"
"@reduxjs/toolkit": "npm:^2.0.1"
"@svgr/webpack": "npm:^5.5.0"
"@testing-library/dom": "npm:^10.2.0"
@@ -2791,8 +2791,8 @@ __metadata:
"@types/requestidlecallback": "npm:^0.3.5"
"@types/webpack": "npm:^4.41.33"
"@types/webpack-env": "npm:^1.18.4"
- "@typescript-eslint/eslint-plugin": "npm:^7.0.0"
- "@typescript-eslint/parser": "npm:^7.0.0"
+ "@typescript-eslint/eslint-plugin": "npm:^8.0.0"
+ "@typescript-eslint/parser": "npm:^8.0.0"
arrow-key-navigation: "npm:^1.2.0"
async-mutex: "npm:^0.5.0"
atrament: "npm:0.2.4"
@@ -2820,9 +2820,9 @@ __metadata:
eslint-define-config: "npm:^2.0.0"
eslint-import-resolver-typescript: "npm:^3.5.5"
eslint-plugin-formatjs: "npm:^4.10.1"
- eslint-plugin-import: "npm:~2.29.0"
+ eslint-plugin-import: "npm:~2.30.0"
eslint-plugin-jsdoc: "npm:^50.0.0"
- eslint-plugin-jsx-a11y: "npm:~6.9.0"
+ eslint-plugin-jsx-a11y: "npm:~6.10.0"
eslint-plugin-promise: "npm:~7.1.0"
eslint-plugin-react: "npm:^7.33.2"
eslint-plugin-react-hooks: "npm:^4.6.0"
@@ -2929,7 +2929,7 @@ __metadata:
eslint-define-config: "npm:^2.0.0"
express: "npm:^4.18.2"
ioredis: "npm:^5.3.2"
- jsdom: "npm:^24.0.0"
+ jsdom: "npm:^25.0.0"
pg: "npm:^8.5.0"
pg-connection-string: "npm:^2.6.0"
pino: "npm:^9.0.0"
@@ -2975,6 +2975,13 @@ __metadata:
languageName: node
linkType: hard
+"@nolyfill/is-core-module@npm:1.0.39":
+ version: 1.0.39
+ resolution: "@nolyfill/is-core-module@npm:1.0.39"
+ checksum: 10c0/34ab85fdc2e0250879518841f74a30c276bca4f6c3e13526d2d1fe515e1adf6d46c25fcd5989d22ea056d76f7c39210945180b4859fc83b050e2da411aa86289
+ languageName: node
+ linkType: hard
+
"@npmcli/agent@npm:^2.0.0":
version: 2.2.0
resolution: "@npmcli/agent@npm:2.2.0"
@@ -3052,10 +3059,10 @@ __metadata:
languageName: node
linkType: hard
-"@rails/ujs@npm:7.1.3":
- version: 7.1.3
- resolution: "@rails/ujs@npm:7.1.3"
- checksum: 10c0/68112d9add9dbc59b40c2ec1bc095a67445c57d20d0ab7d817ce3de0cd90374e2690af8ad54ce6ecc2d1c748b34c0c44d0fbd2f515ce2c443d7c5d23d00b9ce5
+"@rails/ujs@npm:7.1.400":
+ version: 7.1.400
+ resolution: "@rails/ujs@npm:7.1.400"
+ checksum: 10c0/181329e731b925788a530dc5bc44eb4a07ae780e20b0309fd9140ebeeca30d9432ed50be0f25ae60f10beb3aa8883f6d662e4b9c6f6cd19a32c1f42ab2505c47
languageName: node
linkType: hard
@@ -3183,6 +3190,13 @@ __metadata:
languageName: node
linkType: hard
+"@rtsao/scc@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "@rtsao/scc@npm:1.1.0"
+ checksum: 10c0/b5bcfb0d87f7d1c1c7c0f7693f53b07866ed9fec4c34a97a8c948fb9a7c0082e416ce4d3b60beb4f5e167cbe04cdeefbf6771320f3ede059b9ce91188c409a5b
+ languageName: node
+ linkType: hard
+
"@sinclair/typebox@npm:^0.27.8":
version: 0.27.8
resolution: "@sinclair/typebox@npm:0.27.8"
@@ -3368,24 +3382,23 @@ __metadata:
linkType: hard
"@testing-library/jest-dom@npm:^6.0.0":
- version: 6.4.8
- resolution: "@testing-library/jest-dom@npm:6.4.8"
+ version: 6.5.0
+ resolution: "@testing-library/jest-dom@npm:6.5.0"
dependencies:
"@adobe/css-tools": "npm:^4.4.0"
- "@babel/runtime": "npm:^7.9.2"
aria-query: "npm:^5.0.0"
chalk: "npm:^3.0.0"
css.escape: "npm:^1.5.1"
dom-accessibility-api: "npm:^0.6.3"
lodash: "npm:^4.17.21"
redent: "npm:^3.0.0"
- checksum: 10c0/8eececcac1ec7728c038b9d9eabfc8b8dcf4dc1e997c959450bff16d946e3344275862b84bfe0e1d1beb3817368e782464816aca47ab5c94f0ebf66db71df55d
+ checksum: 10c0/fd5936a547f04608d8de15a7de3ae26516f21023f8f45169b10c8c8847015fd20ec259b7309f08aa1031bcbc37c6e5e6f532d1bb85ef8f91bad654193ec66a4c
languageName: node
linkType: hard
"@testing-library/react@npm:^16.0.0":
- version: 16.0.0
- resolution: "@testing-library/react@npm:16.0.0"
+ version: 16.0.1
+ resolution: "@testing-library/react@npm:16.0.1"
dependencies:
"@babel/runtime": "npm:^7.12.5"
peerDependencies:
@@ -3399,7 +3412,7 @@ __metadata:
optional: true
"@types/react-dom":
optional: true
- checksum: 10c0/297f97bf4722dad05f11d9cafd47d387dbdb096fea4b79b876c7466460f0f2e345b55b81b3e37fc81ed8185c528cb53dd8455ca1b6b019b229edf6c796f11c9f
+ checksum: 10c0/67d05dec5ad5a2e6f92b6a3234af785435c7bb62bdbf12f3bfc89c9bca0c871a189e88c4ba023ed4cea504704c87c6ac7e86e24a3962df6c521ae89b62f48ff7
languageName: node
linkType: hard
@@ -3651,12 +3664,12 @@ __metadata:
linkType: hard
"@types/jest@npm:^29.5.2":
- version: 29.5.12
- resolution: "@types/jest@npm:29.5.12"
+ version: 29.5.13
+ resolution: "@types/jest@npm:29.5.13"
dependencies:
expect: "npm:^29.0.0"
pretty-format: "npm:^29.0.0"
- checksum: 10c0/25fc8e4c611fa6c4421e631432e9f0a6865a8cb07c9815ec9ac90d630271cad773b2ee5fe08066f7b95bebd18bb967f8ce05d018ee9ab0430f9dfd1d84665b6f
+ checksum: 10c0/9c31af0b155387b9860908830de63c6b79011d7c87c8b61b39da124e26e55423dd51b006749aafe4f0ef3a065016619a1f93ef4b055157d43727f448e67824b7
languageName: node
linkType: hard
@@ -3758,13 +3771,13 @@ __metadata:
linkType: hard
"@types/pg@npm:^8.6.6":
- version: 8.11.6
- resolution: "@types/pg@npm:8.11.6"
+ version: 8.11.10
+ resolution: "@types/pg@npm:8.11.10"
dependencies:
"@types/node": "npm:*"
pg-protocol: "npm:*"
pg-types: "npm:^4.0.1"
- checksum: 10c0/e68e057d9500b25cd776f4fcc547b4880c4f3b0c7b6e03c8a0e5e262b6189dd7a00f4edc8937ffc55a9f6a136a78d7e4a9b6bbe6a46122a95c134f7be66f6842
+ checksum: 10c0/c8800d0ab2c6424308e6c6b40c73f19583ee1aed758462bd07694844b0a551b5841442205a4ee05207b80109ba502f33f20241b1bd9b4902e713611fb9e08f6c
languageName: node
linkType: hard
@@ -3776,9 +3789,9 @@ __metadata:
linkType: hard
"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.5":
- version: 15.7.12
- resolution: "@types/prop-types@npm:15.7.12"
- checksum: 10c0/1babcc7db6a1177779f8fde0ccc78d64d459906e6ef69a4ed4dd6339c920c2e05b074ee5a92120fe4e9d9f1a01c952f843ebd550bee2332fc2ef81d1706878f8
+ version: 15.7.13
+ resolution: "@types/prop-types@npm:15.7.13"
+ checksum: 10c0/1b20fc67281902c6743379960247bc161f3f0406ffc0df8e7058745a85ea1538612109db0406290512947f9632fe9e10e7337bf0ce6338a91d6c948df16a7c61
languageName: node
linkType: hard
@@ -3921,12 +3934,12 @@ __metadata:
linkType: hard
"@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7":
- version: 18.3.3
- resolution: "@types/react@npm:18.3.3"
+ version: 18.3.8
+ resolution: "@types/react@npm:18.3.8"
dependencies:
"@types/prop-types": "npm:*"
csstype: "npm:^3.0.2"
- checksum: 10c0/fe455f805c5da13b89964c3d68060cebd43e73ec15001a68b34634604a78140e6fc202f3f61679b9d809dde6d7a7c2cb3ed51e0fd1462557911db09879b55114
+ checksum: 10c0/367312c9fe276639ecb142265e090a4dd04bb39f8d718cbab546de3f1ddcfddeff415e1147d0fc40f734badaa7420b7b109d511bd4304b2c4c9c36164612fdf8
languageName: node
linkType: hard
@@ -4104,44 +4117,44 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/eslint-plugin@npm:^7.0.0":
- version: 7.18.0
- resolution: "@typescript-eslint/eslint-plugin@npm:7.18.0"
+"@typescript-eslint/eslint-plugin@npm:^8.0.0":
+ version: 8.1.0
+ resolution: "@typescript-eslint/eslint-plugin@npm:8.1.0"
dependencies:
"@eslint-community/regexpp": "npm:^4.10.0"
- "@typescript-eslint/scope-manager": "npm:7.18.0"
- "@typescript-eslint/type-utils": "npm:7.18.0"
- "@typescript-eslint/utils": "npm:7.18.0"
- "@typescript-eslint/visitor-keys": "npm:7.18.0"
+ "@typescript-eslint/scope-manager": "npm:8.1.0"
+ "@typescript-eslint/type-utils": "npm:8.1.0"
+ "@typescript-eslint/utils": "npm:8.1.0"
+ "@typescript-eslint/visitor-keys": "npm:8.1.0"
graphemer: "npm:^1.4.0"
ignore: "npm:^5.3.1"
natural-compare: "npm:^1.4.0"
ts-api-utils: "npm:^1.3.0"
peerDependencies:
- "@typescript-eslint/parser": ^7.0.0
- eslint: ^8.56.0
+ "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0
+ eslint: ^8.57.0 || ^9.0.0
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10c0/2b37948fa1b0dab77138909dabef242a4d49ab93e4019d4ef930626f0a7d96b03e696cd027fa0087881c20e73be7be77c942606b4a76fa599e6b37f6985304c3
+ checksum: 10c0/7bbeae588f859b59c34d6a76cac06ef0fa605921b40c5d3b65b94829984280ea84c4dd3f5cb9ce2eb326f5563e9abb4c90ebff05c47f83f4def296c2ea1fa86c
languageName: node
linkType: hard
-"@typescript-eslint/parser@npm:^7.0.0":
- version: 7.18.0
- resolution: "@typescript-eslint/parser@npm:7.18.0"
+"@typescript-eslint/parser@npm:^8.0.0":
+ version: 8.1.0
+ resolution: "@typescript-eslint/parser@npm:8.1.0"
dependencies:
- "@typescript-eslint/scope-manager": "npm:7.18.0"
- "@typescript-eslint/types": "npm:7.18.0"
- "@typescript-eslint/typescript-estree": "npm:7.18.0"
- "@typescript-eslint/visitor-keys": "npm:7.18.0"
+ "@typescript-eslint/scope-manager": "npm:8.1.0"
+ "@typescript-eslint/types": "npm:8.1.0"
+ "@typescript-eslint/typescript-estree": "npm:8.1.0"
+ "@typescript-eslint/visitor-keys": "npm:8.1.0"
debug: "npm:^4.3.4"
peerDependencies:
- eslint: ^8.56.0
+ eslint: ^8.57.0 || ^9.0.0
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10c0/370e73fca4278091bc1b657f85e7d74cd52b24257ea20c927a8e17546107ce04fbf313fec99aed0cc2a145ddbae1d3b12e9cc2c1320117636dc1281bcfd08059
+ checksum: 10c0/b94b2d3ab5ca505484d100701fad6a04a5dc8d595029bac1b9f5b8a4a91d80fd605b0f65d230b36a97ab7e5d55eeb0c28af2ab63929a3e4ab8fdefd2a548c36b
languageName: node
linkType: hard
@@ -4155,30 +4168,28 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/scope-manager@npm:7.18.0":
- version: 7.18.0
- resolution: "@typescript-eslint/scope-manager@npm:7.18.0"
+"@typescript-eslint/scope-manager@npm:8.1.0":
+ version: 8.1.0
+ resolution: "@typescript-eslint/scope-manager@npm:8.1.0"
dependencies:
- "@typescript-eslint/types": "npm:7.18.0"
- "@typescript-eslint/visitor-keys": "npm:7.18.0"
- checksum: 10c0/038cd58c2271de146b3a594afe2c99290034033326d57ff1f902976022c8b0138ffd3cb893ae439ae41003b5e4bcc00cabf6b244ce40e8668f9412cc96d97b8e
+ "@typescript-eslint/types": "npm:8.1.0"
+ "@typescript-eslint/visitor-keys": "npm:8.1.0"
+ checksum: 10c0/2bcf8cd176a1819bddcae16c572e7da8fba821b995a91cd53d64d8d6b85a17f5a895522f281ba57e34929574bddd4d6684ee3e545ec4e8096be4c3198e253a9a
languageName: node
linkType: hard
-"@typescript-eslint/type-utils@npm:7.18.0":
- version: 7.18.0
- resolution: "@typescript-eslint/type-utils@npm:7.18.0"
+"@typescript-eslint/type-utils@npm:8.1.0":
+ version: 8.1.0
+ resolution: "@typescript-eslint/type-utils@npm:8.1.0"
dependencies:
- "@typescript-eslint/typescript-estree": "npm:7.18.0"
- "@typescript-eslint/utils": "npm:7.18.0"
+ "@typescript-eslint/typescript-estree": "npm:8.1.0"
+ "@typescript-eslint/utils": "npm:8.1.0"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^1.3.0"
- peerDependencies:
- eslint: ^8.56.0
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10c0/ad92a38007be620f3f7036f10e234abdc2fdc518787b5a7227e55fd12896dacf56e8b34578723fbf9bea8128df2510ba8eb6739439a3879eda9519476d5783fd
+ checksum: 10c0/62753941c4136e8d2daa72fe0410dea48e5317a6f12ece6382ca85e29912bd1b3f739b61d1060fc0a1f8c488dfc905beab4c8b8497951a21c3138a659c7271ec
languageName: node
linkType: hard
@@ -4189,10 +4200,10 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/types@npm:7.18.0":
- version: 7.18.0
- resolution: "@typescript-eslint/types@npm:7.18.0"
- checksum: 10c0/eb7371ac55ca77db8e59ba0310b41a74523f17e06f485a0ef819491bc3dd8909bb930120ff7d30aaf54e888167e0005aa1337011f3663dc90fb19203ce478054
+"@typescript-eslint/types@npm:8.1.0":
+ version: 8.1.0
+ resolution: "@typescript-eslint/types@npm:8.1.0"
+ checksum: 10c0/ceade44455f45974e68956016c4d1c6626580732f7f9675e14ffa63db80b551752b0df596b20473dae9f0dc6ed966e17417dc2cf36e1a82b6ab0edc97c5eaa50
languageName: node
linkType: hard
@@ -4215,12 +4226,12 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/typescript-estree@npm:7.18.0":
- version: 7.18.0
- resolution: "@typescript-eslint/typescript-estree@npm:7.18.0"
+"@typescript-eslint/typescript-estree@npm:8.1.0":
+ version: 8.1.0
+ resolution: "@typescript-eslint/typescript-estree@npm:8.1.0"
dependencies:
- "@typescript-eslint/types": "npm:7.18.0"
- "@typescript-eslint/visitor-keys": "npm:7.18.0"
+ "@typescript-eslint/types": "npm:8.1.0"
+ "@typescript-eslint/visitor-keys": "npm:8.1.0"
debug: "npm:^4.3.4"
globby: "npm:^11.1.0"
is-glob: "npm:^4.0.3"
@@ -4230,21 +4241,21 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10c0/0c7f109a2e460ec8a1524339479cf78ff17814d23c83aa5112c77fb345e87b3642616291908dcddea1e671da63686403dfb712e4a4435104f92abdfddf9aba81
+ checksum: 10c0/a7bc8275df1c79c4cb14ef086c56674316dd4907efec53eddca35d0b5220428b69c82178ce2d95138da2e398269c8bd0764cae8020a36417e411e35c3c47bc4b
languageName: node
linkType: hard
-"@typescript-eslint/utils@npm:7.18.0":
- version: 7.18.0
- resolution: "@typescript-eslint/utils@npm:7.18.0"
+"@typescript-eslint/utils@npm:8.1.0":
+ version: 8.1.0
+ resolution: "@typescript-eslint/utils@npm:8.1.0"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.4.0"
- "@typescript-eslint/scope-manager": "npm:7.18.0"
- "@typescript-eslint/types": "npm:7.18.0"
- "@typescript-eslint/typescript-estree": "npm:7.18.0"
+ "@typescript-eslint/scope-manager": "npm:8.1.0"
+ "@typescript-eslint/types": "npm:8.1.0"
+ "@typescript-eslint/typescript-estree": "npm:8.1.0"
peerDependencies:
- eslint: ^8.56.0
- checksum: 10c0/a25a6d50eb45c514469a01ff01f215115a4725fb18401055a847ddf20d1b681409c4027f349033a95c4ff7138d28c3b0a70253dfe8262eb732df4b87c547bd1e
+ eslint: ^8.57.0 || ^9.0.0
+ checksum: 10c0/c95503a6bdcd98b1ff04d1adbf46377b2036b1c510d90a4a056401f996f775f06c3108c95fb81cd6babc9c97b73b91b8e848f0337bc508de8a49c993582f0e75
languageName: node
linkType: hard
@@ -4275,13 +4286,13 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/visitor-keys@npm:7.18.0":
- version: 7.18.0
- resolution: "@typescript-eslint/visitor-keys@npm:7.18.0"
+"@typescript-eslint/visitor-keys@npm:8.1.0":
+ version: 8.1.0
+ resolution: "@typescript-eslint/visitor-keys@npm:8.1.0"
dependencies:
- "@typescript-eslint/types": "npm:7.18.0"
+ "@typescript-eslint/types": "npm:8.1.0"
eslint-visitor-keys: "npm:^3.4.3"
- checksum: 10c0/538b645f8ff1d9debf264865c69a317074eaff0255e63d7407046176b0f6a6beba34a6c51d511f12444bae12a98c69891eb6f403c9f54c6c2e2849d1c1cb73c0
+ checksum: 10c0/b7544dbb0eec1ddbfcd95c04b51b9a739c2e768c16d1c88508f976a2b0d1bc02fefb7491930e06e48073a5c07c6f488cd8403bba3a8b918888b93a88d5ac3869
languageName: node
linkType: hard
@@ -4834,7 +4845,7 @@ __metadata:
languageName: node
linkType: hard
-"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7, array-includes@npm:^3.1.8":
+"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8":
version: 3.1.8
resolution: "array-includes@npm:3.1.8"
dependencies:
@@ -4892,16 +4903,17 @@ __metadata:
languageName: node
linkType: hard
-"array.prototype.findlastindex@npm:^1.2.3":
- version: 1.2.3
- resolution: "array.prototype.findlastindex@npm:1.2.3"
+"array.prototype.findlastindex@npm:^1.2.5":
+ version: 1.2.5
+ resolution: "array.prototype.findlastindex@npm:1.2.5"
dependencies:
- call-bind: "npm:^1.0.2"
- define-properties: "npm:^1.2.0"
- es-abstract: "npm:^1.22.1"
- es-shim-unscopables: "npm:^1.0.0"
- get-intrinsic: "npm:^1.2.1"
- checksum: 10c0/2c5c4d3f07512d6729f728f6260a314c00f2eb0a243123092661fa1bc65dce90234c3b483b5f978396eccef6f69c50f0bea248448aaf9cdfcd1cedad6217acbb
+ call-bind: "npm:^1.0.7"
+ define-properties: "npm:^1.2.1"
+ es-abstract: "npm:^1.23.2"
+ es-errors: "npm:^1.3.0"
+ es-object-atoms: "npm:^1.0.0"
+ es-shim-unscopables: "npm:^1.0.2"
+ checksum: 10c0/962189487728b034f3134802b421b5f39e42ee2356d13b42d2ddb0e52057ffdcc170b9524867f4f0611a6f638f4c19b31e14606e8bcbda67799e26685b195aa3
languageName: node
linkType: hard
@@ -5124,30 +5136,28 @@ __metadata:
languageName: node
linkType: hard
-"axe-core@npm:^4.9.1":
- version: 4.9.1
- resolution: "axe-core@npm:4.9.1"
- checksum: 10c0/ac9e5a0c6fa115a43ebffc32a1d2189e1ca6431b5a78e88cdcf94a72a25c5964185682edd94fe6bdb1cb4266c0d06301b022866e0e50dcdf6e3cefe556470110
+"axe-core@npm:^4.10.0":
+ version: 4.10.0
+ resolution: "axe-core@npm:4.10.0"
+ checksum: 10c0/732c171d48caaace5e784895c4dacb8ca6155e9d98045138ebe3952f78457dd05b92c57d05b41ce2a570aff87dbd0471e8398d2c0f6ebe79617b746c8f658998
languageName: node
linkType: hard
"axios@npm:^1.4.0":
- version: 1.7.4
- resolution: "axios@npm:1.7.4"
+ version: 1.7.7
+ resolution: "axios@npm:1.7.7"
dependencies:
follow-redirects: "npm:^1.15.6"
form-data: "npm:^4.0.0"
proxy-from-env: "npm:^1.1.0"
- checksum: 10c0/5ea1a93140ca1d49db25ef8e1bd8cfc59da6f9220159a944168860ad15a2743ea21c5df2967795acb15cbe81362f5b157fdebbea39d53117ca27658bab9f7f17
+ checksum: 10c0/4499efc89e86b0b49ffddc018798de05fab26e3bf57913818266be73279a6418c3ce8f9e934c7d2d707ab8c095e837fc6c90608fb7715b94d357720b5f568af7
languageName: node
linkType: hard
-"axobject-query@npm:~3.1.1":
- version: 3.1.1
- resolution: "axobject-query@npm:3.1.1"
- dependencies:
- deep-equal: "npm:^2.0.5"
- checksum: 10c0/fff3175a22fd1f41fceb7ae0cd25f6594a0d7fba28c2335dd904538b80eb4e1040432564a3c643025cd2bb748f68d35aaabffb780b794da97ecfc748810b25ad
+"axobject-query@npm:^4.1.0":
+ version: 4.1.0
+ resolution: "axobject-query@npm:4.1.0"
+ checksum: 10c0/c470e4f95008f232eadd755b018cb55f16c03ccf39c027b941cd8820ac6b68707ce5d7368a46756db4256fbc91bb4ead368f84f7fb034b2b7932f082f6dc0775
languageName: node
linkType: hard
@@ -5169,17 +5179,17 @@ __metadata:
linkType: hard
"babel-loader@npm:^8.3.0":
- version: 8.3.0
- resolution: "babel-loader@npm:8.3.0"
+ version: 8.4.1
+ resolution: "babel-loader@npm:8.4.1"
dependencies:
find-cache-dir: "npm:^3.3.1"
- loader-utils: "npm:^2.0.0"
+ loader-utils: "npm:^2.0.4"
make-dir: "npm:^3.1.0"
schema-utils: "npm:^2.6.5"
peerDependencies:
"@babel/core": ^7.0.0
webpack: ">=2"
- checksum: 10c0/7b83bae35a12fbc5cdf250e2d36a288305fe5b6d20ab044ab7c09bbf456c8895b80af7a4f1e8b64b5c07a4fd48d4b5144dab40b4bc72a4fed532dc000362f38f
+ checksum: 10c0/efdca9c3ef502af58b923a32123d660c54fd0be125b7b64562c8a43bda0a3a55dac0db32331674104e7e5184061b75c3a0e395b2c5ccdc7cb2125dd9ec7108d2
languageName: node
linkType: hard
@@ -5468,9 +5478,9 @@ __metadata:
languageName: node
linkType: hard
-"body-parser@npm:1.20.2":
- version: 1.20.2
- resolution: "body-parser@npm:1.20.2"
+"body-parser@npm:1.20.3":
+ version: 1.20.3
+ resolution: "body-parser@npm:1.20.3"
dependencies:
bytes: "npm:3.1.2"
content-type: "npm:~1.0.5"
@@ -5480,11 +5490,11 @@ __metadata:
http-errors: "npm:2.0.0"
iconv-lite: "npm:0.4.24"
on-finished: "npm:2.4.1"
- qs: "npm:6.11.0"
+ qs: "npm:6.13.0"
raw-body: "npm:2.5.2"
type-is: "npm:~1.6.18"
unpipe: "npm:1.0.0"
- checksum: 10c0/06f1438fff388a2e2354c96aa3ea8147b79bfcb1262dfcc2aae68ec13723d01d5781680657b74e9f83c808266d5baf52804032fbde2b7382b89bd8cdb273ace9
+ checksum: 10c0/0a9a93b7518f222885498dcecaad528cf010dd109b071bf471c93def4bfe30958b83e03496eb9c1ad4896db543d999bb62be1a3087294162a88cfa1b42c16310
languageName: node
linkType: hard
@@ -5899,25 +5909,6 @@ __metadata:
languageName: node
linkType: hard
-"chokidar@npm:>=3.0.0 <4.0.0, chokidar@npm:^3.4.1":
- version: 3.5.3
- resolution: "chokidar@npm:3.5.3"
- dependencies:
- anymatch: "npm:~3.1.2"
- braces: "npm:~3.0.2"
- fsevents: "npm:~2.3.2"
- glob-parent: "npm:~5.1.2"
- is-binary-path: "npm:~2.1.0"
- is-glob: "npm:~4.0.1"
- normalize-path: "npm:~3.0.0"
- readdirp: "npm:~3.6.0"
- dependenciesMeta:
- fsevents:
- optional: true
- checksum: 10c0/1076953093e0707c882a92c66c0f56ba6187831aa51bb4de878c1fec59ae611a3bf02898f190efec8e77a086b8df61c2b2a3ea324642a0558bdf8ee6c5dc9ca1
- languageName: node
- linkType: hard
-
"chokidar@npm:^2.1.8":
version: 2.1.8
resolution: "chokidar@npm:2.1.8"
@@ -5941,6 +5932,34 @@ __metadata:
languageName: node
linkType: hard
+"chokidar@npm:^3.4.1":
+ version: 3.5.3
+ resolution: "chokidar@npm:3.5.3"
+ dependencies:
+ anymatch: "npm:~3.1.2"
+ braces: "npm:~3.0.2"
+ fsevents: "npm:~2.3.2"
+ glob-parent: "npm:~5.1.2"
+ is-binary-path: "npm:~2.1.0"
+ is-glob: "npm:~4.0.1"
+ normalize-path: "npm:~3.0.0"
+ readdirp: "npm:~3.6.0"
+ dependenciesMeta:
+ fsevents:
+ optional: true
+ checksum: 10c0/1076953093e0707c882a92c66c0f56ba6187831aa51bb4de878c1fec59ae611a3bf02898f190efec8e77a086b8df61c2b2a3ea324642a0558bdf8ee6c5dc9ca1
+ languageName: node
+ linkType: hard
+
+"chokidar@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "chokidar@npm:4.0.0"
+ dependencies:
+ readdirp: "npm:^4.0.1"
+ checksum: 10c0/42d03c53b0ad200689e4fae7763133561480561cab8ba5304e8f2298ff45ff84bf0f6065c3f02b9e557b74b156813734439a1a2ff19a1ea6b35692395cd92738
+ languageName: node
+ linkType: hard
+
"chownr@npm:^2.0.0":
version: 2.0.0
resolution: "chownr@npm:2.0.0"
@@ -6699,10 +6718,10 @@ __metadata:
languageName: node
linkType: hard
-"cssdb@npm:^8.1.0":
- version: 8.1.0
- resolution: "cssdb@npm:8.1.0"
- checksum: 10c0/1fa1f1566c7e9964f5c71e443583eaba16a90933a3ef6803815c4281d084b75da948c415bade33d7085894fe0929c082fcb3135bf4400048cfff40d227ebd5dd
+"cssdb@npm:^8.1.1":
+ version: 8.1.1
+ resolution: "cssdb@npm:8.1.1"
+ checksum: 10c0/d60facfad3bca70e21100fc35b9205cb9d3d0ac642f44f0a687e54bf787f21c43d28ce2d17fcd405f67950fb4709516108fe1f3cb15df570eff1007b5fbbc787
languageName: node
linkType: hard
@@ -6715,26 +6734,26 @@ __metadata:
languageName: node
linkType: hard
-"cssnano-preset-default@npm:^7.0.5":
- version: 7.0.5
- resolution: "cssnano-preset-default@npm:7.0.5"
+"cssnano-preset-default@npm:^7.0.6":
+ version: 7.0.6
+ resolution: "cssnano-preset-default@npm:7.0.6"
dependencies:
browserslist: "npm:^4.23.3"
css-declaration-sorter: "npm:^7.2.0"
cssnano-utils: "npm:^5.0.0"
- postcss-calc: "npm:^10.0.1"
+ postcss-calc: "npm:^10.0.2"
postcss-colormin: "npm:^7.0.2"
- postcss-convert-values: "npm:^7.0.3"
- postcss-discard-comments: "npm:^7.0.2"
+ postcss-convert-values: "npm:^7.0.4"
+ postcss-discard-comments: "npm:^7.0.3"
postcss-discard-duplicates: "npm:^7.0.1"
postcss-discard-empty: "npm:^7.0.0"
postcss-discard-overridden: "npm:^7.0.0"
- postcss-merge-longhand: "npm:^7.0.3"
- postcss-merge-rules: "npm:^7.0.3"
+ postcss-merge-longhand: "npm:^7.0.4"
+ postcss-merge-rules: "npm:^7.0.4"
postcss-minify-font-values: "npm:^7.0.0"
postcss-minify-gradients: "npm:^7.0.0"
postcss-minify-params: "npm:^7.0.2"
- postcss-minify-selectors: "npm:^7.0.3"
+ postcss-minify-selectors: "npm:^7.0.4"
postcss-normalize-charset: "npm:^7.0.0"
postcss-normalize-display-values: "npm:^7.0.0"
postcss-normalize-positions: "npm:^7.0.0"
@@ -6748,10 +6767,10 @@ __metadata:
postcss-reduce-initial: "npm:^7.0.2"
postcss-reduce-transforms: "npm:^7.0.0"
postcss-svgo: "npm:^7.0.1"
- postcss-unique-selectors: "npm:^7.0.2"
+ postcss-unique-selectors: "npm:^7.0.3"
peerDependencies:
postcss: ^8.4.31
- checksum: 10c0/ffa7c6fa16c6ad98b7732fc563de74d492e6ad6d243a9f00431c0cbdbc576bcd49226d2695d881465d32dea0a2916add40ac10e7560dd7b5de9fd0fa25ee081b
+ checksum: 10c0/5c827a9f6b35475267af0512d55f569994b8334eb06565498daa2070ef52f0cdd2013f5efc1cbc0b4664370f491b0080f93c8ee56a7730d38fdf451fb65b030c
languageName: node
linkType: hard
@@ -6765,14 +6784,14 @@ __metadata:
linkType: hard
"cssnano@npm:^7.0.0":
- version: 7.0.5
- resolution: "cssnano@npm:7.0.5"
+ version: 7.0.6
+ resolution: "cssnano@npm:7.0.6"
dependencies:
- cssnano-preset-default: "npm:^7.0.5"
+ cssnano-preset-default: "npm:^7.0.6"
lilconfig: "npm:^3.1.2"
peerDependencies:
postcss: ^8.4.31
- checksum: 10c0/cb43ed964787dca33efb44d8f4fea8a49c495db44d1d12940493f0dd5d63db78e01c5b140fe42b480b332733602a25f4c85186d00977eb3070b29f7422761985
+ checksum: 10c0/19ff09931a1531e7c0c0d8928da554d99213aa0bb1f3b93cc6b4987727d60a8cd5537b113a5cf4f95cc1db65bba3f2b35476bd63bb57e7469d4eab73e07d736d
languageName: node
linkType: hard
@@ -6817,12 +6836,12 @@ __metadata:
languageName: node
linkType: hard
-"cssstyle@npm:^4.0.1":
- version: 4.0.1
- resolution: "cssstyle@npm:4.0.1"
+"cssstyle@npm:^4.1.0":
+ version: 4.1.0
+ resolution: "cssstyle@npm:4.1.0"
dependencies:
- rrweb-cssom: "npm:^0.6.0"
- checksum: 10c0/cadf9a8b23e11f4c6d63f21291096a0b0be868bd4ab9c799daa2c5b18330e39e5281605f01da906e901b42f742df0f3b3645af6465e83377ff7d15a88ee432a0
+ rrweb-cssom: "npm:^0.7.1"
+ checksum: 10c0/05c6597e5d3e0ec6b15221f2c0ce9a0443a46cc50a6089a3ba9ee1ac27f83ff86a445a8f95435137dadd859f091fc61b6d342abaf396d3c910471b5b33cfcbfa
languageName: node
linkType: hard
@@ -6917,7 +6936,7 @@ __metadata:
languageName: node
linkType: hard
-"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.6, debug@npm:~4.3.6":
+"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.6, debug@npm:~4.3.6":
version: 4.3.6
resolution: "debug@npm:4.3.6"
dependencies:
@@ -7497,6 +7516,13 @@ __metadata:
languageName: node
linkType: hard
+"encodeurl@npm:~2.0.0":
+ version: 2.0.0
+ resolution: "encodeurl@npm:2.0.0"
+ checksum: 10c0/5d317306acb13e6590e28e27924c754163946a2480de11865c991a3a7eed4315cd3fba378b543ca145829569eefe9b899f3d84bb09870f675ae60bc924b01ceb
+ languageName: node
+ linkType: hard
+
"encoding@npm:^0.1.13":
version: 0.1.13
resolution: "encoding@npm:0.1.13"
@@ -7526,13 +7552,13 @@ __metadata:
languageName: node
linkType: hard
-"enhanced-resolve@npm:^5.12.0":
- version: 5.15.0
- resolution: "enhanced-resolve@npm:5.15.0"
+"enhanced-resolve@npm:^5.15.0":
+ version: 5.17.1
+ resolution: "enhanced-resolve@npm:5.17.1"
dependencies:
graceful-fs: "npm:^4.2.4"
tapable: "npm:^2.2.0"
- checksum: 10c0/69984a7990913948b4150855aed26a84afb4cb1c5a94fb8e3a65bd00729a73fc2eaff6871fb8e345377f294831afe349615c93560f2f54d61b43cdfdf668f19a
+ checksum: 10c0/81a0515675eca17efdba2cf5bad87abc91a528fc1191aad50e275e74f045b41506167d420099022da7181c8d787170ea41e4a11a0b10b7a16f6237daecb15370
languageName: node
linkType: hard
@@ -7835,32 +7861,39 @@ __metadata:
linkType: hard
"eslint-import-resolver-typescript@npm:^3.5.5":
- version: 3.6.1
- resolution: "eslint-import-resolver-typescript@npm:3.6.1"
+ version: 3.6.3
+ resolution: "eslint-import-resolver-typescript@npm:3.6.3"
dependencies:
- debug: "npm:^4.3.4"
- enhanced-resolve: "npm:^5.12.0"
- eslint-module-utils: "npm:^2.7.4"
- fast-glob: "npm:^3.3.1"
- get-tsconfig: "npm:^4.5.0"
- is-core-module: "npm:^2.11.0"
+ "@nolyfill/is-core-module": "npm:1.0.39"
+ debug: "npm:^4.3.5"
+ enhanced-resolve: "npm:^5.15.0"
+ eslint-module-utils: "npm:^2.8.1"
+ fast-glob: "npm:^3.3.2"
+ get-tsconfig: "npm:^4.7.5"
+ is-bun-module: "npm:^1.0.2"
is-glob: "npm:^4.0.3"
peerDependencies:
eslint: "*"
eslint-plugin-import: "*"
- checksum: 10c0/cb1cb4389916fe78bf8c8567aae2f69243dbfe624bfe21078c56ad46fa1ebf0634fa7239dd3b2055ab5c27359e4b4c28b69b11fcb3a5df8a9e6f7add8e034d86
+ eslint-plugin-import-x: "*"
+ peerDependenciesMeta:
+ eslint-plugin-import:
+ optional: true
+ eslint-plugin-import-x:
+ optional: true
+ checksum: 10c0/5933b00791b7b077725b9ba9a85327d2e2dc7c8944c18a868feb317a0bf0e1e77aed2254c9c5e24dcc49360d119331d2c15281837f4269592965ace380a75111
languageName: node
linkType: hard
-"eslint-module-utils@npm:^2.7.4, eslint-module-utils@npm:^2.8.0":
- version: 2.8.0
- resolution: "eslint-module-utils@npm:2.8.0"
+"eslint-module-utils@npm:^2.8.1, eslint-module-utils@npm:^2.9.0":
+ version: 2.9.0
+ resolution: "eslint-module-utils@npm:2.9.0"
dependencies:
debug: "npm:^3.2.7"
peerDependenciesMeta:
eslint:
optional: true
- checksum: 10c0/c7a8d1a58d76ec8217a8fea49271ec8132d1b9390965a75f6a4ecbc9e5983d742195b46d2e4378231d2186801439fe1aa5700714b0bfd4eb17aac6e1b65309df
+ checksum: 10c0/7c45c5b54402a969e99315890c10e9bf8c8bee16c7890573343af05dfa04566d61546585678c413e5228af0550e39461be47e35a8ff0d1863e113bdbb28d1d29
languageName: node
linkType: hard
@@ -7885,30 +7918,31 @@ __metadata:
languageName: node
linkType: hard
-"eslint-plugin-import@npm:~2.29.0":
- version: 2.29.1
- resolution: "eslint-plugin-import@npm:2.29.1"
+"eslint-plugin-import@npm:~2.30.0":
+ version: 2.30.0
+ resolution: "eslint-plugin-import@npm:2.30.0"
dependencies:
- array-includes: "npm:^3.1.7"
- array.prototype.findlastindex: "npm:^1.2.3"
+ "@rtsao/scc": "npm:^1.1.0"
+ array-includes: "npm:^3.1.8"
+ array.prototype.findlastindex: "npm:^1.2.5"
array.prototype.flat: "npm:^1.3.2"
array.prototype.flatmap: "npm:^1.3.2"
debug: "npm:^3.2.7"
doctrine: "npm:^2.1.0"
eslint-import-resolver-node: "npm:^0.3.9"
- eslint-module-utils: "npm:^2.8.0"
- hasown: "npm:^2.0.0"
- is-core-module: "npm:^2.13.1"
+ eslint-module-utils: "npm:^2.9.0"
+ hasown: "npm:^2.0.2"
+ is-core-module: "npm:^2.15.1"
is-glob: "npm:^4.0.3"
minimatch: "npm:^3.1.2"
- object.fromentries: "npm:^2.0.7"
- object.groupby: "npm:^1.0.1"
- object.values: "npm:^1.1.7"
+ object.fromentries: "npm:^2.0.8"
+ object.groupby: "npm:^1.0.3"
+ object.values: "npm:^1.2.0"
semver: "npm:^6.3.1"
tsconfig-paths: "npm:^3.15.0"
peerDependencies:
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
- checksum: 10c0/5f35dfbf4e8e67f741f396987de9504ad125c49f4144508a93282b4ea0127e052bde65ab6def1f31b6ace6d5d430be698333f75bdd7dca3bc14226c92a083196
+ checksum: 10c0/4c9dcb1f27505c4d5dd891d2b551f56c70786d136aa3992a77e785bdc67c9f60200a2c7fb0ce55b7647fe550b12bc433d5dfa59e2c00ab44227791c5ab86badf
languageName: node
linkType: hard
@@ -7933,16 +7967,16 @@ __metadata:
languageName: node
linkType: hard
-"eslint-plugin-jsx-a11y@npm:~6.9.0":
- version: 6.9.0
- resolution: "eslint-plugin-jsx-a11y@npm:6.9.0"
+"eslint-plugin-jsx-a11y@npm:~6.10.0":
+ version: 6.10.0
+ resolution: "eslint-plugin-jsx-a11y@npm:6.10.0"
dependencies:
aria-query: "npm:~5.1.3"
array-includes: "npm:^3.1.8"
array.prototype.flatmap: "npm:^1.3.2"
ast-types-flow: "npm:^0.0.8"
- axe-core: "npm:^4.9.1"
- axobject-query: "npm:~3.1.1"
+ axe-core: "npm:^4.10.0"
+ axobject-query: "npm:^4.1.0"
damerau-levenshtein: "npm:^1.0.8"
emoji-regex: "npm:^9.2.2"
es-iterator-helpers: "npm:^1.0.19"
@@ -7954,8 +7988,8 @@ __metadata:
safe-regex-test: "npm:^1.0.3"
string.prototype.includes: "npm:^2.0.0"
peerDependencies:
- eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
- checksum: 10c0/72ac719ca90b6149c8f3c708ac5b1177f6757668b6e174d72a78512d4ac10329331b9c666c21e9561237a96a45d7f147f6a5d270dadbb99eb4ee093f127792c3
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
+ checksum: 10c0/9f8e29a3317fb6a82e2ecd333fe0fab3a69fff786d087eb65dc723d6e954473ab681d14a252d7cb2971f5e7f68816cb6f7731766558e1833a77bd73af1b5ab34
languageName: node
linkType: hard
@@ -7978,8 +8012,8 @@ __metadata:
linkType: hard
"eslint-plugin-react@npm:^7.33.2":
- version: 7.35.0
- resolution: "eslint-plugin-react@npm:7.35.0"
+ version: 7.35.2
+ resolution: "eslint-plugin-react@npm:7.35.2"
dependencies:
array-includes: "npm:^3.1.8"
array.prototype.findlast: "npm:^1.2.5"
@@ -8001,7 +8035,7 @@ __metadata:
string.prototype.repeat: "npm:^1.0.0"
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
- checksum: 10c0/eedcc33de4b2cda91d56ae517a4f771a0c76da9c1e26c95543969012871381e11d4d6cffdf6fa8423036585c289eb3500f3f93fb1d314fb2624e0aa1e463305e
+ checksum: 10c0/5f891f5a77e902a0ca8d10b23d0b800e90a09400187febe5986c5078d6277baa4b974d6acdbba25baae065dbcf12eb9241b5f5782527d0780314c2ee5006a8af
languageName: node
linkType: hard
@@ -8333,41 +8367,41 @@ __metadata:
linkType: hard
"express@npm:^4.17.1, express@npm:^4.18.2":
- version: 4.19.2
- resolution: "express@npm:4.19.2"
+ version: 4.21.0
+ resolution: "express@npm:4.21.0"
dependencies:
accepts: "npm:~1.3.8"
array-flatten: "npm:1.1.1"
- body-parser: "npm:1.20.2"
+ body-parser: "npm:1.20.3"
content-disposition: "npm:0.5.4"
content-type: "npm:~1.0.4"
cookie: "npm:0.6.0"
cookie-signature: "npm:1.0.6"
debug: "npm:2.6.9"
depd: "npm:2.0.0"
- encodeurl: "npm:~1.0.2"
+ encodeurl: "npm:~2.0.0"
escape-html: "npm:~1.0.3"
etag: "npm:~1.8.1"
- finalhandler: "npm:1.2.0"
+ finalhandler: "npm:1.3.1"
fresh: "npm:0.5.2"
http-errors: "npm:2.0.0"
- merge-descriptors: "npm:1.0.1"
+ merge-descriptors: "npm:1.0.3"
methods: "npm:~1.1.2"
on-finished: "npm:2.4.1"
parseurl: "npm:~1.3.3"
- path-to-regexp: "npm:0.1.7"
+ path-to-regexp: "npm:0.1.10"
proxy-addr: "npm:~2.0.7"
- qs: "npm:6.11.0"
+ qs: "npm:6.13.0"
range-parser: "npm:~1.2.1"
safe-buffer: "npm:5.2.1"
- send: "npm:0.18.0"
- serve-static: "npm:1.15.0"
+ send: "npm:0.19.0"
+ serve-static: "npm:1.16.2"
setprototypeof: "npm:1.2.0"
statuses: "npm:2.0.1"
type-is: "npm:~1.6.18"
utils-merge: "npm:1.0.1"
vary: "npm:~1.1.2"
- checksum: 10c0/e82e2662ea9971c1407aea9fc3c16d6b963e55e3830cd0ef5e00b533feda8b770af4e3be630488ef8a752d7c75c4fcefb15892868eeaafe7353cb9e3e269fdcb
+ checksum: 10c0/4cf7ca328f3fdeb720f30ccb2ea7708bfa7d345f9cc460b64a82bf1b2c91e5b5852ba15a9a11b2a165d6089acf83457fc477dc904d59cd71ed34c7a91762c6cc
languageName: node
linkType: hard
@@ -8420,7 +8454,7 @@ __metadata:
languageName: node
linkType: hard
-"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.1, fast-glob@npm:^3.3.2":
+"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2":
version: 3.3.2
resolution: "fast-glob@npm:3.3.2"
dependencies:
@@ -8576,18 +8610,18 @@ __metadata:
languageName: node
linkType: hard
-"finalhandler@npm:1.2.0":
- version: 1.2.0
- resolution: "finalhandler@npm:1.2.0"
+"finalhandler@npm:1.3.1":
+ version: 1.3.1
+ resolution: "finalhandler@npm:1.3.1"
dependencies:
debug: "npm:2.6.9"
- encodeurl: "npm:~1.0.2"
+ encodeurl: "npm:~2.0.0"
escape-html: "npm:~1.0.3"
on-finished: "npm:2.4.1"
parseurl: "npm:~1.3.3"
statuses: "npm:2.0.1"
unpipe: "npm:~1.0.0"
- checksum: 10c0/64b7e5ff2ad1fcb14931cd012651631b721ce657da24aedb5650ddde9378bf8e95daa451da43398123f5de161a81e79ff5affe4f9f2a6d2df4a813d6d3e254b7
+ checksum: 10c0/d38035831865a49b5610206a3a9a9aae4e8523cbbcd01175d0480ffbf1278c47f11d89be3ca7f617ae6d94f29cf797546a4619cd84dd109009ef33f12f69019f
languageName: node
linkType: hard
@@ -8956,12 +8990,12 @@ __metadata:
languageName: node
linkType: hard
-"get-tsconfig@npm:^4.5.0":
- version: 4.7.2
- resolution: "get-tsconfig@npm:4.7.2"
+"get-tsconfig@npm:^4.7.5":
+ version: 4.8.0
+ resolution: "get-tsconfig@npm:4.8.0"
dependencies:
resolve-pkg-maps: "npm:^1.0.0"
- checksum: 10c0/169b2beababfbb16e8a0ae813ee59d3e14d4960231c816615161ab5be68ec07a394dce59695742ac84295e2efab8d9e89bcf3abaf5e253dfbec3496e01bb9a65
+ checksum: 10c0/943721c996d9a77351aa7c07956de77baece97f997bd30f3247f46907e4b743f7b9da02c7b3692a36f0884d3724271faeb88ed1c3aca3aba2afe3f27d6c4aeb3
languageName: node
linkType: hard
@@ -9534,11 +9568,11 @@ __metadata:
linkType: hard
"husky@npm:^9.0.11":
- version: 9.1.4
- resolution: "husky@npm:9.1.4"
+ version: 9.1.6
+ resolution: "husky@npm:9.1.6"
bin:
husky: bin.js
- checksum: 10c0/f5185003bef9ad9ec3f40e821963e4c12409b993fdcab89e3d660bed7d8c9d8bfd399f05222e27e0ead6589601fb1bb08d1a589c51751a4ab0547ead3429b8de
+ checksum: 10c0/705673db4a247c1febd9c5df5f6a3519106cf0335845027bb50a15fba9b1f542cb2610932ede96fd08008f6d9f49db0f15560509861808b0031cdc0e7c798bac
languageName: node
linkType: hard
@@ -9933,6 +9967,15 @@ __metadata:
languageName: node
linkType: hard
+"is-bun-module@npm:^1.0.2":
+ version: 1.1.0
+ resolution: "is-bun-module@npm:1.1.0"
+ dependencies:
+ semver: "npm:^7.6.3"
+ checksum: 10c0/17cae968c3fe08e2bd66f8477e4d5a166d6299b5e7ce5c7558355551c50267f77dd386297fada6b68e4a32f01ce8920b0423e4d258242ea463b45901ec474beb
+ languageName: node
+ linkType: hard
+
"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7":
version: 1.2.7
resolution: "is-callable@npm:1.2.7"
@@ -9940,12 +9983,12 @@ __metadata:
languageName: node
linkType: hard
-"is-core-module@npm:^2.11.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1":
- version: 2.13.1
- resolution: "is-core-module@npm:2.13.1"
+"is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1":
+ version: 2.15.1
+ resolution: "is-core-module@npm:2.15.1"
dependencies:
- hasown: "npm:^2.0.0"
- checksum: 10c0/2cba9903aaa52718f11c4896dabc189bab980870aae86a62dc0d5cedb546896770ee946fb14c84b7adf0735f5eaea4277243f1b95f5cefa90054f92fbcac2518
+ hasown: "npm:^2.0.2"
+ checksum: 10c0/53432f10c69c40bfd2fa8914133a68709ff9498c86c3bf5fca3cdf3145a56fd2168cbf4a43b29843a6202a120a5f9c5ffba0a4322e1e3441739bc0b641682612
languageName: node
linkType: hard
@@ -11085,11 +11128,11 @@ __metadata:
languageName: node
linkType: hard
-"jsdom@npm:^24.0.0":
- version: 24.1.1
- resolution: "jsdom@npm:24.1.1"
+"jsdom@npm:^25.0.0":
+ version: 25.0.1
+ resolution: "jsdom@npm:25.0.1"
dependencies:
- cssstyle: "npm:^4.0.1"
+ cssstyle: "npm:^4.1.0"
data-urls: "npm:^5.0.0"
decimal.js: "npm:^10.4.3"
form-data: "npm:^4.0.0"
@@ -11102,7 +11145,7 @@ __metadata:
rrweb-cssom: "npm:^0.7.1"
saxes: "npm:^6.0.0"
symbol-tree: "npm:^3.2.4"
- tough-cookie: "npm:^4.1.4"
+ tough-cookie: "npm:^5.0.0"
w3c-xmlserializer: "npm:^5.0.0"
webidl-conversions: "npm:^7.0.0"
whatwg-encoding: "npm:^3.1.1"
@@ -11115,7 +11158,7 @@ __metadata:
peerDependenciesMeta:
canvas:
optional: true
- checksum: 10c0/02d6bfe32f09f26329c0e53ad9f9883a3c671fc1f75725167d2089ca412f5b7ca85ff8aa62327d1cc6fc70ffbb3b18dfc7642c4b2096c2c8b19aaf9a48473eb3
+ checksum: 10c0/6bda32a6dfe4e37a30568bf51136bdb3ba9c0b72aadd6356280404275a34c9e097c8c25b5eb3c742e602623741e172da977ff456684befd77c9042ed9bf8c2b4
languageName: node
linkType: hard
@@ -11360,8 +11403,8 @@ __metadata:
linkType: hard
"lint-staged@npm:^15.0.0":
- version: 15.2.9
- resolution: "lint-staged@npm:15.2.9"
+ version: 15.2.10
+ resolution: "lint-staged@npm:15.2.10"
dependencies:
chalk: "npm:~5.3.0"
commander: "npm:~12.1.0"
@@ -11369,13 +11412,13 @@ __metadata:
execa: "npm:~8.0.1"
lilconfig: "npm:~3.1.2"
listr2: "npm:~8.2.4"
- micromatch: "npm:~4.0.7"
+ micromatch: "npm:~4.0.8"
pidtree: "npm:~0.6.0"
string-argv: "npm:~0.3.2"
yaml: "npm:~2.5.0"
bin:
lint-staged: bin/lint-staged.js
- checksum: 10c0/820c622378b62b826974af17f1747e2a4b0556e4fb99d101af89ad298d392ff079f580fdc576f16a27e975d726b95d73495fd524139402ff654c4649ef2f1a6a
+ checksum: 10c0/6ad7b41f5e87a84fa2eb1990080ea3c68a2f2031b4e81edcdc2a458cc878538eedb310e6f98ffd878a1287e1a52ac968e540ee8a0e96c247e04b0cbc36421cdd
languageName: node
linkType: hard
@@ -11411,7 +11454,7 @@ __metadata:
languageName: node
linkType: hard
-"loader-utils@npm:^2.0.0":
+"loader-utils@npm:^2.0.0, loader-utils@npm:^2.0.4":
version: 2.0.4
resolution: "loader-utils@npm:2.0.4"
dependencies:
@@ -11803,10 +11846,10 @@ __metadata:
languageName: node
linkType: hard
-"merge-descriptors@npm:1.0.1":
- version: 1.0.1
- resolution: "merge-descriptors@npm:1.0.1"
- checksum: 10c0/b67d07bd44cfc45cebdec349bb6e1f7b077ee2fd5beb15d1f7af073849208cb6f144fe403e29a36571baf3f4e86469ac39acf13c318381e958e186b2766f54ec
+"merge-descriptors@npm:1.0.3":
+ version: 1.0.3
+ resolution: "merge-descriptors@npm:1.0.3"
+ checksum: 10c0/866b7094afd9293b5ea5dcd82d71f80e51514bed33b4c4e9f516795dc366612a4cbb4dc94356e943a8a6914889a914530badff27f397191b9b75cda20b6bae93
languageName: node
linkType: hard
@@ -11852,13 +11895,13 @@ __metadata:
languageName: node
linkType: hard
-"micromatch@npm:^4.0.4, micromatch@npm:^4.0.7, micromatch@npm:~4.0.7":
- version: 4.0.7
- resolution: "micromatch@npm:4.0.7"
+"micromatch@npm:^4.0.4, micromatch@npm:^4.0.8, micromatch@npm:~4.0.8":
+ version: 4.0.8
+ resolution: "micromatch@npm:4.0.8"
dependencies:
braces: "npm:^3.0.3"
picomatch: "npm:^2.3.1"
- checksum: 10c0/58fa99bc5265edec206e9163a1d2cec5fabc46a5b473c45f4a700adce88c2520456ae35f2b301e4410fb3afb27e9521fb2813f6fc96be0a48a89430e0916a772
+ checksum: 10c0/166fa6eb926b9553f32ef81f5f531d27b4ce7da60e5baf8c021d043b27a388fb95e46a8038d5045877881e673f8134122b59624d5cecbd16eb50a42e7a6b5ca8
languageName: node
linkType: hard
@@ -12496,7 +12539,7 @@ __metadata:
languageName: node
linkType: hard
-"object.fromentries@npm:^2.0.7, object.fromentries@npm:^2.0.8":
+"object.fromentries@npm:^2.0.8":
version: 2.0.8
resolution: "object.fromentries@npm:2.0.8"
dependencies:
@@ -12521,15 +12564,14 @@ __metadata:
languageName: node
linkType: hard
-"object.groupby@npm:^1.0.1":
- version: 1.0.1
- resolution: "object.groupby@npm:1.0.1"
+"object.groupby@npm:^1.0.3":
+ version: 1.0.3
+ resolution: "object.groupby@npm:1.0.3"
dependencies:
- call-bind: "npm:^1.0.2"
- define-properties: "npm:^1.2.0"
- es-abstract: "npm:^1.22.1"
- get-intrinsic: "npm:^1.2.1"
- checksum: 10c0/61e41fbf08cc04ed860363db9629eedeaa590fce243c0960e948fd7b11f78a9d4350065c339936d118a2dd8775d7259e26207340cc8ce688bec66cb615fec6fe
+ call-bind: "npm:^1.0.7"
+ define-properties: "npm:^1.2.1"
+ es-abstract: "npm:^1.23.2"
+ checksum: 10c0/60d0455c85c736fbfeda0217d1a77525956f76f7b2495edeca9e9bbf8168a45783199e77b894d30638837c654d0cc410e0e02cbfcf445bc8de71c3da1ede6a9c
languageName: node
linkType: hard
@@ -12542,7 +12584,7 @@ __metadata:
languageName: node
linkType: hard
-"object.values@npm:^1.1.0, object.values@npm:^1.1.6, object.values@npm:^1.1.7, object.values@npm:^1.2.0":
+"object.values@npm:^1.1.0, object.values@npm:^1.1.6, object.values@npm:^1.2.0":
version: 1.2.0
resolution: "object.values@npm:1.2.0"
dependencies:
@@ -12926,10 +12968,10 @@ __metadata:
languageName: node
linkType: hard
-"path-to-regexp@npm:0.1.7":
- version: 0.1.7
- resolution: "path-to-regexp@npm:0.1.7"
- checksum: 10c0/50a1ddb1af41a9e68bd67ca8e331a705899d16fb720a1ea3a41e310480948387daf603abb14d7b0826c58f10146d49050a1291ba6a82b78a382d1c02c0b8f905
+"path-to-regexp@npm:0.1.10":
+ version: 0.1.10
+ resolution: "path-to-regexp@npm:0.1.10"
+ checksum: 10c0/34196775b9113ca6df88e94c8d83ba82c0e1a2063dd33bfe2803a980da8d49b91db8104f49d5191b44ea780d46b8670ce2b7f4a5e349b0c48c6779b653f1afe4
languageName: node
linkType: hard
@@ -12983,10 +13025,10 @@ __metadata:
languageName: node
linkType: hard
-"pg-connection-string@npm:^2.6.0, pg-connection-string@npm:^2.6.4":
- version: 2.6.4
- resolution: "pg-connection-string@npm:2.6.4"
- checksum: 10c0/0d0b617df0fc6507bf6a94bdcd56c7a305788a1402d69bff9773350947c8f525d6d8136128065370749a3325e99658ae40fbdcce620fb8e60126181f0591a6a6
+"pg-connection-string@npm:^2.6.0, pg-connection-string@npm:^2.7.0":
+ version: 2.7.0
+ resolution: "pg-connection-string@npm:2.7.0"
+ checksum: 10c0/50a1496a1c858f9495d78a2c7a66d93ef3602e718aff2953bb5738f3ea616d7f727f32fc20513c9bed127650cd14c1ddc7b458396f4000e689d4b64c65c5c51e
languageName: node
linkType: hard
@@ -13004,19 +13046,19 @@ __metadata:
languageName: node
linkType: hard
-"pg-pool@npm:^3.6.2":
- version: 3.6.2
- resolution: "pg-pool@npm:3.6.2"
+"pg-pool@npm:^3.7.0":
+ version: 3.7.0
+ resolution: "pg-pool@npm:3.7.0"
peerDependencies:
pg: ">=8.0"
- checksum: 10c0/14c524549490954b5e48457a4b808df8f619f6deeb3b395b0cd184a8f4ed65a9273fe0697ba0341a41d6745af197f1437eb1cf51fff0cbbf5b0fb3852ebe5392
+ checksum: 10c0/9128673cf941f288c0cb1a74ca959a9b4f6075ef73b2cc7dece5d4db3dd7043784869e7c12bce2e69ca0df22132a419cc45c2050b4373632856fe8bae9eb94b5
languageName: node
linkType: hard
-"pg-protocol@npm:*, pg-protocol@npm:^1.6.1":
- version: 1.6.1
- resolution: "pg-protocol@npm:1.6.1"
- checksum: 10c0/7eadef4010ac0a3925c460be7332ca4098a5c6d5181725a62193fcfa800000ae6632d98d814f3989b42cf5fdc3b45e34c714a1959d29174e81e30730e140ae5f
+"pg-protocol@npm:*, pg-protocol@npm:^1.7.0":
+ version: 1.7.0
+ resolution: "pg-protocol@npm:1.7.0"
+ checksum: 10c0/c4af854d9b843c808231c0040fed89f2b9101006157df8da2bb2f62a7dde702de748d852228dc22df41cc7ffddfb526af3bcb34b278b581e9f76a060789186c1
languageName: node
linkType: hard
@@ -13049,13 +13091,13 @@ __metadata:
linkType: hard
"pg@npm:^8.5.0":
- version: 8.12.0
- resolution: "pg@npm:8.12.0"
+ version: 8.13.0
+ resolution: "pg@npm:8.13.0"
dependencies:
pg-cloudflare: "npm:^1.1.1"
- pg-connection-string: "npm:^2.6.4"
- pg-pool: "npm:^3.6.2"
- pg-protocol: "npm:^1.6.1"
+ pg-connection-string: "npm:^2.7.0"
+ pg-pool: "npm:^3.7.0"
+ pg-protocol: "npm:^1.7.0"
pg-types: "npm:^2.1.0"
pgpass: "npm:1.x"
peerDependencies:
@@ -13066,7 +13108,7 @@ __metadata:
peerDependenciesMeta:
pg-native:
optional: true
- checksum: 10c0/973e49b5e7327c42fc62806efa8c824159ab7a0b676cefe6eeb51a59b6e226587911ec27697f36c18d69e58a7f4f0b76d0829364087194d13ed431ab7c9c417a
+ checksum: 10c0/1521189063d2293d62f3fac61e797a3096a62a69668c223827d00b83c17a320805f31f0b5316feb80f8d9eed0c6c32f95146d8aca866af05816a66fd2ba8e32a
languageName: node
linkType: hard
@@ -13079,10 +13121,10 @@ __metadata:
languageName: node
linkType: hard
-"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1":
- version: 1.0.1
- resolution: "picocolors@npm:1.0.1"
- checksum: 10c0/c63cdad2bf812ef0d66c8db29583802355d4ca67b9285d846f390cc15c2f6ccb94e8cb7eb6a6e97fc5990a6d3ad4ae42d86c84d3146e667c739a4234ed50d400
+"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1, picocolors@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "picocolors@npm:1.1.0"
+ checksum: 10c0/86946f6032148801ef09c051c6fb13b5cf942eaf147e30ea79edb91dd32d700934edebe782a1078ff859fb2b816792e97ef4dab03d7f0b804f6b01a0df35e023
languageName: node
linkType: hard
@@ -13150,14 +13192,14 @@ __metadata:
linkType: hard
"pino-http@npm:^10.0.0":
- version: 10.2.0
- resolution: "pino-http@npm:10.2.0"
+ version: 10.3.0
+ resolution: "pino-http@npm:10.3.0"
dependencies:
get-caller-file: "npm:^2.0.5"
pino: "npm:^9.0.0"
pino-std-serializers: "npm:^7.0.0"
- process-warning: "npm:^3.0.0"
- checksum: 10c0/0b79cd3602531ee5043693e2a3ccf9d955bd93759e80c0b3a458b95b241f36ca8ebc72c8050b395e9d8fcb9581ebc18ecd6b7dc136526bebe924bc5c5079374d
+ process-warning: "npm:^4.0.0"
+ checksum: 10c0/da95d93e1176c02201f9b9bb0af53ad737105c5772acbb077dcad0f52ebce2438e0e9fc8216cd96396d1305d0ecf1f1d23142c7a50110a701ea093b2ee999ea7
languageName: node
linkType: hard
@@ -13193,8 +13235,8 @@ __metadata:
linkType: hard
"pino@npm:^9.0.0":
- version: 9.3.2
- resolution: "pino@npm:9.3.2"
+ version: 9.4.0
+ resolution: "pino@npm:9.4.0"
dependencies:
atomic-sleep: "npm:^1.0.0"
fast-redact: "npm:^3.1.1"
@@ -13209,7 +13251,7 @@ __metadata:
thread-stream: "npm:^3.0.0"
bin:
pino: bin.js
- checksum: 10c0/698eb2ebfcc4252da9d035fcf9c999bf27615b66ebc47f9b3d7e942750e50ebe38429e6457abcf8014d70125964ddf114e696cb8225b480d9930271708e3fb52
+ checksum: 10c0/12a3d74968964d92b18ca7d6095a3c5b86478dc22264a37486d64e102085ed08820fcbe75e640acc3542fdf2937a34e5050b624f98e6ac62dd10f5e1328058a2
languageName: node
linkType: hard
@@ -13274,15 +13316,15 @@ __metadata:
languageName: node
linkType: hard
-"postcss-calc@npm:^10.0.1":
- version: 10.0.1
- resolution: "postcss-calc@npm:10.0.1"
+"postcss-calc@npm:^10.0.2":
+ version: 10.0.2
+ resolution: "postcss-calc@npm:10.0.2"
dependencies:
- postcss-selector-parser: "npm:^6.1.1"
+ postcss-selector-parser: "npm:^6.1.2"
postcss-value-parser: "npm:^4.2.0"
peerDependencies:
postcss: ^8.4.38
- checksum: 10c0/5e38cc6f082f87e82067497b41684410784223ecd3701bf52242ea9f2f467f1fad6b5a561f8aa3be307d89435b4060f58aeb27c4064003586daf653cc4d91fef
+ checksum: 10c0/f57c9db7a7a2f3a0cdf45990089c051248d995bb2b9d1bd1fcd1634507851e92ea85bbc71a3594e359e9e9287ba0a820c90d6d292126a4b735cda364a86ce9cf
languageName: node
linkType: hard
@@ -13350,15 +13392,15 @@ __metadata:
languageName: node
linkType: hard
-"postcss-convert-values@npm:^7.0.3":
- version: 7.0.3
- resolution: "postcss-convert-values@npm:7.0.3"
+"postcss-convert-values@npm:^7.0.4":
+ version: 7.0.4
+ resolution: "postcss-convert-values@npm:7.0.4"
dependencies:
browserslist: "npm:^4.23.3"
postcss-value-parser: "npm:^4.2.0"
peerDependencies:
postcss: ^8.4.31
- checksum: 10c0/dbb6278bd8d8b11e448933d823426c883bff3f6abeaa23c7530cc4668b9da6f714e073840f280273f8a14022c3a99eb461ec732f7539e062b32f5281e1be6526
+ checksum: 10c0/9839b29f7c638672115c9fef5ed7df016aa43ea9dd42a4a2ace16e6a49c75246d2c19f3e03a6409ed3bc7c2fa4de6203bf5789cef8268c76618326b68e3bc591
languageName: node
linkType: hard
@@ -13416,14 +13458,14 @@ __metadata:
languageName: node
linkType: hard
-"postcss-discard-comments@npm:^7.0.2":
- version: 7.0.2
- resolution: "postcss-discard-comments@npm:7.0.2"
+"postcss-discard-comments@npm:^7.0.3":
+ version: 7.0.3
+ resolution: "postcss-discard-comments@npm:7.0.3"
dependencies:
- postcss-selector-parser: "npm:^6.1.1"
+ postcss-selector-parser: "npm:^6.1.2"
peerDependencies:
postcss: ^8.4.31
- checksum: 10c0/c01632e643b6ec1f61ad59efe06a9e8dfc7fcedeb1551ae48fc33fa801353f6222e31954286cd97171c694f34c2b4c7f7a2213fd0f913e37c34d0353258ed234
+ checksum: 10c0/7700c8fb9a83c6ea5cc784267b9afd6e2968fda0358d583af5913baa28dfc91b0f2a4bd0b2bd62a86ebcb8dadb2547e287beae25b5a097e21c1f723367ccf112
languageName: node
linkType: hard
@@ -13568,29 +13610,29 @@ __metadata:
languageName: node
linkType: hard
-"postcss-merge-longhand@npm:^7.0.3":
- version: 7.0.3
- resolution: "postcss-merge-longhand@npm:7.0.3"
+"postcss-merge-longhand@npm:^7.0.4":
+ version: 7.0.4
+ resolution: "postcss-merge-longhand@npm:7.0.4"
dependencies:
postcss-value-parser: "npm:^4.2.0"
- stylehacks: "npm:^7.0.3"
+ stylehacks: "npm:^7.0.4"
peerDependencies:
postcss: ^8.4.31
- checksum: 10c0/b968c3d16f3edc6075b20219a1165c089dc454a6a42951dcdfc94adb932fb96ef7bcd465c6cd21b0e5b55ac08921355ddbbbc7cdcf87a345e4bef8b3cdd2e7e9
+ checksum: 10c0/6f50f7775dd361f83daf1acb3e0001d700ed2b7b9bea02df172143adc7fa196ce9209c9e482010ce36fd704512433b62692c5ab2eef5226db71ea3e694654dc7
languageName: node
linkType: hard
-"postcss-merge-rules@npm:^7.0.3":
- version: 7.0.3
- resolution: "postcss-merge-rules@npm:7.0.3"
+"postcss-merge-rules@npm:^7.0.4":
+ version: 7.0.4
+ resolution: "postcss-merge-rules@npm:7.0.4"
dependencies:
browserslist: "npm:^4.23.3"
caniuse-api: "npm:^3.0.0"
cssnano-utils: "npm:^5.0.0"
- postcss-selector-parser: "npm:^6.1.1"
+ postcss-selector-parser: "npm:^6.1.2"
peerDependencies:
postcss: ^8.4.31
- checksum: 10c0/3cd20484ab6d15c62eded408248d5eeaba52a573935943f933865680e070a0e75b3a7447802c575bc86e1fae667cf51d9d5766537835d9b8c090337b5adf928e
+ checksum: 10c0/fffdcef4ada68e92ab8e6dc34a3b9aa2b87188cd4d08f5ba0ff2aff7e3e3c7f086830748ff64db091b5ccb9ac59ac37cfaab1268ed3efb50ab9c4f3714eb5f6d
languageName: node
linkType: hard
@@ -13631,15 +13673,15 @@ __metadata:
languageName: node
linkType: hard
-"postcss-minify-selectors@npm:^7.0.3":
- version: 7.0.3
- resolution: "postcss-minify-selectors@npm:7.0.3"
+"postcss-minify-selectors@npm:^7.0.4":
+ version: 7.0.4
+ resolution: "postcss-minify-selectors@npm:7.0.4"
dependencies:
cssesc: "npm:^3.0.0"
- postcss-selector-parser: "npm:^6.1.1"
+ postcss-selector-parser: "npm:^6.1.2"
peerDependencies:
postcss: ^8.4.31
- checksum: 10c0/5211f63a1672f646a1bab57bd8eac0816d42adacb5e286ad5e6e342a795bb0d086bd6044a1b338311ca28f33f2c1833165ee611eaa671287379821ba3c5d68ad
+ checksum: 10c0/212b8f3d62eb2a27ed57d4e76b75b0886806ddb9e2497c0bb79308fa75dabaaaa4ed2b97734896e87603272d05231fd74aee2c256a48d77aa468b5b64cc7866a
languageName: node
linkType: hard
@@ -13798,12 +13840,12 @@ __metadata:
languageName: node
linkType: hard
-"postcss-opacity-percentage@npm:^2.0.0":
- version: 2.0.0
- resolution: "postcss-opacity-percentage@npm:2.0.0"
+"postcss-opacity-percentage@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "postcss-opacity-percentage@npm:3.0.0"
peerDependencies:
- postcss: ^8.2
- checksum: 10c0/f031f3281060c4c0ede8f9a5832f65a3d8c2a1896ff324c41de42016e092635f0e0abee07545b01db93dc430a9741674a1d09c377c6c01cd8c2f4be65f889161
+ postcss: ^8.4
+ checksum: 10c0/15c7d66036fa966d265c8737196646b3f93deb83d4eea0b17ed5033460599afc31d3a989345e4d7c472963b2a2bb75c83d06979d5d30d6a60fcc7f74cb6d8d40
languageName: node
linkType: hard
@@ -13851,8 +13893,8 @@ __metadata:
linkType: hard
"postcss-preset-env@npm:^10.0.0":
- version: 10.0.2
- resolution: "postcss-preset-env@npm:10.0.2"
+ version: 10.0.3
+ resolution: "postcss-preset-env@npm:10.0.3"
dependencies:
"@csstools/postcss-cascade-layers": "npm:^5.0.0"
"@csstools/postcss-color-function": "npm:^4.0.2"
@@ -13889,7 +13931,7 @@ __metadata:
css-blank-pseudo: "npm:^7.0.0"
css-has-pseudo: "npm:^7.0.0"
css-prefers-color-scheme: "npm:^10.0.0"
- cssdb: "npm:^8.1.0"
+ cssdb: "npm:^8.1.1"
postcss-attribute-case-insensitive: "npm:^7.0.0"
postcss-clamp: "npm:^4.1.0"
postcss-color-functional-notation: "npm:^7.0.2"
@@ -13908,7 +13950,7 @@ __metadata:
postcss-lab-function: "npm:^7.0.2"
postcss-logical: "npm:^8.0.0"
postcss-nesting: "npm:^13.0.0"
- postcss-opacity-percentage: "npm:^2.0.0"
+ postcss-opacity-percentage: "npm:^3.0.0"
postcss-overflow-shorthand: "npm:^6.0.0"
postcss-page-break: "npm:^3.0.4"
postcss-place: "npm:^10.0.0"
@@ -13917,7 +13959,7 @@ __metadata:
postcss-selector-not: "npm:^8.0.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/51eb19994dfdbb041e87082833bedf8976053c182ae8dafab6b3ee1bf2cfd309ab9c186644ed032518011e44fbcc9f0552083bc431535779a80a919bbe78d10d
+ checksum: 10c0/da42caa2aab4d825fddfde00ebe2416d338c7b9a6f79a68840297888a8384f85991991c3fa10cf2d359fb230c885375f5cebd7bd63972725cd2a596d218f8b6a
languageName: node
linkType: hard
@@ -14000,7 +14042,7 @@ __metadata:
languageName: node
linkType: hard
-"postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.1.0, postcss-selector-parser@npm:^6.1.1, postcss-selector-parser@npm:^6.1.2":
+"postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.1.0, postcss-selector-parser@npm:^6.1.2":
version: 6.1.2
resolution: "postcss-selector-parser@npm:6.1.2"
dependencies:
@@ -14022,14 +14064,14 @@ __metadata:
languageName: node
linkType: hard
-"postcss-unique-selectors@npm:^7.0.2":
- version: 7.0.2
- resolution: "postcss-unique-selectors@npm:7.0.2"
+"postcss-unique-selectors@npm:^7.0.3":
+ version: 7.0.3
+ resolution: "postcss-unique-selectors@npm:7.0.3"
dependencies:
- postcss-selector-parser: "npm:^6.1.1"
+ postcss-selector-parser: "npm:^6.1.2"
peerDependencies:
postcss: ^8.4.31
- checksum: 10c0/cc54c57cd1c5a6e3e166ec63cc036d9e2df80b05e508d9ce754ca4193bf8c1bfcc16b3c6f0d81b8352a3282201d249b90bb87abacfcfb9065c9e3705ea5d110e
+ checksum: 10c0/2eb90eb0745d1e29d411ea5108f1cd9737de5b8f739cabc717074872bc4015950c9963f870b23b33b9ef45e7887eecfe5560cffee56616d4e0b8d0fac4f7cb10
languageName: node
linkType: hard
@@ -14041,13 +14083,13 @@ __metadata:
linkType: hard
"postcss@npm:^8.2.15, postcss@npm:^8.4.24, postcss@npm:^8.4.41":
- version: 8.4.41
- resolution: "postcss@npm:8.4.41"
+ version: 8.4.47
+ resolution: "postcss@npm:8.4.47"
dependencies:
nanoid: "npm:^3.3.7"
- picocolors: "npm:^1.0.1"
- source-map-js: "npm:^1.2.0"
- checksum: 10c0/c1828fc59e7ec1a3bf52b3a42f615dba53c67960ed82a81df6441b485fe43c20aba7f4e7c55425762fd99c594ecabbaaba8cf5b30fd79dfec5b52a9f63a2d690
+ picocolors: "npm:^1.1.0"
+ source-map-js: "npm:^1.2.1"
+ checksum: 10c0/929f68b5081b7202709456532cee2a145c1843d391508c5a09de2517e8c4791638f71dd63b1898dba6712f8839d7a6da046c72a5e44c162e908f5911f57b5f44
languageName: node
linkType: hard
@@ -14177,13 +14219,6 @@ __metadata:
languageName: node
linkType: hard
-"process-warning@npm:^3.0.0":
- version: 3.0.0
- resolution: "process-warning@npm:3.0.0"
- checksum: 10c0/60f3c8ddee586f0706c1e6cb5aa9c86df05774b9330d792d7c8851cf0031afd759d665404d07037e0b4901b55c44a423f07bdc465c63de07d8d23196bb403622
- languageName: node
- linkType: hard
-
"process-warning@npm:^4.0.0":
version: 4.0.0
resolution: "process-warning@npm:4.0.0"
@@ -14329,21 +14364,12 @@ __metadata:
languageName: node
linkType: hard
-"qs@npm:6.11.0":
- version: 6.11.0
- resolution: "qs@npm:6.11.0"
+"qs@npm:6.13.0, qs@npm:^6.11.0":
+ version: 6.13.0
+ resolution: "qs@npm:6.13.0"
dependencies:
- side-channel: "npm:^1.0.4"
- checksum: 10c0/4e4875e4d7c7c31c233d07a448e7e4650f456178b9dd3766b7cfa13158fdb24ecb8c4f059fa91e820dc6ab9f2d243721d071c9c0378892dcdad86e9e9a27c68f
- languageName: node
- linkType: hard
-
-"qs@npm:^6.11.0":
- version: 6.11.2
- resolution: "qs@npm:6.11.2"
- dependencies:
- side-channel: "npm:^1.0.4"
- checksum: 10c0/4f95d4ff18ed480befcafa3390022817ffd3087fc65f146cceb40fc5edb9fa96cb31f648cae2fa96ca23818f0798bd63ad4ca369a0e22702fcd41379b3ab6571
+ side-channel: "npm:^1.0.6"
+ checksum: 10c0/62372cdeec24dc83a9fb240b7533c0fdcf0c5f7e0b83343edd7310f0ab4c8205a5e7c56406531f2e47e1b4878a3821d652be4192c841de5b032ca83619d8f860
languageName: node
linkType: hard
@@ -14507,12 +14533,12 @@ __metadata:
linkType: hard
"react-intl@npm:^6.4.2":
- version: 6.6.8
- resolution: "react-intl@npm:6.6.8"
+ version: 6.7.0
+ resolution: "react-intl@npm:6.7.0"
dependencies:
"@formatjs/ecma402-abstract": "npm:2.0.0"
"@formatjs/icu-messageformat-parser": "npm:2.7.8"
- "@formatjs/intl": "npm:2.10.4"
+ "@formatjs/intl": "npm:2.10.5"
"@formatjs/intl-displaynames": "npm:6.6.8"
"@formatjs/intl-listformat": "npm:7.5.7"
"@types/hoist-non-react-statics": "npm:^3.3.1"
@@ -14526,7 +14552,7 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10c0/7673507eb73ad4edd1593da7173cec68f316cf77037e0959900babd32d5984a39ba7fa10aaa0a23bcddb7b98daf7dd007cb73ddfc39127ede87c18ec780a519c
+ checksum: 10c0/210088bf0e934ad5f09d8e7c6d7d72682bb806583645fb333d4efd8ae55585b675ea8e47bb240140d5143ca15ecc0457c3ddc3e8ca45e9b576bce1fa2f9886b3
languageName: node
linkType: hard
@@ -14687,8 +14713,8 @@ __metadata:
linkType: hard
"react-select@npm:^5.7.3":
- version: 5.8.0
- resolution: "react-select@npm:5.8.0"
+ version: 5.8.1
+ resolution: "react-select@npm:5.8.1"
dependencies:
"@babel/runtime": "npm:^7.12.0"
"@emotion/cache": "npm:^11.4.0"
@@ -14702,7 +14728,7 @@ __metadata:
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
- checksum: 10c0/b4b98aaf117ee5cc4642871b7bd51fd0e2697988d0b880f30b21e933ca90258959147117d8aada36713b622e0e4cb06bd18ec02069f3f108896e0d31e69e3c16
+ checksum: 10c0/0fd73e1e472105f980e09c86f0e6adbdc9f2f5c1befa275b08c71653becdd1829f596155a81b5085cb86f18b20bf4f4cc439ab5fe23e68f326e169dcfe00ccf6
languageName: node
linkType: hard
@@ -14891,6 +14917,13 @@ __metadata:
languageName: node
linkType: hard
+"readdirp@npm:^4.0.1":
+ version: 4.0.1
+ resolution: "readdirp@npm:4.0.1"
+ checksum: 10c0/e5a0b547015f68ecc918f115b62b75b2b840611480a9240cb3317090a0ddac01bb9b40315a8fa08acdf52a43eea17b808c89b645263cba3ab64dc557d7f801f1
+ languageName: node
+ linkType: hard
+
"readdirp@npm:~3.6.0":
version: 3.6.0
resolution: "readdirp@npm:3.6.0"
@@ -15357,13 +15390,6 @@ __metadata:
languageName: node
linkType: hard
-"rrweb-cssom@npm:^0.6.0":
- version: 0.6.0
- resolution: "rrweb-cssom@npm:0.6.0"
- checksum: 10c0/3d9d90d53c2349ea9c8509c2690df5a4ef930c9cf8242aeb9425d4046f09d712bb01047e00da0e1c1dab5db35740b3d78fd45c3e7272f75d3724a563f27c30a3
- languageName: node
- linkType: hard
-
"rrweb-cssom@npm:^0.7.1":
version: 0.7.1
resolution: "rrweb-cssom@npm:0.7.1"
@@ -15466,15 +15492,15 @@ __metadata:
linkType: hard
"sass@npm:^1.62.1":
- version: 1.77.8
- resolution: "sass@npm:1.77.8"
+ version: 1.79.3
+ resolution: "sass@npm:1.79.3"
dependencies:
- chokidar: "npm:>=3.0.0 <4.0.0"
+ chokidar: "npm:^4.0.0"
immutable: "npm:^4.0.0"
source-map-js: "npm:>=0.6.2 <2.0.0"
bin:
sass: sass.js
- checksum: 10c0/2bfd62794070352c804f949e69bd8bb5b4ec846deeb924251b2c3f7b503170fb1ae186f513f0166907749eb34e0277dee747edcb78c886fb471aac01be1e864c
+ checksum: 10c0/ad171bbbb2d7a789cc47803a59dcf2d0ac92ede34b538bb3fd683b6391a9ac3dc3eabaac264fc9582c770c4e435b85840e011785b7adfc0ac002b51ba91179c9
languageName: node
linkType: hard
@@ -15596,9 +15622,9 @@ __metadata:
languageName: node
linkType: hard
-"send@npm:0.18.0":
- version: 0.18.0
- resolution: "send@npm:0.18.0"
+"send@npm:0.19.0":
+ version: 0.19.0
+ resolution: "send@npm:0.19.0"
dependencies:
debug: "npm:2.6.9"
depd: "npm:2.0.0"
@@ -15613,7 +15639,7 @@ __metadata:
on-finished: "npm:2.4.1"
range-parser: "npm:~1.2.1"
statuses: "npm:2.0.1"
- checksum: 10c0/0eb134d6a51fc13bbcb976a1f4214ea1e33f242fae046efc311e80aff66c7a43603e26a79d9d06670283a13000e51be6e0a2cb80ff0942eaf9f1cd30b7ae736a
+ checksum: 10c0/ea3f8a67a8f0be3d6bf9080f0baed6d2c51d11d4f7b4470de96a5029c598a7011c497511ccc28968b70ef05508675cebff27da9151dd2ceadd60be4e6cf845e3
languageName: node
linkType: hard
@@ -15650,15 +15676,15 @@ __metadata:
languageName: node
linkType: hard
-"serve-static@npm:1.15.0":
- version: 1.15.0
- resolution: "serve-static@npm:1.15.0"
+"serve-static@npm:1.16.2":
+ version: 1.16.2
+ resolution: "serve-static@npm:1.16.2"
dependencies:
- encodeurl: "npm:~1.0.2"
+ encodeurl: "npm:~2.0.0"
escape-html: "npm:~1.0.3"
parseurl: "npm:~1.3.3"
- send: "npm:0.18.0"
- checksum: 10c0/fa9f0e21a540a28f301258dfe1e57bb4f81cd460d28f0e973860477dd4acef946a1f41748b5bd41c73b621bea2029569c935faa38578fd34cd42a9b4947088ba
+ send: "npm:0.19.0"
+ checksum: 10c0/528fff6f5e12d0c5a391229ad893910709bc51b5705962b09404a1d813857578149b8815f35d3ee5752f44cd378d0f31669d4b1d7e2d11f41e08283d5134bd1f
languageName: node
linkType: hard
@@ -15988,10 +16014,10 @@ __metadata:
languageName: node
linkType: hard
-"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.1, source-map-js@npm:^1.2.0":
- version: 1.2.0
- resolution: "source-map-js@npm:1.2.0"
- checksum: 10c0/7e5f896ac10a3a50fe2898e5009c58ff0dc102dcb056ed27a354623a0ece8954d4b2649e1a1b2b52ef2e161d26f8859c7710350930751640e71e374fe2d321a4
+"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.1, source-map-js@npm:^1.2.1":
+ version: 1.2.1
+ resolution: "source-map-js@npm:1.2.1"
+ checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf
languageName: node
linkType: hard
@@ -16554,15 +16580,15 @@ __metadata:
languageName: node
linkType: hard
-"stylehacks@npm:^7.0.3":
- version: 7.0.3
- resolution: "stylehacks@npm:7.0.3"
+"stylehacks@npm:^7.0.4":
+ version: 7.0.4
+ resolution: "stylehacks@npm:7.0.4"
dependencies:
browserslist: "npm:^4.23.3"
- postcss-selector-parser: "npm:^6.1.1"
+ postcss-selector-parser: "npm:^6.1.2"
peerDependencies:
postcss: ^8.4.31
- checksum: 10c0/5030334b06ef705b5700444dab120b540b09159e935e75b60f25bd56db1d85f0d11755f0b0f64ce3f12c5a72ff1b6f57fea49c26d18eb0de2334d6a143b94f8d
+ checksum: 10c0/b4d0b280ba274503ecc04111cc11c713e0d65db079fbcd8b42d6350be1cca20e28611eddee93b419aa208176a0d3a5fff83d83ef958d1876713809b6a2787c0c
languageName: node
linkType: hard
@@ -16647,12 +16673,12 @@ __metadata:
linkType: hard
"stylelint@npm:^16.0.2":
- version: 16.8.2
- resolution: "stylelint@npm:16.8.2"
+ version: 16.9.0
+ resolution: "stylelint@npm:16.9.0"
dependencies:
- "@csstools/css-parser-algorithms": "npm:^3.0.0"
- "@csstools/css-tokenizer": "npm:^3.0.0"
- "@csstools/media-query-list-parser": "npm:^3.0.0"
+ "@csstools/css-parser-algorithms": "npm:^3.0.1"
+ "@csstools/css-tokenizer": "npm:^3.0.1"
+ "@csstools/media-query-list-parser": "npm:^3.0.1"
"@csstools/selector-specificity": "npm:^4.0.0"
"@dual-bundle/import-meta-resolve": "npm:^4.1.0"
balanced-match: "npm:^2.0.0"
@@ -16674,7 +16700,7 @@ __metadata:
known-css-properties: "npm:^0.34.0"
mathml-tag-names: "npm:^2.1.3"
meow: "npm:^13.2.0"
- micromatch: "npm:^4.0.7"
+ micromatch: "npm:^4.0.8"
normalize-path: "npm:^3.0.0"
picocolors: "npm:^1.0.1"
postcss: "npm:^8.4.41"
@@ -16685,13 +16711,13 @@ __metadata:
resolve-from: "npm:^5.0.0"
string-width: "npm:^4.2.3"
strip-ansi: "npm:^7.1.0"
- supports-hyperlinks: "npm:^3.0.0"
+ supports-hyperlinks: "npm:^3.1.0"
svg-tags: "npm:^1.0.0"
table: "npm:^6.8.2"
write-file-atomic: "npm:^5.0.1"
bin:
stylelint: bin/stylelint.mjs
- checksum: 10c0/898cde9b5d981f249133df709458eebf2af0a525e72410ddfafd76a7308f7da493578b6a909c593cc70061556b9eda1fed4f477385ee615435f0996d9e18d8df
+ checksum: 10c0/d3ff9c8945c56b04a2fa16ec33d163325496d5db94b6fcb5adf74c76f7f794ac992888273f9a3317652ba8b6195168b2ffff382ca2a667a241e2ace8c9505ae2
languageName: node
linkType: hard
@@ -16745,13 +16771,13 @@ __metadata:
languageName: node
linkType: hard
-"supports-hyperlinks@npm:^3.0.0":
- version: 3.0.0
- resolution: "supports-hyperlinks@npm:3.0.0"
+"supports-hyperlinks@npm:^3.1.0":
+ version: 3.1.0
+ resolution: "supports-hyperlinks@npm:3.1.0"
dependencies:
has-flag: "npm:^4.0.0"
supports-color: "npm:^7.0.0"
- checksum: 10c0/36aaa55e67645dded8e0f846fd81d7dd05ce82ea81e62347f58d86213577eb627b2b45298656ce7a70e7155e39f071d0d3f83be91e112aed801ebaa8db1ef1d0
+ checksum: 10c0/78cc3e17eb27e6846fa355a8ebf343befe36272899cd409e45317a06c1997e95c23ff99d91080a517bd8c96508d4fa456e6ceb338c02ba5d7544277dbec0f10f
languageName: node
linkType: hard
@@ -17027,6 +17053,24 @@ __metadata:
languageName: node
linkType: hard
+"tldts-core@npm:^6.1.47":
+ version: 6.1.47
+ resolution: "tldts-core@npm:6.1.47"
+ checksum: 10c0/538372072aea7153e842646a9e22d0d9335acf7fd877d10ee374cf78dceff79a2ccebadf7d25e0dbddd7b7b60bafe1c885aac3e3b1d5bec7806963c89b163ee7
+ languageName: node
+ linkType: hard
+
+"tldts@npm:^6.1.32":
+ version: 6.1.47
+ resolution: "tldts@npm:6.1.47"
+ dependencies:
+ tldts-core: "npm:^6.1.47"
+ bin:
+ tldts: bin/cli.js
+ checksum: 10c0/42c999ab24ce3ab221cfefe77488d145d16d9523524913badaa4af4f1f0d65e0a92a678659b22b7d26d1c62796540c95158049220c9ff243090b93470f236302
+ languageName: node
+ linkType: hard
+
"tmpl@npm:1.0.5":
version: 1.0.5
resolution: "tmpl@npm:1.0.5"
@@ -17102,7 +17146,7 @@ __metadata:
languageName: node
linkType: hard
-"tough-cookie@npm:^4.1.2, tough-cookie@npm:^4.1.4":
+"tough-cookie@npm:^4.1.2":
version: 4.1.4
resolution: "tough-cookie@npm:4.1.4"
dependencies:
@@ -17114,6 +17158,15 @@ __metadata:
languageName: node
linkType: hard
+"tough-cookie@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "tough-cookie@npm:5.0.0"
+ dependencies:
+ tldts: "npm:^6.1.32"
+ checksum: 10c0/4a69c885bf6f45c5a64e60262af99e8c0d58a33bd3d0ce5da62121eeb9c00996d0128a72df8fc4614cbde59cc8b70aa3e21e4c3c98c2bbde137d7aba7fa00124
+ languageName: node
+ linkType: hard
+
"tr46@npm:^1.0.1":
version: 1.0.1
resolution: "tr46@npm:1.0.1"