Merge branch 'main' into feature/require-mfa-by-admin

This commit is contained in:
FredysFonseca 2025-08-24 20:52:39 -04:00 committed by GitHub
commit a5b2b564ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
110 changed files with 501 additions and 468 deletions

View File

@ -88,7 +88,7 @@ gem 'sidekiq-scheduler', '~> 6.0'
gem 'sidekiq-unique-jobs', '> 8'
gem 'simple_form', '~> 5.2'
gem 'simple-navigation', '~> 4.4'
gem 'stoplight'
gem 'stoplight', github: 'ClearlyClaire/stoplight', ref: 'f13e0c0d5e6d34af8d3cfc888871caa84237db42'
gem 'strong_migrations'
gem 'tty-prompt', '~> 0.23', require: false
gem 'twitter-text', '~> 3.1.0'

View File

@ -1,3 +1,11 @@
GIT
remote: https://github.com/ClearlyClaire/stoplight.git
revision: f13e0c0d5e6d34af8d3cfc888871caa84237db42
ref: f13e0c0d5e6d34af8d3cfc888871caa84237db42
specs:
stoplight (5.3.1)
zeitwerk
GIT
remote: https://github.com/mastodon/webpush.git
revision: 9631ac63045cfabddacc69fc06e919b4c13eb913
@ -853,8 +861,6 @@ GEM
stackprof (0.2.27)
starry (0.2.0)
base64
stoplight (5.3.1)
zeitwerk
stringio (3.1.7)
strong_migrations (2.5.0)
activerecord (>= 7.1)
@ -1086,7 +1092,7 @@ DEPENDENCIES
simplecov (~> 0.22)
simplecov-lcov (~> 0.8)
stackprof
stoplight
stoplight!
strong_migrations
test-prof
thor (~> 1.2)

View File

@ -98,13 +98,13 @@ export const DropdownSelector: React.FC<Props> = ({
break;
case 'Tab':
if (e.shiftKey) {
element =
nodeRef.current?.children[index + 1] ??
nodeRef.current?.firstElementChild;
} else {
element =
nodeRef.current?.children[index - 1] ??
nodeRef.current?.lastElementChild;
} else {
element =
nodeRef.current?.children[index + 1] ??
nodeRef.current?.firstElementChild;
}
break;
case 'Home':

View File

@ -7,11 +7,7 @@ import { normalizeKey, isKeyboardEvent } from './utils';
* the hotkey with a higher priority is selected. All others
* are ignored.
*/
const hotkeyPriority = {
singleKey: 0,
combo: 1,
sequence: 2,
} as const;
const hotkeyPriority = { singleKey: 0, combo: 1, sequence: 2 } as const;
/**
* This type of function receives a keyboard event and an array of
@ -105,14 +101,15 @@ const hotkeyMatcherMap = {
new: just('n'),
forceNew: optionPlus('n'),
focusColumn: any('1', '2', '3', '4', '5', '6', '7', '8', '9'),
focusLoadMore: just('l'),
reply: just('r'),
favourite: just('f'),
boost: just('b'),
mention: just('m'),
open: any('enter', 'o'),
openProfile: just('p'),
moveDown: any('down', 'j'),
moveUp: any('up', 'k'),
moveDown: just('j'),
moveUp: just('k'),
toggleHidden: just('x'),
toggleSensitive: just('h'),
toggleComposeSpoilers: optionPlus('x'),

View File

@ -114,8 +114,6 @@ class Status extends ImmutablePureComponent {
muted: PropTypes.bool,
hidden: PropTypes.bool,
unread: PropTypes.bool,
onMoveUp: PropTypes.func,
onMoveDown: PropTypes.func,
showThread: PropTypes.bool,
isQuotedPost: PropTypes.bool,
getScrollPosition: PropTypes.func,
@ -328,14 +326,6 @@ class Status extends ImmutablePureComponent {
history.push(`/@${status.getIn(['account', 'acct'])}`);
};
handleHotkeyMoveUp = e => {
this.props.onMoveUp?.(this.props.status.get('id'), this.node.getAttribute('data-featured'));
};
handleHotkeyMoveDown = e => {
this.props.onMoveDown?.(this.props.status.get('id'), this.node.getAttribute('data-featured'));
};
handleHotkeyToggleHidden = () => {
const { onToggleHidden } = this.props;
const status = this._properStatus();
@ -399,8 +389,6 @@ class Status extends ImmutablePureComponent {
mention: this.handleHotkeyMention,
open: this.handleHotkeyOpen,
openProfile: this.handleHotkeyOpenProfile,
moveUp: this.handleHotkeyMoveUp,
moveDown: this.handleHotkeyMoveDown,
toggleHidden: this.handleHotkeyToggleHidden,
toggleSensitive: this.handleHotkeyToggleSensitive,
openMedia: this.handleHotkeyOpenMedia,

View File

@ -14,6 +14,7 @@ import { StatusQuoteManager } from '../components/status_quoted';
import { LoadGap } from './load_gap';
import ScrollableList from './scrollable_list';
export default class StatusList extends ImmutablePureComponent {
static propTypes = {
@ -40,84 +41,6 @@ export default class StatusList extends ImmutablePureComponent {
trackScroll: true,
};
componentDidMount() {
this.columnHeaderHeight = this.node?.node
? parseFloat(
getComputedStyle(this.node.node).getPropertyValue('--column-header-height')
) || 0
: 0;
}
getFeaturedStatusCount = () => {
return this.props.featuredStatusIds ? this.props.featuredStatusIds.size : 0;
};
getCurrentStatusIndex = (id, featured) => {
if (featured) {
return this.props.featuredStatusIds.indexOf(id);
} else {
return this.props.statusIds.indexOf(id) + this.getFeaturedStatusCount();
}
};
handleMoveUp = (id, featured) => {
const index = this.getCurrentStatusIndex(id, featured);
this._selectChild(id, index, -1);
};
handleMoveDown = (id, featured) => {
const index = this.getCurrentStatusIndex(id, featured);
this._selectChild(id, index, 1);
};
_selectChild = (id, index, direction) => {
const listContainer = this.node?.node;
let listItem = listContainer?.querySelector(
// :nth-child uses 1-based indexing
`.item-list > :nth-child(${index + 1 + direction})`
);
if (!listItem) {
return;
}
// If selected container element is empty, we skip it
if (listItem.matches(':empty')) {
this._selectChild(id, index + direction, direction);
return;
}
// Check if the list item is a post
let targetElement = listItem.querySelector('.focusable');
// Otherwise, check if the item contains follow suggestions or
// is a 'load more' button.
if (
!targetElement && (
listItem.querySelector('.inline-follow-suggestions') ||
listItem.matches('.load-more')
)
) {
targetElement = listItem;
}
if (targetElement) {
const elementRect = targetElement.getBoundingClientRect();
const isFullyVisible =
elementRect.top >= this.columnHeaderHeight &&
elementRect.bottom <= window.innerHeight;
if (!isFullyVisible) {
targetElement.scrollIntoView({
block: direction === 1 ? 'start' : 'center',
});
}
targetElement.focus();
}
}
handleLoadOlder = debounce(() => {
const { statusIds, lastId, onLoadMore } = this.props;
onLoadMore(lastId || (statusIds.size > 0 ? statusIds.last() : undefined));
@ -158,8 +81,6 @@ export default class StatusList extends ImmutablePureComponent {
<StatusQuoteManager
key={statusId}
id={statusId}
onMoveUp={this.handleMoveUp}
onMoveDown={this.handleMoveDown}
contextType={timelineId}
scrollKey={this.props.scrollKey}
showThread
@ -176,8 +97,6 @@ export default class StatusList extends ImmutablePureComponent {
key={`f-${statusId}`}
id={statusId}
featured
onMoveUp={this.handleMoveUp}
onMoveDown={this.handleMoveDown}
contextType={timelineId}
showThread
withCounters={this.props.withCounters}
@ -191,5 +110,4 @@ export default class StatusList extends ImmutablePureComponent {
</ScrollableList>
);
}
}

View File

@ -45,7 +45,7 @@ const getAccounts = createSelector(
const getStatus = makeGetStatus();
export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown }) => {
export const Conversation = ({ conversation, scrollKey }) => {
const id = conversation.get('id');
const unread = conversation.get('unread');
const lastStatusId = conversation.get('last_status');
@ -110,14 +110,6 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown })
dispatch(deleteConversation(id));
}, [dispatch, id]);
const handleHotkeyMoveUp = useCallback(() => {
onMoveUp(id);
}, [id, onMoveUp]);
const handleHotkeyMoveDown = useCallback(() => {
onMoveDown(id);
}, [id, onMoveDown]);
const handleConversationMute = useCallback(() => {
if (lastStatus.get('muted')) {
dispatch(unmuteStatus(lastStatus.get('id')));
@ -161,8 +153,6 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown })
const handlers = {
reply: handleReply,
open: handleClick,
moveUp: handleHotkeyMoveUp,
moveDown: handleHotkeyMoveDown,
toggleHidden: handleShowMore,
};
@ -224,6 +214,4 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown })
Conversation.propTypes = {
conversation: ImmutablePropTypes.map.isRequired,
scrollKey: PropTypes.string,
onMoveUp: PropTypes.func,
onMoveDown: PropTypes.func,
};

View File

@ -10,20 +10,6 @@ import ScrollableList from 'mastodon/components/scrollable_list';
import { Conversation } from './conversation';
const focusChild = (node, index, alignTop) => {
const element = node.querySelector(`article:nth-of-type(${index + 1}) .focusable`);
if (element) {
if (alignTop && node.scrollTop > element.offsetTop) {
element.scrollIntoView(true);
} else if (!alignTop && node.scrollTop + node.clientHeight < element.offsetTop + element.offsetHeight) {
element.scrollIntoView(false);
}
element.focus();
}
};
export const ConversationsList = ({ scrollKey, ...other }) => {
const listRef = useRef();
const conversations = useSelector(state => state.getIn(['conversations', 'items']));
@ -32,16 +18,6 @@ export const ConversationsList = ({ scrollKey, ...other }) => {
const dispatch = useDispatch();
const lastStatusId = conversations.last()?.get('last_status');
const handleMoveUp = useCallback(id => {
const elementIndex = conversations.findIndex(x => x.get('id') === id) - 1;
focusChild(listRef.current.node, elementIndex, true);
}, [listRef, conversations]);
const handleMoveDown = useCallback(id => {
const elementIndex = conversations.findIndex(x => x.get('id') === id) + 1;
focusChild(listRef.current.node, elementIndex, false);
}, [listRef, conversations]);
const debouncedLoadMore = useMemo(() => debounce(id => {
dispatch(expandConversations({ maxId: id }));
}, 300, { leading: true }), [dispatch]);
@ -58,8 +34,6 @@ export const ConversationsList = ({ scrollKey, ...other }) => {
<Conversation
key={item.get('id')}
conversation={item}
onMoveUp={handleMoveUp}
onMoveDown={handleMoveDown}
scrollKey={scrollKey}
/>
))}

View File

@ -1,4 +1,4 @@
import { useEffect, useCallback, useRef, useState } from 'react';
import { useEffect, useCallback, useRef, useState, useId } from 'react';
import { FormattedMessage, useIntl, defineMessages } from 'react-intl';
@ -19,6 +19,7 @@ import { DisplayName } from 'mastodon/components/display_name';
import { FollowButton } from 'mastodon/components/follow_button';
import { Icon } from 'mastodon/components/icon';
import { IconButton } from 'mastodon/components/icon_button';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import { VerifiedBadge } from 'mastodon/components/verified_badge';
import { domain } from 'mastodon/initial_state';
import { useAppDispatch, useAppSelector } from 'mastodon/store';
@ -56,9 +57,7 @@ const messages = defineMessages({
},
});
const Source: React.FC<{
id: ApiSuggestionSourceJSON;
}> = ({ id }) => {
const Source: React.FC<{ id: ApiSuggestionSourceJSON }> = ({ id }) => {
const intl = useIntl();
let label, hint;
@ -168,10 +167,11 @@ const Card: React.FC<{
const DISMISSIBLE_ID = 'home/follow-suggestions';
export const InlineFollowSuggestions: React.FC<{
hidden?: boolean;
}> = ({ hidden }) => {
export const InlineFollowSuggestions: React.FC<{ hidden?: boolean }> = ({
hidden,
}) => {
const intl = useIntl();
const uniqueId = useId();
const dispatch = useAppDispatch();
const suggestions = useAppSelector((state) => state.suggestions.items);
const isLoading = useAppSelector((state) => state.suggestions.isLoading);
@ -257,9 +257,14 @@ export const InlineFollowSuggestions: React.FC<{
}
return (
<div className='inline-follow-suggestions'>
<div
role='group'
aria-labelledby={uniqueId}
className='inline-follow-suggestions focusable'
tabIndex={-1}
>
<div className='inline-follow-suggestions__header'>
<h3>
<h3 id={uniqueId}>
<FormattedMessage
id='follow_suggestions.who_to_follow'
defaultMessage='Who to follow'
@ -288,13 +293,17 @@ export const InlineFollowSuggestions: React.FC<{
ref={bodyRef}
onScroll={handleScroll}
>
{suggestions.map((suggestion) => (
<Card
key={suggestion.account_id}
id={suggestion.account_id}
sources={suggestion.sources}
/>
))}
{isLoading ? (
<LoadingIndicator />
) : (
suggestions.map((suggestion) => (
<Card
key={suggestion.account_id}
id={suggestion.account_id}
sources={suggestion.sources}
/>
))
)}
</div>
{canScrollLeft && (

View File

@ -83,13 +83,17 @@ class KeyboardShortcuts extends ImmutablePureComponent {
<td><FormattedMessage id='keyboard_shortcuts.toggle_sensitivity' defaultMessage='to show/hide media' /></td>
</tr>
<tr>
<td><kbd>up</kbd>, <kbd>k</kbd></td>
<td><kbd>k</kbd></td>
<td><FormattedMessage id='keyboard_shortcuts.up' defaultMessage='to move up in the list' /></td>
</tr>
<tr>
<td><kbd>down</kbd>, <kbd>j</kbd></td>
<td><kbd>j</kbd></td>
<td><FormattedMessage id='keyboard_shortcuts.down' defaultMessage='to move down in the list' /></td>
</tr>
<tr>
<td><kbd>l</kbd></td>
<td><FormattedMessage id='keyboard_shortcuts.load_more' defaultMessage='Focus "Load more" button' /></td>
</tr>
<tr>
<td><kbd>1</kbd>-<kbd>9</kbd></td>
<td><FormattedMessage id='keyboard_shortcuts.column' defaultMessage='to focus a status in one of the columns' /></td>

View File

@ -57,8 +57,6 @@ class Notification extends ImmutablePureComponent {
static propTypes = {
notification: ImmutablePropTypes.map.isRequired,
hidden: PropTypes.bool,
onMoveUp: PropTypes.func.isRequired,
onMoveDown: PropTypes.func.isRequired,
onMention: PropTypes.func.isRequired,
onFavourite: PropTypes.func.isRequired,
onReblog: PropTypes.func.isRequired,
@ -73,16 +71,6 @@ class Notification extends ImmutablePureComponent {
...WithRouterPropTypes,
};
handleMoveUp = () => {
const { notification, onMoveUp } = this.props;
onMoveUp(notification.get('id'));
};
handleMoveDown = () => {
const { notification, onMoveDown } = this.props;
onMoveDown(notification.get('id'));
};
handleOpen = () => {
const { notification } = this.props;
@ -128,8 +116,6 @@ class Notification extends ImmutablePureComponent {
mention: this.handleMention,
open: this.handleOpen,
openProfile: this.handleOpenProfile,
moveUp: this.handleMoveUp,
moveDown: this.handleMoveDown,
toggleHidden: this.handleHotkeyToggleHidden,
};
}
@ -180,8 +166,6 @@ class Notification extends ImmutablePureComponent {
id={notification.get('status')}
withDismiss
hidden={this.props.hidden}
onMoveDown={this.handleMoveDown}
onMoveUp={this.handleMoveUp}
contextType='notifications'
getScrollPosition={this.props.getScrollPosition}
updateScrollBottom={this.props.updateScrollBottom}

View File

@ -31,21 +31,6 @@ const messages = defineMessages({
dismiss: { id: 'notification_requests.dismiss', defaultMessage: 'Dismiss' },
});
const selectChild = (ref, index, alignTop) => {
const container = ref.current.node;
const element = container.querySelector(`article:nth-of-type(${index + 1}) .focusable`);
if (element) {
if (alignTop && container.scrollTop > element.offsetTop) {
element.scrollIntoView(true);
} else if (!alignTop && container.scrollTop + container.clientHeight < element.offsetTop + element.offsetHeight) {
element.scrollIntoView(false);
}
element.focus();
}
};
export const NotificationRequest = ({ multiColumn, params: { id } }) => {
const columnRef = useRef();
const intl = useIntl();
@ -74,16 +59,6 @@ export const NotificationRequest = ({ multiColumn, params: { id } }) => {
dispatch(acceptNotificationRequest({ id }));
}, [dispatch, id]);
const handleMoveUp = useCallback(id => {
const elementIndex = notifications.findIndex(item => item !== null && item.get('id') === id) - 1;
selectChild(columnRef, elementIndex, true);
}, [columnRef, notifications]);
const handleMoveDown = useCallback(id => {
const elementIndex = notifications.findIndex(item => item !== null && item.get('id') === id) + 1;
selectChild(columnRef, elementIndex, false);
}, [columnRef, notifications]);
useEffect(() => {
dispatch(fetchNotificationRequest({ id }));
}, [dispatch, id]);
@ -146,8 +121,6 @@ export const NotificationRequest = ({ multiColumn, params: { id } }) => {
key={item.get('id')}
notification={item}
accountId={item.get('account')}
onMoveUp={handleMoveUp}
onMoveDown={handleMoveDown}
/>
))}
</ScrollableList>

View File

@ -24,9 +24,7 @@ import { NotificationUpdate } from './notification_update';
export const NotificationGroup: React.FC<{
notificationGroupId: NotificationGroupModel['group_key'];
unread: boolean;
onMoveUp: (groupId: string) => void;
onMoveDown: (groupId: string) => void;
}> = ({ notificationGroupId, unread, onMoveUp, onMoveDown }) => {
}> = ({ notificationGroupId, unread }) => {
const notificationGroup = useAppSelector((state) =>
state.notificationGroups.groups.find(
(item) => item.type !== 'gap' && item.group_key === notificationGroupId,
@ -42,14 +40,6 @@ export const NotificationGroup: React.FC<{
const handlers = useMemo(
() => ({
moveUp: () => {
onMoveUp(notificationGroupId);
},
moveDown: () => {
onMoveDown(notificationGroupId);
},
openProfile: () => {
if (accountId) dispatch(navigateToProfile(accountId));
},
@ -58,7 +48,7 @@ export const NotificationGroup: React.FC<{
if (accountId) dispatch(mentionComposeById(accountId));
},
}),
[dispatch, notificationGroupId, accountId, onMoveUp, onMoveDown],
[dispatch, accountId],
);
if (!notificationGroup || notificationGroup.type === 'gap') return null;

View File

@ -99,29 +99,6 @@ export const Notifications: React.FC<{
const columnRef = useRef<ColumnRef>(null);
const selectChild = useCallback((index: number, alignTop: boolean) => {
const container = columnRef.current?.node as HTMLElement | undefined;
if (!container) return;
const element = container.querySelector<HTMLElement>(
`article:nth-of-type(${index + 1}) .focusable`,
);
if (element) {
if (alignTop && container.scrollTop > element.offsetTop) {
element.scrollIntoView(true);
} else if (
!alignTop &&
container.scrollTop + container.clientHeight <
element.offsetTop + element.offsetHeight
) {
element.scrollIntoView(false);
}
element.focus();
}
}, []);
// Keep track of mounted components for unread notification handling
useEffect(() => {
void dispatch(mountNotifications());
@ -187,28 +164,6 @@ export const Notifications: React.FC<{
columnRef.current?.scrollTop();
}, []);
const handleMoveUp = useCallback(
(id: string) => {
const elementIndex =
notifications.findIndex(
(item) => item.type !== 'gap' && item.group_key === id,
) - 1;
selectChild(elementIndex, true);
},
[notifications, selectChild],
);
const handleMoveDown = useCallback(
(id: string) => {
const elementIndex =
notifications.findIndex(
(item) => item.type !== 'gap' && item.group_key === id,
) + 1;
selectChild(elementIndex, false);
},
[notifications, selectChild],
);
const handleMarkAsRead = useCallback(() => {
dispatch(markNotificationsAsRead());
void dispatch(submitMarkers({ immediate: true }));
@ -241,8 +196,6 @@ export const Notifications: React.FC<{
<NotificationGroup
key={item.group_key}
notificationGroupId={item.group_key}
onMoveUp={handleMoveUp}
onMoveDown={handleMoveDown}
unread={
lastReadId !== '0' &&
!!item.page_max_id &&
@ -251,15 +204,7 @@ export const Notifications: React.FC<{
/>
),
);
}, [
notifications,
isLoading,
hasMore,
lastReadId,
handleLoadGap,
handleMoveUp,
handleMoveDown,
]);
}, [notifications, isLoading, hasMore, lastReadId, handleLoadGap]);
const prepend = (
<>

View File

@ -396,15 +396,6 @@ class Status extends ImmutablePureComponent {
this.props.dispatch(unblockDomain(domain));
};
handleHotkeyMoveUp = () => {
this.handleMoveUp(this.props.status.get('id'));
};
handleHotkeyMoveDown = () => {
this.handleMoveDown(this.props.status.get('id'));
};
handleHotkeyReply = e => {
e.preventDefault();
this.handleReplyClick(this.props.status);
@ -439,54 +430,6 @@ class Status extends ImmutablePureComponent {
this.handleTranslate(this.props.status);
};
handleMoveUp = id => {
const { status, ancestorsIds, descendantsIds } = this.props;
if (id === status.get('id')) {
this._selectChild(ancestorsIds.length - 1, true);
} else {
let index = ancestorsIds.indexOf(id);
if (index === -1) {
index = descendantsIds.indexOf(id);
this._selectChild(ancestorsIds.length + index, true);
} else {
this._selectChild(index - 1, true);
}
}
};
handleMoveDown = id => {
const { status, ancestorsIds, descendantsIds } = this.props;
if (id === status.get('id')) {
this._selectChild(ancestorsIds.length + 1, false);
} else {
let index = ancestorsIds.indexOf(id);
if (index === -1) {
index = descendantsIds.indexOf(id);
this._selectChild(ancestorsIds.length + index + 2, false);
} else {
this._selectChild(index + 1, false);
}
}
};
_selectChild (index, align_top) {
const container = this.node;
const element = container.querySelectorAll('.focusable')[index];
if (element) {
if (align_top && container.scrollTop > element.offsetTop) {
element.scrollIntoView(true);
} else if (!align_top && container.scrollTop + container.clientHeight < element.offsetTop + element.offsetHeight) {
element.scrollIntoView(false);
}
element.focus();
}
}
renderChildren (list, ancestors) {
const { params: { statusId } } = this.props;
@ -494,8 +437,6 @@ class Status extends ImmutablePureComponent {
<StatusQuoteManager
key={id}
id={id}
onMoveUp={this.handleMoveUp}
onMoveDown={this.handleMoveDown}
contextType='thread'
previousId={i > 0 ? list[i - 1] : undefined}
nextId={list[i + 1] || (ancestors && statusId)}
@ -602,8 +543,6 @@ class Status extends ImmutablePureComponent {
}
const handlers = {
moveUp: this.handleHotkeyMoveUp,
moveDown: this.handleHotkeyMoveDown,
reply: this.handleHotkeyReply,
favourite: this.handleHotkeyFavourite,
boost: this.handleHotkeyBoost,
@ -626,7 +565,7 @@ class Status extends ImmutablePureComponent {
/>
<ScrollContainer scrollKey='thread' shouldUpdateScroll={this.shouldUpdateScroll}>
<div className={classNames('scrollable', { fullscreen })} ref={this.setContainerRef}>
<div className={classNames('scrollable item-list', { fullscreen })} ref={this.setContainerRef}>
{ancestors}
<Hotkeys handlers={handlers}>

View File

@ -1,11 +1,4 @@
import {
forwardRef,
useCallback,
useId,
useImperativeHandle,
useMemo,
useState,
} from 'react';
import { forwardRef, useCallback, useId, useMemo, useState } from 'react';
import type { FC } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
@ -16,6 +9,7 @@ import type { ApiQuotePolicy } 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 { Button } from '@/mastodon/components/button';
import { Dropdown } from '@/mastodon/components/dropdown';
import type { SelectItem } from '@/mastodon/components/dropdown_selector';
import { IconButton } from '@/mastodon/components/icon_button';
@ -96,7 +90,8 @@ const selectStatusPolicy = createAppSelector(
);
export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
({ onClose, onChange, statusId }, ref) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
({ onClose, onChange, statusId }, _ref) => {
const intl = useIntl();
const currentVisibility = useAppSelector((state) =>
statusId
@ -172,18 +167,10 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
setQuotePolicy(value);
}
}, []);
// Save on close
useImperativeHandle(
ref,
() => ({
getCloseConfirmationMessage() {
onChange(visibility, quotePolicy);
return null;
},
}),
[onChange, quotePolicy, visibility],
);
const handleSave = useCallback(() => {
onChange(visibility, quotePolicy);
onClose();
}, [onChange, onClose, visibility, quotePolicy]);
const privacyDropdownId = useId();
const quoteDropdownId = useId();
@ -274,6 +261,20 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
<QuotePolicyHelper policy={quotePolicy} visibility={visibility} />
</label>
</div>
<div className='dialog-modal__content__actions'>
<Button onClick={onClose} secondary>
<FormattedMessage
id='confirmation_modal.cancel'
defaultMessage='Cancel'
/>
</Button>
<Button onClick={handleSave}>
<FormattedMessage
id='visibility_modal.save'
defaultMessage='Save'
/>
</Button>
</div>
</div>
</div>
);

View File

@ -77,6 +77,7 @@ import {
AccountFeatured,
} from './util/async-components';
import { ColumnsContextProvider } from './util/columns_context';
import { focusColumn, getFocusedItemIndex, focusItemSibling } from './util/focusUtils';
import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers';
// Dummy import, to make sure that <Status /> ends up in the application bundle.
@ -446,20 +447,34 @@ class UI extends PureComponent {
};
handleHotkeyFocusColumn = e => {
const index = (e.key * 1) + 1; // First child is drawer, skip that
const column = this.node.querySelector(`.column:nth-child(${index})`);
if (!column) return;
const container = column.querySelector('.scrollable');
focusColumn({index: e.key * 1});
};
if (container) {
const status = container.querySelector('.focusable');
handleHotkeyLoadMore = () => {
document.querySelector('.load-more')?.focus();
};
if (status) {
if (container.scrollTop > status.offsetTop) {
status.scrollIntoView(true);
}
status.focus();
}
handleMoveUp = () => {
const currentItemIndex = getFocusedItemIndex();
if (currentItemIndex === -1) {
focusColumn({
index: 1,
focusItem: 'first-visible',
});
} else {
focusItemSibling(currentItemIndex, -1);
}
};
handleMoveDown = () => {
const currentItemIndex = getFocusedItemIndex();
if (currentItemIndex === -1) {
focusColumn({
index: 1,
focusItem: 'first-visible',
});
} else {
focusItemSibling(currentItemIndex, 1);
}
};
@ -542,6 +557,9 @@ class UI extends PureComponent {
forceNew: this.handleHotkeyForceNew,
toggleComposeSpoilers: this.handleHotkeyToggleComposeSpoilers,
focusColumn: this.handleHotkeyFocusColumn,
focusLoadMore: this.handleHotkeyLoadMore,
moveDown: this.handleMoveDown,
moveUp: this.handleMoveUp,
back: this.handleHotkeyBack,
goToHome: this.handleHotkeyGoToHome,
goToNotifications: this.handleHotkeyGoToNotifications,

View File

@ -0,0 +1,132 @@
import initialState from '@/mastodon/initial_state';
interface FocusColumnOptions {
index?: number;
focusItem?: 'first' | 'first-visible';
}
/**
* Move focus to the column of the passed index (1-based).
* Can either focus the topmost item or the first one in the viewport
*/
export function focusColumn({
index = 1,
focusItem = 'first',
}: FocusColumnOptions = {}) {
// Skip the leftmost drawer in multi-column mode
const indexOffset = initialState?.meta.advanced_layout ? 1 : 0;
const column = document.querySelector(
`.column:nth-child(${index + indexOffset})`,
);
if (!column) return;
const container = column.querySelector('.scrollable');
if (!container) return;
let itemToFocus: HTMLElement | null = null;
if (focusItem === 'first-visible') {
const focusableItems = Array.from(
container.querySelectorAll<HTMLElement>(
'.focusable:not(.status__quote .focusable)',
),
);
const viewportHeight =
window.innerHeight || document.documentElement.clientHeight;
// Find first item visible in the viewport
itemToFocus =
focusableItems.find((item) => {
const { top } = item.getBoundingClientRect();
return top >= 0 && top < viewportHeight;
}) ?? null;
} else {
itemToFocus = container.querySelector('.focusable');
}
if (itemToFocus) {
if (container.scrollTop > itemToFocus.offsetTop) {
itemToFocus.scrollIntoView(true);
}
itemToFocus.focus();
}
}
/**
* Get the index of the currently focused item in one of our item lists
*/
export function getFocusedItemIndex() {
const focusedElement = document.activeElement;
const itemList = focusedElement?.closest('.item-list');
if (!focusedElement || !itemList) {
return -1;
}
let focusedItem: HTMLElement | null = null;
if (focusedElement.parentElement === itemList) {
focusedItem = focusedElement as HTMLElement;
} else {
focusedItem = focusedElement.closest('.item-list > *');
}
if (!focusedItem) return -1;
const items = Array.from(itemList.children);
return items.indexOf(focusedItem);
}
/**
* Focus the item next to the one with the provided index
*/
export function focusItemSibling(
index: number,
direction: 1 | -1,
scrollThreshold = 62,
) {
const focusedElement = document.activeElement;
const itemList = focusedElement?.closest('.item-list');
const siblingItem = itemList?.querySelector<HTMLElement>(
// :nth-child uses 1-based indexing
`.item-list > :nth-child(${index + 1 + direction})`,
);
if (!siblingItem) {
return;
}
// If sibling element is empty, we skip it
if (siblingItem.matches(':empty')) {
focusItemSibling(index + direction, direction);
return;
}
// Check if the sibling is a post or a 'follow suggestions' widget
let targetElement = siblingItem.querySelector<HTMLElement>('.focusable');
// Otherwise, check if the item is a 'load more' button.
if (!targetElement && siblingItem.matches('.load-more')) {
targetElement = siblingItem;
}
if (targetElement) {
const elementRect = targetElement.getBoundingClientRect();
const isFullyVisible =
elementRect.top >= scrollThreshold &&
elementRect.bottom <= window.innerHeight;
if (!isFullyVisible) {
targetElement.scrollIntoView({
block: direction === 1 ? 'start' : 'center',
});
}
targetElement.focus();
}
}

View File

@ -743,6 +743,7 @@
"privacy.unlisted.short": "Offentlig (stille)",
"privacy_policy.last_updated": "Senest opdateret {date}",
"privacy_policy.title": "Privatlivspolitik",
"quote_error.unauthorized": "Du er ikke autoriseret til at citere dette indlæg.",
"recommended": "Anbefalet",
"refresh": "Genindlæs",
"regeneration_indicator.please_stand_by": "Vent venligst.",
@ -849,9 +850,11 @@
"status.admin_account": "Åbn modereringsbrugerflade for @{name}",
"status.admin_domain": "Åbn modereringsbrugerflade for {domain}",
"status.admin_status": "Åbn dette indlæg i modereringsbrugerfladen",
"status.all_disabled": "Fremhævelser og citater er deaktiveret",
"status.block": "Blokér @{name}",
"status.bookmark": "Bogmærk",
"status.cancel_reblog_private": "Fjern fremhævelse",
"status.cannot_quote": "Forfatter har deaktiveret citering af dette indlæg",
"status.cannot_reblog": "Dette indlæg kan ikke fremhæves",
"status.context.load_new_replies": "Nye svar tilgængelige",
"status.context.loading": "Tjekker for flere svar",
@ -880,6 +883,8 @@
"status.mute_conversation": "Skjul samtale",
"status.open": "Udvid dette indlæg",
"status.pin": "Fastgør til profil",
"status.quote": "Citér",
"status.quote.cancel": "Annullér citat",
"status.quote_error.filtered": "Skjult grundet et af filterne",
"status.quote_error.not_available": "Indlæg utilgængeligt",
"status.quote_error.pending_approval": "Afventende indlæg",
@ -887,6 +892,7 @@
"status.quote_error.pending_approval_popout.title": "Afventende citat? Tag det roligt",
"status.quote_policy_change": "Ændr hvem der kan citere",
"status.quote_post_author": "Citerede et indlæg fra @{name}",
"status.quote_private": "Private indlæg kan ikke citeres",
"status.read_more": "Læs mere",
"status.reblog": "Fremhæv",
"status.reblog_private": "Fremhæv med oprindelig synlighed",

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Follower",
"privacy.public.long": "Alle in und außerhalb von Mastodon",
"privacy.public.short": "Öffentlich",
"privacy.quote.anyone": "{visibility} alle dürfen zitieren",
"privacy.quote.disabled": "{visibility} niemand darf zitieren",
"privacy.quote.limited": "{visibility} eingeschränktes Zitieren",
"privacy.unlisted.additional": "Das Verhalten ist wie bei „Öffentlich“, jedoch gibt es einige Einschränkungen. Der Beitrag wird nicht in „Live-Feeds“, „Erkunden“, Hashtags oder über die Mastodon-Suchfunktion auffindbar sein selbst wenn die zugehörige Einstellung aktiviert wurde.",
"privacy.unlisted.long": "Weniger im Algorithmus berücksichtigt",
"privacy.unlisted.short": "Öffentlich (still)",
"privacy_policy.last_updated": "Stand: {date}",
"privacy_policy.title": "Datenschutzerklärung",
"quote_error.poll": "Zitieren ist bei Umfragen nicht gestattet.",
"quote_error.quote": "Es ist jeweils nur ein Zitat zulässig.",
"quote_error.unauthorized": "Du bist nicht berechtigt, diesen Beitrag zu zitieren.",
"quote_error.upload": "Zitieren ist mit Medien-Anhängen nicht möglich.",
"recommended": "Empfohlen",
"refresh": "Aktualisieren",
"regeneration_indicator.please_stand_by": "Bitte warten.",
@ -944,6 +951,7 @@
"upload_button.label": "Bilder, Video oder Audio hinzufügen",
"upload_error.limit": "Dateiupload-Limit überschritten.",
"upload_error.poll": "Medien-Anhänge sind zusammen mit Umfragen nicht erlaubt.",
"upload_error.quote": "Medien-Anhänge sind zusammen mit Zitaten nicht erlaubt.",
"upload_form.drag_and_drop.instructions": "Drücke zum Aufnehmen eines Medienanhangs die Eingabe- oder Leertaste. Verwende beim Ziehen die Pfeiltasten, um den Medienanhang zur gewünschten Position zu bewegen. Drücke erneut die Eingabe- oder Leertaste, um den Medienanhang an der gewünschten Position abzulegen. Mit der Escape-Taste kannst du den Vorgang abbrechen.",
"upload_form.drag_and_drop.on_drag_cancel": "Das Ziehen wurde abgebrochen und der Medienanhang {item} wurde abgelegt.",
"upload_form.drag_and_drop.on_drag_end": "Der Medienanhang {item} wurde abgelegt.",

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Ακόλουθοι",
"privacy.public.long": "Όλοι εντός και εκτός του Mastodon",
"privacy.public.short": "Δημόσιο",
"privacy.quote.anyone": "{visibility}, ο καθένας μπορεί να παραθέσει",
"privacy.quote.disabled": "{visibility}, παραθέσεις απενεργοποιημένες",
"privacy.quote.limited": "{visibility}, παραθέσεις περιορισμένες",
"privacy.unlisted.additional": "Αυτό συμπεριφέρεται ακριβώς όπως το δημόσιο, εκτός από το ότι η ανάρτηση δεν θα εμφανιστεί σε ζωντανές ροές ή ετικέτες, εξερεύνηση ή αναζήτηση στο Mastodon, ακόμη και αν το έχεις επιλέξει για τον λογαριασμό σου.",
"privacy.unlisted.long": "Λιγότερα αλγοριθμικά κόλπα",
"privacy.unlisted.short": "Ήσυχα δημόσια",
"privacy_policy.last_updated": "Τελευταία ενημέρωση {date}",
"privacy_policy.title": "Πολιτική Απορρήτου",
"quote_error.poll": "Η παράθεση δεν επιτρέπεται με δημοσκοπήσεις.",
"quote_error.quote": "Επιτρέπεται μόνο μία παράθεση τη φορά.",
"quote_error.unauthorized": "Δεν είστε εξουσιοδοτημένοι να παραθέσετε αυτή την ανάρτηση.",
"quote_error.upload": "Η παράθεση δεν επιτρέπεται με συνημμένα πολυμέσων.",
"recommended": "Προτεινόμενα",
"refresh": "Ανανέωση",
"regeneration_indicator.please_stand_by": "Παρακαλούμε περίμενε.",
@ -944,6 +951,7 @@
"upload_button.label": "Πρόσθεσε εικόνες, ένα βίντεο ή ένα αρχείο ήχου",
"upload_error.limit": "Υπέρβαση ορίου μεγέθους ανεβασμένων αρχείων.",
"upload_error.poll": "Στις δημοσκοπήσεις δεν επιτρέπεται η μεταφόρτωση αρχείου.",
"upload_error.quote": "Δεν επιτρέπεται η μεταφόρτωση αρχείου με παραθέσεις.",
"upload_form.drag_and_drop.instructions": "Για να επιλέξετε ένα συνημμένο αρχείο πολυμέσων, πατήστε το Space ή το Enter. Ενώ το σέρνετε, χρησιμοποιήστε τα πλήκτρα βέλους για να μετακινήσετε το συνημμένο αρχείο πολυμέσων προς οποιαδήποτε κατεύθυνση. Πατήστε ξανά το Space ή το Enter για να αποθέσετε το συνημμένο αρχείο πολυμέσων στη νέα του θέση ή πατήστε το Escape για ακύρωση.",
"upload_form.drag_and_drop.on_drag_cancel": "Η μετακίνηση ακυρώθηκε. Έγινε απόθεση του συνημμένου αρχείου πολυμέσων «{item}».",
"upload_form.drag_and_drop.on_drag_end": "Έγινε απόθεση του συνημμένου αρχείου πολυμέσων «{item}».",

View File

@ -483,6 +483,7 @@
"keyboard_shortcuts.home": "Open home timeline",
"keyboard_shortcuts.hotkey": "Hotkey",
"keyboard_shortcuts.legend": "Display this legend",
"keyboard_shortcuts.load_more": "Focus \"Load more\" button",
"keyboard_shortcuts.local": "Open local timeline",
"keyboard_shortcuts.mention": "Mention author",
"keyboard_shortcuts.muted": "Open muted users list",
@ -986,5 +987,6 @@
"visibility_modal.quote_followers": "Followers only",
"visibility_modal.quote_label": "Change who can quote",
"visibility_modal.quote_nobody": "No one",
"visibility_modal.quote_public": "Anyone"
"visibility_modal.quote_public": "Anyone",
"visibility_modal.save": "Save"
}

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Seguidores",
"privacy.public.long": "Cualquier persona dentro y fuera de Mastodon",
"privacy.public.short": "Público",
"privacy.quote.anyone": "{visibility}, todos pueden citar",
"privacy.quote.disabled": "{visibility}, citas deshabilitadas",
"privacy.quote.limited": "{visibility}, citas limitadas",
"privacy.unlisted.additional": "Esto se comporta exactamente igual que con la configuración de privacidad de mensaje \"Público\", excepto que el mensaje no aparecerá en los líneas temporales en vivo, ni en las etiquetas, ni en la línea temporal \"Explorá\", ni en la búsqueda de Mastodon; incluso si optaste por hacer tu cuenta visible.",
"privacy.unlisted.long": "Menos fanfarrias algorítmicas",
"privacy.unlisted.short": "Público silencioso",
"privacy_policy.last_updated": "Última actualización: {date}",
"privacy_policy.title": "Política de privacidad",
"quote_error.poll": "No se permite citar encuestas.",
"quote_error.quote": "Solo se permite una cita a la vez.",
"quote_error.unauthorized": "No tenés autorización para citar este mensaje.",
"quote_error.upload": "No se permite citar con archivos multimedia.",
"recommended": "Opción recomendada",
"refresh": "Refrescar",
"regeneration_indicator.please_stand_by": "Esperá, por favor.",
@ -944,6 +951,7 @@
"upload_button.label": "Agregá imágenes, o un archivo de audio o video",
"upload_error.limit": "Se excedió el límite de subida de archivos.",
"upload_error.poll": "No se permite la subida de archivos en encuestas.",
"upload_error.quote": "No se permite subir archivos con citas.",
"upload_form.drag_and_drop.instructions": "Para recoger un archivo multimedia, pulsá la barra espaciadora o la tecla Enter. Mientras arrastrás, usá las teclas de flecha para mover el archivo multimedia en cualquier dirección. Volvé a pulsar la barra espaciadora o la tecla Enter para soltar el archivo multimedia en su nueva posición, o pulsá la tecla Escape para cancelar.",
"upload_form.drag_and_drop.on_drag_cancel": "Se canceló el arrastre. Se eliminó el archivo adjunto {item}.",
"upload_form.drag_and_drop.on_drag_end": "El archivo adjunto {item} fue soltado.",

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Seguidores",
"privacy.public.long": "Cualquiera dentro y fuera de Mastodon",
"privacy.public.short": "Público",
"privacy.quote.anyone": "{visibility}, cualquiera puede citar",
"privacy.quote.disabled": "{visibility}, citas deshabilitadas",
"privacy.quote.limited": "{visibility}, citas limitadas",
"privacy.unlisted.additional": "Esto se comporta exactamente igual que el público, excepto que el post no aparecerá en las cronologías en directo o en las etiquetas, la exploración o busquedas en Mastodon, incluso si está optado por activar la cuenta de usuario.",
"privacy.unlisted.long": "Menos fanfares algorítmicos",
"privacy.unlisted.short": "Público silencioso",
"privacy_policy.last_updated": "Actualizado por última vez {date}",
"privacy_policy.title": "Política de Privacidad",
"quote_error.poll": "No es posible citar encuestas.",
"quote_error.quote": "Solo se permite una cita a la vez.",
"quote_error.unauthorized": "No tienes permiso para citar esta publicación.",
"quote_error.upload": "No se permite citar con archivos multimedia.",
"recommended": "Recomendado",
"refresh": "Actualizar",
"regeneration_indicator.please_stand_by": "Espera, por favor.",
@ -944,6 +951,7 @@
"upload_button.label": "Subir multimedia (JPEG, PNG, GIF, WebM, MP4, MOV)",
"upload_error.limit": "Límite de subida de archivos excedido.",
"upload_error.poll": "No se permite subir archivos con las encuestas.",
"upload_error.quote": "No se permite subir archivos a las citas.",
"upload_form.drag_and_drop.instructions": "Para recoger un archivo adjunto, pulsa la barra espaciadora o la tecla Intro. Mientras arrastras, usa las teclas de flecha para mover el archivo adjunto en cualquier dirección. Vuelve a pulsar la barra espaciadora o la tecla Intro para soltar el archivo adjunto en su nueva posición, o pulsa la tecla Escape para cancelar.",
"upload_form.drag_and_drop.on_drag_cancel": "Arrastre cancelado. El archivo adjunto {item} fue eliminado.",
"upload_form.drag_and_drop.on_drag_end": "El archivo adjunto {item} fue eliminado.",

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Seguidores",
"privacy.public.long": "Visible por todo el mundo, dentro y fuera de Mastodon",
"privacy.public.short": "Pública",
"privacy.quote.anyone": "{visibility}, cualquiera puede citar",
"privacy.quote.disabled": "{visibility}, citas deshabilitadas",
"privacy.quote.limited": "{visibility}, citas limitadas",
"privacy.unlisted.additional": "Se comporta exactamente igual que la visibilidad pública, excepto que la publicación no aparecerá en las cronologías públicas o en las etiquetas, la sección de Explorar o la búsqueda de Mastodon, incluso si has habilitado la opción de búsqueda en tu perfil.",
"privacy.unlisted.long": "Sin algoritmos de descubrimiento",
"privacy.unlisted.short": "Pública silenciosa",
"privacy_policy.last_updated": "Actualizado por última vez {date}",
"privacy_policy.title": "Política de Privacidad",
"quote_error.poll": "No es posible citar encuestas.",
"quote_error.quote": "Solo se permite una cita a la vez.",
"quote_error.unauthorized": "No tienes permiso para citar esta publicación.",
"quote_error.upload": "No se permite citar con archivos multimedia.",
"recommended": "Recomendado",
"refresh": "Actualizar",
"regeneration_indicator.please_stand_by": "Espera, por favor.",
@ -944,6 +951,7 @@
"upload_button.label": "Añadir imágenes, un fichero de vídeo o de audio",
"upload_error.limit": "Límite de subida de archivos excedido.",
"upload_error.poll": "No se permite la subida de archivos con encuestas.",
"upload_error.quote": "No se permite subir archivos a las citas.",
"upload_form.drag_and_drop.instructions": "Para recoger un archivo multimedia, pulsa la barra espaciadora o la tecla Enter. Mientras arrastras, utiliza las teclas de flecha para mover el archivo multimedia en cualquier dirección. Vuelve a pulsar la barra espaciadora o la tecla Enter para soltar el archivo multimedia en su nueva posición, o pulsa Escape para cancelar.",
"upload_form.drag_and_drop.on_drag_cancel": "Se canceló el arrastre. Se eliminó el archivo adjunto {item}.",
"upload_form.drag_and_drop.on_drag_end": "El archivo adjunto {item} ha sido eliminado.",

View File

@ -245,6 +245,9 @@
"confirmations.remove_from_followers.confirm": "Eemalda jälgija",
"confirmations.remove_from_followers.message": "{name} lõpetab sellega sinu jälgimise. Kas oled kindel, et soovid jätkata?",
"confirmations.remove_from_followers.title": "Kas eemaldame jälgija?",
"confirmations.revoke_quote.confirm": "Eemalda postitus",
"confirmations.revoke_quote.message": "Seda tegevust ei saa tagasi pöörata.",
"confirmations.revoke_quote.title": "Kas eemaldame postituse?",
"confirmations.unfollow.confirm": "Ära jälgi",
"confirmations.unfollow.message": "Oled kindel, et ei soovi rohkem jälgida kasutajat {name}?",
"confirmations.unfollow.title": "Ei jälgi enam kasutajat?",
@ -289,6 +292,7 @@
"domain_pill.your_handle": "Sinu tunnus:",
"domain_pill.your_server": "Sinu digitaalne kodu, kus on kõik sinu postitused. Sulle ei meeldi see? Vaheta mistahes ajal serverit ja võta jälgijad ka.",
"domain_pill.your_username": "Sinu unikaalne identifikaator siin serveris. On võimalik, et leiad teistes serverites samasuguse kasutajanimega kasutajaid.",
"dropdown.empty": "Vali üks variantidest",
"embed.instructions": "Lisa see postitus oma veebilehele, kopeerides alloleva koodi.",
"embed.preview": "Nii näeb see välja:",
"emoji_button.activity": "Tegevus",
@ -600,6 +604,7 @@
"notification.label.mention": "Mainimine",
"notification.label.private_mention": "Privaatne mainimine",
"notification.label.private_reply": "Privaatne vastus",
"notification.label.quote": "{name} tsiteeris sinu postitust",
"notification.label.reply": "Vastus",
"notification.mention": "Mainimine",
"notification.mentioned_you": "{name} mainis sind",
@ -657,6 +662,7 @@
"notifications.column_settings.mention": "Mainimised:",
"notifications.column_settings.poll": "Küsitluse tulemused:",
"notifications.column_settings.push": "Push teated",
"notifications.column_settings.quote": "Tsitaadid:",
"notifications.column_settings.reblog": "Jagamised:",
"notifications.column_settings.show": "Kuva tulbas",
"notifications.column_settings.sound": "Mängi heli",
@ -732,11 +738,18 @@
"privacy.private.short": "Jälgijad",
"privacy.public.long": "Nii kasutajad kui mittekasutajad",
"privacy.public.short": "Avalik",
"privacy.quote.anyone": "{visibility}, kõik võivad tsiteerida",
"privacy.quote.disabled": "{visibility}, tsiteerimine pole lubatud",
"privacy.quote.limited": "{visibility}, tsiteerimine on piiratud",
"privacy.unlisted.additional": "See on olemuselt küll avalik, aga postitus ei ilmu voogudes ega märksõnades, lehitsedes ega Mastodoni otsingus, isegi kui konto on seadistustes avalik.",
"privacy.unlisted.long": "Vähem algoritmilisi teavitusi",
"privacy.unlisted.short": "Vaikselt avalik",
"privacy_policy.last_updated": "Viimati uuendatud {date}",
"privacy_policy.title": "Isikuandmete kaitse",
"quote_error.poll": "Tsiteerimine pole küsitlustes lubatud.",
"quote_error.quote": "Korraga on lubatud vaid üks tsitaat.",
"quote_error.unauthorized": "Sul pole õigust seda postitust tsiteerida.",
"quote_error.upload": "Tsiteerimine pole manuste puhul lubatud.",
"recommended": "Soovitatud",
"refresh": "Värskenda",
"regeneration_indicator.please_stand_by": "Palun oota.",
@ -843,9 +856,11 @@
"status.admin_account": "Ava @{name} moderaatorivaates",
"status.admin_domain": "Ava {domain} modeereerimisliides",
"status.admin_status": "Ava postitus moderaatorivaates",
"status.all_disabled": "Hooandmine ja tsiteerimine pole lubatud",
"status.block": "Blokeeri @{name}",
"status.bookmark": "Järjehoidja",
"status.cancel_reblog_private": "Lõpeta jagamine",
"status.cannot_quote": "Autor ei luba selle postituse tsiteerimist",
"status.cannot_reblog": "Seda postitust ei saa jagada",
"status.context.load_new_replies": "Leidub uusi vastuseid",
"status.context.loading": "Kontrollin täiendavate vastuste olemasolu",
@ -874,12 +889,16 @@
"status.mute_conversation": "Vaigista vestlus",
"status.open": "Laienda postitus",
"status.pin": "Kinnita profiilile",
"status.quote": "Tsiteeri",
"status.quote.cancel": "Katkesta tsiteerimine",
"status.quote_error.filtered": "Peidetud mõne kasutatud filtri tõttu",
"status.quote_error.not_available": "Postitus pole saadaval",
"status.quote_error.pending_approval": "Postitus on ootel",
"status.quote_error.pending_approval_popout.body": "Kuna erinevates serverites on erinevad reeglid, siis üle Födiversumi jagatud tsitaatide kuvamine võib võtta aega.",
"status.quote_error.pending_approval_popout.title": "Tsiteerimine on ootel? Palun jää rahulikuks",
"status.quote_policy_change": "Muuda neid, kes võivad tsiteerida",
"status.quote_post_author": "Tsiteeris kasutaja @{name} postitust",
"status.quote_private": "Otsepostituste tsiteerimine pole võimalik",
"status.read_more": "Loe veel",
"status.reblog": "Jaga",
"status.reblog_private": "Jaga algse nähtavusega",
@ -894,6 +913,7 @@
"status.reply": "Vasta",
"status.replyAll": "Vasta lõimele",
"status.report": "Raporteeri @{name}",
"status.revoke_quote": "Eemalda minu tsitaat postituses, mille tegi @{name}",
"status.sensitive_warning": "Tundlik sisu",
"status.share": "Jaga",
"status.show_less_all": "Peida kogu tundlik sisu",
@ -931,6 +951,7 @@
"upload_button.label": "Lisa meedia (JPEG, PNG, GIF, WebM, MP4, MOV)",
"upload_error.limit": "Faili üleslaadimise limiit ületatud.",
"upload_error.poll": "Küsitlustes pole faili üleslaadimine lubatud.",
"upload_error.quote": "Tsiteerimisel pole faili üleslaadimine lubatud.",
"upload_form.drag_and_drop.instructions": "Vajuta tühikut või enterit, et tõsta manus. Lohistamise ajal kasuta nooleklahve, et manust liigutada teatud suunas. Vajuta tühikut või enterit uuesti, et paigutada manus oma uuele kohale, või escape tühistamiseks.",
"upload_form.drag_and_drop.on_drag_cancel": "Lohistamine tühistati. Manus {item} on asetatud.",
"upload_form.drag_and_drop.on_drag_end": "Manus {item} on asetatud.",
@ -953,5 +974,17 @@
"video.skip_forward": "Keri edasi",
"video.unmute": "Lõpeta vaigistamine",
"video.volume_down": "Heli vaiksemaks",
"video.volume_up": "Heli valjemaks"
"video.volume_up": "Heli valjemaks",
"visibility_modal.button_title": "Muuda nähtavust",
"visibility_modal.header": "Nähtavus ja kasutus",
"visibility_modal.helper.direct_quoting": "Otsepostituste, kus on mainimisi, tsiteerimine pole võimalik.",
"visibility_modal.helper.privacy_editing": "Avaldatud postitused ei saa muuta oma nähtavust.",
"visibility_modal.helper.private_quoting": "Vaid jälgijatele mõeldud postitusi ei saa tsiteerida.",
"visibility_modal.helper.unlisted_quoting": "Kui teised kasutajad sind tsiteerivad, siis nende postitused peidetakse ajajoonelt, mis näitavad populaarsust koguvaid postitusi.",
"visibility_modal.instructions": "Halda seda, kes võivad antud postitust kasutada. Üldised seadistused leiduvad siin: <link>Eelistused > Muu</link>.",
"visibility_modal.privacy_label": "Privaatsus",
"visibility_modal.quote_followers": "Ainult jälgijad",
"visibility_modal.quote_label": "Muuda seda, kes võivad tsiteerida",
"visibility_modal.quote_nobody": "Mitte keegi",
"visibility_modal.quote_public": "Kõik"
}

View File

@ -26,6 +26,9 @@
"account.edit_profile": "Baguhin ang profile",
"account.enable_notifications": "Ipaalam sa akin kapag nag-post si @{name}",
"account.endorse": "I-tampok sa profile",
"account.familiar_followers_many": "Sinusundan nina {name1}, {name2}, at {othersCount, plural, one {# iba pa na kilala mo} other {# na iba pa na kilala mo}}",
"account.familiar_followers_one": "Sinusindan ni/ng {name1}",
"account.familiar_followers_two": "Sinusindan nina {name1} at {name2}",
"account.featured": "Itinatampok",
"account.featured_tags.last_status_at": "Huling post noong {date}",
"account.featured_tags.last_status_never": "Walang mga post",
@ -34,9 +37,11 @@
"account.followers": "Mga tagasunod",
"account.followers.empty": "Wala pang sumusunod sa tagagamit na ito.",
"account.followers_counter": "{count, plural, one {{counter} tagasunod} other {{counter} tagasunod}}",
"account.followers_you_know_counter": "{counter} (na) kilala mo",
"account.following": "Sinusundan",
"account.following_counter": "{count, plural, one {{counter} sinusundan} other {{counter} sinusundan}}",
"account.follows.empty": "Wala pang sinusundan ang tagagamit na ito.",
"account.follows_you": "Sinusundan ka",
"account.go_to_profile": "Pumunta sa profile",
"account.hide_reblogs": "Itago ang mga pagpapalakas mula sa {name}",
"account.in_memoriam": "Sa Alaala Ni.",

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Fylgjarar",
"privacy.public.long": "Øll í og uttanfyri Mastodon",
"privacy.public.short": "Alment",
"privacy.quote.anyone": "{visibility}, øll kunnu sitera",
"privacy.quote.disabled": "{visibility}, siteringar óvirknar",
"privacy.quote.limited": "{visibility}, siteringar avmarkaðar",
"privacy.unlisted.additional": "Hetta er júst sum almenn, tó verður posturin ikki vístur í samtíðarrásum ella frámerkjum, rannsakan ella Mastodon leitingum, sjálvt um valið er galdandi fyri alla kontuna.",
"privacy.unlisted.long": "Færri algoritmiskar fanfarur",
"privacy.unlisted.short": "Stillur almenningur",
"privacy_policy.last_updated": "Seinast dagført {date}",
"privacy_policy.title": "Privatlívspolitikkur",
"quote_error.poll": "Tað er ikki loyvt at sitera spurnarkanningar.",
"quote_error.quote": "Bara ein sitering er loyvd í senn.",
"quote_error.unauthorized": "Tú hevur ikki rættindi at sitera hendan postin.",
"quote_error.upload": "Sitering er ikki loyvd um miðlar eru viðheftir.",
"recommended": "Viðmælt",
"refresh": "Endurles",
"regeneration_indicator.please_stand_by": "Bíða við.",
@ -944,6 +951,7 @@
"upload_button.label": "Legg myndir, sjónfílu ella ljóðfílu afturat",
"upload_error.limit": "Farið er um markið fyri fíluuppsending.",
"upload_error.poll": "Ikki loyvt at leggja fílur upp í spurnarkanningum.",
"upload_error.quote": "Ikki loyvt at leggja fílur upp við siteringum.",
"upload_form.drag_and_drop.instructions": "Fyri at heinta eitt miðlaviðfesti, trýst á millumrúm ella returknapp. Meðan tú dregur, brúka pílarnar fyri at flyta miðaviðfesti í einhvønn rætning. Trýst á millumrúm ella returknapp aftur fyri at sleppa miðlaviðfestinum í nýggja staðnum ella trýst á esc-knappin fyri at angra.",
"upload_form.drag_and_drop.on_drag_cancel": "Draging varð steðgað. Miðlaviðfestið {item} varð slept.",
"upload_form.drag_and_drop.on_drag_end": "Miðlaviðfestið {item} var slept.",

