Merge tag 'v4.5.0' into chinwag-next
This commit is contained in:
commit
b7aeafa035
351 changed files with 5552 additions and 2547 deletions
|
|
@ -70,7 +70,7 @@ function loaded() {
|
|||
};
|
||||
|
||||
document.querySelectorAll('.emojify').forEach((content) => {
|
||||
content.innerHTML = emojify(content.innerHTML, {}, true); // Force emojify as public doesn't load the new emoji system.
|
||||
content.innerHTML = emojify(content.innerHTML);
|
||||
});
|
||||
|
||||
document
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { throttle } from 'lodash';
|
|||
|
||||
import api from 'mastodon/api';
|
||||
import { browserHistory } from 'mastodon/components/router';
|
||||
import { countableText } from 'mastodon/features/compose/util/counter';
|
||||
import { search as emojiSearch } from 'mastodon/features/emoji/emoji_mart_search_light';
|
||||
import { tagHistory } from 'mastodon/settings';
|
||||
|
||||
|
|
@ -55,7 +56,6 @@ export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT';
|
|||
export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
|
||||
export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE';
|
||||
export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
|
||||
export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
|
||||
export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE';
|
||||
export const COMPOSE_LANGUAGE_CHANGE = 'COMPOSE_LANGUAGE_CHANGE';
|
||||
|
||||
|
|
@ -88,6 +88,7 @@ const messages = defineMessages({
|
|||
open: { id: 'compose.published.open', defaultMessage: 'Open' },
|
||||
published: { id: 'compose.published.body', defaultMessage: 'Post published.' },
|
||||
saved: { id: 'compose.saved.body', defaultMessage: 'Post saved.' },
|
||||
blankPostError: { id: 'compose.error.blank_post', defaultMessage: 'Post can\'t be blank.' },
|
||||
});
|
||||
|
||||
export const ensureComposeIsVisible = (getState) => {
|
||||
|
|
@ -197,7 +198,15 @@ export function submitCompose(successCallback) {
|
|||
const hasQuote = !!getState().getIn(['compose', 'quoted_status_id']);
|
||||
const spoiler_text = getState().getIn(['compose', 'spoiler']) ? getState().getIn(['compose', 'spoiler_text'], '') : '';
|
||||
|
||||
if (!(status?.length || media.size !== 0 || (hasQuote && spoiler_text?.length))) {
|
||||
const fulltext = `${spoiler_text ?? ''}${countableText(status ?? '')}`;
|
||||
const hasText = fulltext.trim().length > 0;
|
||||
|
||||
if (!(hasText || media.size !== 0 || (hasQuote && spoiler_text?.length))) {
|
||||
dispatch(showAlert({
|
||||
message: messages.blankPostError,
|
||||
}));
|
||||
dispatch(focusCompose());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -622,6 +631,7 @@ export function fetchComposeSuggestions(token) {
|
|||
fetchComposeSuggestionsEmojis(dispatch, getState, token);
|
||||
break;
|
||||
case '#':
|
||||
case '#':
|
||||
fetchComposeSuggestionsTags(dispatch, getState, token);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -663,11 +673,11 @@ export function selectComposeSuggestion(position, token, suggestion, path) {
|
|||
|
||||
dispatch(useEmoji(suggestion));
|
||||
} else if (suggestion.type === 'hashtag') {
|
||||
completion = `#${suggestion.name}`;
|
||||
startPosition = position - 1;
|
||||
completion = suggestion.name.slice(token.length - 1);
|
||||
startPosition = position + token.length;
|
||||
} else if (suggestion.type === 'account') {
|
||||
completion = getState().getIn(['accounts', suggestion.id, 'acct']);
|
||||
startPosition = position;
|
||||
completion = `@${getState().getIn(['accounts', suggestion.id, 'acct'])}`;
|
||||
startPosition = position - 1;
|
||||
}
|
||||
|
||||
// We don't want to replace hashtags that vary only in case due to accessibility, but we need to fire off an event so that
|
||||
|
|
@ -727,7 +737,7 @@ function insertIntoTagHistory(recognizedTags, text) {
|
|||
// complicated because of new normalization rules, it's no longer just
|
||||
// a case sensitivity issue
|
||||
const names = recognizedTags.map(tag => {
|
||||
const matches = text.match(new RegExp(`#${tag.name}`, 'i'));
|
||||
const matches = text.match(new RegExp(`[##]${tag.name}`, 'i'));
|
||||
|
||||
if (matches && matches.length > 0) {
|
||||
return matches[0].slice(1);
|
||||
|
|
@ -783,13 +793,6 @@ export function changeComposeSpoilerText(text) {
|
|||
};
|
||||
}
|
||||
|
||||
export function changeComposeVisibility(value) {
|
||||
return {
|
||||
type: COMPOSE_VISIBILITY_CHANGE,
|
||||
value,
|
||||
};
|
||||
}
|
||||
|
||||
export function insertEmojiCompose(position, emoji, needsSpace) {
|
||||
return {
|
||||
type: COMPOSE_EMOJI_INSERT,
|
||||
|
|
|
|||
|
|
@ -13,10 +13,11 @@ import {
|
|||
} from 'mastodon/store/typed_functions';
|
||||
|
||||
import type { ApiQuotePolicy } from '../api_types/quotes';
|
||||
import type { Status } from '../models/status';
|
||||
import type { Status, StatusVisibility } from '../models/status';
|
||||
import type { RootState } from '../store';
|
||||
|
||||
import { showAlert } from './alerts';
|
||||
import { focusCompose } from './compose';
|
||||
import { changeCompose, focusCompose } from './compose';
|
||||
import { importFetchedStatuses } from './importer';
|
||||
import { openModal } from './modal';
|
||||
|
||||
|
|
@ -41,6 +42,10 @@ const messages = defineMessages({
|
|||
id: 'quote_error.unauthorized',
|
||||
defaultMessage: 'You are not authorized to quote this post.',
|
||||
},
|
||||
quoteErrorPrivateMention: {
|
||||
id: 'quote_error.private_mentions',
|
||||
defaultMessage: 'Quoting is not allowed with direct mentions.',
|
||||
},
|
||||
});
|
||||
|
||||
type SimulatedMediaAttachmentJSON = ApiMediaAttachmentJSON & {
|
||||
|
|
@ -67,6 +72,39 @@ const simulateModifiedApiResponse = (
|
|||
return data;
|
||||
};
|
||||
|
||||
export const changeComposeVisibility = createAppThunk(
|
||||
'compose/visibility_change',
|
||||
(visibility: StatusVisibility, { dispatch, getState }) => {
|
||||
if (visibility !== 'direct') {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
const state = getState();
|
||||
const quotedStatusId = state.compose.get('quoted_status_id') as
|
||||
| string
|
||||
| null;
|
||||
if (!quotedStatusId) {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
// Remove the quoted status
|
||||
dispatch(quoteComposeCancel());
|
||||
const quotedStatus = state.statuses.get(quotedStatusId) as Status | null;
|
||||
if (!quotedStatus) {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
// Append the quoted status URL to the compose text
|
||||
const url = quotedStatus.get('url') as string;
|
||||
const text = state.compose.get('text') as string;
|
||||
if (!text.includes(url)) {
|
||||
const newText = text.trim() ? `${text}\n\n${url}` : url;
|
||||
dispatch(changeCompose(newText));
|
||||
}
|
||||
return visibility;
|
||||
},
|
||||
);
|
||||
|
||||
export const changeUploadCompose = createDataLoadingThunk(
|
||||
'compose/changeUpload',
|
||||
async (
|
||||
|
|
@ -130,6 +168,8 @@ export const quoteComposeByStatus = createAppThunk(
|
|||
|
||||
if (composeState.get('id')) {
|
||||
dispatch(showAlert({ message: messages.quoteErrorEdit }));
|
||||
} else if (composeState.get('privacy') === 'direct') {
|
||||
dispatch(showAlert({ message: messages.quoteErrorPrivateMention }));
|
||||
} else if (composeState.get('poll')) {
|
||||
dispatch(showAlert({ message: messages.quoteErrorPoll }));
|
||||
} else if (
|
||||
|
|
@ -173,6 +213,17 @@ export const quoteComposeById = createAppThunk(
|
|||
},
|
||||
);
|
||||
|
||||
const composeStateForbidsLink = (composeState: RootState['compose']) => {
|
||||
return (
|
||||
composeState.get('quoted_status_id') ||
|
||||
composeState.get('is_submitting') ||
|
||||
composeState.get('poll') ||
|
||||
composeState.get('is_uploading') ||
|
||||
composeState.get('id') ||
|
||||
composeState.get('privacy') === 'direct'
|
||||
);
|
||||
};
|
||||
|
||||
export const pasteLinkCompose = createDataLoadingThunk(
|
||||
'compose/pasteLink',
|
||||
async ({ url }: { url: string }) => {
|
||||
|
|
@ -183,15 +234,12 @@ export const pasteLinkCompose = createDataLoadingThunk(
|
|||
limit: 2,
|
||||
});
|
||||
},
|
||||
(data, { dispatch, getState }) => {
|
||||
(data, { dispatch, getState, requestId }) => {
|
||||
const composeState = getState().compose;
|
||||
|
||||
if (
|
||||
composeState.get('quoted_status_id') ||
|
||||
composeState.get('is_submitting') ||
|
||||
composeState.get('poll') ||
|
||||
composeState.get('is_uploading') ||
|
||||
composeState.get('id')
|
||||
composeStateForbidsLink(composeState) ||
|
||||
composeState.get('fetching_link') !== requestId // Request has been cancelled
|
||||
)
|
||||
return;
|
||||
|
||||
|
|
@ -207,6 +255,17 @@ export const pasteLinkCompose = createDataLoadingThunk(
|
|||
dispatch(quoteComposeById(data.statuses[0].id));
|
||||
}
|
||||
},
|
||||
{
|
||||
useLoadingBar: false,
|
||||
condition: (_, { getState }) =>
|
||||
!getState().compose.get('fetching_link') &&
|
||||
!composeStateForbidsLink(getState().compose),
|
||||
},
|
||||
);
|
||||
|
||||
// Ideally this would cancel the action and the HTTP request, but this is good enough
|
||||
export const cancelPasteLinkCompose = createAction(
|
||||
'compose/cancelPasteLinkCompose',
|
||||
);
|
||||
|
||||
export const quoteComposeCancel = createAction('compose/quoteComposeCancel');
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import escapeTextContentForBrowser from 'escape-html';
|
||||
|
||||
import { makeEmojiMap } from 'mastodon/models/custom_emoji';
|
||||
|
||||
import emojify from '../../features/emoji/emoji';
|
||||
import { expandSpoilers } from '../../initial_state';
|
||||
|
||||
const domParser = new DOMParser();
|
||||
|
|
@ -88,11 +85,10 @@ export function normalizeStatus(status, normalOldStatus) {
|
|||
|
||||
const spoilerText = normalStatus.spoiler_text || '';
|
||||
const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
|
||||
const emojiMap = makeEmojiMap(normalStatus.emojis);
|
||||
|
||||
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
|
||||
normalStatus.contentHtml = emojify(normalStatus.content, emojiMap);
|
||||
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap);
|
||||
normalStatus.contentHtml = normalStatus.content;
|
||||
normalStatus.spoilerHtml = escapeTextContentForBrowser(spoilerText);
|
||||
normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive;
|
||||
|
||||
// Remove quote fallback link from the DOM so it doesn't mess with paragraph margins
|
||||
|
|
@ -128,14 +124,12 @@ export function normalizeStatus(status, normalOldStatus) {
|
|||
}
|
||||
|
||||
export function normalizeStatusTranslation(translation, status) {
|
||||
const emojiMap = makeEmojiMap(status.get('emojis').toJS());
|
||||
|
||||
const normalTranslation = {
|
||||
detected_source_language: translation.detected_source_language,
|
||||
language: translation.language,
|
||||
provider: translation.provider,
|
||||
contentHtml: emojify(translation.content, emojiMap),
|
||||
spoilerHtml: emojify(escapeTextContentForBrowser(translation.spoiler_text), emojiMap),
|
||||
contentHtml: translation.content,
|
||||
spoilerHtml: escapeTextContentForBrowser(translation.spoiler_text),
|
||||
spoiler_text: translation.spoiler_text,
|
||||
};
|
||||
|
||||
|
|
@ -149,9 +143,8 @@ export function normalizeStatusTranslation(translation, status) {
|
|||
|
||||
export function normalizeAnnouncement(announcement) {
|
||||
const normalAnnouncement = { ...announcement };
|
||||
const emojiMap = makeEmojiMap(normalAnnouncement.emojis);
|
||||
|
||||
normalAnnouncement.contentHtml = emojify(normalAnnouncement.content, emojiMap);
|
||||
normalAnnouncement.contentHtml = normalAnnouncement.content;
|
||||
|
||||
return normalAnnouncement;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,13 +32,20 @@ import {
|
|||
const randomUpTo = max =>
|
||||
Math.floor(Math.random() * Math.floor(max));
|
||||
|
||||
/**
|
||||
* @typedef {import('mastodon/store').AppDispatch} Dispatch
|
||||
* @typedef {import('mastodon/store').GetState} GetState
|
||||
* @typedef {import('redux').UnknownAction} UnknownAction
|
||||
* @typedef {function(Dispatch, GetState): Promise<void>} FallbackFunction
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} timelineId
|
||||
* @param {string} channelName
|
||||
* @param {Object.<string, string>} params
|
||||
* @param {Object} options
|
||||
* @param {function(Function, Function): Promise<void>} [options.fallback]
|
||||
* @param {function(): void} [options.fillGaps]
|
||||
* @param {FallbackFunction} [options.fallback]
|
||||
* @param {function(): UnknownAction} [options.fillGaps]
|
||||
* @param {function(object): boolean} [options.accept]
|
||||
* @returns {function(): void}
|
||||
*/
|
||||
|
|
@ -46,13 +53,14 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
|
|||
const { messages } = getLocale();
|
||||
|
||||
return connectStream(channelName, params, (dispatch, getState) => {
|
||||
// @ts-ignore
|
||||
const locale = getState().getIn(['meta', 'locale']);
|
||||
|
||||
// @ts-expect-error
|
||||
let pollingId;
|
||||
|
||||
/**
|
||||
* @param {function(Function, Function): Promise<void>} fallback
|
||||
* @param {FallbackFunction} fallback
|
||||
*/
|
||||
|
||||
const useFallback = async fallback => {
|
||||
|
|
@ -132,7 +140,7 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
|
|||
};
|
||||
|
||||
/**
|
||||
* @param {Function} dispatch
|
||||
* @param {Dispatch} dispatch
|
||||
*/
|
||||
async function refreshHomeTimelineAndNotification(dispatch) {
|
||||
await dispatch(expandHomeTimeline({ maxId: undefined }));
|
||||
|
|
@ -151,7 +159,11 @@ async function refreshHomeTimelineAndNotification(dispatch) {
|
|||
* @returns {function(): void}
|
||||
*/
|
||||
export const connectUserStream = () =>
|
||||
connectTimelineStream('home', 'user', {}, { fallback: refreshHomeTimelineAndNotification, fillGaps: fillHomeTimelineGaps });
|
||||
connectTimelineStream('home', 'user', {}, {
|
||||
fallback: refreshHomeTimelineAndNotification,
|
||||
// @ts-expect-error
|
||||
fillGaps: fillHomeTimelineGaps
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Object} options
|
||||
|
|
@ -159,7 +171,10 @@ export const connectUserStream = () =>
|
|||
* @returns {function(): void}
|
||||
*/
|
||||
export const connectCommunityStream = ({ onlyMedia } = {}) =>
|
||||
connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`, {}, { fillGaps: () => (fillCommunityTimelineGaps({ onlyMedia })) });
|
||||
connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`, {}, {
|
||||
// @ts-expect-error
|
||||
fillGaps: () => (fillCommunityTimelineGaps({ onlyMedia }))
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Object} options
|
||||
|
|
@ -168,7 +183,10 @@ export const connectCommunityStream = ({ onlyMedia } = {}) =>
|
|||
* @returns {function(): void}
|
||||
*/
|
||||
export const connectPublicStream = ({ onlyMedia, onlyRemote } = {}) =>
|
||||
connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, {}, { fillGaps: () => fillPublicTimelineGaps({ onlyMedia, onlyRemote }) });
|
||||
connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, {}, {
|
||||
// @ts-expect-error
|
||||
fillGaps: () => fillPublicTimelineGaps({ onlyMedia, onlyRemote })
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} columnId
|
||||
|
|
@ -191,4 +209,7 @@ export const connectDirectStream = () =>
|
|||
* @returns {function(): void}
|
||||
*/
|
||||
export const connectListStream = listId =>
|
||||
connectTimelineStream(`list:${listId}`, 'list', { list: listId }, { fillGaps: () => fillListTimelineGaps(listId) });
|
||||
connectTimelineStream(`list:${listId}`, 'list', { list: listId }, {
|
||||
// @ts-expect-error
|
||||
fillGaps: () => fillListTimelineGaps(listId)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
import { useCallback } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { useLinks } from 'mastodon/hooks/useLinks';
|
||||
|
||||
import { useAppSelector } from '../store';
|
||||
import { isModernEmojiEnabled } from '../utils/environment';
|
||||
|
||||
import { EmojiHTML } from './emoji/html';
|
||||
import { useElementHandledLink } from './status/handled_link';
|
||||
|
|
@ -21,22 +16,6 @@ export const AccountBio: React.FC<AccountBioProps> = ({
|
|||
accountId,
|
||||
showDropdown = false,
|
||||
}) => {
|
||||
const handleClick = useLinks(showDropdown);
|
||||
const handleNodeChange = useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
if (
|
||||
!showDropdown ||
|
||||
!node ||
|
||||
node.childNodes.length === 0 ||
|
||||
isModernEmojiEnabled()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
addDropdownToHashtags(node, accountId);
|
||||
},
|
||||
[showDropdown, accountId],
|
||||
);
|
||||
|
||||
const htmlHandlers = useElementHandledLink({
|
||||
hashtagAccountId: showDropdown ? accountId : undefined,
|
||||
});
|
||||
|
|
@ -62,30 +41,7 @@ export const AccountBio: React.FC<AccountBioProps> = ({
|
|||
htmlString={note}
|
||||
extraEmojis={extraEmojis}
|
||||
className={classNames(className, 'translate')}
|
||||
onClickCapture={handleClick}
|
||||
ref={handleNodeChange}
|
||||
{...htmlHandlers}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
function addDropdownToHashtags(node: HTMLElement | null, accountId: string) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
for (const childNode of node.childNodes) {
|
||||
if (!(childNode instanceof HTMLElement)) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
childNode instanceof HTMLAnchorElement &&
|
||||
(childNode.classList.contains('hashtag') ||
|
||||
childNode.innerText.startsWith('#')) &&
|
||||
!childNode.dataset.menuHashtag
|
||||
) {
|
||||
childNode.dataset.menuHashtag = accountId;
|
||||
} else if (childNode.childNodes.length > 0) {
|
||||
addDropdownToHashtags(childNode, accountId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
|
|||
|
||||
static defaultProps = {
|
||||
autoFocus: true,
|
||||
searchTokens: ['@', ':', '#'],
|
||||
searchTokens: ['@', '@', ':', '#', '#'],
|
||||
};
|
||||
|
||||
state = {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const textAtCursorMatchesToken = (str, caretPosition) => {
|
|||
word = str.slice(left, right + caretPosition);
|
||||
}
|
||||
|
||||
if (!word || word.trim().length < 3 || ['@', ':', '#'].indexOf(word[0]) === -1) {
|
||||
if (!word || word.trim().length < 3 || ['@', '@', ':', '#', '#'].indexOf(word[0]) === -1) {
|
||||
return [null, null];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,6 @@ export const Linked: Story = {
|
|||
acct: username,
|
||||
})
|
||||
: undefined;
|
||||
return <LinkedDisplayName {...args} displayProps={{ account }} />;
|
||||
return <LinkedDisplayName displayProps={{ account, ...args }} />;
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ import { Skeleton } from '../skeleton';
|
|||
import type { DisplayNameProps } from './index';
|
||||
|
||||
export const DisplayNameWithoutDomain: FC<
|
||||
Omit<DisplayNameProps, 'variant' | 'localDomain'> &
|
||||
ComponentPropsWithoutRef<'span'>
|
||||
> = ({ account, className, children, ...props }) => {
|
||||
Omit<DisplayNameProps, 'variant'> & ComponentPropsWithoutRef<'span'>
|
||||
> = ({ account, className, children, localDomain: _, ...props }) => {
|
||||
return (
|
||||
<AnimateEmojiProvider
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ import { EmojiHTML } from '../emoji/html';
|
|||
import type { DisplayNameProps } from './index';
|
||||
|
||||
export const DisplayNameSimple: FC<
|
||||
Omit<DisplayNameProps, 'variant' | 'localDomain'> &
|
||||
ComponentPropsWithoutRef<'span'>
|
||||
> = ({ account, ...props }) => {
|
||||
Omit<DisplayNameProps, 'variant'> & ComponentPropsWithoutRef<'span'>
|
||||
> = ({ account, localDomain: _, ...props }) => {
|
||||
if (!account) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ import {
|
|||
useState,
|
||||
} from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { cleanExtraEmojis } from '@/mastodon/features/emoji/normalize';
|
||||
import { autoPlayGif } from '@/mastodon/initial_state';
|
||||
import { polymorphicForwardRef } from '@/types/polymorphic';
|
||||
|
|
@ -65,11 +63,7 @@ export const AnimateEmojiProvider = polymorphicForwardRef<
|
|||
const parentContext = useContext(AnimateEmojiContext);
|
||||
if (parentContext !== null) {
|
||||
return (
|
||||
<Wrapper
|
||||
{...props}
|
||||
className={classNames(className, 'animate-parent')}
|
||||
ref={ref}
|
||||
>
|
||||
<Wrapper {...props} className={className} ref={ref}>
|
||||
{children}
|
||||
</Wrapper>
|
||||
);
|
||||
|
|
@ -78,7 +72,7 @@ export const AnimateEmojiProvider = polymorphicForwardRef<
|
|||
return (
|
||||
<Wrapper
|
||||
{...props}
|
||||
className={classNames(className, 'animate-parent')}
|
||||
className={className}
|
||||
onMouseEnter={handleEnter}
|
||||
onMouseLeave={handleLeave}
|
||||
ref={ref}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
import { useMemo } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import type { CustomEmojiMapArg } from '@/mastodon/features/emoji/types';
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
import type {
|
||||
OnAttributeHandler,
|
||||
OnElementHandler,
|
||||
|
|
@ -22,7 +19,7 @@ export interface EmojiHTMLProps {
|
|||
onAttribute?: OnAttributeHandler;
|
||||
}
|
||||
|
||||
export const ModernEmojiHTML = polymorphicForwardRef<'div', EmojiHTMLProps>(
|
||||
export const EmojiHTML = polymorphicForwardRef<'div', EmojiHTMLProps>(
|
||||
(
|
||||
{
|
||||
extraEmojis,
|
||||
|
|
@ -59,32 +56,4 @@ export const ModernEmojiHTML = polymorphicForwardRef<'div', EmojiHTMLProps>(
|
|||
);
|
||||
},
|
||||
);
|
||||
ModernEmojiHTML.displayName = 'ModernEmojiHTML';
|
||||
|
||||
export const LegacyEmojiHTML = polymorphicForwardRef<'div', EmojiHTMLProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
as: asElement,
|
||||
htmlString,
|
||||
extraEmojis,
|
||||
className,
|
||||
onElement,
|
||||
onAttribute,
|
||||
...rest
|
||||
} = props;
|
||||
const Wrapper = asElement ?? 'div';
|
||||
return (
|
||||
<Wrapper
|
||||
{...rest}
|
||||
ref={ref}
|
||||
dangerouslySetInnerHTML={{ __html: htmlString }}
|
||||
className={classNames(className, 'animate-parent')}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
LegacyEmojiHTML.displayName = 'LegacyEmojiHTML';
|
||||
|
||||
export const EmojiHTML = isModernEmojiEnabled()
|
||||
? ModernEmojiHTML
|
||||
: LegacyEmojiHTML;
|
||||
EmojiHTML.displayName = 'EmojiHTML';
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ import { domain } from 'mastodon/initial_state';
|
|||
import { getAccountHidden } from 'mastodon/selectors/accounts';
|
||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||
|
||||
import { useLinks } from '../hooks/useLinks';
|
||||
|
||||
export const HoverCardAccount = forwardRef<
|
||||
HTMLDivElement,
|
||||
{ accountId?: string }
|
||||
|
|
@ -66,8 +64,6 @@ export const HoverCardAccount = forwardRef<
|
|||
!isMutual &&
|
||||
!isFollower;
|
||||
|
||||
const handleClick = useLinks();
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
|
|
@ -110,7 +106,7 @@ export const HoverCardAccount = forwardRef<
|
|||
className='hover-card__bio'
|
||||
/>
|
||||
|
||||
<div className='account-fields' onClickCapture={handleClick}>
|
||||
<div className='account-fields'>
|
||||
<AccountFields
|
||||
fields={account.fields.take(2)}
|
||||
emojis={account.emojis}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import type { OnElementHandler } from '@/mastodon/utils/html';
|
|||
import { polymorphicForwardRef } from '@/types/polymorphic';
|
||||
|
||||
import type { EmojiHTMLProps } from '../emoji/html';
|
||||
import { ModernEmojiHTML } from '../emoji/html';
|
||||
import { EmojiHTML } from '../emoji/html';
|
||||
import { useElementHandledLink } from '../status/handled_link';
|
||||
|
||||
export const HTMLBlock = polymorphicForwardRef<
|
||||
|
|
@ -25,6 +25,6 @@ export const HTMLBlock = polymorphicForwardRef<
|
|||
(...args) => onParentElement?.(...args) ?? onLinkElement(...args),
|
||||
[onLinkElement, onParentElement],
|
||||
);
|
||||
return <ModernEmojiHTML {...props} onElement={onElement} />;
|
||||
return <EmojiHTML {...props} onElement={onElement} />;
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
|||
import { openModal } from 'mastodon/actions/modal';
|
||||
import { fetchPoll, vote } from 'mastodon/actions/polls';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import emojify from 'mastodon/features/emoji/emoji';
|
||||
import { useIdentity } from 'mastodon/identity_context';
|
||||
import { makeEmojiMap } from 'mastodon/models/custom_emoji';
|
||||
import type * as Model from 'mastodon/models/poll';
|
||||
import type { Status } from 'mastodon/models/status';
|
||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||
|
|
@ -235,12 +233,11 @@ const PollOption: React.FC<PollOptionProps> = (props) => {
|
|||
let titleHtml = option.translation?.titleHtml ?? option.titleHtml;
|
||||
|
||||
if (!titleHtml) {
|
||||
const emojiMap = makeEmojiMap(poll.emojis);
|
||||
titleHtml = emojify(escapeTextContentForBrowser(title), emojiMap);
|
||||
titleHtml = escapeTextContentForBrowser(title);
|
||||
}
|
||||
|
||||
return titleHtml;
|
||||
}, [option, poll, title]);
|
||||
}, [option, title]);
|
||||
|
||||
// Handlers
|
||||
const handleOptionChange = useCallback(() => {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,12 @@ export const HandledLink: FC<HandledLinkProps & ComponentProps<'a'>> = ({
|
|||
...props
|
||||
}) => {
|
||||
// Handle hashtags
|
||||
if (text.startsWith('#') || prevText?.endsWith('#')) {
|
||||
if (
|
||||
text.startsWith('#') ||
|
||||
prevText?.endsWith('#') ||
|
||||
text.startsWith('#') ||
|
||||
prevText?.endsWith('#')
|
||||
) {
|
||||
const hashtag = text.slice(1).trim();
|
||||
return (
|
||||
<Link
|
||||
|
|
@ -38,7 +43,7 @@ export const HandledLink: FC<HandledLinkProps & ComponentProps<'a'>> = ({
|
|||
{children}
|
||||
</Link>
|
||||
);
|
||||
} else if ((text.startsWith('@') || prevText?.endsWith('@')) && mention) {
|
||||
} else if (mention) {
|
||||
// Handle mentions
|
||||
return (
|
||||
<Link
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ export const StatusBanner: React.FC<{
|
|||
|
||||
<button
|
||||
ref={buttonRef}
|
||||
type='button'
|
||||
className='link-button'
|
||||
onClick={onClick}
|
||||
aria-describedby={descriptionId}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ import { Poll } from 'mastodon/components/poll';
|
|||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { languages as preloadedLanguages } from 'mastodon/initial_state';
|
||||
|
||||
import { isModernEmojiEnabled } from '../utils/environment';
|
||||
|
||||
import { EmojiHTML } from './emoji/html';
|
||||
import { HandledLink } from './status/handled_link';
|
||||
|
||||
|
|
@ -72,6 +70,17 @@ const mapStateToProps = state => ({
|
|||
languages: state.getIn(['server', 'translationLanguages', 'items']),
|
||||
});
|
||||
|
||||
const compareUrls = (href1, href2) => {
|
||||
try {
|
||||
const url1 = new URL(href1);
|
||||
const url2 = new URL(href2);
|
||||
|
||||
return url1.origin === url2.origin && url1.pathname === url2.pathname && url1.search === url2.search;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class StatusContent extends PureComponent {
|
||||
static propTypes = {
|
||||
identity: identityContextPropShape,
|
||||
|
|
@ -108,41 +117,6 @@ class StatusContent extends PureComponent {
|
|||
|
||||
onCollapsedToggle(collapsed);
|
||||
}
|
||||
|
||||
// Exit if modern emoji is enabled, as it handles links using the HandledLink component.
|
||||
if (isModernEmojiEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const links = node.querySelectorAll('a');
|
||||
|
||||
let link, mention;
|
||||
|
||||
for (var i = 0; i < links.length; ++i) {
|
||||
link = links[i];
|
||||
|
||||
if (link.classList.contains('status-link')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
link.classList.add('status-link');
|
||||
|
||||
mention = this.props.status.get('mentions').find(item => link.href === item.get('url'));
|
||||
|
||||
if (mention) {
|
||||
link.addEventListener('click', this.onMentionClick.bind(this, mention), false);
|
||||
link.setAttribute('title', `@${mention.get('acct')}`);
|
||||
link.setAttribute('href', `/@${mention.get('acct')}`);
|
||||
link.setAttribute('data-hover-card-account', mention.get('id'));
|
||||
} else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) {
|
||||
link.addEventListener('click', this.onHashtagClick.bind(this, link.text), false);
|
||||
link.setAttribute('href', `/tags/${link.text.replace(/^#/, '')}`);
|
||||
link.setAttribute('data-menu-hashtag', this.props.status.getIn(['account', 'id']));
|
||||
} else {
|
||||
link.setAttribute('title', link.href);
|
||||
link.classList.add('unhandled-link');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
|
|
@ -153,22 +127,6 @@ class StatusContent extends PureComponent {
|
|||
this._updateStatusLinks();
|
||||
}
|
||||
|
||||
onMentionClick = (mention, e) => {
|
||||
if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.props.history.push(`/@${mention.get('acct')}`);
|
||||
}
|
||||
};
|
||||
|
||||
onHashtagClick = (hashtag, e) => {
|
||||
hashtag = hashtag.replace(/^#/, '');
|
||||
|
||||
if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.props.history.push(`/tags/${hashtag}`);
|
||||
}
|
||||
};
|
||||
|
||||
handleMouseDown = (e) => {
|
||||
this.startXY = [e.clientX, e.clientY];
|
||||
};
|
||||
|
|
@ -206,7 +164,7 @@ class StatusContent extends PureComponent {
|
|||
|
||||
handleElement = (element, { key, ...props }, children) => {
|
||||
if (element instanceof HTMLAnchorElement) {
|
||||
const mention = this.props.status.get('mentions').find(item => element.href === item.get('url'));
|
||||
const mention = this.props.status.get('mentions').find(item => compareUrls(element.href, item.get('url')));
|
||||
return (
|
||||
<HandledLink
|
||||
{...props}
|
||||
|
|
@ -219,7 +177,7 @@ class StatusContent extends PureComponent {
|
|||
{children}
|
||||
</HandledLink>
|
||||
);
|
||||
} else if (element instanceof HTMLParagraphElement && element.classList.contains('quote-inline')) {
|
||||
} else if (element.classList.contains('quote-inline') && this.props.status.get('quote')) {
|
||||
return null;
|
||||
}
|
||||
return undefined;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
|
|
@ -83,6 +83,62 @@ const LimitedAccountHint: React.FC<{ accountId: string }> = ({ accountId }) => {
|
|||
);
|
||||
};
|
||||
|
||||
const FilteredQuote: React.FC<{
|
||||
reveal: VoidFunction;
|
||||
quotedAccountId: string;
|
||||
quoteState: string;
|
||||
}> = ({ reveal, quotedAccountId, quoteState }) => {
|
||||
const account = useAppSelector((state) =>
|
||||
quotedAccountId ? state.accounts.get(quotedAccountId) : undefined,
|
||||
);
|
||||
|
||||
const quoteAuthorName = account?.acct;
|
||||
const domain = quoteAuthorName?.split('@')[1];
|
||||
|
||||
let message;
|
||||
|
||||
switch (quoteState) {
|
||||
case 'blocked_account':
|
||||
message = (
|
||||
<FormattedMessage
|
||||
id='status.quote_error.blocked_account_hint.title'
|
||||
defaultMessage="This post is hidden because you've blocked @{name}."
|
||||
values={{ name: quoteAuthorName }}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case 'blocked_domain':
|
||||
message = (
|
||||
<FormattedMessage
|
||||
id='status.quote_error.blocked_domain_hint.title'
|
||||
defaultMessage="This post is hidden because you've blocked {domain}."
|
||||
values={{ domain }}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case 'muted_account':
|
||||
message = (
|
||||
<FormattedMessage
|
||||
id='status.quote_error.muted_account_hint.title'
|
||||
defaultMessage="This post is hidden because you've muted @{name}."
|
||||
values={{ name: quoteAuthorName }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{message}
|
||||
<button onClick={reveal} className='link-button'>
|
||||
<FormattedMessage
|
||||
id='status.quote_error.limited_account_hint.action'
|
||||
defaultMessage='Show anyway'
|
||||
/>
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
interface QuotedStatusProps {
|
||||
quote: QuoteMap;
|
||||
contextType?: string;
|
||||
|
|
@ -130,6 +186,11 @@ export const QuotedStatus: React.FC<QuotedStatusProps> = ({
|
|||
const isLoaded = loadingState === 'complete';
|
||||
|
||||
const isFetchingQuoteRef = useRef(false);
|
||||
const [revealed, setRevealed] = useState(false);
|
||||
|
||||
const reveal = useCallback(() => {
|
||||
setRevealed(true);
|
||||
}, [setRevealed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoaded) {
|
||||
|
|
@ -189,6 +250,20 @@ export const QuotedStatus: React.FC<QuotedStatusProps> = ({
|
|||
defaultMessage='Post removed by author'
|
||||
/>
|
||||
);
|
||||
} else if (
|
||||
(quoteState === 'blocked_account' ||
|
||||
quoteState === 'blocked_domain' ||
|
||||
quoteState === 'muted_account') &&
|
||||
!revealed &&
|
||||
accountId
|
||||
) {
|
||||
quoteError = (
|
||||
<FilteredQuote
|
||||
quoteState={quoteState}
|
||||
reveal={reveal}
|
||||
quotedAccountId={accountId}
|
||||
/>
|
||||
);
|
||||
} else if (
|
||||
!status ||
|
||||
!quotedStatusId ||
|
||||
|
|
|
|||
|
|
@ -1,30 +1,10 @@
|
|||
import { EmojiHTML } from '@/mastodon/components/emoji/html';
|
||||
import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
||||
|
||||
import { isModernEmojiEnabled } from '../utils/environment';
|
||||
import type { OnAttributeHandler } from '../utils/html';
|
||||
|
||||
import { Icon } from './icon';
|
||||
|
||||
const domParser = new DOMParser();
|
||||
|
||||
const stripRelMe = (html: string) => {
|
||||
if (isModernEmojiEnabled()) {
|
||||
return html;
|
||||
}
|
||||
const document = domParser.parseFromString(html, 'text/html').documentElement;
|
||||
|
||||
document.querySelectorAll<HTMLAnchorElement>('a[rel]').forEach((link) => {
|
||||
link.rel = link.rel
|
||||
.split(' ')
|
||||
.filter((x: string) => x !== 'me')
|
||||
.join(' ');
|
||||
});
|
||||
|
||||
const body = document.querySelector('body');
|
||||
return body?.innerHTML ?? '';
|
||||
};
|
||||
|
||||
const onAttribute: OnAttributeHandler = (name, value, tagName) => {
|
||||
if (name === 'rel' && tagName === 'a') {
|
||||
if (value === 'me') {
|
||||
|
|
@ -47,10 +27,6 @@ interface Props {
|
|||
export const VerifiedBadge: React.FC<Props> = ({ link }) => (
|
||||
<span className='verified-badge'>
|
||||
<Icon id='check' icon={CheckIcon} className='verified-badge__mark' />
|
||||
<EmojiHTML
|
||||
as='span'
|
||||
htmlString={stripRelMe(link)}
|
||||
onAttribute={onAttribute}
|
||||
/>
|
||||
<EmojiHTML as='span' htmlString={link} onAttribute={onAttribute} />
|
||||
</span>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -32,16 +32,38 @@ interface Rule extends BaseRule {
|
|||
translations?: Record<string, BaseRule>;
|
||||
}
|
||||
|
||||
function getDefaultSelectedLocale(
|
||||
currentUiLocale: string,
|
||||
localeOptions: SelectItem[],
|
||||
) {
|
||||
const preciseMatch = localeOptions.find(
|
||||
(option) => option.value === currentUiLocale,
|
||||
);
|
||||
if (preciseMatch) {
|
||||
return preciseMatch.value;
|
||||
}
|
||||
|
||||
const partialLocale = currentUiLocale.split('-')[0];
|
||||
const partialMatch = localeOptions.find(
|
||||
(option) => option.value.split('-')[0] === partialLocale,
|
||||
);
|
||||
|
||||
return partialMatch?.value ?? 'default';
|
||||
}
|
||||
|
||||
export const RulesSection: FC<RulesSectionProps> = ({ isLoading = false }) => {
|
||||
const intl = useIntl();
|
||||
const [locale, setLocale] = useState(intl.locale);
|
||||
const rules = useAppSelector((state) => rulesSelector(state, locale));
|
||||
const localeOptions = useAppSelector((state) =>
|
||||
localeOptionsSelector(state, intl),
|
||||
);
|
||||
const [selectedLocale, setSelectedLocale] = useState(() =>
|
||||
getDefaultSelectedLocale(intl.locale, localeOptions),
|
||||
);
|
||||
const rules = useAppSelector((state) => rulesSelector(state, selectedLocale));
|
||||
|
||||
const handleLocaleChange: ChangeEventHandler<HTMLSelectElement> = useCallback(
|
||||
(e) => {
|
||||
setLocale(e.currentTarget.value);
|
||||
setSelectedLocale(e.currentTarget.value);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
|
@ -74,25 +96,27 @@ export const RulesSection: FC<RulesSectionProps> = ({ isLoading = false }) => {
|
|||
))}
|
||||
</ol>
|
||||
|
||||
<div className='rules-languages'>
|
||||
<label htmlFor='language-select'>
|
||||
<FormattedMessage
|
||||
id='about.language_label'
|
||||
defaultMessage='Language'
|
||||
/>
|
||||
</label>
|
||||
<select onChange={handleLocaleChange} id='language-select'>
|
||||
{localeOptions.map((option) => (
|
||||
<option
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
selected={option.value === locale}
|
||||
>
|
||||
{option.text}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
{localeOptions.length > 1 && (
|
||||
<div className='rules-languages'>
|
||||
<label htmlFor='language-select'>
|
||||
<FormattedMessage
|
||||
id='about.language_label'
|
||||
defaultMessage='Language'
|
||||
/>
|
||||
</label>
|
||||
<select onChange={handleLocaleChange} id='language-select'>
|
||||
{localeOptions.map((option) => (
|
||||
<option
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
selected={option.value === selectedLocale}
|
||||
>
|
||||
{option.text}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ import { ShortNumber } from 'mastodon/components/short_number';
|
|||
import { AccountNote } from 'mastodon/features/account/components/account_note';
|
||||
import { DomainPill } from 'mastodon/features/account/components/domain_pill';
|
||||
import FollowRequestNoteContainer from 'mastodon/features/account/containers/follow_request_note_container';
|
||||
import { useLinks } from 'mastodon/hooks/useLinks';
|
||||
import { useIdentity } from 'mastodon/identity_context';
|
||||
import { autoPlayGif, me, domain as localDomain } from 'mastodon/initial_state';
|
||||
import type { Account } from 'mastodon/models/account';
|
||||
|
|
@ -198,7 +197,6 @@ export const AccountHeader: React.FC<{
|
|||
state.relationships.get(accountId),
|
||||
);
|
||||
const hidden = useAppSelector((state) => getAccountHidden(state, accountId));
|
||||
const handleLinkClick = useLinks();
|
||||
|
||||
const handleBlock = useCallback(() => {
|
||||
if (!account) {
|
||||
|
|
@ -852,10 +850,7 @@ export const AccountHeader: React.FC<{
|
|||
|
||||
{!(suspended || hidden) && (
|
||||
<div className='account__header__extra'>
|
||||
<div
|
||||
className='account__header__bio'
|
||||
onClickCapture={handleLinkClick}
|
||||
>
|
||||
<div className='account__header__bio'>
|
||||
{account.id !== me && signedIn && (
|
||||
<AccountNote accountId={accountId} />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useRef, useCallback, useState, useId } from 'react';
|
||||
import { useEffect, useRef, useCallback, useState } from 'react';
|
||||
|
||||
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||
|
||||
|
|
@ -22,6 +22,8 @@ import { useAudioVisualizer } from 'mastodon/hooks/useAudioVisualizer';
|
|||
import { displayMedia, useBlurhash } from 'mastodon/initial_state';
|
||||
import { playerSettings } from 'mastodon/settings';
|
||||
|
||||
import { AudioVisualizer } from './visualizer';
|
||||
|
||||
const messages = defineMessages({
|
||||
play: { id: 'video.play', defaultMessage: 'Play' },
|
||||
pause: { id: 'video.pause', defaultMessage: 'Pause' },
|
||||
|
|
@ -116,7 +118,6 @@ export const Audio: React.FC<{
|
|||
const seekRef = useRef<HTMLDivElement>(null);
|
||||
const volumeRef = useRef<HTMLDivElement>(null);
|
||||
const hoverTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>();
|
||||
const accessibilityId = useId();
|
||||
|
||||
const { audioContextRef, sourceRef, gainNodeRef, playAudio, pauseAudio } =
|
||||
useAudioContext({ audioElementRef: audioRef });
|
||||
|
|
@ -538,19 +539,6 @@ export const Audio: React.FC<{
|
|||
[togglePlay, toggleMute],
|
||||
);
|
||||
|
||||
const springForBand0 = useSpring({
|
||||
to: { r: 50 + (frequencyBands[0] ?? 0) * 10 },
|
||||
config: config.wobbly,
|
||||
});
|
||||
const springForBand1 = useSpring({
|
||||
to: { r: 50 + (frequencyBands[1] ?? 0) * 10 },
|
||||
config: config.wobbly,
|
||||
});
|
||||
const springForBand2 = useSpring({
|
||||
to: { r: 50 + (frequencyBands[2] ?? 0) * 10 },
|
||||
config: config.wobbly,
|
||||
});
|
||||
|
||||
const progress = Math.min((currentTime / loadedDuration) * 100, 100);
|
||||
const effectivelyMuted = muted || volume === 0;
|
||||
|
||||
|
|
@ -641,81 +629,7 @@ export const Audio: React.FC<{
|
|||
</div>
|
||||
|
||||
<div className='audio-player__controls__play'>
|
||||
<svg
|
||||
className='audio-player__visualizer'
|
||||
viewBox='0 0 124 124'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
<animated.circle
|
||||
opacity={0.5}
|
||||
cx={57}
|
||||
cy={62.5}
|
||||
r={springForBand0.r}
|
||||
fill='var(--player-accent-color)'
|
||||
/>
|
||||
<animated.circle
|
||||
opacity={0.5}
|
||||
cx={65}
|
||||
cy={57.5}
|
||||
r={springForBand1.r}
|
||||
fill='var(--player-accent-color)'
|
||||
/>
|
||||
<animated.circle
|
||||
opacity={0.5}
|
||||
cx={63}
|
||||
cy={66.5}
|
||||
r={springForBand2.r}
|
||||
fill='var(--player-accent-color)'
|
||||
/>
|
||||
|
||||
<g clipPath={`url(#${accessibilityId}-clip)`}>
|
||||
<rect
|
||||
x={14}
|
||||
y={14}
|
||||
width={96}
|
||||
height={96}
|
||||
fill={`url(#${accessibilityId}-pattern)`}
|
||||
/>
|
||||
<rect
|
||||
x={14}
|
||||
y={14}
|
||||
width={96}
|
||||
height={96}
|
||||
fill='var(--player-background-color'
|
||||
opacity={0.45}
|
||||
/>
|
||||
</g>
|
||||
|
||||
<defs>
|
||||
<pattern
|
||||
id={`${accessibilityId}-pattern`}
|
||||
patternContentUnits='objectBoundingBox'
|
||||
width='1'
|
||||
height='1'
|
||||
>
|
||||
<use href={`#${accessibilityId}-image`} />
|
||||
</pattern>
|
||||
|
||||
<clipPath id={`${accessibilityId}-clip`}>
|
||||
<rect
|
||||
x={14}
|
||||
y={14}
|
||||
width={96}
|
||||
height={96}
|
||||
rx={48}
|
||||
fill='white'
|
||||
/>
|
||||
</clipPath>
|
||||
|
||||
<image
|
||||
id={`${accessibilityId}-image`}
|
||||
href={poster}
|
||||
width={1}
|
||||
height={1}
|
||||
preserveAspectRatio='none'
|
||||
/>
|
||||
</defs>
|
||||
</svg>
|
||||
<AudioVisualizer frequencyBands={frequencyBands} poster={poster} />
|
||||
|
||||
<button
|
||||
type='button'
|
||||
|
|
|
|||
100
app/javascript/mastodon/features/audio/visualizer.tsx
Normal file
100
app/javascript/mastodon/features/audio/visualizer.tsx
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import { useId } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { animated, config, useSpring } from '@react-spring/web';
|
||||
|
||||
interface AudioVisualizerProps {
|
||||
frequencyBands?: number[];
|
||||
poster?: string;
|
||||
}
|
||||
|
||||
export const AudioVisualizer: FC<AudioVisualizerProps> = ({
|
||||
frequencyBands = [],
|
||||
poster,
|
||||
}) => {
|
||||
const accessibilityId = useId();
|
||||
|
||||
const springForBand0 = useSpring({
|
||||
to: { r: 50 + (frequencyBands[0] ?? 0) * 10 },
|
||||
config: config.wobbly,
|
||||
});
|
||||
const springForBand1 = useSpring({
|
||||
to: { r: 50 + (frequencyBands[1] ?? 0) * 10 },
|
||||
config: config.wobbly,
|
||||
});
|
||||
const springForBand2 = useSpring({
|
||||
to: { r: 50 + (frequencyBands[2] ?? 0) * 10 },
|
||||
config: config.wobbly,
|
||||
});
|
||||
|
||||
return (
|
||||
<svg
|
||||
className='audio-player__visualizer'
|
||||
viewBox='0 0 124 124'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
<animated.circle
|
||||
opacity={0.5}
|
||||
cx={57}
|
||||
cy={62.5}
|
||||
r={springForBand0.r}
|
||||
fill='var(--player-accent-color)'
|
||||
/>
|
||||
<animated.circle
|
||||
opacity={0.5}
|
||||
cx={65}
|
||||
cy={57.5}
|
||||
r={springForBand1.r}
|
||||
fill='var(--player-accent-color)'
|
||||
/>
|
||||
<animated.circle
|
||||
opacity={0.5}
|
||||
cx={63}
|
||||
cy={66.5}
|
||||
r={springForBand2.r}
|
||||
fill='var(--player-accent-color)'
|
||||
/>
|
||||
|
||||
<g clipPath={`url(#${accessibilityId}-clip)`}>
|
||||
<rect
|
||||
x={14}
|
||||
y={14}
|
||||
width={96}
|
||||
height={96}
|
||||
fill={`url(#${accessibilityId}-pattern)`}
|
||||
/>
|
||||
<rect
|
||||
x={14}
|
||||
y={14}
|
||||
width={96}
|
||||
height={96}
|
||||
fill='var(--player-background-color'
|
||||
opacity={0.45}
|
||||
/>
|
||||
</g>
|
||||
|
||||
<defs>
|
||||
<pattern
|
||||
id={`${accessibilityId}-pattern`}
|
||||
patternContentUnits='objectBoundingBox'
|
||||
width='1'
|
||||
height='1'
|
||||
>
|
||||
<use href={`#${accessibilityId}-image`} />
|
||||
</pattern>
|
||||
|
||||
<clipPath id={`${accessibilityId}-clip`}>
|
||||
<rect x={14} y={14} width={96} height={96} rx={48} fill='white' />
|
||||
</clipPath>
|
||||
|
||||
<image
|
||||
id={`${accessibilityId}-image`}
|
||||
href={poster}
|
||||
width={1}
|
||||
height={1}
|
||||
preserveAspectRatio='none'
|
||||
/>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
|
@ -10,7 +10,8 @@ import { connect } from 'react-redux';
|
|||
import PeopleIcon from '@/material-icons/400-24px/group.svg?react';
|
||||
import { DismissableBanner } from 'mastodon/components/dismissable_banner';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { domain } from 'mastodon/initial_state';
|
||||
import { domain, localLiveFeedAccess } from 'mastodon/initial_state';
|
||||
import { canViewFeed } from 'mastodon/permissions';
|
||||
|
||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||
import { connectCommunityStream } from '../../actions/streaming';
|
||||
|
|
@ -120,8 +121,21 @@ class CommunityTimeline extends PureComponent {
|
|||
|
||||
render () {
|
||||
const { intl, hasUnread, columnId, multiColumn, onlyMedia } = this.props;
|
||||
const { signedIn, permissions } = this.props.identity;
|
||||
const pinned = !!columnId;
|
||||
|
||||
const emptyMessage = canViewFeed(signedIn, permissions, localLiveFeedAccess) ? (
|
||||
<FormattedMessage
|
||||
id='empty_column.community'
|
||||
defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!'
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id='empty_column.disabled_feed'
|
||||
defaultMessage='This feed has been disabled by your server administrators.'
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
||||
<ColumnHeader
|
||||
|
|
@ -144,7 +158,7 @@ class CommunityTimeline extends PureComponent {
|
|||
scrollKey={`community_timeline-${columnId}`}
|
||||
timelineId={`community${onlyMedia ? ':media' : ''}`}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='empty_column.community' defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' />}
|
||||
emptyMessage={emptyMessage}
|
||||
bindToDocument={!multiColumn}
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -123,11 +123,10 @@ class ComposeForm extends ImmutablePureComponent {
|
|||
};
|
||||
|
||||
canSubmit = () => {
|
||||
const { isSubmitting, isChangingUpload, isUploading, anyMedia, maxChars } = this.props;
|
||||
const { isSubmitting, isChangingUpload, isUploading, maxChars } = this.props;
|
||||
const fulltext = this.getFulltextForCharacterCounting();
|
||||
const isOnlyWhitespace = fulltext.length !== 0 && fulltext.trim().length === 0;
|
||||
|
||||
return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > maxChars || (isOnlyWhitespace && !anyMedia));
|
||||
return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > maxChars);
|
||||
};
|
||||
|
||||
handleSubmit = (e) => {
|
||||
|
|
@ -141,7 +140,10 @@ class ComposeForm extends ImmutablePureComponent {
|
|||
return;
|
||||
}
|
||||
|
||||
this.props.onSubmit(missingAltTextModal && this.props.missingAltText && this.props.privacy !== 'direct');
|
||||
this.props.onSubmit({
|
||||
missingAltText: missingAltTextModal && this.props.missingAltText && this.props.privacy !== 'direct',
|
||||
quoteToPrivate: this.props.quoteToPrivate,
|
||||
});
|
||||
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
import { useCallback } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { cancelPasteLinkCompose } from '@/mastodon/actions/compose_typed';
|
||||
import { useAppDispatch } from '@/mastodon/store';
|
||||
import CancelFillIcon from '@/material-icons/400-24px/cancel-fill.svg?react';
|
||||
import { DisplayName } from 'mastodon/components/display_name';
|
||||
import { IconButton } from 'mastodon/components/icon_button';
|
||||
import { Skeleton } from 'mastodon/components/skeleton';
|
||||
|
||||
const messages = defineMessages({
|
||||
quote_cancel: { id: 'status.quote.cancel', defaultMessage: 'Cancel quote' },
|
||||
});
|
||||
|
||||
export const QuotePlaceholder: FC = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const handleQuoteCancel = useCallback(() => {
|
||||
dispatch(cancelPasteLinkCompose());
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<div className='status__quote'>
|
||||
<div className='status'>
|
||||
<div className='status__info'>
|
||||
<div className='status__avatar'>
|
||||
<Skeleton width='32px' height='32px' />
|
||||
</div>
|
||||
<div className='status__display-name'>
|
||||
<DisplayName />
|
||||
</div>
|
||||
<IconButton
|
||||
onClick={handleQuoteCancel}
|
||||
className='status__quote-cancel'
|
||||
title={intl.formatMessage(messages.quote_cancel)}
|
||||
icon='cancel-fill'
|
||||
iconComponent={CancelFillIcon}
|
||||
/>
|
||||
</div>
|
||||
<div className='status__content'>
|
||||
<Skeleton />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -7,11 +7,17 @@ import { quoteComposeCancel } from '@/mastodon/actions/compose_typed';
|
|||
import { QuotedStatus } from '@/mastodon/components/status_quoted';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { QuotePlaceholder } from './quote_placeholder';
|
||||
|
||||
export const ComposeQuotedStatus: FC = () => {
|
||||
const quotedStatusId = useAppSelector(
|
||||
(state) => state.compose.get('quoted_status_id') as string | null,
|
||||
);
|
||||
|
||||
const isFetchingLink = useAppSelector(
|
||||
(state) => !!state.compose.get('fetching_link'),
|
||||
);
|
||||
|
||||
const isEditing = useAppSelector((state) => !!state.compose.get('id'));
|
||||
|
||||
const quote = useMemo(
|
||||
|
|
@ -30,7 +36,9 @@ export const ComposeQuotedStatus: FC = () => {
|
|||
dispatch(quoteComposeCancel());
|
||||
}, [dispatch]);
|
||||
|
||||
if (!quote) {
|
||||
if (isFetchingLink && !quote) {
|
||||
return <QuotePlaceholder />;
|
||||
} else if (!quote) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { useSortable } from '@dnd-kit/sortable';
|
|||
import { CSS } from '@dnd-kit/utilities';
|
||||
|
||||
import CloseIcon from '@/material-icons/400-20px/close.svg?react';
|
||||
import SoundIcon from '@/material-icons/400-24px/audio.svg?react';
|
||||
import EditIcon from '@/material-icons/400-24px/edit.svg?react';
|
||||
import WarningIcon from '@/material-icons/400-24px/warning.svg?react';
|
||||
import { undoUploadCompose } from 'mastodon/actions/compose';
|
||||
|
|
@ -17,7 +18,18 @@ import { openModal } from 'mastodon/actions/modal';
|
|||
import { Blurhash } from 'mastodon/components/blurhash';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import type { MediaAttachment } from 'mastodon/models/media_attachment';
|
||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||
import {
|
||||
createAppSelector,
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
} from 'mastodon/store';
|
||||
|
||||
import { AudioVisualizer } from '../../audio/visualizer';
|
||||
|
||||
const selectUserAvatar = createAppSelector(
|
||||
[(state) => state.accounts, (state) => state.meta.get('me') as string],
|
||||
(accounts, myId) => accounts.get(myId)?.avatar_static,
|
||||
);
|
||||
|
||||
export const Upload: React.FC<{
|
||||
id: string;
|
||||
|
|
@ -38,6 +50,7 @@ export const Upload: React.FC<{
|
|||
const sensitive = useAppSelector(
|
||||
(state) => state.compose.get('spoiler') as boolean,
|
||||
);
|
||||
const userAvatar = useAppSelector(selectUserAvatar);
|
||||
|
||||
const handleUndoClick = useCallback(() => {
|
||||
dispatch(undoUploadCompose(id));
|
||||
|
|
@ -67,6 +80,8 @@ export const Upload: React.FC<{
|
|||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
};
|
||||
const preview_url = media.get('preview_url') as string | null;
|
||||
const blurhash = media.get('blurhash') as string | null;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -85,17 +100,19 @@ export const Upload: React.FC<{
|
|||
<div
|
||||
className='compose-form__upload__thumbnail'
|
||||
style={{
|
||||
backgroundImage: !sensitive
|
||||
? `url(${media.get('preview_url') as string})`
|
||||
: undefined,
|
||||
backgroundImage:
|
||||
!sensitive && preview_url ? `url(${preview_url})` : undefined,
|
||||
backgroundPosition: `${x}% ${y}%`,
|
||||
}}
|
||||
>
|
||||
{sensitive && (
|
||||
<Blurhash
|
||||
hash={media.get('blurhash') as string}
|
||||
className='compose-form__upload__preview'
|
||||
/>
|
||||
{sensitive && blurhash && (
|
||||
<Blurhash hash={blurhash} className='compose-form__upload__preview' />
|
||||
)}
|
||||
{!sensitive && !preview_url && (
|
||||
<div className='compose-form__upload__visualizer'>
|
||||
<AudioVisualizer poster={userAvatar} />
|
||||
<Icon id='sound' icon={SoundIcon} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className='compose-form__upload__actions'>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ import { defineMessages, useIntl } from 'react-intl';
|
|||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { changeComposeVisibility } from '@/mastodon/actions/compose';
|
||||
import { setComposeQuotePolicy } from '@/mastodon/actions/compose_typed';
|
||||
import {
|
||||
changeComposeVisibility,
|
||||
setComposeQuotePolicy,
|
||||
} from '@/mastodon/actions/compose_typed';
|
||||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import type { ApiQuotePolicy } from '@/mastodon/api_types/quotes';
|
||||
import type { StatusVisibility } from '@/mastodon/api_types/statuses';
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from 'mastodon/actions/compose';
|
||||
import { pasteLinkCompose } from 'mastodon/actions/compose_typed';
|
||||
import { openModal } from 'mastodon/actions/modal';
|
||||
import { PRIVATE_QUOTE_MODAL_ID } from 'mastodon/features/ui/components/confirmation_modals/private_quote_notify';
|
||||
|
||||
import ComposeForm from '../components/compose_form';
|
||||
|
||||
|
|
@ -32,6 +33,10 @@ const mapStateToProps = state => ({
|
|||
isUploading: state.getIn(['compose', 'is_uploading']),
|
||||
anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
|
||||
missingAltText: state.getIn(['compose', 'media_attachments']).some(media => ['image', 'gifv'].includes(media.get('type')) && (media.get('description') ?? '').length === 0),
|
||||
quoteToPrivate:
|
||||
!!state.getIn(['compose', 'quoted_status_id'])
|
||||
&& state.getIn(['compose', 'privacy']) === 'private'
|
||||
&& !state.getIn(['settings', 'dismissed_banners', PRIVATE_QUOTE_MODAL_ID]),
|
||||
isInReply: state.getIn(['compose', 'in_reply_to']) !== null,
|
||||
lang: state.getIn(['compose', 'language']),
|
||||
maxChars: state.getIn(['server', 'server', 'configuration', 'statuses', 'max_characters'], 640),
|
||||
|
|
@ -43,12 +48,17 @@ const mapDispatchToProps = (dispatch, props) => ({
|
|||
dispatch(changeCompose(text));
|
||||
},
|
||||
|
||||
onSubmit (missingAltText) {
|
||||
onSubmit ({ missingAltText, quoteToPrivate }) {
|
||||
if (missingAltText) {
|
||||
dispatch(openModal({
|
||||
modalType: 'CONFIRM_MISSING_ALT_TEXT',
|
||||
modalProps: {},
|
||||
}));
|
||||
} else if (quoteToPrivate) {
|
||||
dispatch(openModal({
|
||||
modalType: 'CONFIRM_PRIVATE_QUOTE_NOTIFY',
|
||||
modalProps: {},
|
||||
}));
|
||||
} else {
|
||||
dispatch(submitCompose((status) => {
|
||||
if (props.redirectOnSuccess) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
|
||||
import { changeComposeVisibility } from '../../../actions/compose';
|
||||
import { openModal, closeModal } from '../../../actions/modal';
|
||||
import { isUserTouching } from '../../../is_mobile';
|
||||
import { changeComposeVisibility } from '@/mastodon/actions/compose_typed';
|
||||
|
||||
import PrivacyDropdown from '../components/privacy_dropdown';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import Trie from 'substring-trie';
|
||||
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
import { assetHost } from 'mastodon/utils/config';
|
||||
|
||||
import { autoPlayGif } from '../../initial_state';
|
||||
|
|
@ -153,13 +152,9 @@ const emojifyNode = (node, customEmojis) => {
|
|||
* Legacy emoji processing function.
|
||||
* @param {string} str
|
||||
* @param {object} customEmojis
|
||||
* @param {boolean} force If true, always emojify even if modern emoji is enabled
|
||||
* @returns {string}
|
||||
*/
|
||||
const emojify = (str, customEmojis = {}, force = false) => {
|
||||
if (isModernEmojiEnabled() && !force) {
|
||||
return str;
|
||||
}
|
||||
const emojify = (str, customEmojis = {}) => {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.innerHTML = str;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@ import { uncompress as emojiMartUncompress } from 'emoji-mart/dist/utils/data';
|
|||
|
||||
import data from './emoji_data.json';
|
||||
import emojiMap from './emoji_map.json';
|
||||
import { unicodeToFilename } from './unicode_to_filename';
|
||||
import { unicodeToUnifiedName } from './unicode_to_unified_name';
|
||||
import { unicodeToFilename, unicodeToUnifiedName } from './unicode_utils';
|
||||
|
||||
emojiMartUncompress(data);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import type {
|
|||
ShortCodesToEmojiData,
|
||||
} from 'virtual:mastodon-emoji-compressed';
|
||||
|
||||
import { unicodeToUnifiedName } from './unicode_to_unified_name';
|
||||
import { unicodeToUnifiedName } from './unicode_utils';
|
||||
|
||||
type Emojis = Record<
|
||||
NonNullable<keyof ShortCodesToEmojiData>,
|
||||
|
|
@ -23,7 +23,7 @@ type Emojis = Record<
|
|||
|
||||
const [
|
||||
shortCodesToEmojiData,
|
||||
skins,
|
||||
_skins,
|
||||
categories,
|
||||
short_names,
|
||||
_emojisWithoutShortCodes,
|
||||
|
|
@ -47,4 +47,4 @@ Object.keys(shortCodesToEmojiData).forEach((shortCode) => {
|
|||
};
|
||||
});
|
||||
|
||||
export { emojis, skins, categories, short_names };
|
||||
export { emojis, categories, short_names };
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// This code is largely borrowed from:
|
||||
// https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/emoji-index.js
|
||||
|
||||
import * as data from './emoji_mart_data_light';
|
||||
import { emojis, categories } from './emoji_mart_data_light';
|
||||
import { getData, getSanitizedData, uniq, intersect } from './emoji_utils';
|
||||
|
||||
let originalPool = {};
|
||||
|
|
@ -10,8 +10,8 @@ let emojisList = {};
|
|||
let emoticonsList = {};
|
||||
let customEmojisList = [];
|
||||
|
||||
for (let emoji in data.emojis) {
|
||||
let emojiData = data.emojis[emoji];
|
||||
for (let emoji in emojis) {
|
||||
let emojiData = emojis[emoji];
|
||||
let { short_names, emoticons } = emojiData;
|
||||
let id = short_names[0];
|
||||
|
||||
|
|
@ -84,14 +84,14 @@ function search(value, { emojisToShowFilter, maxResults, include, exclude, custo
|
|||
if (include.length || exclude.length) {
|
||||
pool = {};
|
||||
|
||||
data.categories.forEach(category => {
|
||||
categories.forEach(category => {
|
||||
let isIncluded = include && include.length ? include.indexOf(category.name.toLowerCase()) > -1 : true;
|
||||
let isExcluded = exclude && exclude.length ? exclude.indexOf(category.name.toLowerCase()) > -1 : false;
|
||||
if (!isIncluded || isExcluded) {
|
||||
return;
|
||||
}
|
||||
|
||||
category.emojis.forEach(emojiId => pool[emojiId] = data.emojis[emojiId]);
|
||||
category.emojis.forEach(emojiId => pool[emojiId] = emojis[emojiId]);
|
||||
});
|
||||
|
||||
if (custom.length) {
|
||||
|
|
@ -171,7 +171,7 @@ function search(value, { emojisToShowFilter, maxResults, include, exclude, custo
|
|||
|
||||
if (results) {
|
||||
if (emojisToShowFilter) {
|
||||
results = results.filter((result) => emojisToShowFilter(data.emojis[result.id]));
|
||||
results = results.filter((result) => emojisToShowFilter(emojis[result.id]));
|
||||
}
|
||||
|
||||
if (results && results.length > maxResults) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import type { EmojiProps, PickerProps } from 'emoji-mart';
|
|||
import EmojiRaw from 'emoji-mart/dist-es/components/emoji/nimble-emoji';
|
||||
import PickerRaw from 'emoji-mart/dist-es/components/picker/nimble-picker';
|
||||
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
import { assetHost } from 'mastodon/utils/config';
|
||||
|
||||
import { EMOJI_MODE_NATIVE } from './constants';
|
||||
|
|
@ -27,7 +26,7 @@ const Emoji = ({
|
|||
sheetSize={sheetSize}
|
||||
sheetColumns={sheetColumns}
|
||||
sheetRows={sheetRows}
|
||||
native={mode === EMOJI_MODE_NATIVE && isModernEmojiEnabled()}
|
||||
native={mode === EMOJI_MODE_NATIVE}
|
||||
backgroundImageFn={backgroundImageFn}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -51,7 +50,7 @@ const Picker = ({
|
|||
sheetColumns={sheetColumns}
|
||||
sheetRows={sheetRows}
|
||||
backgroundImageFn={backgroundImageFn}
|
||||
native={mode === EMOJI_MODE_NATIVE && isModernEmojiEnabled()}
|
||||
native={mode === EMOJI_MODE_NATIVE}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import type {
|
|||
ShortCodesToEmojiDataKey,
|
||||
} from 'virtual:mastodon-emoji-compressed';
|
||||
|
||||
import { unicodeToFilename } from './unicode_to_filename';
|
||||
import { unicodeToFilename } from './unicode_utils';
|
||||
|
||||
type UnicodeMapping = Record<
|
||||
FilenameData[number][0],
|
||||
|
|
|
|||
|
|
@ -209,50 +209,9 @@ function intersect(a, b) {
|
|||
return uniqA.filter(item => uniqB.indexOf(item) >= 0);
|
||||
}
|
||||
|
||||
function deepMerge(a, b) {
|
||||
let o = {};
|
||||
|
||||
for (let key in a) {
|
||||
let originalValue = a[key],
|
||||
value = originalValue;
|
||||
|
||||
if (Object.hasOwn(b, key)) {
|
||||
value = b[key];
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
value = deepMerge(originalValue, value);
|
||||
}
|
||||
|
||||
o[key] = value;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
// https://github.com/sonicdoe/measure-scrollbar
|
||||
function measureScrollbar() {
|
||||
const div = document.createElement('div');
|
||||
|
||||
div.style.width = '100px';
|
||||
div.style.height = '100px';
|
||||
div.style.overflow = 'scroll';
|
||||
div.style.position = 'absolute';
|
||||
div.style.top = '-9999px';
|
||||
|
||||
document.body.appendChild(div);
|
||||
const scrollbarWidth = div.offsetWidth - div.clientWidth;
|
||||
document.body.removeChild(div);
|
||||
|
||||
return scrollbarWidth;
|
||||
}
|
||||
|
||||
export {
|
||||
getData,
|
||||
getSanitizedData,
|
||||
uniq,
|
||||
intersect,
|
||||
deepMerge,
|
||||
unifiedToNative,
|
||||
measureScrollbar,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
import { autoPlayGif } from '@/mastodon/initial_state';
|
||||
|
||||
const PARENT_MAX_DEPTH = 10;
|
||||
|
||||
export function handleAnimateGif(event: MouseEvent) {
|
||||
// We already check this in ui/index.jsx, but just to be sure.
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { target, type } = event;
|
||||
const animate = type === 'mouseover'; // Mouse over = animate, mouse out = don't animate.
|
||||
|
||||
if (target instanceof HTMLImageElement) {
|
||||
setAnimateGif(target, animate);
|
||||
} else if (!(target instanceof HTMLElement) || target === document.body) {
|
||||
return;
|
||||
}
|
||||
|
||||
let parent: HTMLElement | null = null;
|
||||
let iter = 0;
|
||||
|
||||
if (target.classList.contains('animate-parent')) {
|
||||
parent = target;
|
||||
} else {
|
||||
// Iterate up to PARENT_MAX_DEPTH levels up the DOM tree to find a parent with the class 'animate-parent'.
|
||||
let current: HTMLElement | null = target;
|
||||
while (current) {
|
||||
if (iter >= PARENT_MAX_DEPTH) {
|
||||
return; // We can just exit right now.
|
||||
}
|
||||
current = current.parentElement;
|
||||
if (current?.classList.contains('animate-parent')) {
|
||||
parent = current;
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
// Affect all animated children within the parent.
|
||||
if (parent) {
|
||||
const animatedChildren =
|
||||
parent.querySelectorAll<HTMLImageElement>('img.custom-emoji');
|
||||
for (const child of animatedChildren) {
|
||||
setAnimateGif(child, animate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setAnimateGif(image: HTMLImageElement, animate: boolean) {
|
||||
const { classList, dataset } = image;
|
||||
if (
|
||||
!classList.contains('custom-emoji') ||
|
||||
!dataset.static ||
|
||||
!dataset.original
|
||||
) {
|
||||
return;
|
||||
}
|
||||
image.src = animate ? dataset.original : dataset.static;
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
import { initialState } from '@/mastodon/initial_state';
|
||||
import { loadWorker } from '@/mastodon/utils/workers';
|
||||
|
||||
import { toSupportedLocale } from './locale';
|
||||
import { emojiLogger } from './utils';
|
||||
// eslint-disable-next-line import/default -- Importing via worker loader.
|
||||
import EmojiWorker from './worker?worker&inline';
|
||||
|
||||
const userLocale = toSupportedLocale(initialState?.meta.locale ?? 'en');
|
||||
|
||||
|
|
@ -16,9 +17,7 @@ export function initializeEmoji() {
|
|||
log('initializing emojis');
|
||||
if (!worker && 'Worker' in window) {
|
||||
try {
|
||||
worker = loadWorker(new URL('./worker', import.meta.url), {
|
||||
type: 'module',
|
||||
});
|
||||
worker = new EmojiWorker();
|
||||
} catch (err) {
|
||||
console.warn('Error creating web worker:', err);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
// taken from:
|
||||
// https://github.com/twitter/twemoji/blob/47732c7/twemoji-generator.js#L848-L866
|
||||
export const unicodeToFilename = (str) => {
|
||||
let result = '';
|
||||
let charCode = 0;
|
||||
let p = 0;
|
||||
let i = 0;
|
||||
while (i < str.length) {
|
||||
charCode = str.charCodeAt(i++);
|
||||
if (p) {
|
||||
if (result.length > 0) {
|
||||
result += '-';
|
||||
}
|
||||
result += (0x10000 + ((p - 0xD800) << 10) + (charCode - 0xDC00)).toString(16);
|
||||
p = 0;
|
||||
} else if (0xD800 <= charCode && charCode <= 0xDBFF) {
|
||||
p = charCode;
|
||||
} else {
|
||||
if (result.length > 0) {
|
||||
result += '-';
|
||||
}
|
||||
result += charCode.toString(16);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
function padLeft(str, num) {
|
||||
while (str.length < num) {
|
||||
str = '0' + str;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
export const unicodeToUnifiedName = (str) => {
|
||||
let output = '';
|
||||
|
||||
for (let i = 0; i < str.length; i += 2) {
|
||||
if (i > 0) {
|
||||
output += '-';
|
||||
}
|
||||
|
||||
output += padLeft(str.codePointAt(i).toString(16).toUpperCase(), 4);
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
43
app/javascript/mastodon/features/emoji/unicode_utils.ts
Normal file
43
app/javascript/mastodon/features/emoji/unicode_utils.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// taken from:
|
||||
// https://github.com/twitter/twemoji/blob/47732c7/twemoji-generator.js#L848-L866
|
||||
export function unicodeToFilename(str: string) {
|
||||
let result = '';
|
||||
let charCode = 0;
|
||||
let p = 0;
|
||||
let i = 0;
|
||||
while (i < str.length) {
|
||||
charCode = str.charCodeAt(i++);
|
||||
if (p) {
|
||||
if (result.length > 0) {
|
||||
result += '-';
|
||||
}
|
||||
result += (0x10000 + ((p - 0xd800) << 10) + (charCode - 0xdc00)).toString(
|
||||
16,
|
||||
);
|
||||
p = 0;
|
||||
} else if (0xd800 <= charCode && charCode <= 0xdbff) {
|
||||
p = charCode;
|
||||
} else {
|
||||
if (result.length > 0) {
|
||||
result += '-';
|
||||
}
|
||||
result += charCode.toString(16);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function unicodeToUnifiedName(str: string) {
|
||||
let output = '';
|
||||
|
||||
for (let i = 0; i < str.length; i += 2) {
|
||||
if (i > 0) {
|
||||
output += '-';
|
||||
}
|
||||
|
||||
output +=
|
||||
str.codePointAt(i)?.toString(16).toUpperCase().padStart(4, '0') ?? '';
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
|
@ -13,7 +13,8 @@ import { changeSetting } from 'mastodon/actions/settings';
|
|||
import { connectPublicStream, connectCommunityStream } from 'mastodon/actions/streaming';
|
||||
import { expandPublicTimeline, expandCommunityTimeline } from 'mastodon/actions/timelines';
|
||||
import { DismissableBanner } from 'mastodon/components/dismissable_banner';
|
||||
import { localLiveFeedAccess, remoteLiveFeedAccess, me, domain } from 'mastodon/initial_state';
|
||||
import { localLiveFeedAccess, remoteLiveFeedAccess, domain } from 'mastodon/initial_state';
|
||||
import { canViewFeed } from 'mastodon/permissions';
|
||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||
|
||||
import Column from '../../components/column';
|
||||
|
|
@ -23,6 +24,14 @@ import StatusListContainer from '../ui/containers/status_list_container';
|
|||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'column.firehose', defaultMessage: 'Live feeds' },
|
||||
title_local: {
|
||||
id: 'column.firehose_local',
|
||||
defaultMessage: 'Live feed for this server',
|
||||
},
|
||||
title_singular: {
|
||||
id: 'column.firehose_singular',
|
||||
defaultMessage: 'Live feed',
|
||||
},
|
||||
});
|
||||
|
||||
const ColumnSettings = () => {
|
||||
|
|
@ -52,7 +61,7 @@ const ColumnSettings = () => {
|
|||
const Firehose = ({ feedType, multiColumn }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
const { signedIn } = useIdentity();
|
||||
const { signedIn, permissions } = useIdentity();
|
||||
const columnRef = useRef(null);
|
||||
|
||||
const onlyMedia = useAppSelector((state) => state.getIn(['settings', 'firehose', 'onlyMedia'], false));
|
||||
|
|
@ -151,13 +160,32 @@ const Firehose = ({ feedType, multiColumn }) => {
|
|||
/>
|
||||
);
|
||||
|
||||
const canViewSelectedFeed = canViewFeed(signedIn, permissions, feedType === 'community' ? localLiveFeedAccess : remoteLiveFeedAccess);
|
||||
|
||||
const disabledTimelineMessage = (
|
||||
<FormattedMessage
|
||||
id='empty_column.disabled_feed'
|
||||
defaultMessage='This feed has been disabled by your server administrators.'
|
||||
/>
|
||||
);
|
||||
|
||||
let title;
|
||||
|
||||
if (canViewFeed(signedIn, permissions, localLiveFeedAccess) && canViewFeed(signedIn, permissions, remoteLiveFeedAccess)) {
|
||||
title = messages.title;
|
||||
} else if (canViewFeed(signedIn, permissions, localLiveFeedAccess)) {
|
||||
title = messages.title_local;
|
||||
} else {
|
||||
title = messages.title_singular;
|
||||
}
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn} ref={columnRef} label={intl.formatMessage(messages.title)}>
|
||||
<ColumnHeader
|
||||
icon='globe'
|
||||
iconComponent={PublicIcon}
|
||||
active={hasUnread}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
title={intl.formatMessage(title)}
|
||||
onPin={handlePin}
|
||||
onClick={handleHeaderClick}
|
||||
multiColumn={multiColumn}
|
||||
|
|
@ -165,7 +193,7 @@ const Firehose = ({ feedType, multiColumn }) => {
|
|||
<ColumnSettings />
|
||||
</ColumnHeader>
|
||||
|
||||
{(signedIn || (localLiveFeedAccess === 'public' && remoteLiveFeedAccess === 'public')) && (
|
||||
{(canViewFeed(signedIn, permissions, localLiveFeedAccess) && canViewFeed(signedIn, permissions, remoteLiveFeedAccess)) && (
|
||||
<div className='account__section-headline'>
|
||||
<NavLink exact to='/public/local'>
|
||||
<FormattedMessage tagName='div' id='firehose.local' defaultMessage='This server' />
|
||||
|
|
@ -187,7 +215,7 @@ const Firehose = ({ feedType, multiColumn }) => {
|
|||
onLoadMore={handleLoadMore}
|
||||
trackScroll
|
||||
scrollKey='firehose'
|
||||
emptyMessage={emptyMessage}
|
||||
emptyMessage={canViewSelectedFeed ? emptyMessage : disabledTimelineMessage}
|
||||
bindToDocument={!multiColumn}
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,458 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import { PureComponent, useCallback, useMemo } from 'react';
|
||||
|
||||
import { defineMessages, injectIntl, FormattedMessage, FormattedDate } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
import { animated, useTransition } from '@react-spring/web';
|
||||
import ReactSwipeableViews from 'react-swipeable-views';
|
||||
|
||||
import elephantUIPlane from '@/images/elephant_ui_plane.svg';
|
||||
import AddIcon from '@/material-icons/400-24px/add.svg?react';
|
||||
import ChevronLeftIcon from '@/material-icons/400-24px/chevron_left.svg?react';
|
||||
import ChevronRightIcon from '@/material-icons/400-24px/chevron_right.svg?react';
|
||||
import { AnimatedNumber } from 'mastodon/components/animated_number';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { IconButton } from 'mastodon/components/icon_button';
|
||||
import EmojiPickerDropdown from 'mastodon/features/compose/containers/emoji_picker_dropdown_container';
|
||||
import { unicodeMapping } from 'mastodon/features/emoji/emoji_unicode_mapping_light';
|
||||
import { autoPlayGif, reduceMotion, disableSwiping, mascot } from 'mastodon/initial_state';
|
||||
import { assetHost } from 'mastodon/utils/config';
|
||||
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||
|
||||
const messages = defineMessages({
|
||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
|
||||
next: { id: 'lightbox.next', defaultMessage: 'Next' },
|
||||
});
|
||||
|
||||
class ContentWithRouter extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
announcement: ImmutablePropTypes.map.isRequired,
|
||||
...WithRouterPropTypes,
|
||||
};
|
||||
|
||||
setRef = c => {
|
||||
this.node = c;
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
this._updateLinks();
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
this._updateLinks();
|
||||
}
|
||||
|
||||
_updateLinks () {
|
||||
const node = this.node;
|
||||
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
const links = node.querySelectorAll('a');
|
||||
|
||||
for (var i = 0; i < links.length; ++i) {
|
||||
let link = links[i];
|
||||
|
||||
if (link.classList.contains('status-link')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
link.classList.add('status-link');
|
||||
|
||||
let mention = this.props.announcement.get('mentions').find(item => link.href === item.get('url'));
|
||||
|
||||
if (mention) {
|
||||
link.addEventListener('click', this.onMentionClick.bind(this, mention), false);
|
||||
link.setAttribute('title', mention.get('acct'));
|
||||
} else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) {
|
||||
link.addEventListener('click', this.onHashtagClick.bind(this, link.text), false);
|
||||
} else {
|
||||
let status = this.props.announcement.get('statuses').find(item => link.href === item.get('url'));
|
||||
if (status) {
|
||||
link.addEventListener('click', this.onStatusClick.bind(this, status), false);
|
||||
}
|
||||
link.setAttribute('title', link.href);
|
||||
link.classList.add('unhandled-link');
|
||||
}
|
||||
|
||||
link.setAttribute('target', '_blank');
|
||||
link.setAttribute('rel', 'noopener');
|
||||
}
|
||||
}
|
||||
|
||||
onMentionClick = (mention, e) => {
|
||||
if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.props.history.push(`/@${mention.get('acct')}`);
|
||||
}
|
||||
};
|
||||
|
||||
onHashtagClick = (hashtag, e) => {
|
||||
hashtag = hashtag.replace(/^#/, '');
|
||||
|
||||
if (this.props.history&& e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.props.history.push(`/tags/${hashtag}`);
|
||||
}
|
||||
};
|
||||
|
||||
onStatusClick = (status, e) => {
|
||||
if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.props.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const { announcement } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className='announcements__item__content translate animate-parent'
|
||||
ref={this.setRef}
|
||||
dangerouslySetInnerHTML={{ __html: announcement.get('contentHtml') }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const Content = withRouter(ContentWithRouter);
|
||||
|
||||
class Emoji extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
emoji: PropTypes.string.isRequired,
|
||||
emojiMap: ImmutablePropTypes.map.isRequired,
|
||||
hovered: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
render () {
|
||||
const { emoji, emojiMap, hovered } = this.props;
|
||||
|
||||
if (unicodeMapping[emoji]) {
|
||||
const { filename, shortCode } = unicodeMapping[this.props.emoji];
|
||||
const title = shortCode ? `:${shortCode}:` : '';
|
||||
|
||||
return (
|
||||
<img
|
||||
draggable='false'
|
||||
className='emojione'
|
||||
alt={emoji}
|
||||
title={title}
|
||||
src={`${assetHost}/emoji/${filename}.svg`}
|
||||
/>
|
||||
);
|
||||
} else if (emojiMap.get(emoji)) {
|
||||
const filename = (autoPlayGif || hovered) ? emojiMap.getIn([emoji, 'url']) : emojiMap.getIn([emoji, 'static_url']);
|
||||
const shortCode = `:${emoji}:`;
|
||||
|
||||
return (
|
||||
<img
|
||||
draggable='false'
|
||||
className='emojione custom-emoji'
|
||||
alt={shortCode}
|
||||
title={shortCode}
|
||||
src={filename}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Reaction extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
announcementId: PropTypes.string.isRequired,
|
||||
reaction: ImmutablePropTypes.map.isRequired,
|
||||
addReaction: PropTypes.func.isRequired,
|
||||
removeReaction: PropTypes.func.isRequired,
|
||||
emojiMap: ImmutablePropTypes.map.isRequired,
|
||||
style: PropTypes.object,
|
||||
};
|
||||
|
||||
state = {
|
||||
hovered: false,
|
||||
};
|
||||
|
||||
handleClick = () => {
|
||||
const { reaction, announcementId, addReaction, removeReaction } = this.props;
|
||||
|
||||
if (reaction.get('me')) {
|
||||
removeReaction(announcementId, reaction.get('name'));
|
||||
} else {
|
||||
addReaction(announcementId, reaction.get('name'));
|
||||
}
|
||||
};
|
||||
|
||||
handleMouseEnter = () => this.setState({ hovered: true });
|
||||
|
||||
handleMouseLeave = () => this.setState({ hovered: false });
|
||||
|
||||
render () {
|
||||
const { reaction } = this.props;
|
||||
|
||||
let shortCode = reaction.get('name');
|
||||
|
||||
if (unicodeMapping[shortCode]) {
|
||||
shortCode = unicodeMapping[shortCode].shortCode;
|
||||
}
|
||||
|
||||
return (
|
||||
<animated.button
|
||||
className={classNames('reactions-bar__item', { active: reaction.get('me') })}
|
||||
onClick={this.handleClick}
|
||||
title={`:${shortCode}:`}
|
||||
style={this.props.style}
|
||||
// This does not use animate-parent as this component is directly rendered by React.
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
>
|
||||
<span className='reactions-bar__item__emoji'>
|
||||
<Emoji hovered={this.state.hovered} emoji={reaction.get('name')} emojiMap={this.props.emojiMap} />
|
||||
</span>
|
||||
<span className='reactions-bar__item__count'>
|
||||
<AnimatedNumber value={reaction.get('count')} />
|
||||
</span>
|
||||
</animated.button>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const ReactionsBar = ({
|
||||
announcementId,
|
||||
reactions,
|
||||
emojiMap,
|
||||
addReaction,
|
||||
removeReaction,
|
||||
}) => {
|
||||
const visibleReactions = useMemo(() => reactions.filter(x => x.get('count') > 0).toArray(), [reactions]);
|
||||
|
||||
const handleEmojiPick = useCallback((emoji) => {
|
||||
addReaction(announcementId, emoji.native.replaceAll(/:/g, ''));
|
||||
}, [addReaction, announcementId]);
|
||||
|
||||
const transitions = useTransition(visibleReactions, {
|
||||
from: {
|
||||
scale: 0,
|
||||
},
|
||||
enter: {
|
||||
scale: 1,
|
||||
},
|
||||
leave: {
|
||||
scale: 0,
|
||||
},
|
||||
keys: visibleReactions.map(x => x.get('name')),
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames('reactions-bar', {
|
||||
'reactions-bar--empty': visibleReactions.length === 0
|
||||
})}
|
||||
>
|
||||
{transitions(({ scale }, reaction) => (
|
||||
<Reaction
|
||||
key={reaction.get('name')}
|
||||
reaction={reaction}
|
||||
style={{ transform: scale.to((s) => `scale(${s})`) }}
|
||||
addReaction={addReaction}
|
||||
removeReaction={removeReaction}
|
||||
announcementId={announcementId}
|
||||
emojiMap={emojiMap}
|
||||
/>
|
||||
))}
|
||||
|
||||
{visibleReactions.length < 8 && (
|
||||
<EmojiPickerDropdown
|
||||
onPickEmoji={handleEmojiPick}
|
||||
button={<Icon id='plus' icon={AddIcon} />}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
ReactionsBar.propTypes = {
|
||||
announcementId: PropTypes.string.isRequired,
|
||||
reactions: ImmutablePropTypes.list.isRequired,
|
||||
addReaction: PropTypes.func.isRequired,
|
||||
removeReaction: PropTypes.func.isRequired,
|
||||
emojiMap: ImmutablePropTypes.map.isRequired,
|
||||
};
|
||||
|
||||
class Announcement extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
announcement: ImmutablePropTypes.map.isRequired,
|
||||
emojiMap: ImmutablePropTypes.map.isRequired,
|
||||
addReaction: PropTypes.func.isRequired,
|
||||
removeReaction: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
selected: PropTypes.bool,
|
||||
};
|
||||
|
||||
state = {
|
||||
unread: !this.props.announcement.get('read'),
|
||||
};
|
||||
|
||||
componentDidUpdate () {
|
||||
const { selected, announcement } = this.props;
|
||||
if (!selected && this.state.unread !== !announcement.get('read')) {
|
||||
this.setState({ unread: !announcement.get('read') });
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { announcement } = this.props;
|
||||
const { unread } = this.state;
|
||||
const startsAt = announcement.get('starts_at') && new Date(announcement.get('starts_at'));
|
||||
const endsAt = announcement.get('ends_at') && new Date(announcement.get('ends_at'));
|
||||
const now = new Date();
|
||||
const hasTimeRange = startsAt && endsAt;
|
||||
const skipTime = announcement.get('all_day');
|
||||
|
||||
let timestamp = null;
|
||||
if (hasTimeRange) {
|
||||
const skipYear = startsAt.getFullYear() === endsAt.getFullYear() && endsAt.getFullYear() === now.getFullYear();
|
||||
const skipEndDate = startsAt.getDate() === endsAt.getDate() && startsAt.getMonth() === endsAt.getMonth() && startsAt.getFullYear() === endsAt.getFullYear();
|
||||
timestamp = (
|
||||
<>
|
||||
<FormattedDate value={startsAt} year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /> - <FormattedDate value={endsAt} year={(skipYear || endsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month={skipEndDate ? undefined : 'short'} day={skipEndDate ? undefined : '2-digit'} hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} />
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
const publishedAt = new Date(announcement.get('published_at'));
|
||||
timestamp = (
|
||||
<FormattedDate value={publishedAt} year={publishedAt.getFullYear() === now.getFullYear() ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='announcements__item'>
|
||||
<strong className='announcements__item__range'>
|
||||
<FormattedMessage id='announcement.announcement' defaultMessage='Announcement' />
|
||||
<span> · {timestamp}</span>
|
||||
</strong>
|
||||
|
||||
<Content announcement={announcement} />
|
||||
|
||||
<ReactionsBar
|
||||
reactions={announcement.get('reactions')}
|
||||
announcementId={announcement.get('id')}
|
||||
addReaction={this.props.addReaction}
|
||||
removeReaction={this.props.removeReaction}
|
||||
emojiMap={this.props.emojiMap}
|
||||
/>
|
||||
|
||||
{unread && <span className='announcements__item__unread' />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Announcements extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
announcements: ImmutablePropTypes.list,
|
||||
emojiMap: ImmutablePropTypes.map.isRequired,
|
||||
dismissAnnouncement: PropTypes.func.isRequired,
|
||||
addReaction: PropTypes.func.isRequired,
|
||||
removeReaction: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
index: 0,
|
||||
};
|
||||
|
||||
static getDerivedStateFromProps(props, state) {
|
||||
if (props.announcements.size > 0 && state.index >= props.announcements.size) {
|
||||
return { index: props.announcements.size - 1 };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this._markAnnouncementAsRead();
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
this._markAnnouncementAsRead();
|
||||
}
|
||||
|
||||
_markAnnouncementAsRead () {
|
||||
const { dismissAnnouncement, announcements } = this.props;
|
||||
const { index } = this.state;
|
||||
const announcement = announcements.get(announcements.size - 1 - index);
|
||||
if (!announcement.get('read')) dismissAnnouncement(announcement.get('id'));
|
||||
}
|
||||
|
||||
handleChangeIndex = index => {
|
||||
this.setState({ index: index % this.props.announcements.size });
|
||||
};
|
||||
|
||||
handleNextClick = () => {
|
||||
this.setState({ index: (this.state.index + 1) % this.props.announcements.size });
|
||||
};
|
||||
|
||||
handlePrevClick = () => {
|
||||
this.setState({ index: (this.props.announcements.size + this.state.index - 1) % this.props.announcements.size });
|
||||
};
|
||||
|
||||
render () {
|
||||
const { announcements, intl } = this.props;
|
||||
const { index } = this.state;
|
||||
|
||||
if (announcements.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='announcements'>
|
||||
<img className='announcements__mastodon' alt='' draggable='false' src={mascot || elephantUIPlane} />
|
||||
|
||||
<div className='announcements__container'>
|
||||
<ReactSwipeableViews animateHeight animateTransitions={!reduceMotion} index={index} onChangeIndex={this.handleChangeIndex}>
|
||||
{announcements.map((announcement, idx) => (
|
||||
<Announcement
|
||||
key={announcement.get('id')}
|
||||
announcement={announcement}
|
||||
emojiMap={this.props.emojiMap}
|
||||
addReaction={this.props.addReaction}
|
||||
removeReaction={this.props.removeReaction}
|
||||
intl={intl}
|
||||
selected={index === idx}
|
||||
disabled={disableSwiping}
|
||||
/>
|
||||
)).reverse()}
|
||||
</ReactSwipeableViews>
|
||||
|
||||
{announcements.size > 1 && (
|
||||
<div className='announcements__pagination'>
|
||||
<IconButton disabled={announcements.size === 1} title={intl.formatMessage(messages.previous)} icon='chevron-left' iconComponent={ChevronLeftIcon} onClick={this.handlePrevClick} size={13} />
|
||||
<span>{index + 1} / {announcements.size}</span>
|
||||
<IconButton disabled={announcements.size === 1} title={intl.formatMessage(messages.next)} icon='chevron-right' iconComponent={ChevronRightIcon} onClick={this.handleNextClick} size={13} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default injectIntl(Announcements);
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
|
||||
import { addReaction, removeReaction, dismissAnnouncement } from 'mastodon/actions/announcements';
|
||||
|
||||
import Announcements from '../components/announcements';
|
||||
|
||||
const customEmojiMap = createSelector([state => state.get('custom_emojis')], items => items.reduce((map, emoji) => map.set(emoji.get('shortcode'), emoji), ImmutableMap()));
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
announcements: state.getIn(['announcements', 'items']),
|
||||
emojiMap: customEmojiMap(state),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
dismissAnnouncement: id => dispatch(dismissAnnouncement(id)),
|
||||
addReaction: (id, name) => dispatch(addReaction(id, name)),
|
||||
removeReaction: (id, name) => dispatch(removeReaction(id, name)),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Announcements);
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import type { FC } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { FormattedDate, FormattedMessage } from 'react-intl';
|
||||
|
||||
import { dismissAnnouncement } from '@/mastodon/actions/announcements';
|
||||
import type { ApiAnnouncementJSON } from '@/mastodon/api_types/announcements';
|
||||
import { AnimateEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
import { EmojiHTML } from '@/mastodon/components/emoji/html';
|
||||
import { useAppDispatch } from '@/mastodon/store';
|
||||
|
||||
import { ReactionsBar } from './reactions';
|
||||
|
||||
|
|
@ -22,13 +24,23 @@ export const Announcement: FC<AnnouncementProps> = ({
|
|||
announcement,
|
||||
selected,
|
||||
}) => {
|
||||
const [unread, setUnread] = useState(!announcement.read);
|
||||
const { read, id } = announcement;
|
||||
|
||||
// Dismiss announcement when it becomes active.
|
||||
const dispatch = useAppDispatch();
|
||||
useEffect(() => {
|
||||
// Only update `unread` marker once the announcement is out of view
|
||||
if (!selected && unread !== !announcement.read) {
|
||||
setUnread(!announcement.read);
|
||||
if (selected && !read) {
|
||||
dispatch(dismissAnnouncement(id));
|
||||
}
|
||||
}, [announcement.read, selected, unread]);
|
||||
}, [selected, id, dispatch, read]);
|
||||
|
||||
// But visually show the announcement as read only when it goes out of view.
|
||||
const [unread, setUnread] = useState(!read);
|
||||
useEffect(() => {
|
||||
if (!selected && unread !== !read) {
|
||||
setUnread(!read);
|
||||
}
|
||||
}, [selected, unread, read]);
|
||||
|
||||
return (
|
||||
<AnimateEmojiProvider className='announcements__item'>
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@ import ReactSwipeableViews from 'react-swipeable-views';
|
|||
import elephantUIPlane from '@/images/elephant_ui_plane.svg';
|
||||
import { CustomEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
import { IconButton } from '@/mastodon/components/icon_button';
|
||||
import LegacyAnnouncements from '@/mastodon/features/getting_started/containers/announcements_container';
|
||||
import { mascot, reduceMotion } from '@/mastodon/initial_state';
|
||||
import { createAppSelector, useAppSelector } from '@/mastodon/store';
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
import ChevronLeftIcon from '@/material-icons/400-24px/chevron_left.svg?react';
|
||||
import ChevronRightIcon from '@/material-icons/400-24px/chevron_right.svg?react';
|
||||
|
||||
|
|
@ -32,7 +30,7 @@ const announcementSelector = createAppSelector(
|
|||
(announcements.get('items')?.toJS() as IAnnouncement[] | undefined) ?? [],
|
||||
);
|
||||
|
||||
export const ModernAnnouncements: FC = () => {
|
||||
export const Announcements: FC = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
const announcements = useAppSelector(announcementSelector);
|
||||
|
|
@ -112,7 +110,3 @@ export const ModernAnnouncements: FC = () => {
|
|||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Announcements = isModernEmojiEnabled()
|
||||
? ModernAnnouncements
|
||||
: LegacyAnnouncements;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import {
|
|||
me,
|
||||
} from 'mastodon/initial_state';
|
||||
import { transientSingleColumn } from 'mastodon/is_mobile';
|
||||
import { canViewFeed } from 'mastodon/permissions';
|
||||
import { selectUnreadNotificationGroupsCount } from 'mastodon/selectors/notifications';
|
||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||
|
||||
|
|
@ -60,6 +61,10 @@ const messages = defineMessages({
|
|||
},
|
||||
explore: { id: 'explore.title', defaultMessage: 'Trending' },
|
||||
firehose: { id: 'column.firehose', defaultMessage: 'Live feeds' },
|
||||
firehose_singular: {
|
||||
id: 'column.firehose_singular',
|
||||
defaultMessage: 'Live feed',
|
||||
},
|
||||
direct: { id: 'navigation_bar.direct', defaultMessage: 'Private mentions' },
|
||||
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favorites' },
|
||||
bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' },
|
||||
|
|
@ -194,7 +199,7 @@ export const NavigationPanel: React.FC<{ multiColumn?: boolean }> = ({
|
|||
multiColumn = false,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const { signedIn, disabledAccountId } = useIdentity();
|
||||
const { signedIn, permissions, disabledAccountId } = useIdentity();
|
||||
const location = useLocation();
|
||||
const showSearch = useBreakpoint('full') && !multiColumn;
|
||||
|
||||
|
|
@ -262,20 +267,24 @@ export const NavigationPanel: React.FC<{ multiColumn?: boolean }> = ({
|
|||
/>
|
||||
)}
|
||||
|
||||
{(signedIn ||
|
||||
localLiveFeedAccess === 'public' ||
|
||||
remoteLiveFeedAccess === 'public') && (
|
||||
{(canViewFeed(signedIn, permissions, localLiveFeedAccess) ||
|
||||
canViewFeed(signedIn, permissions, remoteLiveFeedAccess)) && (
|
||||
<ColumnLink
|
||||
transparent
|
||||
to={
|
||||
signedIn || localLiveFeedAccess === 'public'
|
||||
canViewFeed(signedIn, permissions, localLiveFeedAccess)
|
||||
? '/public/local'
|
||||
: '/public/remote'
|
||||
}
|
||||
icon='globe'
|
||||
iconComponent={PublicIcon}
|
||||
isActive={isFirehoseActive}
|
||||
text={intl.formatMessage(messages.firehose)}
|
||||
text={intl.formatMessage(
|
||||
canViewFeed(signedIn, permissions, localLiveFeedAccess) &&
|
||||
canViewFeed(signedIn, permissions, remoteLiveFeedAccess)
|
||||
? messages.firehose
|
||||
: messages.firehose_singular,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,47 +1,17 @@
|
|||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import type { List } from 'immutable';
|
||||
|
||||
import type { History } from 'history';
|
||||
|
||||
import type { ApiMentionJSON } from '@/mastodon/api_types/statuses';
|
||||
import { EmojiHTML } from '@/mastodon/components/emoji/html';
|
||||
import { useElementHandledLink } from '@/mastodon/components/status/handled_link';
|
||||
import type { Status } from '@/mastodon/models/status';
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
import type { Mention } from './embedded_status';
|
||||
|
||||
const handleMentionClick = (
|
||||
history: History,
|
||||
mention: ApiMentionJSON,
|
||||
e: MouseEvent,
|
||||
) => {
|
||||
if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
history.push(`/@${mention.acct}`);
|
||||
}
|
||||
};
|
||||
|
||||
const handleHashtagClick = (
|
||||
history: History,
|
||||
hashtag: string,
|
||||
e: MouseEvent,
|
||||
) => {
|
||||
if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
history.push(`/tags/${hashtag.replace(/^#/, '')}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const EmbeddedStatusContent: React.FC<{
|
||||
status: Status;
|
||||
className?: string;
|
||||
}> = ({ status, className }) => {
|
||||
const history = useHistory();
|
||||
|
||||
const mentions = useMemo(
|
||||
() => (status.get('mentions') as List<Mention>).toJS(),
|
||||
[status],
|
||||
|
|
@ -57,55 +27,10 @@ export const EmbeddedStatusContent: React.FC<{
|
|||
hrefToMention,
|
||||
});
|
||||
|
||||
const handleContentRef = useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
if (!node || isModernEmojiEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const links = node.querySelectorAll<HTMLAnchorElement>('a');
|
||||
|
||||
for (const link of links) {
|
||||
if (link.classList.contains('status-link')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
link.classList.add('status-link');
|
||||
|
||||
const mention = mentions.find((item) => link.href === item.url);
|
||||
|
||||
if (mention) {
|
||||
link.addEventListener(
|
||||
'click',
|
||||
handleMentionClick.bind(null, history, mention),
|
||||
false,
|
||||
);
|
||||
link.setAttribute('title', `@${mention.acct}`);
|
||||
link.setAttribute('href', `/@${mention.acct}`);
|
||||
} else if (
|
||||
link.textContent.startsWith('#') ||
|
||||
link.previousSibling?.textContent?.endsWith('#')
|
||||
) {
|
||||
link.addEventListener(
|
||||
'click',
|
||||
handleHashtagClick.bind(null, history, link.text),
|
||||
false,
|
||||
);
|
||||
link.setAttribute('href', `/tags/${link.text.replace(/^#/, '')}`);
|
||||
} else {
|
||||
link.setAttribute('title', link.href);
|
||||
link.classList.add('unhandled-link');
|
||||
}
|
||||
}
|
||||
},
|
||||
[mentions, history],
|
||||
);
|
||||
|
||||
return (
|
||||
<EmojiHTML
|
||||
{...htmlHandlers}
|
||||
className={className}
|
||||
ref={handleContentRef}
|
||||
lang={status.get('language') as string}
|
||||
htmlString={status.get('contentHtml') as string}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ import { connect } from 'react-redux';
|
|||
import PublicIcon from '@/material-icons/400-24px/public.svg?react';
|
||||
import { DismissableBanner } from 'mastodon/components/dismissable_banner';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { domain } from 'mastodon/initial_state';
|
||||
import { domain, localLiveFeedAccess, remoteLiveFeedAccess } from 'mastodon/initial_state';
|
||||
import { canViewFeed } from 'mastodon/permissions';
|
||||
|
||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||
import { connectPublicStream } from '../../actions/streaming';
|
||||
|
|
@ -123,8 +124,21 @@ class PublicTimeline extends PureComponent {
|
|||
|
||||
render () {
|
||||
const { intl, columnId, hasUnread, multiColumn, onlyMedia, onlyRemote } = this.props;
|
||||
const { signedIn, permissions } = this.props.identity;
|
||||
const pinned = !!columnId;
|
||||
|
||||
const emptyMessage = (canViewFeed(signedIn, permissions, localLiveFeedAccess) || canViewFeed(signedIn, permissions, remoteLiveFeedAccess)) ? (
|
||||
<FormattedMessage
|
||||
id='empty_column.public'
|
||||
defaultMessage='There is nothing here! Write something publicly, or manually follow users from other servers to fill it up'
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id='empty_column.disabled_feed'
|
||||
defaultMessage='This feed has been disabled by your server administrators.'
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
||||
<ColumnHeader
|
||||
|
|
@ -147,7 +161,7 @@ class PublicTimeline extends PureComponent {
|
|||
onLoadMore={this.handleLoadMore}
|
||||
trackScroll={!pinned}
|
||||
scrollKey={`public_timeline-${columnId}`}
|
||||
emptyMessage={<FormattedMessage id='empty_column.public' defaultMessage='There is nothing here! Write something publicly, or manually follow users from other servers to fill it up' />}
|
||||
emptyMessage={emptyMessage}
|
||||
bindToDocument={!multiColumn}
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import { useEffect, useState, useCallback } from 'react';
|
||||
import { useEffect, useState, useCallback, useMemo } from 'react';
|
||||
|
||||
import { useIntl, defineMessages } from 'react-intl';
|
||||
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
|
||||
import {
|
||||
fetchContext,
|
||||
completeContextRefresh,
|
||||
|
|
@ -13,6 +15,8 @@ import { apiGetAsyncRefresh } from 'mastodon/api/async_refreshes';
|
|||
import { Alert } from 'mastodon/components/alert';
|
||||
import { ExitAnimationWrapper } from 'mastodon/components/exit_animation_wrapper';
|
||||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||
import { useInterval } from 'mastodon/hooks/useInterval';
|
||||
import { useIsDocumentVisible } from 'mastodon/hooks/useIsDocumentVisible';
|
||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||
|
||||
const AnimatedAlert: React.FC<
|
||||
|
|
@ -52,14 +56,151 @@ const messages = defineMessages({
|
|||
|
||||
type LoadingState = 'idle' | 'more-available' | 'loading' | 'success' | 'error';
|
||||
|
||||
/**
|
||||
* Age of thread below which we consider it new & fetch
|
||||
* replies more frequently
|
||||
*/
|
||||
const NEW_THREAD_AGE_THRESHOLD = 30 * 60_000;
|
||||
/**
|
||||
* Interval at which we check for new replies for old threads
|
||||
*/
|
||||
const LONG_AUTO_FETCH_REPLIES_INTERVAL = 5 * 60_000;
|
||||
/**
|
||||
* Interval at which we check for new replies for new threads.
|
||||
* Also used as a threshold to throttle repeated fetch calls
|
||||
*/
|
||||
const SHORT_AUTO_FETCH_REPLIES_INTERVAL = 60_000;
|
||||
/**
|
||||
* Number of refresh_async checks at which an early fetch
|
||||
* will be triggered if there are results
|
||||
*/
|
||||
const LONG_RUNNING_FETCH_THRESHOLD = 3;
|
||||
|
||||
/**
|
||||
* Returns whether the thread is new, based on NEW_THREAD_AGE_THRESHOLD
|
||||
*/
|
||||
function getIsThreadNew(statusCreatedAt: string) {
|
||||
const now = new Date();
|
||||
const newThreadThreshold = new Date(now.getTime() - NEW_THREAD_AGE_THRESHOLD);
|
||||
|
||||
return new Date(statusCreatedAt) > newThreadThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* This hook kicks off a background check for the async refresh job
|
||||
* and loads any newly found replies once the job has finished,
|
||||
* and when LONG_RUNNING_FETCH_THRESHOLD was reached and replies were found
|
||||
*/
|
||||
function useCheckForRemoteReplies({
|
||||
statusId,
|
||||
refreshHeader,
|
||||
isEnabled,
|
||||
onChangeLoadingState,
|
||||
}: {
|
||||
statusId: string;
|
||||
refreshHeader?: AsyncRefreshHeader;
|
||||
isEnabled: boolean;
|
||||
onChangeLoadingState: React.Dispatch<React.SetStateAction<LoadingState>>;
|
||||
}) {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
let timeoutId: ReturnType<typeof setTimeout>;
|
||||
|
||||
const scheduleRefresh = (
|
||||
refresh: AsyncRefreshHeader,
|
||||
iteration: number,
|
||||
) => {
|
||||
timeoutId = setTimeout(() => {
|
||||
void apiGetAsyncRefresh(refresh.id).then((result) => {
|
||||
const { status, result_count } = result.async_refresh;
|
||||
|
||||
// At three scheduled refreshes, we consider the job
|
||||
// long-running and attempt to fetch any new replies so far
|
||||
const isLongRunning = iteration === LONG_RUNNING_FETCH_THRESHOLD;
|
||||
|
||||
// If the refresh status is not finished and not long-running,
|
||||
// we just schedule another refresh and exit
|
||||
if (status === 'running' && !isLongRunning) {
|
||||
scheduleRefresh(refresh, iteration + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// If refresh status is finished, clear `refreshHeader`
|
||||
// (we don't want to do this if it's just a long-running job)
|
||||
if (status === 'finished') {
|
||||
dispatch(completeContextRefresh({ statusId }));
|
||||
}
|
||||
|
||||
// Exit if there's nothing to fetch
|
||||
if (result_count === 0) {
|
||||
if (status === 'finished') {
|
||||
onChangeLoadingState('idle');
|
||||
} else {
|
||||
scheduleRefresh(refresh, iteration + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// A positive result count means there _might_ be new replies,
|
||||
// so we fetch the context in the background to check if there
|
||||
// are any new replies.
|
||||
// If so, they will populate `contexts.pendingReplies[statusId]`
|
||||
void dispatch(fetchContext({ statusId, prefetchOnly: true }))
|
||||
.then(() => {
|
||||
// Reset loading state to `idle`. If the fetch has
|
||||
// resulted in new pending replies, the `hasPendingReplies`
|
||||
// flag will switch the loading state to 'more-available'
|
||||
if (status === 'finished') {
|
||||
onChangeLoadingState('idle');
|
||||
} else {
|
||||
// Keep background fetch going if `isLongRunning` is true
|
||||
scheduleRefresh(refresh, iteration + 1);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// Show an error if the fetch failed
|
||||
onChangeLoadingState('error');
|
||||
});
|
||||
});
|
||||
}, refresh.retry * 1000);
|
||||
};
|
||||
|
||||
// Initialise a refresh
|
||||
if (refreshHeader && isEnabled) {
|
||||
scheduleRefresh(refreshHeader, 1);
|
||||
onChangeLoadingState('loading');
|
||||
}
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeoutId);
|
||||
};
|
||||
}, [onChangeLoadingState, dispatch, statusId, refreshHeader, isEnabled]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This component fetches new post replies in the background
|
||||
* and gives users the option to show them.
|
||||
*
|
||||
* The following three scenarios are handled:
|
||||
*
|
||||
* 1. When the browser tab is visible, replies are refetched periodically
|
||||
* (more frequently for new posts, less frequently for old ones)
|
||||
* 2. Replies are refetched when the browser tab is refocused
|
||||
* after it was hidden or minimised
|
||||
* 3. For remote posts, remote replies that might not yet be known to the
|
||||
* server are imported & fetched using the AsyncRefresh API.
|
||||
*/
|
||||
export const RefreshController: React.FC<{
|
||||
statusId: string;
|
||||
}> = ({ statusId }) => {
|
||||
statusCreatedAt: string;
|
||||
isLocal: boolean;
|
||||
}> = ({ statusId, statusCreatedAt, isLocal }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
|
||||
const refreshHeader = useAppSelector(
|
||||
(state) => state.contexts.refreshing[statusId],
|
||||
const refreshHeader = useAppSelector((state) =>
|
||||
isLocal ? undefined : state.contexts.refreshing[statusId],
|
||||
);
|
||||
const hasPendingReplies = useAppSelector(
|
||||
(state) => !!state.contexts.pendingReplies[statusId]?.length,
|
||||
|
|
@ -78,78 +219,52 @@ export const RefreshController: React.FC<{
|
|||
dispatch(clearPendingReplies({ statusId }));
|
||||
}, [dispatch, statusId]);
|
||||
|
||||
useEffect(() => {
|
||||
let timeoutId: ReturnType<typeof setTimeout>;
|
||||
// Prevent too-frequent context calls
|
||||
const debouncedFetchContext = useDebouncedCallback(
|
||||
() => {
|
||||
void dispatch(fetchContext({ statusId, prefetchOnly: true }));
|
||||
},
|
||||
// Ensure the debounce is a bit shorter than the auto-fetch interval
|
||||
SHORT_AUTO_FETCH_REPLIES_INTERVAL - 500,
|
||||
{
|
||||
leading: true,
|
||||
trailing: false,
|
||||
},
|
||||
);
|
||||
|
||||
const scheduleRefresh = (
|
||||
refresh: AsyncRefreshHeader,
|
||||
iteration: number,
|
||||
) => {
|
||||
timeoutId = setTimeout(() => {
|
||||
void apiGetAsyncRefresh(refresh.id).then((result) => {
|
||||
// At three scheduled refreshes, we consider the job
|
||||
// long-running and attempt to fetch any new replies so far
|
||||
const isLongRunning = iteration === 3;
|
||||
const isDocumentVisible = useIsDocumentVisible({
|
||||
onChange: (isVisible) => {
|
||||
// Auto-fetch new replies when the page is refocused
|
||||
if (isVisible && partialLoadingState !== 'loading' && !wasDismissed) {
|
||||
debouncedFetchContext();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const { status, result_count } = result.async_refresh;
|
||||
// Check for remote replies
|
||||
useCheckForRemoteReplies({
|
||||
statusId,
|
||||
refreshHeader,
|
||||
isEnabled: isDocumentVisible && !isLocal && !wasDismissed,
|
||||
onChangeLoadingState: setLoadingState,
|
||||
});
|
||||
|
||||
// If the refresh status is not finished and not long-running,
|
||||
// we just schedule another refresh and exit
|
||||
if (status === 'running' && !isLongRunning) {
|
||||
scheduleRefresh(refresh, iteration + 1);
|
||||
return;
|
||||
}
|
||||
// Only auto-fetch new replies if there's no ongoing remote replies check
|
||||
const shouldAutoFetchReplies =
|
||||
isDocumentVisible && partialLoadingState !== 'loading' && !wasDismissed;
|
||||
|
||||
// If refresh status is finished, clear `refreshHeader`
|
||||
// (we don't want to do this if it's just a long-running job)
|
||||
if (status === 'finished') {
|
||||
dispatch(completeContextRefresh({ statusId }));
|
||||
}
|
||||
const autoFetchInterval = useMemo(
|
||||
() =>
|
||||
getIsThreadNew(statusCreatedAt)
|
||||
? SHORT_AUTO_FETCH_REPLIES_INTERVAL
|
||||
: LONG_AUTO_FETCH_REPLIES_INTERVAL,
|
||||
[statusCreatedAt],
|
||||
);
|
||||
|
||||
// Exit if there's nothing to fetch
|
||||
if (result_count === 0) {
|
||||
if (status === 'finished') {
|
||||
setLoadingState('idle');
|
||||
} else {
|
||||
scheduleRefresh(refresh, iteration + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// A positive result count means there _might_ be new replies,
|
||||
// so we fetch the context in the background to check if there
|
||||
// are any new replies.
|
||||
// If so, they will populate `contexts.pendingReplies[statusId]`
|
||||
void dispatch(fetchContext({ statusId, prefetchOnly: true }))
|
||||
.then(() => {
|
||||
// Reset loading state to `idle`. If the fetch has
|
||||
// resulted in new pending replies, the `hasPendingReplies`
|
||||
// flag will switch the loading state to 'more-available'
|
||||
if (status === 'finished') {
|
||||
setLoadingState('idle');
|
||||
} else {
|
||||
// Keep background fetch going if `isLongRunning` is true
|
||||
scheduleRefresh(refresh, iteration + 1);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// Show an error if the fetch failed
|
||||
setLoadingState('error');
|
||||
});
|
||||
});
|
||||
}, refresh.retry * 1000);
|
||||
};
|
||||
|
||||
// Initialise a refresh
|
||||
if (refreshHeader && !wasDismissed) {
|
||||
scheduleRefresh(refreshHeader, 1);
|
||||
setLoadingState('loading');
|
||||
}
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeoutId);
|
||||
};
|
||||
}, [dispatch, statusId, refreshHeader, wasDismissed]);
|
||||
useInterval(debouncedFetchContext, {
|
||||
delay: autoFetchInterval,
|
||||
isEnabled: shouldAutoFetchReplies,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Hide success message after a short delay
|
||||
|
|
@ -172,7 +287,7 @@ export const RefreshController: React.FC<{
|
|||
};
|
||||
}, [dispatch, statusId]);
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
const showPending = useCallback(() => {
|
||||
dispatch(showPendingReplies({ statusId }));
|
||||
setLoadingState('success');
|
||||
}, [dispatch, statusId]);
|
||||
|
|
@ -196,7 +311,7 @@ export const RefreshController: React.FC<{
|
|||
isActive={loadingState === 'more-available'}
|
||||
message={intl.formatMessage(messages.moreFound)}
|
||||
action={intl.formatMessage(messages.show)}
|
||||
onActionClick={handleClick}
|
||||
onActionClick={showPending}
|
||||
onDismiss={dismissPrompt}
|
||||
animateFrom='below'
|
||||
/>
|
||||
|
|
@ -205,7 +320,7 @@ export const RefreshController: React.FC<{
|
|||
isActive={loadingState === 'error'}
|
||||
message={intl.formatMessage(messages.error)}
|
||||
action={intl.formatMessage(messages.retry)}
|
||||
onActionClick={handleClick}
|
||||
onActionClick={showPending}
|
||||
onDismiss={dismissPrompt}
|
||||
animateFrom='below'
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -299,6 +299,12 @@ class Status extends ImmutablePureComponent {
|
|||
dispatch(openModal({ modalType: 'COMPOSE_PRIVACY', modalProps: { statusId, onChange: handleChange } }));
|
||||
};
|
||||
|
||||
handleQuote = (status) => {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
dispatch(quoteComposeById(status.get('id')));
|
||||
};
|
||||
|
||||
handleEditClick = (status) => {
|
||||
const { dispatch, askReplyConfirmation } = this.props;
|
||||
|
||||
|
|
@ -504,12 +510,14 @@ class Status extends ImmutablePureComponent {
|
|||
componentDidUpdate (prevProps) {
|
||||
const { status, ancestorsIds, descendantsIds } = this.props;
|
||||
|
||||
if (status && (ancestorsIds.length > prevProps.ancestorsIds.length || prevProps.status?.get('id') !== status.get('id'))) {
|
||||
const isSameStatus = status && (prevProps.status?.get('id') === status.get('id'));
|
||||
|
||||
if (status && (ancestorsIds.length > prevProps.ancestorsIds.length || !isSameStatus)) {
|
||||
this._scrollStatusIntoView();
|
||||
}
|
||||
|
||||
// Only highlight replies after the initial load
|
||||
if (prevProps.descendantsIds.length) {
|
||||
if (prevProps.descendantsIds.length && isSameStatus) {
|
||||
const newRepliesIds = difference(descendantsIds, prevProps.descendantsIds);
|
||||
|
||||
if (newRepliesIds.length) {
|
||||
|
|
@ -571,14 +579,6 @@ class Status extends ImmutablePureComponent {
|
|||
const isLocal = status.getIn(['account', 'acct'], '').indexOf('@') === -1;
|
||||
const isIndexable = !status.getIn(['account', 'noindex']);
|
||||
|
||||
if (!isLocal) {
|
||||
remoteHint = (
|
||||
<RefreshController
|
||||
statusId={status.get('id')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const handlers = {
|
||||
reply: this.handleHotkeyReply,
|
||||
favourite: this.handleHotkeyFavourite,
|
||||
|
|
@ -631,6 +631,7 @@ class Status extends ImmutablePureComponent {
|
|||
onDelete={this.handleDeleteClick}
|
||||
onRevokeQuote={this.handleRevokeQuoteClick}
|
||||
onQuotePolicyChange={this.handleQuotePolicyChange}
|
||||
onQuote={this.handleQuote}
|
||||
onEdit={this.handleEditClick}
|
||||
onDirect={this.handleDirectClick}
|
||||
onMention={this.handleMentionClick}
|
||||
|
|
@ -649,7 +650,12 @@ class Status extends ImmutablePureComponent {
|
|||
</Hotkeys>
|
||||
|
||||
{descendants}
|
||||
{remoteHint}
|
||||
|
||||
<RefreshController
|
||||
isLocal={isLocal}
|
||||
statusId={status.get('id')}
|
||||
statusCreatedAt={status.get('created_at')}
|
||||
/>
|
||||
</div>
|
||||
</ScrollContainer>
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import { IconButton } from 'mastodon/components/icon_button';
|
|||
import InlineAccount from 'mastodon/components/inline_account';
|
||||
import MediaAttachments from 'mastodon/components/media_attachments';
|
||||
import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
|
||||
import emojify from 'mastodon/features/emoji/emoji';
|
||||
import { EmojiHTML } from '@/mastodon/components/emoji/html';
|
||||
import { CustomEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
|
||||
|
|
@ -48,13 +47,8 @@ class CompareHistoryModal extends PureComponent {
|
|||
const { index, versions, language, onClose } = this.props;
|
||||
const currentVersion = versions.get(index);
|
||||
|
||||
const emojiMap = currentVersion.get('emojis').reduce((obj, emoji) => {
|
||||
obj[`:${emoji.get('shortcode')}:`] = emoji.toJS();
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
const content = emojify(currentVersion.get('content'), emojiMap);
|
||||
const spoilerContent = emojify(escapeTextContentForBrowser(currentVersion.get('spoiler_text')), emojiMap);
|
||||
const content = currentVersion.get('content');
|
||||
const spoilerContent = escapeTextContentForBrowser(currentVersion.get('spoiler_text'));
|
||||
|
||||
const formattedDate = <RelativeTimestamp timestamp={currentVersion.get('created_at')} short={false} />;
|
||||
const formattedName = <InlineAccount accountId={currentVersion.get('account')} />;
|
||||
|
|
@ -99,7 +93,7 @@ class CompareHistoryModal extends PureComponent {
|
|||
<EmojiHTML
|
||||
as="span"
|
||||
className='poll__option__text translate'
|
||||
htmlString={emojify(escapeTextContentForBrowser(option.get('title')), emojiMap)}
|
||||
htmlString={escapeTextContentForBrowser(option.get('title'))}
|
||||
lang={language}
|
||||
/>
|
||||
</label>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export const ConfirmationModal: React.FC<
|
|||
onSecondary?: () => void;
|
||||
onConfirm: () => void;
|
||||
closeWhenConfirm?: boolean;
|
||||
extraContent?: React.ReactNode;
|
||||
} & BaseConfirmationModalProps
|
||||
> = ({
|
||||
title,
|
||||
|
|
@ -29,6 +30,7 @@ export const ConfirmationModal: React.FC<
|
|||
secondary,
|
||||
onSecondary,
|
||||
closeWhenConfirm = true,
|
||||
extraContent,
|
||||
}) => {
|
||||
const handleClick = useCallback(() => {
|
||||
if (closeWhenConfirm) {
|
||||
|
|
@ -49,6 +51,8 @@ export const ConfirmationModal: React.FC<
|
|||
<div className='safety-action-modal__confirmation'>
|
||||
<h1>{title}</h1>
|
||||
{message && <p>{message}</p>}
|
||||
|
||||
{extraContent}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
import { forwardRef, useCallback, useState } from 'react';
|
||||
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import { submitCompose } from '@/mastodon/actions/compose';
|
||||
import { changeSetting } from '@/mastodon/actions/settings';
|
||||
import { CheckBox } from '@/mastodon/components/check_box';
|
||||
import { useAppDispatch } from '@/mastodon/store';
|
||||
|
||||
import { ConfirmationModal } from './confirmation_modal';
|
||||
import type { BaseConfirmationModalProps } from './confirmation_modal';
|
||||
import classes from './styles.module.css';
|
||||
|
||||
export const PRIVATE_QUOTE_MODAL_ID = 'quote/private_notify';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: {
|
||||
id: 'confirmations.private_quote_notify.title',
|
||||
defaultMessage: 'Share with followers and mentioned users?',
|
||||
},
|
||||
message: {
|
||||
id: 'confirmations.private_quote_notify.message',
|
||||
defaultMessage:
|
||||
'The person you are quoting and other mentions ' +
|
||||
"will be notified and will be able to view your post, even if they're not following you.",
|
||||
},
|
||||
confirm: {
|
||||
id: 'confirmations.private_quote_notify.confirm',
|
||||
defaultMessage: 'Publish post',
|
||||
},
|
||||
cancel: {
|
||||
id: 'confirmations.private_quote_notify.cancel',
|
||||
defaultMessage: 'Back to editing',
|
||||
},
|
||||
});
|
||||
|
||||
export const PrivateQuoteNotify = forwardRef<
|
||||
HTMLDivElement,
|
||||
BaseConfirmationModalProps
|
||||
>(
|
||||
(
|
||||
{ onClose },
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
_ref,
|
||||
) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const [dismiss, setDismissed] = useState(false);
|
||||
const handleDismissToggle = useCallback(() => {
|
||||
setDismissed((prev) => !prev);
|
||||
}, []);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const handleConfirm = useCallback(() => {
|
||||
dispatch(submitCompose());
|
||||
if (dismiss) {
|
||||
dispatch(
|
||||
changeSetting(['dismissed_banners', PRIVATE_QUOTE_MODAL_ID], true),
|
||||
);
|
||||
}
|
||||
}, [dismiss, dispatch]);
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
title={intl.formatMessage(messages.title)}
|
||||
message={intl.formatMessage(messages.message)}
|
||||
confirm={intl.formatMessage(messages.confirm)}
|
||||
cancel={intl.formatMessage(messages.cancel)}
|
||||
onConfirm={handleConfirm}
|
||||
onClose={onClose}
|
||||
extraContent={
|
||||
<label className={classes.checkbox_wrapper}>
|
||||
<CheckBox
|
||||
value='hide'
|
||||
checked={dismiss}
|
||||
onChange={handleDismissToggle}
|
||||
/>{' '}
|
||||
<FormattedMessage
|
||||
id='confirmations.private_quote_notify.do_not_show_again'
|
||||
defaultMessage="Don't show me this message again"
|
||||
/>
|
||||
</label>
|
||||
}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
PrivateQuoteNotify.displayName = 'PrivateQuoteNotify';
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
.checkbox_wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin: 1rem 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -47,6 +47,7 @@ import MediaModal from './media_modal';
|
|||
import { ModalPlaceholder } from './modal_placeholder';
|
||||
import VideoModal from './video_modal';
|
||||
import { VisibilityModal } from './visibility_modal';
|
||||
import { PrivateQuoteNotify } from './confirmation_modals/private_quote_notify';
|
||||
|
||||
export const MODAL_COMPONENTS = {
|
||||
'MEDIA': () => Promise.resolve({ default: MediaModal }),
|
||||
|
|
@ -66,6 +67,7 @@ export const MODAL_COMPONENTS = {
|
|||
'CONFIRM_LOG_OUT': () => Promise.resolve({ default: ConfirmLogOutModal }),
|
||||
'CONFIRM_FOLLOW_TO_LIST': () => Promise.resolve({ default: ConfirmFollowToListModal }),
|
||||
'CONFIRM_MISSING_ALT_TEXT': () => Promise.resolve({ default: ConfirmMissingAltTextModal }),
|
||||
'CONFIRM_PRIVATE_QUOTE_NOTIFY': () => Promise.resolve({ default: PrivateQuoteNotify }),
|
||||
'CONFIRM_REVOKE_QUOTE': () => Promise.resolve({ default: ConfirmRevokeQuoteModal }),
|
||||
'CONFIRM_QUIET_QUOTE': () => Promise.resolve({ default: QuietPostQuoteInfoModal }),
|
||||
'MUTE': MuteModal,
|
||||
|
|
|
|||
|
|
@ -128,9 +128,12 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
|
|||
const disableVisibility = !!statusId;
|
||||
const disableQuotePolicy =
|
||||
visibility === 'private' || visibility === 'direct';
|
||||
const disablePublicVisibilities: boolean = useAppSelector(
|
||||
const disablePublicVisibilities = useAppSelector(
|
||||
selectDisablePublicVisibilities,
|
||||
);
|
||||
const isQuotePost = useAppSelector(
|
||||
(state) => state.compose.get('quoted_status_id') !== null,
|
||||
);
|
||||
|
||||
const visibilityItems = useMemo<SelectItem<StatusVisibility>[]>(() => {
|
||||
const items: SelectItem<StatusVisibility>[] = [
|
||||
|
|
@ -315,6 +318,21 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
|
|||
id={quoteDescriptionId}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{isQuotePost && visibility === 'direct' && (
|
||||
<div className='visibility-modal__quote-warning'>
|
||||
<FormattedMessage
|
||||
id='visibility_modal.direct_quote_warning.title'
|
||||
defaultMessage="Quotes can't be embedded in private mentions"
|
||||
tagName='h3'
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='visibility_modal.direct_quote_warning.text'
|
||||
defaultMessage='If you save the current settings, the embedded quote will be converted to a link.'
|
||||
tagName='p'
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className='dialog-modal__content__actions'>
|
||||
<Button onClick={onClose} secondary>
|
||||
|
|
|
|||
|
|
@ -22,12 +22,11 @@ import { identityContextPropShape, withIdentity } from 'mastodon/identity_contex
|
|||
import { layoutFromWindow } from 'mastodon/is_mobile';
|
||||
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||
|
||||
import { handleAnimateGif } from '../emoji/handlers';
|
||||
import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose';
|
||||
import { clearHeight } from '../../actions/height_cache';
|
||||
import { fetchServer, fetchServerTranslationLanguages } from '../../actions/server';
|
||||
import { expandHomeTimeline } from '../../actions/timelines';
|
||||
import { initialState, me, owner, singleUserMode, trendsEnabled, trendsAsLanding, disableHoverCards, autoPlayGif } from '../../initial_state';
|
||||
import { initialState, me, owner, singleUserMode, trendsEnabled, landingPage, localLiveFeedAccess, disableHoverCards } from '../../initial_state';
|
||||
|
||||
import BundleColumnError from './components/bundle_column_error';
|
||||
import { NavigationBar } from './components/navigation_bar';
|
||||
|
|
@ -148,8 +147,10 @@ class SwitchingColumnsArea extends PureComponent {
|
|||
}
|
||||
} else if (singleUserMode && owner && initialState?.accounts[owner]) {
|
||||
redirect = <Redirect from='/' to={`/@${initialState.accounts[owner].username}`} exact />;
|
||||
} else if (trendsEnabled && trendsAsLanding) {
|
||||
} else if (trendsEnabled && landingPage === 'trends') {
|
||||
redirect = <Redirect from='/' to='/explore' exact />;
|
||||
} else if (localLiveFeedAccess === 'public' && landingPage === 'local_feed') {
|
||||
redirect = <Redirect from='/' to='/public/local' exact />;
|
||||
} else {
|
||||
redirect = <Redirect from='/' to='/about' exact />;
|
||||
}
|
||||
|
|
@ -380,11 +381,6 @@ class UI extends PureComponent {
|
|||
window.addEventListener('beforeunload', this.handleBeforeUnload, false);
|
||||
window.addEventListener('resize', this.handleResize, { passive: true });
|
||||
|
||||
if (!autoPlayGif) {
|
||||
window.addEventListener('mouseover', handleAnimateGif, { passive: true });
|
||||
window.addEventListener('mouseout', handleAnimateGif, { passive: true });
|
||||
}
|
||||
|
||||
document.addEventListener('dragenter', this.handleDragEnter, false);
|
||||
document.addEventListener('dragover', this.handleDragOver, false);
|
||||
document.addEventListener('drop', this.handleDrop, false);
|
||||
|
|
@ -410,8 +406,6 @@ class UI extends PureComponent {
|
|||
window.removeEventListener('blur', this.handleWindowBlur);
|
||||
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
window.removeEventListener('mouseover', handleAnimateGif);
|
||||
window.removeEventListener('mouseout', handleAnimateGif);
|
||||
|
||||
document.removeEventListener('dragenter', this.handleDragEnter);
|
||||
document.removeEventListener('dragover', this.handleDragOver);
|
||||
|
|
|
|||
39
app/javascript/mastodon/hooks/useInterval.ts
Normal file
39
app/javascript/mastodon/hooks/useInterval.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import { useEffect, useLayoutEffect, useRef } from 'react';
|
||||
|
||||
/**
|
||||
* Hook to create an interval that invokes a callback function
|
||||
* at a specified delay using the setInterval API.
|
||||
* Based on https://usehooks-ts.com/react-hook/use-interval
|
||||
*/
|
||||
export function useInterval(
|
||||
callback: () => void,
|
||||
{
|
||||
delay,
|
||||
isEnabled = true,
|
||||
}: {
|
||||
delay: number;
|
||||
isEnabled?: boolean;
|
||||
},
|
||||
) {
|
||||
// Write callback to a ref so we can omit it from
|
||||
// the interval effect's dependency array
|
||||
const callbackRef = useRef(callback);
|
||||
useLayoutEffect(() => {
|
||||
callbackRef.current = callback;
|
||||
}, [callback]);
|
||||
|
||||
// Set up the interval.
|
||||
useEffect(() => {
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const intervalId = setInterval(() => {
|
||||
callbackRef.current();
|
||||
}, delay);
|
||||
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
}, [delay, isEnabled]);
|
||||
}
|
||||
32
app/javascript/mastodon/hooks/useIsDocumentVisible.ts
Normal file
32
app/javascript/mastodon/hooks/useIsDocumentVisible.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
export function useIsDocumentVisible({
|
||||
onChange,
|
||||
}: {
|
||||
onChange?: (isVisible: boolean) => void;
|
||||
} = {}) {
|
||||
const [isDocumentVisible, setIsDocumentVisible] = useState(
|
||||
() => document.visibilityState === 'visible',
|
||||
);
|
||||
|
||||
const onChangeRef = useRef(onChange);
|
||||
useEffect(() => {
|
||||
onChangeRef.current = onChange;
|
||||
}, [onChange]);
|
||||
|
||||
useEffect(() => {
|
||||
function handleVisibilityChange() {
|
||||
const isVisible = document.visibilityState === 'visible';
|
||||
|
||||
setIsDocumentVisible(isVisible);
|
||||
onChangeRef.current?.(isVisible);
|
||||
}
|
||||
window.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return isDocumentVisible;
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
import { useCallback } from 'react';
|
||||
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import { isFulfilled, isRejected } from '@reduxjs/toolkit';
|
||||
|
||||
import { openURL } from 'mastodon/actions/search';
|
||||
import { useAppDispatch } from 'mastodon/store';
|
||||
|
||||
import { isModernEmojiEnabled } from '../utils/environment';
|
||||
|
||||
const isMentionClick = (element: HTMLAnchorElement) =>
|
||||
element.classList.contains('mention') &&
|
||||
!element.classList.contains('hashtag');
|
||||
|
||||
const isHashtagClick = (element: HTMLAnchorElement) =>
|
||||
element.textContent.startsWith('#') ||
|
||||
element.previousSibling?.textContent?.endsWith('#');
|
||||
|
||||
export const useLinks = (skipHashtags?: boolean) => {
|
||||
const history = useHistory();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleHashtagClick = useCallback(
|
||||
(element: HTMLAnchorElement) => {
|
||||
const { textContent } = element;
|
||||
|
||||
if (!textContent) return;
|
||||
|
||||
history.push(`/tags/${textContent.replace(/^#/, '')}`);
|
||||
},
|
||||
[history],
|
||||
);
|
||||
|
||||
const handleMentionClick = useCallback(
|
||||
async (element: HTMLAnchorElement) => {
|
||||
const result = await dispatch(openURL({ url: element.href }));
|
||||
|
||||
if (isFulfilled(result)) {
|
||||
if (result.payload.accounts[0]) {
|
||||
history.push(`/@${result.payload.accounts[0].acct}`);
|
||||
} else if (result.payload.statuses[0]) {
|
||||
history.push(
|
||||
`/@${result.payload.statuses[0].account.acct}/${result.payload.statuses[0].id}`,
|
||||
);
|
||||
} else {
|
||||
window.location.href = element.href;
|
||||
}
|
||||
} else if (isRejected(result)) {
|
||||
window.location.href = element.href;
|
||||
}
|
||||
},
|
||||
[dispatch, history],
|
||||
);
|
||||
|
||||
const handleClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
// Exit early if modern emoji is enabled, as this is handled by HandledLink.
|
||||
if (isModernEmojiEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const target = (e.target as HTMLElement).closest('a');
|
||||
|
||||
if (!target || e.button !== 0 || e.ctrlKey || e.metaKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isMentionClick(target)) {
|
||||
e.preventDefault();
|
||||
void handleMentionClick(target);
|
||||
} else if (isHashtagClick(target) && !skipHashtags) {
|
||||
e.preventDefault();
|
||||
handleHashtagClick(target);
|
||||
}
|
||||
},
|
||||
[skipHashtags, handleMentionClick, handleHashtagClick],
|
||||
);
|
||||
|
||||
return handleClick;
|
||||
};
|
||||
|
|
@ -33,13 +33,13 @@ interface InitialStateMeta {
|
|||
single_user_mode: boolean;
|
||||
source_url: string;
|
||||
streaming_api_base_url: string;
|
||||
local_live_feed_access: 'public' | 'authenticated';
|
||||
remote_live_feed_access: 'public' | 'authenticated';
|
||||
local_live_feed_access: 'public' | 'authenticated' | 'disabled';
|
||||
remote_live_feed_access: 'public' | 'authenticated' | 'disabled';
|
||||
local_topic_feed_access: 'public' | 'authenticated';
|
||||
remote_topic_feed_access: 'public' | 'authenticated';
|
||||
remote_topic_feed_access: 'public' | 'authenticated' | 'disabled';
|
||||
title: string;
|
||||
show_trends: boolean;
|
||||
trends_as_landing_page: boolean;
|
||||
landing_page: 'about' | 'trends' | 'local_feed';
|
||||
use_blurhash: boolean;
|
||||
use_pending_items?: boolean;
|
||||
version: string;
|
||||
|
|
@ -120,7 +120,7 @@ export const remoteLiveFeedAccess = getMeta('remote_live_feed_access');
|
|||
export const localTopicFeedAccess = getMeta('local_topic_feed_access');
|
||||
export const remoteTopicFeedAccess = getMeta('remote_topic_feed_access');
|
||||
export const title = getMeta('title');
|
||||
export const trendsAsLanding = getMeta('trends_as_landing_page');
|
||||
export const landingPage = getMeta('landing_page');
|
||||
export const useBlurhash = getMeta('use_blurhash');
|
||||
export const usePendingItems = getMeta('use_pending_items');
|
||||
export const version = getMeta('version');
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Рэдагаваць спіс",
|
||||
"column.favourites": "Упадабанае",
|
||||
"column.firehose": "Стужкі",
|
||||
"column.firehose_local": "Жывая стужка гэтага сервера",
|
||||
"column.firehose_singular": "Жывая стужка",
|
||||
"column.follow_requests": "Запыты на падпіску",
|
||||
"column.home": "Галоўная",
|
||||
"column.list_members": "Кіраванне ўдзельнікамі спіса",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Толькі лакальныя",
|
||||
"community.column_settings.media_only": "Толькі медыя",
|
||||
"community.column_settings.remote_only": "Толькі дыстанцыйна",
|
||||
"compose.error.blank_post": "Допіс не можа быць пустым.",
|
||||
"compose.language.change": "Змяніць мову",
|
||||
"compose.language.search": "Шукаць мовы...",
|
||||
"compose.published.body": "Допіс апублікаваны.",
|
||||
|
|
@ -244,6 +247,7 @@
|
|||
"confirmations.missing_alt_text.secondary": "Усё адно апублікаваць",
|
||||
"confirmations.missing_alt_text.title": "Дадаць альтэрнатыўны тэкст?",
|
||||
"confirmations.mute.confirm": "Ігнараваць",
|
||||
"confirmations.private_quote_notify.cancel": "Звяртацца да рэдагавання",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Не нагадваць зноў",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Зразумела",
|
||||
"confirmations.quiet_post_quote_info.message": "Калі будзеце цытаваць ціхі публічны допіс, Ваш допіс будзе схаваны ад трэндавых стужак.",
|
||||
|
|
@ -333,6 +337,7 @@
|
|||
"empty_column.bookmarked_statuses": "У Вашых закладках яшчэ няма допісаў. Калі Вы дадасце закладку, яна з’явіцца тут.",
|
||||
"empty_column.community": "Мясцовая стужка пустая. Напішыце нешта публічнае, каб разварушыць справу!",
|
||||
"empty_column.direct": "Пакуль у Вас няма асабістых згадванняў. Калі Вы дашляце або атрымаеце штосьці, яно з’явіцца тут.",
|
||||
"empty_column.disabled_feed": "Гэта стужка была адключаная Вашымі адміністратарамі сервера.",
|
||||
"empty_column.domain_blocks": "Заблакіраваных даменаў пакуль няма.",
|
||||
"empty_column.explore_statuses": "Зараз не ў трэндзе. Праверце пазней",
|
||||
"empty_column.favourited_statuses": "Вы яшчэ не ўпадабалі ніводны допіс. Калі гэта адбудзецца, Вы ўбачыце яго тут.",
|
||||
|
|
@ -908,9 +913,12 @@
|
|||
"status.pin": "Замацаваць у профілі",
|
||||
"status.quote": "Цытаваць",
|
||||
"status.quote.cancel": "Адмяніць цытаванне",
|
||||
"status.quote_error.blocked_account_hint.title": "Гэты допіс схаваны, бо Вы заблакіравалі @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Гэты допіс схаваны, бо Вы заблакіравалі @{domain}.",
|
||||
"status.quote_error.filtered": "Схавана адным з Вашых фільтраў",
|
||||
"status.quote_error.limited_account_hint.action": "Усё адно паказаць",
|
||||
"status.quote_error.limited_account_hint.title": "Гэты ўліковы запіс быў схаваны мадэратарамі {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Гэты допіс схаваны, бо Вы вырашылі ігнараваць @{name}.",
|
||||
"status.quote_error.not_available": "Допіс недаступны",
|
||||
"status.quote_error.pending_approval": "Допіс чакае пацвярджэння",
|
||||
"status.quote_error.pending_approval_popout.body": "У Mastodon можна кантраляваць магчымасць іншых цытаваць Вас. Гэты допіс будзе знаходзіцца ў стане чакання, пакуль мы не атрымаем ухваленне на цытаванне ад аўтара арыгінальнага допісу.",
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
"account.disable_notifications": "Спиране на известяване при публикуване от @{name}",
|
||||
"account.domain_blocking": "Блокиране на домейн",
|
||||
"account.edit_profile": "Редактиране на профила",
|
||||
"account.edit_profile_short": "Редактиране",
|
||||
"account.enable_notifications": "Известяване при публикуване от @{name}",
|
||||
"account.endorse": "Представи в профила",
|
||||
"account.familiar_followers_many": "Последвано от {name1}, {name2}, и {othersCount, plural, one {един друг, когото познавате} other {# други, които познавате}}",
|
||||
|
|
@ -40,6 +41,9 @@
|
|||
"account.featured_tags.last_status_never": "Няма публикации",
|
||||
"account.follow": "Последване",
|
||||
"account.follow_back": "Последване взаимно",
|
||||
"account.follow_request_cancel": "Отказване на заявката",
|
||||
"account.follow_request_cancel_short": "Отказ",
|
||||
"account.follow_request_short": "Заявка",
|
||||
"account.followers": "Последователи",
|
||||
"account.followers.empty": "Още никой не следва потребителя.",
|
||||
"account.followers_counter": "{count, plural, one {{counter} последовател} other {{counter} последователи}}",
|
||||
|
|
@ -238,6 +242,9 @@
|
|||
"confirmations.missing_alt_text.secondary": "Все пак да се публикува",
|
||||
"confirmations.missing_alt_text.title": "Добавяте ли алтернативен текст?",
|
||||
"confirmations.mute.confirm": "Заглушаване",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Без друго напомняне",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Схванах",
|
||||
"confirmations.quiet_post_quote_info.title": "Цитиране на публикации за тиха публика",
|
||||
"confirmations.redraft.confirm": "Изтриване и преработване",
|
||||
"confirmations.redraft.message": "Наистина ли искате да изтриете тази публикация и да я направите чернова? Означаванията като любими и подсилванията ще се изгубят, а и отговорите към първоначалната публикация ще осиротеят.",
|
||||
"confirmations.redraft.title": "Изтривате и преработвате ли публикацията?",
|
||||
|
|
@ -247,7 +254,11 @@
|
|||
"confirmations.revoke_quote.confirm": "Премахване на публикация",
|
||||
"confirmations.revoke_quote.message": "Действието е неотменимо.",
|
||||
"confirmations.revoke_quote.title": "Премахвате ли публикацията?",
|
||||
"confirmations.unblock.confirm": "Отблокиране",
|
||||
"confirmations.unblock.title": "Отблокирате ли @{name}?",
|
||||
"confirmations.unfollow.confirm": "Без следване",
|
||||
"confirmations.unfollow.title": "Спирате ли следване на {name}?",
|
||||
"confirmations.withdraw_request.confirm": "Оттегляне на заявката",
|
||||
"content_warning.hide": "Скриване на публ.",
|
||||
"content_warning.show": "Нека се покаже",
|
||||
"content_warning.show_more": "Показване на още",
|
||||
|
|
@ -442,10 +453,12 @@
|
|||
"ignore_notifications_modal.private_mentions_title": "Пренебрегвате ли известия от непоискани лични споменавания?",
|
||||
"info_button.label": "Помощ",
|
||||
"info_button.what_is_alt_text": "<h1>Какво е алтернативен текст?</h1> <p>Алтернативният текст осигурява описания на изображение за хора със зрителни увреждания, връзки с ниска честотна лента или търсещите допълнителен контекст.</p> <p>Може да подобрите достъпността и разбираемостта за всеки, пишейки ясен, кратък и обективен алтернативен текст.</p> <ul> <li>Уловете важните елементи</li> <li>Обобщете текста в образите</li> <li>Употребявайте правилна структура на изречението</li> <li>Избягвайте излишна информация</li> <li>Съсредоточете се върху тенденциите и ключови констатации в сложни онагледявания (като диаграми и карти)</li> </ul>",
|
||||
"interaction_modal.action": "Трябва да влезете с акаунта си, в който и да е сървър на Mastodon, когото използвате, за да взаимодействате с публикация на {name}.",
|
||||
"interaction_modal.go": "Напред",
|
||||
"interaction_modal.no_account_yet": "Още ли нямате акаунт?",
|
||||
"interaction_modal.on_another_server": "На различен сървър",
|
||||
"interaction_modal.on_this_server": "На този сървър",
|
||||
"interaction_modal.title": "Влезте, за да продължите",
|
||||
"interaction_modal.username_prompt": "Напр. {example}",
|
||||
"intervals.full.days": "{number, plural, one {# ден} other {# дни}}",
|
||||
"intervals.full.hours": "{number, plural, one {# час} other {# часа}}",
|
||||
|
|
@ -596,6 +609,7 @@
|
|||
"notification.moderation_warning.action_suspend": "Вашият акаунт е спрян.",
|
||||
"notification.own_poll": "Анкетата ви приключи",
|
||||
"notification.poll": "Анкета, в която гласувахте, приключи",
|
||||
"notification.quoted_update": "{name} редактира публикация, която цитирахте",
|
||||
"notification.reblog": "{name} подсили ваша публикация",
|
||||
"notification.reblog.name_and_others_with_link": "{name} и <a>{count, plural, one {# друг} other {# други}}</a> подсилиха ваша публикация",
|
||||
"notification.relationships_severance_event": "Изгуби се връзката с {name}",
|
||||
|
|
@ -715,10 +729,17 @@
|
|||
"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.short": "Тиха публика",
|
||||
"privacy_policy.last_updated": "Последно осъвременяване на {date}",
|
||||
"privacy_policy.title": "Политика за поверителност",
|
||||
"quote_error.edit": "Не може да се добавят цитати, редайтирайки публикация.",
|
||||
"quote_error.poll": "Не може да се цитира при анкетиране.",
|
||||
"quote_error.unauthorized": "Нямате право да цитирате тази публикация.",
|
||||
"quote_error.upload": "Цитирането не е позволено с мултимедийни прикачвания.",
|
||||
"recommended": "Препоръчано",
|
||||
"refresh": "Опресняване",
|
||||
"regeneration_indicator.please_stand_by": "Изчакайте.",
|
||||
|
|
@ -734,6 +755,8 @@
|
|||
"relative_time.minutes": "{number}м.",
|
||||
"relative_time.seconds": "{number}с.",
|
||||
"relative_time.today": "днес",
|
||||
"remove_quote_hint.button_label": "Схванах",
|
||||
"remove_quote_hint.message": "Може да го направите от менюто възможности {icon}.",
|
||||
"reply_indicator.attachments": "{count, plural, one {# прикаване} other {# прикачвания}}",
|
||||
"reply_indicator.cancel": "Отказ",
|
||||
"reply_indicator.poll": "Анкета",
|
||||
|
|
@ -825,13 +848,22 @@
|
|||
"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.loading": "Зареждане на още отговори",
|
||||
"status.context.loading_error": "Не можаха да се заредят нови отговори",
|
||||
"status.context.loading_success": "Новите отговори заредени",
|
||||
"status.context.more_replies_found": "Още намерени отговори",
|
||||
"status.context.retry": "Друг опит",
|
||||
"status.context.show": "Показване",
|
||||
"status.continued_thread": "Продължена нишка",
|
||||
"status.copy": "Копиране на връзката към публикация",
|
||||
"status.delete": "Изтриване",
|
||||
"status.delete.success": "Публикацията е изтрита",
|
||||
"status.detailed_status": "Подробен изглед на разговора",
|
||||
"status.direct": "Частно споменаване на @{name}",
|
||||
"status.direct_indicator": "Частно споменаване",
|
||||
|
|
@ -855,23 +887,32 @@
|
|||
"status.open": "Разширяване на публикацията",
|
||||
"status.pin": "Закачане в профила",
|
||||
"status.quote_error.filtered": "Скрито поради един от филтрите ви",
|
||||
"status.quote_error.limited_account_hint.title": "Този акаунт е бил скрит от модераторите на {domain}.",
|
||||
"status.quote_error.not_available": "Неналична публикация",
|
||||
"status.quote_error.pending_approval": "Публикацията чака одобрение",
|
||||
"status.quote_error.revoked": "Премахната публикация от автора",
|
||||
"status.quote_followers_only": "Само последователи могат да цитират тази публикация",
|
||||
"status.quote_manual_review": "Авторът ще преглежда ръчно",
|
||||
"status.quote_policy_change": "Промяна кой може да цитира",
|
||||
"status.quote_post_author": "Цитирах публикация от @{name}",
|
||||
"status.quote_private": "Частните публикации не може да се цитират",
|
||||
"status.read_more": "Още за четене",
|
||||
"status.reblog": "Подсилване",
|
||||
"status.reblog_or_quote": "Подсилване или цитиране",
|
||||
"status.reblog_private": "Споделете пак с последователите си",
|
||||
"status.reblogged_by": "{name} подсили",
|
||||
"status.reblogs": "{count, plural, one {подсилване} other {подсилвания}}",
|
||||
"status.reblogs.empty": "Още никого не е подсилвал публикацията. Подсилващият ще се покаже тук.",
|
||||
"status.redraft": "Изтриване и преработване",
|
||||
"status.remove_bookmark": "Премахване на отметката",
|
||||
"status.remove_favourite": "Премахване от любими",
|
||||
"status.remove_quote": "Премахване",
|
||||
"status.replied_in_thread": "Отговорено в нишката",
|
||||
"status.replied_to": "В отговор до {name}",
|
||||
"status.reply": "Отговор",
|
||||
"status.replyAll": "Отговор на нишка",
|
||||
"status.report": "Докладване на @{name}",
|
||||
"status.request_quote": "Заявка за цитиране",
|
||||
"status.revoke_quote": "Премахване на моя публикация от публикацията на @{name}",
|
||||
"status.sensitive_warning": "Деликатно съдържание",
|
||||
"status.share": "Споделяне",
|
||||
|
|
@ -910,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} е спуснато.",
|
||||
|
|
@ -935,6 +977,13 @@
|
|||
"video.volume_up": "Увеличаване на звука",
|
||||
"visibility_modal.button_title": "Задаване на видимост",
|
||||
"visibility_modal.header": "Видимост и взаимодействие",
|
||||
"visibility_modal.helper.privacy_editing": "Видимостта не може да се променя след публикуване на публикацията.",
|
||||
"visibility_modal.helper.privacy_private_self_quote": "Самоцитирането на частни публикации не може да се огласява публично.",
|
||||
"visibility_modal.instructions": "Управлява кой може да взаимодейства с тази публикация. Може също да приложите настройките за всички бъдещи публикации, навигирайки към <link>Предпочитания > Публикуване по подразбиране</link>.",
|
||||
"visibility_modal.privacy_label": "Видимост",
|
||||
"visibility_modal.quote_followers": "Само последователи",
|
||||
"visibility_modal.quote_public": "Някой"
|
||||
"visibility_modal.quote_label": "Кой може да цитира",
|
||||
"visibility_modal.quote_nobody": "Само аз",
|
||||
"visibility_modal.quote_public": "Някой",
|
||||
"visibility_modal.save": "Запазване"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,6 +192,7 @@
|
|||
"community.column_settings.local_only": "Només local",
|
||||
"community.column_settings.media_only": "Només contingut",
|
||||
"community.column_settings.remote_only": "Només remot",
|
||||
"compose.error.blank_post": "La publicació no pot estar en blanc.",
|
||||
"compose.language.change": "Canvia d'idioma",
|
||||
"compose.language.search": "Cerca idiomes...",
|
||||
"compose.published.body": "Tut publicat.",
|
||||
|
|
@ -749,7 +750,9 @@
|
|||
"privacy.unlisted.short": "Públic silenciós",
|
||||
"privacy_policy.last_updated": "Darrera actualització {date}",
|
||||
"privacy_policy.title": "Política de Privacitat",
|
||||
"quote_error.edit": "No es poden afegir cites en editar una publicació.",
|
||||
"quote_error.poll": "Amb les enquestes no es permeten cites.",
|
||||
"quote_error.private_mentions": "Amb mencions directes no es permeten cites.",
|
||||
"quote_error.quote": "Només es permet una cita alhora.",
|
||||
"quote_error.unauthorized": "No se us permet de citar aquesta publicació.",
|
||||
"quote_error.upload": "Amb media adjunts no es permeten cites.",
|
||||
|
|
@ -871,6 +874,7 @@
|
|||
"status.contains_quote": "Conté una cita",
|
||||
"status.context.loading": "Es carreguen més respostes",
|
||||
"status.context.loading_error": "No s'han pogut carregar respostes noves",
|
||||
"status.context.loading_success": "S'han carregat les noves respostes",
|
||||
"status.context.more_replies_found": "S'han trobat més respostes",
|
||||
"status.context.retry": "Torna-ho a provar",
|
||||
"status.context.show": "Mostra",
|
||||
|
|
@ -902,9 +906,12 @@
|
|||
"status.pin": "Fixa en el perfil",
|
||||
"status.quote": "Cita",
|
||||
"status.quote.cancel": "Canceŀlar la citació",
|
||||
"status.quote_error.blocked_account_hint.title": "Aquesta publicació està amagada perquè heu blocat a @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Aquesta publicació està amagada perquè heu blocat a {domain}.",
|
||||
"status.quote_error.filtered": "No es mostra a causa d'un dels vostres filtres",
|
||||
"status.quote_error.limited_account_hint.action": "Mostra-la igualment",
|
||||
"status.quote_error.limited_account_hint.title": "Aquest perfil l'han amagat els moderadors de {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Aquesta publicació està amagada perquè heu silenciat a @{name}.",
|
||||
"status.quote_error.not_available": "Publicació no disponible",
|
||||
"status.quote_error.pending_approval": "Publicació pendent",
|
||||
"status.quote_error.pending_approval_popout.body": "A Mastodon pots controlar si algú et pot citar. Aquesta publicació està pendent mentre esperem l'aprovació de l'autor original.",
|
||||
|
|
@ -1003,6 +1010,7 @@
|
|||
"visibility_modal.helper.direct_quoting": "No es poden citar mencions privades fetes a Mastondon.",
|
||||
"visibility_modal.helper.private_quoting": "No es poden citar publicacions fetes a Mastodon només per a seguidors.",
|
||||
"visibility_modal.helper.unlisted_quoting": "Quan la gent et citi les seves publicacions estaran amagades de les línies de temps de tendències.",
|
||||
"visibility_modal.instructions": "Controleu qui pot interactuar amb aquesta publicació. També podeu aplicar la configuració a totes les publicacions futures navegant a <link>Preferències > Valors per defecte de publicació</link>.",
|
||||
"visibility_modal.privacy_label": "Visibilitat",
|
||||
"visibility_modal.quote_followers": "Només seguidors",
|
||||
"visibility_modal.quote_label": "Qui pot citar",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Upravit seznam",
|
||||
"column.favourites": "Oblíbené",
|
||||
"column.firehose": "Živé kanály",
|
||||
"column.firehose_local": "Živý kanál pro tento server",
|
||||
"column.firehose_singular": "Živý kanál",
|
||||
"column.follow_requests": "Žádosti o sledování",
|
||||
"column.home": "Domů",
|
||||
"column.list_members": "Spravovat členy seznamu",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Pouze místní",
|
||||
"community.column_settings.media_only": "Pouze média",
|
||||
"community.column_settings.remote_only": "Pouze vzdálené",
|
||||
"compose.error.blank_post": "Příspěvek nemůže být prázdný.",
|
||||
"compose.language.change": "Změnit jazyk",
|
||||
"compose.language.search": "Prohledat jazyky...",
|
||||
"compose.published.body": "Příspěvek zveřejněn.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Přesto odeslat",
|
||||
"confirmations.missing_alt_text.title": "Přidat popisek?",
|
||||
"confirmations.mute.confirm": "Skrýt",
|
||||
"confirmations.private_quote_notify.cancel": "Zpět k úpravám",
|
||||
"confirmations.private_quote_notify.confirm": "Publikovat příspěvek",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Nezobrazujte mi znovu tuto zprávu",
|
||||
"confirmations.private_quote_notify.message": "Osoba, kterou citujete, a další zmínění budou upozorněni a budou moci si zobrazit váš příspěvek, i pokud vás nesledují.",
|
||||
"confirmations.private_quote_notify.title": "Sdílet se sledujícími a zmíněnými uživateli?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Znovu nepřípomínat",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Rozumím",
|
||||
"confirmations.quiet_post_quote_info.message": "Při citování ztišeného veřejného příspěvku, váš příspěvek bude skrytý z os populárních příspěvků.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Zatím v záložkách nemáte žádné příspěvky. Až si do nich nějaký přidáte, zobrazí se zde.",
|
||||
"empty_column.community": "Místní časová osa je prázdná. Napište něco veřejně a rozhýbejte to tu!",
|
||||
"empty_column.direct": "Zatím nemáte žádné soukromé zmínky. Až nějakou pošlete nebo dostanete, zobrazí se zde.",
|
||||
"empty_column.disabled_feed": "Tento kanál byl zakázán administrátory vašeho serveru.",
|
||||
"empty_column.domain_blocks": "Ještě nemáte žádné zablokované domény.",
|
||||
"empty_column.explore_statuses": "Momentálně není nic populární. Vraťte se později!",
|
||||
"empty_column.favourited_statuses": "Zatím nemáte žádné oblíbené příspěvky. Až si nějaký oblíbíte, zobrazí se zde.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Zásady ochrany osobních údajů",
|
||||
"quote_error.edit": "Citáty nemohou být přidány při úpravě příspěvku.",
|
||||
"quote_error.poll": "Citování není u dotazníků povoleno.",
|
||||
"quote_error.private_mentions": "Citování není povoleno s přímými zmínkami.",
|
||||
"quote_error.quote": "Je povoleno citovat pouze jednou.",
|
||||
"quote_error.unauthorized": "Nemáte oprávnění citovat tento příspěvek.",
|
||||
"quote_error.upload": "Není povoleno citovat s přílohami.",
|
||||
|
|
@ -876,6 +886,7 @@
|
|||
"status.contains_quote": "Obsahuje citaci",
|
||||
"status.context.loading": "Načítání dalších odpovědí",
|
||||
"status.context.loading_error": "Nelze načíst nové odpovědi",
|
||||
"status.context.loading_success": "Nové odpovědi načteny",
|
||||
"status.context.more_replies_found": "Nalezeny další odpovědi",
|
||||
"status.context.retry": "Zkusit znovu",
|
||||
"status.context.show": "Zobrazit",
|
||||
|
|
@ -907,9 +918,12 @@
|
|||
"status.pin": "Připnout na profil",
|
||||
"status.quote": "Citovat",
|
||||
"status.quote.cancel": "Zrušit citování",
|
||||
"status.quote_error.blocked_account_hint.title": "Tento příspěvek je skryt, protože jste zablokovali @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Tento příspěvek je skryt, protože jste zablokovali {domain}.",
|
||||
"status.quote_error.filtered": "Skryté kvůli jednomu z vašich filtrů",
|
||||
"status.quote_error.limited_account_hint.action": "Přesto zobrazit",
|
||||
"status.quote_error.limited_account_hint.title": "Tento účet byl skryt moderátory {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Tento příspěvek je skryt, protože jste ztišili @{name}.",
|
||||
"status.quote_error.not_available": "Příspěvek není dostupný",
|
||||
"status.quote_error.pending_approval": "Příspěvek čeká na schválení",
|
||||
"status.quote_error.pending_approval_popout.body": "Na Mastodonu můžete kontrolovat, zda vás někdo může citovat. Tento příspěvek čeká, dokud neobdržíme schválení od původního autora.",
|
||||
|
|
@ -1004,6 +1018,8 @@
|
|||
"video.volume_down": "Snížit hlasitost",
|
||||
"video.volume_up": "Zvýšit hlasitost",
|
||||
"visibility_modal.button_title": "Nastavit viditelnost",
|
||||
"visibility_modal.direct_quote_warning.text": "Pokud uložíte aktuální nastavení, vložená citace bude převedena na odkaz.",
|
||||
"visibility_modal.direct_quote_warning.title": "Citace nemohou být vloženy do soukromých zmínek",
|
||||
"visibility_modal.header": "Viditelnost a interakce",
|
||||
"visibility_modal.helper.direct_quoting": "Soukromé zmínky, které jsou vytvořeny na Mastodonu, nemohou být citovány ostatními.",
|
||||
"visibility_modal.helper.privacy_editing": "Viditelnost nelze změnit po publikování příspěvku.",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Golygu rhestr",
|
||||
"column.favourites": "Ffefrynnau",
|
||||
"column.firehose": "Ffrydiau byw",
|
||||
"column.firehose_local": "Ffrwd fyw ar gyfer y gweinydd hwn",
|
||||
"column.firehose_singular": "Ffrwd fyw",
|
||||
"column.follow_requests": "Ceisiadau dilyn",
|
||||
"column.home": "Cartref",
|
||||
"column.list_members": "Rheoli aelodau rhestr",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Lleol yn unig",
|
||||
"community.column_settings.media_only": "Cyfryngau yn unig",
|
||||
"community.column_settings.remote_only": "Pell yn unig",
|
||||
"compose.error.blank_post": "Gall postiad ddim bod yn wag.",
|
||||
"compose.language.change": "Newid iaith",
|
||||
"compose.language.search": "Chwilio ieithoedd...",
|
||||
"compose.published.body": "Postiad wedi ei gyhoeddi.",
|
||||
|
|
@ -333,6 +336,7 @@
|
|||
"empty_column.bookmarked_statuses": "Does gennych chi ddim unrhyw bostiad wedi'u cadw fel nod tudalen eto. Pan fyddwch yn gosod nod tudalen i un, mi fydd yn ymddangos yma.",
|
||||
"empty_column.community": "Mae'r ffrwd lleol yn wag. Beth am ysgrifennu rhywbeth cyhoeddus!",
|
||||
"empty_column.direct": "Does gennych chi unrhyw grybwylliadau preifat eto. Pan fyddwch chi'n anfon neu'n derbyn un, bydd yn ymddangos yma.",
|
||||
"empty_column.disabled_feed": "Mae'r ffrwd hon wedi'i hanalluogi gan weinyddwyr eich gweinydd.",
|
||||
"empty_column.domain_blocks": "Does dim parthau wedi'u rhwystro eto.",
|
||||
"empty_column.explore_statuses": "Does dim pynciau llosg ar hyn o bryd. Dewch nôl nes ymlaen!",
|
||||
"empty_column.favourited_statuses": "Rydych chi heb ffafrio unrhyw bostiadau eto. Pan byddwch chi'n ffafrio un, bydd yn ymddangos yma.",
|
||||
|
|
@ -753,6 +757,7 @@
|
|||
"privacy.unlisted.short": "Tewi'r cyhoeddus",
|
||||
"privacy_policy.last_updated": "Diweddarwyd ddiwethaf ar {date}",
|
||||
"privacy_policy.title": "Polisi Preifatrwydd",
|
||||
"quote_error.edit": "Does dim modd ychwanegu dyfyniadau wrth olygu postiad.",
|
||||
"quote_error.poll": "Dyw dyfynnu ddim yn cael ei ganiatáu gyda pholau.",
|
||||
"quote_error.quote": "Dim ond un dyfyniad ar y tro sy'n cael ei ganiatáu.",
|
||||
"quote_error.unauthorized": "Does gennych chi ddim awdurdod i ddyfynnu'r postiad hwn.",
|
||||
|
|
@ -875,6 +880,7 @@
|
|||
"status.contains_quote": "Yn cynnwys dyfyniad",
|
||||
"status.context.loading": "Yn llwytho mwy o atebion",
|
||||
"status.context.loading_error": "Wedi methu llwytho atebion newydd",
|
||||
"status.context.loading_success": "Atebion newydd wedi'u llwytho",
|
||||
"status.context.more_replies_found": "Mwy o atebion wedi'u canfod",
|
||||
"status.context.retry": "Ceisio eto",
|
||||
"status.context.show": "Dangos",
|
||||
|
|
@ -906,9 +912,12 @@
|
|||
"status.pin": "Pinio ar y proffil",
|
||||
"status.quote": "Dyfynnu",
|
||||
"status.quote.cancel": "Diddymu'r dyfyniad",
|
||||
"status.quote_error.blocked_account_hint.title": "Mae'r postiad hwn wedi'i guddio oherwydd eich bod wedi rhwystro @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Mae'r postiad hwn wedi'i guddio oherwydd eich bod wedi rhwystro {domain}.",
|
||||
"status.quote_error.filtered": "Wedi'i guddio oherwydd un o'ch hidlwyr",
|
||||
"status.quote_error.limited_account_hint.action": "Dangos beth bynnag",
|
||||
"status.quote_error.limited_account_hint.title": "Mae'r cyfrif hwn wedi'i guddio gan gymedrolwyr {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Mae'r postiad hwn wedi'i guddio oherwydd eich bod wedi mudo @{name}.",
|
||||
"status.quote_error.not_available": "Postiad ddim ar gael",
|
||||
"status.quote_error.pending_approval": "Postiad yn yr arfaeth",
|
||||
"status.quote_error.pending_approval_popout.body": "Ar Mastodon, gallwch reoli os yw rhywun yn gallu eich dyfynnu. Mae'r postiad hwn yn cael ei ddal nôl tra'n bod yn cael cymeradwyaeth yr awdur gwreiddiol.",
|
||||
|
|
|
|||
|
|
@ -172,7 +172,9 @@
|
|||
"column.domain_blocks": "Blokerede domæner",
|
||||
"column.edit_list": "Redigér liste",
|
||||
"column.favourites": "Favoritter",
|
||||
"column.firehose": "Aktuelt",
|
||||
"column.firehose": "Live feeds",
|
||||
"column.firehose_local": "Live feed for denne server",
|
||||
"column.firehose_singular": "Live feed",
|
||||
"column.follow_requests": "Følgeanmodninger",
|
||||
"column.home": "Hjem",
|
||||
"column.list_members": "Håndtér listemedlemmer",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Kun lokalt",
|
||||
"community.column_settings.media_only": "Kun medier",
|
||||
"community.column_settings.remote_only": "Kun udefra",
|
||||
"compose.error.blank_post": "Indlæg kan ikke være tomt.",
|
||||
"compose.language.change": "Skift sprog",
|
||||
"compose.language.search": "Søg efter sprog...",
|
||||
"compose.published.body": "Indlæg udgivet.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Læg op alligevel",
|
||||
"confirmations.missing_alt_text.title": "Tilføj alt-tekst?",
|
||||
"confirmations.mute.confirm": "Skjul",
|
||||
"confirmations.private_quote_notify.cancel": "Tilbage til redigering",
|
||||
"confirmations.private_quote_notify.confirm": "Offentliggør indlæg",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Vis ikke denne besked igen",
|
||||
"confirmations.private_quote_notify.message": "Den person, du citerer og andre omtalte vil blive underrettet, og vil være i stand til at se dit indlæg, selv om de ikke følger dig.",
|
||||
"confirmations.private_quote_notify.title": "Del med følgere og omtalte brugere?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Påmind mig ikke igen",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Forstået",
|
||||
"confirmations.quiet_post_quote_info.message": "Når du citerer et stille offentligt indlæg, vil dit indlæg blive skjult fra trendtidslinjer.",
|
||||
|
|
@ -279,7 +287,7 @@
|
|||
"directory.recently_active": "Aktive for nyligt",
|
||||
"disabled_account_banner.account_settings": "Kontoindstillinger",
|
||||
"disabled_account_banner.text": "Din konto {disabledAccount} er pt. deaktiveret.",
|
||||
"dismissable_banner.community_timeline": "Disse er de seneste offentlige indlæg fra personer med konti hostet af {domain}.",
|
||||
"dismissable_banner.community_timeline": "Dette er de seneste offentlige indlæg fra personer med konti hostet af {domain}.",
|
||||
"dismissable_banner.dismiss": "Afvis",
|
||||
"dismissable_banner.public_timeline": "Dette er de seneste offentlige indlæg fra personer på fediverset, som folk på {domain} følger.",
|
||||
"domain_block_modal.block": "Blokér server",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Du har ingen bogmærkede indlæg endnu. Når du bogmærker ét, vil det dukke op hér.",
|
||||
"empty_column.community": "Den lokale tidslinje er tom. Skriv noget offentligt for at sætte tingene i gang!",
|
||||
"empty_column.direct": "Du har ikke nogen private omtaler endnu. Når du sender eller modtager en, vil den blive vist her.",
|
||||
"empty_column.disabled_feed": "Dette feed er blevet deaktiveret af dine serveradministratorer.",
|
||||
"empty_column.domain_blocks": "Ingen blokerede domæner endnu.",
|
||||
"empty_column.explore_statuses": "Ingen nye trends lige nu. Tjek igen senere!",
|
||||
"empty_column.favourited_statuses": "Du har endnu ingen favoritindlæg. Når du føjer et opslag til favoritter, vil det dukke op her.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Privatlivspolitik",
|
||||
"quote_error.edit": "Citater kan ikke tilføjes ved redigering af et indlæg.",
|
||||
"quote_error.poll": "Citering ikke tilladt i afstemninger.",
|
||||
"quote_error.private_mentions": "Citering er ikke tilladt med direkte omtaler.",
|
||||
"quote_error.quote": "Kun ét citat ad gangen er tilladt.",
|
||||
"quote_error.unauthorized": "Du har ikke tilladelse til at citere dette indlæg.",
|
||||
"quote_error.upload": "Citering ikke tilladt ved medievedhæftninger.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Fastgør til profil",
|
||||
"status.quote": "Citér",
|
||||
"status.quote.cancel": "Annullér citat",
|
||||
"status.quote_error.blocked_account_hint.title": "Dette indlæg er skjult, fordi du har blokeret @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Dette indlæg er skjult, fordi du har blokeret @{domain}.",
|
||||
"status.quote_error.filtered": "Skjult grundet et af filterne",
|
||||
"status.quote_error.limited_account_hint.action": "Vis alligevel",
|
||||
"status.quote_error.limited_account_hint.title": "Denne profil er blevet skjult af {domain}-moderatorerne.",
|
||||
"status.quote_error.muted_account_hint.title": "Dette indlæg er skjult, fordi du har skjult @{name}.",
|
||||
"status.quote_error.not_available": "Indlæg utilgængeligt",
|
||||
"status.quote_error.pending_approval": "Afventende indlæg",
|
||||
"status.quote_error.pending_approval_popout.body": "På Mastodon kan du kontrollere, om nogen kan citere dig. Dette indlæg afventer, mens vi får den oprindelige forfatters godkendelse.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Lydstyrke ned",
|
||||
"video.volume_up": "Lydstyrke op",
|
||||
"visibility_modal.button_title": "Indstil synlighed",
|
||||
"visibility_modal.direct_quote_warning.text": "Hvis du gemmer de aktuelle indstillinger, vil det indlejrede citat blive konverteret til et link.",
|
||||
"visibility_modal.direct_quote_warning.title": "Citater kan ikke indlejres i private omtaler",
|
||||
"visibility_modal.header": "Synlighed og interaktion",
|
||||
"visibility_modal.helper.direct_quoting": "Private omtaler forfattet på Mastodon kan ikke citeres af andre.",
|
||||
"visibility_modal.helper.privacy_editing": "Synlighed kan ikke ændres, efter at et indlæg er offentliggjort.",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Liste bearbeiten",
|
||||
"column.favourites": "Favoriten",
|
||||
"column.firehose": "Live-Feeds",
|
||||
"column.firehose_local": "Live-Feed für diesen Server",
|
||||
"column.firehose_singular": "Live-Feed",
|
||||
"column.follow_requests": "Follower-Anfragen",
|
||||
"column.home": "Startseite",
|
||||
"column.list_members": "Listenmitglieder verwalten",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Nur lokal",
|
||||
"community.column_settings.media_only": "Nur Beiträge mit Medien",
|
||||
"community.column_settings.remote_only": "Nur andere Mastodon-Server",
|
||||
"compose.error.blank_post": "Beitrag muss einen Inhalt haben.",
|
||||
"compose.language.change": "Sprache festlegen",
|
||||
"compose.language.search": "Sprachen suchen …",
|
||||
"compose.published.body": "Beitrag veröffentlicht.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Trotzdem veröffentlichen",
|
||||
"confirmations.missing_alt_text.title": "Bildbeschreibung hinzufügen?",
|
||||
"confirmations.mute.confirm": "Stummschalten",
|
||||
"confirmations.private_quote_notify.cancel": "Zurück zum Bearbeiten",
|
||||
"confirmations.private_quote_notify.confirm": "Beitrag veröffentlichen",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Diesen Hinweis nicht mehr anzeigen",
|
||||
"confirmations.private_quote_notify.message": "Dein Beitrag wird von dem zitierten sowie den erwähnten Profilen gesehen werden können, auch wenn sie dir nicht folgen.",
|
||||
"confirmations.private_quote_notify.title": "Mit Followern und erwähnten Profilen teilen?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Nicht mehr anzeigen",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Verstanden",
|
||||
"confirmations.quiet_post_quote_info.message": "Beim Zitieren eines Beitrags mit der Sichtbarkeit „Öffentlich (still)“ wird dein zitierter Beitrag ebenfalls nicht in den Trends und öffentlichen Timelines angezeigt.",
|
||||
|
|
@ -257,8 +265,8 @@
|
|||
"confirmations.revoke_quote.confirm": "Beitrag entfernen",
|
||||
"confirmations.revoke_quote.message": "Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"confirmations.revoke_quote.title": "Beitrag entfernen?",
|
||||
"confirmations.unblock.confirm": "Entsperren",
|
||||
"confirmations.unblock.title": "{name} entsperren?",
|
||||
"confirmations.unblock.confirm": "Nicht mehr blockieren",
|
||||
"confirmations.unblock.title": "{name} nicht mehr blockieren?",
|
||||
"confirmations.unfollow.confirm": "Entfolgen",
|
||||
"confirmations.unfollow.title": "{name} entfolgen?",
|
||||
"confirmations.withdraw_request.confirm": "Anfrage zurückziehen",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Du hast bisher keine Beiträge als Lesezeichen abgelegt. Sobald du einen Beitrag als Lesezeichen speicherst, wird er hier erscheinen.",
|
||||
"empty_column.community": "Die lokale Timeline ist leer. Schreibe einen öffentlichen Beitrag, um den Stein ins Rollen zu bringen!",
|
||||
"empty_column.direct": "Du hast noch keine privaten Erwähnungen. Sobald du eine sendest oder erhältst, wird sie hier erscheinen.",
|
||||
"empty_column.disabled_feed": "Diesen Feed haben deine Server-Administrator*innen deaktiviert.",
|
||||
"empty_column.domain_blocks": "Du hast noch keine Domains blockiert.",
|
||||
"empty_column.explore_statuses": "Momentan ist nichts im Trend. Schau später wieder vorbei!",
|
||||
"empty_column.favourited_statuses": "Du hast noch keine Beiträge favorisiert. Sobald du einen favorisierst, wird er hier erscheinen.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Datenschutzerklärung",
|
||||
"quote_error.edit": "Beim Bearbeiten eines Beitrags können keine Zitate hinzugefügt werden.",
|
||||
"quote_error.poll": "Zitieren ist bei Umfragen nicht gestattet.",
|
||||
"quote_error.private_mentions": "Das Zitieren ist bei privaten Erwähnungen nicht erlaubt.",
|
||||
"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.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Im Profil anheften",
|
||||
"status.quote": "Zitieren",
|
||||
"status.quote.cancel": "Zitat abbrechen",
|
||||
"status.quote_error.blocked_account_hint.title": "Dieser Beitrag wurde ausgeblendet, weil du @{name} blockiert hast.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Dieser Beitrag wurde ausgeblendet, weil du {domain} blockiert hast.",
|
||||
"status.quote_error.filtered": "Ausgeblendet wegen eines deiner Filter",
|
||||
"status.quote_error.limited_account_hint.action": "Trotzdem anzeigen",
|
||||
"status.quote_error.limited_account_hint.title": "Dieses Profil wurde von den Moderator*innen von {domain} ausgeblendet.",
|
||||
"status.quote_error.muted_account_hint.title": "Dieser Beitrag wurde ausgeblendet, weil du @{name} stummgeschaltet hast.",
|
||||
"status.quote_error.not_available": "Beitrag nicht verfügbar",
|
||||
"status.quote_error.pending_approval": "Beitragsveröffentlichung ausstehend",
|
||||
"status.quote_error.pending_approval_popout.body": "Auf Mastodon kann festgelegt werden, ob man zitiert werden möchte. Wir warten auf die Genehmigung des ursprünglichen Profils. Bis dahin steht deine Beitragsveröffentlichung noch aus.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Leiser",
|
||||
"video.volume_up": "Lauter",
|
||||
"visibility_modal.button_title": "Sichtbarkeit festlegen",
|
||||
"visibility_modal.direct_quote_warning.text": "Wenn diese Einstellungen gespeichert werden, wird das eingebettete Zitat in einen Link umgewandelt.",
|
||||
"visibility_modal.direct_quote_warning.title": "Zitate können in privaten Erwähnungen nicht eingebettet werden",
|
||||
"visibility_modal.header": "Sichtbarkeit und Interaktion",
|
||||
"visibility_modal.helper.direct_quoting": "Private Erwähnungen, die auf Mastodon verfasst wurden, können nicht von anderen zitiert werden.",
|
||||
"visibility_modal.helper.privacy_editing": "Die Sichtbarkeit eines bereits veröffentlichten Beitrags kann nachträglich nicht mehr geändert werden.",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Επεξεργασία λίστας",
|
||||
"column.favourites": "Αγαπημένα",
|
||||
"column.firehose": "Ζωντανές ροές",
|
||||
"column.firehose_local": "Ζωντανή ροή για αυτόν τον διακομιστή",
|
||||
"column.firehose_singular": "Ζωντανή ροή",
|
||||
"column.follow_requests": "Αιτήματα ακολούθησης",
|
||||
"column.home": "Αρχική",
|
||||
"column.list_members": "Διαχείριση μελών λίστας",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Τοπικά μόνο",
|
||||
"community.column_settings.media_only": "Μόνο πολυμέσα",
|
||||
"community.column_settings.remote_only": "Απομακρυσμένα μόνο",
|
||||
"compose.error.blank_post": "Η ανάρτηση δεν μπορεί να είναι κενή.",
|
||||
"compose.language.change": "Αλλαγή γλώσσας",
|
||||
"compose.language.search": "Αναζήτηση γλωσσών...",
|
||||
"compose.published.body": "Η ανάρτηση δημοσιεύτηκε.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Δημοσίευση όπως και να ΄χει",
|
||||
"confirmations.missing_alt_text.title": "Προσθήκη εναλλακτικού κειμένου;",
|
||||
"confirmations.mute.confirm": "Αποσιώπηση",
|
||||
"confirmations.private_quote_notify.cancel": "Πίσω στην επεξεργασία",
|
||||
"confirmations.private_quote_notify.confirm": "Δημοσίευση ανάρτησης",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Να μην εμφανιστεί ξανά αυτό το μήνυμα",
|
||||
"confirmations.private_quote_notify.message": "Το άτομο που παραθέτετε και άλλες επισημάνσεις θα ειδοποιηθούν και θα μπορούν να δουν την ανάρτησή σας, ακόμη και αν δεν σας ακολουθούν.",
|
||||
"confirmations.private_quote_notify.title": "Κοινοποίηση με τους ακολούθους και τους επισημασμένους χρήστες;",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Μη μου το ξαναθυμίσεις",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Το κατάλαβα",
|
||||
"confirmations.quiet_post_quote_info.message": "Όταν παραθέτετε μια ήσυχη δημόσια ανάρτηση, η ανάρτηση σας θα είναι κρυμμένη από τις δημοφιλείς ροές.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Δεν έχεις καμία ανάρτηση με σελιδοδείκτη ακόμα. Μόλις βάλεις κάποιον, θα εμφανιστεί εδώ.",
|
||||
"empty_column.community": "Η τοπική ροή είναι κενή. Γράψε κάτι δημόσια για να αρχίσει να κυλά η μπάλα!",
|
||||
"empty_column.direct": "Δεν έχεις καμία προσωπική επισήμανση ακόμα. Όταν στείλεις ή λάβεις μία, θα εμφανιστεί εδώ.",
|
||||
"empty_column.disabled_feed": "Αυτή η ροή έχει απενεργοποιηθεί από τους διαχειριστές του διακομιστή σας.",
|
||||
"empty_column.domain_blocks": "Δεν υπάρχουν αποκλεισμένοι τομείς ακόμα.",
|
||||
"empty_column.explore_statuses": "Τίποτα δεν βρίσκεται στις τάσεις αυτή τη στιγμή. Έλεγξε αργότερα!",
|
||||
"empty_column.favourited_statuses": "Δεν έχεις καμία αγαπημένη ανάρτηση ακόμα. Μόλις αγαπήσεις κάποια, θα εμφανιστεί εδώ.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Πολιτική Απορρήτου",
|
||||
"quote_error.edit": "Δεν μπορούν να προστεθούν παραθέσεις κατά την επεξεργασία μιας ανάρτησης.",
|
||||
"quote_error.poll": "Η παράθεση δεν επιτρέπεται με δημοσκοπήσεις.",
|
||||
"quote_error.private_mentions": "Η παράθεση δεν επιτρέπεται με άμεσες επισημάνσεις.",
|
||||
"quote_error.quote": "Επιτρέπεται μόνο μία παράθεση τη φορά.",
|
||||
"quote_error.unauthorized": "Δεν είστε εξουσιοδοτημένοι να παραθέσετε αυτή την ανάρτηση.",
|
||||
"quote_error.upload": "Η παράθεση δεν επιτρέπεται με συνημμένα πολυμέσων.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Καρφίτσωσε στο προφίλ",
|
||||
"status.quote": "Παράθεση",
|
||||
"status.quote.cancel": "Ακύρωση παράθεσης",
|
||||
"status.quote_error.blocked_account_hint.title": "Αυτή η ανάρτηση είναι κρυμμένη επειδή έχετε μπλοκάρει τον/την @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Αυτή η ανάρτηση είναι κρυμμένη επειδή έχετε μπλοκάρει το {domain}.",
|
||||
"status.quote_error.filtered": "Κρυφό λόγω ενός από τα φίλτρα σου",
|
||||
"status.quote_error.limited_account_hint.action": "Εμφάνιση ούτως ή άλλως",
|
||||
"status.quote_error.limited_account_hint.title": "Αυτό το προφίλ έχει αποκρυφτεί από τους διαχειριστές του διακομιστή {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Αυτή η ανάρτηση είναι κρυμμένη επειδή έχετε κάνει σίγαση τον/την @{name}.",
|
||||
"status.quote_error.not_available": "Ανάρτηση μη διαθέσιμη",
|
||||
"status.quote_error.pending_approval": "Ανάρτηση σε αναμονή",
|
||||
"status.quote_error.pending_approval_popout.body": "Στο Mastodon, μπορείς να ελέγξεις αν κάποιος μπορεί να σε παραθέσει. Αυτή η ανάρτηση εκκρεμεί ενώ λαμβάνουμε την έγκριση του αρχικού συντάκτη.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Μείωση έντασης",
|
||||
"video.volume_up": "Αύξηση έντασης",
|
||||
"visibility_modal.button_title": "Ορισμός ορατότητας",
|
||||
"visibility_modal.direct_quote_warning.text": "Εάν αποθηκεύσετε τις τρέχουσες ρυθμίσεις, η ενσωματωμένη παράθεση θα μετατραπεί σε σύνδεσμο.",
|
||||
"visibility_modal.direct_quote_warning.title": "Οι παραθέσεις δεν μπορούν να ενσωματωθούν σε ιδιωτικές επισημάνσεις",
|
||||
"visibility_modal.header": "Ορατότητα και αλληλεπίδραση",
|
||||
"visibility_modal.helper.direct_quoting": "Ιδιωτικές αναφορές που έχουν συνταχθεί στο Mastodon δεν μπορούν να γίνουν παράθεση από άλλους.",
|
||||
"visibility_modal.helper.privacy_editing": "Η ορατότητα δεν μπορεί να αλλάξει μετά τη δημοσίευση μιας ανάρτησης.",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Edit list",
|
||||
"column.favourites": "Favorites",
|
||||
"column.firehose": "Live feeds",
|
||||
"column.firehose_local": "Live feed for this server",
|
||||
"column.firehose_singular": "Live feed",
|
||||
"column.follow_requests": "Follow requests",
|
||||
"column.home": "Home",
|
||||
"column.list_members": "Manage list members",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Local only",
|
||||
"community.column_settings.media_only": "Media Only",
|
||||
"community.column_settings.remote_only": "Remote only",
|
||||
"compose.error.blank_post": "Post can't be blank.",
|
||||
"compose.language.change": "Change language",
|
||||
"compose.language.search": "Search languages...",
|
||||
"compose.published.body": "Post published.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Post anyway",
|
||||
"confirmations.missing_alt_text.title": "Add alt text?",
|
||||
"confirmations.mute.confirm": "Mute",
|
||||
"confirmations.private_quote_notify.cancel": "Back to editing",
|
||||
"confirmations.private_quote_notify.confirm": "Publish post",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Don't show me this message again",
|
||||
"confirmations.private_quote_notify.message": "The person you are quoting and other mentions will be notified and will be able to view your post, even if they're not following you.",
|
||||
"confirmations.private_quote_notify.title": "Share with followers and mentioned users?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Don't remind me again",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Got it",
|
||||
"confirmations.quiet_post_quote_info.message": "When quoting a quiet public post, your post will be hidden from trending timelines.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "You don't have any bookmarked posts yet. When you bookmark one, it will show up here.",
|
||||
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
|
||||
"empty_column.direct": "You don't have any private mentions yet. When you send or receive one, it will show up here.",
|
||||
"empty_column.disabled_feed": "This feed has been disabled by your server administrators.",
|
||||
"empty_column.domain_blocks": "There are no blocked domains yet.",
|
||||
"empty_column.explore_statuses": "Nothing is trending right now. Check back later!",
|
||||
"empty_column.favourited_statuses": "You don't have any favorite posts yet. When you favorite one, it will show up here.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Privacy Policy",
|
||||
"quote_error.edit": "Quotes cannot be added when editing a post.",
|
||||
"quote_error.poll": "Quoting is not allowed with polls.",
|
||||
"quote_error.private_mentions": "Quoting is not allowed with direct mentions.",
|
||||
"quote_error.quote": "Only one quote at a time is allowed.",
|
||||
"quote_error.unauthorized": "You are not authorized to quote this post.",
|
||||
"quote_error.upload": "Quoting is not allowed with media attachments.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Pin on profile",
|
||||
"status.quote": "Quote",
|
||||
"status.quote.cancel": "Cancel quote",
|
||||
"status.quote_error.blocked_account_hint.title": "This post is hidden because you've blocked @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "This post is hidden because you've blocked {domain}.",
|
||||
"status.quote_error.filtered": "Hidden due to one of your filters",
|
||||
"status.quote_error.limited_account_hint.action": "Show anyway",
|
||||
"status.quote_error.limited_account_hint.title": "This account has been hidden by the moderators of {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "This post is hidden because you've muted @{name}.",
|
||||
"status.quote_error.not_available": "Post unavailable",
|
||||
"status.quote_error.pending_approval": "Post pending",
|
||||
"status.quote_error.pending_approval_popout.body": "On Chinwag, you can control whether someone can quote you. This post is pending while we're getting the original author's approval.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Volume down",
|
||||
"video.volume_up": "Volume up",
|
||||
"visibility_modal.button_title": "Set visibility",
|
||||
"visibility_modal.direct_quote_warning.text": "If you save the current settings, the embedded quote will be converted to a link.",
|
||||
"visibility_modal.direct_quote_warning.title": "Quotes can't be embedded in private mentions",
|
||||
"visibility_modal.header": "Visibility and interaction",
|
||||
"visibility_modal.helper.direct_quoting": "Private mentions authored on Chinwag can't be quoted by others.",
|
||||
"visibility_modal.helper.privacy_editing": "Visibility can't be changed after a post is published.",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
"account.featured_tags.last_status_never": "Neniu afiŝo",
|
||||
"account.follow": "Sekvi",
|
||||
"account.follow_back": "Sekvu reen",
|
||||
"account.follow_back_short": "Sekvu reen",
|
||||
"account.followers": "Sekvantoj",
|
||||
"account.followers.empty": "Ankoraŭ neniu sekvas ĉi tiun uzanton.",
|
||||
"account.followers_counter": "{count, plural, one{{counter} sekvanto} other {{counter} sekvantoj}}",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Editar lista",
|
||||
"column.favourites": "Favoritos",
|
||||
"column.firehose": "Líneas temporales en vivo",
|
||||
"column.firehose_local": "Línea temporal en vivo para este servidor",
|
||||
"column.firehose_singular": "Línea temporal en vivo",
|
||||
"column.follow_requests": "Solicitudes de seguimiento",
|
||||
"column.home": "Principal",
|
||||
"column.list_members": "Administrar miembros de la lista",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Sólo local",
|
||||
"community.column_settings.media_only": "Sólo medios",
|
||||
"community.column_settings.remote_only": "Sólo remoto",
|
||||
"compose.error.blank_post": "El mensaje no puede estar en blanco.",
|
||||
"compose.language.change": "Cambiar idioma",
|
||||
"compose.language.search": "Buscar idiomas…",
|
||||
"compose.published.body": "Mensaje publicado.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Enviar de todos modos",
|
||||
"confirmations.missing_alt_text.title": "¿Agregar texto alternativo?",
|
||||
"confirmations.mute.confirm": "Silenciar",
|
||||
"confirmations.private_quote_notify.cancel": "Volver a editar",
|
||||
"confirmations.private_quote_notify.confirm": "Enviar mensaje",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "No mostrarme este mensaje de nuevo",
|
||||
"confirmations.private_quote_notify.message": "La cuenta a la que estás citando y otras menciones serán notificadas y podrán ver tu mensaje, incluso si no te están siguiendo.",
|
||||
"confirmations.private_quote_notify.title": "¿Compartir con seguidores y usuarios mencionados?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "No recordar de nuevo",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Entendido",
|
||||
"confirmations.quiet_post_quote_info.message": "Al citar un mensaje público pero silencioso, tu mensaje se ocultará de las líneas temporales de tendencias.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Todavía no tenés mensajes guardados en \"Marcadores\". Cuando guardés uno en \"Marcadores\", se mostrará acá.",
|
||||
"empty_column.community": "La línea temporal local está vacía. ¡Escribí algo en modo público para que se empiece a correr la bola!",
|
||||
"empty_column.direct": "Todavía no tenés ninguna mención privada. Cuando enviés o recibás una, se mostrará acá.",
|
||||
"empty_column.disabled_feed": "Esta línea temporal fue deshabilitada por los administradores de tu servidor.",
|
||||
"empty_column.domain_blocks": "Todavía no hay dominios bloqueados.",
|
||||
"empty_column.explore_statuses": "No hay nada en tendencia ahora mismo. ¡Volvé a revisar más tarde!",
|
||||
"empty_column.favourited_statuses": "Todavía no tenés mensajes favoritos. Cuando marqués uno como favorito, se mostrará acá.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Política de privacidad",
|
||||
"quote_error.edit": "Las citas no se pueden agregar al editar un mensaje.",
|
||||
"quote_error.poll": "No se permite citar encuestas.",
|
||||
"quote_error.private_mentions": "No se permite citar con menciones directas.",
|
||||
"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.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Fijar en el perfil",
|
||||
"status.quote": "Citar",
|
||||
"status.quote.cancel": "Cancelar cita",
|
||||
"status.quote_error.blocked_account_hint.title": "Este mensaje está oculto porque bloqueaste a @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Este mensaje está oculto porque bloqueaste {domain}.",
|
||||
"status.quote_error.filtered": "Oculto debido a uno de tus filtros",
|
||||
"status.quote_error.limited_account_hint.action": "Mostrar de todos modos",
|
||||
"status.quote_error.limited_account_hint.title": "Esta cuenta fue ocultada por los moderadores de {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Este mensaje está oculto porque silenciaste a @{name}.",
|
||||
"status.quote_error.not_available": "Mensaje no disponible",
|
||||
"status.quote_error.pending_approval": "Mensaje pendiente",
|
||||
"status.quote_error.pending_approval_popout.body": "En Mastodon, podés controlar si alguien te puede citar. Este mensaje está pendiente hasta obtener la aprobación del autor original.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Bajar volumen",
|
||||
"video.volume_up": "Subir volumen",
|
||||
"visibility_modal.button_title": "Establecer visibilidad",
|
||||
"visibility_modal.direct_quote_warning.text": "Si guardás la configuración actual, la cita insertada se convertirá en un enlace.",
|
||||
"visibility_modal.direct_quote_warning.title": "Las citas no pueden ser insertadas en menciones privadas",
|
||||
"visibility_modal.header": "Visibilidad e interacción",
|
||||
"visibility_modal.helper.direct_quoting": "Las menciones privadas redactadas en Mastodon no pueden ser citadas por otras cuentas.",
|
||||
"visibility_modal.helper.privacy_editing": "La visibilidad no se puede cambiar después de que se haya enviado un mensaje.",
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
"account.follow": "Seguir",
|
||||
"account.follow_back": "Seguir también",
|
||||
"account.follow_back_short": "Seguir también",
|
||||
"account.follow_request": "Solicitud de seguimiento",
|
||||
"account.follow_request": "Solicitar seguimiento",
|
||||
"account.follow_request_cancel": "Cancelar solicitud",
|
||||
"account.follow_request_cancel_short": "Cancelar",
|
||||
"account.follow_request_short": "Solicitar",
|
||||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Editar lista",
|
||||
"column.favourites": "Favoritos",
|
||||
"column.firehose": "Cronologías",
|
||||
"column.firehose_local": "Feed en vivo para este servidor",
|
||||
"column.firehose_singular": "Feed en vivo",
|
||||
"column.follow_requests": "Solicitudes de seguimiento",
|
||||
"column.home": "Inicio",
|
||||
"column.list_members": "Administrar miembros de la lista",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Solo local",
|
||||
"community.column_settings.media_only": "Solo media",
|
||||
"community.column_settings.remote_only": "Solo remoto",
|
||||
"compose.error.blank_post": "La publicación no puede estar vacía.",
|
||||
"compose.language.change": "Cambiar idioma",
|
||||
"compose.language.search": "Buscar idiomas...",
|
||||
"compose.published.body": "Publicado.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Publicar de todas maneras",
|
||||
"confirmations.missing_alt_text.title": "¿Añadir texto alternativo?",
|
||||
"confirmations.mute.confirm": "Silenciar",
|
||||
"confirmations.private_quote_notify.cancel": "Seguir editando",
|
||||
"confirmations.private_quote_notify.confirm": "Publicar",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "No mostrar este mensaje de nuevo",
|
||||
"confirmations.private_quote_notify.message": "Tu publicación será notificada y podrá ser vista por la persona a la que mencionas y otras menciones, aún si no te siguen.",
|
||||
"confirmations.private_quote_notify.title": "¿Compartir con seguidores y usuarios mencionados?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "No me lo recuerdes otra vez",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Entendido",
|
||||
"confirmations.quiet_post_quote_info.message": "Al citar una publicación pública discreta, tu publicación se ocultará de las cronologías de tendencias.",
|
||||
|
|
@ -261,8 +269,8 @@
|
|||
"confirmations.unblock.title": "¿Desbloquear a {name}?",
|
||||
"confirmations.unfollow.confirm": "Dejar de seguir",
|
||||
"confirmations.unfollow.title": "¿Dejar de seguir a {name}?",
|
||||
"confirmations.withdraw_request.confirm": "Retirar solicitud",
|
||||
"confirmations.withdraw_request.title": "¿Retirar solicitud de seguimiento a {name}?",
|
||||
"confirmations.withdraw_request.confirm": "Cancelar solicitud",
|
||||
"confirmations.withdraw_request.title": "¿Cancelar solicitud para seguir a {name}?",
|
||||
"content_warning.hide": "Ocultar publicación",
|
||||
"content_warning.show": "Mostrar de todos modos",
|
||||
"content_warning.show_more": "Mostrar más",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Aún no tienes ninguna publicación guardada como marcador. Cuando guardes una, se mostrará aquí.",
|
||||
"empty_column.community": "La cronología local está vacía. ¡Escribe algo públicamente para ponerla en marcha!",
|
||||
"empty_column.direct": "Aún no tienes menciones privadas. Cuando envíes o recibas una, aparecerán aquí.",
|
||||
"empty_column.disabled_feed": "Este feed fue desactivado por los administradores de tu servidor.",
|
||||
"empty_column.domain_blocks": "Todavía no hay dominios ocultos.",
|
||||
"empty_column.explore_statuses": "Nada es tendencia en este momento. ¡Revisa más tarde!",
|
||||
"empty_column.favourited_statuses": "Todavía no tienes publicaciones favoritas. Cuando le des favorito a una publicación se mostrarán acá.",
|
||||
|
|
@ -753,8 +762,9 @@
|
|||
"privacy.unlisted.short": "Pública, pero discreta",
|
||||
"privacy_policy.last_updated": "Actualizado por última vez {date}",
|
||||
"privacy_policy.title": "Política de Privacidad",
|
||||
"quote_error.edit": "No se pueden añadir citas cuando se edita una publicación.",
|
||||
"quote_error.edit": "No se pueden añadir citas mientras un post está siendo editado.",
|
||||
"quote_error.poll": "No se permite citar encuestas.",
|
||||
"quote_error.private_mentions": "Citar no está disponible sin menciones directas.",
|
||||
"quote_error.quote": "Solo se permite una cita a la vez.",
|
||||
"quote_error.unauthorized": "No estás autorizado a citar esta publicación.",
|
||||
"quote_error.upload": "No se permite citar con archivos multimedia.",
|
||||
|
|
@ -876,7 +886,7 @@
|
|||
"status.contains_quote": "Contiene cita",
|
||||
"status.context.loading": "Cargando más respuestas",
|
||||
"status.context.loading_error": "No se pudieron cargar nuevas respuestas",
|
||||
"status.context.loading_success": "Cargadas nuevas respuestas",
|
||||
"status.context.loading_success": "Nuevas respuestas cargadas",
|
||||
"status.context.more_replies_found": "Se han encontrado más respuestas",
|
||||
"status.context.retry": "Reintentar",
|
||||
"status.context.show": "Mostrar",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Fijar",
|
||||
"status.quote": "Citar",
|
||||
"status.quote.cancel": "Cancelar cita",
|
||||
"status.quote_error.blocked_account_hint.title": "Esta publicación se ocultó porque bloqueaste a @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Esta publicación está oculta porque has bloqueado @{domain}.",
|
||||
"status.quote_error.filtered": "Oculto debido a uno de tus filtros",
|
||||
"status.quote_error.limited_account_hint.action": "Mostrar de todas formas",
|
||||
"status.quote_error.limited_account_hint.title": "Esta cuenta ha sido ocultada por los moderadores de {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Esta publicación está oculta porque has silenciado a @{name}.",
|
||||
"status.quote_error.not_available": "Publicación no disponible",
|
||||
"status.quote_error.pending_approval": "Publicación pendiente",
|
||||
"status.quote_error.pending_approval_popout.body": "En Mastodon, puedes controlar si alguien puede citarte. Esta publicación está pendiente mientras obtenemos la aprobación del autor original.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Bajar el volumen",
|
||||
"video.volume_up": "Subir el volumen",
|
||||
"visibility_modal.button_title": "Establece la visibilidad",
|
||||
"visibility_modal.direct_quote_warning.text": "Si guardas la siguiente configuración, se mostrará un enlace en vez de la cita incrustada.",
|
||||
"visibility_modal.direct_quote_warning.title": "No se pueden incrustar citas en menciones privadas",
|
||||
"visibility_modal.header": "Visibilidad e interacción",
|
||||
"visibility_modal.helper.direct_quoting": "Las menciones privadas creadas en Mastodon no pueden ser citadas por otros.",
|
||||
"visibility_modal.helper.privacy_editing": "La visibilidad no se puede cambiar después de que se haya hecho una publicación.",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Editar lista",
|
||||
"column.favourites": "Favoritos",
|
||||
"column.firehose": "Cronologías",
|
||||
"column.firehose_local": "Cronología para este servidor",
|
||||
"column.firehose_singular": "Cronología",
|
||||
"column.follow_requests": "Solicitudes de seguimiento",
|
||||
"column.home": "Inicio",
|
||||
"column.list_members": "Administrar miembros de la lista",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Solo local",
|
||||
"community.column_settings.media_only": "Solo multimedia",
|
||||
"community.column_settings.remote_only": "Solo remoto",
|
||||
"compose.error.blank_post": "El mensaje no puede estar en blanco.",
|
||||
"compose.language.change": "Cambiar idioma",
|
||||
"compose.language.search": "Buscar idiomas...",
|
||||
"compose.published.body": "Publicado.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Publicar de todos modos",
|
||||
"confirmations.missing_alt_text.title": "¿Deseas añadir texto alternativo?",
|
||||
"confirmations.mute.confirm": "Silenciar",
|
||||
"confirmations.private_quote_notify.cancel": "Volver a editar",
|
||||
"confirmations.private_quote_notify.confirm": "Publicar",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "No mostrar este mensaje de nuevo",
|
||||
"confirmations.private_quote_notify.message": "La persona a la que estás citando y otras mencionadas serán notificadas y podrán ver tu publicación, incluso si no te siguen.",
|
||||
"confirmations.private_quote_notify.title": "¿Compartir con seguidores y usuarios mencionados?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "No me lo vuelvas a recordar",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Entendido",
|
||||
"confirmations.quiet_post_quote_info.message": "Cuando cites una publicación pública silenciosa, tu publicación se ocultará de las cronologías de tendencias.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Aún no tienes ninguna publicación guardada como marcador. Cuando guardes una, se mostrará aquí.",
|
||||
"empty_column.community": "La línea de tiempo local está vacía. ¡Escribe algo para empezar la fiesta!",
|
||||
"empty_column.direct": "Aún no tienes menciones privadas. Cuando envíes o recibas una, aparecerán aquí.",
|
||||
"empty_column.disabled_feed": "Esta cronología ha sido desactivada por los administradores del servidor.",
|
||||
"empty_column.domain_blocks": "Todavía no hay dominios bloqueados.",
|
||||
"empty_column.explore_statuses": "No hay nada en tendencia en este momento. ¡Revisa más tarde!",
|
||||
"empty_column.favourited_statuses": "Todavía no tienes publicaciones favoritas. Cuando marques una publicación como favorita, se mostrarán aquí.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Política de Privacidad",
|
||||
"quote_error.edit": "No se pueden añadir citas cuando se edita una publicación.",
|
||||
"quote_error.poll": "No es posible citar encuestas.",
|
||||
"quote_error.private_mentions": "No se permite citar con menciones privadas.",
|
||||
"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.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Fijar",
|
||||
"status.quote": "Citar",
|
||||
"status.quote.cancel": "Cancelar cita",
|
||||
"status.quote_error.blocked_account_hint.title": "Esta publicación está oculta porque has bloqueado a @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Esta publicación está oculta porque has bloqueado @{domain}.",
|
||||
"status.quote_error.filtered": "Oculto debido a uno de tus filtros",
|
||||
"status.quote_error.limited_account_hint.action": "Mostrar de todos modos",
|
||||
"status.quote_error.limited_account_hint.title": "Esta cuenta ha sido ocultada por los moderadores de {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Esta publicación está oculta porque has silenciado a @{name}.",
|
||||
"status.quote_error.not_available": "Publicación no disponible",
|
||||
"status.quote_error.pending_approval": "Publicación pendiente",
|
||||
"status.quote_error.pending_approval_popout.body": "En Mastodon, puedes controlar si alguien puede citarte. Esta publicación está pendiente mientras obtenemos la aprobación del autor original.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Bajar volumen",
|
||||
"video.volume_up": "Subir volumen",
|
||||
"visibility_modal.button_title": "Configura la visibilidad",
|
||||
"visibility_modal.direct_quote_warning.text": "Si guardas la configuración actual, la cita incrustada se convertirá en un enlace.",
|
||||
"visibility_modal.direct_quote_warning.title": "No se pueden incluir citas en menciones privadas",
|
||||
"visibility_modal.header": "Visibilidad e interacciones",
|
||||
"visibility_modal.helper.direct_quoting": "Las menciones privadas publicadas en Mastodon no pueden ser citadas por otros usuarios.",
|
||||
"visibility_modal.helper.privacy_editing": "La visibilidad no se puede cambiar después de que se haya hecho una publicación.",
|
||||
|
|
|
|||
|
|
@ -64,10 +64,10 @@
|
|||
"account.media": "Meedia",
|
||||
"account.mention": "Maini @{name}",
|
||||
"account.moved_to": "{name} on teada andnud, et ta uus konto on nüüd:",
|
||||
"account.mute": "Vaigista @{name}",
|
||||
"account.mute_notifications_short": "Vaigista teavitused",
|
||||
"account.mute_short": "Vaigista",
|
||||
"account.muted": "Vaigistatud",
|
||||
"account.mute": "Summuta @{name}",
|
||||
"account.mute_notifications_short": "Summuta teavitused",
|
||||
"account.mute_short": "Summuta",
|
||||
"account.muted": "Summutatud",
|
||||
"account.muting": "Summutatud konto",
|
||||
"account.mutual": "Te jälgite teineteist",
|
||||
"account.no_bio": "Kirjeldust pole lisatud.",
|
||||
|
|
@ -87,9 +87,9 @@
|
|||
"account.unblock_short": "Eemalda blokeering",
|
||||
"account.unendorse": "Ära kuva profiilil",
|
||||
"account.unfollow": "Jälgid",
|
||||
"account.unmute": "Ära vaigista @{name}",
|
||||
"account.unmute_notifications_short": "Tühista teadete vaigistamine",
|
||||
"account.unmute_short": "Lõpeta vaigistamine",
|
||||
"account.unmute": "Lõpeta {name} kasutaja summutamine",
|
||||
"account.unmute_notifications_short": "Lõpeta teavituste summutamine",
|
||||
"account.unmute_short": "Lõpeta summutamine",
|
||||
"account_note.placeholder": "Klõpsa märke lisamiseks",
|
||||
"admin.dashboard.daily_retention": "Kasutajate päevane allesjäämine peale registreerumist",
|
||||
"admin.dashboard.monthly_retention": "Kasutajate kuine allesjäämine peale registreerumist",
|
||||
|
|
@ -173,11 +173,13 @@
|
|||
"column.edit_list": "Muuda loendit",
|
||||
"column.favourites": "Lemmikud",
|
||||
"column.firehose": "Postitused reaalajas",
|
||||
"column.firehose_local": "Selle serveri sisuvoog reaalajas",
|
||||
"column.firehose_singular": "Postitused reaalajas",
|
||||
"column.follow_requests": "Jälgimistaotlused",
|
||||
"column.home": "Kodu",
|
||||
"column.list_members": "Halda loendi liikmeid",
|
||||
"column.lists": "Loetelud",
|
||||
"column.mutes": "Vaigistatud kasutajad",
|
||||
"column.mutes": "Summutatud kasutajad",
|
||||
"column.notifications": "Teated",
|
||||
"column.pins": "Kinnitatud postitused",
|
||||
"column.public": "Föderatiivne ajajoon",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Ainult kohalik",
|
||||
"community.column_settings.media_only": "Ainult meedia",
|
||||
"community.column_settings.remote_only": "Ainult kaug",
|
||||
"compose.error.blank_post": "Postitus ei saa jääda tühjaks.",
|
||||
"compose.language.change": "Muuda keelt",
|
||||
"compose.language.search": "Otsi keeli...",
|
||||
"compose.published.body": "Postitus tehtud.",
|
||||
|
|
@ -243,7 +246,12 @@
|
|||
"confirmations.missing_alt_text.message": "Sinu postituses on ilma alt-tekstita meediat. Kirjelduse lisamine aitab su sisu muuta ligipääsetavaks rohkematele inimestele.",
|
||||
"confirmations.missing_alt_text.secondary": "Postita siiski",
|
||||
"confirmations.missing_alt_text.title": "Lisada alt-tekst?",
|
||||
"confirmations.mute.confirm": "Vaigista",
|
||||
"confirmations.mute.confirm": "Summuta",
|
||||
"confirmations.private_quote_notify.cancel": "Tagasi muutmise juurde",
|
||||
"confirmations.private_quote_notify.confirm": "Avalda postitus",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Ära kuva enam seda sõnumit uuesti",
|
||||
"confirmations.private_quote_notify.message": "Nii see, keda sa tsiteerid, kui need, keda mainid, saavad asjakohase teavituse ja võivad vaadata sinu postitust ka siis, kui nad pole sinu jälgijad.",
|
||||
"confirmations.private_quote_notify.title": "Kas jagad jälgijate ja mainitud kasutajatega?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Ära tuleta enam meelde",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Sain aru",
|
||||
"confirmations.quiet_post_quote_info.message": "Vaikse, aga avaliku postituse tsiteerimisel sinu postitus on peidetud populaarsust koguvatel ajajoontel.",
|
||||
|
|
@ -287,7 +295,7 @@
|
|||
"domain_block_modal.they_can_interact_with_old_posts": "Inimesed sellest serverist saavad suhestuda sinu vanade postitustega.",
|
||||
"domain_block_modal.they_cant_follow": "Sellest serverist ei saa keegi sind jälgida.",
|
||||
"domain_block_modal.they_wont_know": "Nad ei tea, et nad on blokeeritud.",
|
||||
"domain_block_modal.title": "Blokeerida domeen?",
|
||||
"domain_block_modal.title": "Kas blokeerid domeeni?",
|
||||
"domain_block_modal.you_will_lose_num_followers": "Sult kaob {followersCount, plural, one {{followersCountDisplay} jälgija} other {{followersCountDisplay} jälgijat}} ja {followingCount, plural, one {{followingCountDisplay} inimene} other {{followingCountDisplay} inimest}}, keda sa ise jälgid.",
|
||||
"domain_block_modal.you_will_lose_relationships": "Sa kaotad kõik oma jälgijad ja inimesed, kes sind jälgivad sellest serverist.",
|
||||
"domain_block_modal.you_wont_see_posts": "Sa ei näe selle serveri kasutajate postitusi ega teavitusi.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Järjehoidjatesse pole veel lisatud postitusi. Kui lisad mõne, näed neid siin.",
|
||||
"empty_column.community": "Kohalik ajajoon on tühi. Kirjuta midagi avalikult, et pall veerema ajada!",
|
||||
"empty_column.direct": "Sul pole veel ühtegi privaatset mainimist. Kui saadad või saad mõne, ilmuvad need siin.",
|
||||
"empty_column.disabled_feed": "See infovoog on serveri peakasutajate poolt välja lülitatud.",
|
||||
"empty_column.domain_blocks": "Siin ei ole veel peidetud domeene.",
|
||||
"empty_column.explore_statuses": "Praegu pole ühtegi trendi. Tule hiljem tagasi!",
|
||||
"empty_column.favourited_statuses": "Pole veel lemmikpostitusi. Kui märgid mõne, näed neid siin.",
|
||||
|
|
@ -342,7 +351,7 @@
|
|||
"empty_column.hashtag": "Selle sildi all ei ole ühtegi postitust.",
|
||||
"empty_column.home": "Su koduajajoon on tühi. Jälgi rohkemaid inimesi, et seda täita {suggestions}",
|
||||
"empty_column.list": "Siin loetelus pole veel midagi. Kui loetelu liikmed teevad uusi postitusi, näed neid siin.",
|
||||
"empty_column.mutes": "Sa pole veel ühtegi kasutajat vaigistanud.",
|
||||
"empty_column.mutes": "Sa pole veel ühtegi kasutajat summutanud.",
|
||||
"empty_column.notification_requests": "Kõik tühi! Siin pole mitte midagi. Kui saad uusi teavitusi, ilmuvad need siin vastavalt sinu seadistustele.",
|
||||
"empty_column.notifications": "Ei ole veel teateid. Kui keegi suhtleb sinuga, näed seda siin.",
|
||||
"empty_column.public": "Siin pole midagi! Kirjuta midagi avalikku või jälgi ise kasutajaid täitmaks seda ruumi",
|
||||
|
|
@ -430,7 +439,7 @@
|
|||
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} postitust} other {{counter} postitust}} täna",
|
||||
"hashtag.feature": "Tõsta profiilis esile",
|
||||
"hashtag.follow": "Jälgi silti",
|
||||
"hashtag.mute": "Vaigista @#{hashtag}",
|
||||
"hashtag.mute": "Summuta teemaviide @#{hashtag}",
|
||||
"hashtag.unfeature": "Ära tõsta profiilis esile",
|
||||
"hashtag.unfollow": "Lõpeta sildi jälgimine",
|
||||
"hashtags.and_other": "…ja {count, plural, one {}other {# veel}}",
|
||||
|
|
@ -490,7 +499,7 @@
|
|||
"keyboard_shortcuts.load_more": "Fookus „Laadi veel“ nupule",
|
||||
"keyboard_shortcuts.local": "Ava kohalik ajajoon",
|
||||
"keyboard_shortcuts.mention": "Maini autorit",
|
||||
"keyboard_shortcuts.muted": "Ava vaigistatud kasutajate loetelu",
|
||||
"keyboard_shortcuts.muted": "Ava summutatud kasutajate loetelu",
|
||||
"keyboard_shortcuts.my_profile": "Ava oma profiil",
|
||||
"keyboard_shortcuts.notifications": "Ava teadete veerg",
|
||||
"keyboard_shortcuts.open_media": "Ava meedia",
|
||||
|
|
@ -551,11 +560,11 @@
|
|||
"moved_to_account_banner.text": "Kontot {disabledAccount} ei ole praegu võimalik kasutada, sest kolisid kontole {movedToAccount}.",
|
||||
"mute_modal.hide_from_notifications": "Peida teavituste hulgast",
|
||||
"mute_modal.hide_options": "Peida valikud",
|
||||
"mute_modal.indefinite": "Kuni eemaldan neilt vaigistuse",
|
||||
"mute_modal.indefinite": "Kuni eemaldan neilt summutamise",
|
||||
"mute_modal.show_options": "Kuva valikud",
|
||||
"mute_modal.they_can_mention_and_follow": "Ta saab sind mainida ja sind jälgida, kuid sa ei näe teda.",
|
||||
"mute_modal.they_wont_know": "Ta ei tea, et ta on vaigistatud.",
|
||||
"mute_modal.title": "Vaigistada kasutaja?",
|
||||
"mute_modal.they_wont_know": "Ta ei tea, et ta on summutatud.",
|
||||
"mute_modal.title": "Kas summutad kasutaja?",
|
||||
"mute_modal.you_wont_see_mentions": "Sa ei näe postitusi, mis teda mainivad.",
|
||||
"mute_modal.you_wont_see_posts": "Ta näeb jätkuvalt sinu postitusi, kuid sa ei näe tema omi.",
|
||||
"navigation_bar.about": "Teave",
|
||||
|
|
@ -568,7 +577,7 @@
|
|||
"navigation_bar.direct": "Privaatsed mainimised",
|
||||
"navigation_bar.domain_blocks": "Peidetud domeenid",
|
||||
"navigation_bar.favourites": "Lemmikud",
|
||||
"navigation_bar.filters": "Vaigistatud sõnad",
|
||||
"navigation_bar.filters": "Summutatud sõnad",
|
||||
"navigation_bar.follow_requests": "Jälgimistaotlused",
|
||||
"navigation_bar.followed_tags": "Jälgitavad märksõnad",
|
||||
"navigation_bar.follows_and_followers": "Jälgitavad ja jälgijad",
|
||||
|
|
@ -579,7 +588,7 @@
|
|||
"navigation_bar.logout": "Logi välja",
|
||||
"navigation_bar.moderation": "Modereerimine",
|
||||
"navigation_bar.more": "Lisavalikud",
|
||||
"navigation_bar.mutes": "Vaigistatud kasutajad",
|
||||
"navigation_bar.mutes": "Summutatud kasutajad",
|
||||
"navigation_bar.opened_in_classic_interface": "Postitused, kontod ja teised spetsiaalsed lehed avatakse vaikimisi klassikalises veebiliideses.",
|
||||
"navigation_bar.preferences": "Eelistused",
|
||||
"navigation_bar.privacy_and_reach": "Privaatsus ja ulatus",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Isikuandmete kaitse",
|
||||
"quote_error.edit": "Postituse muutmisel ei saa tsitaati lisada.",
|
||||
"quote_error.poll": "Tsiteerimine pole küsitlustes lubatud.",
|
||||
"quote_error.private_mentions": "Tsiteerimine pole otsemainimiste puhul 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.",
|
||||
|
|
@ -793,8 +803,8 @@
|
|||
"report.comment.title": "Kas arvad, et on veel midagi, mida me peaks teadma?",
|
||||
"report.forward": "Edasta ka {target} domeeni",
|
||||
"report.forward_hint": "See kasutaja on teisest serverist. Kas saadan anonümiseeritud koopia sellest teatest sinna ka?",
|
||||
"report.mute": "Vaigista",
|
||||
"report.mute_explanation": "Sa ei näe tema postitusi. Ta võib ikka sind jälgida ja su postitusi näha. Ta ei saa teada, et ta on vaigistatud.",
|
||||
"report.mute": "Summuta",
|
||||
"report.mute_explanation": "Sa ei näe tema postitusi. Ta võib ikka sind jälgida ja su postitusi näha. Ta ei saa teada, et ta on summutatud.",
|
||||
"report.next": "Järgmine",
|
||||
"report.placeholder": "Lisaks kommentaarid",
|
||||
"report.reasons.dislike": "Mulle ei meeldi see",
|
||||
|
|
@ -902,15 +912,18 @@
|
|||
"status.media_hidden": "Meedia peidetud",
|
||||
"status.mention": "Maini @{name}'i",
|
||||
"status.more": "Veel",
|
||||
"status.mute": "Vaigista @{name}",
|
||||
"status.mute_conversation": "Vaigista vestlus",
|
||||
"status.mute": "Summuta @{name}",
|
||||
"status.mute_conversation": "Summuta vestlus",
|
||||
"status.open": "Laienda postitus",
|
||||
"status.pin": "Kinnita profiilile",
|
||||
"status.quote": "Tsiteeri",
|
||||
"status.quote.cancel": "Katkesta tsiteerimine",
|
||||
"status.quote_error.blocked_account_hint.title": "Kuna sa oled blokeerinud kasutaja @{name}, siis see postitus on peidetud.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Kuna sa oled blokeerinud domeeni @{domain}, siis see postitus on peidetud.",
|
||||
"status.quote_error.filtered": "Peidetud mõne kasutatud filtri tõttu",
|
||||
"status.quote_error.limited_account_hint.action": "Näita ikkagi",
|
||||
"status.quote_error.limited_account_hint.title": "See profiil on peidetud {domain} serveri moderaatorite poolt.",
|
||||
"status.quote_error.muted_account_hint.title": "Kuna sa oled summutanud kasutaja @{name}, siis see postitus on peidetud.",
|
||||
"status.quote_error.not_available": "Postitus pole saadaval",
|
||||
"status.quote_error.pending_approval": "Postitus on ootel",
|
||||
"status.quote_error.pending_approval_popout.body": "Mastodonis saad sa kontrollida seda, kes võib sind tsiteerida. See postitus on seni ootel, kuni pole algse autori kinnitust tsiteerimisele.",
|
||||
|
|
@ -952,7 +965,7 @@
|
|||
"status.translate": "Tõlgi",
|
||||
"status.translated_from_with": "Tõlgitud {lang} keelest kasutades teenust {provider}",
|
||||
"status.uncached_media_warning": "Eelvaade pole saadaval",
|
||||
"status.unmute_conversation": "Ära vaigista vestlust",
|
||||
"status.unmute_conversation": "Lõpeta vestluse summutamine",
|
||||
"status.unpin": "Eemalda profiilile kinnitus",
|
||||
"subscribed_languages.lead": "Pärast muudatust näed koduvaates ja loetelude ajajoontel postitusi valitud keeltes. Ära vali midagi, kui tahad näha postitusi kõikides keeltes.",
|
||||
"subscribed_languages.save": "Salvesta muudatused",
|
||||
|
|
@ -996,15 +1009,17 @@
|
|||
"video.expand": "Suurenda video",
|
||||
"video.fullscreen": "Täisekraan",
|
||||
"video.hide": "Peida video",
|
||||
"video.mute": "Vaigista",
|
||||
"video.mute": "Summuta",
|
||||
"video.pause": "Paus",
|
||||
"video.play": "Mängi",
|
||||
"video.skip_backward": "Keri tagasi",
|
||||
"video.skip_forward": "Keri edasi",
|
||||
"video.unmute": "Lõpeta vaigistamine",
|
||||
"video.unmute": "Lõpeta summutamine",
|
||||
"video.volume_down": "Heli vaiksemaks",
|
||||
"video.volume_up": "Heli valjemaks",
|
||||
"visibility_modal.button_title": "Muuda nähtavust",
|
||||
"visibility_modal.direct_quote_warning.text": "Kui sa need seadistused salvestad, siis lõimitud tsitaat muutub lingiks.",
|
||||
"visibility_modal.direct_quote_warning.title": "Tsitaate ei saa privaatse mainimise puhul lõimida",
|
||||
"visibility_modal.header": "Nähtavus ja kasutus",
|
||||
"visibility_modal.helper.direct_quoting": "Ainult mainituile mõeldud Mastodoni postitusi ei saa teiste poolt tsiteerida.",
|
||||
"visibility_modal.helper.privacy_editing": "Nähtavust ei saa peale postituse avaldamist muuta.",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"about.blocks": "کارسازهای نظارت شده",
|
||||
"about.contact": "تماس:",
|
||||
"about.default_locale": "پیشفرض",
|
||||
"about.default_locale": "پیشگزیده",
|
||||
"about.disclaimer": "ماستودون نرمافزار آزاد و نشان تجاری یک شرکت غیر انتفاعی با مسئولیت محدود آلمانی است.",
|
||||
"about.domain_blocks.no_reason_available": "دلیلی موجود نیست",
|
||||
"about.domain_blocks.preamble": "ماستودون عموماً میگذارد محتوا را از از هر کارساز دیگری در دنیای شبکههای اجتماعی غیرمتمرکز دیده و با آنان برهمکنش داشته باشید. اینها استثناهایی هستند که روی این کارساز خاص وضع شدهاند.",
|
||||
|
|
@ -28,18 +28,24 @@
|
|||
"account.disable_notifications": "آگاه کردن من هنگام فرستههای @{name} را متوقّف کن",
|
||||
"account.domain_blocking": "دامنهٔ مسدود کرده",
|
||||
"account.edit_profile": "ویرایش نمایه",
|
||||
"account.edit_profile_short": "ویرایش",
|
||||
"account.enable_notifications": "هنگام فرستههای @{name} مرا آگاه کن",
|
||||
"account.endorse": "معرّفی در نمایه",
|
||||
"account.familiar_followers_many": "پیگرفته از سوی {name1}، {name2} و {othersCount, plural,one {یکی دیگر از پیگرفتههایتان} other {# نفر دیگر از پیگرفتههایتان}}",
|
||||
"account.familiar_followers_one": "پیگرفته از سوی {name1}",
|
||||
"account.familiar_followers_two": "پیگرفته از سوی {name1} و {name2}",
|
||||
"account.featured": " پیشنهادی",
|
||||
"account.featured": "پیشنهادی",
|
||||
"account.featured.accounts": "نمایهها",
|
||||
"account.featured.hashtags": "برچسبها",
|
||||
"account.featured_tags.last_status_at": "آخرین فرسته در {date}",
|
||||
"account.featured_tags.last_status_never": "بدون فرسته",
|
||||
"account.follow": "پیگرفتن",
|
||||
"account.follow_back": "پیگیری متقابل",
|
||||
"account.follow_back_short": "پیگیری متقابل",
|
||||
"account.follow_request": "درخواست پیگیری",
|
||||
"account.follow_request_cancel": "لغو درخواست",
|
||||
"account.follow_request_cancel_short": "لغو",
|
||||
"account.follow_request_short": "درخواست",
|
||||
"account.followers": "پیگیرندگان",
|
||||
"account.followers.empty": "هنوز کسی پیگیر این کاربر نیست.",
|
||||
"account.followers_counter": "{count, plural, one {{counter} پیگیرنده} other {{counter} پیگیرنده}}",
|
||||
|
|
@ -167,6 +173,8 @@
|
|||
"column.edit_list": "ویرایش سیاهه",
|
||||
"column.favourites": "برگزیدهها",
|
||||
"column.firehose": "خوراکهای زنده",
|
||||
"column.firehose_local": "خوراک زندهٔ این کارساز",
|
||||
"column.firehose_singular": "خوراک زنده",
|
||||
"column.follow_requests": "درخواستهای پیگیری",
|
||||
"column.home": "خانه",
|
||||
"column.list_members": "مدیریت اعضای سیاهه",
|
||||
|
|
@ -186,6 +194,7 @@
|
|||
"community.column_settings.local_only": "فقط محلی",
|
||||
"community.column_settings.media_only": "فقط رسانه",
|
||||
"community.column_settings.remote_only": "تنها دوردست",
|
||||
"compose.error.blank_post": "فرسته نمیتواند خالی باشد",
|
||||
"compose.language.change": "تغییر زبان",
|
||||
"compose.language.search": "جستوجوی زبانها...",
|
||||
"compose.published.body": "فرسته منتشر شد.",
|
||||
|
|
@ -238,6 +247,10 @@
|
|||
"confirmations.missing_alt_text.secondary": "به هر حال پست کن",
|
||||
"confirmations.missing_alt_text.title": "متن جایگزین اضافه شود؟",
|
||||
"confirmations.mute.confirm": "خموش",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "دیگر یادآوری نشود",
|
||||
"confirmations.quiet_post_quote_info.got_it": "گرفتم",
|
||||
"confirmations.quiet_post_quote_info.message": "هنگام نقل کردن فرستهٔ عمومی ساکت، فرستهتان از خطهای زمانی داغ پنهان خواهد بود.",
|
||||
"confirmations.quiet_post_quote_info.title": "نقل کردن فرستههای عمومی ساکت",
|
||||
"confirmations.redraft.confirm": "حذف و بازنویسی",
|
||||
"confirmations.redraft.message": "مطمئنید که میخواهید این فرسته را حذف کنید و از نو بنویسید؟ با این کار تقویتها و پسندهایش از دست رفته و پاسخها به آن بیمرجع میشود.",
|
||||
"confirmations.redraft.title": "حذف و پیشنویسی دوبارهٔ فرسته؟",
|
||||
|
|
@ -247,7 +260,12 @@
|
|||
"confirmations.revoke_quote.confirm": "حذف فرسته",
|
||||
"confirmations.revoke_quote.message": "این اقدام قابل بازگشت نیست.",
|
||||
"confirmations.revoke_quote.title": "آیا فرسته را حذف کنم؟",
|
||||
"confirmations.unblock.confirm": "رفع انسداد",
|
||||
"confirmations.unblock.title": "رفع انسداد {name}؟",
|
||||
"confirmations.unfollow.confirm": "پینگرفتن",
|
||||
"confirmations.unfollow.title": "ناپیگیری {name}؟",
|
||||
"confirmations.withdraw_request.confirm": "انصراف از درخواست",
|
||||
"confirmations.withdraw_request.title": "انصراف از درخواست پیگیری {name}؟",
|
||||
"content_warning.hide": "نهفتن فرسته",
|
||||
"content_warning.show": "در هر صورت نشان داده شود",
|
||||
"content_warning.show_more": "نمایش بیشتر",
|
||||
|
|
@ -318,6 +336,7 @@
|
|||
"empty_column.bookmarked_statuses": "هنوز هیچ فرستهٔ نشانهگذاری شدهای ندارید. هنگامی که فرستهای را نشانهگذاری کنید، اینجا نشان داده خواهد شد.",
|
||||
"empty_column.community": "خط زمانی محلی خالیست. چیزی نوشته تا چرخش بچرخد!",
|
||||
"empty_column.direct": "هنوز هیچ اشاره خصوصیای ندارید. هنگامی که چنین پیامی بگیرید یا بفرستید اینجا نشان داده خواهد شد.",
|
||||
"empty_column.disabled_feed": "این خوراک به دست مدیران کارسازتان از کار انداخته شده.",
|
||||
"empty_column.domain_blocks": "هنوز هیچ دامنهای مسدود نشده است.",
|
||||
"empty_column.explore_statuses": "الآن چیزی پرطرفدار نیست. بعداً دوباره بررسی کنید!",
|
||||
"empty_column.favourited_statuses": "شما هنوز هیچ فرستهای را نپسندیدهاید. هنگامی که فرستهای را بپسندید، اینجا نشان داده خواهد شد.",
|
||||
|
|
@ -446,10 +465,12 @@
|
|||
"ignore_notifications_modal.private_mentions_title": "چشمپوشی از نامبریهای خصوصی ناخواسته؟",
|
||||
"info_button.label": "راهنما",
|
||||
"info_button.what_is_alt_text": "<h1>متن جایگزین چیست؟</h1> <p>متن جایگزین توضیحات تصویری را برای افراد دارای اختلالات بینایی، اتصالات با پهنای باند کم یا کسانی که به دنبال زمینه اضافی هستند ارائه می دهد.</p> <p>با نوشتن متن جایگزین واضح، مختصر و عینی می توانید دسترسی و درک را برای همه بهبود بخشید.</p> <ul> <li>عناصر مهم را ضبط کنید</li> <li>متن را در تصاویر خلاصه کنید</li> <li>از ساختار جمله منظم استفاده کنید</li> <li>از اطلاعات اضافی خودداری کنید</li> <li>روی روندها و یافته های کلیدی در تصاویر پیچیده (مانند نمودارها یا نقشه ها) تمرکز کنید.</li> </ul>",
|
||||
"interaction_modal.action": "برای تعامل با فرستهٔ {name} باید به حسابتان روی هر کارساز ماستودونی که استفاده میکنید وارد شوید.",
|
||||
"interaction_modal.go": "برو",
|
||||
"interaction_modal.no_account_yet": "هنوز حساب کاربری ندارید؟",
|
||||
"interaction_modal.on_another_server": "روی کارسازی دیگر",
|
||||
"interaction_modal.on_this_server": "روی این کارساز",
|
||||
"interaction_modal.title": "ورود برای ادامه",
|
||||
"interaction_modal.username_prompt": "به عنوان مثال {example}",
|
||||
"intervals.full.days": "{number, plural, one {# روز} other {# روز}}",
|
||||
"intervals.full.hours": "{number, plural, one {# ساعت} other {# ساعت}}",
|
||||
|
|
@ -470,6 +491,7 @@
|
|||
"keyboard_shortcuts.home": "گشودن خط زمانی خانگی",
|
||||
"keyboard_shortcuts.hotkey": "میانبر",
|
||||
"keyboard_shortcuts.legend": "نمایش این نشانه",
|
||||
"keyboard_shortcuts.load_more": "تمرکز روی دکمهٔ «بار کردن بیشتر»",
|
||||
"keyboard_shortcuts.local": "گشودن خط زمانی محلی",
|
||||
"keyboard_shortcuts.mention": "اشاره به نویسنده",
|
||||
"keyboard_shortcuts.muted": "گشودن فهرست کاربران خموش",
|
||||
|
|
@ -478,6 +500,7 @@
|
|||
"keyboard_shortcuts.open_media": "گشودن رسانه",
|
||||
"keyboard_shortcuts.pinned": "گشودن سیاههٔ فرستههای سنجاق شده",
|
||||
"keyboard_shortcuts.profile": "گشودن نمایهٔ نویسنده",
|
||||
"keyboard_shortcuts.quote": "نقل فرسته",
|
||||
"keyboard_shortcuts.reply": "پاسخ به فرسته",
|
||||
"keyboard_shortcuts.requests": "گشودن سیاههٔ درخواستهای پیگیری",
|
||||
"keyboard_shortcuts.search": "تمرکز روی نوار جستوجو",
|
||||
|
|
@ -606,6 +629,7 @@
|
|||
"notification.moderation_warning.action_suspend": "حسابتان معلّق شده.",
|
||||
"notification.own_poll": "نظرسنجیتان پایان یافت",
|
||||
"notification.poll": "نظرسنجیای که در آن رأی دادید به پایان رسید",
|
||||
"notification.quoted_update": "{name} فرستهای که نقل کردید را ویراست",
|
||||
"notification.reblog": "{name} فرستهتان را تقویت کرد",
|
||||
"notification.reblog.name_and_others_with_link": "{name} و <a>{count, plural, one {# نفر دیگر} other {# نفر دیگر}}</a> فرستهتان را تقویت کردند",
|
||||
"notification.relationships_severance_event": "قطع ارتباط با {name}",
|
||||
|
|
@ -621,7 +645,7 @@
|
|||
"notification_requests.confirm_accept_multiple.message": "در حال پذیرش {count, plural,one {یک}other {#}} درخواست آگاهی هستید. مطمئنید که میخواهید ادامه دهید؟",
|
||||
"notification_requests.confirm_accept_multiple.title": "پذیرش درخواستهای آگاهی؟",
|
||||
"notification_requests.confirm_dismiss_multiple.button": "رد {count, plural,one {درخواست} other {درخواستها}}",
|
||||
"notification_requests.confirm_dismiss_multiple.message": "شما در شرف رد کردن {count, plural, one {یک درخواست آگاهی} other {درخواست آگاهی}} هستید. دیگر نمی توانید به راحتی به {count, plural, one {آن} other {آنها}} دسترسی پیدا کنید. آیا مطمئن هستید که می خواهید ادامه دهید؟",
|
||||
"notification_requests.confirm_dismiss_multiple.message": "دارید {count, plural, one {یک درخواست آگاهی} other {# درخواست آگاهی}} را رد میکنید که دیگر نمی توانید به راحتی به {count, plural, one {آن} other {آنها}} دسترسی پیدا کنید. مطمئنید که میخواهید ادامه دهید؟",
|
||||
"notification_requests.confirm_dismiss_multiple.title": "رد کردن درخواستهای آگاهی؟",
|
||||
"notification_requests.dismiss": "دورانداختن",
|
||||
"notification_requests.dismiss_multiple": "{count, plural, one {دورانداختن درخواست…} other {دورانداختن درخواستها…}}",
|
||||
|
|
@ -725,10 +749,19 @@
|
|||
"privacy.private.short": "پیگیرندگان",
|
||||
"privacy.public.long": "هرکسی در و بیرون از ماستودون",
|
||||
"privacy.public.short": "عمومی",
|
||||
"privacy.quote.anyone": "{visibility}، هرکسی میتواند نقل کند",
|
||||
"privacy.quote.disabled": "{visibility}، نقلها از کار افتاده",
|
||||
"privacy.quote.limited": "{visibility}، نقلها محدود شده",
|
||||
"privacy.unlisted.additional": "درست مثل عمومی رفتار میکند؛ جز این که فرسته در برچسبها یا خوراکهای زنده، کشف یا جستوجوی ماستودون ظاهر نخواهد شد. حتا اگر کلیّت نمایهتان اجازه داده باشد.",
|
||||
"privacy.unlisted.long": "نهفته از نتیجههای جستوجوی ماستودون و خطهای زمانی داغ و عمومی",
|
||||
"privacy.unlisted.short": "عمومی ساکت",
|
||||
"privacy_policy.last_updated": "آخرین بهروز رسانی در {date}",
|
||||
"privacy_policy.title": "سیاست محرمانگی",
|
||||
"quote_error.edit": "هنگام ویراستن فرسته نمیتوان نقلی افزود.",
|
||||
"quote_error.poll": "نقل نظرسنجیها مجاز نیست.",
|
||||
"quote_error.quote": "در هر زمان تنها یک نقل مجاز است.",
|
||||
"quote_error.unauthorized": "مجاز به نقل این فرسته نیستید.",
|
||||
"quote_error.upload": "نقل پیوستهای رسانهای مجاز نیست.",
|
||||
"recommended": "پیشنهادشده",
|
||||
"refresh": "نوسازی",
|
||||
"regeneration_indicator.please_stand_by": "لطفا منتظر باشید.",
|
||||
|
|
@ -744,6 +777,9 @@
|
|||
"relative_time.minutes": "{number} دقیقه",
|
||||
"relative_time.seconds": "{number} ثانیه",
|
||||
"relative_time.today": "امروز",
|
||||
"remove_quote_hint.button_label": "گرفتم",
|
||||
"remove_quote_hint.message": "میتوانید این کار را از {icon} فهرست گزینهها انجام دهید.",
|
||||
"remove_quote_hint.title": "میخواهید فرستهٔ نقل شدهتان را بردارید؟",
|
||||
"reply_indicator.attachments": "{count, plural, one {# پیوست} other {# پیوست}}",
|
||||
"reply_indicator.cancel": "لغو",
|
||||
"reply_indicator.poll": "نظرسنجی",
|
||||
|
|
@ -835,13 +871,23 @@
|
|||
"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.contains_quote": "دارای نقل",
|
||||
"status.context.loading": "بار کردن پاسخهای بیشتر",
|
||||
"status.context.loading_error": "نتوانست پاسخهای بیشتری بار کند",
|
||||
"status.context.loading_success": "پاسخهای جدید بار شدند",
|
||||
"status.context.more_replies_found": "پاسخهای بیشتری پیدا شد",
|
||||
"status.context.retry": "تلاش دوباره",
|
||||
"status.context.show": "نمایش",
|
||||
"status.continued_thread": "رشتهٔ دنباله دار",
|
||||
"status.copy": "رونوشت از پیوند فرسته",
|
||||
"status.delete": "حذف",
|
||||
"status.delete.success": "فرسته حذف شد",
|
||||
"status.detailed_status": "نمایش کامل گفتگو",
|
||||
"status.direct": "اشارهٔ خصوصی به @{name}",
|
||||
"status.direct_indicator": "اشارهٔ خصوصی",
|
||||
|
|
@ -866,24 +912,43 @@
|
|||
"status.pin": "سنجاق به نمایه",
|
||||
"status.quote": "نقلقول",
|
||||
"status.quote.cancel": "لغو نقل",
|
||||
"status.quote_error.blocked_account_hint.title": "این فرسته نهفته است چرا که @{name} را مسدود کردهاید.",
|
||||
"status.quote_error.blocked_domain_hint.title": "این فرسته نهفته است چرا که {domain} را مسدود کردهاید.",
|
||||
"status.quote_error.filtered": "نهفته بنا بر یکی از پالایههایتان",
|
||||
"status.quote_error.limited_account_hint.action": "نمایش به هر روی",
|
||||
"status.quote_error.limited_account_hint.title": "این حساب به دست ناظمهای {domain} پنهان شده.",
|
||||
"status.quote_error.muted_account_hint.title": "این فرسته نهفته است چرا که @{name} را خموش کردهاید.",
|
||||
"status.quote_error.not_available": "فرسته در دسترس نیست",
|
||||
"status.quote_error.pending_approval": "فرسته منتظر",
|
||||
"status.quote_error.pending_approval_popout.body": "روی ماستودون میتوان افراد مجاز به نقل را واپایید. این فرسته تا زمان گرفتن تأییده از نگارندهٔ اصلی معلّق است.",
|
||||
"status.quote_error.revoked": "فرسته به دست نگارنده برداشته شد",
|
||||
"status.quote_followers_only": "تنها پیگیران میتوانند این فرسته را نقل کنند",
|
||||
"status.quote_manual_review": "نگارنده به صورت دستی بررسی خواهد کرد",
|
||||
"status.quote_noun": "نقل",
|
||||
"status.quote_policy_change": "تغییر کسانی که میتوانند نقل کنند",
|
||||
"status.quote_post_author": "فرستهای از @{name} نقل شد",
|
||||
"status.quote_private": "فرستههای خصوصی نمیتوانند نقل شوند",
|
||||
"status.quotes": "{count, plural, one {نقل} other {نقل}}",
|
||||
"status.quotes.empty": "هنوز کسی این فرسته را نقل نکرده. وقتی کسی چنین کند اینجا نشان داده خواهد شد.",
|
||||
"status.quotes.local_other_disclaimer": "نقلهایی که به دست نگارنده رد شده باشند نشان داده نخواهند شد.",
|
||||
"status.quotes.remote_other_disclaimer": "تنها نقلها از {domain} تضمین نمایش در اینجا را دارند. نقلهای رد شده به دست نگاره نشان داده نخواهند شد.",
|
||||
"status.read_more": "بیشتر بخوانید",
|
||||
"status.reblog": "تقویت",
|
||||
"status.reblog_or_quote": "نقل یا تقویت",
|
||||
"status.reblog_private": "همرسانی دوباره با پیگیرانتان",
|
||||
"status.reblogged_by": "{name} تقویت کرد",
|
||||
"status.reblogs": "{count, plural, one {تقویت} other {تقویت}}",
|
||||
"status.reblogs.empty": "هنوز هیچ کسی این فرسته را تقویت نکرده است. وقتی کسی چنین کاری کند، اینجا نمایش داده خواهد شد.",
|
||||
"status.redraft": "حذف و بازنویسی",
|
||||
"status.remove_bookmark": "برداشتن نشانک",
|
||||
"status.remove_favourite": "حذف از موارد دلخواه",
|
||||
"status.remove_quote": "برداشتن",
|
||||
"status.replied_in_thread": "در رشته پاسخ داده",
|
||||
"status.replied_to": "به {name} پاسخ داد",
|
||||
"status.reply": "پاسخ",
|
||||
"status.replyAll": "پاسخ به رشته",
|
||||
"status.report": "گزارش @{name}",
|
||||
"status.request_quote": "درخواست نقل",
|
||||
"status.revoke_quote": "حذف فرستهام از فرسته @{name}",
|
||||
"status.sensitive_warning": "محتوای حساس",
|
||||
"status.share": "همرسانی",
|
||||
|
|
@ -922,6 +987,7 @@
|
|||
"upload_button.label": "افزودن تصاویر، ویدیو یا یک پروندهٔ صوتی",
|
||||
"upload_error.limit": "از حد مجاز بارگذاری پرونده فراتر رفتید.",
|
||||
"upload_error.poll": "بارگذاری پرونده در نظرسنجیها مجاز نیست.",
|
||||
"upload_error.quote": "بارگذاری پرونده در نقلها محاز نیست.",
|
||||
"upload_form.drag_and_drop.instructions": "برای دریافت پیوست رسانه، space را فشار دهید یا وارد کنید. در حین کشیدن، از کلیدهای جهت دار برای حرکت دادن پیوست رسانه در هر جهت معین استفاده کنید. برای رها کردن ضمیمه رسانه در موقعیت جدید خود، مجدداً space یا enter را فشار دهید، یا برای لغو، escape را فشار دهید.",
|
||||
"upload_form.drag_and_drop.on_drag_cancel": "کشیدن لغو شد. پیوست رسانه {item} حذف شد.",
|
||||
"upload_form.drag_and_drop.on_drag_end": "پیوست رسانه {item} حذف شد.",
|
||||
|
|
@ -947,8 +1013,16 @@
|
|||
"video.volume_up": "افزایش حجم صدا",
|
||||
"visibility_modal.button_title": "تنظیم نمایانی",
|
||||
"visibility_modal.header": "نمایانی و برهمکنش",
|
||||
"visibility_modal.helper.direct_quoting": "اشارههای خصوصی روی ماستودون نیمتوانند به دست دیگران نقل شوند.",
|
||||
"visibility_modal.helper.privacy_editing": "پس از انتشار فرسته نمیتوان نمایانی را تغییر داد.",
|
||||
"visibility_modal.helper.privacy_private_self_quote": "خودنقلی فرستههای خصوصی نمیتواند عمومی شود.",
|
||||
"visibility_modal.helper.private_quoting": "فرستهّای فقط پیگیران روی ماستودون نمیتوانند به دست دیگران نقل شوند.",
|
||||
"visibility_modal.helper.unlisted_quoting": "هنگامی که افراد نقلتان میکنند فرستهشان هم از خطزمانیهای داغ پنهان خواهد بود.",
|
||||
"visibility_modal.instructions": "واپایش کسانی که میتوانند با این فرسته تعامل داشته باشند. میتواند با رفتن به <link>ترجیحات > پیشگزیدهها فرستادن</link> تنظیمات را به همهٔ فرستههای آینده نیز اعمال کنید.",
|
||||
"visibility_modal.privacy_label": "نمایانی",
|
||||
"visibility_modal.quote_followers": "فقط پیگیرندگان",
|
||||
"visibility_modal.quote_label": "چهکسی میتواند نقل کند",
|
||||
"visibility_modal.quote_nobody": "فقط من",
|
||||
"visibility_modal.quote_public": "هرکسی",
|
||||
"visibility_modal.save": "ذخیره"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Muokkaa listaa",
|
||||
"column.favourites": "Suosikit",
|
||||
"column.firehose": "Livesyötteet",
|
||||
"column.firehose_local": "Tämän palvelimen livesyöte",
|
||||
"column.firehose_singular": "Livesyöte",
|
||||
"column.follow_requests": "Seurantapyynnöt",
|
||||
"column.home": "Koti",
|
||||
"column.list_members": "Hallitse listan jäseniä",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Vain paikalliset",
|
||||
"community.column_settings.media_only": "Vain media",
|
||||
"community.column_settings.remote_only": "Vain etätilit",
|
||||
"compose.error.blank_post": "Julkaisu ei voi olla tyhjä.",
|
||||
"compose.language.change": "Vaihda kieli",
|
||||
"compose.language.search": "Hae kieliä…",
|
||||
"compose.published.body": "Julkaisu lähetetty.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Julkaise silti",
|
||||
"confirmations.missing_alt_text.title": "Lisätäänkö vaihtoehtoinen teksti?",
|
||||
"confirmations.mute.confirm": "Mykistä",
|
||||
"confirmations.private_quote_notify.cancel": "Takaisin muokkaukseen",
|
||||
"confirmations.private_quote_notify.confirm": "Julkaise",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Älä näytä tätä viestiä uudelleen",
|
||||
"confirmations.private_quote_notify.message": "Lainaamasi käyttäjä ja muut mainitut saavat ilmoituksen ja voivat tarkastella julkaisuasi, vaikka he eivät seuraisi sinua.",
|
||||
"confirmations.private_quote_notify.title": "Jaetaanko seuraajien ja mainittujen käyttäjien kanssa?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Älä muistuta minua uudelleen",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Selvä",
|
||||
"confirmations.quiet_post_quote_info.message": "Kun lainaat vaivihkaa julkisia julkaisuja, oma julkaisusi piilotetaan suosittujen julkaisujen aikajanoilta.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Et ole vielä lisännyt julkaisuja kirjanmerkkeihisi. Kun lisäät yhden, se näkyy tässä.",
|
||||
"empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista, niin homma lähtee käyntiin!",
|
||||
"empty_column.direct": "Yksityismainintoja ei vielä ole. Jos lähetät tai sinulle lähetetään sellaisia, näet ne täällä.",
|
||||
"empty_column.disabled_feed": "Palvelimen ylläpito on poistanut käytöstä tämän syötteen.",
|
||||
"empty_column.domain_blocks": "Verkkotunnuksia ei ole vielä estetty.",
|
||||
"empty_column.explore_statuses": "Mikään ei ole nyt suosittua. Tarkista myöhemmin uudelleen!",
|
||||
"empty_column.favourited_statuses": "Sinulla ei ole vielä yhtään suosikkijulkaisua. Kun lisäät sellaisen, näkyy se tässä.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Tietosuojakäytäntö",
|
||||
"quote_error.edit": "Lainauksia ei voi lisätä julkaisua muokattaessa.",
|
||||
"quote_error.poll": "Äänestysten lainaaminen ei ole sallittua.",
|
||||
"quote_error.private_mentions": "Lainaaminen ei ole sallittua yksityismaininnoissa.",
|
||||
"quote_error.quote": "Vain yksi lainaus kerrallaan on sallittu.",
|
||||
"quote_error.unauthorized": "Sinulla ei ole valtuuksia lainata tätä julkaisua.",
|
||||
"quote_error.upload": "Medialiitteiden lainaaminen ei ole sallittua.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Kiinnitä profiiliin",
|
||||
"status.quote": "Lainaa",
|
||||
"status.quote.cancel": "Peruuta lainaus",
|
||||
"status.quote_error.blocked_account_hint.title": "Tämä julkaisu on piilotettu, koska olet estänyt käyttäjän @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Tämä julkaisu on piilotettu, koska olet estänyt verkkotunnuksen {domain}.",
|
||||
"status.quote_error.filtered": "Piilotettu jonkin asettamasi suodattimen takia",
|
||||
"status.quote_error.limited_account_hint.action": "Näytä kuitenkin",
|
||||
"status.quote_error.limited_account_hint.title": "Palvelimen {domain} moderaattorit ovat piilottaneet tämän profiilin.",
|
||||
"status.quote_error.muted_account_hint.title": "Tämä julkaisu on piilotettu, koska olet mykistänyt käyttäjän @{name}.",
|
||||
"status.quote_error.not_available": "Julkaisu ei saatavilla",
|
||||
"status.quote_error.pending_approval": "Julkaisu odottaa",
|
||||
"status.quote_error.pending_approval_popout.body": "Mastodonissa voit hallita, voiko joku lainata sinua. Tämä julkaisu on vireillä siihen asti, että saamme alkuperäisen tekijän hyväksynnän.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Vähennä äänenvoimakkuutta",
|
||||
"video.volume_up": "Lisää äänenvoimakkuutta",
|
||||
"visibility_modal.button_title": "Aseta näkyvyys",
|
||||
"visibility_modal.direct_quote_warning.text": "Jos tallennat nykyiset asetukset, upotettu lainaus muunnetaan linkiksi.",
|
||||
"visibility_modal.direct_quote_warning.title": "Lainauksia ei voi upottaa yksityismainintoihin",
|
||||
"visibility_modal.header": "Näkyvyys ja vuorovaikutus",
|
||||
"visibility_modal.helper.direct_quoting": "Muut eivät voi lainata Mastodonissa kirjoitettuja yksityismainintoja.",
|
||||
"visibility_modal.helper.privacy_editing": "Näkyvyyttä ei voi muuttaa julkaisun jälkeen.",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Broyt lista",
|
||||
"column.favourites": "Dámdir postar",
|
||||
"column.firehose": "Beinleiðis rásir",
|
||||
"column.firehose_local": "Beinleiðis rás hjá hesum ambætaranum",
|
||||
"column.firehose_singular": "Beinleiðis rás",
|
||||
"column.follow_requests": "Umbønir at fylgja",
|
||||
"column.home": "Heim",
|
||||
"column.list_members": "Rætta limalista",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Einans lokalt",
|
||||
"community.column_settings.media_only": "Einans miðlar",
|
||||
"community.column_settings.remote_only": "Einans útifrá",
|
||||
"compose.error.blank_post": "Postar kunnu ikki vera blankir.",
|
||||
"compose.language.change": "Skift mál",
|
||||
"compose.language.search": "Leita eftir málum...",
|
||||
"compose.published.body": "Postur útgivin.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Posta allíkavæl",
|
||||
"confirmations.missing_alt_text.title": "Legg alternativan tekst afturat?",
|
||||
"confirmations.mute.confirm": "Doyv",
|
||||
"confirmations.private_quote_notify.cancel": "Aftur til rættingar",
|
||||
"confirmations.private_quote_notify.confirm": "Útgev post",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Ikki vísa hesi boðini aftur",
|
||||
"confirmations.private_quote_notify.message": "Persónurin, sum tú siterar, og onnur, sum eru nevnd, verða kunnaði og kunnu síggja postin hjá tær, sjálvt um tey ikki fylgja tær.",
|
||||
"confirmations.private_quote_notify.title": "Deil við fylgjarum og nevndum brúkarum?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Ikki minna meg á tað aftur",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Eg skilji",
|
||||
"confirmations.quiet_post_quote_info.message": "Tá tú siterar ein stillan almennan post, verður posturin hjá tær fjaldur frá tíðarlinjum, ið vísa vælumtóktar postar.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Tú hevur enn einki goymt uppslag. Tú tú goymir eitt uppslag, kemur tað her.",
|
||||
"empty_column.community": "Lokala tíðarlinjan er tóm. Skriva okkurt alment fyri at fáa boltin á rull!",
|
||||
"empty_column.direct": "Tú hevur ongar privatar umrøður enn. Tá tú sendir ella móttekur eina privata umrøðu, so verður hon sjónlig her.",
|
||||
"empty_column.disabled_feed": "Hendan rásin er gjørd óvirkin av ambætaraumsitarunum hjá tær.",
|
||||
"empty_column.domain_blocks": "Enn eru eingi blokeraði domenir.",
|
||||
"empty_column.explore_statuses": "Einki rák er beint nú. Royn aftur seinni!",
|
||||
"empty_column.favourited_statuses": "Tú hevur ongar yndispostar enn. Tá tú gevur einum posti yndismerki, so sært tú hann her.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Privatlívspolitikkur",
|
||||
"quote_error.edit": "Sitatir kunnu ikki leggjast afturat tá tú rættar ein post.",
|
||||
"quote_error.poll": "Tað er ikki loyvt at sitera spurnarkanningar.",
|
||||
"quote_error.private_mentions": "Sitering er ikki loyvd við beinleiðis umrøðum.",
|
||||
"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.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Ger fastan í vangan",
|
||||
"status.quote": "Sitat",
|
||||
"status.quote.cancel": "Ógilda sitat",
|
||||
"status.quote_error.blocked_account_hint.title": "Hesin posturin er fjaldur, tí tú hevur blokerað @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Hesin posturin er fjaldur, tí tú hevur blokerað @{domain}.",
|
||||
"status.quote_error.filtered": "Eitt av tínum filtrum fjalir hetta",
|
||||
"status.quote_error.limited_account_hint.action": "Vís kortini",
|
||||
"status.quote_error.limited_account_hint.title": "Hendan kontan er fjald av kjakleiðarunum á {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Hesin posturin er fjaldur, tí tú hevur doyvt @{name}.",
|
||||
"status.quote_error.not_available": "Postur ikki tøkur",
|
||||
"status.quote_error.pending_approval": "Postur bíðar",
|
||||
"status.quote_error.pending_approval_popout.body": "Á Mastodon kanst tú avgera, um onkur kann sitera teg. Hesin posturin bíðar eftir góðkenning frá upprunahøvundinum.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Minka ljóðstyrki",
|
||||
"video.volume_up": "Øk um ljóðstyrki",
|
||||
"visibility_modal.button_title": "Set sýni",
|
||||
"visibility_modal.direct_quote_warning.text": "Um tú goymir verandi stillingar, verður innskotna sitatið umskapað til eitt leinki.",
|
||||
"visibility_modal.direct_quote_warning.title": "Sitatir kunnu ikki innskjótast í privatar umrøður",
|
||||
"visibility_modal.header": "Sýni og samvirkni",
|
||||
"visibility_modal.helper.direct_quoting": "Privatar umrøður, sum eru skrivaðar á Mastodon, kunnu ikki siterast av øðrum.",
|
||||
"visibility_modal.helper.privacy_editing": "Sýni kann ikki broytast eftir, at ein postur er útgivin.",
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
"account.disable_notifications": "Ne plus me notifier quand @{name} publie",
|
||||
"account.domain_blocking": "Bloquer domaine",
|
||||
"account.edit_profile": "Modifier le profil",
|
||||
"account.edit_profile_short": "Modifier",
|
||||
"account.enable_notifications": "Me notifier quand @{name} publie",
|
||||
"account.endorse": "Inclure sur profil",
|
||||
"account.familiar_followers_many": "Suivi par {name1},{name2}, et {othersCount, plural,one {une personne connue} other {# autres personnel connues}}",
|
||||
|
|
@ -40,6 +41,11 @@
|
|||
"account.featured_tags.last_status_never": "Aucune publication",
|
||||
"account.follow": "Suivre",
|
||||
"account.follow_back": "Suivre en retour",
|
||||
"account.follow_back_short": "Suivre en retour",
|
||||
"account.follow_request": "Demande d’abonnement",
|
||||
"account.follow_request_cancel": "Annuler la demande",
|
||||
"account.follow_request_cancel_short": "Annuler",
|
||||
"account.follow_request_short": "Requête",
|
||||
"account.followers": "abonné·e·s",
|
||||
"account.followers.empty": "Personne ne suit ce compte pour l'instant.",
|
||||
"account.followers_counter": "{count, plural, one {{counter} abonné·e} other {{counter} abonné·e·s}}",
|
||||
|
|
@ -167,6 +173,8 @@
|
|||
"column.edit_list": "Modifier la liste",
|
||||
"column.favourites": "Favoris",
|
||||
"column.firehose": "Flux en direct",
|
||||
"column.firehose_local": "Flux en direct pour ce serveur",
|
||||
"column.firehose_singular": "Flux en direct",
|
||||
"column.follow_requests": "Demande d'abonnement",
|
||||
"column.home": "Accueil",
|
||||
"column.list_members": "Gérer les membres de la liste",
|
||||
|
|
@ -186,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Local seulement",
|
||||
"community.column_settings.media_only": "Média seulement",
|
||||
"community.column_settings.remote_only": "À distance seulement",
|
||||
"compose.error.blank_post": "Le message ne peut être laissé vide.",
|
||||
"compose.language.change": "Changer de langue",
|
||||
"compose.language.search": "Rechercher des langues…",
|
||||
"compose.published.body": "Publiée.",
|
||||
|
|
@ -327,6 +336,7 @@
|
|||
"empty_column.bookmarked_statuses": "Vous n'avez pas de publications parmi vos signets. Lorsque vous en ajouterez une, elle apparaîtra ici.",
|
||||
"empty_column.community": "Le fil local est vide. Écrivez donc quelque chose pour le remplir!",
|
||||
"empty_column.direct": "Vous n'avez pas encore de mentions privées. Quand vous en envoyez ou en recevez, elles apparaîtront ici.",
|
||||
"empty_column.disabled_feed": "Ce flux a été désactivé par les administrateur·rice·s de votre serveur.",
|
||||
"empty_column.domain_blocks": "Il n’y a aucun domaine bloqué pour le moment.",
|
||||
"empty_column.explore_statuses": "Rien n'est en tendance présentement. Revenez plus tard!",
|
||||
"empty_column.favourited_statuses": "Vous n’avez pas encore de publications favorites. Lorsque vous en ajouterez une, elle apparaîtra ici.",
|
||||
|
|
@ -747,6 +757,7 @@
|
|||
"privacy.unlisted.short": "Public discret",
|
||||
"privacy_policy.last_updated": "Dernière mise à jour {date}",
|
||||
"privacy_policy.title": "Politique de confidentialité",
|
||||
"quote_error.edit": "Les citations ne peuvent pas être ajoutés lors de l'édition d'un message.",
|
||||
"quote_error.poll": "Les citations ne sont pas autorisées avec les sondages.",
|
||||
"quote_error.quote": "Une seule citation à la fois est autorisée.",
|
||||
"quote_error.unauthorized": "Vous n'êtes pas autorisé⋅e à citer cette publication.",
|
||||
|
|
@ -869,6 +880,7 @@
|
|||
"status.contains_quote": "Contient la citation",
|
||||
"status.context.loading": "Chargement de réponses supplémentaires",
|
||||
"status.context.loading_error": "Impossible de charger les nouvelles réponses",
|
||||
"status.context.loading_success": "Nouvelles réponses ont été chargées",
|
||||
"status.context.more_replies_found": "Plus de réponses trouvées",
|
||||
"status.context.retry": "Réessayer",
|
||||
"status.context.show": "Montrer",
|
||||
|
|
@ -900,9 +912,12 @@
|
|||
"status.pin": "Épingler sur profil",
|
||||
"status.quote": "Citer",
|
||||
"status.quote.cancel": "Annuler la citation",
|
||||
"status.quote_error.blocked_account_hint.title": "Ce message est masqué car vous avez bloqué @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Ce message est masqué car vous avez bloqué {domain}.",
|
||||
"status.quote_error.filtered": "Caché en raison de l'un de vos filtres",
|
||||
"status.quote_error.limited_account_hint.action": "Afficher quand même",
|
||||
"status.quote_error.limited_account_hint.title": "Ce profil a été masqué par la modération de {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Ce message est masqué car vous avez Mis en sourdine @{name}.",
|
||||
"status.quote_error.not_available": "Publication non disponible",
|
||||
"status.quote_error.pending_approval": "Publication en attente",
|
||||
"status.quote_error.pending_approval_popout.body": "Sur Mastodon, vous pouvez contrôler si quelqu'un peut vous citer. Ce message est en attente pendant que nous recevons l'approbation de l'auteur original.",
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
"account.disable_notifications": "Ne plus me notifier quand @{name} publie quelque chose",
|
||||
"account.domain_blocking": "Bloquer domaine",
|
||||
"account.edit_profile": "Modifier le profil",
|
||||
"account.edit_profile_short": "Modifier",
|
||||
"account.enable_notifications": "Me notifier quand @{name} publie quelque chose",
|
||||
"account.endorse": "Recommander sur votre profil",
|
||||
"account.familiar_followers_many": "Suivi par {name1},{name2}, et {othersCount, plural,one {une personne connue} other {# autres personnel connues}}",
|
||||
|
|
@ -40,6 +41,11 @@
|
|||
"account.featured_tags.last_status_never": "Aucun message",
|
||||
"account.follow": "Suivre",
|
||||
"account.follow_back": "Suivre en retour",
|
||||
"account.follow_back_short": "Suivre en retour",
|
||||
"account.follow_request": "Demande d’abonnement",
|
||||
"account.follow_request_cancel": "Annuler la demande",
|
||||
"account.follow_request_cancel_short": "Annuler",
|
||||
"account.follow_request_short": "Requête",
|
||||
"account.followers": "Abonné·e·s",
|
||||
"account.followers.empty": "Personne ne suit cet·te utilisateur·rice pour l’instant.",
|
||||
"account.followers_counter": "{count, plural, one {{counter} abonné·e} other {{counter} abonné·e·s}}",
|
||||
|
|
@ -167,6 +173,8 @@
|
|||
"column.edit_list": "Modifier la liste",
|
||||
"column.favourites": "Favoris",
|
||||
"column.firehose": "Flux en direct",
|
||||
"column.firehose_local": "Flux en direct pour ce serveur",
|
||||
"column.firehose_singular": "Flux en direct",
|
||||
"column.follow_requests": "Demandes d'abonnement",
|
||||
"column.home": "Accueil",
|
||||
"column.list_members": "Gérer les membres de la liste",
|
||||
|
|
@ -186,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Local seulement",
|
||||
"community.column_settings.media_only": "Média uniquement",
|
||||
"community.column_settings.remote_only": "Distant seulement",
|
||||
"compose.error.blank_post": "Le message ne peut être laissé vide.",
|
||||
"compose.language.change": "Changer de langue",
|
||||
"compose.language.search": "Rechercher des langues...",
|
||||
"compose.published.body": "Message Publié.",
|
||||
|
|
@ -327,6 +336,7 @@
|
|||
"empty_column.bookmarked_statuses": "Vous n'avez pas de message en marque-page. Lorsque vous en ajouterez un, il apparaîtra ici.",
|
||||
"empty_column.community": "Le fil public local est vide. Écrivez donc quelque chose pour le remplir !",
|
||||
"empty_column.direct": "Vous n'avez pas encore de mentions privées. Quand vous en enverrez ou recevrez, elles apparaîtront ici.",
|
||||
"empty_column.disabled_feed": "Ce flux a été désactivé par les administrateur·rice·s de votre serveur.",
|
||||
"empty_column.domain_blocks": "Il n’y a aucun domaine bloqué pour le moment.",
|
||||
"empty_column.explore_statuses": "Rien n'est en tendance pour le moment. Revenez plus tard !",
|
||||
"empty_column.favourited_statuses": "Vous n’avez pas encore de message en favori. Lorsque vous en ajouterez un, il apparaîtra ici.",
|
||||
|
|
@ -747,6 +757,7 @@
|
|||
"privacy.unlisted.short": "Public discret",
|
||||
"privacy_policy.last_updated": "Dernière mise à jour {date}",
|
||||
"privacy_policy.title": "Politique de confidentialité",
|
||||
"quote_error.edit": "Les citations ne peuvent pas être ajoutés lors de l'édition d'un message.",
|
||||
"quote_error.poll": "Les citations ne sont pas autorisées avec les sondages.",
|
||||
"quote_error.quote": "Une seule citation à la fois est autorisée.",
|
||||
"quote_error.unauthorized": "Vous n'êtes pas autorisé⋅e à citer cette publication.",
|
||||
|
|
@ -869,6 +880,7 @@
|
|||
"status.contains_quote": "Contient la citation",
|
||||
"status.context.loading": "Chargement de réponses supplémentaires",
|
||||
"status.context.loading_error": "Impossible de charger les nouvelles réponses",
|
||||
"status.context.loading_success": "Nouvelles réponses ont été chargées",
|
||||
"status.context.more_replies_found": "Plus de réponses trouvées",
|
||||
"status.context.retry": "Réessayer",
|
||||
"status.context.show": "Montrer",
|
||||
|
|
@ -900,9 +912,12 @@
|
|||
"status.pin": "Épingler sur le profil",
|
||||
"status.quote": "Citer",
|
||||
"status.quote.cancel": "Annuler la citation",
|
||||
"status.quote_error.blocked_account_hint.title": "Ce message est masqué car vous avez bloqué @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Ce message est masqué car vous avez bloqué {domain}.",
|
||||
"status.quote_error.filtered": "Caché en raison de l'un de vos filtres",
|
||||
"status.quote_error.limited_account_hint.action": "Afficher quand même",
|
||||
"status.quote_error.limited_account_hint.title": "Ce profil a été masqué par la modération de {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Ce message est masqué car vous avez Mis en sourdine @{name}.",
|
||||
"status.quote_error.not_available": "Publication non disponible",
|
||||
"status.quote_error.pending_approval": "Publication en attente",
|
||||
"status.quote_error.pending_approval_popout.body": "Sur Mastodon, vous pouvez contrôler si quelqu'un peut vous citer. Ce message est en attente pendant que nous recevons l'approbation de l'auteur original.",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Cuir liosta in eagar",
|
||||
"column.favourites": "Ceanáin",
|
||||
"column.firehose": "Fothaí beo",
|
||||
"column.firehose_local": "Fotha beo don fhreastalaí seo",
|
||||
"column.firehose_singular": "Beo-bheatha",
|
||||
"column.follow_requests": "Iarratais leanúnaí",
|
||||
"column.home": "Baile",
|
||||
"column.list_members": "Bainistigh baill liosta",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Áitiúil amháin",
|
||||
"community.column_settings.media_only": "Meáin Amháin",
|
||||
"community.column_settings.remote_only": "Cian amháin",
|
||||
"compose.error.blank_post": "Ní féidir an post a fhágáil bán.",
|
||||
"compose.language.change": "Athraigh teanga",
|
||||
"compose.language.search": "Cuardaigh teangacha...",
|
||||
"compose.published.body": "Post foilsithe.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Post ar aon nós",
|
||||
"confirmations.missing_alt_text.title": "Cuir téacs alt leis?",
|
||||
"confirmations.mute.confirm": "Balbhaigh",
|
||||
"confirmations.private_quote_notify.cancel": "Ar ais chuig an eagarthóireacht",
|
||||
"confirmations.private_quote_notify.confirm": "Foilsigh an post",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Ná taispeáin an teachtaireacht seo dom arís",
|
||||
"confirmations.private_quote_notify.message": "Cuirfear an duine atá á lua agat agus luanna eile ar an eolas agus beidh siad in ann do phost a fheiceáil, fiú mura bhfuil siad ag leanúint thú.",
|
||||
"confirmations.private_quote_notify.title": "Roinn le leantóirí agus úsáideoirí a luadh?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Ná cuir i gcuimhne dom arís",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Tuigim é",
|
||||
"confirmations.quiet_post_quote_info.message": "Agus post poiblí ciúin á lua, beidh do phost i bhfolach ó amlínte treochta.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Níl aon phostáil leabharmharcaithe agat fós. Nuair a dhéanann tú leabharmharc, beidh sé le feiceáil anseo.",
|
||||
"empty_column.community": "Tá an amlíne áitiúil folamh. Foilsigh rud éigin go poiblí le tús a chur le cúrsaí!",
|
||||
"empty_column.direct": "Níl aon tagairtí príobháideacha agat fós. Nuair a sheolann tú nó a gheobhaidh tú ceann, beidh sé le feiceáil anseo.",
|
||||
"empty_column.disabled_feed": "Tá an fotha seo díchumasaithe ag riarthóirí do fhreastalaí.",
|
||||
"empty_column.domain_blocks": "Níl aon fearainn bhactha ann go fóill.",
|
||||
"empty_column.explore_statuses": "Níl rud ar bith ag treochtáil faoi láthair. Tar ar ais ar ball!",
|
||||
"empty_column.favourited_statuses": "Níl aon postálacha is fearr leat fós. Nuair is fearr leat ceann, beidh sé le feiceáil anseo.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Polasaí príobháideachais",
|
||||
"quote_error.edit": "Ní féidir Sleachta a chur leis agus post á chur in eagar.",
|
||||
"quote_error.poll": "Ní cheadaítear lua le pobalbhreitheanna.",
|
||||
"quote_error.private_mentions": "Ní cheadaítear lua le tagairtí díreacha.",
|
||||
"quote_error.quote": "Ní cheadaítear ach luachan amháin ag an am.",
|
||||
"quote_error.unauthorized": "Níl údarás agat an post seo a lua.",
|
||||
"quote_error.upload": "Ní cheadaítear lua a dhéanamh le ceangaltáin sna meáin.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Pionnáil ar do phróifíl",
|
||||
"status.quote": "Luachan",
|
||||
"status.quote.cancel": "Cealaigh an luachan",
|
||||
"status.quote_error.blocked_account_hint.title": "Tá an post seo i bhfolach mar gur chuir tú bac ar @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Tá an post seo i bhfolach mar gur chuir tú bac ar {domain}.",
|
||||
"status.quote_error.filtered": "I bhfolach mar gheall ar cheann de do scagairí",
|
||||
"status.quote_error.limited_account_hint.action": "Taispeáin ar aon nós",
|
||||
"status.quote_error.limited_account_hint.title": "Tá an cuntas seo i bhfolach ag modhnóirí {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Tá an post seo i bhfolach mar gur chuir tú @{name} ar neamhní.",
|
||||
"status.quote_error.not_available": "Níl an postáil ar fáil",
|
||||
"status.quote_error.pending_approval": "Post ar feitheamh",
|
||||
"status.quote_error.pending_approval_popout.body": "Ar Mastodon, is féidir leat a rialú an féidir le duine tú a lua nó nach féidir. Tá an post seo ar feitheamh fad is atá ceadú an údair bhunaidh á fháil againn.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Toirt síos",
|
||||
"video.volume_up": "Toirt suas",
|
||||
"visibility_modal.button_title": "Socraigh infheictheacht",
|
||||
"visibility_modal.direct_quote_warning.text": "Má shábhálann tú na socruithe reatha, déanfar an luachan leabaithe a thiontú ina nasc.",
|
||||
"visibility_modal.direct_quote_warning.title": "Ní féidir luachana a leabú i luanna príobháideacha",
|
||||
"visibility_modal.header": "Infheictheacht agus idirghníomhaíocht",
|
||||
"visibility_modal.helper.direct_quoting": "Ní féidir le daoine eile tráchtanna príobháideacha a scríobhadh ar Mastodon a lua.",
|
||||
"visibility_modal.helper.privacy_editing": "Ní féidir infheictheacht a athrú tar éis post a fhoilsiú.",
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
"account.disable_notifications": "Na cuir brath thugam tuilleadh nuair a chuireas @{name} post ris",
|
||||
"account.domain_blocking": "Àrainn ’ga bacadh",
|
||||
"account.edit_profile": "Deasaich a’ phròifil",
|
||||
"account.edit_profile_short": "Deasaich",
|
||||
"account.enable_notifications": "Cuir brath thugam nuair a chuireas @{name} post ris",
|
||||
"account.endorse": "Brosnaich air a’ phròifil",
|
||||
"account.familiar_followers_many": "’Ga leantainn le {name1}, {name2}, and {othersCount, plural, one {# eile air a bheil thu eòlach} other {# eile air a bheil thu eòlach}}",
|
||||
|
|
@ -40,6 +41,11 @@
|
|||
"account.featured_tags.last_status_never": "Gun phost",
|
||||
"account.follow": "Lean",
|
||||
"account.follow_back": "Lean air ais",
|
||||
"account.follow_back_short": "Lean air ais",
|
||||
"account.follow_request": "Iarr leantainn",
|
||||
"account.follow_request_cancel": "Sguir dhen iarrtas",
|
||||
"account.follow_request_cancel_short": "Sguir dheth",
|
||||
"account.follow_request_short": "Iarr",
|
||||
"account.followers": "Luchd-leantainn",
|
||||
"account.followers.empty": "Chan eil neach sam bith a’ leantainn air a’ chleachdaiche seo fhathast.",
|
||||
"account.followers_counter": "{count, plural, one {{counter} neach-leantainn} other {{counter} luchd-leantainn}}",
|
||||
|
|
@ -125,7 +131,7 @@
|
|||
"annual_report.summary.new_posts.new_posts": "postaichean ùra",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Tha thu am measg</topLabel><percentage></percentage><bottomLabel>dhen luchd-cleachdaidh as cliùitiche air {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Ainmeil ’nad latha ’s ’nad linn.",
|
||||
"annual_report.summary.thanks": "Mòran taing airson conaltradh air Mastodon.",
|
||||
"annual_report.summary.thanks": "Mòran taing airson conaltradh air Mastodon!",
|
||||
"attachments_list.unprocessed": "(gun phròiseasadh)",
|
||||
"audio.hide": "Falaich an fhuaim",
|
||||
"block_modal.remote_users_caveat": "Iarraidh sinn air an fhrithealaiche {domain} gun gèill iad ri do cho-dhùnadh. Gidheadh, chan eil barantas gun gèill iad on a làimhsicheas cuid a fhrithealaichean bacaidhean air dòigh eadar-dhealaichte. Dh’fhaoidte gum faic daoine gun chlàradh a-steach na postaichean poblach agad fhathast.",
|
||||
|
|
@ -167,6 +173,8 @@
|
|||
"column.edit_list": "Deasaich an liosta",
|
||||
"column.favourites": "Annsachdan",
|
||||
"column.firehose": "An saoghal beò",
|
||||
"column.firehose_local": "Loidhne-ama bheò an fhrithealaiche seo",
|
||||
"column.firehose_singular": "Loidhne-ama bheò beò",
|
||||
"column.follow_requests": "Iarrtasan leantainn",
|
||||
"column.home": "Dachaigh",
|
||||
"column.list_members": "Stiùir buill na liosta",
|
||||
|
|
@ -186,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Feadhainn ionadail a-mhàin",
|
||||
"community.column_settings.media_only": "Meadhanan a-mhàin",
|
||||
"community.column_settings.remote_only": "Feadhainn chèin a-mhàin",
|
||||
"compose.error.blank_post": "Chan urrrainn dho phost a bhith bàn.",
|
||||
"compose.language.change": "Atharraich an cànan",
|
||||
"compose.language.search": "Lorg cànan…",
|
||||
"compose.published.body": "Chaidh am post fhoillseachadh.",
|
||||
|
|
@ -238,10 +247,15 @@
|
|||
"confirmations.missing_alt_text.secondary": "Postaich e co-dhiù",
|
||||
"confirmations.missing_alt_text.title": "A bheil thu airson roghainn teacsa a chur ris?",
|
||||
"confirmations.mute.confirm": "Mùch",
|
||||
"confirmations.private_quote_notify.cancel": "Till dhan deasachadh",
|
||||
"confirmations.private_quote_notify.confirm": "Foillsich am post",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Na seall an teachdaireachd seo a-rithist dhomh",
|
||||
"confirmations.private_quote_notify.message": "Cuiridh sinn brath dhan neach a tha thu a’ luaidh ’s do na daoine eile le iomradh orra agus chì iad am post agad fiù mur eil iad ’gad leantainn.",
|
||||
"confirmations.private_quote_notify.title": "A bheil thu airson a cho-roinneadh leis an luchd-leantainn ’s na cleachdaichean le iomradh orra?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Na cuiribh seo ’nam chuimhne a-rithist",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Tha mi agaibh",
|
||||
"confirmations.quiet_post_quote_info.message": "Nuair a luaidheas tu post a tha poblach ach sàmhach, thèid am post agad fhalach o loidhnichean-ama nan treandaichean.",
|
||||
"confirmations.quiet_post_quote_info.title": "Luaidh air postaichean poblach ach sàmhach",
|
||||
"confirmations.quiet_post_quote_info.title": "Luaidh air postaichean sàmhach",
|
||||
"confirmations.redraft.confirm": "Sguab às ⁊ dèan dreachd ùr",
|
||||
"confirmations.redraft.message": "A bheil thu cinnteach gu bheil thu airson am post seo a sguabadh às agus dreachd ùr a thòiseachadh? Caillidh tu gach annsachd is brosnachadh air agus thèid freagairtean dhan phost thùsail ’nan dìlleachdanan.",
|
||||
"confirmations.redraft.title": "A bheil thu airson am post a sguabadh às ⁊ dreachd ùr a dhèanamh dheth?",
|
||||
|
|
@ -251,7 +265,12 @@
|
|||
"confirmations.revoke_quote.confirm": "Thoir am post air falbh",
|
||||
"confirmations.revoke_quote.message": "Cha ghabh seo a neo-dhèanamh.",
|
||||
"confirmations.revoke_quote.title": "A bheil thu airson am post a thoirt air falbh?",
|
||||
"confirmations.unblock.confirm": "Dì-bhac",
|
||||
"confirmations.unblock.title": "A bheil thu airson {name} a dhì-bhacadh?",
|
||||
"confirmations.unfollow.confirm": "Na lean tuilleadh",
|
||||
"confirmations.unfollow.title": "A bheil thu airson sgur de {name} a leantainn?",
|
||||
"confirmations.withdraw_request.confirm": "Cuir d’ iarrtas dhan dàrna taobh",
|
||||
"confirmations.withdraw_request.title": "A bheil thu airson d’ iarrtas gus {name} a leantainn a chur dhan dàrna taobh?",
|
||||
"content_warning.hide": "Falaich am post",
|
||||
"content_warning.show": "Seall e co-dhiù",
|
||||
"content_warning.show_more": "Seall barrachd dheth",
|
||||
|
|
@ -322,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Chan eil comharra-lìn ri post agad fhathast. Nuair a nì thu comharra-lìn de dh’fhear, nochdaidh e an-seo.",
|
||||
"empty_column.community": "Tha an loidhne-ama ionadail falamh. Sgrìobh rudeigin gu poblach airson toiseach-tòiseachaidh a dhèanamh!",
|
||||
"empty_column.direct": "Chan eil iomradh prìobhaideach agad fhathast. Nuair a chuireas no a gheibh thu tè, nochdaidh i an-seo.",
|
||||
"empty_column.disabled_feed": "Chaidh an loidhne-ama seo a chur à comas le rianairean an fhrithealaiche agad.",
|
||||
"empty_column.domain_blocks": "Cha deach àrainn sam bith a bhacadh fhathast.",
|
||||
"empty_column.explore_statuses": "Chan eil dad a’ treandadh an-dràsta fhèin. Thoir sùil a-rithist an ceann greis!",
|
||||
"empty_column.favourited_statuses": "Chan eil annsachd air post agad fhathast. Nuair a nì thu annsachd de dh’fhear, nochdaidh e an-seo.",
|
||||
|
|
@ -734,15 +754,17 @@
|
|||
"privacy.private.short": "Luchd-leantainn",
|
||||
"privacy.public.long": "Duine sam bith taobh a-staigh no a-muigh Mhastodon",
|
||||
"privacy.public.short": "Poblach",
|
||||
"privacy.quote.anyone": "{visibility}, faodaidh neach sam bith a luaidh",
|
||||
"privacy.quote.disabled": "{visibility}, luaidhean à comas",
|
||||
"privacy.quote.limited": "{visibility}, luaidhean cuingichte",
|
||||
"privacy.quote.anyone": "{visibility}, luaidh fosgailte",
|
||||
"privacy.quote.disabled": "{visibility}, luaidh à comas",
|
||||
"privacy.quote.limited": "{visibility}, luaidh cuingichte",
|
||||
"privacy.unlisted.additional": "Tha seo coltach ris an fhaicsinneachd phoblach ach cha nochd am post air loidhnichean-ama an t-saoghail phoblaich, nan tagaichean hais no an rùrachaidh no ann an toraidhean luirg Mhastodon fiù ’s ma thug thu ro-aonta airson sin seachad.",
|
||||
"privacy.unlisted.long": "Falaichte o na toraidhean-luirg, na treandaichean ’s na loichnichean-ama poblach",
|
||||
"privacy.unlisted.short": "Poblach ach sàmhach",
|
||||
"privacy.unlisted.long": "Poblach ach falaichte o na toraidhean-luirg, na treandaichean ’s na loichnichean-ama poblach",
|
||||
"privacy.unlisted.short": "Sàmhach",
|
||||
"privacy_policy.last_updated": "An t-ùrachadh mu dheireadh {date}",
|
||||
"privacy_policy.title": "Poileasaidh prìobhaideachd",
|
||||
"quote_error.edit": "Chan urrainn dhut luaidh a chur ris nuair a bhios tu ri deasachadh puist.",
|
||||
"quote_error.poll": "Chan fhaod thu luaidh a chur an cois cunntais-bheachd.",
|
||||
"quote_error.private_mentions": "Chan fhaod thu luaidh a chur an cois iomraidh phrìobhaidich.",
|
||||
"quote_error.quote": "Chan eil taic ach ri aon luaidh aig an aon àm.",
|
||||
"quote_error.unauthorized": "Chan fhaod thu am post seo a luaidh.",
|
||||
"quote_error.upload": "Chan fhaod thu meadhan a chur ri luaidh.",
|
||||
|
|
@ -861,6 +883,13 @@
|
|||
"status.cancel_reblog_private": "Na brosnaich tuilleadh",
|
||||
"status.cannot_quote": "Chan fhaod thu am post seo a luaidh",
|
||||
"status.cannot_reblog": "Cha ghabh am post seo brosnachadh",
|
||||
"status.contains_quote": "Tha luaidh na bhroinn",
|
||||
"status.context.loading": "A’ luchdadh barrachd fhreagairtean",
|
||||
"status.context.loading_error": "Cha b’ urrainn dhuinn nam freagairtean ùra a luchdadh",
|
||||
"status.context.loading_success": "Chaidh na freagairtean ùra a luchdadh",
|
||||
"status.context.more_replies_found": "Fhuair sinn lorg air barrachd fhreagairtean",
|
||||
"status.context.retry": "Feuch ris a-rithist",
|
||||
"status.context.show": "Seall",
|
||||
"status.continued_thread": "Pàirt de shnàithlean",
|
||||
"status.copy": "Dèan lethbhreac dhen cheangal dhan phost",
|
||||
"status.delete": "Sguab às",
|
||||
|
|
@ -889,18 +918,26 @@
|
|||
"status.pin": "Prìnich ris a’ phròifil",
|
||||
"status.quote": "Luaidh",
|
||||
"status.quote.cancel": "Sguir dhen luaidh",
|
||||
"status.quote_error.blocked_account_hint.title": "Tha am post seo falaichte on a bhac thu @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Tha am post seo falaichte on a bhac thu {domain}.",
|
||||
"status.quote_error.filtered": "Falaichte le criathrag a th’ agad",
|
||||
"status.quote_error.limited_account_hint.action": "Seall e co-dhiù",
|
||||
"status.quote_error.limited_account_hint.title": "Chaidh an cunntas seo fhalach le maoir {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Tha am post seo falaichte on a mhùch thu @{name}.",
|
||||
"status.quote_error.not_available": "Chan eil am post ri fhaighinn",
|
||||
"status.quote_error.pending_approval": "Cha deach dèiligeadh ris a’ phost fhathast",
|
||||
"status.quote_error.pending_approval_popout.body": "Air Mastodon, ’s urrainn dhut stiùireadh am faod cuideigin do luaidh gus nach fhaod. Tha am post seo a’ feitheamh air aonta an ùghdair thùsail.",
|
||||
"status.quote_error.revoked": "Chaidh am post a thoirt air falbh leis an ùghdar",
|
||||
"status.quote_followers_only": "Chan fhaod ach luchd-leantainn am post seo a luaidh",
|
||||
"status.quote_manual_review": "Nì an t-ùghdar lèirmheas air a làimh",
|
||||
"status.quote_noun": "Luaidh",
|
||||
"status.quote_policy_change": "Atharraich cò dh’fhaodas luaidh",
|
||||
"status.quote_post_author": "Luaidh air post le @{name}",
|
||||
"status.quote_private": "Chan fhaodar postaichean prìobhaideach a luaidh",
|
||||
"status.quotes": "{count, plural, one {luaidh} two {luaidh} few {luaidhean} other {luaidh}}",
|
||||
"status.quotes.empty": "Chan deach am post seo a luaidh le duine sam bith fhathast. Nuair a luaidheas cuideigin e, nochdaidh iad an-seo.",
|
||||
"status.quotes.local_other_disclaimer": "Cha tèid luaidhean a dhiùilt an ùghdar a shealltainn.",
|
||||
"status.quotes.remote_other_disclaimer": "Cha dèid ach luaidhean o {domain} a shealltainn an-seo le cinnt. Cha dèid luaidhean a dhiùilt an ùghdar a shealltainn.",
|
||||
"status.read_more": "Leugh an còrr",
|
||||
"status.reblog": "Brosnaich",
|
||||
"status.reblog_or_quote": "Brosnaich no luaidh",
|
||||
|
|
@ -981,17 +1018,19 @@
|
|||
"video.volume_down": "Lùghdaich an fhuaim",
|
||||
"video.volume_up": "Cuir an fhuaim an àirde",
|
||||
"visibility_modal.button_title": "Suidhich an fhaicsinneachd",
|
||||
"visibility_modal.direct_quote_warning.text": "Ma shàbhaileas tu na roghainnean làithreach, thèid ceangal a dhèanamh dhen luaidh leabaichte.",
|
||||
"visibility_modal.direct_quote_warning.title": "Chan urrainn dhut luaidh a leabachadh ann an iomradh prìobhaideach",
|
||||
"visibility_modal.header": "Faicsinneachd ⁊ eadar-ghabhail",
|
||||
"visibility_modal.helper.direct_quoting": "Chan urrainn do chàch iomraidhean prìobhaideach a chaidh a sgrìobhadh le Mastodon a luaidh.",
|
||||
"visibility_modal.helper.privacy_editing": "Chan urrainn dhut faicsinneachd puist atharrachadh às dhèidh fhoillseachadh.",
|
||||
"visibility_modal.helper.privacy_private_self_quote": "Chan fhaodar fèin-luaidhean air postaichean prìobhaideach a dhèanamh poblach.",
|
||||
"visibility_modal.helper.private_quoting": "Chan urrainn do chàch postaichean dhan luchd-leantainn a-mhàin a chaidh a sgrìobhadh le Mastodon a luaidh.",
|
||||
"visibility_modal.helper.unlisted_quoting": "Nuair a luaidheas daoine thu, thèid am post aca-san fhalach o loidhnichean-ama nan treandaichean.",
|
||||
"visibility_modal.instructions": "Stiùirich cò dh’fhaodas eadar-ghabhahil leis a’ phost seo. ’S urrainn dhut do roghainnean airson nam postaichean ri teachd a thaghadh aig <link>Roghainnean > Bun-roghainnean a’ phostaidh</link>",
|
||||
"visibility_modal.instructions": "Stiùirich cò dh’fhaodas eadar-ghabhahil leis a’ phost seo. ’S urrainn dhut do roghainnean airson nam postaichean ri teachd a thaghadh aig <link>Roghainnean > Bun-roghainnean a’ phostaidh</link>.",
|
||||
"visibility_modal.privacy_label": "Faicsinneachd",
|
||||
"visibility_modal.quote_followers": "Luchd-leantainn a-mhàin",
|
||||
"visibility_modal.quote_label": "Cò dh’fhaodas luaidh",
|
||||
"visibility_modal.quote_nobody": "Mi fhìn a-mhàin",
|
||||
"visibility_modal.quote_public": "Duine sam bith",
|
||||
"visibility_modal.quote_public": "Neach sam bith",
|
||||
"visibility_modal.save": "Sàbhail"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Editar lista",
|
||||
"column.favourites": "Favoritas",
|
||||
"column.firehose": "O que acontece",
|
||||
"column.firehose_local": "Acontece agora neste servidor",
|
||||
"column.firehose_singular": "O que acontece",
|
||||
"column.follow_requests": "Peticións de seguimento",
|
||||
"column.home": "Inicio",
|
||||
"column.list_members": "Xestionar membros da lista",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Só local",
|
||||
"community.column_settings.media_only": "Só multimedia",
|
||||
"community.column_settings.remote_only": "Só remoto",
|
||||
"compose.error.blank_post": "A publicación non pode estar baleira.",
|
||||
"compose.language.change": "Elixe o idioma",
|
||||
"compose.language.search": "Buscar idiomas...",
|
||||
"compose.published.body": "Mensaxe publicada.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Publicar igualmente",
|
||||
"confirmations.missing_alt_text.title": "Engadir texto descritivo?",
|
||||
"confirmations.mute.confirm": "Acalar",
|
||||
"confirmations.private_quote_notify.cancel": "Volver á edición",
|
||||
"confirmations.private_quote_notify.confirm": "Publicar publicación",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Non me volvas a mostrar esta mensaxe",
|
||||
"confirmations.private_quote_notify.message": "A persoa que estás a citar e outras contas mencionadas serán notificadas e poderán ver a túa publicación, incluso se non te seguen.",
|
||||
"confirmations.private_quote_notify.title": "Compartir coas seguidoras e coas usuarias mencionadas?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Non lembrarmo máis",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Entendido",
|
||||
"confirmations.quiet_post_quote_info.message": "Ao citar unha publicación pública limitada a túa publicación non aparecerá nas cronoloxías de tendencias.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Aínda non marcaches ningunha publicación. Cando o fagas, aparecerán aquí.",
|
||||
"empty_column.community": "A cronoloxía local está baleira. Escribe algo de xeito público para espallalo!",
|
||||
"empty_column.direct": "Aínda non tes mencións privadas. Cando envíes ou recibas unha, aparecerá aquí.",
|
||||
"empty_column.disabled_feed": "A administración do teu servidor desactivou esta canle.",
|
||||
"empty_column.domain_blocks": "Aínda non hai dominios agochados.",
|
||||
"empty_column.explore_statuses": "Non hai temas en voga. Volve máis tarde!",
|
||||
"empty_column.favourited_statuses": "Aínda non tes publicacións favoritas. Cando favorezas unha, aparecerá aquí.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Política de Privacidade",
|
||||
"quote_error.edit": "Non se poden engadir citas ao editar unha publicación.",
|
||||
"quote_error.poll": "Non se permite citar as enquisas.",
|
||||
"quote_error.private_mentions": "As citas non están permitidas nas mencións directas.",
|
||||
"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.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Fixar no perfil",
|
||||
"status.quote": "Citar",
|
||||
"status.quote.cancel": "Cancelar a cita",
|
||||
"status.quote_error.blocked_account_hint.title": "A publicación está oculta porque bloqueaches a @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "A publicación está oculta porque bloqueaches {domain}.",
|
||||
"status.quote_error.filtered": "Oculto debido a un dos teus filtros",
|
||||
"status.quote_error.limited_account_hint.action": "Mostrar igualmente",
|
||||
"status.quote_error.limited_account_hint.title": "A moderación de {domain} ocultou esta conta.",
|
||||
"status.quote_error.muted_account_hint.title": "A publicación está oculta porque silenciaches a @{name}.",
|
||||
"status.quote_error.not_available": "Publicación non dispoñible",
|
||||
"status.quote_error.pending_approval": "Publicación pendente",
|
||||
"status.quote_error.pending_approval_popout.body": "En Mastodon podes establecer se permites que te citen. Esta publicación queda pendente á espera de que a persoa autora orixinal o autorice.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Baixar volume",
|
||||
"video.volume_up": "Subir volume",
|
||||
"visibility_modal.button_title": "Establece a visibilidade",
|
||||
"visibility_modal.direct_quote_warning.text": "Se gardas os axustes actuais a cita incluída vaise converter nunha ligazón.",
|
||||
"visibility_modal.direct_quote_warning.title": "As citas non se poden incluír nas mencións privadas",
|
||||
"visibility_modal.header": "Visibilidade e interaccións",
|
||||
"visibility_modal.helper.direct_quoting": "As mencións privadas creadas con Mastodon non poden ser citadas.",
|
||||
"visibility_modal.helper.privacy_editing": "Non se pode cambiar a visibilidade unha vez foi publicada.",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "עריכת רשימה",
|
||||
"column.favourites": "חיבובים",
|
||||
"column.firehose": "פידים עדכניים",
|
||||
"column.firehose_local": "פיד זמן האמת עבור שרת זה",
|
||||
"column.firehose_singular": "פיד זמן אמת",
|
||||
"column.follow_requests": "בקשות מעקב",
|
||||
"column.home": "פיד הבית",
|
||||
"column.list_members": "ניהול חברי הרשימה",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "מקומי בלבד",
|
||||
"community.column_settings.media_only": "מדיה בלבד",
|
||||
"community.column_settings.remote_only": "מרוחק בלבד",
|
||||
"compose.error.blank_post": "הודעה לא יכולה להיות ריקה.",
|
||||
"compose.language.change": "שינוי שפת ההודעה",
|
||||
"compose.language.search": "חיפוש שפות...",
|
||||
"compose.published.body": "הודעה פורסמה.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "לפרסם בכל זאת",
|
||||
"confirmations.missing_alt_text.title": "להוסיף מלל חלופי?",
|
||||
"confirmations.mute.confirm": "להשתיק",
|
||||
"confirmations.private_quote_notify.cancel": "חזרה לעריכה",
|
||||
"confirmations.private_quote_notify.confirm": "פרסום ההודעה",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "אל תראה לי הודעה זו שוב",
|
||||
"confirmations.private_quote_notify.message": "המצוטט ומאוזכרים אחרים יקבלו התראה ויוכלו לקרוא את ההודעה שלך, אפילו אם אינם עוקבים אחריך.",
|
||||
"confirmations.private_quote_notify.title": "לשתף עם עוקבים ומאוזכרים?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "אל תזכיר לי שוב",
|
||||
"confirmations.quiet_post_quote_info.got_it": "הבנתי",
|
||||
"confirmations.quiet_post_quote_info.message": "כשמצטטים הודעה ציבורית שקטה, גם ההודעה המצטטת תוסתר מחלון הנושאים החמים.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "אין עדיין הודעות שחיבבת. כשתחבב את הראשונה, היא תופיע כאן.",
|
||||
"empty_column.community": "פיד השרת המקומי ריק. יש לפרסם משהו כדי שדברים יתרחילו להתגלגל!",
|
||||
"empty_column.direct": "אין לך שום הודעות פרטיות עדיין. כשתשלחו או תקבלו אחת, היא תופיע כאן.",
|
||||
"empty_column.disabled_feed": "פיד זה נחסם לשימוש על ידי מנהלי השרת שלך.",
|
||||
"empty_column.domain_blocks": "אין עדיין קהילות מוסתרות.",
|
||||
"empty_column.explore_statuses": "אין נושאים חמים כרגע. אולי אחר כך!",
|
||||
"empty_column.favourited_statuses": "אין עדיין הודעות שחיבבת. כשתחבב/י את הראשונה, היא תופיע כאן.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "מדיניות פרטיות",
|
||||
"quote_error.edit": "לא ניתן להוסיף ציטוטים בשלב עריכת ההודעה.",
|
||||
"quote_error.poll": "לא ניתן לכלול משאל כאשר מחברים הודעת ציטוט.",
|
||||
"quote_error.private_mentions": "ציטוט אינו אפשרי בהודעות פרטיות.",
|
||||
"quote_error.quote": "רק ציטוט אחד מותר בכל הודעה.",
|
||||
"quote_error.unauthorized": "אין לך הרשאה לצטט את ההודעה הזו.",
|
||||
"quote_error.upload": "ציטוט הכולל מדיה אינו אפשרי.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "הצמדה לפרופיל שלי",
|
||||
"status.quote": "ציטוט",
|
||||
"status.quote.cancel": "ביטול הודעת ציטוט",
|
||||
"status.quote_error.blocked_account_hint.title": "ההודעה הזו מוסתרת כי חסמת את @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "ההודעה הזו מוסתרת כי חסמת את כל {domain}.",
|
||||
"status.quote_error.filtered": "מוסתר בהתאם לסננים שלך",
|
||||
"status.quote_error.limited_account_hint.action": "להציג בכל זאת",
|
||||
"status.quote_error.limited_account_hint.title": "חשבון הזה הוסתר על ידי מנחי הדיון של {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "ההודעה הזו מוסתרת כי השתקת את @{name}.",
|
||||
"status.quote_error.not_available": "ההודעה לא זמינה",
|
||||
"status.quote_error.pending_approval": "ההודעה בהמתנה לאישור",
|
||||
"status.quote_error.pending_approval_popout.body": "ברשת מסטודון, ניתן להגביל את האפשרות לצטט הודעות. ההודעה הזו ממתינה עד שהמחבר.ת של ההודעה המקורית יאשרו לך את הציטוט.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "הנמכת עוצמת השמע",
|
||||
"video.volume_up": "הגברת עוצמת שמע",
|
||||
"visibility_modal.button_title": "בחירת רמת חשיפה",
|
||||
"visibility_modal.direct_quote_warning.text": "אם תשמרו את ההעדפות הנוכחיות, הציטוט המוטמע יהפוך לקישור.",
|
||||
"visibility_modal.direct_quote_warning.title": "לא ניתן להטמיע ציטוטים בהודעות פרטיות",
|
||||
"visibility_modal.header": "חשיפה והידוּד (אינטראקציה)",
|
||||
"visibility_modal.helper.direct_quoting": "איזכורים פרטיים שנוצרו במסטודון חסומים מציטוט על ידי אחרים.",
|
||||
"visibility_modal.helper.privacy_editing": "רמת החשיפה של ההודעה לא ניתנת לשינוי אחרי הפרסום.",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Lista módosítása",
|
||||
"column.favourites": "Kedvencek",
|
||||
"column.firehose": "Hírfolyamok",
|
||||
"column.firehose_local": "Élő hírfolyam a kiszolgálóhoz",
|
||||
"column.firehose_singular": "Élő hírfolyam",
|
||||
"column.follow_requests": "Követési kérések",
|
||||
"column.home": "Kezdőlap",
|
||||
"column.list_members": "Listatagok kezelése",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Csak helyi",
|
||||
"community.column_settings.media_only": "Csak média",
|
||||
"community.column_settings.remote_only": "Csak távoli",
|
||||
"compose.error.blank_post": "A bejegyzés nem lehet üres.",
|
||||
"compose.language.change": "Nyelv megváltoztatása",
|
||||
"compose.language.search": "Nyelvek keresése…",
|
||||
"compose.published.body": "A bejegyzés publikálásra került.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Közzététel mindenképpen",
|
||||
"confirmations.missing_alt_text.title": "Helyettesítő szöveg hozzáadása?",
|
||||
"confirmations.mute.confirm": "Némítás",
|
||||
"confirmations.private_quote_notify.cancel": "Vissza a szerkesztéshez",
|
||||
"confirmations.private_quote_notify.confirm": "Bejegyzés közzététele",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Ne jelenítse meg újra ezt az üzenetet",
|
||||
"confirmations.private_quote_notify.message": "Akit idézel, és a többi megemlített értesítve lesz, és megtekinthetik a bejegyzésed, még akkor is, ha nem követnek.",
|
||||
"confirmations.private_quote_notify.title": "Megosztás a követőkkel és a megemlített felhasználókkal?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Ne emlékeztessen újra",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Rendben",
|
||||
"confirmations.quiet_post_quote_info.message": "Ha csendes nyilvános bejegyzést idézel, akkor a bejegyzés el lesz rejtve a felkapottak idővonalairól.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Még nincs egyetlen könyvjelzőzött bejegyzésed sem. Ha könyvjelzőzöl egyet, itt fog megjelenni.",
|
||||
"empty_column.community": "A helyi idővonal üres. Tégy közzé valamit nyilvánosan, hogy elindítsd az eseményeket!",
|
||||
"empty_column.direct": "Még nincs egy személyes említésed sem. Küldéskor vagy fogadáskor itt fognak megjelenni.",
|
||||
"empty_column.disabled_feed": "A kiszolgálód rendszergazdái letiltották ezt a hírfolyamot.",
|
||||
"empty_column.domain_blocks": "Még nem lett letiltva egyetlen domain sem.",
|
||||
"empty_column.explore_statuses": "Jelenleg semmi sem felkapott. Nézz vissza később!",
|
||||
"empty_column.favourited_statuses": "Még nincs egyetlen kedvenc bejegyzésed sem. Ha kedvencnek jelölsz egyet, itt fog megjelenni.",
|
||||
|
|
@ -908,9 +917,12 @@
|
|||
"status.pin": "Kitűzés a profilodra",
|
||||
"status.quote": "Idézés",
|
||||
"status.quote.cancel": "Idézés elvetése",
|
||||
"status.quote_error.blocked_account_hint.title": "Ez a bejegyzés rejtett, mert blokkoltad @{name} felhasználót.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Ez a bejegyzés rejtett, mert blokkoltad a(z) {domain} domaint.",
|
||||
"status.quote_error.filtered": "A szűrőid miatt rejtett",
|
||||
"status.quote_error.limited_account_hint.action": "Megjelenítés mindenképp",
|
||||
"status.quote_error.limited_account_hint.title": "Ezt a fiókot elrejtették a(z) {domain} moderátorai.",
|
||||
"status.quote_error.muted_account_hint.title": "Ez a bejegyzés rejtett, mert némítottad @{name} felhasználót.",
|
||||
"status.quote_error.not_available": "A bejegyzés nem érhető el",
|
||||
"status.quote_error.pending_approval": "A bejegyzés függőben van",
|
||||
"status.quote_error.pending_approval_popout.body": "A Mastodonon te mondod meg, hogy valaki idézhet-e. Ez a bejegyzés addig függőben marad, amíg az eredeti szerző nem engedélyezi azt.",
|
||||
|
|
@ -1005,6 +1017,8 @@
|
|||
"video.volume_down": "Hangerő le",
|
||||
"video.volume_up": "Hangerő fel",
|
||||
"visibility_modal.button_title": "Láthatóság beállítása",
|
||||
"visibility_modal.direct_quote_warning.text": "Ha mented a jelenlegi beállításokat, akkor a beágyazott idézet hivatkozássá lesz alakítva.",
|
||||
"visibility_modal.direct_quote_warning.title": "Idézetek nem ágyazhatóak be privát említésekbe",
|
||||
"visibility_modal.header": "Láthatóság és interakció",
|
||||
"visibility_modal.helper.direct_quoting": "A Mastodonon készült privát említéseket mások nem idézhetik.",
|
||||
"visibility_modal.helper.privacy_editing": "A láthatóság nem módosítható a bejegyzés közzététele után.",
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@
|
|||
"column.domain_blocks": "Dominios blocate",
|
||||
"column.edit_list": "Modificar lista",
|
||||
"column.favourites": "Favorites",
|
||||
"column.firehose": "Fluxos in directo",
|
||||
"column.firehose": "Fluxos in vivo",
|
||||
"column.follow_requests": "Requestas de sequimento",
|
||||
"column.home": "Initio",
|
||||
"column.list_members": "Gerer le membros del lista",
|
||||
|
|
@ -333,6 +333,7 @@
|
|||
"empty_column.bookmarked_statuses": "Tu non ha ancora messages in marcapaginas. Quando tu adde un message al marcapaginas, illo apparera hic.",
|
||||
"empty_column.community": "Le chronologia local es vacue. Scribe qualcosa public pro poner le cosas in marcha!",
|
||||
"empty_column.direct": "Tu non ha ancora mentiones private. Quando tu invia o recipe un mention, illo apparera hic.",
|
||||
"empty_column.disabled_feed": "Iste canal ha essite disactivate per le adminsistratores de tu servitor.",
|
||||
"empty_column.domain_blocks": "Il non ha dominios blocate ancora.",
|
||||
"empty_column.explore_statuses": "Il non ha tendentias in iste momento. Reveni plus tarde!",
|
||||
"empty_column.favourited_statuses": "Tu non ha alcun message favorite ancora. Quando tu marca un message como favorite, illo apparera hic.",
|
||||
|
|
@ -460,7 +461,7 @@
|
|||
"ignore_notifications_modal.not_following_title": "Ignorar notificationes de personas que tu non seque?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignorar notificationes de mentiones private non requestate?",
|
||||
"info_button.label": "Adjuta",
|
||||
"info_button.what_is_alt_text": "<h1>Que es texto alternative?</h1><p>Le texto alternative forni descriptiones de imagines a personas con impedimentos visual, con connexiones lente, o qui cerca contexto additional.</p><p>Tu pote meliorar le accessibilitate e le comprension pro totes scribente un texto alternative clar, concise e objective.</p><ul><li>Captura le elementos importante</li><li>Summarisa texto in imagines</li><li>Usa le structura de phrase normal</li><li>Evita information redundante</li><li>In figuras complexe (como diagrammas o mappas), concentra te sur le tendentias e punctos clave</li></ul>",
|
||||
"info_button.what_is_alt_text": "<h1>Que es texto alternative?</h1><p>Le texto alternative forni descriptiones de imagines a personas con impedimentos visual, con connexiones lente a internet, o qui cerca contexto supplementari.</p><p>Tu pote meliorar le accessibilitate e le comprension pro totes si tu scribe un texto alternative clar, concise e objective.</p><ul><li>Captura le elementos importante</li><li>Summarisa texto in imagines</li><li>Usa un structura conventional de phrases</li><li>Evita information redundante</li><li>In figuras complexe (como diagrammas o mappas), concentra te sur le tendentias e punctos clave</li></ul>",
|
||||
"interaction_modal.action": "Pro interager con le message de {name}, tu debe acceder a tu conto sur le servitor Mastodon que tu usa.",
|
||||
"interaction_modal.go": "Revenir",
|
||||
"interaction_modal.no_account_yet": "Tu non ha ancora un conto?",
|
||||
|
|
@ -574,8 +575,8 @@
|
|||
"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.live_feed_local": "Canal in vivo (local)",
|
||||
"navigation_bar.live_feed_public": "Canal in vivo (public)",
|
||||
"navigation_bar.logout": "Clauder session",
|
||||
"navigation_bar.moderation": "Moderation",
|
||||
"navigation_bar.more": "Plus",
|
||||
|
|
@ -748,7 +749,7 @@
|
|||
"privacy.quote.anyone": "{visibility}, omnes pote citar",
|
||||
"privacy.quote.disabled": "{visibility}, citation disactivate",
|
||||
"privacy.quote.limited": "{visibility}, citation limitate",
|
||||
"privacy.unlisted.additional": "Isto es exactemente como public, excepte que le message non apparera in fluxos in directo, in hashtags, in Explorar, o in le recerca de Mastodon, mesmo si tu ha optate pro render tote le conto discoperibile.",
|
||||
"privacy.unlisted.additional": "Isto es exactemente como public, excepte que le message non apparera in fluxos in vivo, in hashtags, in Explorar, o in le recerca de Mastodon, mesmo si tu ha optate pro render tote le conto discoperibile.",
|
||||
"privacy.unlisted.long": "Non apparera in le resultatos de recerca, tendentias e chronologias public de Mastodon",
|
||||
"privacy.unlisted.short": "Public, non listate",
|
||||
"privacy_policy.last_updated": "Ultime actualisation {date}",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Breyta lista",
|
||||
"column.favourites": "Eftirlæti",
|
||||
"column.firehose": "Bein streymi",
|
||||
"column.firehose_local": "Beint streymi á þessum netþjóni",
|
||||
"column.firehose_singular": "Beint streymi",
|
||||
"column.follow_requests": "Beiðnir um að fylgjast með",
|
||||
"column.home": "Heim",
|
||||
"column.list_members": "Sýsla með meðlimi listans",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Einungis staðvært",
|
||||
"community.column_settings.media_only": "Einungis myndskrár",
|
||||
"community.column_settings.remote_only": "Einungis fjartengt",
|
||||
"compose.error.blank_post": "Færsla má ekki vera auð.",
|
||||
"compose.language.change": "Skipta um tungumál",
|
||||
"compose.language.search": "Leita að tungumálum...",
|
||||
"compose.published.body": "Færsla birt.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Birta samt",
|
||||
"confirmations.missing_alt_text.title": "Bæta við hjálpartexta?",
|
||||
"confirmations.mute.confirm": "Þagga",
|
||||
"confirmations.private_quote_notify.cancel": "Til baka í breytingar",
|
||||
"confirmations.private_quote_notify.confirm": "Birta færslu",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Ekki birta þessi skilaboð aftur",
|
||||
"confirmations.private_quote_notify.message": "Sá sem vitnað er í og aðrir sem minnst er á verða látin vita og munu geta skoðað færsluna þína, jafnvel þótt viðkomandi fylgist ekki með þér.",
|
||||
"confirmations.private_quote_notify.title": "Deila með fylgjendum og þeim sem minnst er á?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Ekki minna mig aftur á þetta",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Náði því",
|
||||
"confirmations.quiet_post_quote_info.message": "Þegar þú vitnar í hljóðláta opinbera færslu, verður færslan þín ekki birt á vinsældatímalínum.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Þú ert ekki ennþá með neinar bókamerktar færslur. Þegar þú bókamerkir færslu, mun það birtast hér.",
|
||||
"empty_column.community": "Staðværa tímalínan er tóm. Skrifaðu eitthvað opinberlega til að láta boltann fara að rúlla!",
|
||||
"empty_column.direct": "Þú ert ekki ennþá með neitt einkaspjall við neinn. Þegar þú sendir eða tekur við slíku, mun það birtast hér.",
|
||||
"empty_column.disabled_feed": "Þetta streymi hefur verið gert óvirkt af stjórnendum netþjónis þíns.",
|
||||
"empty_column.domain_blocks": "Það eru ennþá engin útilokuð lén.",
|
||||
"empty_column.explore_statuses": "Ekkert er á uppleið í augnablikinu. Athugaðu aftur síðar!",
|
||||
"empty_column.favourited_statuses": "Þú ert ekki ennþá með neinar eftirlætisfærslur. Þegar þú setur færslu í eftirlæti, munu þau birtast hér.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Persónuverndarstefna",
|
||||
"quote_error.edit": "Ekki er hægt að bæta við tilvitnunum þegar færslum er breytt.",
|
||||
"quote_error.poll": "Ekki er leyft að vitna í kannanir.",
|
||||
"quote_error.private_mentions": "Tilvitnanir eru ekki leyfðar í beinu einkaspjalli.",
|
||||
"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.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Festa á notandasnið",
|
||||
"status.quote": "Tilvitnun",
|
||||
"status.quote.cancel": "Hætta við tilvitnun",
|
||||
"status.quote_error.blocked_account_hint.title": "Þessi færsla er falin vegna þess að ú hefur lokað á @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Þessi færsla er falin vegna þess að ú hefur lokað á {domain}.",
|
||||
"status.quote_error.filtered": "Falið vegna einnar síu sem er virk",
|
||||
"status.quote_error.limited_account_hint.action": "Birta samt",
|
||||
"status.quote_error.limited_account_hint.title": "Þessi notandaaðgangur hefur verið falinn af stjórnendum á {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Þessi færsla er falin vegna þess að ú hefur þaggað niður í @{name}.",
|
||||
"status.quote_error.not_available": "Færsla ekki tiltæk",
|
||||
"status.quote_error.pending_approval": "Færsla í bið",
|
||||
"status.quote_error.pending_approval_popout.body": "Á Mastodon geturðu stjórnað því hvort aðrir geti vitnað í þig. Þessi færsla bíður eftir samþykki upprunalegs höfundar.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Lækka hljóðstyrk",
|
||||
"video.volume_up": "Hækka hljóðstyrk",
|
||||
"visibility_modal.button_title": "Stilla sýnileika",
|
||||
"visibility_modal.direct_quote_warning.text": "Ef þú vistar þessa stillingu, þá verður ívöfnu tilvitnuninni breytt í tengil.",
|
||||
"visibility_modal.direct_quote_warning.title": "Ekki er hægt að ívefja tilvitnanir í beinu einkaspjalli",
|
||||
"visibility_modal.header": "Sýnileiki og gagnvirkni",
|
||||
"visibility_modal.helper.direct_quoting": "Ekki er hægt að vitna í einkaspjall sem skrifað er á Mastodon.",
|
||||
"visibility_modal.helper.privacy_editing": "Ekki er hægt að breyta sýnileika færslu eftir að hún hefur verið birt.",
|
||||
|
|
|
|||
|
|
@ -172,7 +172,9 @@
|
|||
"column.domain_blocks": "Domini bloccati",
|
||||
"column.edit_list": "Modifica lista",
|
||||
"column.favourites": "Preferiti",
|
||||
"column.firehose": "Feed dal vivo",
|
||||
"column.firehose": "Feed in diretta",
|
||||
"column.firehose_local": "Feed in diretta per questo server",
|
||||
"column.firehose_singular": "Feed in diretta",
|
||||
"column.follow_requests": "Richieste di seguirti",
|
||||
"column.home": "Home",
|
||||
"column.list_members": "Gestisci i membri della lista",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Solo Locale",
|
||||
"community.column_settings.media_only": "Solo Media",
|
||||
"community.column_settings.remote_only": "Solo Remoto",
|
||||
"compose.error.blank_post": "Il post non può essere vuoto.",
|
||||
"compose.language.change": "Cambia la lingua",
|
||||
"compose.language.search": "Cerca lingue...",
|
||||
"compose.published.body": "Post pubblicato.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Pubblica comunque",
|
||||
"confirmations.missing_alt_text.title": "Aggiungere testo alternativo?",
|
||||
"confirmations.mute.confirm": "Silenzia",
|
||||
"confirmations.private_quote_notify.cancel": "Torna a modificare",
|
||||
"confirmations.private_quote_notify.confirm": "Pubblica il post",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Non mostrarmi più questo messaggio",
|
||||
"confirmations.private_quote_notify.message": "La persona che stai citando e le altre persone menzionate riceveranno una notifica e potranno visualizzare il tuo post, anche se non ti stanno seguendo.",
|
||||
"confirmations.private_quote_notify.title": "Condividere con i seguaci e gli utenti menzionati?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Non ricordarmelo più",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Ho capito",
|
||||
"confirmations.quiet_post_quote_info.message": "Quando citi un post pubblico silenzioso, il tuo post verrà nascosto dalle timeline di tendenza.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Non hai ancora salvato nei segnalibri alcun post. Quando lo farai, apparirà qui.",
|
||||
"empty_column.community": "La cronologia locale è vuota. Scrivi qualcosa pubblicamente per dare inizio alla festa!",
|
||||
"empty_column.direct": "Non hai ancora alcuna menzione privata. Quando ne invierai o riceverai una, apparirà qui.",
|
||||
"empty_column.disabled_feed": "Questo feed è stato disabilitato dagli amministratori del tuo server.",
|
||||
"empty_column.domain_blocks": "Ancora nessun dominio bloccato.",
|
||||
"empty_column.explore_statuses": "Nulla è in tendenza al momento. Ricontrolla più tardi!",
|
||||
"empty_column.favourited_statuses": "Non hai ancora alcun post preferito. Quando ne salverai uno tra i preferiti, apparirà qui.",
|
||||
|
|
@ -574,8 +583,8 @@
|
|||
"navigation_bar.follows_and_followers": "Seguiti e seguaci",
|
||||
"navigation_bar.import_export": "Importa ed esporta",
|
||||
"navigation_bar.lists": "Liste",
|
||||
"navigation_bar.live_feed_local": "Feed live (locale)",
|
||||
"navigation_bar.live_feed_public": "Feed live (pubblico)",
|
||||
"navigation_bar.live_feed_local": "Feed in diretta (locale)",
|
||||
"navigation_bar.live_feed_public": "Feed in diretta (pubblico)",
|
||||
"navigation_bar.logout": "Disconnettiti",
|
||||
"navigation_bar.moderation": "Moderazione",
|
||||
"navigation_bar.more": "Altro",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Politica sulla Privacy",
|
||||
"quote_error.edit": "Le citazioni non possono essere aggiunte quando si modifica un post.",
|
||||
"quote_error.poll": "Nei sondaggi non sono consentite le citazioni.",
|
||||
"quote_error.private_mentions": "Le citazioni non sono consentite con le menzioni dirette.",
|
||||
"quote_error.quote": "È consentita una sola citazione alla volta.",
|
||||
"quote_error.unauthorized": "Non sei autorizzato a citare questo post.",
|
||||
"quote_error.upload": "Le citazioni non sono consentite con gli allegati multimediali.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Fissa in cima sul profilo",
|
||||
"status.quote": "Cita",
|
||||
"status.quote.cancel": "Annulla la citazione",
|
||||
"status.quote_error.blocked_account_hint.title": "Questo post è nascosto perché hai bloccato @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Questo post è nascosto perché hai bloccato @{domain}.",
|
||||
"status.quote_error.filtered": "Nascosto a causa di uno dei tuoi filtri",
|
||||
"status.quote_error.limited_account_hint.action": "Mostra comunque",
|
||||
"status.quote_error.limited_account_hint.title": "Questo profilo è stato nascosto dai moderatori di {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Questo post è nascosto perché hai silenziato @{name}.",
|
||||
"status.quote_error.not_available": "Post non disponibile",
|
||||
"status.quote_error.pending_approval": "Post in attesa",
|
||||
"status.quote_error.pending_approval_popout.body": "Su Mastodon, puoi controllare se qualcuno può citarti. Questo post è in attesa dell'approvazione dell'autore originale.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Abbassa volume",
|
||||
"video.volume_up": "Alza volume",
|
||||
"visibility_modal.button_title": "Imposta la visibilità",
|
||||
"visibility_modal.direct_quote_warning.text": "Se si salvano le impostazioni correnti, la citazione incorporata verrà convertita in un collegamento.",
|
||||
"visibility_modal.direct_quote_warning.title": "Le citazioni non possono essere incorporate in menzioni private",
|
||||
"visibility_modal.header": "Visibilità e interazione",
|
||||
"visibility_modal.helper.direct_quoting": "Le menzioni private scritte su Mastodon non possono essere citate da altri.",
|
||||
"visibility_modal.helper.privacy_editing": "La visibilità non può essere modificata dopo la pubblicazione di un post.",
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@
|
|||
"account.featured_tags.last_status_never": "投稿がありません",
|
||||
"account.follow": "フォロー",
|
||||
"account.follow_back": "フォローバック",
|
||||
"account.follow_back_short": "フォローバック",
|
||||
"account.follow_request": "フォローリクエスト",
|
||||
"account.follow_request_cancel": "リクエストをキャンセル",
|
||||
"account.follow_request_cancel_short": "キャンセル",
|
||||
"account.follow_request_short": "リクエスト",
|
||||
"account.followers": "フォロワー",
|
||||
"account.followers.empty": "まだ誰もフォローしていません。",
|
||||
"account.followers_counter": "{count, plural, other {{counter} フォロワー}}",
|
||||
|
|
@ -247,7 +252,12 @@
|
|||
"confirmations.remove_from_followers.title": "フォロワーを削除しますか?",
|
||||
"confirmations.revoke_quote.confirm": "投稿を削除",
|
||||
"confirmations.revoke_quote.title": "投稿を削除しますか?",
|
||||
"confirmations.unblock.confirm": "ブロック解除",
|
||||
"confirmations.unblock.title": "@{name}さんのブロックを解除しますか?",
|
||||
"confirmations.unfollow.confirm": "フォロー解除",
|
||||
"confirmations.unfollow.title": "{name} さんのフォローを解除しますか?",
|
||||
"confirmations.withdraw_request.confirm": "リクエスト取り消し",
|
||||
"confirmations.withdraw_request.title": "{name} さんのフォローリクエストを取り消しますか?",
|
||||
"content_warning.hide": "内容を隠す",
|
||||
"content_warning.show": "承知して表示",
|
||||
"content_warning.show_more": "続きを表示",
|
||||
|
|
@ -317,6 +327,7 @@
|
|||
"empty_column.bookmarked_statuses": "まだ何もブックマーク登録していません。ブックマーク登録するとここに表示されます。",
|
||||
"empty_column.community": "ローカルタイムラインはまだ使われていません。何か書いてみましょう!",
|
||||
"empty_column.direct": "非公開の返信はまだありません。非公開でやりとりをするとここに表示されます。",
|
||||
"empty_column.disabled_feed": "このフィードはサーバー管理者によって無効にされています。",
|
||||
"empty_column.domain_blocks": "ブロックしているドメインはありません。",
|
||||
"empty_column.explore_statuses": "まだ何もありません。後で確認してください。",
|
||||
"empty_column.favourited_statuses": "お気に入りの投稿はまだありません。お気に入りに登録すると、ここに表示されます。",
|
||||
|
|
@ -841,6 +852,7 @@
|
|||
"status.cancel_reblog_private": "ブースト解除",
|
||||
"status.cannot_quote": "この投稿は引用できません",
|
||||
"status.cannot_reblog": "この投稿はブーストできません",
|
||||
"status.context.retry": "リトライ",
|
||||
"status.continued_thread": "続きのスレッド",
|
||||
"status.copy": "投稿へのリンクをコピー",
|
||||
"status.delete": "削除",
|
||||
|
|
@ -872,7 +884,10 @@
|
|||
"status.quote_error.filtered": "あなたのフィルター設定によって非表示になっています",
|
||||
"status.quote_error.pending_approval": "承認待ちの投稿",
|
||||
"status.quote_noun": "引用",
|
||||
"status.quote_post_author": "{name} の投稿を引用",
|
||||
"status.quote_private": "非公開の投稿は引用できません",
|
||||
"status.quotes": "{count, plural, other {引用}}",
|
||||
"status.quotes.local_other_disclaimer": "投稿者が拒否した引用は表示されません。",
|
||||
"status.read_more": "もっと見る",
|
||||
"status.reblog": "ブースト",
|
||||
"status.reblog_or_quote": "ブーストか引用",
|
||||
|
|
@ -888,6 +903,7 @@
|
|||
"status.reply": "返信",
|
||||
"status.replyAll": "全員に返信",
|
||||
"status.report": "@{name}さんを通報",
|
||||
"status.revoke_quote": "{name} さんの投稿から自分の投稿を削除",
|
||||
"status.sensitive_warning": "閲覧注意",
|
||||
"status.share": "共有",
|
||||
"status.show_less_all": "全て隠す",
|
||||
|
|
@ -925,6 +941,7 @@
|
|||
"upload_button.label": "メディアを追加 (複数の画像または1つの動画か音声ファイル)",
|
||||
"upload_error.limit": "アップロードできる上限を超えています。",
|
||||
"upload_error.poll": "アンケートではファイルをアップロードできません。",
|
||||
"upload_error.quote": "引用ではファイルをアップロードできません。",
|
||||
"upload_form.drag_and_drop.instructions": "メディア添付ファイルを選択するには、スペースキーまたはエンターキーを押してください。ドラッグ中は、矢印キーを使ってメディア添付ファイルを任意の方向に移動できます。再度スペースキーまたはエンターキーを押すと新しい位置にメディア添付ファイルをドロップできます。キャンセルするにはエスケープキーを押してください。",
|
||||
"upload_form.drag_and_drop.on_drag_cancel": "ドラッグがキャンセルされました。メディア添付ファイル {item} がドロップされました。",
|
||||
"upload_form.drag_and_drop.on_drag_end": "メディア添付ファイル {item} がドロップされました。",
|
||||
|
|
@ -949,6 +966,11 @@
|
|||
"video.volume_down": "音量を下げる",
|
||||
"video.volume_up": "音量を上げる",
|
||||
"visibility_modal.button_title": "公開範囲の設定",
|
||||
"visibility_modal.header": "公開範囲と引用",
|
||||
"visibility_modal.helper.direct_quoting": "Mastodon で作成された非公開の返信は他人から引用できません。",
|
||||
"visibility_modal.helper.private_quoting": "Mastodon で作成されたフォロワーのみの投稿は他人から引用できません。",
|
||||
"visibility_modal.helper.unlisted_quoting": "誰かがあなたを引用すると、その投稿もトレンドから非表示になります。",
|
||||
"visibility_modal.instructions": "この投稿の公開・引用範囲を設定します。また、<link>「デフォルトの投稿設定」</link>から今後の投稿の範囲を設定可能です。",
|
||||
"visibility_modal.privacy_label": "公開範囲",
|
||||
"visibility_modal.quote_followers": "フォロワーのみ",
|
||||
"visibility_modal.quote_label": "引用できるユーザー",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
"account.direct": "Bder-d @{name} weḥd-s",
|
||||
"account.disable_notifications": "Ḥbes ur iyi-d-ttazen ara ilɣa mi ara d-isuffeɣ @{name}",
|
||||
"account.edit_profile": "Ẓreg amaɣnu",
|
||||
"account.edit_profile_short": "Ẓreg",
|
||||
"account.enable_notifications": "Azen-iyi-d ilɣa mi ara d-isuffeɣ @{name}",
|
||||
"account.endorse": "Welleh fell-as deg umaɣnu-inek",
|
||||
"account.familiar_followers_many": "Yeṭṭafaṛ-it {name1} d {name2}, akked {othersCount, plural, one {yiwen nniḍen i tessneḍ} other {# nniḍen i tessneḍ}}",
|
||||
|
|
@ -35,6 +36,9 @@
|
|||
"account.featured_tags.last_status_never": "Ulac tisuffaɣ",
|
||||
"account.follow": "Ḍfer",
|
||||
"account.follow_back": "Ḍfer-it ula d kečč·mm",
|
||||
"account.follow_request_cancel": "Semmet asuter",
|
||||
"account.follow_request_cancel_short": "Semmet",
|
||||
"account.follow_request_short": "Asuter",
|
||||
"account.followers": "Imeḍfaren",
|
||||
"account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.",
|
||||
"account.followers_counter": "{count, plural, one {{counter} n umḍfar} other {{counter} n yimeḍfaren}}",
|
||||
|
|
@ -193,7 +197,11 @@
|
|||
"confirmations.remove_from_followers.confirm": "Kkes aneḍfar",
|
||||
"confirmations.revoke_quote.confirm": "Kkes tasuffeɣt",
|
||||
"confirmations.revoke_quote.title": "Kkes tasuffeɣt?",
|
||||
"confirmations.unblock.confirm": "Serreḥ",
|
||||
"confirmations.unblock.title": "Serreḥ i {name}?",
|
||||
"confirmations.unfollow.confirm": "Ur ḍḍafaṛ ara",
|
||||
"confirmations.unfollow.title": "Ḥbes aḍfar n {name}?",
|
||||
"confirmations.withdraw_request.confirm": "Agwi asuter",
|
||||
"content_warning.hide": "Ffer tasuffeɣt",
|
||||
"content_warning.show": "Ssken-d akken tebɣu tili",
|
||||
"content_warning.show_more": "Sken-d ugar",
|
||||
|
|
@ -456,6 +464,7 @@
|
|||
"notification.follow": "iṭṭafar-ik·em-id {name}",
|
||||
"notification.follow.name_and_others": "{name} akked <a>{count, plural, one {# nniḍen} other {# nniḍen}}</a> iḍfeṛ-k·m-id",
|
||||
"notification.follow_request": "{name} yessuter-d ad k·m-yeḍfeṛ",
|
||||
"notification.follow_request.name_and_others": "{name} d {count, plural, one {# nnayeḍ} other {# nniḍen}} yessuter-d ad k·kem-yeḍfer",
|
||||
"notification.label.mention": "Abdar",
|
||||
"notification.label.private_mention": "Abdar uslig",
|
||||
"notification.label.private_reply": "Tiririt tusligt",
|
||||
|
|
@ -646,6 +655,9 @@
|
|||
"status.bookmark": "Creḍ",
|
||||
"status.cancel_reblog_private": "Sefsex beṭṭu",
|
||||
"status.cannot_reblog": "Tasuffeɣt-a ur tezmir ara ad tettwabḍu tikelt-nniḍen",
|
||||
"status.contains_quote": "Yegber tanebdurt",
|
||||
"status.context.loading": "Aɛebbi n tririyin nniḍen",
|
||||
"status.context.more_replies_found": "Ugar n tririyin ttwafent",
|
||||
"status.context.retry": "Ɛreḍ tikkelt nniḍen",
|
||||
"status.context.show": "Sken-d",
|
||||
"status.continued_thread": "Asqerdec yettkemmil",
|
||||
|
|
|
|||
|
|
@ -24,10 +24,11 @@
|
|||
"account.blocking": "차단함",
|
||||
"account.cancel_follow_request": "팔로우 취소",
|
||||
"account.copy": "프로필 링크 복사",
|
||||
"account.direct": "@{name} 님에게 개인적으로 멘션",
|
||||
"account.direct": "@{name} 님에게 개인 멘션",
|
||||
"account.disable_notifications": "@{name} 의 게시물 알림 끄기",
|
||||
"account.domain_blocking": "도메인 차단함",
|
||||
"account.edit_profile": "프로필 편집",
|
||||
"account.edit_profile_short": "수정",
|
||||
"account.enable_notifications": "@{name} 의 게시물 알림 켜기",
|
||||
"account.endorse": "프로필에 추천하기",
|
||||
"account.familiar_followers_many": "{name1}, {name2} 님 외 내가 아는 {othersCount, plural, other {#}} 명이 팔로우함",
|
||||
|
|
@ -40,6 +41,11 @@
|
|||
"account.featured_tags.last_status_never": "게시물 없음",
|
||||
"account.follow": "팔로우",
|
||||
"account.follow_back": "맞팔로우",
|
||||
"account.follow_back_short": "맞팔로우",
|
||||
"account.follow_request": "팔로우 요청",
|
||||
"account.follow_request_cancel": "요청 취소",
|
||||
"account.follow_request_cancel_short": "취소",
|
||||
"account.follow_request_short": "요청",
|
||||
"account.followers": "팔로워",
|
||||
"account.followers.empty": "아직 아무도 이 사용자를 팔로우하고 있지 않습니다.",
|
||||
"account.followers_counter": "{count, plural, other {팔로워 {counter}명}}",
|
||||
|
|
@ -161,12 +167,14 @@
|
|||
"column.bookmarks": "북마크",
|
||||
"column.community": "로컬 타임라인",
|
||||
"column.create_list": "리스트 만들기",
|
||||
"column.direct": "개인적인 멘션",
|
||||
"column.direct": "개인 멘션",
|
||||
"column.directory": "프로필 둘러보기",
|
||||
"column.domain_blocks": "차단한 도메인",
|
||||
"column.edit_list": "리스트 편집",
|
||||
"column.favourites": "좋아요",
|
||||
"column.firehose": "실시간 피드",
|
||||
"column.firehose_local": "이 서버에 대한 실시간 피드",
|
||||
"column.firehose_singular": "실시간 피드",
|
||||
"column.follow_requests": "팔로우 요청",
|
||||
"column.home": "홈",
|
||||
"column.list_members": "리스트 구성원 관리",
|
||||
|
|
@ -186,6 +194,7 @@
|
|||
"community.column_settings.local_only": "로컬만",
|
||||
"community.column_settings.media_only": "미디어만",
|
||||
"community.column_settings.remote_only": "원격지만",
|
||||
"compose.error.blank_post": "빈 게시물은 게시할 수 없습니다.",
|
||||
"compose.language.change": "언어 변경",
|
||||
"compose.language.search": "언어 검색...",
|
||||
"compose.published.body": "게시하였습니다.",
|
||||
|
|
@ -238,6 +247,9 @@
|
|||
"confirmations.missing_alt_text.secondary": "그냥 게시하기",
|
||||
"confirmations.missing_alt_text.title": "대체 텍스트를 추가할까요? ",
|
||||
"confirmations.mute.confirm": "뮤트",
|
||||
"confirmations.private_quote_notify.cancel": "편집으로 돌아가기",
|
||||
"confirmations.private_quote_notify.confirm": "게시",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "이 메시지를 다시 표시하지 않음",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "다시 보지 않기",
|
||||
"confirmations.quiet_post_quote_info.got_it": "알겠습니다",
|
||||
"confirmations.quiet_post_quote_info.message": "조용한 공개 게시물을 인용하면 그 게시물은 유행 타임라인에서 나타나지 않을 것입니다.",
|
||||
|
|
@ -251,7 +263,12 @@
|
|||
"confirmations.revoke_quote.confirm": "게시물 삭제",
|
||||
"confirmations.revoke_quote.message": "이 작업은 되돌릴 수 없습니다.",
|
||||
"confirmations.revoke_quote.title": "게시물을 지울까요?",
|
||||
"confirmations.unblock.confirm": "차단 해제",
|
||||
"confirmations.unblock.title": "{name} 님을 차단 해제할까요?",
|
||||
"confirmations.unfollow.confirm": "팔로우 해제",
|
||||
"confirmations.unfollow.title": "{name} 님을 언팔로우 할까요?",
|
||||
"confirmations.withdraw_request.confirm": "요청 삭제",
|
||||
"confirmations.withdraw_request.title": "{name} 님에 대한 팔로우 요청을 취소할까요?",
|
||||
"content_warning.hide": "게시물 숨기기",
|
||||
"content_warning.show": "무시하고 보기",
|
||||
"content_warning.show_more": "더 보기",
|
||||
|
|
@ -321,7 +338,8 @@
|
|||
"empty_column.blocks": "아직 아무도 차단하지 않았습니다.",
|
||||
"empty_column.bookmarked_statuses": "아직 북마크에 저장한 게시물이 없습니다. 게시물을 북마크 지정하면 여기에 나타납니다.",
|
||||
"empty_column.community": "로컬 타임라인에 아무것도 없습니다. 아무거나 적어 보세요!",
|
||||
"empty_column.direct": "개인적인 멘션이 없습니다. 보내거나 받으면 여기에 표시됩니다.",
|
||||
"empty_column.direct": "개인 멘션이 없습니다. 보내거나 받으면 여기에 표시됩니다.",
|
||||
"empty_column.disabled_feed": "이 피드는 서버 관리자에 의해 비활성화되었습니다.",
|
||||
"empty_column.domain_blocks": "아직 차단한 도메인이 없습니다.",
|
||||
"empty_column.explore_statuses": "아직 유행하는 것이 없습니다. 나중에 다시 확인하세요!",
|
||||
"empty_column.favourited_statuses": "아직 좋아요한 게시물이 없습니다. 게시물을 좋아요 하면 여기에 나타납니다.",
|
||||
|
|
@ -413,7 +431,7 @@
|
|||
"hashtag.column_settings.tag_mode.all": "모두",
|
||||
"hashtag.column_settings.tag_mode.any": "어느것이든",
|
||||
"hashtag.column_settings.tag_mode.none": "이것들을 제외하고",
|
||||
"hashtag.column_settings.tag_toggle": "추가 해시태그를 이 컬럼에 추가합니다",
|
||||
"hashtag.column_settings.tag_toggle": "추가 해시태그를 이 칼럼에 포함하기",
|
||||
"hashtag.counter_by_accounts": "{count, plural, other {참여자 {counter}명}}",
|
||||
"hashtag.counter_by_uses": "{count, plural, other {게시물 {counter}개}}",
|
||||
"hashtag.counter_by_uses_today": "오늘 {count, plural, other {{counter} 개의 게시물}}",
|
||||
|
|
@ -454,6 +472,7 @@
|
|||
"interaction_modal.no_account_yet": "아직 계정이 없나요?",
|
||||
"interaction_modal.on_another_server": "다른 서버에",
|
||||
"interaction_modal.on_this_server": "이 서버에서",
|
||||
"interaction_modal.title": "로그인해서 계속하기",
|
||||
"interaction_modal.username_prompt": "예시: {example}",
|
||||
"intervals.full.days": "{number} 일",
|
||||
"intervals.full.hours": "{number} 시간",
|
||||
|
|
@ -464,7 +483,7 @@
|
|||
"keyboard_shortcuts.column": "해당 컬럼에 포커스",
|
||||
"keyboard_shortcuts.compose": "작성창에 포커스",
|
||||
"keyboard_shortcuts.description": "설명",
|
||||
"keyboard_shortcuts.direct": "개인적인 멘션 컬럼 열기",
|
||||
"keyboard_shortcuts.direct": "개인 멘션 칼럼 열기",
|
||||
"keyboard_shortcuts.down": "리스트에서 아래로 이동",
|
||||
"keyboard_shortcuts.enter": "게시물 열기",
|
||||
"keyboard_shortcuts.favourite": "게시물 좋아요",
|
||||
|
|
@ -552,7 +571,7 @@
|
|||
"navigation_bar.automated_deletion": "게시물 자동 삭제",
|
||||
"navigation_bar.blocks": "차단한 사용자",
|
||||
"navigation_bar.bookmarks": "북마크",
|
||||
"navigation_bar.direct": "개인적인 멘션",
|
||||
"navigation_bar.direct": "개인 멘션",
|
||||
"navigation_bar.domain_blocks": "차단한 도메인",
|
||||
"navigation_bar.favourites": "좋아요",
|
||||
"navigation_bar.filters": "뮤트한 단어",
|
||||
|
|
@ -658,7 +677,7 @@
|
|||
"notifications.column_settings.push": "푸시 알림",
|
||||
"notifications.column_settings.quote": "인용:",
|
||||
"notifications.column_settings.reblog": "부스트:",
|
||||
"notifications.column_settings.show": "컬럼에 표시",
|
||||
"notifications.column_settings.show": "칼럼에 표시",
|
||||
"notifications.column_settings.sound": "효과음 재생",
|
||||
"notifications.column_settings.status": "새 게시물:",
|
||||
"notifications.column_settings.unread_notifications.category": "읽지 않은 알림",
|
||||
|
|
@ -692,7 +711,7 @@
|
|||
"notifications.policy.filter_not_following_hint": "내가 수동으로 승인하지 않는 한",
|
||||
"notifications.policy.filter_not_following_title": "내가 팔로우하지 않는 사람들",
|
||||
"notifications.policy.filter_private_mentions_hint": "내가 한 멘션에 단 답글이거나 내가 발신자를 팔로우 한 것이 아닌 이상 걸러집니다",
|
||||
"notifications.policy.filter_private_mentions_title": "청하지 않은 개인적인 멘션",
|
||||
"notifications.policy.filter_private_mentions_title": "청하지 않은 개인 멘션",
|
||||
"notifications.policy.title": "알림 조건 설정",
|
||||
"notifications_permission_banner.enable": "데스크탑 알림 활성화",
|
||||
"notifications_permission_banner.how_to_control": "마스토돈이 열려 있지 않을 때에도 알림을 받으려면, 데스크탑 알림을 활성화 하세요. 당신은 어떤 종류의 반응이 데스크탑 알림을 발생할 지를 {icon} 버튼을 통해 세세하게 설정할 수 있습니다.",
|
||||
|
|
@ -740,7 +759,9 @@
|
|||
"privacy.unlisted.short": "조용한 공개",
|
||||
"privacy_policy.last_updated": "{date}에 마지막으로 업데이트됨",
|
||||
"privacy_policy.title": "개인정보처리방침",
|
||||
"quote_error.edit": "게시물을 수정하면서 인용을 추가할 수 없습니다.",
|
||||
"quote_error.poll": "인용과 투표를 함께 사용할 수 없습니다.",
|
||||
"quote_error.private_mentions": "인용과 개인 멘션을 함께 사용할 수 없습니다.",
|
||||
"quote_error.quote": "한 번의 인용만 허용됩니다.",
|
||||
"quote_error.unauthorized": "이 게시물을 인용할 권한이 없습니다.",
|
||||
"quote_error.upload": "인용과 미디어 첨부를 함께 사용할 수 없습니다.",
|
||||
|
|
@ -857,16 +878,22 @@
|
|||
"status.block": "@{name} 차단",
|
||||
"status.bookmark": "북마크",
|
||||
"status.cancel_reblog_private": "부스트 취소",
|
||||
"status.cannot_quote": "인용을 비허용하는 게시물",
|
||||
"status.cannot_quote": "인용을 비허용한 게시물",
|
||||
"status.cannot_reblog": "이 게시물은 부스트 할 수 없습니다",
|
||||
"status.contains_quote": "인용 포함",
|
||||
"status.context.loading": "더 많은 답글 불러오는 중",
|
||||
"status.context.loading_error": "새 답글을 불러올 수 없습니다",
|
||||
"status.context.loading_success": "새 답글을 불러왔습니다",
|
||||
"status.context.more_replies_found": "답글을 더 찾았습니다",
|
||||
"status.context.retry": "재시도",
|
||||
"status.context.show": "보기",
|
||||
"status.continued_thread": "이어지는 글타래",
|
||||
"status.copy": "게시물 링크 복사",
|
||||
"status.delete": "삭제",
|
||||
"status.delete.success": "게시물 삭제됨",
|
||||
"status.detailed_status": "대화 자세히 보기",
|
||||
"status.direct": "@{name} 님에게 개인적으로 멘션",
|
||||
"status.direct_indicator": "개인적인 멘션",
|
||||
"status.direct": "@{name} 님에게 개인 멘션",
|
||||
"status.direct_indicator": "개인 멘션",
|
||||
"status.edit": "수정",
|
||||
"status.edited": "{date}에 마지막으로 편집됨",
|
||||
"status.edited_x_times": "{count, plural, other {{count}}} 번 수정됨",
|
||||
|
|
@ -888,9 +915,16 @@
|
|||
"status.pin": "고정",
|
||||
"status.quote": "인용",
|
||||
"status.quote.cancel": "인용 취소",
|
||||
"status.quote_error.blocked_account_hint.title": "@{name}을 차단했기 때문에 이 게시물은 숨겨졌습니다.",
|
||||
"status.quote_error.blocked_domain_hint.title": "{domain}을 차단했기 때문에 이 게시물은 숨겨졌습니다.",
|
||||
"status.quote_error.filtered": "필터에 의해 가려짐",
|
||||
"status.quote_error.limited_account_hint.action": "그냥 보기",
|
||||
"status.quote_error.limited_account_hint.title": "이 계정은 {domain}의 중재자에 의해 숨겨진 상태입니다.",
|
||||
"status.quote_error.muted_account_hint.title": "@{name}을 뮤트했기 때문에 이 게시물은 숨겨졌습니다.",
|
||||
"status.quote_error.not_available": "게시물 사용 불가",
|
||||
"status.quote_error.pending_approval": "게시물 대기중",
|
||||
"status.quote_error.pending_approval": "계류 중인 게시물",
|
||||
"status.quote_error.pending_approval_popout.body": "Mastodon에서는 타인이 인용할 수 있는지 여부를 제어할 수 있습니다. 이 게시물은 원저자의 승인을 얻을 때까지 계류됩니다.",
|
||||
"status.quote_error.revoked": "원작성자에 의해 게시물 삭제됨",
|
||||
"status.quote_followers_only": "팔로워만 인용할 수 있는 게시물",
|
||||
"status.quote_manual_review": "작성자가 직접 검토합니다",
|
||||
"status.quote_noun": "인용",
|
||||
|
|
@ -899,6 +933,8 @@
|
|||
"status.quote_private": "비공개 게시물은 인용할 수 없습니다",
|
||||
"status.quotes": "{count, plural, other {인용}}",
|
||||
"status.quotes.empty": "아직 아무도 이 게시물을 인용하지 않았습니다. 누군가 인용한다면 여기에 표시됩니다.",
|
||||
"status.quotes.local_other_disclaimer": "원작자가 거부한 인용은 표시되지 않습니다.",
|
||||
"status.quotes.remote_other_disclaimer": "{domain}의 인용만 여기에 확정적으로 보여집니다. 원작자가 거부한 인용은 보여지지 않습니다.",
|
||||
"status.read_more": "더 보기",
|
||||
"status.reblog": "부스트",
|
||||
"status.reblog_or_quote": "부스트 또는 인용",
|
||||
|
|
@ -909,6 +945,7 @@
|
|||
"status.redraft": "지우고 다시 쓰기",
|
||||
"status.remove_bookmark": "북마크 삭제",
|
||||
"status.remove_favourite": "즐겨찾기에서 제거",
|
||||
"status.remove_quote": "삭제",
|
||||
"status.replied_in_thread": "글타래에 답장",
|
||||
"status.replied_to": "{name} 님에게",
|
||||
"status.reply": "답장",
|
||||
|
|
@ -979,6 +1016,10 @@
|
|||
"video.volume_up": "음량 증가",
|
||||
"visibility_modal.button_title": "공개범위 설정",
|
||||
"visibility_modal.header": "공개범위와 반응",
|
||||
"visibility_modal.helper.direct_quoting": "마스토돈에서 작성된 개인적인 멘션은 남들이 인용할 수 없습니다.",
|
||||
"visibility_modal.helper.privacy_editing": "공개범위는 게시한 다음 수정할 수 없습니다.",
|
||||
"visibility_modal.helper.privacy_private_self_quote": "자신의 비공개 게시물을 공개 게시물로 인용할 수 없습니다.",
|
||||
"visibility_modal.helper.private_quoting": "마스토돈에서 작성된 팔로워 전용 게시물은 다른 사용자가 인용할 수 없습니다.",
|
||||
"visibility_modal.helper.unlisted_quoting": "사람들에게 인용된 경우, 인용한 게시물도 유행 타임라인에서 감추게 됩니다.",
|
||||
"visibility_modal.instructions": "누가 이 게시물과 상호작용할 수 있는 지 제어합니다. 또한 <link>환경설정 > 게시물 기본설정</link>으로 이동해 향후 모든 게시물의 설정을 적용할 수 있습니다.",
|
||||
"visibility_modal.privacy_label": "공개 범위",
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
"account.edit_profile_short": "Edita",
|
||||
"account.enable_notifications": "Avizame kuando @{name} publike",
|
||||
"account.endorse": "Avalia en profil",
|
||||
"account.featured": "Avaliado",
|
||||
"account.featured.accounts": "Profiles",
|
||||
"account.featured.hashtags": "Etiketas",
|
||||
"account.featured_tags.last_status_at": "Ultima publikasyon de {date}",
|
||||
|
|
@ -38,6 +39,8 @@
|
|||
"account.follow": "Sige",
|
||||
"account.follow_back": "Sige tamyen",
|
||||
"account.follow_back_short": "Sige tambyen",
|
||||
"account.follow_request": "Solisita segirle",
|
||||
"account.follow_request_cancel": "Anula solisitud",
|
||||
"account.follow_request_cancel_short": "Anula",
|
||||
"account.follow_request_short": "Solisitud",
|
||||
"account.followers": "Suivantes",
|
||||
|
|
@ -62,6 +65,7 @@
|
|||
"account.mute_short": "Silensia",
|
||||
"account.muted": "Silensiado",
|
||||
"account.muting": "Silensyando",
|
||||
"account.mutual": "Vos sigesh mutualmente",
|
||||
"account.no_bio": "No ay deskripsion.",
|
||||
"account.open_original_page": "Avre pajina orijnala",
|
||||
"account.posts": "Publikasyones",
|
||||
|
|
@ -97,6 +101,7 @@
|
|||
"alert.unexpected.title": "Atyo!",
|
||||
"alt_text_badge.title": "Teksto alternativo",
|
||||
"alt_text_modal.add_alt_text": "Adjusta teksto alternativo",
|
||||
"alt_text_modal.add_text_from_image": "Adjusta teksto de imaje",
|
||||
"alt_text_modal.cancel": "Anula",
|
||||
"alt_text_modal.change_thumbnail": "Troka minyatura",
|
||||
"alt_text_modal.done": "Fecho",
|
||||
|
|
@ -210,6 +215,7 @@
|
|||
"confirmations.logout.message": "Estas siguro ke keres salir de tu kuento?",
|
||||
"confirmations.logout.title": "Salir?",
|
||||
"confirmations.missing_alt_text.confirm": "Adjusta teksto alternativo",
|
||||
"confirmations.missing_alt_text.secondary": "Puvlika de todos modos",
|
||||
"confirmations.missing_alt_text.title": "Adjustar teksto alternativo?",
|
||||
"confirmations.mute.confirm": "Silensia",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Entyendo",
|
||||
|
|
@ -382,6 +388,7 @@
|
|||
"hints.profiles.see_more_followers": "Ve mas suivantes en {domain}",
|
||||
"hints.profiles.see_more_follows": "Ve mas segidos en {domain}",
|
||||
"hints.profiles.see_more_posts": "Ve mas puvlikasyones en {domain}",
|
||||
"home.column_settings.show_quotes": "Muestra sitas",
|
||||
"home.column_settings.show_reblogs": "Amostra repartajasyones",
|
||||
"home.column_settings.show_replies": "Amostra repuestas",
|
||||
"home.hide_announcements": "Eskonde pregones",
|
||||
|
|
@ -397,8 +404,10 @@
|
|||
"ignore_notifications_modal.private_mentions_title": "Ignorar avizos de mensyones privadas no solisitadas?",
|
||||
"info_button.label": "Ayuda",
|
||||
"interaction_modal.go": "Va",
|
||||
"interaction_modal.no_account_yet": "Ainda no tienes kuento?",
|
||||
"interaction_modal.on_another_server": "En otro sirvidor",
|
||||
"interaction_modal.on_this_server": "En este sirvidor",
|
||||
"interaction_modal.title": "Konektate para kontinuar",
|
||||
"interaction_modal.username_prompt": "Por enshemplo {example}",
|
||||
"intervals.full.days": "{number, plural, one {# diya} other {# diyas}}",
|
||||
"intervals.full.hours": "{number, plural, one {# ora} other {# oras}}",
|
||||
|
|
@ -595,6 +604,7 @@
|
|||
"onboarding.follows.done": "Fecho",
|
||||
"onboarding.follows.empty": "Malorozamente, no se pueden amostrar rezultados en este momento. Puedes aprovar uzar la bushkeda o navigar por la pajina de eksplorasyon para topar personas a las que segir, o aprovarlo de muevo mas tadre.",
|
||||
"onboarding.follows.search": "Bushka",
|
||||
"onboarding.follows.title": "Sige personas para ampezar",
|
||||
"onboarding.profile.discoverable": "Faz ke mi profil apareska en bushkedas",
|
||||
"onboarding.profile.discoverable_hint": "Kuando permites ke tu profil sea diskuvriravle en Mastodon, tus publikasyones podran apareser en rezultados de bushkedas i trendes i tu profil podra ser sujerido a personas kon intereses similares a los tuyos.",
|
||||
"onboarding.profile.display_name": "Nombre amostrado",
|
||||
|
|
@ -631,6 +641,7 @@
|
|||
"privacy_policy.title": "Politika de privasita",
|
||||
"recommended": "Rekomendado",
|
||||
"refresh": "Arefreska",
|
||||
"regeneration_indicator.please_stand_by": "Aspera por favor.",
|
||||
"relative_time.days": "{number} d",
|
||||
"relative_time.full.days": "antes {number, plural, one {# diya} other {# diyas}}",
|
||||
"relative_time.full.hours": "antes {number, plural, one {# ora} other {# oras}}",
|
||||
|
|
@ -733,8 +744,14 @@
|
|||
"status.bookmark": "Marka",
|
||||
"status.cancel_reblog_private": "No repartaja",
|
||||
"status.cannot_reblog": "Esta publikasyon no se puede repartajar",
|
||||
"status.contains_quote": "Kontriene sita",
|
||||
"status.context.loading": "Kargando mas repuestas",
|
||||
"status.context.loading_error": "No se pudieron kargar repuestas muevas",
|
||||
"status.context.loading_success": "Muevas repuestas kargadas",
|
||||
"status.context.more_replies_found": "Se toparon mas repuestas",
|
||||
"status.context.retry": "Reprova",
|
||||
"status.context.show": "Amostra",
|
||||
"status.continued_thread": "Kontinuasion del filo",
|
||||
"status.copy": "Kopia atadijo de publikasyon",
|
||||
"status.delete": "Efasa",
|
||||
"status.delete.success": "Puvlikasyon kitada",
|
||||
|
|
@ -744,6 +761,7 @@
|
|||
"status.edit": "Edita",
|
||||
"status.edited": "Ultima edisyon: {date}",
|
||||
"status.edited_x_times": "Editado {count, plural, one {{count} vez} other {{count} vezes}}",
|
||||
"status.embed": "Obtiene kodiche para enkrustar",
|
||||
"status.favourite": "Te plaze",
|
||||
"status.filter": "Filtra esta publikasyon",
|
||||
"status.history.created": "{name} kriyo {date}",
|
||||
|
|
@ -760,9 +778,20 @@
|
|||
"status.pin": "Fiksa en profil",
|
||||
"status.quote": "Sita",
|
||||
"status.quote.cancel": "Anula la sita",
|
||||
"status.quote_error.limited_account_hint.action": "Amostra entanto",
|
||||
"status.quote_error.limited_account_hint.title": "Este kuento fue eskondido por los moderadores de {domain}.",
|
||||
"status.quote_error.not_available": "Puvlikasyon no desponivle",
|
||||
"status.quote_error.pending_approval": "Puvlikasyon esta asperando",
|
||||
"status.quote_error.revoked": "Puvlikasyon kitada por el otor",
|
||||
"status.quote_followers_only": "Solo los suivantes pueden sitar esta puvlikasyon",
|
||||
"status.quote_noun": "Sita",
|
||||
"status.quote_policy_change": "Troka ken puede sitar",
|
||||
"status.quote_post_author": "Sito una puvlikasyon de @{name}",
|
||||
"status.quote_private": "No se puede sitar puvlikasyones privadas",
|
||||
"status.quotes": "{count, plural, one {sita} other {sitas}}",
|
||||
"status.read_more": "Melda mas",
|
||||
"status.reblog": "Repartaja",
|
||||
"status.reblog_or_quote": "Repartaja o partaja",
|
||||
"status.reblogged_by": "{name} repartajo",
|
||||
"status.reblogs.empty": "Ainda nadie tiene repartajado esta publikasyon. Kuando algien lo aga, se amostrara aki.",
|
||||
"status.redraft": "Efasa i eskrive de muevo",
|
||||
|
|
@ -774,6 +803,7 @@
|
|||
"status.reply": "Arisponde",
|
||||
"status.replyAll": "Arisponde al filo",
|
||||
"status.report": "Raporta @{name}",
|
||||
"status.request_quote": "Solisita sitasyon",
|
||||
"status.sensitive_warning": "Kontenido sensivle",
|
||||
"status.share": "Partaja",
|
||||
"status.show_less_all": "Amostra manko para todo",
|
||||
|
|
@ -823,7 +853,12 @@
|
|||
"video.pause": "Pauza",
|
||||
"video.play": "Reproduze",
|
||||
"video.unmute": "Desilensia",
|
||||
"visibility_modal.button_title": "Konfigura la vizibilita",
|
||||
"visibility_modal.header": "Vizibilita i enteraksyon",
|
||||
"visibility_modal.privacy_label": "Vizivilita",
|
||||
"visibility_modal.quote_followers": "Solo suivantes",
|
||||
"visibility_modal.quote_label": "Ken puede sitar",
|
||||
"visibility_modal.quote_nobody": "Solo yo",
|
||||
"visibility_modal.quote_public": "Todos",
|
||||
"visibility_modal.save": "Guadra"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "編輯列單",
|
||||
"column.favourites": "Siōng kah意",
|
||||
"column.firehose": "Tsit-má ê動態",
|
||||
"column.firehose_local": "Tsit ê服侍器tsit-má ê動態",
|
||||
"column.firehose_singular": "Tsit-má ê動態",
|
||||
"column.follow_requests": "跟tuè請求",
|
||||
"column.home": "頭頁",
|
||||
"column.list_members": "管理列單ê成員",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Kan-ta展示本地ê",
|
||||
"community.column_settings.media_only": "Kan-ta展示媒體",
|
||||
"community.column_settings.remote_only": "Kan-ta展示遠距離ê",
|
||||
"compose.error.blank_post": "PO文bē當空白。",
|
||||
"compose.language.change": "換語言",
|
||||
"compose.language.search": "Tshiau-tshuē語言……",
|
||||
"compose.published.body": "成功PO文。",
|
||||
|
|
@ -333,6 +336,7 @@
|
|||
"empty_column.bookmarked_statuses": "Lí iáu無加添任何冊籤。Nā是lí加添冊籤,伊ē佇tsia顯示。",
|
||||
"empty_column.community": "本站時間線是空ê。緊來公開PO文oh!",
|
||||
"empty_column.direct": "Lí iáu無任何ê私人訊息。Nā是lí送á是收著私人訊息,ē佇tsia顯示。.",
|
||||
"empty_column.disabled_feed": "Tsit ê feed已經hōo lí ê服侍器ê管理員停用。",
|
||||
"empty_column.domain_blocks": "Iáu無封鎖任何網域。",
|
||||
"empty_column.explore_statuses": "目前iáu無有流行ê趨勢,請sió等tsi̍t-ē,koh確認。",
|
||||
"empty_column.favourited_statuses": "Lí iáu無加添任何收藏 ê PO文。Nā是lí加收藏,伊ē佇tsia顯示。",
|
||||
|
|
@ -907,9 +911,12 @@
|
|||
"status.open": "Kā PO文展開",
|
||||
"status.quote": "引用",
|
||||
"status.quote.cancel": "取消引用",
|
||||
"status.quote_error.blocked_account_hint.title": "因為lí有封鎖 @{name},tsit篇PO文受khàm掉。",
|
||||
"status.quote_error.blocked_domain_hint.title": "因為lí有封鎖 {domain},tsit篇PO文受khàm掉。",
|
||||
"status.quote_error.filtered": "Lí所設定ê過濾器kā tse khàm起來",
|
||||
"status.quote_error.limited_account_hint.action": "Iáu是顯示",
|
||||
"status.quote_error.limited_account_hint.title": "Tsit ê口座予 {domain} ê管理員tshàng起來ah。",
|
||||
"status.quote_error.muted_account_hint.title": "因為lí有消音 @{name},tsit篇PO文受khàm掉。",
|
||||
"status.quote_error.not_available": "PO文bē當看",
|
||||
"status.quote_error.pending_approval": "PO文當咧送",
|
||||
"status.quote_error.pending_approval_popout.body": "佇Mastodon,lí ē當控制PO文kám beh hōo lâng引用。Tsit篇PO文teh等原文作者允准。",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Lijst bewerken",
|
||||
"column.favourites": "Favorieten",
|
||||
"column.firehose": "Openbare tijdlijnen",
|
||||
"column.firehose_local": "Lokale tijdlijn",
|
||||
"column.firehose_singular": "Openbare tijdlijn",
|
||||
"column.follow_requests": "Volgverzoeken",
|
||||
"column.home": "Start",
|
||||
"column.list_members": "Lijstleden beheren",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Alleen lokaal",
|
||||
"community.column_settings.media_only": "Alleen media",
|
||||
"community.column_settings.remote_only": "Alleen andere servers",
|
||||
"compose.error.blank_post": "Bericht mag niet leeg zijn.",
|
||||
"compose.language.change": "Taal veranderen",
|
||||
"compose.language.search": "Talen zoeken...",
|
||||
"compose.published.body": "Bericht gepubliceerd.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Toch plaatsen",
|
||||
"confirmations.missing_alt_text.title": "Alt-tekst toevoegen?",
|
||||
"confirmations.mute.confirm": "Negeren",
|
||||
"confirmations.private_quote_notify.cancel": "Terug naar bewerken",
|
||||
"confirmations.private_quote_notify.confirm": "Bericht plaatsen",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Dit bericht niet meer aan mij tonen",
|
||||
"confirmations.private_quote_notify.message": "De persoon die je citeert en andere vermelde personen krijgen een melding en kunnen jouw bericht bekijken, zelfs als ze je niet volgen.",
|
||||
"confirmations.private_quote_notify.title": "Met volgers en vermelde gebruikers delen?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Herinner me er niet nogmaals aan",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Begrepen",
|
||||
"confirmations.quiet_post_quote_info.message": "Wanneer je een minder openbaar bericht citeert, verschijnt jouw bericht niet onder trends.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Jij hebt nog geen berichten aan je bladwijzers toegevoegd. Wanneer je er een aan jouw bladwijzers toevoegt, valt deze hier te zien.",
|
||||
"empty_column.community": "De lokale tijdlijn is nog leeg. Plaats een openbaar bericht om de spits af te bijten!",
|
||||
"empty_column.direct": "Je hebt nog geen privéberichten. Wanneer je er een verstuurt of ontvangt, komen deze hier te staan.",
|
||||
"empty_column.disabled_feed": "Deze tijdlijn is uitgeschakeld door je serverbeheerders.",
|
||||
"empty_column.domain_blocks": "Er zijn nog geen geblokkeerde servers.",
|
||||
"empty_column.explore_statuses": "Momenteel zijn er geen trends. Kom later terug!",
|
||||
"empty_column.favourited_statuses": "Jij hebt nog geen favoriete berichten. Wanneer je een bericht als favoriet markeert, valt deze hier te zien.",
|
||||
|
|
@ -738,7 +747,7 @@
|
|||
"poll.votes": "{votes, plural, one {# stem} other {# stemmen}}",
|
||||
"poll_button.add_poll": "Peiling toevoegen",
|
||||
"poll_button.remove_poll": "Peiling verwijderen",
|
||||
"privacy.change": "Privacy voor een bericht aanpassen",
|
||||
"privacy.change": "Privacy van dit bericht aanpassen",
|
||||
"privacy.direct.long": "Alleen voor mensen die specifiek in het bericht worden vermeld",
|
||||
"privacy.direct.short": "Privébericht",
|
||||
"privacy.private.long": "Alleen jouw volgers",
|
||||
|
|
@ -908,9 +917,12 @@
|
|||
"status.pin": "Aan profielpagina vastmaken",
|
||||
"status.quote": "Citeren",
|
||||
"status.quote.cancel": "Citeren annuleren",
|
||||
"status.quote_error.blocked_account_hint.title": "Dit bericht is verborgen, omdat jij @{name} hebt geblokkeerd.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Dit bericht is verborgen, omdat jij alles van {domain} hebt geblokkeerd.",
|
||||
"status.quote_error.filtered": "Verborgen door een van je filters",
|
||||
"status.quote_error.limited_account_hint.action": "Alsnog tonen",
|
||||
"status.quote_error.limited_account_hint.title": "Dit account is door de moderatoren van {domain} verborgen.",
|
||||
"status.quote_error.muted_account_hint.title": "Dit bericht is verborgen, omdat jij @{name} hebt genegeerd.",
|
||||
"status.quote_error.not_available": "Bericht niet beschikbaar",
|
||||
"status.quote_error.pending_approval": "Bericht in afwachting van goedkeuring",
|
||||
"status.quote_error.pending_approval_popout.body": "Op Mastodon kun je bepalen of iemand je mag citeren. Dit bericht is in afwachting van de goedkeuring van de oorspronkelijke auteur.",
|
||||
|
|
@ -1005,6 +1017,8 @@
|
|||
"video.volume_down": "Volume omlaag",
|
||||
"video.volume_up": "Volume omhoog",
|
||||
"visibility_modal.button_title": "Privacy instellen",
|
||||
"visibility_modal.direct_quote_warning.text": "Wanneer je de huidige instellingen opslaat wordt het citaat in een link veranderd.",
|
||||
"visibility_modal.direct_quote_warning.title": "Privéberichten kunnen geen citaten bevatten",
|
||||
"visibility_modal.header": "Zichtbaarheid en interactie",
|
||||
"visibility_modal.helper.direct_quoting": "Privéberichten afkomstig van Mastodon kunnen niet door anderen worden geciteerd.",
|
||||
"visibility_modal.helper.privacy_editing": "De zichtbaarheid kan niet meer worden gewijzigd nadat een bericht is gepubliceerd.",
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@
|
|||
"column.edit_list": "Rediger liste",
|
||||
"column.favourites": "Favorittar",
|
||||
"column.firehose": "Tidslinjer",
|
||||
"column.firehose_local": "Direktestraum for denne tenaren",
|
||||
"column.firehose_singular": "Direktestraum",
|
||||
"column.follow_requests": "Fylgjeførespurnadar",
|
||||
"column.home": "Heim",
|
||||
"column.list_members": "Administrer medlemer på lista",
|
||||
|
|
@ -192,6 +194,7 @@
|
|||
"community.column_settings.local_only": "Berre lokalt",
|
||||
"community.column_settings.media_only": "Berre media",
|
||||
"community.column_settings.remote_only": "Berre eksternt",
|
||||
"compose.error.blank_post": "Innlegg kan ikkje vera tomme.",
|
||||
"compose.language.change": "Byt språk",
|
||||
"compose.language.search": "Søk språk...",
|
||||
"compose.published.body": "Innlegg publisert.",
|
||||
|
|
@ -244,6 +247,11 @@
|
|||
"confirmations.missing_alt_text.secondary": "Publiser likevel",
|
||||
"confirmations.missing_alt_text.title": "Legg til alternativ tekst?",
|
||||
"confirmations.mute.confirm": "Demp",
|
||||
"confirmations.private_quote_notify.cancel": "Tilbake til redigeringa",
|
||||
"confirmations.private_quote_notify.confirm": "Legg ut innlegget",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Ikkje vis dette fleire gonger",
|
||||
"confirmations.private_quote_notify.message": "Personen du siterer, og andre som er nemnde i innlegget, vil få varsel og kan sjå innlegget ditt, sjølv om dei ikkje fylgjer deg.",
|
||||
"confirmations.private_quote_notify.title": "Del med fylgjarar og folk som er nemnde?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Ikkje minn meg på det att",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Greitt",
|
||||
"confirmations.quiet_post_quote_info.message": "Når du siterer eit stille offentleg innlegg, blir innlegget ditt gøymt frå offentlege populære tidsliner.",
|
||||
|
|
@ -333,6 +341,7 @@
|
|||
"empty_column.bookmarked_statuses": "Du har ikkje lagra noko bokmerke enno. Når du set bokmerke på eit innlegg, dukkar det opp her.",
|
||||
"empty_column.community": "Den lokale tidslina er tom. Skriv noko offentleg å få ballen til å rulle!",
|
||||
"empty_column.direct": "Du har ingen private omtaler enda. Etter du har sendt eller mottatt en, så vil den dukke opp her.",
|
||||
"empty_column.disabled_feed": "Administratorane på tenaren din har skrudd av denne straumen.",
|
||||
"empty_column.domain_blocks": "Det er ingen blokkerte domene enno.",
|
||||
"empty_column.explore_statuses": "Ingenting er populært nett no. Prøv att seinare!",
|
||||
"empty_column.favourited_statuses": "Du har ingen favoritt-statusar ennå. Når du merkjer ein som favoritt, dukkar han opp her.",
|
||||
|
|
@ -755,6 +764,7 @@
|
|||
"privacy_policy.title": "Personvernsreglar",
|
||||
"quote_error.edit": "Du kan ikkje leggja til sitat når du redigerer eit innlegg.",
|
||||
"quote_error.poll": "Du kan ikkje sitera meiningsmålingar.",
|
||||
"quote_error.private_mentions": "Du kan ikkje sitera direkteomtaler.",
|
||||
"quote_error.quote": "Det er berre lov med eitt sitat om gongen.",
|
||||
"quote_error.unauthorized": "Du har ikkje løyve til å sitera dette innlegget.",
|
||||
"quote_error.upload": "Du kan ikkje sitera medievedlegg.",
|
||||
|
|
@ -908,9 +918,12 @@
|
|||
"status.pin": "Fest på profil",
|
||||
"status.quote": "Siter",
|
||||
"status.quote.cancel": "Avbryt siteringa",
|
||||
"status.quote_error.blocked_account_hint.title": "Dette innlegget er gøymt fordi du har blokkert @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Dette innlegget er gøymt fordi du har blokkert {domain}.",
|
||||
"status.quote_error.filtered": "Gøymt på grunn av eitt av filtra dine",
|
||||
"status.quote_error.limited_account_hint.action": "Vis likevel",
|
||||
"status.quote_error.limited_account_hint.title": "Denne kontoen har vorte skjult av moderatorane på {domain}.",
|
||||
"status.quote_error.muted_account_hint.title": "Dette innlegget er gøymt fordi du har dempa @{name}.",
|
||||
"status.quote_error.not_available": "Innlegget er ikkje tilgjengeleg",
|
||||
"status.quote_error.pending_approval": "Innlegget ventar",
|
||||
"status.quote_error.pending_approval_popout.body": "På Mastodon kan du kontrollera om folk får sitera deg. Innlegget ditt ventar medan me ventar på at opphavspersonen godkjenner det.",
|
||||
|
|
@ -1005,6 +1018,8 @@
|
|||
"video.volume_down": "Volum ned",
|
||||
"video.volume_up": "Volum opp",
|
||||
"visibility_modal.button_title": "Vel vising",
|
||||
"visibility_modal.direct_quote_warning.text": "Viss du lagrar innstillingane, vil det innebygde sitatet bli omgjort til lenke.",
|
||||
"visibility_modal.direct_quote_warning.title": "Du kan ikkje byggja inn sitat i direkteomtaler",
|
||||
"visibility_modal.header": "Vising og samhandling",
|
||||
"visibility_modal.helper.direct_quoting": "Private omtalar som er skrivne på Mastodon kan ikkje siterast av andre.",
|
||||
"visibility_modal.helper.privacy_editing": "Du kan ikkje endra korleis eit innlegg viser når du har lagt det ut.",
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue