Merge branch 'main' into compose-language-detection

This commit is contained in:
Thomas Steiner 2025-08-21 18:25:36 +02:00 committed by GitHub
commit c1d09c8d6e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
73 changed files with 1434 additions and 383 deletions

View File

@ -1,17 +1,21 @@
--- ---
Metrics/AbcSize: Metrics/AbcSize:
Exclude: Enabled: false
- lib/mastodon/cli/*.rb
Metrics/BlockLength: Metrics/BlockLength:
Enabled: false Enabled: false
Metrics/BlockNesting:
Enabled: false
Metrics/ClassLength: Metrics/ClassLength:
Enabled: false Enabled: false
Metrics/CollectionLiteralLength:
Enabled: false
Metrics/CyclomaticComplexity: Metrics/CyclomaticComplexity:
Exclude: Enabled: false
- lib/mastodon/cli/*.rb
Metrics/MethodLength: Metrics/MethodLength:
Enabled: false Enabled: false
@ -20,4 +24,7 @@ Metrics/ModuleLength:
Enabled: false Enabled: false
Metrics/ParameterLists: Metrics/ParameterLists:
CountKeywordArgs: false Enabled: false
Metrics/PerceivedComplexity:
Enabled: false

View File

@ -6,23 +6,6 @@
# Note that changes in the inspected code, or installation of new # Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again. # versions of RuboCop, may require this file to be generated again.
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize:
Max: 82
# Configuration parameters: CountBlocks, CountModifierForms, Max.
Metrics/BlockNesting:
Exclude:
- 'lib/tasks/mastodon.rake'
# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/CyclomaticComplexity:
Max: 25
# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/PerceivedComplexity:
Max: 27
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowedVars, DefaultToNil. # Configuration parameters: AllowedVars, DefaultToNil.
Style/FetchEnvVar: Style/FetchEnvVar:

View File

@ -806,10 +806,10 @@ GEM
ruby-saml (1.18.1) ruby-saml (1.18.1)
nokogiri (>= 1.13.10) nokogiri (>= 1.13.10)
rexml rexml
ruby-vips (2.2.4) ruby-vips (2.2.5)
ffi (~> 1.12) ffi (~> 1.12)
logger logger
rubyzip (3.0.1) rubyzip (3.0.2)
rufus-scheduler (3.9.2) rufus-scheduler (3.9.2)
fugit (~> 1.1, >= 1.11.1) fugit (~> 1.1, >= 1.11.1)
safety_net_attestation (0.4.0) safety_net_attestation (0.4.0)

View File

@ -102,6 +102,16 @@ module ApplicationHelper
policy(record).public_send(:"#{action}?") policy(record).public_send(:"#{action}?")
end end
def conditional_link_to(condition, name, options = {}, html_options = {}, &block)
if condition && !current_page?(block_given? ? name : options)
link_to(name, options, html_options, &block)
elsif block_given?
content_tag(:span, options, html_options, &block)
else
content_tag(:span, name, html_options)
end
end
def material_symbol(icon, attributes = {}) def material_symbol(icon, attributes = {})
safe_join( safe_join(
[ [

View File

@ -84,6 +84,7 @@ export const COMPOSE_FOCUS = 'COMPOSE_FOCUS';
const messages = defineMessages({ const messages = defineMessages({
uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' }, uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' }, uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
uploadQuote: { id: 'upload_error.quote', defaultMessage: 'File upload not allowed with quotes.' },
open: { id: 'compose.published.open', defaultMessage: 'Open' }, open: { id: 'compose.published.open', defaultMessage: 'Open' },
published: { id: 'compose.published.body', defaultMessage: 'Post published.' }, published: { id: 'compose.published.body', defaultMessage: 'Post published.' },
saved: { id: 'compose.saved.body', defaultMessage: 'Post saved.' }, saved: { id: 'compose.saved.body', defaultMessage: 'Post saved.' },
@ -146,7 +147,7 @@ export function resetCompose() {
}; };
} }
export const focusCompose = (defaultText) => (dispatch, getState) => { export const focusCompose = (defaultText = '') => (dispatch, getState) => {
dispatch({ dispatch({
type: COMPOSE_FOCUS, type: COMPOSE_FOCUS,
defaultText, defaultText,
@ -303,6 +304,11 @@ export function submitComposeFail(error) {
export function uploadCompose(files) { export function uploadCompose(files) {
return function (dispatch, getState) { return function (dispatch, getState) {
// Exit if there's a quote.
if (getState().compose.get('quoted_status_id')) {
dispatch(showAlert({ message: messages.uploadQuote }));
return;
}
const uploadLimit = getState().getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments']); const uploadLimit = getState().getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments']);
const media = getState().getIn(['compose', 'media_attachments']); const media = getState().getIn(['compose', 'media_attachments']);
const pending = getState().getIn(['compose', 'pending_media_attachments']); const pending = getState().getIn(['compose', 'pending_media_attachments']);

View File

@ -1,3 +1,5 @@
import { defineMessages } from 'react-intl';
import { createAction } from '@reduxjs/toolkit'; import { createAction } from '@reduxjs/toolkit';
import type { List as ImmutableList, Map as ImmutableMap } from 'immutable'; import type { List as ImmutableList, Map as ImmutableMap } from 'immutable';
@ -12,7 +14,27 @@ import {
import type { ApiQuotePolicy } from '../api_types/quotes'; import type { ApiQuotePolicy } from '../api_types/quotes';
import type { Status } from '../models/status'; import type { Status } from '../models/status';
import { ensureComposeIsVisible } from './compose'; import { showAlert } from './alerts';
import { focusCompose } from './compose';
const messages = defineMessages({
quoteErrorUpload: {
id: 'quote_error.upload',
defaultMessage: 'Quoting is not allowed with media attachments.',
},
quoteErrorPoll: {
id: 'quote_error.poll',
defaultMessage: 'Quoting is not allowed with polls.',
},
quoteErrorQuote: {
id: 'quote_error.quote',
defaultMessage: 'Only one quote at a time is allowed.',
},
quoteErrorUnauthorized: {
id: 'quote_error.unauthorized',
defaultMessage: 'You are not authorized to quote this post.',
},
});
type SimulatedMediaAttachmentJSON = ApiMediaAttachmentJSON & { type SimulatedMediaAttachmentJSON = ApiMediaAttachmentJSON & {
unattached?: boolean; unattached?: boolean;
@ -78,14 +100,43 @@ export const changeUploadCompose = createDataLoadingThunk(
}, },
); );
export const quoteComposeByStatus = createAppThunk( export const quoteCompose = createAppThunk(
'compose/quoteComposeStatus', 'compose/quoteComposeStatus',
(status: Status, { getState }) => { (status: Status, { dispatch }) => {
ensureComposeIsVisible(getState); dispatch(focusCompose());
return status; return status;
}, },
); );
export const quoteComposeByStatus = createAppThunk(
(status: Status, { dispatch, getState }) => {
const composeState = getState().compose;
const mediaAttachments = composeState.get('media_attachments');
if (composeState.get('poll')) {
dispatch(showAlert({ message: messages.quoteErrorPoll }));
} else if (
composeState.get('is_uploading') ||
(mediaAttachments &&
typeof mediaAttachments !== 'string' &&
typeof mediaAttachments !== 'number' &&
typeof mediaAttachments !== 'boolean' &&
mediaAttachments.size !== 0)
) {
dispatch(showAlert({ message: messages.quoteErrorUpload }));
} else if (composeState.get('quoted_status_id')) {
dispatch(showAlert({ message: messages.quoteErrorQuote }));
} else if (
status.getIn(['quote_approval', 'current_user']) !== 'automatic' &&
status.getIn(['quote_approval', 'current_user']) !== 'manual'
) {
dispatch(showAlert({ message: messages.quoteErrorUnauthorized }));
} else {
dispatch(quoteCompose(status));
}
},
);
export const quoteComposeById = createAppThunk( export const quoteComposeById = createAppThunk(
(statusId: string, { dispatch, getState }) => { (statusId: string, { dispatch, getState }) => {
const status = getState().statuses.get(statusId); const status = getState().statuses.get(statusId);
@ -97,6 +148,6 @@ export const quoteComposeById = createAppThunk(
export const quoteComposeCancel = createAction('compose/quoteComposeCancel'); export const quoteComposeCancel = createAction('compose/quoteComposeCancel');
export const setQuotePolicy = createAction<ApiQuotePolicy>( export const setComposeQuotePolicy = createAction<ApiQuotePolicy>(
'compose/setQuotePolicy', 'compose/setQuotePolicy',
); );

View File

@ -2,6 +2,7 @@ import type { ApiStatusJSON } from './statuses';
export type ApiQuoteState = 'accepted' | 'pending' | 'revoked' | 'unauthorized'; export type ApiQuoteState = 'accepted' | 'pending' | 'revoked' | 'unauthorized';
export type ApiQuotePolicy = 'public' | 'followers' | 'nobody' | 'unknown'; export type ApiQuotePolicy = 'public' | 'followers' | 'nobody' | 'unknown';
export type ApiUserQuotePolicy = 'automatic' | 'manual' | 'denied' | 'unknown';
interface ApiQuoteEmptyJSON { interface ApiQuoteEmptyJSON {
state: Exclude<ApiQuoteState, 'accepted'>; state: Exclude<ApiQuoteState, 'accepted'>;
@ -25,7 +26,7 @@ export type ApiQuoteJSON = ApiQuoteAcceptedJSON | ApiQuoteEmptyJSON;
export interface ApiQuotePolicyJSON { export interface ApiQuotePolicyJSON {
automatic: ApiQuotePolicy[]; automatic: ApiQuotePolicy[];
manual: ApiQuotePolicy[]; manual: ApiQuotePolicy[];
current_user: ApiQuotePolicy; current_user: ApiUserQuotePolicy;
} }
export function isQuotePolicy(policy: string): policy is ApiQuotePolicy { export function isQuotePolicy(policy: string): policy is ApiQuotePolicy {

View File

@ -133,3 +133,9 @@ export interface ApiStatusSourceJSON {
text: string; text: string;
spoiler_text: string; spoiler_text: string;
} }
export function isStatusVisibility(
visibility: string,
): visibility is StatusVisibility {
return ['public', 'unlisted', 'private', 'direct'].includes(visibility);
}

View File

@ -41,13 +41,16 @@ import { IconButton } from './icon_button';
let id = 0; let id = 0;
type RenderItemFn<Item = MenuItem> = ( export interface RenderItemFnHandlers {
onClick: React.MouseEventHandler;
onKeyUp: React.KeyboardEventHandler;
}
export type RenderItemFn<Item = MenuItem> = (
item: Item, item: Item,
index: number, index: number,
handlers: { handlers: RenderItemFnHandlers,
onClick: (e: React.MouseEvent) => void; focusRefCallback?: (c: HTMLAnchorElement | HTMLButtonElement | null) => void,
onKeyUp: (e: React.KeyboardEvent) => void;
},
) => React.ReactNode; ) => React.ReactNode;
type ItemClickFn<Item = MenuItem> = (item: Item, index: number) => void; type ItemClickFn<Item = MenuItem> = (item: Item, index: number) => void;
@ -173,7 +176,7 @@ export const DropdownMenu = <Item = MenuItem,>({
onItemClick(item, i); onItemClick(item, i);
} else if (isActionItem(item)) { } else if (isActionItem(item)) {
e.preventDefault(); e.preventDefault();
item.action(); item.action(e);
} }
}, },
[onClose, onItemClick, items], [onClose, onItemClick, items],
@ -277,10 +280,15 @@ export const DropdownMenu = <Item = MenuItem,>({
})} })}
> >
{items.map((option, i) => {items.map((option, i) =>
renderItemMethod(option, i, { renderItemMethod(
onClick: handleItemClick, option,
onKeyUp: handleItemKeyUp, i,
}), {
onClick: handleItemClick,
onKeyUp: handleItemKeyUp,
},
i === 0 ? handleFocusedItemRef : undefined,
),
)} )}
</ul> </ul>
)} )}
@ -307,7 +315,9 @@ interface DropdownProps<Item = MenuItem> {
forceDropdown?: boolean; forceDropdown?: boolean;
renderItem?: RenderItemFn<Item>; renderItem?: RenderItemFn<Item>;
renderHeader?: RenderHeaderFn<Item>; renderHeader?: RenderHeaderFn<Item>;
onOpen?: () => void; onOpen?: // Must use a union type for the full function as a union with void is not allowed.
| ((event: React.MouseEvent | React.KeyboardEvent) => void)
| ((event: React.MouseEvent | React.KeyboardEvent) => boolean);
onItemClick?: ItemClickFn<Item>; onItemClick?: ItemClickFn<Item>;
} }
@ -376,7 +386,7 @@ export const Dropdown = <Item = MenuItem,>({
onItemClick(item, i); onItemClick(item, i);
} else if (isActionItem(item)) { } else if (isActionItem(item)) {
e.preventDefault(); e.preventDefault();
item.action(); item.action(e);
} }
}, },
[handleClose, onItemClick, items], [handleClose, onItemClick, items],
@ -389,7 +399,10 @@ export const Dropdown = <Item = MenuItem,>({
if (open) { if (open) {
handleClose(); handleClose();
} else { } else {
onOpen?.(); const allow = onOpen?.(e);
if (allow === false) {
return;
}
if (prefetchAccountId) { if (prefetchAccountId) {
dispatch(fetchRelationships([prefetchAccountId])); dispatch(fetchRelationships([prefetchAccountId]));

View File

@ -110,6 +110,7 @@ class Status extends ImmutablePureComponent {
onToggleCollapsed: PropTypes.func, onToggleCollapsed: PropTypes.func,
onTranslate: PropTypes.func, onTranslate: PropTypes.func,
onInteractionModal: PropTypes.func, onInteractionModal: PropTypes.func,
onQuoteCancel: PropTypes.func,
muted: PropTypes.bool, muted: PropTypes.bool,
hidden: PropTypes.bool, hidden: PropTypes.bool,
unread: PropTypes.bool, unread: PropTypes.bool,
@ -583,7 +584,7 @@ class Status extends ImmutablePureComponent {
<DisplayName account={status.get('account')} /> <DisplayName account={status.get('account')} />
</Link> </Link>
{this.props.contextType === 'compose' && isQuotedPost && ( {isQuotedPost && !!this.props.onQuoteCancel && (
<IconButton <IconButton
onClick={this.handleQuoteCancel} onClick={this.handleQuoteCancel}
className='status__quote-cancel' className='status__quote-cancel'

View File

@ -0,0 +1,89 @@
import type { Meta, StoryObj } from '@storybook/react-vite';
import type { StatusVisibility } from '@/mastodon/api_types/statuses';
import { statusFactoryState } from '@/testing/factories';
import { LegacyReblogButton, StatusReblogButton } from './reblog_button';
interface StoryProps {
visibility: StatusVisibility;
quoteAllowed: boolean;
alreadyBoosted: boolean;
reblogCount: number;
}
const meta = {
title: 'Components/Status/ReblogButton',
args: {
visibility: 'public',
quoteAllowed: true,
alreadyBoosted: false,
reblogCount: 0,
},
argTypes: {
visibility: {
name: 'Visibility',
control: { type: 'select' },
options: ['public', 'unlisted', 'private', 'direct'],
},
reblogCount: {
name: 'Boost Count',
description: 'More than 0 will show the counter',
},
quoteAllowed: {
name: 'Quotes allowed',
},
alreadyBoosted: {
name: 'Already boosted',
},
},
render: (args) => (
<StatusReblogButton
status={argsToStatus(args)}
counters={args.reblogCount > 0}
/>
),
} satisfies Meta<StoryProps>;
export default meta;
function argsToStatus({
reblogCount,
visibility,
quoteAllowed,
alreadyBoosted,
}: StoryProps) {
return statusFactoryState({
reblogs_count: reblogCount,
visibility,
reblogged: alreadyBoosted,
quote_approval: {
automatic: [],
manual: [],
current_user: quoteAllowed ? 'automatic' : 'denied',
},
});
}
type Story = StoryObj<typeof meta>;
export const Default: Story = {};
export const Mine: Story = {
parameters: {
state: {
meta: {
me: '1',
},
},
},
};
export const Legacy: Story = {
render: (args) => (
<LegacyReblogButton
status={argsToStatus(args)}
counters={args.reblogCount > 0}
/>
),
};

View File

@ -0,0 +1,373 @@
import { useCallback, useMemo } from 'react';
import type {
FC,
KeyboardEvent,
MouseEvent,
MouseEventHandler,
SVGProps,
} from 'react';
import type { MessageDescriptor } from 'react-intl';
import { defineMessages, useIntl } from 'react-intl';
import classNames from 'classnames';
import { quoteComposeById } from '@/mastodon/actions/compose_typed';
import { toggleReblog } from '@/mastodon/actions/interactions';
import { openModal } from '@/mastodon/actions/modal';
import type { ActionMenuItem } from '@/mastodon/models/dropdown_menu';
import type { Status, StatusVisibility } from '@/mastodon/models/status';
import {
createAppSelector,
useAppDispatch,
useAppSelector,
} from '@/mastodon/store';
import { isFeatureEnabled } from '@/mastodon/utils/environment';
import FormatQuote from '@/material-icons/400-24px/format_quote.svg?react';
import FormatQuoteOff from '@/material-icons/400-24px/format_quote_off.svg?react';
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
import RepeatActiveIcon from '@/svg-icons/repeat_active.svg?react';
import RepeatDisabledIcon from '@/svg-icons/repeat_disabled.svg?react';
import RepeatPrivateIcon from '@/svg-icons/repeat_private.svg?react';
import RepeatPrivateActiveIcon from '@/svg-icons/repeat_private_active.svg?react';
import type { RenderItemFn, RenderItemFnHandlers } from '../dropdown_menu';
import { Dropdown } from '../dropdown_menu';
import { Icon } from '../icon';
import { IconButton } from '../icon_button';
const messages = defineMessages({
all_disabled: {
id: 'status.all_disabled',
defaultMessage: 'Boosts and quotes are disabled',
},
quote: { id: 'status.quote', defaultMessage: 'Quote' },
quote_cannot: {
id: 'status.cannot_quote',
defaultMessage: 'Author has disabled quoting on this post',
},
quote_private: {
id: 'status.quote_private',
defaultMessage: 'Private posts cannot be quoted',
},
reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
reblog_cancel: {
id: 'status.cancel_reblog_private',
defaultMessage: 'Unboost',
},
reblog_private: {
id: 'status.reblog_private',
defaultMessage: 'Boost with original visibility',
},
reblog_cannot: {
id: 'status.cannot_reblog',
defaultMessage: 'This post cannot be boosted',
},
});
interface ReblogButtonProps {
status: Status;
counters?: boolean;
}
export const StatusReblogButton: FC<ReblogButtonProps> = ({
status,
counters,
}) => {
const intl = useIntl();
const statusState = useAppSelector((state) =>
selectStatusState(state, status),
);
const { isLoggedIn, isReblogged, isReblogAllowed, isQuoteAllowed } =
statusState;
const { iconComponent } = useMemo(
() => reblogIconText(statusState),
[statusState],
);
const disabled = !isQuoteAllowed && !isReblogAllowed;
const dispatch = useAppDispatch();
const statusId = status.get('id') as string;
const items: ActionMenuItem[] = useMemo(
() => [
{
text: 'reblog',
action: (event) => {
if (isLoggedIn) {
dispatch(toggleReblog(statusId, event.shiftKey));
}
},
},
{
text: 'quote',
action: () => {
if (isLoggedIn) {
dispatch(quoteComposeById(statusId));
}
},
},
],
[dispatch, isLoggedIn, statusId],
);
const handleDropdownOpen = useCallback(
(event: MouseEvent | KeyboardEvent) => {
if (!isLoggedIn) {
dispatch(
openModal({
modalType: 'INTERACTION',
modalProps: {
type: 'reblog',
accountId: status.getIn(['account', 'id']),
url: status.get('uri'),
},
}),
);
} else if (event.shiftKey) {
dispatch(toggleReblog(status.get('id'), true));
return false;
}
return true;
},
[dispatch, isLoggedIn, status],
);
const renderMenuItem: RenderItemFn<ActionMenuItem> = useCallback(
(item, index, handlers, focusRefCallback) => (
<ReblogMenuItem
status={status}
index={index}
item={item}
handlers={handlers}
key={`${item.text}-${index}`}
focusRefCallback={focusRefCallback}
/>
),
[status],
);
return (
<Dropdown
items={items}
renderItem={renderMenuItem}
onOpen={handleDropdownOpen}
disabled={disabled}
>
<IconButton
title={intl.formatMessage(
!disabled ? messages.reblog : messages.all_disabled,
)}
icon='retweet'
iconComponent={iconComponent}
counter={counters ? (status.get('reblogs_count') as number) : undefined}
active={isReblogged}
/>
</Dropdown>
);
};
interface ReblogMenuItemProps {
status: Status;
item: ActionMenuItem;
index: number;
handlers: RenderItemFnHandlers;
focusRefCallback?: (c: HTMLAnchorElement | HTMLButtonElement | null) => void;
}
const ReblogMenuItem: FC<ReblogMenuItemProps> = ({
status,
index,
item: { text },
handlers,
focusRefCallback,
}) => {
const intl = useIntl();
const statusState = useAppSelector((state) =>
selectStatusState(state, status),
);
const { title, meta, iconComponent, disabled } = useMemo(
() =>
text === 'quote'
? quoteIconText(statusState)
: reblogIconText(statusState),
[statusState, text],
);
const active = useMemo(
() => text === 'reblog' && !!status.get('reblogged'),
[status, text],
);
return (
<li
className={classNames('dropdown-menu__item reblog-button__item', {
disabled,
active,
})}
key={`${text}-${index}`}
>
<button
{...handlers}
title={intl.formatMessage(title)}
ref={focusRefCallback}
disabled={disabled}
data-index={index}
>
<Icon
id={text === 'quote' ? 'quote' : 'retweet'}
icon={iconComponent}
/>
<div>
{intl.formatMessage(title)}
{meta && (
<span className='reblog-button__meta'>
{intl.formatMessage(meta)}
</span>
)}
</div>
</button>
</li>
);
};
// Legacy helpers
// Switch between the legacy and new reblog button based on feature flag.
export const ReblogButton: FC<ReblogButtonProps> = (props) => {
if (isFeatureEnabled('outgoing_quotes')) {
return <StatusReblogButton {...props} />;
}
return <LegacyReblogButton {...props} />;
};
export const LegacyReblogButton: FC<ReblogButtonProps> = ({
status,
counters,
}) => {
const intl = useIntl();
const statusState = useAppSelector((state) =>
selectStatusState(state, status),
);
const { title, meta, iconComponent, disabled } = useMemo(
() => reblogIconText(statusState),
[statusState],
);
const dispatch = useAppDispatch();
const handleClick: MouseEventHandler = useCallback(
(event) => {
if (statusState.isLoggedIn) {
dispatch(toggleReblog(status.get('id') as string, event.shiftKey));
} else {
dispatch(
openModal({
modalType: 'INTERACTION',
modalProps: {
type: 'reblog',
accountId: status.getIn(['account', 'id']),
url: status.get('uri'),
},
}),
);
}
},
[dispatch, status, statusState.isLoggedIn],
);
return (
<IconButton
disabled={disabled}
active={!!status.get('reblogged')}
title={intl.formatMessage(meta ?? title)}
icon='retweet'
iconComponent={iconComponent}
onClick={!disabled ? handleClick : undefined}
counter={counters ? (status.get('reblogs_count') as number) : undefined}
/>
);
};
// Helpers for copy and state for status.
const selectStatusState = createAppSelector(
[
(state) => state.meta.get('me') as string | undefined,
(_, status: Status) => status,
],
(userId, status) => {
const isPublic = ['public', 'unlisted'].includes(
status.get('visibility') as StatusVisibility,
);
const isMineAndPrivate =
userId === status.getIn(['account', 'id']) &&
status.get('visibility') === 'private';
return {
isLoggedIn: !!userId,
isPublic,
isMine: userId === status.getIn(['account', 'id']),
isPrivateReblog:
userId === status.getIn(['account', 'id']) &&
status.get('visibility') === 'private',
isReblogged: !!status.get('reblogged'),
isReblogAllowed: isPublic || isMineAndPrivate,
isQuoteAllowed:
status.getIn(['quote_approval', 'current_user']) === 'automatic' &&
(isPublic || isMineAndPrivate),
};
},
);
type StatusState = ReturnType<typeof selectStatusState>;
interface IconText {
title: MessageDescriptor;
meta?: MessageDescriptor;
iconComponent: FC<SVGProps<SVGSVGElement>>;
disabled?: boolean;
}
function reblogIconText({
isPublic,
isPrivateReblog,
isReblogged,
}: StatusState): IconText {
if (isReblogged) {
return {
title: messages.reblog_cancel,
iconComponent: isPublic ? RepeatActiveIcon : RepeatPrivateActiveIcon,
};
}
const iconText: IconText = {
title: messages.reblog,
iconComponent: RepeatIcon,
};
if (isPrivateReblog) {
iconText.meta = messages.reblog_private;
iconText.iconComponent = RepeatPrivateIcon;
} else if (!isPublic) {
iconText.meta = messages.reblog_cannot;
iconText.iconComponent = RepeatDisabledIcon;
iconText.disabled = true;
}
return iconText;
}
function quoteIconText({
isMine,
isQuoteAllowed,
isPublic,
}: StatusState): IconText {
const iconText: IconText = {
title: messages.quote,
iconComponent: FormatQuote,
};
if (!isQuoteAllowed || (!isPublic && !isMine)) {
iconText.meta = !isQuoteAllowed
? messages.quote_cannot
: messages.quote_private;
iconText.iconComponent = FormatQuoteOff;
iconText.disabled = true;
}
return iconText;
}

View File

@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames';
import { withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
@ -12,15 +11,10 @@ import { connect } from 'react-redux';
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg?react'; import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg?react';
import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react'; import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react'; import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react';
import StarIcon from '@/material-icons/400-24px/star-fill.svg?react'; import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
import StarBorderIcon from '@/material-icons/400-24px/star.svg?react'; import StarBorderIcon from '@/material-icons/400-24px/star.svg?react';
import RepeatActiveIcon from '@/svg-icons/repeat_active.svg?react';
import RepeatDisabledIcon from '@/svg-icons/repeat_disabled.svg?react';
import RepeatPrivateIcon from '@/svg-icons/repeat_private.svg?react';
import RepeatPrivateActiveIcon from '@/svg-icons/repeat_private_active.svg?react';
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
import { WithRouterPropTypes } from 'mastodon/utils/react_router'; import { WithRouterPropTypes } from 'mastodon/utils/react_router';
@ -30,6 +24,7 @@ import { me } from '../initial_state';
import { IconButton } from './icon_button'; import { IconButton } from './icon_button';
import { isFeatureEnabled } from '../utils/environment'; import { isFeatureEnabled } from '../utils/environment';
import { ReblogButton } from './status/reblog_button';
const messages = defineMessages({ const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' }, delete: { id: 'status.delete', defaultMessage: 'Delete' },
@ -43,10 +38,6 @@ const messages = defineMessages({
share: { id: 'status.share', defaultMessage: 'Share' }, share: { id: 'status.share', defaultMessage: 'Share' },
more: { id: 'status.more', defaultMessage: 'More' }, more: { id: 'status.more', defaultMessage: 'More' },
replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' }, replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' },
reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost with original visibility' },
cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' },
cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' },
favourite: { id: 'status.favourite', defaultMessage: 'Favorite' }, favourite: { id: 'status.favourite', defaultMessage: 'Favorite' },
removeFavourite: { id: 'status.remove_favourite', defaultMessage: 'Remove from favorites' }, removeFavourite: { id: 'status.remove_favourite', defaultMessage: 'Remove from favorites' },
bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' }, bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' },
@ -85,10 +76,9 @@ class StatusActionBar extends ImmutablePureComponent {
identity: identityContextPropShape, identity: identityContextPropShape,
status: ImmutablePropTypes.map.isRequired, status: ImmutablePropTypes.map.isRequired,
relationship: ImmutablePropTypes.record, relationship: ImmutablePropTypes.record,
quotedAccountId: ImmutablePropTypes.string, quotedAccountId: PropTypes.string,
onReply: PropTypes.func, onReply: PropTypes.func,
onFavourite: PropTypes.func, onFavourite: PropTypes.func,
onReblog: PropTypes.func,
onDelete: PropTypes.func, onDelete: PropTypes.func,
onRevokeQuote: PropTypes.func, onRevokeQuote: PropTypes.func,
onQuotePolicyChange: PropTypes.func, onQuotePolicyChange: PropTypes.func,
@ -152,16 +142,6 @@ class StatusActionBar extends ImmutablePureComponent {
} }
}; };
handleReblogClick = e => {
const { signedIn } = this.props.identity;
if (signedIn) {
this.props.onReblog(this.props.status, e);
} else {
this.props.onInteractionModal('reblog', this.props.status);
}
};
handleBookmarkClick = () => { handleBookmarkClick = () => {
this.props.onBookmark(this.props.status); this.props.onBookmark(this.props.status);
}; };
@ -377,25 +357,6 @@ class StatusActionBar extends ImmutablePureComponent {
replyTitle = intl.formatMessage(messages.replyAll); replyTitle = intl.formatMessage(messages.replyAll);
} }
const reblogPrivate = status.getIn(['account', 'id']) === me && status.get('visibility') === 'private';
let reblogTitle, reblogIconComponent;
if (status.get('reblogged')) {
reblogTitle = intl.formatMessage(messages.cancel_reblog_private);
reblogIconComponent = publicStatus ? RepeatActiveIcon : RepeatPrivateActiveIcon;
} else if (publicStatus) {
reblogTitle = intl.formatMessage(messages.reblog);
reblogIconComponent = RepeatIcon;
} else if (reblogPrivate) {
reblogTitle = intl.formatMessage(messages.reblog_private);
reblogIconComponent = RepeatPrivateIcon;
} else {
reblogTitle = intl.formatMessage(messages.cannot_reblog);
reblogIconComponent = RepeatDisabledIcon;
}
const bookmarkTitle = intl.formatMessage(status.get('bookmarked') ? messages.removeBookmark : messages.bookmark); const bookmarkTitle = intl.formatMessage(status.get('bookmarked') ? messages.removeBookmark : messages.bookmark);
const favouriteTitle = intl.formatMessage(status.get('favourited') ? messages.removeFavourite : messages.favourite); const favouriteTitle = intl.formatMessage(status.get('favourited') ? messages.removeFavourite : messages.favourite);
const isReply = status.get('in_reply_to_account_id') === status.getIn(['account', 'id']); const isReply = status.get('in_reply_to_account_id') === status.getIn(['account', 'id']);
@ -406,7 +367,7 @@ class StatusActionBar extends ImmutablePureComponent {
<IconButton className='status__action-bar__button' title={replyTitle} icon={isReply ? 'reply' : replyIcon} iconComponent={isReply ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} counter={status.get('replies_count')} /> <IconButton className='status__action-bar__button' title={replyTitle} icon={isReply ? 'reply' : replyIcon} iconComponent={isReply ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} counter={status.get('replies_count')} />
</div> </div>
<div className='status__action-bar__button-wrapper'> <div className='status__action-bar__button-wrapper'>
<IconButton className={classNames('status__action-bar__button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} counter={withCounters ? status.get('reblogs_count') : undefined} /> <ReblogButton status={status} counters={withCounters} />
</div> </div>
<div className='status__action-bar__button-wrapper'> <div className='status__action-bar__button-wrapper'>
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={favouriteTitle} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} /> <IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={favouriteTitle} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />

View File

@ -63,12 +63,21 @@ type GetStatusSelector = (
props: { id?: string | null; contextType?: string }, props: { id?: string | null; contextType?: string },
) => Status | null; ) => Status | null;
export const QuotedStatus: React.FC<{ interface QuotedStatusProps {
quote: QuoteMap; quote: QuoteMap;
contextType?: string; contextType?: string;
variant?: 'full' | 'link'; variant?: 'full' | 'link';
nestingLevel?: number; nestingLevel?: number;
}> = ({ quote, contextType, nestingLevel = 1, variant = 'full' }) => { onQuoteCancel?: () => void; // Used for composer.
}
export const QuotedStatus: React.FC<QuotedStatusProps> = ({
quote,
contextType,
nestingLevel = 1,
variant = 'full',
onQuoteCancel,
}) => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const quotedStatusId = quote.get('quoted_status'); const quotedStatusId = quote.get('quoted_status');
const quoteState = quote.get('state'); const quoteState = quote.get('state');
@ -160,6 +169,7 @@ export const QuotedStatus: React.FC<{
id={quotedStatusId} id={quotedStatusId}
contextType={contextType} contextType={contextType}
avatarSize={32} avatarSize={32}
onQuoteCancel={onQuoteCancel}
> >
{canRenderChildQuote && ( {canRenderChildQuote && (
<QuotedStatus <QuotedStatus

View File

@ -41,10 +41,10 @@ import {
translateStatus, translateStatus,
undoStatusTranslation, undoStatusTranslation,
} from '../actions/statuses'; } from '../actions/statuses';
import { setStatusQuotePolicy } from '../actions/statuses_typed';
import Status from '../components/status'; import Status from '../components/status';
import { deleteModal } from '../initial_state'; import { deleteModal } from '../initial_state';
import { makeGetStatus, makeGetPictureInPicture } from '../selectors'; import { makeGetStatus, makeGetPictureInPicture } from '../selectors';
import { quoteComposeCancel } from '../actions/compose_typed';
const makeMapStateToProps = () => { const makeMapStateToProps = () => {
const getStatus = makeGetStatus(); const getStatus = makeGetStatus();
@ -112,18 +112,18 @@ const mapDispatchToProps = (dispatch, { contextType }) => ({
} }
}, },
onQuoteCancel() {
if (contextType === 'compose') {
dispatch(quoteComposeCancel());
}
},
onRevokeQuote (status) { onRevokeQuote (status) {
dispatch(openModal({ modalType: 'CONFIRM_REVOKE_QUOTE', modalProps: { statusId: status.get('id'), quotedStatusId: status.getIn(['quote', 'quoted_status']) }})); dispatch(openModal({ modalType: 'CONFIRM_REVOKE_QUOTE', modalProps: { statusId: status.get('id'), quotedStatusId: status.getIn(['quote', 'quoted_status']) }}));
}, },
onQuotePolicyChange(status) { onQuotePolicyChange(status) {
dispatch(openModal({ modalType: 'COMPOSE_PRIVACY', modalProps: { statusId: status.get('id') } })); const statusId = status.get('id');
const handleChange = (_, quotePolicy) => {
dispatch(
setStatusQuotePolicy({ policy: quotePolicy, statusId }),
);
}
dispatch(openModal({ modalType: 'COMPOSE_PRIVACY', modalProps: { statusId, onChange: handleChange } }));
}, },
onEdit (status) { onEdit (status) {

View File

@ -17,7 +17,6 @@ import AutosuggestTextarea from 'mastodon/components/autosuggest_textarea';
import { Button } from 'mastodon/components/button'; import { Button } from 'mastodon/components/button';
import EmojiPickerDropdown from '../containers/emoji_picker_dropdown_container'; import EmojiPickerDropdown from '../containers/emoji_picker_dropdown_container';
import PollButtonContainer from '../containers/poll_button_container'; import PollButtonContainer from '../containers/poll_button_container';
import PrivacyDropdownContainer from '../containers/privacy_dropdown_container';
import SpoilerButtonContainer from '../containers/spoiler_button_container'; import SpoilerButtonContainer from '../containers/spoiler_button_container';
import UploadButtonContainer from '../containers/upload_button_container'; import UploadButtonContainer from '../containers/upload_button_container';
import { countableText } from '../util/counter'; import { countableText } from '../util/counter';
@ -31,6 +30,7 @@ import { ReplyIndicator } from './reply_indicator';
import { UploadForm } from './upload_form'; import { UploadForm } from './upload_form';
import { Warning } from './warning'; import { Warning } from './warning';
import { ComposeQuotedStatus } from './quoted_post'; import { ComposeQuotedStatus } from './quoted_post';
import { VisibilityButton } from './visibility_button';
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d'; const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
@ -259,7 +259,7 @@ class ComposeForm extends ImmutablePureComponent {
<EditIndicator /> <EditIndicator />
<div className='compose-form__dropdowns'> <div className='compose-form__dropdowns'>
<PrivacyDropdownContainer disabled={this.props.isEditing} /> <VisibilityButton disabled={this.props.isEditing} />
<LanguageDropdown /> <LanguageDropdown />
</div> </div>

View File

@ -1,15 +1,17 @@
import { useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import type { FC } from 'react'; import type { FC } from 'react';
import { Map } from 'immutable'; import { Map } from 'immutable';
import { quoteComposeCancel } from '@/mastodon/actions/compose_typed';
import { QuotedStatus } from '@/mastodon/components/status_quoted'; import { QuotedStatus } from '@/mastodon/components/status_quoted';
import { useAppSelector } from '@/mastodon/store'; import { useAppDispatch, useAppSelector } from '@/mastodon/store';
export const ComposeQuotedStatus: FC = () => { export const ComposeQuotedStatus: FC = () => {
const quotedStatusId = useAppSelector( const quotedStatusId = useAppSelector(
(state) => state.compose.get('quoted_status_id') as string | null, (state) => state.compose.get('quoted_status_id') as string | null,
); );
const isEditing = useAppSelector((state) => !!state.compose.get('id'));
const quote = useMemo( const quote = useMemo(
() => () =>
quotedStatusId quotedStatusId
@ -20,8 +22,17 @@ export const ComposeQuotedStatus: FC = () => {
: null, : null,
[quotedStatusId], [quotedStatusId],
); );
const dispatch = useAppDispatch();
const handleQuoteCancel = useCallback(() => {
dispatch(quoteComposeCancel());
}, [dispatch]);
if (!quote) { if (!quote) {
return null; return null;
} }
return <QuotedStatus quote={quote} contextType='compose' />; return (
<QuotedStatus
quote={quote}
onQuoteCancel={!isEditing ? handleQuoteCancel : undefined}
/>
);
}; };

View File

@ -0,0 +1,148 @@
import { useCallback, useMemo } from 'react';
import type { FC } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import classNames from 'classnames';
import { changeComposeVisibility } from '@/mastodon/actions/compose';
import { setComposeQuotePolicy } from '@/mastodon/actions/compose_typed';
import { openModal } from '@/mastodon/actions/modal';
import type { ApiQuotePolicy } from '@/mastodon/api_types/quotes';
import type { StatusVisibility } from '@/mastodon/api_types/statuses';
import { Icon } from '@/mastodon/components/icon';
import { useAppSelector, useAppDispatch } from '@/mastodon/store';
import { isFeatureEnabled } from '@/mastodon/utils/environment';
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
import LockIcon from '@/material-icons/400-24px/lock.svg?react';
import PublicIcon from '@/material-icons/400-24px/public.svg?react';
import QuietTimeIcon from '@/material-icons/400-24px/quiet_time.svg?react';
import type { VisibilityModalCallback } from '../../ui/components/visibility_modal';
import PrivacyDropdownContainer from '../containers/privacy_dropdown_container';
import { messages as privacyMessages } from './privacy_dropdown';
const messages = defineMessages({
anyone_quote: {
id: 'privacy.quote.anyone',
defaultMessage: '{visibility}, anyone can quote',
},
limited_quote: {
id: 'privacy.quote.limited',
defaultMessage: '{visibility}, quotes limited',
},
disabled_quote: {
id: 'privacy.quote.disabled',
defaultMessage: '{visibility}, quotes disabled',
},
});
interface PrivacyDropdownProps {
disabled?: boolean;
}
export const VisibilityButton: FC<PrivacyDropdownProps> = (props) => {
if (!isFeatureEnabled('outgoing_quotes')) {
return <PrivacyDropdownContainer {...props} />;
}
return <PrivacyModalButton {...props} />;
};
const visibilityOptions = {
public: {
icon: 'globe',
iconComponent: PublicIcon,
value: 'public',
text: privacyMessages.public_short,
},
unlisted: {
icon: 'unlock',
iconComponent: QuietTimeIcon,
value: 'unlisted',
text: privacyMessages.unlisted_short,
},
private: {
icon: 'lock',
iconComponent: LockIcon,
value: 'private',
text: privacyMessages.private_short,
},
direct: {
icon: 'at',
iconComponent: AlternateEmailIcon,
value: 'direct',
text: privacyMessages.direct_short,
},
};
const PrivacyModalButton: FC<PrivacyDropdownProps> = ({ disabled = false }) => {
const intl = useIntl();
const { visibility, quotePolicy } = useAppSelector((state) => ({
visibility: state.compose.get('privacy') as StatusVisibility,
quotePolicy: state.compose.get('quote_policy') as ApiQuotePolicy,
}));
const { icon, iconComponent } = useMemo(() => {
const option = visibilityOptions[visibility];
return { icon: option.icon, iconComponent: option.iconComponent };
}, [visibility]);
const text = useMemo(() => {
const visibilityText = intl.formatMessage(
visibilityOptions[visibility].text,
);
if (visibility === 'private' || visibility === 'direct') {
return visibilityText;
}
if (quotePolicy === 'nobody') {
return intl.formatMessage(messages.disabled_quote, {
visibility: visibilityText,
});
}
if (quotePolicy !== 'public') {
return intl.formatMessage(messages.limited_quote, {
visibility: visibilityText,
});
}
return intl.formatMessage(messages.anyone_quote, {
visibility: visibilityText,
});
}, [quotePolicy, visibility, intl]);
const dispatch = useAppDispatch();
const handleChange: VisibilityModalCallback = useCallback(
(newVisibility, newQuotePolicy) => {
if (newVisibility !== visibility) {
dispatch(changeComposeVisibility(newVisibility));
}
if (newQuotePolicy !== quotePolicy) {
dispatch(setComposeQuotePolicy(newQuotePolicy));
}
},
[dispatch, quotePolicy, visibility],
);
const handleOpen = useCallback(() => {
dispatch(
openModal({
modalType: 'COMPOSE_PRIVACY',
modalProps: { onChange: handleChange },
}),
);
}, [dispatch, handleChange]);
return (
<button
type='button'
title={intl.formatMessage(privacyMessages.change_privacy)}
onClick={handleOpen}
disabled={disabled}
className={classNames('dropdown-button')}
>
<Icon id={icon} icon={iconComponent} />
<span className='dropdown-button__label'>{text}</span>
</button>
);
};

View File

@ -3,23 +3,16 @@ import { PureComponent } from 'react';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg?react'; import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg?react';
import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react'; import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react'; import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react';
import StarIcon from '@/material-icons/400-24px/star-fill.svg?react'; import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
import StarBorderIcon from '@/material-icons/400-24px/star.svg?react'; import StarBorderIcon from '@/material-icons/400-24px/star.svg?react';
import RepeatActiveIcon from '@/svg-icons/repeat_active.svg?react';
import RepeatDisabledIcon from '@/svg-icons/repeat_disabled.svg?react';
import RepeatPrivateIcon from '@/svg-icons/repeat_private.svg?react';
import RepeatPrivateActiveIcon from '@/svg-icons/repeat_private_active.svg?react';
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
@ -27,6 +20,7 @@ import { IconButton } from '../../../components/icon_button';
import { Dropdown } from 'mastodon/components/dropdown_menu'; import { Dropdown } from 'mastodon/components/dropdown_menu';
import { me } from '../../../initial_state'; import { me } from '../../../initial_state';
import { isFeatureEnabled } from '@/mastodon/utils/environment'; import { isFeatureEnabled } from '@/mastodon/utils/environment';
import { ReblogButton } from '@/mastodon/components/status/reblog_button';
const messages = defineMessages({ const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' }, delete: { id: 'status.delete', defaultMessage: 'Delete' },
@ -35,10 +29,6 @@ const messages = defineMessages({
direct: { id: 'status.direct', defaultMessage: 'Privately mention @{name}' }, direct: { id: 'status.direct', defaultMessage: 'Privately mention @{name}' },
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
reply: { id: 'status.reply', defaultMessage: 'Reply' }, reply: { id: 'status.reply', defaultMessage: 'Reply' },
reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost with original visibility' },
cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' },
cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' },
favourite: { id: 'status.favourite', defaultMessage: 'Favorite' }, favourite: { id: 'status.favourite', defaultMessage: 'Favorite' },
removeFavourite: { id: 'status.remove_favourite', defaultMessage: 'Remove from favorites' }, removeFavourite: { id: 'status.remove_favourite', defaultMessage: 'Remove from favorites' },
bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' }, bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' },
@ -313,31 +303,15 @@ class ActionBar extends PureComponent {
replyIconComponent = ReplyAllIcon; replyIconComponent = ReplyAllIcon;
} }
const reblogPrivate = status.getIn(['account', 'id']) === me && status.get('visibility') === 'private';
let reblogTitle, reblogIconComponent;
if (status.get('reblogged')) {
reblogTitle = intl.formatMessage(messages.cancel_reblog_private);
reblogIconComponent = publicStatus ? RepeatActiveIcon : RepeatPrivateActiveIcon;
} else if (publicStatus) {
reblogTitle = intl.formatMessage(messages.reblog);
reblogIconComponent = RepeatIcon;
} else if (reblogPrivate) {
reblogTitle = intl.formatMessage(messages.reblog_private);
reblogIconComponent = RepeatPrivateIcon;
} else {
reblogTitle = intl.formatMessage(messages.cannot_reblog);
reblogIconComponent = RepeatDisabledIcon;
}
const bookmarkTitle = intl.formatMessage(status.get('bookmarked') ? messages.removeBookmark : messages.bookmark); const bookmarkTitle = intl.formatMessage(status.get('bookmarked') ? messages.removeBookmark : messages.bookmark);
const favouriteTitle = intl.formatMessage(status.get('favourited') ? messages.removeFavourite : messages.favourite); const favouriteTitle = intl.formatMessage(status.get('favourited') ? messages.removeFavourite : messages.favourite);
return ( return (
<div className='detailed-status__action-bar'> <div className='detailed-status__action-bar'>
<div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} iconComponent={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} /></div> <div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} iconComponent={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} /></div>
<div className='detailed-status__button'><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} /></div> <div className='detailed-status__button'>
<ReblogButton status={status} />
</div>
<div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get('favourited')} title={favouriteTitle} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} /></div> <div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get('favourited')} title={favouriteTitle} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} /></div>
<div className='detailed-status__button'><IconButton className='bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={bookmarkTitle} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} /></div> <div className='detailed-status__button'><IconButton className='bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={bookmarkTitle} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} /></div>

View File

@ -1,6 +1,6 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
@ -15,7 +15,6 @@ import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?reac
import { Hotkeys } from 'mastodon/components/hotkeys'; import { Hotkeys } from 'mastodon/components/hotkeys';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import { LoadingIndicator } from 'mastodon/components/loading_indicator'; import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import { TimelineHint } from 'mastodon/components/timeline_hint';
import ScrollContainer from 'mastodon/containers/scroll_container'; import ScrollContainer from 'mastodon/containers/scroll_container';
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error'; import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
@ -57,6 +56,7 @@ import {
translateStatus, translateStatus,
undoStatusTranslation, undoStatusTranslation,
} from '../../actions/statuses'; } from '../../actions/statuses';
import { setStatusQuotePolicy } from '../../actions/statuses_typed';
import ColumnHeader from '../../components/column_header'; import ColumnHeader from '../../components/column_header';
import { textForScreenReader, defaultMediaVisibility } from '../../components/status'; import { textForScreenReader, defaultMediaVisibility } from '../../components/status';
import { StatusQuoteManager } from '../../components/status_quoted'; import { StatusQuoteManager } from '../../components/status_quoted';
@ -266,8 +266,14 @@ class Status extends ImmutablePureComponent {
}; };
handleQuotePolicyChange = (status) => { handleQuotePolicyChange = (status) => {
const statusId = status.get('id');
const { dispatch } = this.props; const { dispatch } = this.props;
dispatch(openModal({ modalType: 'COMPOSE_PRIVACY', modalProps: { statusId: status.get('id') } })); const handleChange = (_, quotePolicy) => {
dispatch(
setStatusQuotePolicy({ policy: quotePolicy, statusId }),
);
}
dispatch(openModal({ modalType: 'COMPOSE_PRIVACY', modalProps: { statusId, onChange: handleChange } }));
}; };
handleEditClick = (status) => { handleEditClick = (status) => {

View File

@ -1,25 +1,31 @@
import { forwardRef, useCallback, useId, useMemo } from 'react'; import {
forwardRef,
useCallback,
useId,
useImperativeHandle,
useMemo,
useState,
} from 'react';
import type { FC } from 'react'; import type { FC } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { changeComposeVisibility } from '@/mastodon/actions/compose';
import { setStatusQuotePolicy } from '@/mastodon/actions/statuses_typed';
import type { ApiQuotePolicy } from '@/mastodon/api_types/quotes'; import type { ApiQuotePolicy } from '@/mastodon/api_types/quotes';
import { isQuotePolicy } from '@/mastodon/api_types/quotes'; import { isQuotePolicy } from '@/mastodon/api_types/quotes';
import { isStatusVisibility } from '@/mastodon/api_types/statuses';
import type { StatusVisibility } from '@/mastodon/api_types/statuses'; import type { StatusVisibility } from '@/mastodon/api_types/statuses';
import { Dropdown } from '@/mastodon/components/dropdown'; import { Dropdown } from '@/mastodon/components/dropdown';
import type { SelectItem } from '@/mastodon/components/dropdown_selector'; import type { SelectItem } from '@/mastodon/components/dropdown_selector';
import { IconButton } from '@/mastodon/components/icon_button'; import { IconButton } from '@/mastodon/components/icon_button';
import { messages as privacyMessages } from '@/mastodon/features/compose/components/privacy_dropdown'; import { messages as privacyMessages } from '@/mastodon/features/compose/components/privacy_dropdown';
import { import { createAppSelector, useAppSelector } from '@/mastodon/store';
createAppSelector, import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
useAppDispatch,
useAppSelector,
} from '@/mastodon/store';
import CloseIcon from '@/material-icons/400-24px/close.svg?react'; import CloseIcon from '@/material-icons/400-24px/close.svg?react';
import LockIcon from '@/material-icons/400-24px/lock.svg?react';
import PublicIcon from '@/material-icons/400-24px/public.svg?react';
import QuietTimeIcon from '@/material-icons/400-24px/quiet_time.svg?react';
import type { BaseConfirmationModalProps } from './confirmation_modals/confirmation_modal'; import type { BaseConfirmationModalProps } from './confirmation_modals/confirmation_modal';
@ -43,13 +49,26 @@ const messages = defineMessages({
}, },
}); });
export type VisibilityModalCallback = (
visibility: StatusVisibility,
quotePolicy: ApiQuotePolicy,
) => void;
interface VisibilityModalProps extends BaseConfirmationModalProps { interface VisibilityModalProps extends BaseConfirmationModalProps {
statusId: string; statusId?: string;
onChange: VisibilityModalCallback;
} }
const selectStatusPolicy = createAppSelector( const selectStatusPolicy = createAppSelector(
[(state) => state.statuses, (_state, statusId: string) => statusId], [
(statuses, statusId) => { (state) => state.statuses,
(_state, statusId?: string) => statusId,
(state) => state.compose.get('quote_policy') as ApiQuotePolicy,
],
(statuses, statusId, composeQuotePolicy) => {
if (!statusId) {
return composeQuotePolicy;
}
const status = statuses.get(statusId); const status = statuses.get(statusId);
if (!status) { if (!status) {
return 'public'; return 'public';
@ -77,24 +96,25 @@ const selectStatusPolicy = createAppSelector(
); );
export const VisibilityModal: FC<VisibilityModalProps> = forwardRef( export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
// eslint-disable-next-line @typescript-eslint/no-unused-vars ({ onClose, onChange, statusId }, ref) => {
({ onClose, statusId }, ref) => {
const intl = useIntl(); const intl = useIntl();
const currentVisibility = useAppSelector( const currentVisibility = useAppSelector((state) =>
(state) => statusId
(state.statuses.getIn([statusId, 'visibility'], 'public') as ? ((state.statuses.getIn([statusId, 'visibility'], 'public') as
| StatusVisibility | StatusVisibility
| undefined) ?? 'public', | undefined) ?? 'public')
: (state.compose.get('privacy') as StatusVisibility),
); );
const currentQuotePolicy = useAppSelector((state) => const currentQuotePolicy = useAppSelector((state) =>
selectStatusPolicy(state, statusId), selectStatusPolicy(state, statusId),
); );
const [visibility, setVisibility] = useState(currentVisibility);
const [quotePolicy, setQuotePolicy] = useState(currentQuotePolicy);
const disableVisibility = !!statusId;
const disableQuotePolicy = const disableQuotePolicy =
currentVisibility === 'private' || currentVisibility === 'direct'; visibility === 'private' || visibility === 'direct';
const isSaving = useAppSelector(
(state) =>
state.statuses.getIn([statusId, 'isSavingQuotePolicy']) === true,
);
const visibilityItems = useMemo<SelectItem<StatusVisibility>[]>( const visibilityItems = useMemo<SelectItem<StatusVisibility>[]>(
() => [ () => [
@ -102,21 +122,30 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
value: 'public', value: 'public',
text: intl.formatMessage(privacyMessages.public_short), text: intl.formatMessage(privacyMessages.public_short),
meta: intl.formatMessage(privacyMessages.public_long), meta: intl.formatMessage(privacyMessages.public_long),
icon: 'globe',
iconComponent: PublicIcon,
}, },
{ {
value: 'unlisted', value: 'unlisted',
text: intl.formatMessage(privacyMessages.unlisted_short), text: intl.formatMessage(privacyMessages.unlisted_short),
meta: intl.formatMessage(privacyMessages.unlisted_long), meta: intl.formatMessage(privacyMessages.unlisted_long),
extra: intl.formatMessage(privacyMessages.unlisted_extra),
icon: 'unlock',
iconComponent: QuietTimeIcon,
}, },
{ {
value: 'private', value: 'private',
text: intl.formatMessage(privacyMessages.private_short), text: intl.formatMessage(privacyMessages.private_short),
meta: intl.formatMessage(privacyMessages.private_long), meta: intl.formatMessage(privacyMessages.private_long),
icon: 'lock',
iconComponent: LockIcon,
}, },
{ {
value: 'direct', value: 'direct',
text: intl.formatMessage(privacyMessages.direct_short), text: intl.formatMessage(privacyMessages.direct_short),
meta: intl.formatMessage(privacyMessages.direct_long), meta: intl.formatMessage(privacyMessages.direct_long),
icon: 'at',
iconComponent: AlternateEmailIcon,
}, },
], ],
[intl], [intl],
@ -133,24 +162,27 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
[intl], [intl],
); );
const dispatch = useAppDispatch(); const handleVisibilityChange = useCallback((value: string) => {
const handleVisibilityChange = useCallback( if (isStatusVisibility(value)) {
(value: string) => { setVisibility(value);
// Published statuses cannot change visibility. }
if (statusId) { }, []);
return; const handleQuotePolicyChange = useCallback((value: string) => {
} if (isQuotePolicy(value)) {
dispatch(changeComposeVisibility(value)); setQuotePolicy(value);
}, }
[dispatch, statusId], }, []);
);
const handleQuotePolicyChange = useCallback( // Save on close
(value: string) => { useImperativeHandle(
if (isQuotePolicy(value) && !disableQuotePolicy) { ref,
void dispatch(setStatusQuotePolicy({ policy: value, statusId })); () => ({
} getCloseConfirmationMessage() {
}, onChange(visibility, quotePolicy);
[disableQuotePolicy, dispatch, statusId], return null;
},
}),
[onChange, quotePolicy, visibility],
); );
const privacyDropdownId = useId(); const privacyDropdownId = useId();
@ -192,7 +224,7 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
<label <label
htmlFor={privacyDropdownId} htmlFor={privacyDropdownId}
className={classNames('visibility-dropdown__label', { className={classNames('visibility-dropdown__label', {
disabled: isSaving || !!statusId, disabled: disableVisibility,
})} })}
> >
<FormattedMessage <FormattedMessage
@ -203,10 +235,10 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
<Dropdown <Dropdown
items={visibilityItems} items={visibilityItems}
classPrefix='visibility-dropdown' classPrefix='visibility-dropdown'
current={currentVisibility} current={visibility}
onChange={handleVisibilityChange} onChange={handleVisibilityChange}
title={intl.formatMessage(privacyMessages.change_privacy)} title={intl.formatMessage(privacyMessages.change_privacy)}
disabled={isSaving || !!statusId} disabled={disableVisibility}
id={privacyDropdownId} id={privacyDropdownId}
/> />
{!!statusId && ( {!!statusId && (
@ -222,7 +254,7 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
<label <label
htmlFor={quoteDropdownId} htmlFor={quoteDropdownId}
className={classNames('visibility-dropdown__label', { className={classNames('visibility-dropdown__label', {
disabled: disableQuotePolicy || isSaving, disabled: disableQuotePolicy,
})} })}
> >
<FormattedMessage <FormattedMessage
@ -234,15 +266,12 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
items={quoteItems} items={quoteItems}
onChange={handleQuotePolicyChange} onChange={handleQuotePolicyChange}
classPrefix='visibility-dropdown' classPrefix='visibility-dropdown'
current={currentQuotePolicy} current={quotePolicy}
title={intl.formatMessage(messages.buttonTitle)} title={intl.formatMessage(messages.buttonTitle)}
disabled={disableQuotePolicy || isSaving} disabled={disableQuotePolicy}
id={quoteDropdownId} id={quoteDropdownId}
/> />
<QuotePolicyHelper <QuotePolicyHelper policy={quotePolicy} visibility={visibility} />
policy={currentQuotePolicy}
visibility={currentVisibility}
/>
</label> </label>
</div> </div>
</div> </div>

View File

@ -836,22 +836,24 @@
"search_results.see_all": "Праглядзець усе", "search_results.see_all": "Праглядзець усе",
"search_results.statuses": "Допісы", "search_results.statuses": "Допісы",
"search_results.title": "Шукаць \"{q}\"", "search_results.title": "Шукаць \"{q}\"",
"server_banner.about_active_users": "Людзі, якія карыстаюцца гэтым сервера на працягу апошніх 30 дзён (Штомесячна Актыўныя Карыстальнікі)", "server_banner.about_active_users": "Людзі, якія карысталіся гэтым серверам на працягу апошніх 30 дзён (штомесячна актыўныя карыстальнікі)",
"server_banner.active_users": "актыўныя карыстальнікі", "server_banner.active_users": "актыўныя карыстальнікі",
"server_banner.administered_by": "Адміністратар:", "server_banner.administered_by": "Адміністратар:",
"server_banner.is_one_of_many": "{domain} - гэта адзін з многіх незалежных сервераў Mastodon, які Вы можаце выкарыстоўваць для ўдзелу ў федэральным сусвеце.", "server_banner.is_one_of_many": "{domain} - гэта адзін з многіх незалежных сервераў Mastodon, які Вы можаце выкарыстоўваць для ўдзелу ў федэральным сусвеце.",
"server_banner.server_stats": "Статыстыка сервера:", "server_banner.server_stats": "Статыстыка сервера:",
"sign_in_banner.create_account": "Стварыць уліковы запіс", "sign_in_banner.create_account": "Стварыць уліковы запіс",
"sign_in_banner.follow_anyone": "Падпісвайцеся на каго захочаце ва ўсім федэральным сусвеце і глядзіце ўсё ў храналагічным парадку. Ніякіх алгарытмаў, рэкламы або клікбэйту.", "sign_in_banner.follow_anyone": "Падпісвайцеся на каго захочаце ва ўсім федэральным сусвеце і глядзіце ўсё ў храналагічным парадку. Ніякіх алгарытмаў, рэкламы або клікбэйту.",
"sign_in_banner.mastodon_is": "Mastodon - лепшы спосаб быць у курсе ўсяго, што адбываецца.", "sign_in_banner.mastodon_is": "Mastodon - найлепшы спосаб быць у курсе ўсяго, што адбываецца.",
"sign_in_banner.sign_in": "Увайсці", "sign_in_banner.sign_in": "Увайсці",
"sign_in_banner.sso_redirect": "Уваход ці рэгістрацыя", "sign_in_banner.sso_redirect": "Уваход ці рэгістрацыя",
"status.admin_account": "Адкрыць інтэрфейс мадэратара для @{name}", "status.admin_account": "Адкрыць інтэрфейс мадэратара для @{name}",
"status.admin_domain": "Адкрыць інтэрфейс мадэратара для {domain}", "status.admin_domain": "Адкрыць інтэрфейс мадэратара для {domain}",
"status.admin_status": "Адкрыць гэты допіс у інтэрфейсе мадэрацыі", "status.admin_status": "Адкрыць гэты допіс у інтэрфейсе мадэрацыі",
"status.all_disabled": "Пашырэнні і цытаванні адключаны",
"status.block": "Заблакаваць @{name}", "status.block": "Заблакаваць @{name}",
"status.bookmark": "Дадаць закладку", "status.bookmark": "Дадаць закладку",
"status.cancel_reblog_private": "Прыбраць", "status.cancel_reblog_private": "Прыбраць",
"status.cannot_quote": "Аўтар допісу адключыў цытаванне",
"status.cannot_reblog": "Гэты допіс нельга пашырыць", "status.cannot_reblog": "Гэты допіс нельга пашырыць",
"status.context.load_new_replies": "Даступныя новыя адказы", "status.context.load_new_replies": "Даступныя новыя адказы",
"status.context.loading": "Правяраюцца новыя адказы", "status.context.loading": "Правяраюцца новыя адказы",
@ -880,6 +882,8 @@
"status.mute_conversation": "Ігнараваць размову", "status.mute_conversation": "Ігнараваць размову",
"status.open": "Разгарнуць гэты допіс", "status.open": "Разгарнуць гэты допіс",
"status.pin": "Замацаваць у профілі", "status.pin": "Замацаваць у профілі",
"status.quote": "Цытаваць",
"status.quote.cancel": "Адмяніць цытаванне",
"status.quote_error.filtered": "Схавана адным з Вашых фільтраў", "status.quote_error.filtered": "Схавана адным з Вашых фільтраў",
"status.quote_error.not_available": "Допіс недаступны", "status.quote_error.not_available": "Допіс недаступны",
"status.quote_error.pending_approval": "Допіс чакае пацвярджэння", "status.quote_error.pending_approval": "Допіс чакае пацвярджэння",
@ -887,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Цытаваны допіс чакае пацвярджэння? Захоўвайце спакой", "status.quote_error.pending_approval_popout.title": "Цытаваны допіс чакае пацвярджэння? Захоўвайце спакой",
"status.quote_policy_change": "Змяніць, хто можа цытаваць", "status.quote_policy_change": "Змяніць, хто можа цытаваць",
"status.quote_post_author": "Цытаваў допіс @{name}", "status.quote_post_author": "Цытаваў допіс @{name}",
"status.quote_private": "Прыватныя допісы нельга цытаваць",
"status.read_more": "Чытаць болей", "status.read_more": "Чытаць болей",
"status.reblog": "Пашырыць", "status.reblog": "Пашырыць",
"status.reblog_private": "Пашырыць з першапачатковай бачнасцю", "status.reblog_private": "Пашырыць з першапачатковай бачнасцю",

View File

@ -848,9 +848,11 @@
"status.admin_account": "Obre la interfície de moderació per a @{name}", "status.admin_account": "Obre la interfície de moderació per a @{name}",
"status.admin_domain": "Obre la interfície de moderació per a @{domain}", "status.admin_domain": "Obre la interfície de moderació per a @{domain}",
"status.admin_status": "Obre aquest tut a la interfície de moderació", "status.admin_status": "Obre aquest tut a la interfície de moderació",
"status.all_disabled": "S'han deshabilitat impulsos i cites",
"status.block": "Bloca @{name}", "status.block": "Bloca @{name}",
"status.bookmark": "Marca", "status.bookmark": "Marca",
"status.cancel_reblog_private": "Desfés l'impuls", "status.cancel_reblog_private": "Desfés l'impuls",
"status.cannot_quote": "L'autor no permet que se citi aquesta publicació",
"status.cannot_reblog": "No es pot impulsar aquest tut", "status.cannot_reblog": "No es pot impulsar aquest tut",
"status.context.load_new_replies": "Hi ha respostes noves", "status.context.load_new_replies": "Hi ha respostes noves",
"status.context.loading": "Comprovació de més respostes", "status.context.loading": "Comprovació de més respostes",
@ -879,6 +881,7 @@
"status.mute_conversation": "Silencia la conversa", "status.mute_conversation": "Silencia la conversa",
"status.open": "Amplia el tut", "status.open": "Amplia el tut",
"status.pin": "Fixa en el perfil", "status.pin": "Fixa en el perfil",
"status.quote": "Cita",
"status.quote.cancel": "Canceŀlar la citació", "status.quote.cancel": "Canceŀlar la citació",
"status.quote_error.filtered": "No es mostra a causa d'un dels vostres filtres", "status.quote_error.filtered": "No es mostra a causa d'un dels vostres filtres",
"status.quote_error.not_available": "Publicació no disponible", "status.quote_error.not_available": "Publicació no disponible",
@ -887,6 +890,7 @@
"status.quote_error.pending_approval_popout.title": "Publicació pendent? Mantinguem la calma", "status.quote_error.pending_approval_popout.title": "Publicació pendent? Mantinguem la calma",
"status.quote_policy_change": "Canvieu qui us pot citar", "status.quote_policy_change": "Canvieu qui us pot citar",
"status.quote_post_author": "S'ha citat una publicació de @{name}", "status.quote_post_author": "S'ha citat una publicació de @{name}",
"status.quote_private": "No es poden citar les publicacions privades",
"status.read_more": "Més informació", "status.read_more": "Més informació",
"status.reblog": "Impulsa", "status.reblog": "Impulsa",
"status.reblog_private": "Impulsa amb la visibilitat original", "status.reblog_private": "Impulsa amb la visibilitat original",

View File

@ -849,9 +849,11 @@
"status.admin_account": "Otevřít moderátorské rozhraní pro @{name}", "status.admin_account": "Otevřít moderátorské rozhraní pro @{name}",
"status.admin_domain": "Otevřít moderátorské rozhraní pro {domain}", "status.admin_domain": "Otevřít moderátorské rozhraní pro {domain}",
"status.admin_status": "Otevřít tento příspěvek v moderátorském rozhraní", "status.admin_status": "Otevřít tento příspěvek v moderátorském rozhraní",
"status.all_disabled": "Boosty a citace jsou zakázány",
"status.block": "Blokovat @{name}", "status.block": "Blokovat @{name}",
"status.bookmark": "Přidat do záložek", "status.bookmark": "Přidat do záložek",
"status.cancel_reblog_private": "Zrušit boostnutí", "status.cancel_reblog_private": "Zrušit boostnutí",
"status.cannot_quote": "Autor zakázal citování tohoto příspěvku",
"status.cannot_reblog": "Tento příspěvek nemůže být boostnutý", "status.cannot_reblog": "Tento příspěvek nemůže být boostnutý",
"status.context.load_new_replies": "K dispozici jsou nové odpovědi", "status.context.load_new_replies": "K dispozici jsou nové odpovědi",
"status.context.loading": "Hledání dalších odpovědí", "status.context.loading": "Hledání dalších odpovědí",
@ -880,6 +882,8 @@
"status.mute_conversation": "Skrýt konverzaci", "status.mute_conversation": "Skrýt konverzaci",
"status.open": "Rozbalit tento příspěvek", "status.open": "Rozbalit tento příspěvek",
"status.pin": "Připnout na profil", "status.pin": "Připnout na profil",
"status.quote": "Citovat",
"status.quote.cancel": "Zrušit citování",
"status.quote_error.filtered": "Skryté kvůli jednomu z vašich filtrů", "status.quote_error.filtered": "Skryté kvůli jednomu z vašich filtrů",
"status.quote_error.not_available": "Příspěvek není dostupný", "status.quote_error.not_available": "Příspěvek není dostupný",
"status.quote_error.pending_approval": "Příspěvek čeká na schválení", "status.quote_error.pending_approval": "Příspěvek čeká na schválení",
@ -887,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Příspěvek čeká na schválení? Buďte klidní", "status.quote_error.pending_approval_popout.title": "Příspěvek čeká na schválení? Buďte klidní",
"status.quote_policy_change": "Změňte, kdo může citovat", "status.quote_policy_change": "Změňte, kdo může citovat",
"status.quote_post_author": "Citovali příspěvek od @{name}", "status.quote_post_author": "Citovali příspěvek od @{name}",
"status.quote_private": "Soukromé příspěvky nelze citovat",
"status.read_more": "Číst více", "status.read_more": "Číst více",
"status.reblog": "Boostnout", "status.reblog": "Boostnout",
"status.reblog_private": "Boostnout s původní viditelností", "status.reblog_private": "Boostnout s původní viditelností",

View File

@ -849,9 +849,11 @@
"status.admin_account": "@{name} moderieren", "status.admin_account": "@{name} moderieren",
"status.admin_domain": "{domain} moderieren", "status.admin_domain": "{domain} moderieren",
"status.admin_status": "Beitrag moderieren", "status.admin_status": "Beitrag moderieren",
"status.all_disabled": "Teilen und Zitieren von Beiträgen ist deaktiviert",
"status.block": "@{name} blockieren", "status.block": "@{name} blockieren",
"status.bookmark": "Lesezeichen setzen", "status.bookmark": "Lesezeichen setzen",
"status.cancel_reblog_private": "Beitrag nicht mehr teilen", "status.cancel_reblog_private": "Beitrag nicht mehr teilen",
"status.cannot_quote": "Autor*in hat das Zitieren dieses Beitrags deaktiviert",
"status.cannot_reblog": "Dieser Beitrag kann nicht geteilt werden", "status.cannot_reblog": "Dieser Beitrag kann nicht geteilt werden",
"status.context.load_new_replies": "Neue Antworten verfügbar", "status.context.load_new_replies": "Neue Antworten verfügbar",
"status.context.loading": "Weitere Antworten werden abgerufen", "status.context.loading": "Weitere Antworten werden abgerufen",
@ -880,6 +882,7 @@
"status.mute_conversation": "Unterhaltung stummschalten", "status.mute_conversation": "Unterhaltung stummschalten",
"status.open": "Beitrag öffnen", "status.open": "Beitrag öffnen",
"status.pin": "Im Profil anheften", "status.pin": "Im Profil anheften",
"status.quote": "Zitieren",
"status.quote.cancel": "Zitat abbrechen", "status.quote.cancel": "Zitat abbrechen",
"status.quote_error.filtered": "Ausgeblendet wegen eines deiner Filter", "status.quote_error.filtered": "Ausgeblendet wegen eines deiner Filter",
"status.quote_error.not_available": "Beitrag nicht verfügbar", "status.quote_error.not_available": "Beitrag nicht verfügbar",
@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Zitierter Beitrag noch nicht freigegeben? Immer mit der Ruhe", "status.quote_error.pending_approval_popout.title": "Zitierter Beitrag noch nicht freigegeben? Immer mit der Ruhe",
"status.quote_policy_change": "Ändern, wer zitieren darf", "status.quote_policy_change": "Ändern, wer zitieren darf",
"status.quote_post_author": "Zitierte einen Beitrag von @{name}", "status.quote_post_author": "Zitierte einen Beitrag von @{name}",
"status.quote_private": "Private Beiträge können nicht zitiert werden",
"status.read_more": "Gesamten Beitrag anschauen", "status.read_more": "Gesamten Beitrag anschauen",
"status.reblog": "Teilen", "status.reblog": "Teilen",
"status.reblog_private": "Mit der ursprünglichen Zielgruppe teilen", "status.reblog_private": "Mit der ursprünglichen Zielgruppe teilen",

View File

@ -849,9 +849,11 @@
"status.admin_account": "Άνοιγμα διεπαφής συντονισμού για τον/την @{name}", "status.admin_account": "Άνοιγμα διεπαφής συντονισμού για τον/την @{name}",
"status.admin_domain": "Άνοιγμα λειτουργίας διαμεσολάβησης για {domain}", "status.admin_domain": "Άνοιγμα λειτουργίας διαμεσολάβησης για {domain}",
"status.admin_status": "Άνοιγμα αυτής της ανάρτησης σε διεπαφή συντονισμού", "status.admin_status": "Άνοιγμα αυτής της ανάρτησης σε διεπαφή συντονισμού",
"status.all_disabled": "Ενισχύσεις και παραθέσεις είναι απενεργοποιημένες",
"status.block": "Αποκλεισμός @{name}", "status.block": "Αποκλεισμός @{name}",
"status.bookmark": "Σελιδοδείκτης", "status.bookmark": "Σελιδοδείκτης",
"status.cancel_reblog_private": "Ακύρωση ενίσχυσης", "status.cancel_reblog_private": "Ακύρωση ενίσχυσης",
"status.cannot_quote": "Ο συντάκτης έχει απενεργοποιήσει την παράθεση σε αυτή την ανάρτηση",
"status.cannot_reblog": "Αυτή η ανάρτηση δεν μπορεί να ενισχυθεί", "status.cannot_reblog": "Αυτή η ανάρτηση δεν μπορεί να ενισχυθεί",
"status.context.load_new_replies": "Νέες απαντήσεις διαθέσιμες", "status.context.load_new_replies": "Νέες απαντήσεις διαθέσιμες",
"status.context.loading": "Γίνεται έλεγχος για περισσότερες απαντήσεις", "status.context.loading": "Γίνεται έλεγχος για περισσότερες απαντήσεις",
@ -880,6 +882,8 @@
"status.mute_conversation": "Σίγαση συνομιλίας", "status.mute_conversation": "Σίγαση συνομιλίας",
"status.open": "Επέκταση ανάρτησης", "status.open": "Επέκταση ανάρτησης",
"status.pin": "Καρφίτσωσε στο προφίλ", "status.pin": "Καρφίτσωσε στο προφίλ",
"status.quote": "Παράθεση",
"status.quote.cancel": "Ακύρωση παράθεσης",
"status.quote_error.filtered": "Κρυφό λόγω ενός από τα φίλτρα σου", "status.quote_error.filtered": "Κρυφό λόγω ενός από τα φίλτρα σου",
"status.quote_error.not_available": "Ανάρτηση μη διαθέσιμη", "status.quote_error.not_available": "Ανάρτηση μη διαθέσιμη",
"status.quote_error.pending_approval": "Ανάρτηση σε αναμονή", "status.quote_error.pending_approval": "Ανάρτηση σε αναμονή",
@ -887,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Παράθεση σε εκκρεμότητα; Μείνετε ψύχραιμοι", "status.quote_error.pending_approval_popout.title": "Παράθεση σε εκκρεμότητα; Μείνετε ψύχραιμοι",
"status.quote_policy_change": "Αλλάξτε ποιός μπορεί να κάνει παράθεση", "status.quote_policy_change": "Αλλάξτε ποιός μπορεί να κάνει παράθεση",
"status.quote_post_author": "Παρατίθεται μια ανάρτηση από @{name}", "status.quote_post_author": "Παρατίθεται μια ανάρτηση από @{name}",
"status.quote_private": "Ιδιωτικές αναρτήσεις δεν μπορούν να παρατεθούν",
"status.read_more": "Διάβασε περισότερα", "status.read_more": "Διάβασε περισότερα",
"status.reblog": "Ενίσχυση", "status.reblog": "Ενίσχυση",
"status.reblog_private": "Ενίσχυση με αρχική ορατότητα", "status.reblog_private": "Ενίσχυση με αρχική ορατότητα",

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Followers", "privacy.private.short": "Followers",
"privacy.public.long": "Anyone on and off Mastodon", "privacy.public.long": "Anyone on and off Mastodon",
"privacy.public.short": "Public", "privacy.public.short": "Public",
"privacy.quote.anyone": "{visibility}, anyone can quote",
"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.", "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.",
"privacy.unlisted.long": "Fewer algorithmic fanfares", "privacy.unlisted.long": "Fewer algorithmic fanfares",
"privacy.unlisted.short": "Quiet public", "privacy.unlisted.short": "Quiet public",
"privacy_policy.last_updated": "Last updated {date}", "privacy_policy.last_updated": "Last updated {date}",
"privacy_policy.title": "Privacy Policy", "privacy_policy.title": "Privacy Policy",
"quote_error.poll": "Quoting is not allowed with polls.",
"quote_error.quote": "Only one quote at a time is allowed.",
"quote_error.unauthorized": "You are not authorized to quote this post.",
"quote_error.upload": "Quoting is not allowed with media attachments.",
"recommended": "Recommended", "recommended": "Recommended",
"refresh": "Refresh", "refresh": "Refresh",
"regeneration_indicator.please_stand_by": "Please stand by.", "regeneration_indicator.please_stand_by": "Please stand by.",
@ -849,9 +856,11 @@
"status.admin_account": "Open moderation interface for @{name}", "status.admin_account": "Open moderation interface for @{name}",
"status.admin_domain": "Open moderation interface for {domain}", "status.admin_domain": "Open moderation interface for {domain}",
"status.admin_status": "Open this post in the moderation interface", "status.admin_status": "Open this post in the moderation interface",
"status.all_disabled": "Boosts and quotes are disabled",
"status.block": "Block @{name}", "status.block": "Block @{name}",
"status.bookmark": "Bookmark", "status.bookmark": "Bookmark",
"status.cancel_reblog_private": "Unboost", "status.cancel_reblog_private": "Unboost",
"status.cannot_quote": "Author has disabled quoting on this post",
"status.cannot_reblog": "This post cannot be boosted", "status.cannot_reblog": "This post cannot be boosted",
"status.context.load_new_replies": "New replies available", "status.context.load_new_replies": "New replies available",
"status.context.loading": "Checking for more replies", "status.context.loading": "Checking for more replies",
@ -880,6 +889,7 @@
"status.mute_conversation": "Mute conversation", "status.mute_conversation": "Mute conversation",
"status.open": "Expand this post", "status.open": "Expand this post",
"status.pin": "Pin on profile", "status.pin": "Pin on profile",
"status.quote": "Quote",
"status.quote.cancel": "Cancel quote", "status.quote.cancel": "Cancel quote",
"status.quote_error.filtered": "Hidden due to one of your filters", "status.quote_error.filtered": "Hidden due to one of your filters",
"status.quote_error.not_available": "Post unavailable", "status.quote_error.not_available": "Post unavailable",
@ -888,6 +898,7 @@
"status.quote_error.pending_approval_popout.title": "Pending quote? Remain calm", "status.quote_error.pending_approval_popout.title": "Pending quote? Remain calm",
"status.quote_policy_change": "Change who can quote", "status.quote_policy_change": "Change who can quote",
"status.quote_post_author": "Quoted a post by @{name}", "status.quote_post_author": "Quoted a post by @{name}",
"status.quote_private": "Private posts cannot be quoted",
"status.read_more": "Read more", "status.read_more": "Read more",
"status.reblog": "Boost", "status.reblog": "Boost",
"status.reblog_private": "Boost with original visibility", "status.reblog_private": "Boost with original visibility",
@ -940,6 +951,7 @@
"upload_button.label": "Add images, a video or an audio file", "upload_button.label": "Add images, a video or an audio file",
"upload_error.limit": "File upload limit exceeded.", "upload_error.limit": "File upload limit exceeded.",
"upload_error.poll": "File upload not allowed with polls.", "upload_error.poll": "File upload not allowed with polls.",
"upload_error.quote": "File upload not allowed with quotes.",
"upload_form.drag_and_drop.instructions": "To pick up a media attachment, press space or enter. While dragging, use the arrow keys to move the media attachment in any given direction. Press space or enter again to drop the media attachment in its new position, or press escape to cancel.", "upload_form.drag_and_drop.instructions": "To pick up a media attachment, press space or enter. While dragging, use the arrow keys to move the media attachment in any given direction. Press space or enter again to drop the media attachment in its new position, or press escape to cancel.",
"upload_form.drag_and_drop.on_drag_cancel": "Dragging was cancelled. Media attachment {item} was dropped.", "upload_form.drag_and_drop.on_drag_cancel": "Dragging was cancelled. Media attachment {item} was dropped.",
"upload_form.drag_and_drop.on_drag_end": "Media attachment {item} was dropped.", "upload_form.drag_and_drop.on_drag_end": "Media attachment {item} was dropped.",

View File

@ -568,6 +568,8 @@
"navigation_bar.preferences": "Preferoj", "navigation_bar.preferences": "Preferoj",
"navigation_bar.privacy_and_reach": "Privateco kaj atingo", "navigation_bar.privacy_and_reach": "Privateco kaj atingo",
"navigation_bar.search": "Serĉi", "navigation_bar.search": "Serĉi",
"navigation_panel.expand_followed_tags": "Malfermi la menuon de sekvataj haŝetikedoj",
"navigation_panel.expand_lists": "Malfermi la listmenuon",
"not_signed_in_indicator.not_signed_in": "Necesas saluti por aliri tiun rimedon.", "not_signed_in_indicator.not_signed_in": "Necesas saluti por aliri tiun rimedon.",
"notification.admin.report": "{name} raportis {target}", "notification.admin.report": "{name} raportis {target}",
"notification.admin.report_account": "{name} raportis {count, plural, one {afiŝon} other {# afiŝojn}} de {target} por {category}", "notification.admin.report_account": "{name} raportis {count, plural, one {afiŝon} other {# afiŝojn}} de {target} por {category}",
@ -837,6 +839,7 @@
"status.block": "Bloki @{name}", "status.block": "Bloki @{name}",
"status.bookmark": "Aldoni al la legosignoj", "status.bookmark": "Aldoni al la legosignoj",
"status.cancel_reblog_private": "Ne plu diskonigi", "status.cancel_reblog_private": "Ne plu diskonigi",
"status.cannot_quote": "La aŭtoro malŝaltis citadon en ĉi tiu afiŝo",
"status.cannot_reblog": "Ĉi tiun afiŝon ne eblas diskonigi", "status.cannot_reblog": "Ĉi tiun afiŝon ne eblas diskonigi",
"status.context.load_new_replies": "Disponeblaj novaj respondoj", "status.context.load_new_replies": "Disponeblaj novaj respondoj",
"status.context.loading": "Serĉante pliajn respondojn", "status.context.loading": "Serĉante pliajn respondojn",
@ -865,9 +868,16 @@
"status.mute_conversation": "Silentigi konversacion", "status.mute_conversation": "Silentigi konversacion",
"status.open": "Pligrandigu ĉi tiun afiŝon", "status.open": "Pligrandigu ĉi tiun afiŝon",
"status.pin": "Alpingli al la profilo", "status.pin": "Alpingli al la profilo",
"status.quote": "Citaĵo",
"status.quote.cancel": "Nuligi citaĵon",
"status.quote_error.filtered": "Kaŝita pro unu el viaj filtriloj",
"status.quote_error.not_available": "Afiŝo ne disponebla", "status.quote_error.not_available": "Afiŝo ne disponebla",
"status.quote_error.pending_approval": "Pritraktata afiŝo", "status.quote_error.pending_approval": "Pritraktata afiŝo",
"status.quote_error.pending_approval_popout.body": "Citaĵoj diskonigitaj tra la Fediverso povas bezoni tempon por montriĝi, ĉar malsamaj serviloj havas malsamajn protokolojn.",
"status.quote_error.pending_approval_popout.title": "Ĉu pritraktata citaĵo? Restu trankvila", "status.quote_error.pending_approval_popout.title": "Ĉu pritraktata citaĵo? Restu trankvila",
"status.quote_policy_change": "Ŝanĝi kiu povas citi",
"status.quote_post_author": "Citis afiŝon de @{name}",
"status.quote_private": "Privataj afiŝoj ne povas esti cititaj",
"status.read_more": "Legi pli", "status.read_more": "Legi pli",
"status.reblog": "Diskonigi", "status.reblog": "Diskonigi",
"status.reblog_private": "Diskonigi kun la sama videbleco", "status.reblog_private": "Diskonigi kun la sama videbleco",
@ -882,6 +892,7 @@
"status.reply": "Respondi", "status.reply": "Respondi",
"status.replyAll": "Respondi al la fadeno", "status.replyAll": "Respondi al la fadeno",
"status.report": "Raporti @{name}", "status.report": "Raporti @{name}",
"status.revoke_quote": "Forigu mian afiŝon el la afiŝo de @{name}",
"status.sensitive_warning": "Tikla enhavo", "status.sensitive_warning": "Tikla enhavo",
"status.share": "Kundividi", "status.share": "Kundividi",
"status.show_less_all": "Montri malpli ĉiun", "status.show_less_all": "Montri malpli ĉiun",

View File

@ -849,9 +849,11 @@
"status.admin_account": "Abrir interface de moderación para @{name}", "status.admin_account": "Abrir interface de moderación para @{name}",
"status.admin_domain": "Abrir interface de moderación para {domain}", "status.admin_domain": "Abrir interface de moderación para {domain}",
"status.admin_status": "Abrir este mensaje en la interface de moderación", "status.admin_status": "Abrir este mensaje en la interface de moderación",
"status.all_disabled": "Las adhesiones y citas están deshabilitadas",
"status.block": "Bloquear a @{name}", "status.block": "Bloquear a @{name}",
"status.bookmark": "Marcar", "status.bookmark": "Marcar",
"status.cancel_reblog_private": "Quitar adhesión", "status.cancel_reblog_private": "Quitar adhesión",
"status.cannot_quote": "El autor deshabilitó las citas en este mensaje",
"status.cannot_reblog": "No se puede adherir a este mensaje", "status.cannot_reblog": "No se puede adherir a este mensaje",
"status.context.load_new_replies": "Hay nuevas respuestas", "status.context.load_new_replies": "Hay nuevas respuestas",
"status.context.loading": "Buscando más respuestas", "status.context.loading": "Buscando más respuestas",
@ -880,6 +882,7 @@
"status.mute_conversation": "Silenciar conversación", "status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir este mensaje", "status.open": "Expandir este mensaje",
"status.pin": "Fijar en el perfil", "status.pin": "Fijar en el perfil",
"status.quote": "Citar",
"status.quote.cancel": "Cancelar cita", "status.quote.cancel": "Cancelar cita",
"status.quote_error.filtered": "Oculto debido a uno de tus filtros", "status.quote_error.filtered": "Oculto debido a uno de tus filtros",
"status.quote_error.not_available": "Mensaje no disponible", "status.quote_error.not_available": "Mensaje no disponible",
@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "¿Cita pendiente? Esperá un momento", "status.quote_error.pending_approval_popout.title": "¿Cita pendiente? Esperá un momento",
"status.quote_policy_change": "Cambiá quién puede citar", "status.quote_policy_change": "Cambiá quién puede citar",
"status.quote_post_author": "Se citó un mensaje de @{name}", "status.quote_post_author": "Se citó un mensaje de @{name}",
"status.quote_private": "No se pueden citar los mensajes privados",
"status.read_more": "Leé más", "status.read_more": "Leé más",
"status.reblog": "Adherir", "status.reblog": "Adherir",
"status.reblog_private": "Adherir a la audiencia original", "status.reblog_private": "Adherir a la audiencia original",

View File

@ -849,9 +849,11 @@
"status.admin_account": "Abrir interfaz de moderación para @{name}", "status.admin_account": "Abrir interfaz de moderación para @{name}",
"status.admin_domain": "Abrir interfaz de moderación para {domain}", "status.admin_domain": "Abrir interfaz de moderación para {domain}",
"status.admin_status": "Abrir este estado en la interfaz de moderación", "status.admin_status": "Abrir este estado en la interfaz de moderación",
"status.all_disabled": "Los impulsos y las citas están desactivadas",
"status.block": "Bloquear a @{name}", "status.block": "Bloquear a @{name}",
"status.bookmark": "Añadir marcador", "status.bookmark": "Añadir marcador",
"status.cancel_reblog_private": "Deshacer impulso", "status.cancel_reblog_private": "Deshacer impulso",
"status.cannot_quote": "El autor ha desactivado las citas de esta publicación",
"status.cannot_reblog": "Esta publicación no puede ser impulsada", "status.cannot_reblog": "Esta publicación no puede ser impulsada",
"status.context.load_new_replies": "Nuevas respuestas disponibles", "status.context.load_new_replies": "Nuevas respuestas disponibles",
"status.context.loading": "Comprobando si hay más respuestas", "status.context.loading": "Comprobando si hay más respuestas",
@ -880,6 +882,7 @@
"status.mute_conversation": "Silenciar conversación", "status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir estado", "status.open": "Expandir estado",
"status.pin": "Fijar", "status.pin": "Fijar",
"status.quote": "Cita",
"status.quote.cancel": "Cancelar cita", "status.quote.cancel": "Cancelar cita",
"status.quote_error.filtered": "Oculto debido a uno de tus filtros", "status.quote_error.filtered": "Oculto debido a uno de tus filtros",
"status.quote_error.not_available": "Publicación no disponible", "status.quote_error.not_available": "Publicación no disponible",
@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "¿Cita pendiente? Mantén la calma", "status.quote_error.pending_approval_popout.title": "¿Cita pendiente? Mantén la calma",
"status.quote_policy_change": "Cambia quién puede citarte", "status.quote_policy_change": "Cambia quién puede citarte",
"status.quote_post_author": "Ha citado una publicación de @{name}", "status.quote_post_author": "Ha citado una publicación de @{name}",
"status.quote_private": "Las publicaciones privadas no pueden citarse",
"status.read_more": "Leer más", "status.read_more": "Leer más",
"status.reblog": "Impulsar", "status.reblog": "Impulsar",
"status.reblog_private": "Implusar a la audiencia original", "status.reblog_private": "Implusar a la audiencia original",

View File

@ -849,9 +849,11 @@
"status.admin_account": "Abrir interfaz de moderación para @{name}", "status.admin_account": "Abrir interfaz de moderación para @{name}",
"status.admin_domain": "Abrir interfaz de moderación para {domain}", "status.admin_domain": "Abrir interfaz de moderación para {domain}",
"status.admin_status": "Abrir esta publicación en la interfaz de moderación", "status.admin_status": "Abrir esta publicación en la interfaz de moderación",
"status.all_disabled": "Los impulsos y las citas están deshabilitados",
"status.block": "Bloquear a @{name}", "status.block": "Bloquear a @{name}",
"status.bookmark": "Añadir marcador", "status.bookmark": "Añadir marcador",
"status.cancel_reblog_private": "Deshacer impulso", "status.cancel_reblog_private": "Deshacer impulso",
"status.cannot_quote": "El autor ha deshabilitado las citas en esta publicación",
"status.cannot_reblog": "Esta publicación no se puede impulsar", "status.cannot_reblog": "Esta publicación no se puede impulsar",
"status.context.load_new_replies": "Hay nuevas respuestas", "status.context.load_new_replies": "Hay nuevas respuestas",
"status.context.loading": "Buscando más respuestas", "status.context.loading": "Buscando más respuestas",
@ -880,6 +882,7 @@
"status.mute_conversation": "Silenciar conversación", "status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir publicación", "status.open": "Expandir publicación",
"status.pin": "Fijar", "status.pin": "Fijar",
"status.quote": "Cita",
"status.quote.cancel": "Cancelar cita", "status.quote.cancel": "Cancelar cita",
"status.quote_error.filtered": "Oculto debido a uno de tus filtros", "status.quote_error.filtered": "Oculto debido a uno de tus filtros",
"status.quote_error.not_available": "Publicación no disponible", "status.quote_error.not_available": "Publicación no disponible",
@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "¿Cita pendiente? Mantén la calma", "status.quote_error.pending_approval_popout.title": "¿Cita pendiente? Mantén la calma",
"status.quote_policy_change": "Cambia quién puede citarte", "status.quote_policy_change": "Cambia quién puede citarte",
"status.quote_post_author": "Ha citado una publicación de @{name}", "status.quote_post_author": "Ha citado una publicación de @{name}",
"status.quote_private": "Las publicaciones privadas no pueden ser citadas",
"status.read_more": "Leer más", "status.read_more": "Leer más",
"status.reblog": "Impulsar", "status.reblog": "Impulsar",
"status.reblog_private": "Impulsar a la audiencia original", "status.reblog_private": "Impulsar a la audiencia original",
@ -966,7 +970,7 @@
"visibility_modal.button_title": "Configura la visibilidad", "visibility_modal.button_title": "Configura la visibilidad",
"visibility_modal.header": "Visibilidad e interacciones", "visibility_modal.header": "Visibilidad e interacciones",
"visibility_modal.helper.direct_quoting": "Las menciones privadas no se pueden citar.", "visibility_modal.helper.direct_quoting": "Las menciones privadas no se pueden citar.",
"visibility_modal.helper.privacy_editing": "Las publicaciones no pueden cambiar su visibilidad.", "visibility_modal.helper.privacy_editing": "Una vez publicada, no se puede cambiar su visibilidad.",
"visibility_modal.helper.private_quoting": "Las publicaciones para seguidores no pueden citarse.", "visibility_modal.helper.private_quoting": "Las publicaciones para seguidores no pueden citarse.",
"visibility_modal.helper.unlisted_quoting": "Cuando la gente te cite, su publicación tampoco se mostrará en las cronologías públicas.", "visibility_modal.helper.unlisted_quoting": "Cuando la gente te cite, su publicación tampoco se mostrará en las cronologías públicas.",
"visibility_modal.instructions": "Controla quién puede interactuar con esta publicación. Puedes encontrar los ajustes globales en <link>Preferencias > Otros</link>.", "visibility_modal.instructions": "Controla quién puede interactuar con esta publicación. Puedes encontrar los ajustes globales en <link>Preferencias > Otros</link>.",

View File

@ -43,7 +43,7 @@
"account.followers": "پی‌گیرندگان", "account.followers": "پی‌گیرندگان",
"account.followers.empty": "هنوز کسی پی‌گیر این کاربر نیست.", "account.followers.empty": "هنوز کسی پی‌گیر این کاربر نیست.",
"account.followers_counter": "{count, plural, one {{counter} پی‌گیرنده} other {{counter} پی‌گیرنده}}", "account.followers_counter": "{count, plural, one {{counter} پی‌گیرنده} other {{counter} پی‌گیرنده}}",
"account.followers_you_know_counter": "{counter} را می‌شناسید", "account.followers_you_know_counter": "{counter} نفر را می‌شناسید",
"account.following": "پی می‌گیرید", "account.following": "پی می‌گیرید",
"account.following_counter": "{count, plural, one {{counter} پی‌گرفته} other {{counter} پی‌گرفته}}", "account.following_counter": "{count, plural, one {{counter} پی‌گرفته} other {{counter} پی‌گرفته}}",
"account.follows.empty": "این کاربر هنوز پی‌گیر کسی نیست.", "account.follows.empty": "این کاربر هنوز پی‌گیر کسی نیست.",
@ -880,6 +880,7 @@
"status.mute_conversation": "خموشاندن گفت‌وگو", "status.mute_conversation": "خموشاندن گفت‌وگو",
"status.open": "گسترش این فرسته", "status.open": "گسترش این فرسته",
"status.pin": "سنجاق به نمایه", "status.pin": "سنجاق به نمایه",
"status.quote.cancel": "لغو نقل",
"status.quote_error.filtered": "نهفته بنا بر یکی از پالایه‌هایتان", "status.quote_error.filtered": "نهفته بنا بر یکی از پالایه‌هایتان",
"status.quote_error.not_available": "فرسته در دسترس نیست", "status.quote_error.not_available": "فرسته در دسترس نیست",
"status.quote_error.pending_approval": "فرسته منتظر", "status.quote_error.pending_approval": "فرسته منتظر",

View File

@ -849,9 +849,11 @@
"status.admin_account": "Avaa tilin @{name} moderointinäkymä", "status.admin_account": "Avaa tilin @{name} moderointinäkymä",
"status.admin_domain": "Avaa palvelimen {domain} moderointinäkymä", "status.admin_domain": "Avaa palvelimen {domain} moderointinäkymä",
"status.admin_status": "Avaa julkaisu moderointinäkymässä", "status.admin_status": "Avaa julkaisu moderointinäkymässä",
"status.all_disabled": "Tehostukset ja lainaukset ovat poissa käytöstä",
"status.block": "Estä @{name}", "status.block": "Estä @{name}",
"status.bookmark": "Lisää kirjanmerkki", "status.bookmark": "Lisää kirjanmerkki",
"status.cancel_reblog_private": "Peru tehostus", "status.cancel_reblog_private": "Peru tehostus",
"status.cannot_quote": "Julkaisun tekijä on poistanut lainaamisen käytöstä",
"status.cannot_reblog": "Tätä julkaisua ei voi tehostaa", "status.cannot_reblog": "Tätä julkaisua ei voi tehostaa",
"status.context.load_new_replies": "Uusia vastauksia saatavilla", "status.context.load_new_replies": "Uusia vastauksia saatavilla",
"status.context.loading": "Tarkistetaan lisävastauksia", "status.context.loading": "Tarkistetaan lisävastauksia",
@ -880,6 +882,7 @@
"status.mute_conversation": "Mykistä keskustelu", "status.mute_conversation": "Mykistä keskustelu",
"status.open": "Laajenna julkaisu", "status.open": "Laajenna julkaisu",
"status.pin": "Kiinnitä profiiliin", "status.pin": "Kiinnitä profiiliin",
"status.quote": "Lainaa",
"status.quote.cancel": "Peruuta lainaus", "status.quote.cancel": "Peruuta lainaus",
"status.quote_error.filtered": "Piilotettu jonkin asettamasi suodattimen takia", "status.quote_error.filtered": "Piilotettu jonkin asettamasi suodattimen takia",
"status.quote_error.not_available": "Julkaisu ei saatavilla", "status.quote_error.not_available": "Julkaisu ei saatavilla",
@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Odottava lainaus? Pysy rauhallisena", "status.quote_error.pending_approval_popout.title": "Odottava lainaus? Pysy rauhallisena",
"status.quote_policy_change": "Vaihda, kuka voi lainata", "status.quote_policy_change": "Vaihda, kuka voi lainata",
"status.quote_post_author": "Lainaa käyttäjän @{name} julkaisua", "status.quote_post_author": "Lainaa käyttäjän @{name} julkaisua",
"status.quote_private": "Yksityisiä julkaisuja ei voi lainata",
"status.read_more": "Näytä enemmän", "status.read_more": "Näytä enemmän",
"status.reblog": "Tehosta", "status.reblog": "Tehosta",
"status.reblog_private": "Tehosta alkuperäiselle yleisölle", "status.reblog_private": "Tehosta alkuperäiselle yleisölle",

View File

@ -849,9 +849,11 @@
"status.admin_account": "Lat kjakleiðaramarkamót upp fyri @{name}", "status.admin_account": "Lat kjakleiðaramarkamót upp fyri @{name}",
"status.admin_domain": "Lat umsjónarmarkamót upp fyri {domain}", "status.admin_domain": "Lat umsjónarmarkamót upp fyri {domain}",
"status.admin_status": "Lat hendan postin upp í kjakleiðaramarkamótinum", "status.admin_status": "Lat hendan postin upp í kjakleiðaramarkamótinum",
"status.all_disabled": "Stimbranir og sitatir eru gjørd óvirkin",
"status.block": "Blokera @{name}", "status.block": "Blokera @{name}",
"status.bookmark": "Goym", "status.bookmark": "Goym",
"status.cancel_reblog_private": "Strika stimbran", "status.cancel_reblog_private": "Strika stimbran",
"status.cannot_quote": "Høvundurin hevur gjørt sitering óvirkna fyri hendan postin",
"status.cannot_reblog": "Tað ber ikki til at stimbra hendan postin", "status.cannot_reblog": "Tað ber ikki til at stimbra hendan postin",
"status.context.load_new_replies": "Nýggj svar tøk", "status.context.load_new_replies": "Nýggj svar tøk",
"status.context.loading": "Kanni um tað eru fleiri svar", "status.context.loading": "Kanni um tað eru fleiri svar",
@ -880,6 +882,7 @@
"status.mute_conversation": "Doyv samrøðu", "status.mute_conversation": "Doyv samrøðu",
"status.open": "Víðka henda postin", "status.open": "Víðka henda postin",
"status.pin": "Ger fastan í vangan", "status.pin": "Ger fastan í vangan",
"status.quote": "Sitat",
"status.quote.cancel": "Ógilda sitat", "status.quote.cancel": "Ógilda sitat",
"status.quote_error.filtered": "Eitt av tínum filtrum fjalir hetta", "status.quote_error.filtered": "Eitt av tínum filtrum fjalir hetta",
"status.quote_error.not_available": "Postur ikki tøkur", "status.quote_error.not_available": "Postur ikki tøkur",
@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Bíðar eftir sitati? Tak tað róligt", "status.quote_error.pending_approval_popout.title": "Bíðar eftir sitati? Tak tað róligt",
"status.quote_policy_change": "Broyt hvør kann sitera", "status.quote_policy_change": "Broyt hvør kann sitera",
"status.quote_post_author": "Siteraði ein post hjá @{name}", "status.quote_post_author": "Siteraði ein post hjá @{name}",
"status.quote_private": "Privatir postar kunnu ikki siterast",
"status.read_more": "Les meira", "status.read_more": "Les meira",
"status.reblog": "Stimbra", "status.reblog": "Stimbra",
"status.reblog_private": "Stimbra við upprunasýni", "status.reblog_private": "Stimbra við upprunasýni",

View File

@ -849,9 +849,11 @@
"status.admin_account": "פתח/י ממשק פיקוח דיון עבור @{name}", "status.admin_account": "פתח/י ממשק פיקוח דיון עבור @{name}",
"status.admin_domain": "פתיחת ממשק פיקוח דיון עבור {domain}", "status.admin_domain": "פתיחת ממשק פיקוח דיון עבור {domain}",
"status.admin_status": "לפתוח הודעה זו במסך ניהול הדיונים", "status.admin_status": "לפתוח הודעה זו במסך ניהול הדיונים",
"status.all_disabled": "הדהודים וציטוטים כובו",
"status.block": "חסימת @{name}", "status.block": "חסימת @{name}",
"status.bookmark": "סימניה", "status.bookmark": "סימניה",
"status.cancel_reblog_private": "הסרת הדהוד", "status.cancel_reblog_private": "הסרת הדהוד",
"status.cannot_quote": "יוצר\\ת ההודעה חסמו את האפשרות לצטט אותה",
"status.cannot_reblog": "לא ניתן להדהד חצרוץ זה", "status.cannot_reblog": "לא ניתן להדהד חצרוץ זה",
"status.context.load_new_replies": "הגיעו תגובות חדשות", "status.context.load_new_replies": "הגיעו תגובות חדשות",
"status.context.loading": "מחפש תגובות חדשות", "status.context.loading": "מחפש תגובות חדשות",
@ -880,6 +882,7 @@
"status.mute_conversation": "השתקת שיחה", "status.mute_conversation": "השתקת שיחה",
"status.open": "הרחבת הודעה זו", "status.open": "הרחבת הודעה זו",
"status.pin": "הצמדה לפרופיל שלי", "status.pin": "הצמדה לפרופיל שלי",
"status.quote": "ציטוט",
"status.quote.cancel": "ביטול הודעת ציטוט", "status.quote.cancel": "ביטול הודעת ציטוט",
"status.quote_error.filtered": "מוסתר בהתאם לסננים שלך", "status.quote_error.filtered": "מוסתר בהתאם לסננים שלך",
"status.quote_error.not_available": "ההודעה לא זמינה", "status.quote_error.not_available": "ההודעה לא זמינה",
@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "ההודעה בהמתנה? המתינו ברוגע", "status.quote_error.pending_approval_popout.title": "ההודעה בהמתנה? המתינו ברוגע",
"status.quote_policy_change": "הגדרת הרשאה לציטוט הודעותיך", "status.quote_policy_change": "הגדרת הרשאה לציטוט הודעותיך",
"status.quote_post_author": "ההודעה צוטטה על ידי @{name}", "status.quote_post_author": "ההודעה צוטטה על ידי @{name}",
"status.quote_private": "הודעות פרטיות לא ניתנות לציטוט",
"status.read_more": "לקרוא עוד", "status.read_more": "לקרוא עוד",
"status.reblog": "הדהוד", "status.reblog": "הדהוד",
"status.reblog_private": "להדהד ברמת הנראות המקורית", "status.reblog_private": "להדהד ברמת הנראות המקורית",

View File

@ -1,6 +1,7 @@
{ {
"about.blocks": "Servitores moderate", "about.blocks": "Servitores moderate",
"about.contact": "Contacto:", "about.contact": "Contacto:",
"about.default_locale": "Default",
"about.disclaimer": "Mastodon es software libere, de codice aperte, e un marca de Mastodon gGmbH.", "about.disclaimer": "Mastodon es software libere, de codice aperte, e un marca de Mastodon gGmbH.",
"about.domain_blocks.no_reason_available": "Ration non disponibile", "about.domain_blocks.no_reason_available": "Ration non disponibile",
"about.domain_blocks.preamble": "Mastodon generalmente permitte vider le contento de, e interager con, usatores de qualcunque altere servitor in le fediverso. Istes es le exceptiones que ha essite facite sur iste servitor particular.", "about.domain_blocks.preamble": "Mastodon generalmente permitte vider le contento de, e interager con, usatores de qualcunque altere servitor in le fediverso. Istes es le exceptiones que ha essite facite sur iste servitor particular.",
@ -8,6 +9,7 @@
"about.domain_blocks.silenced.title": "Limitate", "about.domain_blocks.silenced.title": "Limitate",
"about.domain_blocks.suspended.explanation": "Nulle datos de iste servitor essera processate, immagazinate o excambiate, rendente omne interaction o communication con usatores de iste servitor impossibile.", "about.domain_blocks.suspended.explanation": "Nulle datos de iste servitor essera processate, immagazinate o excambiate, rendente omne interaction o communication con usatores de iste servitor impossibile.",
"about.domain_blocks.suspended.title": "Suspendite", "about.domain_blocks.suspended.title": "Suspendite",
"about.language_label": "Lingua",
"about.not_available": "Iste information non ha essite rendite disponibile sur iste servitor.", "about.not_available": "Iste information non ha essite rendite disponibile sur iste servitor.",
"about.powered_by": "Rete social decentralisate, actionate per {mastodon}", "about.powered_by": "Rete social decentralisate, actionate per {mastodon}",
"about.rules": "Regulas del servitor", "about.rules": "Regulas del servitor",
@ -41,6 +43,7 @@
"account.followers": "Sequitores", "account.followers": "Sequitores",
"account.followers.empty": "Necuno seque ancora iste usator.", "account.followers.empty": "Necuno seque ancora iste usator.",
"account.followers_counter": "{count, plural, one {{counter} sequitor} other {{counter} sequitores}}", "account.followers_counter": "{count, plural, one {{counter} sequitor} other {{counter} sequitores}}",
"account.followers_you_know_counter": "{counter} que tu cognosce",
"account.following": "Sequente", "account.following": "Sequente",
"account.following_counter": "{count, plural, one {{counter} sequite} other {{counter} sequites}}", "account.following_counter": "{count, plural, one {{counter} sequite} other {{counter} sequites}}",
"account.follows.empty": "Iste usator non seque ancora alcuno.", "account.follows.empty": "Iste usator non seque ancora alcuno.",
@ -216,6 +219,13 @@
"confirmations.delete_list.confirm": "Deler", "confirmations.delete_list.confirm": "Deler",
"confirmations.delete_list.message": "Es tu secur que tu vole deler permanentemente iste lista?", "confirmations.delete_list.message": "Es tu secur que tu vole deler permanentemente iste lista?",
"confirmations.delete_list.title": "Deler lista?", "confirmations.delete_list.title": "Deler lista?",
"confirmations.discard_draft.confirm": "Discartar e continuar",
"confirmations.discard_draft.edit.cancel": "Reprender le modification",
"confirmations.discard_draft.edit.message": "Si tu continua, tu perdera tote le modificatione que tu ha apportate al message que tu modifica in iste momento.",
"confirmations.discard_draft.edit.title": "Discartar le modificationes de tu message?",
"confirmations.discard_draft.post.cancel": "Retornar al esbosso",
"confirmations.discard_draft.post.message": "Si tu continua, tu perdera le message que tu compone in iste momento.",
"confirmations.discard_draft.post.title": "Discartar tu esbosso de message?",
"confirmations.discard_edit_media.confirm": "Abandonar", "confirmations.discard_edit_media.confirm": "Abandonar",
"confirmations.discard_edit_media.message": "Tu ha cambiamentos non salvate in le description o previsualisation del objecto multimedial. Abandonar los?", "confirmations.discard_edit_media.message": "Tu ha cambiamentos non salvate in le description o previsualisation del objecto multimedial. Abandonar los?",
"confirmations.follow_to_list.confirm": "Sequer e adder al lista", "confirmations.follow_to_list.confirm": "Sequer e adder al lista",
@ -235,6 +245,9 @@
"confirmations.remove_from_followers.confirm": "Remover sequitor", "confirmations.remove_from_followers.confirm": "Remover sequitor",
"confirmations.remove_from_followers.message": "{name} non plus te sequera. Es tu secur de voler continuar?", "confirmations.remove_from_followers.message": "{name} non plus te sequera. Es tu secur de voler continuar?",
"confirmations.remove_from_followers.title": "Remover sequitor?", "confirmations.remove_from_followers.title": "Remover sequitor?",
"confirmations.revoke_quote.confirm": "Remover message",
"confirmations.revoke_quote.message": "Iste action non pote esser disfacite.",
"confirmations.revoke_quote.title": "Remover message?",
"confirmations.unfollow.confirm": "Non plus sequer", "confirmations.unfollow.confirm": "Non plus sequer",
"confirmations.unfollow.message": "Es tu secur que tu vole cessar de sequer {name}?", "confirmations.unfollow.message": "Es tu secur que tu vole cessar de sequer {name}?",
"confirmations.unfollow.title": "Cessar de sequer le usator?", "confirmations.unfollow.title": "Cessar de sequer le usator?",
@ -279,6 +292,7 @@
"domain_pill.your_handle": "Tu pseudonymo:", "domain_pill.your_handle": "Tu pseudonymo:",
"domain_pill.your_server": "Tu casa digital, ubi vive tote tu messages. Non te place? Cambia de servitor a omne momento e porta tu sequitores con te.", "domain_pill.your_server": "Tu casa digital, ubi vive tote tu messages. Non te place? Cambia de servitor a omne momento e porta tu sequitores con te.",
"domain_pill.your_username": "Tu identificator unic sur iste servitor. Es possibile trovar usatores con le mesme nomine de usator sur servitores differente.", "domain_pill.your_username": "Tu identificator unic sur iste servitor. Es possibile trovar usatores con le mesme nomine de usator sur servitores differente.",
"dropdown.empty": "Selige un option",
"embed.instructions": "Incorpora iste message sur tu sito web con le codice sequente.", "embed.instructions": "Incorpora iste message sur tu sito web con le codice sequente.",
"embed.preview": "Ecce como illlo parera:", "embed.preview": "Ecce como illlo parera:",
"emoji_button.activity": "Activitate", "emoji_button.activity": "Activitate",
@ -296,6 +310,8 @@
"emoji_button.search_results": "Resultatos de recerca", "emoji_button.search_results": "Resultatos de recerca",
"emoji_button.symbols": "Symbolos", "emoji_button.symbols": "Symbolos",
"emoji_button.travel": "Viages e locos", "emoji_button.travel": "Viages e locos",
"empty_column.account_featured.me": "Tu non ha ancora mittite alcun cosa in evidentia. Sapeva tu que tu pote mitter in evidentia sur tu profilo le hashtags que tu usa le plus e mesmo le contos de tu amicos?",
"empty_column.account_featured.other": "{acct} non ha ancora mittite alcun cosa in evidentia. Sapeva tu que tu pote mitter in evidentia sur tu profilo le hashtags que tu usa le plus e mesmo le contos de tu amicos?",
"empty_column.account_featured_other.unknown": "Iste conto non ha ancora mittite alcun cosa in evidentia.", "empty_column.account_featured_other.unknown": "Iste conto non ha ancora mittite alcun cosa in evidentia.",
"empty_column.account_hides_collections": "Le usator non ha rendite iste information disponibile", "empty_column.account_hides_collections": "Le usator non ha rendite iste information disponibile",
"empty_column.account_suspended": "Conto suspendite", "empty_column.account_suspended": "Conto suspendite",
@ -325,9 +341,15 @@
"errors.unexpected_crash.copy_stacktrace": "Copiar le traciamento del pila al area de transferentia", "errors.unexpected_crash.copy_stacktrace": "Copiar le traciamento del pila al area de transferentia",
"errors.unexpected_crash.report_issue": "Reportar problema", "errors.unexpected_crash.report_issue": "Reportar problema",
"explore.suggested_follows": "Personas", "explore.suggested_follows": "Personas",
"explore.title": "In tendentia",
"explore.trending_links": "Novas", "explore.trending_links": "Novas",
"explore.trending_statuses": "Messages", "explore.trending_statuses": "Messages",
"explore.trending_tags": "Hashtags", "explore.trending_tags": "Hashtags",
"featured_carousel.header": "{count, plural, one {Message fixate} other {Messages fixate}}",
"featured_carousel.next": "Sequente",
"featured_carousel.post": "Message",
"featured_carousel.previous": "Precedente",
"featured_carousel.slide": "{index} de {total}",
"filter_modal.added.context_mismatch_explanation": "Iste categoria de filtros non se applica al contexto in le qual tu ha accedite a iste message. Pro filtrar le message in iste contexto tamben, modifica le filtro.", "filter_modal.added.context_mismatch_explanation": "Iste categoria de filtros non se applica al contexto in le qual tu ha accedite a iste message. Pro filtrar le message in iste contexto tamben, modifica le filtro.",
"filter_modal.added.context_mismatch_title": "Contexto incoherente!", "filter_modal.added.context_mismatch_title": "Contexto incoherente!",
"filter_modal.added.expired_explanation": "Iste categoria de filtros ha expirate. Tu debe modificar le data de expiration pro applicar lo.", "filter_modal.added.expired_explanation": "Iste categoria de filtros ha expirate. Tu debe modificar le data de expiration pro applicar lo.",
@ -380,6 +402,8 @@
"generic.saved": "Salvate", "generic.saved": "Salvate",
"getting_started.heading": "Prime passos", "getting_started.heading": "Prime passos",
"hashtag.admin_moderation": "Aperir le interfacie de moderation pro #{name}", "hashtag.admin_moderation": "Aperir le interfacie de moderation pro #{name}",
"hashtag.browse": "Percurrer messages in #{hashtag}",
"hashtag.browse_from_account": "Percurrer le messages de @{name} in #{hashtag}",
"hashtag.column_header.tag_mode.all": "e {additional}", "hashtag.column_header.tag_mode.all": "e {additional}",
"hashtag.column_header.tag_mode.any": "o {additional}", "hashtag.column_header.tag_mode.any": "o {additional}",
"hashtag.column_header.tag_mode.none": "sin {additional}", "hashtag.column_header.tag_mode.none": "sin {additional}",
@ -404,6 +428,7 @@
"hints.profiles.see_more_followers": "Vider plus de sequitores sur {domain}", "hints.profiles.see_more_followers": "Vider plus de sequitores sur {domain}",
"hints.profiles.see_more_follows": "Vider plus de sequites sur {domain}", "hints.profiles.see_more_follows": "Vider plus de sequites sur {domain}",
"hints.profiles.see_more_posts": "Vider plus de messages sur {domain}", "hints.profiles.see_more_posts": "Vider plus de messages sur {domain}",
"home.column_settings.show_quotes": "Monstrar citationes",
"home.column_settings.show_reblogs": "Monstrar impulsos", "home.column_settings.show_reblogs": "Monstrar impulsos",
"home.column_settings.show_replies": "Monstrar responsas", "home.column_settings.show_replies": "Monstrar responsas",
"home.hide_announcements": "Celar annuncios", "home.hide_announcements": "Celar annuncios",
@ -477,6 +502,8 @@
"keyboard_shortcuts.translate": "a traducer un message", "keyboard_shortcuts.translate": "a traducer un message",
"keyboard_shortcuts.unfocus": "Disfocalisar le area de composition de texto/de recerca", "keyboard_shortcuts.unfocus": "Disfocalisar le area de composition de texto/de recerca",
"keyboard_shortcuts.up": "Displaciar in alto in le lista", "keyboard_shortcuts.up": "Displaciar in alto in le lista",
"learn_more_link.got_it": "Comprendite",
"learn_more_link.learn_more": "Pro saper plus",
"lightbox.close": "Clauder", "lightbox.close": "Clauder",
"lightbox.next": "Sequente", "lightbox.next": "Sequente",
"lightbox.previous": "Precedente", "lightbox.previous": "Precedente",
@ -526,8 +553,10 @@
"mute_modal.you_wont_see_mentions": "Tu non videra le messages que mentiona iste persona.", "mute_modal.you_wont_see_mentions": "Tu non videra le messages que mentiona iste persona.",
"mute_modal.you_wont_see_posts": "Iste persona pote totevia vider tu messages, ma tu non videra le sues.", "mute_modal.you_wont_see_posts": "Iste persona pote totevia vider tu messages, ma tu non videra le sues.",
"navigation_bar.about": "A proposito", "navigation_bar.about": "A proposito",
"navigation_bar.account_settings": "Contrasigno e securitate",
"navigation_bar.administration": "Administration", "navigation_bar.administration": "Administration",
"navigation_bar.advanced_interface": "Aperir in le interfacie web avantiate", "navigation_bar.advanced_interface": "Aperir in le interfacie web avantiate",
"navigation_bar.automated_deletion": "Deletion automatic del message",
"navigation_bar.blocks": "Usatores blocate", "navigation_bar.blocks": "Usatores blocate",
"navigation_bar.bookmarks": "Marcapaginas", "navigation_bar.bookmarks": "Marcapaginas",
"navigation_bar.direct": "Mentiones private", "navigation_bar.direct": "Mentiones private",
@ -537,13 +566,23 @@
"navigation_bar.follow_requests": "Requestas de sequimento", "navigation_bar.follow_requests": "Requestas de sequimento",
"navigation_bar.followed_tags": "Hashtags sequite", "navigation_bar.followed_tags": "Hashtags sequite",
"navigation_bar.follows_and_followers": "Sequites e sequitores", "navigation_bar.follows_and_followers": "Sequites e sequitores",
"navigation_bar.import_export": "Importar e exportar",
"navigation_bar.lists": "Listas", "navigation_bar.lists": "Listas",
"navigation_bar.live_feed_local": "Canal in directo (local)",
"navigation_bar.live_feed_public": "Canal in directo (public)",
"navigation_bar.logout": "Clauder session", "navigation_bar.logout": "Clauder session",
"navigation_bar.moderation": "Moderation", "navigation_bar.moderation": "Moderation",
"navigation_bar.more": "Plus",
"navigation_bar.mutes": "Usatores silentiate", "navigation_bar.mutes": "Usatores silentiate",
"navigation_bar.opened_in_classic_interface": "Messages, contos e altere paginas specific es aperite per predefinition in le interfacie web classic.", "navigation_bar.opened_in_classic_interface": "Messages, contos e altere paginas specific es aperite per predefinition in le interfacie web classic.",
"navigation_bar.preferences": "Preferentias", "navigation_bar.preferences": "Preferentias",
"navigation_bar.privacy_and_reach": "Confidentialitate e portata",
"navigation_bar.search": "Cercar", "navigation_bar.search": "Cercar",
"navigation_bar.search_trends": "Cercar / In tendentia",
"navigation_panel.collapse_followed_tags": "Contraher le menu de hashtags sequite",
"navigation_panel.collapse_lists": "Contraher le menu de listas",
"navigation_panel.expand_followed_tags": "Expander le menu de hashtags sequite",
"navigation_panel.expand_lists": "Expander le menu de listas",
"not_signed_in_indicator.not_signed_in": "Es necessari aperir session pro acceder a iste ressource.", "not_signed_in_indicator.not_signed_in": "Es necessari aperir session pro acceder a iste ressource.",
"notification.admin.report": "{name} ha reportate {target}", "notification.admin.report": "{name} ha reportate {target}",
"notification.admin.report_account": "{name} ha reportate {count, plural, one {un message} other {# messages}} de {target} per {category}", "notification.admin.report_account": "{name} ha reportate {count, plural, one {un message} other {# messages}} de {target} per {category}",
@ -565,6 +604,7 @@
"notification.label.mention": "Mention", "notification.label.mention": "Mention",
"notification.label.private_mention": "Mention private", "notification.label.private_mention": "Mention private",
"notification.label.private_reply": "Responsa private", "notification.label.private_reply": "Responsa private",
"notification.label.quote": "{name} ha citate tu message",
"notification.label.reply": "Responder", "notification.label.reply": "Responder",
"notification.mention": "Mention", "notification.mention": "Mention",
"notification.mentioned_you": "{name} te ha mentionate", "notification.mentioned_you": "{name} te ha mentionate",
@ -622,6 +662,7 @@
"notifications.column_settings.mention": "Mentiones:", "notifications.column_settings.mention": "Mentiones:",
"notifications.column_settings.poll": "Resultatos del sondage:", "notifications.column_settings.poll": "Resultatos del sondage:",
"notifications.column_settings.push": "Notificationes push", "notifications.column_settings.push": "Notificationes push",
"notifications.column_settings.quote": "Citationes:",
"notifications.column_settings.reblog": "Impulsos:", "notifications.column_settings.reblog": "Impulsos:",
"notifications.column_settings.show": "Monstrar in columna", "notifications.column_settings.show": "Monstrar in columna",
"notifications.column_settings.sound": "Reproducer sono", "notifications.column_settings.sound": "Reproducer sono",
@ -770,6 +811,7 @@
"report_notification.categories.violation": "Violation del regulas", "report_notification.categories.violation": "Violation del regulas",
"report_notification.categories.violation_sentence": "violation del regulas", "report_notification.categories.violation_sentence": "violation del regulas",
"report_notification.open": "Aperir reporto", "report_notification.open": "Aperir reporto",
"search.clear": "Rader le recerca",
"search.no_recent_searches": "Nulle recercas recente", "search.no_recent_searches": "Nulle recercas recente",
"search.placeholder": "Cercar", "search.placeholder": "Cercar",
"search.quick_action.account_search": "Profilos correspondente a {x}", "search.quick_action.account_search": "Profilos correspondente a {x}",
@ -811,6 +853,8 @@
"status.bookmark": "Adder al marcapaginas", "status.bookmark": "Adder al marcapaginas",
"status.cancel_reblog_private": "Disfacer impulso", "status.cancel_reblog_private": "Disfacer impulso",
"status.cannot_reblog": "Iste message non pote esser impulsate", "status.cannot_reblog": "Iste message non pote esser impulsate",
"status.context.load_new_replies": "Nove responsas disponibile",
"status.context.loading": "Cercante plus responsas",
"status.continued_thread": "Continuation del discussion", "status.continued_thread": "Continuation del discussion",
"status.copy": "Copiar ligamine a message", "status.copy": "Copiar ligamine a message",
"status.delete": "Deler", "status.delete": "Deler",
@ -836,6 +880,14 @@
"status.mute_conversation": "Silentiar conversation", "status.mute_conversation": "Silentiar conversation",
"status.open": "Expander iste message", "status.open": "Expander iste message",
"status.pin": "Fixar sur profilo", "status.pin": "Fixar sur profilo",
"status.quote.cancel": "Cancellar le citation",
"status.quote_error.filtered": "Celate a causa de un de tu filtros",
"status.quote_error.not_available": "Message indisponibile",
"status.quote_error.pending_approval": "Message pendente",
"status.quote_error.pending_approval_popout.body": "Le citationes distribuite a transverso le Fediverso pote tardar in apparer, perque differente servitores ha differente protocollos.",
"status.quote_error.pending_approval_popout.title": "Citation pendente? Resta calme",
"status.quote_policy_change": "Cambiar qui pote citar",
"status.quote_post_author": "Ha citate un message de @{name}",
"status.read_more": "Leger plus", "status.read_more": "Leger plus",
"status.reblog": "Impulsar", "status.reblog": "Impulsar",
"status.reblog_private": "Impulsar con visibilitate original", "status.reblog_private": "Impulsar con visibilitate original",
@ -850,6 +902,7 @@
"status.reply": "Responder", "status.reply": "Responder",
"status.replyAll": "Responder al discussion", "status.replyAll": "Responder al discussion",
"status.report": "Reportar @{name}", "status.report": "Reportar @{name}",
"status.revoke_quote": "Remover mi message del message de @{name}",
"status.sensitive_warning": "Contento sensibile", "status.sensitive_warning": "Contento sensibile",
"status.share": "Compartir", "status.share": "Compartir",
"status.show_less_all": "Monstrar minus pro totes", "status.show_less_all": "Monstrar minus pro totes",
@ -865,9 +918,13 @@
"subscribed_languages.save": "Salvar le cambiamentos", "subscribed_languages.save": "Salvar le cambiamentos",
"subscribed_languages.target": "Cambiar le linguas subscribite pro {target}", "subscribed_languages.target": "Cambiar le linguas subscribite pro {target}",
"tabs_bar.home": "Initio", "tabs_bar.home": "Initio",
"tabs_bar.menu": "Menu",
"tabs_bar.notifications": "Notificationes", "tabs_bar.notifications": "Notificationes",
"tabs_bar.publish": "Nove message",
"tabs_bar.search": "Cercar",
"terms_of_service.effective_as_of": "In vigor a partir de {date}", "terms_of_service.effective_as_of": "In vigor a partir de {date}",
"terms_of_service.title": "Conditiones de servicio", "terms_of_service.title": "Conditiones de servicio",
"terms_of_service.upcoming_changes_on": "Cambiamentos a venir le {date}",
"time_remaining.days": "{number, plural, one {# die} other {# dies}} restante", "time_remaining.days": "{number, plural, one {# die} other {# dies}} restante",
"time_remaining.hours": "{number, plural, one {# hora} other {# horas}} restante", "time_remaining.hours": "{number, plural, one {# hora} other {# horas}} restante",
"time_remaining.minutes": "{number, plural, one {# minuta} other {# minutas}} restante", "time_remaining.minutes": "{number, plural, one {# minuta} other {# minutas}} restante",
@ -875,7 +932,7 @@
"time_remaining.seconds": "{number, plural, one {# secunda} other {# secundas}} restante", "time_remaining.seconds": "{number, plural, one {# secunda} other {# secundas}} restante",
"trends.counter_by_accounts": "{count, plural, one {{counter} persona} other {{counter} personas}} in le passate {days, plural, one {die} other {{days} dies}}", "trends.counter_by_accounts": "{count, plural, one {{counter} persona} other {{counter} personas}} in le passate {days, plural, one {die} other {{days} dies}}",
"trends.trending_now": "Ora in tendentias", "trends.trending_now": "Ora in tendentias",
"ui.beforeunload": "Tu esbosso essera predite si tu exi de Mastodon.", "ui.beforeunload": "Tu esbosso essera perdite si tu exi de Mastodon.",
"units.short.billion": "{count}B", "units.short.billion": "{count}B",
"units.short.million": "{count}M", "units.short.million": "{count}M",
"units.short.thousand": "{count}K", "units.short.thousand": "{count}K",
@ -902,7 +959,20 @@
"video.pause": "Pausa", "video.pause": "Pausa",
"video.play": "Reproducer", "video.play": "Reproducer",
"video.skip_backward": "Saltar a retro", "video.skip_backward": "Saltar a retro",
"video.skip_forward": "Avantiar",
"video.unmute": "Non plus silentiar", "video.unmute": "Non plus silentiar",
"video.volume_down": "Abassar le volumine", "video.volume_down": "Abassar le volumine",
"video.volume_up": "Augmentar le volumine" "video.volume_up": "Augmentar le volumine",
"visibility_modal.button_title": "Definir visibilitate",
"visibility_modal.header": "Visibilitate e interaction",
"visibility_modal.helper.direct_quoting": "Le mentiones private non pote esser citate.",
"visibility_modal.helper.privacy_editing": "Le messages ja publicate non pote cambiar de visibilitate.",
"visibility_modal.helper.private_quoting": "Le messages reservate al sequitores non pote esser citate.",
"visibility_modal.helper.unlisted_quoting": "Quando un persona te cita, su message essera tamben celate del chronologia \"In tendentia\".",
"visibility_modal.instructions": "Controla qui pote interager con iste message. Le parametros global se trova sub <link>Preferentias > Alteres</link>.",
"visibility_modal.privacy_label": "Confidentialitate",
"visibility_modal.quote_followers": "Solmente sequitores",
"visibility_modal.quote_label": "Cambiar qui pote citar",
"visibility_modal.quote_nobody": "Necuno",
"visibility_modal.quote_public": "Omnes"
} }

View File

@ -849,9 +849,11 @@
"status.admin_account": "Opna umsjónarviðmót fyrir @{name}", "status.admin_account": "Opna umsjónarviðmót fyrir @{name}",
"status.admin_domain": "Opna umsjónarviðmót fyrir @{domain}", "status.admin_domain": "Opna umsjónarviðmót fyrir @{domain}",
"status.admin_status": "Opna þessa færslu í umsjónarviðmótinu", "status.admin_status": "Opna þessa færslu í umsjónarviðmótinu",
"status.all_disabled": "Endurbirtingar og tilvitnanir eru óvirkar",
"status.block": "Útiloka @{name}", "status.block": "Útiloka @{name}",
"status.bookmark": "Bókamerki", "status.bookmark": "Bókamerki",
"status.cancel_reblog_private": "Taka úr endurbirtingu", "status.cancel_reblog_private": "Taka úr endurbirtingu",
"status.cannot_quote": "Höfundurinn hefur gert tilvitnanir óvirkar fyrir þessa færslu",
"status.cannot_reblog": "Þessa færslu er ekki hægt að endurbirta", "status.cannot_reblog": "Þessa færslu er ekki hægt að endurbirta",
"status.context.load_new_replies": "Ný svör hafa borist", "status.context.load_new_replies": "Ný svör hafa borist",
"status.context.loading": "Athuga með fleiri svör", "status.context.loading": "Athuga með fleiri svör",
@ -880,6 +882,7 @@
"status.mute_conversation": "Þagga niður í samtali", "status.mute_conversation": "Þagga niður í samtali",
"status.open": "Opna þessa færslu", "status.open": "Opna þessa færslu",
"status.pin": "Festa á notandasnið", "status.pin": "Festa á notandasnið",
"status.quote": "Tilvitnun",
"status.quote.cancel": "Hætta við tilvitnun", "status.quote.cancel": "Hætta við tilvitnun",
"status.quote_error.filtered": "Falið vegna einnar síu sem er virk", "status.quote_error.filtered": "Falið vegna einnar síu sem er virk",
"status.quote_error.not_available": "Færsla ekki tiltæk", "status.quote_error.not_available": "Færsla ekki tiltæk",
@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Færsla í bið? Verum róleg", "status.quote_error.pending_approval_popout.title": "Færsla í bið? Verum róleg",
"status.quote_policy_change": "Breyttu því hver getur tilvitnað", "status.quote_policy_change": "Breyttu því hver getur tilvitnað",
"status.quote_post_author": "Vitnaði í færslu frá @{name}", "status.quote_post_author": "Vitnaði í færslu frá @{name}",
"status.quote_private": "Ekki er hægt að vitna í einkafærslur",
"status.read_more": "Lesa meira", "status.read_more": "Lesa meira",
"status.reblog": "Endurbirting", "status.reblog": "Endurbirting",
"status.reblog_private": "Endurbirta til upphaflegra lesenda", "status.reblog_private": "Endurbirta til upphaflegra lesenda",

View File

@ -245,6 +245,9 @@
"confirmations.remove_from_followers.confirm": "Rimuovi il seguace", "confirmations.remove_from_followers.confirm": "Rimuovi il seguace",
"confirmations.remove_from_followers.message": "{name} smetterà di seguirti. Si è sicuri di voler procedere?", "confirmations.remove_from_followers.message": "{name} smetterà di seguirti. Si è sicuri di voler procedere?",
"confirmations.remove_from_followers.title": "Rimuovi il seguace?", "confirmations.remove_from_followers.title": "Rimuovi il seguace?",
"confirmations.revoke_quote.confirm": "Elimina il post",
"confirmations.revoke_quote.message": "Questa azione non può essere annullata.",
"confirmations.revoke_quote.title": "Rimuovere il post?",
"confirmations.unfollow.confirm": "Smetti di seguire", "confirmations.unfollow.confirm": "Smetti di seguire",
"confirmations.unfollow.message": "Sei sicuro di voler smettere di seguire {name}?", "confirmations.unfollow.message": "Sei sicuro di voler smettere di seguire {name}?",
"confirmations.unfollow.title": "Smettere di seguire l'utente?", "confirmations.unfollow.title": "Smettere di seguire l'utente?",
@ -289,6 +292,7 @@
"domain_pill.your_handle": "Il tuo nome univoco:", "domain_pill.your_handle": "Il tuo nome univoco:",
"domain_pill.your_server": "La tua casa digitale, dove vivono tutti i tuoi post. Non ti piace questa? Cambia server in qualsiasi momento e porta con te anche i tuoi seguaci.", "domain_pill.your_server": "La tua casa digitale, dove vivono tutti i tuoi post. Non ti piace questa? Cambia server in qualsiasi momento e porta con te anche i tuoi seguaci.",
"domain_pill.your_username": "Il tuo identificatore univoco su questo server. È possibile trovare utenti con lo stesso nome utente su server diversi.", "domain_pill.your_username": "Il tuo identificatore univoco su questo server. È possibile trovare utenti con lo stesso nome utente su server diversi.",
"dropdown.empty": "Seleziona un'opzione",
"embed.instructions": "Incorpora questo post sul tuo sito web, copiando il seguente codice.", "embed.instructions": "Incorpora questo post sul tuo sito web, copiando il seguente codice.",
"embed.preview": "Ecco come apparirà:", "embed.preview": "Ecco come apparirà:",
"emoji_button.activity": "Attività", "emoji_button.activity": "Attività",
@ -845,9 +849,11 @@
"status.admin_account": "Apri interfaccia di moderazione per @{name}", "status.admin_account": "Apri interfaccia di moderazione per @{name}",
"status.admin_domain": "Apri l'interfaccia di moderazione per {domain}", "status.admin_domain": "Apri l'interfaccia di moderazione per {domain}",
"status.admin_status": "Apri questo post nell'interfaccia di moderazione", "status.admin_status": "Apri questo post nell'interfaccia di moderazione",
"status.all_disabled": "Condivisioni e citazioni sono disabilitate",
"status.block": "Blocca @{name}", "status.block": "Blocca @{name}",
"status.bookmark": "Aggiungi segnalibro", "status.bookmark": "Aggiungi segnalibro",
"status.cancel_reblog_private": "Annulla reblog", "status.cancel_reblog_private": "Annulla reblog",
"status.cannot_quote": "L'autore ha disabilitato le citazioni su questo post",
"status.cannot_reblog": "Questo post non può essere condiviso", "status.cannot_reblog": "Questo post non può essere condiviso",
"status.context.load_new_replies": "Nuove risposte disponibili", "status.context.load_new_replies": "Nuove risposte disponibili",
"status.context.loading": "Controllo per altre risposte", "status.context.loading": "Controllo per altre risposte",
@ -876,12 +882,16 @@
"status.mute_conversation": "Silenzia conversazione", "status.mute_conversation": "Silenzia conversazione",
"status.open": "Espandi questo post", "status.open": "Espandi questo post",
"status.pin": "Fissa in cima sul profilo", "status.pin": "Fissa in cima sul profilo",
"status.quote": "Cita",
"status.quote.cancel": "Annulla la citazione",
"status.quote_error.filtered": "Nascosto a causa di uno dei tuoi filtri", "status.quote_error.filtered": "Nascosto a causa di uno dei tuoi filtri",
"status.quote_error.not_available": "Post non disponibile", "status.quote_error.not_available": "Post non disponibile",
"status.quote_error.pending_approval": "Post in attesa", "status.quote_error.pending_approval": "Post in attesa",
"status.quote_error.pending_approval_popout.body": "Le citazioni condivise in tutto il Fediverso possono richiedere del tempo per la visualizzazione, poiché server diversi hanno protocolli diversi.", "status.quote_error.pending_approval_popout.body": "Le citazioni condivise in tutto il Fediverso possono richiedere del tempo per la visualizzazione, poiché server diversi hanno protocolli diversi.",
"status.quote_error.pending_approval_popout.title": "Citazione in attesa? Resta calmo", "status.quote_error.pending_approval_popout.title": "Citazione in attesa? Resta calmo",
"status.quote_policy_change": "Cambia chi può citare",
"status.quote_post_author": "Citato un post di @{name}", "status.quote_post_author": "Citato un post di @{name}",
"status.quote_private": "I post privati non possono essere citati",
"status.read_more": "Leggi di più", "status.read_more": "Leggi di più",
"status.reblog": "Reblog", "status.reblog": "Reblog",
"status.reblog_private": "Reblog con visibilità originale", "status.reblog_private": "Reblog con visibilità originale",
@ -896,6 +906,7 @@
"status.reply": "Rispondi", "status.reply": "Rispondi",
"status.replyAll": "Rispondi alla conversazione", "status.replyAll": "Rispondi alla conversazione",
"status.report": "Segnala @{name}", "status.report": "Segnala @{name}",
"status.revoke_quote": "Rimuovi la mia citazione dal post di @{name}",
"status.sensitive_warning": "Contenuto sensibile", "status.sensitive_warning": "Contenuto sensibile",
"status.share": "Condividi", "status.share": "Condividi",
"status.show_less_all": "Mostra meno per tutti", "status.show_less_all": "Mostra meno per tutti",
@ -955,5 +966,17 @@
"video.skip_forward": "Vai avanti", "video.skip_forward": "Vai avanti",
"video.unmute": "Muta", "video.unmute": "Muta",
"video.volume_down": "Abbassa volume", "video.volume_down": "Abbassa volume",
"video.volume_up": "Alza volume" "video.volume_up": "Alza volume",
"visibility_modal.button_title": "Imposta la visibilità",
"visibility_modal.header": "Visibilità e interazione",
"visibility_modal.helper.direct_quoting": "Le menzioni private non possono essere citate.",
"visibility_modal.helper.privacy_editing": "La visibilità dei post pubblicati non può essere modificata.",
"visibility_modal.helper.private_quoting": "I post riservati ai seguaci non possono essere citati.",
"visibility_modal.helper.unlisted_quoting": "Quando le persone ti citano, il loro post verrà nascosto anche dalle timeline di tendenza.",
"visibility_modal.instructions": "Controlla chi può interagire con questo post. Le impostazioni globali si trovano in <link>Preferenze > Altro</link>.",
"visibility_modal.privacy_label": "Privacy",
"visibility_modal.quote_followers": "Solo i seguaci",
"visibility_modal.quote_label": "Cambia chi può citare",
"visibility_modal.quote_nobody": "Nessuno",
"visibility_modal.quote_public": "Chiunque"
} }

View File

@ -23,11 +23,14 @@
"account.edit_profile": "प्रोफाइल सम्पादन गर्नुहोस्", "account.edit_profile": "प्रोफाइल सम्पादन गर्नुहोस्",
"account.enable_notifications": "@{name} ले पोस्ट गर्दा मलाई सूचित गर्नुहोस्", "account.enable_notifications": "@{name} ले पोस्ट गर्दा मलाई सूचित गर्नुहोस्",
"account.endorse": "प्रोफाइलमा फिचर गर्नुहोस्", "account.endorse": "प्रोफाइलमा फिचर गर्नुहोस्",
"account.featured": "फिचर गरिएको",
"account.featured.accounts": "प्रोफाइलहरू",
"account.featured.hashtags": "ह्यासट्यागहरू",
"account.featured_tags.last_status_never": "कुनै पोस्ट छैन", "account.featured_tags.last_status_never": "कुनै पोस्ट छैन",
"account.follow": "फलो गर्नुहोस", "account.follow": "फलो गर्नुहोस",
"account.follow_back": "फलो ब्याक गर्नुहोस्", "account.follow_back": "फलो ब्याक गर्नुहोस्",
"account.followers": "फलोअरहरु", "account.followers": "फलोअरहरु",
"account.followers.empty": "यस प्रयोगकर्तालाई अहिलेसम्म कसैले फलो गर्दैन।", "account.followers.empty": "यस प्रयोगकर्तालाई अहिलेसम्म कसैले फलो गरेको छैन।",
"account.followers_counter": "{count, plural, one {{counter} फलोअर} other {{counter} फलोअरहरू}}", "account.followers_counter": "{count, plural, one {{counter} फलोअर} other {{counter} फलोअरहरू}}",
"account.following": "फलो गर्दै", "account.following": "फलो गर्दै",
"account.following_counter": "{count, plural, one {{counter} फलो गर्दै} other {{counter} फलो गर्दै}}", "account.following_counter": "{count, plural, one {{counter} फलो गर्दै} other {{counter} फलो गर्दै}}",
@ -42,6 +45,7 @@
"account.mute_notifications_short": "सूचनाहरू म्यूट गर्नुहोस्", "account.mute_notifications_short": "सूचनाहरू म्यूट गर्नुहोस्",
"account.mute_short": "म्युट", "account.mute_short": "म्युट",
"account.muted": "म्युट गरिएको", "account.muted": "म्युट गरिएको",
"account.mutual": "तपाईंहरु एकअर्कालाई फलो गर्नुहुन्छ",
"account.no_bio": "कुनै विवरण प्रदान गरिएको छैन।", "account.no_bio": "कुनै विवरण प्रदान गरिएको छैन।",
"account.posts": "पोस्टहरू", "account.posts": "पोस्टहरू",
"account.posts_with_replies": "पोस्ट र जवाफहरू", "account.posts_with_replies": "पोस्ट र जवाफहरू",
@ -53,6 +57,7 @@
"account.statuses_counter": "{count, plural, one {{counter} पोस्ट} other {{counter} पोस्टहरू}}", "account.statuses_counter": "{count, plural, one {{counter} पोस्ट} other {{counter} पोस्टहरू}}",
"account.unblock": "@{name} लाई अनब्लक गर्नुहोस्", "account.unblock": "@{name} लाई अनब्लक गर्नुहोस्",
"account.unblock_domain": "{domain} डोमेनलाई अनब्लक गर्नुहोस्", "account.unblock_domain": "{domain} डोमेनलाई अनब्लक गर्नुहोस्",
"account.unblock_domain_short": "अनब्लक गर्नुहोस्",
"account.unblock_short": "अनब्लक गर्नुहोस्", "account.unblock_short": "अनब्लक गर्नुहोस्",
"account.unendorse": "प्रोफाइलमा फिचर नगर्नुहोस्", "account.unendorse": "प्रोफाइलमा फिचर नगर्नुहोस्",
"account.unfollow": "अनफलो गर्नुहोस्", "account.unfollow": "अनफलो गर्नुहोस्",
@ -64,6 +69,7 @@
"admin.dashboard.retention.cohort_size": "नयाँ प्रयोगकर्ताहरू", "admin.dashboard.retention.cohort_size": "नयाँ प्रयोगकर्ताहरू",
"alert.rate_limited.message": "कृपया {retry_time, time, medium} पछि पुन: प्रयास गर्नुहोस्।", "alert.rate_limited.message": "कृपया {retry_time, time, medium} पछि पुन: प्रयास गर्नुहोस्।",
"alert.unexpected.message": "एउटा अनपेक्षित त्रुटि भयो।", "alert.unexpected.message": "एउटा अनपेक्षित त्रुटि भयो।",
"alt_text_modal.cancel": "रद्द गर्नुहोस्",
"announcement.announcement": "घोषणा", "announcement.announcement": "घोषणा",
"annual_report.summary.followers.followers": "फलोअरहरु", "annual_report.summary.followers.followers": "फलोअरहरु",
"annual_report.summary.highlighted_post.by_reblogs": "सबैभन्दा बढि बूस्ट गरिएको पोस्ट", "annual_report.summary.highlighted_post.by_reblogs": "सबैभन्दा बढि बूस्ट गरिएको पोस्ट",
@ -156,8 +162,13 @@
"notification_requests.confirm_accept_multiple.title": "सूचना अनुरोधहरू स्वीकार गर्ने?", "notification_requests.confirm_accept_multiple.title": "सूचना अनुरोधहरू स्वीकार गर्ने?",
"notification_requests.confirm_dismiss_multiple.title": "सूचना अनुरोधहरू खारेज गर्ने?", "notification_requests.confirm_dismiss_multiple.title": "सूचना अनुरोधहरू खारेज गर्ने?",
"notifications.clear_title": "सूचनाहरू खाली गर्ने?", "notifications.clear_title": "सूचनाहरू खाली गर्ने?",
"notifications.column_settings.follow": "नयाँ फलोअरहरु:",
"notifications.column_settings.follow_request": "नयाँ फलोअर अनुरोधहरु",
"notifications.column_settings.reblog": "बूस्टहरू:", "notifications.column_settings.reblog": "बूस्टहरू:",
"notifications.filter.boosts": "बूस्टहरू", "notifications.filter.boosts": "बूस्टहरू",
"privacy.private.long": "मात्र तपाईंको फलोअरहरु",
"privacy.private.short": "फलोअरहरु",
"reply_indicator.cancel": "रद्द गर्नुहोस्",
"report.comment.title": "के हामीले थाहा पाउनुपर्ने अरू केही छ जस्तो लाग्छ?", "report.comment.title": "के हामीले थाहा पाउनुपर्ने अरू केही छ जस्तो लाग्छ?",
"report.forward_hint": "यो खाता अर्को सर्भरबाट हो। त्यहाँ पनि रिपोर्टको गुमनाम प्रतिलिपि पठाउने हो?", "report.forward_hint": "यो खाता अर्को सर्भरबाट हो। त्यहाँ पनि रिपोर्टको गुमनाम प्रतिलिपि पठाउने हो?",
"report.rules.title": "कुन नियमहरू उल्लङ्घन भइरहेका छन्?", "report.rules.title": "कुन नियमहरू उल्लङ्घन भइरहेका छन्?",
@ -172,5 +183,6 @@
"status.reblog": "बूस्ट गर्नुहोस्", "status.reblog": "बूस्ट गर्नुहोस्",
"status.reblogged_by": "{name} ले बूस्ट गर्नुभएको", "status.reblogged_by": "{name} ले बूस्ट गर्नुभएको",
"status.reblogs": "{count, plural, one {बूस्ट} other {बूस्टहरू}}", "status.reblogs": "{count, plural, one {बूस्ट} other {बूस्टहरू}}",
"status.unmute_conversation": "कुराकानी अनम्यूट गर्नुहोस्" "status.unmute_conversation": "कुराकानी अनम्यूट गर्नुहोस्",
"visibility_modal.quote_followers": "फलोअरहरु मात्र"
} }

View File

@ -350,14 +350,14 @@
"featured_carousel.previous": "Предыдущий", "featured_carousel.previous": "Предыдущий",
"featured_carousel.slide": "{index} из {total}", "featured_carousel.slide": "{index} из {total}",
"filter_modal.added.context_mismatch_explanation": "Этот фильтр не применяется в том контексте, в котором вы видели этот пост. Если вы хотите, чтобы пост был отфильтрован в текущем контексте, необходимо редактировать фильтр.", "filter_modal.added.context_mismatch_explanation": "Этот фильтр не применяется в том контексте, в котором вы видели этот пост. Если вы хотите, чтобы пост был отфильтрован в текущем контексте, необходимо редактировать фильтр.",
"filter_modal.added.context_mismatch_title": "Несоответствие контекста!", "filter_modal.added.context_mismatch_title": "Несоответствие контекста",
"filter_modal.added.expired_explanation": "Этот фильтр истёк. Чтобы он был применён, вам нужно изменить срок действия фильтра.", "filter_modal.added.expired_explanation": "Этот фильтр истёк. Чтобы он был применён, вам нужно изменить срок действия фильтра.",
"filter_modal.added.expired_title": "Истёкший фильтр!", "filter_modal.added.expired_title": "Истёкший фильтр",
"filter_modal.added.review_and_configure": "Для просмотра или редактирования этого фильтра перейдите в {settings_link}.", "filter_modal.added.review_and_configure": "Для просмотра или редактирования этого фильтра перейдите в {settings_link}.",
"filter_modal.added.review_and_configure_title": "Настройки фильтра", "filter_modal.added.review_and_configure_title": "Настройки фильтра",
"filter_modal.added.settings_link": "настройки", "filter_modal.added.settings_link": "настройки",
"filter_modal.added.short_explanation": "Этот пост был добавлен к фильтру «{title}».", "filter_modal.added.short_explanation": "Этот пост был добавлен к фильтру «{title}».",
"filter_modal.added.title": "Фильтр добавлен!", "filter_modal.added.title": "Фильтр добавлен",
"filter_modal.select_filter.context_mismatch": "не применяется в этом контексте", "filter_modal.select_filter.context_mismatch": "не применяется в этом контексте",
"filter_modal.select_filter.expired": "истёкший", "filter_modal.select_filter.expired": "истёкший",
"filter_modal.select_filter.prompt_new": "Новый фильтр: {name}", "filter_modal.select_filter.prompt_new": "Новый фильтр: {name}",
@ -433,7 +433,7 @@
"home.hide_announcements": "Скрыть объявления", "home.hide_announcements": "Скрыть объявления",
"home.pending_critical_update.body": "Пожалуйста, обновите свой сервер Mastodon как можно скорее!", "home.pending_critical_update.body": "Пожалуйста, обновите свой сервер Mastodon как можно скорее!",
"home.pending_critical_update.link": "Посмотреть обновления", "home.pending_critical_update.link": "Посмотреть обновления",
"home.pending_critical_update.title": "Доступно критическое обновление безопасности!", "home.pending_critical_update.title": "Доступно критическое обновление безопасности",
"home.show_announcements": "Показать объявления", "home.show_announcements": "Показать объявления",
"ignore_notifications_modal.disclaimer": "Mastodon не может сообщить пользователям, что вы игнорируете их уведомления. Игнорирование уведомлений не остановит отправку самих сообщений.", "ignore_notifications_modal.disclaimer": "Mastodon не может сообщить пользователям, что вы игнорируете их уведомления. Игнорирование уведомлений не остановит отправку самих сообщений.",
"ignore_notifications_modal.filter_instead": "Фильтровать", "ignore_notifications_modal.filter_instead": "Фильтровать",
@ -590,7 +590,7 @@
"notification.admin.report_statuses_other": "{name} пожаловался (-лась) на {target}", "notification.admin.report_statuses_other": "{name} пожаловался (-лась) на {target}",
"notification.admin.sign_up": "{name} зарегистрировался (-лась) на сервере", "notification.admin.sign_up": "{name} зарегистрировался (-лась) на сервере",
"notification.admin.sign_up.name_and_others": "{name} и ещё {count, plural, one {# пользователь} few {# пользователя} other {# пользователей}} зарегистрировались на сервере", "notification.admin.sign_up.name_and_others": "{name} и ещё {count, plural, one {# пользователь} few {# пользователя} other {# пользователей}} зарегистрировались на сервере",
"notification.annual_report.message": "#Wrapstodon за {year} год ждёт вас! Откройте для себя итоги и памятные моменты этого года в Mastodon!", "notification.annual_report.message": "#Wrapstodon за {year} год ждёт вас! Откройте для себя итоги и памятные моменты этого года в Mastodon.",
"notification.annual_report.view": "Перейти к #Wrapstodon", "notification.annual_report.view": "Перейти к #Wrapstodon",
"notification.favourite": "{name} добавил(а) ваш пост в избранное", "notification.favourite": "{name} добавил(а) ваш пост в избранное",
"notification.favourite.name_and_others_with_link": "{name} и ещё <a>{count, plural, one {# пользователь} few {# пользователя} other {# пользователей}}</a> добавили ваш пост в избранное", "notification.favourite.name_and_others_with_link": "{name} и ещё <a>{count, plural, one {# пользователь} few {# пользователя} other {# пользователей}}</a> добавили ваш пост в избранное",
@ -861,7 +861,7 @@
"status.direct": "Упомянуть @{name} лично", "status.direct": "Упомянуть @{name} лично",
"status.direct_indicator": "Личное упоминание", "status.direct_indicator": "Личное упоминание",
"status.edit": "Редактировать", "status.edit": "Редактировать",
"status.edited": "Дата последнего изменения: {date}", "status.edited": "Последнее изменение: {date}",
"status.edited_x_times": "{count, plural, one {{count} изменение} many {{count} изменений} other {{count} изменения}}", "status.edited_x_times": "{count, plural, one {{count} изменение} many {{count} изменений} other {{count} изменения}}",
"status.embed": "Встроить на свой сайт", "status.embed": "Встроить на свой сайт",
"status.favourite": "Добавить в избранное", "status.favourite": "Добавить в избранное",

View File

@ -246,6 +246,7 @@
"confirmations.remove_from_followers.message": "{name} kommer att sluta följa dig. Är du säker på att du vill fortsätta?", "confirmations.remove_from_followers.message": "{name} kommer att sluta följa dig. Är du säker på att du vill fortsätta?",
"confirmations.remove_from_followers.title": "Ta bort följare?", "confirmations.remove_from_followers.title": "Ta bort följare?",
"confirmations.revoke_quote.confirm": "Ta bort inlägg", "confirmations.revoke_quote.confirm": "Ta bort inlägg",
"confirmations.revoke_quote.message": "Denna åtgärd kan inte ångras.",
"confirmations.revoke_quote.title": "Ta bort inlägg?", "confirmations.revoke_quote.title": "Ta bort inlägg?",
"confirmations.unfollow.confirm": "Avfölj", "confirmations.unfollow.confirm": "Avfölj",
"confirmations.unfollow.message": "Är du säker på att du vill avfölja {name}?", "confirmations.unfollow.message": "Är du säker på att du vill avfölja {name}?",
@ -603,6 +604,7 @@
"notification.label.mention": "Nämn", "notification.label.mention": "Nämn",
"notification.label.private_mention": "Privat omnämnande", "notification.label.private_mention": "Privat omnämnande",
"notification.label.private_reply": "Privata svar", "notification.label.private_reply": "Privata svar",
"notification.label.quote": "{name} citerade ditt inlägg",
"notification.label.reply": "Svar", "notification.label.reply": "Svar",
"notification.mention": "Nämn", "notification.mention": "Nämn",
"notification.mentioned_you": "{name} nämnde dig", "notification.mentioned_you": "{name} nämnde dig",
@ -660,6 +662,7 @@
"notifications.column_settings.mention": "Omnämningar:", "notifications.column_settings.mention": "Omnämningar:",
"notifications.column_settings.poll": "Omröstningsresultat:", "notifications.column_settings.poll": "Omröstningsresultat:",
"notifications.column_settings.push": "Push-aviseringar", "notifications.column_settings.push": "Push-aviseringar",
"notifications.column_settings.quote": "Citerat:",
"notifications.column_settings.reblog": "Boostar:", "notifications.column_settings.reblog": "Boostar:",
"notifications.column_settings.show": "Visa i kolumnen", "notifications.column_settings.show": "Visa i kolumnen",
"notifications.column_settings.sound": "Spela upp ljud", "notifications.column_settings.sound": "Spela upp ljud",
@ -877,8 +880,14 @@
"status.mute_conversation": "Tysta konversation", "status.mute_conversation": "Tysta konversation",
"status.open": "Utvidga detta inlägg", "status.open": "Utvidga detta inlägg",
"status.pin": "Fäst i profil", "status.pin": "Fäst i profil",
"status.quote.cancel": "Återkalla citering",
"status.quote_error.filtered": "Dolt på grund av ett av dina filter", "status.quote_error.filtered": "Dolt på grund av ett av dina filter",
"status.quote_error.not_available": "Inlägg ej tillgängligt", "status.quote_error.not_available": "Inlägg ej tillgängligt",
"status.quote_error.pending_approval": "Väntande inlägg",
"status.quote_error.pending_approval_popout.body": "Citat som delas över Fediverse kan ta tid att visa, eftersom olika servrar har olika protokoll.",
"status.quote_error.pending_approval_popout.title": "Väntande citat? Förbli lugn",
"status.quote_policy_change": "Ändra vem som kan citera",
"status.quote_post_author": "Citerade ett inlägg av @{name}",
"status.read_more": "Läs mer", "status.read_more": "Läs mer",
"status.reblog": "Boosta", "status.reblog": "Boosta",
"status.reblog_private": "Boosta med ursprunglig synlighet", "status.reblog_private": "Boosta med ursprunglig synlighet",
@ -893,6 +902,7 @@
"status.reply": "Svara", "status.reply": "Svara",
"status.replyAll": "Svara på tråden", "status.replyAll": "Svara på tråden",
"status.report": "Rapportera @{name}", "status.report": "Rapportera @{name}",
"status.revoke_quote": "Ta bort mitt inlägg från @{name}s inlägg",
"status.sensitive_warning": "Känsligt innehåll", "status.sensitive_warning": "Känsligt innehåll",
"status.share": "Dela", "status.share": "Dela",
"status.show_less_all": "Visa mindre för alla", "status.show_less_all": "Visa mindre för alla",
@ -953,9 +963,16 @@
"video.unmute": "Avtysta", "video.unmute": "Avtysta",
"video.volume_down": "Volym ned", "video.volume_down": "Volym ned",
"video.volume_up": "Volym upp", "video.volume_up": "Volym upp",
"visibility_modal.button_title": "Ange synlighet",
"visibility_modal.header": "Synlighet och interaktion", "visibility_modal.header": "Synlighet och interaktion",
"visibility_modal.helper.direct_quoting": "Privata omnämnanden kan inte bli citerade.",
"visibility_modal.helper.privacy_editing": "Publicerade inlägg kan inte ändra deras synlighet.",
"visibility_modal.helper.private_quoting": "Inlägg som endast är synliga för följare kan inte citeras.",
"visibility_modal.helper.unlisted_quoting": "När folk citerar dig, deras inlägg kommer också att döljas från trendiga tidslinjer.",
"visibility_modal.instructions": "Kontrollera vem som kan interagera med det här inlägget. Globala inställningar kan hittas under <link>Inställningar > Andra</link>.",
"visibility_modal.privacy_label": "Integritet", "visibility_modal.privacy_label": "Integritet",
"visibility_modal.quote_followers": "Endast följare", "visibility_modal.quote_followers": "Endast följare",
"visibility_modal.quote_label": "Ändra vem som kan citera",
"visibility_modal.quote_nobody": "Ingen", "visibility_modal.quote_nobody": "Ingen",
"visibility_modal.quote_public": "Alla" "visibility_modal.quote_public": "Alla"
} }

View File

@ -292,6 +292,7 @@
"domain_pill.your_handle": "Tanıtıcınız:", "domain_pill.your_handle": "Tanıtıcınız:",
"domain_pill.your_server": "Dijital anasayfanız, tüm gönderilerinizin yaşadığı yerdir. Bunu beğenmediniz mi? İstediğiniz zaman sunucularınızı değiştirin ve takipçilerinizi de getirin.", "domain_pill.your_server": "Dijital anasayfanız, tüm gönderilerinizin yaşadığı yerdir. Bunu beğenmediniz mi? İstediğiniz zaman sunucularınızı değiştirin ve takipçilerinizi de getirin.",
"domain_pill.your_username": "Bu sunucudaki tekil tanımlayıcınız. Farklı sunucularda aynı kullanıcı adına sahip kullanıcıları bulmak mümkündür.", "domain_pill.your_username": "Bu sunucudaki tekil tanımlayıcınız. Farklı sunucularda aynı kullanıcı adına sahip kullanıcıları bulmak mümkündür.",
"dropdown.empty": "Bir seçenek seçin",
"embed.instructions": "Aşağıdaki kodu kopyalayarak bu durumu sitenize gömün.", "embed.instructions": "Aşağıdaki kodu kopyalayarak bu durumu sitenize gömün.",
"embed.preview": "İşte nasıl görüneceği:", "embed.preview": "İşte nasıl görüneceği:",
"emoji_button.activity": "Aktivite", "emoji_button.activity": "Aktivite",
@ -848,9 +849,11 @@
"status.admin_account": "@{name} için denetim arayüzünü açın", "status.admin_account": "@{name} için denetim arayüzünü açın",
"status.admin_domain": "{domain} için denetim arayüzünü açın", "status.admin_domain": "{domain} için denetim arayüzünü açın",
"status.admin_status": "Denetim arayüzünde bu gönderiyi açın", "status.admin_status": "Denetim arayüzünde bu gönderiyi açın",
"status.all_disabled": "Yükseltmeler ve alıntılar devre dışı bırakıldı",
"status.block": "@{name} adlı kişiyi engelle", "status.block": "@{name} adlı kişiyi engelle",
"status.bookmark": "Yer işareti ekle", "status.bookmark": "Yer işareti ekle",
"status.cancel_reblog_private": "Yeniden paylaşımı geri al", "status.cancel_reblog_private": "Yeniden paylaşımı geri al",
"status.cannot_quote": "Yazar bu gönderide alıntılamayı devre dışı bıraktı",
"status.cannot_reblog": "Bu gönderi yeniden paylaşılamaz", "status.cannot_reblog": "Bu gönderi yeniden paylaşılamaz",
"status.context.load_new_replies": "Yeni yanıtlar mevcut", "status.context.load_new_replies": "Yeni yanıtlar mevcut",
"status.context.loading": "Daha fazla yanıt için kontrol ediliyor", "status.context.loading": "Daha fazla yanıt için kontrol ediliyor",
@ -879,12 +882,16 @@
"status.mute_conversation": "Sohbeti sessize al", "status.mute_conversation": "Sohbeti sessize al",
"status.open": "Bu gönderiyi genişlet", "status.open": "Bu gönderiyi genişlet",
"status.pin": "Profile sabitle", "status.pin": "Profile sabitle",
"status.quote": "Teklif",
"status.quote.cancel": "Teklifi iptal et",
"status.quote_error.filtered": "Bazı filtrelerinizden dolayı gizlenmiştir", "status.quote_error.filtered": "Bazı filtrelerinizden dolayı gizlenmiştir",
"status.quote_error.not_available": "Gönderi kullanılamıyor", "status.quote_error.not_available": "Gönderi kullanılamıyor",
"status.quote_error.pending_approval": "Gönderi beklemede", "status.quote_error.pending_approval": "Gönderi beklemede",
"status.quote_error.pending_approval_popout.body": "Fediverse genelinde paylaşılan alıntıların görüntülenmesi zaman alabilir, çünkü farklı sunucuların farklı protokolleri vardır.", "status.quote_error.pending_approval_popout.body": "Fediverse genelinde paylaşılan alıntıların görüntülenmesi zaman alabilir, çünkü farklı sunucuların farklı protokolleri vardır.",
"status.quote_error.pending_approval_popout.title": "Bekleyen bir teklif mi var? Sakin olun.", "status.quote_error.pending_approval_popout.title": "Bekleyen bir teklif mi var? Sakin olun.",
"status.quote_policy_change": "Kimin alıntı yapabileceğini değiştirin",
"status.quote_post_author": "@{name} adlı kullanıcının bir gönderisini alıntıladı", "status.quote_post_author": "@{name} adlı kullanıcının bir gönderisini alıntıladı",
"status.quote_private": "Özel gönderiler alıntılanamaz",
"status.read_more": "Devamını okuyun", "status.read_more": "Devamını okuyun",
"status.reblog": "Yeniden paylaş", "status.reblog": "Yeniden paylaş",
"status.reblog_private": "Özgün görünürlük ile yeniden paylaş", "status.reblog_private": "Özgün görünürlük ile yeniden paylaş",
@ -959,5 +966,17 @@
"video.skip_forward": "İleriye atla", "video.skip_forward": "İleriye atla",
"video.unmute": "Sesi aç", "video.unmute": "Sesi aç",
"video.volume_down": "Sesi kıs", "video.volume_down": "Sesi kıs",
"video.volume_up": "Sesi yükselt" "video.volume_up": "Sesi yükselt",
"visibility_modal.button_title": "Görünürlüğü ayarla",
"visibility_modal.header": "Görünürlük ve etkileşim",
"visibility_modal.helper.direct_quoting": "Özel gönderiler alıntılanamaz.",
"visibility_modal.helper.privacy_editing": "Yayınlanan gönderilerin görünürlüğü değiştirilemez.",
"visibility_modal.helper.private_quoting": "Sadece takipçilere özel paylaşımlar alıntılanamaz.",
"visibility_modal.helper.unlisted_quoting": "İnsanlar sizden alıntı yaptığında, onların gönderileri de trend zaman tünellerinden gizlenecektir.",
"visibility_modal.instructions": "Bu gönderiyle kimlerin etkileşimde bulunabileceğini kontrol edin. Genel ayarlara <link>Tercihler > Diğer</link> bölümünden ulaşabilirsiniz.",
"visibility_modal.privacy_label": "Gizlilik",
"visibility_modal.quote_followers": "Sadece takipçiler",
"visibility_modal.quote_label": "Kimin alıntı yapabileceğini değiştirin",
"visibility_modal.quote_nobody": "Kimseden",
"visibility_modal.quote_public": "Herkesten"
} }

View File

@ -849,9 +849,11 @@
"status.admin_account": "Mở giao diện quản trị @{name}", "status.admin_account": "Mở giao diện quản trị @{name}",
"status.admin_domain": "Mở giao diện quản trị @{domain}", "status.admin_domain": "Mở giao diện quản trị @{domain}",
"status.admin_status": "Mở tút này trong giao diện quản trị", "status.admin_status": "Mở tút này trong giao diện quản trị",
"status.all_disabled": "Đăng lại và trích dẫn bị tắt",
"status.block": "Chặn @{name}", "status.block": "Chặn @{name}",
"status.bookmark": "Lưu", "status.bookmark": "Lưu",
"status.cancel_reblog_private": "Bỏ đăng lại", "status.cancel_reblog_private": "Bỏ đăng lại",
"status.cannot_quote": "Tác giả không cho phép trích dẫn tút này",
"status.cannot_reblog": "Không thể đăng lại tút này", "status.cannot_reblog": "Không thể đăng lại tút này",
"status.context.load_new_replies": "Có những trả lời mới", "status.context.load_new_replies": "Có những trả lời mới",
"status.context.loading": "Kiểm tra nhiều trả lời hơn", "status.context.loading": "Kiểm tra nhiều trả lời hơn",
@ -880,6 +882,7 @@
"status.mute_conversation": "Tắt thông báo", "status.mute_conversation": "Tắt thông báo",
"status.open": "Mở tút", "status.open": "Mở tút",
"status.pin": "Ghim lên hồ sơ", "status.pin": "Ghim lên hồ sơ",
"status.quote": "Trích dẫn",
"status.quote.cancel": "Bỏ trích dẫn", "status.quote.cancel": "Bỏ trích dẫn",
"status.quote_error.filtered": "Bị ẩn vì một bộ lọc của bạn", "status.quote_error.filtered": "Bị ẩn vì một bộ lọc của bạn",
"status.quote_error.not_available": "Tút không khả dụng", "status.quote_error.not_available": "Tút không khả dụng",
@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Đang chờ trích dẫn? Hãy bình tĩnh", "status.quote_error.pending_approval_popout.title": "Đang chờ trích dẫn? Hãy bình tĩnh",
"status.quote_policy_change": "Thay đổi người có thể trích dẫn", "status.quote_policy_change": "Thay đổi người có thể trích dẫn",
"status.quote_post_author": "Trích dẫn từ tút của @{name}", "status.quote_post_author": "Trích dẫn từ tút của @{name}",
"status.quote_private": "Không thể trích dẫn nhắn riêng",
"status.read_more": "Đọc tiếp", "status.read_more": "Đọc tiếp",
"status.reblog": "Đăng lại", "status.reblog": "Đăng lại",
"status.reblog_private": "Đăng lại (Riêng tư)", "status.reblog_private": "Đăng lại (Riêng tư)",

View File

@ -849,9 +849,11 @@
"status.admin_account": "開啟 @{name} 的管理介面", "status.admin_account": "開啟 @{name} 的管理介面",
"status.admin_domain": "開啟 {domain} 的管理介面", "status.admin_domain": "開啟 {domain} 的管理介面",
"status.admin_status": "於管理介面開啟此嘟文", "status.admin_status": "於管理介面開啟此嘟文",
"status.all_disabled": "已停用轉嘟與引用",
"status.block": "封鎖 @{name}", "status.block": "封鎖 @{name}",
"status.bookmark": "書籤", "status.bookmark": "書籤",
"status.cancel_reblog_private": "取消轉嘟", "status.cancel_reblog_private": "取消轉嘟",
"status.cannot_quote": "作者已停用引用此嘟文",
"status.cannot_reblog": "這則嘟文無法被轉嘟", "status.cannot_reblog": "這則嘟文無法被轉嘟",
"status.context.load_new_replies": "有新回嘟", "status.context.load_new_replies": "有新回嘟",
"status.context.loading": "正在檢查更多回嘟", "status.context.loading": "正在檢查更多回嘟",
@ -880,6 +882,7 @@
"status.mute_conversation": "靜音對話", "status.mute_conversation": "靜音對話",
"status.open": "展開此嘟文", "status.open": "展開此嘟文",
"status.pin": "釘選至個人檔案頁面", "status.pin": "釘選至個人檔案頁面",
"status.quote": "引用",
"status.quote.cancel": "取消引用嘟文", "status.quote.cancel": "取消引用嘟文",
"status.quote_error.filtered": "由於您的過濾器,該嘟文被隱藏", "status.quote_error.filtered": "由於您的過濾器,該嘟文被隱藏",
"status.quote_error.not_available": "無法取得該嘟文", "status.quote_error.not_available": "無法取得該嘟文",
@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "引用嘟文正在發送中?別著急,請稍候片刻", "status.quote_error.pending_approval_popout.title": "引用嘟文正在發送中?別著急,請稍候片刻",
"status.quote_policy_change": "變更可以引用的人", "status.quote_policy_change": "變更可以引用的人",
"status.quote_post_author": "已引用 @{name} 之嘟文", "status.quote_post_author": "已引用 @{name} 之嘟文",
"status.quote_private": "無法引用私人嘟文",
"status.read_more": "閱讀更多", "status.read_more": "閱讀更多",
"status.reblog": "轉嘟", "status.reblog": "轉嘟",
"status.reblog_private": "依照原嘟可見性轉嘟", "status.reblog_private": "依照原嘟可見性轉嘟",

View File

@ -1,10 +1,12 @@
import type { KeyboardEvent, MouseEvent, TouchEvent } from 'react';
interface BaseMenuItem { interface BaseMenuItem {
text: string; text: string;
dangerous?: boolean; dangerous?: boolean;
} }
export interface ActionMenuItem extends BaseMenuItem { export interface ActionMenuItem extends BaseMenuItem {
action: () => void; action: (event: MouseEvent | KeyboardEvent | TouchEvent) => void;
} }
export interface LinkMenuItem extends BaseMenuItem { export interface LinkMenuItem extends BaseMenuItem {

View File

@ -2,9 +2,9 @@ import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrde
import { import {
changeUploadCompose, changeUploadCompose,
quoteComposeByStatus, quoteCompose,
quoteComposeCancel, quoteComposeCancel,
setQuotePolicy, setComposeQuotePolicy,
} from 'mastodon/actions/compose_typed'; } from 'mastodon/actions/compose_typed';
import { timelineDelete } from 'mastodon/actions/timelines_typed'; import { timelineDelete } from 'mastodon/actions/timelines_typed';
@ -329,22 +329,15 @@ export const composeReducer = (state = initialState, action) => {
return state.set('is_changing_upload', true); return state.set('is_changing_upload', true);
} else if (changeUploadCompose.rejected.match(action)) { } else if (changeUploadCompose.rejected.match(action)) {
return state.set('is_changing_upload', false); return state.set('is_changing_upload', false);
} else if (quoteComposeByStatus.match(action)) { } else if (quoteCompose.match(action)) {
const status = action.payload; const status = action.payload;
if ( return state
status.getIn(['quote_approval', 'current_user']) === 'automatic' && .set('quoted_status_id', status.get('id'))
state.get('media_attachments').size === 0 && .set('spoiler', status.get('sensitive'))
!state.get('is_uploading') && .set('spoiler_text', status.get('spoiler_text'));
!state.get('poll')
) {
return state
.set('quoted_status_id', status.get('id'))
.set('spoiler', status.get('sensitive'))
.set('spoiler_text', status.get('spoiler_text'));
}
} else if (quoteComposeCancel.match(action)) { } else if (quoteComposeCancel.match(action)) {
return state.set('quoted_status_id', null); return state.set('quoted_status_id', null);
} else if (setQuotePolicy.match(action)) { } else if (setComposeQuotePolicy.match(action)) {
return state.set('quote_policy', action.payload); return state.set('quote_policy', action.payload);
} }
@ -520,6 +513,7 @@ export const composeReducer = (state = initialState, action) => {
map.set('sensitive', action.status.get('sensitive')); map.set('sensitive', action.status.get('sensitive'));
map.set('language', action.status.get('language')); map.set('language', action.status.get('language'));
map.set('id', null); map.set('id', null);
map.set('quoted_status_id', action.status.getIn(['quote', 'quoted_status']));
// Mastodon-authored posts can be expected to have at most one automatic approval policy // Mastodon-authored posts can be expected to have at most one automatic approval policy
map.set('quote_policy', action.status.getIn(['quote_approval', 'automatic', 0]) || 'nobody'); map.set('quote_policy', action.status.getIn(['quote_approval', 'automatic', 0]) || 'nobody');
@ -551,6 +545,7 @@ export const composeReducer = (state = initialState, action) => {
map.set('idempotencyKey', uuid()); map.set('idempotencyKey', uuid());
map.set('sensitive', action.status.get('sensitive')); map.set('sensitive', action.status.get('sensitive'));
map.set('language', action.status.get('language')); map.set('language', action.status.get('language'));
map.set('quoted_status_id', action.status.getIn(['quote', 'quoted_status']));
// Mastodon-authored posts can be expected to have at most one automatic approval policy // Mastodon-authored posts can be expected to have at most one automatic approval policy
map.set('quote_policy', action.status.getIn(['quote_approval', 'automatic', 0]) || 'nobody'); map.set('quote_policy', action.status.getIn(['quote_approval', 'automatic', 0]) || 'nobody');

View File

@ -15,7 +15,7 @@ export const getFilters = createSelector(
(_, { contextType }: { contextType: string }) => contextType, (_, { contextType }: { contextType: string }) => contextType,
], ],
(filters, contextType) => { (filters, contextType) => {
if (!contextType || contextType === 'compose') { if (!contextType) {
return null; return null;
} }

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><path d="M791-56 425-422 320-240h-92l92-160q-66 0-113-47t-47-113q0-27 8.5-51t23.5-44L56-791l56-57 736 736-57 56Zm-55-281L520-553v-7q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T818-480l-82 143ZM320-500q6 0 12-1t11-3l-79-79q-2 5-3 11t-1 12q0 25 17.5 42.5T320-500Zm360 0q25 0 42.5-17.5T740-560q0-25-17.5-42.5T680-620q-25 0-42.5 17.5T620-560q0 25 17.5 42.5T680-500Zm-374-41Zm374-19Z"/></svg>

After

Width:  |  Height:  |  Size: 488 B

View File

@ -1482,18 +1482,19 @@ body > [data-popper-placement] {
border-bottom: 0; border-bottom: 0;
.status__content, & > .status__content,
.status__action-bar, & > .status__action-bar,
.media-gallery, & > .media-gallery,
.video-player, & > .video-player,
.audio-player, & > .audio-player,
.attachment-list, & > .attachment-list,
.picture-in-picture-placeholder, & > .picture-in-picture-placeholder,
.more-from-author, & > .more-from-author,
.status-card, & > .status-card,
.hashtag-bar, & > .hashtag-bar,
.content-warning, & > .content-warning,
.filter-warning { & > .filter-warning,
& > .status__quote {
margin-inline-start: var(--thread-margin); margin-inline-start: var(--thread-margin);
width: calc(100% - var(--thread-margin)); width: calc(100% - var(--thread-margin));
} }
@ -2383,6 +2384,7 @@ a .account__avatar {
.detailed-status__display-name, .detailed-status__display-name,
.detailed-status__datetime, .detailed-status__datetime,
.detailed-status__application, .detailed-status__application,
.detailed-status__link,
.account__display-name { .account__display-name {
text-decoration: none; text-decoration: none;
} }
@ -2415,7 +2417,8 @@ a.account__display-name {
} }
.detailed-status__application, .detailed-status__application,
.detailed-status__datetime { .detailed-status__datetime,
.detailed-status__link {
color: inherit; color: inherit;
} }
@ -2601,8 +2604,9 @@ a.account__display-name {
} }
.status__relative-time, .status__relative-time,
.detailed-status__datetime { .detailed-status__datetime,
&:hover { .detailed-status__link {
&:is(a):hover {
text-decoration: underline; text-decoration: underline;
} }
} }
@ -2856,10 +2860,43 @@ a.account__display-name {
&:focus, &:focus,
&:hover, &:hover,
&:active { &:active {
background: var(--dropdown-border-color); &:not(:disabled) {
outline: 0; background: var(--dropdown-border-color);
outline: 0;
}
} }
} }
button:disabled {
color: $dark-text-color;
cursor: default;
}
}
.reblog-button {
&__item {
width: 280px;
button {
display: flex;
align-items: center;
gap: 8px;
white-space: inherit;
}
div {
display: flex;
flex-direction: column;
}
&.active:not(.disabled) {
color: $highlight-text-color;
}
}
&__meta {
font-weight: 400;
}
} }
.inline-account { .inline-account {
@ -5478,7 +5515,10 @@ a.status-card {
.privacy-dropdown__option__content, .privacy-dropdown__option__content,
.privacy-dropdown__option__content strong, .privacy-dropdown__option__content strong,
.privacy-dropdown__option__additional { .privacy-dropdown__option__additional,
.visibility-dropdown__option__content,
.visibility-dropdown__option__content strong,
.visibility-dropdown__option__additional {
color: $primary-text-color; color: $primary-text-color;
} }
} }
@ -5492,13 +5532,15 @@ a.status-card {
} }
} }
.privacy-dropdown__option__icon { .privacy-dropdown__option__icon,
.visibility-dropdown__option__icon {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.privacy-dropdown__option__content { .privacy-dropdown__option__content,
.visibility-dropdown__option__content {
flex: 1 1 auto; flex: 1 1 auto;
color: $darker-text-color; color: $darker-text-color;

View File

@ -1,9 +1,13 @@
import { Map as ImmutableMap } from 'immutable';
import type { ApiRelationshipJSON } from '@/mastodon/api_types/relationships'; import type { ApiRelationshipJSON } from '@/mastodon/api_types/relationships';
import type { ApiStatusJSON } from '@/mastodon/api_types/statuses';
import type { import type {
CustomEmojiData, CustomEmojiData,
UnicodeEmojiData, UnicodeEmojiData,
} from '@/mastodon/features/emoji/types'; } from '@/mastodon/features/emoji/types';
import { createAccountFromServerJSON } from '@/mastodon/models/account'; import { createAccountFromServerJSON } from '@/mastodon/models/account';
import type { Status } from '@/mastodon/models/status';
import type { ApiAccountJSON } from 'mastodon/api_types/accounts'; import type { ApiAccountJSON } from 'mastodon/api_types/accounts';
type FactoryOptions<T> = { type FactoryOptions<T> = {
@ -51,6 +55,36 @@ export const accountFactoryState = (
options: FactoryOptions<ApiAccountJSON> = {}, options: FactoryOptions<ApiAccountJSON> = {},
) => createAccountFromServerJSON(accountFactory(options)); ) => createAccountFromServerJSON(accountFactory(options));
export const statusFactory: FactoryFunction<ApiStatusJSON> = ({
id,
...data
} = {}) => ({
id: id ?? '1',
created_at: '2023-01-01T00:00:00.000Z',
sensitive: false,
visibility: 'public',
language: 'en',
uri: 'https://example.com/status/1',
url: 'https://example.com/status/1',
replies_count: 0,
reblogs_count: 0,
favorites_count: 0,
account: accountFactory(),
media_attachments: [],
mentions: [],
tags: [],
emojis: [],
content: '<p>This is a test status.</p>',
...data,
});
export const statusFactoryState = (
options: FactoryOptions<ApiStatusJSON> = {},
) =>
ImmutableMap<string, unknown>(
statusFactory(options) as unknown as Record<string, unknown>,
) as unknown as Status;
export const relationshipsFactory: FactoryFunction<ApiRelationshipJSON> = ({ export const relationshipsFactory: FactoryFunction<ApiRelationshipJSON> = ({
id, id,
...data ...data

View File

@ -45,6 +45,10 @@ class StatusEdit < ApplicationRecord
delegate :local?, :application, :edited?, :edited_at, delegate :local?, :application, :edited?, :edited_at,
:discarded?, :visibility, :language, to: :status :discarded?, :visibility, :language, to: :status
def with_media?
ordered_media_attachments.any?
end
def emojis def emojis
return @emojis if defined?(@emojis) return @emojis if defined?(@emojis)

View File

@ -12,7 +12,7 @@ class InitialStateSerializer < ActiveModel::Serializer
has_one :push_subscription, serializer: REST::WebPushSubscriptionSerializer has_one :push_subscription, serializer: REST::WebPushSubscriptionSerializer
has_one :role, serializer: REST::RoleSerializer has_one :role, serializer: REST::RoleSerializer
def meta # rubocop:disable Metrics/AbcSize def meta
store = default_meta_store store = default_meta_store
if object.current_account if object.current_account

View File

@ -1,6 +0,0 @@
- if status.ordered_media_attachments.first.video?
= render_video_component(status, visible: false)
- elsif status.ordered_media_attachments.first.audio?
= render_audio_component(status)
- else
= render_media_gallery_component(status, visible: false)

View File

@ -1,53 +0,0 @@
.batch-table__row
%label.batch-table__row__select.batch-checkbox
= f.check_box :status_ids, { multiple: true, include_hidden: false }, status.id
.batch-table__row__content
.status__card
- if status.reblog?
.status__prepend
= material_symbol('repeat')
= t('statuses.boosted_from_html', acct_link: admin_account_inline_link_to(status.proper.account, path: admin_account_status_path(status.proper.account.id, status.proper.id)))
- elsif status.reply? && status.in_reply_to_id.present?
.status__prepend
= material_symbol('reply')
= t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(status.in_reply_to_account, path: status.thread.present? ? admin_account_status_path(status.thread.account_id, status.in_reply_to_id) : nil))
.status__content><
- if status.proper.spoiler_text.blank?
= prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis)
- else
%details<
%summary><
%strong> Content warning: #{prerender_custom_emojis(h(status.proper.spoiler_text), status.proper.emojis)}
= prerender_custom_emojis(status_content_format(status.proper), status.proper.emojis)
- unless status.proper.ordered_media_attachments.empty?
= render partial: 'admin/reports/media_attachments', locals: { status: status.proper }
.detailed-status__meta
- if status.application
= status.application.name
·
= link_to admin_account_status_path(status.account.id, status), class: 'detailed-status__datetime' do
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
- if status.edited?
·
= link_to t('statuses.edited_at_html', date: content_tag(:time, l(status.edited_at), datetime: status.edited_at.iso8601, title: l(status.edited_at), class: 'formatted')),
admin_account_status_path(status.account_id, status),
class: 'detailed-status__datetime'
- if status.discarded?
·
%span.negative-hint= t('admin.statuses.deleted')
·
= material_symbol visibility_icon(status)
= t("statuses.visibilities.#{status.visibility}")
·
= link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', rel: 'noopener' do
= t('admin.statuses.view_publicly')
- if status.proper.sensitive?
·
= material_symbol('visibility_off')
= t('stream_entries.sensitive_content')

View File

@ -57,7 +57,7 @@
- if @statuses.empty? - if @statuses.empty?
= nothing_here 'nothing-here--under-tabs' = nothing_here 'nothing-here--under-tabs'
- else - else
= render partial: 'admin/reports/status', collection: @statuses, locals: { f: f } = render partial: 'admin/shared/status_batch_row', collection: @statuses, as: :status, locals: { f: f }
- if @report.unresolved? - if @report.unresolved?
%hr.spacer/ %hr.spacer/

View File

@ -0,0 +1,40 @@
-# locals: (status:)
.status__card><
- if status.reblog?
.status__prepend
= material_symbol('repeat')
= t('statuses.boosted_from_html', acct_link: admin_account_inline_link_to(status.proper.account, path: admin_account_status_path(status.proper.account.id, status.proper.id)))
- elsif status.reply? && status.in_reply_to_id.present?
.status__prepend
= material_symbol('reply')
= t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(status.in_reply_to_account, path: status.thread.present? ? admin_account_status_path(status.thread.account_id, status.in_reply_to_id) : nil))
= render partial: 'admin/shared/status_content', locals: { status: status.proper }
.detailed-status__meta
- if status.application
= status.application.name
·
= conditional_link_to can?(:show, status), admin_account_status_path(status.account.id, status), class: 'detailed-status__datetime' do
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }><= l(status.created_at)
- if status.edited?
&nbsp;·
= conditional_link_to can?(:show, status), admin_account_status_path(status.account.id, status, { anchor: 'history' }), class: 'detailed-status__datetime' do
%span><= t('statuses.edited_at_html', date: content_tag(:time, l(status.edited_at), datetime: status.edited_at.iso8601, title: l(status.edited_at), class: 'relative-formatted'))
- if status.discarded?
&nbsp;·
%span.negative-hint= t('admin.statuses.deleted')
- unless status.reblog?
&nbsp;·
%span<
= material_symbol(visibility_icon(status))
= t("statuses.visibilities.#{status.visibility}")
- if status.proper.sensitive?
&nbsp;·
= material_symbol('visibility_off')
= t('stream_entries.sensitive_content')
- unless status.direct_visibility?
&nbsp;·
= link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', target: 'blank', rel: 'noopener' do
= t('admin.statuses.view_publicly')

View File

@ -0,0 +1,7 @@
- if status.with_media?
- if status.ordered_media_attachments.first.video?
= render_video_component(status, visible: false)
- elsif status.ordered_media_attachments.first.audio?
= render_audio_component(status)
- else
= render_media_gallery_component(status, visible: false)

View File

@ -0,0 +1,5 @@
.batch-table__row
%label.batch-table__row__select.batch-checkbox
= f.check_box :status_ids, { multiple: true, include_hidden: false }, status.id
.batch-table__row__content
= render partial: 'admin/shared/status', object: status

View File

@ -0,0 +1,10 @@
.status__content><
- if status.spoiler_text.present?
%details<
%summary><
%strong> Content warning: #{prerender_custom_emojis(h(status.spoiler_text), status.emojis)}
= prerender_custom_emojis(status_content_format(status), status.emojis)
= render partial: 'admin/shared/status_attachments', locals: { status: status.proper }
- else
= prerender_custom_emojis(status_content_format(status), status.emojis)
= render partial: 'admin/shared/status_attachments', locals: { status: status.proper }

View File

@ -9,17 +9,7 @@
%time.formatted{ datetime: status_edit.created_at.iso8601, title: l(status_edit.created_at) }= l(status_edit.created_at) %time.formatted{ datetime: status_edit.created_at.iso8601, title: l(status_edit.created_at) }= l(status_edit.created_at)
.status .status
.status__content>< = render partial: 'admin/shared/status_content', locals: { status: status_edit }
- if status_edit.spoiler_text.blank?
= prerender_custom_emojis(status_content_format(status_edit), status_edit.emojis)
- else
%details<
%summary><
%strong> Content warning: #{prerender_custom_emojis(h(status_edit.spoiler_text), status_edit.emojis)}
= prerender_custom_emojis(status_content_format(status_edit), status_edit.emojis)
- unless status_edit.ordered_media_attachments.empty?
= render partial: 'admin/reports/media_attachments', locals: { status: status_edit }
.detailed-status__meta .detailed-status__meta
%time.formatted{ datetime: status_edit.created_at.iso8601, title: l(status_edit.created_at) }= l(status_edit.created_at) %time.formatted{ datetime: status_edit.created_at.iso8601, title: l(status_edit.created_at) }= l(status_edit.created_at)

View File

@ -47,6 +47,6 @@
- if @statuses.empty? - if @statuses.empty?
= nothing_here 'nothing-here--under-tabs' = nothing_here 'nothing-here--under-tabs'
- else - else
= render partial: 'admin/reports/status', collection: @statuses, locals: { f: f } = render partial: 'admin/shared/status_batch_row', collection: @statuses, as: :status, locals: { f: f }
= paginate @statuses = paginate @statuses

View File

@ -53,52 +53,11 @@
%h3= t('admin.statuses.contents') %h3= t('admin.statuses.contents')
.status__card = render partial: 'admin/shared/status', object: @status
- if @status.reblog?
.status__prepend
= material_symbol('repeat')
= t('statuses.boosted_from_html', acct_link: admin_account_inline_link_to(@status.proper.account, path: admin_account_status_path(@status.proper.account.id, @status.proper.id)))
- elsif @status.reply? && @status.in_reply_to_id.present?
.status__prepend
= material_symbol('reply')
= t('admin.statuses.replied_to_html', acct_link: admin_account_inline_link_to(@status.in_reply_to_account, path: @status.thread.present? ? admin_account_status_path(@status.thread.account_id, @status.in_reply_to_id) : nil))
.status__content><
- if @status.proper.spoiler_text.blank?
= prerender_custom_emojis(status_content_format(@status.proper), @status.proper.emojis)
- else
%details<
%summary><
%strong> Content warning: #{prerender_custom_emojis(h(@status.proper.spoiler_text), @status.proper.emojis)}
= prerender_custom_emojis(status_content_format(@status.proper), @status.proper.emojis)
- unless @status.proper.ordered_media_attachments.empty?
= render partial: 'admin/reports/media_attachments', locals: { status: @status.proper }
.detailed-status__meta
- if @status.application
= @status.application.name
·
%span.detailed-status__datetime
%time.formatted{ datetime: @status.created_at.iso8601, title: l(@status.created_at) }= l(@status.created_at)
- if @status.edited?
·
%span.detailed-status__datetime
= t('statuses.edited_at_html', date: content_tag(:time, l(@status.edited_at), datetime: @status.edited_at.iso8601, title: l(@status.edited_at), class: 'formatted'))
- if @status.discarded?
·
%span.negative-hint= t('admin.statuses.deleted')
- unless @status.reblog?
·
= material_symbol(visibility_icon(@status))
= t("statuses.visibilities.#{@status.visibility}")
- if @status.proper.sensitive?
·
= material_symbol('visibility_off')
= t('stream_entries.sensitive_content')
%hr.spacer/ %hr.spacer/
%h3= t('admin.statuses.history') %h3#history= t('admin.statuses.history')
- if @status.edits.empty? - if @status.edits.empty?
%p= t('admin.statuses.no_history') %p= t('admin.statuses.no_history')
- else - else

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
# Disable httplog in production unless log_level is `debug` # Disable in production unless log level is `debug`
if !Rails.env.production? || Rails.configuration.log_level == :debug if Rails.env.local? || Rails.logger.debug?
require 'httplog' require 'httplog'
HttpLog.configure do |config| HttpLog.configure do |config|

View File

@ -49,6 +49,10 @@ ia:
attributes: attributes:
reblog: reblog:
taken: del message jam existe taken: del message jam existe
terms_of_service:
attributes:
effective_date:
too_soon: es troppo tosto, debe esser plus tarde que %{date}
user: user:
attributes: attributes:
date_of_birth: date_of_birth:

View File

@ -72,7 +72,7 @@ fa:
revoke: آیا مطمئن هستید؟ revoke: آیا مطمئن هستید؟
index: index:
authorized_at: تایید شده در %{date} authorized_at: تایید شده در %{date}
description_html: اینها نرم‌افزار هایی هستند که می‌توانند به حساب کاربری شما با استفاده از رابط نرم‌افزاری دسترسی پیدا کنند. اگر نرم‌افزار های در اینجا هستند که نمی‌شناسید، یا نرم‌افزاری که رفتار مشکوک دارد، می‌توانید دسترسی اش را باطل کنید. description_html: اینها برنامه‌هاییند که می‌توانند با استفاده از میانای برنامه‌نویسی به حسابتان دسترسی پیدا کنند. اگر برنامه‌ای هست که نمی‌شناسیدش یا رفتار بدی دارد می‌توانید دسترسیش را باطل کنید.
last_used_at: آخرین استفاده در %{date} last_used_at: آخرین استفاده در %{date}
never_used: هرگز استفاده نشده never_used: هرگز استفاده نشده
scopes: اجازه‌ها scopes: اجازه‌ها

View File

@ -1915,7 +1915,7 @@ en:
public: Everyone public: Everyone
title: '%{name}: "%{quote}"' title: '%{name}: "%{quote}"'
visibilities: visibilities:
direct: Direct direct: Private mention
private: Followers-only private: Followers-only
private_long: Only show to followers private_long: Only show to followers
public: Public public: Public

View File

@ -2090,4 +2090,4 @@ eo:
not_enabled: Vi ankoraŭ ne ŝaltis WebAuth not_enabled: Vi ankoraŭ ne ŝaltis WebAuth
not_supported: Ĉi tiu legilo ne povas uzi sekurecŝlosilojn not_supported: Ĉi tiu legilo ne povas uzi sekurecŝlosilojn
otp_required: Por uzi sekurecŝlosilojn, ebligu 2-faktoran autentigon unue. otp_required: Por uzi sekurecŝlosilojn, ebligu 2-faktoran autentigon unue.
registered_on: Registrigita je %{date} registered_on: Registrita je %{date}

View File

@ -190,6 +190,7 @@ ia:
create_relay: Crear repetitor create_relay: Crear repetitor
create_unavailable_domain: Crear dominio indisponibile create_unavailable_domain: Crear dominio indisponibile
create_user_role: Crear un rolo create_user_role: Crear un rolo
create_username_block: Crear regula de nomine de usator
demote_user: Degradar usator demote_user: Degradar usator
destroy_announcement: Deler annuncio destroy_announcement: Deler annuncio
destroy_canonical_email_block: Deler blocada de e-mail destroy_canonical_email_block: Deler blocada de e-mail
@ -203,6 +204,7 @@ ia:
destroy_status: Deler message destroy_status: Deler message
destroy_unavailable_domain: Deler dominio indisponibile destroy_unavailable_domain: Deler dominio indisponibile
destroy_user_role: Destruer rolo destroy_user_role: Destruer rolo
destroy_username_block: Deler regula de nomine de usator
disable_2fa_user: Disactivar A2F disable_2fa_user: Disactivar A2F
disable_custom_emoji: Disactivar emoji personalisate disable_custom_emoji: Disactivar emoji personalisate
disable_relay: Disactivar repetitor disable_relay: Disactivar repetitor
@ -237,6 +239,7 @@ ia:
update_report: Actualisar le reporto update_report: Actualisar le reporto
update_status: Actualisar le message update_status: Actualisar le message
update_user_role: Actualisar rolo update_user_role: Actualisar rolo
update_username_block: Actualisar regula de nomine de usator
actions: actions:
approve_appeal_html: "%{name} approbava appello del decision de moderation de %{target}" approve_appeal_html: "%{name} approbava appello del decision de moderation de %{target}"
approve_user_html: "%{name} approbava inscription de %{target}" approve_user_html: "%{name} approbava inscription de %{target}"
@ -255,6 +258,7 @@ ia:
create_relay_html: "%{name} ha create un repetitor %{target}" create_relay_html: "%{name} ha create un repetitor %{target}"
create_unavailable_domain_html: "%{name} stoppava livration al dominio %{target}" create_unavailable_domain_html: "%{name} stoppava livration al dominio %{target}"
create_user_role_html: "%{name} creava rolo de %{target}" create_user_role_html: "%{name} creava rolo de %{target}"
create_username_block_html: "%{name} ha addite un regula pro nomines de usator que contine %{target}"
demote_user_html: "%{name} degradava usator %{target}" demote_user_html: "%{name} degradava usator %{target}"
destroy_announcement_html: "%{name} deleva annuncio %{target}" destroy_announcement_html: "%{name} deleva annuncio %{target}"
destroy_canonical_email_block_html: "%{name} disblocava le e-mail con le hash %{target}" destroy_canonical_email_block_html: "%{name} disblocava le e-mail con le hash %{target}"
@ -268,6 +272,7 @@ ia:
destroy_status_html: "%{name} removeva un message de %{target}" destroy_status_html: "%{name} removeva un message de %{target}"
destroy_unavailable_domain_html: "%{name} reprendeva le livration al dominio %{target}" destroy_unavailable_domain_html: "%{name} reprendeva le livration al dominio %{target}"
destroy_user_role_html: "%{name} deleva le rolo %{target}" destroy_user_role_html: "%{name} deleva le rolo %{target}"
destroy_username_block_html: "%{name} ha removite un regula pro nomines de usator que contine %{target}"
disable_2fa_user_html: "%{name} disactivava le authentication a duo factores pro le usator %{target}" disable_2fa_user_html: "%{name} disactivava le authentication a duo factores pro le usator %{target}"
disable_custom_emoji_html: "%{name} disactivava le emoji %{target}" disable_custom_emoji_html: "%{name} disactivava le emoji %{target}"
disable_relay_html: "%{name} ha disactivate le repetitor %{target}" disable_relay_html: "%{name} ha disactivate le repetitor %{target}"
@ -302,6 +307,7 @@ ia:
update_report_html: "%{name} actualisava reporto %{target}" update_report_html: "%{name} actualisava reporto %{target}"
update_status_html: "%{name} actualisava message de %{target}" update_status_html: "%{name} actualisava message de %{target}"
update_user_role_html: "%{name} cambiava rolo de %{target}" update_user_role_html: "%{name} cambiava rolo de %{target}"
update_username_block_html: "%{name} ha actualisate un regula pro nomines de usator que contine %{target}"
deleted_account: conto delite deleted_account: conto delite
empty: Nulle registros trovate. empty: Nulle registros trovate.
filter_by_action: Filtrar per action filter_by_action: Filtrar per action
@ -321,7 +327,7 @@ ia:
preview: preview:
disclaimer: Proque le usatores non pote optar pro non reciper los, le notificationes per e-mail debe limitar se a annuncios importante tal como le notificationes de violation de datos personal o de clausura de servitores. disclaimer: Proque le usatores non pote optar pro non reciper los, le notificationes per e-mail debe limitar se a annuncios importante tal como le notificationes de violation de datos personal o de clausura de servitores.
explanation_html: 'Le e-mail essera inviate a <strong>%{display_count} usatores</strong>. Le sequente texto essera includite in le e-mail:' explanation_html: 'Le e-mail essera inviate a <strong>%{display_count} usatores</strong>. Le sequente texto essera includite in le e-mail:'
title: Previder le notification de annuncio title: Previsualisar le notification de annuncio
publish: Publicar publish: Publicar
published_msg: Annuncio publicate con successo! published_msg: Annuncio publicate con successo!
scheduled_for: Programmate pro %{time} scheduled_for: Programmate pro %{time}
@ -480,6 +486,36 @@ ia:
new: new:
title: Importar blocadas de dominio title: Importar blocadas de dominio
no_file: Necun file seligite no_file: Necun file seligite
fasp:
debug:
callbacks:
created_at: Data de creation
delete: Deler
ip: Adresse IP
request_body: Corpore del requesta
title: Depurar le appellos de retorno
providers:
active: Active
base_url: URL de base
callback: Appello de retorno
delete: Deler
edit: Modificar fornitor
finish_registration: Terminar registration
name: Nomine
providers: Fornitores
public_key_fingerprint: Dactylogramma del clave public
registration_requested: Registration requestate
registrations:
confirm: Confirmar
description: Tu ha recipite un registration de un FSAF. Rejecta lo si tu non lo ha initiate. Si tu lo ha initiate, compara attentemente le nomine e le dactylogramma del clave ante de confirmar le registration.
reject: Rejectar
title: Confirmar registration FSAF
save: Salvar
select_capabilities: Selige capacitates
sign_in: Aperir session
status: Stato
title: Fornitores de Servicios Auxiliar del Fediverso
title: FSAF
follow_recommendations: follow_recommendations:
description_html: "<strong>Le recommendationes de sequimento adjuta le nove usatores a trovar rapidemente contento interessante.</strong> Quando un usator non ha un historia sufficiente de interactiones con alteres pro formar recommendationes personalisate de sequimento, iste contos es recommendate. Illos se recalcula cata die a partir de un mixtura de contos con le plus grande numero de ingagiamentos recente e le numero de sequitores local le plus alte pro un lingua date." description_html: "<strong>Le recommendationes de sequimento adjuta le nove usatores a trovar rapidemente contento interessante.</strong> Quando un usator non ha un historia sufficiente de interactiones con alteres pro formar recommendationes personalisate de sequimento, iste contos es recommendate. Illos se recalcula cata die a partir de un mixtura de contos con le plus grande numero de ingagiamentos recente e le numero de sequitores local le plus alte pro un lingua date."
language: Pro le lingua language: Pro le lingua
@ -548,6 +584,13 @@ ia:
all: Toto all: Toto
limited: Limitate limited: Limitate
title: Moderation title: Moderation
moderation_notes:
create: Adder nota de moderation
created_msg: Le nota de moderation del servitor ha essite create.
description_html: Vider e lassar notas pro altere moderatores e pro referentia futur
destroyed_msg: Le nota de moderation del servitor ha essite delite.
placeholder: Informationes sur iste servitor, actiones prendite o altere cosas que pote adjutar te a moderar iste servitor in le futuro.
title: Notas de moderation
private_comment: Commento private private_comment: Commento private
public_comment: Commento public public_comment: Commento public
purge: Purgar purge: Purgar
@ -756,11 +799,17 @@ ia:
title: Rolos title: Rolos
rules: rules:
add_new: Adder regula add_new: Adder regula
add_translation: Adder traduction
delete: Deler delete: Deler
description_html: Ben que multes affirma de haber legite e acceptate le conditiones de servicio, generalmente le gente non los lege completemente usque un problema surge. <strong>Facilita le visibilitate del regulas de tu servitor in un colpo de oculo forniente los in un lista a punctos.</strong> Tenta mantener le regulas individual curte e simple, ma sin divider los in multe punctos separate. description_html: Ben que multes affirma de haber legite e acceptate le conditiones de servicio, generalmente le gente non los lege completemente usque un problema surge. <strong>Facilita le visibilitate del regulas de tu servitor in un colpo de oculo forniente los in un lista a punctos.</strong> Tenta mantener le regulas individual curte e simple, ma sin divider los in multe punctos separate.
edit: Modificar regula edit: Modificar regula
empty: Necun regula del servitor ha essite definite ancora. empty: Necun regula del servitor ha essite definite ancora.
move_down: Displaciar a basso
move_up: Displaciar in alto
title: Regulas del servitor title: Regulas del servitor
translation: Traduction
translations: Traductiones
translations_explanation: Tu ha le option de adder traductiones al regulas. Le valor predefinite apparera si necun version traducite es disponibile. Per favor sempre assecura te que omne traduction fornite es ben synchronisate con le valor predefinite.
settings: settings:
about: about:
manage_rules: Gerer le regulas del servitor manage_rules: Gerer le regulas del servitor
@ -877,7 +926,7 @@ ia:
database_schema_check: database_schema_check:
message_html: Il ha migrationes de base de datos pendente. Per favor exeque los pro assecurar que le application se comporta como expectate message_html: Il ha migrationes de base de datos pendente. Per favor exeque los pro assecurar que le application se comporta como expectate
elasticsearch_analysis_index_mismatch: elasticsearch_analysis_index_mismatch:
message_html: Le parametros del analisator del indice de Elasticsearch es obsolete. Executa <code>tootctl search deploy --only-mapping --only=%{value}</code> message_html: Le parametros del analysator del indice de Elasticsearch es obsolete. Executa <code>tootctl search deploy --only-mapping --only=%{value}</code>
elasticsearch_health_red: elasticsearch_health_red:
message_html: Le aggregation Elasticsearch es malsan (stato rubie), le functiones de recerca es indisponibile message_html: Le aggregation Elasticsearch es malsan (stato rubie), le functiones de recerca es indisponibile
elasticsearch_health_yellow: elasticsearch_health_yellow:
@ -942,7 +991,7 @@ ia:
changelog: Lo que ha cambiate changelog: Lo que ha cambiate
create: Usar tu proprie create: Usar tu proprie
current: Actual current: Actual
draft: Provisori draft: Esbosso
generate: Usar modello generate: Usar modello
generates: generates:
action: Generar action: Generar
@ -965,7 +1014,7 @@ ia:
title: Previsualisar le notification sur le conditiones de servicio title: Previsualisar le notification sur le conditiones de servicio
publish: Publicar publish: Publicar
published_on_html: Publicate le %{date} published_on_html: Publicate le %{date}
save_draft: Salvar version provisori save_draft: Salvar esbosso
title: Conditiones de servicio title: Conditiones de servicio
title: Administration title: Administration
trends: trends:
@ -1043,8 +1092,17 @@ ia:
title: Recommendationes e tendentias title: Recommendationes e tendentias
trending: In tendentia trending: In tendentia
username_blocks: username_blocks:
add_new: Adder nove
block_registrations: Blocar registrationes
comparison:
contains: Contine
equals: Es equal a
contains_html: Contine %{string}
created_msg: Regula de nomine de usator create con successo
delete: Deler
edit: edit:
title: Modificar regula de nomine de usator title: Modificar regula de nomine de usator
matches_exactly_html: Es equal a %{string}
new: new:
create: Crear regula create: Crear regula
title: Crear nove regula de nomine de usator title: Crear nove regula de nomine de usator
@ -1316,6 +1374,10 @@ ia:
basic_information: Information basic basic_information: Information basic
hint_html: "<strong>Personalisa lo que le personas vide sur tu profilo public e presso tu messages.</strong> Il es plus probabile que altere personas te seque e interage con te quando tu ha un profilo complete e un photo." hint_html: "<strong>Personalisa lo que le personas vide sur tu profilo public e presso tu messages.</strong> Il es plus probabile que altere personas te seque e interage con te quando tu ha un profilo complete e un photo."
other: Alteres other: Alteres
emoji_styles:
auto: Automatic
native: Native
twemoji: Twemoji
errors: errors:
'400': Le requesta que tu ha inviate non es valide o es mal formate. '400': Le requesta que tu ha inviate non es valide o es mal formate.
'403': Tu non ha le permission de acceder a iste pagina. '403': Tu non ha le permission de acceder a iste pagina.
@ -1625,6 +1687,10 @@ ia:
title: Nove mention title: Nove mention
poll: poll:
subject: Un sondage de %{name} ha finite subject: Un sondage de %{name} ha finite
quote:
body: 'Tu message ha essite citate per %{name}:'
subject: "%{name} ha citate tu message"
title: Nove citation
reblog: reblog:
body: "%{name} ha impulsate tu message:" body: "%{name} ha impulsate tu message:"
subject: "%{name} ha impulsate tu message" subject: "%{name} ha impulsate tu message"
@ -1835,6 +1901,7 @@ ia:
edited_at_html: Modificate le %{date} edited_at_html: Modificate le %{date}
errors: errors:
in_reply_not_found: Le message a que tu tenta responder non pare exister. in_reply_not_found: Le message a que tu tenta responder non pare exister.
quoted_status_not_found: Le message que tu tenta citar non pare exister.
over_character_limit: limite de characteres de %{max} excedite over_character_limit: limite de characteres de %{max} excedite
pin_errors: pin_errors:
direct: Messages que es solo visibile a usatores mentionate non pote esser appunctate direct: Messages que es solo visibile a usatores mentionate non pote esser appunctate
@ -1842,6 +1909,8 @@ ia:
ownership: Le message de alcuno altere non pote esser appunctate ownership: Le message de alcuno altere non pote esser appunctate
reblog: Un impulso non pote esser affixate reblog: Un impulso non pote esser affixate
quote_policies: quote_policies:
followers: Solmente tu sequitores
nobody: Necuno
public: Omnes public: Omnes
title: "%{name}: “%{quote}”" title: "%{name}: “%{quote}”"
visibilities: visibilities:
@ -1897,7 +1966,7 @@ ia:
terms_of_service: terms_of_service:
title: Conditiones de servicio title: Conditiones de servicio
terms_of_service_interstitial: terms_of_service_interstitial:
future_preamble_html: Nos face alcun cambios a nostre conditiones de servicio, que entrara in vigor in <strong>%{date}</strong>. Nos te invita a revider le conditiones actualisate. future_preamble_html: Nos apporta alcun modificationes a nostre conditiones de servicio, le quales entrara in vigor le <strong>%{date}</strong>. Nos te invita a revider le conditiones actualisate.
past_preamble_html: Nos ha cambiate nostre conditiones de servicio desde tu ultime visita. Nos te invita a revider le conditiones actualisate. past_preamble_html: Nos ha cambiate nostre conditiones de servicio desde tu ultime visita. Nos te invita a revider le conditiones actualisate.
review_link: Revider le conditiones de servicio review_link: Revider le conditiones de servicio
title: Le conditiones de servicio de %{domain} cambia title: Le conditiones de servicio de %{domain} cambia
@ -1969,7 +2038,7 @@ ia:
agreement: Si tu continua a usar %{domain}, tu accepta iste conditiones. Si tu non es de accordo con le conditiones actualisate, tu pote sempre eliminar tu conto pro terminar tu accordo con %{domain}. agreement: Si tu continua a usar %{domain}, tu accepta iste conditiones. Si tu non es de accordo con le conditiones actualisate, tu pote sempre eliminar tu conto pro terminar tu accordo con %{domain}.
changelog: 'In summario, ecce lo que iste actualisation significa pro te:' changelog: 'In summario, ecce lo que iste actualisation significa pro te:'
description: 'Tu recipe iste e-mail proque nos face alcun cambios al nostre conditiones de servicio a %{domain}. Iste actualisationes entrara in vigor in %{date}. Nos te invita a revider integralmente le conditiones actualisate hic:' description: 'Tu recipe iste e-mail proque nos face alcun cambios al nostre conditiones de servicio a %{domain}. Iste actualisationes entrara in vigor in %{date}. Nos te invita a revider integralmente le conditiones actualisate hic:'
description_html: Tu recipe iste e-mail proque nos face alcun cambios al nostre conditiones de servicio a %{domain}. Iste actualisationes entrara in vigor in <strong>%{date}</strong>. Nos te invita a revider <a href="%{path}" target="_blank">integralmente le conditiones actualisate hic</a>. description_html: Tu recipe iste message perque nos apporta alcun modificationes a nostre conditiones de servicio sur %{domain}. Iste actualisationes entrara in vigor le <strong>%{date}</strong>. Nos te invita a <a href="%{path}" target="_blank">leger integralmente le conditiones actualisate</a>.
sign_off: Le equipa de %{domain} sign_off: Le equipa de %{domain}
subject: Actualisationes de nostre conditiones de servicio subject: Actualisationes de nostre conditiones de servicio
subtitle: Le conditiones de servicio de %{domain} ha cambiate subtitle: Le conditiones de servicio de %{domain} ha cambiate

View File

@ -1,7 +1,7 @@
--- ---
ru: ru:
about: about:
about_mastodon_html: 'Социальная сеть будущего: никакой рекламы или слежки со стороны корпораций, этичный дизайн и децентрализация! С Mastodon ваши данные находятся только под вашим контролем!' about_mastodon_html: 'Социальная сеть будущего: никакой рекламы или слежки со стороны корпораций, этичный дизайн и децентрализация. С Mastodon ваши данные находятся только под вашим контролем!'
contact_missing: Не указано contact_missing: Не указано
contact_unavailable: N/A contact_unavailable: N/A
hosted_on: Сервер Mastodon на сайте %{domain} hosted_on: Сервер Mastodon на сайте %{domain}
@ -350,9 +350,9 @@ ru:
copy: Копировать copy: Копировать
copy_failed_msg: Не удалось создать локальную копию эмодзи copy_failed_msg: Не удалось создать локальную копию эмодзи
create_new_category: Создать новую категорию create_new_category: Создать новую категорию
created_msg: Эмодзи добавлен! created_msg: Эмодзи добавлен
delete: Удалить delete: Удалить
destroyed_msg: Эмодзи удалён! destroyed_msg: Эмодзи удалён
disable: Отключить disable: Отключить
disabled: Отключён disabled: Отключён
disabled_msg: Эмодзи отключён disabled_msg: Эмодзи отключён
@ -375,7 +375,7 @@ ru:
unlist: Из списка unlist: Из списка
unlisted: Не в списке unlisted: Не в списке
update_failed_msg: Не удалось обновить эмодзи update_failed_msg: Не удалось обновить эмодзи
updated_msg: Эмодзи обновлён! updated_msg: Эмодзи обновлён
upload: Загрузить upload: Загрузить
dashboard: dashboard:
active_users: активные пользователи active_users: активные пользователи
@ -1247,7 +1247,7 @@ ru:
delete_account: Удалить учётную запись delete_account: Удалить учётную запись
delete_account_html: Вы можете <a href="%{path}">удалить свою учётную запись</a>. Перед удалением у вас будет запрошено подтверждение. delete_account_html: Вы можете <a href="%{path}">удалить свою учётную запись</a>. Перед удалением у вас будет запрошено подтверждение.
description: description:
prefix_invited_by_user: Вы получили приглашение на сервер Mastodon от @%{name}! prefix_invited_by_user: Вы получили приглашение на сервер Mastodon от @%{name}.
prefix_sign_up: Зарегистрируйтесь в Mastodon прямо сейчас! prefix_sign_up: Зарегистрируйтесь в Mastodon прямо сейчас!
suffix: С учётной записью вы сможете подписываться на людей, публиковать посты и обмениваться сообщениями с пользователями любого сервера Mastodon — и не только! suffix: С учётной записью вы сможете подписываться на людей, публиковать посты и обмениваться сообщениями с пользователями любого сервера Mastodon — и не только!
didnt_get_confirmation: Не получили письмо со ссылкой для подтверждения? didnt_get_confirmation: Не получили письмо со ссылкой для подтверждения?
@ -1497,7 +1497,7 @@ ru:
one: Выбран <strong>%{count}</strong> элемент, соответствующий вашему запросу. one: Выбран <strong>%{count}</strong> элемент, соответствующий вашему запросу.
other: Выбраны все <strong>%{count}</strong> элементов, соответствующих вашему запросу. other: Выбраны все <strong>%{count}</strong> элементов, соответствующих вашему запросу.
cancel: Отмена cancel: Отмена
changes_saved_msg: Изменения сохранены! changes_saved_msg: Изменения сохранены
confirm: Подтвердить confirm: Подтвердить
copy: Копировать copy: Копировать
delete: Удалить delete: Удалить
@ -1731,7 +1731,7 @@ ru:
subject: "%{name} добавил(а) ваш пост в избранное" subject: "%{name} добавил(а) ваш пост в избранное"
title: Ваш пост добавили в избранное title: Ваш пост добавили в избранное
follow: follow:
body: "%{name} теперь подписан(а) на вас!" body: "%{name} теперь подписан(а) на вас"
subject: "%{name} теперь подписан(а) на вас" subject: "%{name} теперь подписан(а) на вас"
title: Новый подписчик title: Новый подписчик
follow_request: follow_request:
@ -1965,7 +1965,7 @@ ru:
many: 'содержались запрещённые хэштеги: %{tags}' many: 'содержались запрещённые хэштеги: %{tags}'
one: 'содержался запрещённый хэштег: %{tags}' one: 'содержался запрещённый хэштег: %{tags}'
other: 'содержались запрещённые хэштеги: %{tags}' other: 'содержались запрещённые хэштеги: %{tags}'
edited_at_html: 'Дата последнего изменения: %{date}' edited_at_html: 'Последнее изменение: %{date}'
errors: errors:
in_reply_not_found: Пост, на который вы собирались ответить, был удалён или не существует. in_reply_not_found: Пост, на который вы собирались ответить, был удалён или не существует.
quoted_status_not_found: Пост, который вы собирались процитировать, был удалён или не существует. quoted_status_not_found: Пост, который вы собирались процитировать, был удалён или не существует.

View File

@ -56,10 +56,12 @@ ia:
scopes: Le APIs al quales le application habera accesso. Si tu selige un ambito de nivello superior, non es necessari seliger ambitos individual. scopes: Le APIs al quales le application habera accesso. Si tu selige un ambito de nivello superior, non es necessari seliger ambitos individual.
setting_aggregate_reblogs: Non monstrar nove impulsos pro messages que ha essite recentemente impulsate (affecta solmente le impulsos novemente recipite) setting_aggregate_reblogs: Non monstrar nove impulsos pro messages que ha essite recentemente impulsate (affecta solmente le impulsos novemente recipite)
setting_always_send_emails: Normalmente, le notificationes de e-mail non es inviate quando tu activemente usa Mastodon setting_always_send_emails: Normalmente, le notificationes de e-mail non es inviate quando tu activemente usa Mastodon
setting_default_quote_policy: Iste parametro solo habera effecto pro messages create con le proxime version de Mastodon, ma tu pote seliger tu preferentia anticipatemente.
setting_default_sensitive: Le medios sensibile es celate de ordinario e pote esser revelate con un clic setting_default_sensitive: Le medios sensibile es celate de ordinario e pote esser revelate con un clic
setting_display_media_default: Celar le medios marcate como sensibile setting_display_media_default: Celar le medios marcate como sensibile
setting_display_media_hide_all: Sempre celar contento multimedial setting_display_media_hide_all: Sempre celar contento multimedial
setting_display_media_show_all: Sempre monstrar contento multimedial setting_display_media_show_all: Sempre monstrar contento multimedial
setting_emoji_style: Como monstrar emojis. “Automatic” tentara usar emojis native, ma recurre al Twemojis pro navigatores ancian.
setting_system_scrollbars_ui: Se applica solmente al navigatores de scriptorio basate sur Safari e Chrome setting_system_scrollbars_ui: Se applica solmente al navigatores de scriptorio basate sur Safari e Chrome
setting_use_blurhash: Le imagines degradate se basa sur le colores del visuales celate, ma illos offusca tote le detalios setting_use_blurhash: Le imagines degradate se basa sur le colores del visuales celate, ma illos offusca tote le detalios
setting_use_pending_items: Requirer un clic pro monstrar nove messages in vice de rolar automaticamente le fluxo setting_use_pending_items: Requirer un clic pro monstrar nove messages in vice de rolar automaticamente le fluxo
@ -134,16 +136,23 @@ ia:
name: Tu pote solmente cambiar le litteras inter majusculas e minusculas, per exemplo, pro render lo plus legibile name: Tu pote solmente cambiar le litteras inter majusculas e minusculas, per exemplo, pro render lo plus legibile
terms_of_service: terms_of_service:
changelog: Pote esser structurate con le syntaxe Markdown. changelog: Pote esser structurate con le syntaxe Markdown.
effective_date: Un periodo rationabile pote variar inter 10 e 30 dies post le data al qual tu notifica tu usatores.
text: Pote esser structurate con le syntaxe Markdown. text: Pote esser structurate con le syntaxe Markdown.
terms_of_service_generator: terms_of_service_generator:
admin_email: Le avisos juridic include le contra-avisos, ordinantias judiciari, demandas de retiro e demandas de application del lege. admin_email: Le avisos juridic include le contra-avisos, ordinantias judiciari, demandas de retiro e demandas de application del lege.
arbitration_address: Pote esser le mesme que le adresse physic supra, o “N/A” si se usa e-mail.
arbitration_website: Pote esser un formulario web, o “N/A” si se usa e-mail.
choice_of_law: Citate, region, territorio o stato cuje leges substantive interne governa omne disputa juridic. choice_of_law: Citate, region, territorio o stato cuje leges substantive interne governa omne disputa juridic.
dmca_address: Pro operatores in le SUA, usa le adresse registrate in le Directorio de Agentes Designate pro le DMCA (DMCA Designated Agent Directory). Un adresse de cassa postal es disponibile per requesta directe; usa le Requesta de Exemption de Cassa Postal pro Agentes Designate del DMCA (DMCA Designated Agent Post Office Box Waiver Request) pro inviar un message electronic al Officio del Derecto de Autor (Copyright Office) e describer que tu es un moderator de contento que travalia de casa e qui time vengiantias o represalias pro tu actiones, necessitante le uso un cassa postal pro remover tu adresse personal del vista public. dmca_address: Pro operatores in le SUA, usa le adresse registrate in le Directorio de Agentes Designate pro le DMCA (DMCA Designated Agent Directory). Un adresse de cassa postal es disponibile per requesta directe; usa le Requesta de Exemption de Cassa Postal pro Agentes Designate del DMCA (DMCA Designated Agent Post Office Box Waiver Request) pro inviar un message electronic al Officio del Derecto de Autor (Copyright Office) e describer que tu es un moderator de contento que travalia de casa e qui time vengiantias o represalias pro tu actiones, necessitante le uso un cassa postal pro remover tu adresse personal del vista public.
dmca_email: Pote esser le mesme adresse de e-mail usate pro “Adresse de e-mail pro avisos juridic” supra.
domain: Identification unic del servicio in linea que tu forni. domain: Identification unic del servicio in linea que tu forni.
jurisdiction: Indica le pais ubi vive le persona qui paga le facturas. Si se tracta de un interprisa o altere organisation, indica le pais ubi illo es incorporate, e le citate, region, territorio o stato del maniera appropriate pro le pais. jurisdiction: Indica le pais ubi vive le persona qui paga le facturas. Si se tracta de un interprisa o altere organisation, indica le pais ubi illo es incorporate, e le citate, region, territorio o stato del maniera appropriate pro le pais.
min_age: Non deberea esser infra le etate minime requirite per le leges de tu jurisdiction. min_age: Non deberea esser infra le etate minime requirite per le leges de tu jurisdiction.
user: user:
chosen_languages: Si marcate, solmente le messages in le linguas seligite apparera in chronologias public chosen_languages: Si marcate, solmente le messages in le linguas seligite apparera in chronologias public
date_of_birth:
one: Nos debe assecurar que tu ha al minus %{count} anno pro usar %{domain}. Nos non va immagazinar isto.
other: Nos debe assecurar que tu ha al minus %{count} annos pro usar %{domain}. Nos non va immagazinar isto.
role: Le rolo controla qual permissos le usator ha. role: Le rolo controla qual permissos le usator ha.
user_role: user_role:
color: Color a esser usate pro le rolo in omne parte del UI, como RGB in formato hexadecimal color: Color a esser usate pro le rolo in omne parte del UI, como RGB in formato hexadecimal
@ -151,6 +160,10 @@ ia:
name: Nomine public del rolo, si rolo es definite a esser monstrate como insignia name: Nomine public del rolo, si rolo es definite a esser monstrate como insignia
permissions_as_keys: Usatores con iste rolo habera accesso a... permissions_as_keys: Usatores con iste rolo habera accesso a...
position: Rolo superior decide resolution de conflicto in certe situationes. Certe actiones pote solo esser exequite sur rolos con un prioritate inferior position: Rolo superior decide resolution de conflicto in certe situationes. Certe actiones pote solo esser exequite sur rolos con un prioritate inferior
username_block:
allow_with_approval: In loco de impedir totalmente le inscription, le inscriptiones correspondente requirera tu approbation
comparison: Tene in conto le “problema Scunthorpe” si tu bloca correspondentias partial
username: Correspondera independentemente de majusculas e minusculas e de homoglyphos commun como "4" pro "a" or "3" pro "e"
webhook: webhook:
events: Selige le eventos a inviar events: Selige le eventos a inviar
template: Compone tu proprie carga utile JSON per interpolation de variabile. Lassar blanc pro JSON predefinite. template: Compone tu proprie carga utile JSON per interpolation de variabile. Lassar blanc pro JSON predefinite.
@ -233,6 +246,7 @@ ia:
setting_display_media_default: Predefinite setting_display_media_default: Predefinite
setting_display_media_hide_all: Celar toto setting_display_media_hide_all: Celar toto
setting_display_media_show_all: Monstrar toto setting_display_media_show_all: Monstrar toto
setting_emoji_style: Stilo de emojis
setting_expand_spoilers: Sempre expander messages marcate con avisos de contento setting_expand_spoilers: Sempre expander messages marcate con avisos de contento
setting_hide_network: Cela tu rete social setting_hide_network: Cela tu rete social
setting_missing_alt_text_modal: Monstrar un dialogo de confirmation ante de publicar multimedia sin texto alternative setting_missing_alt_text_modal: Monstrar un dialogo de confirmation ante de publicar multimedia sin texto alternative
@ -271,6 +285,7 @@ ia:
favicon: Favicon favicon: Favicon
mascot: Personalisar le mascotte (hereditage) mascot: Personalisar le mascotte (hereditage)
media_cache_retention_period: Periodo de retention del cache multimedial media_cache_retention_period: Periodo de retention del cache multimedial
min_age: Etate minime requirite
peers_api_enabled: Publicar le lista de servitores discoperite in le API peers_api_enabled: Publicar le lista de servitores discoperite in le API
profile_directory: Activar directorio de profilos profile_directory: Activar directorio de profilos
registrations_mode: Qui pote inscriber se registrations_mode: Qui pote inscriber se
@ -314,6 +329,7 @@ ia:
follow_request: Alcuno ha demandate de sequer te follow_request: Alcuno ha demandate de sequer te
mention: Alcuno te ha mentionate mention: Alcuno te ha mentionate
pending_account: Nove conto besonia de revision pending_account: Nove conto besonia de revision
quote: Alcuno te ha citate
reblog: Alcuno ha impulsate tu message reblog: Alcuno ha impulsate tu message
report: Un nove reporto es inviate report: Un nove reporto es inviate
software_updates: software_updates:
@ -360,6 +376,10 @@ ia:
name: Nomine name: Nomine
permissions_as_keys: Permissiones permissions_as_keys: Permissiones
position: Prioritate position: Prioritate
username_block:
allow_with_approval: Permitter registrationes con approbation
comparison: Methodo de comparation
username: Parola a comparar
webhook: webhook:
events: Eventos activate events: Eventos activate
template: Modello de carga utile template: Modello de carga utile

View File

@ -56,6 +56,7 @@ sv:
scopes: 'Vilka API: er applikationen kommer tillåtas åtkomst till. Om du väljer en omfattning på högstanivån behöver du inte välja individuella sådana.' scopes: 'Vilka API: er applikationen kommer tillåtas åtkomst till. Om du väljer en omfattning på högstanivån behöver du inte välja individuella sådana.'
setting_aggregate_reblogs: Visa inte nya boostar för inlägg som nyligen blivit boostade (påverkar endast nymottagna boostar) setting_aggregate_reblogs: Visa inte nya boostar för inlägg som nyligen blivit boostade (påverkar endast nymottagna boostar)
setting_always_send_emails: E-postnotiser kommer vanligtvis inte skickas när du aktivt använder Mastodon setting_always_send_emails: E-postnotiser kommer vanligtvis inte skickas när du aktivt använder Mastodon
setting_default_quote_policy: Denna inställning kommer bara att träda i kraft för inlägg som skapats med nästa Mastodon-version, men du kan förbereda dina önskemål.
setting_default_sensitive: Känslig media döljs som standard och kan visas med ett klick setting_default_sensitive: Känslig media döljs som standard och kan visas med ett klick
setting_display_media_default: Dölj media markerad som känslig setting_display_media_default: Dölj media markerad som känslig
setting_display_media_hide_all: Dölj alltid all media setting_display_media_hide_all: Dölj alltid all media
@ -149,6 +150,9 @@ sv:
min_age: Bör inte vara lägre än den minimiålder som krävs enligt lagarna i din jurisdiktion. min_age: Bör inte vara lägre än den minimiålder som krävs enligt lagarna i din jurisdiktion.
user: user:
chosen_languages: Vid aktivering visas bara inlägg på dina valda språk i offentliga tidslinjer chosen_languages: Vid aktivering visas bara inlägg på dina valda språk i offentliga tidslinjer
date_of_birth:
one: Vi måste se till att du är minst %{count} för att använda %{domain}. Vi sparar inte denna information.
other: Vi måste se till att du är minst %{count} för att använda %{domain}. Vi lagrar inte denna information.
role: Rollen styr vilka behörigheter användaren har. role: Rollen styr vilka behörigheter användaren har.
user_role: user_role:
color: Färgen som ska användas för rollen i användargränssnittet, som RGB i hex-format color: Färgen som ska användas för rollen i användargränssnittet, som RGB i hex-format
@ -156,6 +160,10 @@ sv:
name: Offentligt namn på rollen, om rollen är inställd på att visas som ett emblem name: Offentligt namn på rollen, om rollen är inställd på att visas som ett emblem
permissions_as_keys: Användare med denna roll kommer ha tillgång till... permissions_as_keys: Användare med denna roll kommer ha tillgång till...
position: Högre roll avgör konfliktlösning i vissa situationer. Vissa åtgärder kan endast utföras på roller med lägre prioritet position: Högre roll avgör konfliktlösning i vissa situationer. Vissa åtgärder kan endast utföras på roller med lägre prioritet
username_block:
allow_with_approval: I stället för att förhindra direkt registrering kräver matchning av registreringar ditt godkännande
comparison: Var uppmärksam på Scunthorpe Problem vid blockering av partiella matcher
username: Matchas oavsett versaler och gemena bokstäver som ”4” för ”a” eller 3 för ”e”
webhook: webhook:
events: Välj händelser att skicka events: Välj händelser att skicka
template: Skriv din egen JSON-nyttolast med variabel interpolation. Lämna tomt för förvald JSON. template: Skriv din egen JSON-nyttolast med variabel interpolation. Lämna tomt för förvald JSON.
@ -321,6 +329,7 @@ sv:
follow_request: Någon begärt att följa dig follow_request: Någon begärt att följa dig
mention: Någon nämnt dig mention: Någon nämnt dig
pending_account: Ett nytt konto behöver granskas pending_account: Ett nytt konto behöver granskas
quote: Någon citerade dig
reblog: Någon boostade ditt inlägg reblog: Någon boostade ditt inlägg
report: En ny rapport har skickats report: En ny rapport har skickats
software_updates: software_updates:
@ -369,6 +378,7 @@ sv:
position: Prioritet position: Prioritet
username_block: username_block:
allow_with_approval: Tillåt registreringar med godkännande allow_with_approval: Tillåt registreringar med godkännande
comparison: Jämförelsesätt
username: Ord att matcha username: Ord att matcha
webhook: webhook:
events: Aktiverade händelser events: Aktiverade händelser

View File

@ -258,6 +258,7 @@ sv:
create_relay_html: "%{name} skapade ombudet %{target}" create_relay_html: "%{name} skapade ombudet %{target}"
create_unavailable_domain_html: "%{name} stoppade leverans till domänen %{target}" create_unavailable_domain_html: "%{name} stoppade leverans till domänen %{target}"
create_user_role_html: "%{name} skapade rollen %{target}" create_user_role_html: "%{name} skapade rollen %{target}"
create_username_block_html: "%{name} lade till regel för användarnamn som innehåller %{target}"
demote_user_html: "%{name} nedgraderade användare %{target}" demote_user_html: "%{name} nedgraderade användare %{target}"
destroy_announcement_html: "%{name} raderade kungörelsen %{target}" destroy_announcement_html: "%{name} raderade kungörelsen %{target}"
destroy_canonical_email_block_html: "%{name} avblockerade e-post med hash%{target}" destroy_canonical_email_block_html: "%{name} avblockerade e-post med hash%{target}"
@ -271,6 +272,7 @@ sv:
destroy_status_html: "%{name} tog bort inlägget av %{target}" destroy_status_html: "%{name} tog bort inlägget av %{target}"
destroy_unavailable_domain_html: "%{name} återupptog leverans till domänen %{target}" destroy_unavailable_domain_html: "%{name} återupptog leverans till domänen %{target}"
destroy_user_role_html: "%{name} raderade rollen %{target}" destroy_user_role_html: "%{name} raderade rollen %{target}"
destroy_username_block_html: "%{name} borttagna regler för användarnamn som innehåller %{target}"
disable_2fa_user_html: "%{name} inaktiverade tvåfaktorsautentiseringskrav för användaren %{target}" disable_2fa_user_html: "%{name} inaktiverade tvåfaktorsautentiseringskrav för användaren %{target}"
disable_custom_emoji_html: "%{name} inaktiverade emoji %{target}" disable_custom_emoji_html: "%{name} inaktiverade emoji %{target}"
disable_relay_html: "%{name} inaktiverade ombudet %{target}" disable_relay_html: "%{name} inaktiverade ombudet %{target}"
@ -305,6 +307,7 @@ sv:
update_report_html: "%{name} uppdaterade rapporten %{target}" update_report_html: "%{name} uppdaterade rapporten %{target}"
update_status_html: "%{name} uppdaterade inlägget av %{target}" update_status_html: "%{name} uppdaterade inlägget av %{target}"
update_user_role_html: "%{name} ändrade rollen %{target}" update_user_role_html: "%{name} ändrade rollen %{target}"
update_username_block_html: "%{name} uppdaterade regel för användarnamn som innehåller %{target}"
deleted_account: raderat konto deleted_account: raderat konto
empty: Inga loggar hittades. empty: Inga loggar hittades.
filter_by_action: Filtrera efter åtgärd filter_by_action: Filtrera efter åtgärd
@ -1090,15 +1093,23 @@ sv:
trending: Trendande trending: Trendande
username_blocks: username_blocks:
add_new: Lägg till ny add_new: Lägg till ny
block_registrations: Registrerade blockeringar
comparison: comparison:
contains: Innehåller contains: Innehåller
equals: Lika
contains_html: Innehåller %{string}
created_msg: Användarnamnsregel har skapats
delete: Ta bort delete: Ta bort
edit: edit:
title: Redigera användarnamnsregel title: Redigera användarnamnsregel
matches_exactly_html: Lika med %{string}
new: new:
create: Skapa regel create: Skapa regel
title: Skapa ny användarnamnsregel title: Skapa ny användarnamnsregel
no_username_block_selected: Inga användarnamn regler ändrades eftersom ingen valdes
not_permitted: Ej tillåtet not_permitted: Ej tillåtet
title: Regler för användarnamn
updated_msg: Uppdaterade användarnamnsregel
warning_presets: warning_presets:
add_new: Lägg till ny add_new: Lägg till ny
delete: Radera delete: Radera
@ -1676,6 +1687,10 @@ sv:
title: Ny omnämning title: Ny omnämning
poll: poll:
subject: En undersökning av %{name} har avslutats subject: En undersökning av %{name} har avslutats
quote:
body: 'Ditt inlägg citerades av %{name}:'
subject: "%{name} citerade ditt inlägg"
title: Nytt citat
reblog: reblog:
body: 'Ditt inlägg boostades av %{name}:' body: 'Ditt inlägg boostades av %{name}:'
subject: "%{name} boostade ditt inlägg" subject: "%{name} boostade ditt inlägg"

View File

@ -5945,9 +5945,9 @@ __metadata:
linkType: hard linkType: hard
"core-js@npm:^3.30.2, core-js@npm:^3.45.0": "core-js@npm:^3.30.2, core-js@npm:^3.45.0":
version: 3.45.0 version: 3.45.1
resolution: "core-js@npm:3.45.0" resolution: "core-js@npm:3.45.1"
checksum: 10c0/118350f9f1d81f42a1276590d6c217dca04c789fdb8074c82e53056b1a784948769a62b16b98493fd73e8a988545432f302bca798571e56ad881b9c039a5a83c checksum: 10c0/c38e5fae5a05ee3a129c45e10056aafe61dbb15fd35d27e0c289f5490387541c89741185e0aeb61acb558559c6697e016c245cca738fa169a73f2b06cd30e6b6
languageName: node languageName: node
linkType: hard linkType: hard
@ -13818,8 +13818,8 @@ __metadata:
linkType: hard linkType: hard
"vite-plugin-pwa@npm:^1.0.2": "vite-plugin-pwa@npm:^1.0.2":
version: 1.0.2 version: 1.0.3
resolution: "vite-plugin-pwa@npm:1.0.2" resolution: "vite-plugin-pwa@npm:1.0.3"
dependencies: dependencies:
debug: "npm:^4.3.6" debug: "npm:^4.3.6"
pretty-bytes: "npm:^6.1.1" pretty-bytes: "npm:^6.1.1"
@ -13834,13 +13834,13 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
"@vite-pwa/assets-generator": "@vite-pwa/assets-generator":
optional: true optional: true
checksum: 10c0/e4f2f4dfff843ee2585a0d89e74187168ba20da77cd0d127ce7ad7eebcf5a68b2bf09000afb6bb86d43a2034fea9f568cd6db2a2d4b47a72e175d999a5e07eb1 checksum: 10c0/03fc24bd12ae4a4130979da4877e3dabddf13d7d6ff2bd68e5e8497a2643b8874a78e6c2502874277ddf2f28593d0a3b025d78af2335bdcc5d2966295784fd46
languageName: node languageName: node
linkType: hard linkType: hard
"vite-plugin-static-copy@npm:^3.1.1": "vite-plugin-static-copy@npm:^3.1.1":
version: 3.1.1 version: 3.1.2
resolution: "vite-plugin-static-copy@npm:3.1.1" resolution: "vite-plugin-static-copy@npm:3.1.2"
dependencies: dependencies:
chokidar: "npm:^3.6.0" chokidar: "npm:^3.6.0"
fs-extra: "npm:^11.3.0" fs-extra: "npm:^11.3.0"
@ -13849,7 +13849,7 @@ __metadata:
tinyglobby: "npm:^0.2.14" tinyglobby: "npm:^0.2.14"
peerDependencies: peerDependencies:
vite: ^5.0.0 || ^6.0.0 || ^7.0.0 vite: ^5.0.0 || ^6.0.0 || ^7.0.0
checksum: 10c0/a4dd5d31212b037d4902d55c2ee83866e496857bf948f258599dc24ec61b4628cf0dd23e4a7d7dc189d33ad1489427e976fa95e4db61b394d0be4f63077ef92c checksum: 10c0/1a65f4c9d291cc27483a5b225b1ac5610edc3aa2f13fa3a76a77327874c83bbee52e1011ee0bf5b0168b9b7b974213d49fe800e44af398cfbcb6607814b45c5b
languageName: node languageName: node
linkType: hard linkType: hard