View File

@ -849,9 +849,11 @@
"status.admin_account": "Oscail comhéadan modhnóireachta do @{name}",
"status.admin_domain": "Oscail comhéadan modhnóireachta le haghaidh {domain}",
"status.admin_status": "Oscail an postáil seo sa chomhéadan modhnóireachta",
"status.all_disabled": "Tá borradh agus luachana díchumasaithe",
"status.block": "Bac @{name}",
"status.bookmark": "Leabharmharcanna",
"status.cancel_reblog_private": "Dímhol",
"status.cannot_quote": "Tá an t-údar tar éis lua a dhíchumasú ar an bpost seo",
"status.cannot_reblog": "Ní féidir an phostáil seo a mholadh",
"status.context.load_new_replies": "Freagraí nua ar fáil",
"status.context.loading": "Ag seiceáil le haghaidh tuilleadh freagraí",
@ -880,6 +882,8 @@
"status.mute_conversation": "Balbhaigh comhrá",
"status.open": "Leathnaigh an post seo",
"status.pin": "Pionnáil ar do phróifíl",
"status.quote": "Luachan",
"status.quote.cancel": "Cealaigh an luachan",
"status.quote_error.filtered": "I bhfolach mar gheall ar cheann de do scagairí",
"status.quote_error.not_available": "Níl an postáil ar fáil",
"status.quote_error.pending_approval": "Post ar feitheamh",
@ -887,6 +891,7 @@
"status.quote_error.pending_approval_popout.title": "Ag fanacht le luachan? Fan socair",
"status.quote_policy_change": "Athraigh cé a fhéadann luachan a thabhairt",
"status.quote_post_author": "Luaigh mé post le @{name}",
"status.quote_private": "Ní féidir poist phríobháideacha a lua",
"status.read_more": "Léan a thuilleadh",
"status.reblog": "Treisiú",
"status.reblog_private": "Mol le léargas bunúsach",

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Seguidoras",
"privacy.public.long": "Para todas dentro e fóra de Mastodon",
"privacy.public.short": "Público",
"privacy.quote.anyone": "{visibility}, calquera pode citar",
"privacy.quote.disabled": "{visibility}, citas desactivadas",
"privacy.quote.limited": "{visibility}, citas limitadas",
"privacy.unlisted.additional": "Do mesmo xeito que público, menos que a publicación non aparecerá nas cronoloxías en directo ou nos cancelos, en descubrir ou nas buscas de Mastodon, incluso se estivese establecido nas opcións xerais da conta.",
"privacy.unlisted.long": "Menor implicación dos algoritmos",
"privacy.unlisted.short": "Público limitado",
"privacy_policy.last_updated": "Actualizado por última vez no {date}",
"privacy_policy.title": "Política de Privacidade",
"quote_error.poll": "Non se permite citar as enquisas.",
"quote_error.quote": "Só se permite citar unha vez.",
"quote_error.unauthorized": "Non tes permiso para citar esta publicación.",
"quote_error.upload": "As citas non están permitidas para anexos multimedia.",
"recommended": "Aconsellable",
"refresh": "Actualizar",
"regeneration_indicator.please_stand_by": "Por favor, agarda.",
@ -849,9 +856,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 esta publicación na interface de moderación",
"status.all_disabled": "As promocións e citas están desactivadas",
"status.block": "Bloquear a @{name}",
"status.bookmark": "Marcar",
"status.cancel_reblog_private": "Desfacer compartido",
"status.cannot_quote": "A persoa autora desactivou as citas desta publicación",
"status.cannot_reblog": "Esta publicación non pode ser promovida",
"status.context.load_new_replies": "Non hai respostas dispoñibles",
"status.context.loading": "Mirando se hai máis respostas",
@ -880,6 +889,7 @@
"status.mute_conversation": "Silenciar conversa",
"status.open": "Estender esta publicación",
"status.pin": "Fixar no perfil",
"status.quote": "Citar",
"status.quote.cancel": "Cancelar a cita",
"status.quote_error.filtered": "Oculto debido a un dos teus filtros",
"status.quote_error.not_available": "Publicación non dispoñible",
@ -888,6 +898,7 @@
"status.quote_error.pending_approval_popout.title": "Cita pendente? Non te apures",
"status.quote_policy_change": "Cambia quen pode citarte",
"status.quote_post_author": "Citou unha publicación de @{name}",
"status.quote_private": "As publicacións privadas non se poden citar",
"status.read_more": "Ler máis",
"status.reblog": "Promover",
"status.reblog_private": "Compartir coa audiencia orixinal",
@ -940,6 +951,7 @@
"upload_button.label": "Engadir imaxes, un vídeo ou ficheiro de audio",
"upload_error.limit": "Límite máximo do ficheiro a subir excedido.",
"upload_error.poll": "Non se poden subir ficheiros nas enquisas.",
"upload_error.quote": "Non se permite subir ficheiros ao citar.",
"upload_form.drag_and_drop.instructions": "Preme en Espazo ou Enter para escoller un anexo multimedia. Ao arrastrar usa as teclas de frecha para mover o anexo en todas direccións.Preme Espazo ou Enter outra vez para soltalo na súa nova posición, ou preme Escape para desbotar.",
"upload_form.drag_and_drop.on_drag_cancel": "Cancelouse o movemento. O anexo {item} soltouse.",
"upload_form.drag_and_drop.on_drag_end": "Soltouse o anexo multimedia {item}.",

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Követők",
"privacy.public.long": "Bárki a Mastodonon és azon kívül",
"privacy.public.short": "Nyilvános",
"privacy.quote.anyone": "{visibility}, bárki idézheti",
"privacy.quote.disabled": "{visibility}, idézés letiltva",
"privacy.quote.limited": "{visibility}, idézés korlátozva",
"privacy.unlisted.additional": "Ez pontosan úgy viselkedik, mint a nyilvános, kivéve, hogy a bejegyzés nem jelenik meg élő hírfolyamokban, hashtagekben, felfedezésben vagy a Mastodonos keresésben, még akkor sem, ha ezt az egész fiókra engedélyezted.",
"privacy.unlisted.long": "Kevesebb algoritmikus fanfár",
"privacy.unlisted.short": "Csendes nyilvános",
"privacy_policy.last_updated": "Utoljára frissítve: {date}",
"privacy_policy.title": "Adatvédelmi szabályzat",
"quote_error.poll": "Az idézés szavazások esetén nincs engedélyezve.",
"quote_error.quote": "Egyszerre csak egy idézet van engedélyezve.",
"quote_error.unauthorized": "Nem idézheted ezt a bejegyzést.",
"quote_error.upload": "Az idézés médiamellékletek esetén nem engedélyezett.",
"recommended": "Ajánlott",
"refresh": "Frissítés",
"regeneration_indicator.please_stand_by": "Kis türelmet.",
@ -939,6 +946,7 @@
"upload_button.label": "Képek, videó vagy audiófájl hozzáadása",
"upload_error.limit": "A fájlfeltöltési korlát elérésre került.",
"upload_error.poll": "Szavazásnál nem lehet fájlt feltölteni.",
"upload_error.quote": "Idézésnél nem lehet fájlt feltölteni.",
"upload_form.drag_and_drop.instructions": "Egy médiamelléklet kiválasztásához nyomj Szóközt vagy Entert. Húzás közben használd a nyílgombokat a médiamelléklet adott irányba történő mozgatásához. A médiamelléklet új pozícióba helyezéséhez nyomd meg a Szóközt vagy az Entert, vagy a megszakításhoz nyomd meg az Esc gombot.",
"upload_form.drag_and_drop.on_drag_cancel": "Az áthúzás megszakítva. A(z) {item} médiamelléklet el lett dobva.",
"upload_form.drag_and_drop.on_drag_end": "A(z) {item} médiamelléklet el lett dobva.",

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Fylgjendur",
"privacy.public.long": "Hver sem er, á og utan Mastodon",
"privacy.public.short": "Opinbert",
"privacy.quote.anyone": "{visibility}, hver sem er getur vitnað í færslu",
"privacy.quote.disabled": "{visibility}, tilvitnanir eru óvirkar",
"privacy.quote.limited": "{visibility}, tilvitnanir eru takmarkaðar",
"privacy.unlisted.additional": "Þetta hegðar sér eins og opinber færsla, fyrir utan að færslan birtist ekki í beinum streymum eða myllumerkjum, né heldur í Mastodon-leitum jafnvel þótt þú hafir valið að falla undir slíkt í notandasniðinu þínu.",
"privacy.unlisted.long": "Minni stælar í reikniritum",
"privacy.unlisted.short": "Hljóðlátt opinbert",
"privacy_policy.last_updated": "Síðast uppfært {date}",
"privacy_policy.title": "Persónuverndarstefna",
"quote_error.poll": "Ekki er leyft að vitna í kannanir.",
"quote_error.quote": "Einungis ein tilvitnun er leyfð í einu.",
"quote_error.unauthorized": "Þú hefur ekki heimild til að vitna í þessa færslu.",
"quote_error.upload": "Ekki er leyft að vitna í myndviðhengi.",
"recommended": "Mælt með",
"refresh": "Endurlesa",
"regeneration_indicator.please_stand_by": "Hinkraðu við.",
@ -944,6 +951,7 @@
"upload_button.label": "Bæta við myndum, myndskeiði eða hljóðskrá",
"upload_error.limit": "Fór yfir takmörk á innsendingum skráa.",
"upload_error.poll": "Innsending skráa er ekki leyfð í könnunum.",
"upload_error.quote": "Innsending skráa er ekki leyfð í tilvitnunum.",
"upload_form.drag_and_drop.instructions": "Til að taka í myndefnisviðhengi skaltu ýta á bilslána eða Enter. Til að draga geturðu notað örvalyklana til að færa viðhengið í samsvarandi áttir. Ýttu aftur á bilslána eða Enter til að sleppa viðhenginu á nýja staðinn, eða ýttu á Escape til að hætta við.",
"upload_form.drag_and_drop.on_drag_cancel": "Hætt var við að draga. Myndefnisviðhenginu {item} var sleppt.",
"upload_form.drag_and_drop.on_drag_end": "Myndefnisviðhenginu {item} var sleppt.",

