Merge commit 'e770303968dc04d20dd5f3a5d7da3b9d7ba888fc' into glitch-soc/merge-upstream

Conflicts:
- `.rubocop_todo.yml`:
  Glitch-soc had different overrides, but upstream simply disabled the rules.
  Disabled them as well.
- `app/serializers/initial_state_serializer.rb`:
  Not really a conflict, again because of a rubocop comment.
This commit is contained in:
Claire committed 2025-08-22 22:33:11 +02:00
commit 02134172f1
47 files changed
+975 -169

No files matched your search

+2 -1
View File
@@ -2,6 +2,7 @@ import type { ApiStatusJSON } from './statuses';
export type ApiQuoteState = 'accepted' | 'pending' | 'revoked' | 'unauthorized';
export type ApiQuotePolicy = 'public' | 'followers' | 'nobody' | 'unknown';
export type ApiUserQuotePolicy = 'automatic' | 'manual' | 'denied' | 'unknown';
interface ApiQuoteEmptyJSON {
state: Exclude<ApiQuoteState, 'accepted'>;
@@ -25,7 +26,7 @@ export type ApiQuoteJSON = ApiQuoteAcceptedJSON | ApiQuoteEmptyJSON;
export interface ApiQuotePolicyJSON {
automatic: ApiQuotePolicy[];
manual: ApiQuotePolicy[];
current_user: ApiQuotePolicy;
current_user: ApiUserQuotePolicy;
}
export function isQuotePolicy(policy: string): policy is ApiQuotePolicy {
@@ -41,13 +41,16 @@ import { IconButton } from './icon_button';
let id = 0;
type RenderItemFn<Item = MenuItem> = (
export interface RenderItemFnHandlers {
onClick: React.MouseEventHandler;
onKeyUp: React.KeyboardEventHandler;
}
export type RenderItemFn<Item = MenuItem> = (
item: Item,
index: number,
handlers: {
onClick: (e: React.MouseEvent) => void;
onKeyUp: (e: React.KeyboardEvent) => void;
},
handlers: RenderItemFnHandlers,
focusRefCallback?: (c: HTMLAnchorElement | HTMLButtonElement | null) => void,
) => React.ReactNode;
type ItemClickFn<Item = MenuItem> = (item: Item, index: number) => void;
@@ -173,7 +176,7 @@ export const DropdownMenu = <Item = MenuItem,>({
onItemClick(item, i);
} else if (isActionItem(item)) {
e.preventDefault();
item.action();
item.action(e);
}
},
[onClose, onItemClick, items],
@@ -277,10 +280,15 @@ export const DropdownMenu = <Item = MenuItem,>({
})}
>
{items.map((option, i) =>
renderItemMethod(option, i, {
onClick: handleItemClick,
onKeyUp: handleItemKeyUp,
}),
renderItemMethod(
option,
i,
{
onClick: handleItemClick,
onKeyUp: handleItemKeyUp,
},
i === 0 ? handleFocusedItemRef : undefined,
),
)}
</ul>
)}
@@ -307,7 +315,9 @@ interface DropdownProps<Item = MenuItem> {
forceDropdown?: boolean;
renderItem?: RenderItemFn<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>;
}
@@ -376,7 +386,7 @@ export const Dropdown = <Item = MenuItem,>({
onItemClick(item, i);
} else if (isActionItem(item)) {
e.preventDefault();
item.action();
item.action(e);
}
},
[handleClose, onItemClick, items],
@@ -389,7 +399,10 @@ export const Dropdown = <Item = MenuItem,>({
if (open) {
handleClose();
} else {
onOpen?.();
const allow = onOpen?.(e);
if (allow === false) {
return;
}
if (prefetchAccountId) {
dispatch(fetchRelationships([prefetchAccountId]));
@@ -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}
/>
),
};
@@ -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;
}
@@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
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 BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.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 ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react';
import StarIcon from '@/material-icons/400-24px/star-fill.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 { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
@@ -30,6 +24,7 @@ import { me } from '../initial_state';
import { IconButton } from './icon_button';
import { isFeatureEnabled } from '../utils/environment';
import { ReblogButton } from './status/reblog_button';
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
@@ -43,10 +38,6 @@ const messages = defineMessages({
share: { id: 'status.share', defaultMessage: 'Share' },
more: { id: 'status.more', defaultMessage: 'More' },
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' },
removeFavourite: { id: 'status.remove_favourite', defaultMessage: 'Remove from favorites' },
bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' },
@@ -85,10 +76,9 @@ class StatusActionBar extends ImmutablePureComponent {
identity: identityContextPropShape,
status: ImmutablePropTypes.map.isRequired,
relationship: ImmutablePropTypes.record,
quotedAccountId: ImmutablePropTypes.string,
quotedAccountId: PropTypes.string,
onReply: PropTypes.func,
onFavourite: PropTypes.func,
onReblog: PropTypes.func,
onDelete: PropTypes.func,
onRevokeQuote: 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 = () => {
this.props.onBookmark(this.props.status);
};
@@ -377,25 +357,6 @@ class StatusActionBar extends ImmutablePureComponent {
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 favouriteTitle = intl.formatMessage(status.get('favourited') ? messages.removeFavourite : messages.favourite);
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')} />
</div>
<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 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} />
@@ -3,23 +3,16 @@ import { PureComponent } from 'react';
import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg?react';
import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.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 ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react';
import StarIcon from '@/material-icons/400-24px/star-fill.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 { 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 { me } from '../../../initial_state';
import { isFeatureEnabled } from '@/mastodon/utils/environment';
import { ReblogButton } from '@/mastodon/components/status/reblog_button';
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
@@ -35,10 +29,6 @@ const messages = defineMessages({
direct: { id: 'status.direct', defaultMessage: 'Privately mention @{name}' },
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
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' },
removeFavourite: { id: 'status.remove_favourite', defaultMessage: 'Remove from favorites' },
bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' },
@@ -313,31 +303,15 @@ class ActionBar extends PureComponent {
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 favouriteTitle = intl.formatMessage(status.get('favourited') ? messages.removeFavourite : messages.favourite);
return (
<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 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='bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={bookmarkTitle} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} /></div>
+7 -2
View File
@@ -836,22 +836,24 @@
"search_results.see_all": "Праглядзець усе",
"search_results.statuses": "Допісы",
"search_results.title": "Шукаць \"{q}\"",
"server_banner.about_active_users": "Людзі, якія карыстаюцца гэтым сервера на працягу апошніх 30 дзён (Штомесячна Актыўныя Карыстальнікі)",
"server_banner.about_active_users": "Людзі, якія карысталіся гэтым серверам на працягу апошніх 30 дзён (штомесячна актыўныя карыстальнікі)",
"server_banner.active_users": "актыўныя карыстальнікі",
"server_banner.administered_by": "Адміністратар:",
"server_banner.is_one_of_many": "{domain} - гэта адзін з многіх незалежных сервераў Mastodon, які Вы можаце выкарыстоўваць для ўдзелу ў федэральным сусвеце.",
"server_banner.server_stats": "Статыстыка сервера:",
"sign_in_banner.create_account": "Стварыць уліковы запіс",
"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.sso_redirect": "Уваход ці рэгістрацыя",
"status.admin_account": "Адкрыць інтэрфейс мадэратара для @{name}",
"status.admin_domain": "Адкрыць інтэрфейс мадэратара для {domain}",
"status.admin_status": "Адкрыць гэты допіс у інтэрфейсе мадэрацыі",
"status.all_disabled": "Пашырэнні і цытаванні адключаны",
"status.block": "Заблакаваць @{name}",
"status.bookmark": "Дадаць закладку",
"status.cancel_reblog_private": "Прыбраць",
"status.cannot_quote": "Аўтар допісу адключыў цытаванне",
"status.cannot_reblog": "Гэты допіс нельга пашырыць",
"status.context.load_new_replies": "Даступныя новыя адказы",
"status.context.loading": "Правяраюцца новыя адказы",
@@ -880,6 +882,8 @@
"status.mute_conversation": "Ігнараваць размову",
"status.open": "Разгарнуць гэты допіс",
"status.pin": "Замацаваць у профілі",
"status.quote": "Цытаваць",
"status.quote.cancel": "Адмяніць цытаванне",
"status.quote_error.filtered": "Схавана адным з Вашых фільтраў",
"status.quote_error.not_available": "Допіс недаступны",
"status.quote_error.pending_approval": "Допіс чакае пацвярджэння",
@@ -887,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Цытаваны допіс чакае пацвярджэння? Захоўвайце спакой",
"status.quote_policy_change": "Змяніць, хто можа цытаваць",
"status.quote_post_author": "Цытаваў допіс @{name}",
"status.quote_private": "Прыватныя допісы нельга цытаваць",
"status.read_more": "Чытаць болей",
"status.reblog": "Пашырыць",
"status.reblog_private": "Пашырыць з першапачатковай бачнасцю",
+4
View File
@@ -848,9 +848,11 @@
"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_status": "Obre aquest tut a la interfície de moderació",
"status.all_disabled": "S'han deshabilitat impulsos i cites",
"status.block": "Bloca @{name}",
"status.bookmark": "Marca",
"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.context.load_new_replies": "Hi ha respostes noves",
"status.context.loading": "Comprovació de més respostes",
@@ -879,6 +881,7 @@
"status.mute_conversation": "Silencia la conversa",
"status.open": "Amplia el tut",
"status.pin": "Fixa en el perfil",
"status.quote": "Cita",
"status.quote.cancel": "Canceŀlar la citació",
"status.quote_error.filtered": "No es mostra a causa d'un dels vostres filtres",
"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_policy_change": "Canvieu qui us pot citar",
"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.reblog": "Impulsa",
"status.reblog_private": "Impulsa amb la visibilitat original",
+5
View File
@@ -849,9 +849,11 @@
"status.admin_account": "Otevřít moderátorské rozhraní pro @{name}",
"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.all_disabled": "Boosty a citace jsou zakázány",
"status.block": "Blokovat @{name}",
"status.bookmark": "Přidat do záložek",
"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.context.load_new_replies": "K dispozici jsou nové odpovědi",
"status.context.loading": "Hledání dalších odpovědí",
@@ -880,6 +882,8 @@
"status.mute_conversation": "Skrýt konverzaci",
"status.open": "Rozbalit tento příspěvek",
"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.not_available": "Příspěvek není dostupný",
"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_policy_change": "Změňte, kdo může citovat",
"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.reblog": "Boostnout",
"status.reblog_private": "Boostnout s původní viditelností",
+4
View File
@@ -849,9 +849,11 @@
"status.admin_account": "@{name} moderieren",
"status.admin_domain": "{domain} moderieren",
"status.admin_status": "Beitrag moderieren",
"status.all_disabled": "Teilen und Zitieren von Beiträgen ist deaktiviert",
"status.block": "@{name} blockieren",
"status.bookmark": "Lesezeichen setzen",
"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.context.load_new_replies": "Neue Antworten verfügbar",
"status.context.loading": "Weitere Antworten werden abgerufen",
@@ -880,6 +882,7 @@
"status.mute_conversation": "Unterhaltung stummschalten",
"status.open": "Beitrag öffnen",
"status.pin": "Im Profil anheften",
"status.quote": "Zitieren",
"status.quote.cancel": "Zitat abbrechen",
"status.quote_error.filtered": "Ausgeblendet wegen eines deiner Filter",
"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_policy_change": "Ändern, wer zitieren darf",
"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.reblog": "Teilen",
"status.reblog_private": "Mit der ursprünglichen Zielgruppe teilen",
+5
View File
@@ -849,9 +849,11 @@
"status.admin_account": "Άνοιγμα διεπαφής συντονισμού για τον/την @{name}",
"status.admin_domain": "Άνοιγμα λειτουργίας διαμεσολάβησης για {domain}",
"status.admin_status": "Άνοιγμα αυτής της ανάρτησης σε διεπαφή συντονισμού",
"status.all_disabled": "Ενισχύσεις και παραθέσεις είναι απενεργοποιημένες",
"status.block": "Αποκλεισμός @{name}",
"status.bookmark": "Σελιδοδείκτης",
"status.cancel_reblog_private": "Ακύρωση ενίσχυσης",
"status.cannot_quote": "Ο συντάκτης έχει απενεργοποιήσει την παράθεση σε αυτή την ανάρτηση",
"status.cannot_reblog": "Αυτή η ανάρτηση δεν μπορεί να ενισχυθεί",
"status.context.load_new_replies": "Νέες απαντήσεις διαθέσιμες",
"status.context.loading": "Γίνεται έλεγχος για περισσότερες απαντήσεις",
@@ -880,6 +882,8 @@
"status.mute_conversation": "Σίγαση συνομιλίας",
"status.open": "Επέκταση ανάρτησης",
"status.pin": "Καρφίτσωσε στο προφίλ",
"status.quote": "Παράθεση",
"status.quote.cancel": "Ακύρωση παράθεσης",
"status.quote_error.filtered": "Κρυφό λόγω ενός από τα φίλτρα σου",
"status.quote_error.not_available": "Ανάρτηση μη διαθέσιμη",
"status.quote_error.pending_approval": "Ανάρτηση σε αναμονή",
@@ -887,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Παράθεση σε εκκρεμότητα; Μείνετε ψύχραιμοι",
"status.quote_policy_change": "Αλλάξτε ποιός μπορεί να κάνει παράθεση",
"status.quote_post_author": "Παρατίθεται μια ανάρτηση από @{name}",
"status.quote_private": "Ιδιωτικές αναρτήσεις δεν μπορούν να παρατεθούν",
"status.read_more": "Διάβασε περισότερα",
"status.reblog": "Ενίσχυση",
"status.reblog_private": "Ενίσχυση με αρχική ορατότητα",
+4
View File
@@ -849,9 +849,11 @@
"status.admin_account": "Open moderation interface for @{name}",
"status.admin_domain": "Open moderation interface for {domain}",
"status.admin_status": "Open this post in the moderation interface",
"status.all_disabled": "Boosts and quotes are disabled",
"status.block": "Block @{name}",
"status.bookmark": "Bookmark",
"status.cancel_reblog_private": "Unboost",
"status.cannot_quote": "Author has disabled quoting on this post",
"status.cannot_reblog": "This post cannot be boosted",
"status.context.load_new_replies": "New replies available",
"status.context.loading": "Checking for more replies",
@@ -880,6 +882,7 @@
"status.mute_conversation": "Mute conversation",
"status.open": "Expand this post",
"status.pin": "Pin on profile",
"status.quote": "Quote",
"status.quote.cancel": "Cancel quote",
"status.quote_error.filtered": "Hidden due to one of your filters",
"status.quote_error.not_available": "Post unavailable",
@@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Pending quote? Remain calm",
"status.quote_policy_change": "Change who can quote",
"status.quote_post_author": "Quoted a post by @{name}",
"status.quote_private": "Private posts cannot be quoted",
"status.read_more": "Read more",
"status.reblog": "Boost",
"status.reblog_private": "Boost with original visibility",
+11
View File
@@ -568,6 +568,8 @@
"navigation_bar.preferences": "Preferoj",
"navigation_bar.privacy_and_reach": "Privateco kaj atingo",
"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.",
"notification.admin.report": "{name} raportis {target}",
"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.bookmark": "Aldoni al la legosignoj",
"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.context.load_new_replies": "Disponeblaj novaj respondoj",
"status.context.loading": "Serĉante pliajn respondojn",
@@ -865,9 +868,16 @@
"status.mute_conversation": "Silentigi konversacion",
"status.open": "Pligrandigu ĉi tiun afiŝon",
"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.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_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.reblog": "Diskonigi",
"status.reblog_private": "Diskonigi kun la sama videbleco",
@@ -882,6 +892,7 @@
"status.reply": "Respondi",
"status.replyAll": "Respondi al la fadeno",
"status.report": "Raporti @{name}",
"status.revoke_quote": "Forigu mian afiŝon el la afiŝo de @{name}",
"status.sensitive_warning": "Tikla enhavo",
"status.share": "Kundividi",
"status.show_less_all": "Montri malpli ĉiun",
@@ -849,9 +849,11 @@
"status.admin_account": "Abrir interface de moderación para @{name}",
"status.admin_domain": "Abrir interface de moderación para {domain}",
"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.bookmark": "Marcar",
"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.context.load_new_replies": "Hay nuevas respuestas",
"status.context.loading": "Buscando más respuestas",
@@ -880,6 +882,7 @@
"status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir este mensaje",
"status.pin": "Fijar en el perfil",
"status.quote": "Citar",
"status.quote.cancel": "Cancelar cita",
"status.quote_error.filtered": "Oculto debido a uno de tus filtros",
"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_policy_change": "Cambiá quién puede citar",
"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.reblog": "Adherir",
"status.reblog_private": "Adherir a la audiencia original",
@@ -849,9 +849,11 @@
"status.admin_account": "Abrir interfaz de moderación para @{name}",
"status.admin_domain": "Abrir interfaz de moderación para {domain}",
"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.bookmark": "Añadir marcador",
"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.context.load_new_replies": "Nuevas respuestas disponibles",
"status.context.loading": "Comprobando si hay más respuestas",
@@ -880,6 +882,7 @@
"status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir estado",
"status.pin": "Fijar",
"status.quote": "Cita",
"status.quote.cancel": "Cancelar cita",
"status.quote_error.filtered": "Oculto debido a uno de tus filtros",
"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_policy_change": "Cambia quién puede citarte",
"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.reblog": "Impulsar",
"status.reblog_private": "Implusar a la audiencia original",
+5 -1
View File
@@ -849,9 +849,11 @@
"status.admin_account": "Abrir interfaz de moderación para @{name}",
"status.admin_domain": "Abrir interfaz de moderación para {domain}",
"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.bookmark": "Añadir marcador",
"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.context.load_new_replies": "Hay nuevas respuestas",
"status.context.loading": "Buscando más respuestas",
@@ -880,6 +882,7 @@
"status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir publicación",
"status.pin": "Fijar",
"status.quote": "Cita",
"status.quote.cancel": "Cancelar cita",
"status.quote_error.filtered": "Oculto debido a uno de tus filtros",
"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_policy_change": "Cambia quién puede citarte",
"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.reblog": "Impulsar",
"status.reblog_private": "Impulsar a la audiencia original",
@@ -966,7 +970,7 @@
"visibility_modal.button_title": "Configura la visibilidad",
"visibility_modal.header": "Visibilidad e interacciones",
"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.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>.",
+2 -1
View File
@@ -43,7 +43,7 @@
"account.followers": "پی‌گیرندگان",
"account.followers.empty": "هنوز کسی پی‌گیر این کاربر نیست.",
"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_counter": "{count, plural, one {{counter} پی‌گرفته} other {{counter} پی‌گرفته}}",
"account.follows.empty": "این کاربر هنوز پی‌گیر کسی نیست.",
@@ -880,6 +880,7 @@
"status.mute_conversation": "خموشاندن گفت‌وگو",
"status.open": "گسترش این فرسته",
"status.pin": "سنجاق به نمایه",
"status.quote.cancel": "لغو نقل",
"status.quote_error.filtered": "نهفته بنا بر یکی از پالایه‌هایتان",
"status.quote_error.not_available": "فرسته در دسترس نیست",
"status.quote_error.pending_approval": "فرسته منتظر",
+4
View File
@@ -849,9 +849,11 @@
"status.admin_account": "Avaa tilin @{name} moderointinäkymä",
"status.admin_domain": "Avaa palvelimen {domain} moderointinäkymä",
"status.admin_status": "Avaa julkaisu moderointinäkymässä",
"status.all_disabled": "Tehostukset ja lainaukset ovat poissa käytöstä",
"status.block": "Estä @{name}",
"status.bookmark": "Lisää kirjanmerkki",
"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.context.load_new_replies": "Uusia vastauksia saatavilla",
"status.context.loading": "Tarkistetaan lisävastauksia",
@@ -880,6 +882,7 @@
"status.mute_conversation": "Mykistä keskustelu",
"status.open": "Laajenna julkaisu",
"status.pin": "Kiinnitä profiiliin",
"status.quote": "Lainaa",
"status.quote.cancel": "Peruuta lainaus",
"status.quote_error.filtered": "Piilotettu jonkin asettamasi suodattimen takia",
"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_policy_change": "Vaihda, kuka voi lainata",
"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.reblog": "Tehosta",
"status.reblog_private": "Tehosta alkuperäiselle yleisölle",
+4
View File
@@ -849,9 +849,11 @@
"status.admin_account": "Lat kjakleiðaramarkamót upp fyri @{name}",
"status.admin_domain": "Lat umsjónarmarkamót upp fyri {domain}",
"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.bookmark": "Goym",
"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.context.load_new_replies": "Nýggj svar tøk",
"status.context.loading": "Kanni um tað eru fleiri svar",
@@ -880,6 +882,7 @@
"status.mute_conversation": "Doyv samrøðu",
"status.open": "Víðka henda postin",
"status.pin": "Ger fastan í vangan",
"status.quote": "Sitat",
"status.quote.cancel": "Ógilda sitat",
"status.quote_error.filtered": "Eitt av tínum filtrum fjalir hetta",
"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_policy_change": "Broyt hvør kann sitera",
"status.quote_post_author": "Siteraði ein post hjá @{name}",
"status.quote_private": "Privatir postar kunnu ikki siterast",
"status.read_more": "Les meira",
"status.reblog": "Stimbra",
"status.reblog_private": "Stimbra við upprunasýni",
+4
View File
@@ -849,9 +849,11 @@
"status.admin_account": "פתח/י ממשק פיקוח דיון עבור @{name}",
"status.admin_domain": "פתיחת ממשק פיקוח דיון עבור {domain}",
"status.admin_status": "לפתוח הודעה זו במסך ניהול הדיונים",
"status.all_disabled": "הדהודים וציטוטים כובו",
"status.block": "חסימת @{name}",
"status.bookmark": "סימניה",
"status.cancel_reblog_private": "הסרת הדהוד",
"status.cannot_quote": "יוצר\\ת ההודעה חסמו את האפשרות לצטט אותה",
"status.cannot_reblog": "לא ניתן להדהד חצרוץ זה",
"status.context.load_new_replies": "הגיעו תגובות חדשות",
"status.context.loading": "מחפש תגובות חדשות",
@@ -880,6 +882,7 @@
"status.mute_conversation": "השתקת שיחה",
"status.open": "הרחבת הודעה זו",
"status.pin": "הצמדה לפרופיל שלי",
"status.quote": "ציטוט",
"status.quote.cancel": "ביטול הודעת ציטוט",
"status.quote_error.filtered": "מוסתר בהתאם לסננים שלך",
"status.quote_error.not_available": "ההודעה לא זמינה",
@@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "ההודעה בהמתנה? המתינו ברוגע",
"status.quote_policy_change": "הגדרת הרשאה לציטוט הודעותיך",
"status.quote_post_author": "ההודעה צוטטה על ידי @{name}",
"status.quote_private": "הודעות פרטיות לא ניתנות לציטוט",
"status.read_more": "לקרוא עוד",
"status.reblog": "הדהוד",
"status.reblog_private": "להדהד ברמת הנראות המקורית",
+72 -2
View File
@@ -1,6 +1,7 @@
{
"about.blocks": "Servitores moderate",
"about.contact": "Contacto:",
"about.default_locale": "Default",
"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.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.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.language_label": "Lingua",
"about.not_available": "Iste information non ha essite rendite disponibile sur iste servitor.",
"about.powered_by": "Rete social decentralisate, actionate per {mastodon}",
"about.rules": "Regulas del servitor",
@@ -41,6 +43,7 @@
"account.followers": "Sequitores",
"account.followers.empty": "Necuno seque ancora iste usator.",
"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_counter": "{count, plural, one {{counter} sequite} other {{counter} sequites}}",
"account.follows.empty": "Iste usator non seque ancora alcuno.",
@@ -216,6 +219,13 @@
"confirmations.delete_list.confirm": "Deler",
"confirmations.delete_list.message": "Es tu secur que tu vole deler permanentemente iste 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.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",
@@ -235,6 +245,9 @@
"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.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.message": "Es tu secur que tu vole cessar de sequer {name}?",
"confirmations.unfollow.title": "Cessar de sequer le usator?",
@@ -279,6 +292,7 @@
"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_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.preview": "Ecce como illlo parera:",
"emoji_button.activity": "Activitate",
@@ -296,6 +310,8 @@
"emoji_button.search_results": "Resultatos de recerca",
"emoji_button.symbols": "Symbolos",
"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_hides_collections": "Le usator non ha rendite iste information disponibile",
"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.report_issue": "Reportar problema",
"explore.suggested_follows": "Personas",
"explore.title": "In tendentia",
"explore.trending_links": "Novas",
"explore.trending_statuses": "Messages",
"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_title": "Contexto incoherente!",
"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",
"getting_started.heading": "Prime passos",
"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.any": "o {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_follows": "Vider plus de sequites 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_replies": "Monstrar responsas",
"home.hide_announcements": "Celar annuncios",
@@ -477,6 +502,8 @@
"keyboard_shortcuts.translate": "a traducer un message",
"keyboard_shortcuts.unfocus": "Disfocalisar le area de composition de texto/de recerca",
"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.next": "Sequente",
"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_posts": "Iste persona pote totevia vider tu messages, ma tu non videra le sues.",
"navigation_bar.about": "A proposito",
"navigation_bar.account_settings": "Contrasigno e securitate",
"navigation_bar.administration": "Administration",
"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.bookmarks": "Marcapaginas",
"navigation_bar.direct": "Mentiones private",
@@ -537,13 +566,23 @@
"navigation_bar.follow_requests": "Requestas de sequimento",
"navigation_bar.followed_tags": "Hashtags sequite",
"navigation_bar.follows_and_followers": "Sequites e sequitores",
"navigation_bar.import_export": "Importar e exportar",
"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.moderation": "Moderation",
"navigation_bar.more": "Plus",
"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.preferences": "Preferentias",
"navigation_bar.privacy_and_reach": "Confidentialitate e portata",
"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.",
"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}",
@@ -565,6 +604,7 @@
"notification.label.mention": "Mention",
"notification.label.private_mention": "Mention private",
"notification.label.private_reply": "Responsa private",
"notification.label.quote": "{name} ha citate tu message",
"notification.label.reply": "Responder",
"notification.mention": "Mention",
"notification.mentioned_you": "{name} te ha mentionate",
@@ -622,6 +662,7 @@
"notifications.column_settings.mention": "Mentiones:",
"notifications.column_settings.poll": "Resultatos del sondage:",
"notifications.column_settings.push": "Notificationes push",
"notifications.column_settings.quote": "Citationes:",
"notifications.column_settings.reblog": "Impulsos:",
"notifications.column_settings.show": "Monstrar in columna",
"notifications.column_settings.sound": "Reproducer sono",
@@ -770,6 +811,7 @@
"report_notification.categories.violation": "Violation del regulas",
"report_notification.categories.violation_sentence": "violation del regulas",
"report_notification.open": "Aperir reporto",
"search.clear": "Rader le recerca",
"search.no_recent_searches": "Nulle recercas recente",
"search.placeholder": "Cercar",
"search.quick_action.account_search": "Profilos correspondente a {x}",
@@ -811,6 +853,8 @@
"status.bookmark": "Adder al marcapaginas",
"status.cancel_reblog_private": "Disfacer impulso",
"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.copy": "Copiar ligamine a message",
"status.delete": "Deler",
@@ -836,6 +880,14 @@
"status.mute_conversation": "Silentiar conversation",
"status.open": "Expander iste message",
"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.reblog": "Impulsar",
"status.reblog_private": "Impulsar con visibilitate original",
@@ -850,6 +902,7 @@
"status.reply": "Responder",
"status.replyAll": "Responder al discussion",
"status.report": "Reportar @{name}",
"status.revoke_quote": "Remover mi message del message de @{name}",
"status.sensitive_warning": "Contento sensibile",
"status.share": "Compartir",
"status.show_less_all": "Monstrar minus pro totes",
@@ -865,9 +918,13 @@
"subscribed_languages.save": "Salvar le cambiamentos",
"subscribed_languages.target": "Cambiar le linguas subscribite pro {target}",
"tabs_bar.home": "Initio",
"tabs_bar.menu": "Menu",
"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.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.hours": "{number, plural, one {# hora} other {# horas}} 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",
"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",
"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.million": "{count}M",
"units.short.thousand": "{count}K",
@@ -902,7 +959,20 @@
"video.pause": "Pausa",
"video.play": "Reproducer",
"video.skip_backward": "Saltar a retro",
"video.skip_forward": "Avantiar",
"video.unmute": "Non plus silentiar",
"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"
}
+4
View File
@@ -849,9 +849,11 @@
"status.admin_account": "Opna umsjónarviðmót fyrir @{name}",
"status.admin_domain": "Opna umsjónarviðmót fyrir @{domain}",
"status.admin_status": "Opna þessa færslu í umsjónarviðmótinu",
"status.all_disabled": "Endurbirtingar og tilvitnanir eru óvirkar",
"status.block": "Útiloka @{name}",
"status.bookmark": "Bókamerki",
"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.context.load_new_replies": "Ný svör hafa borist",
"status.context.loading": "Athuga með fleiri svör",
@@ -880,6 +882,7 @@
"status.mute_conversation": "Þagga niður í samtali",
"status.open": "Opna þessa færslu",
"status.pin": "Festa á notandasnið",
"status.quote": "Tilvitnun",
"status.quote.cancel": "Hætta við tilvitnun",
"status.quote_error.filtered": "Falið vegna einnar síu sem er virk",
"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_policy_change": "Breyttu því hver getur tilvitnað",
"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.reblog": "Endurbirting",
"status.reblog_private": "Endurbirta til upphaflegra lesenda",
+24 -1
View File
@@ -245,6 +245,9 @@
"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.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.message": "Sei sicuro di voler smettere di seguire {name}?",
"confirmations.unfollow.title": "Smettere di seguire l'utente?",
@@ -289,6 +292,7 @@
"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_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.preview": "Ecco come apparirà:",
"emoji_button.activity": "Attività",
@@ -845,9 +849,11 @@
"status.admin_account": "Apri interfaccia di moderazione per @{name}",
"status.admin_domain": "Apri l'interfaccia di moderazione per {domain}",
"status.admin_status": "Apri questo post nell'interfaccia di moderazione",
"status.all_disabled": "Condivisioni e citazioni sono disabilitate",
"status.block": "Blocca @{name}",
"status.bookmark": "Aggiungi segnalibro",
"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.context.load_new_replies": "Nuove risposte disponibili",
"status.context.loading": "Controllo per altre risposte",
@@ -876,12 +882,16 @@
"status.mute_conversation": "Silenzia conversazione",
"status.open": "Espandi questo post",
"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.not_available": "Post non disponibile",
"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.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_private": "I post privati non possono essere citati",
"status.read_more": "Leggi di più",
"status.reblog": "Reblog",
"status.reblog_private": "Reblog con visibilità originale",
@@ -896,6 +906,7 @@
"status.reply": "Rispondi",
"status.replyAll": "Rispondi alla conversazione",
"status.report": "Segnala @{name}",
"status.revoke_quote": "Rimuovi la mia citazione dal post di @{name}",
"status.sensitive_warning": "Contenuto sensibile",
"status.share": "Condividi",
"status.show_less_all": "Mostra meno per tutti",
@@ -955,5 +966,17 @@
"video.skip_forward": "Vai avanti",
"video.unmute": "Muta",
"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"
}
+14 -2
View File
@@ -23,11 +23,14 @@
"account.edit_profile": "प्रोफाइल सम्पादन गर्नुहोस्",
"account.enable_notifications": "@{name} ले पोस्ट गर्दा मलाई सूचित गर्नुहोस्",
"account.endorse": "प्रोफाइलमा फिचर गर्नुहोस्",
"account.featured": "फिचर गरिएको",
"account.featured.accounts": "प्रोफाइलहरू",
"account.featured.hashtags": "ह्यासट्यागहरू",
"account.featured_tags.last_status_never": "कुनै पोस्ट छैन",
"account.follow": "फलो गर्नुहोस",
"account.follow_back": "फलो ब्याक गर्नुहोस्",
"account.followers": "फलोअरहरु",
"account.followers.empty": "यस प्रयोगकर्तालाई अहिलेसम्म कसैले फलो गर्दैन।",
"account.followers.empty": "यस प्रयोगकर्तालाई अहिलेसम्म कसैले फलो गरेको छैन।",
"account.followers_counter": "{count, plural, one {{counter} फलोअर} other {{counter} फलोअरहरू}}",
"account.following": "फलो गर्दै",
"account.following_counter": "{count, plural, one {{counter} फलो गर्दै} other {{counter} फलो गर्दै}}",
@@ -42,6 +45,7 @@
"account.mute_notifications_short": "सूचनाहरू म्यूट गर्नुहोस्",
"account.mute_short": "म्युट",
"account.muted": "म्युट गरिएको",
"account.mutual": "तपाईंहरु एकअर्कालाई फलो गर्नुहुन्छ",
"account.no_bio": "कुनै विवरण प्रदान गरिएको छैन।",
"account.posts": "पोस्टहरू",
"account.posts_with_replies": "पोस्ट र जवाफहरू",
@@ -53,6 +57,7 @@
"account.statuses_counter": "{count, plural, one {{counter} पोस्ट} other {{counter} पोस्टहरू}}",
"account.unblock": "@{name} लाई अनब्लक गर्नुहोस्",
"account.unblock_domain": "{domain} डोमेनलाई अनब्लक गर्नुहोस्",
"account.unblock_domain_short": "अनब्लक गर्नुहोस्",
"account.unblock_short": "अनब्लक गर्नुहोस्",
"account.unendorse": "प्रोफाइलमा फिचर नगर्नुहोस्",
"account.unfollow": "अनफलो गर्नुहोस्",
@@ -64,6 +69,7 @@
"admin.dashboard.retention.cohort_size": "नयाँ प्रयोगकर्ताहरू",
"alert.rate_limited.message": "कृपया {retry_time, time, medium} पछि पुन: प्रयास गर्नुहोस्।",
"alert.unexpected.message": "एउटा अनपेक्षित त्रुटि भयो।",
"alt_text_modal.cancel": "रद्द गर्नुहोस्",
"announcement.announcement": "घोषणा",
"annual_report.summary.followers.followers": "फलोअरहरु",
"annual_report.summary.highlighted_post.by_reblogs": "सबैभन्दा बढि बूस्ट गरिएको पोस्ट",
@@ -156,8 +162,13 @@
"notification_requests.confirm_accept_multiple.title": "सूचना अनुरोधहरू स्वीकार गर्ने?",
"notification_requests.confirm_dismiss_multiple.title": "सूचना अनुरोधहरू खारेज गर्ने?",
"notifications.clear_title": "सूचनाहरू खाली गर्ने?",
"notifications.column_settings.follow": "नयाँ फलोअरहरु:",
"notifications.column_settings.follow_request": "नयाँ फलोअर अनुरोधहरु",
"notifications.column_settings.reblog": "बूस्टहरू:",
"notifications.filter.boosts": "बूस्टहरू",
"privacy.private.long": "मात्र तपाईंको फलोअरहरु",
"privacy.private.short": "फलोअरहरु",
"reply_indicator.cancel": "रद्द गर्नुहोस्",
"report.comment.title": "के हामीले थाहा पाउनुपर्ने अरू केही छ जस्तो लाग्छ?",
"report.forward_hint": "यो खाता अर्को सर्भरबाट हो। त्यहाँ पनि रिपोर्टको गुमनाम प्रतिलिपि पठाउने हो?",
"report.rules.title": "कुन नियमहरू उल्लङ्घन भइरहेका छन्?",
@@ -172,5 +183,6 @@
"status.reblog": "बूस्ट गर्नुहोस्",
"status.reblogged_by": "{name} ले बूस्ट गर्नुभएको",
"status.reblogs": "{count, plural, one {बूस्ट} other {बूस्टहरू}}",
"status.unmute_conversation": "कुराकानी अनम्यूट गर्नुहोस्"
"status.unmute_conversation": "कुराकानी अनम्यूट गर्नुहोस्",
"visibility_modal.quote_followers": "फलोअरहरु मात्र"
}
+6 -6
View File
@@ -350,14 +350,14 @@
"featured_carousel.previous": "Предыдущий",
"featured_carousel.slide": "{index} из {total}",
"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_title": "Истёкший фильтр!",
"filter_modal.added.expired_title": "Истёкший фильтр",
"filter_modal.added.review_and_configure": "Для просмотра или редактирования этого фильтра перейдите в {settings_link}.",
"filter_modal.added.review_and_configure_title": "Настройки фильтра",
"filter_modal.added.settings_link": "настройки",
"filter_modal.added.short_explanation": "Этот пост был добавлен к фильтру «{title}».",
"filter_modal.added.title": "Фильтр добавлен!",
"filter_modal.added.title": "Фильтр добавлен",
"filter_modal.select_filter.context_mismatch": "не применяется в этом контексте",
"filter_modal.select_filter.expired": "истёкший",
"filter_modal.select_filter.prompt_new": "Новый фильтр: {name}",
@@ -433,7 +433,7 @@
"home.hide_announcements": "Скрыть объявления",
"home.pending_critical_update.body": "Пожалуйста, обновите свой сервер Mastodon как можно скорее!",
"home.pending_critical_update.link": "Посмотреть обновления",
"home.pending_critical_update.title": "Доступно критическое обновление безопасности!",
"home.pending_critical_update.title": "Доступно критическое обновление безопасности",
"home.show_announcements": "Показать объявления",
"ignore_notifications_modal.disclaimer": "Mastodon не может сообщить пользователям, что вы игнорируете их уведомления. Игнорирование уведомлений не остановит отправку самих сообщений.",
"ignore_notifications_modal.filter_instead": "Фильтровать",
@@ -590,7 +590,7 @@
"notification.admin.report_statuses_other": "{name} пожаловался (-лась) на {target}",
"notification.admin.sign_up": "{name} зарегистрировался (-лась) на сервере",
"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.favourite": "{name} добавил(а) ваш пост в избранное",
"notification.favourite.name_and_others_with_link": "{name} и ещё <a>{count, plural, one {# пользователь} few {# пользователя} other {# пользователей}}</a> добавили ваш пост в избранное",
@@ -861,7 +861,7 @@
"status.direct": "Упомянуть @{name} лично",
"status.direct_indicator": "Личное упоминание",
"status.edit": "Редактировать",
"status.edited": "Дата последнего изменения: {date}",
"status.edited": "Последнее изменение: {date}",
"status.edited_x_times": "{count, plural, one {{count} изменение} many {{count} изменений} other {{count} изменения}}",
"status.embed": "Встроить на свой сайт",
"status.favourite": "Добавить в избранное",
+17
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.title": "Ta bort följare?",
"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.unfollow.confirm": "Avfölj",
"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.private_mention": "Privat omnämnande",
"notification.label.private_reply": "Privata svar",
"notification.label.quote": "{name} citerade ditt inlägg",
"notification.label.reply": "Svar",
"notification.mention": "Nämn",
"notification.mentioned_you": "{name} nämnde dig",
@@ -660,6 +662,7 @@
"notifications.column_settings.mention": "Omnämningar:",
"notifications.column_settings.poll": "Omröstningsresultat:",
"notifications.column_settings.push": "Push-aviseringar",
"notifications.column_settings.quote": "Citerat:",
"notifications.column_settings.reblog": "Boostar:",
"notifications.column_settings.show": "Visa i kolumnen",
"notifications.column_settings.sound": "Spela upp ljud",
@@ -877,8 +880,14 @@
"status.mute_conversation": "Tysta konversation",
"status.open": "Utvidga detta inlägg",
"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.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.reblog": "Boosta",
"status.reblog_private": "Boosta med ursprunglig synlighet",
@@ -893,6 +902,7 @@
"status.reply": "Svara",
"status.replyAll": "Svara på tråden",
"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.share": "Dela",
"status.show_less_all": "Visa mindre för alla",
@@ -953,9 +963,16 @@
"video.unmute": "Avtysta",
"video.volume_down": "Volym ned",
"video.volume_up": "Volym upp",
"visibility_modal.button_title": "Ange synlighet",
"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.quote_followers": "Endast följare",
"visibility_modal.quote_label": "Ändra vem som kan citera",
"visibility_modal.quote_nobody": "Ingen",
"visibility_modal.quote_public": "Alla"
}
+20 -1
View File
@@ -292,6 +292,7 @@
"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_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.preview": "İşte nasıl görüneceği:",
"emoji_button.activity": "Aktivite",
@@ -848,9 +849,11 @@
"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_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.bookmark": "Yer işareti ekle",
"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.context.load_new_replies": "Yeni yanıtlar mevcut",
"status.context.loading": "Daha fazla yanıt için kontrol ediliyor",
@@ -879,12 +882,16 @@
"status.mute_conversation": "Sohbeti sessize al",
"status.open": "Bu gönderiyi genişlet",
"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.not_available": "Gönderi kullanılamıyor",
"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.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_private": "Özel gönderiler alıntılanamaz",
"status.read_more": "Devamını okuyun",
"status.reblog": "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.unmute": "Sesi aç",
"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"
}
+4
View File
@@ -849,9 +849,11 @@
"status.admin_account": "Mở giao diện quản trị @{name}",
"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.all_disabled": "Đăng lại và trích dẫn bị tắt",
"status.block": "Chặn @{name}",
"status.bookmark": "Lưu",
"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.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",
@@ -880,6 +882,7 @@
"status.mute_conversation": "Tắt thông báo",
"status.open": "Mở tút",
"status.pin": "Ghim lên hồ sơ",
"status.quote": "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.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_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_private": "Không thể trích dẫn nhắn riêng",
"status.read_more": "Đọc tiếp",
"status.reblog": "Đăng lại",
"status.reblog_private": "Đăng lại (Riêng tư)",
@@ -849,9 +849,11 @@
"status.admin_account": "開啟 @{name} 的管理介面",
"status.admin_domain": "開啟 {domain} 的管理介面",
"status.admin_status": "於管理介面開啟此嘟文",
"status.all_disabled": "已停用轉嘟與引用",
"status.block": "封鎖 @{name}",
"status.bookmark": "書籤",
"status.cancel_reblog_private": "取消轉嘟",
"status.cannot_quote": "作者已停用引用此嘟文",
"status.cannot_reblog": "這則嘟文無法被轉嘟",
"status.context.load_new_replies": "有新回嘟",
"status.context.loading": "正在檢查更多回嘟",
@@ -880,6 +882,7 @@
"status.mute_conversation": "靜音對話",
"status.open": "展開此嘟文",
"status.pin": "釘選至個人檔案頁面",
"status.quote": "引用",
"status.quote.cancel": "取消引用嘟文",
"status.quote_error.filtered": "由於您的過濾器,該嘟文被隱藏",
"status.quote_error.not_available": "無法取得該嘟文",
@@ -888,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "引用嘟文正在發送中?別著急,請稍候片刻",
"status.quote_policy_change": "變更可以引用的人",
"status.quote_post_author": "已引用 @{name} 之嘟文",
"status.quote_private": "無法引用私人嘟文",
"status.read_more": "閱讀更多",
"status.reblog": "轉嘟",
"status.reblog_private": "依照原嘟可見性轉嘟",
@@ -1,10 +1,12 @@
import type { KeyboardEvent, MouseEvent, TouchEvent } from 'react';
interface BaseMenuItem {
text: string;
dangerous?: boolean;
}
export interface ActionMenuItem extends BaseMenuItem {
action: () => void;
action: (event: MouseEvent | KeyboardEvent | TouchEvent) => void;
}
export interface LinkMenuItem extends BaseMenuItem {
@@ -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

+48 -14
View File
@@ -1482,18 +1482,19 @@ body > [data-popper-placement] {
border-bottom: 0;
.status__content,
.status__action-bar,
.media-gallery,
.video-player,
.audio-player,
.attachment-list,
.picture-in-picture-placeholder,
.more-from-author,
.status-card,
.hashtag-bar,
.content-warning,
.filter-warning {
& > .status__content,
& > .status__action-bar,
& > .media-gallery,
& > .video-player,
& > .audio-player,
& > .attachment-list,
& > .picture-in-picture-placeholder,
& > .more-from-author,
& > .status-card,
& > .hashtag-bar,
& > .content-warning,
& > .filter-warning,
& > .status__quote {
margin-inline-start: var(--thread-margin);
width: calc(100% - var(--thread-margin));
}
@@ -2856,10 +2857,43 @@ a.account__display-name {
&:focus,
&:hover,
&:active {
background: var(--dropdown-border-color);
outline: 0;
&:not(:disabled) {
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 {
+34
View File
@@ -1,9 +1,13 @@
import { Map as ImmutableMap } from 'immutable';
import type { ApiRelationshipJSON } from '@/mastodon/api_types/relationships';
import type { ApiStatusJSON } from '@/mastodon/api_types/statuses';
import type {
CustomEmojiData,
UnicodeEmojiData,
} from '@/mastodon/features/emoji/types';
import { createAccountFromServerJSON } from '@/mastodon/models/account';
import type { Status } from '@/mastodon/models/status';
import type { ApiAccountJSON } from 'mastodon/api_types/accounts';
type FactoryOptions<T> = {
@@ -51,6 +55,36 @@ export const accountFactoryState = (
options: FactoryOptions<ApiAccountJSON> = {},
) => 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> = ({
id,
...data