+
= ({
const topHashtag = report.data.top_hashtags[0];
return (
-
+
Wrapstodon {report.year}
{account &&
@{account.acct}
}
diff --git a/app/javascript/mastodon/features/annual_report/modal.tsx b/app/javascript/mastodon/features/annual_report/modal.tsx
index 01d7c4bbdbf..d591954bbf3 100644
--- a/app/javascript/mastodon/features/annual_report/modal.tsx
+++ b/app/javascript/mastodon/features/annual_report/modal.tsx
@@ -60,11 +60,8 @@ const AnnualReportModal: React.FC<{
// default modal backdrop, preventing clicks to pass through.
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
{!showAnnouncement ? (
diff --git a/app/javascript/mastodon/features/collections/editor.tsx b/app/javascript/mastodon/features/collections/editor.tsx
new file mode 100644
index 00000000000..138e7764e50
--- /dev/null
+++ b/app/javascript/mastodon/features/collections/editor.tsx
@@ -0,0 +1,272 @@
+import { useCallback, useState, useEffect } from 'react';
+
+import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
+
+import { Helmet } from 'react-helmet';
+import { useParams, useHistory } from 'react-router-dom';
+
+import { isFulfilled } from '@reduxjs/toolkit';
+
+import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
+import type {
+ ApiCollectionJSON,
+ ApiCreateCollectionPayload,
+ ApiUpdateCollectionPayload,
+} from 'mastodon/api_types/collections';
+import { Button } from 'mastodon/components/button';
+import { Column } from 'mastodon/components/column';
+import { ColumnHeader } from 'mastodon/components/column_header';
+import { TextAreaField, ToggleField } from 'mastodon/components/form_fields';
+import { TextInputField } from 'mastodon/components/form_fields/text_input_field';
+import { LoadingIndicator } from 'mastodon/components/loading_indicator';
+import {
+ createCollection,
+ fetchCollection,
+ updateCollection,
+} from 'mastodon/reducers/slices/collections';
+import { useAppDispatch, useAppSelector } from 'mastodon/store';
+
+const messages = defineMessages({
+ edit: { id: 'column.edit_collection', defaultMessage: 'Edit collection' },
+ create: {
+ id: 'column.create_collection',
+ defaultMessage: 'Create collection',
+ },
+});
+
+const CollectionSettings: React.FC<{
+ collection?: ApiCollectionJSON | null;
+}> = ({ collection }) => {
+ const dispatch = useAppDispatch();
+ const history = useHistory();
+
+ const {
+ id,
+ name: initialName = '',
+ description: initialDescription = '',
+ tag,
+ discoverable: initialDiscoverable = true,
+ sensitive: initialSensitive = false,
+ } = collection ?? {};
+
+ const [name, setName] = useState(initialName);
+ const [description, setDescription] = useState(initialDescription);
+ const [topic, setTopic] = useState(tag?.name ?? '');
+ const [discoverable] = useState(initialDiscoverable);
+ const [sensitive, setSensitive] = useState(initialSensitive);
+
+ const handleNameChange = useCallback(
+ (event: React.ChangeEvent
) => {
+ setName(event.target.value);
+ },
+ [],
+ );
+
+ const handleDescriptionChange = useCallback(
+ (event: React.ChangeEvent) => {
+ setDescription(event.target.value);
+ },
+ [],
+ );
+
+ const handleTopicChange = useCallback(
+ (event: React.ChangeEvent) => {
+ setTopic(event.target.value);
+ },
+ [],
+ );
+
+ const handleSensitiveChange = useCallback(
+ (event: React.ChangeEvent) => {
+ setSensitive(event.target.checked);
+ },
+ [],
+ );
+
+ const handleSubmit = useCallback(
+ (e: React.FormEvent) => {
+ e.preventDefault();
+
+ if (id) {
+ const payload: ApiUpdateCollectionPayload = {
+ id,
+ name,
+ description,
+ tag_name: topic,
+ discoverable,
+ sensitive,
+ };
+
+ void dispatch(updateCollection({ payload })).then(() => {
+ history.push(`/collections`);
+ });
+ } else {
+ const payload: ApiCreateCollectionPayload = {
+ name,
+ description,
+ discoverable,
+ sensitive,
+ };
+ if (topic) {
+ payload.tag_name = topic;
+ }
+
+ void dispatch(
+ createCollection({
+ payload,
+ }),
+ ).then((result) => {
+ if (isFulfilled(result)) {
+ history.replace(
+ `/collections/${result.payload.collection.id}/edit`,
+ );
+ history.push(`/collections`);
+ }
+ });
+ }
+ },
+ [id, dispatch, name, description, topic, discoverable, sensitive, history],
+ );
+
+ return (
+
+ );
+};
+
+export const CollectionEditorPage: React.FC<{
+ multiColumn?: boolean;
+}> = ({ multiColumn }) => {
+ const intl = useIntl();
+ const dispatch = useAppDispatch();
+ const { id } = useParams<{ id?: string }>();
+ const collection = useAppSelector((state) =>
+ id ? state.collections.collections[id] : undefined,
+ );
+ const isEditMode = !!id;
+ const isLoading = isEditMode && !collection;
+
+ useEffect(() => {
+ if (id) {
+ void dispatch(fetchCollection({ collectionId: id }));
+ }
+ }, [dispatch, id]);
+
+ const pageTitle = intl.formatMessage(id ? messages.edit : messages.create);
+
+ return (
+
+
+
+
+ {isLoading ? (
+
+ ) : (
+
+ )}
+
+
+
+ {pageTitle}
+
+
+
+ );
+};
diff --git a/app/javascript/mastodon/features/collections/index.tsx b/app/javascript/mastodon/features/collections/index.tsx
new file mode 100644
index 00000000000..bd1c4f790bb
--- /dev/null
+++ b/app/javascript/mastodon/features/collections/index.tsx
@@ -0,0 +1,160 @@
+import { useEffect, useMemo, useCallback } from 'react';
+
+import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
+
+import { Helmet } from 'react-helmet';
+import { Link } from 'react-router-dom';
+
+import AddIcon from '@/material-icons/400-24px/add.svg?react';
+import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
+import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
+import SquigglyArrow from '@/svg-icons/squiggly_arrow.svg?react';
+import { openModal } from 'mastodon/actions/modal';
+import { Column } from 'mastodon/components/column';
+import { ColumnHeader } from 'mastodon/components/column_header';
+import { Dropdown } from 'mastodon/components/dropdown_menu';
+import { Icon } from 'mastodon/components/icon';
+import ScrollableList from 'mastodon/components/scrollable_list';
+import {
+ fetchAccountCollections,
+ selectMyCollections,
+} from 'mastodon/reducers/slices/collections';
+import { useAppSelector, useAppDispatch } from 'mastodon/store';
+
+const messages = defineMessages({
+ heading: { id: 'column.collections', defaultMessage: 'My collections' },
+ create: {
+ id: 'collections.create_collection',
+ defaultMessage: 'Create collection',
+ },
+ view: {
+ id: 'collections.view_collection',
+ defaultMessage: 'View collection',
+ },
+ delete: {
+ id: 'collections.delete_collection',
+ defaultMessage: 'Delete collection',
+ },
+ more: { id: 'status.more', defaultMessage: 'More' },
+});
+
+const ListItem: React.FC<{
+ id: string;
+ name: string;
+}> = ({ id, name }) => {
+ const dispatch = useAppDispatch();
+ const intl = useIntl();
+
+ const handleDeleteClick = useCallback(() => {
+ dispatch(
+ openModal({
+ modalType: 'CONFIRM_DELETE_COLLECTION',
+ modalProps: {
+ name,
+ id,
+ },
+ }),
+ );
+ }, [dispatch, id, name]);
+
+ const menu = useMemo(
+ () => [
+ { text: intl.formatMessage(messages.view), to: `/collections/${id}` },
+ { text: intl.formatMessage(messages.delete), action: handleDeleteClick },
+ ],
+ [intl, id, handleDeleteClick],
+ );
+
+ return (
+
+
+ {name}
+
+
+
+
+ );
+};
+
+export const Collections: React.FC<{
+ multiColumn?: boolean;
+}> = ({ multiColumn }) => {
+ const dispatch = useAppDispatch();
+ const intl = useIntl();
+ const me = useAppSelector((state) => state.meta.get('me') as string);
+ const { collections, status } = useAppSelector(selectMyCollections);
+
+ useEffect(() => {
+ void dispatch(fetchAccountCollections({ accountId: me }));
+ }, [dispatch, me]);
+
+ const emptyMessage =
+ status === 'error' ? (
+
+ ) : (
+ <>
+
+
+
+
+
+
+
+ >
+ );
+
+ return (
+
+
+
+
+ }
+ />
+
+
+ {collections.map((item) => (
+
+ ))}
+
+
+
+ {intl.formatMessage(messages.heading)}
+
+
+
+ );
+};
diff --git a/app/javascript/mastodon/features/collections/utils.ts b/app/javascript/mastodon/features/collections/utils.ts
new file mode 100644
index 00000000000..616d0297a74
--- /dev/null
+++ b/app/javascript/mastodon/features/collections/utils.ts
@@ -0,0 +1,11 @@
+import {
+ isClientFeatureEnabled,
+ isServerFeatureEnabled,
+} from '@/mastodon/utils/environment';
+
+export function areCollectionsEnabled() {
+ return (
+ isClientFeatureEnabled('collections') &&
+ isServerFeatureEnabled('collections')
+ );
+}
diff --git a/app/javascript/mastodon/features/compose/components/upload.tsx b/app/javascript/mastodon/features/compose/components/upload.tsx
index 85fed0cbd3b..4190f3248e3 100644
--- a/app/javascript/mastodon/features/compose/components/upload.tsx
+++ b/app/javascript/mastodon/features/compose/components/upload.tsx
@@ -10,8 +10,8 @@ import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import CloseIcon from '@/material-icons/400-20px/close.svg?react';
-import SoundIcon from '@/material-icons/400-24px/audio.svg?react';
import EditIcon from '@/material-icons/400-24px/edit.svg?react';
+import SoundIcon from '@/material-icons/400-24px/graphic_eq.svg?react';
import WarningIcon from '@/material-icons/400-24px/warning.svg?react';
import { undoUploadCompose } from 'mastodon/actions/compose';
import { openModal } from 'mastodon/actions/modal';
diff --git a/app/javascript/mastodon/features/directory/index.tsx b/app/javascript/mastodon/features/directory/index.tsx
index 0fe140b4eb4..54317a6c76d 100644
--- a/app/javascript/mastodon/features/directory/index.tsx
+++ b/app/javascript/mastodon/features/directory/index.tsx
@@ -83,6 +83,9 @@ export const Directory: React.FC<{
(state) =>
state.user_lists.getIn(['directory', 'isLoading'], true) as boolean,
);
+ const hasMore = useAppSelector(
+ (state) => !!state.user_lists.getIn(['directory', 'next']),
+ );
useEffect(() => {
void dispatch(fetchDirectory({ order, local }));
@@ -182,7 +185,7 @@ export const Directory: React.FC<{
diff --git a/app/javascript/mastodon/features/emoji/__tests__/emoji-test.js b/app/javascript/mastodon/features/emoji/__tests__/emoji-test.js
index 35804de82ae..5d0683dace8 100644
--- a/app/javascript/mastodon/features/emoji/__tests__/emoji-test.js
+++ b/app/javascript/mastodon/features/emoji/__tests__/emoji-test.js
@@ -86,7 +86,7 @@ describe('emoji', () => {
it('does an emoji containing ZWJ properly', () => {
expect(emojify('💂♀️💂♂️'))
- .toEqual('


');
+ .toEqual('


');
});
it('keeps ordering as expected (issue fixed by PR 20677)', () => {
diff --git a/app/javascript/mastodon/features/emoji/emoji.js b/app/javascript/mastodon/features/emoji/emoji.js
index f8fa0ae1923..859665a5312 100644
--- a/app/javascript/mastodon/features/emoji/emoji.js
+++ b/app/javascript/mastodon/features/emoji/emoji.js
@@ -1,6 +1,6 @@
import Trie from 'substring-trie';
-import { getUserTheme, isDarkMode } from '@/mastodon/utils/theme';
+import { getIsSystemTheme, isDarkMode } from '@/mastodon/utils/theme';
import { assetHost } from 'mastodon/utils/config';
import { autoPlayGif } from '../../initial_state';
@@ -98,7 +98,7 @@ const emojifyTextNode = (node, customEmojis) => {
const { filename, shortCode } = unicodeMapping[unicode_emoji];
const title = shortCode ? `:${shortCode}:` : '';
- const isSystemTheme = getUserTheme() === 'system';
+ const isSystemTheme = getIsSystemTheme();
const theme = (isSystemTheme || !isDarkMode()) ? 'light' : 'dark';
diff --git a/app/javascript/mastodon/features/lists/new.tsx b/app/javascript/mastodon/features/lists/new.tsx
index d89f27478fd..53084fb5689 100644
--- a/app/javascript/mastodon/features/lists/new.tsx
+++ b/app/javascript/mastodon/features/lists/new.tsx
@@ -20,6 +20,7 @@ import { Avatar } from 'mastodon/components/avatar';
import { AvatarGroup } from 'mastodon/components/avatar_group';
import { Column } from 'mastodon/components/column';
import { ColumnHeader } from 'mastodon/components/column_header';
+import { SelectField, TextInputField } from 'mastodon/components/form_fields';
import { Icon } from 'mastodon/components/icon';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import type { List } from 'mastodon/models/list';
@@ -149,68 +150,49 @@ const NewList: React.FC<{ list?: List | null }> = ({ list }) => {
return (
-
-
-
+ }
+ hint={
-
-
-
-
-
+ }
+ value={displayName}
+ onChange={handleDisplayNameChange}
+ hasError={!!errors?.display_name}
+ id='display_name'
+ />
-
-
-
+ }
+ hint={
-
-
-
-
-
+ }
+ value={note}
+ onChange={handleNoteChange}
+ hasError={!!errors?.note}
+ id='note'
+ />
diff --git a/app/javascript/mastodon/features/ui/components/confirmation_modals/delete_collection.tsx b/app/javascript/mastodon/features/ui/components/confirmation_modals/delete_collection.tsx
new file mode 100644
index 00000000000..4bc2374603d
--- /dev/null
+++ b/app/javascript/mastodon/features/ui/components/confirmation_modals/delete_collection.tsx
@@ -0,0 +1,54 @@
+import { useCallback } from 'react';
+
+import { defineMessages, useIntl } from 'react-intl';
+
+import { useHistory } from 'react-router';
+
+import { deleteCollection } from 'mastodon/reducers/slices/collections';
+import { useAppDispatch } from 'mastodon/store';
+
+import type { BaseConfirmationModalProps } from './confirmation_modal';
+import { ConfirmationModal } from './confirmation_modal';
+
+const messages = defineMessages({
+ deleteListTitle: {
+ id: 'confirmations.delete_collection.title',
+ defaultMessage: 'Delete "{name}"?',
+ },
+ deleteListMessage: {
+ id: 'confirmations.delete_collection.message',
+ defaultMessage: 'This action cannot be undone.',
+ },
+ deleteListConfirm: {
+ id: 'confirmations.delete_collection.confirm',
+ defaultMessage: 'Delete',
+ },
+});
+
+export const ConfirmDeleteCollectionModal: React.FC<
+ {
+ id: string;
+ name: string;
+ } & BaseConfirmationModalProps
+> = ({ id, name, onClose }) => {
+ const intl = useIntl();
+ const dispatch = useAppDispatch();
+ const history = useHistory();
+
+ const onConfirm = useCallback(() => {
+ void dispatch(deleteCollection({ collectionId: id }));
+ history.push('/collections');
+ }, [dispatch, history, id]);
+
+ return (
+
+ );
+};
diff --git a/app/javascript/mastodon/features/ui/components/confirmation_modals/index.ts b/app/javascript/mastodon/features/ui/components/confirmation_modals/index.ts
index 9aff30eeac1..389ad7ea835 100644
--- a/app/javascript/mastodon/features/ui/components/confirmation_modals/index.ts
+++ b/app/javascript/mastodon/features/ui/components/confirmation_modals/index.ts
@@ -1,6 +1,7 @@
export { ConfirmationModal } from './confirmation_modal';
export { ConfirmDeleteStatusModal } from './delete_status';
export { ConfirmDeleteListModal } from './delete_list';
+export { ConfirmDeleteCollectionModal } from './delete_collection';
export {
ConfirmReplyModal,
ConfirmEditStatusModal,
diff --git a/app/javascript/mastodon/features/ui/components/modal_root.jsx b/app/javascript/mastodon/features/ui/components/modal_root.jsx
index 6f9b23042d7..30d7578c55c 100644
--- a/app/javascript/mastodon/features/ui/components/modal_root.jsx
+++ b/app/javascript/mastodon/features/ui/components/modal_root.jsx
@@ -29,6 +29,7 @@ import {
ConfirmationModal,
ConfirmDeleteStatusModal,
ConfirmDeleteListModal,
+ ConfirmDeleteCollectionModal,
ConfirmReplyModal,
ConfirmEditStatusModal,
ConfirmUnblockModal,
@@ -57,6 +58,7 @@ export const MODAL_COMPONENTS = {
'CONFIRM': () => Promise.resolve({ default: ConfirmationModal }),
'CONFIRM_DELETE_STATUS': () => Promise.resolve({ default: ConfirmDeleteStatusModal }),
'CONFIRM_DELETE_LIST': () => Promise.resolve({ default: ConfirmDeleteListModal }),
+ 'CONFIRM_DELETE_COLLECTION': () => Promise.resolve({ default: ConfirmDeleteCollectionModal }),
'CONFIRM_REPLY': () => Promise.resolve({ default: ConfirmReplyModal }),
'CONFIRM_EDIT_STATUS': () => Promise.resolve({ default: ConfirmEditStatusModal }),
'CONFIRM_UNBLOCK': () => Promise.resolve({ default: ConfirmUnblockModal }),
@@ -85,6 +87,8 @@ export const MODAL_COMPONENTS = {
'IGNORE_NOTIFICATIONS': IgnoreNotificationsModal,
'ANNUAL_REPORT': AnnualReportModal,
'COMPOSE_PRIVACY': () => Promise.resolve({ default: VisibilityModal }),
+ 'ACCOUNT_NOTE': () => import('@/mastodon/features/account_timeline/modals/note_modal').then(module => ({ default: module.AccountNoteModal })),
+ 'ACCOUNT_FIELDS': () => import('mastodon/features/account_timeline/components/fields_modal.tsx').then(module => ({ default: module.AccountFieldsModal })),
};
export default class ModalRoot extends PureComponent {
diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx
index 61317fff5b2..5ba78f599a8 100644
--- a/app/javascript/mastodon/features/ui/index.jsx
+++ b/app/javascript/mastodon/features/ui/index.jsx
@@ -63,6 +63,8 @@ import {
Lists,
ListEdit,
ListMembers,
+ Collections,
+ CollectionsEditor,
Blocks,
DomainBlocks,
Mutes,
@@ -85,6 +87,7 @@ import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers';
// Dummy import, to make sure that
ends up in the application bundle.
// Without this it ends up in ~8 very commonly used bundles.
import '../../components/status';
+import { areCollectionsEnabled } from '../collections/utils';
const messages = defineMessages({
beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave Mastodon.' },
@@ -227,6 +230,15 @@ class SwitchingColumnsArea extends PureComponent {
+ {areCollectionsEnabled() &&
+
+ }
+ {areCollectionsEnabled() &&
+
+ }
+ {areCollectionsEnabled() &&
+
+ }
diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js
index a2a5fd8c1bf..7500575d7a8 100644
--- a/app/javascript/mastodon/features/ui/util/async-components.js
+++ b/app/javascript/mastodon/features/ui/util/async-components.js
@@ -1,3 +1,5 @@
+import { isClientFeatureEnabled } from '@/mastodon/utils/environment';
+
export function EmojiPicker () {
return import('../../emoji/emoji_picker');
}
@@ -42,6 +44,18 @@ export function Lists () {
return import('../../lists');
}
+export function Collections () {
+ return import('../../collections').then(
+ module => ({default: module.Collections})
+ );
+}
+
+export function CollectionsEditor () {
+ return import('../../collections/editor').then(
+ module => ({default: module.CollectionEditorPage})
+ );
+}
+
export function Status () {
return import('../../status');
}
@@ -59,6 +73,9 @@ export function PinnedStatuses () {
}
export function AccountTimeline () {
+ if (isClientFeatureEnabled('profile_redesign')) {
+ return import('../../account_timeline/v2');
+ }
return import('../../account_timeline');
}
diff --git a/app/javascript/mastodon/hooks/useAccount.ts b/app/javascript/mastodon/hooks/useAccount.ts
new file mode 100644
index 00000000000..277fa16931d
--- /dev/null
+++ b/app/javascript/mastodon/hooks/useAccount.ts
@@ -0,0 +1,26 @@
+import { useEffect } from 'react';
+
+import { fetchAccount } from '../actions/accounts';
+import { createAppSelector, useAppDispatch, useAppSelector } from '../store';
+
+export const accountSelector = createAppSelector(
+ [
+ (state) => state.accounts,
+ (_, accountId: string | null | undefined) => accountId,
+ ],
+ (accounts, accountId) => (accountId ? accounts.get(accountId) : undefined),
+);
+
+export function useAccount(accountId: string | null | undefined) {
+ const account = useAppSelector((state) => accountSelector(state, accountId));
+
+ const dispatch = useAppDispatch();
+ const accountInStore = !!account;
+ useEffect(() => {
+ if (accountId && !accountInStore) {
+ dispatch(fetchAccount(accountId));
+ }
+ }, [accountId, accountInStore, dispatch]);
+
+ return account;
+}
diff --git a/app/javascript/mastodon/hooks/useOverflow.ts b/app/javascript/mastodon/hooks/useOverflow.ts
new file mode 100644
index 00000000000..e5a9ab407e5
--- /dev/null
+++ b/app/javascript/mastodon/hooks/useOverflow.ts
@@ -0,0 +1,172 @@
+import { useState, useRef, useCallback, useEffect } from 'react';
+
+/**
+ * Calculate and manage overflow of child elements within a container.
+ *
+ * To use, wire up the `wrapperRef` to the container element, and the `listRef` to the
+ * child element that contains the items to be measured. If autoResize is true,
+ * the list element will have its max-width set to prevent wrapping. The listRef element
+ * requires both position:relative and overflow:hidden styles to work correctly.
+ */
+export function useOverflow({
+ autoResize,
+ padding = 4,
+}: { autoResize?: boolean; padding?: number } = {}) {
+ const [hiddenIndex, setHiddenIndex] = useState(-1);
+ const [hiddenCount, setHiddenCount] = useState(0);
+ const [maxWidth, setMaxWidth] = useState
('none');
+
+ // This is the item container element.
+ const listRef = useRef(null);
+
+ // The main recalculation function.
+ const handleRecalculate = useCallback(() => {
+ const listEle = listRef.current;
+ if (!listEle) return;
+
+ const reset = () => {
+ setHiddenIndex(-1);
+ setHiddenCount(0);
+ setMaxWidth('none');
+ };
+
+ // Calculate the width via the parent element, minus the more button, minus the padding.
+ const maxWidth =
+ (listEle.parentElement?.offsetWidth ?? 0) -
+ (listEle.nextElementSibling?.scrollWidth ?? 0) -
+ padding;
+ if (maxWidth <= 0) {
+ reset();
+ return;
+ }
+
+ // Iterate through children until we exceed max width.
+ let visible = 0;
+ let index = 0;
+ let totalWidth = 0;
+ for (const child of listEle.children) {
+ if (child instanceof HTMLElement) {
+ const rightOffset = child.offsetLeft + child.offsetWidth;
+ if (rightOffset <= maxWidth) {
+ visible += 1;
+ totalWidth = rightOffset;
+ } else {
+ break;
+ }
+ }
+ index++;
+ }
+
+ // All are visible, so remove max-width restriction.
+ if (visible === listEle.children.length) {
+ reset();
+ return;
+ }
+
+ // Set the width to avoid wrapping, and set hidden count.
+ setHiddenIndex(index);
+ setHiddenCount(listEle.children.length - visible);
+ setMaxWidth(totalWidth);
+ }, [padding]);
+
+ useEffect(() => {
+ if (listRef.current && autoResize) {
+ listRef.current.style.maxWidth =
+ typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth;
+ }
+ }, [autoResize, maxWidth]);
+
+ // Set up observers to watch for size and content changes.
+ const resizeObserverRef = useRef(null);
+ const mutationObserverRef = useRef(null);
+
+ // Helper to get or create the resize observer.
+ const resizeObserver = useCallback(() => {
+ const observer = (resizeObserverRef.current ??= new ResizeObserver(
+ handleRecalculate,
+ ));
+ return observer;
+ }, [handleRecalculate]);
+
+ // Iterate through children and observe them for size changes.
+ const handleChildrenChange = useCallback(() => {
+ const listEle = listRef.current;
+ const observer = resizeObserver();
+
+ if (listEle) {
+ for (const child of listEle.children) {
+ if (child instanceof HTMLElement) {
+ observer.observe(child);
+ }
+ }
+ }
+ handleRecalculate();
+ }, [handleRecalculate, resizeObserver]);
+
+ // Helper to get or create the mutation observer.
+ const mutationObserver = useCallback(() => {
+ const observer = (mutationObserverRef.current ??= new MutationObserver(
+ handleChildrenChange,
+ ));
+ return observer;
+ }, [handleChildrenChange]);
+
+ // Set up observers.
+ const handleObserve = useCallback(() => {
+ if (wrapperRef.current) {
+ resizeObserver().observe(wrapperRef.current);
+ }
+ if (listRef.current) {
+ mutationObserver().observe(listRef.current, { childList: true });
+ handleChildrenChange();
+ }
+ }, [handleChildrenChange, mutationObserver, resizeObserver]);
+
+ // Watch the wrapper for size changes, and recalculate when it resizes.
+ const wrapperRef = useRef(null);
+ const wrapperRefCallback = useCallback(
+ (node: HTMLElement | null) => {
+ if (node) {
+ wrapperRef.current = node;
+ handleObserve();
+ }
+ },
+ [handleObserve],
+ );
+
+ // If there are changes to the children, recalculate which are visible.
+ const listRefCallback = useCallback(
+ (node: HTMLElement | null) => {
+ if (node) {
+ listRef.current = node;
+ handleObserve();
+ }
+ },
+ [handleObserve],
+ );
+
+ useEffect(() => {
+ handleObserve();
+
+ return () => {
+ if (resizeObserverRef.current) {
+ resizeObserverRef.current.disconnect();
+ resizeObserverRef.current = null;
+ }
+ if (mutationObserverRef.current) {
+ mutationObserverRef.current.disconnect();
+ mutationObserverRef.current = null;
+ }
+ };
+ }, [handleObserve]);
+
+ return {
+ hiddenCount,
+ hasOverflow: hiddenCount > 0,
+ wrapperRef: wrapperRefCallback,
+ hiddenIndex,
+ maxWidth,
+ listRef: listRefCallback,
+ recalculate: handleRecalculate,
+ };
+}
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 53d90d3eabd..94c244ea389 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -714,7 +714,6 @@
"privacy.private.short": "للمتابِعين",
"privacy.public.long": "أي شخص على أو خارج ماستدون",
"privacy.public.short": "للعامة",
- "privacy.quote.anyone": "{visibility}، يمكن لأي شخص الاقتباس",
"privacy.quote.disabled": "{visibility}، الاقتباس معطل",
"privacy.quote.limited": "{visibility}، الاقتباسات محدودة",
"privacy.unlisted.additional": "هذا يتصرف بالضبط مثل النشر للعامة، باستثناء أن المنشور لن يظهر في الموجزات الحية أو في الوسوم أو في الإستكشاف، أو في نتائج بحث ماستدون، حتى وإن قمت بتفعيله على مستوى الحساب.",
diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json
index da4aa544093..02cbb73877f 100644
--- a/app/javascript/mastodon/locales/be.json
+++ b/app/javascript/mastodon/locales/be.json
@@ -14,6 +14,8 @@
"about.powered_by": "Дэцэнтралізаваная сацыяльная сетка, створаная {mastodon}",
"about.rules": "Правілы сервера",
"account.account_note_header": "Асабістая нататка",
+ "account.activity": "Актыўнасць",
+ "account.add_note": "Дадаць асабістую нататку",
"account.add_or_remove_from_list": "Дадаць або выдаліць са спісаў",
"account.badges.bot": "Бот",
"account.badges.group": "Група",
@@ -27,6 +29,7 @@
"account.direct": "Згадаць прыватна @{name}",
"account.disable_notifications": "Не паведамляць мне пра публікацыі @{name}",
"account.domain_blocking": "Блакіраванне дамена",
+ "account.edit_note": "Рэдагаваць асабістую нататку",
"account.edit_profile": "Рэдагаваць профіль",
"account.edit_profile_short": "Рэдагаваць",
"account.enable_notifications": "Апавяшчаць мяне пра допісы @{name}",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Хэштэгі",
"account.featured_tags.last_status_at": "Апошні допіс ад {date}",
"account.featured_tags.last_status_never": "Няма допісаў",
+ "account.filters.all": "Уся актыўнасць",
+ "account.filters.boosts_toggle": "Паказваць пашырэнні",
+ "account.filters.posts_boosts": "Допісы і пашырэнні",
+ "account.filters.posts_only": "Допісы",
+ "account.filters.posts_replies": "Допісы і адказы",
+ "account.filters.replies_toggle": "Паказваць адказы",
"account.follow": "Падпісацца",
"account.follow_back": "Падпісацца ў адказ",
"account.follow_back_short": "Падпісацца ў адказ",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Перайсці да профілю",
"account.hide_reblogs": "Схаваць пашырэнні ад @{name}",
"account.in_memoriam": "У памяць.",
+ "account.joined_long": "Далучыў(-ла)ся {date}",
"account.joined_short": "Далучыўся",
"account.languages": "Змяніць выбраныя мовы",
"account.link_verified_on": "Права ўласнасці на гэтую спасылку праверана {date}",
@@ -71,6 +81,14 @@
"account.muting": "Ігнараванне",
"account.mutual": "Вы падпісаны адно на аднаго",
"account.no_bio": "Апісанне адсутнічае.",
+ "account.node_modal.callout": "Асабістыя нататкі бачныя толькі Вам.",
+ "account.node_modal.edit_title": "Рэдагаваць асабістую нататку",
+ "account.node_modal.error_unknown": "Немагчыма захаваць нататку",
+ "account.node_modal.field_label": "Асабістая нататка",
+ "account.node_modal.save": "Захаваць",
+ "account.node_modal.title": "Дадаць асабістую нататку",
+ "account.note.edit_button": "Змяніць",
+ "account.note.title": "Асабістая нататка (бачная толькі Вам)",
"account.open_original_page": "Адкрыць арыгінальную старонку",
"account.posts": "Допісы",
"account.posts_with_replies": "Допісы і адказы",
@@ -90,6 +108,8 @@
"account.unmute": "Не ігнараваць @{name}",
"account.unmute_notifications_short": "Апавяшчаць",
"account.unmute_short": "Не ігнараваць",
+ "account_fields_modal.close": "Закрыць",
+ "account_fields_modal.title": "Інфармацыя пра {name}",
"account_note.placeholder": "Націсніце, каб дадаць нататку",
"admin.dashboard.daily_retention": "Штодзённы паказчык утрымання карыстальнікаў пасля рэгістрацыі",
"admin.dashboard.monthly_retention": "Штомесячны паказчык утрымання карыстальнікаў пасля рэгістрацыі",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Закрыць",
"bundle_modal_error.message": "Падчас загрузкі гэтага экрана штосьці пайшло не так.",
"bundle_modal_error.retry": "Паспрабуйце зноў",
+ "callout.dismiss": "Адхіліць",
"carousel.current": "Слайд {current, number} з {max, number}",
"carousel.slide": "Слайд {current, number} з {max, number}",
"closed_registrations.other_server_instructions": "Паколькі Mastodon дэцэнтралізаваны, вы можаце стварыць уліковы запіс на іншым серверы і працягваць узаемадзейнічаць з ім.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Знайсці іншы сервер",
"closed_registrations_modal.preamble": "Mastodon дэцэнтралізаваны, так што дзе б вы ні стварылі ўліковы запіс, вы зможаце падпісвацца і камунікаваць з кім хочаце на гэтым серверы. Вы нават можаце стварыць свой!",
"closed_registrations_modal.title": "Рэгістрацыя ў Mastodon",
+ "collections.collection_description": "Апісанне",
+ "collections.collection_name": "Назва",
+ "collections.collection_topic": "Тэма",
+ "collections.create_a_collection_hint": "Стварыце калекцыю, каб параіць або падзяліцца сваімі любімымі ўліковымі запісамі з іншымі.",
+ "collections.create_collection": "Стварыць калекцыю",
+ "collections.delete_collection": "Выдаліць калекцыю",
+ "collections.description_length_hint": "Максімум 100 сімвалаў",
+ "collections.error_loading_collections": "Адбылася памылка падчас загрузкі Вашых калекцый.",
+ "collections.mark_as_sensitive": "Пазначыць як далікатную",
+ "collections.mark_as_sensitive_hint": "Схаваць апісанне калекцыі і ўліковыя запісы за банерам з папярэджаннем. Назва калекцыі застанецца бачнай.",
+ "collections.name_length_hint": "Максімум 100 сімвалаў",
+ "collections.no_collections_yet": "Пакуль няма калекцый.",
+ "collections.topic_hint": "Дадайце хэштэг, які дапаможа іншым зразумець галоўную тэму гэтай калекцыі.",
+ "collections.view_collection": "Глядзець калекцыю",
"column.about": "Пра нас",
"column.blocks": "Заблакіраваныя карыстальнікі",
"column.bookmarks": "Закладкі",
+ "column.collections": "Мае калекцыі",
"column.community": "Лакальная стужка",
+ "column.create_collection": "Стварыць калекцыю",
"column.create_list": "Стварыць спіс",
"column.direct": "Прыватныя згадванні",
"column.directory": "Праглядзець профілі",
"column.domain_blocks": "Заблакіраваныя дамены",
+ "column.edit_collection": "Змяніць калекцыю",
"column.edit_list": "Рэдагаваць спіс",
"column.favourites": "Упадабанае",
"column.firehose": "Стужкі",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Выдаліць",
"confirmations.delete.message": "Вы ўпэўненыя, што хочаце выдаліць гэты допіс?",
"confirmations.delete.title": "Выдаліць допіс?",
+ "confirmations.delete_collection.confirm": "Выдаліць",
+ "confirmations.delete_collection.message": "Гэтае дзеянне немагчыма скасаваць.",
+ "confirmations.delete_collection.title": "Выдаліць \"{name}\"?",
"confirmations.delete_list.confirm": "Выдаліць",
"confirmations.delete_list.message": "Вы ўпэўненыя, што хочаце беззваротна выдаліць гэты спіс?",
"confirmations.delete_list.title": "Выдаліць спіс?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Допіс {current, number} з {max, number}",
"featured_carousel.header": "{count, plural,one {Замацаваны допіс} other {Замацаваныя допісы}}",
"featured_carousel.slide": "Допіс {current, number} з {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Гэтая катэгорыя фільтра не прымяняецца да кантэксту, у якім Вы адкрылі гэты допіс. Калі Вы хочаце, каб паведамленне таксама было адфільтраванае ў гэтым кантэксце, Вам трэба будзе адрэдагаваць фільтр.",
"filter_modal.added.context_mismatch_title": "Неадпаведны кантэкст!",
"filter_modal.added.expired_explanation": "Тэрмін дзеяння гэтай катэгорыі фільтраў скончыўся, вам трэба будзе змяніць дату заканчэння тэрміну дзеяння, каб яна прымянялася",
@@ -451,6 +493,7 @@
"footer.source_code": "Прагледзець зыходны код",
"footer.status": "Статус",
"footer.terms_of_service": "Умовы выкарыстання",
+ "form_field.optional": "(неабавязкова)",
"generic.saved": "Захавана",
"getting_started.heading": "Пачатак працы",
"hashtag.admin_moderation": "Адкрыць інтэрфейс мадэратара для #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# новы элемент} few {# новыя элементы} many {# новых элементаў} other {# новых элементаў}}",
"loading_indicator.label": "Ідзе загрузка…",
"media_gallery.hide": "Схаваць",
+ "minicard.more_items": "+{count}",
"moved_to_account_banner.text": "Ваш уліковы запіс {disabledAccount} зараз адключаны, таму што Вы перайшлі на {movedToAccount}.",
"mute_modal.hide_from_notifications": "Схаваць з апавяшчэнняў",
"mute_modal.hide_options": "Схаваць опцыі",
@@ -699,7 +743,7 @@
"notifications.clear_confirmation": "Вы ўпэўнены, што хочаце назаўсёды сцерці ўсе свае паведамленні?",
"notifications.clear_title": "Ачысціць апавяшчэнні?",
"notifications.column_settings.admin.report": "Новыя скаргі:",
- "notifications.column_settings.admin.sign_up": "Новыя ўваходы:",
+ "notifications.column_settings.admin.sign_up": "Новыя рэгістрацыі:",
"notifications.column_settings.alert": "Апавяшчэнні на працоўным стале",
"notifications.column_settings.favourite": "Упадабанае:",
"notifications.column_settings.filter_bar.advanced": "Паказаць усе катэгорыі",
@@ -786,7 +830,7 @@
"privacy.private.short": "Падпісчыкі",
"privacy.public.long": "Усе, хто ёсць і каго няма ў Mastodon",
"privacy.public.short": "Публічны",
- "privacy.quote.anyone": "{visibility}, усе могуць цытаваць",
+ "privacy.quote.anyone": "{visibility}, цытаты дазволеныя",
"privacy.quote.disabled": "{visibility}, цытаты адключаныя",
"privacy.quote.limited": "{visibility}, абмежаваныя цытаты",
"privacy.unlisted.additional": "Паводзіць сябе гэтак жа, як і публічны, за выключэннем таго, што допіс не будзе адлюстроўвацца ў жывой стужцы, хэштэгах, аглядзе або ў пошуку Mastodon, нават калі Вы ўключылі бачнасць у пошуку ў наладах.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Апавяшчэнні",
"tabs_bar.publish": "Новы допіс",
"tabs_bar.search": "Пошук",
+ "tag.remove": "Выдаліць",
"terms_of_service.effective_as_of": "Дзейнічае да {date}",
"terms_of_service.title": "Умовы выкарыстання",
"terms_of_service.upcoming_changes_on": "Змены, якія адбудуцца {date}",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index d9f9006d3ea..3549c0ae2a3 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -714,7 +714,6 @@
"privacy.private.short": "Последователи",
"privacy.public.long": "Всеки във и извън Mastodon",
"privacy.public.short": "Публично",
- "privacy.quote.anyone": "{visibility}, всеки може да цитира",
"privacy.quote.disabled": "{visibility}, цитатите са изключени",
"privacy.quote.limited": "{visibility}, цитатите са ограничени",
"privacy.unlisted.additional": "Това действие е точно като публичното, с изключение на това, че публикацията няма да се появява в каналите на живо, хаштаговете, разглеждането или търсенето в Mastodon, дори ако сте избрали да се публично видими на ниво акаунт.",
diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json
index eb144adfa06..0e9e9d33e6a 100644
--- a/app/javascript/mastodon/locales/br.json
+++ b/app/javascript/mastodon/locales/br.json
@@ -559,7 +559,6 @@
"privacy.private.long": "Hoc'h heulierien·ezed hepken",
"privacy.private.short": "Heulierien",
"privacy.public.short": "Publik",
- "privacy.quote.anyone": "{visibility}, n'eus forzh piv a c'hall menegiñ",
"privacy.quote.disabled": "{visibility}, menegoù diweredekaet",
"privacy_policy.last_updated": "Hizivadenn ziwezhañ {date}",
"privacy_policy.title": "Reolennoù Prevezded",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index 2e0d7aee041..10b290037e1 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -14,6 +14,8 @@
"about.powered_by": "Xarxa social descentralitzada impulsada per {mastodon}",
"about.rules": "Normes del servidor",
"account.account_note_header": "Nota personal",
+ "account.activity": "Activitat",
+ "account.add_note": "Afegeix una nota personal",
"account.add_or_remove_from_list": "Afegeix o elimina de les llistes",
"account.badges.bot": "Automatitzat",
"account.badges.group": "Grup",
@@ -27,6 +29,7 @@
"account.direct": "Menciona privadament @{name}",
"account.disable_notifications": "Deixa de notificar-me els tuts de @{name}",
"account.domain_blocking": "Bloquem el domini",
+ "account.edit_note": "Edita una nota personal",
"account.edit_profile": "Edita el perfil",
"account.edit_profile_short": "Edita",
"account.enable_notifications": "Notifica'm els tuts de @{name}",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Etiquetes",
"account.featured_tags.last_status_at": "Darrer tut el {date}",
"account.featured_tags.last_status_never": "No hi ha tuts",
+ "account.filters.all": "Tota l'activitat",
+ "account.filters.boosts_toggle": "Mostra els impulsos",
+ "account.filters.posts_boosts": "Publicacions i impulsos",
+ "account.filters.posts_only": "Publicacions",
+ "account.filters.posts_replies": "Publicacions i respostes",
+ "account.filters.replies_toggle": "Mostra les respostes",
"account.follow": "Segueix",
"account.follow_back": "Segueix tu també",
"account.follow_back_short": "Segueix tu també",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Vés al perfil",
"account.hide_reblogs": "Amaga els impulsos de @{name}",
"account.in_memoriam": "En Memòria.",
+ "account.joined_long": "Membre des de {date}",
"account.joined_short": "S'hi va unir",
"account.languages": "Canvia les llengües subscrites",
"account.link_verified_on": "La propietat d'aquest enllaç es va verificar el dia {date}",
@@ -71,6 +81,14 @@
"account.muting": "Silenciem",
"account.mutual": "Us seguiu l'un a l'altre",
"account.no_bio": "No s'ha proporcionat cap descripció.",
+ "account.node_modal.callout": "Ningú més pot veure les vostres notes personals.",
+ "account.node_modal.edit_title": "Edita una nota personal",
+ "account.node_modal.error_unknown": "No s'ha pogut desar la nota",
+ "account.node_modal.field_label": "Nota Personal",
+ "account.node_modal.save": "Desa",
+ "account.node_modal.title": "Afegeix una nota personal",
+ "account.note.edit_button": "Edita",
+ "account.note.title": "Nota personal (visible només per a vós)",
"account.open_original_page": "Obre la pàgina original",
"account.posts": "Tuts",
"account.posts_with_replies": "Tuts i respostes",
@@ -90,6 +108,8 @@
"account.unmute": "Deixa de silenciar @{name}",
"account.unmute_notifications_short": "Deixa de silenciar les notificacions",
"account.unmute_short": "Deixa de silenciar",
+ "account_fields_modal.close": "Tanca",
+ "account_fields_modal.title": "Informació de {name}",
"account_note.placeholder": "Clica per a afegir-hi una nota",
"admin.dashboard.daily_retention": "Ràtio de retenció d'usuaris per dia, després de registrar-se",
"admin.dashboard.monthly_retention": "Ràtio de retenció d'usuaris per mes, després de registrar-se",
@@ -158,6 +178,7 @@
"bundle_modal_error.close": "Tanca",
"bundle_modal_error.message": "S'ha produït un error en carregar aquesta pantalla.",
"bundle_modal_error.retry": "Torna-ho a provar",
+ "callout.dismiss": "Omet",
"carousel.current": "Diapositiva {current, number} / {max, number}",
"carousel.slide": "Diapositiva {current, number} de {max, number}",
"closed_registrations.other_server_instructions": "Com que Mastodon és descentralitzat, pots crear un compte en un altre servidor i continuar interactuant amb aquest.",
@@ -165,9 +186,16 @@
"closed_registrations_modal.find_another_server": "Troba un altre servidor",
"closed_registrations_modal.preamble": "Mastodon és descentralitzat. Per tant, tinguis on tinguis el compte, seràs capaç de seguir i interactuar amb tothom des d'aquest servidor. Fins i tot pots tenir el compte en el teu propi servidor!",
"closed_registrations_modal.title": "Registrant-se a Mastodon",
+ "collections.create_a_collection_hint": "Creeu una coŀlecció per a recomanar o compartir amb d'altres els vostres comptes preferits.",
+ "collections.create_collection": "Crea una coŀlecció",
+ "collections.delete_collection": "Elimina la coŀlecció",
+ "collections.error_loading_collections": "Hi ha hagut un error en carregar les vostres coŀleccions.",
+ "collections.no_collections_yet": "Encara no hi ha coŀleccions.",
+ "collections.view_collection": "Mostra la coŀlecció",
"column.about": "Quant a",
"column.blocks": "Usuaris blocats",
"column.bookmarks": "Marcadors",
+ "column.collections": "Les meves coŀleccions",
"column.community": "Línia de temps local",
"column.create_list": "Crea una llista",
"column.direct": "Mencions privades",
@@ -425,6 +453,7 @@
"footer.source_code": "Mostra el codi font",
"footer.status": "Estat",
"footer.terms_of_service": "Condicions de servei",
+ "form_field.optional": "(opcional)",
"generic.saved": "Desat",
"getting_started.heading": "Primeres passes",
"hashtag.admin_moderation": "Obre la interfície de moderació per a #{name}",
@@ -562,6 +591,7 @@
"load_pending": "{count, plural, one {# element nou} other {# elements nous}}",
"loading_indicator.label": "Es carrega…",
"media_gallery.hide": "Amaga",
+ "minicard.more_items": "+{count}",
"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",
@@ -759,7 +789,7 @@
"privacy.private.short": "Seguidors",
"privacy.public.long": "Tothom dins o fora Mastodon",
"privacy.public.short": "Públic",
- "privacy.quote.anyone": "{visibility}, qualsevol pot citar",
+ "privacy.quote.anyone": "{visibility}, cites permeses",
"privacy.quote.disabled": "{visibility}, cites desactivades",
"privacy.quote.limited": "{visibility}, cites limitades",
"privacy.unlisted.additional": "Es comporta igual que públic, excepte que la publicació no apareixerà als canals en directe o etiquetes, l'explora o a la cerca de Mastodon, fins i tot si ho heu activat a nivell de compte.",
@@ -980,6 +1010,7 @@
"tabs_bar.notifications": "Notificacions",
"tabs_bar.publish": "Nova Publicació",
"tabs_bar.search": "Cerca",
+ "tag.remove": "Elimina",
"terms_of_service.effective_as_of": "En vigor a partir de {date}",
"terms_of_service.title": "Condicions de servei",
"terms_of_service.upcoming_changes_on": "Propers canvis el {date}",
@@ -1027,7 +1058,7 @@
"visibility_modal.direct_quote_warning.title": "Les cites no es poden incrustar a les mencions privades",
"visibility_modal.header": "Visibilitat i interacció",
"visibility_modal.helper.direct_quoting": "No es poden citar mencions privades fetes a Mastondon.",
- "visibility_modal.helper.privacy_editing": "La visibilitat no es pot canviar després de publicar una publicació.",
+ "visibility_modal.helper.privacy_editing": "La visibilitat no es pot canviar després s'ha fet una publicació.",
"visibility_modal.helper.privacy_private_self_quote": "Les autocites de publicacions privades no es poden fer públiques.",
"visibility_modal.helper.private_quoting": "No es poden citar publicacions fetes a Mastodon només per a seguidors.",
"visibility_modal.helper.unlisted_quoting": "Quan la gent us citi, les seves publicacions quedaran amagades de les línies de temps de tendències.",
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index 447bbf56ea0..4a1dd2b8873 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -14,6 +14,7 @@
"about.powered_by": "Decentralizovaná sociální média poháněná {mastodon}",
"about.rules": "Pravidla serveru",
"account.account_note_header": "Osobní poznámka",
+ "account.activity": "Aktivita",
"account.add_or_remove_from_list": "Přidat nebo odstranit ze seznamů",
"account.badges.bot": "Bot",
"account.badges.group": "Skupina",
@@ -57,6 +58,7 @@
"account.go_to_profile": "Přejít na profil",
"account.hide_reblogs": "Skrýt boosty od @{name}",
"account.in_memoriam": "In Memoriam.",
+ "account.joined_long": "Přidali se {date}",
"account.joined_short": "Připojen/a",
"account.languages": "Změnit odebírané jazyky",
"account.link_verified_on": "Vlastnictví tohoto odkazu bylo zkontrolováno {date}",
@@ -90,6 +92,8 @@
"account.unmute": "Zrušit skrytí @{name}",
"account.unmute_notifications_short": "Zrušit ztlumení oznámení",
"account.unmute_short": "Zrušit skrytí",
+ "account_fields_modal.close": "Zavřít",
+ "account_fields_modal.title": "info o {name}",
"account_note.placeholder": "Klikněte pro přidání poznámky",
"admin.dashboard.daily_retention": "Míra udržení uživatelů podle dne po registraci",
"admin.dashboard.monthly_retention": "Míra udržení uživatelů podle měsíce po registraci",
@@ -191,6 +195,9 @@
"closed_registrations_modal.find_another_server": "Najít jiný server",
"closed_registrations_modal.preamble": "Mastodon je decentralizovaný, takže bez ohledu na to, kde vytvoříte svůj účet, budete moci sledovat a komunikovat s kýmkoli na tomto serveru. Můžete ho dokonce hostovat!",
"closed_registrations_modal.title": "Registrace na Mastodon",
+ "collections.mark_as_sensitive_hint": "Skryje popis kolekce a účty za varováním obsahu. Název kolekce bude stále viditelný.",
+ "collections.name_length_hint": "Max. 100 znaků",
+ "collections.topic_hint": "Přidat štítek, který pomůže ostatním pochopit hlavní téma této kolekce.",
"column.about": "O aplikaci",
"column.blocks": "Blokovaní uživatelé",
"column.bookmarks": "Záložky",
@@ -589,6 +596,7 @@
"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.hide": "Skrýt",
+ "minicard.more_items": "+{count}",
"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 oznámení",
"mute_modal.hide_options": "Skrýt možnosti",
@@ -786,7 +794,6 @@
"privacy.private.short": "Sledující",
"privacy.public.long": "Kdokoliv na Mastodonu i mimo něj",
"privacy.public.short": "Veřejné",
- "privacy.quote.anyone": "{visibility}, kdokoliv může citovat",
"privacy.quote.disabled": "{visibility}, citování je zakázáno",
"privacy.quote.limited": "{visibility}, citování je omezené",
"privacy.unlisted.additional": "Chová se stejně jako veřejný, až na to, že se příspěvek neobjeví v živých kanálech nebo hashtazích, v objevování nebo vyhledávání na Mastodonu, a to i když je účet nastaven tak, aby se zde všude tyto příspěvky zobrazovaly.",
@@ -1007,6 +1014,7 @@
"tabs_bar.notifications": "Oznámení",
"tabs_bar.publish": "Nový příspěvek",
"tabs_bar.search": "Vyhledávání",
+ "tag.remove": "Odebrat",
"terms_of_service.effective_as_of": "Platné od {date}",
"terms_of_service.title": "Podmínky služby",
"terms_of_service.upcoming_changes_on": "Nadcházející změny v {date}",
diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json
index 6c7223b38b0..3eeb9cf6eae 100644
--- a/app/javascript/mastodon/locales/cy.json
+++ b/app/javascript/mastodon/locales/cy.json
@@ -785,7 +785,6 @@
"privacy.private.short": "Dilynwyr",
"privacy.public.long": "Unrhyw un ar ac oddi ar Mastodon",
"privacy.public.short": "Cyhoeddus",
- "privacy.quote.anyone": "{visibility}, gall unrhyw un ddyfynnu",
"privacy.quote.disabled": "{visibility}, dyfyniadau wedi'u hanalluogi",
"privacy.quote.limited": "{visibility}, dyfyniadau wedi'u cyfyngu",
"privacy.unlisted.additional": "Mae hwn yn ymddwyn yn union fel y cyhoeddus, ac eithrio na fydd y postiad yn ymddangos mewn ffrydiau byw neu hashnodau, archwilio, neu chwiliad Mastodon, hyd yn oed os ydych wedi eich cynnwys ar draws y cyfrif.",
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index 035037fccbb..185e3a54ac8 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -14,6 +14,8 @@
"about.powered_by": "Decentraliserede sociale medier drevet af {mastodon}",
"about.rules": "Serverregler",
"account.account_note_header": "Personligt notat",
+ "account.activity": "Aktivitet",
+ "account.add_note": "Tilføj en personlig note",
"account.add_or_remove_from_list": "Tilføj eller fjern fra lister",
"account.badges.bot": "Automatisert",
"account.badges.group": "Gruppe",
@@ -27,6 +29,7 @@
"account.direct": "Nævn @{name} privat",
"account.disable_notifications": "Giv mig ikke længere en notifikation, når @{name} laver indlæg",
"account.domain_blocking": "Blokerer domæne",
+ "account.edit_note": "Rediger personlig note",
"account.edit_profile": "Redigér profil",
"account.edit_profile_short": "Rediger",
"account.enable_notifications": "Giv mig besked, når @{name} laver indlæg",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Hashtags",
"account.featured_tags.last_status_at": "Seneste indlæg {date}",
"account.featured_tags.last_status_never": "Ingen indlæg",
+ "account.filters.all": "Al aktivitet",
+ "account.filters.boosts_toggle": "Vis fremhævelser",
+ "account.filters.posts_boosts": "Indlæg og fremhævelser",
+ "account.filters.posts_only": "Indlæg",
+ "account.filters.posts_replies": "Indlæg og svar",
+ "account.filters.replies_toggle": "Vis svar",
"account.follow": "Følg",
"account.follow_back": "Følg tilbage",
"account.follow_back_short": "Følg tilbage",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Gå til profil",
"account.hide_reblogs": "Skjul fremhævelser fra @{name}",
"account.in_memoriam": "Til minde om.",
+ "account.joined_long": "Tilmeldt {date}",
"account.joined_short": "Oprettet",
"account.languages": "Skift abonnementssprog",
"account.link_verified_on": "Ejerskab af dette link blev tjekket {date}",
@@ -71,6 +81,14 @@
"account.muting": "Skjuler",
"account.mutual": "I følger hinanden",
"account.no_bio": "Ingen beskrivelse til rådighed.",
+ "account.node_modal.callout": "Personlige noter er kun synlige for dig.",
+ "account.node_modal.edit_title": "Rediger personlig note",
+ "account.node_modal.error_unknown": "Kunne ikke gemme noten",
+ "account.node_modal.field_label": "Personlig note",
+ "account.node_modal.save": "Gem",
+ "account.node_modal.title": "Tilføj en personlig note",
+ "account.note.edit_button": "Rediger",
+ "account.note.title": "Personlig note (kun synlige for dig)",
"account.open_original_page": "Åbn oprindelig side",
"account.posts": "Indlæg",
"account.posts_with_replies": "Indlæg og svar",
@@ -90,6 +108,8 @@
"account.unmute": "Vis @{name} igen",
"account.unmute_notifications_short": "Vis notifikationer igen",
"account.unmute_short": "Vis igen",
+ "account_fields_modal.close": "Luk",
+ "account_fields_modal.title": "Information om {name}",
"account_note.placeholder": "Klik for at tilføje notat",
"admin.dashboard.daily_retention": "Brugerfastholdelsesrate pr. dag efter tilmelding",
"admin.dashboard.monthly_retention": "Brugerfastholdelsesrate pr. måned efter tilmelding",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Luk",
"bundle_modal_error.message": "Noget gik galt under indlæsningen af denne skærm.",
"bundle_modal_error.retry": "Forsøg igen",
+ "callout.dismiss": "Afvis",
"carousel.current": "Dias {current, number} / {max, number}",
"carousel.slide": "Dias {current, number} af {max, number}",
"closed_registrations.other_server_instructions": "Eftersom Mastodon er decentraliseret, kan du oprette en konto på en anden server og stadig interagere med denne.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Find en anden server",
"closed_registrations_modal.preamble": "Mastodon er decentraliseret, så uanset hvor du opretter din konto, vil du være i stand til at følge og interagere med hvem som helst på denne server. Du kan endda selv være vært for den!",
"closed_registrations_modal.title": "Oprettelse på Mastodon",
+ "collections.collection_description": "Beskrivelse",
+ "collections.collection_name": "Navn",
+ "collections.collection_topic": "Emne",
+ "collections.create_a_collection_hint": "Opret en samling for at anbefale eller dele dine yndlingskonti med andre.",
+ "collections.create_collection": "Opret samling",
+ "collections.delete_collection": "Slet samling",
+ "collections.description_length_hint": "Begrænset til 100 tegn",
+ "collections.error_loading_collections": "Der opstod en fejl under indlæsning af dine samlinger.",
+ "collections.mark_as_sensitive": "Markér som sensitiv",
+ "collections.mark_as_sensitive_hint": "Skjuler samlingens beskrivelse og konti bag en indholdsadvarsel. Samlingens navn vil stadig være synligt.",
+ "collections.name_length_hint": "Begrænset til 100 tegn",
+ "collections.no_collections_yet": "Ingen samlinger endnu.",
+ "collections.topic_hint": "Tilføj et hashtag, der hjælper andre med at forstå det overordnede emne for denne samling.",
+ "collections.view_collection": "Vis samling",
"column.about": "Om",
"column.blocks": "Blokerede brugere",
"column.bookmarks": "Bogmærker",
+ "column.collections": "Mine samlinger",
"column.community": "Lokal tidslinje",
+ "column.create_collection": "Opret samling",
"column.create_list": "Opret liste",
"column.direct": "Private omtaler",
"column.directory": "Gennemse profiler",
"column.domain_blocks": "Blokerede domæner",
+ "column.edit_collection": "Rediger samling",
"column.edit_list": "Redigér liste",
"column.favourites": "Favoritter",
"column.firehose": "Live feeds",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Slet",
"confirmations.delete.message": "Er du sikker på, at du vil slette dette indlæg?",
"confirmations.delete.title": "Slet indlæg?",
+ "confirmations.delete_collection.confirm": "Slet",
+ "confirmations.delete_collection.message": "Denne handling kan ikke fortrydes.",
+ "confirmations.delete_collection.title": "Slet \"{name}\"?",
"confirmations.delete_list.confirm": "Slet",
"confirmations.delete_list.message": "Er du sikker på, at du vil slette denne liste permanent?",
"confirmations.delete_list.title": "Slet liste?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Indlæg {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {fastgjort indlæg} other {fastgjorte indlæg}}",
"featured_carousel.slide": "Indlæg {current, number} af {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Denne filterkategori omfatter ikke konteksten, hvorunder dette indlæg er tilgået. Redigér filteret, hvis indlægget også ønskes filtreret i denne kontekst.",
"filter_modal.added.context_mismatch_title": "Kontekstmisforhold!",
"filter_modal.added.expired_explanation": "Denne filterkategori er udløbet. Ændr dens udløbsdato, for at anvende den.",
@@ -451,6 +493,7 @@
"footer.source_code": "Vis kildekode",
"footer.status": "Status",
"footer.terms_of_service": "Tjenestevilkår",
+ "form_field.optional": "(valgfri)",
"generic.saved": "Gemt",
"getting_started.heading": "Startmenu",
"hashtag.admin_moderation": "Åbn modereringsbrugerflade for #{name}",
@@ -565,7 +608,7 @@
"lists.add_to_list": "Føj til liste",
"lists.add_to_lists": "Føj {name} til lister",
"lists.create": "Opret",
- "lists.create_a_list_to_organize": "Opret en ny liste til organisering af hjemmefeed",
+ "lists.create_a_list_to_organize": "Opret en ny liste til organisering af dit Hjem-feed",
"lists.create_list": "Opret liste",
"lists.delete": "Slet liste",
"lists.done": "Færdig",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# nyt element} other {# nye elementer}}",
"loading_indicator.label": "Indlæser…",
"media_gallery.hide": "Skjul",
+ "minicard.more_items": "+{count}",
"moved_to_account_banner.text": "Din konto {disabledAccount} er i øjeblikket deaktiveret, fordi du er flyttet til {movedToAccount}.",
"mute_modal.hide_from_notifications": "Skjul fra notifikationer",
"mute_modal.hide_options": "Skjul valgmuligheder",
@@ -786,7 +830,7 @@
"privacy.private.short": "Følgere",
"privacy.public.long": "Alle på og udenfor Mastodon",
"privacy.public.short": "Offentlig",
- "privacy.quote.anyone": "{visibility}, alle kan citere",
+ "privacy.quote.anyone": "{visibility}, citering tilladt",
"privacy.quote.disabled": "{visibility}, citering deaktiveret",
"privacy.quote.limited": "{visibility}, citering begrænset",
"privacy.unlisted.additional": "Dette svarer til offentlig, bortset fra at indlægget ikke vises i live-feeds eller hashtags, udforsk eller Mastodon-søgning, selvom du har tilvalgt dette for kontoen.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notifikationer",
"tabs_bar.publish": "Nyt indlæg",
"tabs_bar.search": "Søg",
+ "tag.remove": "Fjern",
"terms_of_service.effective_as_of": "Gældende pr. {date}",
"terms_of_service.title": "Tjenestevilkår",
"terms_of_service.upcoming_changes_on": "Kommende ændringer pr. {date}",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 9e63460159b..c67339dd320 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -14,6 +14,8 @@
"about.powered_by": "Ein dezentralisiertes soziales Netzwerk, ermöglicht durch {mastodon}",
"about.rules": "Serverregeln",
"account.account_note_header": "Persönliche Notiz",
+ "account.activity": "Aktivitäten",
+ "account.add_note": "Persönliche Notiz hinzufügen",
"account.add_or_remove_from_list": "Listen verwalten",
"account.badges.bot": "Bot",
"account.badges.group": "Gruppe",
@@ -27,6 +29,7 @@
"account.direct": "@{name} privat erwähnen",
"account.disable_notifications": "Benachrichtige mich nicht mehr, wenn @{name} etwas veröffentlicht",
"account.domain_blocking": "Domain blockiert",
+ "account.edit_note": "Persönliche Notiz bearbeiten",
"account.edit_profile": "Profil bearbeiten",
"account.edit_profile_short": "Bearbeiten",
"account.enable_notifications": "Benachrichtige mich, wenn @{name} etwas veröffentlicht",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Hashtags",
"account.featured_tags.last_status_at": "Neuester Beitrag vom {date}",
"account.featured_tags.last_status_never": "Keine Beiträge",
+ "account.filters.all": "Alle Aktivitäten",
+ "account.filters.boosts_toggle": "Geteilte Beiträge anzeigen",
+ "account.filters.posts_boosts": "Beiträge & geteilte Beiträge",
+ "account.filters.posts_only": "Beiträge",
+ "account.filters.posts_replies": "Beiträge & Antworten",
+ "account.filters.replies_toggle": "Antworten anzeigen",
"account.follow": "Folgen",
"account.follow_back": "Ebenfalls folgen",
"account.follow_back_short": "Zurückfolgen",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Profil aufrufen",
"account.hide_reblogs": "Geteilte Beiträge von @{name} ausblenden",
"account.in_memoriam": "Zum Andenken.",
+ "account.joined_long": "Registriert am {date}",
"account.joined_short": "Registriert am",
"account.languages": "Sprachen verwalten",
"account.link_verified_on": "Das Profil mit dieser E-Mail-Adresse wurde bereits am {date} bestätigt",
@@ -71,6 +81,14 @@
"account.muting": "Stummgeschaltet",
"account.mutual": "Ihr folgt einander",
"account.no_bio": "Keine Beschreibung verfügbar.",
+ "account.node_modal.callout": "Persönliche Notizen sind nur für dich sichtbar.",
+ "account.node_modal.edit_title": "Persönliche Notiz bearbeiten",
+ "account.node_modal.error_unknown": "Persönliche Notiz konnte nicht gespeichert werden",
+ "account.node_modal.field_label": "Persönliche Notiz",
+ "account.node_modal.save": "Speichern",
+ "account.node_modal.title": "Persönliche Notiz hinzufügen",
+ "account.note.edit_button": "Bearbeiten",
+ "account.note.title": "Persönliche Notiz (nur für dich sichtbar)",
"account.open_original_page": "Originalbeitrag öffnen",
"account.posts": "Beiträge",
"account.posts_with_replies": "Beiträge & Antworten",
@@ -90,6 +108,8 @@
"account.unmute": "Stummschaltung von @{name} aufheben",
"account.unmute_notifications_short": "Stummschaltung der Benachrichtigungen aufheben",
"account.unmute_short": "Stummschaltung aufheben",
+ "account_fields_modal.close": "Schließen",
+ "account_fields_modal.title": "Informationen über {name}",
"account_note.placeholder": "Klicken, um private Anmerkung hinzuzufügen",
"admin.dashboard.daily_retention": "Verweildauer der Nutzer*innen pro Tag seit der Registrierung",
"admin.dashboard.monthly_retention": "Verweildauer der Nutzer*innen pro Monat seit der Registrierung",
@@ -175,7 +195,7 @@
"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!",
- "bundle_column_error.network.body": "Beim Versuch, diese Seite zu laden, ist ein Fehler aufgetreten. Dies könnte auf ein vorübergehendes Problem mit deiner Internetverbindung oder diesem Server zurückzuführen sein.",
+ "bundle_column_error.network.body": "Beim Laden dieser Seite ist ein Fehler aufgetreten. Die Ursache könnte ein vorübergehendes Problem mit deiner Internetverbindung oder diesem Server sein.",
"bundle_column_error.network.title": "Netzwerkfehler",
"bundle_column_error.retry": "Erneut versuchen",
"bundle_column_error.return": "Zurück zur Startseite",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Schließen",
"bundle_modal_error.message": "Beim Laden des Inhalts ist etwas schiefgelaufen.",
"bundle_modal_error.retry": "Erneut versuchen",
+ "callout.dismiss": "Verwerfen",
"carousel.current": "Seite {current, number}/{max, number}",
"carousel.slide": "Seite {current, number} von {max, number}",
"closed_registrations.other_server_instructions": "Da Mastodon dezentralisiert ist, kannst du dich auch woanders im Fediverse registrieren und trotzdem mit diesem Server in Kontakt bleiben.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Anderen Server suchen",
"closed_registrations_modal.preamble": "Mastodon ist dezentralisiert, das heißt, unabhängig davon, wo du dein Konto erstellst, kannst du jedem Profil auf diesem Server folgen und mit ihm interagieren. Du kannst sogar deinen eigenen Mastodon-Server hosten!",
"closed_registrations_modal.title": "Bei Mastodon registrieren",
+ "collections.collection_description": "Beschreibung",
+ "collections.collection_name": "Titel",
+ "collections.collection_topic": "Thema",
+ "collections.create_a_collection_hint": "Erstelle eine Sammlung, um deine Lieblingsprofile anderen zu empfehlen oder sie zu teilen.",
+ "collections.create_collection": "Sammlung erstellen",
+ "collections.delete_collection": "Sammlung löschen",
+ "collections.description_length_hint": "Maximal 100 Zeichen",
+ "collections.error_loading_collections": "Beim Laden deiner Sammlungen ist ein Fehler aufgetreten.",
+ "collections.mark_as_sensitive": "Mit Inhaltswarnung versehen",
+ "collections.mark_as_sensitive_hint": "Die Beschreibung sowie enthaltenen Profile werden durch eine Inhaltswarnung ausgeblendet. Der Titel bleibt weiterhin sichtbar.",
+ "collections.name_length_hint": "Maximal 100 Zeichen",
+ "collections.no_collections_yet": "Bisher keine Sammlungen vorhanden.",
+ "collections.topic_hint": "Ein Hashtag hilft anderen dabei, das zentrale Thema dieser Sammlung besser zu verstehen.",
+ "collections.view_collection": "Sammlungen anzeigen",
"column.about": "Über",
"column.blocks": "Blockierte Profile",
"column.bookmarks": "Lesezeichen",
+ "column.collections": "Meine Sammlungen",
"column.community": "Lokale Timeline",
+ "column.create_collection": "Sammlung erstellen",
"column.create_list": "Liste erstellen",
"column.direct": "Private Erwähnungen",
"column.directory": "Profile durchstöbern",
"column.domain_blocks": "Blockierte Domains",
+ "column.edit_collection": "Sammlung bearbeiten",
"column.edit_list": "Liste bearbeiten",
"column.favourites": "Favoriten",
"column.firehose": "Live-Feeds",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Löschen",
"confirmations.delete.message": "Möchtest du diesen Beitrag wirklich löschen?",
"confirmations.delete.title": "Beitrag löschen?",
+ "confirmations.delete_collection.confirm": "Löschen",
+ "confirmations.delete_collection.message": "Diese Aktion kann nicht rückgängig gemacht werden.",
+ "confirmations.delete_collection.title": "„{name}“ löschen?",
"confirmations.delete_list.confirm": "Löschen",
"confirmations.delete_list.message": "Bist du dir sicher, dass du diese Liste endgültig löschen möchtest?",
"confirmations.delete_list.title": "Liste löschen?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Beitrag {current, number}/{max, number}",
"featured_carousel.header": "{count, plural, one {Angehefteter Beitrag} other {Angeheftete Beiträge}}",
"featured_carousel.slide": "Beitrag {current, number} von {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Diese Filterkategorie gilt nicht für den Kontext, in welchem du auf diesen Beitrag zugegriffen hast. Wenn der Beitrag auch in diesem Kontext gefiltert werden soll, musst du den Filter bearbeiten.",
"filter_modal.added.context_mismatch_title": "Kontext stimmt nicht überein!",
"filter_modal.added.expired_explanation": "Diese Filterkategorie ist abgelaufen. Du musst das Ablaufdatum für diese Kategorie ändern.",
@@ -451,6 +493,7 @@
"footer.source_code": "Quellcode anzeigen",
"footer.status": "Status",
"footer.terms_of_service": "Nutzungsbedingungen",
+ "form_field.optional": "(optional)",
"generic.saved": "Gespeichert",
"getting_started.heading": "Auf gehts!",
"hashtag.admin_moderation": "#{name} moderieren",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# neuer Beitrag} other {# neue Beiträge}}",
"loading_indicator.label": "Lädt …",
"media_gallery.hide": "Ausblenden",
+ "minicard.more_items": "+{count}",
"moved_to_account_banner.text": "Dein Konto {disabledAccount} ist derzeit deaktiviert, weil du zu {movedToAccount} umgezogen bist.",
"mute_modal.hide_from_notifications": "Auch aus den Benachrichtigungen entfernen",
"mute_modal.hide_options": "Optionen ausblenden",
@@ -600,7 +644,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 von diesem stummgeschalteten Profil weiterhin gesehen werden, aber du wirst dessen Beiträge nicht mehr sehen.",
"navigation_bar.about": "Über",
- "navigation_bar.account_settings": "Passwort und Sicherheit",
+ "navigation_bar.account_settings": "Passwort & Sicherheit",
"navigation_bar.administration": "Administration",
"navigation_bar.advanced_interface": "Erweitertes Webinterface öffnen",
"navigation_bar.automated_deletion": "Automatisiertes Löschen",
@@ -786,7 +830,7 @@
"privacy.private.short": "Follower",
"privacy.public.long": "Alle innerhalb und außerhalb von Mastodon",
"privacy.public.short": "Öffentlich",
- "privacy.quote.anyone": "{visibility} – alle dürfen zitieren",
+ "privacy.quote.anyone": "{visibility} – Zitieren erlaubt",
"privacy.quote.disabled": "{visibility} – Zitieren deaktiviert",
"privacy.quote.limited": "{visibility} – nur Follower",
"privacy.unlisted.additional": "Das Verhalten ist wie bei „Öffentlich“, jedoch gibt es einige Einschränkungen. Der Beitrag wird nicht in „Live-Feeds“, „Erkunden“, Hashtags oder über die Mastodon-Suchfunktion auffindbar sein – selbst wenn die zugehörige Einstellung aktiviert wurde.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Benachrichtigungen",
"tabs_bar.publish": "Neuer Beitrag",
"tabs_bar.search": "Suche",
+ "tag.remove": "Entfernen",
"terms_of_service.effective_as_of": "Gültig ab {date}",
"terms_of_service.title": "Nutzungsbedingungen",
"terms_of_service.upcoming_changes_on": "Anstehende Änderungen am {date}",
diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json
index e31e6f3bde0..d60509ba345 100644
--- a/app/javascript/mastodon/locales/el.json
+++ b/app/javascript/mastodon/locales/el.json
@@ -14,6 +14,8 @@
"about.powered_by": "Αποκεντρωμένα μέσα κοινωνικής δικτύωσης που βασίζονται στο {mastodon}",
"about.rules": "Κανόνες διακομιστή",
"account.account_note_header": "Προσωπική σημείωση",
+ "account.activity": "Δραστηριότητα",
+ "account.add_note": "Προσθέστε μια προσωπική σημείωση",
"account.add_or_remove_from_list": "Προσθήκη ή Αφαίρεση από λίστες",
"account.badges.bot": "Αυτοματοποιημένος",
"account.badges.group": "Ομάδα",
@@ -27,6 +29,7 @@
"account.direct": "Ιδιωτική επισήμανση @{name}",
"account.disable_notifications": "Σταμάτα να με ειδοποιείς όταν δημοσιεύει ο @{name}",
"account.domain_blocking": "Αποκλείεται ο τομέας",
+ "account.edit_note": "Επεξεργασία προσωπικής σημείωσης",
"account.edit_profile": "Επεξεργασία προφίλ",
"account.edit_profile_short": "Επεξεργασία",
"account.enable_notifications": "Ειδοποίησέ με όταν δημοσιεύει ο @{name}",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Ετικέτες",
"account.featured_tags.last_status_at": "Τελευταία ανάρτηση στις {date}",
"account.featured_tags.last_status_never": "Καμία ανάρτηση",
+ "account.filters.all": "Όλη η δραστηριότητα",
+ "account.filters.boosts_toggle": "Εμφάνιση ενισχύσεων",
+ "account.filters.posts_boosts": "Αναρτήσεις και ενισχύσεις",
+ "account.filters.posts_only": "Αναρτήσεις",
+ "account.filters.posts_replies": "Αναρτήσεις και απαντήσεις",
+ "account.filters.replies_toggle": "Εμφάνιση απαντήσεων",
"account.follow": "Ακολούθησε",
"account.follow_back": "Ακολούθησε και εσύ",
"account.follow_back_short": "Ακολούθησε και εσύ",
@@ -57,9 +66,10 @@
"account.go_to_profile": "Μετάβαση στο προφίλ",
"account.hide_reblogs": "Απόκρυψη ενισχύσεων από @{name}",
"account.in_memoriam": "Εις μνήμην.",
+ "account.joined_long": "Έγινε μέλος {date}",
"account.joined_short": "Έγινε μέλος",
"account.languages": "Αλλαγή εγγεγραμμένων γλωσσών",
- "account.link_verified_on": "Η ιδιοκτησία αυτού του συνδέσμου ελέχθηκε στις {date}",
+ "account.link_verified_on": "Η ιδιοκτησία αυτού του συνδέσμου ελέγχθηκε στις {date}",
"account.locked_info": "Η κατάσταση απορρήτου αυτού του λογαριασμού έχει ρυθμιστεί σε κλειδωμένη. Ο ιδιοκτήτης αξιολογεί χειροκίνητα ποιος μπορεί να τον ακολουθήσει.",
"account.media": "Πολυμέσα",
"account.mention": "Επισήμανε @{name}",
@@ -71,6 +81,14 @@
"account.muting": "Σίγαση",
"account.mutual": "Ακολουθείτε ο ένας τον άλλο",
"account.no_bio": "Δεν υπάρχει περιγραφή.",
+ "account.node_modal.callout": "Οι προσωπικές σημειώσεις είναι ορατές μόνο σε εσάς.",
+ "account.node_modal.edit_title": "Επεξεργασία προσωπικής σημείωσης",
+ "account.node_modal.error_unknown": "Δεν ήταν δυνατή η αποθήκευση της σημείωσης",
+ "account.node_modal.field_label": "Προσωπική σημείωση",
+ "account.node_modal.save": "Αποθήκευση",
+ "account.node_modal.title": "Προσθέστε μια προσωπική σημείωση",
+ "account.note.edit_button": "Επεξεργασία",
+ "account.note.title": "Προσωπική σημείωση (ορατή μόνο σε εσάς)",
"account.open_original_page": "Άνοιγμα αυθεντικής σελίδας",
"account.posts": "Αναρτήσεις",
"account.posts_with_replies": "Αναρτήσεις και απαντήσεις",
@@ -90,6 +108,8 @@
"account.unmute": "Άρση σίγασης @{name}",
"account.unmute_notifications_short": "Σίγαση ειδοποιήσεων",
"account.unmute_short": "Κατάργηση σίγασης",
+ "account_fields_modal.close": "Κλείσιμο",
+ "account_fields_modal.title": "Πληροφορίες {name}",
"account_note.placeholder": "Κάνε κλικ για να προσθέσεις σημείωση",
"admin.dashboard.daily_retention": "Ποσοστό χρηστών που παραμένουν μετά την εγγραφή, ανά ημέρα",
"admin.dashboard.monthly_retention": "Ποσοστό χρηστών που παραμένουν μετά την εγγραφή, ανά μήνα",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Κλείσιμο",
"bundle_modal_error.message": "Κάτι πήγε στραβά κατά τη φόρτωση αυτής της οθόνης.",
"bundle_modal_error.retry": "Δοκίμασε ξανά",
+ "callout.dismiss": "Απόρριψη",
"carousel.current": "Διαφάνεια {current, number} / {max, number}",
"carousel.slide": "Διαφάνεια {current, number} από {max, number}",
"closed_registrations.other_server_instructions": "Καθώς το Mastodon είναι αποκεντρωμένο, μπορείς να δημιουργήσεις λογαριασμό σε άλλον διακομιστή αλλά να συνεχίσεις να αλληλεπιδράς με αυτόν.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Βρες άλλον διακομιστή",
"closed_registrations_modal.preamble": "Το Mastodon είναι αποκεντρωμένο, οπότε ανεξάρτητα από το πού θα δημιουργήσεις τον λογαριασμό σου, μπορείς να ακολουθήσεις και να αλληλεπιδράσεις με οποιονδήποτε σε αυτόν τον διακομιστή. Μπορείς ακόμη και να κάνεις τον δικό σου!",
"closed_registrations_modal.title": "Εγγραφή στο Mastodon",
+ "collections.collection_description": "Περιγραφή",
+ "collections.collection_name": "Όνομα",
+ "collections.collection_topic": "Θέμα",
+ "collections.create_a_collection_hint": "Δημιουργήστε μια συλλογή για να προτείνετε ή να μοιραστείτε τους αγαπημένους σας λογαριασμούς με άλλους.",
+ "collections.create_collection": "Δημιουργία συλλογής",
+ "collections.delete_collection": "Διαγραφή συλλογής",
+ "collections.description_length_hint": "Όριο 100 χαρακτήρων",
+ "collections.error_loading_collections": "Παρουσιάστηκε σφάλμα κατά την προσπάθεια φόρτωσης των συλλογών σας.",
+ "collections.mark_as_sensitive": "Σήμανση ως ευαίσθητο",
+ "collections.mark_as_sensitive_hint": "Κρύβει την περιγραφή και τους λογαριασμούς της συλλογής πίσω από μια προειδοποίηση περιεχομένου. Το όνομα της συλλογής θα είναι ακόμη ορατό.",
+ "collections.name_length_hint": "Όριο 100 χαρακτήρων",
+ "collections.no_collections_yet": "Καμία συλλογή ακόμη.",
+ "collections.topic_hint": "Προσθέστε μια ετικέτα που βοηθά άλλους να κατανοήσουν το κύριο θέμα αυτής της συλλογής.",
+ "collections.view_collection": "Προβολή συλλογής",
"column.about": "Σχετικά με",
"column.blocks": "Αποκλεισμένοι χρήστες",
"column.bookmarks": "Σελιδοδείκτες",
+ "column.collections": "Οι συλλογές μου",
"column.community": "Τοπική ροή",
+ "column.create_collection": "Δημιουργία συλλογής",
"column.create_list": "Δημιουργία λίστας",
"column.direct": "Ιδιωτικές επισημάνσεις",
"column.directory": "Περιήγηση στα προφίλ",
"column.domain_blocks": "Αποκλεισμένοι τομείς",
+ "column.edit_collection": "Επεξεργασία συλλογής",
"column.edit_list": "Επεξεργασία λίστας",
"column.favourites": "Αγαπημένα",
"column.firehose": "Ζωντανές ροές",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Διαγραφή",
"confirmations.delete.message": "Σίγουρα θες να διαγράψεις αυτή την ανάρτηση;",
"confirmations.delete.title": "Διαγραφή ανάρτησης;",
+ "confirmations.delete_collection.confirm": "Διαγραφή",
+ "confirmations.delete_collection.message": "Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.",
+ "confirmations.delete_collection.title": "Διαγραφή \"{name}\";",
"confirmations.delete_list.confirm": "Διαγραφή",
"confirmations.delete_list.message": "Σίγουρα θες να διαγράψεις οριστικά αυτή τη λίστα;",
"confirmations.delete_list.title": "Διαγραφή λίστας;",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Ανάρτηση {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Καρφιτσωμένη Ανάρτηση} other {Καρφιτσωμένες Αναρτήσεις}}",
"featured_carousel.slide": "Ανάρτηση {current, number} από {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Αυτή η κατηγορία φίλτρων δεν ισχύει για το περιεχόμενο εντός του οποίου προσπελάσατε αυτή την ανάρτηση. Αν θέλετε να φιλτραριστεί η ανάρτηση και εντός αυτού του πλαισίου, θα πρέπει να τροποποιήσετε το φίλτρο.",
"filter_modal.added.context_mismatch_title": "Ασυμφωνία περιεχομένου!",
"filter_modal.added.expired_explanation": "Αυτή η κατηγορία φίλτρων έχει λήξει, πρέπει να αλλάξετε την ημερομηνία λήξης για να ισχύσει.",
@@ -451,11 +493,12 @@
"footer.source_code": "Προβολή πηγαίου κώδικα",
"footer.status": "Κατάσταση",
"footer.terms_of_service": "Όροι υπηρεσίας",
+ "form_field.optional": "(προαιρετικό)",
"generic.saved": "Αποθηκεύτηκε",
"getting_started.heading": "Ας ξεκινήσουμε",
"hashtag.admin_moderation": "Άνοιγμα διεπαφής συντονισμού για το #{name}",
"hashtag.browse": "Περιήγηση αναρτήσεων με #{hashtag}",
- "hashtag.browse_from_account": "Περιήγηση αναρτήσεων από @{name} σε #{hashtag}",
+ "hashtag.browse_from_account": "Περιήγηση αναρτήσεων από @{name} με #{hashtag}",
"hashtag.column_header.tag_mode.all": "και {additional}",
"hashtag.column_header.tag_mode.any": "ή {additional}",
"hashtag.column_header.tag_mode.none": "χωρίς {additional}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# νέο στοιχείο} other {# νέα στοιχεία}}",
"loading_indicator.label": "Φόρτωση…",
"media_gallery.hide": "Απόκρυψη",
+ "minicard.more_items": "+{count}",
"moved_to_account_banner.text": "Ο λογαριασμός σου {disabledAccount} είναι προσωρινά απενεργοποιημένος επειδή μεταφέρθηκες στον {movedToAccount}.",
"mute_modal.hide_from_notifications": "Απόκρυψη από ειδοποιήσεις",
"mute_modal.hide_options": "Απόκρυψη επιλογών",
@@ -786,7 +830,7 @@
"privacy.private.short": "Ακόλουθοι",
"privacy.public.long": "Όλοι εντός και εκτός του Mastodon",
"privacy.public.short": "Δημόσια",
- "privacy.quote.anyone": "{visibility}, ο καθένας μπορεί να παραθέσει",
+ "privacy.quote.anyone": "{visibility}, παραθέσεις επιτρεπτές",
"privacy.quote.disabled": "{visibility}, παραθέσεις απενεργοποιημένες",
"privacy.quote.limited": "{visibility}, παραθέσεις περιορισμένες",
"privacy.unlisted.additional": "Αυτό συμπεριφέρεται ακριβώς όπως το δημόσιο, εκτός από το ότι η ανάρτηση δεν θα εμφανιστεί σε ζωντανές ροές ή ετικέτες, εξερεύνηση ή αναζήτηση στο Mastodon, ακόμη και αν το έχεις επιλέξει για τον λογαριασμό σου.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Ειδοποιήσεις",
"tabs_bar.publish": "Νέα Ανάρτηση",
"tabs_bar.search": "Αναζήτηση",
+ "tag.remove": "Αφαίρεση",
"terms_of_service.effective_as_of": "Ενεργό από {date}",
"terms_of_service.title": "Όροι Παροχής Υπηρεσιών",
"terms_of_service.upcoming_changes_on": "Επερχόμενες αλλαγές στις {date}",
diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json
index 0863df66995..84c656903ca 100644
--- a/app/javascript/mastodon/locales/en-GB.json
+++ b/app/javascript/mastodon/locales/en-GB.json
@@ -14,6 +14,8 @@
"about.powered_by": "Decentralised social media powered by {mastodon}",
"about.rules": "Server rules",
"account.account_note_header": "Personal note",
+ "account.activity": "Activity",
+ "account.add_note": "Add a personal note",
"account.add_or_remove_from_list": "Add or Remove from lists",
"account.badges.bot": "Automated",
"account.badges.group": "Group",
@@ -27,6 +29,7 @@
"account.direct": "Privately mention @{name}",
"account.disable_notifications": "Stop notifying me when @{name} posts",
"account.domain_blocking": "Blocking domain",
+ "account.edit_note": "Edit personal note",
"account.edit_profile": "Edit profile",
"account.edit_profile_short": "Edit",
"account.enable_notifications": "Notify me when @{name} posts",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Hashtags",
"account.featured_tags.last_status_at": "Last post on {date}",
"account.featured_tags.last_status_never": "No posts",
+ "account.filters.all": "All activity",
+ "account.filters.boosts_toggle": "Show boosts",
+ "account.filters.posts_boosts": "Posts and boosts",
+ "account.filters.posts_only": "Posts",
+ "account.filters.posts_replies": "Posts and replies",
+ "account.filters.replies_toggle": "Show replies",
"account.follow": "Follow",
"account.follow_back": "Follow back",
"account.follow_back_short": "Follow back",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Go to profile",
"account.hide_reblogs": "Hide boosts from @{name}",
"account.in_memoriam": "In Memoriam.",
+ "account.joined_long": "Joined on {date}",
"account.joined_short": "Joined",
"account.languages": "Change subscribed languages",
"account.link_verified_on": "Ownership of this link was checked on {date}",
@@ -71,6 +81,14 @@
"account.muting": "Muting",
"account.mutual": "You follow each other",
"account.no_bio": "No description provided.",
+ "account.node_modal.callout": "Personal notes are visible only to you.",
+ "account.node_modal.edit_title": "Edit personal note",
+ "account.node_modal.error_unknown": "Could not save the note",
+ "account.node_modal.field_label": "Personal Note",
+ "account.node_modal.save": "Save",
+ "account.node_modal.title": "Add a personal note",
+ "account.note.edit_button": "Edit",
+ "account.note.title": "Personal note (visible only to you)",
"account.open_original_page": "Open original page",
"account.posts": "Posts",
"account.posts_with_replies": "Posts and replies",
@@ -90,6 +108,8 @@
"account.unmute": "Unmute @{name}",
"account.unmute_notifications_short": "Unmute notifications",
"account.unmute_short": "Unmute",
+ "account_fields_modal.close": "Close",
+ "account_fields_modal.title": "{name}'s info",
"account_note.placeholder": "Click to add note",
"admin.dashboard.daily_retention": "User retention rate by day after sign-up",
"admin.dashboard.monthly_retention": "User retention rate by month after sign-up",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Close",
"bundle_modal_error.message": "Something went wrong while loading this screen.",
"bundle_modal_error.retry": "Try again",
+ "callout.dismiss": "Dismiss",
"carousel.current": "Slide {current, number} / {max, number}",
"carousel.slide": "Slide {current, number} of {max, number}",
"closed_registrations.other_server_instructions": "Since Mastodon is decentralised, you can create an account on another server and still interact with this one.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Find another server",
"closed_registrations_modal.preamble": "Mastodon is decentralised, so no matter where you create your account, you will be able to follow and interact with anyone on this server. You can even self-host it!",
"closed_registrations_modal.title": "Signing up on Mastodon",
+ "collections.collection_description": "Description",
+ "collections.collection_name": "Name",
+ "collections.collection_topic": "Topic",
+ "collections.create_a_collection_hint": "Create a collection to recommend or share your favourite accounts with others.",
+ "collections.create_collection": "Create collection",
+ "collections.delete_collection": "Delete collection",
+ "collections.description_length_hint": "100 characters limit",
+ "collections.error_loading_collections": "There was an error when trying to load your collections.",
+ "collections.mark_as_sensitive": "Mark as sensitive",
+ "collections.mark_as_sensitive_hint": "Hides the collection's description and accounts behind a content warning. The collection name will still be visible.",
+ "collections.name_length_hint": "100 characters limit",
+ "collections.no_collections_yet": "No collections yet.",
+ "collections.topic_hint": "Add a hashtag that helps others understand the main topic of this collection.",
+ "collections.view_collection": "View collection",
"column.about": "About",
"column.blocks": "Blocked users",
"column.bookmarks": "Bookmarks",
+ "column.collections": "My collections",
"column.community": "Local timeline",
+ "column.create_collection": "Create collection",
"column.create_list": "Create list",
"column.direct": "Private mentions",
"column.directory": "Browse profiles",
"column.domain_blocks": "Blocked domains",
+ "column.edit_collection": "Edit collection",
"column.edit_list": "Edit list",
"column.favourites": "Favourites",
"column.firehose": "Live feeds",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Delete",
"confirmations.delete.message": "Are you sure you want to delete this post?",
"confirmations.delete.title": "Delete post?",
+ "confirmations.delete_collection.confirm": "Delete",
+ "confirmations.delete_collection.message": "This action cannot be undone.",
+ "confirmations.delete_collection.title": "Delete \"{name}\"?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"confirmations.delete_list.title": "Delete list?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Post {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Pinned Post} other {Pinned Posts}}",
"featured_carousel.slide": "Post {current, number} of {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
"filter_modal.added.context_mismatch_title": "Context mismatch!",
"filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
@@ -451,6 +493,7 @@
"footer.source_code": "View source code",
"footer.status": "Status",
"footer.terms_of_service": "Terms of service",
+ "form_field.optional": "(optional)",
"generic.saved": "Saved",
"getting_started.heading": "Getting started",
"hashtag.admin_moderation": "Open moderation interface for #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# new item} other {# new items}}",
"loading_indicator.label": "Loading…",
"media_gallery.hide": "Hide",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +830,7 @@
"privacy.private.short": "Followers",
"privacy.public.long": "Anyone on and off Mastodon",
"privacy.public.short": "Public",
- "privacy.quote.anyone": "{visibility}, anyone can quote",
+ "privacy.quote.anyone": "{visibility}, quotes allowed",
"privacy.quote.disabled": "{visibility}, quotes disabled",
"privacy.quote.limited": "{visibility}, quotes limited",
"privacy.unlisted.additional": "This behaves exactly like public, except the post will not appear in live feeds or hashtags, explore, or Mastodon search, even if you are opted-in account-wide.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notifications",
"tabs_bar.publish": "New Post",
"tabs_bar.search": "Search",
+ "tag.remove": "Remove",
"terms_of_service.effective_as_of": "Effective as of {date}",
"terms_of_service.title": "Terms of Service",
"terms_of_service.upcoming_changes_on": "Upcoming changes on {date}",
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index f1ab23570af..49448c4f335 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -14,6 +14,8 @@
"about.powered_by": "Decentralized social media powered by {mastodon}",
"about.rules": "Server rules",
"account.account_note_header": "Personal note",
+ "account.activity": "Activity",
+ "account.add_note": "Add a personal note",
"account.add_or_remove_from_list": "Add or Remove from lists",
"account.badges.bot": "Automated",
"account.badges.group": "Group",
@@ -27,6 +29,7 @@
"account.direct": "Privately mention @{name}",
"account.disable_notifications": "Stop notifying me when @{name} posts",
"account.domain_blocking": "Blocking domain",
+ "account.edit_note": "Edit personal note",
"account.edit_profile": "Edit profile",
"account.edit_profile_short": "Edit",
"account.enable_notifications": "Notify me when @{name} posts",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Hashtags",
"account.featured_tags.last_status_at": "Last post on {date}",
"account.featured_tags.last_status_never": "No posts",
+ "account.filters.all": "All activity",
+ "account.filters.boosts_toggle": "Show boosts",
+ "account.filters.posts_boosts": "Posts and boosts",
+ "account.filters.posts_only": "Posts",
+ "account.filters.posts_replies": "Posts and replies",
+ "account.filters.replies_toggle": "Show replies",
"account.follow": "Follow",
"account.follow_back": "Follow back",
"account.follow_back_short": "Follow back",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Go to profile",
"account.hide_reblogs": "Hide boosts from @{name}",
"account.in_memoriam": "In Memoriam.",
+ "account.joined_long": "Joined on {date}",
"account.joined_short": "Joined",
"account.languages": "Change subscribed languages",
"account.link_verified_on": "Ownership of this link was checked on {date}",
@@ -71,6 +81,14 @@
"account.muting": "Muting",
"account.mutual": "You follow each other",
"account.no_bio": "No description provided.",
+ "account.node_modal.callout": "Personal notes are visible only to you.",
+ "account.node_modal.edit_title": "Edit personal note",
+ "account.node_modal.error_unknown": "Could not save the note",
+ "account.node_modal.field_label": "Personal Note",
+ "account.node_modal.save": "Save",
+ "account.node_modal.title": "Add a personal note",
+ "account.note.edit_button": "Edit",
+ "account.note.title": "Personal note (visible only to you)",
"account.open_original_page": "Open original page",
"account.posts": "Posts",
"account.posts_with_replies": "Posts and replies",
@@ -90,6 +108,8 @@
"account.unmute": "Unmute @{name}",
"account.unmute_notifications_short": "Unmute notifications",
"account.unmute_short": "Unmute",
+ "account_fields_modal.close": "Close",
+ "account_fields_modal.title": "{name}'s info",
"account_note.placeholder": "Click to add note",
"admin.dashboard.daily_retention": "User retention rate by day after sign-up",
"admin.dashboard.monthly_retention": "User retention rate by month after sign-up",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Close",
"bundle_modal_error.message": "Something went wrong while loading this screen.",
"bundle_modal_error.retry": "Try again",
+ "callout.dismiss": "Dismiss",
"carousel.current": "Slide {current, number} / {max, number}",
"carousel.slide": "Slide {current, number} of {max, number}",
"closed_registrations.other_server_instructions": "Since Mastodon is decentralized, you can create an account on another server and still interact with this one.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Find another server",
"closed_registrations_modal.preamble": "Mastodon is decentralized, so no matter where you create your account, you will be able to follow and interact with anyone on this server. You can even self-host it!",
"closed_registrations_modal.title": "Signing up on Mastodon",
+ "collections.collection_description": "Description",
+ "collections.collection_name": "Name",
+ "collections.collection_topic": "Topic",
+ "collections.create_a_collection_hint": "Create a collection to recommend or share your favourite accounts with others.",
+ "collections.create_collection": "Create collection",
+ "collections.delete_collection": "Delete collection",
+ "collections.description_length_hint": "100 characters limit",
+ "collections.error_loading_collections": "There was an error when trying to load your collections.",
+ "collections.mark_as_sensitive": "Mark as sensitive",
+ "collections.mark_as_sensitive_hint": "Hides the collection's description and accounts behind a content warning. The collection name will still be visible.",
+ "collections.name_length_hint": "100 characters limit",
+ "collections.no_collections_yet": "No collections yet.",
+ "collections.topic_hint": "Add a hashtag that helps others understand the main topic of this collection.",
+ "collections.view_collection": "View collection",
"column.about": "About",
"column.blocks": "Blocked users",
"column.bookmarks": "Bookmarks",
+ "column.collections": "My collections",
"column.community": "Local timeline",
+ "column.create_collection": "Create collection",
"column.create_list": "Create list",
"column.direct": "Private mentions",
"column.directory": "Browse profiles",
"column.domain_blocks": "Blocked domains",
+ "column.edit_collection": "Edit collection",
"column.edit_list": "Edit list",
"column.favourites": "Favorites",
"column.firehose": "Live feeds",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Delete",
"confirmations.delete.message": "Are you sure you want to delete this post?",
"confirmations.delete.title": "Delete post?",
+ "confirmations.delete_collection.confirm": "Delete",
+ "confirmations.delete_collection.message": "This action cannot be undone.",
+ "confirmations.delete_collection.title": "Delete \"{name}\"?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"confirmations.delete_list.title": "Delete list?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Post {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Pinned Post} other {Pinned Posts}}",
"featured_carousel.slide": "Post {current, number} of {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
"filter_modal.added.context_mismatch_title": "Context mismatch!",
"filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
@@ -451,6 +493,7 @@
"footer.source_code": "View source code",
"footer.status": "Status",
"footer.terms_of_service": "Terms of service",
+ "form_field.optional": "(optional)",
"generic.saved": "Saved",
"getting_started.heading": "Getting started",
"hashtag.admin_moderation": "Open moderation interface for #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# new item} other {# new items}}",
"loading_indicator.label": "Loading…",
"media_gallery.hide": "Hide",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +830,7 @@
"privacy.private.short": "Followers",
"privacy.public.long": "Anyone on and off Mastodon",
"privacy.public.short": "Public",
- "privacy.quote.anyone": "{visibility}, anyone can quote",
+ "privacy.quote.anyone": "{visibility}, quotes allowed",
"privacy.quote.disabled": "{visibility}, quotes disabled",
"privacy.quote.limited": "{visibility}, quotes limited",
"privacy.unlisted.additional": "This behaves exactly like public, except the post will not appear in live feeds or hashtags, explore, or Mastodon search, even if you are opted-in account-wide.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notifications",
"tabs_bar.publish": "New Post",
"tabs_bar.search": "Search",
+ "tag.remove": "Remove",
"terms_of_service.effective_as_of": "Effective as of {date}",
"terms_of_service.title": "Terms of Service",
"terms_of_service.upcoming_changes_on": "Upcoming changes on {date}",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 23e26b4dd5d..a8d960bc934 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -86,6 +86,7 @@
"account.unmute": "Malsilentigi @{name}",
"account.unmute_notifications_short": "Malsilentigu sciigojn",
"account.unmute_short": "Ne plu silentigi",
+ "account_fields_modal.close": "Fermi",
"account_note.placeholder": "Alklaku por aldoni noton",
"admin.dashboard.daily_retention": "Uzantoretenprocento laŭ tag post registro",
"admin.dashboard.monthly_retention": "Uzantoretenprocento laŭ monato post registro",
@@ -112,6 +113,7 @@
"annual_report.announcement.action_dismiss": "Ne, dankon",
"annual_report.nav_item.badge": "Nova",
"annual_report.shared_page.donate": "Donaci",
+ "annual_report.summary.close": "Fermi",
"annual_report.summary.copy_link": "Kopii ligilon",
"annual_report.summary.highlighted_post.title": "Plej populara afiŝo",
"annual_report.summary.most_used_app.most_used_app": "plej uzita aplikaĵo",
@@ -149,6 +151,9 @@
"closed_registrations_modal.find_another_server": "Trovi alian servilon",
"closed_registrations_modal.preamble": "Mastodon estas malcentraliza, do sendepende de tio, kie vi kreas vian konton, vi povos sekvi kaj komuniki kun ĉiuj ajn el ĉi tiu servilo. Vi eĉ povas mem starigi propran servilon!",
"closed_registrations_modal.title": "Registriĝi en Mastodon",
+ "collections.create_collection": "Krei kolekton",
+ "collections.delete_collection": "Forigi kolekton",
+ "collections.error_loading_collections": "Okazis eraro provante ŝargi viajn kolektojn.",
"column.about": "Pri",
"column.blocks": "Blokitaj uzantoj",
"column.bookmarks": "Legosignoj",
@@ -179,6 +184,7 @@
"community.column_settings.local_only": "Nur loka",
"community.column_settings.media_only": "Nur aŭdovidaĵoj",
"community.column_settings.remote_only": "Nur fora",
+ "compose.error.blank_post": "Afiŝo ne povas esti malplena.",
"compose.language.change": "Ŝanĝi lingvon",
"compose.language.search": "Serĉi lingvojn...",
"compose.published.body": "Afiŝo publikigita.",
@@ -213,6 +219,7 @@
"confirmations.delete_list.title": "Ĉu forigi liston?",
"confirmations.discard_draft.confirm": "Forĵetu kaj daŭrigu",
"confirmations.discard_draft.edit.cancel": "Daŭrigi redaktadon",
+ "confirmations.discard_draft.edit.message": "Daŭrigo forigos ĉiujn ŝanĝojn, kiujn vi faris al la afiŝo, kiun vi nun redaktas.",
"confirmations.discard_draft.edit.title": "Ĉu forĵeti ŝanĝojn al via afiŝo?",
"confirmations.discard_draft.post.cancel": "Daŭrigi malneton",
"confirmations.discard_draft.post.message": "Daŭrigo forigos la afiŝon, kiun vi nun verkas.",
@@ -230,6 +237,8 @@
"confirmations.missing_alt_text.secondary": "Afiŝi ĉiuokaze",
"confirmations.missing_alt_text.title": "Ĉu aldoni alttekston?",
"confirmations.mute.confirm": "Silentigi",
+ "confirmations.private_quote_notify.confirm": "Publikigi afiŝon",
+ "confirmations.private_quote_notify.do_not_show_again": "Ne montru al mi ĉi tiun mesaĝon denove",
"confirmations.quiet_post_quote_info.dismiss": "Ne memorigu min denove",
"confirmations.quiet_post_quote_info.got_it": "Komprenite",
"confirmations.redraft.confirm": "Forigi kaj reskribi",
@@ -336,6 +345,7 @@
"explore.trending_statuses": "Afiŝoj",
"explore.trending_tags": "Kradvortoj",
"featured_carousel.header": "{count, plural, one {Alpinglita afiŝo} other {Alpinglitaj afiŝoj}}",
+ "featured_carousel.slide": "Afiŝo {current, number} de {max, number}",
"filter_modal.added.context_mismatch_explanation": "Ĉi tiu filtrilkategorio ne kongruas kun la kunteksto en kiu vi akcesis ĉi tiun afiŝon. Se vi volas ke la afiŝo estas ankaŭ filtrita en ĉi tiu kunteksto, vi devus redakti la filtrilon.",
"filter_modal.added.context_mismatch_title": "Ne kongruas la kunteksto!",
"filter_modal.added.expired_explanation": "Ĉi tiu filtrilkategorio eksvalidiĝis, vu bezonos ŝanĝi la eksvaliddaton por ĝi.",
@@ -378,6 +388,9 @@
"follow_suggestions.who_to_follow": "Kiun sekvi",
"followed_tags": "Sekvataj kradvortoj",
"footer.about": "Pri",
+ "footer.about_mastodon": "Pri Mastodon",
+ "footer.about_server": "Pri {domain}",
+ "footer.about_this_server": "Pri",
"footer.directory": "Profilujo",
"footer.get_app": "Akiri la apon",
"footer.keyboard_shortcuts": "Fulmoklavoj",
@@ -710,7 +723,6 @@
"privacy.private.short": "Sekvantoj",
"privacy.public.long": "Ĉiujn ajn ĉe kaj ekster Mastodon",
"privacy.public.short": "Publika",
- "privacy.quote.anyone": "{visibility}, iu ajn povas citi",
"privacy.quote.disabled": "{visibility}, malŝaltitaj citaĵoj",
"privacy.quote.limited": "{visibility}, limigitaj citaĵoj",
"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.",
@@ -835,6 +847,7 @@
"status.cancel_reblog_private": "Ne plu diskonigi",
"status.cannot_quote": "Vi ne rajtas citi ĉi tiun afiŝon",
"status.cannot_reblog": "Ĉi tiun afiŝon ne eblas diskonigi",
+ "status.context.show": "Montri",
"status.continued_thread": "Daŭrigis fadenon",
"status.copy": "Kopii la ligilon al la afiŝo",
"status.delete": "Forigi",
diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json
index 670cc70055e..8563cbae817 100644
--- a/app/javascript/mastodon/locales/es-AR.json
+++ b/app/javascript/mastodon/locales/es-AR.json
@@ -14,6 +14,8 @@
"about.powered_by": "Redes sociales descentralizadas con tecnología de {mastodon}",
"about.rules": "Reglas del servidor",
"account.account_note_header": "Nota personal",
+ "account.activity": "Actividad",
+ "account.add_note": "Agregar una nota personal",
"account.add_or_remove_from_list": "Agregar o quitar de las listas",
"account.badges.bot": "Automatizada",
"account.badges.group": "Grupo",
@@ -27,6 +29,7 @@
"account.direct": "Mención privada a @{name}",
"account.disable_notifications": "Dejar de notificarme cuando @{name} envíe mensajes",
"account.domain_blocking": "Dominio bloqueado",
+ "account.edit_note": "Editar nota personal",
"account.edit_profile": "Editar perfil",
"account.edit_profile_short": "Editar",
"account.enable_notifications": "Notificarme cuando @{name} envíe mensajes",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Etiquetas",
"account.featured_tags.last_status_at": "Último mensaje: {date}",
"account.featured_tags.last_status_never": "Sin mensajes",
+ "account.filters.all": "Toda la actividad",
+ "account.filters.boosts_toggle": "Mostrar adhesiones",
+ "account.filters.posts_boosts": "Mensajes y adhesiones",
+ "account.filters.posts_only": "Mensajes",
+ "account.filters.posts_replies": "Mensajes y respuestas",
+ "account.filters.replies_toggle": "Mostrar respuestas",
"account.follow": "Seguir",
"account.follow_back": "Seguir",
"account.follow_back_short": "Seguir",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Ir al perfil",
"account.hide_reblogs": "Ocultar adhesiones de @{name}",
"account.in_memoriam": "Cuenta conmemorativa.",
+ "account.joined_long": "En este servidor desde el {date}",
"account.joined_short": "En este servidor desde el",
"account.languages": "Cambiar idiomas suscritos",
"account.link_verified_on": "La propiedad de este enlace fue verificada el {date}",
@@ -71,6 +81,14 @@
"account.muting": "Silenciada",
"account.mutual": "Se siguen mutuamente",
"account.no_bio": "Sin descripción provista.",
+ "account.node_modal.callout": "Las notas personales son visibles solo para vos.",
+ "account.node_modal.edit_title": "Editar nota personal",
+ "account.node_modal.error_unknown": "No se pudo guardar la nota",
+ "account.node_modal.field_label": "Nota personal",
+ "account.node_modal.save": "Guardar",
+ "account.node_modal.title": "Agregar una nota personal",
+ "account.note.edit_button": "Editar",
+ "account.note.title": "Nota personal (visible solo para vos)",
"account.open_original_page": "Abrir página original",
"account.posts": "Mensajes",
"account.posts_with_replies": "Mnsjs y resp. públicas",
@@ -90,6 +108,8 @@
"account.unmute": "Dejar de silenciar a @{name}",
"account.unmute_notifications_short": "Dejar de silenciar notificaciones",
"account.unmute_short": "Dejar de silenciar",
+ "account_fields_modal.close": "Cerrar",
+ "account_fields_modal.title": "Información de {name}",
"account_note.placeholder": "Hacé clic par agregar una nota",
"admin.dashboard.daily_retention": "Tasa de retención de usuarios por día, después del registro",
"admin.dashboard.monthly_retention": "Tasa de retención de usuarios por mes, después del registro",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Cerrar",
"bundle_modal_error.message": "Algo salió mal al cargar esta pantalla.",
"bundle_modal_error.retry": "Intentá de nuevo",
+ "callout.dismiss": "Descartar",
"carousel.current": "Diapositiva {current, number} / {max, number}",
"carousel.slide": "Diapositiva {current, number} de {max, number}",
"closed_registrations.other_server_instructions": "Ya que Mastodon es descentralizado, podés crearte una cuenta en otro servidor y todavía interactuar con éste.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Buscar otro servidor",
"closed_registrations_modal.preamble": "Mastodon es descentralizado, por lo que no importa dónde creés tu cuenta, podrás seguir e interactuar con cualquier persona en este servidor. ¡Incluso podés montar tu propio servidor!",
"closed_registrations_modal.title": "Registrarse en Mastodon",
+ "collections.collection_description": "Descripción",
+ "collections.collection_name": "Nombre",
+ "collections.collection_topic": "Tema",
+ "collections.create_a_collection_hint": "Creá una colección para recomendar o compartir tus cuentas favoritas con otras personas.",
+ "collections.create_collection": "Crear colección",
+ "collections.delete_collection": "Eliminar colección",
+ "collections.description_length_hint": "Límite de 100 caracteres",
+ "collections.error_loading_collections": "Hubo un error al intentar cargar tus colecciones.",
+ "collections.mark_as_sensitive": "Marcar como sensible",
+ "collections.mark_as_sensitive_hint": "Oculta la descripción de la colección y las cuentas detrás de una advertencia de contenido. El nombre de la colección seguirá siendo visible.",
+ "collections.name_length_hint": "Límite de 100 caracteres",
+ "collections.no_collections_yet": "No hay colecciones aún.",
+ "collections.topic_hint": "Agregá una etiqueta que ayude a otros usuarios a entender el tema principal de esta colección.",
+ "collections.view_collection": "Abrir colección",
"column.about": "Información",
"column.blocks": "Usuarios bloqueados",
"column.bookmarks": "Marcadores",
+ "column.collections": "Mis colecciones",
"column.community": "Línea temporal local",
+ "column.create_collection": "Crear colección",
"column.create_list": "Crear lista",
"column.direct": "Menciones privadas",
"column.directory": "Explorar perfiles",
"column.domain_blocks": "Dominios bloqueados",
+ "column.edit_collection": "Editar colección",
"column.edit_list": "Editar lista",
"column.favourites": "Favoritos",
"column.firehose": "Líneas temporales en vivo",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Eliminar",
"confirmations.delete.message": "¿Estás seguro que querés eliminar este mensaje?",
"confirmations.delete.title": "¿Eliminar mensaje?",
+ "confirmations.delete_collection.confirm": "Eliminar",
+ "confirmations.delete_collection.message": "Esta acción no se puede deshacer.",
+ "confirmations.delete_collection.title": "¿Eliminar «{name}»?",
"confirmations.delete_list.confirm": "Eliminar",
"confirmations.delete_list.message": "¿Estás seguro que querés eliminar permanentemente esta lista?",
"confirmations.delete_list.title": "¿Eliminar lista?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Mensaje {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Mensaje fijado} other {Mensajes fijados}}",
"featured_carousel.slide": "Mensaje {current, number} de {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Esta categoría de filtro no se aplica al contexto en el que accediste a este mensaje. Si querés que el mensaje sea filtrado también en este contexto, vas a tener que editar el filtro.",
"filter_modal.added.context_mismatch_title": "¡El contexto no coincide!",
"filter_modal.added.expired_explanation": "Esta categoría de filtro caducó; vas a necesitar cambiar la fecha de caducidad para que se aplique.",
@@ -451,6 +493,7 @@
"footer.source_code": "Ver código fuente",
"footer.status": "Estado",
"footer.terms_of_service": "Términos del servicio",
+ "form_field.optional": "(opcional)",
"generic.saved": "Guardado",
"getting_started.heading": "Inicio de Mastodon",
"hashtag.admin_moderation": "Abrir interface de moderación para #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# elemento nuevo} other {# elementos nuevos}}",
"loading_indicator.label": "Cargando…",
"media_gallery.hide": "Ocultar",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +830,7 @@
"privacy.private.short": "Seguidores",
"privacy.public.long": "Cualquier persona dentro y fuera de Mastodon",
"privacy.public.short": "Público",
- "privacy.quote.anyone": "{visibility}, todos pueden citar",
+ "privacy.quote.anyone": "{visibility}, citas permitidas",
"privacy.quote.disabled": "{visibility}, citas deshabilitadas",
"privacy.quote.limited": "{visibility}, citas limitadas",
"privacy.unlisted.additional": "Esto se comporta exactamente igual que con la configuración de privacidad de mensaje «Público», excepto que el mensaje no aparecerá en las líneas temporales en vivo, ni en las etiquetas, ni en la línea temporal «Explorá», ni en la búsqueda de Mastodon; incluso si optaste por hacer tu cuenta visible.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notificaciones",
"tabs_bar.publish": "Nuevo mensaje",
"tabs_bar.search": "Buscar",
+ "tag.remove": "Quitar",
"terms_of_service.effective_as_of": "Efectivo a partir de {date}",
"terms_of_service.title": "Términos del servicio",
"terms_of_service.upcoming_changes_on": "Próximos cambios el {date}",
diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json
index db87e024631..425c0f058c8 100644
--- a/app/javascript/mastodon/locales/es-MX.json
+++ b/app/javascript/mastodon/locales/es-MX.json
@@ -14,6 +14,8 @@
"about.powered_by": "Medio social descentralizado con tecnología de {mastodon}",
"about.rules": "Reglas del servidor",
"account.account_note_header": "Nota personal",
+ "account.activity": "Actividad",
+ "account.add_note": "Añadir una nota personal",
"account.add_or_remove_from_list": "Agregar o eliminar de las listas",
"account.badges.bot": "Automatizada",
"account.badges.group": "Grupo",
@@ -27,6 +29,7 @@
"account.direct": "Mención privada @{name}",
"account.disable_notifications": "Dejar de notificarme cuando @{name} publique algo",
"account.domain_blocking": "Bloqueando dominio",
+ "account.edit_note": "Editar nota personal",
"account.edit_profile": "Editar perfil",
"account.edit_profile_short": "Editar",
"account.enable_notifications": "Notificarme cuando @{name} publique algo",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Etiquetas",
"account.featured_tags.last_status_at": "Última publicación el {date}",
"account.featured_tags.last_status_never": "Sin publicaciones",
+ "account.filters.all": "Toda la actividad",
+ "account.filters.boosts_toggle": "Mostrar impulsos",
+ "account.filters.posts_boosts": "Publicaciones e impulsos",
+ "account.filters.posts_only": "Publicaciones",
+ "account.filters.posts_replies": "Publicaciones y respuestas",
+ "account.filters.replies_toggle": "Mostrar respuestas",
"account.follow": "Seguir",
"account.follow_back": "Seguir también",
"account.follow_back_short": "Seguir también",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Ir al perfil",
"account.hide_reblogs": "Ocultar impulsos de @{name}",
"account.in_memoriam": "En memoria.",
+ "account.joined_long": "Se unión el {date}",
"account.joined_short": "Se unió",
"account.languages": "Cambiar idiomas suscritos",
"account.link_verified_on": "El proprietario de este enlace fue comprobado el {date}",
@@ -71,6 +81,14 @@
"account.muting": "Silenciando",
"account.mutual": "Se siguen el uno al otro",
"account.no_bio": "Sin biografía.",
+ "account.node_modal.callout": "Las notas personales solo son visibles para ti.",
+ "account.node_modal.edit_title": "Editar nota personal",
+ "account.node_modal.error_unknown": "No se pudo guardar la nota",
+ "account.node_modal.field_label": "Nota personal",
+ "account.node_modal.save": "Guardar",
+ "account.node_modal.title": "Añadir una nota personal",
+ "account.note.edit_button": "Editar",
+ "account.note.title": "Nota personal (visible solo para ti)",
"account.open_original_page": "Abrir página original",
"account.posts": "Publicaciones",
"account.posts_with_replies": "Publicaciones y respuestas",
@@ -90,6 +108,8 @@
"account.unmute": "Dejar de silenciar a @{name}",
"account.unmute_notifications_short": "Dejar de silenciar notificaciones",
"account.unmute_short": "Dejar de silenciar",
+ "account_fields_modal.close": "Cerrar",
+ "account_fields_modal.title": "Información de {name}",
"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",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Cerrar",
"bundle_modal_error.message": "Algo ha fallado al cargar esta pantalla.",
"bundle_modal_error.retry": "Inténtalo de nuevo",
+ "callout.dismiss": "Descartar",
"carousel.current": "Diapositiva {current, number} / {max, number}",
"carousel.slide": "Diapositiva {current, number} de {max, number}",
"closed_registrations.other_server_instructions": "Como Mastodon es descentralizado, puedes crear una cuenta en otro servidor y seguir interactuando con este.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Buscar otro servidor",
"closed_registrations_modal.preamble": "Mastodon es descentralizado, por lo que no importa dónde crees tu cuenta, podrás seguir e interactuar con cualquier persona en este servidor. ¡Incluso puedes alojarlo tú mismo!",
"closed_registrations_modal.title": "Registrarse en Mastodon",
+ "collections.collection_description": "Descripción",
+ "collections.collection_name": "Nombre",
+ "collections.collection_topic": "Tema",
+ "collections.create_a_collection_hint": "Crea una colección para recomendar o compartir tus cuentas favoritas con otras personas.",
+ "collections.create_collection": "Crear colección",
+ "collections.delete_collection": "Eliminar colección",
+ "collections.description_length_hint": "Limitado a 100 caracteres",
+ "collections.error_loading_collections": "Se produjo un error al intentar cargar tus colecciones.",
+ "collections.mark_as_sensitive": "Marcar como sensible",
+ "collections.mark_as_sensitive_hint": "Oculta la descripción y las cuentas de la colección detrás de una advertencia de contenido. El nombre de la colección seguirá siendo visible.",
+ "collections.name_length_hint": "Limitado a 100 caracteres",
+ "collections.no_collections_yet": "No hay colecciones todavía.",
+ "collections.topic_hint": "Agrega una etiqueta que ayude a los demás a comprender el tema principal de esta colección.",
+ "collections.view_collection": "Ver colección",
"column.about": "Acerca de",
"column.blocks": "Usuarios bloqueados",
"column.bookmarks": "Marcadores",
+ "column.collections": "Mis colecciones",
"column.community": "Cronología local",
+ "column.create_collection": "Crear colección",
"column.create_list": "Crear lista",
"column.direct": "Menciones privadas",
"column.directory": "Buscar perfiles",
"column.domain_blocks": "Dominios ocultados",
+ "column.edit_collection": "Editar colección",
"column.edit_list": "Editar lista",
"column.favourites": "Favoritos",
"column.firehose": "Feeds en vivo",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Eliminar",
"confirmations.delete.message": "¿Estás seguro de que quieres borrar esta publicación?",
"confirmations.delete.title": "¿Deseas eliminar la publicación?",
+ "confirmations.delete_collection.confirm": "Eliminar",
+ "confirmations.delete_collection.message": "Esta acción no se puede deshacer.",
+ "confirmations.delete_collection.title": "¿Eliminar \"{name}\"?",
"confirmations.delete_list.confirm": "Eliminar",
"confirmations.delete_list.message": "¿Estás seguro de que quieres eliminar esta lista de forma permanente?",
"confirmations.delete_list.title": "¿Deseas eliminar la lista?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Publicación {current, number} / {max, number}",
"featured_carousel.header": "{count, plural,one {Publicación fijada}other {Publicaciones fijadas}}",
"featured_carousel.slide": "Publicación {current, number} de {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Esta categoría de filtro no se aplica al contexto en el que has accedido a esta publlicación. Si quieres que la publicación sea filtrada también en este contexto, tendrás que editar el filtro.",
"filter_modal.added.context_mismatch_title": "¡El contexto no coincide!",
"filter_modal.added.expired_explanation": "Esta categoría de filtro ha caducado, necesitaras cambiar la fecha de caducidad para que se aplique.",
@@ -451,6 +493,7 @@
"footer.source_code": "Ver código fuente",
"footer.status": "Estado",
"footer.terms_of_service": "Condiciones del servicio",
+ "form_field.optional": "(opcional)",
"generic.saved": "Guardado",
"getting_started.heading": "Primeros pasos",
"hashtag.admin_moderation": "Abrir interfaz de moderación para #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}",
"loading_indicator.label": "Cargando…",
"media_gallery.hide": "Ocultar",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +830,7 @@
"privacy.private.short": "Seguidores",
"privacy.public.long": "Cualquiera dentro y fuera de Mastodon",
"privacy.public.short": "Público",
- "privacy.quote.anyone": "{visibility}, cualquiera puede citar",
+ "privacy.quote.anyone": "{visibility}, citas permitidas",
"privacy.quote.disabled": "{visibility}, citas desactivadas",
"privacy.quote.limited": "{visibility}, citas limitadas",
"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.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notificaciones",
"tabs_bar.publish": "Nueva publicación",
"tabs_bar.search": "Buscar",
+ "tag.remove": "Eliminar",
"terms_of_service.effective_as_of": "En vigor a partir del {date}",
"terms_of_service.title": "Condiciones del servicio",
"terms_of_service.upcoming_changes_on": "Próximos cambios el {date}",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 2b7d1905350..990fdf64274 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -14,6 +14,8 @@
"about.powered_by": "Redes sociales descentralizadas con tecnología de {mastodon}",
"about.rules": "Reglas del servidor",
"account.account_note_header": "Nota personal",
+ "account.activity": "Actividad",
+ "account.add_note": "Añadir una nota personal",
"account.add_or_remove_from_list": "Agregar o eliminar de listas",
"account.badges.bot": "Automatizada",
"account.badges.group": "Grupo",
@@ -27,6 +29,7 @@
"account.direct": "Mención privada a @{name}",
"account.disable_notifications": "Dejar de notificarme cuando @{name} publique algo",
"account.domain_blocking": "Bloqueando dominio",
+ "account.edit_note": "Eidtar nota personal",
"account.edit_profile": "Editar perfil",
"account.edit_profile_short": "Editar",
"account.enable_notifications": "Notificarme cuando @{name} publique algo",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Etiquetas",
"account.featured_tags.last_status_at": "Última publicación el {date}",
"account.featured_tags.last_status_never": "Sin publicaciones",
+ "account.filters.all": "Toda la actividad",
+ "account.filters.boosts_toggle": "Mostrar impulsos",
+ "account.filters.posts_boosts": "Publicaciones e impulsos",
+ "account.filters.posts_only": "Publicaciones",
+ "account.filters.posts_replies": "Publicaciones y respuestas",
+ "account.filters.replies_toggle": "Mostrar respuestas",
"account.follow": "Seguir",
"account.follow_back": "Seguir también",
"account.follow_back_short": "Seguir también",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Ir al perfil",
"account.hide_reblogs": "Ocultar impulsos de @{name}",
"account.in_memoriam": "Cuenta conmemorativa.",
+ "account.joined_long": "Se unió el {date}",
"account.joined_short": "Se unió",
"account.languages": "Cambiar idiomas suscritos",
"account.link_verified_on": "La propiedad de este enlace fue verificada el {date}",
@@ -71,6 +81,14 @@
"account.muting": "Silenciando",
"account.mutual": "Os seguís mutuamente",
"account.no_bio": "Sin biografía.",
+ "account.node_modal.callout": "Las notas personales solo son visibles para ti.",
+ "account.node_modal.edit_title": "Editar nota personal",
+ "account.node_modal.error_unknown": "No se pudo guardar la nota",
+ "account.node_modal.field_label": "Nota Personal",
+ "account.node_modal.save": "Guardar",
+ "account.node_modal.title": "Añadir una nota personal",
+ "account.note.edit_button": "Editar",
+ "account.note.title": "Nota personal (visible solo para ti)",
"account.open_original_page": "Abrir página original",
"account.posts": "Publicaciones",
"account.posts_with_replies": "Publicaciones y respuestas",
@@ -90,6 +108,8 @@
"account.unmute": "Dejar de silenciar a @{name}",
"account.unmute_notifications_short": "Dejar de silenciar notificaciones",
"account.unmute_short": "Dejar de silenciar",
+ "account_fields_modal.close": "Cerrar",
+ "account_fields_modal.title": "Información de {name}",
"account_note.placeholder": "Haz clic para añadir nota",
"admin.dashboard.daily_retention": "Tasa de retención de usuarios por día después del registro",
"admin.dashboard.monthly_retention": "Tasa de retención de usuarios por mes después del registro",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Cerrar",
"bundle_modal_error.message": "Ha habido algún error mientras cargábamos esta pantalla.",
"bundle_modal_error.retry": "Inténtalo de nuevo",
+ "callout.dismiss": "Descartar",
"carousel.current": "Diapositiva {current, number} / {max, number}",
"carousel.slide": "Diapositiva {current, number} de {max, number}",
"closed_registrations.other_server_instructions": "Como Mastodon es descentralizado, puedes crear una cuenta en otro servidor y seguir interactuando con este.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Buscar otro servidor",
"closed_registrations_modal.preamble": "Mastodon es descentralizado, por lo que no importa dónde crees tu cuenta, podrás seguir e interactuar con cualquier persona en este servidor. ¡Incluso puedes alojarlo tú mismo!",
"closed_registrations_modal.title": "Registrarse en Mastodon",
+ "collections.collection_description": "Descripción",
+ "collections.collection_name": "Nombre",
+ "collections.collection_topic": "Tema",
+ "collections.create_a_collection_hint": "Crea una colección para recomendar o compartir tus cuentas favoritas con otros.",
+ "collections.create_collection": "Crear colección",
+ "collections.delete_collection": "Eliminar colección",
+ "collections.description_length_hint": "Limitado a 100 caracteres",
+ "collections.error_loading_collections": "Se ha producido un error al intentar cargar tus colecciones.",
+ "collections.mark_as_sensitive": "Marcar como sensible",
+ "collections.mark_as_sensitive_hint": "Oculta la descripción de la colección y las cuentas detrás de una advertencia de contenido. El nombre de la colección seguirá siendo visible.",
+ "collections.name_length_hint": "Limitado a 100 caracteres",
+ "collections.no_collections_yet": "Aún no hay colecciones.",
+ "collections.topic_hint": "Añadir una etiqueta que ayude a otros a entender el tema principal de esta colección.",
+ "collections.view_collection": "Ver colección",
"column.about": "Acerca de",
"column.blocks": "Usuarios bloqueados",
"column.bookmarks": "Marcadores",
+ "column.collections": "Mis colecciones",
"column.community": "Cronología local",
+ "column.create_collection": "Crear colección",
"column.create_list": "Crear lista",
"column.direct": "Menciones privadas",
"column.directory": "Buscar perfiles",
"column.domain_blocks": "Dominios bloqueados",
+ "column.edit_collection": "Editar colección",
"column.edit_list": "Editar lista",
"column.favourites": "Favoritos",
"column.firehose": "Cronologías",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Eliminar",
"confirmations.delete.message": "¿Estás seguro de que quieres borrar esta publicación?",
"confirmations.delete.title": "¿Eliminar publicación?",
+ "confirmations.delete_collection.confirm": "Eliminar",
+ "confirmations.delete_collection.message": "Esta acción no se puede deshacer.",
+ "confirmations.delete_collection.title": "¿Eliminar \"{name}\"?",
"confirmations.delete_list.confirm": "Eliminar",
"confirmations.delete_list.message": "¿Seguro que quieres borrar esta lista permanentemente?",
"confirmations.delete_list.title": "¿Eliminar lista?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Publicación {current, number} / {max, number}",
"featured_carousel.header": "{count, plural,one {Publicación fijada} other {Publicaciones fijadas}}",
"featured_carousel.slide": "Publicación {current, number} de {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Esta categoría de filtro no se aplica al contexto en el que ha accedido a esta publlicación. Si quieres que la publicación sea filtrada también en este contexto, tendrás que editar el filtro.",
"filter_modal.added.context_mismatch_title": "¡El contexto no coincide!",
"filter_modal.added.expired_explanation": "Esta categoría de filtro ha caducado, tendrás que cambiar la fecha de caducidad para que se aplique.",
@@ -451,6 +493,7 @@
"footer.source_code": "Ver código fuente",
"footer.status": "Estado",
"footer.terms_of_service": "Términos del servicio",
+ "form_field.optional": "(opcional)",
"generic.saved": "Guardado",
"getting_started.heading": "Primeros pasos",
"hashtag.admin_moderation": "Abrir interfaz de moderación para #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}",
"loading_indicator.label": "Cargando…",
"media_gallery.hide": "Ocultar",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +830,7 @@
"privacy.private.short": "Seguidores",
"privacy.public.long": "Visible por todo el mundo, dentro y fuera de Mastodon",
"privacy.public.short": "Pública",
- "privacy.quote.anyone": "{visibility}, cualquiera puede citar",
+ "privacy.quote.anyone": "{visibility}, citas permitidas",
"privacy.quote.disabled": "{visibility}, citas deshabilitadas",
"privacy.quote.limited": "{visibility}, citas limitadas",
"privacy.unlisted.additional": "Se comporta exactamente igual que la visibilidad pública, excepto que la publicación no aparecerá en las cronologías públicas o en las etiquetas, la sección de Explorar o la búsqueda de Mastodon, incluso si has habilitado la opción de búsqueda en tu perfil.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notificaciones",
"tabs_bar.publish": "Nueva Publicación",
"tabs_bar.search": "Buscar",
+ "tag.remove": "Eliminar",
"terms_of_service.effective_as_of": "En vigor a partir del {date}",
"terms_of_service.title": "Términos del servicio",
"terms_of_service.upcoming_changes_on": "Próximos cambios el {date}",
diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json
index 854d70b0ce1..263d0b12918 100644
--- a/app/javascript/mastodon/locales/et.json
+++ b/app/javascript/mastodon/locales/et.json
@@ -2,15 +2,15 @@
"about.blocks": "Modereeritavad serverid",
"about.contact": "Kontakt:",
"about.default_locale": "Vaikimisi",
- "about.disclaimer": "Mastodon on tasuta ja vaba tarkvara ning Mastodon gGmbH kaubamärk.",
+ "about.disclaimer": "Mastodon on vaba, tasuta ja avatud lähtekoodiga tarkvara ning Mastodon gGmbH kaubamärk.",
"about.domain_blocks.no_reason_available": "Põhjus on teadmata",
- "about.domain_blocks.preamble": "Mastodon lubab tavaliselt vaadata sisu ning suhelda kasutajatega ükskõik millisest teisest fediversumi serverist. Need on erandid, mis on paika pandud sellel kindlal serveril.",
- "about.domain_blocks.silenced.explanation": "Sa ei näe üldiselt profiile ja sisu sellelt serverilt, kui sa just tahtlikult seda ei otsi või jälgimise moel nõusolekut ei anna.",
+ "about.domain_blocks.preamble": "Mastodon lubab üldiselt vaadata sisu ning suhelda kasutajatega ükskõik millisest teisest födiversumi serverist. Need on erandid, mis kehtivad selles kindlas serveris.",
+ "about.domain_blocks.silenced.explanation": "Sa üldjuhul ei näe profiile ja sisu sellest serverist, kui sa just tahtlikult neid ei otsi või jälgimise moel nõusolekut ei anna.",
"about.domain_blocks.silenced.title": "Piiratud",
- "about.domain_blocks.suspended.explanation": "Mitte mingeid andmeid sellelt serverilt ei töödelda, salvestata ega vahetata, tehes igasuguse interaktsiooni või kirjavahetuse selle serveri kasutajatega võimatuks.",
+ "about.domain_blocks.suspended.explanation": "Mitte mingeid andmeid sellelt serverilt ei töödelda, salvestata ega vahetata, tehes igasuguse suhestumise või infovahetuse selle serveri kasutajatega võimatuks.",
"about.domain_blocks.suspended.title": "Peatatud",
"about.language_label": "Keel",
- "about.not_available": "See info ei ole sellel serveril saadavaks tehtud.",
+ "about.not_available": "See info ei ole selles serveris saadavaks tehtud.",
"about.powered_by": "Hajutatud sotsiaalmeedia, mille taga on {mastodon}",
"about.rules": "Serveri reeglid",
"account.account_note_header": "Isiklik märge",
@@ -18,19 +18,19 @@
"account.badges.bot": "Robot",
"account.badges.group": "Grupp",
"account.block": "Blokeeri @{name}",
- "account.block_domain": "Peida kõik domeenist {domain}",
+ "account.block_domain": "Blokeeri kõik domeenist {domain}",
"account.block_short": "Blokeerimine",
"account.blocked": "Blokeeritud",
"account.blocking": "Blokeeritud kasutaja",
"account.cancel_follow_request": "Võta jälgimistaotlus tagasi",
"account.copy": "Kopeeri profiili link",
"account.direct": "Maini privaatselt @{name}",
- "account.disable_notifications": "Peata teavitused @{name} postitustest",
+ "account.disable_notifications": "Ära teavita, kui @{name} postitab",
"account.domain_blocking": "Blokeeritud domeen",
"account.edit_profile": "Muuda profiili",
"account.edit_profile_short": "Muuda",
- "account.enable_notifications": "Teavita mind @{name} postitustest",
- "account.endorse": "Too profiilil esile",
+ "account.enable_notifications": "Teavita mind, kui {name} postitab",
+ "account.endorse": "Too profiilis esile",
"account.familiar_followers_many": "Jälgijateks {name1}, {name2} ja veel {othersCount, plural, one {üks kasutaja, keda tead} other {# kasutajat, keda tead}}",
"account.familiar_followers_one": "Jälgijaks {name1}",
"account.familiar_followers_two": "Jälgijateks {name1} ja {name2}",
@@ -57,11 +57,12 @@
"account.go_to_profile": "Mine profiilile",
"account.hide_reblogs": "Peida @{name} jagamised",
"account.in_memoriam": "In Memoriam.",
+ "account.joined_long": "Liitus {date}",
"account.joined_short": "Liitus",
"account.languages": "Muuda tellitud keeli",
"account.link_verified_on": "Selle lingi autorsust kontrolliti {date}",
"account.locked_info": "Selle konto privaatsussätteks on lukustatud. Omanik vaatab käsitsi üle, kes teda jälgida saab.",
- "account.media": "Meedia",
+ "account.media": "Meedium",
"account.mention": "Maini @{name}",
"account.moved_to": "{name} on teada andnud, et ta uus konto on nüüd:",
"account.mute": "Summuta @{name}",
@@ -81,20 +82,22 @@
"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": "Lõpeta {name} kasutaja blokeerimine",
+ "account.unblock_domain": "Lõpeta {domain} domeeni blokeerimine",
"account.unblock_domain_short": "Lõpeta blokeerimine",
- "account.unblock_short": "Eemalda blokeering",
+ "account.unblock_short": "Lõpeta blokeerimine",
"account.unendorse": "Ära kuva profiilil",
- "account.unfollow": "Jälgid",
+ "account.unfollow": "Ära jälgi",
"account.unmute": "Lõpeta {name} kasutaja summutamine",
"account.unmute_notifications_short": "Lõpeta teavituste summutamine",
"account.unmute_short": "Lõpeta summutamine",
+ "account_fields_modal.close": "Sulge",
+ "account_fields_modal.title": "Kasutaja teave: {name}",
"account_note.placeholder": "Klõpsa märke lisamiseks",
"admin.dashboard.daily_retention": "Kasutajate päevane allesjäämine peale registreerumist",
"admin.dashboard.monthly_retention": "Kasutajate kuine allesjäämine peale registreerumist",
"admin.dashboard.retention.average": "Keskmine",
- "admin.dashboard.retention.cohort": "Registreerumiskuu",
+ "admin.dashboard.retention.cohort": "Liitumiskuu",
"admin.dashboard.retention.cohort_size": "Uued kasutajad",
"admin.impact_report.instance_accounts": "Kontode profiilid, mille see kustutaks",
"admin.impact_report.instance_followers": "Jälgijad, kelle meie kasutajad kaotaks",
@@ -103,11 +106,11 @@
"alert.rate_limited.message": "Palun proovi uuesti pärast {retry_time, time, medium}.",
"alert.rate_limited.title": "Kiiruspiirang",
"alert.unexpected.message": "Tekkis ootamatu viga.",
- "alert.unexpected.title": "Oih!",
- "alt_text_badge.title": "Alternatiivtekst",
- "alt_text_modal.add_alt_text": "Lisa alt-tekst",
+ "alert.unexpected.title": "Vaat kus lops!",
+ "alt_text_badge.title": "Selgitustekst",
+ "alt_text_modal.add_alt_text": "Lisa selgitustekst",
"alt_text_modal.add_text_from_image": "Lisa tekst pildilt",
- "alt_text_modal.cancel": "Tühista",
+ "alt_text_modal.cancel": "Katkesta",
"alt_text_modal.change_thumbnail": "Muuda pisipilti",
"alt_text_modal.describe_for_people_with_hearing_impairments": "Kirjelda seda kuulmispuudega inimeste jaoks…",
"alt_text_modal.describe_for_people_with_visual_impairments": "Kirjelda seda nägemispuudega inimeste jaoks…",
@@ -119,7 +122,7 @@
"annual_report.announcement.description": "Vaata teavet oma suhestumise kohta Mastodonis eelmisel aastal.",
"annual_report.announcement.title": "{year}. aasta Mastodoni kokkuvõte on valmis",
"annual_report.nav_item.badge": "Uus",
- "annual_report.shared_page.donate": "Anneta",
+ "annual_report.shared_page.donate": "Toeta rahaliselt",
"annual_report.shared_page.footer": "Loodud {heart} Mastodoni meeskonna poolt",
"annual_report.shared_page.footer_server_info": "{username} kasutab {domain}-i, üht paljudest kogukondadest, mis toimivad Mastodonil.",
"annual_report.summary.archetype.booster.desc_public": "{name} jätkas postituste otsimist, et neid edendada, tugevdades teisi loojaid täiusliku täpsusega.",
@@ -184,6 +187,7 @@
"bundle_modal_error.close": "Sulge",
"bundle_modal_error.message": "Selle ekraanitäie laadimisel läks midagi valesti.",
"bundle_modal_error.retry": "Proovi uuesti",
+ "callout.dismiss": "Loobu",
"carousel.current": "Slaid {current, number} / {max, number}",
"carousel.slide": "Slaid {current, number} / {max, number}",
"closed_registrations.other_server_instructions": "Kuna Mastodon on detsentraliseeritud, võib konto teha teise serverisse ja sellegipoolest siinse kontoga suhelda.",
@@ -191,9 +195,16 @@
"closed_registrations_modal.find_another_server": "Leia teine server",
"closed_registrations_modal.preamble": "Mastodon on detsentraliseeritud, mis tähendab, et konto võib luua ükskõik kuhu, kuid ikkagi saab jälgida ja suhelda igaühega sellel serveril. Võib isegi oma serveri püsti panna!",
"closed_registrations_modal.title": "Mastodoni registreerumine",
+ "collections.create_a_collection_hint": "Soovitamaks oma lemmikuid teistele kasutajatele lisa asjakohane kogumik.",
+ "collections.create_collection": "Loo kogumik",
+ "collections.delete_collection": "Kustuta kogumik",
+ "collections.error_loading_collections": "Sinu kogumike laadimisel tekkis viga.",
+ "collections.no_collections_yet": "Kogumikke veel pole.",
+ "collections.view_collection": "Vaata kogumikku",
"column.about": "Teave",
"column.blocks": "Blokeeritud kasutajad",
"column.bookmarks": "Järjehoidjad",
+ "column.collections": "Minu kogumikud",
"column.community": "Kohalik ajajoon",
"column.create_list": "Loo loend",
"column.direct": "Privaatsed mainimised",
@@ -210,7 +221,7 @@
"column.lists": "Loetelud",
"column.mutes": "Summutatud kasutajad",
"column.notifications": "Teated",
- "column.pins": "Kinnitatud postitused",
+ "column.pins": "Esiletõstetud postitused",
"column.public": "Föderatiivne ajajoon",
"column_back_button.label": "Tagasi",
"column_header.hide_settings": "Peida sätted",
@@ -451,6 +462,7 @@
"footer.source_code": "Lähtekood",
"footer.status": "Olek",
"footer.terms_of_service": "Kasutustingimused",
+ "form_field.optional": "(valikuline)",
"generic.saved": "Salvestatud",
"getting_started.heading": "Alustamine",
"hashtag.admin_moderation": "Ava modereerimisliides #{name} jaoks",
@@ -534,7 +546,7 @@
"keyboard_shortcuts.my_profile": "Ava oma profiil",
"keyboard_shortcuts.notifications": "Ava teadete veerg",
"keyboard_shortcuts.open_media": "Ava meedia",
- "keyboard_shortcuts.pinned": "Ava kinnitatud postituste loetelu",
+ "keyboard_shortcuts.pinned": "Ava esiletõstetud postituste loend",
"keyboard_shortcuts.profile": "Ava autori profiil",
"keyboard_shortcuts.quote": "Tsiteeri postitust",
"keyboard_shortcuts.reply": "Vasta postitusele",
@@ -589,6 +601,7 @@
"load_pending": "{count, plural, one {# uus kirje} other {# uut kirjet}}",
"loading_indicator.label": "Laadimine…",
"media_gallery.hide": "Peida",
+ "minicard.more_items": "+{count}",
"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",
@@ -767,7 +780,7 @@
"onboarding.profile.upload_avatar": "Laadi üles profiilipilt",
"onboarding.profile.upload_header": "Laadi üles profiili päis",
"password_confirmation.exceeds_maxlength": "Salasõnakinnitus on pikem kui salasõna maksimumpikkus",
- "password_confirmation.mismatching": "Salasõnakinnitus ei sobi kokku",
+ "password_confirmation.mismatching": "Salasõnad ei klapi",
"picture_in_picture.restore": "Pane tagasi",
"poll.closed": "Suletud",
"poll.refresh": "Värskenda",
@@ -786,7 +799,7 @@
"privacy.private.short": "Jälgijad",
"privacy.public.long": "Nii kasutajad kui mittekasutajad",
"privacy.public.short": "Avalik",
- "privacy.quote.anyone": "{visibility}, kõik võivad tsiteerida",
+ "privacy.quote.anyone": "{visibility}, tsiteerimine on lubatud",
"privacy.quote.disabled": "{visibility}, tsiteerimine pole lubatud",
"privacy.quote.limited": "{visibility}, tsiteerimine on piiratud",
"privacy.unlisted.additional": "See on olemuselt küll avalik, aga postitus ei ilmu voogudes ega teemaviidetes, lehitsedes ega Mastodoni otsingus, isegi kui konto on seadistustes avalik.",
diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json
index 306e24e59f9..fb50eff98b0 100644
--- a/app/javascript/mastodon/locales/eu.json
+++ b/app/javascript/mastodon/locales/eu.json
@@ -785,7 +785,6 @@
"privacy.private.short": "Jarraitzaileak",
"privacy.public.long": "Mastodonen dagoen edo ez dagoen edonor",
"privacy.public.short": "Publikoa",
- "privacy.quote.anyone": "{visibility}, edonork aipa dezake",
"privacy.quote.disabled": "{visibility}, aipuak desgaituta",
"privacy.quote.limited": "{visibility}, aipuak mugatuta",
"privacy.unlisted.additional": "Aukera honek publiko modua bezala funtzionatzen du, baina argitalpena ez da agertuko zuzeneko jarioetan edo traoletan, \"Arakatu\" atalean edo Mastodonen bilaketan, nahiz eta kontua zabaltzeko onartu duzun.",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 110f8a71536..9501be8b939 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -785,7 +785,6 @@
"privacy.private.short": "پیگیرندگان",
"privacy.public.long": "هرکسی در و بیرون از ماستودون",
"privacy.public.short": "عمومی",
- "privacy.quote.anyone": "{visibility}، هرکسی میتواند نقل کند",
"privacy.quote.disabled": "{visibility}، نقلها از کار افتاده",
"privacy.quote.limited": "{visibility}، نقلها محدود شده",
"privacy.unlisted.additional": "درست مثل عمومی رفتار میکند؛ جز این که فرسته در برچسبها یا خوراکهای زنده، کشف یا جستوجوی ماستودون ظاهر نخواهد شد. حتا اگر کلیّت نمایهتان اجازه داده باشد.",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index c0cd9a77cd5..fb3c6b4d79c 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -14,6 +14,8 @@
"about.powered_by": "Hajautetun sosiaalisen median tarjoaa {mastodon}",
"about.rules": "Palvelimen säännöt",
"account.account_note_header": "Henkilökohtainen muistiinpano",
+ "account.activity": "Toiminta",
+ "account.add_note": "Lisää henkilökohtainen muistiinpano",
"account.add_or_remove_from_list": "Lisää tai poista listoista",
"account.badges.bot": "Botti",
"account.badges.group": "Ryhmä",
@@ -27,6 +29,7 @@
"account.direct": "Mainitse @{name} yksityisesti",
"account.disable_notifications": "Lopeta ilmoittamasta minulle, kun @{name} julkaisee",
"account.domain_blocking": "Verkkotunnus estetty",
+ "account.edit_note": "Muokkaa henkilökohtaista muistiinpanoa",
"account.edit_profile": "Muokkaa profiilia",
"account.edit_profile_short": "Muokkaa",
"account.enable_notifications": "Ilmoita minulle, kun @{name} julkaisee",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Aihetunnisteet",
"account.featured_tags.last_status_at": "Viimeisin julkaisu {date}",
"account.featured_tags.last_status_never": "Ei julkaisuja",
+ "account.filters.all": "Kaikki toiminta",
+ "account.filters.boosts_toggle": "Näytä tehostukset",
+ "account.filters.posts_boosts": "Julkaisut ja tehostukset",
+ "account.filters.posts_only": "Julkaisut",
+ "account.filters.posts_replies": "Julkaisut ja vastaukset",
+ "account.filters.replies_toggle": "Näytä vastaukset",
"account.follow": "Seuraa",
"account.follow_back": "Seuraa takaisin",
"account.follow_back_short": "Seuraa takaisin",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Siirry profiiliin",
"account.hide_reblogs": "Piilota käyttäjän @{name} tehostukset",
"account.in_memoriam": "Muistoissamme.",
+ "account.joined_long": "Liittynyt {date}",
"account.joined_short": "Liittynyt",
"account.languages": "Vaihda tilattuja kieliä",
"account.link_verified_on": "Linkin omistus tarkistettiin {date}",
@@ -71,6 +81,14 @@
"account.muting": "Mykistetty",
"account.mutual": "Seuraatte toisianne",
"account.no_bio": "Kuvausta ei ole annettu.",
+ "account.node_modal.callout": "Henkilökohtaiset muistiinpanot näkyvät vain sinulle.",
+ "account.node_modal.edit_title": "Muokkaa henkilökohtaista muistiinpanoa",
+ "account.node_modal.error_unknown": "Muistiinpanoa ei voitu tallentaa",
+ "account.node_modal.field_label": "Henkilökohtainen muistiinpano",
+ "account.node_modal.save": "Tallenna",
+ "account.node_modal.title": "Lisää henkilökohtainen muistiinpano",
+ "account.note.edit_button": "Muokkaa",
+ "account.note.title": "Henkilökohtainen muistiinpano (näkyy vain sinulle)",
"account.open_original_page": "Avaa alkuperäinen sivu",
"account.posts": "Julkaisut",
"account.posts_with_replies": "Julkaisut ja vastaukset",
@@ -90,6 +108,8 @@
"account.unmute": "Poista käyttäjän @{name} mykistys",
"account.unmute_notifications_short": "Poista ilmoitusten mykistys",
"account.unmute_short": "Poista mykistys",
+ "account_fields_modal.close": "Sulje",
+ "account_fields_modal.title": "Käyttäjän {name} tiedot",
"account_note.placeholder": "Lisää muistiinpano napsauttamalla",
"admin.dashboard.daily_retention": "Käyttäjien pysyvyys päivittäin rekisteröitymisen jälkeen",
"admin.dashboard.monthly_retention": "Käyttäjien pysyvyys kuukausittain rekisteröitymisen jälkeen",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Sulje",
"bundle_modal_error.message": "Jotain meni pieleen tätä näyttöä ladattaessa.",
"bundle_modal_error.retry": "Yritä uudelleen",
+ "callout.dismiss": "Hylkää",
"carousel.current": "Dia {current, number} / {max, number}",
"carousel.slide": "Dia {current, number} / {max, number}",
"closed_registrations.other_server_instructions": "Koska Mastodon on hajautettu, voit luoda tilin toiselle palvelimelle ja olla silti vuorovaikutuksessa tämän kanssa.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Etsi toinen palvelin",
"closed_registrations_modal.preamble": "Mastodon on hajautettu, joten riippumatta siitä, missä luot tilisi, voit seurata ja olla vuorovaikutuksessa kenen tahansa kanssa tällä palvelimella. Voit jopa isännöidä palvelinta!",
"closed_registrations_modal.title": "Rekisteröityminen Mastodoniin",
+ "collections.collection_description": "Kuvaus",
+ "collections.collection_name": "Nimi",
+ "collections.collection_topic": "Aihe",
+ "collections.create_a_collection_hint": "Luomalla kokoelman voit suositella tai jakaa suosikkitilejäsi muiden kanssa.",
+ "collections.create_collection": "Luo kokoelma",
+ "collections.delete_collection": "Poista kokoelma",
+ "collections.description_length_hint": "100 merkin rajoitus",
+ "collections.error_loading_collections": "Kokoelmien latauksessa tapahtui virhe.",
+ "collections.mark_as_sensitive": "Merkitse arkaluonteiseksi",
+ "collections.mark_as_sensitive_hint": "Piilottaa kokoelman kuvauksen ja tilit sisältövaroituksen taakse. Kokoelman nimi jää esiin.",
+ "collections.name_length_hint": "100 merkin rajoitus",
+ "collections.no_collections_yet": "Ei vielä kokoelmia.",
+ "collections.topic_hint": "Lisää aihetunniste, joka auttaa muita ymmärtämään tämän kokelman pääaiheen.",
+ "collections.view_collection": "Näytä kokoelma",
"column.about": "Tietoja",
"column.blocks": "Estetyt käyttäjät",
"column.bookmarks": "Kirjanmerkit",
+ "column.collections": "Omat kokoelmat",
"column.community": "Paikallinen aikajana",
+ "column.create_collection": "Luo kokoelma",
"column.create_list": "Luo lista",
"column.direct": "Yksityismaininnat",
"column.directory": "Selaa profiileja",
"column.domain_blocks": "Estetyt verkkotunnukset",
+ "column.edit_collection": "Muokkaa kokoelmaa",
"column.edit_list": "Muokkaa listaa",
"column.favourites": "Suosikit",
"column.firehose": "Livesyötteet",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Poista",
"confirmations.delete.message": "Haluatko varmasti poistaa tämän julkaisun?",
"confirmations.delete.title": "Poistetaanko julkaisu?",
+ "confirmations.delete_collection.confirm": "Poista",
+ "confirmations.delete_collection.message": "Tätä toimea ei voi peruuttaa.",
+ "confirmations.delete_collection.title": "Poistetaanko ”{name}”?",
"confirmations.delete_list.confirm": "Poista",
"confirmations.delete_list.message": "Haluatko varmasti poistaa tämän listan pysyvästi?",
"confirmations.delete_list.title": "Poistetaanko lista?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Julkaisu {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Kiinnitetty julkaisu} other {Kiinnitetyt julkaisut}}",
"featured_carousel.slide": "Julkaisu {current, number} / {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Tämä suodatinluokka ei koske asiayhteyttä, jossa olet tarkastellut tätä julkaisua. Jos haluat julkaisun suodatettavan myös tässä asiayhteydessä, muokkaa suodatinta.",
"filter_modal.added.context_mismatch_title": "Asiayhteys ei täsmää!",
"filter_modal.added.expired_explanation": "Tämä suodatinluokka on vanhentunut, joten sinun on muutettava viimeistä voimassaolopäivää, jotta suodatusta käytettäisiin.",
@@ -451,6 +493,7 @@
"footer.source_code": "Näytä lähdekoodi",
"footer.status": "Tila",
"footer.terms_of_service": "Käyttöehdot",
+ "form_field.optional": "(valinnainen)",
"generic.saved": "Tallennettu",
"getting_started.heading": "Näin pääset alkuun",
"hashtag.admin_moderation": "Avaa tunnisteen #{name} moderointinäkymä",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# uusi kohde} other {# uutta kohdetta}}",
"loading_indicator.label": "Ladataan…",
"media_gallery.hide": "Piilota",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +830,7 @@
"privacy.private.short": "Seuraajat",
"privacy.public.long": "Kuka tahansa Mastodonissa ja sen ulkopuolella",
"privacy.public.short": "Julkinen",
- "privacy.quote.anyone": "{visibility}, kuka tahansa voi lainata",
+ "privacy.quote.anyone": "{visibility}, lainaukset sallittu",
"privacy.quote.disabled": "{visibility}, lainaukset poissa käytöstä",
"privacy.quote.limited": "{visibility}, lainauksia rajoitettu",
"privacy.unlisted.additional": "Tämä toimii muuten kuin julkinen, mutta julkaisut eivät näy livesyöte-, aihetunniste- tai selausnäkymissä eivätkä Mastodonin hakutuloksissa, vaikka ne olisivat käyttäjätililläsi yleisesti sallittuina.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Ilmoitukset",
"tabs_bar.publish": "Uusi julkaisu",
"tabs_bar.search": "Haku",
+ "tag.remove": "Poista",
"terms_of_service.effective_as_of": "Tulee voimaan {date}",
"terms_of_service.title": "Käyttöehdot",
"terms_of_service.upcoming_changes_on": "Tulevia muutoksia {date}",
diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json
index 52ef3946c51..16861bb5a20 100644
--- a/app/javascript/mastodon/locales/fo.json
+++ b/app/javascript/mastodon/locales/fo.json
@@ -14,6 +14,8 @@
"about.powered_by": "Miðfirra almennur miðil koyrandi á {mastodon}",
"about.rules": "Ambætarareglur",
"account.account_note_header": "Persónlig viðmerking",
+ "account.activity": "Virksemi",
+ "account.add_note": "Legg persónliga notu afturat",
"account.add_or_remove_from_list": "Legg afturat ella tak av listum",
"account.badges.bot": "Bottur",
"account.badges.group": "Bólkur",
@@ -27,6 +29,7 @@
"account.direct": "Umrøð @{name} privat",
"account.disable_notifications": "Ikki boða mær frá, tá @{name} skrivar",
"account.domain_blocking": "Banni økisnavn",
+ "account.edit_note": "Rætta persónliga notu",
"account.edit_profile": "Broyt vanga",
"account.edit_profile_short": "Rætta",
"account.enable_notifications": "Boða mær frá, tá @{name} skrivar",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Frámerki",
"account.featured_tags.last_status_at": "Seinasta strongur skrivaður {date}",
"account.featured_tags.last_status_never": "Einki uppslag",
+ "account.filters.all": "Alt virksemi",
+ "account.filters.boosts_toggle": "Vís stimbranir",
+ "account.filters.posts_boosts": "Postar og stimbranir",
+ "account.filters.posts_only": "Postar",
+ "account.filters.posts_replies": "Postar og svar",
+ "account.filters.replies_toggle": "Vís svar",
"account.follow": "Fylg",
"account.follow_back": "Fylg aftur",
"account.follow_back_short": "Fylg aftur",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Far til vanga",
"account.hide_reblogs": "Fjal stimbran frá @{name}",
"account.in_memoriam": "In memoriam.",
+ "account.joined_long": "Meldaði til {date}",
"account.joined_short": "Gjørdist limur",
"account.languages": "Broyt fylgd mál",
"account.link_verified_on": "Ognarskapur av hesum leinki var eftirkannaður {date}",
@@ -71,6 +81,14 @@
"account.muting": "Doyvir",
"account.mutual": "Tit fylgja hvønn annan",
"account.no_bio": "Lýsing vantar.",
+ "account.node_modal.callout": "Einans tú sær tínar persónligu notur.",
+ "account.node_modal.edit_title": "Rætta persónliga notu",
+ "account.node_modal.error_unknown": "Eydnaðist ikki at goyma notuna",
+ "account.node_modal.field_label": "Persónlig nota",
+ "account.node_modal.save": "Goym",
+ "account.node_modal.title": "Legg persónliga notu afturat",
+ "account.note.edit_button": "Rætta",
+ "account.note.title": "Persónlig nota (einans sjónlig fyri teg)",
"account.open_original_page": "Opna upprunasíðuna",
"account.posts": "Uppsløg",
"account.posts_with_replies": "Uppsløg og svar",
@@ -90,6 +108,8 @@
"account.unmute": "Doyv ikki @{name}",
"account.unmute_notifications_short": "Tendra fráboðanir",
"account.unmute_short": "Doyv ikki",
+ "account_fields_modal.close": "Lat aftur",
+ "account_fields_modal.title": "Upplýsingarnar hjá {name}",
"account_note.placeholder": "Klikka fyri at leggja viðmerking afturat",
"admin.dashboard.daily_retention": "Hvussu nógvir brúkarar eru eftir, síðani tey skrásettu seg, roknað í døgum",
"admin.dashboard.monthly_retention": "Hvussu nógvir brúkarar eru eftir síðani tey skrásettu seg, roknað í mánaðum",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Lat aftur",
"bundle_modal_error.message": "Okkurt gekk galið, tá hendan síðan bleiv innlisin.",
"bundle_modal_error.retry": "Royn umaftur",
+ "callout.dismiss": "Avvís",
"carousel.current": "Glæra {current, number} / {max, number}",
"carousel.slide": "Glæra {current, number} av {max, number}",
"closed_registrations.other_server_instructions": "Av tí at Mastodon er desentraliserað, kanst tú stovna eina kontu á einum øðrum ambætara og framvegis virka saman við hesum ambætaranum.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Finn ein annan ambætara",
"closed_registrations_modal.preamble": "Mastodon er desentraliserað, so óansæð hvar tú stovnar tína kontu, so ber til hjá tær at fylgja og virka saman við einum og hvørjum á hesum ambætaranum. Tað ber enntá til at hýsa tí sjálvi!",
"closed_registrations_modal.title": "At stovna kontu á Mastodon",
+ "collections.collection_description": "Lýsing",
+ "collections.collection_name": "Navn",
+ "collections.collection_topic": "Evni",
+ "collections.create_a_collection_hint": "Ger eitt savn sum kann brúkast til at viðmæla ella deila yndiskontur við øðrum.",
+ "collections.create_collection": "Ger savn",
+ "collections.delete_collection": "Strika savn",
+ "collections.description_length_hint": "Í mesta lagi 100 tekn",
+ "collections.error_loading_collections": "Ein feilur hendi, tá tú royndi at finna fram søvnini hjá tær.",
+ "collections.mark_as_sensitive": "Merk sum viðkvæmt",
+ "collections.mark_as_sensitive_hint": "Fjalið lýsingina av og konturnar hjá savninum aftan fyri eina innihaldsávaring. Savnsnavnið verður framvegis sjónligt.",
+ "collections.name_length_hint": "Í mesta lagi 100 tekn",
+ "collections.no_collections_yet": "Eingi søvn enn.",
+ "collections.topic_hint": "Legg afturat eitt frámerki, sum hjálpir øðrum at skilja høvuðevnið í hesum savninum.",
+ "collections.view_collection": "Vís savn",
"column.about": "Um",
"column.blocks": "Bannaðir brúkarar",
"column.bookmarks": "Bókamerki",
+ "column.collections": "Míni søvn",
"column.community": "Lokal tíðarlinja",
+ "column.create_collection": "Ger savn",
"column.create_list": "Ger lista",
"column.direct": "Privatar umrøður",
"column.directory": "Blaða gjøgnum vangar",
"column.domain_blocks": "Bannað økisnøvn",
+ "column.edit_collection": "Rætta savn",
"column.edit_list": "Broyt lista",
"column.favourites": "Dámdir postar",
"column.firehose": "Beinleiðis rásir",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Strika",
"confirmations.delete.message": "Er tað tilætlað, at tú strikar hetta uppslagið?",
"confirmations.delete.title": "Strika post?",
+ "confirmations.delete_collection.confirm": "Strika",
+ "confirmations.delete_collection.message": "Hendan atgerðin kann ikki angrast.",
+ "confirmations.delete_collection.title": "Strika \"{name}\"?",
"confirmations.delete_list.confirm": "Strika",
"confirmations.delete_list.message": "Ert tú vís/ur í, at tú vilt strika hetta uppslagið?",
"confirmations.delete_list.title": "Strika lista?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Postur {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {festur postur} other {festir postar}}",
"featured_carousel.slide": "Postur {current, number} av {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Hesin filturbólkurin viðvíkur ikki kontekstinum, sum tú hevur fingið atgongd til hendan postin. Ynskir tú at posturin verður filtreraður í hesum kontekstinum eisini, so er neyðugt at tú rættar filtrið.",
"filter_modal.added.context_mismatch_title": "Ósamsvar við kontekst!",
"filter_modal.added.expired_explanation": "Hesin filturbólkurin er útgingin, og tú mást broyta dagfestingina fyri at hann skal virka.",
@@ -451,6 +493,7 @@
"footer.source_code": "Vís keldukotuna",
"footer.status": "Støða",
"footer.terms_of_service": "Tænastutreytir",
+ "form_field.optional": "(valfrítt)",
"generic.saved": "Goymt",
"getting_started.heading": "At byrja",
"hashtag.admin_moderation": "Lat umsjónarmarkamót upp fyri #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# nýtt evni} other {# nýggj evni}}",
"loading_indicator.label": "Innlesur…",
"media_gallery.hide": "Fjal",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +830,7 @@
"privacy.private.short": "Fylgjarar",
"privacy.public.long": "Øll í og uttanfyri Mastodon",
"privacy.public.short": "Alment",
- "privacy.quote.anyone": "{visibility}, øll kunnu sitera",
+ "privacy.quote.anyone": "{visibility}, siteringar loyvdar",
"privacy.quote.disabled": "{visibility}, siteringar óvirknar",
"privacy.quote.limited": "{visibility}, siteringar avmarkaðar",
"privacy.unlisted.additional": "Hetta er júst sum almenn, tó verður posturin ikki vístur í samtíðarrásum ella frámerkjum, rannsakan ella Mastodon leitingum, sjálvt um valið er galdandi fyri alla kontuna.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Fráboðanir",
"tabs_bar.publish": "Nýggjur postur",
"tabs_bar.search": "Leita",
+ "tag.remove": "Burturbein",
"terms_of_service.effective_as_of": "Galdandi frá {date}",
"terms_of_service.title": "Tænastutreytir",
"terms_of_service.upcoming_changes_on": "Komandi broytingar {date}",
diff --git a/app/javascript/mastodon/locales/fr-CA.json b/app/javascript/mastodon/locales/fr-CA.json
index 5cf1c8b4b9f..9205251a892 100644
--- a/app/javascript/mastodon/locales/fr-CA.json
+++ b/app/javascript/mastodon/locales/fr-CA.json
@@ -14,6 +14,8 @@
"about.powered_by": "Réseau social décentralisé propulsé par {mastodon}",
"about.rules": "Règles du serveur",
"account.account_note_header": "Note personnelle",
+ "account.activity": "Activités",
+ "account.add_note": "Ajouter une note personnelle",
"account.add_or_remove_from_list": "Ajouter ou enlever de listes",
"account.badges.bot": "Bot",
"account.badges.group": "Groupe",
@@ -21,24 +23,31 @@
"account.block_domain": "Bloquer le domaine {domain}",
"account.block_short": "Bloquer",
"account.blocked": "Bloqué·e",
- "account.blocking": "Bloqué",
+ "account.blocking": "Bloqué·e",
"account.cancel_follow_request": "Retirer cette demande d'abonnement",
"account.copy": "Copier le lien du profil",
"account.direct": "Mention privée @{name}",
"account.disable_notifications": "Ne plus me notifier quand @{name} publie",
"account.domain_blocking": "Domaine bloqué",
+ "account.edit_note": "Modifier la note personnelle",
"account.edit_profile": "Modifier le profil",
"account.edit_profile_short": "Modifier",
"account.enable_notifications": "Me notifier quand @{name} publie",
"account.endorse": "Inclure sur profil",
"account.familiar_followers_many": "Suivi par {name1}, {name2}, et {othersCount, plural, one {une autre personne que vous suivez} other {# autres personnes que vous suivez}}",
- "account.familiar_followers_one": "Suivi par {name1}",
- "account.familiar_followers_two": "Suivi par {name1} et {name2}",
+ "account.familiar_followers_one": "Suivi·e par {name1}",
+ "account.familiar_followers_two": "Suivi·e par {name1} et {name2}",
"account.featured": "En vedette",
"account.featured.accounts": "Profils",
"account.featured.hashtags": "Hashtags",
"account.featured_tags.last_status_at": "Dernière publication {date}",
"account.featured_tags.last_status_never": "Aucune publication",
+ "account.filters.all": "Toutes les activités",
+ "account.filters.boosts_toggle": "Afficher les partages",
+ "account.filters.posts_boosts": "Messages et partages",
+ "account.filters.posts_only": "Messages",
+ "account.filters.posts_replies": "Messages et réponses",
+ "account.filters.replies_toggle": "Afficher les réponses",
"account.follow": "Suivre",
"account.follow_back": "Suivre en retour",
"account.follow_back_short": "Suivre en retour",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Voir ce profil",
"account.hide_reblogs": "Masquer les boosts de @{name}",
"account.in_memoriam": "En souvenir de",
+ "account.joined_long": "Ici depuis le {date}",
"account.joined_short": "Inscrit·e",
"account.languages": "Changer les langues abonnées",
"account.link_verified_on": "La propriété de ce lien a été vérifiée le {date}",
@@ -71,6 +81,14 @@
"account.muting": "Sourdine",
"account.mutual": "Vous vous suivez mutuellement",
"account.no_bio": "Description manquante.",
+ "account.node_modal.callout": "Les notes personnelles sont ne sont visibles que pour vous.",
+ "account.node_modal.edit_title": "Modifier la note personnelle",
+ "account.node_modal.error_unknown": "Impossible d'enregistrer la note",
+ "account.node_modal.field_label": "Note personnelle",
+ "account.node_modal.save": "Enregistrer",
+ "account.node_modal.title": "Ajouter une note personnelle",
+ "account.note.edit_button": "Modifier",
+ "account.note.title": "Note personnelle (visible uniquement pour vous)",
"account.open_original_page": "Ouvrir la page d'origine",
"account.posts": "Publications",
"account.posts_with_replies": "Publications et réponses",
@@ -90,6 +108,8 @@
"account.unmute": "Ne plus masquer @{name}",
"account.unmute_notifications_short": "Ne plus masquer les notifications",
"account.unmute_short": "Ne plus masquer",
+ "account_fields_modal.close": "Fermer",
+ "account_fields_modal.title": "Infos de {name}",
"account_note.placeholder": "Cliquez pour ajouter une note",
"admin.dashboard.daily_retention": "Taux de rétention des comptes par jour après inscription",
"admin.dashboard.monthly_retention": "Taux de rétention des comptes par mois après inscription",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Fermer",
"bundle_modal_error.message": "Un problème s'est produit lors du chargement de cet écran.",
"bundle_modal_error.retry": "Réessayer",
+ "callout.dismiss": "Rejeter",
"carousel.current": "Diapositive {current, number} / {max, number}",
"carousel.slide": "Diapositive {current, number} de {max, number}",
"closed_registrations.other_server_instructions": "Puisque Mastodon est décentralisé, vous pouvez créer un compte sur un autre serveur et interagir quand même avec celui-ci.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Trouver un autre serveur",
"closed_registrations_modal.preamble": "Mastodon est décentralisé, donc peu importe où vous créez votre compte, vous serez en mesure de suivre et d'interagir avec quiconque sur ce serveur. Vous pouvez même l'héberger vous-même!",
"closed_registrations_modal.title": "S'inscrire sur Mastodon",
+ "collections.collection_description": "Description",
+ "collections.collection_name": "Nom",
+ "collections.collection_topic": "Sujet",
+ "collections.create_a_collection_hint": "Créer une collection pour recommander ou partager vos comptes préférés.",
+ "collections.create_collection": "Créer une collection",
+ "collections.delete_collection": "Supprimer la collection",
+ "collections.description_length_hint": "Maximum 100 caractères",
+ "collections.error_loading_collections": "Une erreur s'est produite durant le chargement de vos collections.",
+ "collections.mark_as_sensitive": "Marquer comme sensible",
+ "collections.mark_as_sensitive_hint": "Masque la description et les comptes de la collection derrière un avertissement de contenu. Le titre reste visible.",
+ "collections.name_length_hint": "Maximum 100 caractères",
+ "collections.no_collections_yet": "Aucune collection pour le moment.",
+ "collections.topic_hint": "Ajouter un hashtag pour aider les autres personnes à comprendre le sujet de la collection.",
+ "collections.view_collection": "Voir la collection",
"column.about": "À propos",
"column.blocks": "Comptes bloqués",
"column.bookmarks": "Signets",
+ "column.collections": "Mes collections",
"column.community": "Fil local",
+ "column.create_collection": "Créer une collection",
"column.create_list": "Créer une liste",
"column.direct": "Mention privée",
"column.directory": "Parcourir les profils",
"column.domain_blocks": "Domaines bloqués",
+ "column.edit_collection": "Modifier la collection",
"column.edit_list": "Modifier la liste",
"column.favourites": "Favoris",
"column.firehose": "Flux en direct",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Supprimer",
"confirmations.delete.message": "Voulez-vous vraiment supprimer cette publication?",
"confirmations.delete.title": "Supprimer le message ?",
+ "confirmations.delete_collection.confirm": "Supprimer",
+ "confirmations.delete_collection.message": "Cette action ne peut pas être annulée.",
+ "confirmations.delete_collection.title": "Supprimer « {name} » ?",
"confirmations.delete_list.confirm": "Supprimer",
"confirmations.delete_list.message": "Voulez-vous vraiment supprimer définitivement cette liste?",
"confirmations.delete_list.title": "Supprimer la liste ?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Message {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Pinned Post} other {Pinned Posts}}",
"featured_carousel.slide": "Message {current, number} de {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Cette catégorie de filtre ne s'applique pas au contexte dans lequel vous avez accédé à cette publication. Si vous voulez que la publication soit filtrée dans ce contexte également, vous devrez modifier le filtre.",
"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.",
@@ -451,6 +493,7 @@
"footer.source_code": "Voir le code source",
"footer.status": "État",
"footer.terms_of_service": "Conditions d’utilisation",
+ "form_field.optional": "(facultatif)",
"generic.saved": "Sauvegardé",
"getting_started.heading": "Pour commencer",
"hashtag.admin_moderation": "Ouvrir l'interface de modération pour #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# nouvel élément} other {# nouveaux éléments}}",
"loading_indicator.label": "Chargement…",
"media_gallery.hide": "Masquer",
+ "minicard.more_items": "+{count}",
"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",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notifications",
"tabs_bar.publish": "Nouveau message",
"tabs_bar.search": "Chercher",
+ "tag.remove": "Supprimer",
"terms_of_service.effective_as_of": "En vigueur à compter du {date}",
"terms_of_service.title": "Conditions d'utilisation",
"terms_of_service.upcoming_changes_on": "Modifications à venir le {date}",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index df03661c9df..49d0de5e177 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -4,7 +4,7 @@
"about.default_locale": "Défaut",
"about.disclaimer": "Mastodon est un logiciel libre, open-source et une marque déposée de Mastodon gGmbH.",
"about.domain_blocks.no_reason_available": "Raison non disponible",
- "about.domain_blocks.preamble": "Mastodon vous permet de visualiser le contenu et d'interagir avec les utilisateurs et utilisatrices de généralement n'importe quel autre serveur dans le fédivers. Voici les exceptions qui ont été faites sur ce serveur.",
+ "about.domain_blocks.preamble": "Mastodon vous permet généralement de visualiser le contenu et d'interagir avec les utilisateurs et utilisatrices de n'importe quel autre serveur dans le fédivers. Voici les exceptions qui ont été faites sur ce serveur.",
"about.domain_blocks.silenced.explanation": "Vous ne verrez généralement pas les profils et le contenu de ce serveur, à moins que vous ne les recherchiez explicitement ou que vous ne choisissiez de les suivre.",
"about.domain_blocks.silenced.title": "Limité",
"about.domain_blocks.suspended.explanation": "Aucune donnée de ce serveur ne sera traitée, enregistrée ou échangée, rendant impossible toute interaction ou communication avec les comptes de ce serveur.",
@@ -14,6 +14,8 @@
"about.powered_by": "Réseau social décentralisé propulsé par {mastodon}",
"about.rules": "Règles du serveur",
"account.account_note_header": "Note personnelle",
+ "account.activity": "Activités",
+ "account.add_note": "Ajouter une note personnelle",
"account.add_or_remove_from_list": "Ajouter ou retirer des listes",
"account.badges.bot": "Bot",
"account.badges.group": "Groupe",
@@ -21,24 +23,31 @@
"account.block_domain": "Bloquer le domaine {domain}",
"account.block_short": "Bloquer",
"account.blocked": "Bloqué·e",
- "account.blocking": "Bloqué",
+ "account.blocking": "Bloqué·e",
"account.cancel_follow_request": "Annuler l'abonnement",
"account.copy": "Copier le lien du profil",
- "account.direct": "Mention privée @{name}",
- "account.disable_notifications": "Ne plus me notifier quand @{name} publie quelque chose",
+ "account.direct": "Mentionner @{name} en privé",
+ "account.disable_notifications": "Ne plus me notifier les publications de @{name}",
"account.domain_blocking": "Domaine bloqué",
+ "account.edit_note": "Modifier la note personnelle",
"account.edit_profile": "Modifier le profil",
"account.edit_profile_short": "Modifier",
- "account.enable_notifications": "Me notifier quand @{name} publie quelque chose",
+ "account.enable_notifications": "Me notifier les publications de @{name}",
"account.endorse": "Recommander sur votre profil",
"account.familiar_followers_many": "Suivi par {name1}, {name2}, et {othersCount, plural, one {une autre personne que vous suivez} other {# autres personnes que vous suivez}}",
- "account.familiar_followers_one": "Suivi par {name1}",
- "account.familiar_followers_two": "Suivi par {name1} et {name2}",
+ "account.familiar_followers_one": "Suivi·e par {name1}",
+ "account.familiar_followers_two": "Suivi·e par {name1} et {name2}",
"account.featured": "En vedette",
"account.featured.accounts": "Profils",
"account.featured.hashtags": "Hashtags",
"account.featured_tags.last_status_at": "Dernier message le {date}",
"account.featured_tags.last_status_never": "Aucun message",
+ "account.filters.all": "Toutes les activités",
+ "account.filters.boosts_toggle": "Afficher les partages",
+ "account.filters.posts_boosts": "Messages et partages",
+ "account.filters.posts_only": "Messages",
+ "account.filters.posts_replies": "Messages et réponses",
+ "account.filters.replies_toggle": "Afficher les réponses",
"account.follow": "Suivre",
"account.follow_back": "Suivre en retour",
"account.follow_back_short": "Suivre en retour",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Voir le profil",
"account.hide_reblogs": "Masquer les partages de @{name}",
"account.in_memoriam": "En mémoire de.",
+ "account.joined_long": "Ici depuis le {date}",
"account.joined_short": "Ici depuis",
"account.languages": "Modifier les langues d'abonnements",
"account.link_verified_on": "La propriété de ce lien a été vérifiée le {date}",
@@ -71,6 +81,14 @@
"account.muting": "Sourdine",
"account.mutual": "Vous vous suivez mutuellement",
"account.no_bio": "Aucune description fournie.",
+ "account.node_modal.callout": "Les notes personnelles sont ne sont visibles que pour vous.",
+ "account.node_modal.edit_title": "Modifier la note personnelle",
+ "account.node_modal.error_unknown": "Impossible d'enregistrer la note",
+ "account.node_modal.field_label": "Note personnelle",
+ "account.node_modal.save": "Enregistrer",
+ "account.node_modal.title": "Ajouter une note personnelle",
+ "account.note.edit_button": "Modifier",
+ "account.note.title": "Note personnelle (visible uniquement pour vous)",
"account.open_original_page": "Ouvrir la page d'origine",
"account.posts": "Messages",
"account.posts_with_replies": "Messages et réponses",
@@ -90,6 +108,8 @@
"account.unmute": "Ne plus masquer @{name}",
"account.unmute_notifications_short": "Réactiver les notifications",
"account.unmute_short": "Ne plus masquer",
+ "account_fields_modal.close": "Fermer",
+ "account_fields_modal.title": "Infos de {name}",
"account_note.placeholder": "Cliquez pour ajouter une note",
"admin.dashboard.daily_retention": "Taux de rétention des utilisateur·rice·s par jour après inscription",
"admin.dashboard.monthly_retention": "Taux de rétention des utilisateur·rice·s par mois après inscription",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Fermer",
"bundle_modal_error.message": "Un problème s'est produit lors du chargement de cet écran.",
"bundle_modal_error.retry": "Réessayer",
+ "callout.dismiss": "Rejeter",
"carousel.current": "Diapositive {current, number} / {max, number}",
"carousel.slide": "Diapositive {current, number} de {max, number}",
"closed_registrations.other_server_instructions": "Puisque Mastodon est décentralisé, vous pouvez créer un compte sur un autre serveur et interagir quand même avec celui-ci.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Trouver un autre serveur",
"closed_registrations_modal.preamble": "Mastodon est décentralisé : peu importe où vous créez votre compte, vous serez en mesure de suivre et d'interagir avec quiconque sur ce serveur. Vous pouvez même l'héberger !",
"closed_registrations_modal.title": "Inscription sur Mastodon",
+ "collections.collection_description": "Description",
+ "collections.collection_name": "Nom",
+ "collections.collection_topic": "Sujet",
+ "collections.create_a_collection_hint": "Créer une collection pour recommander ou partager vos comptes préférés.",
+ "collections.create_collection": "Créer une collection",
+ "collections.delete_collection": "Supprimer la collection",
+ "collections.description_length_hint": "Maximum 100 caractères",
+ "collections.error_loading_collections": "Une erreur s'est produite durant le chargement de vos collections.",
+ "collections.mark_as_sensitive": "Marquer comme sensible",
+ "collections.mark_as_sensitive_hint": "Masque la description et les comptes de la collection derrière un avertissement de contenu. Le titre reste visible.",
+ "collections.name_length_hint": "Maximum 100 caractères",
+ "collections.no_collections_yet": "Aucune collection pour le moment.",
+ "collections.topic_hint": "Ajouter un hashtag pour aider les autres personnes à comprendre le sujet de la collection.",
+ "collections.view_collection": "Voir la collection",
"column.about": "À propos",
"column.blocks": "Utilisateurs bloqués",
"column.bookmarks": "Marque-pages",
+ "column.collections": "Mes collections",
"column.community": "Fil public local",
+ "column.create_collection": "Créer une collection",
"column.create_list": "Créer une liste",
"column.direct": "Mentions privées",
"column.directory": "Parcourir les profils",
"column.domain_blocks": "Domaines bloqués",
+ "column.edit_collection": "Modifier la collection",
"column.edit_list": "Modifier la liste",
"column.favourites": "Favoris",
"column.firehose": "Flux en direct",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Supprimer",
"confirmations.delete.message": "Voulez-vous vraiment supprimer ce message ?",
"confirmations.delete.title": "Supprimer le message ?",
+ "confirmations.delete_collection.confirm": "Supprimer",
+ "confirmations.delete_collection.message": "Cette action ne peut pas être annulée.",
+ "confirmations.delete_collection.title": "Supprimer « {name} » ?",
"confirmations.delete_list.confirm": "Supprimer",
"confirmations.delete_list.message": "Voulez-vous vraiment supprimer définitivement cette liste ?",
"confirmations.delete_list.title": "Supprimer la liste ?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Message {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Pinned Post} other {Pinned Posts}}",
"featured_carousel.slide": "Message {current, number} de {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Cette catégorie de filtre ne s'applique pas au contexte dans lequel vous avez accédé à ce message. Si vous voulez que le message soit filtré dans ce contexte également, vous devrez modifier le filtre.",
"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.",
@@ -451,6 +493,7 @@
"footer.source_code": "Voir le code source",
"footer.status": "État",
"footer.terms_of_service": "Conditions d’utilisation",
+ "form_field.optional": "(facultatif)",
"generic.saved": "Sauvegardé",
"getting_started.heading": "Pour commencer",
"hashtag.admin_moderation": "Ouvrir l'interface de modération pour #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# nouvel élément} other {# nouveaux éléments}}",
"loading_indicator.label": "Chargement…",
"media_gallery.hide": "Masquer",
+ "minicard.more_items": "+{count}",
"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",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notifications",
"tabs_bar.publish": "Nouveau message",
"tabs_bar.search": "Chercher",
+ "tag.remove": "Supprimer",
"terms_of_service.effective_as_of": "En vigueur à compter du {date}",
"terms_of_service.title": "Conditions d'utilisation",
"terms_of_service.upcoming_changes_on": "Modifications à venir le {date}",
diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json
index c3a57d6e09d..f759ddc2c87 100644
--- a/app/javascript/mastodon/locales/ga.json
+++ b/app/javascript/mastodon/locales/ga.json
@@ -57,6 +57,7 @@
"account.go_to_profile": "Téigh go dtí próifíl",
"account.hide_reblogs": "Folaigh moltaí ó @{name}",
"account.in_memoriam": "Ón tseanaimsir.",
+ "account.joined_long": "Chuaigh isteach ar {date}",
"account.joined_short": "Cláraithe",
"account.languages": "Athraigh teangacha foscríofa",
"account.link_verified_on": "Seiceáladh úinéireacht an naisc seo ar {date}",
@@ -90,6 +91,8 @@
"account.unmute": "Díbhalbhaigh @{name}",
"account.unmute_notifications_short": "Díbhalbhaigh fógraí",
"account.unmute_short": "Díbhalbhaigh",
+ "account_fields_modal.close": "Dún",
+ "account_fields_modal.title": "Eolas {name}",
"account_note.placeholder": "Cliceáil chun nóta a chuir leis",
"admin.dashboard.daily_retention": "Ráta coinneála an úsáideora de réir an lae tar éis clárú",
"admin.dashboard.monthly_retention": "Ráta coinneála na n-úsáideoirí de réir na míosa tar éis dóibh clárú",
@@ -184,6 +187,7 @@
"bundle_modal_error.close": "Dún",
"bundle_modal_error.message": "Tharla earráid agus an scáileán seo á lódáil.",
"bundle_modal_error.retry": "Bain triail as arís",
+ "callout.dismiss": "Díbhe",
"carousel.current": "Sleamhnán {current, number} / {max, number}",
"carousel.slide": "Sleamhnán {current, number} of {max, number}",
"closed_registrations.other_server_instructions": "Mar rud díláraithe Mastodon, is féidir leat cuntas a chruthú ar seirbheálaí eile ach fós idirghníomhaigh leis an ceann seo.",
@@ -191,9 +195,16 @@
"closed_registrations_modal.find_another_server": "Faigh freastalaí eile",
"closed_registrations_modal.preamble": "Ós rud é go bhfuil Mastodon díláraithe, is cuma cá háit a chruthaíonn tú do chuntas, beidh tú in ann idirghníomhú le haon duine ar an bhfreastalaí seo agus iad a leanúint. Is féidir fiú é a féin-óstáil!",
"closed_registrations_modal.title": "Cláraigh le Mastodon",
+ "collections.create_a_collection_hint": "Cruthaigh bailiúchán chun do chuntais is fearr leat a mholadh nó a roinnt le daoine eile.",
+ "collections.create_collection": "Cruthaigh bailiúchán",
+ "collections.delete_collection": "Scrios bailiúchán",
+ "collections.error_loading_collections": "Tharla earráid agus iarracht á déanamh do bhailiúcháin a luchtú.",
+ "collections.no_collections_yet": "Gan aon bhailiúcháin fós.",
+ "collections.view_collection": "Féach ar bhailiúchán",
"column.about": "Maidir le",
"column.blocks": "Cuntais choiscthe",
"column.bookmarks": "Leabharmharcanna",
+ "column.collections": "Mo bhailiúcháin",
"column.community": "Amlíne áitiúil",
"column.create_list": "Cruthaigh liosta",
"column.direct": "Luann príobháideach",
@@ -451,6 +462,7 @@
"footer.source_code": "Féach ar an gcód foinseach",
"footer.status": "Stádas",
"footer.terms_of_service": "Téarmaí seirbhíse",
+ "form_field.optional": "(roghnach)",
"generic.saved": "Sábháilte",
"getting_started.heading": "Ag tosú amach",
"hashtag.admin_moderation": "Oscail comhéadan modhnóireachta le haghaidh #{name}",
@@ -589,6 +601,7 @@
"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.hide": "Folaigh",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +799,7 @@
"privacy.private.short": "Leantóirí",
"privacy.public.long": "Duine ar bith ar agus amach Mastodon",
"privacy.public.short": "Poiblí",
- "privacy.quote.anyone": "{visibility}, is féidir le duine ar bith lua",
+ "privacy.quote.anyone": "{visibility}, ceadaítear comharthaí athfhriotail",
"privacy.quote.disabled": "{visibility}, sleachta díchumasaithe",
"privacy.quote.limited": "{visibility}, sleachta teoranta",
"privacy.unlisted.additional": "Iompraíonn sé seo díreach mar a bheadh poiblí, ach amháin ní bheidh an postáil le feiceáil i bhfothaí beo nó i hashtags, in iniúchadh nó i gcuardach Mastodon, fiú má tá tú liostáilte ar fud an chuntais.",
diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json
index 2f4cb44de80..7a250a6c502 100644
--- a/app/javascript/mastodon/locales/gd.json
+++ b/app/javascript/mastodon/locales/gd.json
@@ -113,11 +113,52 @@
"alt_text_modal.describe_for_people_with_visual_impairments": "Mìnich seo dhan fheadhainn air a bheil cion-lèirsinne…",
"alt_text_modal.done": "Deiseil",
"announcement.announcement": "Brath-fios",
+ "annual_report.announcement.action_build": "Cruthaich Wrapstodon dhomh",
+ "annual_report.announcement.action_dismiss": "Na cruthaich",
+ "annual_report.announcement.action_view": "Seall an Wrapstodon agam",
+ "annual_report.announcement.description": "Fidir mar a chaidh leat air Mastodon am bliadhna.",
+ "annual_report.announcement.title": "Tha Wrapstodon {year} air a thighinn",
+ "annual_report.nav_item.badge": "Ùr",
+ "annual_report.shared_page.donate": "Thoir tabhartas",
+ "annual_report.shared_page.footer": "Chaidh a ghintinn le {heart} le sgioba Mhastodon",
+ "annual_report.shared_page.footer_server_info": "Tha {username} a’ cleachdadh {domain}, sin fear de dh’iomadh coimhearsnachd le cumhachd Mastodon.",
+ "annual_report.summary.archetype.booster.desc_public": "Bhiodh {name} an toir air postaichean rim brosnachadh, a’ toirt taic do chruthadairean gu sgiobalta.",
+ "annual_report.summary.archetype.booster.desc_self": "Bhiodh tu an toir air postaichean rim brosnachadh, a’ toirt taic do chruthadairean gu sgiobalta.",
+ "annual_report.summary.archetype.booster.name": "Am Boghadair",
+ "annual_report.summary.archetype.die_drei_fragezeichen": "???",
+ "annual_report.summary.archetype.lurker.desc_public": "Tha fios againn gun robh {name} ann am badeigin, a’ gabhail tlachd à Mastodon air an dòigh fhèin.",
+ "annual_report.summary.archetype.lurker.desc_self": "Tha fios againn gun robh thu ann am badeigin, a’ gabhail tlachd à Mastodon air do dhòigh fhèin.",
+ "annual_report.summary.archetype.lurker.name": "An Socaireach",
+ "annual_report.summary.archetype.oracle.desc_public": "Chruthaich {name} barrachd phostaichean ùra na freagairtean, a’ cumail Mastodon ùr ’s beòthail.",
+ "annual_report.summary.archetype.oracle.desc_self": "Chruthaich thu barrachd phostaichean ùra na freagairtean, a’ cumail Mastodon ùr ’s beòthail.",
+ "annual_report.summary.archetype.oracle.name": "Coinneach Odhar",
+ "annual_report.summary.archetype.pollster.desc_public": "Chruthaich {name} barrachd chunntasan-beachd na seòrsaichean eile de phost, a’ cur ris an iongantas air Mastodon.",
+ "annual_report.summary.archetype.pollster.desc_self": "Chruthaich thu barrachd chunntasan-beachd na seòrsaichean eile de phost, a’ cur ris an iongantas air Mastodon.",
+ "annual_report.summary.archetype.pollster.name": "An Culaidh-iongantais",
+ "annual_report.summary.archetype.replier.desc_public": "Fhreagradh {name} gu tric air postaichean càich, a’ cur deasbadan ùra gu dol air Mastodon.",
+ "annual_report.summary.archetype.replier.desc_self": "Fhreagradh tu gu tric air postaichean càich, a’ cur deasbadan ùra gu dol air Mastodon.",
+ "annual_report.summary.archetype.replier.name": "An Dealan-dè",
+ "annual_report.summary.archetype.reveal": "Nochd am prìomh-choltas a th’ orm",
+ "annual_report.summary.archetype.reveal_description": "Mòran taing airson conaltradh air Mastodon! Thàinig an t-àm a gheibheadh tu a-mach dè am prìomh-choltas a bh’ ort {year}.",
+ "annual_report.summary.archetype.title_public": "Am prìomh-choltas air {name}",
+ "annual_report.summary.archetype.title_self": "Am prìomh-choltas a th’ ort",
+ "annual_report.summary.close": "Dùin",
+ "annual_report.summary.copy_link": "Dèan lethbhreac dhen cheangal",
+ "annual_report.summary.followers.new_followers": "{count, plural, one {neach-leantainn ùr} two {neach-leantainn ùra} few {luchd-leantainn ùra} other {luchd-leantainn ùra}}",
+ "annual_report.summary.highlighted_post.boost_count": "Chaidh am post seo a bhrosnachadh {count, plural, one {# turas} two {# thuras} few {# tursan} other {# turas}}.",
+ "annual_report.summary.highlighted_post.favourite_count": "Chaidh am post seo a chur ris na h-annsachdan {count, plural, one {# turas} two {# thuras} few {# tursan} other {# turas}}.",
+ "annual_report.summary.highlighted_post.reply_count": "Fhuair am post seo {count, plural, one {# fhreagairt} two {# fhreagairt} few {# freagairtean} other {# freagairt}}.",
+ "annual_report.summary.highlighted_post.title": "Am post air an robh fèill as motha",
"annual_report.summary.most_used_app.most_used_app": "an aplacaid a chaidh a cleachdadh as trice",
"annual_report.summary.most_used_hashtag.most_used_hashtag": "an taga hais a chaidh a cleachdadh as trice",
+ "annual_report.summary.most_used_hashtag.used_count": "Ghabh thu a-staigh an taga hais seo ann an {count, plural, one {# phost} two {# phost} few {# postaichean} other {# post}}.",
+ "annual_report.summary.most_used_hashtag.used_count_public": "Ghabh {name} a-staigh an taga hais seo ann an {count, plural, one {# phost} two {# phost} few {# postaichean} other {# post}}.",
"annual_report.summary.new_posts.new_posts": "postaichean ùra",
"annual_report.summary.percentile.text": "Tha thu am measgdhen luchd-cleachdaidh as cliùitiche air {domain}.",
"annual_report.summary.percentile.we_wont_tell_bernie": "Ainmeil ’nad latha ’s ’nad linn.",
+ "annual_report.summary.share_elsewhere": "Co-roinn am badeigin eile",
+ "annual_report.summary.share_message": "’S e {archetype} am prìomh-choltas a th’ orm!",
+ "annual_report.summary.share_on_mastodon": "Co-roinn air Mastodon",
"attachments_list.unprocessed": "(gun phròiseasadh)",
"audio.hide": "Falaich an fhuaim",
"block_modal.remote_users_caveat": "Iarraidh sinn air an fhrithealaiche {domain} gun gèill iad ri do cho-dhùnadh. Gidheadh, chan eil barantas gun gèill iad on a làimhsicheas cuid a fhrithealaichean bacaidhean air dòigh eadar-dhealaichte. Dh’fhaoidte gum faic daoine gun chlàradh a-steach na postaichean poblach agad fhathast.",
@@ -162,7 +203,7 @@
"column.favourites": "Annsachdan",
"column.firehose": "An saoghal beò",
"column.firehose_local": "Loidhne-ama bheò an fhrithealaiche seo",
- "column.firehose_singular": "Loidhne-ama bheò beò",
+ "column.firehose_singular": "Loidhne-ama bheò",
"column.follow_requests": "Iarrtasan leantainn",
"column.home": "Dachaigh",
"column.list_members": "Stiùir buill na liosta",
@@ -242,7 +283,7 @@
"confirmations.private_quote_notify.title": "A bheil thu airson a cho-roinneadh leis an luchd-leantainn ’s na cleachdaichean le iomradh orra?",
"confirmations.quiet_post_quote_info.dismiss": "Na cuiribh seo ’nam chuimhne a-rithist",
"confirmations.quiet_post_quote_info.got_it": "Tha mi agaibh",
- "confirmations.quiet_post_quote_info.message": "Nuair a luaidheas tu post a tha poblach ach sàmhach, thèid am post agad fhalach o loidhnichean-ama nan treandaichean.",
+ "confirmations.quiet_post_quote_info.message": "Nuair a luaidheas tu post sàmhach, thèid am post agad fhalach o loidhnichean-ama nan treandaichean.",
"confirmations.quiet_post_quote_info.title": "Luaidh air postaichean sàmhach",
"confirmations.redraft.confirm": "Sguab às ⁊ dèan dreachd ùr",
"confirmations.redraft.message": "A bheil thu cinnteach gu bheil thu airson am post seo a sguabadh às agus dreachd ùr a thòiseachadh? Caillidh tu gach annsachd is brosnachadh air agus thèid freagairtean dhan phost thùsail ’nan dìlleachdanan.",
@@ -343,6 +384,7 @@
"empty_column.notification_requests": "Glan! Chan eil dad an-seo. Nuair a gheibh thu brathan ùra, nochdaidh iad an-seo a-rèir nan roghainnean agad.",
"empty_column.notifications": "Cha d’ fhuair thu brath sam bith fhathast. Nuair a nì càch conaltradh leat, chì thu an-seo e.",
"empty_column.public": "Chan eil dad an-seo! Sgrìobh rudeigin gu poblach no lean càch o fhrithealaichean eile a làimh airson seo a lìonadh",
+ "error.no_hashtag_feed_access": "Cruthaich cunntas no clàraich a-steach airson an taga hais seo a shealltainn is leantainn.",
"error.unexpected_crash.explanation": "Air sàilleibh buga sa chòd againn no duilgheadas co-chòrdalachd leis a’ bhrabhsair, chan urrainn dhuinn an duilleag seo a shealltainn mar bu chòir.",
"error.unexpected_crash.explanation_addons": "Cha b’ urrainn dhuinn an duilleag seo a shealltainn mar bu chòir. Tha sinn an dùil gu do dh’adhbharaich tuilleadan a’ bhrabhsair no inneal eadar-theangachaidh fèin-obrachail a’ mhearachd.",
"error.unexpected_crash.next_steps": "Feuch an ath-nuadhaich thu an duilleag seo. Mura cuidich sin, dh’fhaoidte gur urrainn dhut Mastodon a chleachdadh fhathast le brabhsair eile no le aplacaid thùsail.",
@@ -399,6 +441,8 @@
"follow_suggestions.who_to_follow": "Molaidhean leantainn",
"followed_tags": "Tagaichean hais ’gan leantainn",
"footer.about": "Mu dhèidhinn",
+ "footer.about_mastodon": "Mu Mhastodon",
+ "footer.about_server": "Mu {domain}",
"footer.about_this_server": "Mu dhèidhinn",
"footer.directory": "Eòlaire nam pròifil",
"footer.get_app": "Faigh an aplacaid",
@@ -473,6 +517,7 @@
"keyboard_shortcuts.column": "Cuir am fòcas air colbh",
"keyboard_shortcuts.compose": "Cuir am fòcas air raon teacsa an sgrìobhaidh",
"keyboard_shortcuts.description": "Tuairisgeul",
+ "keyboard_shortcuts.direct": "Fosgail colbh nan iomraidhean prìobhaideach",
"keyboard_shortcuts.down": "Gluais sìos air an liosta",
"keyboard_shortcuts.enter": "Fosgail post",
"keyboard_shortcuts.favourite": "Cuir am post ris na h-annsachdan",
@@ -500,6 +545,7 @@
"keyboard_shortcuts.toggle_hidden": "Seall/Falaich an teacsa fo rabhadh susbainte",
"keyboard_shortcuts.toggle_sensitivity": "Seall/Falaich na meadhanan",
"keyboard_shortcuts.toot": "Tòisich air post ùr",
+ "keyboard_shortcuts.top": "Gluais gu bàrr na liosta",
"keyboard_shortcuts.translate": "airson post eadar-theangachadh",
"keyboard_shortcuts.unfocus": "Thoir am fòcas far raon teacsa an sgrìobhaidh/an luirg",
"keyboard_shortcuts.up": "Gluais suas air an liosta",
@@ -740,11 +786,10 @@
"privacy.private.short": "Luchd-leantainn",
"privacy.public.long": "Duine sam bith taobh a-staigh no a-muigh Mhastodon",
"privacy.public.short": "Poblach",
- "privacy.quote.anyone": "{visibility}, luaidh fosgailte",
"privacy.quote.disabled": "{visibility}, luaidh à comas",
"privacy.quote.limited": "{visibility}, luaidh cuingichte",
"privacy.unlisted.additional": "Tha seo coltach ris an fhaicsinneachd phoblach ach cha nochd am post air loidhnichean-ama an t-saoghail phoblaich, nan tagaichean hais no an rùrachaidh no ann an toraidhean luirg Mhastodon fiù ’s ma thug thu ro-aonta airson sin seachad.",
- "privacy.unlisted.long": "Poblach ach falaichte o na toraidhean-luirg, na treandaichean ’s na loichnichean-ama poblach",
+ "privacy.unlisted.long": "Falaichte o na toraidhean-luirg, na treandaichean ’s na loidhnichean-ama poblach",
"privacy.unlisted.short": "Sàmhach",
"privacy_policy.last_updated": "An t-ùrachadh mu dheireadh {date}",
"privacy_policy.title": "Poileasaidh prìobhaideachd",
@@ -888,6 +933,7 @@
"status.edited_x_times": "Chaidh a dheasachadh {count, plural, one {{count} turas} two {{count} thuras} few {{count} tursan} other {{count} turas}}",
"status.embed": "Faigh còd leabachaidh",
"status.favourite": "Cuir ris na h-annsachdan",
+ "status.favourites_count": "{count, plural, one {{counter} annsachd} two {{counter} annsachd} few {{counter} annsachdan} other {{counter} annsachd}}",
"status.filter": "Criathraich am post seo",
"status.history.created": "Chruthaich {name} {date} e",
"status.history.edited": "Dheasaich {name} {date} e",
@@ -922,12 +968,14 @@
"status.quotes.empty": "Chan deach am post seo a luaidh le duine sam bith fhathast. Nuair a luaidheas cuideigin e, nochdaidh iad an-seo.",
"status.quotes.local_other_disclaimer": "Cha tèid luaidhean a dhiùilt an ùghdar a shealltainn.",
"status.quotes.remote_other_disclaimer": "Cha dèid ach luaidhean o {domain} a shealltainn an-seo le cinnt. Cha dèid luaidhean a dhiùilt an ùghdar a shealltainn.",
+ "status.quotes_count": "{count, plural, one {{counter} luaidh} two {{counter} luaidh} few {{counter} luaidhean} other {{counter} luaidh}}",
"status.read_more": "Leugh an còrr",
"status.reblog": "Brosnaich",
"status.reblog_or_quote": "Brosnaich no luaidh",
"status.reblog_private": "Co-roinn leis an luchd-leantainn agad a-rithist",
"status.reblogged_by": "’Ga bhrosnachadh le {name}",
"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.reblogs_count": "{count, plural, one {{counter} bhrosnachadh} two {{counter} bhrosnachadh} few {{counter} brosnachaidhean} other {{counter} brosnachadh}}",
"status.redraft": "Sguab às ⁊ dèan dreachd ùr",
"status.remove_bookmark": "Thoir an comharra-lìn air falbh",
"status.remove_favourite": "Thoir air falbh o na h-annsachdan",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index 03a4e4acf94..06b940593c2 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -14,11 +14,13 @@
"about.powered_by": "Comunicación social descentralizada grazas a {mastodon}",
"about.rules": "Regras do servidor",
"account.account_note_header": "Nota persoal",
+ "account.activity": "Actividade",
+ "account.add_note": "Engadir nota persoal",
"account.add_or_remove_from_list": "Engadir ou eliminar das listaxes",
"account.badges.bot": "Automatizada",
"account.badges.group": "Grupo",
"account.block": "Bloquear @{name}",
- "account.block_domain": "Agochar todo de {domain}",
+ "account.block_domain": "Bloquear o dominio {domain}",
"account.block_short": "Bloquear",
"account.blocked": "Bloqueada",
"account.blocking": "Bloqueos",
@@ -27,6 +29,7 @@
"account.direct": "Mencionar de xeito privado a @{name}",
"account.disable_notifications": "Deixar de notificarme cando @{name} publica",
"account.domain_blocking": "Bloqueo do dominio",
+ "account.edit_note": "Editar a nota persoal",
"account.edit_profile": "Editar perfil",
"account.edit_profile_short": "Editar",
"account.enable_notifications": "Noficarme cando @{name} publique",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Cancelos",
"account.featured_tags.last_status_at": "Última publicación o {date}",
"account.featured_tags.last_status_never": "Sen publicacións",
+ "account.filters.all": "Toda actividade",
+ "account.filters.boosts_toggle": "Mostrar promocións",
+ "account.filters.posts_boosts": "Publicacións e promocións",
+ "account.filters.posts_only": "Publicacións",
+ "account.filters.posts_replies": "Publicacións e respostas",
+ "account.filters.replies_toggle": "Mostrar respostas",
"account.follow": "Seguir",
"account.follow_back": "Seguir tamén",
"account.follow_back_short": "Seguir tamén",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Ir ao perfil",
"account.hide_reblogs": "Agochar promocións de @{name}",
"account.in_memoriam": "Lembranzas.",
+ "account.joined_long": "Uníuse o {date}",
"account.joined_short": "Uniuse",
"account.languages": "Modificar os idiomas subscritos",
"account.link_verified_on": "A propiedade desta ligazón foi verificada o {date}",
@@ -71,6 +81,14 @@
"account.muting": "Silenciamento",
"account.mutual": "Seguimento mútuo",
"account.no_bio": "Sen descrición.",
+ "account.node_modal.callout": "As notas persoais só as podes ver ti.",
+ "account.node_modal.edit_title": "Editar nota persoal",
+ "account.node_modal.error_unknown": "Non se puido gardar a nota",
+ "account.node_modal.field_label": "Nota persoal",
+ "account.node_modal.save": "Gardar",
+ "account.node_modal.title": "Engadir nota persoal",
+ "account.note.edit_button": "Editar",
+ "account.note.title": "Nota persoal (só ti podes vela)",
"account.open_original_page": "Abrir páxina orixinal",
"account.posts": "Publicacións",
"account.posts_with_replies": "Publicacións e respostas",
@@ -90,6 +108,8 @@
"account.unmute": "Deixar de silenciar a @{name}",
"account.unmute_notifications_short": "Reactivar notificacións",
"account.unmute_short": "Non silenciar",
+ "account_fields_modal.close": "Fechar",
+ "account_fields_modal.title": "Info sobre {name}",
"account_note.placeholder": "Preme para engadir nota",
"admin.dashboard.daily_retention": "Ratio de retención de usuarias diaria após rexistrarse",
"admin.dashboard.monthly_retention": "Ratio de retención de usuarias mensual após o rexistro",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Pechar",
"bundle_modal_error.message": "Algo fallou mentras cargaba esta páxina.",
"bundle_modal_error.retry": "Téntao de novo",
+ "callout.dismiss": "Desbotar",
"carousel.current": "Filmina {current, number} / {max, number}",
"carousel.slide": "Filmina {current, number} de {max, number}",
"closed_registrations.other_server_instructions": "Cómo Mastodon é descentralizado, podes crear unha conta noutro servidor e interactuar igualmente con este.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Atopa outro servidor",
"closed_registrations_modal.preamble": "Mastodon é descentralizado, así que non importa onde crees a conta, poderás seguir e interactuar con calquera conta deste servidor. Incluso podes ter o teu servidor!",
"closed_registrations_modal.title": "Crear conta en Mastodon",
+ "collections.collection_description": "Descrición",
+ "collections.collection_name": "Nome",
+ "collections.collection_topic": "Temática",
+ "collections.create_a_collection_hint": "Crear unha colección para recomendar ou compartir as túas contas favoritas.",
+ "collections.create_collection": "Crear colección",
+ "collections.delete_collection": "Eliminar colección",
+ "collections.description_length_hint": "Límite de 100 caracteres",
+ "collections.error_loading_collections": "Houbo un erro ao intentar cargar as túas coleccións.",
+ "collections.mark_as_sensitive": "Marcar como sensible",
+ "collections.mark_as_sensitive_hint": "Oculta a descrición e contas da colección detrás dun aviso sobre o contido. O nome da colección permanece visible.",
+ "collections.name_length_hint": "Límite de 100 caracteres",
+ "collections.no_collections_yet": "Aínda non tes coleccións.",
+ "collections.topic_hint": "Engadir un cancelo para que axudar a que outras persoas coñezan a temática desta colección.",
+ "collections.view_collection": "Ver colección",
"column.about": "Sobre",
"column.blocks": "Usuarias bloqueadas",
"column.bookmarks": "Marcadores",
+ "column.collections": "As miñas coleccións",
"column.community": "Cronoloxía local",
+ "column.create_collection": "Crear colección",
"column.create_list": "Crear lista",
"column.direct": "Mencións privadas",
"column.directory": "Procurar perfís",
"column.domain_blocks": "Dominios agochados",
+ "column.edit_collection": "Editar colección",
"column.edit_list": "Editar lista",
"column.favourites": "Favoritas",
"column.firehose": "O que acontece",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Eliminar",
"confirmations.delete.message": "Tes a certeza de querer eliminar esta publicación?",
"confirmations.delete.title": "Eliminar a publicación?",
+ "confirmations.delete_collection.confirm": "Eliminar",
+ "confirmations.delete_collection.message": "Esta acción non se pode desfacer.",
+ "confirmations.delete_collection.title": "Eliminar \"{name}\"?",
"confirmations.delete_list.confirm": "Eliminar",
"confirmations.delete_list.message": "Tes a certeza de querer eliminar de xeito permanente esta listaxe?",
"confirmations.delete_list.title": "Eliminar a lista?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Publicación {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Publicación fixada} other {Publicacións fixadas}}",
"featured_carousel.slide": "Publicación {current, number} de {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Esta categoría de filtro non se aplica ao contexto no que accedeches a esta publicación. Se queres que a publicación se filtre nese contexto tamén, terás que editar o filtro.",
"filter_modal.added.context_mismatch_title": "Non concorda o contexto!",
"filter_modal.added.expired_explanation": "Esta categoría de filtro caducou, terás que cambiar a data de caducidade para que se aplique.",
@@ -451,6 +493,7 @@
"footer.source_code": "Ver código fonte",
"footer.status": "Estado",
"footer.terms_of_service": "Condicións do servizo",
+ "form_field.optional": "(optativo)",
"generic.saved": "Gardado",
"getting_started.heading": "Primeiros pasos",
"hashtag.admin_moderation": "Abrir interface de moderación para ##{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# novo elemento} other {# novos elementos}}",
"loading_indicator.label": "Estase a cargar…",
"media_gallery.hide": "Agochar",
+ "minicard.more_items": "+{count}",
"moved_to_account_banner.text": "A túa conta {disabledAccount} está actualmente desactivada porque movéchela a {movedToAccount}.",
"mute_modal.hide_from_notifications": "Agochar nas notificacións",
"mute_modal.hide_options": "Opcións ao ocultar",
@@ -786,7 +830,7 @@
"privacy.private.short": "Seguidoras",
"privacy.public.long": "Para todas dentro e fóra de Mastodon",
"privacy.public.short": "Público",
- "privacy.quote.anyone": "{visibility}, calquera pode citar",
+ "privacy.quote.anyone": "{visibility}, permítese citar",
"privacy.quote.disabled": "{visibility}, citas desactivadas",
"privacy.quote.limited": "{visibility}, citas limitadas",
"privacy.unlisted.additional": "Do mesmo xeito que público, menos que a publicación non aparecerá nas cronoloxías en directo ou nos cancelos, en descubrir ou nas buscas de Mastodon, incluso se estivese establecido nas opcións xerais da conta.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notificacións",
"tabs_bar.publish": "Nova publicación",
"tabs_bar.search": "Buscar",
+ "tag.remove": "Retirar",
"terms_of_service.effective_as_of": "Con efecto desde o {date}",
"terms_of_service.title": "Condicións do Servizo",
"terms_of_service.upcoming_changes_on": "Cambios por vir o {date}",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 3cee7adc5e1..91eb94e52b5 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -14,6 +14,8 @@
"about.powered_by": "רשת חברתית מבוזרת המופעלת על ידי {mastodon}",
"about.rules": "כללי השרת",
"account.account_note_header": "הערה אישית",
+ "account.activity": "פעילות",
+ "account.add_note": "הוספת הערה פרטית",
"account.add_or_remove_from_list": "הוספה או הסרה מרשימות",
"account.badges.bot": "בוט",
"account.badges.group": "קבוצה",
@@ -27,6 +29,7 @@
"account.direct": "הודעה פרטית אל @{name}",
"account.disable_notifications": "הפסק לשלוח לי התראות כש@{name} מפרסמים",
"account.domain_blocking": "רשימת השרתים החסומים",
+ "account.edit_note": "עריכת הערה פרטית",
"account.edit_profile": "עריכת פרופיל",
"account.edit_profile_short": "עריכה",
"account.enable_notifications": "שלח לי התראות כש@{name} מפרסם",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "תגיות",
"account.featured_tags.last_status_at": "חצרוץ אחרון בתאריך {date}",
"account.featured_tags.last_status_never": "אין חצרוצים",
+ "account.filters.all": "כל הפעילות",
+ "account.filters.boosts_toggle": "הצגת הדהודים",
+ "account.filters.posts_boosts": "הודעות והדהודים",
+ "account.filters.posts_only": "הודעות",
+ "account.filters.posts_replies": "הודעות ותגובות",
+ "account.filters.replies_toggle": "הצגת תגובות",
"account.follow": "לעקוב",
"account.follow_back": "לעקוב בחזרה",
"account.follow_back_short": "לעקוב בחזרה",
@@ -57,6 +66,7 @@
"account.go_to_profile": "מעבר לפרופיל",
"account.hide_reblogs": "להסתיר הידהודים מאת @{name}",
"account.in_memoriam": "פרופיל זכרון.",
+ "account.joined_long": "הצטרפו ב־{date}",
"account.joined_short": "תאריך הצטרפות",
"account.languages": "שנה רישום לשפות",
"account.link_verified_on": "בעלות על הקישור הזה נבדקה לאחרונה ב{date}",
@@ -71,6 +81,14 @@
"account.muting": "רשימת החשבונות המושתקים",
"account.mutual": "אתם עוקביםות הדדית",
"account.no_bio": "לא סופק תיאור.",
+ "account.node_modal.callout": "הערות פרטיות גלויות לך בלבד.",
+ "account.node_modal.edit_title": "עריכת הערה פרטית",
+ "account.node_modal.error_unknown": "לא ניתן לשמור הערה",
+ "account.node_modal.field_label": "הערה פרטית",
+ "account.node_modal.save": "שמירה",
+ "account.node_modal.title": "הוספת הערה פרטית",
+ "account.note.edit_button": "עריכה",
+ "account.note.title": "הערה פרטית (זמין רק לך)",
"account.open_original_page": "לפתיחת העמוד המקורי",
"account.posts": "פוסטים",
"account.posts_with_replies": "הודעות ותגובות",
@@ -90,6 +108,8 @@
"account.unmute": "הפסקת השתקת @{name}",
"account.unmute_notifications_short": "הפעלת הודעות",
"account.unmute_short": "ביטול השתקה",
+ "account_fields_modal.close": "סגירה",
+ "account_fields_modal.title": "הפרטים של {name}",
"account_note.placeholder": "יש ללחוץ כדי להוסיף הערות",
"admin.dashboard.daily_retention": "קצב שימור משתמשים יומי אחרי ההרשמה",
"admin.dashboard.monthly_retention": "קצב שימור משתמשים (פר חודש) אחרי ההרשמה",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "לסגור",
"bundle_modal_error.message": "משהו השתבש בעת טעינת המסך הזה.",
"bundle_modal_error.retry": "לנסות שוב",
+ "callout.dismiss": "לבטל",
"carousel.current": "שקופית{current, number} מתוך {max, number}",
"carousel.slide": "שקופית {current, number} מתוך {max, number}",
"closed_registrations.other_server_instructions": "מכיוון שמסטודון היא רשת מבוזרת, ניתן ליצור חשבון על שרת נוסף ועדיין לקיים קשר עם משתמשים בשרת זה.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "חיפוש שרת אחר",
"closed_registrations_modal.preamble": "מסטודון הוא רשת מבוזרת, כך שלא משנה היכן החשבון שלך, קיימת האפשרות לעקוב ולתקשר עם משתמשים בשרת הזה. אפשר אפילו להריץ שרת בעצמך!",
"closed_registrations_modal.title": "להרשם למסטודון",
+ "collections.collection_description": "תיאור",
+ "collections.collection_name": "כינוי",
+ "collections.collection_topic": "נושא",
+ "collections.create_a_collection_hint": "יצירת אוסף כדי להמליץ או לשתף את החשבונות החביבים עליך עם אחרים.",
+ "collections.create_collection": "יצירת אוסף",
+ "collections.delete_collection": "מחיקת האוסף",
+ "collections.description_length_hint": "מגבלה של 100 תווים",
+ "collections.error_loading_collections": "חלה שגיאה בנסיון לטעון את אוספיך.",
+ "collections.mark_as_sensitive": "מסומנים כרגישים",
+ "collections.mark_as_sensitive_hint": "הסתרת תיאור וחשבונות האוסף מאחורי אזהרת תוכן. שם האוסף עדיין ישאר גלוי.",
+ "collections.name_length_hint": "מגבלה של 100 תווים",
+ "collections.no_collections_yet": "עוד אין אוספים.",
+ "collections.topic_hint": "הוספת תגית שמסייעת לאחרים להבין את הנושא הראשי של האוסף.",
+ "collections.view_collection": "צפיה באוסף",
"column.about": "אודות",
"column.blocks": "משתמשים חסומים",
"column.bookmarks": "סימניות",
+ "column.collections": "האוספים שלי",
"column.community": "פיד שרת מקומי",
+ "column.create_collection": "יצירת אוסף",
"column.create_list": "יצירת רשימה",
"column.direct": "הודעות פרטיות",
"column.directory": "עיין בפרופילים",
"column.domain_blocks": "קהילות (שמות מתחם) מוסתרות",
+ "column.edit_collection": "עריכת אוסף",
"column.edit_list": "עריכת רשימה",
"column.favourites": "חיבובים",
"column.firehose": "פידים עדכניים",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "למחוק",
"confirmations.delete.message": "בטוח/ה שאת/ה רוצה למחוק את ההודעה?",
"confirmations.delete.title": "למחוק הודעה?",
+ "confirmations.delete_collection.confirm": "מחק",
+ "confirmations.delete_collection.message": "פעולה זו אינה הפיכה.",
+ "confirmations.delete_collection.title": "למחוק את \"{name}\"?",
"confirmations.delete_list.confirm": "למחוק",
"confirmations.delete_list.message": "האם אתם בטוחים שאתם רוצים למחוק את הרשימה לצמיתות?",
"confirmations.delete_list.title": "למחוק רשימה?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "הודעה{current, number} מתוך {max, number}",
"featured_carousel.header": "{count, plural, one {הודעה אחת נעוצה} two {הודעותיים נעוצות} many {הודעות נעוצות} other {הודעות נעוצות}}",
"featured_carousel.slide": "הודעה {current, number} מתוך {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "קטגוריית הסנן הזאת לא חלה על ההקשר שממנו הגעת אל ההודעה הזו. אם תרצה/י שההודעה תסונן גם בהקשר זה, תצטרך/י לערוך את הסנן.",
"filter_modal.added.context_mismatch_title": "אין התאמה להקשר!",
"filter_modal.added.expired_explanation": "פג תוקפה של קטגוריית הסינון הזו, יש צורך לשנות את תאריך התפוגה כדי שהסינון יוחל.",
@@ -451,6 +493,7 @@
"footer.source_code": "צפיה בקוד המקור",
"footer.status": "מצב",
"footer.terms_of_service": "תנאי השירות",
+ "form_field.optional": "(אפשרות)",
"generic.saved": "נשמר",
"getting_started.heading": "בואו נתחיל",
"hashtag.admin_moderation": "פתיחת ממשק פיקוח דיון עבור #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# פריט חדש} other {# פריטים חדשים}}",
"loading_indicator.label": "בטעינה…",
"media_gallery.hide": "להסתיר",
+ "minicard.more_items": "+{count}",
"moved_to_account_banner.text": "חשבונך {disabledAccount} אינו פעיל כרגע עקב מעבר ל{movedToAccount}.",
"mute_modal.hide_from_notifications": "להסתיר מהתראות",
"mute_modal.hide_options": "הסתרת אפשרויות",
@@ -786,7 +830,7 @@
"privacy.private.short": "עוקבים",
"privacy.public.long": "כל הגולשים, מחוברים למסטודון או לא",
"privacy.public.short": "פומבי",
- "privacy.quote.anyone": "{visibility}, הציטוט מותר לכל",
+ "privacy.quote.anyone": "{visibility}, רשות הציטוט נתונה",
"privacy.quote.disabled": "{visibility}, האפשרות לציטוט מכובה",
"privacy.quote.limited": "{visibility}, האפשרות לציטוט מוגבלת",
"privacy.unlisted.additional": "ההתנהגות דומה להודעה ציבורית, מלבד שההודעה לא תופיע בפיד החי המקומי או בתגיות, תגליות או חיפוש מסטודון, אפילו אם ביקשת שהחשבון כולו יהיה פומבי.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "התראות",
"tabs_bar.publish": "הודעה חדשה",
"tabs_bar.search": "חיפוש",
+ "tag.remove": "הסרה",
"terms_of_service.effective_as_of": "בתוקף החל מתאריך {date}",
"terms_of_service.title": "תנאי השירות",
"terms_of_service.upcoming_changes_on": "שינויים עתידיים שיחולו ביום {date}",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 0f53d1b18eb..4d0a9b03149 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -57,6 +57,7 @@
"account.go_to_profile": "Ugrás a profilhoz",
"account.hide_reblogs": "@{name} megtolásainak elrejtése",
"account.in_memoriam": "Emlékünkben.",
+ "account.joined_long": "Csatlakozás ideje: {date}",
"account.joined_short": "Csatlakozott",
"account.languages": "Feliratkozott nyelvek módosítása",
"account.link_verified_on": "A linket eredetiségét ebben az időpontban ellenőriztük: {date}",
@@ -90,6 +91,8 @@
"account.unmute": "@{name} némításának feloldása",
"account.unmute_notifications_short": "Értesítések némításának feloldása",
"account.unmute_short": "Némitás feloldása",
+ "account_fields_modal.close": "Bezárás",
+ "account_fields_modal.title": "{name} információi",
"account_note.placeholder": "Kattintás jegyzet hozzáadásához",
"admin.dashboard.daily_retention": "Napi regisztráció utáni felhasználómegtartási arány",
"admin.dashboard.monthly_retention": "Havi regisztráció utáni felhasználómegtartási arány",
@@ -191,9 +194,16 @@
"closed_registrations_modal.find_another_server": "Másik kiszolgáló keresése",
"closed_registrations_modal.preamble": "A Mastodon decentralizált, így teljesen mindegy, hol hozod létre a fiókodat, követhetsz és kapcsolódhatsz bárkivel ezen a kiszolgálón is. Saját magad is üzemeltethetsz kiszolgálót!",
"closed_registrations_modal.title": "Regisztráció a Mastodonra",
+ "collections.create_a_collection_hint": "Gyűjtemény létrehozása a kedvenc fiókok másoknak való ajánlásához.",
+ "collections.create_collection": "Gyűjtemény létrehozása",
+ "collections.delete_collection": "Gyűjtemény törlése",
+ "collections.error_loading_collections": "Hiba történt a gyűjtemények betöltése során.",
+ "collections.no_collections_yet": "Még nincsenek gyűjtemények.",
+ "collections.view_collection": "Gyűjtemény megtekintése",
"column.about": "Névjegy",
"column.blocks": "Letiltott felhasználók",
"column.bookmarks": "Könyvjelzők",
+ "column.collections": "Saját gyűjtemények",
"column.community": "Helyi idővonal",
"column.create_list": "Lista létrehozása",
"column.direct": "Személyes említések",
@@ -589,6 +599,7 @@
"load_pending": "{count, plural, one {# új elem} other {# új elem}}",
"loading_indicator.label": "Betöltés…",
"media_gallery.hide": "Elrejtés",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +797,6 @@
"privacy.private.short": "Követők",
"privacy.public.long": "Bárki a Mastodonon és azon kívül",
"privacy.public.short": "Nyilvános",
- "privacy.quote.anyone": "{visibility}, bárki idézheti",
"privacy.quote.disabled": "{visibility}, idézés letiltva",
"privacy.quote.limited": "{visibility}, idézés korlátozva",
"privacy.unlisted.additional": "Ez pontosan úgy viselkedik, mint a nyilvános, kivéve, hogy a bejegyzés nem jelenik meg élő hírfolyamokban, hashtagekben, felfedezésben vagy a Mastodonos keresésben, még akkor sem, ha ezt az egész fiókra engedélyezted.",
diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json
index ac8e9fe438e..d9a2f5e8447 100644
--- a/app/javascript/mastodon/locales/ia.json
+++ b/app/javascript/mastodon/locales/ia.json
@@ -741,7 +741,6 @@
"privacy.private.short": "Sequitores",
"privacy.public.long": "Quicunque, sur Mastodon o non",
"privacy.public.short": "Public",
- "privacy.quote.anyone": "{visibility}, omnes pote citar",
"privacy.quote.disabled": "{visibility}, citation disactivate",
"privacy.quote.limited": "{visibility}, citation limitate",
"privacy.unlisted.additional": "Isto es exactemente como public, excepte que le message non apparera in fluxos in vivo, in hashtags, in Explorar, o in le recerca de Mastodon, mesmo si tu ha optate pro render tote le conto discoperibile.",
diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json
index 0f255dfa977..cd9dc2b45c8 100644
--- a/app/javascript/mastodon/locales/is.json
+++ b/app/javascript/mastodon/locales/is.json
@@ -14,6 +14,8 @@
"about.powered_by": "Dreifhýstur samskiptamiðill keyrður með {mastodon}",
"about.rules": "Reglur netþjónsins",
"account.account_note_header": "Einkaminnispunktur",
+ "account.activity": "Virkni",
+ "account.add_note": "Bæta við einkaminnispunkti",
"account.add_or_remove_from_list": "Bæta við eða fjarlægja af listum",
"account.badges.bot": "Yrki",
"account.badges.group": "Hópur",
@@ -27,6 +29,7 @@
"account.direct": "Einkaspjall við @{name}",
"account.disable_notifications": "Hætta að láta mig vita þegar @{name} sendir inn",
"account.domain_blocking": "Útiloka lén",
+ "account.edit_note": "Breyta einkaminnispunkti",
"account.edit_profile": "Breyta notandasniði",
"account.edit_profile_short": "Breyta",
"account.enable_notifications": "Láta mig vita þegar @{name} sendir inn",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Myllumerki",
"account.featured_tags.last_status_at": "Síðasta færsla þann {date}",
"account.featured_tags.last_status_never": "Engar færslur",
+ "account.filters.all": "Öll virkni",
+ "account.filters.boosts_toggle": "Sýna endurbirtingar",
+ "account.filters.posts_boosts": "Færslur og endurbirtingar",
+ "account.filters.posts_only": "Færslur",
+ "account.filters.posts_replies": "Færslur og svör",
+ "account.filters.replies_toggle": "Birta svör",
"account.follow": "Fylgjast með",
"account.follow_back": "Fylgjast með til baka",
"account.follow_back_short": "Fylgjast með til baka",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Fara í notandasnið",
"account.hide_reblogs": "Fela endurbirtingar fyrir @{name}",
"account.in_memoriam": "Minning.",
+ "account.joined_long": "Skáði sig {date}",
"account.joined_short": "Gerðist þátttakandi",
"account.languages": "Breyta tungumálum í áskrift",
"account.link_verified_on": "Eignarhald á þessum tengli var athugað þann {date}",
@@ -71,6 +81,14 @@
"account.muting": "Þöggun",
"account.mutual": "Þið fylgist með hvor öðrum",
"account.no_bio": "Engri lýsingu útvegað.",
+ "account.node_modal.callout": "Persónulegir einkaminnispunktar eru einungis sýnilegir þér.",
+ "account.node_modal.edit_title": "Breyta einkaminnispunkti",
+ "account.node_modal.error_unknown": "Tókst ekki að vista minnispunktinn",
+ "account.node_modal.field_label": "Einkaminnispunktur",
+ "account.node_modal.save": "Vista",
+ "account.node_modal.title": "Bæta við einkaminnispunkti",
+ "account.note.edit_button": "Breyta",
+ "account.note.title": "Einkaminnispunktur (einungis sýnilegur þér)",
"account.open_original_page": "Opna upprunalega síðu",
"account.posts": "Færslur",
"account.posts_with_replies": "Færslur og svör",
@@ -90,6 +108,8 @@
"account.unmute": "Hætta að þagga niður í @{name}",
"account.unmute_notifications_short": "Hætta að þagga í tilkynningum",
"account.unmute_short": "Hætta að þagga niður",
+ "account_fields_modal.close": "Loka",
+ "account_fields_modal.title": "Upplýsingar um {name}",
"account_note.placeholder": "Smelltu til að bæta við minnispunkti",
"admin.dashboard.daily_retention": "Hlutfall virkra notenda eftir nýskráningu eftir dögum",
"admin.dashboard.monthly_retention": "Hlutfall virkra notenda eftir nýskráningu eftir mánuðum",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Loka",
"bundle_modal_error.message": "Eitthvað fór úrskeiðis við að hlaða inn þessum skjá.",
"bundle_modal_error.retry": "Reyndu aftur",
+ "callout.dismiss": "Vísa frá",
"carousel.current": "Skyggna {current, number} / {max, number}",
"carousel.slide": "Skyggna {current, number} af {max, number}",
"closed_registrations.other_server_instructions": "Þar sem Mastodon er ekki miðstýrt, þá getur þú búið til aðgang á öðrum þjóni, en samt haft samskipti við þennan.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Finna annan netþjón",
"closed_registrations_modal.preamble": "Mastodon er ekki miðstýrt, svo það skiptir ekki máli hvar þú býrð til aðgang; þú munt get fylgt eftir og haft samskipti við hvern sem er á þessum þjóni. Þú getur jafnvel hýst þinn eigin Mastodon þjón!",
"closed_registrations_modal.title": "Að nýskrá sig á Mastodon",
+ "collections.collection_description": "Lýsing",
+ "collections.collection_name": "Nafn",
+ "collections.collection_topic": "Umfjöllunarefni",
+ "collections.create_a_collection_hint": "Búðu til safn með eftirlætisnotendunum þínum til að deila eða mæla með við aðra.",
+ "collections.create_collection": "Búa til safn",
+ "collections.delete_collection": "Eyða safni",
+ "collections.description_length_hint": "100 stafa takmörk",
+ "collections.error_loading_collections": "Villa kom upp þegar reynt var að hlaða inn söfnunum þínum.",
+ "collections.mark_as_sensitive": "Merkja sem viðkvæmt",
+ "collections.mark_as_sensitive_hint": "Felur lýsingu safnsins og notendur á bakvið aðvörun vegna efnis. Nafn safnsins verður áfram sýnilegt.",
+ "collections.name_length_hint": "100 stafa takmörk",
+ "collections.no_collections_yet": "Engin söfn ennþá.",
+ "collections.topic_hint": "Bættu við myllumerki sem hjálpar öðrum að skilja aðalefni þessa safns.",
+ "collections.view_collection": "Skoða safn",
"column.about": "Um hugbúnaðinn",
"column.blocks": "Útilokaðir notendur",
"column.bookmarks": "Bókamerki",
+ "column.collections": "Söfnin mín",
"column.community": "Staðvær tímalína",
+ "column.create_collection": "Búa til safn",
"column.create_list": "Búa til lista",
"column.direct": "Einkaspjall",
"column.directory": "Skoða notendasnið",
"column.domain_blocks": "Útilokuð lén",
+ "column.edit_collection": "Breyta safni",
"column.edit_list": "Breyta lista",
"column.favourites": "Eftirlæti",
"column.firehose": "Bein streymi",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Eyða",
"confirmations.delete.message": "Ertu viss um að þú viljir eyða þessari færslu?",
"confirmations.delete.title": "Eyða færslu?",
+ "confirmations.delete_collection.confirm": "Eyða",
+ "confirmations.delete_collection.message": "Þessa aðgerð er ekki hægt að afturkalla.",
+ "confirmations.delete_collection.title": "Eyða “{name}\"?",
"confirmations.delete_list.confirm": "Eyða",
"confirmations.delete_list.message": "Ertu viss um að þú viljir eyða þessum lista endanlega?",
"confirmations.delete_list.title": "Eyða lista?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Færsla {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Fest færsla} other {Festar færslur}}",
"featured_carousel.slide": "Færsla {current, number} af {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Þessi síuflokkur á ekki við í því samhengi sem aðgangur þinn að þessari færslu felur í sér. Ef þú vilt að færslan sé einnig síuð í þessu samhengi, þá þarftu að breyta síunni.",
"filter_modal.added.context_mismatch_title": "Misræmi í samhengi!",
"filter_modal.added.expired_explanation": "Þessi síuflokkur er útrunninn, þú þarft að breyta gidistímanum svo hann geti átt við.",
@@ -451,6 +493,7 @@
"footer.source_code": "Skoða frumkóða",
"footer.status": "Staða",
"footer.terms_of_service": "Þjónustuskilmálar",
+ "form_field.optional": "(valfrjálst)",
"generic.saved": "Vistað",
"getting_started.heading": "Komast í gang",
"hashtag.admin_moderation": "Opna umsjónarviðmót fyrir #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# nýtt atriði} other {# ný atriði}}",
"loading_indicator.label": "Hleð inn…",
"media_gallery.hide": "Fela",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +830,7 @@
"privacy.private.short": "Fylgjendur",
"privacy.public.long": "Hver sem er, á og utan Mastodon",
"privacy.public.short": "Opinbert",
- "privacy.quote.anyone": "{visibility}, hver sem er getur vitnað í færslu",
+ "privacy.quote.anyone": "{visibility}, tilvitnanir leyfðar",
"privacy.quote.disabled": "{visibility}, tilvitnanir eru óvirkar",
"privacy.quote.limited": "{visibility}, tilvitnanir eru takmarkaðar",
"privacy.unlisted.additional": "Þetta hegðar sér eins og opinber færsla, fyrir utan að færslan birtist ekki í beinum streymum eða myllumerkjum, né heldur í Mastodon-leitum jafnvel þótt þú hafir valið að falla undir slíkt í notandasniðinu þínu.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Tilkynningar",
"tabs_bar.publish": "Ný færsla",
"tabs_bar.search": "Leita",
+ "tag.remove": "Fjarlægja",
"terms_of_service.effective_as_of": "Gildir frá og með {date}",
"terms_of_service.title": "Þjónustuskilmálar",
"terms_of_service.upcoming_changes_on": "Væntanlegar breytingar þann {date}",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index 8b6c70bd140..c813e0f6b88 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -14,6 +14,8 @@
"about.powered_by": "Social media decentralizzato alimentato da {mastodon}",
"about.rules": "Regole del server",
"account.account_note_header": "Note personali",
+ "account.activity": "Attività",
+ "account.add_note": "Aggiungi una nota personale",
"account.add_or_remove_from_list": "Aggiungi o Rimuovi dalle liste",
"account.badges.bot": "Bot",
"account.badges.group": "Gruppo",
@@ -27,6 +29,7 @@
"account.direct": "Menziona privatamente @{name}",
"account.disable_notifications": "Smetti di avvisarmi quando @{name} pubblica un post",
"account.domain_blocking": "Account di un dominio bloccato",
+ "account.edit_note": "Modifica la nota personale",
"account.edit_profile": "Modifica profilo",
"account.edit_profile_short": "Modifica",
"account.enable_notifications": "Avvisami quando @{name} pubblica un post",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Hashtag",
"account.featured_tags.last_status_at": "Ultimo post il {date}",
"account.featured_tags.last_status_never": "Nessun post",
+ "account.filters.all": "Tutte le attività",
+ "account.filters.boosts_toggle": "Mostra le condivisioni",
+ "account.filters.posts_boosts": "Post e condivisioni",
+ "account.filters.posts_only": "Post",
+ "account.filters.posts_replies": "Post e risposte",
+ "account.filters.replies_toggle": "Mostra le risposte",
"account.follow": "Segui",
"account.follow_back": "Segui a tua volta",
"account.follow_back_short": "Segui a tua volta",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Vai al profilo",
"account.hide_reblogs": "Nascondi condivisioni da @{name}",
"account.in_memoriam": "In memoria.",
+ "account.joined_long": "Su questa istanza dal {date}",
"account.joined_short": "Iscritto",
"account.languages": "Modifica le lingue d'iscrizione",
"account.link_verified_on": "La proprietà di questo link è stata controllata il {date}",
@@ -71,6 +81,14 @@
"account.muting": "Account silenziato",
"account.mutual": "Vi seguite a vicenda",
"account.no_bio": "Nessuna descrizione fornita.",
+ "account.node_modal.callout": "Le note personali sono visibili solo per te.",
+ "account.node_modal.edit_title": "Modifica la nota personale",
+ "account.node_modal.error_unknown": "Impossibile salvare la nota",
+ "account.node_modal.field_label": "Nota personale",
+ "account.node_modal.save": "Salva",
+ "account.node_modal.title": "Aggiungi una nota personale",
+ "account.note.edit_button": "Modifica",
+ "account.note.title": "Nota personale (visibile solo per te)",
"account.open_original_page": "Apri la pagina originale",
"account.posts": "Post",
"account.posts_with_replies": "Post e risposte",
@@ -90,6 +108,8 @@
"account.unmute": "Riattiva @{name}",
"account.unmute_notifications_short": "Riattiva notifiche",
"account.unmute_short": "Attiva audio",
+ "account_fields_modal.close": "Chiudi",
+ "account_fields_modal.title": "Informazioni su {name}",
"account_note.placeholder": "Clicca per aggiungere una nota",
"admin.dashboard.daily_retention": "Tasso di ritenzione dell'utente per giorno, dopo la registrazione",
"admin.dashboard.monthly_retention": "Tasso di ritenzione dell'utente per mese, dopo la registrazione",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Chiudi",
"bundle_modal_error.message": "Si è verificato un errore durante il caricamento di questa schermata.",
"bundle_modal_error.retry": "Riprova",
+ "callout.dismiss": "Ignora",
"carousel.current": "Diapositiva {current, number} / {max, number}",
"carousel.slide": "Diapositiva {current, number} di {max, number}",
"closed_registrations.other_server_instructions": "Poiché Mastodon è decentralizzato, puoi creare un profilo su un altro server, pur continuando a interagire con questo.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Trova un altro server",
"closed_registrations_modal.preamble": "Mastodon è decentralizzato, quindi, non importa dove crei il tuo profilo, potrai seguire e interagire con chiunque su questo server. Anche se sei tu stesso a ospitarlo!",
"closed_registrations_modal.title": "Registrazione su Mastodon",
+ "collections.collection_description": "Descrizione",
+ "collections.collection_name": "Nome",
+ "collections.collection_topic": "Argomento",
+ "collections.create_a_collection_hint": "Crea una collezione per consigliare o condividere i tuoi account preferiti con altri.",
+ "collections.create_collection": "Crea la collezione",
+ "collections.delete_collection": "Cancella la collezione",
+ "collections.description_length_hint": "Limite di 100 caratteri",
+ "collections.error_loading_collections": "Si è verificato un errore durante il tentativo di caricare le tue collezioni.",
+ "collections.mark_as_sensitive": "Segna come sensibile",
+ "collections.mark_as_sensitive_hint": "Nasconde la descrizione e gli account della collezione dietro un avviso di contenuto. Il nome della collezione rimarrà visibile.",
+ "collections.name_length_hint": "Limite di 100 caratteri",
+ "collections.no_collections_yet": "Nessuna collezione ancora.",
+ "collections.topic_hint": "Aggiungi un hashtag che aiuti gli altri a comprendere l'argomento principale di questa collezione.",
+ "collections.view_collection": "Visualizza la collezione",
"column.about": "Info",
"column.blocks": "Utenti bloccati",
"column.bookmarks": "Segnalibri",
+ "column.collections": "Le mie collezioni",
"column.community": "Cronologia locale",
+ "column.create_collection": "Crea la collezione",
"column.create_list": "Crea lista",
"column.direct": "Menzioni private",
"column.directory": "Sfoglia profili",
"column.domain_blocks": "Domini bloccati",
+ "column.edit_collection": "Modifica la collezione",
"column.edit_list": "Modifica lista",
"column.favourites": "Preferiti",
"column.firehose": "Feed in diretta",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Elimina",
"confirmations.delete.message": "Sei sicuro di voler eliminare questo post?",
"confirmations.delete.title": "Eliminare il post?",
+ "confirmations.delete_collection.confirm": "Cancella",
+ "confirmations.delete_collection.message": "Questa azione non può essere annullata.",
+ "confirmations.delete_collection.title": "Cancellare \"{name}\"?",
"confirmations.delete_list.confirm": "Elimina",
"confirmations.delete_list.message": "Sei sicuro/a di voler eliminare permanentemente questo elenco?",
"confirmations.delete_list.title": "Eliminare la lista?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Post {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Post appuntato} other {Post appuntati}}",
"featured_carousel.slide": "Post {current, number} di {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "La categoria di questo filtro non si applica al contesto in cui hai acceduto a questo post. Se desideri che il post sia filtrato anche in questo contesto, dovrai modificare il filtro.",
"filter_modal.added.context_mismatch_title": "Contesto non corrispondente!",
"filter_modal.added.expired_explanation": "La categoria di questo filtro è scaduta, dovrvai modificarne la data di scadenza per applicarlo.",
@@ -451,6 +493,7 @@
"footer.source_code": "Visualizza il codice sorgente",
"footer.status": "Stato",
"footer.terms_of_service": "Termini di servizio",
+ "form_field.optional": "(opzionale)",
"generic.saved": "Salvato",
"getting_started.heading": "Per iniziare",
"hashtag.admin_moderation": "Apri l'interfaccia di moderazione per #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# nuovo oggetto} other {# nuovi oggetti}}",
"loading_indicator.label": "Caricamento…",
"media_gallery.hide": "Nascondi",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +830,7 @@
"privacy.private.short": "Follower",
"privacy.public.long": "Chiunque dentro e fuori Mastodon",
"privacy.public.short": "Pubblico",
- "privacy.quote.anyone": "{visibility}, chiunque può citare",
+ "privacy.quote.anyone": "{visibility}, citazioni autorizzate",
"privacy.quote.disabled": "{visibility}, citazioni disabilitate",
"privacy.quote.limited": "{visibility}, citazioni limitate",
"privacy.unlisted.additional": "Si comporta esattamente come pubblico, tranne per il fatto che il post non verrà visualizzato nei feed live o negli hashtag, nell'esplorazione o nella ricerca Mastodon, anche se hai attivato l'attivazione a livello di account.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notifiche",
"tabs_bar.publish": "Nuovo post",
"tabs_bar.search": "Cerca",
+ "tag.remove": "Rimuovi",
"terms_of_service.effective_as_of": "In vigore a partire dal giorno {date}",
"terms_of_service.title": "Termini di Servizio",
"terms_of_service.upcoming_changes_on": "Prossime modifiche nel giorno {date}",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 37722559424..45cce53213d 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -729,7 +729,7 @@
"privacy.private.short": "フォロワー",
"privacy.public.long": "すべての人 (Mastodon以外も含む)",
"privacy.public.short": "公開",
- "privacy.quote.anyone": "{visibility}、誰でも引用可能",
+ "privacy.quote.anyone": "{visibility}、引用可",
"privacy.quote.disabled": "{visibility}、引用不可",
"privacy.quote.limited": "{visibility}、引用は制限",
"privacy.unlisted.additional": "「公開」とほとんど同じですが、リアルタイムフィードやハッシュタグ、探索機能、Mastodon検索などに投稿が表示されない点で「公開」と異なります。また、アカウント設定で投稿の検索や表示を許可している場合でも、この公開範囲を設定した投稿は前述の機能には表示されません。",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 92850880aac..857c18821f0 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -782,7 +782,6 @@
"privacy.private.short": "팔로워",
"privacy.public.long": "마스토돈 내외 모두",
"privacy.public.short": "공개",
- "privacy.quote.anyone": "{visibility}, 누구나 인용 가능",
"privacy.quote.disabled": "{visibility}, 인용 비활성화",
"privacy.quote.limited": "{visibility}, 제한된 인용",
"privacy.unlisted.additional": "공개와 똑같지만 게시물이 실시간 피드나 해시태그, 둘러보기, (계정 설정에서 허용했더라도) 마스토돈 검색에서 제외됩니다.",
diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json
index cfbb355bb30..154d4aeb428 100644
--- a/app/javascript/mastodon/locales/lt.json
+++ b/app/javascript/mastodon/locales/lt.json
@@ -69,7 +69,7 @@
"account.mute_short": "Nutildyti",
"account.muted": "Nutildytas",
"account.muting": "Užtildymas",
- "account.mutual": "Jūs sekate vienas kitą",
+ "account.mutual": "Sekate vienas kitą",
"account.no_bio": "Nėra pateikto aprašymo.",
"account.open_original_page": "Atidaryti originalų puslapį",
"account.posts": "Įrašai",
@@ -685,7 +685,7 @@
"notifications.filter.follows": "Sekimai",
"notifications.filter.mentions": "Paminėjimai",
"notifications.filter.polls": "Balsavimo rezultatai",
- "notifications.filter.statuses": "Naujinimai iš žmonių, kuriuos seki",
+ "notifications.filter.statuses": "Naujienos iš žmonių, kuriuos sekate",
"notifications.grant_permission": "Suteikti leidimą.",
"notifications.group": "{count} pranešimai",
"notifications.mark_as_read": "Pažymėti kiekvieną pranešimą kaip perskaitytą",
@@ -747,7 +747,6 @@
"privacy.private.short": "Sekėjai",
"privacy.public.long": "Bet kas iš Mastodon ir ne Mastodon",
"privacy.public.short": "Vieša",
- "privacy.quote.anyone": "{visibility}, kiekvienas gali cituoti",
"privacy.quote.disabled": "{visibility}, paminėjimai išjungti",
"privacy.quote.limited": "{visibility}, paminėjimai apriboti",
"privacy.unlisted.additional": "Tai veikia lygiai taip pat, kaip ir vieša, tik įrašas nebus rodomas tiesioginiuose srautuose, grotažymėse, naršyme ar Mastodon paieškoje, net jei esi įtraukęs (-usi) visą paskyrą.",
@@ -821,7 +820,7 @@
"report.thanks.title": "Nenori to matyti?",
"report.thanks.title_actionable": "Ačiū, kad pranešei, mes tai išnagrinėsime.",
"report.unfollow": "Nebesekti @{name}",
- "report.unfollow_explanation": "Tu seki šią paskyrą. Jei nori nebematyti jų įrašų savo pagrindiniame sraute, nebesek jų.",
+ "report.unfollow_explanation": "Jūs sekate šią paskyrą. Kad nebematytumėte jų įrašų savo pagrindiniame sraute, nebesekite.",
"report_notification.attached_statuses": "Pridėti {count, plural, one {{count} įrašas} few {{count} įrašai} many {{count} įrašo} other {{count} įrašų}}",
"report_notification.categories.legal": "Teisinės",
"report_notification.categories.legal_sentence": "nelegalus turinys",
diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json
index f30c31cf95c..d73177da907 100644
--- a/app/javascript/mastodon/locales/lv.json
+++ b/app/javascript/mastodon/locales/lv.json
@@ -633,7 +633,6 @@
"privacy.private.short": "Sekotāji",
"privacy.public.long": "Jebkurš Mastodon platformā un ārpus tās",
"privacy.public.short": "Publisks",
- "privacy.quote.anyone": "{visibility}, jebkurš var citēt",
"privacy.quote.disabled": "{visibility}, aizliegta citēšana",
"privacy.quote.limited": "{visibility}, ierobežota citēšana",
"privacy.unlisted.additional": "Šis uzvedas tieši kā publisks, izņemot to, ka ieraksts neparādīsies tiešraides barotnēs vai tēmturos, izpētē vai Mastodon meklēšanā, pat ja esi to norādījis visa konta ietvaros.",
diff --git a/app/javascript/mastodon/locales/nan.json b/app/javascript/mastodon/locales/nan-TW.json
similarity index 99%
rename from app/javascript/mastodon/locales/nan.json
rename to app/javascript/mastodon/locales/nan-TW.json
index 4d7df2e529b..31e0b68d9ef 100644
--- a/app/javascript/mastodon/locales/nan.json
+++ b/app/javascript/mastodon/locales/nan-TW.json
@@ -786,7 +786,6 @@
"privacy.private.short": "跟tuè lí ê",
"privacy.public.long": "逐ê lâng(無論佇Mastodon以內á是以外)",
"privacy.public.short": "公開ê",
- "privacy.quote.anyone": "{visibility},ta̍k ê lâng lóng ē當引用",
"privacy.quote.disabled": "{visibility},停止引用PO文",
"privacy.quote.limited": "{visibility},PO文引用受限",
"privacy.unlisted.additional": "Tse ê行為kap公開相siâng,m̄-koh 就算lí佇口座設定phah開有關ê公開功能,PO文mā bē顯示佇即時ê動態、hashtag、探索kap Mastodon ê搜尋結果。",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index 1411a222f81..359adb32ad9 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -14,6 +14,8 @@
"about.powered_by": "Gedecentraliseerde sociale media mogelijk gemaakt door {mastodon}",
"about.rules": "Serverregels",
"account.account_note_header": "Persoonlijke opmerking",
+ "account.activity": "Activiteit",
+ "account.add_note": "Een persoonlijke opmerking toevoegen",
"account.add_or_remove_from_list": "Toevoegen aan of verwijderen uit lijsten",
"account.badges.bot": "Geautomatiseerd",
"account.badges.group": "Groep",
@@ -27,6 +29,7 @@
"account.direct": "@{name} een privébericht sturen",
"account.disable_notifications": "Geen melding meer geven wanneer @{name} een bericht plaatst",
"account.domain_blocking": "Server geblokkeerd",
+ "account.edit_note": "Persoonlijke opmerking bewerken",
"account.edit_profile": "Profiel bewerken",
"account.edit_profile_short": "Bewerken",
"account.enable_notifications": "Geef een melding wanneer @{name} een bericht plaatst",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Hashtags",
"account.featured_tags.last_status_at": "Laatste bericht op {date}",
"account.featured_tags.last_status_never": "Geen berichten",
+ "account.filters.all": "Alle activiteit",
+ "account.filters.boosts_toggle": "Boosts tonen",
+ "account.filters.posts_boosts": "Berichten en boosts",
+ "account.filters.posts_only": "Berichten",
+ "account.filters.posts_replies": "Berichten en reacties",
+ "account.filters.replies_toggle": "Reacties tonen",
"account.follow": "Volgen",
"account.follow_back": "Terugvolgen",
"account.follow_back_short": "Terugvolgen",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Ga naar profiel",
"account.hide_reblogs": "Boosts van @{name} verbergen",
"account.in_memoriam": "In memoriam.",
+ "account.joined_long": "Geregistreerd op {date}",
"account.joined_short": "Geregistreerd op",
"account.languages": "Getoonde talen wijzigen",
"account.link_verified_on": "Eigendom van deze link is gecontroleerd op {date}",
@@ -71,6 +81,14 @@
"account.muting": "Genegeerd",
"account.mutual": "Jullie volgen elkaar",
"account.no_bio": "Geen beschrijving opgegeven.",
+ "account.node_modal.callout": "Persoonlijke opmerkingen zijn alleen zichtbaar voor jou.",
+ "account.node_modal.edit_title": "Persoonlijke opmerking bewerken",
+ "account.node_modal.error_unknown": "Kon opmerking niet opslaan",
+ "account.node_modal.field_label": "Persoonlijke opmerking",
+ "account.node_modal.save": "Opslaan",
+ "account.node_modal.title": "Een persoonlijke opmerking toevoegen",
+ "account.note.edit_button": "Bewerken",
+ "account.note.title": "Persoonlijke opmerking (alleen zichtbaar voor jou)",
"account.open_original_page": "Originele pagina openen",
"account.posts": "Berichten",
"account.posts_with_replies": "Reacties",
@@ -90,6 +108,8 @@
"account.unmute": "@{name} niet langer negeren",
"account.unmute_notifications_short": "Meldingen niet langer negeren",
"account.unmute_short": "Niet langer negeren",
+ "account_fields_modal.close": "Sluiten",
+ "account_fields_modal.title": "Info over {name}",
"account_note.placeholder": "Klik om een opmerking toe te voegen",
"admin.dashboard.daily_retention": "Retentiegraad van gebruikers per dag, vanaf registratie",
"admin.dashboard.monthly_retention": "Retentiegraad van gebruikers per maand, vanaf registratie",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Sluiten",
"bundle_modal_error.message": "Er ging iets mis tijdens het laden van dit scherm.",
"bundle_modal_error.retry": "Opnieuw proberen",
+ "callout.dismiss": "Afwijzen",
"carousel.current": "Bericht {current, number} / {max, number}",
"carousel.slide": "Bericht {current, number} van {max, number}",
"closed_registrations.other_server_instructions": "Omdat Mastodon gedecentraliseerd is, kun je op een andere server een account registreren en vanaf daar nog steeds met deze server communiceren.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Een andere server zoeken",
"closed_registrations_modal.preamble": "Mastodon is gedecentraliseerd. Op welke server je ook een account hebt, je kunt overal vandaan mensen op deze server volgen en er mee interactie hebben. Je kunt zelfs zelf een Mastodon-server hosten!",
"closed_registrations_modal.title": "Registreren op Mastodon",
+ "collections.collection_description": "Omschrijving",
+ "collections.collection_name": "Naam",
+ "collections.collection_topic": "Onderwerp",
+ "collections.create_a_collection_hint": "Een verzameling aanmaken om je favoriete accounts aan te bevelen of te delen met anderen.",
+ "collections.create_collection": "Verzameling aanmaken",
+ "collections.delete_collection": "Verzameling verwijderen",
+ "collections.description_length_hint": "100 tekens limiet",
+ "collections.error_loading_collections": "Er is een fout opgetreden bij het laden van je verzamelingen.",
+ "collections.mark_as_sensitive": "Als gevoelig markeren",
+ "collections.mark_as_sensitive_hint": "Verbergt de omschrijving en de accounts van de verzameling achter een waarschuwing. De naam van de verzameling blijft zichtbaar.",
+ "collections.name_length_hint": "100 tekens limiet",
+ "collections.no_collections_yet": "Nog geen verzamelingen.",
+ "collections.topic_hint": "Voeg een hashtag toe die anderen helpt het hoofdonderwerp van deze collectie te begrijpen.",
+ "collections.view_collection": "Verzameling bekijken",
"column.about": "Over",
"column.blocks": "Geblokkeerde gebruikers",
"column.bookmarks": "Bladwijzers",
+ "column.collections": "Mijn verzamelingen",
"column.community": "Lokale tijdlijn",
+ "column.create_collection": "Verzameling aanmaken",
"column.create_list": "Lijst aanmaken",
"column.direct": "Privéberichten",
"column.directory": "Gebruikersgids",
"column.domain_blocks": "Geblokkeerde servers",
+ "column.edit_collection": "Verzameling bewerken",
"column.edit_list": "Lijst bewerken",
"column.favourites": "Favorieten",
"column.firehose": "Openbare tijdlijnen",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Verwijderen",
"confirmations.delete.message": "Weet je het zeker dat je dit bericht wilt verwijderen?",
"confirmations.delete.title": "Bericht verwijderen?",
+ "confirmations.delete_collection.confirm": "Verwijderen",
+ "confirmations.delete_collection.message": "Deze actie kan niet ongedaan worden gemaakt.",
+ "confirmations.delete_collection.title": "\"{name}\" verwijderen?",
"confirmations.delete_list.confirm": "Verwijderen",
"confirmations.delete_list.message": "Weet je zeker dat je deze lijst definitief wilt verwijderen?",
"confirmations.delete_list.title": "Lijst verwijderen?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Bericht {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Vastgezet bericht} other {Vastgezette berichten}}",
"featured_carousel.slide": "Bericht {current, number} van {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Deze filtercategorie is niet van toepassing op de context waarin je dit bericht hebt benaderd. Als je wilt dat het bericht ook in deze context wordt gefilterd, moet je het filter bewerken.",
"filter_modal.added.context_mismatch_title": "Context komt niet overeen!",
"filter_modal.added.expired_explanation": "Deze filtercategorie is verlopen. Je moet de vervaldatum wijzigen om de categorie toe te kunnen passen.",
@@ -451,6 +493,7 @@
"footer.source_code": "Broncode bekijken",
"footer.status": "Status",
"footer.terms_of_service": "Gebruiksvoorwaarden",
+ "form_field.optional": "(optioneel)",
"generic.saved": "Opgeslagen",
"getting_started.heading": "Aan de slag",
"hashtag.admin_moderation": "Moderatie-omgeving van #{name} openen",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# nieuw item} other {# nieuwe items}}",
"loading_indicator.label": "Laden…",
"media_gallery.hide": "Verberg",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +830,7 @@
"privacy.private.short": "Volgers",
"privacy.public.long": "Iedereen op Mastodon en daarbuiten",
"privacy.public.short": "Openbaar",
- "privacy.quote.anyone": "{visibility}, iedereen mag citeren",
+ "privacy.quote.anyone": "{visibility}, citeren toegestaan",
"privacy.quote.disabled": "{visibility}, citeren uitgeschakeld",
"privacy.quote.limited": "{visibility}, citeren beperkt",
"privacy.unlisted.additional": "Dit is vergelijkbaar met openbaar, behalve dat het bericht niet op openbare tijdlijnen, onder hashtags, verkennen of zoeken verschijnt, zelfs als je je account daarvoor hebt ingesteld.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Meldingen",
"tabs_bar.publish": "Nieuw bericht",
"tabs_bar.search": "Zoeken",
+ "tag.remove": "Verwijderen",
"terms_of_service.effective_as_of": "Van kracht met ingang van {date}",
"terms_of_service.title": "Gebruiksvoorwaarden",
"terms_of_service.upcoming_changes_on": "Aankomende wijzigingen op {date}",
diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json
index e22d0f0b524..5ff6778dc3c 100644
--- a/app/javascript/mastodon/locales/nn.json
+++ b/app/javascript/mastodon/locales/nn.json
@@ -14,6 +14,8 @@
"about.powered_by": "Desentraliserte sosiale medium drive av {mastodon}",
"about.rules": "Tenarreglar",
"account.account_note_header": "Personleg notat",
+ "account.activity": "Aktivitet",
+ "account.add_note": "Legg til eit personleg notat",
"account.add_or_remove_from_list": "Legg til eller fjern frå lister",
"account.badges.bot": "Robot",
"account.badges.group": "Gruppe",
@@ -27,6 +29,7 @@
"account.direct": "Nemn @{name} privat",
"account.disable_notifications": "Slutt å varsle meg når @{name} skriv innlegg",
"account.domain_blocking": "Blokkerer domenet",
+ "account.edit_note": "Rediger det personlege notatet",
"account.edit_profile": "Rediger profil",
"account.edit_profile_short": "Rediger",
"account.enable_notifications": "Varsle meg når @{name} skriv innlegg",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Emneknaggar",
"account.featured_tags.last_status_at": "Sist nytta {date}",
"account.featured_tags.last_status_never": "Ingen innlegg",
+ "account.filters.all": "All aktivitet",
+ "account.filters.boosts_toggle": "Vis framhevingar",
+ "account.filters.posts_boosts": "Innlegg og framhevingar",
+ "account.filters.posts_only": "Innlegg",
+ "account.filters.posts_replies": "Innlegg og svar",
+ "account.filters.replies_toggle": "Vis svar",
"account.follow": "Fylg",
"account.follow_back": "Fylg tilbake",
"account.follow_back_short": "Fylg tilbake",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Gå til profil",
"account.hide_reblogs": "Gøym framhevingar frå @{name}",
"account.in_memoriam": "Til minne om.",
+ "account.joined_long": "Vart med {date}",
"account.joined_short": "Vart med",
"account.languages": "Endre språktingingar",
"account.link_verified_on": "Eigarskap for denne lenkja vart sist sjekka {date}",
@@ -71,6 +81,14 @@
"account.muting": "Dempa",
"account.mutual": "De fylgjer kvarandre",
"account.no_bio": "Inga skildring er gjeven.",
+ "account.node_modal.callout": "Berre du kan sjå personlege notat.",
+ "account.node_modal.edit_title": "Rediger det personlege notatet",
+ "account.node_modal.error_unknown": "Klarte ikkje å lagra notatet",
+ "account.node_modal.field_label": "Personleg notat",
+ "account.node_modal.save": "Lagre",
+ "account.node_modal.title": "Legg til eit personleg notat",
+ "account.note.edit_button": "Rediger",
+ "account.note.title": "Personleg notat (berre synleg for deg)",
"account.open_original_page": "Opne originalsida",
"account.posts": "Tut",
"account.posts_with_replies": "Tut og svar",
@@ -90,6 +108,8 @@
"account.unmute": "Opphev demping av @{name}",
"account.unmute_notifications_short": "Opphev demping av varslingar",
"account.unmute_short": "Opphev demping",
+ "account_fields_modal.close": "Lukk",
+ "account_fields_modal.title": "{name} sine opplysingar",
"account_note.placeholder": "Klikk for å leggja til merknad",
"admin.dashboard.daily_retention": "Mengda brukarar aktive ved dagar etter registrering",
"admin.dashboard.monthly_retention": "Mengda brukarar aktive ved månader etter registrering",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Lat att",
"bundle_modal_error.message": "Noko gjekk gale då denne sida vart lasta.",
"bundle_modal_error.retry": "Prøv igjen",
+ "callout.dismiss": "Avvis",
"carousel.current": "Side {current, number} / {max, number}",
"carousel.slide": "Side {current, number} av {max, number}",
"closed_registrations.other_server_instructions": "Sidan Mastodon er desentralisert kan du lage ein brukar på ein anna tenar og framleis interagere med denne.",
@@ -191,9 +212,16 @@
"closed_registrations_modal.find_another_server": "Finn ein annan tenar",
"closed_registrations_modal.preamble": "Mastodon er desentralisert, så uansett kvar du opprettar ein konto, vil du kunne fylgje og samhandle med alle på denne tenaren. Du kan til og med ha din eigen tenar!",
"closed_registrations_modal.title": "Registrer deg på Mastodon",
+ "collections.create_a_collection_hint": "Lag ei samling for å tilrå eller dela favorittbrukarkontoane dine med andre.",
+ "collections.create_collection": "Lag ei samling",
+ "collections.delete_collection": "Slett samlinga",
+ "collections.error_loading_collections": "Noko gjekk gale då me prøvde å henta samlingane dine.",
+ "collections.no_collections_yet": "Du har ingen samlingar enno.",
+ "collections.view_collection": "Sjå samlinga",
"column.about": "Om",
"column.blocks": "Blokkerte brukarar",
"column.bookmarks": "Bokmerke",
+ "column.collections": "Samlingane mine",
"column.community": "Lokal tidsline",
"column.create_list": "Lag liste",
"column.direct": "Private omtaler",
@@ -451,6 +479,7 @@
"footer.source_code": "Vis kjeldekode",
"footer.status": "Status",
"footer.terms_of_service": "Brukarvilkår",
+ "form_field.optional": "(valfritt)",
"generic.saved": "Lagra",
"getting_started.heading": "Kom i gang",
"hashtag.admin_moderation": "Opne moderasjonsgrensesnitt for #{name}",
@@ -589,6 +618,7 @@
"load_pending": "{count, plural, one {# nytt element} other {# nye element}}",
"loading_indicator.label": "Lastar…",
"media_gallery.hide": "Gøym",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +816,7 @@
"privacy.private.short": "Fylgjarar",
"privacy.public.long": "Kven som helst på og av Mastodon",
"privacy.public.short": "Offentleg",
- "privacy.quote.anyone": "{visibility}, alle kan sitera",
+ "privacy.quote.anyone": "{visibility}, det er lov å sitera",
"privacy.quote.disabled": "{visibility}, ingen kan sitera",
"privacy.quote.limited": "{visibility}, avgrensa sitat",
"privacy.unlisted.additional": "Dette er akkurat som offentleg, bortsett frå at innlegga ikkje dukkar opp i direktestraumar eller emneknaggar, i oppdagingar eller Mastodon-søk, sjølv om du har sagt ja til at kontoen skal vera synleg.",
@@ -1007,6 +1037,7 @@
"tabs_bar.notifications": "Varsel",
"tabs_bar.publish": "Nytt innlegg",
"tabs_bar.search": "Søk",
+ "tag.remove": "Fjern",
"terms_of_service.effective_as_of": "I kraft frå {date}",
"terms_of_service.title": "Bruksvilkår",
"terms_of_service.upcoming_changes_on": "Komande endringar {date}",
diff --git a/app/javascript/mastodon/locales/pa.json b/app/javascript/mastodon/locales/pa.json
index 2520939eb77..e0ced02cbd3 100644
--- a/app/javascript/mastodon/locales/pa.json
+++ b/app/javascript/mastodon/locales/pa.json
@@ -49,6 +49,7 @@
"account.follows_you": "ਤੁਹਾਨੂੰ ਫ਼ਾਲੋ ਕਰਦੇ ਹਨ",
"account.go_to_profile": "ਪਰੋਫਾਇਲ ਉੱਤੇ ਜਾਓ",
"account.hide_reblogs": "{name} ਵਲੋਂ ਬੂਸਟ ਨੂੰ ਲੁਕਾਓ",
+ "account.joined_long": "{date} ਨੂੰ ਜੁਆਇਨ ਕੀਤਾ",
"account.joined_short": "ਜੁਆਇਨ ਕੀਤਾ",
"account.media": "ਮੀਡੀਆ",
"account.mention": "@{name} ਦਾ ਜ਼ਿਕਰ",
@@ -76,6 +77,8 @@
"account.unmute": "@{name} ਲਈ ਮੌਨ ਹਟਾਓ",
"account.unmute_notifications_short": "ਨੋਟਫਿਕੇਸ਼ਨਾਂ ਨੂੰ ਅਣ-ਮੌਨ ਕਰੋ",
"account.unmute_short": "ਮੌਨ-ਰਹਿਤ ਕਰੋ",
+ "account_fields_modal.close": "ਬੰਦ ਕਰੋ",
+ "account_fields_modal.title": "{name} ਦੀ ਜਾਣਕਾਰੀ",
"account_note.placeholder": "Click to add a note",
"admin.dashboard.retention.average": "ਔਸਤ",
"admin.dashboard.retention.cohort_size": "ਨਵੇਂ ਵਰਤੋਂਕਾਰ",
@@ -85,6 +88,13 @@
"alt_text_modal.cancel": "ਰੱਦ ਕਰੋ",
"alt_text_modal.done": "ਮੁਕੰਮਲ",
"announcement.announcement": "ਹੋਕਾ",
+ "annual_report.announcement.action_dismiss": "ਨਹੀਂ, ਧੰਨਵਾਦ",
+ "annual_report.nav_item.badge": "ਨਵਾਂ",
+ "annual_report.shared_page.donate": "ਦਾਨ ਕਰੋ",
+ "annual_report.summary.archetype.die_drei_fragezeichen": "???",
+ "annual_report.summary.close": "ਬੰਦ ਕਰੋ",
+ "annual_report.summary.copy_link": "ਲਿੰਕ ਨੂੰ ਕਾਪੀ ਕਰੋ",
+ "annual_report.summary.highlighted_post.title": "ਸਭ ਤੋਂ ਵੱਧ ਹਰਮਨਪਿਆਰੀ ਪੋਸਟ",
"annual_report.summary.most_used_app.most_used_app": "ਸਭ ਤੋਂ ਵੱਧ ਵਰਤੀ ਐਪ",
"annual_report.summary.new_posts.new_posts": "ਨਵੀਆਂ ਪੋਸਟਾਂ",
"audio.hide": "ਆਡੀਓ ਨੂੰ ਲੁਕਾਓ",
@@ -273,6 +283,8 @@
"follow_suggestions.who_to_follow": "ਕਿਸ ਨੂੰ ਫ਼ਾਲੋ ਕਰੀਏ",
"followed_tags": "ਫ਼ਾਲੋ ਕੀਤੇ ਹੈਸ਼ਟੈਗ",
"footer.about": "ਸਾਡੇ ਬਾਰੇ",
+ "footer.about_mastodon": "Mastodon ਬਾਰੇ",
+ "footer.about_server": "{domain} ਬਾਰੇ",
"footer.about_this_server": "ਇਸ ਬਾਰੇ",
"footer.directory": "ਪਰੋਫਾਇਲ ਡਾਇਰੈਕਟਰੀ",
"footer.get_app": "ਐਪ ਲਵੋ",
@@ -293,6 +305,7 @@
"hashtag.column_settings.tag_mode.any": "ਇਹਨਾਂ ਵਿੱਚੋਂ ਕੋਈ",
"hashtag.column_settings.tag_mode.none": "ਇਹਨਾਂ ਵਿੱਚੋਂ ਕੋਈ ਨਹੀਂ",
"hashtag.column_settings.tag_toggle": "Include additional tags in this column",
+ "hashtag.feature": "ਪਰੋਫਾਇਲ ਉੱਤੇ ਫ਼ੀਚਰ",
"hashtag.follow": "ਹੈਸ਼ਟੈਗ ਨੂੰ ਫ਼ਾਲੋ ਕਰੋ",
"hashtag.mute": "#{hashtag} ਨੂੰ ਮੌਨ ਕਰੋ",
"hashtag.unfollow": "ਹੈਸ਼ਟੈਗ ਨੂੰ ਅਣ-ਫ਼ਾਲੋ ਕਰੋ",
@@ -438,6 +451,7 @@
"notification_requests.exit_selection": "ਮੁਕੰਮਲ",
"notification_requests.notifications_from": "{name} ਵਲੋਂ ਨੋਟੀਫਿਕੇਸ਼ਨ",
"notification_requests.title": "ਫਿਲਟਰ ਕੀਤੇ ਨੋਟੀਫਿਕੇਸ਼ਨ",
+ "notification_requests.view": "ਨੋਟਫਿਕੇਸ਼ਨਾਂ ਨੂੰ ਵੇਖੋ",
"notifications.clear": "ਸੂਚਨਾਵਾਂ ਨੂੰ ਮਿਟਾਓ",
"notifications.clear_confirmation": "ਕੀ ਤੁਸੀਂ ਆਪਣੇ ਸਾਰੇ ਨੋਟੀਫਿਕੇਸ਼ਨਾਂ ਨੂੰ ਪੱਕੇ ਤੌਰ ਉੱਤੇ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?",
"notifications.clear_title": "ਨੋਟਫਿਕੇਸ਼ਨਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?",
@@ -481,6 +495,7 @@
"onboarding.follows.back": "ਪਿੱਛੇ",
"onboarding.follows.done": "ਮੁਕੰਮਲ",
"onboarding.follows.search": "ਖੋਜੋ",
+ "onboarding.profile.display_name": "ਦਿਖਾਇਆ ਜਾਣ ਵਾਲਾ ਨਾਂ",
"onboarding.profile.note": "ਜਾਣਕਾਰੀ",
"onboarding.profile.save_and_continue": "ਸੰਭਾਲੋ ਅਤੇ ਜਾਰੀ ਰੱਖੋ",
"onboarding.profile.title": "ਪਰੋਫਾਈਲ ਸੈਟਅੱਪ",
@@ -584,6 +599,7 @@
"status.edited": "ਆਖਰੀ ਸੋਧ ਦੀ ਤਾਰੀਖ {date}",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
"status.favourite": "ਪਸੰਦ",
+ "status.filter": "ਇਸ ਪੋਸਟ ਨੂੰ ਫਿਲਟਰ ਕਰੋ",
"status.history.created": "{name} ਨੇ {date} ਨੂੰ ਬਣਾਇਆ",
"status.history.edited": "{name} ਨੇ {date} ਨੂੰ ਸੋਧਿਆ",
"status.load_more": "ਹੋਰ ਦਿਖਾਓ",
@@ -598,6 +614,7 @@
"status.pin": "ਪਰੋਫਾਈਲ ਉੱਤੇ ਟੰਗੋ",
"status.quote": "ਹਵਾਲਾ",
"status.quote.cancel": "ਹਵਾਲੇ ਨੂੰ ਰੱਦ ਕਰੋ",
+ "status.quote_noun": "ਹਵਾਲਾ",
"status.quotes_count": "{count, plural, one {{counter} ਹਵਾਲਾ} other {{counter} ਹਵਾਲੇ}}",
"status.read_more": "ਹੋਰ ਪੜ੍ਹੋ",
"status.reblog": "ਬੂਸਟ",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index f7aa78d1289..ee44d1c30a2 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -57,6 +57,7 @@
"account.go_to_profile": "Przejdź do profilu",
"account.hide_reblogs": "Ukryj podbicia od @{name}",
"account.in_memoriam": "Ku pamięci.",
+ "account.joined_long": "Dołączył(a) dnia {date}",
"account.joined_short": "Dołączył(a)",
"account.languages": "Zmień subskrybowane języki",
"account.link_verified_on": "Własność tego odnośnika została potwierdzona {date}",
@@ -90,6 +91,8 @@
"account.unmute": "Nie wyciszaj @{name}",
"account.unmute_notifications_short": "Nie wyciszaj powiadomień",
"account.unmute_short": "Nie wyciszaj",
+ "account_fields_modal.close": "Zamknij",
+ "account_fields_modal.title": "Informacje o {name}",
"account_note.placeholder": "Kliknij, aby dodać notatkę",
"admin.dashboard.daily_retention": "Wskaźnik utrzymania użytkowników według dni od rejestracji",
"admin.dashboard.monthly_retention": "Wskaźnik utrzymania użytkowników według miesięcy od rejestracji",
@@ -126,6 +129,8 @@
"annual_report.summary.archetype.booster.desc_self": "Pozostałeś na polowaniu na posty do wzmocnienia i wzmocnienia innych twórców doskonałym celem.",
"annual_report.summary.archetype.booster.name": "Łucznik",
"annual_report.summary.archetype.die_drei_fragezeichen": "???",
+ "annual_report.summary.archetype.lurker.desc_public": "Wiemy, że {name} był(a) tam gdzieś i cieszył(a) się Mastodonem na swój własny, cichy sposób.",
+ "annual_report.summary.archetype.lurker.desc_self": "Wiemy, że byłeś(-aś) tam gdzieś i cieszyłeś(-aś) się Mastodonem na swój własny, cichy sposób.",
"annual_report.summary.archetype.lurker.name": "Stoik",
"annual_report.summary.archetype.oracle.name": "Wyrocznia",
"annual_report.summary.archetype.pollster.name": "Zastanawiacz",
@@ -764,7 +769,6 @@
"privacy.private.short": "Obserwujący",
"privacy.public.long": "Każdy na i poza Mastodon",
"privacy.public.short": "Publiczny",
- "privacy.quote.anyone": "{visibility}, każdy może cytować",
"privacy.quote.disabled": "{visibility}, cytaty wyłączone",
"privacy.quote.limited": "{visibility}, cytaty ograniczone",
"privacy.unlisted.additional": "Dostępny podobnie jak wpis publiczny, ale nie będzie widoczny w aktualnościach, hashtagach ani wyszukiwarce Mastodon, nawet jeśli twoje konto jest widoczne.",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index ad244780f9f..327d3a22b02 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -14,6 +14,8 @@
"about.powered_by": "Rede social descentralizada baseada no {mastodon}",
"about.rules": "Regras do servidor",
"account.account_note_header": "Nota pessoal",
+ "account.activity": "Atividade",
+ "account.add_note": "Adicionar nota pessoal",
"account.add_or_remove_from_list": "Adicionar ou remover de listas",
"account.badges.bot": "Robô",
"account.badges.group": "Grupo",
@@ -785,7 +787,6 @@
"privacy.private.short": "Seguidores",
"privacy.public.long": "Qualquer um dentro ou fora do Mastodon",
"privacy.public.short": "Público",
- "privacy.quote.anyone": "{visibility} Qualquer pessoa pode citar",
"privacy.quote.disabled": "{visibility} Citações desabilitadas",
"privacy.quote.limited": "{visibility} Citações limitadas",
"privacy.unlisted.additional": "Isso se comporta exatamente como público, exceto que a publicação não aparecerá nos _feeds ao vivo_ ou nas _hashtags_, explorar, ou barra de busca, mesmo que você seja escolhido em toda a conta.",
diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json
index 66710d1172b..95542aef6b7 100644
--- a/app/javascript/mastodon/locales/pt-PT.json
+++ b/app/javascript/mastodon/locales/pt-PT.json
@@ -14,6 +14,8 @@
"about.powered_by": "Rede social descentralizada baseada no {mastodon}",
"about.rules": "Regras do servidor",
"account.account_note_header": "Nota pessoal",
+ "account.activity": "Atividade",
+ "account.add_note": "Adicionar uma nota pessoal",
"account.add_or_remove_from_list": "Adicionar ou remover das listas",
"account.badges.bot": "Robô",
"account.badges.group": "Grupo",
@@ -27,6 +29,7 @@
"account.direct": "Mencionar @{name} em privado",
"account.disable_notifications": "Parar de me notificar das publicações de @{name}",
"account.domain_blocking": "A bloquear domínio",
+ "account.edit_note": "Editar nota pessoal",
"account.edit_profile": "Editar perfil",
"account.edit_profile_short": "Editar",
"account.enable_notifications": "Notificar-me das publicações de @{name}",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Etiquetas",
"account.featured_tags.last_status_at": "Última publicação em {date}",
"account.featured_tags.last_status_never": "Sem publicações",
+ "account.filters.all": "Toda a atividade",
+ "account.filters.boosts_toggle": "Mostrar partilhas",
+ "account.filters.posts_boosts": "Publicações e partilhas",
+ "account.filters.posts_only": "Publicações",
+ "account.filters.posts_replies": "Publicações e respostas",
+ "account.filters.replies_toggle": "Mostrar respostas",
"account.follow": "Seguir",
"account.follow_back": "Seguir também",
"account.follow_back_short": "Seguir de volta",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Ir para o perfil",
"account.hide_reblogs": "Esconder partilhas de @{name}",
"account.in_memoriam": "Em Memória.",
+ "account.joined_long": "Juntou-se em {date}",
"account.joined_short": "Juntou-se a",
"account.languages": "Alterar idiomas subscritos",
"account.link_verified_on": "O proprietário desta hiperligação foi verificado em {date}",
@@ -71,6 +81,14 @@
"account.muting": "A silenciar",
"account.mutual": "Seguem-se mutuamente",
"account.no_bio": "Nenhuma descrição fornecida.",
+ "account.node_modal.callout": "As notas pessoais só são visíveis por si.",
+ "account.node_modal.edit_title": "Editar nota pessoal",
+ "account.node_modal.error_unknown": "Não foi possível guardar a nota",
+ "account.node_modal.field_label": "Nota Pessoal",
+ "account.node_modal.save": "Guardar",
+ "account.node_modal.title": "Adicionar uma nota pessoal",
+ "account.note.edit_button": "Editar",
+ "account.note.title": "Nota pessoal (visível apenas por si)",
"account.open_original_page": "Abrir a página original",
"account.posts": "Publicações",
"account.posts_with_replies": "Publicações e respostas",
@@ -90,6 +108,8 @@
"account.unmute": "Desocultar @{name}",
"account.unmute_notifications_short": "Desocultar notificações",
"account.unmute_short": "Desocultar",
+ "account_fields_modal.close": "Fechar",
+ "account_fields_modal.title": "Info de {name}",
"account_note.placeholder": "Clicar para adicionar nota",
"admin.dashboard.daily_retention": "Taxa de retenção de utilizadores por dia após a inscrição",
"admin.dashboard.monthly_retention": "Taxa de retenção de utilizadores por mês após a inscrição",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Fechar",
"bundle_modal_error.message": "Algo correu mal ao carregar este ecrã.",
"bundle_modal_error.retry": "Tenta de novo",
+ "callout.dismiss": "Descartar",
"carousel.current": "Slide {current, number} / {max, number}",
"carousel.slide": "Slide {current, number} de {max, number}",
"closed_registrations.other_server_instructions": "Visto que o Mastodon é descentralizado, podes criar uma conta noutro servidor e interagir com este na mesma.",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "Procurar outro servidor",
"closed_registrations_modal.preamble": "O Mastodon é descentralizado, por isso não importa onde a tua conta é criada, pois continuarás a poder acompanhar e interagir com qualquer um neste servidor. Podes até alojar o teu próprio servidor!",
"closed_registrations_modal.title": "Criar uma conta no Mastodon",
+ "collections.collection_description": "Descrição",
+ "collections.collection_name": "Nome",
+ "collections.collection_topic": "Tópico",
+ "collections.create_a_collection_hint": "Crie uma coleção para recomendar ou partilhar as suas contas favoritas com outras pessoas.",
+ "collections.create_collection": "Criar coleção",
+ "collections.delete_collection": "Eliminar coleção",
+ "collections.description_length_hint": "Limite de 100 caracteres",
+ "collections.error_loading_collections": "Ocorreu um erro ao tentar carregar as suas coleções.",
+ "collections.mark_as_sensitive": "Marcar como sensível",
+ "collections.mark_as_sensitive_hint": "Oculta a descrição e as contas da coleção por trás de um aviso de conteúdo. O nome da coleção ainda estará visível.",
+ "collections.name_length_hint": "Limite de 100 caracteres",
+ "collections.no_collections_yet": "Ainda não existem coleções.",
+ "collections.topic_hint": "Adicione uma etiqueta para ajudar outros a entender o tópico principal desta coleção.",
+ "collections.view_collection": "Ver coleções",
"column.about": "Sobre",
"column.blocks": "Utilizadores bloqueados",
"column.bookmarks": "Marcadores",
+ "column.collections": "As minhas coleções",
"column.community": "Cronologia local",
+ "column.create_collection": "Criar coleção",
"column.create_list": "Criar lista",
"column.direct": "Menções privadas",
"column.directory": "Explorar perfis",
"column.domain_blocks": "Domínios bloqueados",
+ "column.edit_collection": "Editar coleção",
"column.edit_list": "Editar lista",
"column.favourites": "Favoritos",
"column.firehose": "Cronologias em tempo real",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "Eliminar",
"confirmations.delete.message": "De certeza que queres eliminar esta publicação?",
"confirmations.delete.title": "Eliminar publicação?",
+ "confirmations.delete_collection.confirm": "Eliminar",
+ "confirmations.delete_collection.message": "Esta ação é irreversível.",
+ "confirmations.delete_collection.title": "Eliminar \"{name}\"?",
"confirmations.delete_list.confirm": "Eliminar",
"confirmations.delete_list.message": "Tens a certeza de que desejas eliminar permanentemente esta lista?",
"confirmations.delete_list.title": "Eliminar lista?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Publicação {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Publicação Afixada} other {Publicações Afixadas}}",
"featured_carousel.slide": "Publicação {current, number} de {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Esta categoria de filtro não se aplica ao contexto em que acedeste a esta publicação. Se pretenderes que esta publicação seja filtrada também neste contexto, terás que editar o filtro.",
"filter_modal.added.context_mismatch_title": "O contexto não coincide!",
"filter_modal.added.expired_explanation": "Esta categoria de filtro expirou, tens de alterar a data de validade para que ele seja aplicado.",
@@ -451,6 +493,7 @@
"footer.source_code": "Ver código-fonte",
"footer.status": "Estado",
"footer.terms_of_service": "Termos de serviço",
+ "form_field.optional": "(opcional)",
"generic.saved": "Guardado",
"getting_started.heading": "Primeiros passos",
"hashtag.admin_moderation": "Abrir interface de moderação para #{name}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# novo item} other {# novos itens}}",
"loading_indicator.label": "A carregar…",
"media_gallery.hide": "Esconder",
+ "minicard.more_items": "+{count}",
"moved_to_account_banner.text": "A tua conta {disabledAccount} está neste momento desativada porque migraste para {movedToAccount}.",
"mute_modal.hide_from_notifications": "Ocultar das notificações",
"mute_modal.hide_options": "Ocultar opções",
@@ -786,7 +830,7 @@
"privacy.private.short": "Seguidores",
"privacy.public.long": "Qualquer pessoa no Mastodon ou não",
"privacy.public.short": "Público",
- "privacy.quote.anyone": "{visibility}, qualquer pessoa pode citar",
+ "privacy.quote.anyone": "{visibility}, citações permitidas",
"privacy.quote.disabled": "{visibility}, citações desativadas",
"privacy.quote.limited": "{visibility}, citações limitadas",
"privacy.unlisted.additional": "Este comportamento é exatamente igual ao do público, exceto que a publicação não aparecerá em cronologias, nas etiquetas, ao explorar ou na pesquisa do Mastodon, mesmo que tenhas optado por participar em toda a tua conta.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Notificações",
"tabs_bar.publish": "Nova publicação",
"tabs_bar.search": "Pesquisar",
+ "tag.remove": "Remover",
"terms_of_service.effective_as_of": "Válido a partir de {date}",
"terms_of_service.title": "Termos do serviço",
"terms_of_service.upcoming_changes_on": "Próximas aterações em {date}",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index 9a18842f76d..7424a73f12e 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -759,7 +759,6 @@
"privacy.private.short": "Для подписчиков",
"privacy.public.long": "Для кого угодно в интернете",
"privacy.public.short": "Публичный",
- "privacy.quote.anyone": "{visibility}, цитировать разрешено всем",
"privacy.quote.disabled": "{visibility}, без возможности цитирования",
"privacy.quote.limited": "{visibility}, с ограничениями цитирования",
"privacy.unlisted.additional": "Похоже на «Публичный» за исключением того, что пост не появится ни в живых лентах, ни в лентах хештегов, ни в разделе «Актуальное», ни в поиске Mastodon, даже если вы разрешили поиск по своим постам в настройках профиля.",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index d3209da5100..b5c7605285c 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -14,6 +14,7 @@
"about.powered_by": "Decentralizovaná sociálna sieť na základe technológie {mastodon}",
"about.rules": "Pravidlá servera",
"account.account_note_header": "Osobná poznámka",
+ "account.activity": "Aktivita",
"account.add_or_remove_from_list": "Pridať alebo odobrať zo zoznamov",
"account.badges.bot": "Bot",
"account.badges.group": "Skupina",
@@ -39,6 +40,8 @@
"account.featured.hashtags": "Hashtagy",
"account.featured_tags.last_status_at": "Posledný príspevok dňa {date}",
"account.featured_tags.last_status_never": "Žiadne príspevky",
+ "account.filters.posts_only": "Príspevky",
+ "account.filters.posts_replies": "Príspevky a odpovede",
"account.follow": "Sledovať",
"account.follow_back": "Sledovať späť",
"account.follow_back_short": "Sledovať späť",
@@ -665,7 +668,6 @@
"privacy.private.short": "Sledovatelia",
"privacy.public.long": "Ktokoľvek na Mastodone aj mimo neho",
"privacy.public.short": "Verejné",
- "privacy.quote.anyone": "{visibility}, hocikto môže citovať",
"privacy.quote.disabled": "{visibility}, citovanie nepovolené",
"privacy.quote.limited": "{visibility}, citovanie obmedzené",
"privacy.unlisted.additional": "Presne ako verejné, s tým rozdielom, že sa príspevok nezobrazí v živých kanáloch, hashtagoch, objavovaní či vo vyhľadávaní na Mastodone, aj keď máte pre účet objaviteľnosť zapnutú.",
diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json
index 4e401c5c882..c7aeff8ed2c 100644
--- a/app/javascript/mastodon/locales/sl.json
+++ b/app/javascript/mastodon/locales/sl.json
@@ -21,10 +21,12 @@
"account.block_domain": "Blokiraj domeno {domain}",
"account.block_short": "Blokiraj",
"account.blocked": "Blokirano",
+ "account.blocking": "Blokirano",
"account.cancel_follow_request": "Umakni zahtevo za sledenje",
"account.copy": "Kopiraj povezavo do profila",
"account.direct": "Zasebno omeni @{name}",
"account.disable_notifications": "Ne obveščaj me več, ko ima @{name} novo objavo",
+ "account.domain_blocking": "Blokirana domena",
"account.edit_profile": "Uredi profil",
"account.edit_profile_short": "Uredi",
"account.enable_notifications": "Obvesti me, ko ima @{name} novo objavo",
@@ -38,11 +40,14 @@
"account.follow": "Sledi",
"account.follow_back": "Sledi nazaj",
"account.follow_back_short": "Sledi nazaj",
+ "account.follow_request": "Zaprosi za sledenje",
"account.follow_request_cancel": "Prekliči zahtevo",
"account.follow_request_cancel_short": "Prekliči",
+ "account.follow_request_short": "Zaprosi",
"account.followers": "Sledilci",
"account.followers.empty": "Nihče še ne sledi temu uporabniku.",
"account.followers_counter": "{count, plural, one {{counter} sledilec} two {{counter} sledilca} few {{counter} sledilci} other {{counter} sledilcev}}",
+ "account.followers_you_know_counter": "{counter} znanih",
"account.following": "Sledim",
"account.following_counter": "{count, plural, one {{counter} sleden} two {{counter} sledena} few {{counter} sledeni} other {{counter} sledenih}}",
"account.follows.empty": "Ta uporabnik še ne sledi nikomur.",
@@ -50,6 +55,7 @@
"account.go_to_profile": "Pojdi na profil",
"account.hide_reblogs": "Skrij izpostavitve od @{name}",
"account.in_memoriam": "V spomin.",
+ "account.joined_long": "Pridružen/a {date}",
"account.joined_short": "Pridružil/a",
"account.languages": "Spremeni naročene jezike",
"account.link_verified_on": "Lastništvo te povezave je bilo preverjeno {date}",
@@ -61,13 +67,16 @@
"account.mute_notifications_short": "Utišaj obvestila",
"account.mute_short": "Utišaj",
"account.muted": "Utišan",
+ "account.muting": "Izklop zvoka",
"account.mutual": "Drug drugemu sledita",
"account.no_bio": "Ni opisa.",
"account.open_original_page": "Odpri izvirno stran",
"account.posts": "Objave",
"account.posts_with_replies": "Objave in odgovori",
+ "account.remove_from_followers": "Odstrani {name} iz sledilcev",
"account.report": "Prijavi @{name}",
"account.requested_follow": "{name} vam želi slediti",
+ "account.requests_to_follow_you": "Vas prosi za sledenje",
"account.share": "Deli profil osebe @{name}",
"account.show_reblogs": "Pokaži izpostavitve osebe @{name}",
"account.statuses_counter": "{count, plural, one {{counter} objava} two {{counter} objavi} few {{counter} objave} other {{counter} objav}}",
@@ -80,6 +89,8 @@
"account.unmute": "Povrni glas @{name}",
"account.unmute_notifications_short": "Izklopi utišanje obvestil",
"account.unmute_short": "Povrni glas",
+ "account_fields_modal.close": "Zapri",
+ "account_fields_modal.title": "Podatki o: {name}",
"account_note.placeholder": "Kliknite, da dodate opombo",
"admin.dashboard.daily_retention": "Mera ohranjanja uporabnikov po dnevih od registracije",
"admin.dashboard.monthly_retention": "Mera ohranjanja uporabnikov po mesecih od registracije",
@@ -103,11 +114,29 @@
"alt_text_modal.describe_for_people_with_visual_impairments": "Podaj opis za slabovidne ...",
"alt_text_modal.done": "Opravljeno",
"announcement.announcement": "Oznanilo",
+ "annual_report.announcement.action_dismiss": "Ne, hvala",
+ "annual_report.nav_item.badge": "Nov",
+ "annual_report.shared_page.donate": "Prispevaj",
+ "annual_report.shared_page.footer": "S {heart} ustvarila ekipa Mastodon",
+ "annual_report.summary.archetype.booster.name": "Lokostrelec",
+ "annual_report.summary.archetype.die_drei_fragezeichen": "???",
+ "annual_report.summary.archetype.lurker.name": "Stoik",
+ "annual_report.summary.archetype.oracle.name": "Orakelj",
+ "annual_report.summary.archetype.replier.name": "Metulj",
+ "annual_report.summary.archetype.reveal": "Razkrij moj arhetip",
+ "annual_report.summary.archetype.title_public": "Arhetip {name}",
+ "annual_report.summary.archetype.title_self": "Vaš arhetip",
+ "annual_report.summary.close": "Zapri",
+ "annual_report.summary.copy_link": "Kopiraj povezavo",
+ "annual_report.summary.followers.new_followers": "{count, plural, one {{counter} nov sledilec} two {{counter} nova sledilca} few {{counter} novi sledilci} other {{counter} novih sledilcev}}",
+ "annual_report.summary.highlighted_post.title": "Najbolj priljubljena objava",
"annual_report.summary.most_used_app.most_used_app": "najpogosteje uporabljena aplikacija",
"annual_report.summary.most_used_hashtag.most_used_hashtag": "največkrat uporabljen ključnik",
"annual_report.summary.new_posts.new_posts": "nove objave",
"annual_report.summary.percentile.text": "S tem ste se uvrstili med zgornjih uporabnikov domene {domain}.",
"annual_report.summary.percentile.we_wont_tell_bernie": "Živi duši ne bomo povedali.",
+ "annual_report.summary.share_elsewhere": "Deli drugje",
+ "annual_report.summary.share_on_mastodon": "Deli na Mastodonu",
"attachments_list.unprocessed": "(neobdelano)",
"audio.hide": "Skrij zvok",
"block_modal.remote_users_caveat": "Strežnik {domain} bomo pozvali, naj spoštuje vašo odločitev. Kljub temu pa ni gotovo, da bo strežnik prošnjo upošteval, saj nekateri strežniki blokiranja obravnavajo drugače. Javne objave bodo morda še vedno vidne neprijavljenim uporabnikom.",
@@ -133,14 +162,21 @@
"bundle_modal_error.close": "Zapri",
"bundle_modal_error.message": "Med nalaganjem prikaza je prišlo do napake.",
"bundle_modal_error.retry": "Poskusi znova",
+ "callout.dismiss": "Opusti",
+ "carousel.current": "Prosojnica {current, number} / {max, number}",
+ "carousel.slide": "Prosojnica {current, number} od {max, number}",
"closed_registrations.other_server_instructions": "Ker je Mastodon decentraliziran, lahko ustvarite račun na drugem strežniku in ste še vedno v interakciji s tem.",
"closed_registrations_modal.description": "Odpiranje računa na domeni {domain} trenutno ni možno, upoštevajte pa, da ne potrebujete računa prav na domeni {domain}, da bi uporabljali Mastodon.",
"closed_registrations_modal.find_another_server": "Najdi drug strežnik",
"closed_registrations_modal.preamble": "Mastodon je decentraliziran, kar pomeni, da ni pomembno, kje ustvarite svoj račun; od koder koli je mogoče slediti in komunicirati z vsemi s tega strežnika. Strežnik lahko gostite tudi sami!",
"closed_registrations_modal.title": "Registracija v Mastodon",
+ "collections.create_collection": "Ustvari zbirko",
+ "collections.delete_collection": "Izbriši zbirko",
+ "collections.view_collection": "Pokaži zbirko",
"column.about": "O programu",
"column.blocks": "Blokirani uporabniki",
"column.bookmarks": "Zaznamki",
+ "column.collections": "Moje zbirke",
"column.community": "Krajevna časovnica",
"column.create_list": "Ustvari seznam",
"column.direct": "Zasebne omembe",
@@ -203,6 +239,7 @@
"confirmations.delete_list.confirm": "Izbriši",
"confirmations.delete_list.message": "Ali ste prepričani, da želite trajno izbrisati ta seznam?",
"confirmations.delete_list.title": "Želite izbrisati seznam?",
+ "confirmations.discard_draft.confirm": "Opusti in nadaljuj",
"confirmations.discard_draft.edit.cancel": "Nadaljuj z urejanjem",
"confirmations.discard_draft.post.cancel": "Nadaljuj na osnutku",
"confirmations.discard_edit_media.confirm": "Opusti",
@@ -277,6 +314,7 @@
"domain_pill.your_handle": "Vaša ročica:",
"domain_pill.your_server": "Vaše digitalno domovanje, kjer bivajo vse vaše objave. Vam ni všeč? Kadar koli ga prenesite med strežniki in z njim tudi svoje sledilce.",
"domain_pill.your_username": "Vaš edinstveni identifikator na tem strežniku. Uporabnike z istim uporabniškim imenom je možno najti na različnih strežnikih.",
+ "dropdown.empty": "Izberite možnost",
"embed.instructions": "Vstavite to objavo na svojo spletno stran tako, da kopirate spodnjo kodo.",
"embed.preview": "Takole bo videti:",
"emoji_button.activity": "Dejavnost",
@@ -326,6 +364,8 @@
"explore.trending_links": "Novice",
"explore.trending_statuses": "Objave",
"explore.trending_tags": "Ključniki",
+ "featured_carousel.current": "Objava {current, number} / {max, number}",
+ "featured_carousel.slide": "Objava {current, number} od {max, number}",
"filter_modal.added.context_mismatch_explanation": "Ta kategorija filtra ne velja za kontekst, v katerem ste dostopali do te objave. Če želite, da je objava filtrirana tudi v tem kontekstu, morate urediti filter.",
"filter_modal.added.context_mismatch_title": "Neujemanje konteksta!",
"filter_modal.added.expired_explanation": "Ta kategorija filtra je pretekla. Morali boste spremeniti datum veljavnosti, da bo veljal še naprej.",
@@ -368,6 +408,8 @@
"follow_suggestions.who_to_follow": "Komu slediti",
"followed_tags": "Sledeni ključniki",
"footer.about": "O Mastodonu",
+ "footer.about_mastodon": "O Mastodonu",
+ "footer.about_server": "O {domain}",
"footer.directory": "Imenik profilov",
"footer.get_app": "Prenesite aplikacijo",
"footer.keyboard_shortcuts": "Tipkovne bližnjice",
@@ -375,6 +417,7 @@
"footer.source_code": "Pokaži izvorno kodo",
"footer.status": "Stanje",
"footer.terms_of_service": "Pogoji uporabe",
+ "form_field.optional": "(neobvezno)",
"generic.saved": "Shranjeno",
"getting_started.heading": "Kako začeti",
"hashtag.admin_moderation": "Odpri vmesnik za moderiranje za #{name}",
@@ -464,6 +507,7 @@
"keyboard_shortcuts.toggle_hidden": "Pokaži/skrij besedilo za CW",
"keyboard_shortcuts.toggle_sensitivity": "Pokaži/skrij predstavnosti",
"keyboard_shortcuts.toot": "Začni povsem novo objavo",
+ "keyboard_shortcuts.top": "Premakni na vrh seznama",
"keyboard_shortcuts.translate": "za prevod objave",
"keyboard_shortcuts.unfocus": "Odstrani pozornost z območja za sestavljanje besedila/iskanje",
"keyboard_shortcuts.up": "Premakni navzgor po seznamu",
@@ -507,6 +551,7 @@
"load_pending": "{count, plural, one {# nov element} two {# nova elementa} few {# novi elementi} other {# novih elementov}}",
"loading_indicator.label": "Nalaganje …",
"media_gallery.hide": "Skrij",
+ "minicard.more_items": "+{count}",
"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",
@@ -533,6 +578,8 @@
"navigation_bar.follows_and_followers": "Sledenja in sledilci",
"navigation_bar.import_export": "Uvoz in izvoz",
"navigation_bar.lists": "Seznami",
+ "navigation_bar.live_feed_local": "Vir v živo (krajevno)",
+ "navigation_bar.live_feed_public": "Vir v živo (javno)",
"navigation_bar.logout": "Odjava",
"navigation_bar.moderation": "Moderiranje",
"navigation_bar.more": "Več",
@@ -812,6 +859,10 @@
"status.cancel_reblog_private": "Prekliči izpostavitev",
"status.cannot_reblog": "Te objave ni mogoče izpostaviti",
"status.contains_quote": "Vsebuje citat",
+ "status.context.loading": "Nalaganje več odgovorov",
+ "status.context.loading_error": "Novih odgovorov ni bilo možno naložiti",
+ "status.context.loading_success": "Novi odgovori naloženi",
+ "status.context.more_replies_found": "Najdenih več odgovorov",
"status.context.retry": "Poskusi znova",
"status.context.show": "Pokaži",
"status.continued_thread": "Nadaljevanje niti",
@@ -839,14 +890,22 @@
"status.mute_conversation": "Utišaj pogovor",
"status.open": "Razširi to objavo",
"status.pin": "Pripni na profil",
+ "status.quote": "Citiraj",
"status.quote.cancel": "Prekliči citat",
+ "status.quote_error.blocked_account_hint.title": "Ta objava je skrita, ker ste blokirali up. @{name}.",
+ "status.quote_error.blocked_domain_hint.title": "Ta objava je skrita, ker ste blokirali {domain}.",
"status.quote_error.filtered": "Skrito zaradi enega od vaših filtrov",
"status.quote_error.limited_account_hint.action": "Vseeno pokaži",
"status.quote_error.limited_account_hint.title": "Ta račun so moderatorji {domain} skrili.",
+ "status.quote_error.muted_account_hint.title": "Ta objava je skrita, ker ste utišali up. @{name}.",
"status.quote_error.not_available": "Objava ni na voljo",
+ "status.quote_error.revoked": "Avtor je umaknil objavo",
"status.quote_followers_only": "Samo sledilci lahko citirajo to objavo",
"status.quote_policy_change": "Spremenite, kdo lahko citira",
"status.quote_private": "Zasebnih objav ni možno citirati",
+ "status.quotes.empty": "Nihče še ni citiral te objave. Ko se bo to zgodilo, se bodo pojavile tukaj.",
+ "status.quotes.local_other_disclaimer": "Citati, ki jih je avtor zavrnil, ne bodo prikazani.",
+ "status.quotes_count": "{count, plural, one {{counter} citat} two {{counter} citata} few {{counter} citati} other {{counter} citatov}}",
"status.read_more": "Preberi več",
"status.reblog": "Izpostavi",
"status.reblogged_by": "{name} je izpostavil/a",
@@ -897,6 +956,7 @@
"upload_button.label": "Dodajte slike, video ali zvočno datoteko",
"upload_error.limit": "Omejitev prenosa datoteke je presežena.",
"upload_error.poll": "Prenos datoteke z anketami ni dovoljen.",
+ "upload_error.quote": "Prenos datoteke s citati ni dovoljen.",
"upload_form.drag_and_drop.instructions": "Predstavnostno priponko lahko poberete tako, da pritisnete preslednico ali vnašalko. S puščicami na tipkovnici premikate priponko v posamezno smer. Priponko lahko odložite na novem položaju s ponovnim pritiskom na preslednico ali vnašalko ali pa dejanje prekličete s tipko ubežnica.",
"upload_form.drag_and_drop.on_drag_cancel": "Premikanje priponke je preklicano. Predstavnostna priponka {item} je padla nazaj na prejšnje mesto.",
"upload_form.drag_and_drop.on_drag_end": "Predstavnostna priponka {item} je padla nazaj.",
@@ -920,7 +980,9 @@
"video.unmute": "Odtišaj",
"video.volume_down": "Zmanjšaj glasnost",
"video.volume_up": "Povečaj glasnost",
+ "visibility_modal.button_title": "Določi vidnost",
"visibility_modal.header": "Vidnost in interakcija",
+ "visibility_modal.helper.privacy_editing": "Vidnosti ni moč spremeniti, ko je objava objavljena.",
"visibility_modal.privacy_label": "Vidnost",
"visibility_modal.quote_followers": "Samo sledilci",
"visibility_modal.quote_label": "Kdo lahko citira",
diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json
index 300966b2093..ad9e19c2af5 100644
--- a/app/javascript/mastodon/locales/sq.json
+++ b/app/javascript/mastodon/locales/sq.json
@@ -14,6 +14,8 @@
"about.powered_by": "Media shoqërore e decentralizuar, bazuar në {mastodon}",
"about.rules": "Rregulla shërbyesi",
"account.account_note_header": "Shënim personal",
+ "account.activity": "Veprimtari",
+ "account.add_note": "Shtoni një shënim personal",
"account.add_or_remove_from_list": "Shtoni ose Hiqni prej listash",
"account.badges.bot": "Robot",
"account.badges.group": "Grup",
@@ -27,6 +29,7 @@
"account.direct": "Përmendje private për @{name}",
"account.disable_notifications": "Resht së njoftuari mua, kur poston @{name}",
"account.domain_blocking": "Bllokim përkatësie",
+ "account.edit_note": "Përpunoni shënim personal",
"account.edit_profile": "Përpunoni profilin",
"account.edit_profile_short": "Përpunojeni",
"account.enable_notifications": "Njoftomë, kur poston @{name}",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Hashtag-ë",
"account.featured_tags.last_status_at": "Postimi i fundit më {date}",
"account.featured_tags.last_status_never": "Pa postime",
+ "account.filters.all": "Krejt veprimtarinë",
+ "account.filters.boosts_toggle": "Shfaq përforcime",
+ "account.filters.posts_boosts": "Postime dhe përforcime",
+ "account.filters.posts_only": "Postime",
+ "account.filters.posts_replies": "Postime dhe përgjigje",
+ "account.filters.replies_toggle": "Shfaq përgjigje",
"account.follow": "Ndiqeni",
"account.follow_back": "Ndiqe gjithashtu",
"account.follow_back_short": "Ndiqe gjithashtu",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Kalo te profili",
"account.hide_reblogs": "Fshih përforcime nga @{name}",
"account.in_memoriam": "In Memoriam.",
+ "account.joined_long": "U bë pjesë më {date}",
"account.joined_short": "U bë pjesë",
"account.languages": "Ndryshoni gjuhë pajtimesh",
"account.link_verified_on": "Pronësia e kësaj lidhjeje qe kontrolluar më {date}",
@@ -71,6 +81,14 @@
"account.muting": "Heshtim",
"account.mutual": "Ndiqni njëri-tjetrin",
"account.no_bio": "S’u dha përshkrim.",
+ "account.node_modal.callout": "Shënimet personale janë të dukshme vetëm për ju.",
+ "account.node_modal.edit_title": "Përpunoni shënim personal",
+ "account.node_modal.error_unknown": "S’u ruajt dot shënimi",
+ "account.node_modal.field_label": "Shënim Personal",
+ "account.node_modal.save": "Ruaje",
+ "account.node_modal.title": "Shtoni një shënim personal",
+ "account.note.edit_button": "Përpunojeni",
+ "account.note.title": "Shënim personal (i dukshëm vetëm për ju)",
"account.open_original_page": "Hap faqen origjinale",
"account.posts": "Mesazhe",
"account.posts_with_replies": "Mesazhe dhe përgjigje",
@@ -90,6 +108,8 @@
"account.unmute": "Ktheji zërin @{name}",
"account.unmute_notifications_short": "Shfaqi njoftimet",
"account.unmute_short": "Çheshtoje",
+ "account_fields_modal.close": "Mbylle",
+ "account_fields_modal.title": "Hollësi për {name}",
"account_note.placeholder": "Klikoni për të shtuar shënim",
"admin.dashboard.daily_retention": "Shkallë mbajtjeje përdoruesi, në ditë, pas regjistrimit",
"admin.dashboard.monthly_retention": "Shkallë mbajtjeje përdoruesi, në muaj, pas regjistrimit",
@@ -182,6 +202,7 @@
"bundle_modal_error.close": "Mbylle",
"bundle_modal_error.message": "Diç shkoi ters, teksa ngarkohej kjo skenë.",
"bundle_modal_error.retry": "Riprovoni",
+ "callout.dismiss": "Hidhe tej",
"carousel.current": "Diapozitivi {current, number} / {max, number}",
"carousel.slide": "Diapozitivi {current, number} nga {max, number} gjithsej",
"closed_registrations.other_server_instructions": "Ngaqë Mastodon-i është i decentralizuar, mund të krijoni një llogari në një tjetër shërbyes dhe prapë të ndëveproni me këtë këtu.",
@@ -189,14 +210,31 @@
"closed_registrations_modal.find_another_server": "Gjeni shërbyes tjetër",
"closed_registrations_modal.preamble": "Mastodon-i është i decentralizuar, ndaj pavarësisht se ku krijoni llogarinë tuaj, do të jeni në gjendje të ndiqni dhe ndërveproni me këdo në këtë shërbyes. Mundeni madje edhe ta strehoni ju vetë!",
"closed_registrations_modal.title": "Po regjistroheni në Mastodon",
+ "collections.collection_description": "Përshkrim",
+ "collections.collection_name": "Emër",
+ "collections.collection_topic": "Temë",
+ "collections.create_a_collection_hint": "Krijoni një koleksion për ta rekomanduar, ose për të ndarë me të tjerët llogaritë tuaja të parapëlqyera.",
+ "collections.create_collection": "Krijoni koleksion",
+ "collections.delete_collection": "Fshije koleksionin",
+ "collections.description_length_hint": "Kufi prej 100 shenjash",
+ "collections.error_loading_collections": "Pati një gabim teksa provohej të ngarkoheshin koleksionet tuaj.",
+ "collections.mark_as_sensitive": "Vëri shenjë si rezervat",
+ "collections.mark_as_sensitive_hint": "Bën fshehejn e përshkrimit të koleksionit dhe llogarive prapa një sinjalizimi lënde. Emri i koleksionit do të jetë ende i dukshëm.",
+ "collections.name_length_hint": "Kufi prej 100 shenjash",
+ "collections.no_collections_yet": "Ende pa koleksione.",
+ "collections.topic_hint": "Shtoni një hashtag që ndihmon të tjerët të kuptojnë temën kryesore të këtij koleksion.",
+ "collections.view_collection": "Shiheni koleksionin",
"column.about": "Mbi",
"column.blocks": "Përdorues të bllokuar",
"column.bookmarks": "Faqerojtës",
+ "column.collections": "Koleksionet e mi",
"column.community": "Rrjedhë kohore vendore",
+ "column.create_collection": "Krijoni koleksion",
"column.create_list": "Krijo listë",
"column.direct": "Përmendje private",
"column.directory": "Shfletoni profile",
"column.domain_blocks": "Përkatësi të bllokuara",
+ "column.edit_collection": "Përpunoni koleksion",
"column.edit_list": "Përpunoni listën",
"column.favourites": "Të parapëlqyer",
"column.firehose": "Prurje “live”",
@@ -251,6 +289,9 @@
"confirmations.delete.confirm": "Fshije",
"confirmations.delete.message": "Jeni i sigurt se doni të fshihet kjo gjendje?",
"confirmations.delete.title": "Të fshihet postimi?",
+ "confirmations.delete_collection.confirm": "Fshije",
+ "confirmations.delete_collection.message": "Kjo llogari s’mund të zhbëhet.",
+ "confirmations.delete_collection.title": "Të fshihet “{name}”?",
"confirmations.delete_list.confirm": "Fshije",
"confirmations.delete_list.message": "Jeni i sigurt se doni të fshihet përgjithmonë kjo listë?",
"confirmations.delete_list.title": "Të fshihet lista?",
@@ -397,6 +438,7 @@
"featured_carousel.current": "Postimi {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {Postim i Fiksuar} other {Postime të Fiksuar}}",
"featured_carousel.slide": "Postimi {current, number} nga {max, number} gjithsej",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Kjo kategori filtrash nuk aplikohet për kontekstin nën të cilin po merreni me këtë postim. Nëse doni që postimi të filtrohet edhe në këtë kontekst, do t’ju duhet të përpunoni filtrin.",
"filter_modal.added.context_mismatch_title": "Mospërputhje kontekstesh!",
"filter_modal.added.expired_explanation": "Kjo kategori filtrash ka skaduar, do t’ju duhet të ndryshoni datën e skadimit për të, pa të aplikohet.",
@@ -449,6 +491,7 @@
"footer.source_code": "Shihni kodin burim",
"footer.status": "Gjendje",
"footer.terms_of_service": "Kushte shërbimi",
+ "form_field.optional": "(opsionale)",
"generic.saved": "U ruajt",
"getting_started.heading": "Si t’ia fillohet",
"hashtag.admin_moderation": "Hap ndërfaqe moderimi për #{name}",
@@ -587,6 +630,7 @@
"load_pending": "{count, plural,one {# objekt i ri }other {# objekte të rinj }}",
"loading_indicator.label": "Po ngarkohet…",
"media_gallery.hide": "Fshihe",
+ "minicard.more_items": "+{count}",
"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ë",
@@ -784,7 +828,7 @@
"privacy.private.short": "Ndjekës",
"privacy.public.long": "Cilido që hyn e del në Mastodon",
"privacy.public.short": "Publik",
- "privacy.quote.anyone": "{visibility}, mund të citojë cilido",
+ "privacy.quote.anyone": "{visibility}, lejohen citimet",
"privacy.quote.disabled": "{visibility}, citimet janë çaktivizuar",
"privacy.quote.limited": "{visibility}, citime të kufizuara",
"privacy.unlisted.additional": "Ky sillet saktësisht si publik, vetëm se postimi s’do të shfaqet në prurje të drejtpërdrejta, ose në hashtag-ë, te eksploroni, apo kërkim në Mastodon, edhe kur keni zgjedhur të jetë për tërë llogarinë.",
@@ -1005,6 +1049,7 @@
"tabs_bar.notifications": "Njoftime",
"tabs_bar.publish": "Postimi i Ri",
"tabs_bar.search": "Kërkim",
+ "tag.remove": "Hiqe",
"terms_of_service.effective_as_of": "Hyn në fuqi që prej {date}",
"terms_of_service.title": "Kushte Shërbimi",
"terms_of_service.upcoming_changes_on": "Ndryshime të ardhshme më {date}",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index 67b8aea8c1b..c4839f6c54d 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -57,6 +57,7 @@
"account.go_to_profile": "Gå till profilen",
"account.hide_reblogs": "Dölj boostar från @{name}",
"account.in_memoriam": "Till minne av.",
+ "account.joined_long": "Gick med {date}",
"account.joined_short": "Gick med",
"account.languages": "Ändra vilka språk du helst vill se i ditt flöde",
"account.link_verified_on": "Ägarskap för denna länk kontrollerades den {date}",
@@ -90,6 +91,8 @@
"account.unmute": "Sluta tysta @{name}",
"account.unmute_notifications_short": "Aktivera aviseringsljud",
"account.unmute_short": "Avtysta",
+ "account_fields_modal.close": "Stäng",
+ "account_fields_modal.title": "{name}s info",
"account_note.placeholder": "Klicka för att lägga till anteckning",
"admin.dashboard.daily_retention": "Användarlojalitet per dag efter registrering",
"admin.dashboard.monthly_retention": "Användarlojalitet per månad efter registrering",
@@ -184,6 +187,7 @@
"bundle_modal_error.close": "Stäng",
"bundle_modal_error.message": "Något gick fel när skärmen laddades.",
"bundle_modal_error.retry": "Försök igen",
+ "callout.dismiss": "Avfärda",
"carousel.current": "Bild{current, number} / {max, number}",
"carousel.slide": "Bild {current, number} av {max, number}",
"closed_registrations.other_server_instructions": "Eftersom Mastodon är decentraliserat kan du skapa ett konto på en annan server och fortfarande interagera med denna.",
@@ -191,9 +195,16 @@
"closed_registrations_modal.find_another_server": "Hitta en annan server",
"closed_registrations_modal.preamble": "Mastodon är decentraliserat så oavsett var du skapar ditt konto kommer du att kunna följa och interagera med någon på denna server. Du kan också köra din egen server!",
"closed_registrations_modal.title": "Registrera sig på Mastodon",
+ "collections.create_a_collection_hint": "Skapa en samling för att rekommendera eller dela dina favoritkonton med andra.",
+ "collections.create_collection": "Skapa samling",
+ "collections.delete_collection": "Radera samling",
+ "collections.error_loading_collections": "Det uppstod ett fel när dina samlingar skulle laddas.",
+ "collections.no_collections_yet": "Inga samlingar än.",
+ "collections.view_collection": "Visa samling",
"column.about": "Om",
"column.blocks": "Blockerade användare",
"column.bookmarks": "Bokmärken",
+ "column.collections": "Mina samlingar",
"column.community": "Lokal tidslinje",
"column.create_list": "Skapa lista",
"column.direct": "Privata omnämnande",
@@ -786,7 +797,6 @@
"privacy.private.short": "Följare",
"privacy.public.long": "Alla på och utanför Mastodon",
"privacy.public.short": "Offentlig",
- "privacy.quote.anyone": "{visibility}, vem som helst kan citera",
"privacy.quote.disabled": "{visibility}, citat inaktiverade",
"privacy.quote.limited": "{visibility}, citat begränsade",
"privacy.unlisted.additional": "Detta fungerar precis som offentlig, förutom att inlägget inte visas i liveflöden eller hashtaggar, utforska eller Mastodon-sökning, även om du har valt detta för hela kontot.",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index a6fc469c2d1..52887b84515 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -708,7 +708,6 @@
"privacy.private.short": "ผู้ติดตาม",
"privacy.public.long": "ใครก็ตามที่อยู่ในและนอก Mastodon",
"privacy.public.short": "สาธารณะ",
- "privacy.quote.anyone": "{visibility}, ใครก็ตามสามารถอ้างอิง",
"privacy.quote.disabled": "{visibility}, ปิดใช้งานการอ้างอิงแล้ว",
"privacy.quote.limited": "{visibility}, จำกัดการอ้างอิงอยู่",
"privacy.unlisted.additional": "สิ่งนี้ทำงานเหมือนกับสาธารณะทุกประการ ยกเว้นโพสต์จะไม่ปรากฏในฟีดสดหรือแฮชแท็ก, การสำรวจ หรือการค้นหา Mastodon แม้ว่าคุณได้เลือกรับทั่วทั้งบัญชีก็ตาม",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index 4356fce6c5d..f3beb3f9d91 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -14,6 +14,8 @@
"about.powered_by": "{mastodon} destekli merkeziyetsiz sosyal ağ",
"about.rules": "Sunucu kuralları",
"account.account_note_header": "Kişisel not",
+ "account.activity": "Aktivite",
+ "account.add_note": "Kişisel bir not ekle",
"account.add_or_remove_from_list": "Listelere ekle veya kaldır",
"account.badges.bot": "Bot",
"account.badges.group": "Grup",
@@ -27,6 +29,7 @@
"account.direct": "@{name} kullanıcısından özel olarak bahset",
"account.disable_notifications": "@{name} kişisinin gönderi bildirimlerini kapat",
"account.domain_blocking": "Alan adını engelleme",
+ "account.edit_note": "Kişisel notu düzenle",
"account.edit_profile": "Profili düzenle",
"account.edit_profile_short": "Düzenle",
"account.enable_notifications": "@{name} kişisinin gönderi bildirimlerini aç",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "Etiketler",
"account.featured_tags.last_status_at": "Son gönderinin tarihi {date}",
"account.featured_tags.last_status_never": "Gönderi yok",
+ "account.filters.all": "Tüm aktiviteler",
+ "account.filters.boosts_toggle": "Yeniden paylaşımları göster",
+ "account.filters.posts_boosts": "Gönderiler ve yeniden paylaşımlar",
+ "account.filters.posts_only": "Gönderiler",
+ "account.filters.posts_replies": "Gönderiler ve yanıtlar",
+ "account.filters.replies_toggle": "Yanıtları göster",
"account.follow": "Takip et",
"account.follow_back": "Geri takip et",
"account.follow_back_short": "Geri takip et",
@@ -57,6 +66,7 @@
"account.go_to_profile": "Profile git",
"account.hide_reblogs": "@{name} kişisinin yeniden paylaşımlarını gizle",
"account.in_memoriam": "Hatırasına.",
+ "account.joined_long": "{date} tarihinde katıldı",
"account.joined_short": "Katıldı",
"account.languages": "Abone olunan dilleri değiştir",
"account.link_verified_on": "Bu bağlantının sahipliği {date} tarihinde denetlendi",
@@ -71,6 +81,14 @@
"account.muting": "Sessize alınıyor",
"account.mutual": "Birbirinizi takip ediyorsunuz",
"account.no_bio": "Herhangi bir açıklama belirtilmedi.",
+ "account.node_modal.callout": "Kişisel notları sadece siz görüntüleyebilirsiniz.",
+ "account.node_modal.edit_title": "Kişisel notu düzenle",
+ "account.node_modal.error_unknown": "Not kaydedilemiyor",
+ "account.node_modal.field_label": "Kişisel Not",
+ "account.node_modal.save": "Kaydet",
+ "account.node_modal.title": "Kişisel bir not ekle",
+ "account.note.edit_button": "Düzenle",
+ "account.note.title": "Kişisel not (sadece siz görüntüleyebilirsiniz)",
"account.open_original_page": "Asıl sayfayı aç",
"account.posts": "Gönderiler",
"account.posts_with_replies": "Gönderiler ve yanıtlar",
@@ -90,6 +108,8 @@
"account.unmute": "@{name} adlı kişinin sesini aç",
"account.unmute_notifications_short": "Bildirimlerin sesini aç",
"account.unmute_short": "Susturmayı kaldır",
+ "account_fields_modal.close": "Kapat",
+ "account_fields_modal.title": "{name} bilgileri",
"account_note.placeholder": "Not eklemek için tıklayın",
"admin.dashboard.daily_retention": "Kayıttan sonra günlük kullanıcı saklama oranı",
"admin.dashboard.monthly_retention": "Kayıttan sonra aylık kullanıcı saklama oranı",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "Kapat",
"bundle_modal_error.message": "Bu ekran yüklenirken bir şeyler ters gitti.",
"bundle_modal_error.retry": "Tekrar deneyin",
+ "callout.dismiss": "Yoksay",
"carousel.current": "Slayt {current, number} / {max, number}",
"carousel.slide": "Slayt {current, number} / {max, number}",
"closed_registrations.other_server_instructions": "Mastodon merkeziyetsiz olduğu için, başka bir sunucuda bir hesap oluşturabilir ve bu sunucuyla etkileşimde bulunmaya devam edebilirsiniz.",
@@ -191,9 +212,16 @@
"closed_registrations_modal.find_another_server": "Başka sunucu bul",
"closed_registrations_modal.preamble": "Mastodon merkeziyetsizdir, bu yüzden hesabınızı nerede oluşturursanız oluşturun, bu sunucudaki herhangi birini takip edebilecek veya onunla etkileşebileceksiniz. Hatta kendi sunucunuzu bile barındırabilirsiniz!",
"closed_registrations_modal.title": "Mastodon'a kayıt olmak",
+ "collections.create_a_collection_hint": "En sevdiğiniz hesapları başkalarına önermek veya paylaşmak için bir koleksiyon oluşturun.",
+ "collections.create_collection": "Koleksiyon oluştur",
+ "collections.delete_collection": "Koleksiyonu sil",
+ "collections.error_loading_collections": "Koleksiyonlarınızı yüklemeye çalışırken bir hata oluştu.",
+ "collections.no_collections_yet": "Henüz hiçbir koleksiyon yok.",
+ "collections.view_collection": "Koleksiyonu görüntüle",
"column.about": "Hakkında",
"column.blocks": "Engellenen kullanıcılar",
"column.bookmarks": "Yer İşaretleri",
+ "column.collections": "Koleksiyonlarım",
"column.community": "Yerel ağ akışı",
"column.create_list": "Liste oluştur",
"column.direct": "Özel bahsetmeler",
@@ -399,6 +427,7 @@
"featured_carousel.current": "Gönderi {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, one {{counter} Sabitlenmiş Gönderi} other {{counter} Sabitlenmiş Gönderi}}",
"featured_carousel.slide": "Gönderi {current, number} / {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Bu süzgeç kategorisi, bu gönderide eriştiğin bağlama uymuyor. Eğer gönderinin bu bağlamda da filtrelenmesini istiyorsanız, süzgeci düzenlemeniz gerekiyor.",
"filter_modal.added.context_mismatch_title": "Bağlam uyumsuzluğu!",
"filter_modal.added.expired_explanation": "Bu süzgeç kategorisinin süresi dolmuş, süzgeci uygulamak için bitiş tarihini değiştirmeniz gerekiyor.",
@@ -451,6 +480,7 @@
"footer.source_code": "Kaynak kodu görüntüle",
"footer.status": "Durum",
"footer.terms_of_service": "Hizmet şartları",
+ "form_field.optional": "(isteğe bağlı)",
"generic.saved": "Kaydet",
"getting_started.heading": "Başlarken",
"hashtag.admin_moderation": "#{name} için denetim arayüzünü açın",
@@ -589,6 +619,7 @@
"load_pending": "{count, plural, one {# yeni öğe} other {# yeni öğe}}",
"loading_indicator.label": "Yükleniyor…",
"media_gallery.hide": "Gizle",
+ "minicard.more_items": "+{count}",
"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",
@@ -786,7 +817,7 @@
"privacy.private.short": "Takipçiler",
"privacy.public.long": "Mastodon'da olan olmayan herkes",
"privacy.public.short": "Herkese açık",
- "privacy.quote.anyone": "{visibility}, herkes alıntılayabilir",
+ "privacy.quote.anyone": "{visibility}, alıntı yapılabilir",
"privacy.quote.disabled": "{visibility}, alıntı yapılamaz",
"privacy.quote.limited": "{visibility}, sınırlı alıntı",
"privacy.unlisted.additional": "Bu neredeyse herkese açık gibi çalışır, tek farkı gönderi canlı akışlarda veya etiketlerde, keşfette, veya Mastodon aramasında gözükmez, hesap çapında öyle seçmiş olsanız bile.",
@@ -1007,6 +1038,7 @@
"tabs_bar.notifications": "Bildirimler",
"tabs_bar.publish": "Yeni Gönderi",
"tabs_bar.search": "Arama",
+ "tag.remove": "Kaldır",
"terms_of_service.effective_as_of": "{date} itibariyle yürürlükte",
"terms_of_service.title": "Hizmet Şartları",
"terms_of_service.upcoming_changes_on": "{date} tarihinde gerçekleşecek değişiklikler",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index e2a7816df45..80702ff3f65 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -718,7 +718,6 @@
"privacy.private.short": "Підписники",
"privacy.public.long": "Усі з Mastodon",
"privacy.public.short": "Публічно",
- "privacy.quote.anyone": "{visibility}, будь-хто може цитувати",
"privacy.quote.disabled": "{visibility}, цитування вимкнено",
"privacy.quote.limited": "{visibility}, цитування обмежено",
"privacy.unlisted.additional": "Має таку ж поведінку, як у людей, але повідомлення не з'являтимуться у стрічках або хештегах, оглядах, або пошуку Mastodon, навіть якщо ви використовуєте облікові записи.",
diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json
index 4a9158e5b94..6d387ea2821 100644
--- a/app/javascript/mastodon/locales/vi.json
+++ b/app/javascript/mastodon/locales/vi.json
@@ -4,16 +4,18 @@
"about.default_locale": "Mặc định",
"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 đọ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.preamble": "Mastodon cho phép bạn đọc nội dung và giao tiếp với người/trang 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/trang 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.",
+ "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/trang ở máy chủ này đều bị cấm.",
"about.domain_blocks.suspended.title": "Vô hiệu hóa",
"about.language_label": "Ngôn ngữ",
"about.not_available": "Máy chủ này chưa cung cấp thông tin.",
"about.powered_by": "Mạng xã hội liên hợp {mastodon}",
"about.rules": "Nội quy máy chủ",
"account.account_note_header": "Ghi chú cá nhân",
+ "account.activity": "Hoạt động",
+ "account.add_note": "Thêm ghi chú cá nhân",
"account.add_or_remove_from_list": "Sửa danh sách",
"account.badges.bot": "Bot",
"account.badges.group": "Nhóm",
@@ -27,18 +29,25 @@
"account.direct": "Nhắn riêng @{name}",
"account.disable_notifications": "Tắt thông báo khi @{name} đăng tút",
"account.domain_blocking": "Máy chủ đang chủ",
+ "account.edit_note": "Sửa ghi chú cá nhân",
"account.edit_profile": "Sửa hồ sơ",
"account.edit_profile_short": "Sửa",
"account.enable_notifications": "Nhận thông báo khi @{name} đăng tút",
- "account.endorse": "Nêu bật người này",
+ "account.endorse": "Nêu bật người/trang này",
"account.familiar_followers_many": "Theo dõi bởi {name1}, {name2} và {othersCount, plural, other {# người khác mà bạn biết}}",
"account.familiar_followers_one": "Theo dõi bởi {name1}",
"account.familiar_followers_two": "Theo dõi bởi {name1} và {name2}",
"account.featured": "Nêu bật",
- "account.featured.accounts": "Mọi người",
+ "account.featured.accounts": "Người/trang",
"account.featured.hashtags": "Hashtag thường dùng",
"account.featured_tags.last_status_at": "Tút gần nhất {date}",
"account.featured_tags.last_status_never": "Chưa có tút",
+ "account.filters.all": "Tất cả hoạt động",
+ "account.filters.boosts_toggle": "Hiện những lượt đăng lại",
+ "account.filters.posts_boosts": "Tút và lượt đăng lại",
+ "account.filters.posts_only": "Tút",
+ "account.filters.posts_replies": "Tút và lượt trả lời",
+ "account.filters.replies_toggle": "Hiện những lượt trả lời",
"account.follow": "Theo dõi",
"account.follow_back": "Theo dõi lại",
"account.follow_back_short": "Theo dõi lại",
@@ -51,12 +60,13 @@
"account.followers_counter": "{count, plural, other {{counter} Người theo dõi}}",
"account.followers_you_know_counter": "{counter} bạn biết",
"account.following": "Đ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.following_counter": "{count, plural, other {{counter} theo dõi}}",
+ "account.follows.empty": "Người/trang này chưa theo dõi ai.",
"account.follows_you": "Đang theo dõi bạn",
"account.go_to_profile": "Xem hồ sơ",
"account.hide_reblogs": "Ẩn tút @{name} đăng lại",
"account.in_memoriam": "Tưởng Niệm.",
+ "account.joined_long": "Tham gia {date}",
"account.joined_short": "Tham gia",
"account.languages": "Đổi ngôn ngữ mong muốn",
"account.link_verified_on": "Liên kết này đã được xác minh vào {date}",
@@ -71,6 +81,14 @@
"account.muting": "Đang ẩn",
"account.mutual": "Theo dõi nhau",
"account.no_bio": "Chưa có miêu tả.",
+ "account.node_modal.callout": "Các ghi chú cá nhân chỉ hiển thị với bạn.",
+ "account.node_modal.edit_title": "Sửa ghi chú cá nhân",
+ "account.node_modal.error_unknown": "Không thể lưu ghi chú",
+ "account.node_modal.field_label": "Ghi chú cá nhân",
+ "account.node_modal.save": "Lưu",
+ "account.node_modal.title": "Thêm ghi chú cá nhân",
+ "account.note.edit_button": "Sửa",
+ "account.note.title": "Ghi chú cá nhân (chỉ hiển thị với bạn)",
"account.open_original_page": "Mở liên kết gốc",
"account.posts": "Tút",
"account.posts_with_replies": "Trả lời",
@@ -85,17 +103,19 @@
"account.unblock_domain": "Bỏ ẩn {domain}",
"account.unblock_domain_short": "Bỏ chặn",
"account.unblock_short": "Bỏ chặn",
- "account.unendorse": "Bỏ nêu bật người này",
+ "account.unendorse": "Bỏ nêu bật người/trang này",
"account.unfollow": "Bỏ theo dõi",
"account.unmute": "Bỏ ẩn @{name}",
"account.unmute_notifications_short": "Mở lại thông báo",
"account.unmute_short": "Bỏ ẩn",
+ "account_fields_modal.close": "Đóng",
+ "account_fields_modal.title": "Thông tin {name}",
"account_note.placeholder": "Nhấn để thêm",
"admin.dashboard.daily_retention": "Tỉ lệ người dùng sau đăng ký ở lại theo ngày",
"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": "Số người",
+ "admin.dashboard.retention.cohort_size": "Mớ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",
@@ -122,8 +142,8 @@
"annual_report.shared_page.donate": "Quyên góp",
"annual_report.shared_page.footer": "Tạo bằng {heart} bởi đội ngũ Mastodon",
"annual_report.shared_page.footer_server_info": "{username} ở {domain}, một trong nhiều cộng đồng Mastodon.",
- "annual_report.summary.archetype.booster.desc_public": "{name} thích tìm kiếm và đăng lại các tút, lan tỏa những người sáng tạo khác với mục tiêu hoàn hảo.",
- "annual_report.summary.archetype.booster.desc_self": "Bạn thích tìm kiếm và đăng lại các tút, lan tỏa những người sáng tạo khác với mục tiêu hoàn hảo.",
+ "annual_report.summary.archetype.booster.desc_public": "{name} thích tìm kiếm và đăng lại các tút, lan tỏa những người/trang khác với mục tiêu hoàn hảo.",
+ "annual_report.summary.archetype.booster.desc_self": "Bạn thích tìm kiếm và đăng lại các tút, lan tỏa những người/trang khác với mục tiêu hoàn hảo.",
"annual_report.summary.archetype.booster.name": "Cung Thủ",
"annual_report.summary.archetype.die_drei_fragezeichen": "???",
"annual_report.summary.archetype.lurker.desc_public": "Chúng tôi biết {name} đang ở đâu đó ngoài kia, tận hưởng Mastodon theo cách riêng của họ.",
@@ -167,7 +187,7 @@
"block_modal.they_cant_mention": "Họ không thể theo dõi & nhắc đến bạn.",
"block_modal.they_cant_see_posts": "Cả hai không còn nhìn thấy tút của nhau.",
"block_modal.they_will_know": "Họ sẽ biết đã bị bạn chặn.",
- "block_modal.title": "Chặn người này?",
+ "block_modal.title": "Chặn người/trang này?",
"block_modal.you_wont_see_mentions": "Bạn không cò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?",
@@ -184,21 +204,39 @@
"bundle_modal_error.close": "Đóng",
"bundle_modal_error.message": "Đã có lỗi xảy ra trong khi tải màn hình này.",
"bundle_modal_error.retry": "Thử lại",
+ "callout.dismiss": "Bỏ qua",
"carousel.current": "Slide {current, number} / {max, number}",
"carousel.slide": "Slide {current, number} trong {max, number}",
"closed_registrations.other_server_instructions": "Tạo tài khoản trên máy chủ khác và vẫn tương tác với máy chủ này.",
"closed_registrations_modal.description": "{domain} hiện tắt đăng ký, nhưng hãy lưu ý rằng bạn không cần một tài khoản riêng trên {domain} để sử dụng Mastodon.",
"closed_registrations_modal.find_another_server": "Tìm máy chủ khác",
- "closed_registrations_modal.preamble": "Mastodon liên hợp nên bất kể bạn tạo tài khoản ở đâu, bạn cũng sẽ có thể theo dõi và tương tác với mọi người trên máy chủ này. Bạn thậm chí có thể tự mở máy chủ!",
+ "closed_registrations_modal.preamble": "Mastodon liên hợp nên bất kể bạn tạo tài khoản ở đâu, bạn cũng sẽ có thể theo dõi và tương tác với người/trang trên máy chủ này. Bạn thậm chí có thể tự mở máy chủ!",
"closed_registrations_modal.title": "Đăng ký Mastodon",
+ "collections.collection_description": "Mô tả",
+ "collections.collection_name": "Tên",
+ "collections.collection_topic": "Chủ đề",
+ "collections.create_a_collection_hint": "Tạo một collection để giới thiệu hoặc chia sẻ những người/trang yêu thích của bạn với người khác.",
+ "collections.create_collection": "Tạo collection",
+ "collections.delete_collection": "Xóa collection",
+ "collections.description_length_hint": "Giới hạn 100 ký tự",
+ "collections.error_loading_collections": "Đã xảy ra lỗi khi tải những collection của bạn.",
+ "collections.mark_as_sensitive": "Đánh dấu nhạy cảm",
+ "collections.mark_as_sensitive_hint": "Ẩn phần mô tả và thông tin tài khoản của collection phía sau cảnh báo nội dung. Tên bộ sưu tập vẫn hiển thị.",
+ "collections.name_length_hint": "Giới hạn 100 ký tự",
+ "collections.no_collections_yet": "Chưa có collection.",
+ "collections.topic_hint": "Thêm hashtag giúp người khác hiểu chủ đề chính của collection này.",
+ "collections.view_collection": "Xem collection",
"column.about": "Giới thiệu",
- "column.blocks": "Người đã chặn",
+ "column.blocks": "Người/trang đã chặn",
"column.bookmarks": "Những tút đã lưu",
+ "column.collections": "Collection của tôi",
"column.community": "Máy chủ này",
+ "column.create_collection": "Tạo collection",
"column.create_list": "Tạo danh sách",
"column.direct": "Nhắn riêng",
- "column.directory": "Kết nối dựa trên sở thích",
+ "column.directory": "Tìm người/trang",
"column.domain_blocks": "Máy chủ đã chặn",
+ "column.edit_collection": "Sửa collection",
"column.edit_list": "Sửa danh sách",
"column.favourites": "Những tút đã thích",
"column.firehose": "Bảng tin",
@@ -206,9 +244,9 @@
"column.firehose_singular": "Bảng tin",
"column.follow_requests": "Yêu cầu theo dõi",
"column.home": "Trang chủ",
- "column.list_members": "Những người trong danh sách",
+ "column.list_members": "Quản lý người/trang trong danh sách",
"column.lists": "Danh sách",
- "column.mutes": "Người đã ẩn",
+ "column.mutes": "Người/trang đã ẩn",
"column.notifications": "Thông báo",
"column.pins": "Tút ghim",
"column.public": "Liên hợp",
@@ -222,7 +260,7 @@
"column_search.cancel": "Hủy bỏ",
"community.column_settings.local_only": "Chỉ máy chủ của bạn",
"community.column_settings.media_only": "Chỉ hiện tút có media",
- "community.column_settings.remote_only": "Chỉ người ở máy chủ khác",
+ "community.column_settings.remote_only": "Chỉ người/trang ở máy chủ khác",
"compose.error.blank_post": "Không thể để trống.",
"compose.language.change": "Chọn ngôn ngữ tút",
"compose.language.search": "Tìm ngôn ngữ...",
@@ -253,6 +291,9 @@
"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_collection.confirm": "Xóa",
+ "confirmations.delete_collection.message": "Hành động này không thể hoàn tác.",
+ "confirmations.delete_collection.title": "Xóa \"{name}\"?",
"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",
@@ -267,7 +308,7 @@
"confirmations.discard_edit_media.message": "Bạn chưa lưu thay đổi của phần mô tả hoặc bản xem trước của media, vẫn bỏ qua?",
"confirmations.follow_to_list.confirm": "Theo dõi & thêm vào danh sách",
"confirmations.follow_to_list.message": "Bạn cần theo dõi {name} trước khi thêm họ vào danh sách.",
- "confirmations.follow_to_list.title": "Theo dõi người này?",
+ "confirmations.follow_to_list.title": "Theo dõi người/trang này?",
"confirmations.logout.confirm": "Đăng xuất",
"confirmations.logout.message": "Bạn có chắc muốn thoát?",
"confirmations.logout.title": "Đăng xuất",
@@ -279,8 +320,8 @@
"confirmations.private_quote_notify.cancel": "Quay lại chỉnh sửa",
"confirmations.private_quote_notify.confirm": "Đăng tút",
"confirmations.private_quote_notify.do_not_show_again": "Không hiện thông báo này nữa",
- "confirmations.private_quote_notify.message": "Người mà bạn trích dẫn và những người được bạn nhắc đến khác sẽ được thông báo và có thể xem tút của bạn, ngay cả khi họ không theo dõi bạn.",
- "confirmations.private_quote_notify.title": "Chia sẻ với người được nhắc đến và người theo dõi?",
+ "confirmations.private_quote_notify.message": "Người/trang mà bạn trích dẫn và những người được bạn nhắc đến khác sẽ được thông báo và có thể xem tút của bạn, ngay cả khi họ không theo dõi bạn.",
+ "confirmations.private_quote_notify.title": "Chia sẻ với người/trang được nhắc đến và người theo dõi?",
"confirmations.quiet_post_quote_info.dismiss": "Không nhắc lại nữa",
"confirmations.quiet_post_quote_info.got_it": "Đã hiểu",
"confirmations.quiet_post_quote_info.message": "Khi trích dẫn một tút hạn chế, tút của bạn sẽ bị ẩn khỏi dòng thời gian thịnh hành.",
@@ -325,14 +366,14 @@
"domain_block_modal.they_cant_follow": "Không ai trên máy chủ này có thể theo dõi bạn.",
"domain_block_modal.they_wont_know": "Họ không biết đã bị bạn chặn.",
"domain_block_modal.title": "Chặn máy chủ?",
- "domain_block_modal.you_will_lose_num_followers": "Bạn sẽ mất {followersCount, plural, other {{followersCountDisplay} người theo dõi}} và {followingCount, plural, other {{followingCountDisplay} người bạn theo dõi}}.",
- "domain_block_modal.you_will_lose_relationships": "Bạn sẽ mất tất cả người theo dõi và những người bạn theo dõi từ máy chủ này.",
+ "domain_block_modal.you_will_lose_num_followers": "Bạn sẽ mất {followersCount, plural, other {{followersCountDisplay} người theo dõi}} và {followingCount, plural, other {{followingCountDisplay} người/trang mà bạn theo dõi}}.",
+ "domain_block_modal.you_will_lose_relationships": "Bạn sẽ mất tất cả người theo dõi và những người/trang mà bạn theo dõi ở máy chủ này.",
"domain_block_modal.you_wont_see_posts": "Bạn không còn thấy tút hoặc thông báo từ thành viên máy chủ này.",
"domain_pill.activitypub_lets_connect": "Nó cho phép bạn kết nối và tương tác với mọi người, không chỉ trên Mastodon mà còn trên các nền tảng khác.",
"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": "Nơi lưu trữ tút của người này.",
+ "domain_pill.their_server": "Nơi lưu trữ tút của người/trang 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ì?",
@@ -361,8 +402,8 @@
"emoji_button.travel": "Du lịch",
"empty_column.account_featured.me": "Bạn chưa nêu bật gì. Bạn có biết rằng, bạn có thể giới thiệu hashtag thường dùng và hồ sơ của bạn bè trên trang cá nhân của mình không?",
"empty_column.account_featured.other": "{acct} chưa nêu bật gì. Bạn có biết rằng, bạn có thể giới thiệu hashtag thường dùng và hồ sơ của bạn bè trên trang cá nhân của mình không?",
- "empty_column.account_featured_other.unknown": "Người này chưa nêu bật nội dung gì.",
- "empty_column.account_hides_collections": "Người này đã chọn ẩn thông tin",
+ "empty_column.account_featured_other.unknown": "Người/trang này chưa nêu bật gì.",
+ "empty_column.account_hides_collections": "Người/trang này đã chọn ẩn thông tin",
"empty_column.account_suspended": "Tài khoản vô hiệu hóa",
"empty_column.account_timeline": "Chưa có tút nào!",
"empty_column.account_unavailable": "Tài khoản bị đình chỉ",
@@ -378,12 +419,12 @@
"empty_column.follow_requests": "Bạn chưa có yêu cầu theo dõi nào.",
"empty_column.followed_tags": "Bạn chưa theo dõi hashtag nào. Khi bạn theo dõi, chúng sẽ hiện lên ở đây.",
"empty_column.hashtag": "Chưa có tút nào dùng hashtag này.",
- "empty_column.home": "Trang chủ của bạn đang trống! Hãy theo dõi nhiều người hơn để lấp đầy.",
- "empty_column.list": "Chưa có tút. Khi những người trong danh sách này đăng tút mới, chúng sẽ xuất hiện ở đây.",
+ "empty_column.home": "Trang chủ của bạn đang trống! Hãy theo dõi nhiều người/trang hơn để lấp đầy.",
+ "empty_column.list": "Chưa có tút. Khi những người/trang trong danh sách này đăng tút mới, chúng sẽ xuất hiện ở đây.",
"empty_column.mutes": "Bạn chưa ẩn bất kỳ ai.",
"empty_column.notification_requests": "Sạch sẽ! Không còn gì ở đây. Khi bạn nhận được thông báo mới, chúng sẽ xuất hiện ở đây theo cài đặt của bạn.",
"empty_column.notifications": "Bạn chưa có thông báo nào. Hãy thử theo dõi hoặc nhắn riêng cho ai đó.",
- "empty_column.public": "Trống trơn! Bạn hãy viết gì đó hoặc bắt đầu theo dõi những người khác",
+ "empty_column.public": "Trống trơn! Bạn hãy viết gì đó hoặc bắt đầu theo dõi những người/trang khác",
"error.no_hashtag_feed_access": "Tham gia hoặc đăng nhập để xem và theo dõi hashtag này.",
"error.unexpected_crash.explanation": "Trang này có thể không hiển thị chính xác do lỗi lập trình Mastodon hoặc vấn đề tương thích trình duyệt.",
"error.unexpected_crash.explanation_addons": "Trang này không thể hiển thị do xung khắc với add-on của trình duyệt hoặc công cụ tự động dịch ngôn ngữ.",
@@ -399,6 +440,7 @@
"featured_carousel.current": "Tút {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, other {Tút đã ghim}}",
"featured_carousel.slide": "Tút {current, number} trong {max, number}",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "Danh mục bộ lọc này không áp dụng cho ngữ cảnh mà bạn đã truy cập tút này. Nếu bạn muốn tút cũng được lọc trong ngữ cảnh này, bạn sẽ phải chỉnh sửa bộ lọc.",
"filter_modal.added.context_mismatch_title": "Bối cảnh không phù hợp!",
"filter_modal.added.expired_explanation": "Danh mục bộ lọc này đã hết hạn, bạn sẽ cần thay đổi ngày hết hạn để áp dụng.",
@@ -416,27 +458,27 @@
"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.pending_requests": "Từ {count, plural, =0 {không ai} other {# người/trang}} mà bạn có thể biết",
"filtered_notifications_banner.title": "Thông báo đã lọc",
"firehose.all": "Toàn bộ",
"firehose.local": "Máy chủ này",
"firehose.remote": "Máy chủ khác",
"follow_request.authorize": "Chấp nhận",
"follow_request.reject": "Từ chối",
- "follow_requests.unlocked_explanation": "Mặc dù tài khoản của bạn đang ở chế độ công khai, quản trị viên của {domain} vẫn tin rằng bạn sẽ muốn xem lại yêu cầu theo dõi từ những người khác.",
+ "follow_requests.unlocked_explanation": "Mặc dù tài khoản của bạn đang ở chế độ công khai, quản trị viên {domain} tin rằng bạn sẽ muốn xem lại yêu cầu theo dõi từ những người khác.",
"follow_suggestions.curated_suggestion": "Gợi ý từ máy chủ",
"follow_suggestions.dismiss": "Không hiện lại",
"follow_suggestions.featured_longer": "Tuyển chọn bởi {domain}",
"follow_suggestions.friends_of_friends_longer": "Nổi tiếng với những người mà bạn theo dõi",
- "follow_suggestions.hints.featured": "Người này được đội ngũ {domain} đề xuất.",
- "follow_suggestions.hints.friends_of_friends": "Người này nổi tiếng với những người bạn theo dõi.",
- "follow_suggestions.hints.most_followed": "Người này được theo dõi nhiều nhất trên {domain}.",
- "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.hints.featured": "Được đội ngũ {domain} đề xuất.",
+ "follow_suggestions.hints.friends_of_friends": "Nổi tiếng với những người bạn theo dõi.",
+ "follow_suggestions.hints.most_followed": "Được theo dõi nhiều nhất trên {domain}.",
+ "follow_suggestions.hints.most_interactions": "Đang được quan tâm nhiều trên {domain}.",
+ "follow_suggestions.hints.similar_to_recently_followed": "Tương tự 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": "Người nổi tiếng",
+ "follow_suggestions.popular_suggestion": "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",
+ "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ả",
"follow_suggestions.who_to_follow": "Gợi ý theo dõi",
"followed_tags": "Hashtag theo dõi",
@@ -451,6 +493,7 @@
"footer.source_code": "Mã nguồn",
"footer.status": "Trạng thái",
"footer.terms_of_service": "Điều khoản dịch vụ",
+ "form_field.optional": "(tùy chọn)",
"generic.saved": "Đã lưu",
"getting_started.heading": "Quản lý",
"hashtag.admin_moderation": "Mở giao diện quản trị #{name}",
@@ -474,11 +517,11 @@
"hashtag.unfeature": "Bỏ nêu bật trên hồ sơ",
"hashtag.unfollow": "Bỏ theo dõi hashtag",
"hashtags.and_other": "…và {count, plural, other {# nữa}}",
- "hints.profiles.followers_may_be_missing": "Số người theo dõi có thể không đầy đủ.",
- "hints.profiles.follows_may_be_missing": "Số người mà người này theo dõi có thể không đầy đủ.",
- "hints.profiles.posts_may_be_missing": "Số tút của người này có thể không đầy đủ.",
+ "hints.profiles.followers_may_be_missing": "Số người theo dõi có thể bị thiếu.",
+ "hints.profiles.follows_may_be_missing": "Số người/trang mà người này theo dõi có thể bị thiếu.",
+ "hints.profiles.posts_may_be_missing": "Số tút của người/trang này có thể bị thiếu.",
"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_follows": "Xem thêm người mà người/trang này theo dõi ở {domain}",
"hints.profiles.see_more_posts": "Xem thêm tút ở {domain}",
"home.column_settings.show_quotes": "Hiện những trích dẫn",
"home.column_settings.show_reblogs": "Hiện những lượt đăng lại",
@@ -490,14 +533,14 @@
"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_act_users": "Bạn vẫn có thể chấp nhận, từ chối hoặc báo cáo người/trang khác",
"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 các thông báo đã được lọc riêng",
"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.not_followers_title": "Bỏ qua thông báo từ những người/trang chưa theo dõi bạn?",
+ "ignore_notifications_modal.not_following_title": "Bỏ qua thông báo từ những người/trang 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?",
"info_button.label": "Trợ giúp",
"info_button.what_is_alt_text": "Văn bản thay thế là gì?
Văn bản thay thế giúp mô tả hình ảnh cho những người khiếm thị, kết nối mạng chậm hoặc đơn giản là bổ sung ngữ cảnh.
Bạn có thể cải thiện khả năng tiếp cận và giải thích kỹ hơn cho mọi người bằng cách viết văn bản thay thế rõ ràng, ngắn gọn và khách quan.
- Nắm bắt thành phần quan trọng
- Tóm tắt văn bản trong hình
- Dùng cấu trúc câu đơn
- Tránh giải thích rối rắm
- Tập trung vào các xu hướng và kết luận chính trong hình ảnh phức tạp (như biểu đồ hoặc bản đồ)
",
@@ -512,7 +555,7 @@
"intervals.full.hours": "{number, plural, other {# giờ}}",
"intervals.full.minutes": "{number, plural, other {# phút}}",
"keyboard_shortcuts.back": "quay lại",
- "keyboard_shortcuts.blocked": "mở danh sách người đã chặn",
+ "keyboard_shortcuts.blocked": "mở danh sách người/trang đã chặn",
"keyboard_shortcuts.boost": "đăng lại",
"keyboard_shortcuts.column": "mở các cột",
"keyboard_shortcuts.compose": "mở khung soạn tút",
@@ -530,7 +573,7 @@
"keyboard_shortcuts.load_more": "Mở nút \"Tải thêm\"",
"keyboard_shortcuts.local": "mở máy chủ của bạn",
"keyboard_shortcuts.mention": "nhắc đến ai đó",
- "keyboard_shortcuts.muted": "mở danh sách người đã ẩn",
+ "keyboard_shortcuts.muted": "mở danh sách người/trang đã ẩn",
"keyboard_shortcuts.my_profile": "mở hồ sơ của bạn",
"keyboard_shortcuts.notifications": "mở thông báo",
"keyboard_shortcuts.open_media": "mở ảnh hoặc video",
@@ -557,7 +600,7 @@
"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 {domain}.",
+ "limited_account_hint.title": "Người/trang này đã bị ẩn bởi quản trị viên {domain}.",
"link_preview.author": "Bởi {name}",
"link_preview.more_from_author": "Viết bởi {name}",
"link_preview.shares": "{count, plural, other {{counter} lượt chia sẻ}}",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, one {# tút mới} other {# tút mới}}",
"loading_indicator.label": "Đang tải…",
"media_gallery.hide": "Ẩn",
+ "minicard.more_items": "+{count}",
"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": "Ẩn tùy chọn",
@@ -740,11 +784,11 @@
"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": "Dưới {days, plural, other {# ngày}}",
- "notifications.policy.filter_new_accounts_title": "Những người mới tạo tài khoản",
- "notifications.policy.filter_not_followers_hint": "Kể cả người theo dõi bạn dưới {days, plural, other {# ngày}}",
- "notifications.policy.filter_not_followers_title": "Những người không theo dõi bạn",
+ "notifications.policy.filter_new_accounts_title": "Người/trang mới tạo",
+ "notifications.policy.filter_not_followers_hint": "Kể cả người/trang theo dõi bạn dưới {days, plural, other {# ngày}}",
+ "notifications.policy.filter_not_followers_title": "Người/trang không theo dõi bạn",
"notifications.policy.filter_not_following_hint": "Cho đến 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_not_following_title": "Người/trang bạn không theo dõi",
"notifications.policy.filter_private_mentions_hint": "Trừ khi bạn nhắn họ trước hoặc bạn có theo dõi họ",
"notifications.policy.filter_private_mentions_title": "Nhắn riêng không mong muốn",
"notifications.policy.title": "Quản lý thông báo từ…",
@@ -786,7 +830,7 @@
"privacy.private.short": "Người theo dõi",
"privacy.public.long": "Bất cứ ai",
"privacy.public.short": "Công khai",
- "privacy.quote.anyone": "{visibility}, mọi người có thể trích dẫn",
+ "privacy.quote.anyone": "{visibility}, cho phép trích dẫn",
"privacy.quote.disabled": "{visibility}, tắt trích dẫn",
"privacy.quote.limited": "{visibility}, hạn chế trích dẫn",
"privacy.unlisted.additional": "Công khai, nhưng tút sẽ không hiện trong bảng tin, hashtag, khám phá hoặc tìm kiếm Mastodon, kể cả trong cài đặt tài khoản bạn chọn cho phép.",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "Thông báo",
"tabs_bar.publish": "Soạn tút",
"tabs_bar.search": "Tìm kiếm",
+ "tag.remove": "Gỡ bỏ",
"terms_of_service.effective_as_of": "Có hiệu lực vào {date}",
"terms_of_service.title": "Điều khoản Dịch vụ",
"terms_of_service.upcoming_changes_on": "Sắp thay đổi vào {date}",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index d69f490b5b4..ca39da4c2c1 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -14,6 +14,8 @@
"about.powered_by": "由 {mastodon} 驱动的去中心化社交媒体",
"about.rules": "站点规则",
"account.account_note_header": "个人备注",
+ "account.activity": "活动",
+ "account.add_note": "添加个人备注",
"account.add_or_remove_from_list": "从列表中添加或移除",
"account.badges.bot": "机器人",
"account.badges.group": "群组",
@@ -27,6 +29,7 @@
"account.direct": "私下提及 @{name}",
"account.disable_notifications": "当 @{name} 发布嘟文时不要通知我",
"account.domain_blocking": "正在屏蔽中的域名",
+ "account.edit_note": "编辑个人备注",
"account.edit_profile": "修改个人资料",
"account.edit_profile_short": "编辑",
"account.enable_notifications": "当 @{name} 发布嘟文时通知我",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "话题",
"account.featured_tags.last_status_at": "上次发言于 {date}",
"account.featured_tags.last_status_never": "暂无嘟文",
+ "account.filters.all": "所有活动",
+ "account.filters.boosts_toggle": "显示转嘟",
+ "account.filters.posts_boosts": "嘟文与转嘟",
+ "account.filters.posts_only": "嘟文",
+ "account.filters.posts_replies": "嘟文与回复",
+ "account.filters.replies_toggle": "显示回复",
"account.follow": "关注",
"account.follow_back": "回关",
"account.follow_back_short": "回关",
@@ -57,6 +66,7 @@
"account.go_to_profile": "前往个人资料页",
"account.hide_reblogs": "隐藏来自 @{name} 的转嘟",
"account.in_memoriam": "谨此悼念。",
+ "account.joined_long": "加入于 {date}",
"account.joined_short": "加入于",
"account.languages": "更改订阅语言",
"account.link_verified_on": "此链接的所有权已在 {date} 检查",
@@ -71,6 +81,14 @@
"account.muting": "正在静音",
"account.mutual": "你们互相关注",
"account.no_bio": "未提供描述。",
+ "account.node_modal.callout": "个人备注仅对您个人可见。",
+ "account.node_modal.edit_title": "编辑个人备注",
+ "account.node_modal.error_unknown": "无法保存备注",
+ "account.node_modal.field_label": "个人备注",
+ "account.node_modal.save": "保存",
+ "account.node_modal.title": "添加个人备注",
+ "account.note.edit_button": "编辑",
+ "account.note.title": "个人备注(仅对您可见)",
"account.open_original_page": "打开原始页面",
"account.posts": "嘟文",
"account.posts_with_replies": "嘟文和回复",
@@ -90,6 +108,8 @@
"account.unmute": "不再隐藏 @{name}",
"account.unmute_notifications_short": "恢复通知",
"account.unmute_short": "取消隐藏",
+ "account_fields_modal.close": "关闭",
+ "account_fields_modal.title": "{name} 的信息",
"account_note.placeholder": "点击添加备注",
"admin.dashboard.daily_retention": "注册后用户留存率(按日计算)",
"admin.dashboard.monthly_retention": "注册后用户留存率(按月计算)",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "关闭",
"bundle_modal_error.message": "加载此页面时发生了错误。",
"bundle_modal_error.retry": "重试",
+ "callout.dismiss": "忽略",
"carousel.current": "幻灯片 {current, number} / {max, number}",
"carousel.slide": "第 {current, number} 张幻灯片,共 {max, number} 张",
"closed_registrations.other_server_instructions": "基于 Mastodon 去中心化的特性,你可以其他服务器上创建账号,并继续与此服务器互动。",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "查找其他服务器",
"closed_registrations_modal.preamble": "Mastodon 是去中心化的,所以无论在哪个实例创建账号,都可以关注本服务器上的账号并与之交流。 或者你还可以自己搭建实例!",
"closed_registrations_modal.title": "注册 Mastodon 账号",
+ "collections.collection_description": "说明",
+ "collections.collection_name": "名称",
+ "collections.collection_topic": "话题",
+ "collections.create_a_collection_hint": "创建用于向其他人推荐或分享你最喜欢账号的收藏列表。",
+ "collections.create_collection": "创建收藏列表",
+ "collections.delete_collection": "删除收藏列表",
+ "collections.description_length_hint": "100字限制",
+ "collections.error_loading_collections": "加载您的收藏列表时发生错误。",
+ "collections.mark_as_sensitive": "标记为敏感内容",
+ "collections.mark_as_sensitive_hint": "将此收藏列表的说明用内容警告隐藏。此收藏列表的名称仍将可见。",
+ "collections.name_length_hint": "100字限制",
+ "collections.no_collections_yet": "尚无收藏列表。",
+ "collections.topic_hint": "添加话题标签,帮助他人了解此收藏列表的主题。",
+ "collections.view_collection": "查看收藏列表",
"column.about": "关于",
"column.blocks": "屏蔽的用户",
"column.bookmarks": "书签",
+ "column.collections": "我的收藏列表",
"column.community": "本站时间线",
+ "column.create_collection": "创建收藏列表",
"column.create_list": "创建列表",
"column.direct": "私下提及",
"column.directory": "浏览用户资料",
"column.domain_blocks": "已屏蔽的域名",
+ "column.edit_collection": "编辑收藏列表",
"column.edit_list": "编辑列表",
"column.favourites": "喜欢",
"column.firehose": "实时动态",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "删除",
"confirmations.delete.message": "你确定要删除这条嘟文吗?",
"confirmations.delete.title": "确定要删除嘟文?",
+ "confirmations.delete_collection.confirm": "删除",
+ "confirmations.delete_collection.message": "该操作无法撤销。",
+ "confirmations.delete_collection.title": "删除“{name}”吗?",
"confirmations.delete_list.confirm": "删除",
"confirmations.delete_list.message": "确定要永久删除此列表吗?",
"confirmations.delete_list.title": "确定要删除列表?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "嘟文 {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, other {# 条置顶嘟文}}",
"featured_carousel.slide": "第 {current, number} 条嘟文,共 {max, number} 条",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "这条过滤规则不适用于你当前访问此嘟文的场景。要在此场景下过滤嘟文,你必须编辑此过滤规则。",
"filter_modal.added.context_mismatch_title": "场景不匹配!",
"filter_modal.added.expired_explanation": "此过滤规则类别已过期,你需要修改到期日期才能应用。",
@@ -451,6 +493,7 @@
"footer.source_code": "查看源代码",
"footer.status": "状态",
"footer.terms_of_service": "服务条款",
+ "form_field.optional": "(选填)",
"generic.saved": "已保存",
"getting_started.heading": "开始使用",
"hashtag.admin_moderation": "打开 #{name} 的管理界面",
@@ -589,6 +632,7 @@
"load_pending": "{count} 项",
"loading_indicator.label": "加载中…",
"media_gallery.hide": "隐藏",
+ "minicard.more_items": "+{count}",
"moved_to_account_banner.text": "你的账号 {disabledAccount} 已禁用,因为你已迁移到 {movedToAccount}。",
"mute_modal.hide_from_notifications": "从通知中隐藏",
"mute_modal.hide_options": "隐藏选项",
@@ -786,7 +830,7 @@
"privacy.private.short": "关注者",
"privacy.public.long": "所有 Mastodon 内外的人",
"privacy.public.short": "公开",
- "privacy.quote.anyone": "{visibility},任何人都能引用",
+ "privacy.quote.anyone": "{visibility},允许嘟文引用",
"privacy.quote.disabled": "{visibility},禁用嘟文引用",
"privacy.quote.limited": "{visibility},嘟文引用受限",
"privacy.unlisted.additional": "此模式的行为与“公开”类似,只是嘟文不会出现在实时动态、话题、探索或 Mastodon 搜索页面中,即使你已全局开启了对应的发现设置。",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "通知",
"tabs_bar.publish": "新嘟文",
"tabs_bar.search": "搜索",
+ "tag.remove": "移除",
"terms_of_service.effective_as_of": "自 {date} 起生效",
"terms_of_service.title": "服务条款",
"terms_of_service.upcoming_changes_on": "{date} 起即将生效的更改",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 78d191efa38..2ef07fe8055 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -14,6 +14,8 @@
"about.powered_by": "由 {mastodon} 提供之去中心化社群媒體",
"about.rules": "伺服器規則",
"account.account_note_header": "個人備註",
+ "account.activity": "活動",
+ "account.add_note": "新增個人備註",
"account.add_or_remove_from_list": "自列表中新增或移除",
"account.badges.bot": "機器人",
"account.badges.group": "群組",
@@ -27,6 +29,7 @@
"account.direct": "私訊 @{name}",
"account.disable_notifications": "取消來自 @{name} 嘟文之通知",
"account.domain_blocking": "封鎖中網域",
+ "account.edit_note": "編輯個人備註",
"account.edit_profile": "編輯個人檔案",
"account.edit_profile_short": "編輯",
"account.enable_notifications": "當 @{name} 發嘟時通知我",
@@ -39,6 +42,12 @@
"account.featured.hashtags": "主題標籤",
"account.featured_tags.last_status_at": "上次發嘟於 {date}",
"account.featured_tags.last_status_never": "沒有嘟文",
+ "account.filters.all": "所有活動",
+ "account.filters.boosts_toggle": "顯示轉嘟",
+ "account.filters.posts_boosts": "嘟文與轉嘟",
+ "account.filters.posts_only": "嘟文",
+ "account.filters.posts_replies": "嘟文與回嘟",
+ "account.filters.replies_toggle": "顯示回嘟",
"account.follow": "跟隨",
"account.follow_back": "跟隨回去",
"account.follow_back_short": "跟隨回去",
@@ -57,6 +66,7 @@
"account.go_to_profile": "前往個人檔案",
"account.hide_reblogs": "隱藏來自 @{name} 之轉嘟",
"account.in_memoriam": "謹此悼念。",
+ "account.joined_long": "加入於 {date}",
"account.joined_short": "加入時間",
"account.languages": "變更訂閱的語言",
"account.link_verified_on": "已於 {date} 檢查此連結的擁有者權限",
@@ -71,6 +81,14 @@
"account.muting": "靜音",
"account.mutual": "跟隨彼此",
"account.no_bio": "無個人檔案描述。",
+ "account.node_modal.callout": "僅有您能見到您的個人備註。",
+ "account.node_modal.edit_title": "編輯個人備註",
+ "account.node_modal.error_unknown": "無法儲存此筆記",
+ "account.node_modal.field_label": "個人備註",
+ "account.node_modal.save": "儲存",
+ "account.node_modal.title": "新增個人備註",
+ "account.note.edit_button": "編輯",
+ "account.note.title": "個人備註(僅有您可見)",
"account.open_original_page": "檢視原始頁面",
"account.posts": "嘟文",
"account.posts_with_replies": "嘟文與回覆",
@@ -90,6 +108,8 @@
"account.unmute": "解除靜音 @{name}",
"account.unmute_notifications_short": "解除靜音推播通知",
"account.unmute_short": "解除靜音",
+ "account_fields_modal.close": "關閉",
+ "account_fields_modal.title": "{name} 之資訊",
"account_note.placeholder": "點擊以新增備註",
"admin.dashboard.daily_retention": "註冊後使用者存留率(日)",
"admin.dashboard.monthly_retention": "註冊後使用者存留率(月)",
@@ -184,6 +204,7 @@
"bundle_modal_error.close": "關閉",
"bundle_modal_error.message": "載入此畫面時發生錯誤。",
"bundle_modal_error.retry": "重試",
+ "callout.dismiss": "關閉",
"carousel.current": "頁面 {current, number} / {max, number}",
"carousel.slide": "{max, number} 頁中之第 {current, number} 頁",
"closed_registrations.other_server_instructions": "因為 Mastodon 是去中心化的,所以您也能於其他伺服器上建立帳號,並仍然與此伺服器互動。",
@@ -191,14 +212,31 @@
"closed_registrations_modal.find_another_server": "尋找另一個伺服器",
"closed_registrations_modal.preamble": "Mastodon 是去中心化的,所以無論您於哪個伺服器新增帳號,都可以與此伺服器上的任何人跟隨及互動。您甚至能自行架設自己的伺服器!",
"closed_registrations_modal.title": "註冊 Mastodon",
+ "collections.collection_description": "說明",
+ "collections.collection_name": "名稱",
+ "collections.collection_topic": "主題",
+ "collections.create_a_collection_hint": "建立用以向其他人推薦或分享您最喜愛帳號之收藏名單。",
+ "collections.create_collection": "建立收藏名單",
+ "collections.delete_collection": "刪除收藏名單",
+ "collections.description_length_hint": "100 字限制",
+ "collections.error_loading_collections": "讀取您的收藏名單時發生錯誤。",
+ "collections.mark_as_sensitive": "標記為敏感內容",
+ "collections.mark_as_sensitive_hint": "將此收藏名單之說明隱藏於內容警告之後。此收藏名單名稱仍將可見。",
+ "collections.name_length_hint": "100 字限制",
+ "collections.no_collections_yet": "您沒有任何收藏名單。",
+ "collections.topic_hint": "新增主題標籤以協助其他人瞭解此收藏名單之主題。",
+ "collections.view_collection": "檢視收藏名單",
"column.about": "關於",
"column.blocks": "已封鎖使用者",
"column.bookmarks": "書籤",
+ "column.collections": "我的收藏名單",
"column.community": "本站時間軸",
+ "column.create_collection": "建立收藏名單",
"column.create_list": "建立列表",
"column.direct": "私訊",
"column.directory": "瀏覽個人檔案",
"column.domain_blocks": "已封鎖網域",
+ "column.edit_collection": "編輯收藏名單",
"column.edit_list": "編輯列表",
"column.favourites": "最愛",
"column.firehose": "即時內容",
@@ -253,6 +291,9 @@
"confirmations.delete.confirm": "刪除",
"confirmations.delete.message": "您確定要刪除這則嘟文嗎?",
"confirmations.delete.title": "是否刪除該嘟文?",
+ "confirmations.delete_collection.confirm": "刪除",
+ "confirmations.delete_collection.message": "此動作無法復原。",
+ "confirmations.delete_collection.title": "是否刪除 「{name}」?",
"confirmations.delete_list.confirm": "刪除",
"confirmations.delete_list.message": "您確定要永久刪除此列表嗎?",
"confirmations.delete_list.title": "是否刪除該列表?",
@@ -399,6 +440,7 @@
"featured_carousel.current": "嘟文 {current, number} / {max, number}",
"featured_carousel.header": "{count, plural, other {# 則釘選嘟文}}",
"featured_carousel.slide": "{max, number} 則嘟文中之第 {current, number} 則",
+ "featured_tags.more_items": "+{count}",
"filter_modal.added.context_mismatch_explanation": "此過濾器類別不是用您所存取嘟文的情境。若您想要此嘟文被於此情境被過濾,您必須編輯過濾器。",
"filter_modal.added.context_mismatch_title": "不符合情境!",
"filter_modal.added.expired_explanation": "此過濾器類別已失效,您需要更新過期日期以套用。",
@@ -451,6 +493,7 @@
"footer.source_code": "檢視原始碼",
"footer.status": "狀態",
"footer.terms_of_service": "服務條款",
+ "form_field.optional": "(可選的)",
"generic.saved": "已儲存",
"getting_started.heading": "開始使用",
"hashtag.admin_moderation": "開啟 #{name} 的管理介面",
@@ -589,6 +632,7 @@
"load_pending": "{count, plural, other {# 個新項目}}",
"loading_indicator.label": "正在載入...",
"media_gallery.hide": "隱藏",
+ "minicard.more_items": "+{count}",
"moved_to_account_banner.text": "您的帳號 {disabledAccount} 目前已停用,因為您已搬家至 {movedToAccount}。",
"mute_modal.hide_from_notifications": "於推播通知中隱藏",
"mute_modal.hide_options": "隱藏選項",
@@ -786,7 +830,7 @@
"privacy.private.short": "跟隨者",
"privacy.public.long": "所有人 (無論在 Mastodon 上與否)",
"privacy.public.short": "公開",
- "privacy.quote.anyone": "{visibility},任何人皆可引用",
+ "privacy.quote.anyone": "{visibility},允許引用嘟文",
"privacy.quote.disabled": "{visibility},停用引用嘟文",
"privacy.quote.limited": "{visibility},受限的引用嘟文",
"privacy.unlisted.additional": "此與公開嘟文完全相同,但嘟文不會出現於即時內容或主題標籤、探索、及 Mastodon 搜尋中,即使您於帳戶設定中選擇加入。",
@@ -1007,6 +1051,7 @@
"tabs_bar.notifications": "通知",
"tabs_bar.publish": "新增嘟文",
"tabs_bar.search": "搜尋",
+ "tag.remove": "移除",
"terms_of_service.effective_as_of": "{date} 起生效",
"terms_of_service.title": "服務條款",
"terms_of_service.upcoming_changes_on": "{date} 起即將發生之異動",
diff --git a/app/javascript/mastodon/reducers/slices/collections.ts b/app/javascript/mastodon/reducers/slices/collections.ts
new file mode 100644
index 00000000000..6f8637bb2cc
--- /dev/null
+++ b/app/javascript/mastodon/reducers/slices/collections.ts
@@ -0,0 +1,208 @@
+import { createSlice } from '@reduxjs/toolkit';
+
+import { importFetchedAccounts } from '@/mastodon/actions/importer';
+import {
+ apiCreateCollection,
+ apiGetAccountCollections,
+ apiUpdateCollection,
+ apiGetCollection,
+ apiDeleteCollection,
+} from '@/mastodon/api/collections';
+import type {
+ ApiCollectionJSON,
+ ApiCreateCollectionPayload,
+ ApiUpdateCollectionPayload,
+} from '@/mastodon/api_types/collections';
+import {
+ createAppSelector,
+ createDataLoadingThunk,
+} from '@/mastodon/store/typed_functions';
+
+type QueryStatus = 'idle' | 'loading' | 'error';
+
+interface CollectionState {
+ // Collections mapped by collection id
+ collections: Record;
+ // Lists of collection ids mapped by account id
+ accountCollections: Record<
+ string,
+ {
+ collectionIds: string[];
+ status: QueryStatus;
+ }
+ >;
+}
+
+const initialState: CollectionState = {
+ collections: {},
+ accountCollections: {},
+};
+
+const collectionSlice = createSlice({
+ name: 'collections',
+ initialState,
+ reducers: {},
+ extraReducers(builder) {
+ /**
+ * Fetching account collections
+ */
+ builder.addCase(fetchAccountCollections.pending, (state, action) => {
+ const { accountId } = action.meta.arg;
+ state.accountCollections[accountId] ??= {
+ status: 'loading',
+ collectionIds: [],
+ };
+ state.accountCollections[accountId].status = 'loading';
+ });
+
+ builder.addCase(fetchAccountCollections.rejected, (state, action) => {
+ const { accountId } = action.meta.arg;
+ state.accountCollections[accountId] = {
+ status: 'error',
+ collectionIds: [],
+ };
+ });
+
+ builder.addCase(fetchAccountCollections.fulfilled, (state, action) => {
+ const { collections } = action.payload;
+
+ const collectionsMap: Record =
+ state.collections;
+ const collectionIds: string[] = [];
+
+ collections.forEach((collection) => {
+ const { id } = collection;
+ collectionsMap[id] = collection;
+ collectionIds.push(id);
+ });
+
+ state.collections = collectionsMap;
+ state.accountCollections[action.meta.arg.accountId] = {
+ collectionIds,
+ status: 'idle',
+ };
+ });
+
+ /**
+ * Fetching a single collection
+ */
+
+ builder.addCase(fetchCollection.fulfilled, (state, action) => {
+ const { collection } = action.payload;
+ state.collections[collection.id] = collection;
+ });
+
+ /**
+ * Updating a collection
+ */
+
+ builder.addCase(updateCollection.fulfilled, (state, action) => {
+ const { collection } = action.payload;
+ state.collections[collection.id] = collection;
+ });
+
+ /**
+ * Deleting a collection
+ */
+
+ builder.addCase(deleteCollection.fulfilled, (state, action) => {
+ const { collectionId } = action.meta.arg;
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
+ delete state.collections[collectionId];
+ });
+
+ /**
+ * Creating a collection
+ */
+
+ builder.addCase(createCollection.fulfilled, (state, actions) => {
+ const { collection } = actions.payload;
+
+ state.collections[collection.id] = collection;
+
+ if (state.accountCollections[collection.account_id]) {
+ state.accountCollections[collection.account_id]?.collectionIds.unshift(
+ collection.id,
+ );
+ } else {
+ state.accountCollections[collection.account_id] = {
+ collectionIds: [collection.id],
+ status: 'idle',
+ };
+ }
+ });
+ },
+});
+
+export const fetchAccountCollections = createDataLoadingThunk(
+ `${collectionSlice.name}/fetchAccountCollections`,
+ ({ accountId }: { accountId: string }) => apiGetAccountCollections(accountId),
+);
+
+export const fetchCollection = createDataLoadingThunk(
+ `${collectionSlice.name}/fetchCollection`,
+ ({ collectionId }: { collectionId: string }) =>
+ apiGetCollection(collectionId),
+ (payload, { dispatch }) => {
+ if (payload.accounts.length > 0) {
+ dispatch(importFetchedAccounts(payload.accounts));
+ }
+ return payload;
+ },
+);
+
+export const createCollection = createDataLoadingThunk(
+ `${collectionSlice.name}/createCollection`,
+ ({ payload }: { payload: ApiCreateCollectionPayload }) =>
+ apiCreateCollection(payload),
+);
+
+export const updateCollection = createDataLoadingThunk(
+ `${collectionSlice.name}/updateCollection`,
+ ({ payload }: { payload: ApiUpdateCollectionPayload }) =>
+ apiUpdateCollection(payload),
+);
+
+export const deleteCollection = createDataLoadingThunk(
+ `${collectionSlice.name}/deleteCollection`,
+ ({ collectionId }: { collectionId: string }) =>
+ apiDeleteCollection(collectionId),
+);
+
+export const collections = collectionSlice.reducer;
+
+/**
+ * Selectors
+ */
+
+interface AccountCollectionQuery {
+ status: QueryStatus;
+ collections: ApiCollectionJSON[];
+}
+
+export const selectMyCollections = createAppSelector(
+ [
+ (state) => state.meta.get('me') as string,
+ (state) => state.collections.accountCollections,
+ (state) => state.collections.collections,
+ ],
+ (me, collectionsByAccountId, collectionsMap) => {
+ const myCollectionsQuery = collectionsByAccountId[me];
+
+ if (!myCollectionsQuery) {
+ return {
+ status: 'error',
+ collections: [] as ApiCollectionJSON[],
+ } satisfies AccountCollectionQuery;
+ }
+
+ const { status, collectionIds } = myCollectionsQuery;
+
+ return {
+ status,
+ collections: collectionIds
+ .map((id) => collectionsMap[id])
+ .filter((c) => !!c),
+ } satisfies AccountCollectionQuery;
+ },
+);
diff --git a/app/javascript/mastodon/reducers/slices/index.ts b/app/javascript/mastodon/reducers/slices/index.ts
index dfea3951275..06a384d5629 100644
--- a/app/javascript/mastodon/reducers/slices/index.ts
+++ b/app/javascript/mastodon/reducers/slices/index.ts
@@ -1,5 +1,7 @@
import { annualReport } from './annual_report';
+import { collections } from './collections';
export const sliceReducers = {
annualReport,
+ collections,
};
diff --git a/app/javascript/mastodon/reducers/user_lists.js b/app/javascript/mastodon/reducers/user_lists.js
index 466bfe54d65..0393c06763a 100644
--- a/app/javascript/mastodon/reducers/user_lists.js
+++ b/app/javascript/mastodon/reducers/user_lists.js
@@ -204,9 +204,9 @@ export default function userLists(state = initialState, action) {
else if (fetchFeaturedTags.rejected.match(action))
return state.setIn(['featured_tags', action.meta.arg.accountId, 'isLoading'], false);
else if (fetchDirectory.fulfilled.match(action))
- return normalizeList(state, ['directory'], action.payload.accounts, undefined);
+ return normalizeList(state, ['directory'], action.payload.accounts, action.payload.isLast ? null : true);
else if (expandDirectory.fulfilled.match(action))
- return appendToList(state, ['directory'], action.payload.accounts, undefined);
+ return appendToList(state, ['directory'], action.payload.accounts, action.payload.isLast ? null : true);
else if (fetchDirectory.pending.match(action) ||
expandDirectory.pending.match(action))
return state.setIn(['directory', 'isLoading'], true);
diff --git a/app/javascript/mastodon/selectors/accounts.ts b/app/javascript/mastodon/selectors/accounts.ts
index f9ba1a76a6a..bf608fec4e4 100644
--- a/app/javascript/mastodon/selectors/accounts.ts
+++ b/app/javascript/mastodon/selectors/accounts.ts
@@ -1,12 +1,15 @@
-import { createSelector } from '@reduxjs/toolkit';
-import { Record as ImmutableRecord } from 'immutable';
+import type { Map as ImmutableMap } from 'immutable';
+import { Record as ImmutableRecord, List as ImmutableList } from 'immutable';
import { me } from 'mastodon/initial_state';
import { accountDefaultValues } from 'mastodon/models/account';
import type { Account, AccountShape } from 'mastodon/models/account';
import type { Relationship } from 'mastodon/models/relationship';
+import { createAppSelector } from 'mastodon/store';
import type { RootState } from 'mastodon/store';
+import type { ApiHashtagJSON } from '../api_types/tags';
+
const getAccountBase = (state: RootState, id: string) =>
state.accounts.get(id, null);
@@ -33,7 +36,7 @@ const FullAccountFactory = ImmutableRecord({
});
export function makeGetAccount() {
- return createSelector(
+ return createAppSelector(
[getAccountBase, getAccountRelationship, getAccountMoved],
(base, relationship, moved) => {
if (base === null) {
@@ -47,23 +50,23 @@ export function makeGetAccount() {
);
}
-export const getAccountHidden = createSelector(
+export const getAccountHidden = createAppSelector(
[
- (state: RootState, id: string) => state.accounts.get(id)?.hidden,
- (state: RootState, id: string) =>
+ (state, id: string) => state.accounts.get(id)?.hidden,
+ (state, id: string) =>
state.relationships.get(id)?.following ||
state.relationships.get(id)?.requested,
- (state: RootState, id: string) => id === me,
+ (_, id: string) => id === me,
],
(hidden, followingOrRequested, isSelf) => {
return hidden && !(isSelf || followingOrRequested);
},
);
-export const getAccountFamiliarFollowers = createSelector(
+export const getAccountFamiliarFollowers = createAppSelector(
[
- (state: RootState) => state.accounts,
- (state: RootState, id: string) => state.accounts_familiar_followers[id],
+ (state) => state.accounts,
+ (state, id: string) => state.accounts_familiar_followers[id],
],
(accounts, accounts_familiar_followers) => {
if (!accounts_familiar_followers) return null;
@@ -72,3 +75,36 @@ export const getAccountFamiliarFollowers = createSelector(
.filter((f) => !!f);
},
);
+
+export type TagType = Omit<
+ ApiHashtagJSON,
+ 'history' | 'following' | 'featured'
+> & {
+ accountId: string;
+ statuses_count: number;
+ last_status_at: string;
+};
+
+export const selectAccountFeaturedTags = createAppSelector(
+ [(state) => state.user_lists, (_, accountId: string) => accountId],
+ (user_lists, accountId) => {
+ const list = user_lists.getIn(
+ ['featured_tags', accountId, 'items'],
+ ImmutableList(),
+ ) as ImmutableList>;
+ return list.toArray().map(
+ (tag) =>
+ ({
+ id: tag.get('id') as string,
+ name: tag.get('name') as string,
+ url: tag.get('url') as string,
+ accountId: tag.get('accountId') as string,
+ statuses_count: Number.parseInt(
+ tag.get('statuses_count') as string,
+ 10,
+ ),
+ last_status_at: tag.get('last_status_at') as string,
+ }) satisfies TagType,
+ );
+ },
+);
diff --git a/app/javascript/mastodon/selectors/timelines.ts b/app/javascript/mastodon/selectors/timelines.ts
new file mode 100644
index 00000000000..5db50ea894c
--- /dev/null
+++ b/app/javascript/mastodon/selectors/timelines.ts
@@ -0,0 +1,51 @@
+import type { Map as ImmutableMap } from 'immutable';
+import { List as ImmutableList } from 'immutable';
+
+import type { TimelineParams } from '../actions/timelines_typed';
+import { timelineKey } from '../actions/timelines_typed';
+import { createAppSelector } from '../store';
+
+interface TimelineShape {
+ unread: number;
+ online: boolean;
+ top: boolean;
+ isLoading: boolean;
+ hasMore: boolean;
+ pendingItems: ImmutableList;
+ items: ImmutableList;
+}
+
+type TimelinesState = ImmutableMap>;
+
+const emptyList = ImmutableList();
+
+export const selectTimelineByKey = createAppSelector(
+ [(_, key: string) => key, (state) => state.timelines as TimelinesState],
+ (key, timelines) => toTypedTimeline(timelines.get(key)),
+);
+
+export const selectTimelineByParams = createAppSelector(
+ [
+ (_, params: TimelineParams) => timelineKey(params),
+ (state) => state.timelines as TimelinesState,
+ ],
+ (key, timelines) => toTypedTimeline(timelines.get(key)),
+);
+
+export function toTypedTimeline(timeline?: ImmutableMap) {
+ if (!timeline) {
+ return null;
+ }
+ return {
+ unread: timeline.get('unread', 0) as number,
+ online: !!timeline.get('online', false),
+ top: !!timeline.get('top', false),
+ isLoading: !!timeline.get('isLoading', true),
+ hasMore: !!timeline.get('hasMore', false),
+ pendingItems: timeline.get(
+ 'pendingItems',
+ emptyList,
+ ) as ImmutableList,
+ items: timeline.get('items', emptyList) as ImmutableList,
+ } as TimelineShape;
+}
diff --git a/app/javascript/mastodon/utils/environment.ts b/app/javascript/mastodon/utils/environment.ts
index 84767322b04..c7fecee0227 100644
--- a/app/javascript/mastodon/utils/environment.ts
+++ b/app/javascript/mastodon/utils/environment.ts
@@ -12,13 +12,13 @@ export function isProduction() {
else return import.meta.env.PROD;
}
-export type ServerFeatures = 'fasp';
+export type ServerFeatures = 'fasp' | 'collections';
export function isServerFeatureEnabled(feature: ServerFeatures) {
return initialState?.features.includes(feature) ?? false;
}
-type ClientFeatures = 'profile_redesign';
+type ClientFeatures = 'profile_redesign' | 'collections';
export function isClientFeatureEnabled(feature: ClientFeatures) {
try {
diff --git a/app/javascript/mastodon/utils/theme.ts b/app/javascript/mastodon/utils/theme.ts
index 921787a6c43..494ee3cb53b 100644
--- a/app/javascript/mastodon/utils/theme.ts
+++ b/app/javascript/mastodon/utils/theme.ts
@@ -1,11 +1,9 @@
-export function getUserTheme() {
- const { userTheme } = document.documentElement.dataset;
- return userTheme;
+export function getIsSystemTheme() {
+ const { systemTheme } = document.documentElement.dataset;
+ return systemTheme === 'true';
}
export function isDarkMode() {
- const { userTheme } = document.documentElement.dataset;
- return userTheme === 'system'
- ? window.matchMedia('(prefers-color-scheme: dark)').matches
- : userTheme !== 'mastodon-light';
+ const { colorScheme } = document.documentElement.dataset;
+ return colorScheme === 'dark';
}
diff --git a/app/javascript/mastodon/utils/types.ts b/app/javascript/mastodon/utils/types.ts
index 019b0748138..f51b3ad8b31 100644
--- a/app/javascript/mastodon/utils/types.ts
+++ b/app/javascript/mastodon/utils/types.ts
@@ -22,3 +22,5 @@ export type OmitValueType = {
};
export type AnyFunction = (...args: never) => unknown;
+
+export type OmitUnion = TBase & Omit;
diff --git a/app/javascript/material-icons/400-24px/audio.svg b/app/javascript/material-icons/400-24px/audio.svg
deleted file mode 100644
index 417e47c18fe..00000000000
--- a/app/javascript/material-icons/400-24px/audio.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/block-fill.svg b/app/javascript/material-icons/400-24px/block-fill.svg
index 20e9889ae80..2d3801613c9 100644
--- a/app/javascript/material-icons/400-24px/block-fill.svg
+++ b/app/javascript/material-icons/400-24px/block-fill.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/block.svg b/app/javascript/material-icons/400-24px/block.svg
index 20e9889ae80..e9df4cdd35d 100644
--- a/app/javascript/material-icons/400-24px/block.svg
+++ b/app/javascript/material-icons/400-24px/block.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/error-fill.svg b/app/javascript/material-icons/400-24px/error-fill.svg
new file mode 100644
index 00000000000..5125e9acce6
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/error-fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/error.svg b/app/javascript/material-icons/400-24px/error.svg
new file mode 100644
index 00000000000..86c45553268
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/error.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/graphic_eq-fill.svg b/app/javascript/material-icons/400-24px/graphic_eq-fill.svg
new file mode 100644
index 00000000000..a83414784d1
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/graphic_eq-fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/graphic_eq.svg b/app/javascript/material-icons/400-24px/graphic_eq.svg
new file mode 100644
index 00000000000..a83414784d1
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/graphic_eq.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/help-fill.svg b/app/javascript/material-icons/400-24px/help-fill.svg
new file mode 100644
index 00000000000..6fd48ca5dd1
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/help-fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/material-icons/400-24px/help.svg b/app/javascript/material-icons/400-24px/help.svg
new file mode 100644
index 00000000000..0f10691c552
--- /dev/null
+++ b/app/javascript/material-icons/400-24px/help.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/javascript/styles/contrast.scss b/app/javascript/styles/contrast.scss
index 93bbfed0805..cc23627a15a 100644
--- a/app/javascript/styles/contrast.scss
+++ b/app/javascript/styles/contrast.scss
@@ -1,2 +1 @@
@use 'common';
-@use 'mastodon/high-contrast';
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 95460764030..b30509813f3 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -39,8 +39,8 @@
color: var(--color-text-error);
}
- &:hover,
- &:active {
+ &:not(:disabled):hover,
+ &:not(:disabled):active {
text-decoration: underline;
}
@@ -275,7 +275,7 @@
height: 24px;
aspect-ratio: 1;
- path {
+ &:not(.icon--no-fill) path {
fill: currentColor;
}
}
@@ -1081,20 +1081,36 @@ body > [data-popper-placement] {
}
a {
+ --text-decoration-default: none;
+ --text-decoration-hover: underline;
+
+ [data-contrast='high'] & {
+ --text-decoration-default: underline;
+ --text-decoration-hover: none;
+ }
+
color: var(--color-text-status-links);
- text-decoration: none;
+ text-decoration: var(--text-decoration-default);
unicode-bidi: isolate;
- &:hover {
- text-decoration: underline;
+ &:hover,
+ &:focus,
+ &:active {
+ text-decoration: var(--text-decoration-hover);
}
&.mention {
- &:hover {
- text-decoration: none;
+ text-decoration: none;
+ span {
+ text-decoration: var(--text-decoration-default);
+ }
+
+ &:hover,
+ &:focus,
+ &:active {
span {
- text-decoration: underline;
+ text-decoration: var(--text-decoration-hover);
}
}
}
@@ -1356,6 +1372,15 @@ body > [data-popper-placement] {
text-decoration: underline;
}
+ [data-contrast='high'] & {
+ text-decoration: underline;
+
+ &:hover,
+ &:active {
+ text-decoration: none;
+ }
+ }
+
.icon {
width: 15px;
height: 15px;
diff --git a/app/javascript/styles/mastodon/high-contrast.scss b/app/javascript/styles/mastodon/high-contrast.scss
deleted file mode 100644
index f55e7fae3b8..00000000000
--- a/app/javascript/styles/mastodon/high-contrast.scss
+++ /dev/null
@@ -1,40 +0,0 @@
-.status__content a,
-.reply-indicator__content a,
-.edit-indicator__content a,
-.link-footer a,
-.status__content__read-more-button,
-.status__content__translate-button {
- text-decoration: underline;
-
- &:hover,
- &:focus,
- &:active {
- text-decoration: none;
- }
-
- &.mention {
- text-decoration: none;
-
- span {
- text-decoration: underline;
- }
-
- &:hover,
- &:focus,
- &:active {
- span {
- text-decoration: none;
- }
- }
- }
-}
-
-.link-button:disabled {
- cursor: not-allowed;
-
- &:hover,
- &:focus,
- &:active {
- text-decoration: none !important;
- }
-}
diff --git a/app/javascript/styles/mastodon/theme/_dark.scss b/app/javascript/styles/mastodon/theme/_dark.scss
index e6fd6d3cc14..9485464e099 100644
--- a/app/javascript/styles/mastodon/theme/_dark.scss
+++ b/app/javascript/styles/mastodon/theme/_dark.scss
@@ -142,6 +142,7 @@
var(--border-strength-primary)
)};
--color-border-media: rgb(252 248 255 / 15%);
+ --color-border-verified: rgb(220, 3, 240);
--color-border-on-bg-secondary: #{utils.css-alpha(
var(--color-indigo-200),
calc(var(--border-strength-primary) / 1.5)
diff --git a/app/javascript/styles/mastodon/theme/_light.scss b/app/javascript/styles/mastodon/theme/_light.scss
index f0dc1bdfbc3..534a18367ca 100644
--- a/app/javascript/styles/mastodon/theme/_light.scss
+++ b/app/javascript/styles/mastodon/theme/_light.scss
@@ -140,6 +140,7 @@
var(--color-grey-950) var(--border-strength-primary)
);
--color-border-media: rgb(252 248 255 / 15%);
+ --color-border-verified: rgb(220, 3, 240);
--color-border-on-bg-secondary: var(--color-grey-200);
--color-border-on-bg-brand-softer: var(--color-indigo-200);
--color-border-on-bg-error-softer: #{utils.css-alpha(
diff --git a/app/javascript/styles/mastodon/theme/index.scss b/app/javascript/styles/mastodon/theme/index.scss
index a907299887d..a84b8b80da2 100644
--- a/app/javascript/styles/mastodon/theme/index.scss
+++ b/app/javascript/styles/mastodon/theme/index.scss
@@ -5,49 +5,29 @@
html {
@include base.palette;
-
- &:where([data-user-theme='system']) {
- color-scheme: dark light;
-
- @media (prefers-color-scheme: dark) {
- @include dark.tokens;
- @include utils.invert-on-dark;
-
- @media (prefers-contrast: more) {
- @include dark.contrast-overrides;
- }
- }
-
- @media (prefers-color-scheme: light) {
- @include light.tokens;
- @include utils.invert-on-light;
-
- @media (prefers-contrast: more) {
- @include light.contrast-overrides;
- }
- }
- }
}
-.theme-dark,
-html:where(
- :not([data-user-theme='mastodon-light'], [data-user-theme='system'])
-) {
+[data-color-scheme='dark'],
+html:not([data-color-scheme]) {
color-scheme: dark;
@include dark.tokens;
@include utils.invert-on-dark;
+
+ &[data-contrast='high'],
+ [data-contrast='high'] & {
+ @include dark.contrast-overrides;
+ }
}
-html[data-user-theme='contrast'],
-html[data-user-theme='contrast'] .theme-dark {
- @include dark.contrast-overrides;
-}
-
-.theme-light,
-html:where([data-user-theme='mastodon-light']) {
+[data-color-scheme='light'] {
color-scheme: light;
@include light.tokens;
@include utils.invert-on-light;
+
+ &[data-contrast='high'],
+ [data-contrast='high'] & {
+ @include light.contrast-overrides;
+ }
}
diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb
index d07d1c2f241..eab345ce457 100644
--- a/app/lib/activitypub/activity.rb
+++ b/app/lib/activitypub/activity.rb
@@ -5,6 +5,7 @@ class ActivityPub::Activity
include Redisable
include Lockable
+ MAX_JSON_SIZE = 1.megabyte
SUPPORTED_TYPES = %w(Note Question).freeze
CONVERTED_TYPES = %w(Image Audio Video Article Page Event).freeze
diff --git a/app/lib/activitypub/activity/accept.rb b/app/lib/activitypub/activity/accept.rb
index 144ba9645c5..92a8190c038 100644
--- a/app/lib/activitypub/activity/accept.rb
+++ b/app/lib/activitypub/activity/accept.rb
@@ -46,7 +46,7 @@ class ActivityPub::Activity::Accept < ActivityPub::Activity
def accept_quote!(quote)
approval_uri = value_or_id(first_of_value(@json['result']))
- return if unsupported_uri_scheme?(approval_uri) || quote.quoted_account != @account || !quote.status.local?
+ return if unsupported_uri_scheme?(approval_uri) || quote.quoted_account != @account || !quote.status.local? || !quote.pending?
# NOTE: we are not going through `ActivityPub::VerifyQuoteService` as the `Accept` is as authoritative
# as the stamp, but this means we are not checking the stamp, which may lead to inconsistencies
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index 43c7bb1fe71..24ea62510b6 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -144,7 +144,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
# Accounts that are tagged but are not in the audience are not
# supposed to be notified explicitly
- @silenced_account_ids = @mentions.map(&:account_id) - accounts_in_audience.map(&:id)
+ @silenced_account_ids = @mentions.filter_map { |mention| mention.account_id if mention.account.local? } - accounts_in_audience.map(&:id)
end
def postprocess_audience_and_deliver
@@ -379,6 +379,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def conversation_from_uri(uri)
return nil if uri.nil?
return Conversation.find_by(id: OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Conversation')) if OStatus::TagManager.instance.local_id?(uri)
+ return ActivityPub::TagManager.instance.uri_to_resource(uri, Conversation) if ActivityPub::TagManager.instance.local_uri?(uri)
begin
Conversation.find_or_create_by!(uri: uri)
diff --git a/app/lib/activitypub/activity/delete.rb b/app/lib/activitypub/activity/delete.rb
index 3e77f9b9556..f606d9520f0 100644
--- a/app/lib/activitypub/activity/delete.rb
+++ b/app/lib/activitypub/activity/delete.rb
@@ -56,7 +56,7 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity
end
def revoke_quote
- @quote = Quote.find_by(approval_uri: object_uri, quoted_account: @account)
+ @quote = Quote.find_by(approval_uri: object_uri, quoted_account: @account, state: [:pending, :accepted])
return if @quote.nil?
ActivityPub::Forwarder.new(@account, @json, @quote.status).forward! if @quote.status.present?
diff --git a/app/lib/activitypub/activity/update.rb b/app/lib/activitypub/activity/update.rb
index d94f8767618..e22bea2c64f 100644
--- a/app/lib/activitypub/activity/update.rb
+++ b/app/lib/activitypub/activity/update.rb
@@ -30,7 +30,8 @@ class ActivityPub::Activity::Update < ActivityPub::Activity
@status = Status.find_by(uri: object_uri, account_id: @account.id)
# Ignore updates for old unknown objects, since those are updates we are not interested in
- return if @status.nil? && object_too_old?
+ # Also ignore unknown objects from suspended users for the same reasons
+ return if @status.nil? && (@account.suspended? || object_too_old?)
# We may be getting `Create` and `Update` out of order
@status ||= ActivityPub::Activity::Create.new(@json, @account, **@options).perform
diff --git a/app/lib/activitypub/parser/poll_parser.rb b/app/lib/activitypub/parser/poll_parser.rb
index 758c03f07ec..d43eaf6cfb4 100644
--- a/app/lib/activitypub/parser/poll_parser.rb
+++ b/app/lib/activitypub/parser/poll_parser.rb
@@ -3,6 +3,10 @@
class ActivityPub::Parser::PollParser
include JsonLdHelper
+ # Limit the number of items for performance purposes.
+ # We truncate rather than error out to avoid missing the post entirely.
+ MAX_ITEMS = 500
+
def initialize(json)
@json = json
end
@@ -48,6 +52,6 @@ class ActivityPub::Parser::PollParser
private
def items
- @json['anyOf'] || @json['oneOf']
+ (@json['anyOf'] || @json['oneOf'])&.take(MAX_ITEMS)
end
end
diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb
index 9f01b005780..f9cb90f548c 100644
--- a/app/lib/activitypub/tag_manager.rb
+++ b/app/lib/activitypub/tag_manager.rb
@@ -63,7 +63,7 @@ class ActivityPub::TagManager
when :flag
target.uri
when :featured_collection
- ap_account_featured_collection_url(target.account.id, target)
+ ap_account_collection_url(target.account.id, target)
end
end
@@ -135,7 +135,7 @@ class ActivityPub::TagManager
def collection_uri_for(target, ...)
raise ArgumentError, 'target must be a local account' unless target.local?
- target.numeric_ap_id? ? ap_account_collection_url(target.id, ...) : account_collection_url(target, ...)
+ target.numeric_ap_id? ? ap_account_actor_collection_url(target.id, ...) : account_actor_collection_url(target, ...)
end
def inbox_uri_for(target)
@@ -243,12 +243,6 @@ class ActivityPub::TagManager
!host.nil? && (::TagManager.instance.local_domain?(host) || ::TagManager.instance.web_domain?(host))
end
- def uri_to_local_id(uri, param = :id)
- path_params = Rails.application.routes.recognize_path(uri)
- path_params[:username] = Rails.configuration.x.local_domain if path_params[:controller] == 'instance_actors'
- path_params[param]
- end
-
def uris_to_local_accounts(uris)
usernames = []
ids = []
@@ -266,6 +260,14 @@ class ActivityPub::TagManager
uri_to_resource(uri, Account)
end
+ def uri_to_local_conversation(uri)
+ path_params = Rails.application.routes.recognize_path(uri)
+ return unless path_params[:controller] == 'activitypub/contexts'
+
+ account_id, conversation_id = path_params[:id].split('-')
+ Conversation.find_by(parent_account_id: account_id, id: conversation_id)
+ end
+
def uri_to_resource(uri, klass)
return if uri.nil?
@@ -273,6 +275,8 @@ class ActivityPub::TagManager
case klass.name
when 'Account'
uris_to_local_accounts([uri]).first
+ when 'Conversation'
+ uri_to_local_conversation(uri)
else
StatusFinder.new(uri).status
end
diff --git a/app/lib/admin/metrics/dimension/software_versions_dimension.rb b/app/lib/admin/metrics/dimension/software_versions_dimension.rb
index e64a6b1180a..032abb75250 100644
--- a/app/lib/admin/metrics/dimension/software_versions_dimension.rb
+++ b/app/lib/admin/metrics/dimension/software_versions_dimension.rb
@@ -10,7 +10,7 @@ class Admin::Metrics::Dimension::SoftwareVersionsDimension < Admin::Metrics::Dim
protected
def perform_query
- [mastodon_version, ruby_version, postgresql_version, redis_version, elasticsearch_version, libvips_version, imagemagick_version, ffmpeg_version].compact
+ [mastodon_version, ruby_version, postgresql_version, redis_version, elasticsearch_version, libvips_version, ffmpeg_version].compact
end
def mastodon_version
@@ -70,8 +70,6 @@ class Admin::Metrics::Dimension::SoftwareVersionsDimension < Admin::Metrics::Dim
end
def libvips_version
- return unless Rails.configuration.x.use_vips
-
{
key: 'libvips',
human_key: 'libvips',
@@ -80,28 +78,6 @@ class Admin::Metrics::Dimension::SoftwareVersionsDimension < Admin::Metrics::Dim
}
end
- def imagemagick_version
- return if Rails.configuration.x.use_vips
-
- imagemagick_binary = Paperclip.options[:is_windows] ? 'magick convert' : 'convert'
-
- version_output = Terrapin::CommandLine.new(imagemagick_binary, '-version').run
- version_match = version_output.match(/Version: ImageMagick (\S+)/)[1].strip
-
- return nil unless version_match
-
- version = version_match
-
- {
- key: 'imagemagick',
- human_key: 'ImageMagick',
- value: version,
- human_value: version,
- }
- rescue Terrapin::CommandNotFoundError, Terrapin::ExitStatusError, Paperclip::Errors::CommandNotFoundError, Paperclip::Errors::CommandFailedError
- nil
- end
-
def ffmpeg_version
version_output = Terrapin::CommandLine.new(Rails.configuration.x.ffprobe_binary, '-show_program_version -v 0 -of json').run
version = Oj.load(version_output, mode: :strict, symbol_keys: true).dig(:program_version, :version)
diff --git a/app/lib/admin/metrics/dimension/tag_servers_dimension.rb b/app/lib/admin/metrics/dimension/tag_servers_dimension.rb
index 29145e14871..ee40d2c9c86 100644
--- a/app/lib/admin/metrics/dimension/tag_servers_dimension.rb
+++ b/app/lib/admin/metrics/dimension/tag_servers_dimension.rb
@@ -22,7 +22,7 @@ class Admin::Metrics::Dimension::TagServersDimension < Admin::Metrics::Dimension
end
def sql_query_string
- <<-SQL.squish
+ <<~SQL.squish
SELECT accounts.domain, count(*) AS value
FROM statuses
INNER JOIN accounts ON accounts.id = statuses.account_id
diff --git a/app/lib/connection_pool/shared_timed_stack.rb b/app/lib/connection_pool/shared_timed_stack.rb
index 14a5285c457..8a13f4473ba 100644
--- a/app/lib/connection_pool/shared_timed_stack.rb
+++ b/app/lib/connection_pool/shared_timed_stack.rb
@@ -70,6 +70,7 @@ class ConnectionPool::SharedTimedStack
if @created == @max && !@queue.empty?
throw_away_connection = @queue.pop
@tagged_queue[throw_away_connection.site].delete(throw_away_connection)
+ throw_away_connection.close
@create_block.call(preferred_tag)
elsif @created != @max
connection = @create_block.call(preferred_tag)
diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb
index 9c5c306e966..ab5ee106c7e 100644
--- a/app/lib/feed_manager.rb
+++ b/app/lib/feed_manager.rb
@@ -450,6 +450,7 @@ class FeedManager
return :filter if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?)
return :skip_home if timeline_type != :list && crutches[:exclusive_list_users][status.account_id].present?
return :filter if crutches[:languages][status.account_id].present? && status.language.present? && !crutches[:languages][status.account_id].include?(status.language)
+ return :filter if status.reblog? && status.reblog.blank?
check_for_blocks = crutches[:active_mentions][status.id] || []
check_for_blocks.push(status.account_id)
diff --git a/app/lib/ostatus/tag_manager.rb b/app/lib/ostatus/tag_manager.rb
index cb0c9f89668..7d0f23c4dc1 100644
--- a/app/lib/ostatus/tag_manager.rb
+++ b/app/lib/ostatus/tag_manager.rb
@@ -11,16 +11,12 @@ class OStatus::TagManager
def unique_tag_to_local_id(tag, expected_type)
return nil unless local_id?(tag)
- if ActivityPub::TagManager.instance.local_uri?(tag)
- ActivityPub::TagManager.instance.uri_to_local_id(tag)
- else
- matches = Regexp.new("objectId=([\\d]+):objectType=#{expected_type}").match(tag)
- matches[1] unless matches.nil?
- end
+ matches = Regexp.new("objectId=([\\d]+):objectType=#{expected_type}").match(tag)
+ matches[1] unless matches.nil?
end
def local_id?(id)
- id.start_with?("tag:#{Rails.configuration.x.local_domain}") || ActivityPub::TagManager.instance.local_uri?(id)
+ id.start_with?("tag:#{Rails.configuration.x.local_domain}")
end
def uri_for(target)
diff --git a/app/lib/tag_manager.rb b/app/lib/tag_manager.rb
index c1bd2973ed1..5a6284cc5b6 100644
--- a/app/lib/tag_manager.rb
+++ b/app/lib/tag_manager.rb
@@ -18,7 +18,7 @@ class TagManager
return if domain.nil?
uri = Addressable::URI.new
- uri.host = domain.delete_suffix('/')
+ uri.host = domain.strip.delete_suffix('/')
uri.normalized_host
end
diff --git a/app/models/account.rb b/app/models/account.rb
index deb1589a090..7623e2398cc 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -9,6 +9,7 @@
# also_known_as :string is an Array
# attribution_domains :string default([]), is an Array
# avatar_content_type :string
+# avatar_description :string default(""), not null
# avatar_file_name :string
# avatar_file_size :integer
# avatar_remote_url :string
@@ -23,6 +24,7 @@
# followers_url :string default(""), not null
# following_url :string default(""), not null
# header_content_type :string
+# header_description :string default(""), not null
# header_file_name :string
# header_file_size :integer
# header_remote_url :string default(""), not null
@@ -81,6 +83,13 @@ class Account < ApplicationRecord
DISPLAY_NAME_LENGTH_LIMIT = 30
NOTE_LENGTH_LIMIT = 500
+ # Hard limits for federated content
+ USERNAME_LENGTH_HARD_LIMIT = 2048
+ DISPLAY_NAME_LENGTH_HARD_LIMIT = 2048
+ NOTE_LENGTH_HARD_LIMIT = 20.kilobytes
+ ATTRIBUTION_DOMAINS_HARD_LIMIT = 256
+ ALSO_KNOWN_AS_HARD_LIMIT = 256
+
AUTOMATED_ACTOR_TYPES = %w(Application Service).freeze
include Attachmentable # Load prior to Avatar & Header concerns
@@ -114,7 +123,7 @@ class Account < ApplicationRecord
validates_with UniqueUsernameValidator, if: -> { will_save_change_to_username? }
# Remote user validations, also applies to internal actors
- validates :username, format: { with: USERNAME_ONLY_RE }, if: -> { (remote? || actor_type_application?) && will_save_change_to_username? }
+ validates :username, format: { with: USERNAME_ONLY_RE }, length: { maximum: USERNAME_LENGTH_HARD_LIMIT }, if: -> { (remote? || actor_type_application?) && will_save_change_to_username? }
# Remote user validations
validates :uri, presence: true, unless: :local?, on: :create
diff --git a/app/models/collection.rb b/app/models/collection.rb
index b732a3d220b..3681c41d84f 100644
--- a/app/models/collection.rb
+++ b/app/models/collection.rb
@@ -8,6 +8,7 @@
# description :text not null
# discoverable :boolean not null
# item_count :integer default(0), not null
+# language :string
# local :boolean not null
# name :string not null
# original_number_of_items :integer
@@ -36,11 +37,13 @@ class Collection < ApplicationRecord
presence: true,
numericality: { greater_than_or_equal: 0 },
if: :remote?
+ validates :language, language: { if: :local?, allow_nil: true }
validate :tag_is_usable
validate :items_do_not_exceed_limit
scope :with_items, -> { includes(:collection_items).merge(CollectionItem.with_accounts) }
scope :with_tag, -> { includes(:tag) }
+ scope :discoverable, -> { where(discoverable: true) }
def remote?
!local?
diff --git a/app/models/concerns/account/associations.rb b/app/models/concerns/account/associations.rb
index e1684d25607..03ec7139411 100644
--- a/app/models/concerns/account/associations.rb
+++ b/app/models/concerns/account/associations.rb
@@ -9,8 +9,10 @@ module Account::Associations
# Association where account owns record
with_options inverse_of: :account do
has_many :account_moderation_notes
+ has_many :account_notes
has_many :account_pins
has_many :account_warnings
+ has_many :action_logs, class_name: 'Admin::ActionLog'
has_many :aliases, class_name: 'AccountAlias'
has_many :bookmarks
has_many :collections
@@ -45,6 +47,7 @@ module Account::Associations
# Association where account is targeted by record
with_options foreign_key: :target_account_id, inverse_of: :target_account do
has_many :strikes, class_name: 'AccountWarning'
+ has_many :targeted_account_notes, class_name: 'AccountNote'
has_many :targeted_moderation_notes, class_name: 'AccountModerationNote'
has_many :targeted_reports, class_name: 'Report'
end
diff --git a/app/models/concerns/account/avatar.rb b/app/models/concerns/account/avatar.rb
index a60a289d5b0..945ba3592cd 100644
--- a/app/models/concerns/account/avatar.rb
+++ b/app/models/concerns/account/avatar.rb
@@ -4,7 +4,7 @@ module Account::Avatar
extend ActiveSupport::Concern
AVATAR_IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze
- AVATAR_LIMIT = Rails.configuration.x.use_vips ? 8.megabytes : 2.megabytes
+ AVATAR_LIMIT = 8.megabytes
AVATAR_DIMENSIONS = [400, 400].freeze
AVATAR_GEOMETRY = [AVATAR_DIMENSIONS.first, AVATAR_DIMENSIONS.last].join('x')
@@ -24,6 +24,8 @@ module Account::Avatar
validates_attachment_content_type :avatar, content_type: AVATAR_IMAGE_MIME_TYPES
validates_attachment_size :avatar, less_than: AVATAR_LIMIT
remotable_attachment :avatar, AVATAR_LIMIT, suppress_errors: false
+
+ validates :avatar_description, length: { maximum: MediaAttachment::MAX_DESCRIPTION_LENGTH }
end
def avatar_original_url
diff --git a/app/models/concerns/account/counters.rb b/app/models/concerns/account/counters.rb
index 536d5ca7bcd..887cd07374b 100644
--- a/app/models/concerns/account/counters.rb
+++ b/app/models/concerns/account/counters.rb
@@ -20,8 +20,8 @@ module Account::Counters
to: :account_stat
# @param [Symbol] key
- def increment_count!(key)
- update_count!(key, 1)
+ def increment_count!(key, status_created_at: nil)
+ update_count!(key, 1, status_created_at:)
end
# @param [Symbol] key
@@ -31,11 +31,11 @@ module Account::Counters
# @param [Symbol] key
# @param [Integer] value
- def update_count!(key, value)
+ def update_count!(key, value, status_created_at: nil)
raise ArgumentError, "Invalid key #{key}" unless ALLOWED_COUNTER_KEYS.include?(key)
raise ArgumentError, 'Do not call update_count! on dirty objects' if association(:account_stat).loaded? && account_stat&.changed? && account_stat.changed_attribute_names_to_save == %w(id)
- result = updated_account_stat(key, value.to_i)
+ result = updated_account_stat(key, value.to_i, status_created_at:)
# Reload account_stat if it was loaded, taking into account newly-created unsaved records
if association(:account_stat).loaded?
@@ -50,25 +50,27 @@ module Account::Counters
private
- def updated_account_stat(key, value)
+ def updated_account_stat(key, value, status_created_at: nil)
+ status_created_at = Time.now.utc if status_created_at.nil? || status_created_at > Time.now.utc
+
AccountStat.upsert(
- initial_values(key, value),
+ initial_values(key, value, status_created_at:),
on_duplicate: Arel.sql(
- duplicate_values(key, value).join(', ')
+ duplicate_values(key, value, status_created_at:).join(', ')
),
unique_by: :account_id
)
end
- def initial_values(key, value)
+ def initial_values(key, value, status_created_at: nil)
{ :account_id => id, key => [value, 0].max }.tap do |values|
- values.merge!(last_status_at: Time.current) if key == :statuses_count
+ values.merge!(last_status_at: status_created_at) if key == :statuses_count
end
end
- def duplicate_values(key, value)
+ def duplicate_values(key, value, status_created_at: nil)
["#{key} = (account_stats.#{key} + #{value})", 'updated_at = CURRENT_TIMESTAMP'].tap do |values|
- values << 'last_status_at = CURRENT_TIMESTAMP' if key == :statuses_count && value.positive?
+ values << AccountStat.sanitize_sql_array(['last_status_at = GREATEST(account_stats.last_status_at, ?::timestamp)', status_created_at]) if key == :statuses_count && value.positive?
end
end
diff --git a/app/models/concerns/account/header.rb b/app/models/concerns/account/header.rb
index 662ee7caf78..1b70715a9e7 100644
--- a/app/models/concerns/account/header.rb
+++ b/app/models/concerns/account/header.rb
@@ -4,7 +4,7 @@ module Account::Header
extend ActiveSupport::Concern
HEADER_IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze
- HEADER_LIMIT = Rails.configuration.x.use_vips ? 8.megabytes : 2.megabytes
+ HEADER_LIMIT = 8.megabytes
HEADER_DIMENSIONS = [1500, 500].freeze
HEADER_GEOMETRY = [HEADER_DIMENSIONS.first, HEADER_DIMENSIONS.last].join('x')
HEADER_MAX_PIXELS = HEADER_DIMENSIONS.first * HEADER_DIMENSIONS.last
@@ -25,6 +25,8 @@ module Account::Header
validates_attachment_content_type :header, content_type: HEADER_IMAGE_MIME_TYPES
validates_attachment_size :header, less_than: HEADER_LIMIT
remotable_attachment :header, HEADER_LIMIT, suppress_errors: false
+
+ validates :header_description, length: { maximum: MediaAttachment::MAX_DESCRIPTION_LENGTH }
end
def header_original_url
diff --git a/app/models/concerns/account/interactions.rb b/app/models/concerns/account/interactions.rb
index c51ccf1229e..e204ddb7957 100644
--- a/app/models/concerns/account/interactions.rb
+++ b/app/models/concerns/account/interactions.rb
@@ -23,9 +23,6 @@ module Account::Interactions
# Hashtag follows
has_many :tag_follows, inverse_of: :account, dependent: :destroy
- # Account notes
- has_many :account_notes, dependent: :destroy
-
# Block relationships
with_options class_name: 'Block', dependent: :destroy do
has_many :block_relationships, foreign_key: 'account_id', inverse_of: :account
@@ -164,6 +161,13 @@ module Account::Interactions
end
end
+ def blocking_or_domain_blocking?(other_account)
+ return true if blocking?(other_account)
+ return false if other_account.domain.blank?
+
+ domain_blocking?(other_account.domain)
+ end
+
def muting?(other_account)
other_id = other_account.is_a?(Account) ? other_account.id : other_account
diff --git a/app/models/concerns/status/threading_concern.rb b/app/models/concerns/status/threading_concern.rb
index 3b0a3cd0281..91b3450f949 100644
--- a/app/models/concerns/status/threading_concern.rb
+++ b/app/models/concerns/status/threading_concern.rb
@@ -49,7 +49,7 @@ module Status::ThreadingConcern
end
def ancestor_statuses(limit)
- Status.find_by_sql([<<-SQL.squish, id: in_reply_to_id, limit: limit])
+ Status.find_by_sql([<<~SQL.squish, id: in_reply_to_id, limit: limit])
WITH RECURSIVE search_tree(id, in_reply_to_id, path)
AS (
SELECT id, in_reply_to_id, ARRAY[id]
@@ -73,7 +73,7 @@ module Status::ThreadingConcern
depth += 1 if depth.present?
limit += 1 if limit.present?
- descendants_with_self = Status.find_by_sql([<<-SQL.squish, id: id, limit: limit, depth: depth])
+ descendants_with_self = Status.find_by_sql([<<~SQL.squish, id: id, limit: limit, depth: depth])
WITH RECURSIVE search_tree(id, path) AS (
SELECT id, ARRAY[id]
FROM statuses
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 65a2faa9fd5..5c39e053be1 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -26,6 +26,8 @@ class CustomEmoji < ApplicationRecord
LIMIT = 256.kilobytes
MINIMUM_SHORTCODE_SIZE = 2
+ MAX_SHORTCODE_SIZE = 128
+ MAX_FEDERATED_SHORTCODE_SIZE = 2048
SHORTCODE_RE_FRAGMENT = '[a-zA-Z0-9_]{2,}'
@@ -45,7 +47,8 @@ class CustomEmoji < ApplicationRecord
normalizes :domain, with: ->(domain) { domain.downcase.strip }
validates_attachment :image, content_type: { content_type: IMAGE_MIME_TYPES }, presence: true, size: { less_than: LIMIT }
- validates :shortcode, uniqueness: { scope: :domain }, format: { with: SHORTCODE_ONLY_RE }, length: { minimum: MINIMUM_SHORTCODE_SIZE }
+ validates :shortcode, uniqueness: { scope: :domain }, format: { with: SHORTCODE_ONLY_RE }, length: { minimum: MINIMUM_SHORTCODE_SIZE, maximum: MAX_FEDERATED_SHORTCODE_SIZE }
+ validates :shortcode, length: { maximum: MAX_SHORTCODE_SIZE }, if: :local?
scope :local, -> { where(domain: nil) }
scope :remote, -> { where.not(domain: nil) }
diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb
index 07bbfd43733..1151c7de985 100644
--- a/app/models/custom_filter.rb
+++ b/app/models/custom_filter.rb
@@ -30,6 +30,8 @@ class CustomFilter < ApplicationRecord
EXPIRATION_DURATIONS = [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].freeze
+ TITLE_LENGTH_LIMIT = 256
+
include Expireable
include Redisable
@@ -41,6 +43,7 @@ class CustomFilter < ApplicationRecord
accepts_nested_attributes_for :keywords, reject_if: :all_blank, allow_destroy: true
validates :title, :context, presence: true
+ validates :title, length: { maximum: TITLE_LENGTH_LIMIT }
validate :context_must_be_valid
normalizes :context, with: ->(context) { context.map(&:strip).filter_map(&:presence) }
diff --git a/app/models/custom_filter_keyword.rb b/app/models/custom_filter_keyword.rb
index 112798b10a9..1abec4ddc4d 100644
--- a/app/models/custom_filter_keyword.rb
+++ b/app/models/custom_filter_keyword.rb
@@ -17,7 +17,9 @@ class CustomFilterKeyword < ApplicationRecord
belongs_to :custom_filter
- validates :keyword, presence: true
+ KEYWORD_LENGTH_LIMIT = 512
+
+ validates :keyword, presence: true, length: { maximum: KEYWORD_LENGTH_LIMIT }
alias_attribute :phrase, :keyword
diff --git a/app/models/list.rb b/app/models/list.rb
index 8fd1953ab31..49ead642ac9 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -17,6 +17,7 @@ class List < ApplicationRecord
include Paginable
PER_ACCOUNT_LIMIT = 50
+ TITLE_LENGTH_LIMIT = 256
enum :replies_policy, { list: 0, followed: 1, none: 2 }, prefix: :show, validate: true
@@ -26,7 +27,7 @@ class List < ApplicationRecord
has_many :accounts, through: :list_accounts
has_many :active_accounts, -> { merge(ListAccount.active) }, through: :list_accounts, source: :account
- validates :title, presence: true
+ validates :title, presence: true, length: { maximum: TITLE_LENGTH_LIMIT }
validate :validate_account_lists_limit, on: :create
diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb
index 2615eed4e39..c0c768154b4 100644
--- a/app/models/media_attachment.rb
+++ b/app/models/media_attachment.rb
@@ -214,6 +214,14 @@ class MediaAttachment < ApplicationRecord
scope :remote, -> { where.not(remote_url: '') }
scope :unattached, -> { where(status_id: nil, scheduled_status_id: nil) }
scope :updated_before, ->(value) { where(arel_table[:updated_at].lt(value)) }
+ scope :without_local_interaction, lambda {
+ where.not(Favourite.joins(:account).merge(Account.local).where(Favourite.arel_table[:status_id].eq(MediaAttachment.arel_table[:status_id])).select(1).arel.exists)
+ .where.not(Bookmark.where(Bookmark.arel_table[:status_id].eq(MediaAttachment.arel_table[:status_id])).select(1).arel.exists)
+ .where.not(Status.local.where(Status.arel_table[:in_reply_to_id].eq(MediaAttachment.arel_table[:status_id])).select(1).arel.exists)
+ .where.not(Status.local.where(Status.arel_table[:reblog_of_id].eq(MediaAttachment.arel_table[:status_id])).select(1).arel.exists)
+ .where.not(Quote.joins(:status).merge(Status.local).where(Quote.arel_table[:quoted_status_id].eq(MediaAttachment.arel_table[:status_id])).select(1).arel.exists)
+ .where.not(Quote.joins(:quoted_status).merge(Status.local).where(Quote.arel_table[:status_id].eq(MediaAttachment.arel_table[:status_id])).select(1).arel.exists)
+ }
attr_accessor :skip_download
diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb
index 8e0e13cdb94..644be2671a9 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 = Rails.configuration.x.use_vips ? 8.megabytes : 2.megabytes
+ LIMIT = 8.megabytes
BLURHASH_OPTIONS = {
x_comp: 4,
@@ -63,7 +63,7 @@ class PreviewCard < ApplicationRecord
belongs_to :author_account, class_name: 'Account', optional: true
has_attached_file :image,
- processors: [Rails.configuration.x.use_vips ? :lazy_thumbnail : :thumbnail, :blurhash_transcoder],
+ processors: [:lazy_thumbnail, :blurhash_transcoder],
styles: ->(f) { image_styles(f) },
convert_options: { all: '-quality 90 +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' },
validate_media_type: false
diff --git a/app/models/quote.rb b/app/models/quote.rb
index e81d427089d..e4f3b823fe4 100644
--- a/app/models/quote.rb
+++ b/app/models/quote.rb
@@ -47,13 +47,15 @@ class Quote < ApplicationRecord
def accept!
update!(state: :accepted)
+
+ reset_parent_cache! if attribute_previously_changed?(:state)
end
def reject!
if accepted?
- update!(state: :revoked)
+ update!(state: :revoked, approval_uri: nil)
elsif !revoked?
- update!(state: :rejected)
+ update!(state: :rejected, approval_uri: nil)
end
end
@@ -75,6 +77,15 @@ class Quote < ApplicationRecord
private
+ def reset_parent_cache!
+ return if status_id.nil?
+
+ Rails.cache.delete("v3:statuses/#{status_id}")
+
+ # This clears the web cache for the ActivityPub representation
+ Rails.cache.delete("statuses/show:v3:statuses/#{status_id}")
+ end
+
def set_accounts
self.account = status.account
self.quoted_account = quoted_status&.account
diff --git a/app/models/status.rb b/app/models/status.rb
index 8ee290b297b..2b5f8e58a3c 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -90,6 +90,7 @@ class Status < ApplicationRecord
has_many :local_favorited, -> { merge(Account.local) }, through: :favourites, source: :account
has_many :local_reblogged, -> { merge(Account.local) }, through: :reblogs, source: :account
has_many :local_bookmarked, -> { merge(Account.local) }, through: :bookmarks, source: :account
+ has_many :local_replied, -> { merge(Account.local) }, through: :replies, source: :account
has_and_belongs_to_many :tags # rubocop:disable Rails/HasAndBelongsToMany
@@ -481,7 +482,7 @@ class Status < ApplicationRecord
def increment_counter_caches
return if direct_visibility?
- account&.increment_count!(:statuses_count)
+ account&.increment_count!(:statuses_count, status_created_at: created_at)
reblog&.increment_count!(:reblogs_count) if reblog?
thread&.increment_count!(:replies_count) if in_reply_to_id.present? && distributable?
end
diff --git a/app/policies/account_policy.rb b/app/policies/account_policy.rb
index ab3b41d6280..1fef35714cd 100644
--- a/app/policies/account_policy.rb
+++ b/app/policies/account_policy.rb
@@ -68,4 +68,8 @@ class AccountPolicy < ApplicationPolicy
def feature?
record.featureable? && !current_account.blocking?(record) && !current_account.blocked_by?(record)
end
+
+ def index_collections?
+ current_account.nil? || !record.blocking_or_domain_blocking?(current_account)
+ end
end
diff --git a/app/policies/collection_policy.rb b/app/policies/collection_policy.rb
index 12adfbcad1a..4d100c0e32f 100644
--- a/app/policies/collection_policy.rb
+++ b/app/policies/collection_policy.rb
@@ -6,7 +6,7 @@ class CollectionPolicy < ApplicationPolicy
end
def show?
- true
+ current_account.nil? || !owner.blocking_or_domain_blocking?(current_account)
end
def create?
@@ -24,6 +24,10 @@ class CollectionPolicy < ApplicationPolicy
private
def owner?
- current_account == record.account
+ current_account == owner
+ end
+
+ def owner
+ record.account
end
end
diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb
index c19d42bfb43..ff1a70104b8 100644
--- a/app/serializers/activitypub/actor_serializer.rb
+++ b/app/serializers/activitypub/actor_serializer.rb
@@ -19,6 +19,7 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
:discoverable, :indexable, :published, :memorial
attribute :interaction_policy, if: -> { Mastodon::Feature.collections_enabled? }
+ attribute :featured_collections, if: -> { Mastodon::Feature.collections_enabled? }
has_one :public_key, serializer: ActivityPub::PublicKeySerializer
@@ -177,6 +178,12 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
}
end
+ def featured_collections
+ return nil if instance_actor?
+
+ ap_account_featured_collections_url(object.id)
+ end
+
class CustomEmojiSerializer < ActivityPub::EmojiSerializer
end
diff --git a/app/serializers/activitypub/add_serializer.rb b/app/serializers/activitypub/add_serializer.rb
index 640d7742726..a2a1256ec56 100644
--- a/app/serializers/activitypub/add_serializer.rb
+++ b/app/serializers/activitypub/add_serializer.rb
@@ -10,11 +10,13 @@ class ActivityPub::AddSerializer < ActivityPub::Serializer
end
def self.serializer_for(model, options)
- case model.class.name
- when 'Status'
+ case model
+ when Status
UriSerializer
- when 'FeaturedTag'
+ when FeaturedTag
ActivityPub::HashtagSerializer
+ when Collection
+ ActivityPub::FeaturedCollectionSerializer
else
super
end
@@ -38,6 +40,16 @@ class ActivityPub::AddSerializer < ActivityPub::Serializer
end
def target
- ActivityPub::TagManager.instance.collection_uri_for(object.account, :featured)
+ case object
+ when Status, FeaturedTag
+ # Technically this is not correct, as tags have their own collection.
+ # But sadly we do not store the collection URI for tags anywhere so cannot
+ # handle `Add` activities to that properly (yet). The receiving code for
+ # this currently looks at the type of the contained objects to do the
+ # right thing.
+ ActivityPub::TagManager.instance.collection_uri_for(object.account, :featured)
+ when Collection
+ ap_account_featured_collections_url(object.account_id)
+ end
end
end
diff --git a/app/serializers/activitypub/collection_serializer.rb b/app/serializers/activitypub/collection_serializer.rb
index 1b410cecaef..ba0d17f5408 100644
--- a/app/serializers/activitypub/collection_serializer.rb
+++ b/app/serializers/activitypub/collection_serializer.rb
@@ -18,6 +18,8 @@ class ActivityPub::CollectionSerializer < ActivityPub::Serializer
ActivityPub::HashtagSerializer
when 'ActivityPub::CollectionPresenter'
ActivityPub::CollectionSerializer
+ when 'Collection'
+ ActivityPub::FeaturedCollectionSerializer
when 'String'
StringSerializer
else
diff --git a/app/serializers/activitypub/featured_collection_serializer.rb b/app/serializers/activitypub/featured_collection_serializer.rb
index e70d155a1a0..af4c5548514 100644
--- a/app/serializers/activitypub/featured_collection_serializer.rb
+++ b/app/serializers/activitypub/featured_collection_serializer.rb
@@ -17,9 +17,12 @@ class ActivityPub::FeaturedCollectionSerializer < ActivityPub::Serializer
end
end
- attributes :id, :type, :total_items, :name, :summary, :attributed_to,
+ attributes :id, :type, :total_items, :name, :attributed_to,
:sensitive, :discoverable, :published, :updated
+ attribute :summary, unless: :language_present?
+ attribute :summary_map, if: :language_present?
+
has_one :tag, key: :topic, serializer: ActivityPub::NoteSerializer::TagSerializer
has_many :collection_items, key: :ordered_items, serializer: FeaturedItemSerializer
@@ -36,6 +39,10 @@ class ActivityPub::FeaturedCollectionSerializer < ActivityPub::Serializer
object.description
end
+ def summary_map
+ { object.language => object.description }
+ end
+
def attributed_to
ActivityPub::TagManager.instance.uri_for(object.account)
end
@@ -51,4 +58,8 @@ class ActivityPub::FeaturedCollectionSerializer < ActivityPub::Serializer
def updated
object.updated_at.iso8601
end
+
+ def language_present?
+ object.language.present?
+ end
end
diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb
index fe2a857d509..a8e4b1d7f79 100644
--- a/app/serializers/initial_state_serializer.rb
+++ b/app/serializers/initial_state_serializer.rb
@@ -140,7 +140,7 @@ class InitialStateSerializer < ActiveModel::Serializer
end
def serialized_account(account)
- ActiveModelSerializers::SerializableResource.new(account, serializer: REST::AccountSerializer)
+ ActiveModelSerializers::SerializableResource.new(account, serializer: REST::AccountSerializer, scope_name: :current_user, scope: object.current_account&.user)
end
def instance_presenter
diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb
index 26715dd1032..3fa541f445d 100644
--- a/app/serializers/rest/account_serializer.rb
+++ b/app/serializers/rest/account_serializer.rb
@@ -7,7 +7,7 @@ class REST::AccountSerializer < ActiveModel::Serializer
# Please update `app/javascript/mastodon/api_types/accounts.ts` when making changes to the attributes
attributes :id, :username, :acct, :display_name, :locked, :bot, :discoverable, :indexable, :group, :created_at,
- :note, :url, :uri, :avatar, :avatar_static, :header, :header_static,
+ :note, :url, :uri, :avatar, :avatar_static, :avatar_description, :header, :header_static, :header_description,
:followers_count, :following_count, :statuses_count, :last_status_at, :hide_collections
has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested?
@@ -82,6 +82,10 @@ class REST::AccountSerializer < ActiveModel::Serializer
full_asset_url(object.unavailable? ? object.avatar.default_url : object.avatar_static_url)
end
+ def avatar_description
+ object.unavailable? ? '' : object.avatar_description
+ end
+
def header
full_asset_url(object.unavailable? ? object.header.default_url : object.header_original_url)
end
@@ -90,6 +94,10 @@ class REST::AccountSerializer < ActiveModel::Serializer
full_asset_url(object.unavailable? ? object.header.default_url : object.header_static_url)
end
+ def header_description
+ object.unavailable? ? '' : object.header_description
+ end
+
def created_at
object.created_at.midnight.as_json
end
diff --git a/app/serializers/rest/base_collection_serializer.rb b/app/serializers/rest/base_collection_serializer.rb
deleted file mode 100644
index be26aac6fe2..00000000000
--- a/app/serializers/rest/base_collection_serializer.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class REST::BaseCollectionSerializer < ActiveModel::Serializer
- attributes :id, :uri, :name, :description, :local, :sensitive,
- :discoverable, :item_count, :created_at, :updated_at
-
- belongs_to :tag, serializer: REST::StatusSerializer::TagSerializer
-
- def id
- object.id.to_s
- end
-end
diff --git a/app/serializers/rest/collection_item_serializer.rb b/app/serializers/rest/collection_item_serializer.rb
index d35a8fdef28..8628960403d 100644
--- a/app/serializers/rest/collection_item_serializer.rb
+++ b/app/serializers/rest/collection_item_serializer.rb
@@ -3,11 +3,15 @@
class REST::CollectionItemSerializer < ActiveModel::Serializer
delegate :accepted?, to: :object
- attributes :id, :position, :state
+ attributes :id, :state
- belongs_to :account, serializer: REST::AccountSerializer, if: :accepted?
+ attribute :account_id, if: :accepted?
def id
object.id.to_s
end
+
+ def account_id
+ object.account_id.to_s
+ end
end
diff --git a/app/serializers/rest/collection_serializer.rb b/app/serializers/rest/collection_serializer.rb
index ce2d8933c4e..9296a5cf4ad 100644
--- a/app/serializers/rest/collection_serializer.rb
+++ b/app/serializers/rest/collection_serializer.rb
@@ -1,11 +1,23 @@
# frozen_string_literal: true
-class REST::CollectionSerializer < REST::BaseCollectionSerializer
- belongs_to :account, serializer: REST::AccountSerializer
+class REST::CollectionSerializer < ActiveModel::Serializer
+ attributes :id, :uri, :name, :description, :language, :account_id,
+ :local, :sensitive, :discoverable, :item_count,
+ :created_at, :updated_at
+
+ belongs_to :tag, serializer: REST::StatusSerializer::TagSerializer
has_many :items, serializer: REST::CollectionItemSerializer
+ def id
+ object.id.to_s
+ end
+
def items
object.items_for(current_user&.account)
end
+
+ def account_id
+ object.account_id.to_s
+ end
end
diff --git a/app/serializers/rest/collection_with_accounts_serializer.rb b/app/serializers/rest/collection_with_accounts_serializer.rb
new file mode 100644
index 00000000000..5d05a32d687
--- /dev/null
+++ b/app/serializers/rest/collection_with_accounts_serializer.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class REST::CollectionWithAccountsSerializer < ActiveModel::Serializer
+ belongs_to :collection, serializer: REST::CollectionSerializer
+
+ has_many :accounts, serializer: REST::AccountSerializer
+
+ def collection
+ object
+ end
+
+ def accounts
+ [object.account] + object.collection_items.map(&:account)
+ end
+end
diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb
index 75d3acfea58..1900330475c 100644
--- a/app/serializers/rest/instance_serializer.rb
+++ b/app/serializers/rest/instance_serializer.rb
@@ -71,6 +71,9 @@ class REST::InstanceSerializer < ActiveModel::Serializer
accounts: {
max_featured_tags: FeaturedTag::LIMIT,
max_pinned_statuses: StatusPinValidator::PIN_LIMIT,
+ max_profile_fields: Account::DEFAULT_FIELDS_SIZE,
+ profile_field_name_limit: Account::Field::MAX_CHARACTERS_LOCAL,
+ profile_field_value_limit: Account::Field::MAX_CHARACTERS_LOCAL,
},
statuses: {
diff --git a/app/services/activitypub/fetch_remote_status_service.rb b/app/services/activitypub/fetch_remote_status_service.rb
index 0473bb5939f..e08f82f7d9a 100644
--- a/app/services/activitypub/fetch_remote_status_service.rb
+++ b/app/services/activitypub/fetch_remote_status_service.rb
@@ -92,7 +92,6 @@ class ActivityPub::FetchRemoteStatusService < BaseService
existing_status = Status.remote.find_by(uri: uri)
if existing_status&.distributable?
Rails.logger.debug { "FetchRemoteStatusService - Got 404 for orphaned status with URI #{uri}, deleting" }
- Tombstone.find_or_create_by(uri: uri, account: existing_status.account)
RemoveStatusService.new.call(existing_status, redraft: false)
end
end
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index f133fbc84ae..efdaa269747 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -6,6 +6,7 @@ class ActivityPub::ProcessAccountService < BaseService
include Redisable
include Lockable
+ MAX_PROFILE_FIELDS = 50
SUBDOMAINS_RATELIMIT = 10
DISCOVERIES_PER_REQUEST = 400
@@ -124,15 +125,15 @@ class ActivityPub::ProcessAccountService < BaseService
def set_immediate_attributes!
@account.featured_collection_url = valid_collection_uri(@json['featured'])
- @account.display_name = @json['name'] || ''
- @account.note = @json['summary'] || ''
+ @account.display_name = (@json['name'] || '')[0...(Account::DISPLAY_NAME_LENGTH_HARD_LIMIT)]
+ @account.note = (@json['summary'] || '')[0...(Account::NOTE_LENGTH_HARD_LIMIT)]
@account.locked = @json['manuallyApprovesFollowers'] || false
@account.fields = property_values || {}
- @account.also_known_as = as_array(@json['alsoKnownAs'] || []).map { |item| value_or_id(item) }
+ @account.also_known_as = as_array(@json['alsoKnownAs'] || []).take(Account::ALSO_KNOWN_AS_HARD_LIMIT).map { |item| value_or_id(item) }
@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) }
+ @account.attribution_domains = as_array(@json['attributionDomains'] || []).take(Account::ATTRIBUTION_DOMAINS_HARD_LIMIT).map { |item| value_or_id(item) }
end
def set_fetchable_key!
@@ -141,14 +142,18 @@ class ActivityPub::ProcessAccountService < BaseService
def set_fetchable_attributes!
begin
- @account.avatar_remote_url = image_url('icon') || '' unless skip_download?
+ avatar_url, avatar_description = image_url_and_description('icon')
+ @account.avatar_remote_url = avatar_url || '' unless skip_download?
@account.avatar = nil if @account.avatar_remote_url.blank?
+ @account.avatar_description = avatar_description || ''
rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
RedownloadAvatarWorker.perform_in(rand(30..600).seconds, @account.id)
end
begin
- @account.header_remote_url = image_url('image') || '' unless skip_download?
+ header_url, header_description = image_url_and_description('image')
+ @account.header_remote_url = header_url || '' unless skip_download?
@account.header = nil if @account.header_remote_url.blank?
+ @account.header_description = header_description || ''
rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
RedownloadHeaderWorker.perform_in(rand(30..600).seconds, @account.id)
end
@@ -213,7 +218,7 @@ class ActivityPub::ProcessAccountService < BaseService
end
end
- def image_url(key)
+ def image_url_and_description(key)
value = first_of_value(@json[key])
return if value.nil?
@@ -223,9 +228,21 @@ class ActivityPub::ProcessAccountService < BaseService
return if value.nil?
end
- value = first_of_value(value['url']) if value.is_a?(Hash) && value['type'] == 'Image'
- value = value['href'] if value.is_a?(Hash)
- value if value.is_a?(String)
+ if value.is_a?(Hash) && value['type'] == 'Image'
+ url = first_of_value(value['url'])
+ url = url['href'] if url.is_a?(Hash)
+ description = value['summary'].presence || value['name'].presence
+ description = description.strip[0...MediaAttachment::MAX_DESCRIPTION_LENGTH] if description.present?
+ else
+ url = value
+ end
+
+ url = url['href'] if url.is_a?(Hash)
+
+ url = nil unless url.is_a?(String)
+ description = nil unless description.is_a?(String)
+
+ [url, description]
end
def public_key
@@ -253,7 +270,10 @@ class ActivityPub::ProcessAccountService < BaseService
def property_values
return unless @json['attachment'].is_a?(Array)
- as_array(@json['attachment']).select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') }
+ as_array(@json['attachment'])
+ .select { |attachment| attachment['type'] == 'PropertyValue' }
+ .take(MAX_PROFILE_FIELDS)
+ .map { |attachment| attachment.slice('name', 'value') }
end
def mismatching_origin?(url)
diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb
index 1cdf0b48302..166db90e0b3 100644
--- a/app/services/activitypub/process_status_update_service.rb
+++ b/app/services/activitypub/process_status_update_service.rb
@@ -204,7 +204,11 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
def update_tags!
previous_tags = @status.tags.to_a
- current_tags = @status.tags = Tag.find_or_create_by_names(@raw_tags)
+ current_tags = @status.tags = @raw_tags.flat_map do |tag|
+ Tag.find_or_create_by_names([tag])
+ rescue ActiveRecord::RecordInvalid
+ []
+ end
return unless @status.distributable?
diff --git a/app/services/create_collection_service.rb b/app/services/create_collection_service.rb
index 10843cb9677..008d4b5c093 100644
--- a/app/services/create_collection_service.rb
+++ b/app/services/create_collection_service.rb
@@ -8,11 +8,18 @@ class CreateCollectionService
build_items
@collection.save!
+
+ distribute_add_activity if Mastodon::Feature.collections_federation_enabled?
+
@collection
end
private
+ def distribute_add_activity
+ ActivityPub::AccountRawDistributionWorker.perform_async(activity_json, @account.id)
+ end
+
def build_items
return if @accounts_to_add.empty?
@@ -23,4 +30,8 @@ class CreateCollectionService
@collection.collection_items.build(account: account_to_add)
end
end
+
+ def activity_json
+ ActiveModelSerializers::SerializableResource.new(@collection, serializer: ActivityPub::AddSerializer, adapter: ActivityPub::Adapter).to_json
+ end
end
diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb
index 64769230b7c..727a6a63c4b 100644
--- a/app/services/fan_out_on_write_service.rb
+++ b/app/services/fan_out_on_write_service.rb
@@ -14,6 +14,8 @@ class FanOutOnWriteService < BaseService
@account = status.account
@options = options
+ return if @status.proper.account.suspended?
+
check_race_condition!
warm_payload_cache!
@@ -77,9 +79,11 @@ class FanOutOnWriteService < BaseService
end
def notify_mentioned_accounts!
- @status.active_mentions.where.not(id: @options[:silenced_account_ids] || []).joins(:account).merge(Account.local).select(:id, :account_id).reorder(nil).find_in_batches do |mentions|
+ @status.active_mentions.joins(:account).merge(Account.local).select(:id, :account_id).reorder(nil).find_in_batches do |mentions|
LocalNotificationWorker.push_bulk(mentions) do |mention|
- [mention.account_id, mention.id, 'Mention', 'mention']
+ options = { 'silenced' => true } if @options[:silenced_account_ids]&.include?(mention.account_id)
+
+ [mention.account_id, mention.id, 'Mention', 'mention', options].compact
end
next unless update?
diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb
index 666eccb9ce5..514c838d648 100644
--- a/app/services/fetch_resource_service.rb
+++ b/app/services/fetch_resource_service.rb
@@ -58,13 +58,7 @@ class FetchResourceService < BaseService
[@url, { prefetched_body: body }]
elsif !terminal
- link_header = response['Link'] && parse_link_header(response)
-
- if link_header&.find_link(%w(rel alternate))
- process_link_headers(link_header)
- elsif response.mime_type == 'text/html'
- process_html(response)
- end
+ process_link_headers(response) || process_html(response)
end
end
@@ -73,13 +67,18 @@ class FetchResourceService < BaseService
end
def process_html(response)
+ return unless response.mime_type == 'text/html'
+
page = Nokogiri::HTML5(response.body_with_limit)
json_link = page.xpath('//link[nokogiri:link_rel_include(@rel, "alternate")]', NokogiriHandler).find { |link| ACTIVITY_STREAM_LINK_TYPES.include?(link['type']) }
process(json_link['href'], terminal: true) unless json_link.nil?
end
- def process_link_headers(link_header)
+ def process_link_headers(response)
+ link_header = response['Link'] && parse_link_header(response)
+ return if link_header.nil?
+
json_link = link_header.find_link(%w(rel alternate), %w(type application/activity+json)) || link_header.find_link(%w(rel alternate), ['type', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'])
process(json_link.href, terminal: true) unless json_link.nil?
diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb
index 8d0986adcb9..2f009d5a23b 100644
--- a/app/services/notify_service.rb
+++ b/app/services/notify_service.rb
@@ -30,12 +30,13 @@ class NotifyService < BaseService
annual_report
).freeze
- def initialize(notification)
+ def initialize(notification, **options)
@recipient = notification.account
@sender = notification.from_account
@notification = notification
@policy = NotificationPolicy.find_or_initialize_by(account: @recipient)
@from_staff = @sender.local? && @sender.user.present? && @sender.user_role&.bypass_block?(@recipient.user_role)
+ @options = options
end
private
@@ -83,7 +84,7 @@ class NotifyService < BaseService
# This queries private mentions from the recipient to the sender up in the thread.
# This allows up to 100 messages that do not match in the thread, allowing conversations
# involving multiple people.
- Status.count_by_sql([<<-SQL.squish, id: @notification.target_status.in_reply_to_id, recipient_id: @recipient.id, sender_id: @sender.id, depth_limit: 100])
+ Status.count_by_sql([<<~SQL.squish, id: @notification.target_status.in_reply_to_id, recipient_id: @recipient.id, sender_id: @sender.id, depth_limit: 100])
WITH RECURSIVE ancestors(id, in_reply_to_id, mention_id, path, depth) AS (
SELECT s.id, s.in_reply_to_id, m.id, ARRAY[s.id], 0
FROM statuses s
@@ -164,7 +165,7 @@ class NotifyService < BaseService
end
def blocked_by_limited_accounts_policy?
- @policy.drop_limited_accounts? && @sender.silenced? && not_following?
+ @policy.drop_limited_accounts? && (@options[:silenced] || @sender.silenced?) && not_following?
end
end
@@ -200,13 +201,14 @@ class NotifyService < BaseService
end
def filtered_by_limited_accounts_policy?
- @policy.filter_limited_accounts? && @sender.silenced? && not_following?
+ @policy.filter_limited_accounts? && (@options[:silenced] || @sender.silenced?) && not_following?
end
end
- def call(recipient, type, activity)
+ def call(recipient, type, activity, **options)
return if recipient.user.nil?
+ @options = options
@recipient = recipient
@activity = activity
@notification = Notification.new(account: @recipient, type: type, activity: @activity)
@@ -236,11 +238,11 @@ class NotifyService < BaseService
private
def drop?
- DropCondition.new(@notification).drop?
+ DropCondition.new(@notification, silenced: @options[:silenced]).drop?
end
def filter?
- FilterCondition.new(@notification).filter?
+ FilterCondition.new(@notification, silenced: @options[:silenced]).filter?
end
def update_notification_request!
diff --git a/app/views/admin/announcements/edit.html.haml b/app/views/admin/announcements/edit.html.haml
index 8cec7d36c2d..5f2022be680 100644
--- a/app/views/admin/announcements/edit.html.haml
+++ b/app/views/admin/announcements/edit.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('.title')
-= simple_form_for @announcement, url: admin_announcement_path(@announcement), html: { novalidate: false } do |form|
+= simple_form_for [:admin, @announcement], html: { novalidate: false } do |form|
= render 'shared/error_messages', object: @announcement
= render form
diff --git a/app/views/admin/announcements/new.html.haml b/app/views/admin/announcements/new.html.haml
index 266ca65e80e..e7adb98f2f5 100644
--- a/app/views/admin/announcements/new.html.haml
+++ b/app/views/admin/announcements/new.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('.title')
-= simple_form_for @announcement, url: admin_announcements_path, html: { novalidate: false } do |form|
+= simple_form_for [:admin, @announcement], html: { novalidate: false } do |form|
= render 'shared/error_messages', object: @announcement
= render form
diff --git a/app/views/admin/custom_emojis/new.html.haml b/app/views/admin/custom_emojis/new.html.haml
index e59ae02b3bc..acf2231b8ec 100644
--- a/app/views/admin/custom_emojis/new.html.haml
+++ b/app/views/admin/custom_emojis/new.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('.title')
-= simple_form_for @custom_emoji, url: admin_custom_emojis_path do |f|
+= simple_form_for [:admin, @custom_emoji] do |f|
= render 'shared/error_messages', object: @custom_emoji
.fields-group
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index c3b7933293f..d2ff6e4a005 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -6,11 +6,7 @@
- unless @system_checks.empty?
.flash-message-stack
- - @system_checks.each do |message|
- .flash-message{ class: message.critical ? 'alert' : 'warning' }
- = t("admin.system_checks.#{message.key}.message_html", value: message.value ? content_tag(:strong, message.value) : nil)
- - if message.action
- = link_to t("admin.system_checks.#{message.key}.action"), message.action
+ = render collection: @system_checks, partial: 'admin/system_check/messages/message'
.dashboard
.dashboard__item
diff --git a/app/views/admin/domain_allows/new.html.haml b/app/views/admin/domain_allows/new.html.haml
index 85ab7e46441..d8cefee997d 100644
--- a/app/views/admin/domain_allows/new.html.haml
+++ b/app/views/admin/domain_allows/new.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('admin.domain_allows.add_new')
-= simple_form_for @domain_allow, url: admin_domain_allows_path do |f|
+= simple_form_for [:admin, @domain_allow] do |f|
= render 'shared/error_messages', object: @domain_allow
.fields-group
diff --git a/app/views/admin/domain_blocks/edit.html.haml b/app/views/admin/domain_blocks/edit.html.haml
index cd52953a40c..b47e0fcdcca 100644
--- a/app/views/admin/domain_blocks/edit.html.haml
+++ b/app/views/admin/domain_blocks/edit.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('admin.domain_blocks.edit')
-= simple_form_for @domain_block, url: admin_domain_block_path(@domain_block) do |form|
+= simple_form_for [:admin, @domain_block] do |form|
= render 'shared/error_messages', object: @domain_block
= render form
diff --git a/app/views/admin/domain_blocks/new.html.haml b/app/views/admin/domain_blocks/new.html.haml
index 78bcfcba8e7..5f80c9b4f6f 100644
--- a/app/views/admin/domain_blocks/new.html.haml
+++ b/app/views/admin/domain_blocks/new.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('.title')
-= simple_form_for @domain_block, url: admin_domain_blocks_path do |form|
+= simple_form_for [:admin, @domain_block] do |form|
= render 'shared/error_messages', object: @domain_block
= render form
diff --git a/app/views/admin/email_domain_blocks/new.html.haml b/app/views/admin/email_domain_blocks/new.html.haml
index 4db8fbe5e54..6508ef1d3b8 100644
--- a/app/views/admin/email_domain_blocks/new.html.haml
+++ b/app/views/admin/email_domain_blocks/new.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('.title')
-= simple_form_for @email_domain_block, url: admin_email_domain_blocks_path do |f|
+= simple_form_for [:admin, @email_domain_block] do |f|
= render 'shared/error_messages', object: @email_domain_block
.fields-group
diff --git a/app/views/admin/invites/index.html.haml b/app/views/admin/invites/index.html.haml
index 964deaba8f3..1507b816c97 100644
--- a/app/views/admin/invites/index.html.haml
+++ b/app/views/admin/invites/index.html.haml
@@ -14,7 +14,7 @@
- if policy(:invite).create?
%p= t('invites.prompt')
- = simple_form_for(@invite, url: admin_invites_path) do |form|
+ = simple_form_for [:admin, @invite] do |form|
= render partial: 'invites/form', object: form
%hr.spacer/
diff --git a/app/views/admin/ip_blocks/new.html.haml b/app/views/admin/ip_blocks/new.html.haml
index 81493012c60..acf632e476a 100644
--- a/app/views/admin/ip_blocks/new.html.haml
+++ b/app/views/admin/ip_blocks/new.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('.title')
-= simple_form_for @ip_block, url: admin_ip_blocks_path do |f|
+= simple_form_for [:admin, @ip_block] do |f|
= render 'shared/error_messages', object: @ip_block
.fields-group
diff --git a/app/views/admin/relays/new.html.haml b/app/views/admin/relays/new.html.haml
index 126794acfe5..4decb467b8e 100644
--- a/app/views/admin/relays/new.html.haml
+++ b/app/views/admin/relays/new.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('admin.relays.add_new')
-= simple_form_for @relay, url: admin_relays_path do |f|
+= simple_form_for [:admin, @relay] do |f|
= render 'shared/error_messages', object: @relay
.field-group
diff --git a/app/views/admin/reports/_comment.html.haml b/app/views/admin/reports/_comment.html.haml
index 2b3af15c498..9ccd05eb24b 100644
--- a/app/views/admin/reports/_comment.html.haml
+++ b/app/views/admin/reports/_comment.html.haml
@@ -1,12 +1,12 @@
- if report.account.instance_actor?
%p= t('admin.reports.comment_description_html', name: content_tag(:strong, site_hostname, class: 'username'))
-- elsif report.account.local?
+- elsif report.local?
%p= t('admin.reports.comment_description_html', name: content_tag(:strong, report.account.username, class: 'username'))
- else
%p= t('admin.reports.comment_description_html', name: t('admin.reports.remote_user_placeholder', instance: report.account.domain))
.report-notes
.report-notes__item
- - if report.account.local? && !report.account.instance_actor?
+ - if report.local? && !report.account.instance_actor?
= image_tag report.account.avatar.url, class: 'report-notes__item__avatar'
- else
= image_tag(full_asset_url('avatars/original/missing.png', skip_pipeline: true), class: 'report-notes__item__avatar')
@@ -14,7 +14,7 @@
%span.username
- if report.account.instance_actor?
= site_hostname
- - elsif report.account.local?
+ - elsif report.local?
= link_to report.account.username, admin_account_path(report.account_id)
- else
= link_to report.account.domain, admin_instance_path(report.account.domain)
diff --git a/app/views/admin/reports/_header_details.html.haml b/app/views/admin/reports/_header_details.html.haml
index cf81670845f..91242f0eaf6 100644
--- a/app/views/admin/reports/_header_details.html.haml
+++ b/app/views/admin/reports/_header_details.html.haml
@@ -10,7 +10,7 @@
.report-header__details__item__content
- if report.account.instance_actor?
= site_hostname
- - elsif report.account.local?
+ - elsif report.local?
= admin_account_link_to report.account
- else
= report.account.domain
@@ -28,7 +28,7 @@
= t('admin.reports.resolved')
- else
= t('admin.reports.unresolved')
- - if report.account.local? && !report.target_account.local?
+ - if report.local? && !report.target_account.local?
.report-header__details__item
.report-header__details__item__header
%strong= t('admin.reports.forwarded')
diff --git a/app/views/admin/reports/index.html.haml b/app/views/admin/reports/index.html.haml
index e08218a05d9..b910e1aab52 100644
--- a/app/views/admin/reports/index.html.haml
+++ b/app/views/admin/reports/index.html.haml
@@ -51,7 +51,7 @@
.report-card__summary__item__reported-by
- if report.account.instance_actor?
= site_hostname
- - elsif report.account.local?
+ - elsif report.local?
= admin_account_link_to report.account
- else
= report.account.domain
diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml
index 86f87f197eb..af92b05768e 100644
--- a/app/views/admin/reports/show.html.haml
+++ b/app/views/admin/reports/show.html.haml
@@ -7,7 +7,7 @@
- else
= link_to t('admin.reports.mark_as_unresolved'), reopen_admin_report_path(@report), method: :post, class: 'button'
-- unless @report.account.local? || @report.target_account.local?
+- unless @report.local? || @report.target_account.local?
.flash-message= t('admin.reports.forwarded_replies_explanation')
.report-header
diff --git a/app/views/admin/rules/edit.html.haml b/app/views/admin/rules/edit.html.haml
index b64a27d7512..944480fa5a8 100644
--- a/app/views/admin/rules/edit.html.haml
+++ b/app/views/admin/rules/edit.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('admin.rules.edit')
-= simple_form_for @rule, url: admin_rule_path(@rule) do |form|
+= simple_form_for [:admin, @rule] do |form|
= render 'shared/error_messages', object: @rule
= render form
diff --git a/app/views/admin/rules/new.html.haml b/app/views/admin/rules/new.html.haml
index bc93c7df55c..6c703ef8ff0 100644
--- a/app/views/admin/rules/new.html.haml
+++ b/app/views/admin/rules/new.html.haml
@@ -5,7 +5,7 @@
%hr.spacer/
-= simple_form_for @rule, url: admin_rules_path do |form|
+= simple_form_for [:admin, @rule] do |form|
= render 'shared/error_messages', object: @rule
= render form
diff --git a/app/views/admin/system_check/messages/_message.html.haml b/app/views/admin/system_check/messages/_message.html.haml
new file mode 100644
index 00000000000..650c2be7381
--- /dev/null
+++ b/app/views/admin/system_check/messages/_message.html.haml
@@ -0,0 +1,4 @@
+.flash-message{ class: message.critical ? 'alert' : 'warning' }
+ = t("admin.system_checks.#{message.key}.message_html", value: message.value ? tag.strong(message.value) : nil)
+ - if message.action
+ = link_to t("admin.system_checks.#{message.key}.action"), message.action
diff --git a/app/views/admin/username_blocks/edit.html.haml b/app/views/admin/username_blocks/edit.html.haml
index eee0fedef07..c869bb53df4 100644
--- a/app/views/admin/username_blocks/edit.html.haml
+++ b/app/views/admin/username_blocks/edit.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('admin.username_blocks.edit.title')
-= simple_form_for @username_block, url: admin_username_block_path(@username_block) do |form|
+= simple_form_for [:admin, @username_block] do |form|
= render 'shared/error_messages', object: @username_block
= render form
diff --git a/app/views/admin/username_blocks/new.html.haml b/app/views/admin/username_blocks/new.html.haml
index 0f5bd27952b..a63aad5f345 100644
--- a/app/views/admin/username_blocks/new.html.haml
+++ b/app/views/admin/username_blocks/new.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('admin.username_blocks.new.title')
-= simple_form_for @username_block, url: admin_username_blocks_path do |form|
+= simple_form_for [:admin, @username_block] do |form|
= render 'shared/error_messages', object: @username_block
= render form
diff --git a/app/views/admin/webhooks/edit.html.haml b/app/views/admin/webhooks/edit.html.haml
index abc9bdfabc4..7e7658f7264 100644
--- a/app/views/admin/webhooks/edit.html.haml
+++ b/app/views/admin/webhooks/edit.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('admin.webhooks.edit')
-= simple_form_for @webhook, url: admin_webhook_path(@webhook) do |form|
+= simple_form_for [:admin, @webhook] do |form|
= render form
.actions
= form.button :button, t('generic.save_changes'), type: :submit
diff --git a/app/views/admin/webhooks/new.html.haml b/app/views/admin/webhooks/new.html.haml
index 50fcdc2be7f..be589111db1 100644
--- a/app/views/admin/webhooks/new.html.haml
+++ b/app/views/admin/webhooks/new.html.haml
@@ -1,7 +1,7 @@
- content_for :page_title do
= t('admin.webhooks.new')
-= simple_form_for @webhook, url: admin_webhooks_path do |form|
+= simple_form_for [:admin, @webhook] do |form|
= render form
.actions
= form.button :button, t('admin.webhooks.add_new'), type: :submit
diff --git a/app/views/admin_mailer/new_report.text.erb b/app/views/admin_mailer/new_report.text.erb
index 8482225abe7..1b7355ada8f 100644
--- a/app/views/admin_mailer/new_report.text.erb
+++ b/app/views/admin_mailer/new_report.text.erb
@@ -1,3 +1,3 @@
-<%= raw(@report.account.local? ? t('admin_mailer.new_report.body', target: @report.target_account.pretty_acct, reporter: @report.account.pretty_acct) : t('admin_mailer.new_report.body_remote', target: @report.target_account.acct, domain: @report.account.domain)) %>
+<%= raw(@report.local? ? t('admin_mailer.new_report.body', target: @report.target_account.pretty_acct, reporter: @report.account.pretty_acct) : t('admin_mailer.new_report.body_remote', target: @report.target_account.acct, domain: @report.account.domain)) %>
<%= raw t('application_mailer.view')%> <%= admin_report_url(@report) %>
diff --git a/app/views/auth/registrations/rules.html.haml b/app/views/auth/registrations/rules.html.haml
index a5a96c57378..1e3d934c375 100644
--- a/app/views/auth/registrations/rules.html.haml
+++ b/app/views/auth/registrations/rules.html.haml
@@ -17,12 +17,7 @@
%p.lead= t('auth.rules.preamble', domain: site_hostname)
%ol.rules-list
- - @rules.each do |rule|
- - translation = rule.translation_for(I18n.locale.to_s)
- %li
- %button{ type: 'button', aria: { expanded: 'false' } }
- .rules-list__text= translation.text
- .rules-list__hint= translation.hint
+ = render collection: @rule_translations, partial: 'auth/rule_translations/rule_translation'
.stacked-actions
- accept_path = @invite_code.present? ? public_invite_url(invite_code: @invite_code, accept: @accept_token) : new_user_registration_path(accept: @accept_token)
diff --git a/app/views/auth/rule_translations/_rule_translation.html.haml b/app/views/auth/rule_translations/_rule_translation.html.haml
new file mode 100644
index 00000000000..32b9cc28af1
--- /dev/null
+++ b/app/views/auth/rule_translations/_rule_translation.html.haml
@@ -0,0 +1,4 @@
+%li
+ %button{ type: 'button', aria: { expanded: 'false' } }
+ .rules-list__text= rule_translation.text
+ .rules-list__hint= rule_translation.hint
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index dccb6035cae..15f1e961ed6 100755
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -1,5 +1,5 @@
!!! 5
-%html{ lang: I18n.locale, class: html_classes, 'data-user-theme': current_theme.parameterize, 'data-contrast': contrast.parameterize, 'data-mode': color_scheme.parameterize }
+%html{ html_attributes }
%head
%meta{ charset: 'utf-8' }/
%meta{ name: 'viewport', content: 'width=device-width, initial-scale=1, viewport-fit=cover' }/
@@ -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) }/
= javascript_inline_tag 'theme-selection.js'
- = theme_color_tags current_theme
+ = theme_color_tags color_scheme
%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 b802854ae72..d815b59140e 100644
--- a/app/views/layouts/embedded.html.haml
+++ b/app/views/layouts/embedded.html.haml
@@ -1,5 +1,5 @@
!!! 5
-%html{ lang: I18n.locale }
+%html{ lang: I18n.locale, 'data-contrast': 'auto', 'data-color-scheme': 'light' }
%head
%meta{ charset: 'utf-8' }/
%meta{ name: 'robots', content: 'noindex' }/
@@ -11,10 +11,11 @@
- if storage_host?
%link{ rel: 'dns-prefetch', href: storage_host }/
+ = javascript_inline_tag 'theme-selection.js'
= vite_client_tag
= vite_react_refresh_tag
= vite_polyfills_tag
- = theme_style_tags 'mastodon-light'
+ = theme_style_tags 'system'
= vite_preload_file_tag "mastodon/locales/#{I18n.locale}.json"
= render_initial_state
= vite_typescript_tag 'embed.tsx', integrity: true, crossorigin: 'anonymous'
diff --git a/app/views/layouts/error.html.haml b/app/views/layouts/error.html.haml
index f85a671a531..03cb93dba7b 100644
--- a/app/views/layouts/error.html.haml
+++ b/app/views/layouts/error.html.haml
@@ -1,5 +1,5 @@
!!!
-%html{ lang: I18n.locale }
+%html{ lang: I18n.locale, 'data-contrast': 'auto', 'data-color-scheme': 'auto' }
%head
%meta{ 'content' => 'text/html; charset=UTF-8', 'http-equiv' => 'Content-Type' }/
%meta{ charset: 'utf-8' }/
@@ -8,6 +8,7 @@
= vite_client_tag
= vite_react_refresh_tag
= vite_polyfills_tag
+ = vite_typescript_tag 'theme-selection.ts', crossorigin: 'anonymous', blocking: 'render'
= theme_style_tags Setting.default_settings['theme']
= vite_typescript_tag 'error.ts', crossorigin: 'anonymous'
%body.error
diff --git a/app/views/wrapstodon/show.html.haml b/app/views/wrapstodon/show.html.haml
index ed1e64d4665..8a20001ad55 100644
--- a/app/views/wrapstodon/show.html.haml
+++ b/app/views/wrapstodon/show.html.haml
@@ -13,7 +13,7 @@
= vite_typescript_tag 'wrapstodon.tsx', crossorigin: 'anonymous'
-- content_for :html_classes, 'theme-dark'
+- content_for :force_color_scheme, 'dark'
#wrapstodon
= render_wrapstodon_share_data @generated_annual_report
diff --git a/app/workers/admin/account_deletion_worker.rb b/app/workers/admin/account_deletion_worker.rb
index 5dfdfb6e73c..cd0d9c1f5e5 100644
--- a/app/workers/admin/account_deletion_worker.rb
+++ b/app/workers/admin/account_deletion_worker.rb
@@ -6,7 +6,10 @@ class Admin::AccountDeletionWorker
sidekiq_options queue: 'pull', lock: :until_executed, lock_ttl: 1.week.to_i
def perform(account_id)
- DeleteAccountService.new.call(Account.find(account_id), reserve_username: true, reserve_email: true)
+ delete_account = Account.find(account_id)
+ return unless delete_account.unavailable?
+
+ DeleteAccountService.new.call(delete_account, reserve_username: true, reserve_email: true)
rescue ActiveRecord::RecordNotFound
true
end
diff --git a/app/workers/feed_insert_worker.rb b/app/workers/feed_insert_worker.rb
index e883daf3ea8..b0c9c9181f7 100644
--- a/app/workers/feed_insert_worker.rb
+++ b/app/workers/feed_insert_worker.rb
@@ -53,7 +53,7 @@ class FeedInsertWorker
def notify?(filter_result)
return false if @type != :home || @status.reblog? || (@status.reply? && @status.in_reply_to_account_id != @status.account_id) ||
- filter_result == :filter
+ update? || filter_result == :filter
Follow.find_by(account: @follower, target_account: @status.account)&.notify?
end
diff --git a/app/workers/local_notification_worker.rb b/app/workers/local_notification_worker.rb
index e76572984df..7e9bd0c92b7 100644
--- a/app/workers/local_notification_worker.rb
+++ b/app/workers/local_notification_worker.rb
@@ -3,14 +3,9 @@
class LocalNotificationWorker
include Sidekiq::Worker
- def perform(receiver_account_id, activity_id = nil, activity_class_name = nil, type = nil)
- if activity_id.nil? && activity_class_name.nil?
- activity = Mention.find(receiver_account_id)
- receiver = activity.account
- else
- receiver = Account.find(receiver_account_id)
- activity = activity_class_name.constantize.find(activity_id)
- end
+ def perform(receiver_account_id, activity_id, activity_class_name, type = nil, options = {})
+ receiver = Account.find(receiver_account_id)
+ activity = activity_class_name.constantize.find(activity_id)
# For most notification types, only one notification should exist, and the older one is
# preferred. For updates, such as when a status is edited, the new notification
@@ -23,7 +18,7 @@ class LocalNotificationWorker
return
end
- NotifyService.new.call(receiver, type || activity_class_name.underscore, activity)
+ NotifyService.new.call(receiver, type || activity_class_name.underscore, activity, **options.symbolize_keys)
rescue ActiveRecord::RecordNotFound
true
end
diff --git a/app/workers/move_worker.rb b/app/workers/move_worker.rb
index 1a5745a86ae..81274a79360 100644
--- a/app/workers/move_worker.rb
+++ b/app/workers/move_worker.rb
@@ -45,10 +45,9 @@ class MoveWorker
end
# Then handle accounts that follow both the old and new account
- @source_account.passive_relationships
- .where(account: Account.local)
- .where(account: @target_account.followers.local)
- .in_batches do |follows|
+ source_local_followers
+ .where(account: @target_account.followers.local)
+ .in_batches do |follows|
ListAccount.where(follow: follows).includes(:list).find_each do |list_account|
list_account.list.accounts << @target_account
rescue ActiveRecord::RecordInvalid
@@ -57,18 +56,33 @@ class MoveWorker
end
# Finally, handle the common case of accounts not following the new account
- @source_account.passive_relationships
- .where(account: Account.local)
- .where.not(account: @target_account.followers.local)
- .where.not(account_id: @target_account.id)
- .in_batches do |follows|
+ source_local_followers
+ .where.not(account: @target_account.followers.local)
+ .where.not(account_id: @target_account.id)
+ .in_batches do |follows|
ListAccount.where(follow: follows).in_batches.update_all(account_id: @target_account.id)
num_moved += follows.update_all(target_account_id: @target_account.id)
+
+ # Clear any relationship cache, since callbacks are not called
+ Rails.cache.delete_multi(follows.flat_map do |follow|
+ [
+ ['relationship', follow.account_id, follow.target_account_id],
+ ['relationship', follow.target_account_id, follow.account_id],
+ ['relationship', follow.account_id, @target_account.id],
+ ['relationship', @target_account.id, follow.account_id],
+ ]
+ end)
end
num_moved
end
+ def source_local_followers
+ @source_account
+ .passive_relationships
+ .where(account: Account.local)
+ end
+
def queue_follow_unfollows!
bypass_locked = @target_account.local?
@@ -80,17 +94,17 @@ class MoveWorker
end
def copy_account_notes!
- AccountNote.where(target_account: @source_account).find_each do |note|
+ @source_account.targeted_account_notes.find_each do |note|
text = I18n.with_locale(note.account.user_locale.presence || I18n.default_locale) do
I18n.t('move_handler.copy_account_note_text', acct: @source_account.acct)
end
- new_note = AccountNote.find_by(account: note.account, target_account: @target_account)
+ new_note = @target_account.targeted_account_notes.find_by(account: note.account)
if new_note.nil?
begin
- AccountNote.create!(account: note.account, target_account: @target_account, comment: [text, note.comment].join("\n"))
+ @target_account.targeted_account_notes.create!(account: note.account, comment: [text, note.comment].join("\n"))
rescue ActiveRecord::RecordInvalid
- AccountNote.create!(account: note.account, target_account: @target_account, comment: note.comment)
+ @target_account.targeted_account_notes.create!(account: note.account, comment: note.comment)
end
else
new_note.update!(comment: [text, note.comment, "\n", new_note.comment].join("\n"))
@@ -125,7 +139,7 @@ class MoveWorker
end
def add_account_note_if_needed!(account, id)
- return if AccountNote.exists?(account: account, target_account: @target_account)
+ return if @target_account.targeted_account_notes.exists?(account:)
text = I18n.with_locale(account.user_locale.presence || I18n.default_locale) do
I18n.t(id, acct: @source_account.acct)
diff --git a/config/application.rb b/config/application.rb
index 90cfe47428f..4e58bd9f6c2 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -94,13 +94,7 @@ module Mastodon
require 'mastodon/redis_configuration'
::REDIS_CONFIGURATION = Mastodon::RedisConfiguration.new
- config.x.use_vips = ENV['MASTODON_USE_LIBVIPS'] != 'false'
-
- if config.x.use_vips
- require_relative '../lib/paperclip/vips_lazy_thumbnail'
- else
- require_relative '../lib/paperclip/lazy_thumbnail'
- end
+ require_relative '../lib/paperclip/vips_lazy_thumbnail'
end
config.x.cache_buster = config_for(:cache_buster)
diff --git a/config/imagemagick/policy.xml b/config/imagemagick/policy.xml
deleted file mode 100644
index e2aa202f274..00000000000
--- a/config/imagemagick/policy.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/config/initializers/deprecations.rb b/config/initializers/deprecations.rb
index 520707e59ff..2c1057e5058 100644
--- a/config/initializers/deprecations.rb
+++ b/config/initializers/deprecations.rb
@@ -17,12 +17,6 @@ if ENV['REDIS_NAMESPACE']
abort message # rubocop:disable Rails/Exit
end
-if ENV['MASTODON_USE_LIBVIPS'] == 'false'
- warn <<~MESSAGE
- WARNING: Mastodon support for ImageMagick is deprecated and will be removed in future versions. Please consider using libvips instead.
- MESSAGE
-end
-
if ENV.key?('WHITELIST_MODE')
warn(<<~MESSAGE.squish)
WARNING: The environment variable WHITELIST_MODE has been replaced with
diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb
index b444c5611b0..18d35a27f18 100644
--- a/config/initializers/paperclip.rb
+++ b/config/initializers/paperclip.rb
@@ -182,10 +182,3 @@ unless defined?(Seahorse)
end
end
end
-
-# Set our ImageMagick security policy, but allow admins to override it
-ENV['MAGICK_CONFIGURE_PATH'] = begin
- imagemagick_config_paths = ENV.fetch('MAGICK_CONFIGURE_PATH', '').split(File::PATH_SEPARATOR)
- imagemagick_config_paths << Rails.root.join('config', 'imagemagick').expand_path.to_s
- imagemagick_config_paths.join(File::PATH_SEPARATOR)
-end
diff --git a/config/initializers/vips.rb b/config/initializers/vips.rb
index 09210d60ebe..cd8d2410b92 100644
--- a/config/initializers/vips.rb
+++ b/config/initializers/vips.rb
@@ -1,35 +1,33 @@
# frozen_string_literal: true
-if Rails.configuration.x.use_vips
- ENV['VIPS_BLOCK_UNTRUSTED'] = 'true'
+ENV['VIPS_BLOCK_UNTRUSTED'] = 'true'
- require 'vips'
+require 'vips'
- unless Vips.at_least_libvips?(8, 13)
- abort <<~ERROR.squish # rubocop:disable Rails/Exit
- Incompatible libvips version (#{Vips.version_string}), please install libvips >= 8.13
- ERROR
- end
-
- Vips.block('VipsForeign', true)
-
- %w(
- VipsForeignLoadNsgif
- VipsForeignLoadJpeg
- VipsForeignLoadPng
- VipsForeignLoadWebp
- VipsForeignLoadHeif
- VipsForeignSavePng
- VipsForeignSaveSpng
- VipsForeignSaveJpeg
- VipsForeignSaveWebp
- ).each do |operation|
- Vips.block(operation, false)
- end
-
- Vips.block_untrusted(true)
+unless Vips.at_least_libvips?(8, 13)
+ abort <<~ERROR.squish # rubocop:disable Rails/Exit
+ Incompatible libvips version (#{Vips.version_string}), please install libvips >= 8.13
+ ERROR
end
+Vips.block('VipsForeign', true)
+
+%w(
+ VipsForeignLoadNsgif
+ VipsForeignLoadJpeg
+ VipsForeignLoadPng
+ VipsForeignLoadWebp
+ VipsForeignLoadHeif
+ VipsForeignSavePng
+ VipsForeignSaveSpng
+ VipsForeignSaveJpeg
+ VipsForeignSaveWebp
+).each do |operation|
+ Vips.block(operation, false)
+end
+
+Vips.block_untrusted(true)
+
# In some places of the code, we rescue this exception, but we don't always
# load libvips, so it may be an undefined constant:
unless defined?(Vips)
diff --git a/config/locales/activerecord.gd.yml b/config/locales/activerecord.gd.yml
index 6b068d04dc6..572fcc83df5 100644
--- a/config/locales/activerecord.gd.yml
+++ b/config/locales/activerecord.gd.yml
@@ -32,6 +32,12 @@ gd:
attributes:
url:
invalid: "– chan eil seo ’na URL dligheach"
+ collection:
+ attributes:
+ collection_items:
+ too_many: "– tha cus dhiubh ann, chan eil còrr is %{count} ceadaichte"
+ tag:
+ unusable: "– chan fhaodar seo a chleachdadh"
doorkeeper/application:
attributes:
website:
diff --git a/config/locales/activerecord.nan.yml b/config/locales/activerecord.nan-TW.yml
similarity index 98%
rename from config/locales/activerecord.nan.yml
rename to config/locales/activerecord.nan-TW.yml
index 60f5d107176..3096d7880bb 100644
--- a/config/locales/activerecord.nan.yml
+++ b/config/locales/activerecord.nan-TW.yml
@@ -1,5 +1,5 @@
---
-nan:
+nan-TW:
activerecord:
attributes:
poll:
diff --git a/config/locales/activerecord.sl.yml b/config/locales/activerecord.sl.yml
index e4c4fe598f9..cecd0444d72 100644
--- a/config/locales/activerecord.sl.yml
+++ b/config/locales/activerecord.sl.yml
@@ -32,6 +32,12 @@ sl:
attributes:
url:
invalid: ni veljaven URL
+ collection:
+ attributes:
+ collection_items:
+ too_many: je preveč, dovoljenih je največ %{count}
+ tag:
+ unusable: ni možno uporabiti
doorkeeper/application:
attributes:
website:
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index 0cbbb08f83e..6adcf1871c7 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -2162,6 +2162,7 @@ ca:
error: Hi ha hagut un problema al esborrar la teva clau de seguretat. Tornau-ho a provar.
success: La teva clau de seguretat s'ha esborrat correctament.
invalid_credential: Clau de seguretat invàlida
+ nickname: Sobrenom
nickname_hint: Introdueix el sobrenom de la teva clau de seguretat nova
not_enabled: Encara no has activat WebAuthn
not_supported: Aquest navegador no suporta claus de seguretat
diff --git a/config/locales/cy.yml b/config/locales/cy.yml
index a74a51d31f0..1f38ea6eeea 100644
--- a/config/locales/cy.yml
+++ b/config/locales/cy.yml
@@ -904,6 +904,7 @@ cy:
publish_statistics: Cyhoeddi ystadegau
title: Darganfod
trends: Tueddiadau
+ wrapstodon: Wrapstodon
domain_blocks:
all: I bawb
disabled: I neb
diff --git a/config/locales/da.yml b/config/locales/da.yml
index fe49f5b3c58..5c28950e058 100644
--- a/config/locales/da.yml
+++ b/config/locales/da.yml
@@ -1473,7 +1473,7 @@ da:
other: "%{count} individuelle indlæg skjult"
title: Filtre
new:
- save: Gem nye filter
+ save: Gem nyt filter
title: Tilføj nyt filter
statuses:
back_to_filter: Tilbage til filter
@@ -2044,7 +2044,7 @@ da:
lost_recovery_codes: Gendannelseskoder giver dig mulighed for at få adgang til din konto igen, hvis du mister din telefon. Hvis du har mistet dine gendannelseskoder, kan du generere dem igen her. Dine gamle gendannelseskoder vil blive ugyldige.
methods: Tofaktormetoder
otp: Godkendelses-app
- recovery_codes: Sikkerhedskopieret gendannelseskoder
+ recovery_codes: Reserve-gendannelseskoder
recovery_codes_regenerated: Gendannelseskoder er regenereret
recovery_instructions_html: Mister du nogensinde adgang til din mobil, kan en af gendannelseskoderne nedenfor bruges til at opnå adgang til din konto. Opbevar disse et sikkert sted. De kan f.eks. udskrives og gemmes sammen med andre vigtige dokumenter.
webauthn: Sikkerhedsnøgler
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 2cc27c5af6b..7db19f067a2 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -1695,7 +1695,7 @@ de:
notification_mailer:
admin:
report:
- subject: "%{name} hat eine Meldung eingereicht"
+ subject: "%{name} reichte eine Meldung ein"
sign_up:
subject: "%{name} registrierte sich"
favourite:
diff --git a/config/locales/devise.da.yml b/config/locales/devise.da.yml
index 0326535befd..a4aff6a6ef6 100644
--- a/config/locales/devise.da.yml
+++ b/config/locales/devise.da.yml
@@ -89,8 +89,8 @@ da:
success: Godkendt fra %{kind}-konto.
passwords:
no_token: Denne side er kun tilgængelig via linket fra en e-mail til adgangskodenulstillings. Husk i den forbindelse at benytte den fuldstændige URL fra e-mailen.
- send_instructions: Er din e-mailadresse allerede registreret, e-mailes du et link til adgangskodenulstilling. Tjek spammappen, hvis e-mailen ikke ses i indbakken indenfor få minutter.
- send_paranoid_instructions: Er din e-mailadresse allerede registreret, e-mailes du et link til adgangskodenulstilling. Tjek spammappen, hvis e-mailen ikke ses i indbakken indenfor få minutter.
+ send_instructions: Hvis din e-mailadresse findes i vores database, vil du inden for få minutter modtage et link til adgangskodenulstilling på din e-mailadresse. Tjek din spam-mappe, hvis du ikke har modtaget denne e-mail.
+ send_paranoid_instructions: Hvis din e-mailadresse findes i vores database, vil du inden for få minutter modtage et link til adgangskodenulstilling på din e-mailadresse. Tjek din spam-mappe, hvis du ikke har modtaget denne e-mail.
updated: Din adgangskode er skiftet, og du er nu logget ind.
updated_not_active: Din adgangskode er skiftet.
registrations:
diff --git a/config/locales/devise.et.yml b/config/locales/devise.et.yml
index 5843761ddba..6ed4c2dd701 100644
--- a/config/locales/devise.et.yml
+++ b/config/locales/devise.et.yml
@@ -29,23 +29,23 @@ et:
title: Kinnita e-postiaadress
email_changed:
explanation: 'Sinu konto e-postiaadress muudetakse:'
- extra: Kui sa ei muutnud oma e-posti, on tõenäoline, et kellelgi on ligipääs su kontole. Palun muuda koheselt oma salasõna. Kui oled aga oma kontost välja lukustatud, võta ühendust oma serveri administraatoriga.
+ extra: Kui sa ei muutnud oma e-posti, on tõenäoline, et kellelgi on ligipääs su kontole. Palun muuda koheselt oma salasõna. Kui oled aga oma kontole ligipääsu kaotanud, palun võta kohe ühendust oma serveri haldajaga.
subject: 'Mastodon: e-post muudetud'
title: Uus e-postiaadress
password_change:
explanation: Konto salasõna on vahetatud.
extra: Kui sa ei muutnud oma salasõna, on tõenäoline, et keegi on su kontole ligi pääsenud. Palun muuda viivitamata oma salasõna. Kui sa oma kontole ligi ei pääse, võta ühendust serveri haldajaga.
- subject: 'Mastodon: salasõna muudetud'
- title: Salasõna muudetud
+ subject: 'Mastodon: salasõna on muudetud'
+ title: Salasõna on muudetud
reconfirmation_instructions:
explanation: Kinnita uus aadress, et oma e-posti aadress muuta.
extra: Kui see muudatus pole sinu poolt algatatud, palun eira seda kirja. Selle Mastodoni konto e-postiaadress ei muutu enne, kui vajutad üleval olevale lingile.
subject: 'Mastodon: kinnita e-postiaadress %{instance} jaoks'
title: Kinnita e-postiaadress
reset_password_instructions:
- action: Salasõna muutmine
- explanation: Kontole on küsitud uut salasõna.
- extra: Kui see tuleb üllatusena, võib seda kirja eirata. Salasõna ei muutu enne ülaoleva lingi külastamist ja uue salasõna määramist.
+ action: Muuda salasõna
+ explanation: Sa palusid oma kasutajakontole luua uus salasõna.
+ extra: Kui see tuleb üllatusena, võid seda kirja eirata. Salasõna ei muutu enne ülaoleva lingi külastamist ja uue salasõna sisestamist.
subject: 'Mastodon: salasõna lähtestamisjuhendid'
title: Salasõna lähtestamine
two_factor_disabled:
diff --git a/config/locales/devise.nan.yml b/config/locales/devise.nan-TW.yml
similarity index 98%
rename from config/locales/devise.nan.yml
rename to config/locales/devise.nan-TW.yml
index 885e509fdea..ae81f4bd54b 100644
--- a/config/locales/devise.nan.yml
+++ b/config/locales/devise.nan-TW.yml
@@ -1,5 +1,5 @@
---
-nan:
+nan-TW:
devise:
failure:
locked: Lí ê口座hőng鎖定ah。
diff --git a/config/locales/doorkeeper.nan.yml b/config/locales/doorkeeper.nan-TW.yml
similarity index 98%
rename from config/locales/doorkeeper.nan.yml
rename to config/locales/doorkeeper.nan-TW.yml
index 554d991641e..e0f5429d822 100644
--- a/config/locales/doorkeeper.nan.yml
+++ b/config/locales/doorkeeper.nan-TW.yml
@@ -1,5 +1,5 @@
---
-nan:
+nan-TW:
activerecord:
attributes:
doorkeeper/application:
diff --git a/config/locales/et.yml b/config/locales/et.yml
index 508329e996f..58df54c8dfb 100644
--- a/config/locales/et.yml
+++ b/config/locales/et.yml
@@ -142,7 +142,7 @@ et:
security: Turvalisus
security_measures:
only_password: Ainult salasõna
- password_and_2fa: Salasõna ja 2-etapine autentimine (2FA)
+ password_and_2fa: Salasõna ja kahefaktoriline autentimine (2FA)
sensitive: Tundlik sisu
sensitized: Märgitud kui tundlik sisu
shared_inbox_url: Jagatud sisendkausta URL
@@ -292,7 +292,7 @@ et:
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"
+ reset_password_user_html: "%{name} lähtestas %{target} kasutaja salasõna"
resolve_report_html: "%{name} lahendas raporti %{target}"
sensitive_account_html: "%{name} märkis %{target} meedia kui tundlik sisu"
silence_account_html: "%{name} piiras %{target} konto"
@@ -787,7 +787,7 @@ et:
manage_taxonomies: Halda taksonoomiaid
manage_taxonomies_description: Luba kasutajatel populaarset sisu üle vaadata ning uuendada teemaviidete seadistusi
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_user_access_description: Võimaldab kasutajatel keelata teiste kasutajate kaheastmelise autentimise, muuta nende e-posti aadressi ja lähtestada oma salasõna
manage_users: Kasutajate haldamine
manage_users_description: Lubab kasutajail näha teiste kasutajate üksikasju ja teha nende suhtes modereerimisotsuseid
manage_webhooks: Halda webhook'e
@@ -1249,7 +1249,7 @@ et:
suffix: Kasutajakontoga saad jälgida inimesi, postitada uudiseid ning pidada kirjavahetust ükskõik millise Mastodoni serveri kasutajatega ja muudki!
didnt_get_confirmation: Ei saanud kinnituslinki?
dont_have_your_security_key: Pole turvavõtit?
- forgot_password: Salasõna ununenud?
+ forgot_password: Kas unustasid oma salasõna?
invalid_reset_password_token: Salasõna lähtestusvõti on vale või aegunud. Palun taotle uus.
link_to_otp: Kaheastmeline kood telefonist või taastekood
link_to_webauth: Turvavõtmete seadme kasutamine
@@ -1270,7 +1270,7 @@ et:
register: Loo konto
registration_closed: "%{instance} ei võta vastu uusi liikmeid"
resend_confirmation: Saada kinnituslink uuesti
- reset_password: Salasõna lähtestamine
+ reset_password: Lähtesta salasõna
rules:
accept: Nõus
back: Tagasi
@@ -1280,7 +1280,7 @@ et:
title: Mõned põhireeglid.
title_invited: Oled kutsutud.
security: Turvalisus
- set_new_password: Uue salasõna määramine
+ set_new_password: Sisesta uus salasõna
setup:
email_below_hint_html: Kontrolli rämpsposti kausta või palu uue kirja saatmist. Kui sinu e-posti aadress on vale, siis saad seda parandada.
email_settings_hint_html: Klõpsa aadressile %{email} saadetud linki, et alustada Mastodoni kasutamist. Me oleme ootel.
@@ -1316,9 +1316,9 @@ et:
title: Autori tunnustamine
challenge:
confirm: Jätka
- hint_html: "Nõuanne: Me ei küsi salasõna uuesti järgmise tunni jooksul."
+ hint_html: "Nõuanne: Me ei küsi sinu salasõna uuesti järgmise tunni jooksul."
invalid_password: Vigane salasõna
- prompt: Jätkamiseks salasõna veelkord
+ prompt: Jätkamiseks korda salasõna
color_scheme:
auto: Auto
dark: Tume
@@ -1627,7 +1627,7 @@ et:
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.
+ description_html: Kui paistab tundmatuid tegevusi, palun vaheta salasõna ja aktiveeri kaheastmeline autentimine.
empty: Autentimisajalugu pole saadaval
failed_sign_in_html: Nurjunud sisenemine meetodiga %{method} aadressilt %{ip} (%{browser})
successful_sign_in_html: Edukas sisenemine meetodiga %{method} aadressilt %{ip} (%{browser})
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index c2e5ef0750e..24b0ebd4bc8 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -12,7 +12,7 @@ fi:
followers:
one: seuraaja
other: seuraajaa
- following: Seurattavat
+ following: seurattavaa
instance_actor_flash: Tämä tili on virtuaalinen toimija, jota käytetään edustamaan itse palvelinta eikä yksittäistä käyttäjää. Sitä käytetään federointitarkoituksiin, eikä sitä tule jäädyttää.
last_active: viimeksi aktiivinen
link_verified_on: Tämän linkin omistus on tarkastettu %{date}
diff --git a/config/locales/gd.yml b/config/locales/gd.yml
index b637a9eb71f..543cd0cb460 100644
--- a/config/locales/gd.yml
+++ b/config/locales/gd.yml
@@ -7,6 +7,8 @@ gd:
hosted_on: Mastodon ’ga òstadh air %{domain}
title: Mu dhèidhinn
accounts:
+ errors:
+ cannot_be_added_to_collections: Cha ghabh an cunntas seo a chur ri cruinneachadh.
followers:
few: Luchd-leantainn
one: Neach-leantainn
@@ -874,6 +876,7 @@ gd:
publish_statistics: Foillsich an stadastaireachd
title: Rùrachadh
trends: Treandaichean
+ wrapstodon: Wrapstodon
domain_blocks:
all: Dhan a h-uile duine
disabled: Na seall idir
@@ -1354,6 +1357,13 @@ gd:
hint_html: "Gliocas: Chan iarr sinn am facal-faire agad ort a-rithist fad uair a thìde."
invalid_password: Facal-faire mì-dhligheach
prompt: Dearbh am facal-faire airson leantainn air adhart
+ color_scheme:
+ auto: Fèin-obrachail
+ dark: Dorcha
+ light: Soilleir
+ contrast:
+ auto: Fèin-obrachail
+ high: Àrd
crypto:
errors:
invalid_key: "– chan e iuchair Ed25519 no Curve25519 dhligheach a th’ ann"
@@ -1784,16 +1794,22 @@ gd:
body: 'Thug %{name} iomradh ort an-seo:'
subject: Thug %{name} iomradh ort
title: Iomradh ùr
+ moderation_warning:
+ subject: Fhuair thu rabhadh on mhaorsainneachd
poll:
subject: Thàinig cunntas-bheachd le %{name} gu crìoch
quote:
body: 'Chaidh post a luaidh le %{name}:'
subject: Luaidh %{name} am post agad
title: Luaidh ùr
+ quoted_update:
+ subject: Dheasaich %{name} post a luaidh thu
reblog:
body: 'Chaidh am post agad a bhrosnachadh le %{name}:'
subject: Bhrosnaich %{name} am post agad
title: Brosnachadh ùr
+ severed_relationships:
+ subject: Chaill thu dàimhean ri linn co-dhùnadh na maorsainneachd
status:
subject: Tha %{name} air post a sgrìobhadh
update:
@@ -2038,14 +2054,16 @@ gd:
public: Poblach
public_long: Neach sam bith taobh a-staigh no a-muigh Mhastodon
unlisted: Sàmhach
- unlisted_long: Falaichte o na toraidhean-luirg, na treandaichean ’s na loichnichean-ama poblach
+ unlisted_long: Falaichte o na toraidhean-luirg, na treandaichean ’s na loidhnichean-ama poblach
statuses_cleanup:
enabled: Sguab às seann-phostaichean gu fèin-obrachail
enabled_hint: Sguabaidh seo às na seann-phostaichean agad gu fèin-obrachail nuair a ruigeas iad stairsneach aoise sònraichte ach ma fhreagras iad ri gin dhe na h-eisgeachdan gu h-ìosal
exceptions: Eisgeachdan
+ explanation: Tha prìomhachas ìosal air an sguabadh às fhèin-obrachail. Dh’fhaoidte gum bi dàil eadar ruigsinn stairsneach na h-aoise agus an toirt air falbh.
ignore_favs: Leig seachad na h-annsachdan
ignore_reblogs: Leig seachad na brosnachaidhean
interaction_exceptions: Eisgeachdan stèidhichte air eadar-ghnìomhan
+ interaction_exceptions_explanation: Faodaidh postaichean mairsinn ma thèid iad thar stairsneach nan annsachdan no brosnachaidhean rè seal fiù ma bhios an cunntas as ìsle an uairsin.
keep_direct: Cùm na teachdaireachdan dìreach
keep_direct_hint: Cha dèid gin dhe na teachdaireachdan dìreach agad a sguabadh às
keep_media: Cùm postaichean le ceanglachan meadhain
@@ -2260,8 +2278,12 @@ gd:
error: Bha duilgheadas ann le bhith a’ sguabadh às an iuchair tèarainteachd agad. Feuch ris a-rithist.
success: Chaidh an iuchair tèarainteachd agad a sguabadh às.
invalid_credential: Iuchair tèarainteachd mì-dhligheach
+ nickname: Far-ainm
nickname_hint: Cuir a-steach far-ainm na h-iuchrach tèarainteachd ùir agad
not_enabled: Cha do chuir thu WebAuthn an comas fhathast
not_supported: Cha chuir am brabhsair seo taic ri iuchraichean tèarainteachd
otp_required: Mus cleachd thu iuchraichean tèarainteachd, feumaidh tu an dearbhadh dà-cheumnach a chur an comas.
registered_on: Air a chlàradh %{date}
+ wrapstodon:
+ description: Seall mar a chleachd %{name} Mastodon am bliadhna!
+ title: Wrapstodon %{year} dha %{name}
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 62346c68597..f0ede70b9d5 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -1748,7 +1748,7 @@ ko:
unrecognized_emoji: 인식 되지 않은 에모지입니다
redirects:
prompt: 이 링크를 믿을 수 있다면, 클릭해서 계속하세요.
- title: "%{instance}를 떠나려고 합니다."
+ title: "%{instance}을(를) 떠나려고 합니다."
relationships:
activity: 계정 활동
confirm_follow_selected_followers: 정말로 선택된 팔로워들을 팔로우하시겠습니까?
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
index 33028404502..6666a4d7bd8 100644
--- a/config/locales/lt.yml
+++ b/config/locales/lt.yml
@@ -1033,7 +1033,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: Gali importuoti duomenis, kuriuos eksportavai iš kito serverio, pavyzdžiui, sekamų arba blokuojamų žmonių sąrašą.
+ preface: Galite importuoti duomenis, kuriuos eksportavote iš kito serverio kaip 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
diff --git a/config/locales/nan.yml b/config/locales/nan-TW.yml
similarity index 99%
rename from config/locales/nan.yml
rename to config/locales/nan-TW.yml
index c19edeeed10..04c7b48feb5 100644
--- a/config/locales/nan.yml
+++ b/config/locales/nan-TW.yml
@@ -1,5 +1,5 @@
---
-nan:
+nan-TW:
about:
about_mastodon_html: 社交網路ê未來:Bô廣告、bô企業監控、設計有道德,兼非中心化!加入Mastodon,保有lí ê資料!
contact_missing: Iáu bē設定
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index 805c6532b0c..427810a7453 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -1971,13 +1971,13 @@ nl:
unlisted_long: Niet zichtbaar in de zoekresultaten van Mastodon, onder trends, hashtags en op openbare tijdlijnen
statuses_cleanup:
enabled: Automatisch oude berichten verwijderen
- enabled_hint: Verwijder uw berichten automatisch zodra ze een bepaalde leeftijdsgrens bereiken, tenzij ze overeenkomen met een van de onderstaande uitzonderingen
+ enabled_hint: Verwijder jouw berichten automatisch zodra ze een bepaalde leeftijdsgrens bereiken, tenzij ze overeenkomen met een van de onderstaande uitzonderingen
exceptions: Uitzonderingen
explanation: Geautomatiseerde verwijdering wordt uitgevoerd met lage prioriteit. Er kan een vertraging optreden tussen het bereiken van de leeftijdsgrens en het verwijderen.
ignore_favs: Favorieten negeren
ignore_reblogs: Boosts negeren
interaction_exceptions: Uitzonderingen op basis van interacties
- interaction_exceptions_explanation: Berichten die tijdelijk de drempel voor favorieten of boosten overschrijden, kunnen worden bewaard, zelfs als ze later worden verlaagd.
+ interaction_exceptions_explanation: Berichten die tijdelijk de opgegeven drempel voor favorieten of boosten overschrijden kunnen worden bewaard, zelfs als ze later weer onder die drempel komen.
keep_direct: Privéberichten behouden
keep_direct_hint: Verwijdert geen enkel privébericht van jou
keep_media: Berichten met mediabijlagen behouden
diff --git a/config/locales/nn.yml b/config/locales/nn.yml
index 9d92e42a541..792a4e28666 100644
--- a/config/locales/nn.yml
+++ b/config/locales/nn.yml
@@ -2190,6 +2190,7 @@ nn:
error: Det oppsto et problem med å slette sikkerhetsnøkkelen. Prøv igjen.
success: Sikkerhetsnøkkelen din ble vellykket slettet.
invalid_credential: Ugyldig sikkerhetsnøkkel
+ nickname: Kallenamn
nickname_hint: Skriv inn kallenavnet til din nye sikkerhetsnøkkel
not_enabled: Du har ikke aktivert WebAuthn ennå
not_supported: Denne nettleseren støtter ikke sikkerhetsnøkler
diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml
index 6b5247e8030..b1dd7ba81b8 100644
--- a/config/locales/simple_form.da.yml
+++ b/config/locales/simple_form.da.yml
@@ -131,7 +131,7 @@ da:
hint: Valgfrit. Oplys yderligere detaljer om reglen
text: Beskriv på en kort og enkel form en regel/krav for brugere på denne server
sessions:
- otp: 'Angiv tofaktorkoden generet af din mobil-app eller brug en af genoprettelseskoderne:'
+ otp: 'Angiv tofaktorkoden generet af din mobil-app eller brug en af dine gendannelseskoder:'
webauthn: Er det en USB-nøgle, så sørg for at isætte den og, om nødvendigt, åbne den manuelt.
settings:
indexable: Din profilside kan fremgå i søgeresultater på Google, Bing mv.
diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml
index 98defb79cdb..a39cf443594 100644
--- a/config/locales/simple_form.de.yml
+++ b/config/locales/simple_form.de.yml
@@ -175,7 +175,7 @@ de:
labels:
account:
attribution_domains: Websites, die auf dich verweisen dürfen
- discoverable: Profil und Beiträge in Suchalgorithmen berücksichtigen
+ discoverable: Profil und Beiträge in Empfehlungsalgorithmen berücksichtigen
fields:
name: Beschriftung
value: Inhalt
diff --git a/config/locales/simple_form.el.yml b/config/locales/simple_form.el.yml
index 3c06421aee9..6ca8c6c8db2 100644
--- a/config/locales/simple_form.el.yml
+++ b/config/locales/simple_form.el.yml
@@ -211,7 +211,7 @@ el:
text: Εξηγήστε γιατί αυτή η απόφαση πρέπει να αντιστραφεί
defaults:
autofollow: Προσκάλεσε για να ακολουθήσουν το λογαριασμό σου
- avatar: Άβαταρ
+ avatar: Εικόνα προφίλ
bot: Αυτός είναι ένας αυτοματοποιημένος λογαριασμός (bot)
chosen_languages: Φιλτράρισμα γλωσσών
confirm_new_password: Επιβεβαίωσε νέο συνθηματικό
@@ -241,8 +241,8 @@ el:
setting_boost_modal: Έλεγχος ορατότητας της ενίσχυσης
setting_color_scheme: Λειτουργία
setting_contrast: Αντίθεση
- setting_default_language: Γλώσσα κατά την ανάρτηση
- setting_default_privacy: Ορατότητα αναρτήσεων
+ setting_default_language: Γλώσσα ανάρτησης
+ setting_default_privacy: Ορατότητα ανάρτησης
setting_default_quote_policy: Ποιος μπορεί να παραθέσει
setting_default_sensitive: Σημείωση όλων των πολυμέσων ως ευαίσθητου περιεχομένου
setting_delete_modal: Προειδοποίηση πριν από τη διαγραφή μιας ανάρτησης
@@ -255,7 +255,7 @@ el:
setting_emoji_style: Στυλ Emoji
setting_expand_spoilers: Μόνιμη ανάπτυξη των τουτ με προειδοποίηση περιεχομένου
setting_hide_network: Κρύψε τις διασυνδέσεις σου
- setting_missing_alt_text_modal: Προειδοποίηση πριν από την ανάρτηση πολυμέσων χωρίς εναλλακτικό κείμενο
+ setting_missing_alt_text_modal: Προειδοποίηση πριν από τη δημοσίευση πολυμέσων χωρίς εναλλακτικό κείμενο
setting_quick_boosting: Ενεργοποίηση γρήγορης ενίσχυσης
setting_reduce_motion: Μείωση κίνησης κινουμένων στοιχείων
setting_system_font_ui: Χρήση της προεπιλεγμένης γραμματοσειράς του συστήματος
diff --git a/config/locales/simple_form.et.yml b/config/locales/simple_form.et.yml
index d51e816d2e5..2e45c6ffa07 100644
--- a/config/locales/simple_form.et.yml
+++ b/config/locales/simple_form.et.yml
@@ -51,7 +51,7 @@ et:
inbox_url: Kopeeri soovitud sõnumivahendusserveri avalehe võrguaadress
irreversible: Filtreeritud postitused kaovad taastamatult, isegi kui filter on hiljem eemaldatud
locale: Kasutajaliidese, e-kirjade ja tõuketeadete keel
- password: Vajalik on vähemalt 8 märki
+ password: Vajalik on vähemalt 8 tähemärki
phrase: Kattub olenemata postituse teksti suurtähtedest või sisuhoiatusest
scopes: Milliseid API-sid see rakendus tohib kasutada. Kui valid kõrgeima taseme, ei pea üksikuid eraldi valima.
setting_advanced_layout: Näita Mastodoni mitme veeruga paigutuses, mispuhul näed korraga nii ajajoont, teavitusi, kui sinu valitud kolmandat veergu. Ei sobi kasutamiseks väikeste ekraanide puhul.
@@ -113,7 +113,7 @@ et:
trends: Trendid näitavad, millised postitused, teemaviited ja uudislood koguvad sinu serveris tähelepanu.
wrapstodon: Paku kohalikele kasutajatele luua nende Mastodoni kasutamise aastast mänguline kokkuvõte. See võimalus on saadaval igal aastal 10. ja 31. detsembri vahel ja seda pakutakse kasutajatele, kes tegid vähemalt ühe avaliku või vaikse avaliku postituse ja kes kasutas aasta jooksul vähemalt ühte silti.
form_challenge:
- current_password: Turvalisse alasse sisenemine
+ current_password: Sisened turvalisse alasse
imports:
data: CSV fail eksporditi teisest Mastodoni serverist
invite_request:
@@ -214,8 +214,8 @@ et:
avatar: Profiilipilt
bot: See konto on robot
chosen_languages: Keelte filtreerimine
- confirm_new_password: Uue salasõna kinnitamine
- confirm_password: Salasõna kinnitamine
+ confirm_new_password: Korda uut salasõna
+ confirm_password: Korda salasõna
context: Filtreeri kontekste
current_password: Kehtiv salasõna
data: Andmed
diff --git a/config/locales/simple_form.gd.yml b/config/locales/simple_form.gd.yml
index e11b300b33a..2673988df10 100644
--- a/config/locales/simple_form.gd.yml
+++ b/config/locales/simple_form.gd.yml
@@ -88,6 +88,7 @@ gd:
activity_api_enabled: Cunntasan nam postaichean a chaidh fhoillseachadh gu h-ionadail, nan cleachdaichean gnìomhach ’s nan clàraidhean ùra an am bucaidean seachdaineil
app_icon: WEBP, PNG, GIF no JPG. Tar-àithnidh seo ìomhaigheag bhunaiteach na h-aplacaid air uidheaman mobile le ìomhaigheag ghnàthaichte.
backups_retention_period: "’S urrainn do chleachdaichean tasg-lannan dhe na postaichean aca a gintinn airson an luchdadh a-nuas an uairsin. Nuair a bhios luach dearbh air, thèid na tasg-lannan a sguabadh às on stòras agad gu fèin-obrachail às dèidh an àireamh de làithean a shònraich thu."
+ bootstrap_timeline_accounts: Thèid na cunntasan seo a phrìneachadh air bàrr nam molaidhean leantainn dhan luchd-cleachdaidh ùr. Solar liosta de chunntasan sgaraichte le cromagan.
closed_registrations_message: Thèid seo a shealltainn nuair a bhios an clàradh dùinte
content_cache_retention_period: Thèid a h-uile post o fhrithealaiche sam bith eile (a’ gabhail a-staigh brosnachaidhean is freagairtean) a sguabadh às às dèidh na h-àireimh de làithean a shònraich thu ’s gun diù a chon air eadar-ghabhail ionadail air na postaichean ud. Gabhaidh seo a-steach na postaichean a chuir cleachdaiche ionadail ris na h-annsachdan aca no comharran-lìn riutha. Thèid iomraidhean prìobhaideach eadar cleachdaichean o ionstansan diofraichte air chall cuideachd agus cha ghabh an aiseag idir. Tha an roghainn seo do dh’ionstansan sònraichte a-mhàin agus briseadh e dùilean an luchd-cleachdaidh nuair a rachadh a chleachdadh gu coitcheann.
custom_css: "’S urrainn dhut stoidhlean gnàthaichte a chur an sàs air an tionndadh-lìn de Mhastodon."
@@ -110,6 +111,7 @@ gd:
thumbnail: Dealbh mu 2:1 a thèid a shealltainn ri taobh fiosrachadh an fhrithealaiche agad.
trendable_by_default: Geàrr leum thar lèirmheas a làimh na susbainte a’ treandadh. Gabhaidh nithean fa leth a thoirt far nan treandaichean fhathast an uairsin.
trends: Seallaidh na treandaichean na postaichean, tagaichean hais is naidheachdan a tha fèill mhòr orra air an fhrithealaiche agad.
+ wrapstodon: Tairg gintinn geàrr-chunntais àbhaich air mar a chleachd iad Mastodon rè a’ bhliadhna dhan luchd-cleachdaidh ionadail. Bidh an gleus seo ri fhaighinn eadar an 10mh is 31mh dhen Dùbhlachd gach bliadhna ’s thèid a thairgsinn dhan luchd-cleachdaidh a rinn co-dhiù aon post poblach no sàmhach ’s a chleachd co-dhiù aon taga hais rè a’ bhliadhna.
form_challenge:
current_password: Tha thu a’ tighinn a-steach gu raon tèarainte
imports:
@@ -239,6 +241,8 @@ gd:
setting_always_send_emails: Cuir brathan puist-d an-còmhnaidh
setting_auto_play_gif: Cluich GIFs beòthaichte gu fèin-obrachail
setting_boost_modal: Smachd air faicsinneachd nam brosnachaidhean
+ setting_color_scheme: Modh
+ setting_contrast: Iomsgaradh
setting_default_language: Cànan postaidh
setting_default_privacy: Faicsinneachd nam post
setting_default_quote_policy: Cò dh’fhaodas luaidh
@@ -313,6 +317,7 @@ gd:
thumbnail: Dealbhag an fhrithealaiche
trendable_by_default: Ceadaich treandaichean gun lèirmheas ro làimh
trends: Cuir na treandaichean an comas
+ wrapstodon: Cuir Wrapstodon an comas
interactions:
must_be_follower: Bac na brathan nach eil o luchd-leantainn
must_be_following: Bac na brathan o dhaoine nach lean thu
@@ -373,7 +378,9 @@ gd:
jurisdiction: Uachdranas laghail
min_age: An aois as lugha
user:
+ date_of_birth_1i: Bliadhna
date_of_birth_2i: Mìos
+ date_of_birth_3i: Latha
role: Dreuchd
time_zone: Roinn-tìde
user_role:
diff --git a/config/locales/simple_form.nan.yml b/config/locales/simple_form.nan-TW.yml
similarity index 99%
rename from config/locales/simple_form.nan.yml
rename to config/locales/simple_form.nan-TW.yml
index 08ae2a55df5..84b955ddb0a 100644
--- a/config/locales/simple_form.nan.yml
+++ b/config/locales/simple_form.nan-TW.yml
@@ -1,5 +1,5 @@
---
-nan:
+nan-TW:
simple_form:
hints:
account:
diff --git a/config/locales/simple_form.sl.yml b/config/locales/simple_form.sl.yml
index e87dd799d2a..a6b2b96d2b2 100644
--- a/config/locales/simple_form.sl.yml
+++ b/config/locales/simple_form.sl.yml
@@ -54,6 +54,7 @@ sl:
password: Uporabite najmanj 8 znakov
phrase: Se bo ujemal, ne glede na začetnice v besedilu ali opozorilo o vsebini objave
scopes: Do katerih API-jev bo imel program dostop. Če izberete obseg najvišje ravni, vam ni treba izbrati posameznih.
+ setting_advanced_layout: Prikaži Mastodon v večstolpčni postavitvi, kar prikaže časovnico, obbvestila in tretji stolpec po izboru. Ne priporočamo za manjše zaslone.
setting_aggregate_reblogs: Ne prikažite novih izpostavitev za objave, ki so bile nedavno izpostavljene (vpliva samo na novo prejete izpostavitve)
setting_always_send_emails: Običajno e-obvestila ne bodo poslana, če ste na Mastodonu dejavni
setting_default_sensitive: Občutljivi mediji so privzeto skriti in jih je mogoče razkriti s klikom
@@ -73,6 +74,7 @@ sl:
featured_tag:
name: 'Tukaj je nekaj ključnikov, ki ste jih nedavno uporabili:'
filters:
+ action: Izberite, kako naj se program vede, ko se objava sklada s filtrom
actions:
hide: Povsem skrij filtrirano vsebino, kot da ne bi obstajala
warn: Skrij filtrirano vsebino za opozorilom, ki pomenja naslov filtra
@@ -220,6 +222,8 @@ sl:
setting_always_send_emails: Vedno pošlji e-obvestila
setting_auto_play_gif: Samodejno predvajanje animiranih GIF-ov
setting_boost_modal: Nadziraj vidnost objav
+ setting_color_scheme: Način
+ setting_contrast: Kontrast
setting_default_language: Jezik objavljanja
setting_default_privacy: Vidnost objav
setting_default_quote_policy: Kdo lahko citira
@@ -231,6 +235,7 @@ sl:
setting_display_media_default: Privzeto
setting_display_media_hide_all: Skrij vse
setting_display_media_show_all: Prikaži vse
+ setting_emoji_style: Slog čustvenih simbolov
setting_expand_spoilers: Vedno razširi objave, označene z opozorili o vsebini
setting_hide_network: Skrij svoje omrežje
setting_reduce_motion: Zmanjšanje premikanja v animacijah
@@ -265,6 +270,7 @@ sl:
content_cache_retention_period: Obdobje hranjenja vsebine z ostalih strežnikov
custom_css: CSS po meri
favicon: Ikona spletne strani
+ landing_page: Ciljna stran za nove obiskovalce
mascot: Maskota po meri (opuščeno)
media_cache_retention_period: Obdobje hrambe predpomnilnika predstavnosti
min_age: Spodnja starostna meja
@@ -285,6 +291,7 @@ sl:
thumbnail: Sličica strežnika
trendable_by_default: Dovoli trende brez predhodnega pregleda
trends: Omogoči trende
+ wrapstodon: Omogoči Wrapstodon
interactions:
must_be_follower: Blokiraj obvestila nesledilcev
must_be_following: Blokiraj obvestila oseb, ki jim ne sledite
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
index 2fc26113588..b577eb45a5e 100644
--- a/config/locales/sl.yml
+++ b/config/locales/sl.yml
@@ -7,6 +7,8 @@ sl:
hosted_on: Mastodon gostuje na %{domain}
title: O programu
accounts:
+ errors:
+ cannot_be_added_to_collections: Tega računa ni možno dodati v zbirke.
followers:
few: Sledilci
one: Sledilec
@@ -196,6 +198,7 @@ sl:
create_relay: Ustvari rele
create_unavailable_domain: Ustvari domeno, ki ni na voljo
create_user_role: Ustvari vlogo
+ create_username_block: Ustvari pravilo uporabniškega imena
demote_user: Ponižaj uporabnika
destroy_announcement: Izbriši obvestilo
destroy_canonical_email_block: Izbriši blokado e-naslova
@@ -209,6 +212,7 @@ sl:
destroy_status: Izbriši objavo
destroy_unavailable_domain: Izbriši nedosegljivo domeno
destroy_user_role: Uniči vlogo
+ destroy_username_block: Izbriši pravilo uporabniškega imena
disable_2fa_user: Onemogoči
disable_custom_emoji: Onemogoči emotikon po meri
disable_relay: Onemogoči rele
@@ -243,6 +247,7 @@ sl:
update_report: Posodobi poročilo
update_status: Posodobi objavo
update_user_role: Posodobi vlogo
+ update_username_block: Posodobi pravilo uporabniškega imena
actions:
approve_appeal_html: "%{name} je ugodil pritožbi uporabnika %{target} na moderatorsko odločitev"
approve_user_html: "%{name} je odobril/a registracijo iz %{target}"
@@ -261,6 +266,7 @@ sl:
create_relay_html: "%{name} je ustvaril/a rele %{target}"
create_unavailable_domain_html: "%{name} je prekinil/a dostavo v domeno %{target}"
create_user_role_html: "%{name} je ustvaril/a vlogo %{target}"
+ create_username_block_html: "%{name} je dodal/a pravilo za uporabniška imena, ki vsebujejo %{target}"
demote_user_html: "%{name} je ponižal/a uporabnika %{target}"
destroy_announcement_html: "%{name} je izbrisal/a obvestilo %{target}"
destroy_canonical_email_block_html: "%{name} je odstranil/a s črnega seznama e-pošto s ključnikom %{target}"
@@ -274,6 +280,7 @@ sl:
destroy_status_html: "%{name} je odstranil/a objavo uporabnika %{target}"
destroy_unavailable_domain_html: "%{name} je nadaljeval/a dostav v domeno %{target}"
destroy_user_role_html: "%{name} je izbrisal/a vlogo %{target}"
+ destroy_username_block_html: "%{name} je odstranil/a pravilo za uporabniška imena, ki vsebujejo %{target}"
disable_2fa_user_html: "%{name} je onemogočil/a dvofaktorsko zahtevo za uporabnika %{target}"
disable_custom_emoji_html: "%{name} je onemogočil/a emotikone %{target}"
disable_relay_html: "%{name} je onemogočil/a rele %{target}"
@@ -308,6 +315,7 @@ sl:
update_report_html: "%{name} je posodobil poročilo %{target}"
update_status_html: "%{name} je posodobil/a objavo uporabnika %{target}"
update_user_role_html: "%{name} je spremenil/a vlogo %{target}"
+ update_username_block_html: "%{name} je posodobil/a pravilo za uporabniška imena, ki vsebujejo %{target}"
deleted_account: izbrisan račun
empty: Ni najdenih zapisnikov.
filter_by_action: Filtriraj po dejanjih
@@ -498,21 +506,30 @@ sl:
fasp:
debug:
callbacks:
+ created_at: Ustvarjeno
delete: Izbriši
ip: Naslov IP
+ request_body: Telo zahteve
providers:
+ active: Dejaven
base_url: Osnovna povezava
callback: Povratni klic
delete: Izbriši
edit: Uredi ponudnika
finish_registration: Dokončaj registracijo
name: Ime
+ providers: Ponudniki
+ public_key_fingerprint: Prstni odtis javnega ključa
+ registration_requested: Registracija je obvezna
registrations:
confirm: Potrdi
reject: Zavrni
+ title: Potrdri registracijo FASP
save: Shrani
sign_in: Prijava
status: Stanje
+ title: Ponudniki dodatnih storitev Fediverse
+ title: FASP
follow_recommendations:
description_html: "Sledi priporočilom pomaga novim uporabnikom, da hitro najdejo zanimivo vsebino. Če uporabnik ni dovolj komuniciral z drugimi, da bi oblikoval prilagojena priporočila za sledenje, se namesto tega priporočajo ti računi. Dnevno se ponovno izračunajo iz kombinacije računov z najvišjimi nedavnimi angažiranostmi in najvišjim številom krajevnih sledilcev za določen jezik."
language: Za jezik
@@ -844,12 +861,18 @@ sl:
publish_statistics: Objavi statistiko
title: Razkrivanje
trends: Trendi
+ wrapstodon: Wrapstodon
domain_blocks:
all: Vsem
disabled: Nikomur
users: Prijavljenim krajevnim uporabnikom
+ feed_access:
+ modes:
+ authenticated: Samo overjeni uporabniki
+ public: Vsi
landing_page:
values:
+ local_feed: Krajevni vir
trends: Trendi
registrations:
moderation_recommandation: Preden prijave odprete za vse poskrbite, da imate v ekipi moderatorjev zadosti aktivnih članov.
@@ -912,6 +935,7 @@ sl:
title: Objave računa - @%{name}
trending: V trendu
view_publicly: Prikaži javno
+ view_quoted_post: Pokaži citirano objavo
visibility: Vidnost
with_media: Z mediji
strikes:
@@ -1103,13 +1127,23 @@ sl:
trending: V porastu
username_blocks:
add_new: Dodaj novo
+ block_registrations: Blokiraj registracije
comparison:
contains: Vsebuje
+ equals: Je enako
contains_html: Vsebuje %{string}
+ created_msg: Pravilo uporabniškega imena uspešno ustvarjeno
delete: Izbriši
+ edit:
+ title: Uredi pravilo uporabniškega imena
+ matches_exactly_html: Je enako %{string}
new:
create: Ustvari pravilo
+ title: Ustvari novo pravilo uporabniškega imena
+ no_username_block_selected: Nobeno pravilo uporabniškega imena ni bilo spremenjeno, ker nobeno ni bilo izbrano
not_permitted: Ni dovoljeno
+ title: Pravila uporabniškega imena
+ updated_msg: Pravilo uporabniškega imena uspešno posodobljeno
warning_presets:
add_new: Dodaj novo
delete: Izbriši
@@ -1302,6 +1336,13 @@ sl:
hint_html: "Namig: naslednjo uro vas ne bomo več vprašali po vašem geslu."
invalid_password: Neveljavno geslo
prompt: Potrdite geslo za nadaljevanje
+ color_scheme:
+ auto: Samodejno
+ dark: Temno
+ light: Svetlo
+ contrast:
+ auto: Samodejno
+ high: Visoko
crypto:
errors:
invalid_key: ni veljaven ključ Ed25519 ali Curve25519
@@ -1376,6 +1417,7 @@ sl:
other: Drugo
emoji_styles:
auto: Samodejno
+ native: Domoroden
errors:
'400': Zahteva, ki ste jo oddali, je neveljavna ali nepravilno oblikovana.
'403': Nimate dovoljenja za ogled te strani.
@@ -1629,6 +1671,7 @@ sl:
author_html: Avtor/ica %{name}
potentially_sensitive_content:
action: Kliknite za prikaz
+ confirm_visit: Ali ste prepričani, da želite odpreti to povezavo?
hide_button: Skrij
lists:
errors:
@@ -1727,10 +1770,13 @@ sl:
body: "%{name} vas je omenil/a v:"
subject: "%{name} vas je omenil/a"
title: Nova omemba
+ moderation_warning:
+ subject: Prejeli ste opozorilo moderatorjev
poll:
subject: Anketa, ki jo je pripravil/a %{name}, se je iztekla
quote:
body: 'Vašo objavo je citiral/a %{name}:'
+ subject: "%{name} je citiral/a vašo objavo"
title: Nov citat
reblog:
body: 'Vašo objavo je izpostavil/a %{name}:'
@@ -1962,6 +2008,7 @@ sl:
reblog: Izpostavitev ne more biti pripeta
quote_error:
not_available: Objava ni na voljo
+ revoked: Avtor je umaknil objavo
quote_policies:
followers: Samo sledilci
nobody: Samo jaz
@@ -2191,8 +2238,12 @@ sl:
error: Pri brisanju vašega varnostnega ključa je prišlo do težav. Poskusite znova.
success: Vaš varnostni ključ je bil uspešno izbrisan.
invalid_credential: Neveljaven varnostni ključ
+ nickname: Vzdevek
nickname_hint: Vnesite vzdevek svojega novega varnostnega ključa
not_enabled: Niste še omogočili WebAuthn
not_supported: Ta brskalnik ne podpira varnostnih ključev
otp_required: Za uporabo varnostnih ključev morate najprej omogočiti 2FA (dvostopenjsko overjanje).
registered_on: Datum registracije %{date}
+ wrapstodon:
+ description: Oglejte si, kako je %{name} letos uporabljal/a Mastodon!
+ title: Wrapstodon %{year} za %{name}
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
index bf2e7f7a60e..159014d1685 100644
--- a/config/locales/sq.yml
+++ b/config/locales/sq.yml
@@ -884,7 +884,7 @@ sq:
types:
major: Hedhje e rëndësishme në qarkullim
minor: Hedhje e vockël në qarkullim
- patch: Hedhje në qarkullim arnimesh — ndreqje të meash dhe ndryshime të lehta për t’u aplikuar
+ patch: Hedhje në qarkullim arnimesh — ndreqje të metash dhe ndryshime të lehta për t’u aplikuar
version: Version
statuses:
account: Autor
diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml
index 4f1c03a46a9..557ae88e3d0 100644
--- a/config/locales/zh-CN.yml
+++ b/config/locales/zh-CN.yml
@@ -8,7 +8,7 @@ zh-CN:
title: 关于本站
accounts:
errors:
- cannot_be_added_to_collections: 此账号无法被添加到关注列表内。
+ cannot_be_added_to_collections: 此账号无法被添加到收藏列表内。
followers:
other: 关注者
following: 正在关注
diff --git a/config/routes.rb b/config/routes.rb
index ff79c758fb3..bf50b67fe13 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -96,14 +96,14 @@ Rails.application.routes.draw do
get '/authorize_follow', to: redirect { |_, request| "/authorize_interaction?#{request.params.to_query}" }
concern :account_resources do
- resources :featured_collections, only: [:show]
+ resources :collections, only: [:show], constraints: { id: /\d+/ }
resources :followers, only: [:index], controller: :follower_accounts
resources :following, only: [:index], controller: :following_accounts
scope module: :activitypub do
resource :outbox, only: [:show]
resource :inbox, only: [:create]
- resources :collections, only: [:show]
+ resources :collections, only: [:show], as: :actor_collections, constraints: { id: Regexp.union(ActivityPub::CollectionsController::SUPPORTED_COLLECTIONS) }
resource :followers_synchronization, only: [:show]
resources :quote_authorizations, only: [:show]
end
@@ -124,6 +124,8 @@ Rails.application.routes.draw do
scope path: 'ap', as: 'ap' do
resources :accounts, path: 'users', only: [:show], param: :id, concerns: :account_resources do
+ resources :featured_collections, only: [:index], module: :activitypub
+
resources :statuses, only: [:show] do
member do
get :activity
diff --git a/config/routes/web_app.rb b/config/routes/web_app.rb
index c09232d1f21..2901e227151 100644
--- a/config/routes/web_app.rb
+++ b/config/routes/web_app.rb
@@ -7,6 +7,7 @@
%w(
/blocks
/bookmarks
+ /collections/(*any)
/conversations
/deck/(*any)
/directory
diff --git a/db/migrate/20180608213548_reject_following_blocked_users.rb b/db/migrate/20180608213548_reject_following_blocked_users.rb
index 4cb6395469c..a82bff62b41 100644
--- a/db/migrate/20180608213548_reject_following_blocked_users.rb
+++ b/db/migrate/20180608213548_reject_following_blocked_users.rb
@@ -4,14 +4,14 @@ class RejectFollowingBlockedUsers < ActiveRecord::Migration[5.2]
disable_ddl_transaction!
def up
- blocked_follows = Follow.find_by_sql(<<-SQL.squish)
+ blocked_follows = Follow.find_by_sql(<<~SQL.squish)
select f.* from follows f
inner join blocks b on
f.account_id = b.target_account_id and
f.target_account_id = b.account_id
SQL
- domain_blocked_follows = Follow.find_by_sql(<<-SQL.squish)
+ domain_blocked_follows = Follow.find_by_sql(<<~SQL.squish)
select f.* from follows f
inner join accounts following on f.account_id = following.id
inner join account_domain_blocks b on
diff --git a/db/migrate/20180812173710_copy_status_stats.rb b/db/migrate/20180812173710_copy_status_stats.rb
index 087b1290dbc..74c4fe03871 100644
--- a/db/migrate/20180812173710_copy_status_stats.rb
+++ b/db/migrate/20180812173710_copy_status_stats.rb
@@ -27,7 +27,7 @@ class CopyStatusStats < ActiveRecord::Migration[5.2]
say 'Upsert is available, importing counters using the fast method'
Status.unscoped.select('id').find_in_batches(batch_size: 5_000) do |statuses|
- execute <<-SQL.squish
+ execute <<~SQL.squish
INSERT INTO status_stats (status_id, reblogs_count, favourites_count, created_at, updated_at)
SELECT id, reblogs_count, favourites_count, created_at, updated_at
FROM statuses
diff --git a/db/migrate/20181116173541_copy_account_stats.rb b/db/migrate/20181116173541_copy_account_stats.rb
index e5faee0cb5f..f80d71b7776 100644
--- a/db/migrate/20181116173541_copy_account_stats.rb
+++ b/db/migrate/20181116173541_copy_account_stats.rb
@@ -31,7 +31,7 @@ class CopyAccountStats < ActiveRecord::Migration[5.2]
say 'Upsert is available, importing counters using the fast method'
MigrationAccount.unscoped.select('id').find_in_batches(batch_size: 5_000) do |accounts|
- execute <<-SQL.squish
+ execute <<~SQL.squish
INSERT INTO account_stats (account_id, statuses_count, following_count, followers_count, created_at, updated_at)
SELECT id, statuses_count, following_count, followers_count, created_at, updated_at
FROM accounts
diff --git a/db/migrate/20220613110711_migrate_custom_filters.rb b/db/migrate/20220613110711_migrate_custom_filters.rb
index ea6a9b8c6d1..f3b2e01a06a 100644
--- a/db/migrate/20220613110711_migrate_custom_filters.rb
+++ b/db/migrate/20220613110711_migrate_custom_filters.rb
@@ -5,7 +5,7 @@ class MigrateCustomFilters < ActiveRecord::Migration[6.1]
# Preserve IDs as much as possible to not confuse existing clients.
# As long as this migration is irreversible, we do not have to deal with conflicts.
safety_assured do
- execute <<-SQL.squish
+ execute <<~SQL.squish
INSERT INTO custom_filter_keywords (id, custom_filter_id, keyword, whole_word, created_at, updated_at)
SELECT id, id, phrase, whole_word, created_at, updated_at
FROM custom_filters
@@ -16,7 +16,7 @@ class MigrateCustomFilters < ActiveRecord::Migration[6.1]
def down
# Copy back changes from custom filters guaranteed to be from the old API
safety_assured do
- execute <<-SQL.squish
+ execute <<~SQL.squish
UPDATE custom_filters
SET phrase = custom_filter_keywords.keyword, whole_word = custom_filter_keywords.whole_word
FROM custom_filter_keywords
@@ -26,7 +26,7 @@ class MigrateCustomFilters < ActiveRecord::Migration[6.1]
# Drop every keyword as we can't safely provide a 1:1 mapping
safety_assured do
- execute <<-SQL.squish
+ execute <<~SQL.squish
TRUNCATE custom_filter_keywords RESTART IDENTITY
SQL
end
diff --git a/db/migrate/20260115153219_use_snowflake_ids_for_collections.rb b/db/migrate/20260115153219_use_snowflake_ids_for_collections.rb
new file mode 100644
index 00000000000..25aad0732ed
--- /dev/null
+++ b/db/migrate/20260115153219_use_snowflake_ids_for_collections.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class UseSnowflakeIdsForCollections < ActiveRecord::Migration[8.0]
+ def up
+ safety_assured do
+ execute(<<~SQL.squish)
+ ALTER TABLE collections ALTER COLUMN id SET DEFAULT timestamp_id('collections');
+ ALTER TABLE collection_items ALTER COLUMN id SET DEFAULT timestamp_id('collection_items');
+ SQL
+ end
+
+ Mastodon::Snowflake.ensure_id_sequences_exist
+ end
+
+ def down
+ execute(<<~SQL.squish)
+ LOCK collections;
+ SELECT setval('collections_id_seq', (SELECT MAX(id) FROM collections));
+ ALTER TABLE collections ALTER COLUMN id SET DEFAULT nextval('collections_id_seq');
+ LOCK collection_items;
+ SELECT setval('collection_items_id_seq', (SELECT MAX(id) FROM collection_items));
+ ALTER TABLE collection_items ALTER COLUMN id SET DEFAULT nextval('collection_items_id_seq');
+ SQL
+ end
+end
diff --git a/db/migrate/20260119153538_add_language_to_collections.rb b/db/migrate/20260119153538_add_language_to_collections.rb
new file mode 100644
index 00000000000..066288b070a
--- /dev/null
+++ b/db/migrate/20260119153538_add_language_to_collections.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddLanguageToCollections < ActiveRecord::Migration[8.0]
+ def change
+ add_column :collections, :language, :string
+ end
+end
diff --git a/db/migrate/20260127141459_add_avatar_description_to_accounts.rb b/db/migrate/20260127141459_add_avatar_description_to_accounts.rb
new file mode 100644
index 00000000000..831342c50cb
--- /dev/null
+++ b/db/migrate/20260127141459_add_avatar_description_to_accounts.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddAvatarDescriptionToAccounts < ActiveRecord::Migration[8.0]
+ def change
+ add_column :accounts, :avatar_description, :string, null: false, default: ''
+ end
+end
diff --git a/db/migrate/20260127141820_add_header_description_to_accounts.rb b/db/migrate/20260127141820_add_header_description_to_accounts.rb
new file mode 100644
index 00000000000..74d03d5c851
--- /dev/null
+++ b/db/migrate/20260127141820_add_header_description_to_accounts.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddHeaderDescriptionToAccounts < ActiveRecord::Migration[8.0]
+ def change
+ add_column :accounts, :header_description, :string, null: false, default: ''
+ end
+end
diff --git a/db/post_migrate/20190519130537_remove_boosts_widening_audience.rb b/db/post_migrate/20190519130537_remove_boosts_widening_audience.rb
index 89a95041ee0..8faeba7be0b 100644
--- a/db/post_migrate/20190519130537_remove_boosts_widening_audience.rb
+++ b/db/post_migrate/20190519130537_remove_boosts_widening_audience.rb
@@ -4,7 +4,7 @@ class RemoveBoostsWideningAudience < ActiveRecord::Migration[5.2]
disable_ddl_transaction!
def up
- public_boosts = Status.find_by_sql(<<-SQL.squish)
+ public_boosts = Status.find_by_sql(<<~SQL.squish)
SELECT boost.id
FROM statuses AS boost
LEFT JOIN statuses AS boosted ON boost.reblog_of_id = boosted.id
diff --git a/db/post_migrate/20220729171123_fix_custom_filter_keywords_id_seq.rb b/db/post_migrate/20220729171123_fix_custom_filter_keywords_id_seq.rb
index eb437c86c5a..edc689a7164 100644
--- a/db/post_migrate/20220729171123_fix_custom_filter_keywords_id_seq.rb
+++ b/db/post_migrate/20220729171123_fix_custom_filter_keywords_id_seq.rb
@@ -7,7 +7,7 @@ class FixCustomFilterKeywordsIdSeq < ActiveRecord::Migration[6.1]
# 20220613110711 manually inserts items with set `id` in the database, but
# we also need to bump the sequence number, otherwise
safety_assured do
- execute <<-SQL.squish
+ execute <<~SQL.squish
BEGIN;
LOCK TABLE custom_filter_keywords IN EXCLUSIVE MODE;
SELECT setval('custom_filter_keywords_id_seq'::regclass, id) FROM custom_filter_keywords ORDER BY id DESC LIMIT 1;
diff --git a/db/schema.rb b/db/schema.rb
index 78d7ef68261..9080de8fb89 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[8.0].define(version: 2025_12_17_091936) do
+ActiveRecord::Schema[8.0].define(version: 2026_01_27_141820) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
@@ -201,6 +201,8 @@ ActiveRecord::Schema[8.0].define(version: 2025_12_17_091936) do
t.string "following_url", default: "", null: false
t.integer "id_scheme", default: 1
t.integer "feature_approval_policy", default: 0, null: false
+ t.string "avatar_description", default: "", null: false
+ t.string "header_description", default: "", null: false
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"
@@ -352,7 +354,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_12_17_091936) do
t.index ["reference_account_id"], name: "index_canonical_email_blocks_on_reference_account_id"
end
- create_table "collection_items", force: :cascade do |t|
+ create_table "collection_items", id: :bigint, default: -> { "timestamp_id('collection_items'::text)" }, force: :cascade do |t|
t.bigint "collection_id", null: false
t.bigint "account_id"
t.integer "position", default: 1, null: false
@@ -369,7 +371,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_12_17_091936) do
t.index ["object_uri"], name: "index_collection_items_on_object_uri", unique: true, where: "(activity_uri IS NOT NULL)"
end
- create_table "collections", force: :cascade do |t|
+ create_table "collections", id: :bigint, default: -> { "timestamp_id('collections'::text)" }, force: :cascade do |t|
t.bigint "account_id", null: false
t.string "name", null: false
t.text "description", null: false
@@ -382,6 +384,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_12_17_091936) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "item_count", default: 0, null: false
+ t.string "language"
t.index ["account_id"], name: "index_collections_on_account_id"
t.index ["tag_id"], name: "index_collections_on_tag_id"
end
diff --git a/docker-compose.yml b/docker-compose.yml
index d4974eb1bdd..52d2a83f443 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -59,7 +59,7 @@ services:
web:
# 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.5.4
+ image: ghcr.io/mastodon/mastodon:v4.5.5
restart: always
env_file: .env.production
command: bundle exec puma -C config/puma.rb
@@ -83,7 +83,7 @@ services:
# build:
# dockerfile: ./streaming/Dockerfile
# context: .
- image: ghcr.io/mastodon/mastodon-streaming:v4.5.4
+ image: ghcr.io/mastodon/mastodon-streaming:v4.5.5
restart: always
env_file: .env.production
command: node ./streaming/index.js
@@ -102,7 +102,7 @@ services:
sidekiq:
# 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.5.4
+ image: ghcr.io/mastodon/mastodon:v4.5.5
restart: always
env_file: .env.production
command: bundle exec sidekiq
diff --git a/eslint.config.mjs b/eslint.config.mjs
index a9dc9732bfc..c7ba755d67e 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -399,6 +399,7 @@ export default tseslint.config([
allowNumber: true,
},
],
+ '@typescript-eslint/non-nullable-type-assertion-style': 'off',
},
},
{
diff --git a/lib/mastodon/cli/media.rb b/lib/mastodon/cli/media.rb
index 02c9894c36d..4a1e7574067 100644
--- a/lib/mastodon/cli/media.rb
+++ b/lib/mastodon/cli/media.rb
@@ -17,6 +17,7 @@ module Mastodon::CLI
option :concurrency, type: :numeric, default: 5, aliases: [:c]
option :verbose, type: :boolean, default: false, aliases: [:v]
option :dry_run, type: :boolean, default: false
+ option :keep_interacted, type: :boolean, default: false
desc 'remove', 'Remove remote media files, headers or avatars'
long_desc <<-DESC
Removes locally cached copies of media attachments (and optionally profile
@@ -26,6 +27,9 @@ module Mastodon::CLI
they are removed. In case of avatars and headers, it specifies how old
the last webfinger request and update to the user has to be before they
are pruned. It defaults to 7 days.
+ If --keep-interacted is specified, any media attached to a status that
+ was favourited, bookmarked, quoted, replied to, or reblogged by a local
+ account will be preserved.
If --prune-profiles is specified, only avatars and headers are removed.
If --remove-headers is specified, only headers are removed.
If --include-follows is specified along with --prune-profiles or
@@ -61,7 +65,11 @@ module Mastodon::CLI
end
unless options[:prune_profiles] || options[:remove_headers]
- processed, aggregate = parallelize_with_progress(MediaAttachment.cached.remote.where(created_at: ..time_ago)) do |media_attachment|
+ attachment_scope = MediaAttachment.cached.remote.where(created_at: ..time_ago)
+
+ attachment_scope = attachment_scope.without_local_interaction if options[:keep_interacted]
+
+ processed, aggregate = parallelize_with_progress(attachment_scope) do |media_attachment|
next if media_attachment.file.blank?
size = (media_attachment.file_file_size || 0) + (media_attachment.thumbnail_file_size || 0)
diff --git a/lib/mastodon/cli/statuses.rb b/lib/mastodon/cli/statuses.rb
index 7188bc970ce..df0fcf0fbb0 100644
--- a/lib/mastodon/cli/statuses.rb
+++ b/lib/mastodon/cli/statuses.rb
@@ -52,7 +52,7 @@ module Mastodon::CLI
# Skip accounts followed by local accounts
clean_followed_sql = 'AND NOT EXISTS (SELECT 1 FROM follows WHERE statuses.account_id = follows.target_account_id)' unless options[:clean_followed]
- ActiveRecord::Base.connection.exec_insert(<<-SQL.squish, 'SQL', [max_id])
+ ActiveRecord::Base.connection.exec_insert(<<~SQL.squish, 'SQL', [max_id])
INSERT INTO statuses_to_be_deleted (id)
SELECT statuses.id FROM statuses WHERE deleted_at IS NULL AND NOT local AND uri IS NOT NULL AND (id < $1)
AND NOT EXISTS (SELECT 1 FROM statuses AS statuses1 WHERE statuses.id = statuses1.in_reply_to_id)
@@ -137,7 +137,7 @@ module Mastodon::CLI
ActiveRecord::Base.connection.create_table('conversations_to_be_deleted', force: true)
- ActiveRecord::Base.connection.exec_insert(<<-SQL.squish, 'SQL')
+ ActiveRecord::Base.connection.exec_insert(<<~SQL.squish, 'SQL')
INSERT INTO conversations_to_be_deleted (id)
SELECT id FROM conversations WHERE NOT EXISTS (SELECT 1 FROM statuses WHERE statuses.conversation_id = conversations.id)
SQL
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index 235ac92cbd6..f532276f85e 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -17,7 +17,7 @@ module Mastodon
end
def default_prerelease
- 'alpha.2'
+ 'alpha.3'
end
def prerelease
diff --git a/lib/paperclip/attachment_extensions.rb b/lib/paperclip/attachment_extensions.rb
index 011e165ed74..7141adc9edc 100644
--- a/lib/paperclip/attachment_extensions.rb
+++ b/lib/paperclip/attachment_extensions.rb
@@ -16,8 +16,7 @@ module Paperclip
# if we're processing the original, close + unlink the source tempfile
intermediate_files << original if name == :original
- @queued_for_write[name] = style.processors
- .inject(original) do |file, processor|
+ @queued_for_write[name] = style.processors.inject(original) do |file, processor|
file = Paperclip.processor(processor).make(file, style.processor_options, self)
intermediate_files << file unless file == original
file
diff --git a/lib/paperclip/blurhash_transcoder.rb b/lib/paperclip/blurhash_transcoder.rb
index b4ff4a12a0e..e9ff1dd9dd8 100644
--- a/lib/paperclip/blurhash_transcoder.rb
+++ b/lib/paperclip/blurhash_transcoder.rb
@@ -19,14 +19,8 @@ module Paperclip
private
def blurhash_params
- if Rails.configuration.x.use_vips
- image = Vips::Image.thumbnail(@file.path, 100)
- [image.width, image.height, image.colourspace(:srgb).extract_band(0, n: 3).to_a.flatten]
- else
- pixels = convert(':source -depth 8 RGB:-', source: File.expand_path(@file.path)).unpack('C*')
- geometry = options.fetch(:file_geometry_parser).from_file(@file)
- [geometry.width, geometry.height, pixels]
- end
+ image = Vips::Image.thumbnail(@file.path, 100)
+ [image.width, image.height, image.colourspace(:srgb).extract_band(0, n: 3).to_a.flatten]
end
end
end
diff --git a/lib/paperclip/color_extractor.rb b/lib/paperclip/color_extractor.rb
index 62daa077952..1c9ef4bd3d6 100644
--- a/lib/paperclip/color_extractor.rb
+++ b/lib/paperclip/color_extractor.rb
@@ -10,7 +10,7 @@ module Paperclip
BINS = 10
def make
- background_palette, foreground_palette = Rails.configuration.x.use_vips ? palettes_from_libvips : palettes_from_imagemagick
+ background_palette, foreground_palette = palettes_from_libvips
background_color = background_palette.first || foreground_palette.first
foreground_colors = []
@@ -93,17 +93,6 @@ module Paperclip
[background_palette, foreground_palette]
end
- def palettes_from_imagemagick
- depth = 8
-
- # Determine background palette by getting colors close to the image's edge only
- background_palette = palette_from_im_histogram(convert(':source -alpha set -gravity Center -region 75%x75% -fill None -colorize 100% -alpha transparent +region -format %c -colors :quantity -depth :depth histogram:info:', source: File.expand_path(@file.path), quantity: 10, depth: depth), 10)
-
- # Determine foreground palette from the whole image
- foreground_palette = palette_from_im_histogram(convert(':source -format %c -colors :quantity -depth :depth histogram:info:', source: File.expand_path(@file.path), quantity: 10, depth: depth), 10)
- [background_palette, foreground_palette]
- end
-
def downscaled_image
image = Vips::Image.new_from_file(@file.path, access: :random).thumbnail_image(100)
diff --git a/package.json b/package.json
index 8a1ecc77374..aca5bd82feb 100644
--- a/package.json
+++ b/package.json
@@ -40,7 +40,7 @@
},
"private": true,
"dependencies": {
- "@csstools/stylelint-formatter-github": "^1.0.0",
+ "@csstools/stylelint-formatter-github": "^2.0.0",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
@@ -85,7 +85,7 @@
"lodash": "^4.17.21",
"marky": "^1.2.5",
"path-complete-extname": "^1.0.0",
- "postcss-preset-env": "^10.1.5",
+ "postcss-preset-env": "^11.0.0",
"prop-types": "^15.8.1",
"punycode": "^2.3.0",
"react": "^18.2.0",
@@ -175,7 +175,7 @@
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-storybook": "^10.0.2",
"fake-indexeddb": "^6.0.1",
- "globals": "^16.0.0",
+ "globals": "^17.0.0",
"husky": "^9.0.11",
"lint-staged": "^16.2.6",
"msw": "^2.12.1",
@@ -184,9 +184,9 @@
"prettier": "^3.3.3",
"react-test-renderer": "^18.2.0",
"storybook": "^10.0.5",
- "stylelint": "^16.19.1",
+ "stylelint": "^17.0.0",
"stylelint-config-prettier-scss": "^1.0.0",
- "stylelint-config-standard-scss": "^16.0.0",
+ "stylelint-config-standard-scss": "^17.0.0",
"typescript": "~5.9.0",
"typescript-eslint": "^8.45.0",
"typescript-plugin-css-modules": "^5.2.0",
diff --git a/spec/controllers/oauth/authorizations_controller_spec.rb b/spec/controllers/oauth/authorizations_controller_spec.rb
deleted file mode 100644
index aa557b67d87..00000000000
--- a/spec/controllers/oauth/authorizations_controller_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe OAuth::AuthorizationsController do
- render_views
-
- let(:app) { Doorkeeper::Application.create!(name: 'test', redirect_uri: 'http://localhost/', scopes: 'read') }
-
- describe 'GET #new' do
- subject do
- get :new, params: { client_id: app.uid, response_type: 'code', redirect_uri: 'http://localhost/', scope: 'read' }
- end
-
- context 'when signed in' do
- let!(:user) { Fabricate(:user) }
-
- before do
- sign_in user, scope: :user
- end
-
- it 'returns http success and private cache control headers' do
- subject
-
- expect(response)
- .to have_http_status(200)
- expect(response.headers['Cache-Control'])
- .to include('private, no-store')
- expect(response.parsed_body.at('body.modal-layout'))
- .to be_present
- expect(controller.stored_location_for(:user))
- .to eq authorize_path_for(app)
- end
-
- context 'when app is already authorized' do
- before do
- Doorkeeper::AccessToken.find_or_create_for(
- application: app,
- resource_owner: user.id,
- scopes: app.scopes,
- expires_in: Doorkeeper.configuration.access_token_expires_in,
- use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?
- )
- end
-
- it 'redirects to callback' do
- subject
- expect(response).to redirect_to(/\A#{app.redirect_uri}/)
- end
-
- 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
-
- it { is_expected.to have_http_status(:success) }
- end
- end
- end
-
- context 'when not signed in' do
- it 'redirects' do
- subject
-
- 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/settings/aliases_controller_spec.rb b/spec/controllers/settings/aliases_controller_spec.rb
deleted file mode 100644
index 4858c15298c..00000000000
--- a/spec/controllers/settings/aliases_controller_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Settings::AliasesController do
- render_views
-
- let!(:user) { Fabricate(:user) }
- let(:account) { user.account }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #index' do
- before do
- 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 'POST #create' do
- context 'with valid alias' do
- before { stub_resolver }
-
- it 'creates an alias for the user' do
- expect do
- post :create, params: { account_alias: { acct: 'new@example.com' } }
- end.to change(AccountAlias, :count).by(1)
-
- expect(response).to redirect_to(settings_aliases_path)
- end
- end
-
- context 'with invalid alias' do
- it 'does not create an alias for the user' do
- expect do
- post :create, params: { account_alias: { acct: 'format-wrong' } }
- end.to_not change(AccountAlias, :count)
-
- expect(response).to have_http_status(200)
- end
- end
- end
-
- describe 'DELETE #destroy' do
- let(:account_alias) do
- AccountAlias.new(account: user.account, acct: 'new@example.com').tap do |account_alias|
- account_alias.save(validate: false)
- end
- end
-
- it 'removes an alias' do
- delete :destroy, params: { id: account_alias.id }
-
- expect(response).to redirect_to(settings_aliases_path)
- expect { account_alias.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- private
-
- def stub_resolver
- resolver = instance_double(ResolveAccountService, call: Fabricate(:account))
- allow(ResolveAccountService).to receive(:new).and_return(resolver)
- end
-end
diff --git a/spec/helpers/theme_helper_spec.rb b/spec/helpers/theme_helper_spec.rb
index 9eefa01f902..a4028857114 100644
--- a/spec/helpers/theme_helper_spec.rb
+++ b/spec/helpers/theme_helper_spec.rb
@@ -9,17 +9,10 @@ RSpec.describe ThemeHelper do
context 'when using "system" theme' do
let(:theme) { 'system' }
- it 'returns the mastodon-light and application stylesheets with correct color schemes' do
+ it 'returns the default theme' do
expect(html_links.first.attributes.symbolize_keys)
.to include(
- # This is now identical to the default theme & will be unified very soon
- href: have_attributes(value: match(/default/)),
- media: have_attributes(value: 'not all and (prefers-color-scheme: dark)')
- )
- expect(html_links.last.attributes.symbolize_keys)
- .to include(
- href: have_attributes(value: match(/default/)),
- media: have_attributes(value: '(prefers-color-scheme: dark)')
+ href: have_attributes(value: match(/default/))
)
end
end
@@ -41,20 +34,19 @@ RSpec.describe ThemeHelper do
it 'returns the theme stylesheet without color scheme information' do
expect(html_links.first.attributes.symbolize_keys)
.to include(
- href: have_attributes(value: match(/contrast/)),
- media: have_attributes(value: 'all')
+ href: have_attributes(value: match(/default/))
)
end
end
end
describe 'theme_color_tags' do
- let(:result) { helper.theme_color_tags(theme) }
+ let(:result) { helper.theme_color_tags(color_scheme) }
context 'when using system theme' do
- let(:theme) { 'system' }
+ let(:color_scheme) { 'auto' }
- it 'returns the mastodon-light and default stylesheets with correct color schemes' do
+ it 'returns both color schemes with appropriate media queries' do
expect(html_theme_colors.first.attributes.symbolize_keys)
.to include(
content: have_attributes(value: Themes::THEME_COLORS[:dark]),
@@ -68,10 +60,10 @@ RSpec.describe ThemeHelper do
end
end
- context 'when using mastodon-light theme' do
- let(:theme) { 'mastodon-light' }
+ context 'when light color scheme' do
+ let(:color_scheme) { 'light' }
- it 'returns the theme stylesheet without color scheme information' do
+ it 'returns the light color' do
expect(html_theme_colors.first.attributes.symbolize_keys)
.to include(
content: have_attributes(value: Themes::THEME_COLORS[:light])
@@ -79,10 +71,10 @@ RSpec.describe ThemeHelper do
end
end
- context 'when using other theme' do
- let(:theme) { 'contrast' }
+ context 'when using dark color scheme' do
+ let(:color_scheme) { 'dark' }
- it 'returns the theme stylesheet without color scheme information' do
+ it 'returns the dark color' do
expect(html_theme_colors.first.attributes.symbolize_keys)
.to include(
content: have_attributes(value: Themes::THEME_COLORS[:dark])
diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb
index 1e8a2a29db4..19b6014af15 100644
--- a/spec/lib/activitypub/activity/create_spec.rb
+++ b/spec/lib/activitypub/activity/create_spec.rb
@@ -471,7 +471,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
- context 'with a reply' do
+ context 'with a reply without explicitly setting a conversation' do
let(:original_status) { Fabricate(:status) }
let(:object_json) do
@@ -493,6 +493,30 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
+ context 'with a reply explicitly setting a conversation' do
+ let(:original_status) { Fabricate(:status) }
+
+ let(:object_json) do
+ build_object(
+ inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status),
+ conversation: ActivityPub::TagManager.instance.uri_for(original_status.conversation),
+ context: ActivityPub::TagManager.instance.uri_for(original_status.conversation)
+ )
+ end
+
+ it 'creates status' do
+ expect { subject.perform }.to change(sender.statuses, :count).by(1)
+
+ status = sender.statuses.first
+
+ expect(status).to_not be_nil
+ expect(status.thread).to eq original_status
+ expect(status.reply?).to be true
+ expect(status.in_reply_to_account).to eq original_status.account
+ expect(status.conversation).to eq original_status.conversation
+ end
+ end
+
context 'with mentions' do
let(:recipient) { Fabricate(:account) }
diff --git a/spec/lib/activitypub/tag_manager_spec.rb b/spec/lib/activitypub/tag_manager_spec.rb
index bacbb3251cc..a15529057cb 100644
--- a/spec/lib/activitypub/tag_manager_spec.rb
+++ b/spec/lib/activitypub/tag_manager_spec.rb
@@ -198,7 +198,7 @@ RSpec.describe ActivityPub::TagManager do
it 'returns a string starting with web domain and with the expected path' do
expect(subject.uri_for(collection))
- .to eq("#{host_prefix}/ap/users/#{collection.account.id}/featured_collections/#{collection.id}")
+ .to eq("#{host_prefix}/ap/users/#{collection.account.id}/collections/#{collection.id}")
end
end
@@ -629,14 +629,6 @@ RSpec.describe ActivityPub::TagManager do
end
end
- describe '#uri_to_local_id' do
- let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
-
- it 'returns the local ID' do
- expect(subject.uri_to_local_id(subject.uri_for(account), :username)).to eq account.username
- end
- end
-
describe '#uris_to_local_accounts' do
it 'returns the expected local accounts' do
account = Fabricate(:account)
diff --git a/spec/lib/mastodon/cli/media_spec.rb b/spec/lib/mastodon/cli/media_spec.rb
index fa7a3161d09..da66951c3bc 100644
--- a/spec/lib/mastodon/cli/media_spec.rb
+++ b/spec/lib/mastodon/cli/media_spec.rb
@@ -73,6 +73,66 @@ RSpec.describe Mastodon::CLI::Media do
expect(media_attachment.reload.thumbnail).to be_blank
end
end
+
+ context 'with --keep-interacted' do
+ let(:options) { { keep_interacted: true } }
+
+ let!(:favourited_media) { Fabricate(:media_attachment, created_at: 1.month.ago, remote_url: 'https://example.com/image.jpg') }
+ let!(:bookmarked_media) { Fabricate(:media_attachment, created_at: 1.month.ago, remote_url: 'https://example.com/image.jpg') }
+ let!(:replied_to_media) { Fabricate(:media_attachment, created_at: 1.month.ago, remote_url: 'https://example.com/image.jpg') }
+ let!(:reblogged_media) { Fabricate(:media_attachment, created_at: 1.month.ago, remote_url: 'https://example.com/image.jpg') }
+ let!(:remote_quoted_media) { Fabricate(:media_attachment, created_at: 1.month.ago, remote_url: 'https://example.com/image.jpg') }
+ let!(:remote_quoting_media) { Fabricate(:media_attachment, created_at: 1.month.ago, remote_url: 'https://example.com/image.jpg') }
+
+ before do
+ local_account = Fabricate(:account, username: 'alice')
+ remote_account = Fabricate(:account, username: 'bob', domain: 'example.com')
+
+ favourited_status = Fabricate(:status, account: remote_account)
+ bookmarked_status = Fabricate(:status, account: remote_account)
+ replied_to_status = Fabricate(:status, account: remote_account)
+ reblogged_status = Fabricate(:status, account: remote_account)
+
+ favourited_media.update!(status: favourited_status)
+ bookmarked_media.update!(status: bookmarked_status)
+ replied_to_media.update!(status: replied_to_status)
+ reblogged_media.update!(status: reblogged_status)
+
+ local_quoting_status = Fabricate(:status, account: local_account)
+ remote_quoted_status = Fabricate(:status, account: remote_account)
+ local_status_being_quoted = Fabricate(:status, account: local_account)
+ remote_quoting_status = Fabricate(:status, account: remote_account)
+
+ remote_quoted_media.update!(status: remote_quoted_status)
+ remote_quoting_media.update!(status: remote_quoting_status)
+
+ non_interacted_status = Fabricate(:status, account: remote_account)
+
+ media_attachment.update(status: non_interacted_status)
+
+ Fabricate(:favourite, account: local_account, status: favourited_status)
+ Fabricate(:bookmark, account: local_account, status: bookmarked_status)
+ Fabricate(:status, account: local_account, in_reply_to_id: replied_to_status.id)
+ Fabricate(:status, account: local_account, reblog: reblogged_status)
+ Fabricate(:quote, account: local_account, status: local_quoting_status, quoted_status: remote_quoted_status)
+ Fabricate(:quote, account: remote_account, status: remote_quoting_status, quoted_status: local_status_being_quoted)
+ end
+
+ it 'keeps media associated with statuses that have been favourited, bookmarked, replied to, or reblogged by a local account' do
+ expect { subject }
+ .to output_results('Removed 1')
+
+ expect(favourited_media.reload.file).to be_present
+ expect(bookmarked_media.reload.file).to be_present
+ expect(replied_to_media.reload.file).to be_present
+ expect(reblogged_media.reload.file).to be_present
+ expect(remote_quoted_media.reload.file).to be_present
+ expect(remote_quoting_media.reload.file).to be_present
+
+ expect(media_attachment.reload.file).to be_blank
+ expect(media_attachment.reload.thumbnail).to be_blank
+ end
+ end
end
end
diff --git a/spec/lib/tag_manager_spec.rb b/spec/lib/tag_manager_spec.rb
index 38203a55f70..927214bb40c 100644
--- a/spec/lib/tag_manager_spec.rb
+++ b/spec/lib/tag_manager_spec.rb
@@ -54,12 +54,44 @@ RSpec.describe TagManager do
end
describe '#normalize_domain' do
- it 'returns nil if the given parameter is nil' do
- expect(described_class.instance.normalize_domain(nil)).to be_nil
+ subject { described_class.instance.normalize_domain(domain) }
+
+ context 'with a nil value' do
+ let(:domain) { nil }
+
+ it { is_expected.to be_nil }
end
- it 'returns normalized domain' do
- expect(described_class.instance.normalize_domain('DoMaIn.Example.com/')).to eq 'domain.example.com'
+ context 'with a blank value' do
+ let(:domain) { '' }
+
+ it { is_expected.to be_blank }
+ end
+
+ context 'with a mixed case string' do
+ let(:domain) { 'DoMaIn.Example.com' }
+
+ it { is_expected.to eq('domain.example.com') }
+ end
+
+ context 'with a trailing slash string' do
+ let(:domain) { 'domain.example.com/' }
+
+ it { is_expected.to eq('domain.example.com') }
+ end
+
+ context 'with a space padded string' do
+ let(:domain) { ' domain.example.com ' }
+
+ it { is_expected.to eq('domain.example.com') }
+ end
+
+ context 'with an invalid domain string' do
+ let(:domain) { ' !@#$@#$@$@# ' }
+
+ it 'raises invalid uri error' do
+ expect { subject }.to raise_error(Addressable::URI::InvalidURIError)
+ end
end
end
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
index 89a2f78c2e1..ca85b0fbfcd 100644
--- a/spec/models/account_spec.rb
+++ b/spec/models/account_spec.rb
@@ -6,6 +6,12 @@ RSpec.describe Account do
it_behaves_like 'Account::Search'
it_behaves_like 'Reviewable'
+ describe 'Associations' do
+ it { is_expected.to have_many(:account_notes).inverse_of(:account) }
+ it { is_expected.to have_many(:action_logs).class_name('Admin::ActionLog') }
+ it { is_expected.to have_many(:targeted_account_notes).inverse_of(:target_account) }
+ end
+
context 'with an account record' do
subject { Fabricate(:account) }
@@ -564,6 +570,8 @@ RSpec.describe Account do
it { is_expected.to_not allow_values('username', 'Username').for(:username) }
end
+ it { is_expected.to validate_length_of(:username).is_at_most(described_class::USERNAME_LENGTH_HARD_LIMIT) }
+
it { is_expected.to allow_values('the-doctor', username_over_limit).for(:username) }
it { is_expected.to_not allow_values('the doctor').for(:username) }
diff --git a/spec/models/collection_spec.rb b/spec/models/collection_spec.rb
index bcc31fd0877..b50969b68a9 100644
--- a/spec/models/collection_spec.rb
+++ b/spec/models/collection_spec.rb
@@ -16,12 +16,18 @@ RSpec.describe Collection do
it { is_expected.to_not allow_value(nil).for(:discoverable) }
+ it { is_expected.to allow_value('en').for(:language) }
+
+ it { is_expected.to_not allow_value('randomstuff').for(:language) }
+
context 'when collection is remote' do
subject { Fabricate.build :collection, local: false }
it { is_expected.to validate_presence_of(:uri) }
it { is_expected.to validate_presence_of(:original_number_of_items) }
+
+ it { is_expected.to allow_value('randomstuff').for(:language) }
end
context 'when using a hashtag as category' do
diff --git a/spec/models/concerns/account/counters_spec.rb b/spec/models/concerns/account/counters_spec.rb
index bbbaa7d06c9..17c63dd0e81 100644
--- a/spec/models/concerns/account/counters_spec.rb
+++ b/spec/models/concerns/account/counters_spec.rb
@@ -21,6 +21,28 @@ RSpec.describe Account::Counters do
expect(account.statuses_count).to eq increment_by
end
+
+ it 'updates last_status_at when discovering a new post' do
+ status_created_at = Time.now.utc
+
+ expect { account.increment_count!(:statuses_count, status_created_at:) }
+ .to(change { account.reload.last_status_at })
+ end
+
+ it 'does not update last_status_at when discovering an older post' do
+ account_stat = Fabricate(
+ :account_stat,
+ account: account,
+ last_status_at: 1.day.ago.utc,
+ statuses_count: 10
+ )
+
+ status_created_at = 2.days.ago.utc
+
+ expect { account.increment_count!(:statuses_count, status_created_at:) }
+ .to change { account_stat.reload.statuses_count }
+ .and(not_change { account_stat.reload.last_status_at })
+ end
end
describe '#decrement_count!' do
diff --git a/spec/models/concerns/account/interactions_spec.rb b/spec/models/concerns/account/interactions_spec.rb
index cc50c465517..5bca7959080 100644
--- a/spec/models/concerns/account/interactions_spec.rb
+++ b/spec/models/concerns/account/interactions_spec.rb
@@ -450,6 +450,44 @@ RSpec.describe Account::Interactions do
end
end
+ describe '#blocking_or_domain_blocking?' do
+ subject { account.blocking_or_domain_blocking?(target_account) }
+
+ context 'when blocking target_account' do
+ before do
+ account.block_relationships.create(target_account: target_account)
+ end
+
+ it 'returns true' do
+ result = nil
+ expect { result = subject }.to execute_queries
+
+ expect(result).to be true
+ end
+ end
+
+ context 'when blocking the domain' do
+ let(:target_account) { Fabricate(:remote_account) }
+
+ before do
+ account_domain_block = Fabricate(:account_domain_block, domain: target_account.domain)
+ account.domain_blocks << account_domain_block
+ end
+
+ it 'returns true' do
+ result = nil
+ expect { result = subject }.to execute_queries
+ expect(result).to be true
+ end
+ end
+
+ context 'when blocking neither target_account nor its domain' do
+ it 'returns false' do
+ expect(subject).to be false
+ end
+ end
+ end
+
describe '#muting?' do
subject { account.muting?(target_account) }
diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb
index 244d0d126f1..ab757d39683 100644
--- a/spec/models/custom_emoji_spec.rb
+++ b/spec/models/custom_emoji_spec.rb
@@ -90,8 +90,14 @@ RSpec.describe CustomEmoji, :attachment_processing 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 validate_length_of(:shortcode).is_at_least(described_class::MINIMUM_SHORTCODE_SIZE).is_at_most(described_class::MAX_SHORTCODE_SIZE) }
it { is_expected.to allow_values('cats').for(:shortcode) }
it { is_expected.to_not allow_values('@#$@#$', 'X').for(:shortcode) }
+
+ context 'when remote' do
+ subject { Fabricate.build :custom_emoji, domain: 'host.example' }
+
+ it { is_expected.to validate_length_of(:shortcode).is_at_most(described_class::MAX_FEDERATED_SHORTCODE_SIZE) }
+ end
end
end
diff --git a/spec/models/custom_filter_keyword_spec.rb b/spec/models/custom_filter_keyword_spec.rb
index 4e3ab060a04..cc6558ea693 100644
--- a/spec/models/custom_filter_keyword_spec.rb
+++ b/spec/models/custom_filter_keyword_spec.rb
@@ -3,6 +3,11 @@
require 'rails_helper'
RSpec.describe CustomFilterKeyword do
+ describe 'Validations' do
+ it { is_expected.to validate_length_of(:keyword).is_at_most(described_class::KEYWORD_LENGTH_LIMIT) }
+ it { is_expected.to validate_presence_of(:keyword) }
+ end
+
describe '#to_regex' do
context 'when whole_word is true' do
it 'builds a regex with boundaries and the keyword' do
diff --git a/spec/models/custom_filter_spec.rb b/spec/models/custom_filter_spec.rb
index 03914fa6b48..8a60f1dd491 100644
--- a/spec/models/custom_filter_spec.rb
+++ b/spec/models/custom_filter_spec.rb
@@ -6,8 +6,9 @@ RSpec.describe CustomFilter do
it_behaves_like 'Expireable'
describe 'Validations' do
- it { is_expected.to validate_presence_of(:title) }
+ it { is_expected.to validate_length_of(:title).is_at_most(described_class::TITLE_LENGTH_LIMIT) }
it { is_expected.to validate_presence_of(:context) }
+ it { is_expected.to validate_presence_of(:title) }
it { is_expected.to_not allow_values([], %w(invalid)).for(:context) }
it { is_expected.to allow_values(%w(home)).for(:context) }
diff --git a/spec/models/instance_moderation_note_spec.rb b/spec/models/instance_moderation_note_spec.rb
index 4d77d497122..23e6e3d5e14 100644
--- a/spec/models/instance_moderation_note_spec.rb
+++ b/spec/models/instance_moderation_note_spec.rb
@@ -5,7 +5,7 @@ require 'rails_helper'
RSpec.describe InstanceModerationNote do
describe 'chronological' do
it 'returns the instance notes sorted by oldest first' do
- instance = Instance.find_or_initialize_by(domain: TagManager.instance.normalize_domain('mastodon.example'))
+ instance = Instance.find_or_initialize_by(domain: 'mastodon.example')
note1 = Fabricate(:instance_moderation_note, domain: instance.domain)
note2 = Fabricate(:instance_moderation_note, domain: instance.domain)
@@ -14,24 +14,12 @@ RSpec.describe InstanceModerationNote do
end
end
- describe 'validations' do
- it 'is invalid if the content is empty' do
- note = Fabricate.build(:instance_moderation_note, domain: 'mastodon.example', content: '')
- expect(note.valid?).to be false
- end
+ describe 'Validations' do
+ subject { Fabricate.build :instance_moderation_note }
- it 'is invalid if content is longer than character limit' do
- note = Fabricate.build(:instance_moderation_note, domain: 'mastodon.example', content: comment_over_limit)
- expect(note.valid?).to be false
- end
-
- it 'is valid even if the instance does not exist yet' do
- note = Fabricate.build(:instance_moderation_note, domain: 'non-existent.example', content: 'test comment')
- expect(note.valid?).to be true
- end
-
- def comment_over_limit
- Faker::Lorem.paragraph_by_chars(number: described_class::CONTENT_SIZE_LIMIT * 2)
- end
+ it { is_expected.to allow_value('non-existent.example').for(:domain) }
+ it { is_expected.to validate_length_of(:content).is_at_most(described_class::CONTENT_SIZE_LIMIT) }
+ it { is_expected.to validate_presence_of(:content) }
+ it { is_expected.to validate_presence_of(:domain) }
end
end
diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb
index e2d91835ec7..bc6e67d8bff 100644
--- a/spec/models/list_spec.rb
+++ b/spec/models/list_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe List do
describe 'Validations' do
subject { Fabricate.build :list }
+ it { is_expected.to validate_length_of(:title).is_at_most(described_class::TITLE_LENGTH_LIMIT) }
it { is_expected.to validate_presence_of(:title) }
context 'when account has hit max list limit' do
diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb
index a712cdde1dc..cbabb1d0dd3 100644
--- a/spec/models/media_attachment_spec.rb
+++ b/spec/models/media_attachment_spec.rb
@@ -219,9 +219,7 @@ RSpec.describe MediaAttachment, :attachment_processing do
describe 'ogg with cover art' do
let(:media) { Fabricate(:media_attachment, file: attachment_fixture('boop.ogg')) }
let(:expected_media_duration) { 0.235102 }
-
- # The libvips and ImageMagick implementations produce different results
- let(:expected_background_color) { Rails.configuration.x.use_vips ? '#268cd9' : '#3088d4' }
+ let(:expected_background_color) { '#268cd9' }
it 'sets correct file metadata' do
expect(media)
diff --git a/spec/models/preview_card_spec.rb b/spec/models/preview_card_spec.rb
index 0fe76c37b07..bac29046eac 100644
--- a/spec/models/preview_card_spec.rb
+++ b/spec/models/preview_card_spec.rb
@@ -3,12 +3,6 @@
require 'rails_helper'
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 'url' do
it { is_expected.to allow_values('http://example.host/path', 'https://example.host/path').for(:url) }
diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb
index 0bee7dfed1d..3fa545ee048 100644
--- a/spec/models/report_spec.rb
+++ b/spec/models/report_spec.rb
@@ -156,6 +156,10 @@ RSpec.describe Report do
end
end
+ describe 'Delegations' do
+ it { is_expected.to delegate_method(:local?).to(:account) }
+ end
+
describe 'Validations' do
let(:remote_account) { Fabricate(:account, domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox') }
diff --git a/spec/policies/account_policy_spec.rb b/spec/policies/account_policy_spec.rb
index f877bded252..96fcbdb4d82 100644
--- a/spec/policies/account_policy_spec.rb
+++ b/spec/policies/account_policy_spec.rb
@@ -188,4 +188,24 @@ RSpec.describe AccountPolicy do
end
end
end
+
+ permissions :index_collections? do
+ it 'permits when no user is given' do
+ expect(subject).to permit(nil, john)
+ end
+
+ it 'permits unblocked users' do
+ expect(subject).to permit(john, john)
+ expect(subject).to permit(alice, john)
+ end
+
+ it 'denies blocked users' do
+ domain_blocked_user = Fabricate(:remote_account)
+ john.block_domain!(domain_blocked_user.domain)
+ john.block!(alice)
+
+ expect(subject).to_not permit(domain_blocked_user, john)
+ expect(subject).to_not permit(alice, john)
+ end
+ end
end
diff --git a/spec/policies/announcement_policy_spec.rb b/spec/policies/announcement_policy_spec.rb
index 2fec34f8e4b..a78b016a61c 100644
--- a/spec/policies/announcement_policy_spec.rb
+++ b/spec/policies/announcement_policy_spec.rb
@@ -3,20 +3,45 @@
require 'rails_helper'
RSpec.describe AnnouncementPolicy do
- let(:policy) { described_class }
+ subject { described_class }
+
let(:admin) { Fabricate(:admin_user).account }
let(:john) { Fabricate(:account) }
permissions :index?, :create?, :update?, :destroy? do
context 'with an admin' do
- it 'permits' do
- expect(policy).to permit(admin, Announcement)
- end
+ it { is_expected.to permit(admin, Announcement) }
end
context 'with a non-admin' do
- it 'denies' do
- expect(policy).to_not permit(john, Announcement)
+ it { is_expected.to_not permit(john, Announcement) }
+ end
+ end
+
+ permissions :distribute? do
+ let(:announcement) { Fabricate :announcement }
+
+ context 'with non admin role' do
+ it { is_expected.to_not permit(john, announcement) }
+ end
+
+ context 'with admin role' do
+ context 'with unpublished announcement' do
+ let(:announcement) { Fabricate :announcement, published: false, scheduled_at: 5.days.from_now }
+
+ it { is_expected.to_not permit(admin, announcement) }
+ end
+
+ context 'with published already sent announcement' do
+ let(:announcement) { Fabricate :announcement, notification_sent_at: 3.days.ago }
+
+ it { is_expected.to_not permit(admin, announcement) }
+ end
+
+ context 'with published not sent announcement' do
+ let(:announcement) { Fabricate :announcement }
+
+ it { is_expected.to permit(admin, announcement) }
end
end
end
diff --git a/spec/policies/collection_policy_spec.rb b/spec/policies/collection_policy_spec.rb
index 156e1a76572..ecef6e899d9 100644
--- a/spec/policies/collection_policy_spec.rb
+++ b/spec/policies/collection_policy_spec.rb
@@ -16,11 +16,23 @@ RSpec.describe CollectionPolicy do
end
permissions :show? do
- it 'permits everyone to show' do
+ it 'permits when no user is given' do
expect(policy).to permit(nil, collection)
+ end
+
+ it 'permits unblocked users' do
expect(policy).to permit(owner, collection)
expect(policy).to permit(other_user, collection)
end
+
+ it 'denies blocked users' do
+ domain_blocked_user = Fabricate(:remote_account)
+ owner.block_domain!(domain_blocked_user.domain)
+ owner.block!(other_user)
+
+ expect(policy).to_not permit(domain_blocked_user, collection)
+ expect(policy).to_not permit(other_user, collection)
+ end
end
permissions :create? do
diff --git a/spec/policies/instance_moderation_note_policy_spec.rb b/spec/policies/instance_moderation_note_policy_spec.rb
new file mode 100644
index 00000000000..66b4e7f937f
--- /dev/null
+++ b/spec/policies/instance_moderation_note_policy_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe InstanceModerationNotePolicy do
+ subject { described_class }
+
+ let(:admin) { Fabricate(:admin_user).account }
+ let(:account) { Fabricate(:account) }
+
+ permissions :create? do
+ context 'when admin' do
+ it { is_expected.to permit(admin, InstanceModerationNote.new) }
+ end
+
+ context 'when not admin' do
+ it { is_expected.to_not permit(account, InstanceModerationNote.new) }
+ end
+ end
+
+ permissions :destroy? do
+ context 'when owner of note' do
+ let(:note) { Fabricate :instance_moderation_note, account: account }
+
+ it { is_expected.to permit(account, note) }
+ end
+
+ context 'when not owner of note' do
+ context 'when admin and overrides' do
+ let(:note) { Fabricate :instance_moderation_note }
+
+ it { is_expected.to permit(admin, note) }
+ end
+
+ context 'when admin and does not override' do
+ let(:note) { Fabricate :instance_moderation_note, account: Fabricate(:admin_user).account }
+
+ it { is_expected.to_not permit(admin, note) }
+ end
+ end
+ end
+end
diff --git a/spec/policies/media_attachment_policy_spec.rb b/spec/policies/media_attachment_policy_spec.rb
new file mode 100644
index 00000000000..d194cd819c6
--- /dev/null
+++ b/spec/policies/media_attachment_policy_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe MediaAttachmentPolicy do
+ subject { described_class }
+
+ let(:admin) { Fabricate(:admin_user).account }
+ let(:account) { Fabricate(:account) }
+
+ permissions :download? do
+ context 'when attachment is on private discarded status' do
+ let(:media_attachment) { Fabricate.build :media_attachment, status: Fabricate.build(:status, deleted_at: 5.days.ago, visibility: :private) }
+
+ context 'when admin' do
+ it { is_expected.to permit(admin, media_attachment) }
+ end
+
+ context 'when not admin' do
+ it { is_expected.to_not permit(account, media_attachment) }
+ end
+ end
+
+ context 'when attachment is on public status' do
+ let(:media_attachment) { Fabricate.build :media_attachment, status: Fabricate.build(:status, visibility: :public) }
+
+ context 'when admin' do
+ it { is_expected.to permit(admin, media_attachment) }
+ end
+
+ context 'when not admin' do
+ it { is_expected.to permit(account, media_attachment) }
+ end
+ end
+ end
+end
diff --git a/spec/policies/quote_policy_spec.rb b/spec/policies/quote_policy_spec.rb
new file mode 100644
index 00000000000..71708a9b715
--- /dev/null
+++ b/spec/policies/quote_policy_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe QuotePolicy do
+ subject { described_class }
+
+ let(:account) { Fabricate(:account) }
+
+ permissions :revoke? do
+ context 'when quote matches the revoking account' do
+ let(:quote) { Fabricate.build :quote, quoted_account_id: account.id }
+
+ it { is_expected.to permit(account, quote) }
+ end
+
+ context 'when quote does not match the revoking account' do
+ let(:quote) { Fabricate.build :quote, quoted_account_id: Fabricate(:account).id }
+
+ it { is_expected.to_not permit(account, quote) }
+ end
+
+ context 'when quote does not have quoted account id' do
+ let(:quote) { Fabricate.build :quote }
+
+ it { is_expected.to_not permit(account, quote) }
+ end
+ end
+end
diff --git a/spec/policies/username_block_policy_spec.rb b/spec/policies/username_block_policy_spec.rb
new file mode 100644
index 00000000000..5092f71274d
--- /dev/null
+++ b/spec/policies/username_block_policy_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe UsernameBlockPolicy do
+ subject { described_class }
+
+ let(:admin) { Fabricate(:admin_user).account }
+ let(:account) { Fabricate(:account) }
+
+ permissions :index?, :create?, :update?, :destroy? do
+ context 'when admin' do
+ it { is_expected.to permit(admin, UsernameBlock.new) }
+ end
+
+ context 'when not admin' do
+ it { is_expected.to_not permit(account, UsernameBlock.new) }
+ end
+ end
+end
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
index 6be93ecb70e..bc12d1bece8 100644
--- a/spec/rails_helper.rb
+++ b/spec/rails_helper.rb
@@ -119,6 +119,7 @@ RSpec.configure do |config|
config.include SignedRequestHelpers, type: :request
config.include CommandLineHelpers, type: :cli
config.include SystemHelpers, type: :system
+ config.include Shoulda::Matchers::ActiveModel, type: :validator
# TODO: Remove when Devise fixes https://github.com/heartcombo/devise/issues/5705
config.before do
diff --git a/spec/requests/activitypub/collections_spec.rb b/spec/requests/activitypub/collections_spec.rb
index d2761f98ea3..39bd2252e78 100644
--- a/spec/requests/activitypub/collections_spec.rb
+++ b/spec/requests/activitypub/collections_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'ActivityPub Collections' do
end
describe 'GET #show' do
- subject { get account_collection_path(id: id, account_username: account.username), headers: nil, sign_with: remote_account }
+ subject { get account_actor_collection_path(id: id, account_username: account.username), headers: nil, sign_with: remote_account }
context 'when id is "featured"' do
let(:id) { 'featured' }
@@ -131,16 +131,5 @@ RSpec.describe 'ActivityPub Collections' do
end
end
end
-
- context 'when id is not "featured"' do
- let(:id) { 'hoge' }
-
- it 'returns http not found' do
- subject
-
- expect(response)
- .to have_http_status(404)
- end
- end
end
end
diff --git a/spec/requests/activitypub/featured_collections_spec.rb b/spec/requests/activitypub/featured_collections_spec.rb
new file mode 100644
index 00000000000..09a17c53bea
--- /dev/null
+++ b/spec/requests/activitypub/featured_collections_spec.rb
@@ -0,0 +1,153 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Collections' do
+ describe 'GET /ap/users/@:account_id/featured_collections', feature: :collections do
+ subject { get ap_account_featured_collections_path(account.id, format: :json) }
+
+ let(:collection) { Fabricate(:collection) }
+ let(:account) { collection.account }
+
+ context 'when signed out' do
+ context 'when account is permanently suspended' do
+ before do
+ account.suspend!
+ account.deletion_request.destroy
+ end
+
+ it 'returns http gone' do
+ subject
+
+ expect(response)
+ .to have_http_status(410)
+ end
+ end
+
+ context 'when account is temporarily suspended' do
+ before { account.suspend! }
+
+ it 'returns http forbidden' do
+ subject
+
+ expect(response)
+ .to have_http_status(403)
+ end
+ end
+
+ context 'when account is accessible' do
+ it 'renders ActivityPub Collection successfully', :aggregate_failures do
+ subject
+
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
+
+ expect(response.headers).to include(
+ 'Content-Type' => include('application/activity+json')
+ )
+ expect(response.parsed_body)
+ .to include({
+ 'type' => 'Collection',
+ 'totalItems' => 1,
+ 'first' => match(%r{^https://.*page=1.*$}),
+ })
+ end
+
+ context 'when requesting the first page' do
+ subject { get ap_account_featured_collections_path(account.id, page: 1, format: :json) }
+
+ context 'when account has many collections' do
+ before do
+ Fabricate.times(5, :collection, account:)
+ end
+
+ it 'includes a link to the next page', :aggregate_failures do
+ subject
+
+ expect(response)
+ .to have_http_status(200)
+
+ expect(response.parsed_body)
+ .to include({
+ 'type' => 'CollectionPage',
+ 'totalItems' => 6,
+ 'next' => match(%r{^https://.*page=2.*$}),
+ })
+ end
+ end
+ end
+ end
+ end
+
+ context 'when signed in' do
+ let(:user) { Fabricate(:user) }
+
+ before do
+ post user_session_path, params: { user: { email: user.email, password: user.password } }
+ end
+
+ context 'when account blocks user' do
+ before { account.block!(user.account) }
+
+ it 'returns http not found' do
+ subject
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+ end
+
+ context 'with "HTTP Signature" access signed by a remote account' do
+ subject do
+ get ap_account_featured_collections_path(account.id, format: :json),
+ headers: nil,
+ sign_with: remote_account
+ end
+
+ let(:remote_account) { Fabricate(:account, domain: 'host.example') }
+
+ context 'when account blocks the remote account' do
+ before { account.block!(remote_account) }
+
+ it 'returns http not found' do
+ subject
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+
+ context 'when account domain blocks the domain of the remote account' do
+ before { account.block_domain!(remote_account.domain) }
+
+ it 'returns http not found' do
+ subject
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+
+ context 'with JSON' do
+ it 'renders ActivityPub FeaturedCollection object successfully', :aggregate_failures do
+ subject
+
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
+
+ expect(response.headers).to include(
+ 'Content-Type' => include('application/activity+json')
+ )
+ expect(response.parsed_body)
+ .to include({
+ 'type' => 'Collection',
+ 'totalItems' => 1,
+ })
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/activitypub/inboxes_spec.rb b/spec/requests/activitypub/inboxes_spec.rb
index b21881b10fd..e33afa53c9b 100644
--- a/spec/requests/activitypub/inboxes_spec.rb
+++ b/spec/requests/activitypub/inboxes_spec.rb
@@ -20,6 +20,19 @@ RSpec.describe 'ActivityPub Inboxes' do
end
end
+ context 'with an excessively large payload' do
+ subject { post inbox_path, params: { this: :that, those: :these }.to_json, sign_with: remote_account }
+
+ before { stub_const('ActivityPub::Activity::MAX_JSON_SIZE', 1.byte) }
+
+ it 'returns http content too large' do
+ subject
+
+ expect(response)
+ .to have_http_status(413)
+ end
+ end
+
context 'with a specific account' do
subject { post account_inbox_path(account_username: account.username), params: {}.to_json, sign_with: remote_account }
diff --git a/spec/requests/api/v1/media_spec.rb b/spec/requests/api/v1/media_spec.rb
index 347ff4b2797..89e34998db7 100644
--- a/spec/requests/api/v1/media_spec.rb
+++ b/spec/requests/api/v1/media_spec.rb
@@ -102,7 +102,7 @@ RSpec.describe 'Media' do
allow(user.account).to receive(:media_attachments).and_return(media_attachments)
end
- context 'when imagemagick cannot identify the file type' do
+ context 'when file type cannot be identified' do
it 'returns http unprocessable entity' do
allow(media_attachments).to receive(:create!).and_raise(Paperclip::Errors::NotIdentifiedByImageMagickError)
diff --git a/spec/requests/api/v1/statuses_spec.rb b/spec/requests/api/v1/statuses_spec.rb
index 5db9889e2d5..3fbf26c54a7 100644
--- a/spec/requests/api/v1/statuses_spec.rb
+++ b/spec/requests/api/v1/statuses_spec.rb
@@ -508,6 +508,15 @@ RSpec.describe '/api/v1/statuses' do
.to start_with('application/json')
end
end
+
+ context 'when status has non-default quote policy and param is omitted' do
+ let(:status) { Fabricate(:status, account: user.account, quote_approval_policy: 'nobody') }
+
+ it 'preserves existing quote approval policy' do
+ expect { subject }
+ .to_not(change { status.reload.quote_approval_policy })
+ end
+ end
end
end
diff --git a/spec/requests/api/v1_alpha/collection_items_spec.rb b/spec/requests/api/v1_alpha/collection_items_spec.rb
index 5c44a7edf80..6d33e6a7113 100644
--- a/spec/requests/api/v1_alpha/collection_items_spec.rb
+++ b/spec/requests/api/v1_alpha/collection_items_spec.rb
@@ -26,6 +26,7 @@ RSpec.describe 'Api::V1Alpha::CollectionItems', feature: :collections do
end.to change(collection.collection_items, :count).by(1)
expect(response).to have_http_status(200)
+ expect(response.parsed_body).to have_key('collection_item')
end
end
diff --git a/spec/requests/api/v1_alpha/collections_spec.rb b/spec/requests/api/v1_alpha/collections_spec.rb
index 3921fabfde8..a0573342d8f 100644
--- a/spec/requests/api/v1_alpha/collections_spec.rb
+++ b/spec/requests/api/v1_alpha/collections_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe 'Api::V1Alpha::Collections', feature: :collections do
subject
expect(response).to have_http_status(200)
- expect(response.parsed_body.size).to eq 3
+ expect(response.parsed_body[:collections].size).to eq 3
end
context 'with limit param' do
@@ -30,7 +30,7 @@ RSpec.describe 'Api::V1Alpha::Collections', feature: :collections do
subject
expect(response).to have_http_status(200)
- expect(response.parsed_body.size).to eq 1
+ expect(response.parsed_body[:collections].size).to eq 1
expect(response)
.to include_pagination_headers(
@@ -46,7 +46,7 @@ RSpec.describe 'Api::V1Alpha::Collections', feature: :collections do
subject
expect(response).to have_http_status(200)
- expect(response.parsed_body.size).to eq 1
+ expect(response.parsed_body[:collections].size).to eq 1
expect(response)
.to include_pagination_headers(
@@ -55,6 +55,45 @@ RSpec.describe 'Api::V1Alpha::Collections', feature: :collections do
)
end
end
+
+ context 'when some collections are not discoverable' do
+ before do
+ Fabricate(:collection, account:, discoverable: false)
+ end
+
+ context 'when requesting user is a third party' do
+ it 'hides the collections that are not discoverable' do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(response.parsed_body[:collections].size).to eq 3
+ end
+ end
+
+ context 'when requesting user owns the collection' do
+ let(:account) { user.account }
+
+ it 'returns all collections, including the ones that are not discoverable' do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(response.parsed_body[:collections].size).to eq 4
+ end
+ end
+ end
+
+ context 'when the requesting user is blocked by the given account' do
+ before do
+ account.block!(user.account)
+ end
+
+ it 'returns an empty array' do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(response.parsed_body[:collections]).to eq []
+ end
+ end
end
describe 'GET /api/v1_alpha/collections/:id' do
@@ -70,7 +109,7 @@ RSpec.describe 'Api::V1Alpha::Collections', feature: :collections do
subject
expect(response).to have_http_status(200)
- expect(response.parsed_body[:items].size).to eq 2
+ expect(response.parsed_body[:collection][:items].size).to eq 2
end
end
@@ -94,8 +133,8 @@ RSpec.describe 'Api::V1Alpha::Collections', feature: :collections do
subject
expect(response).to have_http_status(200)
- expect(response.parsed_body[:items].size).to eq 1
- expect(response.parsed_body[:items][0]['position']).to eq items.last.position
+ expect(response.parsed_body[:collection][:items].size).to eq 1
+ expect(response.parsed_body[:collection][:items][0]['id']).to eq items.last.id.to_s
end
end
end
@@ -115,6 +154,7 @@ RSpec.describe 'Api::V1Alpha::Collections', feature: :collections do
{
name: 'Low-traffic bots',
description: 'Really nice bots, please follow',
+ language: 'en',
sensitive: '0',
discoverable: '1',
}
diff --git a/spec/requests/api/v2/media_spec.rb b/spec/requests/api/v2/media_spec.rb
index 04e48bc02c3..1f149b9634d 100644
--- a/spec/requests/api/v2/media_spec.rb
+++ b/spec/requests/api/v2/media_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe 'Media API', :attachment_processing do
allow(user.account).to receive(:media_attachments).and_return(media_attachments)
end
- context 'when imagemagick cannot identify the file type' do
+ context 'when file type cannot be identified' do
before do
allow(media_attachments).to receive(:create!).and_raise(Paperclip::Errors::NotIdentifiedByImageMagickError)
end
diff --git a/spec/requests/api/web/push_subscriptions_spec.rb b/spec/requests/api/web/push_subscriptions_spec.rb
index 21830d1b1c1..3c33f0d2d29 100644
--- a/spec/requests/api/web/push_subscriptions_spec.rb
+++ b/spec/requests/api/web/push_subscriptions_spec.rb
@@ -163,9 +163,10 @@ RSpec.describe 'API Web Push Subscriptions' do
end
describe 'PUT /api/web/push_subscriptions/:id' do
- before { sign_in Fabricate :user }
+ before { sign_in user }
- let(:subscription) { Fabricate :web_push_subscription }
+ let(:user) { Fabricate(:user) }
+ let(:subscription) { Fabricate(:web_push_subscription, user: user) }
it 'gracefully handles invalid nested params' do
put api_web_push_subscription_path(subscription), params: { data: 'invalid' }
@@ -189,6 +190,17 @@ RSpec.describe 'API Web Push Subscriptions' do
.to eq(alerts_payload[:data][:alerts][type.to_sym].to_s)
end
end
+
+ context 'when using other user subscription' do
+ let(:subscription) { Fabricate(:web_push_subscription) }
+
+ it 'does not change settings' do
+ put api_web_push_subscription_path(subscription), params: alerts_payload
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
end
def created_push_subscription
diff --git a/spec/requests/collections_spec.rb b/spec/requests/collections_spec.rb
new file mode 100644
index 00000000000..fece4b62b82
--- /dev/null
+++ b/spec/requests/collections_spec.rb
@@ -0,0 +1,138 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Collections' do
+ describe 'GET /@:account_username/collections/:id', feature: :collections do
+ subject { get account_collection_path(account, collection, format: :json) }
+
+ let(:collection) { Fabricate(:collection) }
+ let(:account) { collection.account }
+
+ context 'when signed out' do
+ context 'when account is permanently suspended' do
+ before do
+ account.suspend!
+ account.deletion_request.destroy
+ end
+
+ it 'returns http gone' do
+ subject
+
+ expect(response)
+ .to have_http_status(410)
+ end
+ end
+
+ context 'when account is temporarily suspended' do
+ before { account.suspend! }
+
+ it 'returns http forbidden' do
+ subject
+
+ expect(response)
+ .to have_http_status(403)
+ end
+ end
+
+ context 'when account is accessible' do
+ context 'with JSON' do
+ subject { get ap_account_collection_path(account.id, collection, format: :json) }
+
+ it 'renders ActivityPub FeaturedCollection object successfully', :aggregate_failures do
+ subject
+
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
+
+ expect(response.headers).to include(
+ 'Content-Type' => include('application/activity+json')
+ )
+ expect(response.parsed_body)
+ .to include({
+ 'type' => 'FeaturedCollection',
+ 'name' => collection.name,
+ })
+ end
+ end
+ end
+ end
+
+ context 'when signed in' do
+ let(:user) { Fabricate(:user) }
+
+ before do
+ post user_session_path, params: { user: { email: user.email, password: user.password } }
+ end
+
+ context 'when account blocks user' do
+ before { account.block!(user.account) }
+
+ it 'returns http not found' do
+ subject
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+ end
+
+ context 'with "HTTP Signature" access signed by a remote account' do
+ subject do
+ get account_collection_path(account, collection, format: :json),
+ headers: nil,
+ sign_with: remote_account
+ end
+
+ let(:remote_account) { Fabricate(:account, domain: 'host.example') }
+
+ context 'when account blocks the remote account' do
+ before { account.block!(remote_account) }
+
+ it 'returns http not found' do
+ subject
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+
+ context 'when account domain blocks the domain of the remote account' do
+ before { account.block_domain!(remote_account.domain) }
+
+ it 'returns http not found' do
+ subject
+
+ expect(response)
+ .to have_http_status(404)
+ end
+ end
+
+ context 'with JSON' do
+ subject do
+ get ap_account_collection_path(account.id, collection, format: :json),
+ headers: nil,
+ sign_with: remote_account
+ end
+
+ it 'renders ActivityPub FeaturedCollection object successfully', :aggregate_failures do
+ subject
+
+ expect(response)
+ .to have_http_status(200)
+ .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie')
+
+ expect(response.headers).to include(
+ 'Content-Type' => include('application/activity+json')
+ )
+ expect(response.parsed_body)
+ .to include({
+ 'type' => 'FeaturedCollection',
+ 'name' => collection.name,
+ })
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/content_security_policy_spec.rb b/spec/requests/content_security_policy_spec.rb
index 0aa4494ef0b..c84c3802f24 100644
--- a/spec/requests/content_security_policy_spec.rb
+++ b/spec/requests/content_security_policy_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'Content-Security-Policy' do
img-src 'self' data: blob: #{local_domain}
manifest-src 'self' #{local_domain}
media-src 'self' data: #{local_domain}
- script-src 'self' #{local_domain} 'wasm-unsafe-eval' 'sha256-Q/2Cjx8v06hAdOF8/DeBUpsmBcSj7sLN3I/WpTF8T8c='
+ script-src 'self' #{local_domain} 'wasm-unsafe-eval' 'sha256-Z5KW83D+6/pygIQS3h9XDpF52xW3l3BHc7JL9tj3uMs='
style-src 'self' #{local_domain} 'nonce-ZbA+JmE7+bK8F5qvADZHuQ=='
worker-src 'self' blob: #{local_domain}
CSP
diff --git a/spec/requests/oauth/authorizations_spec.rb b/spec/requests/oauth/authorizations_spec.rb
new file mode 100644
index 00000000000..f17b58a002a
--- /dev/null
+++ b/spec/requests/oauth/authorizations_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'OAuth Authorizations' do
+ let(:application) { Fabricate :application, name: 'test', redirect_uri: 'http://localhost/', scopes: 'read' }
+ let(:params) { { client_id: application.uid, response_type: 'code', redirect_uri: 'http://localhost/', scope: 'read' } }
+
+ describe 'GET #new' do
+ subject { get oauth_authorization_path(params) }
+
+ context 'when signed in' do
+ let(:user) { Fabricate(:user) }
+
+ before { sign_in user }
+
+ it 'returns http success and private cache control headers' do
+ subject
+
+ expect(response)
+ .to have_http_status(:success)
+ expect(response.headers['Cache-Control'])
+ .to include('private, no-store')
+ expect(response.parsed_body.at('body.modal-layout'))
+ .to be_present
+ expect(controller.stored_location_for(:user))
+ .to eq authorize_path_for(application)
+ end
+
+ context 'when app is already authorized' do
+ before do
+ Doorkeeper::AccessToken.find_or_create_for(
+ application: application,
+ resource_owner: user.id,
+ scopes: application.scopes,
+ expires_in: Doorkeeper.configuration.access_token_expires_in,
+ use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?
+ )
+ end
+
+ it 'redirects to callback' do
+ subject
+
+ expect(response)
+ .to redirect_to(/\A#{application.redirect_uri}/)
+ end
+
+ context 'with `force_login` param true' do
+ subject do
+ get oauth_authorization_path(params.merge(force_login: 'true'))
+ end
+
+ it 'renders new page with success status' do
+ subject
+
+ expect(response)
+ .to have_http_status(:success)
+ expect(response.parsed_body.title)
+ .to match(I18n.t('doorkeeper.authorizations.new.title'))
+ end
+ end
+ end
+ end
+
+ context 'when not signed in' do
+ it 'redirects' do
+ subject
+
+ expect(response)
+ .to redirect_to(new_user_session_path)
+ expect(controller.stored_location_for(:user))
+ .to eq authorize_path_for(application)
+ end
+ end
+
+ def authorize_path_for(application)
+ "/oauth/authorize?client_id=#{application.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/requests/oauth/authorized_applications_spec.rb
similarity index 53%
rename from spec/controllers/oauth/authorized_applications_controller_spec.rb
rename to spec/requests/oauth/authorized_applications_spec.rb
index 8d804476eec..397cac98db8 100644
--- a/spec/controllers/oauth/authorized_applications_controller_spec.rb
+++ b/spec/requests/oauth/authorized_applications_spec.rb
@@ -2,21 +2,16 @@
require 'rails_helper'
-RSpec.describe OAuth::AuthorizedApplicationsController do
- render_views
-
- describe 'GET #index' do
- subject do
- get :index
- end
+RSpec.describe 'OAuth Authorized Applications' do
+ describe 'GET /oauth/authorized_applications' do
+ subject { get oauth_authorized_applications_path }
context 'when signed in' do
- before do
- sign_in Fabricate(:user), scope: :user
- end
+ before { sign_in Fabricate(:user) }
it 'returns http success with private cache control headers' do
subject
+
expect(response)
.to have_http_status(200)
expect(response.headers['Cache-Control'])
@@ -40,29 +35,29 @@ RSpec.describe OAuth::AuthorizedApplicationsController do
end
end
- describe 'DELETE #destroy' do
+ describe 'DELETE /oauth/authorized_applications/:id' do
+ subject { delete oauth_authorized_application_path(application) }
+
let!(:user) { Fabricate(:user) }
let!(:application) { Fabricate(:application) }
let!(:access_token) { Fabricate(:accessible_access_token, application: application, resource_owner_id: user.id) }
let!(:web_push_subscription) { Fabricate(:web_push_subscription, user: user, access_token: access_token) }
let(:redis_pipeline_stub) { instance_double(Redis::PipelinedConnection, publish: nil) }
- before do
- sign_in user, scope: :user
- allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub)
- end
+ before { allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub) }
- it 'revokes access tokens for the application and removes subscriptions and sends kill payload to streaming' do
- post :destroy, params: { id: application.id }
+ context 'when signed in' do
+ before { sign_in user }
- 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"}')
+ it 'revokes access tokens for the application and removes subscriptions and sends kill payload to streaming' do
+ expect { subject }
+ .to change { Doorkeeper::AccessToken.where(application:).first.reload.revoked_at }.from(nil).to(be_present)
+ .and change { Web::PushSubscription.where(user:).reload.count }.to(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
end
diff --git a/spec/serializers/activitypub/add_serializer_spec.rb b/spec/serializers/activitypub/add_serializer_spec.rb
index 3b3eaeb1b01..a5e1052fa03 100644
--- a/spec/serializers/activitypub/add_serializer_spec.rb
+++ b/spec/serializers/activitypub/add_serializer_spec.rb
@@ -18,10 +18,38 @@ RSpec.describe ActivityPub::AddSerializer do
it { is_expected.to eq(ActivityPub::HashtagSerializer) }
end
+ context 'with a Collection model' do
+ let(:model) { Collection.new }
+
+ it { is_expected.to eq(ActivityPub::FeaturedCollectionSerializer) }
+ end
+
context 'with an Array' do
let(:model) { [] }
it { is_expected.to eq(ActiveModel::Serializer::CollectionSerializer) }
end
end
+
+ describe '#target' do
+ subject { described_class.new(object).target }
+
+ context 'when object is a Status' do
+ let(:object) { Fabricate(:status) }
+
+ it { is_expected.to match(%r{/#{object.account_id}/collections/featured$}) }
+ end
+
+ context 'when object is a FeaturedTag' do
+ let(:object) { Fabricate(:featured_tag) }
+
+ it { is_expected.to match(%r{/#{object.account_id}/collections/featured$}) }
+ end
+
+ context 'when object is a Collection' do
+ let(:object) { Fabricate(:collection) }
+
+ it { is_expected.to match(%r{/#{object.account_id}/featured_collections$}) }
+ end
+ end
end
diff --git a/spec/serializers/activitypub/collection_serializer_spec.rb b/spec/serializers/activitypub/collection_serializer_spec.rb
index 7726df914f2..d7099ba3d5a 100644
--- a/spec/serializers/activitypub/collection_serializer_spec.rb
+++ b/spec/serializers/activitypub/collection_serializer_spec.rb
@@ -35,5 +35,11 @@ RSpec.describe ActivityPub::CollectionSerializer do
it { is_expected.to eq(ActiveModel::Serializer::CollectionSerializer) }
end
+
+ context 'with a Collection' do
+ let(:model) { Collection.new }
+
+ it { is_expected.to eq(ActivityPub::FeaturedCollectionSerializer) }
+ end
end
end
diff --git a/spec/serializers/activitypub/featured_collection_serializer_spec.rb b/spec/serializers/activitypub/featured_collection_serializer_spec.rb
index b01cce12d81..e6bb4ea4b0f 100644
--- a/spec/serializers/activitypub/featured_collection_serializer_spec.rb
+++ b/spec/serializers/activitypub/featured_collection_serializer_spec.rb
@@ -45,4 +45,20 @@ RSpec.describe ActivityPub::FeaturedCollectionSerializer do
'updated' => match_api_datetime_format,
})
end
+
+ context 'when a language is set' do
+ before do
+ collection.language = 'en'
+ end
+
+ it 'uses "summaryMap" to include the language' do
+ expect(subject).to include({
+ 'summaryMap' => {
+ 'en' => 'These are really amazing',
+ },
+ })
+
+ expect(subject).to_not have_key('summary')
+ end
+ end
end
diff --git a/spec/serializers/rest/base_collection_serializer_spec.rb b/spec/serializers/rest/base_collection_serializer_spec.rb
deleted file mode 100644
index 5ac6bc615d0..00000000000
--- a/spec/serializers/rest/base_collection_serializer_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe REST::BaseCollectionSerializer do
- subject do
- serialized_record_json(collection, described_class, options: {
- scope: current_user,
- scope_name: :current_user,
- })
- end
-
- let(:current_user) { nil }
-
- let(:tag) { Fabricate(:tag, name: 'discovery') }
- let(:collection) do
- Fabricate(:collection,
- id: 2342,
- name: 'Exquisite follows',
- description: 'Always worth a follow',
- local: true,
- sensitive: true,
- discoverable: false,
- tag:)
- end
-
- it 'includes the relevant attributes' do
- expect(subject)
- .to include(
- 'id' => '2342',
- 'name' => 'Exquisite follows',
- 'description' => 'Always worth a follow',
- 'local' => true,
- 'sensitive' => true,
- 'discoverable' => false,
- 'tag' => a_hash_including('name' => 'discovery'),
- 'created_at' => match_api_datetime_format,
- 'updated_at' => match_api_datetime_format
- )
- end
-end
diff --git a/spec/serializers/rest/collection_item_serializer_spec.rb b/spec/serializers/rest/collection_item_serializer_spec.rb
index b12553ec034..348107fb916 100644
--- a/spec/serializers/rest/collection_item_serializer_spec.rb
+++ b/spec/serializers/rest/collection_item_serializer_spec.rb
@@ -8,8 +8,7 @@ RSpec.describe REST::CollectionItemSerializer do
let(:collection_item) do
Fabricate(:collection_item,
id: 2342,
- state:,
- position: 4)
+ state:)
end
context 'when state is `accepted`' do
@@ -19,9 +18,8 @@ RSpec.describe REST::CollectionItemSerializer do
expect(subject)
.to include(
'id' => '2342',
- 'account' => an_instance_of(Hash),
- 'state' => 'accepted',
- 'position' => 4
+ 'account_id' => collection_item.account_id.to_s,
+ 'state' => 'accepted'
)
end
end
@@ -31,7 +29,7 @@ RSpec.describe REST::CollectionItemSerializer do
let(:state) { unaccepted_state }
it 'does not include an account' do
- expect(subject.keys).to_not include('account')
+ expect(subject.keys).to_not include('account_id')
end
end
end
diff --git a/spec/serializers/rest/collection_serializer_spec.rb b/spec/serializers/rest/collection_serializer_spec.rb
index f0baf7dff87..0fbe955b2eb 100644
--- a/spec/serializers/rest/collection_serializer_spec.rb
+++ b/spec/serializers/rest/collection_serializer_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe REST::CollectionSerializer do
id: 2342,
name: 'Exquisite follows',
description: 'Always worth a follow',
+ language: 'en',
local: true,
sensitive: true,
discoverable: false,
@@ -27,16 +28,19 @@ RSpec.describe REST::CollectionSerializer do
it 'includes the relevant attributes' do
expect(subject)
.to include(
- 'account' => an_instance_of(Hash),
+ 'account_id' => collection.account_id.to_s,
'id' => '2342',
'name' => 'Exquisite follows',
'description' => 'Always worth a follow',
+ 'language' => 'en',
'local' => true,
'sensitive' => true,
'discoverable' => false,
'tag' => a_hash_including('name' => 'discovery'),
'created_at' => match_api_datetime_format,
- 'updated_at' => match_api_datetime_format
+ 'updated_at' => match_api_datetime_format,
+ 'item_count' => 0,
+ 'items' => []
)
end
end
diff --git a/spec/serializers/rest/collection_with_accounts_serializer_spec.rb b/spec/serializers/rest/collection_with_accounts_serializer_spec.rb
new file mode 100644
index 00000000000..6a2b8683977
--- /dev/null
+++ b/spec/serializers/rest/collection_with_accounts_serializer_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe REST::CollectionWithAccountsSerializer do
+ subject do
+ serialized_record_json(collection, described_class, options: {
+ scope: current_user,
+ scope_name: :current_user,
+ })
+ end
+
+ let(:current_user) { nil }
+
+ let(:tag) { Fabricate(:tag, name: 'discovery') }
+ let(:accounts) { Fabricate.times(3, :account) }
+ let(:collection) do
+ Fabricate(:collection,
+ account: accounts.first,
+ id: 2342,
+ name: 'Exquisite follows',
+ description: 'Always worth a follow',
+ language: 'en',
+ local: true,
+ sensitive: true,
+ discoverable: false,
+ tag:)
+ end
+
+ before do
+ accounts[1..2].each do |account|
+ Fabricate(:collection_item, collection:, account:)
+ end
+ collection.reload
+ end
+
+ it 'includes the relevant attributes' do
+ expect(subject)
+ .to include(
+ 'accounts' => an_instance_of(Array),
+ 'collection' => a_hash_including({
+ 'account_id' => accounts.first.id.to_s,
+ 'id' => '2342',
+ 'name' => 'Exquisite follows',
+ 'description' => 'Always worth a follow',
+ 'language' => 'en',
+ 'local' => true,
+ 'sensitive' => true,
+ 'discoverable' => false,
+ 'tag' => a_hash_including('name' => 'discovery'),
+ 'created_at' => match_api_datetime_format,
+ 'updated_at' => match_api_datetime_format,
+ 'item_count' => 2,
+ 'items' => an_instance_of(Array),
+ })
+ )
+ expect(subject['accounts'].size).to eq 3
+ end
+end
diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb
index 1a19cbb782b..cceeda1bb13 100644
--- a/spec/services/activitypub/process_status_update_service_spec.rb
+++ b/spec/services/activitypub/process_status_update_service_spec.rb
@@ -258,6 +258,7 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
tag: [
{ type: 'Hashtag', name: 'foo' },
{ type: 'Hashtag', name: 'bar' },
+ { type: 'Hashtag', name: '#2024' },
],
}
end
diff --git a/spec/services/create_collection_service_spec.rb b/spec/services/create_collection_service_spec.rb
index f88a366a6c2..8189b01fbe4 100644
--- a/spec/services/create_collection_service_spec.rb
+++ b/spec/services/create_collection_service_spec.rb
@@ -29,6 +29,12 @@ RSpec.describe CreateCollectionService do
expect(collection).to be_local
end
+ it 'federates an `Add` activity', feature: :collections_federation do
+ subject.call(base_params, author)
+
+ expect(ActivityPub::AccountRawDistributionWorker).to have_enqueued_sidekiq_job
+ end
+
context 'when given account ids' do
let(:accounts) do
Fabricate.times(2, :account)
diff --git a/spec/services/fan_out_on_write_service_spec.rb b/spec/services/fan_out_on_write_service_spec.rb
index c6dd020cdff..79ecd06c8d9 100644
--- a/spec/services/fan_out_on_write_service_spec.rb
+++ b/spec/services/fan_out_on_write_service_spec.rb
@@ -23,18 +23,32 @@ RSpec.describe FanOutOnWriteService do
Fabricate(:media_attachment, status: status, account: alice)
allow(redis).to receive(:publish)
-
- subject.call(status)
end
def home_feed_of(account)
HomeFeed.new(account).get(10).map(&:id)
end
+ context 'when status account is suspended' do
+ let(:visibility) { 'public' }
+
+ before { alice.suspend! }
+
+ it 'does not execute or broadcast' do
+ expect(subject.call(status))
+ .to be_nil
+ expect_no_broadcasting
+ end
+ end
+
context 'when status is public' do
let(:visibility) { 'public' }
it 'adds status to home feed of author and followers and broadcasts', :inline_jobs do
+ expect { subject.call(status) }
+ .to change(bob.notifications, :count).by(1)
+ .and change(eve.notifications, :count).by(1)
+
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
@@ -46,12 +60,22 @@ RSpec.describe FanOutOnWriteService do
expect(redis).to have_received(:publish).with('timeline:public:local', anything)
expect(redis).to have_received(:publish).with('timeline:public:media', anything)
end
+
+ context 'with silenced_account_ids' do
+ it 'calls LocalNotificationWorker with the expected arguments' do
+ expect { subject.call(status, silenced_account_ids: [eve.id]) }
+ .to enqueue_sidekiq_job(LocalNotificationWorker).with(bob.id, anything, 'Mention', 'mention')
+ .and enqueue_sidekiq_job(LocalNotificationWorker).with(eve.id, anything, 'Mention', 'mention', { 'silenced' => true })
+ end
+ end
end
context 'when status is limited' do
let(:visibility) { 'limited' }
it 'adds status to home feed of author and mentioned followers and does not broadcast', :inline_jobs do
+ subject.call(status)
+
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
@@ -66,6 +90,8 @@ RSpec.describe FanOutOnWriteService do
let(:visibility) { 'private' }
it 'adds status to home feed of author and followers and does not broadcast', :inline_jobs do
+ subject.call(status)
+
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
@@ -79,6 +105,8 @@ RSpec.describe FanOutOnWriteService do
let(:visibility) { 'direct' }
it 'is added to the home feed of its author and mentioned followers and does not broadcast', :inline_jobs do
+ subject.call(status)
+
expect(status.id)
.to be_in(home_feed_of(alice))
.and be_in(home_feed_of(bob))
diff --git a/spec/services/notify_service_spec.rb b/spec/services/notify_service_spec.rb
index 9d9d4eed3d4..9927fa9f049 100644
--- a/spec/services/notify_service_spec.rb
+++ b/spec/services/notify_service_spec.rb
@@ -224,13 +224,25 @@ RSpec.describe NotifyService do
end
end
+ context 'when sender is considered silenced through `silenced` option and recipient has a policy to ignore silenced accounts' do
+ subject { described_class.new(notification, silenced: true) }
+
+ before do
+ notification.account.create_notification_policy!(for_limited_accounts: :drop)
+ end
+
+ it 'returns true' do
+ expect(subject.drop?).to be true
+ end
+ end
+
context 'when sender is new and recipient has a default policy' do
it 'returns false' do
expect(subject.drop?).to be false
end
end
- context 'when sender is new and recipient has a policy to ignore silenced accounts' do
+ context 'when sender is new and recipient has a policy to ignore new accounts' do
before do
notification.account.create_notification_policy!(for_new_accounts: :drop)
end
@@ -240,7 +252,7 @@ RSpec.describe NotifyService do
end
end
- context 'when sender is new and followed and recipient has a policy to ignore silenced accounts' do
+ context 'when sender is new and followed and recipient has a policy to ignore new accounts' do
before do
notification.account.create_notification_policy!(for_new_accounts: :drop)
notification.account.follow!(notification.from_account)
@@ -300,6 +312,34 @@ RSpec.describe NotifyService do
end
end
+ context 'when sender is considered silenced through the `silenced` option' do
+ subject { described_class.new(notification, silenced: true) }
+
+ it 'returns true' do
+ expect(subject.filter?).to be true
+ end
+
+ context 'when recipient follows sender' do
+ before do
+ notification.account.follow!(notification.from_account)
+ end
+
+ it 'returns false' do
+ expect(subject.filter?).to be false
+ end
+ end
+
+ context 'when recipient is allowing limited accounts' do
+ before do
+ notification.account.create_notification_policy!(for_limited_accounts: :accept)
+ end
+
+ it 'returns false' do
+ expect(subject.filter?).to be false
+ end
+ end
+ end
+
context 'when recipient is filtering not-followed senders' do
before do
Fabricate(:notification_policy, account: notification.account, filter_not_following: true)
diff --git a/spec/system/settings/aliases_spec.rb b/spec/system/settings/aliases_spec.rb
new file mode 100644
index 00000000000..96d94615038
--- /dev/null
+++ b/spec/system/settings/aliases_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings aliases page' do
+ let!(:user) { Fabricate(:user) }
+ let(:account) { user.account }
+
+ before { sign_in user }
+
+ describe 'Viewing aliases' do
+ it 'shows index page with private cache control headers' do
+ visit settings_aliases_path
+
+ # View index page
+ expect(page)
+ .to have_content(I18n.t('settings.aliases'))
+ .and have_private_cache_control
+ end
+ end
+
+ describe 'Creating an alias' do
+ context 'with valid alias value' do
+ before { stub_resolver }
+
+ it 'creates an alias for the user' do
+ visit settings_aliases_path
+
+ fill_in 'account_alias_acct',
+ with: 'new@host.example'
+ expect { submit_form }
+ .to change(AccountAlias, :count).by(1)
+ expect(page)
+ .to have_content(I18n.t('aliases.created_msg'))
+ end
+ end
+
+ context 'with invalid value' do
+ it 'does not create an alias for the user' do
+ visit settings_aliases_path
+
+ fill_in 'account_alias_acct',
+ with: 'invalid-value'
+ expect { submit_form }
+ .to not_change(AccountAlias, :count)
+ expect(page)
+ .to have_content(I18n.t('settings.aliases'))
+ end
+ end
+
+ def submit_form
+ click_on I18n.t('aliases.add_new')
+ end
+ end
+
+ describe 'Removing an alias' do
+ let!(:account_alias) do
+ AccountAlias.new(account: user.account, acct: 'new@example.com').tap do |account_alias|
+ account_alias.save(validate: false)
+ end
+ end
+
+ it 'removes an alias' do
+ visit settings_aliases_path
+ expect { click_on I18n.t('aliases.remove') }
+ .to change(AccountAlias, :count).by(-1)
+
+ expect(page)
+ .to have_content(I18n.t('settings.aliases'))
+ .and have_content(I18n.t('aliases.deleted_msg'))
+ expect { account_alias.reload }
+ .to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ private
+
+ def stub_resolver
+ resolver = instance_double(ResolveAccountService, call: Fabricate(:account))
+ allow(ResolveAccountService).to receive(:new).and_return(resolver)
+ end
+end
diff --git a/spec/validators/date_of_birth_validator_spec.rb b/spec/validators/date_of_birth_validator_spec.rb
index 33e69e811b2..65b63db2349 100644
--- a/spec/validators/date_of_birth_validator_spec.rb
+++ b/spec/validators/date_of_birth_validator_spec.rb
@@ -3,49 +3,25 @@
require 'rails_helper'
RSpec.describe DateOfBirthValidator do
- let(:record_class) do
- Class.new do
- include ActiveModel::Validations
+ subject { Fabricate.build :user }
- attr_accessor :date_of_birth
+ before { Setting.min_age = 16 }
- validates :date_of_birth, date_of_birth: true
- end
+ context 'with an invalid date' do
+ let(:invalid_date) { '76.830.10' }
+
+ it { is_expected.to_not allow_values(invalid_date).for(:date_of_birth) }
end
- let(:record) { record_class.new }
+ context 'with a date below the age limit' do
+ let(:too_young) { 13.years.ago }
- before do
- Setting.min_age = 16
+ it { is_expected.to_not allow_values(too_young).for(:date_of_birth).with_message(:below_limit) }
end
- describe '#validate_each' do
- context 'with an invalid date' do
- it 'adds errors' do
- record.date_of_birth = '76.830.10'
+ context 'with a date above the age limit' do
+ let(:old_enough) { 16.years.ago }
- expect(record).to_not be_valid
- expect(record.errors.first.attribute).to eq(:date_of_birth)
- expect(record.errors.first.type).to eq(:invalid)
- end
- end
-
- context 'with a date below age limit' do
- it 'adds errors' do
- record.date_of_birth = 13.years.ago.strftime('%d.%m.%Y')
-
- expect(record).to_not be_valid
- expect(record.errors.first.attribute).to eq(:date_of_birth)
- expect(record.errors.first.type).to eq(:below_limit)
- end
- end
-
- context 'with a date above age limit' do
- it 'does not add errors' do
- record.date_of_birth = 16.years.ago.strftime('%d.%m.%Y')
-
- expect(record).to be_valid
- end
- end
+ it { is_expected.to allow_values(old_enough).for(:date_of_birth) }
end
end
diff --git a/spec/validators/poll_expiration_validator_spec.rb b/spec/validators/poll_expiration_validator_spec.rb
index 41b8c962119..ea726c05914 100644
--- a/spec/validators/poll_expiration_validator_spec.rb
+++ b/spec/validators/poll_expiration_validator_spec.rb
@@ -3,35 +3,23 @@
require 'rails_helper'
RSpec.describe PollExpirationValidator do
- describe '#validate' do
- before do
- validator.validate(poll)
- end
+ subject { Fabricate.build :poll }
- let(:validator) { described_class.new }
- let(:poll) { instance_double(Poll, options: options, expires_at: expires_at, errors: errors) }
- let(:errors) { instance_double(ActiveModel::Errors, add: nil) }
- let(:options) { %w(foo bar) }
- let(:expires_at) { 1.day.from_now }
+ context 'when poll expires in far future' do
+ let(:far_future) { 6.months.from_now }
- it 'has no errors' do
- expect(errors).to_not have_received(:add)
- end
+ it { is_expected.to_not allow_value(far_future).for(:expires_at).with_message(I18n.t('polls.errors.duration_too_long')) }
+ end
- context 'when the poll expires in 5 min from now' do
- let(:expires_at) { 5.minutes.from_now }
+ context 'when poll expires in far past' do
+ let(:past_date) { 6.days.ago }
- it 'has no errors' do
- expect(errors).to_not have_received(:add)
- end
- end
+ it { is_expected.to_not allow_value(past_date).for(:expires_at).with_message(I18n.t('polls.errors.duration_too_short')) }
+ end
- context 'when the poll expires in the past' do
- let(:expires_at) { 5.minutes.ago }
+ context 'when poll expires in medium future' do
+ let(:allowed_future) { 10.minutes.from_now }
- it 'has errors' do
- expect(errors).to have_received(:add)
- end
- end
+ it { is_expected.to allow_value(allowed_future).for(:expires_at) }
end
end
diff --git a/spec/workers/admin/account_deletion_worker_spec.rb b/spec/workers/admin/account_deletion_worker_spec.rb
index e41b734f214..7fc56e42891 100644
--- a/spec/workers/admin/account_deletion_worker_spec.rb
+++ b/spec/workers/admin/account_deletion_worker_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Admin::AccountDeletionWorker do
let(:worker) { described_class.new }
describe 'perform' do
- let(:account) { Fabricate(:account) }
+ let(:account) { Fabricate(:account, suspended: true) }
let(:service) { instance_double(DeleteAccountService, call: true) }
it 'calls delete account service' do
diff --git a/streaming/index.js b/streaming/index.js
index 2a4d89ffe48..b342d5243d8 100644
--- a/streaming/index.js
+++ b/streaming/index.js
@@ -30,7 +30,8 @@ const dotenvFilePath = path.resolve(
);
dotenv.config({
- path: dotenvFilePath
+ path: dotenvFilePath,
+ quiet: true,
});
initializeLogLevel(process.env, environment);
diff --git a/streaming/package.json b/streaming/package.json
index 0f6651b741a..7a1685749a6 100644
--- a/streaming/package.json
+++ b/streaming/package.json
@@ -18,7 +18,7 @@
},
"dependencies": {
"cors": "^2.8.5",
- "dotenv": "^16.0.3",
+ "dotenv": "^17.0.0",
"express": "^5.1.0",
"ioredis": "^5.3.2",
"jsdom": "^27.0.0",
@@ -36,7 +36,7 @@
"@types/express": "^5.0.5",
"@types/pg": "^8.6.6",
"@types/ws": "^8.5.9",
- "globals": "^16.0.0",
+ "globals": "^17.0.0",
"pino-pretty": "^13.0.0",
"typescript": "~5.9.0",
"typescript-eslint": "^8.28.0"
diff --git a/stylelint.config.js b/stylelint.config.js
index 9ccee477484..d4d50849f10 100644
--- a/stylelint.config.js
+++ b/stylelint.config.js
@@ -43,7 +43,7 @@ module.exports = {
},
},
{
- files: ['app/javascript/**/*.module.scss'],
+ files: ['app/javascript/**/*.module.scss', 'app/javascript/**/*.module.css'],
rules: {
'selector-pseudo-class-no-unknown': [
true,
diff --git a/vite.config.mts b/vite.config.mts
index 0a10b30a5b3..30b1dc1511d 100644
--- a/vite.config.mts
+++ b/vite.config.mts
@@ -214,7 +214,10 @@ export const config: UserConfigFnPromise = async ({ mode, command }) => {
svgr(),
// Old library types need to be converted
optimizeLodashImports() as PluginOption,
- !!process.env.ANALYZE_BUNDLE_SIZE && (visualizer() as PluginOption),
+ !!process.env.ANALYZE_BUNDLE_SIZE &&
+ (visualizer({
+ template: process.env.CI ? 'raw-data' : 'treemap',
+ }) as PluginOption),
MastodonNameLookup(),
],
} satisfies UserConfig;
diff --git a/yarn.lock b/yarn.lock
index 424b0d623fd..8ab0bae75e6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1248,13 +1248,13 @@ __metadata:
languageName: node
linkType: hard
-"@csstools/cascade-layer-name-parser@npm:^2.0.5":
- version: 2.0.5
- resolution: "@csstools/cascade-layer-name-parser@npm:2.0.5"
+"@csstools/cascade-layer-name-parser@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/cascade-layer-name-parser@npm:3.0.0"
peerDependencies:
- "@csstools/css-parser-algorithms": ^3.0.5
- "@csstools/css-tokenizer": ^3.0.4
- checksum: 10c0/b6c73d5c8132f922edc88b9df5272c93c9753945f1e1077b80d03b314076ffe03c2cc9bf6cbc85501ee7c7f27e477263df96997c9125fd2fd0cfe82fe2d7c141
+ "@csstools/css-parser-algorithms": ^4.0.0
+ "@csstools/css-tokenizer": ^4.0.0
+ checksum: 10c0/657b325261dfa567e26b56a1a6a00fcfc877b9e95ce8ae3595ec95c89323fc2123dad7a4ca79bede8dec475ccc41d9d528470b0be01c4f22104f6962f2bfb40c
languageName: node
linkType: hard
@@ -1265,6 +1265,13 @@ __metadata:
languageName: node
linkType: hard
+"@csstools/color-helpers@npm:^6.0.1":
+ version: 6.0.1
+ resolution: "@csstools/color-helpers@npm:6.0.1"
+ checksum: 10c0/866844267d5aa5a02fe9d54f6db6fc18f6306595edb03664cc8ef15c99d3e6f3b42eb1a413c98bafa5b2dc0d8e0193da9b3bcc9d6a04f5de74cbd44935e74b3c
+ languageName: node
+ linkType: hard
+
"@csstools/css-calc@npm:^2.1.4":
version: 2.1.4
resolution: "@csstools/css-calc@npm:2.1.4"
@@ -1275,6 +1282,16 @@ __metadata:
languageName: node
linkType: hard
+"@csstools/css-calc@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/css-calc@npm:3.0.0"
+ peerDependencies:
+ "@csstools/css-parser-algorithms": ^4.0.0
+ "@csstools/css-tokenizer": ^4.0.0
+ checksum: 10c0/2f062db206dcdcb561a802d791aaf8b410f0e4d91ded89eb4075f75f1eafe8f5392c431a8d602d6ae660fca6299e02fcc555efdb235f3403ffc56ac6f14a1c2b
+ languageName: node
+ linkType: hard
+
"@csstools/css-color-parser@npm:^3.1.0":
version: 3.1.0
resolution: "@csstools/css-color-parser@npm:3.1.0"
@@ -1288,6 +1305,19 @@ __metadata:
languageName: node
linkType: hard
+"@csstools/css-color-parser@npm:^4.0.1":
+ version: 4.0.1
+ resolution: "@csstools/css-color-parser@npm:4.0.1"
+ dependencies:
+ "@csstools/color-helpers": "npm:^6.0.1"
+ "@csstools/css-calc": "npm:^3.0.0"
+ peerDependencies:
+ "@csstools/css-parser-algorithms": ^4.0.0
+ "@csstools/css-tokenizer": ^4.0.0
+ checksum: 10c0/c46be5b9f5c0ef3cd25b47a71bd2a4d1c4856b123ecba4abe8eaa0688d3fc47f58fa67ea281d6b9efca4b9fdfa88fb045c51d0f9b8c612a56bd546d38260b138
+ languageName: node
+ linkType: hard
+
"@csstools/css-parser-algorithms@npm:^3.0.5":
version: 3.0.5
resolution: "@csstools/css-parser-algorithms@npm:3.0.5"
@@ -1297,6 +1327,15 @@ __metadata:
languageName: node
linkType: hard
+"@csstools/css-parser-algorithms@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "@csstools/css-parser-algorithms@npm:4.0.0"
+ peerDependencies:
+ "@csstools/css-tokenizer": ^4.0.0
+ checksum: 10c0/94558c2428d6ef0ddef542e86e0a8376aa1263a12a59770abb13ba50d7b83086822c75433f32aa2e7fef00555e1cc88292f9ca5bce79aed232bb3fed73b1528d
+ languageName: node
+ linkType: hard
+
"@csstools/css-syntax-patches-for-csstree@npm:1.0.14":
version: 1.0.14
resolution: "@csstools/css-syntax-patches-for-csstree@npm:1.0.14"
@@ -1306,10 +1345,10 @@ __metadata:
languageName: node
linkType: hard
-"@csstools/css-syntax-patches-for-csstree@npm:^1.0.19":
- version: 1.0.20
- resolution: "@csstools/css-syntax-patches-for-csstree@npm:1.0.20"
- checksum: 10c0/335fcd24eb563068338153066d580bfdfc87b1e0f7650432a332e925c88d247a56f8e5851cd27dd68e49cde2dbeb465db60a51bb92a18e6721b5166b2e046d91
+"@csstools/css-syntax-patches-for-csstree@npm:^1.0.25":
+ version: 1.0.25
+ resolution: "@csstools/css-syntax-patches-for-csstree@npm:1.0.25"
+ checksum: 10c0/a24229cc44cd64642ba76c73f59e7b0b00cfaffd992bf515d32f266aa68b983d9a945ebf8d45c90671d1e2c775a225d8b6257b01fdfeb6602c0c1f7e3faf77c0
languageName: node
linkType: hard
@@ -1320,550 +1359,569 @@ __metadata:
languageName: node
linkType: hard
-"@csstools/media-query-list-parser@npm:^4.0.3":
- version: 4.0.3
- resolution: "@csstools/media-query-list-parser@npm:4.0.3"
- peerDependencies:
- "@csstools/css-parser-algorithms": ^3.0.5
- "@csstools/css-tokenizer": ^3.0.4
- checksum: 10c0/e29d856d57e9a036694662163179fc061a99579f05e7c3c35438b3e063790ae8a9ee9f1fb4b4693d8fc7672ae0801764fe83762ab7b9df2921fcc6172cfd5584
- languageName: node
- linkType: hard
-
-"@csstools/postcss-alpha-function@npm:^1.0.1":
- version: 1.0.1
- resolution: "@csstools/postcss-alpha-function@npm:1.0.1"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/35ca209e572534ade21ac5c18aad702aa492eb39e2d0e475f441371063418fe9650554e6a59b1318d3a615da83ef54d9a588faa27063ecc0a568ef7290a6b488
- languageName: node
- linkType: hard
-
-"@csstools/postcss-cascade-layers@npm:^5.0.2":
- version: 5.0.2
- resolution: "@csstools/postcss-cascade-layers@npm:5.0.2"
- dependencies:
- "@csstools/selector-specificity": "npm:^5.0.0"
- postcss-selector-parser: "npm:^7.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/dd8e29cfd3a93932fa35e3a59aa62fd2e720772d450f40f38f65ce1e736e2fe839635eb6f033abcc8ee8bc2856161a297f4458b352b26d2216856feb03176612
- languageName: node
- linkType: hard
-
-"@csstools/postcss-color-function-display-p3-linear@npm:^1.0.1":
- version: 1.0.1
- resolution: "@csstools/postcss-color-function-display-p3-linear@npm:1.0.1"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/d02d45410c9257f5620c766f861f8fa3762b74ef01fdba8060b33a4c98f929e2219cd476b25bd4181ac186158a4d99a0da555c0b6ba45a7ac4a3a5885baad1f5
- languageName: node
- linkType: hard
-
-"@csstools/postcss-color-function@npm:^4.0.12":
- version: 4.0.12
- resolution: "@csstools/postcss-color-function@npm:4.0.12"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/a355b04d90f89c8e37a4a23543151558060acc68fb2e7d1c3549bebeeae2b147eec26af1fbc6ee690f0ba4830263f2d181f5331d16d3483b5542be46996fa755
- languageName: node
- linkType: hard
-
-"@csstools/postcss-color-mix-function@npm:^3.0.12":
- version: 3.0.12
- resolution: "@csstools/postcss-color-mix-function@npm:3.0.12"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/3e98a5118852083d1f87a3f842f78088192b1f9f08fdf1f3b3ef1e8969e18fdadc1e3bcac3d113a07c8917a7e8fa65fdec55a31df9a1b726c8d7ae89db86e8e5
- languageName: node
- linkType: hard
-
-"@csstools/postcss-color-mix-variadic-function-arguments@npm:^1.0.2":
- version: 1.0.2
- resolution: "@csstools/postcss-color-mix-variadic-function-arguments@npm:1.0.2"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/34073f0f0d33e4958f90763e692955a8e8c678b74284234497c4aa0d2143756e1b3616e0c09832caad498870e227ca0a681316afe3a71224fc40ade0ead1bdd9
- languageName: node
- linkType: hard
-
-"@csstools/postcss-content-alt-text@npm:^2.0.8":
- version: 2.0.8
- resolution: "@csstools/postcss-content-alt-text@npm:2.0.8"
- dependencies:
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/4c330cc2a1e434688a62613ecceb1434cd725ce024c1ad8d4a4c76b9839d1f3ea8566a8c6494921e2b46ec7feef6af8ed6548c216dcb8f0feab4b1d52c96228e
- languageName: node
- linkType: hard
-
-"@csstools/postcss-contrast-color-function@npm:^2.0.12":
- version: 2.0.12
- resolution: "@csstools/postcss-contrast-color-function@npm:2.0.12"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/b783ce948cdf1513ee238e9115b42881a8d3e5d13c16038601b1c470d661cfaeeece4eea29904fb9fcae878bad86f766810fa798a703ab9ad4b0cf276b173f8f
- languageName: node
- linkType: hard
-
-"@csstools/postcss-exponential-functions@npm:^2.0.9":
- version: 2.0.9
- resolution: "@csstools/postcss-exponential-functions@npm:2.0.9"
- dependencies:
- "@csstools/css-calc": "npm:^2.1.4"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/78ea627a87fb23e12616c4e54150363b0e8793064634983dbe0368a0aca1ff73206c2d1f29845773daaf42787e7d1f180ce1b57c43e2b0d10da450101f9f34b6
- languageName: node
- linkType: hard
-
-"@csstools/postcss-font-format-keywords@npm:^4.0.0":
+"@csstools/css-tokenizer@npm:^4.0.0":
version: 4.0.0
- resolution: "@csstools/postcss-font-format-keywords@npm:4.0.0"
- dependencies:
- "@csstools/utilities": "npm:^2.0.0"
- postcss-value-parser: "npm:^4.2.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/eb794fb95fefcac75e606d185255e601636af177866a317b0c6b6c375055e7240be53918229fd8d4bba00df01bedd2256bdac2b0ad4a4c2ec64f9d27cd6ff639
+ resolution: "@csstools/css-tokenizer@npm:4.0.0"
+ checksum: 10c0/669cf3d0f9c8e1ffdf8c9955ad8beba0c8cfe03197fe29a4fcbd9ee6f7a18856cfa42c62670021a75183d9ab37f5d14a866e6a9df753a6c07f59e36797a9ea9f
languageName: node
linkType: hard
-"@csstools/postcss-gamut-mapping@npm:^2.0.11":
- version: 2.0.11
- resolution: "@csstools/postcss-gamut-mapping@npm:2.0.11"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/490b8ccf10e30879a4415afbdd3646e1cdac3671586b7916855cf47a536f3be75eed014396056bde6528e0cb76d904e79bad78afc0b499e837264cf22519d145
- languageName: node
- linkType: hard
-
-"@csstools/postcss-gradients-interpolation-method@npm:^5.0.12":
- version: 5.0.12
- resolution: "@csstools/postcss-gradients-interpolation-method@npm:5.0.12"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/70b3d6c7050ce882ed2281e71eb4493531ae8d55d21899920eeeb6c205d90aaf430419a66235484ccce3a1a1891367dfc0ef772f3866ae3a9d8ec5ddd0cfe894
- languageName: node
- linkType: hard
-
-"@csstools/postcss-hwb-function@npm:^4.0.12":
- version: 4.0.12
- resolution: "@csstools/postcss-hwb-function@npm:4.0.12"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/d0dac34da9d7ac654060b6b27690a419718e990b21ff3e63266ea59934a865bc6aeae8eb8e1ca3e227a8b2a208657e3ab70ccdf0437f1f09d21ab848bbffcaa2
- languageName: node
- linkType: hard
-
-"@csstools/postcss-ic-unit@npm:^4.0.4":
- version: 4.0.4
- resolution: "@csstools/postcss-ic-unit@npm:4.0.4"
- dependencies:
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- postcss-value-parser: "npm:^4.2.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/20168e70ecb4abf7a69e407d653b6c7c9c82f2c7b1da0920e1d035f62b5ef8552cc7f1b62e0dca318df13c348e79fba862e1a4bb0e9432119a82b10aeb511752
- languageName: node
- linkType: hard
-
-"@csstools/postcss-initial@npm:^2.0.1":
- version: 2.0.1
- resolution: "@csstools/postcss-initial@npm:2.0.1"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/dbff7084ef4f1c4647efe2b147001daf172003c15b5e22689f0540d03c8d362f2a332cd9cf136e6c8dcda7564ee30492a4267ea188f72cb9c1000fb9bcfbfef8
- languageName: node
- linkType: hard
-
-"@csstools/postcss-is-pseudo-class@npm:^5.0.3":
- version: 5.0.3
- resolution: "@csstools/postcss-is-pseudo-class@npm:5.0.3"
- dependencies:
- "@csstools/selector-specificity": "npm:^5.0.0"
- postcss-selector-parser: "npm:^7.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/7980f1cabf32850bac72552e4e9de47412359e36e259a92b9b9af25dae4cce42bbcc5fdca8f384a589565bf383ecb23dec3af9f084d8df18b82552318b2841b6
- languageName: node
- linkType: hard
-
-"@csstools/postcss-light-dark-function@npm:^2.0.11":
- version: 2.0.11
- resolution: "@csstools/postcss-light-dark-function@npm:2.0.11"
- dependencies:
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/0175be41bb0044a48bc98d5c55cce41ed6b9ada88253c5f20d0ca17287cba4b429742b458ac5744675b9a286109e13ac51d64e226ab16040d7b051ba64c0c77b
- languageName: node
- linkType: hard
-
-"@csstools/postcss-logical-float-and-clear@npm:^3.0.0":
- version: 3.0.0
- resolution: "@csstools/postcss-logical-float-and-clear@npm:3.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/71a20e8c37877bf68ae615d7bb93fc11b4f8da8be8b1dc1a6e0fc69e27f189712ed71436b8ed51fa69fdb98b8e6718df2b5f42f246c4d39badaf0e43020fcfd4
- languageName: node
- linkType: hard
-
-"@csstools/postcss-logical-overflow@npm:^2.0.0":
- version: 2.0.0
- resolution: "@csstools/postcss-logical-overflow@npm:2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/0e103343d3ff8b34eef01b02355c5e010d272fd12d149a242026bb13ab1577b7f3a11fd4514be9342d96f73d61dac1f093a9bd36ece591753ed09a84eb7fca0a
- languageName: node
- linkType: hard
-
-"@csstools/postcss-logical-overscroll-behavior@npm:^2.0.0":
- version: 2.0.0
- resolution: "@csstools/postcss-logical-overscroll-behavior@npm:2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/1649601bb26f04d760fb5ebc42cdf414fa2a380b8ec22fe1c117f664c286665a786bd7bbda01b7e7567eaf3cc018a4f36a5c9805f6751cc497da223e0ffe9524
- languageName: node
- linkType: hard
-
-"@csstools/postcss-logical-resize@npm:^3.0.0":
- version: 3.0.0
- resolution: "@csstools/postcss-logical-resize@npm:3.0.0"
- dependencies:
- postcss-value-parser: "npm:^4.2.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/4f12efcaf5468ff359bb3f32f0f66034b9acc9b3ac21fcd2f30a1c8998fc653ebac0091f35c8b7e8dbfe6ccf595aee67f9b06a67adf45a8844e49a82d98b4386
- languageName: node
- linkType: hard
-
-"@csstools/postcss-logical-viewport-units@npm:^3.0.4":
- version: 3.0.4
- resolution: "@csstools/postcss-logical-viewport-units@npm:3.0.4"
- dependencies:
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/f0b5ba38acde3bf0ca880c6e0a883950c99fa9919b0e6290c894d5716569663590f26aa1170fd9483ce14544e46afac006ab3b02781410d5e7c8dd1467c674ce
- languageName: node
- linkType: hard
-
-"@csstools/postcss-media-minmax@npm:^2.0.9":
- version: 2.0.9
- resolution: "@csstools/postcss-media-minmax@npm:2.0.9"
- dependencies:
- "@csstools/css-calc": "npm:^2.1.4"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/media-query-list-parser": "npm:^4.0.3"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/d82622ee9de6eacba1abbf31718cd58759d158ed8a575f36f08e982d07a7d83e51fb184178b96c6f7b76cb333bb33cac04d06a750b6b9c5c43ae1c56232880f9
- languageName: node
- linkType: hard
-
-"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^3.0.5":
- version: 3.0.5
- resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:3.0.5"
- dependencies:
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/media-query-list-parser": "npm:^4.0.3"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/a47abdaa7f4b26596bd9d6bb77aed872a232fc12bd144d2c062d9da626e8dfd8336e2fff67617dba61a1666c2b8027145b390d70d5cd4d4f608604e077cfb04e
- languageName: node
- linkType: hard
-
-"@csstools/postcss-nested-calc@npm:^4.0.0":
- version: 4.0.0
- resolution: "@csstools/postcss-nested-calc@npm:4.0.0"
- dependencies:
- "@csstools/utilities": "npm:^2.0.0"
- postcss-value-parser: "npm:^4.2.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/fb61512fa4909bdf0ee32a23e771145086c445f2208a737b52093c8adfab7362c56d3aeaf2a6e33ffcec067e99a07219775465d2fbb1a3ac30cdcfb278b218b7
- languageName: node
- linkType: hard
-
-"@csstools/postcss-normalize-display-values@npm:^4.0.1":
- version: 4.0.1
- resolution: "@csstools/postcss-normalize-display-values@npm:4.0.1"
- dependencies:
- postcss-value-parser: "npm:^4.2.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/5d19364bad8554b047cebd94ad7e203723ed76abaf690e4b92c74e6fc7c3642cb8858ade3263da61aff26d97bb258af567b1036e97865b7aa3b17522241fd1e1
- languageName: node
- linkType: hard
-
-"@csstools/postcss-oklab-function@npm:^4.0.12":
- version: 4.0.12
- resolution: "@csstools/postcss-oklab-function@npm:4.0.12"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/40d4f51b568c8299c054f8971d0e85fa7da609ba23ce6c84dc17e16bc3838640ed6da75c3886dc9a96a11005773c6e23cba13a5510c781b2d633d07ad7bda6b7
- languageName: node
- linkType: hard
-
-"@csstools/postcss-position-area-property@npm:^1.0.0":
- version: 1.0.0
- resolution: "@csstools/postcss-position-area-property@npm:1.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/38f770454d46bfed01d43a3f5e7ac07d3111399b374a7198ae6503cdb6288e410c7b4199f5a7af8f16aeb688216445ade97be417c084313d6c56f55e50d34559
- languageName: node
- linkType: hard
-
-"@csstools/postcss-progressive-custom-properties@npm:^4.2.1":
- version: 4.2.1
- resolution: "@csstools/postcss-progressive-custom-properties@npm:4.2.1"
- dependencies:
- postcss-value-parser: "npm:^4.2.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/56e9a147799719fd5c550c035437693dd50cdfef46d66a4f2ce8f196e1006a096aa47d412710a89c3dc9808068a0a101c7f607a507ed68e925580c6f921e84d5
- languageName: node
- linkType: hard
-
-"@csstools/postcss-property-rule-prelude-list@npm:^1.0.0":
- version: 1.0.0
- resolution: "@csstools/postcss-property-rule-prelude-list@npm:1.0.0"
- dependencies:
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/ae8bbca3a77ca59c21c11899a904f9d9417a19a3359d01dee042e0489b7ddfe7cea13ae275b7e7936d9b0b99c0a13f7f685f962cd63ca3d3d2b6e5eacc293a0d
- languageName: node
- linkType: hard
-
-"@csstools/postcss-random-function@npm:^2.0.1":
- version: 2.0.1
- resolution: "@csstools/postcss-random-function@npm:2.0.1"
- dependencies:
- "@csstools/css-calc": "npm:^2.1.4"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/475bacf685b8bb82942d388e9e3b95f4156800f370299f19f5acc490475dc2813100de81a5a6bf48b696b4d83247622005b616af3166a668556b4b1aceded70d
- languageName: node
- linkType: hard
-
-"@csstools/postcss-relative-color-syntax@npm:^3.0.12":
- version: 3.0.12
- resolution: "@csstools/postcss-relative-color-syntax@npm:3.0.12"
- dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/11af386c8193e22c148ac034eee94c56da3060bdbde3196d2d641b088e12de35bef187bcd7d421f9e4d49c4f1cfc28b24e136e62107e02ed7007a3a28f635d06
- languageName: node
- linkType: hard
-
-"@csstools/postcss-scope-pseudo-class@npm:^4.0.1":
- version: 4.0.1
- resolution: "@csstools/postcss-scope-pseudo-class@npm:4.0.1"
- dependencies:
- postcss-selector-parser: "npm:^7.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/6a0ca50fae655f4498200d1ce298ca794c85fbe2e3fd5d6419843254f055df5007a973e09b5f1e78e376c02b54278e411516c8d824300c68b265d3e5b311d7ee
- languageName: node
- linkType: hard
-
-"@csstools/postcss-sign-functions@npm:^1.1.4":
- version: 1.1.4
- resolution: "@csstools/postcss-sign-functions@npm:1.1.4"
- dependencies:
- "@csstools/css-calc": "npm:^2.1.4"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/ff58108b2527832a84c571a1f40224b5c8d2afa8db2fe3b1e3599ff6f3469d9f4c528a70eb3c25c5d7801e30474fabfec04e7c23bfdad8572ad492053cd4f899
- languageName: node
- linkType: hard
-
-"@csstools/postcss-stepped-value-functions@npm:^4.0.9":
- version: 4.0.9
- resolution: "@csstools/postcss-stepped-value-functions@npm:4.0.9"
- dependencies:
- "@csstools/css-calc": "npm:^2.1.4"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/f143ca06338c30abb2aa37adc3d7e43a78f3b4493093160cb5babe3ec8cf6b86d83876746ee8e162db87b5e9af6e0066958d89fe8b4a503a29568e5c57c1bf8a
- languageName: node
- linkType: hard
-
-"@csstools/postcss-syntax-descriptor-syntax-production@npm:^1.0.1":
- version: 1.0.1
- resolution: "@csstools/postcss-syntax-descriptor-syntax-production@npm:1.0.1"
- dependencies:
- "@csstools/css-tokenizer": "npm:^3.0.4"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/b9b3d84a50b86b1af1b8b7e56a64d5eebc1c89c323a5263306c5c69ddb05a4d468d7072a7786b0ea6601629035df0089565e9d98d55d0f4eb7201cf7ed1bb3e9
- languageName: node
- linkType: hard
-
-"@csstools/postcss-system-ui-font-family@npm:^1.0.0":
- version: 1.0.0
- resolution: "@csstools/postcss-system-ui-font-family@npm:1.0.0"
- dependencies:
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/6a81761ae3cae643659b1416a7a892cf1505474896193b8abc26cff319cb6b1a20b64c5330d64019fba458e058da3abc9407d0ebf0c102289c0b79ef99b4c6d6
- languageName: node
- linkType: hard
-
-"@csstools/postcss-text-decoration-shorthand@npm:^4.0.3":
- version: 4.0.3
- resolution: "@csstools/postcss-text-decoration-shorthand@npm:4.0.3"
- dependencies:
- "@csstools/color-helpers": "npm:^5.1.0"
- postcss-value-parser: "npm:^4.2.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/f6af7d5dcf599edcf76c5e396ef2d372bbe1c1f3fbaaccd91e91049e64b6ff68b44f459277aef0a8110baca3eaa21275012adc52ccb8c0fc526a4c35577f8fce
- languageName: node
- linkType: hard
-
-"@csstools/postcss-trigonometric-functions@npm:^4.0.9":
- version: 4.0.9
- resolution: "@csstools/postcss-trigonometric-functions@npm:4.0.9"
- dependencies:
- "@csstools/css-calc": "npm:^2.1.4"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/6ba3d381c977c224f01d47a36f78c9b99d3b89d060a357a9f8840537fdf497d9587a28165dc74e96abdf02f8db0a277d3558646355085a74c8915ee73c6780d1
- languageName: node
- linkType: hard
-
-"@csstools/postcss-unset-value@npm:^4.0.0":
- version: 4.0.0
- resolution: "@csstools/postcss-unset-value@npm:4.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/8424ac700ded5bf59d49310335896f10c069e2c3fc6a676b5d13ca5a6fb78689b948f50494df875da284c4c76651deb005eafba70d87e693274628c5a685abfa
- languageName: node
- linkType: hard
-
-"@csstools/selector-resolve-nested@npm:^3.1.0":
- version: 3.1.0
- resolution: "@csstools/selector-resolve-nested@npm:3.1.0"
- peerDependencies:
- postcss-selector-parser: ^7.0.0
- checksum: 10c0/c2b1a930ad03c1427ab90b28c4940424fb39e8175130148f16209be3a3937f7a146d5483ca1da1dfc100aa7ae86df713f0ee82d4bbaa9b986e7f47f35cb67cca
- languageName: node
- linkType: hard
-
-"@csstools/selector-specificity@npm:^5.0.0":
+"@csstools/media-query-list-parser@npm:^5.0.0":
version: 5.0.0
- resolution: "@csstools/selector-specificity@npm:5.0.0"
+ resolution: "@csstools/media-query-list-parser@npm:5.0.0"
peerDependencies:
- postcss-selector-parser: ^7.0.0
- checksum: 10c0/186b444cabcdcdeb553bfe021f80c58bfe9ef38dcc444f2b1f34a5aab9be063ab4e753022b2d5792049c041c28cfbb78e4b707ec398459300e402030d35c07eb
+ "@csstools/css-parser-algorithms": ^4.0.0
+ "@csstools/css-tokenizer": ^4.0.0
+ checksum: 10c0/dbc22654769eca02c182f3a57be02cd5b8d0b958adc8397e66770b64b0e8fcd32faa93a3f6a99e1457bde11862485de3cd83a31dac7b03925d32f9891b31ccfd
languageName: node
linkType: hard
-"@csstools/stylelint-formatter-github@npm:^1.0.0":
- version: 1.0.0
- resolution: "@csstools/stylelint-formatter-github@npm:1.0.0"
- peerDependencies:
- stylelint: ^16.6.0
- checksum: 10c0/2052c4e4d89656b2b4176a6d07508ef73278d33c24a7408a3555d07f26ec853f85da95525590c51751fb3150a2ebb5e3083d8200dc6597af2cd8e93198695269
- languageName: node
- linkType: hard
-
-"@csstools/utilities@npm:^2.0.0":
- version: 2.0.0
- resolution: "@csstools/utilities@npm:2.0.0"
+"@csstools/postcss-alpha-function@npm:^2.0.2":
+ version: 2.0.2
+ resolution: "@csstools/postcss-alpha-function@npm:2.0.2"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/be5c31437b726928f64cd4bb3e47f5b90bfd2e2a69a8eaabd8e89cc6c0977e4f0f7ee48de50c8ed8b07e04e3956a02293247e0da3236d521fb2e836f88f65822
+ checksum: 10c0/2ffb1d4c6db63f9b841b8de18a0baf1b37bc321632af4d8dc0bba0c9472980ffb9c3c94a4b3445eedcc986399791fd2bc5e682b676d5a021d4db3e2602ad892f
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-cascade-layers@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "@csstools/postcss-cascade-layers@npm:6.0.0"
+ dependencies:
+ "@csstools/selector-specificity": "npm:^6.0.0"
+ postcss-selector-parser: "npm:^7.1.1"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/f9cf3fa52d0f2615a69ad52067cc2229573151525792272eb82a28f0feca64f9ca54e8459c0ae5c254807507e4630aa9866690a4b22e57250c353ee28db86a50
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-color-function-display-p3-linear@npm:^2.0.1":
+ version: 2.0.1
+ resolution: "@csstools/postcss-color-function-display-p3-linear@npm:2.0.1"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/cc6b79d8a19338f930f68bf4bac31bcbf38842068ed5779193979b5e2041a7b12386e4e992065cbf898c537ac6887ac530651f2164aaf77ced92d1bc4dd4ae50
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-color-function@npm:^5.0.1":
+ version: 5.0.1
+ resolution: "@csstools/postcss-color-function@npm:5.0.1"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/c6d28aae458a2f914367b3fa87ac300366bcf44c57ed7a6c6ebcdaec4d42901b7892a867b01d23af0edc0798035e205a7e590ccc3f288c632d8ed5ed9219455b
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-color-mix-function@npm:^4.0.1":
+ version: 4.0.1
+ resolution: "@csstools/postcss-color-mix-function@npm:4.0.1"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/5137bb1fe2037609366e6282000ed1305151988a6968e336e9599cfed020495f9bf523d2eab64f83d74089f15a30d26d376a49c32ae3a3df16b3846d8690e477
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-color-mix-variadic-function-arguments@npm:^2.0.1":
+ version: 2.0.1
+ resolution: "@csstools/postcss-color-mix-variadic-function-arguments@npm:2.0.1"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/b4cd04a4650ba1b3340d99e5d020e860cef481d4ba4ecf1300ffb20863778a3376742c2b1209f14f0b13f1c0c63c7f3d84d1df812ef2a26ea53934f2f676d1df
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-content-alt-text@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/postcss-content-alt-text@npm:3.0.0"
+ dependencies:
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/88f62ade9fa8af8b3292d9437e4df2002d79c139fc63e3030a72276a56cc5a13904fb18d20f07b09de45904da1a37eee4b448cdad07487fc28f96a0e3209bb9d
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-contrast-color-function@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "@csstools/postcss-contrast-color-function@npm:3.0.1"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/00d17c77aae78953782cb51988fa76c00bb25316a59aba7a70c11142554f49ad48ce37963f10689fd908a98484d16e9531e808e5d2df60ae26aa6509a0c6b4f5
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-exponential-functions@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/postcss-exponential-functions@npm:3.0.0"
+ dependencies:
+ "@csstools/css-calc": "npm:^3.0.0"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/911101ec98ac89f56cb7ea52ab2d836646b48e13163d46e1a1f70b680dcc903d314ddf80eeeecfa7b561a99fad2f4b6ce2b0702fbcaa6d379b2c047bde20d398
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-font-format-keywords@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "@csstools/postcss-font-format-keywords@npm:5.0.0"
+ dependencies:
+ "@csstools/utilities": "npm:^3.0.0"
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/ae776eb164a4501549924a0b153c47cac31b4d288867c71775ff34941653bfe38d3d5a27888ab76fbef0289163e1687daae74e0b317547b7bd281e63b75afa98
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-gamut-mapping@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "@csstools/postcss-gamut-mapping@npm:3.0.1"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/a94337b13ed0332e2a80d07424e07bd726339476ce0ac009d00238c39b007cc7f2d58aeb48fe04d366a3015d7032f41bcc6a223f2f108574dcbfff7e53f694b0
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-gradients-interpolation-method@npm:^6.0.1":
+ version: 6.0.1
+ resolution: "@csstools/postcss-gradients-interpolation-method@npm:6.0.1"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/c930cfba3168d7d2016f7b30489fe3e8e6433ef2cc922635fb088946495439d7a4505ca65841897da60760c2962e0a112a15c0f67845e7f0ac9377e2736cc8c8
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-hwb-function@npm:^5.0.1":
+ version: 5.0.1
+ resolution: "@csstools/postcss-hwb-function@npm:5.0.1"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/3951f49fdf081133bc339011e909fd60a2e36618a2ee20acf00baa0e1ebc6d5e30e988f5d70a4017c5247ef699d77e55ea9bb32cd7eb7a3683d2fc0f202429aa
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-ic-unit@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "@csstools/postcss-ic-unit@npm:5.0.0"
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/04148390bcdd0722af7bab6e05dbc573d8d1b5a216ca1f1021ea0cec955a8c3489e4788b3649f3a7be4a9267e0b3a6012f5e9d80d6f3ac3f1f52e585e5ce0c6e
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-initial@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/postcss-initial@npm:3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/4c59994c1ff6443f69ba54d2177adf3441756f067876500f281bd3021da1d9a18ae36cf7264a7ef7ca720508cac936f1120dc872f57fb3f6f28ac523c111a890
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-is-pseudo-class@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "@csstools/postcss-is-pseudo-class@npm:6.0.0"
+ dependencies:
+ "@csstools/selector-specificity": "npm:^6.0.0"
+ postcss-selector-parser: "npm:^7.1.1"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/55dfb215843258167426eecf7cb8dd2361c2502722469ffc4f3aa7bad6987a08c5ff819ef6bca427c59ee9ad7b3942b89b17bde1d0288ece03f8760c56df7542
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-light-dark-function@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/postcss-light-dark-function@npm:3.0.0"
+ dependencies:
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/769324f8acda2ce759cad959f43d49ccbc578ccb326362260019a7f7a126408c925d49f437c85d28fb2696cfe1405740a271c250184d9f34ea5603a0b8220936
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-logical-float-and-clear@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "@csstools/postcss-logical-float-and-clear@npm:4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/bbb2e69878965943fc9686c4827a2f363f7a42c051e6df288e68d68741b424fb3cbdc2aa3e2d2169bcf1a4cfd6a24f0aa06c3061ea02ac03e0ad0bfae8fdc999
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-logical-overflow@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/postcss-logical-overflow@npm:3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/cca3397de39eb858a216d0566598ff24a8c94d20c12630568437d8145d78c0d5f36533c72dab72f50702dabbcada87fd34b1129aa4d9c24b427aaa211df124c1
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-logical-overscroll-behavior@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/postcss-logical-overscroll-behavior@npm:3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/0138d89c739dae70b3496d68e08109d97c82d0038fe9bcc5b40f6efb136428def62e81c316f1902d2e4e5611c90c66f70e2008e99fdd0c7358dcfdffb4e326cc
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-logical-resize@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "@csstools/postcss-logical-resize@npm:4.0.0"
+ dependencies:
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/b9a7eb1ecb1637dac76c957e05f3579e390514d3e93245b5e0a3764542e7875c89811c3526548d466a2fdf76f1cd1a8fadb62c536b3d2521d4310a2f143e405e
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-logical-viewport-units@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "@csstools/postcss-logical-viewport-units@npm:4.0.0"
+ dependencies:
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/1213ee92b5d9aad68c65478d4243dbd1bd75b88090edec18e1ebaf0aa38459a53609b9aa0e8c48070d546a1c873b1de94a5449fa173a3440334a3ba366c14549
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-media-minmax@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/postcss-media-minmax@npm:3.0.0"
+ dependencies:
+ "@csstools/css-calc": "npm:^3.0.0"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/media-query-list-parser": "npm:^5.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/0b03ab1ad162d53eef69470246025d01390cc84d2cb0983ffaf09c47bb3d27951e4794638430e778c737cf57c891f834adf3be08fcd5a84c4f6698a03ee9be4a
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:4.0.0"
+ dependencies:
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/media-query-list-parser": "npm:^5.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/80397e21d16f443445d03b79171c5c5444ef0e921a6eb1e0419eec24150bd9112469e2e9825aaf0612fa98d05fb0a50cf09f09c2b86d01a238229f205c15d2b2
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-mixins@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "@csstools/postcss-mixins@npm:1.0.0"
+ dependencies:
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/3160f87f8c307ccdb97fe9ef3507c36e59bec11c0cfa7e486fbe7b0df96cb41b071d7e475d8ef52974bbcc4bf8a2243d5c2c849c0ba8a171aa384ba4b6c0b768
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-nested-calc@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "@csstools/postcss-nested-calc@npm:5.0.0"
+ dependencies:
+ "@csstools/utilities": "npm:^3.0.0"
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/57764637a4855e941ab9360e1b4603e1fa0a29043148b67b80629d12ae4c93b4d2f156069826c4b8100ad3a90552744424b9a1e05710fe9b6958e1a817e6e07e
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-normalize-display-values@npm:^5.0.1":
+ version: 5.0.1
+ resolution: "@csstools/postcss-normalize-display-values@npm:5.0.1"
+ dependencies:
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/16b53d11db7ea6a48e1e43e06eb76d4d2b5c2c9af43b4f7e4d0d03345aa5f935a625d321d38a607739bfb59f6cc24b0506983dc5c599a7b795626ada33bba68f
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-oklab-function@npm:^5.0.1":
+ version: 5.0.1
+ resolution: "@csstools/postcss-oklab-function@npm:5.0.1"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/ef5298c499fda9854f93d8ab1416cdb2bdb9120bca14ac7f97ea867821777aa67219c7784ffd70c793b02ba3ca3988a1c5f4fbd8be43f5d97cae822556847fe2
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-position-area-property@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "@csstools/postcss-position-area-property@npm:2.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/54b9a97a9ef636dfc8b62cdabb7d194438c6f510effdff4339073626446c078033d475dfec8c82fdbcf25745fb05caafffc9512e3be7ff53ced55f1d38d2da6a
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-progressive-custom-properties@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "@csstools/postcss-progressive-custom-properties@npm:5.0.0"
+ dependencies:
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/8476a58b777e7015f40fea53829d31429c8bab114b884b87c1706b5df095102232fb46b275a76c719f73399d3dbdfec2c172fb68c2fb362dbe68569446366a1a
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-property-rule-prelude-list@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "@csstools/postcss-property-rule-prelude-list@npm:2.0.0"
+ dependencies:
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/6ce0c962391b27966fba1623bca2dacc61fb7b1c9916f08d17256a800b0f8476d34835d50cb2ed77bdc4e920e4be5dddc1569c7e5140895e7b0076694d769182
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-random-function@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/postcss-random-function@npm:3.0.0"
+ dependencies:
+ "@csstools/css-calc": "npm:^3.0.0"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/bf9b8836ce3eafd670bfb9fa16d3befde8827ad220edc80eb4301fa716c1a4ff444254ab7612a6f6f952d16d3ac6d6e594448dcdd860f6ca8b575ffe59946864
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-relative-color-syntax@npm:^4.0.1":
+ version: 4.0.1
+ resolution: "@csstools/postcss-relative-color-syntax@npm:4.0.1"
+ dependencies:
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/101cb35ac950f45f21cb5aa853b57e304178d366390036e5390eda0ebcc21032f096d77863f6d978233f3b52b02c77acb6c394a965260ad41d1f49ddc0015aae
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-scope-pseudo-class@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "@csstools/postcss-scope-pseudo-class@npm:5.0.0"
+ dependencies:
+ postcss-selector-parser: "npm:^7.1.1"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/2b67bd6af9a1175ca47c6593ee73564d70cb39c1adc9ffc5099ba513b49055994786c60687b44d88beccd09f1a6196e5e9157fd439632ae34381a60adaef5246
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-sign-functions@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "@csstools/postcss-sign-functions@npm:2.0.0"
+ dependencies:
+ "@csstools/css-calc": "npm:^3.0.0"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/e5239e012e78cfcb244e8599d93700bbbcd15fd78e4a71f8bd5296022bd1d1ead750689bdacc35a47d2061729dd727e2fb1a185bee0620a62b64e4ee3434861e
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-stepped-value-functions@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "@csstools/postcss-stepped-value-functions@npm:5.0.0"
+ dependencies:
+ "@csstools/css-calc": "npm:^3.0.0"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/a8354fa0f4b74def1c258bf267c00d029f65618ccebb9c14837522f11eeb6b673717b56720588d5fec7bd07036ed84826dea01c44e9a085ae7af78a2b4ea7ec0
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-syntax-descriptor-syntax-production@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "@csstools/postcss-syntax-descriptor-syntax-production@npm:2.0.0"
+ dependencies:
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/0c9ef2f5cd21079db1df497adf99a3d66c912f69c471dd89283a1b8ed3a9c4e7670bfa439b615ac27acd86ce2e1adf4a5eb7b551113ecf5e95ee77269446bbbe
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-system-ui-font-family@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "@csstools/postcss-system-ui-font-family@npm:2.0.0"
+ dependencies:
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/e4f59c093565ed3753f3561a754fe3c0c8152a3b25f184cb370fa5cb1e9b54ad62fe53f7886ed840d445201120197ae6d42c6266ef4d5cfd063226f95c433c06
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-text-decoration-shorthand@npm:^5.0.1":
+ version: 5.0.1
+ resolution: "@csstools/postcss-text-decoration-shorthand@npm:5.0.1"
+ dependencies:
+ "@csstools/color-helpers": "npm:^6.0.1"
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/e9a6f4d02a4584bf227783296eb4016542d70345152c2c0f1012146376eaf7e3efa7e27d8eab6856857612b8d682ea1085b5d027ad6f05406e0adee7b6244c33
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-trigonometric-functions@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "@csstools/postcss-trigonometric-functions@npm:5.0.0"
+ dependencies:
+ "@csstools/css-calc": "npm:^3.0.0"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/8b2e149f4fb8ac1bc7a642c99265df7f54729fbace29cde24f65078c0d97e9050e75576ef55b869ab78fbb94a2408adae2bc6f3ced759fca96519c6ceb92cc20
+ languageName: node
+ linkType: hard
+
+"@csstools/postcss-unset-value@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "@csstools/postcss-unset-value@npm:5.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/21e26cccf7824e4366378a20bc043034105db654632b941f77a0cbbf4fe0de291d1ae94845280c08c8d851ae14ce6d07bc09a33c5fbbcb7ce1f21b10212df1f1
+ languageName: node
+ linkType: hard
+
+"@csstools/selector-resolve-nested@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "@csstools/selector-resolve-nested@npm:4.0.0"
+ peerDependencies:
+ postcss-selector-parser: ^7.1.1
+ checksum: 10c0/f6bccfe24a47c3e55710d421740550b868bbe7f0820f32d14d1eb737eefe7ec26261fb726cc5cfdf8236b3173d0a657ebdc9602e0c53824603f719b14a76bcaf
+ languageName: node
+ linkType: hard
+
+"@csstools/selector-specificity@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "@csstools/selector-specificity@npm:6.0.0"
+ peerDependencies:
+ postcss-selector-parser: ^7.1.1
+ checksum: 10c0/7a93973f9054f2e1f03c8543cde68e0b0c65e5e72da6e4e959974d28fe809e11bd2afa1ff2ca11a1690a4c9a2f2bbe00d00e2b07fb2108bf89c5e48fe441c432
+ languageName: node
+ linkType: hard
+
+"@csstools/stylelint-formatter-github@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "@csstools/stylelint-formatter-github@npm:2.0.0"
+ peerDependencies:
+ stylelint: ^17.0.0
+ checksum: 10c0/1eddcb749eb93efff2e2d7edb4405459bf558ceaa6d90e792408802f30c55e3482a4cead9e69fd651f04a927e863782fc6cf813c37433da9ff1f068910080a06
+ languageName: node
+ linkType: hard
+
+"@csstools/utilities@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@csstools/utilities@npm:3.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/65b6f6aa4ea899777bea710aab5f17028aa5e1aa41f7fe892c2e916b188da2b929c76be643d4a5d8d9ca5a7853df94f05c0247dd6b63540b360055d36db3104f
languageName: node
linkType: hard
@@ -1916,13 +1974,6 @@ __metadata:
languageName: node
linkType: hard
-"@dual-bundle/import-meta-resolve@npm:^4.2.1":
- version: 4.2.1
- resolution: "@dual-bundle/import-meta-resolve@npm:4.2.1"
- checksum: 10c0/8f1e572c14c4d20ea35734635085213abd13bd440c251309cf8ae5ed1082f6759cefa1c2c52a631f76859c57e26062f78a8cee4acc239c0edc87cd316a5d3b5b
- languageName: node
- linkType: hard
-
"@emnapi/core@npm:^1.4.3":
version: 1.4.5
resolution: "@emnapi/core@npm:1.4.5"
@@ -2095,13 +2146,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/aix-ppc64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/aix-ppc64@npm:0.25.5"
- conditions: os=aix & cpu=ppc64
- languageName: node
- linkType: hard
-
"@esbuild/aix-ppc64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/aix-ppc64@npm:0.27.2"
@@ -2109,13 +2153,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/android-arm64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/android-arm64@npm:0.25.5"
- conditions: os=android & cpu=arm64
- languageName: node
- linkType: hard
-
"@esbuild/android-arm64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/android-arm64@npm:0.27.2"
@@ -2123,13 +2160,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/android-arm@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/android-arm@npm:0.25.5"
- conditions: os=android & cpu=arm
- languageName: node
- linkType: hard
-
"@esbuild/android-arm@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/android-arm@npm:0.27.2"
@@ -2137,13 +2167,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/android-x64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/android-x64@npm:0.25.5"
- conditions: os=android & cpu=x64
- languageName: node
- linkType: hard
-
"@esbuild/android-x64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/android-x64@npm:0.27.2"
@@ -2151,13 +2174,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/darwin-arm64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/darwin-arm64@npm:0.25.5"
- conditions: os=darwin & cpu=arm64
- languageName: node
- linkType: hard
-
"@esbuild/darwin-arm64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/darwin-arm64@npm:0.27.2"
@@ -2165,13 +2181,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/darwin-x64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/darwin-x64@npm:0.25.5"
- conditions: os=darwin & cpu=x64
- languageName: node
- linkType: hard
-
"@esbuild/darwin-x64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/darwin-x64@npm:0.27.2"
@@ -2179,13 +2188,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/freebsd-arm64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/freebsd-arm64@npm:0.25.5"
- conditions: os=freebsd & cpu=arm64
- languageName: node
- linkType: hard
-
"@esbuild/freebsd-arm64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/freebsd-arm64@npm:0.27.2"
@@ -2193,13 +2195,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/freebsd-x64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/freebsd-x64@npm:0.25.5"
- conditions: os=freebsd & cpu=x64
- languageName: node
- linkType: hard
-
"@esbuild/freebsd-x64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/freebsd-x64@npm:0.27.2"
@@ -2207,13 +2202,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/linux-arm64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/linux-arm64@npm:0.25.5"
- conditions: os=linux & cpu=arm64
- languageName: node
- linkType: hard
-
"@esbuild/linux-arm64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/linux-arm64@npm:0.27.2"
@@ -2221,13 +2209,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/linux-arm@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/linux-arm@npm:0.25.5"
- conditions: os=linux & cpu=arm
- languageName: node
- linkType: hard
-
"@esbuild/linux-arm@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/linux-arm@npm:0.27.2"
@@ -2235,13 +2216,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/linux-ia32@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/linux-ia32@npm:0.25.5"
- conditions: os=linux & cpu=ia32
- languageName: node
- linkType: hard
-
"@esbuild/linux-ia32@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/linux-ia32@npm:0.27.2"
@@ -2249,13 +2223,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/linux-loong64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/linux-loong64@npm:0.25.5"
- conditions: os=linux & cpu=loong64
- languageName: node
- linkType: hard
-
"@esbuild/linux-loong64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/linux-loong64@npm:0.27.2"
@@ -2263,13 +2230,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/linux-mips64el@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/linux-mips64el@npm:0.25.5"
- conditions: os=linux & cpu=mips64el
- languageName: node
- linkType: hard
-
"@esbuild/linux-mips64el@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/linux-mips64el@npm:0.27.2"
@@ -2277,13 +2237,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/linux-ppc64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/linux-ppc64@npm:0.25.5"
- conditions: os=linux & cpu=ppc64
- languageName: node
- linkType: hard
-
"@esbuild/linux-ppc64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/linux-ppc64@npm:0.27.2"
@@ -2291,13 +2244,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/linux-riscv64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/linux-riscv64@npm:0.25.5"
- conditions: os=linux & cpu=riscv64
- languageName: node
- linkType: hard
-
"@esbuild/linux-riscv64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/linux-riscv64@npm:0.27.2"
@@ -2305,13 +2251,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/linux-s390x@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/linux-s390x@npm:0.25.5"
- conditions: os=linux & cpu=s390x
- languageName: node
- linkType: hard
-
"@esbuild/linux-s390x@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/linux-s390x@npm:0.27.2"
@@ -2319,13 +2258,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/linux-x64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/linux-x64@npm:0.25.5"
- conditions: os=linux & cpu=x64
- languageName: node
- linkType: hard
-
"@esbuild/linux-x64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/linux-x64@npm:0.27.2"
@@ -2333,13 +2265,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/netbsd-arm64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/netbsd-arm64@npm:0.25.5"
- conditions: os=netbsd & cpu=arm64
- languageName: node
- linkType: hard
-
"@esbuild/netbsd-arm64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/netbsd-arm64@npm:0.27.2"
@@ -2347,13 +2272,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/netbsd-x64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/netbsd-x64@npm:0.25.5"
- conditions: os=netbsd & cpu=x64
- languageName: node
- linkType: hard
-
"@esbuild/netbsd-x64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/netbsd-x64@npm:0.27.2"
@@ -2361,13 +2279,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/openbsd-arm64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/openbsd-arm64@npm:0.25.5"
- conditions: os=openbsd & cpu=arm64
- languageName: node
- linkType: hard
-
"@esbuild/openbsd-arm64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/openbsd-arm64@npm:0.27.2"
@@ -2375,13 +2286,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/openbsd-x64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/openbsd-x64@npm:0.25.5"
- conditions: os=openbsd & cpu=x64
- languageName: node
- linkType: hard
-
"@esbuild/openbsd-x64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/openbsd-x64@npm:0.27.2"
@@ -2396,13 +2300,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/sunos-x64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/sunos-x64@npm:0.25.5"
- conditions: os=sunos & cpu=x64
- languageName: node
- linkType: hard
-
"@esbuild/sunos-x64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/sunos-x64@npm:0.27.2"
@@ -2410,13 +2307,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/win32-arm64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/win32-arm64@npm:0.25.5"
- conditions: os=win32 & cpu=arm64
- languageName: node
- linkType: hard
-
"@esbuild/win32-arm64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/win32-arm64@npm:0.27.2"
@@ -2424,13 +2314,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/win32-ia32@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/win32-ia32@npm:0.25.5"
- conditions: os=win32 & cpu=ia32
- languageName: node
- linkType: hard
-
"@esbuild/win32-ia32@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/win32-ia32@npm:0.27.2"
@@ -2438,13 +2321,6 @@ __metadata:
languageName: node
linkType: hard
-"@esbuild/win32-x64@npm:0.25.5":
- version: 0.25.5
- resolution: "@esbuild/win32-x64@npm:0.25.5"
- conditions: os=win32 & cpu=x64
- languageName: node
- linkType: hard
-
"@esbuild/win32-x64@npm:0.27.2":
version: 0.27.2
resolution: "@esbuild/win32-x64@npm:0.27.2"
@@ -2959,7 +2835,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@mastodon/mastodon@workspace:."
dependencies:
- "@csstools/stylelint-formatter-github": "npm:^1.0.0"
+ "@csstools/stylelint-formatter-github": "npm:^2.0.0"
"@dnd-kit/core": "npm:^6.1.0"
"@dnd-kit/sortable": "npm:^10.0.0"
"@dnd-kit/utilities": "npm:^3.2.2"
@@ -3039,7 +2915,7 @@ __metadata:
fake-indexeddb: "npm:^6.0.1"
fast-glob: "npm:^3.3.3"
fuzzysort: "npm:^3.0.0"
- globals: "npm:^16.0.0"
+ globals: "npm:^17.0.0"
history: "npm:^4.10.1"
hoist-non-react-statics: "npm:^3.3.2"
http-link-header: "npm:^1.1.1"
@@ -3056,7 +2932,7 @@ __metadata:
msw-storybook-addon: "npm:^2.0.6"
path-complete-extname: "npm:^1.0.0"
playwright: "npm:^1.57.0"
- postcss-preset-env: "npm:^10.1.5"
+ postcss-preset-env: "npm:^11.0.0"
prettier: "npm:^3.3.3"
prop-types: "npm:^15.8.1"
punycode: "npm:^2.3.0"
@@ -3086,9 +2962,9 @@ __metadata:
stacktrace-js: "npm:^2.0.2"
storybook: "npm:^10.0.5"
stringz: "npm:^2.1.0"
- stylelint: "npm:^16.19.1"
+ stylelint: "npm:^17.0.0"
stylelint-config-prettier-scss: "npm:^1.0.0"
- stylelint-config-standard-scss: "npm:^16.0.0"
+ stylelint-config-standard-scss: "npm:^17.0.0"
substring-trie: "npm:^1.0.2"
tesseract.js: "npm:^7.0.0"
tiny-queue: "npm:^0.2.1"
@@ -3129,9 +3005,9 @@ __metadata:
"@types/ws": "npm:^8.5.9"
bufferutil: "npm:^4.0.7"
cors: "npm:^2.8.5"
- dotenv: "npm:^16.0.3"
+ dotenv: "npm:^17.0.0"
express: "npm:^5.1.0"
- globals: "npm:^16.0.0"
+ globals: "npm:^17.0.0"
ioredis: "npm:^5.3.2"
jsdom: "npm:^27.0.0"
pg: "npm:^8.5.0"
@@ -3816,6 +3692,13 @@ __metadata:
languageName: node
linkType: hard
+"@sindresorhus/merge-streams@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "@sindresorhus/merge-streams@npm:4.0.0"
+ checksum: 10c0/482ee543629aa1933b332f811a1ae805a213681ecdd98c042b1c1b89387df63e7812248bb4df3910b02b3cc5589d3d73e4393f30e197c9dde18046ccd471fc6b
+ languageName: node
+ linkType: hard
+
"@standard-schema/spec@npm:^1.0.0":
version: 1.0.0
resolution: "@standard-schema/spec@npm:1.0.0"
@@ -5453,13 +5336,6 @@ __metadata:
languageName: node
linkType: hard
-"array-union@npm:^2.1.0":
- version: 2.1.0
- resolution: "array-union@npm:2.1.0"
- checksum: 10c0/429897e68110374f39b771ec47a7161fc6a8fc33e196857c0a396dc75df0b5f65e4d046674db764330b6bb66b39ef48dd7c53b6a2ee75cfb0681e0c1a7033962
- languageName: node
- linkType: hard
-
"array.prototype.findlast@npm:^1.2.5":
version: 1.2.5
resolution: "array.prototype.findlast@npm:1.2.5"
@@ -5660,13 +5536,13 @@ __metadata:
linkType: hard
"axios@npm:^1.4.0":
- version: 1.13.2
- resolution: "axios@npm:1.13.2"
+ version: 1.13.4
+ resolution: "axios@npm:1.13.4"
dependencies:
follow-redirects: "npm:^1.15.6"
form-data: "npm:^4.0.4"
proxy-from-env: "npm:^1.1.0"
- checksum: 10c0/e8a42e37e5568ae9c7a28c348db0e8cf3e43d06fcbef73f0048669edfe4f71219664da7b6cc991b0c0f01c28a48f037c515263cb79be1f1ae8ff034cd813867b
+ checksum: 10c0/474c00b7d71f4de4ad562589dae6b615149df7c2583bbc5ebba96229f3f85bfb0775d23705338df072f12e48d3e85685c065a3cf6855d58968a672d19214c728
languageName: node
linkType: hard
@@ -5757,10 +5633,10 @@ __metadata:
languageName: node
linkType: hard
-"balanced-match@npm:^2.0.0":
- version: 2.0.0
- resolution: "balanced-match@npm:2.0.0"
- checksum: 10c0/60a54e0b75a61674e16a7a336b805f06c72d6f8fc457639c24efc512ba2bf9cb5744b9f6f5225afcefb99da39714440c83c737208cc65c5d9ecd1f3093331ca3
+"balanced-match@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "balanced-match@npm:3.0.1"
+ checksum: 10c0/ac8dd63a5b260610c2cbda982f436e964c1b9ae8764d368a523769da40a31710abd6e19f0fdf1773c4ad7b2ea7ba7b285d547375dc723f6e754369835afc8e9f
languageName: node
linkType: hard
@@ -6300,19 +6176,19 @@ __metadata:
linkType: hard
"core-js@npm:^3.30.2, core-js@npm:^3.45.0":
- version: 3.47.0
- resolution: "core-js@npm:3.47.0"
- checksum: 10c0/9b1a7088b7c660c7b8f1d4c90bb1816a8d5352ebdcb7bc742e3a0e4eb803316b5aa17bacb8769522342196351a5430178f46914644f2bfdb94ce0ced3c7fd523
+ version: 3.48.0
+ resolution: "core-js@npm:3.48.0"
+ checksum: 10c0/6c3115900dd7cce9fab74c07cb262b3517fc250d02e8fd2ff34f80bda5f43a28482a909dbc4491dc6e1ddd9807f57a7df4c3eeecd1f202b7d9c8bfe25f9d680c
languageName: node
linkType: hard
"cors@npm:^2.8.5":
- version: 2.8.5
- resolution: "cors@npm:2.8.5"
+ version: 2.8.6
+ resolution: "cors@npm:2.8.6"
dependencies:
object-assign: "npm:^4"
vary: "npm:^1"
- checksum: 10c0/373702b7999409922da80de4a61938aabba6929aea5b6fd9096fefb9e8342f626c0ebd7507b0e8b0b311380744cc985f27edebc0a26e0ddb784b54e1085de761
+ checksum: 10c0/ab2bc57b8af8ef8476682a59647f7c55c1a7d406b559ac06119aa1c5f70b96d35036864d197b24cf86e228e4547231088f1f94ca05061dbb14d89cc0bc9d4cab
languageName: node
linkType: hard
@@ -6394,14 +6270,14 @@ __metadata:
languageName: node
linkType: hard
-"css-blank-pseudo@npm:^7.0.1":
- version: 7.0.1
- resolution: "css-blank-pseudo@npm:7.0.1"
+"css-blank-pseudo@npm:^8.0.1":
+ version: 8.0.1
+ resolution: "css-blank-pseudo@npm:8.0.1"
dependencies:
- postcss-selector-parser: "npm:^7.0.0"
+ postcss-selector-parser: "npm:^7.1.1"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/46c3d3a611972fdb0c264db7c0b34fe437bc4300961d11945145cf04962f52a545a6ef55bc8ff4afd82b605bd692b4970f2b54582616dea00441105e725d4618
+ checksum: 10c0/851d38cb3e11a63db4a0f44751cde99d6825bb11adc78418e8e83f32f0a3dcc3245e6e4b5053e796635560a1224af8ae63dfe330f87175fcc7bf34a1af3ecddc
languageName: node
linkType: hard
@@ -6412,25 +6288,25 @@ __metadata:
languageName: node
linkType: hard
-"css-has-pseudo@npm:^7.0.3":
- version: 7.0.3
- resolution: "css-has-pseudo@npm:7.0.3"
+"css-has-pseudo@npm:^8.0.0":
+ version: 8.0.0
+ resolution: "css-has-pseudo@npm:8.0.0"
dependencies:
- "@csstools/selector-specificity": "npm:^5.0.0"
- postcss-selector-parser: "npm:^7.0.0"
+ "@csstools/selector-specificity": "npm:^6.0.0"
+ postcss-selector-parser: "npm:^7.1.1"
postcss-value-parser: "npm:^4.2.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/c89f68e17bed229e9a3e98da5032e1360c83d45d974bc3fb8d6b5358399bca80cce7929e4a621a516a75536edb78678dc486eb41841eeed28cca79e3be4bdc27
+ checksum: 10c0/fb623c09d3cb1d5ec029c61b5a24484ee712fbd20bffae37a20a2843917706cadb1c4d695585382e4839dde136922ffee6924ec83f633dde2e2afc6d77a26be8
languageName: node
linkType: hard
-"css-prefers-color-scheme@npm:^10.0.0":
- version: 10.0.0
- resolution: "css-prefers-color-scheme@npm:10.0.0"
+"css-prefers-color-scheme@npm:^11.0.0":
+ version: 11.0.0
+ resolution: "css-prefers-color-scheme@npm:11.0.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/a66c727bb2455328b18862f720819fc98ff5c1486b69f758bdb5c66f46cc6d484f9fc0bfa4f00f2693c5da6707ad136ca789496982f713ade693f08af624930e
+ checksum: 10c0/dea9f17cc33b5bedb660ed3925a53c9034bd5f4f94222d3b6df1dffd011061c124800dfc3bbeb1136fd69e84be577c63ac3da9220e175ea10b49275d7d0ada40
languageName: node
linkType: hard
@@ -6451,10 +6327,10 @@ __metadata:
languageName: node
linkType: hard
-"cssdb@npm:^8.6.0":
- version: 8.6.0
- resolution: "cssdb@npm:8.6.0"
- checksum: 10c0/4bb7b77ba24902e8d481e9514ec0be56e205186a2b7d9f5027fedfe718952c559c62acfd2859f92869f8090da7c2170f83d68170db5058a6ba8d9d5e8ded3b3e
+"cssdb@npm:^8.7.0":
+ version: 8.7.0
+ resolution: "cssdb@npm:8.7.0"
+ checksum: 10c0/8db722877a68732d378e6f734dcf343f5d62670a1df630a74f5ae4a4c1ec482223730128825c5bcd99307fcd2128160b3705a6b1508d446e80e6ab2eebc7e8bc
languageName: node
linkType: hard
@@ -6706,15 +6582,6 @@ __metadata:
languageName: node
linkType: hard
-"dir-glob@npm:^3.0.1":
- version: 3.0.1
- resolution: "dir-glob@npm:3.0.1"
- dependencies:
- path-type: "npm:^4.0.0"
- checksum: 10c0/dcac00920a4d503e38bb64001acb19df4efc14536ada475725e12f52c16777afdee4db827f55f13a908ee7efc0cb282e2e3dbaeeb98c0993dd93d1802d3bf00c
- languageName: node
- linkType: hard
-
"doctrine@npm:^2.1.0":
version: 2.1.0
resolution: "doctrine@npm:2.1.0"
@@ -6767,13 +6634,20 @@ __metadata:
languageName: node
linkType: hard
-"dotenv@npm:^16.0.3, dotenv@npm:^16.4.2":
+"dotenv@npm:^16.4.2":
version: 16.6.1
resolution: "dotenv@npm:16.6.1"
checksum: 10c0/15ce56608326ea0d1d9414a5c8ee6dcf0fffc79d2c16422b4ac2268e7e2d76ff5a572d37ffe747c377de12005f14b3cc22361e79fc7f1061cce81f77d2c973dc
languageName: node
linkType: hard
+"dotenv@npm:^17.0.0":
+ version: 17.2.3
+ resolution: "dotenv@npm:17.2.3"
+ checksum: 10c0/c884403209f713214a1b64d4d1defa4934c2aa5b0002f5a670ae298a51e3c3ad3ba79dfee2f8df49f01ae74290fcd9acdb1ab1d09c7bfb42b539036108bb2ba0
+ languageName: node
+ linkType: hard
+
"dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1":
version: 1.0.1
resolution: "dunder-proto@npm:1.0.1"
@@ -7118,7 +6992,7 @@ __metadata:
languageName: node
linkType: hard
-"esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0":
+"esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0, esbuild@npm:^0.27.0":
version: 0.27.2
resolution: "esbuild@npm:0.27.2"
dependencies:
@@ -7207,92 +7081,6 @@ __metadata:
languageName: node
linkType: hard
-"esbuild@npm:^0.25.0":
- version: 0.25.5
- resolution: "esbuild@npm:0.25.5"
- dependencies:
- "@esbuild/aix-ppc64": "npm:0.25.5"
- "@esbuild/android-arm": "npm:0.25.5"
- "@esbuild/android-arm64": "npm:0.25.5"
- "@esbuild/android-x64": "npm:0.25.5"
- "@esbuild/darwin-arm64": "npm:0.25.5"
- "@esbuild/darwin-x64": "npm:0.25.5"
- "@esbuild/freebsd-arm64": "npm:0.25.5"
- "@esbuild/freebsd-x64": "npm:0.25.5"
- "@esbuild/linux-arm": "npm:0.25.5"
- "@esbuild/linux-arm64": "npm:0.25.5"
- "@esbuild/linux-ia32": "npm:0.25.5"
- "@esbuild/linux-loong64": "npm:0.25.5"
- "@esbuild/linux-mips64el": "npm:0.25.5"
- "@esbuild/linux-ppc64": "npm:0.25.5"
- "@esbuild/linux-riscv64": "npm:0.25.5"
- "@esbuild/linux-s390x": "npm:0.25.5"
- "@esbuild/linux-x64": "npm:0.25.5"
- "@esbuild/netbsd-arm64": "npm:0.25.5"
- "@esbuild/netbsd-x64": "npm:0.25.5"
- "@esbuild/openbsd-arm64": "npm:0.25.5"
- "@esbuild/openbsd-x64": "npm:0.25.5"
- "@esbuild/sunos-x64": "npm:0.25.5"
- "@esbuild/win32-arm64": "npm:0.25.5"
- "@esbuild/win32-ia32": "npm:0.25.5"
- "@esbuild/win32-x64": "npm:0.25.5"
- dependenciesMeta:
- "@esbuild/aix-ppc64":
- optional: true
- "@esbuild/android-arm":
- optional: true
- "@esbuild/android-arm64":
- optional: true
- "@esbuild/android-x64":
- optional: true
- "@esbuild/darwin-arm64":
- optional: true
- "@esbuild/darwin-x64":
- optional: true
- "@esbuild/freebsd-arm64":
- optional: true
- "@esbuild/freebsd-x64":
- optional: true
- "@esbuild/linux-arm":
- optional: true
- "@esbuild/linux-arm64":
- optional: true
- "@esbuild/linux-ia32":
- optional: true
- "@esbuild/linux-loong64":
- optional: true
- "@esbuild/linux-mips64el":
- optional: true
- "@esbuild/linux-ppc64":
- optional: true
- "@esbuild/linux-riscv64":
- optional: true
- "@esbuild/linux-s390x":
- optional: true
- "@esbuild/linux-x64":
- optional: true
- "@esbuild/netbsd-arm64":
- optional: true
- "@esbuild/netbsd-x64":
- optional: true
- "@esbuild/openbsd-arm64":
- optional: true
- "@esbuild/openbsd-x64":
- optional: true
- "@esbuild/sunos-x64":
- optional: true
- "@esbuild/win32-arm64":
- optional: true
- "@esbuild/win32-ia32":
- optional: true
- "@esbuild/win32-x64":
- optional: true
- bin:
- esbuild: bin/esbuild
- checksum: 10c0/aba8cbc11927fa77562722ed5e95541ce2853f67ad7bdc40382b558abc2e0ec57d92ffb820f082ba2047b4ef9f3bc3da068cdebe30dfd3850cfa3827a78d604e
- languageName: node
- linkType: hard
-
"escalade@npm:^3.1.1, escalade@npm:^3.2.0":
version: 3.2.0
resolution: "escalade@npm:3.2.0"
@@ -7773,7 +7561,7 @@ __metadata:
languageName: node
linkType: hard
-"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.3":
+"fast-glob@npm:^3.3.3":
version: 3.3.3
resolution: "fast-glob@npm:3.3.3"
dependencies:
@@ -8275,10 +8063,10 @@ __metadata:
languageName: node
linkType: hard
-"globals@npm:^16.0.0":
- version: 16.5.0
- resolution: "globals@npm:16.5.0"
- checksum: 10c0/615241dae7851c8012f5aa0223005b1ed6607713d6813de0741768bd4ddc39353117648f1a7086b4b0fa45eae733f1c0a0fe369aa4e543bb63f8de8990178ea9
+"globals@npm:^17.0.0":
+ version: 17.0.0
+ resolution: "globals@npm:17.0.0"
+ checksum: 10c0/e3c169fdcb0fc6755707b697afb367bea483eb29992cfc0de1637382eb893146e17f8f96db6d7453e3696b478a7863ae2000e6c71cd2f4061410285106d3847a
languageName: node
linkType: hard
@@ -8292,17 +8080,17 @@ __metadata:
languageName: node
linkType: hard
-"globby@npm:^11.1.0":
- version: 11.1.0
- resolution: "globby@npm:11.1.0"
+"globby@npm:^16.1.0":
+ version: 16.1.0
+ resolution: "globby@npm:16.1.0"
dependencies:
- array-union: "npm:^2.1.0"
- dir-glob: "npm:^3.0.1"
- fast-glob: "npm:^3.2.9"
- ignore: "npm:^5.2.0"
- merge2: "npm:^1.4.1"
- slash: "npm:^3.0.0"
- checksum: 10c0/b39511b4afe4bd8a7aead3a27c4ade2b9968649abab0a6c28b1a90141b96ca68ca5db1302f7c7bd29eab66bf51e13916b8e0a3d0ac08f75e1e84a39b35691189
+ "@sindresorhus/merge-streams": "npm:^4.0.0"
+ fast-glob: "npm:^3.3.3"
+ ignore: "npm:^7.0.5"
+ is-path-inside: "npm:^4.0.0"
+ slash: "npm:^5.1.0"
+ unicorn-magic: "npm:^0.4.0"
+ checksum: 10c0/45dd4dd8311401b37ed426ad7ea7a6e8fdda2518bb0d62fbf0a46c2e6b81bcbd2c8d4fbcbcf4c0600bba15c5a8f4621785d0177acbb1b545f02f6b49f2cdbe24
languageName: node
linkType: hard
@@ -8362,6 +8150,13 @@ __metadata:
languageName: node
linkType: hard
+"has-flag@npm:^5.0.1":
+ version: 5.0.1
+ resolution: "has-flag@npm:5.0.1"
+ checksum: 10c0/6c214902e9d829979ef0f906980599df1db5ca289a9c72cc1b1ebc2c8c924681c60b632a21bfc23728a1098a3f300029a8608f293fcc559962ecd495652aa250
+ languageName: node
+ linkType: hard
+
"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2":
version: 1.0.2
resolution: "has-property-descriptors@npm:1.0.2"
@@ -8497,10 +8292,10 @@ __metadata:
languageName: node
linkType: hard
-"html-tags@npm:^3.3.1":
- version: 3.3.1
- resolution: "html-tags@npm:3.3.1"
- checksum: 10c0/680165e12baa51bad7397452d247dbcc5a5c29dac0e6754b1187eee3bf26f514bc1907a431dd2f7eb56207611ae595ee76a0acc8eaa0d931e72c791dd6463d79
+"html-tags@npm:^5.1.0":
+ version: 5.1.0
+ resolution: "html-tags@npm:5.1.0"
+ checksum: 10c0/2dda19bc07e75837d0c52984558d92e8b82768050e4d6421b3164b1cb6ca5e73719209c2b23c0fa71faf097a7a3d18cf7f2021b488f1b1f270fca516c4c634c9
languageName: node
linkType: hard
@@ -8669,6 +8464,13 @@ __metadata:
languageName: node
linkType: hard
+"import-meta-resolve@npm:^4.2.0":
+ version: 4.2.0
+ resolution: "import-meta-resolve@npm:4.2.0"
+ checksum: 10c0/3ee8aeecb61d19b49d2703987f977e9d1c7d4ba47db615a570eaa02fe414f40dfa63f7b953e842cbe8470d26df6371332bfcf21b2fd92b0112f9fea80dde2c4c
+ languageName: node
+ linkType: hard
+
"imurmurhash@npm:^0.1.4":
version: 0.1.4
resolution: "imurmurhash@npm:0.1.4"
@@ -8747,8 +8549,8 @@ __metadata:
linkType: hard
"ioredis@npm:^5.3.2":
- version: 5.9.1
- resolution: "ioredis@npm:5.9.1"
+ version: 5.9.2
+ resolution: "ioredis@npm:5.9.2"
dependencies:
"@ioredis/commands": "npm:1.5.0"
cluster-key-slot: "npm:^1.1.0"
@@ -8759,7 +8561,7 @@ __metadata:
redis-errors: "npm:^1.2.0"
redis-parser: "npm:^3.0.0"
standard-as-callback: "npm:^2.1.0"
- checksum: 10c0/0993372ac380332d487e329882f247254a77dbf2d6f746e67c2211b50dda8067c0bce16c120b77ffe1eb693766dc4f36fac8cf5679231ab0c27671e34ef13449
+ checksum: 10c0/9732a3adab56c63a0e76bd1a1c891e4201448c44ab31e7e9aee8e83005be07597a4969199593c0d59642fb3fcd64ce00e9a8fad6c92d80e648df20b4b2b184ce
languageName: node
linkType: hard
@@ -9000,6 +8802,13 @@ __metadata:
languageName: node
linkType: hard
+"is-path-inside@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "is-path-inside@npm:4.0.0"
+ checksum: 10c0/51188d7e2b1d907a9a5f7c18d99a90b60870b951ed87cf97595d9aaa429d4c010652c3350bcbf31182e7f4b0eab9a1860b43e16729b13cb1a44baaa6cdb64c46
+ languageName: node
+ linkType: hard
+
"is-plain-object@npm:^5.0.0":
version: 5.0.0
resolution: "is-plain-object@npm:5.0.0"
@@ -9495,13 +9304,6 @@ __metadata:
languageName: node
linkType: hard
-"known-css-properties@npm:^0.36.0":
- version: 0.36.0
- resolution: "known-css-properties@npm:0.36.0"
- checksum: 10c0/098c8f956408a7ce26a639c2354e0184fb2bb2772bb7d1ba23192b6b6cf5818cbb8a0acfb4049705ea103d9916065703bc540fa084a6349fdb41bf745aada4bc
- languageName: node
- linkType: hard
-
"known-css-properties@npm:^0.37.0":
version: 0.37.0
resolution: "known-css-properties@npm:0.37.0"
@@ -9690,9 +9492,9 @@ __metadata:
linkType: hard
"lodash@npm:^4.17.20, lodash@npm:^4.17.21":
- version: 4.17.21
- resolution: "lodash@npm:4.17.21"
- checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c
+ version: 4.17.23
+ resolution: "lodash@npm:4.17.23"
+ checksum: 10c0/1264a90469f5bb95d4739c43eb6277d15b6d9e186df4ac68c3620443160fc669e2f14c11e7d8b2ccf078b81d06147c01a8ccced9aab9f9f63d50dcf8cace6bf6
languageName: node
linkType: hard
@@ -9849,10 +9651,10 @@ __metadata:
languageName: node
linkType: hard
-"mathml-tag-names@npm:^2.1.3":
- version: 2.1.3
- resolution: "mathml-tag-names@npm:2.1.3"
- checksum: 10c0/e2b094658a2618433efd2678a5a3e551645e09ba17c7c777783cd8dfa0178b0195fda0a5c46a6be5e778923662cf8dde891c894c869ff14fbb4ea3208c31bc4d
+"mathml-tag-names@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "mathml-tag-names@npm:4.0.0"
+ checksum: 10c0/2e928554c61b5e502ee551a23bb4157b99ffd042578e28fb4038ee67d19ea2b1a79c34a3c2ab1611437f668f6b29436e1c8f6fdc20eaf3c88d511ce5b8954fe8
languageName: node
linkType: hard
@@ -9863,10 +9665,10 @@ __metadata:
languageName: node
linkType: hard
-"mdn-data@npm:^2.21.0":
- version: 2.21.0
- resolution: "mdn-data@npm:2.21.0"
- checksum: 10c0/cd26902551af2cc29f06f130893cb04bca9ee278939fce3ffbcb759497cc80d53a6f4abdef2ae2f3ed3c95ac8d651f53fc141defd580ebf4ae2f93aea325957b
+"mdn-data@npm:^2.25.0":
+ version: 2.26.0
+ resolution: "mdn-data@npm:2.26.0"
+ checksum: 10c0/e5f17f4dac247f3e260c081761628d371e23659a7ff13413f83f5bd7fd0f2d8317e72277bb77f0e13115041334ff728a5363db64aabaf376c0e1b0b31016d0b8
languageName: node
linkType: hard
@@ -9884,13 +9686,20 @@ __metadata:
languageName: node
linkType: hard
-"meow@npm:^13.0.0, meow@npm:^13.2.0":
+"meow@npm:^13.0.0":
version: 13.2.0
resolution: "meow@npm:13.2.0"
checksum: 10c0/d5b339ae314715bcd0b619dd2f8a266891928e21526b4800d49b4fba1cc3fff7e2c1ff5edd3344149fac841bc2306157f858e8c4d5eaee4d52ce52ad925664ce
languageName: node
linkType: hard
+"meow@npm:^14.0.0":
+ version: 14.0.0
+ resolution: "meow@npm:14.0.0"
+ checksum: 10c0/dbe4e136e0f858472d8b8c24d382054fe9898f6f47c58a42be25e6b1985e5ae31048573bf399f6e5877bf9d5b89cb840beae7350682019f998ff30baaa5e4106
+ languageName: node
+ linkType: hard
+
"merge-descriptors@npm:^2.0.0":
version: 2.0.0
resolution: "merge-descriptors@npm:2.0.0"
@@ -9898,7 +9707,7 @@ __metadata:
languageName: node
linkType: hard
-"merge2@npm:^1.3.0, merge2@npm:^1.4.1":
+"merge2@npm:^1.3.0":
version: 1.4.1
resolution: "merge2@npm:1.4.1"
checksum: 10c0/254a8a4605b58f450308fc474c82ac9a094848081bf4c06778200207820e5193726dc563a0d2c16468810516a5c97d9d3ea0ca6585d23c58ccfff2403e8dbbeb
@@ -10695,17 +10504,17 @@ __metadata:
languageName: node
linkType: hard
-"pg-cloudflare@npm:^1.2.7":
- version: 1.2.7
- resolution: "pg-cloudflare@npm:1.2.7"
- checksum: 10c0/8a52713dbdecc9d389dc4e65e3b7ede2e199ec3715f7491ee80a15db171f2d75677a102e9c2cef0cb91a2f310e91f976eaec0dd6ef5d8bf357de0b948f9d9431
+"pg-cloudflare@npm:^1.3.0":
+ version: 1.3.0
+ resolution: "pg-cloudflare@npm:1.3.0"
+ checksum: 10c0/b0866c88af8e54c7b3ed510719d92df37714b3af5e3a3a10d9f761fcec99483e222f5b78a1f2de590368127648087c45c01aaf66fadbe46edb25673eedc4f8fc
languageName: node
linkType: hard
-"pg-connection-string@npm:^2.6.0, pg-connection-string@npm:^2.9.1":
- version: 2.9.1
- resolution: "pg-connection-string@npm:2.9.1"
- checksum: 10c0/9a646529bbc0843806fc5de98ce93735a4612b571f11867178a85665d11989a827e6fd157388ca0e34ec948098564fce836c178cfd499b9f0e8cd9972b8e2e5c
+"pg-connection-string@npm:^2.10.1, pg-connection-string@npm:^2.6.0":
+ version: 2.10.1
+ resolution: "pg-connection-string@npm:2.10.1"
+ checksum: 10c0/f218a72b59c661022caca9a7f2116655632b1d7e7d6dc9a8ee9f238744e0927e0d6f44e12f50d9767c6d9cd47d9b3766aa054b77504b15c6bf503400530e053e
languageName: node
linkType: hard
@@ -10716,19 +10525,19 @@ __metadata:
languageName: node
linkType: hard
-"pg-pool@npm:^3.10.1":
- version: 3.10.1
- resolution: "pg-pool@npm:3.10.1"
+"pg-pool@npm:^3.11.0":
+ version: 3.11.0
+ resolution: "pg-pool@npm:3.11.0"
peerDependencies:
pg: ">=8.0"
- checksum: 10c0/a00916b7df64226cc597fe769e3a757ff9b11562dc87ce5b0a54101a18c1fe282daaa2accaf27221e81e1e4cdf4da6a33dab09614734d32904d6c4e11c44a079
+ checksum: 10c0/4b104b48a47257a0edad0c62e5ea1908b72cb79386270264b452e69895e9e4c589d00cdbf6e46d4e9c05bc7e7d191656b66814b5282d65f33b12648a21df3c7f
languageName: node
linkType: hard
-"pg-protocol@npm:*, pg-protocol@npm:^1.10.3":
- version: 1.10.3
- resolution: "pg-protocol@npm:1.10.3"
- checksum: 10c0/f7ef54708c93ee6d271e37678296fc5097e4337fca91a88a3d99359b78633dbdbf6e983f0adb34b7cdd261b7ec7266deb20c3233bf3dfdb498b3e1098e8750b9
+"pg-protocol@npm:*, pg-protocol@npm:^1.11.0":
+ version: 1.11.0
+ resolution: "pg-protocol@npm:1.11.0"
+ checksum: 10c0/93e83581781418c9173eba4e4545f73392cfe66b78dd1d3624d7339fbd37e7f4abebaf2615e68e0701a9bf0edf5b81a4ad533836f388f775fe25fa24a691c464
languageName: node
linkType: hard
@@ -10746,13 +10555,13 @@ __metadata:
linkType: hard
"pg@npm:^8.5.0":
- version: 8.16.3
- resolution: "pg@npm:8.16.3"
+ version: 8.17.2
+ resolution: "pg@npm:8.17.2"
dependencies:
- pg-cloudflare: "npm:^1.2.7"
- pg-connection-string: "npm:^2.9.1"
- pg-pool: "npm:^3.10.1"
- pg-protocol: "npm:^1.10.3"
+ pg-cloudflare: "npm:^1.3.0"
+ pg-connection-string: "npm:^2.10.1"
+ pg-pool: "npm:^3.11.0"
+ pg-protocol: "npm:^1.11.0"
pg-types: "npm:2.2.0"
pgpass: "npm:1.0.5"
peerDependencies:
@@ -10763,7 +10572,7 @@ __metadata:
peerDependenciesMeta:
pg-native:
optional: true
- checksum: 10c0/a6a407ff0efb7599760d72ffdcda47a74c34c0fd71d896623caac45cf2cfb0f49a10973cce23110f182b9810639a1e9f6904454d7358c7001574ee0ffdcbce2a
+ checksum: 10c0/74b022587f92953f498dba747ccf9c7c90767af70326595d30c7ab0e2f00b2b468226c8abae54caef63ab444a8ac6f1597d859174386c7ba7c318c225d711c5f
languageName: node
linkType: hard
@@ -10865,8 +10674,8 @@ __metadata:
linkType: hard
"pino@npm:^10.0.0":
- version: 10.1.1
- resolution: "pino@npm:10.1.1"
+ version: 10.3.0
+ resolution: "pino@npm:10.3.0"
dependencies:
"@pinojs/redact": "npm:^0.4.0"
atomic-sleep: "npm:^1.0.0"
@@ -10881,7 +10690,7 @@ __metadata:
thread-stream: "npm:^4.0.0"
bin:
pino: bin.js
- checksum: 10c0/c0a78ae4209b81879e3b2c72abd523c6045412066d214b7577f4073b23369751bbb7a1c6abb691bdf347ac81fab5e9cad9d8db0612fe2e5a9607ef895651a1bb
+ checksum: 10c0/cfbbc7dfaa2df2aa2dce728d751aa4b5b7ab973b2cd4bfff57868567563ef0c1c021f22932769141d535c72662390e09a0190e44f4413496dbe5e3c672816308
languageName: node
linkType: hard
@@ -10934,14 +10743,14 @@ __metadata:
languageName: node
linkType: hard
-"postcss-attribute-case-insensitive@npm:^7.0.1":
- version: 7.0.1
- resolution: "postcss-attribute-case-insensitive@npm:7.0.1"
+"postcss-attribute-case-insensitive@npm:^8.0.0":
+ version: 8.0.0
+ resolution: "postcss-attribute-case-insensitive@npm:8.0.0"
dependencies:
- postcss-selector-parser: "npm:^7.0.0"
+ postcss-selector-parser: "npm:^7.1.1"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/48945abe2024e2d2e4c37d30b8c1aaf37af720f24f6a996f7ea7e7ed33621f5c22cf247ed22028c0c922de040c58c0802729bc39b903cb1693f4b63c0b49da34
+ checksum: 10c0/d6442d1580a3ec5083ff41435e8423dfe9c5b3b65b610e082769d27f11b98e0699d5361f7e9a9e499805c0a78d83a8aec3dd9f9d9280636cca82ec1aea79e928
languageName: node
linkType: hard
@@ -10956,131 +10765,131 @@ __metadata:
languageName: node
linkType: hard
-"postcss-color-functional-notation@npm:^7.0.12":
- version: 7.0.12
- resolution: "postcss-color-functional-notation@npm:7.0.12"
+"postcss-color-functional-notation@npm:^8.0.1":
+ version: 8.0.1
+ resolution: "postcss-color-functional-notation@npm:8.0.1"
dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/dc80ba1a956ae9b396596bda72d9bdb92de96874378a38ba4e2177ffa35339dc76d894920bb013b6f10c9b75cfb41778e09956a438c2e9ea41b684f766c55f4a
+ checksum: 10c0/e5f1ec677f752344bbb9a65b011465d08d1fe5a2cf02eea2b337e472a555bf137030b96b42b833bfa07ffe9afbf76b9f5cd2ac05dbf5df7d66c785b8fb9a365a
languageName: node
linkType: hard
-"postcss-color-hex-alpha@npm:^10.0.0":
+"postcss-color-hex-alpha@npm:^11.0.0":
+ version: 11.0.0
+ resolution: "postcss-color-hex-alpha@npm:11.0.0"
+ dependencies:
+ "@csstools/utilities": "npm:^3.0.0"
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/375509c404b0ac496f66bf0910d12e5aabca058c0d9de9d10719e9a0729013d5f4fafd06d8c8073b2d68613b3346e8ff79ef223a5ce4ddf0d4c4f645fd7a5436
+ languageName: node
+ linkType: hard
+
+"postcss-color-rebeccapurple@npm:^11.0.0":
+ version: 11.0.0
+ resolution: "postcss-color-rebeccapurple@npm:11.0.0"
+ dependencies:
+ "@csstools/utilities": "npm:^3.0.0"
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/9f22fff4ce2f0d7ce07be2ba2d07697e24f7db83a6252f02f36aa3a556cf69e1346a3cbab3908264e267306cc5a79b5d95c21e6fa4257a68c13c7411224543b9
+ languageName: node
+ linkType: hard
+
+"postcss-custom-media@npm:^12.0.0":
+ version: 12.0.0
+ resolution: "postcss-custom-media@npm:12.0.0"
+ dependencies:
+ "@csstools/cascade-layer-name-parser": "npm:^3.0.0"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/media-query-list-parser": "npm:^5.0.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/bf1f3939d83a24eb7ef86f9fc2cb799026d4dc4620d3769eef9234d23fd528c73e907c2b88cb239290d169e5ddf8f0624cf8b22084874953c224e6000d55bf50
+ languageName: node
+ linkType: hard
+
+"postcss-custom-properties@npm:^15.0.0":
+ version: 15.0.0
+ resolution: "postcss-custom-properties@npm:15.0.0"
+ dependencies:
+ "@csstools/cascade-layer-name-parser": "npm:^3.0.0"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/d766f1632075f8db2cd5075967cc4397c46b59699dd7a70762d9bd3e1ff91d3ada167b4f79e7e254518cdaae8d71645cd92faeb89559175ed50337c0acf5b0b4
+ languageName: node
+ linkType: hard
+
+"postcss-custom-selectors@npm:^9.0.0":
+ version: 9.0.0
+ resolution: "postcss-custom-selectors@npm:9.0.0"
+ dependencies:
+ "@csstools/cascade-layer-name-parser": "npm:^3.0.0"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ postcss-selector-parser: "npm:^7.1.1"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/a99d87639e8bca0a3eebd910356cecd67a4153789a77e15604db68caee415e64bc90d3e58a8322ed3d37addb80574a1180e58d603ac6541364b373b322e7de9f
+ languageName: node
+ linkType: hard
+
+"postcss-dir-pseudo-class@npm:^10.0.0":
version: 10.0.0
- resolution: "postcss-color-hex-alpha@npm:10.0.0"
+ resolution: "postcss-dir-pseudo-class@npm:10.0.0"
dependencies:
- "@csstools/utilities": "npm:^2.0.0"
- postcss-value-parser: "npm:^4.2.0"
+ postcss-selector-parser: "npm:^7.1.1"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/8a6dcb27403d04b55d6de88bf3074622bcea537fc4436bbcb346e92289c4d17059444e2e6c3554c325e7a777bb4cdc711e764a83123b4000aec211052e957d5b
+ checksum: 10c0/c7cae0b4e96bf0e51845c20b6fae7eec7b428b569b4fbae639b4f1f3b16a0ced4f5610ffb0209484ba4dfc8858abc64a9577cc8d2e3f1dbf3154f4ed0eb07669
languageName: node
linkType: hard
-"postcss-color-rebeccapurple@npm:^10.0.0":
+"postcss-double-position-gradients@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "postcss-double-position-gradients@npm:7.0.0"
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
+ postcss-value-parser: "npm:^4.2.0"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/0a9a1c567c79ddbe7bbeafe9770f2393d4d0eb344a79a2823dc5944690d74c311841ff6fd533b823d282029eff07418eeb671fabc85db6414ace48cce37223e8
+ languageName: node
+ linkType: hard
+
+"postcss-focus-visible@npm:^11.0.0":
+ version: 11.0.0
+ resolution: "postcss-focus-visible@npm:11.0.0"
+ dependencies:
+ postcss-selector-parser: "npm:^7.1.1"
+ peerDependencies:
+ postcss: ^8.4
+ checksum: 10c0/001cdfb200fe83b25a0fdbb7315b70fcf91c71d0134e16d48334fc7eab3d41c7cd3b8fe7bb8201a0ef9f242afb10f71aed238715a1d6923f68a02e6dc4219916
+ languageName: node
+ linkType: hard
+
+"postcss-focus-within@npm:^10.0.0":
version: 10.0.0
- resolution: "postcss-color-rebeccapurple@npm:10.0.0"
+ resolution: "postcss-focus-within@npm:10.0.0"
dependencies:
- "@csstools/utilities": "npm:^2.0.0"
- postcss-value-parser: "npm:^4.2.0"
+ postcss-selector-parser: "npm:^7.1.1"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/308e33f76f2b48c1c2121d4502fc053e869f3415898de7d30314353df680e79b37497e7b628e3447edc1049091da3672f7d891e45604f238598e846e06b893ed
- languageName: node
- linkType: hard
-
-"postcss-custom-media@npm:^11.0.6":
- version: 11.0.6
- resolution: "postcss-custom-media@npm:11.0.6"
- dependencies:
- "@csstools/cascade-layer-name-parser": "npm:^2.0.5"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/media-query-list-parser": "npm:^4.0.3"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/62dcb2858fd490d90aab32062621d58892a7b2a54948ee63af81a2cd61807a11815d28d4ef6bc800c5e142ac73098f7e56822c7cc63192eb20d5b16071543a73
- languageName: node
- linkType: hard
-
-"postcss-custom-properties@npm:^14.0.6":
- version: 14.0.6
- resolution: "postcss-custom-properties@npm:14.0.6"
- dependencies:
- "@csstools/cascade-layer-name-parser": "npm:^2.0.5"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/utilities": "npm:^2.0.0"
- postcss-value-parser: "npm:^4.2.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/0eeef77bc713551f5cb8fa5982d24da4e854075f3af020f1c94366c47a23a4cc225ebfecc978bdb17f00ee0bdee9d2c784e0d01adc64a447321e408abbe2c83b
- languageName: node
- linkType: hard
-
-"postcss-custom-selectors@npm:^8.0.5":
- version: 8.0.5
- resolution: "postcss-custom-selectors@npm:8.0.5"
- dependencies:
- "@csstools/cascade-layer-name-parser": "npm:^2.0.5"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- postcss-selector-parser: "npm:^7.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/bd8f2f85bbec4bd56ff408cb699d9fe649e2af0db82d5752eee05481ae522f06f5a47950ca22fcb4c8601071c03346df67cf20b0b0bcade32ce58d07ebaf9b32
- languageName: node
- linkType: hard
-
-"postcss-dir-pseudo-class@npm:^9.0.1":
- version: 9.0.1
- resolution: "postcss-dir-pseudo-class@npm:9.0.1"
- dependencies:
- postcss-selector-parser: "npm:^7.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/da9d3387648c5c3161a653d354c8f3e70a299108df3977e8aa65cf10793e4dd58a2711b3426cd63716245b13584ca8d95adcd6e10e3c9adbc61d08743e2d8690
- languageName: node
- linkType: hard
-
-"postcss-double-position-gradients@npm:^6.0.4":
- version: 6.0.4
- resolution: "postcss-double-position-gradients@npm:6.0.4"
- dependencies:
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
- postcss-value-parser: "npm:^4.2.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/6dbbe7a3855e84a9319df434e210225f6dfa7262e5959611355f1769c2c9d30d37a19737712f20eac6354876fff4ba556d8d0b12a90c78d8ab97c9a8da534a7c
- languageName: node
- linkType: hard
-
-"postcss-focus-visible@npm:^10.0.1":
- version: 10.0.1
- resolution: "postcss-focus-visible@npm:10.0.1"
- dependencies:
- postcss-selector-parser: "npm:^7.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/c5ecc8536a708a49a99d0abd68a88a160664e6c832c808db8edd9f0221e7017a258daa87e49daf2cb098cb037005d46cf492403c8c9c92ad8835d30adaccf665
- languageName: node
- linkType: hard
-
-"postcss-focus-within@npm:^9.0.1":
- version: 9.0.1
- resolution: "postcss-focus-within@npm:9.0.1"
- dependencies:
- postcss-selector-parser: "npm:^7.0.0"
- peerDependencies:
- postcss: ^8.4
- checksum: 10c0/d6ab49d2a7f33485a9e137dc77ec92c5619a3ec92e1e672734fc604853ff1f3c0c189085c12461614be4fcb03ea0347d91791a45986a18d50b5228d161eda57a
+ checksum: 10c0/297ba52c07ba9284e7bf862e23ce90312bc2068d005a3c95833d832462691fac276850dd5508228fc808ec5f2963cb61a8b510645e08b78a74a9aaff9a79b02b
languageName: node
linkType: hard
@@ -11093,39 +10902,39 @@ __metadata:
languageName: node
linkType: hard
-"postcss-gap-properties@npm:^6.0.0":
- version: 6.0.0
- resolution: "postcss-gap-properties@npm:6.0.0"
+"postcss-gap-properties@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "postcss-gap-properties@npm:7.0.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/4e07e0d3927d0e65d67eaf047ac39e08d39cb1bf74e16e10c7df7f0d01b184a77ea59f63fd5691b5ed6df159970b972db28cb784d883e26e981137696460897d
+ checksum: 10c0/c93a0d15d40a7ae474a1bf05bd8f77410c6a353c7ea3bbad3aa61c38f6471d9bf23bac738aa1b3ca58805a33a730a4e6d15b7d03e0d2f1a29ef70969c14b483d
languageName: node
linkType: hard
-"postcss-image-set-function@npm:^7.0.0":
- version: 7.0.0
- resolution: "postcss-image-set-function@npm:7.0.0"
+"postcss-image-set-function@npm:^8.0.0":
+ version: 8.0.0
+ resolution: "postcss-image-set-function@npm:8.0.0"
dependencies:
- "@csstools/utilities": "npm:^2.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
postcss-value-parser: "npm:^4.2.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/913fd9492f00122aa0c2550fb0d72130428cbe1e6465bc65e8fe71e9deb10ac0c01d7caceb68b560da759139e8cbc6c90ed22dfe6cf34949af49bb86bcbf4d3a
+ checksum: 10c0/b2c527d8731c97f09e79ab477069138eba994a656473f57e1afd2480b18cd54cdb6600888e44d208b11efae01c123bc81629ecb77d8ed19397bc2a4b8da6da52
languageName: node
linkType: hard
-"postcss-lab-function@npm:^7.0.12":
- version: 7.0.12
- resolution: "postcss-lab-function@npm:7.0.12"
+"postcss-lab-function@npm:^8.0.1":
+ version: 8.0.1
+ resolution: "postcss-lab-function@npm:8.0.1"
dependencies:
- "@csstools/css-color-parser": "npm:^3.1.0"
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/utilities": "npm:^2.0.0"
+ "@csstools/css-color-parser": "npm:^4.0.1"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/utilities": "npm:^3.0.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/de39b59da3b97c18d055d81fba68993e93253184ed76f103c888273584f868c551d047814dd54445980a1bdc5987e8f8af141383d84ecc641e5a6ee7bd901095
+ checksum: 10c0/f1fd9d7cd99c1b87247c87de9d5f462c12ad9bcfe922837f37ecf20c43893ef863aa3dc35fd90fed69a5120a1379e8f952ca3cc2112faecbc8196192d15d805b
languageName: node
linkType: hard
@@ -11147,14 +10956,14 @@ __metadata:
languageName: node
linkType: hard
-"postcss-logical@npm:^8.1.0":
- version: 8.1.0
- resolution: "postcss-logical@npm:8.1.0"
+"postcss-logical@npm:^9.0.0":
+ version: 9.0.0
+ resolution: "postcss-logical@npm:9.0.0"
dependencies:
postcss-value-parser: "npm:^4.2.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/0e2e9e901d8a550db7f682d46b1f7e4f363c1ada061dc8e4548e2b563c5e39f3684a2d7c3f11fe061188782bca37874e34967fc6179fa6d98a49ff66a0076d27
+ checksum: 10c0/058394f2234464b043249317b2c0a2271fa5194ada0f39afdb0f5b7e2ad172b1f24da7ae2641dfbd44d1ee98f5438844bc85d6005b881f691630381673707c32
languageName: node
linkType: hard
@@ -11198,16 +11007,16 @@ __metadata:
languageName: node
linkType: hard
-"postcss-nesting@npm:^13.0.2":
- version: 13.0.2
- resolution: "postcss-nesting@npm:13.0.2"
+"postcss-nesting@npm:^14.0.0":
+ version: 14.0.0
+ resolution: "postcss-nesting@npm:14.0.0"
dependencies:
- "@csstools/selector-resolve-nested": "npm:^3.1.0"
- "@csstools/selector-specificity": "npm:^5.0.0"
- postcss-selector-parser: "npm:^7.0.0"
+ "@csstools/selector-resolve-nested": "npm:^4.0.0"
+ "@csstools/selector-specificity": "npm:^6.0.0"
+ postcss-selector-parser: "npm:^7.1.1"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/bfa0578b3b686c6374f5a7b2f6ef955cb7e13400de95a919975a982ae43c1e25db37385618f210715ff15393dc7ff8c26c7b156f06b8fb3118a426099cf7f1f2
+ checksum: 10c0/ffa1799ed49759be7f09940614a8cfd06f15bd13e01a7eaabf788939c23a6b617ef281ae383f5b3b3078ddd6d78fd90624af164ea5a421698a1b0972cf14253c
languageName: node
linkType: hard
@@ -11220,14 +11029,14 @@ __metadata:
languageName: node
linkType: hard
-"postcss-overflow-shorthand@npm:^6.0.0":
- version: 6.0.0
- resolution: "postcss-overflow-shorthand@npm:6.0.0"
+"postcss-overflow-shorthand@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "postcss-overflow-shorthand@npm:7.0.0"
dependencies:
postcss-value-parser: "npm:^4.2.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/6598321b2ed0b68461135395bba9c7f76a4672617770df1e8487f459bc975f4ded6c3d37b6f72a44f4f77f7b6789e0c6f927e66dbbf1bcde1537167dbea39968
+ checksum: 10c0/706430a2b1c28f361aad1d90e618c04c7ad7861971f2447fbd0e34c1d095bec0e5f4ed2857c98e05f5a7bcc694b7b763d08d5f515d5d45dd942f4b046593d638
languageName: node
linkType: hard
@@ -11240,106 +11049,107 @@ __metadata:
languageName: node
linkType: hard
-"postcss-place@npm:^10.0.0":
- version: 10.0.0
- resolution: "postcss-place@npm:10.0.0"
+"postcss-place@npm:^11.0.0":
+ version: 11.0.0
+ resolution: "postcss-place@npm:11.0.0"
dependencies:
postcss-value-parser: "npm:^4.2.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/ebb13deaac7648ba6042622375a31f78fbcc5209b7d196e478debbdf94525963fe621c932f4737a5b6b3d487af3b5ed6d059ed6193fdcbff6d3d5b150886ccc1
+ checksum: 10c0/0b6b27426b198507583388a0e4f27552a136e5b9ccd1fc356dbd9a04c91e2bf6dcd680c3ad540ffc5aa1a63779467b9c7dc43d2164f83a0658505ca2408d79a9
languageName: node
linkType: hard
-"postcss-preset-env@npm:^10.1.5":
- version: 10.6.1
- resolution: "postcss-preset-env@npm:10.6.1"
+"postcss-preset-env@npm:^11.0.0":
+ version: 11.1.2
+ resolution: "postcss-preset-env@npm:11.1.2"
dependencies:
- "@csstools/postcss-alpha-function": "npm:^1.0.1"
- "@csstools/postcss-cascade-layers": "npm:^5.0.2"
- "@csstools/postcss-color-function": "npm:^4.0.12"
- "@csstools/postcss-color-function-display-p3-linear": "npm:^1.0.1"
- "@csstools/postcss-color-mix-function": "npm:^3.0.12"
- "@csstools/postcss-color-mix-variadic-function-arguments": "npm:^1.0.2"
- "@csstools/postcss-content-alt-text": "npm:^2.0.8"
- "@csstools/postcss-contrast-color-function": "npm:^2.0.12"
- "@csstools/postcss-exponential-functions": "npm:^2.0.9"
- "@csstools/postcss-font-format-keywords": "npm:^4.0.0"
- "@csstools/postcss-gamut-mapping": "npm:^2.0.11"
- "@csstools/postcss-gradients-interpolation-method": "npm:^5.0.12"
- "@csstools/postcss-hwb-function": "npm:^4.0.12"
- "@csstools/postcss-ic-unit": "npm:^4.0.4"
- "@csstools/postcss-initial": "npm:^2.0.1"
- "@csstools/postcss-is-pseudo-class": "npm:^5.0.3"
- "@csstools/postcss-light-dark-function": "npm:^2.0.11"
- "@csstools/postcss-logical-float-and-clear": "npm:^3.0.0"
- "@csstools/postcss-logical-overflow": "npm:^2.0.0"
- "@csstools/postcss-logical-overscroll-behavior": "npm:^2.0.0"
- "@csstools/postcss-logical-resize": "npm:^3.0.0"
- "@csstools/postcss-logical-viewport-units": "npm:^3.0.4"
- "@csstools/postcss-media-minmax": "npm:^2.0.9"
- "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^3.0.5"
- "@csstools/postcss-nested-calc": "npm:^4.0.0"
- "@csstools/postcss-normalize-display-values": "npm:^4.0.1"
- "@csstools/postcss-oklab-function": "npm:^4.0.12"
- "@csstools/postcss-position-area-property": "npm:^1.0.0"
- "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1"
- "@csstools/postcss-property-rule-prelude-list": "npm:^1.0.0"
- "@csstools/postcss-random-function": "npm:^2.0.1"
- "@csstools/postcss-relative-color-syntax": "npm:^3.0.12"
- "@csstools/postcss-scope-pseudo-class": "npm:^4.0.1"
- "@csstools/postcss-sign-functions": "npm:^1.1.4"
- "@csstools/postcss-stepped-value-functions": "npm:^4.0.9"
- "@csstools/postcss-syntax-descriptor-syntax-production": "npm:^1.0.1"
- "@csstools/postcss-system-ui-font-family": "npm:^1.0.0"
- "@csstools/postcss-text-decoration-shorthand": "npm:^4.0.3"
- "@csstools/postcss-trigonometric-functions": "npm:^4.0.9"
- "@csstools/postcss-unset-value": "npm:^4.0.0"
+ "@csstools/postcss-alpha-function": "npm:^2.0.2"
+ "@csstools/postcss-cascade-layers": "npm:^6.0.0"
+ "@csstools/postcss-color-function": "npm:^5.0.1"
+ "@csstools/postcss-color-function-display-p3-linear": "npm:^2.0.1"
+ "@csstools/postcss-color-mix-function": "npm:^4.0.1"
+ "@csstools/postcss-color-mix-variadic-function-arguments": "npm:^2.0.1"
+ "@csstools/postcss-content-alt-text": "npm:^3.0.0"
+ "@csstools/postcss-contrast-color-function": "npm:^3.0.1"
+ "@csstools/postcss-exponential-functions": "npm:^3.0.0"
+ "@csstools/postcss-font-format-keywords": "npm:^5.0.0"
+ "@csstools/postcss-gamut-mapping": "npm:^3.0.1"
+ "@csstools/postcss-gradients-interpolation-method": "npm:^6.0.1"
+ "@csstools/postcss-hwb-function": "npm:^5.0.1"
+ "@csstools/postcss-ic-unit": "npm:^5.0.0"
+ "@csstools/postcss-initial": "npm:^3.0.0"
+ "@csstools/postcss-is-pseudo-class": "npm:^6.0.0"
+ "@csstools/postcss-light-dark-function": "npm:^3.0.0"
+ "@csstools/postcss-logical-float-and-clear": "npm:^4.0.0"
+ "@csstools/postcss-logical-overflow": "npm:^3.0.0"
+ "@csstools/postcss-logical-overscroll-behavior": "npm:^3.0.0"
+ "@csstools/postcss-logical-resize": "npm:^4.0.0"
+ "@csstools/postcss-logical-viewport-units": "npm:^4.0.0"
+ "@csstools/postcss-media-minmax": "npm:^3.0.0"
+ "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^4.0.0"
+ "@csstools/postcss-mixins": "npm:^1.0.0"
+ "@csstools/postcss-nested-calc": "npm:^5.0.0"
+ "@csstools/postcss-normalize-display-values": "npm:^5.0.1"
+ "@csstools/postcss-oklab-function": "npm:^5.0.1"
+ "@csstools/postcss-position-area-property": "npm:^2.0.0"
+ "@csstools/postcss-progressive-custom-properties": "npm:^5.0.0"
+ "@csstools/postcss-property-rule-prelude-list": "npm:^2.0.0"
+ "@csstools/postcss-random-function": "npm:^3.0.0"
+ "@csstools/postcss-relative-color-syntax": "npm:^4.0.1"
+ "@csstools/postcss-scope-pseudo-class": "npm:^5.0.0"
+ "@csstools/postcss-sign-functions": "npm:^2.0.0"
+ "@csstools/postcss-stepped-value-functions": "npm:^5.0.0"
+ "@csstools/postcss-syntax-descriptor-syntax-production": "npm:^2.0.0"
+ "@csstools/postcss-system-ui-font-family": "npm:^2.0.0"
+ "@csstools/postcss-text-decoration-shorthand": "npm:^5.0.1"
+ "@csstools/postcss-trigonometric-functions": "npm:^5.0.0"
+ "@csstools/postcss-unset-value": "npm:^5.0.0"
autoprefixer: "npm:^10.4.23"
browserslist: "npm:^4.28.1"
- css-blank-pseudo: "npm:^7.0.1"
- css-has-pseudo: "npm:^7.0.3"
- css-prefers-color-scheme: "npm:^10.0.0"
- cssdb: "npm:^8.6.0"
- postcss-attribute-case-insensitive: "npm:^7.0.1"
+ css-blank-pseudo: "npm:^8.0.1"
+ css-has-pseudo: "npm:^8.0.0"
+ css-prefers-color-scheme: "npm:^11.0.0"
+ cssdb: "npm:^8.7.0"
+ postcss-attribute-case-insensitive: "npm:^8.0.0"
postcss-clamp: "npm:^4.1.0"
- postcss-color-functional-notation: "npm:^7.0.12"
- postcss-color-hex-alpha: "npm:^10.0.0"
- postcss-color-rebeccapurple: "npm:^10.0.0"
- postcss-custom-media: "npm:^11.0.6"
- postcss-custom-properties: "npm:^14.0.6"
- postcss-custom-selectors: "npm:^8.0.5"
- postcss-dir-pseudo-class: "npm:^9.0.1"
- postcss-double-position-gradients: "npm:^6.0.4"
- postcss-focus-visible: "npm:^10.0.1"
- postcss-focus-within: "npm:^9.0.1"
+ postcss-color-functional-notation: "npm:^8.0.1"
+ postcss-color-hex-alpha: "npm:^11.0.0"
+ postcss-color-rebeccapurple: "npm:^11.0.0"
+ postcss-custom-media: "npm:^12.0.0"
+ postcss-custom-properties: "npm:^15.0.0"
+ postcss-custom-selectors: "npm:^9.0.0"
+ postcss-dir-pseudo-class: "npm:^10.0.0"
+ postcss-double-position-gradients: "npm:^7.0.0"
+ postcss-focus-visible: "npm:^11.0.0"
+ postcss-focus-within: "npm:^10.0.0"
postcss-font-variant: "npm:^5.0.0"
- postcss-gap-properties: "npm:^6.0.0"
- postcss-image-set-function: "npm:^7.0.0"
- postcss-lab-function: "npm:^7.0.12"
- postcss-logical: "npm:^8.1.0"
- postcss-nesting: "npm:^13.0.2"
+ postcss-gap-properties: "npm:^7.0.0"
+ postcss-image-set-function: "npm:^8.0.0"
+ postcss-lab-function: "npm:^8.0.1"
+ postcss-logical: "npm:^9.0.0"
+ postcss-nesting: "npm:^14.0.0"
postcss-opacity-percentage: "npm:^3.0.0"
- postcss-overflow-shorthand: "npm:^6.0.0"
+ postcss-overflow-shorthand: "npm:^7.0.0"
postcss-page-break: "npm:^3.0.4"
- postcss-place: "npm:^10.0.0"
- postcss-pseudo-class-any-link: "npm:^10.0.1"
+ postcss-place: "npm:^11.0.0"
+ postcss-pseudo-class-any-link: "npm:^11.0.0"
postcss-replace-overflow-wrap: "npm:^4.0.0"
- postcss-selector-not: "npm:^8.0.1"
+ postcss-selector-not: "npm:^9.0.0"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/e8da96f208918ebc0dc9acc8ba8961a92569f1d130b29abe25adaf7dbd56ef29fc6f778b75964c80fe7f3469012c763ea9447e5c2f559a002a155bc0462cce35
+ checksum: 10c0/01cf7e5bc399e9c7521a8fdb6ef20763addd16c9e0fdf57ab6d3fa8da9ddfbc937db36bf6ea0d55492f2c788bb5ec3b43f40eb91ee1abf78622a30fbc812107f
languageName: node
linkType: hard
-"postcss-pseudo-class-any-link@npm:^10.0.1":
- version: 10.0.1
- resolution: "postcss-pseudo-class-any-link@npm:10.0.1"
+"postcss-pseudo-class-any-link@npm:^11.0.0":
+ version: 11.0.0
+ resolution: "postcss-pseudo-class-any-link@npm:11.0.0"
dependencies:
- postcss-selector-parser: "npm:^7.0.0"
+ postcss-selector-parser: "npm:^7.1.1"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/95e883996e87baf14fc09d25f9a763a2e9d599eb3b9c6b736e83a8c3d0b55841bcb886bccdf51b5b7fefc128cbd0187ad8841f59878f85bd1613642e592d7673
+ checksum: 10c0/bd7e1daa582bc19fe0e30c3ab8b13f8cf75ae2f116124960e9d28092255ede77455cd982bef8010d7ea64fdffc66a14624e63fe438e6d957415f5a4bc16b59a4
languageName: node
linkType: hard
@@ -11377,24 +11187,24 @@ __metadata:
languageName: node
linkType: hard
-"postcss-selector-not@npm:^8.0.1":
- version: 8.0.1
- resolution: "postcss-selector-not@npm:8.0.1"
+"postcss-selector-not@npm:^9.0.0":
+ version: 9.0.0
+ resolution: "postcss-selector-not@npm:9.0.0"
dependencies:
- postcss-selector-parser: "npm:^7.0.0"
+ postcss-selector-parser: "npm:^7.1.1"
peerDependencies:
postcss: ^8.4
- checksum: 10c0/491ea3dcc421cd90135be786078521605e2062fb93624ea8813cfd5ba0d35143f931e2e608d5f20effd5ea7d3f4786d2afea2afa42d117779a0288e135f132b6
+ checksum: 10c0/090ce6d65667b8b6b9c1c26b7bd7740a31f3e7f36c29574e622d5fac5ab2ce291ac11622914745f22dda531d75e36fcdd395339fbe8fac0fc04fa7d750bb5248
languageName: node
linkType: hard
-"postcss-selector-parser@npm:^7.0.0, postcss-selector-parser@npm:^7.1.0":
- version: 7.1.0
- resolution: "postcss-selector-parser@npm:7.1.0"
+"postcss-selector-parser@npm:^7.0.0, postcss-selector-parser@npm:^7.1.1":
+ version: 7.1.1
+ resolution: "postcss-selector-parser@npm:7.1.1"
dependencies:
cssesc: "npm:^3.0.0"
util-deprecate: "npm:^1.0.2"
- checksum: 10c0/0fef257cfd1c0fe93c18a3f8a6e739b4438b527054fd77e9a62730a89b2d0ded1b59314a7e4aaa55bc256204f40830fecd2eb50f20f8cb7ab3a10b52aa06c8aa
+ checksum: 10c0/02d3b1589ddcddceed4b583b098b95a7266dacd5135f041e5d913ebb48e874fd333a36e564cc9a2ec426a464cb18db11cb192ac76247aced5eba8c951bf59507
languageName: node
linkType: hard
@@ -12240,13 +12050,6 @@ __metadata:
languageName: node
linkType: hard
-"resolve-from@npm:^5.0.0":
- version: 5.0.0
- resolution: "resolve-from@npm:5.0.0"
- checksum: 10c0/b21cb7f1fb746de8107b9febab60095187781137fd803e6a59a76d421444b1531b641bba5857f5dc011974d8a5c635d61cec49e6bd3b7fc20e01f0fafc4efbf2
- languageName: node
- linkType: hard
-
"resolve-pathname@npm:^3.0.0":
version: 3.0.0
resolution: "resolve-pathname@npm:3.0.0"
@@ -12556,8 +12359,8 @@ __metadata:
linkType: hard
"sass@npm:^1.62.1, sass@npm:^1.70.0":
- version: 1.97.2
- resolution: "sass@npm:1.97.2"
+ version: 1.97.3
+ resolution: "sass@npm:1.97.3"
dependencies:
"@parcel/watcher": "npm:^2.4.1"
chokidar: "npm:^4.0.0"
@@ -12568,7 +12371,7 @@ __metadata:
optional: true
bin:
sass: sass.js
- checksum: 10c0/5622a4f9d0acf5cdfb72c73c448366b3ec7bfe2b6e1ecb62c6e9f8eaff9c02a6afd86a31ded246fc818fe660cedea6bd27335e82fc9bd7cce46c29f95774bece
+ checksum: 10c0/67f6b5d220f20c1c23a8b16dda5fd1c5d119ad5caf8195b185d553b5b239fb188a3787f04fc00171c62515f2c4e5e0eb5ad4992a80f8543428556883c1240ba3
languageName: node
linkType: hard
@@ -12843,10 +12646,10 @@ __metadata:
languageName: node
linkType: hard
-"slash@npm:^3.0.0":
- version: 3.0.0
- resolution: "slash@npm:3.0.0"
- checksum: 10c0/e18488c6a42bdfd4ac5be85b2ced3ccd0224773baae6ad42cfbb9ec74fc07f9fa8396bd35ee638084ead7a2a0818eb5e7151111544d4731ce843019dab4be47b
+"slash@npm:^5.1.0":
+ version: 5.1.0
+ resolution: "slash@npm:5.1.0"
+ checksum: 10c0/eb48b815caf0bdc390d0519d41b9e0556a14380f6799c72ba35caf03544d501d18befdeeef074bc9c052acf69654bc9e0d79d7f1de0866284137a40805299eb3
languageName: node
linkType: hard
@@ -13182,7 +12985,7 @@ __metadata:
languageName: node
linkType: hard
-"string-width@npm:^8.0.0":
+"string-width@npm:^8.0.0, string-width@npm:^8.1.0":
version: 8.1.0
resolution: "string-width@npm:8.1.0"
dependencies:
@@ -13368,88 +13171,88 @@ __metadata:
languageName: node
linkType: hard
-"stylelint-config-recommended-scss@npm:^16.0.1":
- version: 16.0.2
- resolution: "stylelint-config-recommended-scss@npm:16.0.2"
+"stylelint-config-recommended-scss@npm:^17.0.0":
+ version: 17.0.0
+ resolution: "stylelint-config-recommended-scss@npm:17.0.0"
dependencies:
postcss-scss: "npm:^4.0.9"
- stylelint-config-recommended: "npm:^17.0.0"
- stylelint-scss: "npm:^6.12.1"
+ stylelint-config-recommended: "npm:^18.0.0"
+ stylelint-scss: "npm:^7.0.0"
peerDependencies:
postcss: ^8.3.3
- stylelint: ^16.24.0
+ stylelint: ^17.0.0
peerDependenciesMeta:
postcss:
optional: true
- checksum: 10c0/d4e30a881e248d8b039347bf967526f6afe6d6a07f18e2747e14568de32273e819ba478be7a61a0dd63178931b4e891050a34e73d296ab533aa434209a7f3146
+ checksum: 10c0/05b2e8d4316c2a8cc66eed0a2a8f01237e0ee8966a2e73d0b3c6706694f7630be165daa5a0cef511bc51f7e3fcb07a84c55d948c15fe6193a7e13cf9bb67c913
languageName: node
linkType: hard
-"stylelint-config-recommended@npm:^17.0.0":
+"stylelint-config-recommended@npm:^18.0.0":
+ version: 18.0.0
+ resolution: "stylelint-config-recommended@npm:18.0.0"
+ peerDependencies:
+ stylelint: ^17.0.0
+ checksum: 10c0/c7f8ff45c76ec23f4c8c0438894726976fd5e872c59d489f959b728d9879bba20dbf0040cd29ad3bbc00eb32befd95f5b6ca150002bb8aea74b0797bc42ccc17
+ languageName: node
+ linkType: hard
+
+"stylelint-config-standard-scss@npm:^17.0.0":
version: 17.0.0
- resolution: "stylelint-config-recommended@npm:17.0.0"
- peerDependencies:
- stylelint: ^16.23.0
- checksum: 10c0/49e5d1c0f58197b2c5585b85fad814fed9bdec44c9870368c46a762664c5ff158c1145b6337456ae194409d692992b5b87421d62880422f71d8a3360417f5ad1
- languageName: node
- linkType: hard
-
-"stylelint-config-standard-scss@npm:^16.0.0":
- version: 16.0.0
- resolution: "stylelint-config-standard-scss@npm:16.0.0"
+ resolution: "stylelint-config-standard-scss@npm:17.0.0"
dependencies:
- stylelint-config-recommended-scss: "npm:^16.0.1"
- stylelint-config-standard: "npm:^39.0.0"
+ stylelint-config-recommended-scss: "npm:^17.0.0"
+ stylelint-config-standard: "npm:^40.0.0"
peerDependencies:
postcss: ^8.3.3
- stylelint: ^16.23.1
+ stylelint: ^17.0.0
peerDependenciesMeta:
postcss:
optional: true
- checksum: 10c0/eb77f23824c5d649b193cb71d7f9b538b32b8cc1769451b2993270361127243d4011baf891ec265711b8e34e69ce28acb57ab6c3947b51fa3713ac26f4276439
+ checksum: 10c0/0506537ba896f3d5e0fb002608090fcb41aa8ba7b65f1de8533702ce7c70e3f92b275782788a8356b5b687c86c53468c223e082226dda62780294b1cba324a36
languageName: node
linkType: hard
-"stylelint-config-standard@npm:^39.0.0":
- version: 39.0.1
- resolution: "stylelint-config-standard@npm:39.0.1"
+"stylelint-config-standard@npm:^40.0.0":
+ version: 40.0.0
+ resolution: "stylelint-config-standard@npm:40.0.0"
dependencies:
- stylelint-config-recommended: "npm:^17.0.0"
+ stylelint-config-recommended: "npm:^18.0.0"
peerDependencies:
- stylelint: ^16.23.0
- checksum: 10c0/70a9862a2cedcc2a1807bd92fc91c40877270cf8a39576b91ae056d6de51d3b68104b26f71056ff22461b4319e9ec988d009abf10ead513b2ec15569d82e865a
+ stylelint: ^17.0.0
+ checksum: 10c0/d8942552d53a3afda59b64d0c49503bb626fe5cef39a9e8c9583fcd60869f21431125ef4480ff27a59f7f2cf0da8af810d377129ef1d670ddc5def4defe2880c
languageName: node
linkType: hard
-"stylelint-scss@npm:^6.12.1":
- version: 6.12.1
- resolution: "stylelint-scss@npm:6.12.1"
+"stylelint-scss@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "stylelint-scss@npm:7.0.0"
dependencies:
css-tree: "npm:^3.0.1"
is-plain-object: "npm:^5.0.0"
- known-css-properties: "npm:^0.36.0"
- mdn-data: "npm:^2.21.0"
+ known-css-properties: "npm:^0.37.0"
+ mdn-data: "npm:^2.25.0"
postcss-media-query-parser: "npm:^0.2.3"
postcss-resolve-nested-selector: "npm:^0.1.6"
- postcss-selector-parser: "npm:^7.1.0"
+ postcss-selector-parser: "npm:^7.1.1"
postcss-value-parser: "npm:^4.2.0"
peerDependencies:
- stylelint: ^16.0.2
- checksum: 10c0/9a0903d34be3c75a72bef32402899db5f6b94c0823c5944fdf1acb2c3dc61c1f70fbb322558f8cb7e42dd01ed5e0dec22ed298f03b7bacc9f467c28330acae71
+ stylelint: ^16.8.2 || ^17.0.0
+ checksum: 10c0/07d0f20c6bcb34b8b0b6bfb1d4367b4825b52a7eef7dde2adfbaec11ebc67242e6b99dccf70dfbef1eb0a9bf8712fe0ab49d183ff6e4cca9c7f89752f7e27027
languageName: node
linkType: hard
-"stylelint@npm:^16.19.1":
- version: 16.26.1
- resolution: "stylelint@npm:16.26.1"
+"stylelint@npm:^17.0.0":
+ version: 17.0.0
+ resolution: "stylelint@npm:17.0.0"
dependencies:
- "@csstools/css-parser-algorithms": "npm:^3.0.5"
- "@csstools/css-syntax-patches-for-csstree": "npm:^1.0.19"
- "@csstools/css-tokenizer": "npm:^3.0.4"
- "@csstools/media-query-list-parser": "npm:^4.0.3"
- "@csstools/selector-specificity": "npm:^5.0.0"
- "@dual-bundle/import-meta-resolve": "npm:^4.2.1"
- balanced-match: "npm:^2.0.0"
+ "@csstools/css-parser-algorithms": "npm:^4.0.0"
+ "@csstools/css-syntax-patches-for-csstree": "npm:^1.0.25"
+ "@csstools/css-tokenizer": "npm:^4.0.0"
+ "@csstools/media-query-list-parser": "npm:^5.0.0"
+ "@csstools/selector-resolve-nested": "npm:^4.0.0"
+ "@csstools/selector-specificity": "npm:^6.0.0"
+ balanced-match: "npm:^3.0.1"
colord: "npm:^2.9.3"
cosmiconfig: "npm:^9.0.0"
css-functions-list: "npm:^3.2.3"
@@ -13459,32 +13262,31 @@ __metadata:
fastest-levenshtein: "npm:^1.0.16"
file-entry-cache: "npm:^11.1.1"
global-modules: "npm:^2.0.0"
- globby: "npm:^11.1.0"
+ globby: "npm:^16.1.0"
globjoin: "npm:^0.1.4"
- html-tags: "npm:^3.3.1"
+ html-tags: "npm:^5.1.0"
ignore: "npm:^7.0.5"
+ import-meta-resolve: "npm:^4.2.0"
imurmurhash: "npm:^0.1.4"
is-plain-object: "npm:^5.0.0"
known-css-properties: "npm:^0.37.0"
- mathml-tag-names: "npm:^2.1.3"
- meow: "npm:^13.2.0"
+ mathml-tag-names: "npm:^4.0.0"
+ meow: "npm:^14.0.0"
micromatch: "npm:^4.0.8"
normalize-path: "npm:^3.0.0"
picocolors: "npm:^1.1.1"
postcss: "npm:^8.5.6"
- postcss-resolve-nested-selector: "npm:^0.1.6"
postcss-safe-parser: "npm:^7.0.1"
- postcss-selector-parser: "npm:^7.1.0"
+ postcss-selector-parser: "npm:^7.1.1"
postcss-value-parser: "npm:^4.2.0"
- resolve-from: "npm:^5.0.0"
- string-width: "npm:^4.2.3"
- supports-hyperlinks: "npm:^3.2.0"
+ string-width: "npm:^8.1.0"
+ supports-hyperlinks: "npm:^4.4.0"
svg-tags: "npm:^1.0.0"
table: "npm:^6.9.0"
- write-file-atomic: "npm:^5.0.1"
+ write-file-atomic: "npm:^7.0.0"
bin:
stylelint: bin/stylelint.mjs
- checksum: 10c0/3805dfe868abdcc5a62e5726eebe5e950432cfadfc5b47c2f103ef4dede8ee1eb8a1247c9ceb01a1739c0aba68865d79899d33a707256365bb2004664524908b
+ checksum: 10c0/ad1ebabb17904c1bc0e386b078b9656c02942b60ae3663a00b2b23c60e9c6adffbd6787999ad4473cb558c0fc195c0d9e0de5a5e8f063752b61fe3a281fc4433
languageName: node
linkType: hard
@@ -13517,7 +13319,14 @@ __metadata:
languageName: node
linkType: hard
-"supports-color@npm:^7.0.0, supports-color@npm:^7.1.0":
+"supports-color@npm:^10.2.2":
+ version: 10.2.2
+ resolution: "supports-color@npm:10.2.2"
+ checksum: 10c0/fb28dd7e0cdf80afb3f2a41df5e068d60c8b4f97f7140de2eaed5b42e075d82a0e980b20a2c0efd2b6d73cfacb55555285d8cc719fa0472220715aefeaa1da7c
+ languageName: node
+ linkType: hard
+
+"supports-color@npm:^7.1.0":
version: 7.2.0
resolution: "supports-color@npm:7.2.0"
dependencies:
@@ -13526,13 +13335,13 @@ __metadata:
languageName: node
linkType: hard
-"supports-hyperlinks@npm:^3.2.0":
- version: 3.2.0
- resolution: "supports-hyperlinks@npm:3.2.0"
+"supports-hyperlinks@npm:^4.4.0":
+ version: 4.4.0
+ resolution: "supports-hyperlinks@npm:4.4.0"
dependencies:
- has-flag: "npm:^4.0.0"
- supports-color: "npm:^7.0.0"
- checksum: 10c0/bca527f38d4c45bc95d6a24225944675746c515ddb91e2456d00ae0b5c537658e9dd8155b996b191941b0c19036195a098251304b9082bbe00cd1781f3cd838e
+ has-flag: "npm:^5.0.1"
+ supports-color: "npm:^10.2.2"
+ checksum: 10c0/1172347b736e52f012506e162d5782d5fe9c64e22d286bd6daffbd182ca5696cc341fb0f66a550e2b96b5cdf31fc5217b009c6b92150843585debc6d8f1697bd
languageName: node
linkType: hard
@@ -14141,6 +13950,13 @@ __metadata:
languageName: node
linkType: hard
+"unicorn-magic@npm:^0.4.0":
+ version: 0.4.0
+ resolution: "unicorn-magic@npm:0.4.0"
+ checksum: 10c0/cd6eff90967a5528dfa2016bdb5b38b0cd64c8558f9ba04fb5c2c23f3a232a67dfe2bfa4c45af3685d5f1a40dbac6a36d48e053f80f97ae4da1e0f6a55431685
+ languageName: node
+ linkType: hard
+
"unique-filename@npm:^4.0.0":
version: 4.0.0
resolution: "unique-filename@npm:4.0.0"
@@ -14433,26 +14249,23 @@ __metadata:
linkType: hard
"vite-tsconfig-paths@npm:^6.0.0":
- version: 6.0.3
- resolution: "vite-tsconfig-paths@npm:6.0.3"
+ version: 6.0.5
+ resolution: "vite-tsconfig-paths@npm:6.0.5"
dependencies:
debug: "npm:^4.1.1"
globrex: "npm:^0.1.2"
tsconfck: "npm:^3.0.3"
peerDependencies:
vite: "*"
- peerDependenciesMeta:
- vite:
- optional: true
- checksum: 10c0/75cfe470f1ec0e776b2aec1d2e71316d5e1214f485fce7daaed4e4789d6f667881fb85d98129b6463a5b70c7524ef258b401c4871ed8b6318ac45cc892ee778a
+ checksum: 10c0/c62dd84804b9d2d35460146bda0bb752d270043d805df0e806ade6a9bbf37c5ad5da8a29d822b89931821545c201bc7ca07c594f245aebabe92d51d0cd1b63df
languageName: node
linkType: hard
"vite@npm:^6.0.0 || ^7.0.0, vite@npm:^7.1.1":
- version: 7.2.7
- resolution: "vite@npm:7.2.7"
+ version: 7.3.1
+ resolution: "vite@npm:7.3.1"
dependencies:
- esbuild: "npm:^0.25.0"
+ esbuild: "npm:^0.27.0"
fdir: "npm:^6.5.0"
fsevents: "npm:~2.3.3"
picomatch: "npm:^4.0.3"
@@ -14499,7 +14312,7 @@ __metadata:
optional: true
bin:
vite: bin/vite.js
- checksum: 10c0/0c502d9eb898d9c05061dbd8fd199f280b524bbb4c12ab5f88c7b12779947386684a269e4dd0aa424aa35bcd857f1aa44aadb9ea764702a5043af433052455b5
+ checksum: 10c0/5c7548f5f43a23533e53324304db4ad85f1896b1bfd3ee32ae9b866bac2933782c77b350eb2b52a02c625c8ad1ddd4c000df077419410650c982cd97fde8d014
languageName: node
linkType: hard
@@ -15007,13 +14820,13 @@ __metadata:
languageName: node
linkType: hard
-"write-file-atomic@npm:^5.0.1":
- version: 5.0.1
- resolution: "write-file-atomic@npm:5.0.1"
+"write-file-atomic@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "write-file-atomic@npm:7.0.0"
dependencies:
imurmurhash: "npm:^0.1.4"
signal-exit: "npm:^4.0.1"
- checksum: 10c0/e8c850a8e3e74eeadadb8ad23c9d9d63e4e792bd10f4836ed74189ef6e996763959f1249c5650e232f3c77c11169d239cbfc8342fc70f3fe401407d23810505d
+ checksum: 10c0/f5dd7c0324ae03b399974484fbe56363654c3884920e3c4f4d59b690596f113f60f4061a3c0aa5e6f4c22e5b9e7e0608954fd8131a916c9123b68a17ba886345
languageName: node
linkType: hard