View File

@ -218,6 +218,7 @@
"domain_pill.who_you_are": "Imi isulay-ik·im yeqqar-d anwa i d kečč·kemmi d wanda i telliḍ, zemren medden ad myigwen yid-k·m deg web anmetti yebnan s <button>tɣeṛɣaṛ yemmugen s ActivityPub</button>.",
"domain_pill.your_handle": "Asulay-ik·im:",
"domain_pill.your_server": "D axxam-inek·inem umḍin, anda i zedɣent akk tsuffaɣ-ik·im. Ur k·m-yeεǧib ara wa? Ssenfel-d iqeddacen melmi i ak·m-yehwa, awi-d daɣen ineḍfaren-ik·im yid-k·m.",
"dropdown.empty": "Fren taxtiṛit",
"embed.instructions": "Ẓẓu addad-agi deg usmel-inek·inem s wenɣal n tangalt yellan sdaw-agi.",
"embed.preview": "Akka ara d-iban:",
"emoji_button.activity": "Aqeddic",
@ -315,6 +316,7 @@
"hashtag.follow": "Ḍfeṛ ahacṭag",
"hashtag.mute": "Sgugem #{hashtag}",
"hashtags.and_other": "…d {count, plural, one {}other {# nniḍen}}",
"hints.profiles.see_more_posts": "Wali ugar n tsuffaɣ ɣef {domain}",
"home.column_settings.show_quotes": "Sken-d tibdarin",
"home.column_settings.show_reblogs": "Ssken-d beṭṭu",
"home.column_settings.show_replies": "Ssken-d tiririyin",
@ -322,6 +324,7 @@
"home.pending_critical_update.body": "Ma ulac aɣilif, leqqem aqeddac-ik Mastodon akken kan tzemreḍ !",
"home.pending_critical_update.link": "Wali ileqman",
"home.show_announcements": "Ssken-d ulɣuyen",
"ignore_notifications_modal.ignore": "Ttu ilɣa",
"info_button.label": "Tallelt",
"interaction_modal.action.favourite": "I wakken ad tkemmleḍ, yessefk ad d-tḥemmleḍ seg umiḍan-ik·im.",
"interaction_modal.action.follow": "I wakken ad tkemmleḍ, yessefk ad d-tḍefreḍ seg umiḍan-ik·im.",
@ -389,6 +392,7 @@
"lists.delete": "Kkes tabdart",
"lists.done": "Immed",
"lists.edit": "Ẓreg tabdart",
"lists.find_users_to_add": "Af-d iseqdacen ara ternuḍ",
"lists.list_name": "Isem n tebdart",
"lists.new_list_name": "Isem n tebdart tamaynut",
"lists.no_lists_yet": "Ulac tibdarin akka tura.",
@ -412,6 +416,7 @@
"mute_modal.you_wont_see_mentions": "Ur tezmireḍ ara ad twaliḍ tisuffaɣ anda d-yettwabdar.",
"mute_modal.you_wont_see_posts": "Yezmer ad yettwali tisuffaɣ-ik·im, maca ur tettwaliḍ ara tidak-is.",
"navigation_bar.about": "Ɣef",
"navigation_bar.account_settings": "Awal n uɛeddi akked tɣellist",
"navigation_bar.administration": "Tadbelt",
"navigation_bar.advanced_interface": "Ldi deg ugrudem n web leqqayen",
"navigation_bar.blocks": "Iseqdacen yettusḥebsen",
@ -449,6 +454,7 @@
"notification.label.private_reply": "Tiririt tusligt",
"notification.label.reply": "Tiririt",
"notification.mention": "Abdar",
"notification.mentioned_you": "{name} yebder-ik·em-id",
"notification.moderation-warning.learn_more": "Issin ugar",
"notification.moderation_warning.action_suspend": "Yettwaseḥbes umiḍan-ik.",
"notification.own_poll": "Tafrant-ik·im tfuk",
@ -461,8 +467,10 @@
"notification_requests.exit_selection": "Immed",
"notification_requests.notifications_from": "Ilɣa sɣur {name}",
"notification_requests.title": "Ilɣa yettwasizdgen",
"notification_requests.view": "Wali ilɣa",
"notifications.clear": "Sfeḍ ilɣa",
"notifications.clear_confirmation": "Tebɣiḍ s tidet ad tekkseḍ akk ilɣa-inek·em i lebda?",
"notifications.clear_title": "Sfeḍ ilɣa?",
"notifications.column_settings.admin.report": "Ineqqisen imaynuten:",
"notifications.column_settings.alert": "Ilɣa n tnarit",
"notifications.column_settings.favourite": "Imenyafen:",
@ -648,6 +656,8 @@
"status.mute_conversation": "Sgugem adiwenni",
"status.open": "Semɣeṛ tasuffeɣt-ayi",
"status.pin": "Senteḍ-itt deg umaɣnu",
"status.quote": "Tanebdurt",
"status.quote.cancel": "Semmet tanebdurt",
"status.quote_post_author": "Yebder-d tasuffeɣt sɣur @{name}",
"status.read_more": "Issin ugar",
"status.reblog": "Bḍu",
@ -707,5 +717,10 @@
"video.mute": "Sgugem",
"video.pause": "Sgunfu",
"video.play": "Seddu",
"video.unmute": "Kkes asgugem"
"video.unmute": "Kkes asgugem",
"visibility_modal.privacy_label": "Tabaḍnit",
"visibility_modal.quote_followers": "Imeḍfaṛen kan",
"visibility_modal.quote_label": "Beddel anwa i izemren ad k-id-yebder",
"visibility_modal.quote_nobody": "Ula yiwen",
"visibility_modal.quote_public": "Yal yiwen"
}

View File

@ -738,11 +738,18 @@
"privacy.private.short": "Người theo dõi",
"privacy.public.long": "Bất cứ ai",
"privacy.public.short": "Công khai",
"privacy.quote.anyone": "{visibility}, mọi người có thể trích dẫn",
"privacy.quote.disabled": "{visibility}, tắt trích dẫn",
"privacy.quote.limited": "{visibility}, hạn chế trích dẫn",
"privacy.unlisted.additional": "Công khai, nhưng tút sẽ không hiện trong bảng tin, hashtag, khám phá hoặc tìm kiếm Mastodon, kể cả trong cài đặt tài khoản bạn chọn cho phép.",
"privacy.unlisted.long": "Ít hướng thuật toán hơn",
"privacy.unlisted.short": "Hạn chế",
"privacy_policy.last_updated": "Cập nhật lần cuối {date}",
"privacy_policy.title": "Chính sách bảo mật",
"quote_error.poll": "Không thể trích dẫn vốt.",
"quote_error.quote": "Chỉ được trích dẫn một lần.",
"quote_error.unauthorized": "Bạn không được cấp quyền trích dẫn tút này.",
"quote_error.upload": "Không thể trích dẫn với media đính kèm.",
"recommended": "Đề xuất",
"refresh": "Làm mới",
"regeneration_indicator.please_stand_by": "Hãy chờ đã.",
@ -944,6 +951,7 @@
"upload_button.label": "Thêm media (JPEG, PNG, GIF, WebM, MP4, MOV)",
"upload_error.limit": "Tập tin tải lên vượt quá giới hạn cho phép.",
"upload_error.poll": "Không cho phép đính kèm tập tin.",
"upload_error.quote": "Không cho phép đính kèm tập tin với trích dẫn.",
"upload_form.drag_and_drop.instructions": "Để chọn tập tin đính kèm, hãy nhấn phím cách hoặc phím Enter. Trong khi kéo, sử dụng các phím mũi tên để di chuyển tập tin đính kèm theo bất kỳ hướng nào. Nhấn phím cách hoặc phím Enter một lần nữa để thả tập tin đính kèm vào vị trí mới hoặc nhấn phím thoát để hủy.",
"upload_form.drag_and_drop.on_drag_cancel": "Kéo thả đã bị hủy bỏ. Tập tin đính kèm {item} bị bỏ qua.",
"upload_form.drag_and_drop.on_drag_end": "Tập tin đính kèm {item} bị bỏ qua.",

View File

@ -738,11 +738,18 @@
"privacy.private.short": "跟隨者",
"privacy.public.long": "所有人 (無論在 Mastodon 上與否)",
"privacy.public.short": "公開",
"privacy.quote.anyone": "{visibility},任何人皆可引用",
"privacy.quote.disabled": "{visibility},停用引用嘟文",
"privacy.quote.limited": "{visibility},受限的引用嘟文",
"privacy.unlisted.additional": "此與公開嘟文完全相同,但嘟文不會出現於即時內容或主題標籤、探索、及 Mastodon 搜尋中,即使您在帳戶設定中選擇加入。",
"privacy.unlisted.long": "悄然無聲",
"privacy.unlisted.short": "不公開",
"privacy_policy.last_updated": "最後更新:{date}",
"privacy_policy.title": "隱私權政策",
"quote_error.poll": "無法引用投票嘟文。",
"quote_error.quote": "一次僅能引用一則嘟文。",
"quote_error.unauthorized": "您不被授權允許引用此嘟文。",
"quote_error.upload": "無法引用多媒體內容嘟文。",
"recommended": "推薦設定",
"refresh": "重新整理",
"regeneration_indicator.please_stand_by": "請稍候。",
@ -944,6 +951,7 @@
"upload_button.label": "上傳圖片、影片、或者音訊檔案",
"upload_error.limit": "已達到檔案上傳限制。",
"upload_error.poll": "不允許於投票時上傳檔案。",
"upload_error.quote": "引用嘟文無法上傳檔案。",
"upload_form.drag_and_drop.instructions": "請按空白鍵或 Enter 鍵取多媒體附加檔案。使用方向鍵移動多媒體附加檔案。按下空白鍵或 Enter 鍵於新位置放置多媒體附加檔案,或按下 ESC 鍵取消。",
"upload_form.drag_and_drop.on_drag_cancel": "移動已取消。多媒體附加檔案 {item} 已被放置。",
"upload_form.drag_and_drop.on_drag_end": "多媒體附加檔案 {item} 已被放置。",

View File

@ -384,14 +384,8 @@
.compose-form__actions .icon-button.active,
.dropdown-button.active,
.privacy-dropdown__option.active,
.privacy-dropdown__option:focus,
.language-dropdown__dropdown__results__item:focus,
.language-dropdown__dropdown__results__item.active,
.privacy-dropdown__option:focus .privacy-dropdown__option__content,
.privacy-dropdown__option:focus .privacy-dropdown__option__content strong,
.privacy-dropdown__option.active .privacy-dropdown__option__content,
.privacy-dropdown__option.active .privacy-dropdown__option__content strong,
.language-dropdown__dropdown__results__item:focus
.language-dropdown__dropdown__results__item__common-name,
.language-dropdown__dropdown__results__item.active
@ -399,6 +393,14 @@
color: $white;
}
.privacy-dropdown__option,
.visibility-dropdown__option {
&:focus,
&.active {
--dropdown-text-color: #{$white};
}
}
.compose-form .spoiler-input__input {
color: lighten($ui-highlight-color, 8%);
}
@ -435,6 +437,10 @@
.inline-follow-suggestions {
background-color: color.change($ui-highlight-color, $alpha: 0.1);
border-bottom-color: color.change($ui-highlight-color, $alpha: 0.3);
&.focusable:focus-visible {
background: color.change($ui-highlight-color, $alpha: 0.1);
}
}
.inline-follow-suggestions__body__scrollable__card {

View File

@ -1438,9 +1438,9 @@ body > [data-popper-placement] {
.focusable {
&:focus-visible {
outline: 0;
outline: 2px solid $ui-button-focus-outline-color;
outline-offset: -2px;
background: color.change($ui-highlight-color, $alpha: 0.05);
box-shadow: inset 0 0 0 2px $ui-button-focus-outline-color;
}
}
@ -4373,6 +4373,11 @@ a.status-card {
background: var(--on-surface-color);
}
&:focus-visible {
outline: 2px solid $ui-button-focus-outline-color;
outline-offset: -2px;
}
.icon {
width: 22px;
height: 22px;
@ -5491,6 +5496,8 @@ a.status-card {
.privacy-dropdown__option,
.visibility-dropdown__option {
--dropdown-text-color: $primary-text-color;
font-size: 14px;
line-height: 20px;
letter-spacing: 0.25px;
@ -5500,7 +5507,22 @@ a.status-card {
align-items: center;
gap: 12px;
border-radius: 4px;
color: $primary-text-color;
color: var(--dropdown-text-color);
// Make sure adjacent hover/active states don't have a meeting radius.
&:hover + &:is(:focus, .active),
&:is(:focus, .active) + &:hover,
&:is(:focus, .active) + &:is(:focus, .active) {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
&:hover:has(+ :focus, .active),
&:is(:focus, .active):has(+ :hover),
&:is(:focus, .active):has(+ :is(:focus, .active)) {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
&:hover,
&:active {
@ -5510,7 +5532,7 @@ a.status-card {
&:focus,
&.active {
background: $ui-highlight-color;
color: $primary-text-color;
color: var(--dropdown-text-color);
outline: 0;
.privacy-dropdown__option__content,
@ -5519,7 +5541,7 @@ a.status-card {
.visibility-dropdown__option__content,
.visibility-dropdown__option__content strong,
.visibility-dropdown__option__additional {
color: $primary-text-color;
color: var(--dropdown-text-color);
}
}
@ -6527,6 +6549,14 @@ a.status-card {
max-height: 45vh;
}
}
&__actions {
display: flex;
align-items: center;
gap: 8px;
justify-content: flex-end;
padding: 0 24px 24px;
}
}
&__popout {
@ -10376,6 +10406,10 @@ noscript {
border-bottom: 1px solid var(--background-border-color);
background: color.change($ui-highlight-color, $alpha: 0.05);
&.focusable:focus-visible {
background: color.change($ui-highlight-color, $alpha: 0.05);
}
&__header {
display: flex;
align-items: center;
@ -10448,8 +10482,10 @@ noscript {
}
&__scrollable {
box-sizing: border-box;
display: flex;
flex-wrap: nowrap;
min-height: 228px;
gap: 16px;
padding: 16px;
scroll-snap-type: x mandatory;

View File

@ -22,6 +22,6 @@ class RuleTranslation < ApplicationRecord
scope :by_language_length, -> { order(Arel.sql('LENGTH(LANGUAGE)').desc) }
def self.languages
RuleTranslation.joins(:rule).merge(Rule.kept).select(:language).distinct.pluck(:language).sort
joins(:rule).merge(Rule.kept).distinct.pluck(:language).sort
end
end

View File

@ -307,7 +307,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
@quote_changed = true
else
quote = @status.quote
quote.update(approval_uri: approval_uri, state: :pending, legacy: @status_parser.legacy_quote?) if quote.approval_uri != @status_parser.quote_approval_uri
quote.update(approval_uri: approval_uri, state: :pending, legacy: @status_parser.legacy_quote?) if quote.approval_uri != approval_uri
end
else
quote = Quote.create(status: @status, approval_uri: approval_uri, legacy: @status_parser.legacy_quote?)

View File

@ -13,7 +13,7 @@ class ActivityPub::VerifyQuoteService < BaseService
@fetching_error = nil
fetch_quoted_post_if_needed!(fetchable_quoted_uri, prefetched_body: prefetched_quoted_object)
return handle_local_quote! if quote.quoted_account&.local?
return if quote.quoted_account&.local?
return if fast_track_approval! || quote.approval_uri.blank?
@json = fetch_approval_object(quote.approval_uri, prefetched_body: prefetched_approval)
@ -35,15 +35,6 @@ class ActivityPub::VerifyQuoteService < BaseService
private
def handle_local_quote!
@quote.update!(approval_uri: nil)
if StatusPolicy.new(@quote.account, @quote.quoted_status).quote?
@quote.accept!
else
@quote.reject!
end
end
# FEP-044f defines rules that don't require the approval flow
def fast_track_approval!
return false if @quote.quoted_status_id.blank?

View File

@ -1410,7 +1410,6 @@ an:
reblog: Un boost no puede fixar-se
title: "%{name}: «%{quote}»"
visibilities:
direct: Directa
private: Nomás amostrar a seguidores
private_long: Nomás amostrar a las tuyas seguidores
public: Publico

View File

@ -2050,7 +2050,6 @@ ar:
public: الجميع
title: '%{name}: "%{quote}"'
visibilities:
direct: مباشرة
private: لمتابِعيك فقط
private_long: اعرضه لمتابعيك فقط
public: للعامة

View File

@ -811,7 +811,6 @@ ast:
reblog: Nun se pue fixar una publicación compartida
title: "%{name}: «%{quote}»"
visibilities:
direct: Mensaxe direutu
private: Namás siguidores
private_long: Namás los ven los perfiles siguidores
public_long: Tol mundu pue velos

View File

@ -2000,7 +2000,6 @@ be:
public: Усе
title: '%{name}: "%{quote}"'
visibilities:
direct: Асабіста
private: Для падпісчыкаў
private_long: Паказваць толькі падпісчыкам
public: Публічны

View File

@ -1898,7 +1898,6 @@ bg:
public: Всеки
title: "%{name}: „%{quote}“"
visibilities:
direct: Директно
private: Покажи само на последователите си
private_long: Видими само за последователи
public: Публично

View File

@ -567,7 +567,6 @@ br:
quote_policies:
public: Pep den
visibilities:
direct: War-eeun
public: Publik
statuses_cleanup:
keep_direct: Mirout ar c'hannadoù eeun

View File

@ -1887,7 +1887,6 @@ ca:
public: Tothom
title: '%{name}: "%{quote}"'
visibilities:
direct: Directe
private: Només seguidors
private_long: Mostra només als seguidors
public: Públic

View File

@ -924,7 +924,6 @@ co:
reblog: Ùn pudete micca puntarulà una spartera
title: '%{name}: "%{quote}"'
visibilities:
direct: Direttu
private: Solu per labbunati
private_long: Mustrà solu à labbunati
public: Pubblicu

View File

@ -2000,7 +2000,6 @@ cs:
public: Všichni
title: "%{name}: „%{quote}“"
visibilities:
direct: Přímé
private: Pouze pro sledující
private_long: Zobrazit pouze sledujícím
public: Veřejné

View File

@ -2085,7 +2085,6 @@ cy:
public: Pawb
title: '%{name}: "%{quote}"'
visibilities:
direct: Uniongyrchol
private: Dilynwyr yn unig
private_long: Dangos i ddilynwyr yn unig
public: Cyhoeddus

View File

@ -1914,7 +1914,7 @@ da:
public: Alle
title: '%{name}: "%{quote}"'
visibilities:
direct: Direkte
direct: Privat omtale
private: Kun følgere
private_long: Vis kun til følgere
public: Offentlig
@ -2020,7 +2020,7 @@ da:
explanation: Der er anmodet om en fuld sikkerhedskopi af din Mastodon-konto.
extra: Sikkerhedskopien kan nu downloades!
subject: Dit arkiv er klar til download
title: Arkiv download
title: Arkiv-download
failed_2fa:
details: 'Her er detaljerne om login-forsøget:'
explanation: Nogen har forsøgt at logge ind på kontoen, men har angivet en ugyldig anden godkendelsesfaktor.

View File

@ -1914,7 +1914,7 @@ de:
public: Alle
title: "%{name}: „%{quote}“"
visibilities:
direct: Direktnachricht
direct: Private Erwähnung
private: Nur Follower
private_long: Nur für deine Follower sichtbar
public: Öffentlich

View File

@ -121,6 +121,7 @@ kab:
admin:
nav:
applications: Isnasen
oauth2_provider: Asaǧǧaw OAuth2
application:
title: Tlaq tsiregt n OAuth
scopes:

View File

@ -1914,7 +1914,7 @@ el:
public: Όλοι
title: '%{name}: "%{quote}"'
visibilities:
direct: Άμεση
direct: Ιδιωτική επισήμανση
private: Μόνο ακόλουθοι
private_long: Εμφάνιση μόνο σε ακόλουθους
public: Δημόσιο

View File

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

View File

@ -1863,7 +1863,6 @@ eo:
public: Ĉiuj
title: "%{name}: “%{quote}”"
visibilities:
direct: Rekta
private: Montri nur al sekvantoj
private_long: Montri nur al sekvantoj
public: Publika

View File

@ -1914,7 +1914,7 @@ es-AR:
public: Todos
title: '%{name}: "%{quote}"'
visibilities:
direct: Directo
direct: Mención privada
private: Sólo a seguidores
private_long: Sólo mostrar a seguidores
public: Público

View File

@ -1914,7 +1914,7 @@ es-MX:
public: Cualquiera
title: "%{name}: «%{quote}»"
visibilities:
direct: Directa
direct: Mención privada
private: Sólo mostrar a seguidores
private_long: Solo mostrar a tus seguidores
public: Público

View File

@ -1914,7 +1914,7 @@ es:
public: Cualquiera
title: "%{name}: «%{quote}»"
visibilities:
direct: Directa
direct: Mención privada
private: Solo seguidores
private_long: Solo mostrar a tus seguidores
public: Pública

View File

@ -1896,7 +1896,6 @@ et:
public: Kõik
title: '%{name}: "%{quote}"'
visibilities:
direct: Otsene
private: Ainult jälgijatele
private_long: Näevad ainult jälgijad
public: Avalik

View File

@ -1745,7 +1745,6 @@ eu:
public: Guztiak
title: '%{name}: "%{quote}"'
visibilities:
direct: Zuzena
private: Jarraitzaileak soilik
private_long: Erakutsi jarraitzaileei soilik
public: Publikoa

View File

@ -1914,7 +1914,6 @@ fa:
public: هرکسی
title: "%{name}: «%{quote}»"
visibilities:
direct: مستقیم
private: خصوصی
private_long: تنها پیگیران شما می‌بینند
public: عمومی

View File

@ -1914,7 +1914,6 @@ fi:
public: Kaikki
title: "%{name}: ”%{quote}”"
visibilities:
direct: Suoraan
private: Vain seuraajat
private_long: Näytä vain seuraajille
public: Julkinen

View File

@ -1914,7 +1914,6 @@ fo:
public: Øll
title: '%{name}: "%{quote}"'
visibilities:
direct: Beinleiðis
private: Einans fylgjarar
private_long: Vís einans fyri fylgjarum
public: Alment

View File

@ -1858,7 +1858,6 @@ fr-CA:
public: Tout le monde
title: "%{name}: « %{quote} »"
visibilities:
direct: Direct
private: Abonné⋅e⋅s uniquement
private_long: Afficher seulement à vos vos abonné·e·s
public: Publique

View File

@ -1858,7 +1858,6 @@ fr:
public: Tout le monde
title: "%{name}: « %{quote} »"
visibilities:
direct: Direct
private: Abonné⋅e⋅s uniquement
private_long: Afficher seulement à vos vos abonné·e·s
public: Publique

View File

@ -1908,7 +1908,6 @@ fy:
public: Elkenien
title: '%{name}: "%{quote}"'
visibilities:
direct: Direkt
private: Allinnich folgers
private_long: Allinnich oan jo folgers toane
public: Iepenbier

View File

@ -2043,7 +2043,6 @@ ga:
public: Gach duine
title: '%{name}: "%{quote}"'
visibilities:
direct: Díreach
private: Leantóirí amháin
private_long: Taispeáin do leantóirí amháin
public: Poiblí

View File

@ -1964,7 +1964,6 @@ gd:
public: A h-uile duine
title: "%{name}: “%{quote}”"
visibilities:
direct: Dìreach
private: Luchd-leantainn a-mhàin
private_long: Na seall ach dhan luchd-leantainn
public: Poblach

View File

@ -1914,7 +1914,7 @@ gl:
public: Calquera
title: '%{name}: "%{quote}"'
visibilities:
direct: Directa
direct: Mención privada
private: Só seguidoras
private_long: Mostrar só as seguidoras
public: Público

View File

@ -2000,7 +2000,6 @@ he:
public: כולם
title: '%{name}: "%{quote}"'
visibilities:
direct: ישיר
private: לעוקבים בלבד
private_long: להצגה לעוקבים בלבד
public: פומבי

View File

@ -1914,7 +1914,7 @@ hu:
public: Mindenki
title: "%{name}: „%{quote}”"
visibilities:
direct: Közvetlen
direct: Privát említés
private: Csak követőknek
private_long: Csak a követőidnek jelenik meg
public: Nyilvános

View File

@ -777,7 +777,6 @@ hy:
over_character_limit: "%{max} նիշի սահմանը գերազանցուած է"
title: '%{name}: "%{quote}"'
visibilities:
direct: Հասցէագրուած
private: Միայն հետեւողներին
private_long: Հասանելի միայն հետեւորդներին
public: Հրապարակային

View File

@ -1914,7 +1914,6 @@ ia:
public: Omnes
title: "%{name}: “%{quote}”"
visibilities:
direct: Directe
private: Solmente sequitores
private_long: Solmente monstrar a sequitores
public: Public

View File

@ -1379,7 +1379,6 @@ id:
reblog: Boost tidak bisa disematkan
title: '%{name}: "%{quote}"'
visibilities:
direct: Langsung
private: Khusus pengikut
private_long: Hanya tampilkan ke pengikut
public: Publik

View File

@ -1622,7 +1622,6 @@ ie:
reblog: On ne posse pinglar un boost
title: "%{name}: «%{quote}»"
visibilities:
direct: Direct
private: Solmen por sequitores
private_long: Monstrar solmen a sequitores
public: Public

View File

@ -1743,7 +1743,6 @@ io:
reblog: Repeto ne povas pinglizesar
title: '%{name}: "%{quote}"'
visibilities:
direct: Direta
private: Montrar nur a sequanti
private_long: Nur montrez a sequanti
public: Publika

View File

@ -1918,7 +1918,7 @@ is:
public: Allir
title: "%{name}: „%{quote}‟"
visibilities:
direct: Beint
direct: Einkaspjall
private: Einungis fylgjendur
private_long: Aðeins birt fylgjendum
public: Opinber

View File

@ -1916,7 +1916,6 @@ it:
public: Tutti
title: '%{name}: "%{quote}"'
visibilities:
direct: Diretto
private: Mostra solo ai tuoi seguaci
private_long: Mostra solo ai seguaci
public: Pubblico

View File

@ -1828,7 +1828,6 @@ ja:
public: 全員
title: '%{name}: "%{quote}"'
visibilities:
direct: ダイレクト
private: フォロワー限定
private_long: フォロワーにのみ表示されます
public: 公開

View File

@ -395,6 +395,7 @@ kab:
everyone: Tisirag timezwura
privileges:
administrator: Anedbal
manage_federation: Sefrek Tafidiralit
manage_settings: Asefrek n iɣewwaṛen
view_dashboard: Timẓriwt n tfelwit
rules:
@ -444,6 +445,7 @@ kab:
media:
title: Amidya
open: Ldi tasuffeɣt
status_title: Tasuffeɣt sɣur @%{name}
trending: Inezzaɣ
visibility: Abani
with_media: S umidya
@ -454,6 +456,8 @@ kab:
action: Wali tasemlit
rules_check:
action: Sefrek ilugan n uqeddac
software_version_check:
message_html: Yella lqem n Mastodon.
software_version_critical_check:
action: Wali ileqqman yellan
software_version_patch_check:
@ -466,7 +470,10 @@ kab:
title: Ihacṭagen
terms_of_service:
changelog: Amaynut
create: Sqedcet ayla-nwen
draft: Arewway
generates:
action: Sirew
history: Amazray
live: Srid
publish: Asuffeɣ
@ -476,6 +483,7 @@ kab:
trends:
allow: Sireg
links:
allow: Sireg aseɣwen
title: Iseɣwan inezzaɣ
statuses:
title: Tisuffaɣ tinezzaɣ
@ -489,6 +497,7 @@ kab:
add_new: Rnu amaynut
comparison:
contains: Igber
delete: Kkes
new:
create: Rnu alugen
title: Rnu alugen n useqdac amaynut
@ -645,6 +654,7 @@ kab:
date: Azemz
download: Sider-d aḥraz-ik·im
size: Teɣzi
blocks: Tregleḍ
bookmarks: Ticraḍ
csv: CSV
lists: Tibdarin
@ -858,6 +868,8 @@ kab:
statuses_cleanup: Tukksa tawurmant n tsuffaɣ
two_factor_authentication: Asesteb s snat n tarrayin
webauthn_authentication: Tisura n teɣlist
severed_relationships:
download: Azdam (%{count})
statuses:
attached:
audio:
@ -876,7 +888,6 @@ kab:
public: Yal yiwen
title: '%{name}: "%{quote}"'
visibilities:
direct: Usrid
private: Imeḍfaṛen kan
private_long: Ssken i ymeḍfaṛen kan
public: Azayez
@ -960,6 +971,9 @@ kab:
verification:
here_is_how: Ha-t-a amek
verification: Asenqed
website_verification: Asenqed n usmel web
webauthn_credentials:
add: Rnu tasarut n teɣlist tamaynut
create:
success: Tasarut-ik·im n tɣellist tettwarna akken iwata.
delete: Kkes

View File

@ -1873,7 +1873,6 @@ ko:
public: 모두
title: '%{name}: "%{quote}"'
visibilities:
direct: 다이렉트
private: 비공개
private_long: 팔로워에게만 공개됩니다
public: 공개

View File

@ -1405,7 +1405,6 @@ ku:
reblog: Ev şandî nayê derzî kirin
title: "%{name}%{quote}"
visibilities:
direct: Rasterast
private: Tenê şopîneran
private_long: Tenê bo şopîneran nîşan bide
public: Gelemperî

View File

@ -1750,7 +1750,6 @@ lad:
public: Todos
title: '%{name}: "%{quote}"'
visibilities:
direct: Direkto
private: Solo suivantes
private_long: Solo amostra a tus segidores
public: Publiko

View File

@ -1908,7 +1908,6 @@ lv:
public: Visi
title: "%{name}: “%{quote}”"
visibilities:
direct: Tiešs
private: Tikai sekotājiem
private_long: Rādīt tikai sekotājiem
public: Publisks

View File

@ -1554,7 +1554,6 @@ ms:
reblog: Rangsangan tidak boleh disematkan
title: '%{name}: "%{quote}"'
visibilities:
direct: Terus
private: Pengikut sahaja
private_long: Hanya tunjukkan kepada pengikut
public: Awam

View File

@ -1545,7 +1545,6 @@ my:
reblog: Boost လုပ်ထားသောပို့စ်ကို ပင်ထား၍မရပါ
title: '%{name}: "%{quote}"'
visibilities:
direct: တိုက်ရိုက်
private: စောင့်ကြည့်သူများသာ
private_long: စောင့်ကြည့်သူများကိုသာ ပြရန်
public: အများမြင်

View File

@ -1914,7 +1914,6 @@ nl:
public: Iedereen
title: '%{name}: "%{quote}"'
visibilities:
direct: Privébericht
private: Alleen volgers
private_long: Alleen aan jouw volgers tonen
public: Openbaar

View File

@ -1914,7 +1914,6 @@ nn:
public: Alle
title: "%{name}: «%{quote}»"
visibilities:
direct: Direkte
private: Berre fylgjarar
private_long: Vis berre til fylgjarar
public: Offentleg

View File

@ -1629,7 +1629,6 @@
reblog: En fremheving kan ikke festes
title: "%{name}: «%{quote}»"
visibilities:
direct: Direkte
private: Privat
private_long: Synlig kun for følgere
public: Offentlig

View File

@ -848,7 +848,6 @@ oc:
reblog: Se pòt pas penjar un tut partejat
title: '%{name}: "%{quote}"'
visibilities:
direct: Dirècte
private: Seguidors solament
private_long: Mostrar pas quals seguidors
public: Public

View File

@ -1978,7 +1978,6 @@ pl:
public: Wszyscy
title: '%{name}: "%{quote}"'
visibilities:
direct: Bezpośredni
private: Tylko dla obserwujących
private_long: Widoczne tylko dla osób, które Cię obserwują
public: Publiczne

View File

@ -1873,7 +1873,6 @@ pt-BR:
public: Todos
title: '%{name}: "%{quote}"'
visibilities:
direct: Direto
private: Apenas seguidores
private_long: Exibir apenas para seguidores
public: Público

View File

@ -1914,7 +1914,6 @@ pt-PT:
public: Todos
title: '%{name}: "%{quote}"'
visibilities:
direct: Direto
private: Só para seguidores
private_long: Mostrar só aos seguidores
public: Público

View File

@ -1981,7 +1981,6 @@ ru:
public: Кто угодно
title: "%{name}: «%{quote}»"
visibilities:
direct: Личное упоминание
private: Только для подписчиков
private_long: Доступен только вашим подписчикам
public: Публичный

View File

@ -1156,7 +1156,6 @@ sc:
reblog: Is cumpartziduras non podent èssere apicadas
title: '%{name}: "%{quote}"'
visibilities:
direct: Deretu
private: Isceti pro chie ti sighit
private_long: Ammustra isceti a chie ti sighit
public: Pùblicu

View File

@ -1395,7 +1395,6 @@ sco:
reblog: A heeze cannae be preent
title: '%{name}: "%{quote}"'
visibilities:
direct: Direck
private: Follaers-ainly
private_long: Ainly shaw tae follaers
public: Public

View File

@ -1268,7 +1268,6 @@ si:
ownership: වෙනත් අයගේ ලිපි ඇමිණීමට නොහැකිය
title: '%{name}: "%{quote}"'
visibilities:
direct: සෘජු
private: අනුගාමිකයින් පමණි
private_long: අනුගාමිකයින්ට පමණක් පෙන්වන්න
public: ප්‍රසිද්ධ

View File

@ -1278,7 +1278,6 @@ sk:
reblog: Vyzdvihnutie sa nedá pripnúť
title: '%{name}: „%{quote}"'
visibilities:
direct: Súkromne
private: Iba pre sledovateľov
private_long: Ukáž iba následovateľom
public: Verejné

View File

@ -1912,7 +1912,6 @@ sl:
reblog: Izpostavitev ne more biti pripeta
title: "%{name}: »%{quote}«"
visibilities:
direct: Neposredno
private: Samo sledilci
private_long: Prikaži samo sledilcem
public: Javno

Some files were not shown because too many files have changed in this diff Show More