Merge remote-tracking branch 'parent/main' into upstream-20240503

This commit is contained in:
KMY 2024-05-03 11:17:22 +09:00
commit 80789a603a
193 changed files with 1871 additions and 1061 deletions

View file

@ -25,6 +25,8 @@ class Admin::DomainAllowsController < Admin::BaseController
def destroy
authorize @domain_allow, :destroy?
UnallowDomainService.new.call(@domain_allow)
log_action :destroy, @domain_allow
redirect_to admin_instances_path, notice: I18n.t('admin.domain_allows.destroyed_msg')
end

View file

@ -29,10 +29,11 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
def create
authorize :domain_block, :create?
@domain_block = DomainBlock.new(resource_params)
existing_domain_block = resource_params[:domain].present? ? DomainBlock.rule_for(resource_params[:domain]) : nil
return render json: existing_domain_block, serializer: REST::Admin::ExistingDomainBlockErrorSerializer, status: 422 if existing_domain_block.present?
return render json: existing_domain_block, serializer: REST::Admin::ExistingDomainBlockErrorSerializer, status: 422 if conflicts_with_existing_block?(@domain_block, existing_domain_block)
@domain_block = DomainBlock.create!(resource_params)
@domain_block.save!
DomainBlockWorker.perform_async(@domain_block.id)
log_action :create, @domain_block
render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer
@ -55,6 +56,10 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
private
def conflicts_with_existing_block?(domain_block, existing_domain_block)
existing_domain_block.present? && (existing_domain_block.domain == TagManager.instance.normalize_domain(domain_block.domain) || !domain_block.stricter_than?(existing_domain_block))
end
def set_domain_blocks
@domain_blocks = filtered_domain_blocks.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
end

View file

@ -1,5 +1,5 @@
import './public-path';
import main from "mastodon/main";
import main from 'mastodon/main';
import { start } from '../mastodon/common';
import { loadLocale } from '../mastodon/locales';
@ -10,6 +10,6 @@ start();
loadPolyfills()
.then(loadLocale)
.then(main)
.catch(e => {
.catch((e: unknown) => {
console.error(e);
});

View file

@ -2,7 +2,9 @@ import './public-path';
import ready from '../mastodon/ready';
ready(() => {
const image = document.querySelector('img');
const image = document.querySelector<HTMLImageElement>('img');
if (!image) return;
image.addEventListener('mouseenter', () => {
image.src = '/oops.gif';
@ -11,4 +13,6 @@ ready(() => {
image.addEventListener('mouseleave', () => {
image.src = '/oops.png';
});
}).catch((e: unknown) => {
console.error(e);
});

View file

@ -2,7 +2,7 @@
// to share the same assets regardless of instance configuration.
// See https://webpack.js.org/guides/public-path/#on-the-fly
function removeOuterSlashes(string) {
function removeOuterSlashes(string: string) {
return string.replace(/^\/*/, '').replace(/\/*$/, '');
}
@ -15,7 +15,9 @@ function formatPublicPath(host = '', path = '') {
return `${formattedHost}/${formattedPath}/`;
}
const cdnHost = document.querySelector('meta[name=cdn-host]');
const cdnHost = document.querySelector<HTMLMetaElement>('meta[name=cdn-host]');
// eslint-disable-next-line no-undef
__webpack_public_path__ = formatPublicPath(cdnHost ? cdnHost.content : '', process.env.PUBLIC_OUTPUT_PATH);
__webpack_public_path__ = formatPublicPath(
cdnHost ? cdnHost.content : '',
process.env.PUBLIC_OUTPUT_PATH,
);

View file

@ -2,7 +2,7 @@ import './public-path';
import { createRoot } from 'react-dom/client';
import { start } from '../mastodon/common';
import ComposeContainer from '../mastodon/containers/compose_container';
import ComposeContainer from '../mastodon/containers/compose_container';
import { loadPolyfills } from '../mastodon/polyfills';
import ready from '../mastodon/ready';
@ -16,7 +16,7 @@ function loaded() {
if (!attr) return;
const props = JSON.parse(attr);
const props = JSON.parse(attr) as object;
const root = createRoot(mountNode);
root.render(<ComposeContainer {...props} />);
@ -24,9 +24,13 @@ function loaded() {
}
function main() {
ready(loaded);
ready(loaded).catch((error: unknown) => {
console.error(error);
});
}
loadPolyfills().then(main).catch(error => {
console.error(error);
});
loadPolyfills()
.then(main)
.catch((error: unknown) => {
console.error(error);
});

View file

@ -1,42 +0,0 @@
import './public-path';
import axios from 'axios';
import ready from '../mastodon/ready';
ready(() => {
setInterval(() => {
axios.get('/api/v1/emails/check_confirmation').then((response) => {
if (response.data) {
window.location = '/start';
}
}).catch(error => {
console.error(error);
});
}, 5000);
document.querySelectorAll('.timer-button').forEach(button => {
let counter = 30;
const container = document.createElement('span');
const updateCounter = () => {
container.innerText = ` (${counter})`;
};
updateCounter();
const countdown = setInterval(() => {
counter--;
if (counter === 0) {
button.disabled = false;
button.removeChild(container);
clearInterval(countdown);
} else {
updateCounter();
}
}, 1000);
button.appendChild(container);
});
});

View file

@ -0,0 +1,48 @@
import './public-path';
import axios from 'axios';
import ready from '../mastodon/ready';
async function checkConfirmation() {
const response = await axios.get('/api/v1/emails/check_confirmation');
if (response.data) {
window.location.href = '/start';
}
}
ready(() => {
setInterval(() => {
void checkConfirmation();
}, 5000);
document
.querySelectorAll<HTMLButtonElement>('button.timer-button')
.forEach((button) => {
let counter = 30;
const container = document.createElement('span');
const updateCounter = () => {
container.innerText = ` (${counter})`;
};
updateCounter();
const countdown = setInterval(() => {
counter--;
if (counter === 0) {
button.disabled = false;
button.removeChild(container);
clearInterval(countdown);
} else {
updateCounter();
}
}, 1000);
button.appendChild(container);
});
}).catch((e: unknown) => {
throw e;
});

View file

@ -1,119 +0,0 @@
import * as WebAuthnJSON from '@github/webauthn-json';
import axios from 'axios';
import ready from '../mastodon/ready';
import 'regenerator-runtime/runtime';
function getCSRFToken() {
var CSRFSelector = document.querySelector('meta[name="csrf-token"]');
if (CSRFSelector) {
return CSRFSelector.getAttribute('content');
} else {
return null;
}
}
function hideFlashMessages() {
Array.from(document.getElementsByClassName('flash-message')).forEach(function(flashMessage) {
flashMessage.classList.add('hidden');
});
}
function callback(url, body) {
axios.post(url, JSON.stringify(body), {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-CSRF-Token': getCSRFToken(),
},
credentials: 'same-origin',
}).then(function(response) {
window.location.replace(response.data.redirect_path);
}).catch(function(error) {
if (error.response.status === 422) {
const errorMessage = document.getElementById('security-key-error-message');
errorMessage.classList.remove('hidden');
console.error(error.response.data.error);
} else {
console.error(error);
}
});
}
ready(() => {
if (!WebAuthnJSON.supported()) {
const unsupported_browser_message = document.getElementById('unsupported-browser-message');
if (unsupported_browser_message) {
unsupported_browser_message.classList.remove('hidden');
document.querySelector('.btn.js-webauthn').disabled = true;
}
}
const webAuthnCredentialRegistrationForm = document.getElementById('new_webauthn_credential');
if (webAuthnCredentialRegistrationForm) {
webAuthnCredentialRegistrationForm.addEventListener('submit', (event) => {
event.preventDefault();
var nickname = event.target.querySelector('input[name="new_webauthn_credential[nickname]"]');
if (nickname.value) {
axios.get('/settings/security_keys/options')
.then((response) => {
const credentialOptions = response.data;
WebAuthnJSON.create({ 'publicKey': credentialOptions }).then((credential) => {
var params = { 'credential': credential, 'nickname': nickname.value };
callback('/settings/security_keys', params);
}).catch((error) => {
const errorMessage = document.getElementById('security-key-error-message');
errorMessage.classList.remove('hidden');
console.error(error);
});
}).catch((error) => {
console.error(error.response.data.error);
});
} else {
nickname.focus();
}
});
}
const webAuthnCredentialAuthenticationForm = document.getElementById('webauthn-form');
if (webAuthnCredentialAuthenticationForm) {
webAuthnCredentialAuthenticationForm.addEventListener('submit', (event) => {
event.preventDefault();
axios.get('sessions/security_key_options')
.then((response) => {
const credentialOptions = response.data;
WebAuthnJSON.get({ 'publicKey': credentialOptions }).then((credential) => {
var params = { 'user': { 'credential': credential } };
callback('sign_in', params);
}).catch((error) => {
const errorMessage = document.getElementById('security-key-error-message');
errorMessage.classList.remove('hidden');
console.error(error);
});
}).catch((error) => {
console.error(error.response.data.error);
});
});
const otpAuthenticationForm = document.getElementById('otp-authentication-form');
const linkToOtp = document.getElementById('link-to-otp');
linkToOtp.addEventListener('click', () => {
webAuthnCredentialAuthenticationForm.classList.add('hidden');
otpAuthenticationForm.classList.remove('hidden');
hideFlashMessages();
});
const linkToWebAuthn = document.getElementById('link-to-webauthn');
linkToWebAuthn.addEventListener('click', () => {
otpAuthenticationForm.classList.add('hidden');
webAuthnCredentialAuthenticationForm.classList.remove('hidden');
hideFlashMessages();
});
}
});

View file

@ -0,0 +1,197 @@
import * as WebAuthnJSON from '@github/webauthn-json';
import axios, { AxiosError } from 'axios';
import ready from '../mastodon/ready';
import 'regenerator-runtime/runtime';
type PublicKeyCredentialCreationOptionsJSON =
WebAuthnJSON.CredentialCreationOptionsJSON['publicKey'];
function exceptionHasAxiosError(
error: unknown,
): error is AxiosError<{ error: unknown }> {
return (
error instanceof AxiosError &&
typeof error.response?.data === 'object' &&
'error' in error.response.data
);
}
function logAxiosResponseError(error: unknown) {
if (exceptionHasAxiosError(error)) console.error(error);
}
function getCSRFToken() {
return document
.querySelector<HTMLMetaElement>('meta[name="csrf-token"]')
?.getAttribute('content');
}
function hideFlashMessages() {
document.querySelectorAll('.flash-message').forEach((flashMessage) => {
flashMessage.classList.add('hidden');
});
}
async function callback(
url: string,
body:
| {
credential: WebAuthnJSON.PublicKeyCredentialWithAttestationJSON;
nickname: string;
}
| {
user: { credential: WebAuthnJSON.PublicKeyCredentialWithAssertionJSON };
},
) {
try {
const response = await axios.post<{ redirect_path: string }>(
url,
JSON.stringify(body),
{
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'X-CSRF-Token': getCSRFToken(),
},
},
);
window.location.replace(response.data.redirect_path);
} catch (error) {
if (error instanceof AxiosError && error.response?.status === 422) {
const errorMessage = document.getElementById(
'security-key-error-message',
);
errorMessage?.classList.remove('hidden');
logAxiosResponseError(error);
} else {
console.error(error);
}
}
}
async function handleWebauthnCredentialRegistration(nickname: string) {
try {
const response = await axios.get<PublicKeyCredentialCreationOptionsJSON>(
'/settings/security_keys/options',
);
const credentialOptions = response.data;
try {
const credential = await WebAuthnJSON.create({
publicKey: credentialOptions,
});
const params = {
credential: credential,
nickname: nickname,
};
await callback('/settings/security_keys', params);
} catch (error) {
const errorMessage = document.getElementById(
'security-key-error-message',
);
errorMessage?.classList.remove('hidden');
console.error(error);
}
} catch (error) {
logAxiosResponseError(error);
}
}
async function handleWebauthnCredentialAuthentication() {
try {
const response = await axios.get<PublicKeyCredentialCreationOptionsJSON>(
'sessions/security_key_options',
);
const credentialOptions = response.data;
try {
const credential = await WebAuthnJSON.get({
publicKey: credentialOptions,
});
const params = { user: { credential: credential } };
void callback('sign_in', params);
} catch (error) {
const errorMessage = document.getElementById(
'security-key-error-message',
);
errorMessage?.classList.remove('hidden');
console.error(error);
}
} catch (error) {
logAxiosResponseError(error);
}
}
ready(() => {
if (!WebAuthnJSON.supported()) {
const unsupported_browser_message = document.getElementById(
'unsupported-browser-message',
);
if (unsupported_browser_message) {
unsupported_browser_message.classList.remove('hidden');
const button = document.querySelector<HTMLButtonElement>(
'button.btn.js-webauthn',
);
if (button) button.disabled = true;
}
}
const webAuthnCredentialRegistrationForm =
document.querySelector<HTMLFormElement>('form#new_webauthn_credential');
if (webAuthnCredentialRegistrationForm) {
webAuthnCredentialRegistrationForm.addEventListener('submit', (event) => {
event.preventDefault();
if (!(event.target instanceof HTMLFormElement)) return;
const nickname = event.target.querySelector<HTMLInputElement>(
'input[name="new_webauthn_credential[nickname]"]',
);
if (nickname?.value) {
void handleWebauthnCredentialRegistration(nickname.value);
} else {
nickname?.focus();
}
});
}
const webAuthnCredentialAuthenticationForm =
document.getElementById('webauthn-form');
if (webAuthnCredentialAuthenticationForm) {
webAuthnCredentialAuthenticationForm.addEventListener('submit', (event) => {
event.preventDefault();
void handleWebauthnCredentialAuthentication();
});
const otpAuthenticationForm = document.getElementById(
'otp-authentication-form',
);
const linkToOtp = document.getElementById('link-to-otp');
linkToOtp?.addEventListener('click', () => {
webAuthnCredentialAuthenticationForm.classList.add('hidden');
otpAuthenticationForm?.classList.remove('hidden');
hideFlashMessages();
});
const linkToWebAuthn = document.getElementById('link-to-webauthn');
linkToWebAuthn?.addEventListener('click', () => {
otpAuthenticationForm?.classList.add('hidden');
webAuthnCredentialAuthenticationForm.classList.remove('hidden');
hideFlashMessages();
});
}
}).catch((e: unknown) => {
throw e;
});

View file

@ -1,5 +1,3 @@
import { List as ImmutableList } from 'immutable';
import { debounce } from 'lodash';
import type { MarkerJSON } from 'mastodon/api_types/markers';
@ -71,19 +69,6 @@ interface MarkerParam {
last_read_id?: string;
}
function getLastHomeId(state: RootState): string | undefined {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return (
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
state
// @ts-expect-error state.timelines is not yet typed
.getIn(['timelines', 'home', 'items'], ImmutableList())
// @ts-expect-error state.timelines is not yet typed
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
.find((item) => item !== null)
);
}
function getLastNotificationId(state: RootState): string | undefined {
// @ts-expect-error state.notifications is not yet typed
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call
@ -93,15 +78,8 @@ function getLastNotificationId(state: RootState): string | undefined {
const buildPostMarkersParams = (state: RootState) => {
const params = {} as { home?: MarkerParam; notifications?: MarkerParam };
const lastHomeId = getLastHomeId(state);
const lastNotificationId = getLastNotificationId(state);
if (lastHomeId && compareId(lastHomeId, state.markers.home) > 0) {
params.home = {
last_read_id: lastHomeId,
};
}
if (
lastNotificationId &&
compareId(lastNotificationId, state.markers.notifications) > 0

View file

@ -7,7 +7,7 @@ import PersonIcon from '@/material-icons/400-24px/person.svg?react';
import SmartToyIcon from '@/material-icons/400-24px/smart_toy.svg?react';
export const Badge = ({ icon, label, domain, roleId }) => (
export const Badge = ({ icon = <PersonIcon />, label, domain, roleId }) => (
<div className='account-role' data-account-role-id={roleId}>
{icon}
{label}
@ -22,10 +22,6 @@ Badge.propTypes = {
roleId: PropTypes.string
};
Badge.defaultProps = {
icon: <PersonIcon />,
};
export const GroupBadge = () => (
<Badge icon={<GroupsIcon />} label={<FormattedMessage id='account.badges.group' defaultMessage='Group' />} />
);

View file

@ -1,16 +1,16 @@
import PropTypes from 'prop-types';
import { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import FindInPageIcon from '@/material-icons/400-24px/find_in_page.svg?react';
import PeopleIcon from '@/material-icons/400-24px/group.svg?react';
import TagIcon from '@/material-icons/400-24px/tag.svg?react';
import { expandSearch } from 'mastodon/actions/search';
import { Icon } from 'mastodon/components/icon';
import { LoadMore } from 'mastodon/components/load_more';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import { SearchSection } from 'mastodon/features/explore/components/search_section';
import { useAppDispatch, useAppSelector } from 'mastodon/store';
import { ImmutableHashtag as Hashtag } from '../../../components/hashtag';
import AccountContainer from '../../../containers/account_container';
@ -26,62 +26,68 @@ const withoutLastResult = list => {
}
};
class SearchResults extends ImmutablePureComponent {
export const SearchResults = () => {
const results = useAppSelector((state) => state.getIn(['search', 'results']));
const isLoading = useAppSelector((state) => state.getIn(['search', 'isLoading']));
static propTypes = {
results: ImmutablePropTypes.map.isRequired,
expandSearch: PropTypes.func.isRequired,
searchTerm: PropTypes.string,
};
const dispatch = useAppDispatch();
handleLoadMoreAccounts = () => this.props.expandSearch('accounts');
const handleLoadMoreAccounts = useCallback(() => {
dispatch(expandSearch('accounts'));
}, [dispatch]);
handleLoadMoreStatuses = () => this.props.expandSearch('statuses');
const handleLoadMoreStatuses = useCallback(() => {
dispatch(expandSearch('statuses'));
}, [dispatch]);
handleLoadMoreHashtags = () => this.props.expandSearch('hashtags');
const handleLoadMoreHashtags = useCallback(() => {
dispatch(expandSearch('hashtags'));
}, [dispatch]);
render () {
const { results } = this.props;
let accounts, statuses, hashtags;
let accounts, statuses, hashtags;
if (results.get('accounts') && results.get('accounts').size > 0) {
accounts = (
<SearchSection title={<><Icon id='users' icon={PeopleIcon} /><FormattedMessage id='search_results.accounts' defaultMessage='Profiles' /></>}>
{withoutLastResult(results.get('accounts')).map(accountId => <AccountContainer key={accountId} id={accountId} />)}
{(results.get('accounts').size > INITIAL_PAGE_LIMIT && results.get('accounts').size % INITIAL_PAGE_LIMIT === 1) && <LoadMore visible onClick={this.handleLoadMoreAccounts} />}
</SearchSection>
);
}
if (results.get('hashtags') && results.get('hashtags').size > 0) {
hashtags = (
<SearchSection title={<><Icon id='hashtag' icon={TagIcon} /><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></>}>
{withoutLastResult(results.get('hashtags')).map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}
{(results.get('hashtags').size > INITIAL_PAGE_LIMIT && results.get('hashtags').size % INITIAL_PAGE_LIMIT === 1) && <LoadMore visible onClick={this.handleLoadMoreHashtags} />}
</SearchSection>
);
}
if (results.get('statuses') && results.get('statuses').size > 0) {
statuses = (
<SearchSection title={<><Icon id='quote-right' icon={FindInPageIcon} /><FormattedMessage id='search_results.statuses' defaultMessage='Posts' /></>}>
{withoutLastResult(results.get('statuses')).map(statusId => <StatusContainer key={statusId} id={statusId} />)}
{(results.get('statuses').size > INITIAL_PAGE_LIMIT && results.get('statuses').size % INITIAL_PAGE_LIMIT === 1) && <LoadMore visible onClick={this.handleLoadMoreStatuses} />}
</SearchSection>
);
}
return (
<div className='search-results'>
{accounts}
{hashtags}
{statuses}
</div>
if (results.get('accounts') && results.get('accounts').size > 0) {
accounts = (
<SearchSection title={<><Icon id='users' icon={PeopleIcon} /><FormattedMessage id='search_results.accounts' defaultMessage='Profiles' /></>}>
{withoutLastResult(results.get('accounts')).map(accountId => <AccountContainer key={accountId} id={accountId} />)}
{(results.get('accounts').size > INITIAL_PAGE_LIMIT && results.get('accounts').size % INITIAL_PAGE_LIMIT === 1) && <LoadMore visible onClick={handleLoadMoreAccounts} />}
</SearchSection>
);
}
}
if (results.get('hashtags') && results.get('hashtags').size > 0) {
hashtags = (
<SearchSection title={<><Icon id='hashtag' icon={TagIcon} /><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></>}>
{withoutLastResult(results.get('hashtags')).map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}
{(results.get('hashtags').size > INITIAL_PAGE_LIMIT && results.get('hashtags').size % INITIAL_PAGE_LIMIT === 1) && <LoadMore visible onClick={handleLoadMoreHashtags} />}
</SearchSection>
);
}
export default SearchResults;
if (results.get('statuses') && results.get('statuses').size > 0) {
statuses = (
<SearchSection title={<><Icon id='quote-right' icon={FindInPageIcon} /><FormattedMessage id='search_results.statuses' defaultMessage='Posts' /></>}>
{withoutLastResult(results.get('statuses')).map(statusId => <StatusContainer key={statusId} id={statusId} />)}
{(results.get('statuses').size > INITIAL_PAGE_LIMIT && results.get('statuses').size % INITIAL_PAGE_LIMIT === 1) && <LoadMore visible onClick={handleLoadMoreStatuses} />}
</SearchSection>
);
}
return (
<div className='search-results'>
{!accounts && !hashtags && !statuses && (
isLoading ? (
<LoadingIndicator />
) : (
<div className='empty-column-indicator'>
<FormattedMessage id='search_results.nothing_found' defaultMessage='Could not find anything for these search terms' />
</div>
)
)}
{accounts}
{hashtags}
{statuses}
</div>
);
};

View file

@ -1,20 +0,0 @@
import { connect } from 'react-redux';
import { expandSearch } from 'mastodon/actions/search';
import { fetchSuggestions, dismissSuggestion } from 'mastodon/actions/suggestions';
import SearchResults from '../components/search_results';
const mapStateToProps = state => ({
results: state.getIn(['search', 'results']),
suggestions: state.getIn(['suggestions', 'items']),
searchTerm: state.getIn(['search', 'searchTerm']),
});
const mapDispatchToProps = dispatch => ({
fetchSuggestions: () => dispatch(fetchSuggestions()),
expandSearch: type => dispatch(expandSearch(type)),
dismissSuggestion: account => dispatch(dismissSuggestion(account.get('id'))),
});
export default connect(mapStateToProps, mapDispatchToProps)(SearchResults);

View file

@ -29,9 +29,9 @@ import { mascot } from '../../initial_state';
import { isMobile } from '../../is_mobile';
import Motion from '../ui/util/optional_motion';
import { SearchResults } from './components/search_results';
import ComposeFormContainer from './containers/compose_form_container';
import SearchContainer from './containers/search_container';
import SearchResultsContainer from './containers/search_results_container';
const messages = defineMessages({
start: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
@ -138,7 +138,7 @@ class Compose extends PureComponent {
<Motion defaultStyle={{ x: -100 }} style={{ x: spring(showSearch ? 0 : -100, { stiffness: 210, damping: 20 }) }}>
{({ x }) => (
<div className='drawer__inner darker' style={{ transform: `translateX(${x}%)`, visibility: x === -100 ? 'hidden' : 'visible' }}>
<SearchResultsContainer />
<SearchResults />
</div>
)}
</Motion>

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "Въпреки че акаунтът ви не е заключен, служителите на {domain} помислиха, че може да искате да преглеждате ръчно заявките за последване на тези профили.",
"follow_suggestions.curated_suggestion": "Избор на персонал",
"follow_suggestions.dismiss": "Без ново показване",
"follow_suggestions.featured_longer": "Ръчно избрано от отбора на {domain}",
"follow_suggestions.friends_of_friends_longer": "Популярно измежду хората, които следвате",
"follow_suggestions.hints.featured": "Този профил е ръчно подбран от отбора на {domain}.",
"follow_suggestions.hints.friends_of_friends": "Този профил е популярен измежду хората, които следвате.",
"follow_suggestions.hints.most_followed": "Този профил е един от най-следваните при {domain}.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Този профил е подобен на профилите, които сте последвали наскоро.",
"follow_suggestions.personalized_suggestion": "Персонализирано предложение",
"follow_suggestions.popular_suggestion": "Популярно предложение",
"follow_suggestions.popular_suggestion_longer": "Популярно из {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Подобни на профилите, които наскоро сте последвали",
"follow_suggestions.view_all": "Преглед на всички",
"follow_suggestions.who_to_follow": "Кого да се следва",
"followed_tags": "Последвани хаштагове",
@ -469,6 +473,15 @@
"notification.follow": "{name} ви последва",
"notification.follow_request": "{name} поиска да ви последва",
"notification.mention": "{name} ви спомена",
"notification.moderation-warning.learn_more": "Научете повече",
"notification.moderation_warning": "Получихте предупреждение за модериране",
"notification.moderation_warning.action_delete_statuses": "Някои от публикациите ви са премахнати.",
"notification.moderation_warning.action_disable": "Вашият акаунт е изключен.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Някои от публикациите ви са означени като деликатни.",
"notification.moderation_warning.action_none": "Акаунтът ви получи предупреждение за модериране.",
"notification.moderation_warning.action_sensitive": "Публикациите ви ще се означават като деликатни от сега нататък.",
"notification.moderation_warning.action_silence": "Вашият акаунт е ограничен.",
"notification.moderation_warning.action_suspend": "Вашият акаунт е спрян.",
"notification.own_poll": "Анкетата ви приключи",
"notification.poll": "Анкета, в която гласувахте, приключи",
"notification.reblog": "{name} подсили ваша публикация",

View file

@ -263,6 +263,8 @@
"follow_request.authorize": "Aotren",
"follow_request.reject": "Nac'hañ",
"follow_requests.unlocked_explanation": "Daoust ma n'eo ket ho kont prennet, skipailh {domain} a soñj e fellfe deoc'h gwiriekaat pedadennoù heuliañ deus ar c'hontoù-se diwar-zorn.",
"follow_suggestions.friends_of_friends_longer": "Diouzh ar c'hiz e-touez an dud heuliet ganeoc'h",
"follow_suggestions.popular_suggestion_longer": "Diouzh ar c'hiz war {domain}",
"follow_suggestions.view_all": "Gwelet pep tra",
"followed_tags": "Hashtagoù o heuliañ",
"footer.about": "Diwar-benn",
@ -395,6 +397,7 @@
"notification.follow": "heuliañ a ra {name} ac'hanoc'h",
"notification.follow_request": "Gant {name} eo bet goulennet ho heuliañ",
"notification.mention": "Gant {name} oc'h bet meneget",
"notification.moderation-warning.learn_more": "Gouzout hiroc'h",
"notification.own_poll": "Echu eo ho sontadeg",
"notification.poll": "Ur sontadeg ho deus mouezhet warnañ a zo echuet",
"notification.reblog": "Gant {name} eo bet skignet ho toud",

View file

@ -318,7 +318,7 @@
"follow_suggestions.personalized_suggestion": "Suggeriment personalitzat",
"follow_suggestions.popular_suggestion": "Suggeriment popular",
"follow_suggestions.popular_suggestion_longer": "Popular a {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Semblant a perfils que has seguit fa poc",
"follow_suggestions.similar_to_recently_followed_longer": "Semblant a perfils que seguiu fa poc",
"follow_suggestions.view_all": "Mostra-ho tot",
"follow_suggestions.who_to_follow": "A qui seguir",
"followed_tags": "Etiquetes seguides",
@ -473,6 +473,14 @@
"notification.follow": "{name} et segueix",
"notification.follow_request": "{name} ha sol·licitat de seguir-te",
"notification.mention": "{name} t'ha esmentat",
"notification.moderation_warning": "Heu rebut un avís de moderació",
"notification.moderation_warning.action_delete_statuses": "S'han eliminat algunes de les vostres publicacions.",
"notification.moderation_warning.action_disable": "S'ha desactivat el vostre compte.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "S'ha marcat com a sensibles algunes de les vostres publicacions.",
"notification.moderation_warning.action_none": "El vostre compte ha rebut un avís de moderació.",
"notification.moderation_warning.action_sensitive": "A partir d'ara les vostres publicacions es marcaran com sensibles.",
"notification.moderation_warning.action_silence": "S'ha limitat el vostre compte.",
"notification.moderation_warning.action_suspend": "S'ha suspès el vostre compte.",
"notification.own_poll": "La teva enquesta ha finalitzat",
"notification.poll": "Ha finalitzat una enquesta en què has votat",
"notification.reblog": "{name} t'ha impulsat",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "Přestože váš účet není uzamčen, personál {domain} usoudil, že byste mohli chtít tyto požadavky na sledování zkontrolovat ručně.",
"follow_suggestions.curated_suggestion": "Výběr personálů",
"follow_suggestions.dismiss": "Znovu nezobrazovat",
"follow_suggestions.featured_longer": "Ručně vybráno týmem {domain}",
"follow_suggestions.friends_of_friends_longer": "Populární mezi lidmi, které sledujete",
"follow_suggestions.hints.featured": "Tento profil byl ručně vybrán týmem {domain}.",
"follow_suggestions.hints.friends_of_friends": "Tento profil je populární mezi lidmi, které sledujete.",
"follow_suggestions.hints.most_followed": "Tento profil je jedním z nejvíce sledovaných na {domain}.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Tento profil je podobný profilům, které jste nedávno sledovali.",
"follow_suggestions.personalized_suggestion": "Přizpůsobený návrh",
"follow_suggestions.popular_suggestion": "Populární návrh",
"follow_suggestions.popular_suggestion_longer": "Populární na {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Podobné profilům, které jste nedávno sledovali",
"follow_suggestions.view_all": "Zobrazit vše",
"follow_suggestions.who_to_follow": "Koho sledovat",
"followed_tags": "Sledované hashtagy",
@ -469,6 +473,15 @@
"notification.follow": "Uživatel {name} vás začal sledovat",
"notification.follow_request": "Uživatel {name} požádal o povolení vás sledovat",
"notification.mention": "Uživatel {name} vás zmínil",
"notification.moderation-warning.learn_more": "Zjistit více",
"notification.moderation_warning": "Obdrželi jste moderační varování",
"notification.moderation_warning.action_delete_statuses": "Některé z vašich příspěvků byly odstraněny.",
"notification.moderation_warning.action_disable": "Váš účet je zablokován.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Některé z vašich příspěvků byly označeny jako citlivé.",
"notification.moderation_warning.action_none": "Váš účet obdržel moderační varování.",
"notification.moderation_warning.action_sensitive": "Vaše příspěvky budou od nynějška označeny jako citlivé.",
"notification.moderation_warning.action_silence": "Váš účet byl omezen.",
"notification.moderation_warning.action_suspend": "Váš účet byl pozastaven.",
"notification.own_poll": "Vaše anketa skončila",
"notification.poll": "Anketa, ve které jste hlasovali, skončila",
"notification.reblog": "Uživatel {name} boostnul váš příspěvek",

View file

@ -89,6 +89,14 @@
"announcement.announcement": "Cyhoeddiad",
"attachments_list.unprocessed": "(heb eu prosesu)",
"audio.hide": "Cuddio sain",
"block_modal.remote_users_caveat": "Byddwn yn gofyn i'r gweinydd {domain} barchu eich penderfyniad. Fodd bynnag, nid yw cydymffurfiad wedi'i warantu gan y gall rhai gweinyddwyr drin rhwystro mewn ffyrdd gwahanol. Mae'n bosibl y bydd postiadau cyhoeddus yn dal i fod yn weladwy i ddefnyddwyr nad ydynt wedi mewngofnodi.",
"block_modal.show_less": "Dangos llai",
"block_modal.show_more": "Dangos mwy",
"block_modal.they_cant_mention": "Nid ydynt yn gallu eich crybwyll na'ch dilyn.",
"block_modal.they_cant_see_posts": "Nid ydynt yn gallu gweld eich postiadau ac ni fyddwch yn gweld eu rhai hwy.",
"block_modal.they_will_know": "Gallant weld eu bod wedi'u rhwystro.",
"block_modal.title": "Rhwystro defnyddiwr?",
"block_modal.you_wont_see_mentions": "Ni welwch bostiadau sy'n sôn amdanynt.",
"boost_modal.combo": "Mae modd pwyso {combo} er mwyn hepgor hyn tro nesa",
"bundle_column_error.copy_stacktrace": "Copïo'r adroddiad gwall",
"bundle_column_error.error.body": "Nid oedd modd cynhyrchu'r dudalen honno. Gall fod oherwydd gwall yn ein cod neu fater cydnawsedd porwr.",
@ -169,6 +177,7 @@
"confirmations.delete_list.message": "Ydych chi'n siŵr eich bod eisiau dileu'r rhestr hwn am byth?",
"confirmations.discard_edit_media.confirm": "Dileu",
"confirmations.discard_edit_media.message": "Mae gennych newidiadau heb eu cadw i'r disgrifiad cyfryngau neu'r rhagolwg - eu dileu beth bynnag?",
"confirmations.domain_block.confirm": "Rhwystro gweinydd",
"confirmations.domain_block.message": "Ydych chi wir, wir eisiau blocio'r holl {domain}? Fel arfer, mae blocio neu dewi pobl penodol yn broses mwy effeithiol. Fyddwch chi ddim yn gweld cynnwys o'r parth hwnnw mewn ffrydiau cyhoeddus neu yn eich hysbysiadau. Bydd eich dilynwyr o'r parth hwnnw yn cael eu ddileu.",
"confirmations.edit.confirm": "Golygu",
"confirmations.edit.message": "Bydd golygu nawr yn trosysgrifennu'r neges rydych yn ei ysgrifennu ar hyn o bryd. Ydych chi'n siŵr eich bod eisiau gwneud hyn?",
@ -200,6 +209,27 @@
"dismissable_banner.explore_statuses": "Mae'r rhain yn bostiadau o bob rhan o'r we gymdeithasol sydd ar gynnydd heddiw. Mae postiadau mwy diweddar sydd â mwy o hybiau a ffefrynu'n cael eu graddio'n uwch.",
"dismissable_banner.explore_tags": "Mae'r rhain yn hashnodau sydd ar gynnydd ar y we gymdeithasol heddiw. Mae hashnodau sy'n cael eu defnyddio gan fwy o unigolion gwahanol yn cael eu graddio'n uwch.",
"dismissable_banner.public_timeline": "Dyma'r postiadau cyhoeddus diweddaraf gan bobl ar y we gymdeithasol y mae pobl ar {domain} yn eu dilyn.",
"domain_block_modal.block": "Rhwystro gweinydd",
"domain_block_modal.block_account_instead": "Rhwystro @{name} yn lle hynny",
"domain_block_modal.they_can_interact_with_old_posts": "Gall pobl o'r gweinydd hwn ryngweithio â'ch hen bostiadau.",
"domain_block_modal.they_cant_follow": "Ni all neb o'r gweinydd hwn eich dilyn.",
"domain_block_modal.they_wont_know": "Fyddan nhw ddim yn gwybod eu bod wedi cael eu rhwystro.",
"domain_block_modal.title": "Rhwystro parth?",
"domain_block_modal.you_will_lose_followers": "Bydd eich holl ddilynwyr o'r gweinydd hwn yn cael eu tynnu.",
"domain_block_modal.you_wont_see_posts": "Fyddwch chi ddim yn gweld postiadau na hysbysiadau gan ddefnyddwyr ar y gweinydd hwn.",
"domain_pill.activitypub_lets_connect": "Mae'n caniatáu ichi gysylltu a rhyngweithio â phobl nid yn unig ar Mastodon, ond ar draws gwahanol apiau cymdeithasol hefyd.",
"domain_pill.activitypub_like_language": "Mae ActivityPub fel yr iaith y mae Mastodon yn ei siarad â rhwydweithiau cymdeithasol eraill.",
"domain_pill.server": "Gweinydd",
"domain_pill.their_handle": "Eu handlen:",
"domain_pill.their_server": "Eu cartref digidol, lle mae eu holl negeseuon yn byw.",
"domain_pill.their_username": "Eu dynodwr unigryw ar eu gweinydd. Mae'n bosibl dod o hyd i ddefnyddwyr gyda'r un enw defnyddiwr ar wahanol weinyddion.",
"domain_pill.username": "Enw Defnyddiwr",
"domain_pill.whats_in_a_handle": "Beth sydd mewn handlen?",
"domain_pill.who_they_are": "Gan fod handlen yn dweud pwy yw rhywun a ble maen nhw, gallwch chi ryngweithio â phobl ar draws gwe gymdeithasol <button>llwyfannau wedi'u pweru gan ActivityPub</button> .",
"domain_pill.who_you_are": "Oherwydd bod eich handlen yn dweud pwy ydych chi a ble rydych chi, gall pobl ryngweithio â chi ar draws gwe gymdeithasol <button>llwyfannau wedi'u pweru gan ActivityPub</button> .",
"domain_pill.your_handle": "Eich handlen:",
"domain_pill.your_server": "Eich cartref digidol, lle mae'ch holl bostiadau'n byw. Ddim yn hoffi'r un hon? Trosglwyddwch weinyddion ar unrhyw adeg a dewch â'ch dilynwyr hefyd.",
"domain_pill.your_username": "Eich dynodwr unigryw ar y gweinydd hwn. Mae'n bosibl dod o hyd i ddefnyddwyr gyda'r un enw defnyddiwr ar wahanol weinyddion.",
"embed.instructions": "Gosodwch y post hwn ar eich gwefan drwy gopïo'r côd isod.",
"embed.preview": "Dyma sut olwg fydd arno:",
"emoji_button.activity": "Gweithgarwch",
@ -267,6 +297,8 @@
"filter_modal.select_filter.subtitle": "Defnyddiwch gategori sy'n bodoli eisoes neu crëu un newydd",
"filter_modal.select_filter.title": "Hidlo'r postiad hwn",
"filter_modal.title.status": "Hidlo postiad",
"filtered_notifications_banner.mentions": "{count, plural, one {crybwylliad} other {crybwylliad}}",
"filtered_notifications_banner.pending_requests": "Hysbysiadau gan {count, plural, =0 {neb} one {un person} other {# person}} efallai y gwyddoch amdanyn nhw",
"filtered_notifications_banner.title": "Hysbysiadau wedi'u hidlo",
"firehose.all": "Popeth",
"firehose.local": "Gweinydd hwn",
@ -276,6 +308,8 @@
"follow_requests.unlocked_explanation": "Er nid yw eich cyfrif wedi'i gloi, roedd y staff {domain} yn meddwl efallai hoffech adolygu ceisiadau dilyn o'r cyfrifau rhain wrth law.",
"follow_suggestions.curated_suggestion": "Dewis staff",
"follow_suggestions.dismiss": "Peidio â dangos hwn eto",
"follow_suggestions.featured_longer": "Wedi'i ddewis â llaw gan dîm {domain}",
"follow_suggestions.friends_of_friends_longer": "Yn boblogaidd ymhlith y bobl rydych chi'n eu dilyn",
"follow_suggestions.hints.featured": "Mae'r proffil hwn wedi'i ddewis yn arbennig gan dîm {domain}.",
"follow_suggestions.hints.friends_of_friends": "Mae'r proffil hwn yn boblogaidd ymhlith y bobl rydych chi'n eu dilyn.",
"follow_suggestions.hints.most_followed": "Mae'r proffil hwn yn un o'r rhai sy'n cael ei ddilyn fwyaf ar {domain}.",
@ -283,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Mae'r proffil hwn yn debyg i'r proffiliau rydych chi wedi'u dilyn yn fwyaf diweddar.",
"follow_suggestions.personalized_suggestion": "Awgrym personol",
"follow_suggestions.popular_suggestion": "Awgrym poblogaidd",
"follow_suggestions.popular_suggestion_longer": "Yn boblogaidd ar {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Yn debyg i broffiliau y gwnaethoch chi eu dilyn yn ddiweddar",
"follow_suggestions.view_all": "Gweld y cyfan",
"follow_suggestions.who_to_follow": "Pwy i ddilyn",
"followed_tags": "Hashnodau rydych yn eu dilyn",
@ -396,6 +432,15 @@
"loading_indicator.label": "Yn llwytho…",
"media_gallery.toggle_visible": "{number, plural, one {Cuddio delwedd} other {Cuddio delwedd}}",
"moved_to_account_banner.text": "Ar hyn y bryd, mae eich cyfrif {disabledAccount} wedi ei analluogi am i chi symud i {movedToAccount}.",
"mute_modal.hide_from_notifications": "Cuddio rhag hysbysiadau",
"mute_modal.hide_options": "Cuddio'r dewis",
"mute_modal.indefinite": "Nes i mi eu dad-dewi",
"mute_modal.show_options": "Dangos y dewis",
"mute_modal.they_can_mention_and_follow": "Gallan nhw eich crybwyll a'ch dilyn, ond fyddwch chi ddim yn eu gweld.",
"mute_modal.they_wont_know": "Fyddan nhw ddim yn gwybod eu bod wedi cael eu tawelu.",
"mute_modal.title": "Tewi defnyddiwr?",
"mute_modal.you_wont_see_mentions": "Welwch chi ddim postiadau sy'n sôn amdanyn nhw.",
"mute_modal.you_wont_see_posts": "Gallan nhw weld eich postiadau o hyd, ond fyddwch chi ddim yn gweld eu rhai hwy.",
"navigation_bar.about": "Ynghylch",
"navigation_bar.advanced_interface": "Agor mewn rhyngwyneb gwe uwch",
"navigation_bar.blocks": "Defnyddwyr wedi eu blocio",
@ -428,9 +473,23 @@
"notification.follow": "Dilynodd {name} chi",
"notification.follow_request": "Mae {name} wedi gwneud cais i'ch dilyn",
"notification.mention": "Crybwyllodd {name} amdanoch chi",
"notification.moderation-warning.learn_more": "Dysgu mwy",
"notification.moderation_warning": "Rydych wedi derbyn rhybudd cymedroli",
"notification.moderation_warning.action_delete_statuses": "Mae rhai o'ch postiadau wedi'u dileu.",
"notification.moderation_warning.action_disable": "Mae eich cyfrif wedi'i analluogi.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Mae rhai o'ch postiadau wedi'u marcio'n sensitif.",
"notification.moderation_warning.action_none": "Mae eich cyfrif wedi derbyn rhybudd cymedroli.",
"notification.moderation_warning.action_sensitive": "Bydd eich postiadau'n cael eu marcio'n sensitif o hyn ymlaen.",
"notification.moderation_warning.action_silence": "Mae eich cyfrif wedi'i gyfyngu.",
"notification.moderation_warning.action_suspend": "Mae eich cyfrif wedi'i hatal.",
"notification.own_poll": "Mae eich pleidlais wedi dod i ben",
"notification.poll": "Mae pleidlais rydych wedi pleidleisio ynddi wedi dod i ben",
"notification.reblog": "Hybodd {name} eich post",
"notification.relationships_severance_event": "Wedi colli cysylltiad â {name}",
"notification.relationships_severance_event.account_suspension": "Mae gweinyddwr o {from} wedi atal {target}, sy'n golygu na allwch dderbyn diweddariadau ganddynt mwyach na rhyngweithio â nhw.",
"notification.relationships_severance_event.domain_block": "Mae gweinyddwr o {from} wedi rhwystro {target}, gan gynnwys {followersCount} o'ch dilynwyr a {followingCount, plural, one {# cyfrif} other {# cyfrif}} arall rydych chi'n ei ddilyn.",
"notification.relationships_severance_event.learn_more": "Dysgu mwy",
"notification.relationships_severance_event.user_domain_block": "Rydych wedi rhwystro {target}, gan ddileu {followersCount} o'ch dilynwyr a {followingCount, plural, one {# cyfrif} other {#cyfrifon}} arall rydych yn ei ddilyn.",
"notification.status": "{name} newydd ei bostio",
"notification.update": "Golygodd {name} bostiad",
"notification_requests.accept": "Derbyn",
@ -443,6 +502,8 @@
"notifications.column_settings.admin.sign_up": "Cofrestriadau newydd:",
"notifications.column_settings.alert": "Hysbysiadau bwrdd gwaith",
"notifications.column_settings.favourite": "Ffefrynnau:",
"notifications.column_settings.filter_bar.advanced": "Dangos pob categori",
"notifications.column_settings.filter_bar.category": "Bar hidlo cyflym",
"notifications.column_settings.follow": "Dilynwyr newydd:",
"notifications.column_settings.follow_request": "Ceisiadau dilyn newydd:",
"notifications.column_settings.mention": "Crybwylliadau:",
@ -653,9 +714,11 @@
"status.direct": "Crybwyll yn breifat @{name}",
"status.direct_indicator": "Crybwyll preifat",
"status.edit": "Golygu",
"status.edited": "Golygwyd ddiwethaf {date}",
"status.edited_x_times": "Golygwyd {count, plural, one {count} two {count} other {{count} gwaith}}",
"status.embed": "Mewnblannu",
"status.favourite": "Hoffi",
"status.favourites": "{count, plural, one {ffefryn} other {ffefryn}}",
"status.filter": "Hidlo'r postiad hwn",
"status.filtered": "Wedi'i hidlo",
"status.hide": "Cuddio'r postiad",
@ -676,6 +739,7 @@
"status.reblog": "Hybu",
"status.reblog_private": "Hybu i'r gynulleidfa wreiddiol",
"status.reblogged_by": "Hybodd {name}",
"status.reblogs": "{count, plural, one {hwb} other {hwb}}",
"status.reblogs.empty": "Does neb wedi hybio'r post yma eto. Pan y bydd rhywun yn gwneud, byddent yn ymddangos yma.",
"status.redraft": "Dileu ac ailddrafftio",
"status.remove_bookmark": "Tynnu nod tudalen",

View file

@ -241,7 +241,7 @@
"emoji_button.nature": "Naturaleza",
"emoji_button.not_found": "No se encontraron emojis coincidentes",
"emoji_button.objects": "Objetos",
"emoji_button.people": "Gente",
"emoji_button.people": "Cuentas",
"emoji_button.recent": "Usados frecuentemente",
"emoji_button.search": "Buscar...",
"emoji_button.search_results": "Resultados de búsqueda",
@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "A pesar de que tu cuenta no es privada, el equipo de {domain} pensó que podrías querer revisar manualmente las solicitudes de seguimiento de estas cuentas.",
"follow_suggestions.curated_suggestion": "Selección del equipo",
"follow_suggestions.dismiss": "No mostrar de nuevo",
"follow_suggestions.featured_longer": "Seleccionada a mano por el equipo de {domain}",
"follow_suggestions.friends_of_friends_longer": "Populares entre las cuentas que seguís",
"follow_suggestions.hints.featured": "Este perfil fue seleccionado a mano por el equipo de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Este perfil es popular entre las cuentas que seguís.",
"follow_suggestions.hints.most_followed": "Este perfil es uno de los más seguidos en {domain}.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Este perfil es similar a los que comenzaste a seguir.",
"follow_suggestions.personalized_suggestion": "Sugerencia personalizada",
"follow_suggestions.popular_suggestion": "Sugerencia popular",
"follow_suggestions.popular_suggestion_longer": "Popular en {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Similares a perfiles que comenzaste a seguir recientemente",
"follow_suggestions.view_all": "Ver todo",
"follow_suggestions.who_to_follow": "A quién seguir",
"followed_tags": "Etiquetas seguidas",
@ -469,6 +473,15 @@
"notification.follow": "{name} te empezó a seguir",
"notification.follow_request": "{name} solicitó seguirte",
"notification.mention": "{name} te mencionó",
"notification.moderation-warning.learn_more": "Aprendé más",
"notification.moderation_warning": "Recibiste una advertencia de moderación",
"notification.moderation_warning.action_delete_statuses": "Se eliminaron algunos de tus mensajes.",
"notification.moderation_warning.action_disable": "Se deshabilitó tu cuenta.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Se marcaron como sensibles a algunos de tus mensajes.",
"notification.moderation_warning.action_none": "Tu cuenta recibió una advertencia de moderación.",
"notification.moderation_warning.action_sensitive": "A partir de ahora, tus mensajes serán marcados como sensibles.",
"notification.moderation_warning.action_silence": "Tu cuenta fue limitada.",
"notification.moderation_warning.action_suspend": "Tu cuenta fue suspendida.",
"notification.own_poll": "Tu encuesta finalizó",
"notification.poll": "Finalizó una encuesta en la que votaste",
"notification.reblog": "{name} adhirió a tu mensaje",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "A pesar de que tu cuenta no es privada, el personal de {domain} ha pensado que quizás deberías revisar manualmente las solicitudes de seguimiento de estas cuentas.",
"follow_suggestions.curated_suggestion": "Recomendaciones del equipo",
"follow_suggestions.dismiss": "No mostrar de nuevo",
"follow_suggestions.featured_longer": "Escogidos por el equipo de {domain}",
"follow_suggestions.friends_of_friends_longer": "Populares entre las personas a las que sigues",
"follow_suggestions.hints.featured": "Este perfil ha sido seleccionado a mano por el equipo de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Este perfil es popular entre las personas que sigues.",
"follow_suggestions.hints.most_followed": "Este perfil es uno de los más seguidos en {domain}.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Este perfil es similar a los perfiles que has seguido recientemente.",
"follow_suggestions.personalized_suggestion": "Sugerencia personalizada",
"follow_suggestions.popular_suggestion": "Sugerencia popular",
"follow_suggestions.popular_suggestion_longer": "Populares en {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Similares a los perfiles que has seguido recientemente",
"follow_suggestions.view_all": "Ver todo",
"follow_suggestions.who_to_follow": "Recomendamos seguir",
"followed_tags": "Hashtags seguidos",
@ -469,6 +473,15 @@
"notification.follow": "{name} te empezó a seguir",
"notification.follow_request": "{name} ha solicitado seguirte",
"notification.mention": "{name} te ha mencionado",
"notification.moderation-warning.learn_more": "Saber más",
"notification.moderation_warning": "Has recibido una advertencia de moderación",
"notification.moderation_warning.action_delete_statuses": "Se han eliminado algunas de tus publicaciones.",
"notification.moderation_warning.action_disable": "Se ha desactivado su cuenta.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Se han marcado como sensibles algunas de tus publicaciones.",
"notification.moderation_warning.action_none": "Tu cuenta ha recibido un aviso de moderación.",
"notification.moderation_warning.action_sensitive": "De ahora en adelante, todas tus publicaciones se marcarán como sensibles.",
"notification.moderation_warning.action_silence": "Se ha limitado tu cuenta.",
"notification.moderation_warning.action_suspend": "Se ha suspendido tu cuenta.",
"notification.own_poll": "Tu encuesta ha terminado",
"notification.poll": "Una encuesta en la que has votado ha terminado",
"notification.reblog": "{name} ha retooteado tu estado",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "A pesar de que tu cuenta no es privada, el personal de {domain} ha pensado que quizás deberías revisar manualmente las solicitudes de seguimiento de estas cuentas.",
"follow_suggestions.curated_suggestion": "Recomendaciones del equipo",
"follow_suggestions.dismiss": "No mostrar de nuevo",
"follow_suggestions.featured_longer": "Escogidos por el equipo de {domain}",
"follow_suggestions.friends_of_friends_longer": "Populares entre las personas a las que sigues",
"follow_suggestions.hints.featured": "Este perfil ha sido elegido a mano por el equipo de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Este perfil es popular entre las personas que sigues.",
"follow_suggestions.hints.most_followed": "Este perfil es uno de los más seguidos en {domain}.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Este perfil es similar a los perfiles que has seguido recientemente.",
"follow_suggestions.personalized_suggestion": "Sugerencia personalizada",
"follow_suggestions.popular_suggestion": "Sugerencia popular",
"follow_suggestions.popular_suggestion_longer": "Populares en {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Similares a los perfiles que has seguido recientemente",
"follow_suggestions.view_all": "Ver todo",
"follow_suggestions.who_to_follow": "A quién seguir",
"followed_tags": "Etiquetas seguidas",
@ -469,6 +473,15 @@
"notification.follow": "{name} te empezó a seguir",
"notification.follow_request": "{name} ha solicitado seguirte",
"notification.mention": "{name} te ha mencionado",
"notification.moderation-warning.learn_more": "Saber más",
"notification.moderation_warning": "Has recibido una advertencia de moderación",
"notification.moderation_warning.action_delete_statuses": "Se han eliminado algunas de tus publicaciones.",
"notification.moderation_warning.action_disable": "Se ha desactivado su cuenta.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Se han marcado como sensibles algunas de tus publicaciones.",
"notification.moderation_warning.action_none": "Tu cuenta ha recibido un aviso de moderación.",
"notification.moderation_warning.action_sensitive": "De ahora en adelante, todas tus publicaciones se marcarán como sensibles.",
"notification.moderation_warning.action_silence": "Se ha limitado tu cuenta.",
"notification.moderation_warning.action_suspend": "Se ha suspendido tu cuenta.",
"notification.own_poll": "Tu encuesta ha terminado",
"notification.poll": "Una encuesta en la que has votado ha terminado",
"notification.reblog": "{name} ha impulsado tu publicación",

View file

@ -473,6 +473,15 @@
"notification.follow": "{name} במעקב אחרייך",
"notification.follow_request": "{name} ביקשו לעקוב אחריך",
"notification.mention": "אוזכרת על ידי {name}",
"notification.moderation-warning.learn_more": "למידע נוסף",
"notification.moderation_warning": "קיבלת אזהרה מצוות ניהול התוכן",
"notification.moderation_warning.action_delete_statuses": "חלק מהודעותיך הוסרו.",
"notification.moderation_warning.action_disable": "חשבונך הושבת.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "חלק מהודעותיך סומנו כרגישות.",
"notification.moderation_warning.action_none": "חשבונך קיבל אזהרה מצוות ניהול התוכן.",
"notification.moderation_warning.action_sensitive": "הודעותיך יסומנו כרגישות מעתה ואילך.",
"notification.moderation_warning.action_silence": "חשבונך הוגבל.",
"notification.moderation_warning.action_suspend": "חשבונך הושעה.",
"notification.own_poll": "הסקר שלך הסתיים",
"notification.poll": "סקר שהצבעת בו הסתיים",
"notification.reblog": "הודעתך הודהדה על ידי {name}",

View file

@ -309,7 +309,7 @@
"follow_suggestions.curated_suggestion": "A stáb választása",
"follow_suggestions.dismiss": "Ne jelenjen meg újra",
"follow_suggestions.featured_longer": "A {domain} csapata által kézzel kiválasztott",
"follow_suggestions.friends_of_friends_longer": "Népszerű az Ön által követett emberek körében",
"follow_suggestions.friends_of_friends_longer": "Népszerű az általad követett emberek körében",
"follow_suggestions.hints.featured": "Ezt a profilt a(z) {domain} csapata választotta ki.",
"follow_suggestions.hints.friends_of_friends": "Ez a profil népszerű az általad követett emberek körében.",
"follow_suggestions.hints.most_followed": "Ez a profil a leginkább követett a(z) {domain} oldalon.",
@ -318,7 +318,7 @@
"follow_suggestions.personalized_suggestion": "Személyre szabott javaslat",
"follow_suggestions.popular_suggestion": "Népszerű javaslat",
"follow_suggestions.popular_suggestion_longer": "Népszerű itt: {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Hasonló profilok, melyeket nemrég követett",
"follow_suggestions.similar_to_recently_followed_longer": "Hasonló azokhoz a profilokhoz, melyeket nemrég követtél be",
"follow_suggestions.view_all": "Összes megtekintése",
"follow_suggestions.who_to_follow": "Kit érdemes követni",
"followed_tags": "Követett hashtagek",
@ -473,7 +473,7 @@
"notification.follow": "{name} követ téged",
"notification.follow_request": "{name} követni szeretne téged",
"notification.mention": "{name} megemlített",
"notification.moderation-warning.learn_more": "További információk",
"notification.moderation-warning.learn_more": "További információ",
"notification.moderation_warning": "Moderációs figyelmeztetést kaptál",
"notification.moderation_warning.action_delete_statuses": "Néhány bejegyzésedet eltávolították.",
"notification.moderation_warning.action_disable": "A fiókod le van tiltva.",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "Benque tu conto non es serrate, le personal de {domain} pensa que es un bon idea que tu revide manualmente le sequente requestas de iste contos.",
"follow_suggestions.curated_suggestion": "Selection del equipa",
"follow_suggestions.dismiss": "Non monstrar novemente",
"follow_suggestions.featured_longer": "Seligite con cura per le equipa de {domain}",
"follow_suggestions.friends_of_friends_longer": "Popular inter le gente que tu seque",
"follow_suggestions.hints.featured": "Iste profilo ha essite seligite manualmente per le equipa de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Iste profilo es popular inter le gente que tu seque.",
"follow_suggestions.hints.most_followed": "Iste profilo es un del plus sequites sur {domain}.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Iste profilo es similar al profilos que tu ha recentemente sequite.",
"follow_suggestions.personalized_suggestion": "Suggestion personalisate",
"follow_suggestions.popular_suggestion": "Suggestion personalisate",
"follow_suggestions.popular_suggestion_longer": "Popular sur {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Similar al profilos que tu ha sequite recentemente",
"follow_suggestions.view_all": "Vider toto",
"follow_suggestions.who_to_follow": "Qui sequer",
"followed_tags": "Hashtags sequite",
@ -469,6 +473,15 @@
"notification.follow": "{name} te ha sequite",
"notification.follow_request": "{name} ha requestate de sequer te",
"notification.mention": "{name} te ha mentionate",
"notification.moderation-warning.learn_more": "Apprender plus",
"notification.moderation_warning": "Tu ha recipite un advertimento de moderation",
"notification.moderation_warning.action_delete_statuses": "Alcunes de tu messages ha essite removite.",
"notification.moderation_warning.action_disable": "Tu conto ha essite disactivate.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Alcunes de tu messages ha essite marcate como sensibile.",
"notification.moderation_warning.action_none": "Tu conto ha recipite un advertimento de moderation.",
"notification.moderation_warning.action_sensitive": "Tu messages essera marcate como sensibile a partir de ora.",
"notification.moderation_warning.action_silence": "Tu conto ha essite limitate.",
"notification.moderation_warning.action_suspend": "Tu conto ha essite suspendite.",
"notification.own_poll": "Tu sondage ha finite",
"notification.poll": "Un sondage in le qual tu ha votate ha finite",
"notification.reblog": "{name} ha impulsate tu message",

View file

@ -393,7 +393,7 @@
"filter_modal.title.status": "投稿をフィルターする",
"filtered_notifications_banner.mentions": "{count, plural, one {メンション} other {メンション}}",
"filtered_notifications_banner.pending_requests": "{count, plural, =0 {通知がブロックされているアカウントはありません} other {#アカウントからの通知がブロックされています}}",
"filtered_notifications_banner.title": "ブロック済みの通知",
"filtered_notifications_banner.title": "保留中の通知",
"firehose.all": "すべて",
"firehose.local": "このサーバー",
"firehose.remote": "ほかのサーバー",
@ -402,6 +402,8 @@
"follow_requests.unlocked_explanation": "あなたのアカウントは承認制ではありませんが、{domain}のスタッフはこれらのアカウントからのフォローリクエストの確認が必要であると判断しました。",
"follow_suggestions.curated_suggestion": "サーバースタッフ公認",
"follow_suggestions.dismiss": "今後表示しない",
"follow_suggestions.featured_longer": "{domain} スタッフ公認",
"follow_suggestions.friends_of_friends_longer": "フォロー中のユーザーに人気",
"follow_suggestions.hints.featured": "{domain} の運営スタッフが選んだアカウントです。",
"follow_suggestions.hints.friends_of_friends": "フォロー中のユーザーのあいだで人気のアカウントです。",
"follow_suggestions.hints.most_followed": "{domain} でもっともフォローされているアカウントのひとつです。",
@ -409,6 +411,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "最近フォローしたユーザーに似ているアカウントです。",
"follow_suggestions.personalized_suggestion": "フォローに基づく提案",
"follow_suggestions.popular_suggestion": "人気のアカウント",
"follow_suggestions.popular_suggestion_longer": "{domain} で人気",
"follow_suggestions.similar_to_recently_followed_longer": "最近フォローしたユーザーと似ているアカウント",
"follow_suggestions.view_all": "すべて表示",
"follow_suggestions.who_to_follow": "フォローを増やしてみませんか?",
"followed_tags": "フォロー中のハッシュタグ",
@ -588,7 +592,7 @@
"notification_requests.accept": "受け入れる",
"notification_requests.dismiss": "無視",
"notification_requests.notifications_from": "{name}からの通知",
"notification_requests.title": "ブロック済みの通知",
"notification_requests.title": "保留中の通知",
"notifications.clear": "通知を消去",
"notifications.clear_confirmation": "本当に通知を消去しますか?",
"notifications.column_settings.admin.report": "新しい通報:",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "귀하의 계정이 잠긴 계정이 아닐지라도, {domain} 스태프는 이 계정들의 팔로우 요청을 수동으로 처리해 주시면 좋겠다고 생각했습니다.",
"follow_suggestions.curated_suggestion": "스태프의 추천",
"follow_suggestions.dismiss": "다시 보지 않기",
"follow_suggestions.featured_longer": "{domain} 팀이 손수 고름",
"follow_suggestions.friends_of_friends_longer": "내가 팔로우 하는 사람들 사이에서 인기",
"follow_suggestions.hints.featured": "이 프로필은 {domain} 팀이 손수 선택했습니다.",
"follow_suggestions.hints.friends_of_friends": "이 프로필은 내가 팔로우 하는 사람들에게서 유명합니다.",
"follow_suggestions.hints.most_followed": "이 프로필은 {domain}에서 가장 많이 팔로우 된 사람들 중 하나입니다.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "이 프로필은 내가 최근에 팔로우 한 프로필들과 유사합니다.",
"follow_suggestions.personalized_suggestion": "개인화된 추천",
"follow_suggestions.popular_suggestion": "인기있는 추천",
"follow_suggestions.popular_suggestion_longer": "{domain}에서 인기",
"follow_suggestions.similar_to_recently_followed_longer": "내가 최근에 팔로우 한 프로필들과 유사",
"follow_suggestions.view_all": "모두 보기",
"follow_suggestions.who_to_follow": "팔로우할 만한 사람",
"followed_tags": "팔로우 중인 해시태그",
@ -469,6 +473,15 @@
"notification.follow": "{name} 님이 나를 팔로우했습니다",
"notification.follow_request": "{name} 님이 팔로우 요청을 보냈습니다",
"notification.mention": "{name} 님의 멘션",
"notification.moderation-warning.learn_more": "더 알아보기",
"notification.moderation_warning": "중재 경고를 받았습니다",
"notification.moderation_warning.action_delete_statuses": "게시물 몇 개가 삭제되었습니다.",
"notification.moderation_warning.action_disable": "계정이 비활성화되었습니다.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "게시물 몇 개가 민감함 처리되었습니다.",
"notification.moderation_warning.action_none": "계정에 중재 경고를 받았습니다.",
"notification.moderation_warning.action_sensitive": "앞으로의 게시물을 민감한 것으로 표시됩니다.",
"notification.moderation_warning.action_silence": "계정이 제한되었습니다.",
"notification.moderation_warning.action_suspend": "계정이 정지되었습니다.",
"notification.own_poll": "설문을 마침",
"notification.poll": "참여한 설문이 종료됨",
"notification.reblog": "{name} 님이 부스트했습니다",

View file

@ -295,6 +295,7 @@
"follow_requests.unlocked_explanation": "Aunke tu kuento no esta serrado, la taifa de {domain} kreye ke talvez keres revizar manualmente las solisitudes de segimento de estos kuentos.",
"follow_suggestions.curated_suggestion": "Seleksyon de la taifa",
"follow_suggestions.dismiss": "No amostra mas",
"follow_suggestions.friends_of_friends_longer": "Popular entre personas a las kualas siges",
"follow_suggestions.hints.featured": "Este profil tiene sido eskojido por la taifa de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Este profil es popular entre las personas ke siges.",
"follow_suggestions.hints.most_followed": "Este profil es uno de los mas segidos en {domain}.",
@ -454,6 +455,9 @@
"notification.follow": "{name} te ampeso a segir",
"notification.follow_request": "{name} tiene solisitado segirte",
"notification.mention": "{name} te enmento",
"notification.moderation-warning.learn_more": "Ambezate mas",
"notification.moderation_warning.action_silence": "Tu kuento tiene sido limitado.",
"notification.moderation_warning.action_suspend": "Tu kuento tiene sido suspendido.",
"notification.own_poll": "Tu anketa eskapo",
"notification.poll": "Anketa en ke votates eskapo",
"notification.reblog": "{name} repartajo tu publikasyon",

View file

@ -282,6 +282,7 @@
"filter_modal.select_filter.subtitle": "Naudok esamą kategoriją arba sukurk naują.",
"filter_modal.select_filter.title": "Filtruoti šį įrašą",
"filter_modal.title.status": "Filtruoti įrašą",
"filtered_notifications_banner.mentions": "{count, plural, one {paminėjimas} few {paminėjimai} many {paminėjimo} other {paminėjimų}}",
"firehose.all": "Visi",
"firehose.local": "Šis serveris",
"firehose.remote": "Kiti serveriai",
@ -290,6 +291,8 @@
"follow_requests.unlocked_explanation": "Nors tavo paskyra neužrakinta, {domain} personalas mano, kad galbūt norėsi rankiniu būdu patikrinti šių paskyrų sekimo prašymus.",
"follow_suggestions.curated_suggestion": "Personalo pasirinkimai",
"follow_suggestions.dismiss": "Daugiau nerodyti",
"follow_suggestions.featured_longer": "Rankomis atrinkta {domain} komanda",
"follow_suggestions.friends_of_friends_longer": "Populiarus tarp žmonių, kurių seki",
"follow_suggestions.hints.featured": "Šį profilį atrinko {domain} komanda.",
"follow_suggestions.hints.friends_of_friends": "Šis profilis yra populiarus tarp žmonių, kuriuos seki.",
"follow_suggestions.hints.most_followed": "Šis profilis yra vienas iš labiausiai sekamų {domain}.",
@ -297,6 +300,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Šis profilis panašus į profilius, kuriuos neseniai sekei.",
"follow_suggestions.personalized_suggestion": "Suasmenintas pasiūlymas",
"follow_suggestions.popular_suggestion": "Populiarus pasiūlymas",
"follow_suggestions.popular_suggestion_longer": "Populiarus domene {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Panašūs į profilius, kuriuos neseniai seki",
"follow_suggestions.view_all": "Peržiūrėti viską",
"follow_suggestions.who_to_follow": "Ką sekti",
"followed_tags": "Sekami saitažodžiai",
@ -442,6 +447,15 @@
"notification.follow": "{name} seka tave",
"notification.follow_request": "{name} paprašė tave sekti",
"notification.mention": "{name} paminėjo tave",
"notification.moderation-warning.learn_more": "Sužinoti daugiau",
"notification.moderation_warning": "Gavai prižiūrėjimo įspėjimą",
"notification.moderation_warning.action_delete_statuses": "Kai kurie tavo įrašai buvo pašalintos.",
"notification.moderation_warning.action_disable": "Tavo paskyra buvo išjungta.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Kai kurie tavo įrašai buvo pažymėtos kaip jautrios.",
"notification.moderation_warning.action_none": "Tavo paskyra gavo prižiūrėjimo įspėjimą.",
"notification.moderation_warning.action_sensitive": "Nuo šiol tavo įrašai bus pažymėti kaip jautrūs.",
"notification.moderation_warning.action_silence": "Tavo paskyra buvo apribota.",
"notification.moderation_warning.action_suspend": "Tavo paskyra buvo sustabdyta.",
"notification.own_poll": "Tavo apklausa baigėsi",
"notification.poll": "Apklausa, kurioje balsavai, pasibaigė",
"notification.reblog": "{name} pakėlė tavo įrašą",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "Apesar de seu perfil não ser trancado, {domain} exige que você revise a solicitação para te seguir destes perfis manualmente.",
"follow_suggestions.curated_suggestion": "Escolha da equipe",
"follow_suggestions.dismiss": "Não mostrar novamente",
"follow_suggestions.featured_longer": "Escolhido à mão pela equipe de {domain}",
"follow_suggestions.friends_of_friends_longer": "Popular entre as pessoas que você segue",
"follow_suggestions.hints.featured": "Este perfil foi escolhido a dedo pela equipe {domain}.",
"follow_suggestions.hints.friends_of_friends": "Este perfil é popular entre as pessoas que você segue.",
"follow_suggestions.hints.most_followed": "Este perfil é um dos mais seguidos em {domain}.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Este perfil é semelhante aos perfis que você seguiu recentemente.",
"follow_suggestions.personalized_suggestion": "Sugestão personalizada",
"follow_suggestions.popular_suggestion": "Sugestão popular",
"follow_suggestions.popular_suggestion_longer": "Popular em {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Similar a perfis que você seguiu recentemente",
"follow_suggestions.view_all": "Visualizar tudo",
"follow_suggestions.who_to_follow": "Quem seguir",
"followed_tags": "Hashtags seguidas",
@ -469,6 +473,15 @@
"notification.follow": "{name} te seguiu",
"notification.follow_request": "{name} quer te seguir",
"notification.mention": "{name} te mencionou",
"notification.moderation-warning.learn_more": "Aprender mais",
"notification.moderation_warning": "Você recebeu um aviso de moderação",
"notification.moderation_warning.action_delete_statuses": "Algumas das suas publicações foram removidas.",
"notification.moderation_warning.action_disable": "Sua conta foi desativada.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Algumas de suas publicações foram marcadas por ter conteúdo sensível.",
"notification.moderation_warning.action_none": "Sua conta recebeu um aviso de moderação.",
"notification.moderation_warning.action_sensitive": "Suas publicações serão marcadas como sensíveis a partir de agora.",
"notification.moderation_warning.action_silence": "Sua conta foi limitada.",
"notification.moderation_warning.action_suspend": "Sua conta foi suspensa.",
"notification.own_poll": "Sua enquete terminou",
"notification.poll": "Uma enquete que você votou terminou",
"notification.reblog": "{name} deu boost no teu toot",

View file

@ -246,6 +246,7 @@
"empty_column.list": "Tento zoznam je zatiaľ prázdny. Keď ale členovia tohoto zoznamu uverejnia nové príspevky, objavia sa tu.",
"empty_column.lists": "Zatiaľ nemáte žiadne zoznamy. Keď nejaký vytvoríte, zobrazí sa tu.",
"empty_column.mutes": "Zatiaľ ste si nikoho nestíšili.",
"empty_column.notification_requests": "Všetko čisté! Nič tu nieje. Keď dostaneš nové oboznámenia, zobrazia sa tu podľa tvojich nastavení.",
"empty_column.notifications": "Zatiaľ nemáte žiadne upozornenia. Začnú vám pribúdať, keď s vami začnú interagovať ostatní.",
"empty_column.public": "Zatiaľ tu nič nie je. Napíšte niečo verejné alebo začnite sledovať účty z iných serverov, aby tu niečo pribudlo.",
"error.unexpected_crash.explanation": "Pre chybu v našom kóde alebo problém s kompatibilitou prehliadača nebolo túto stránku možné zobraziť správne.",
@ -293,6 +294,7 @@
"follow_suggestions.hints.similar_to_recently_followed": "Tento profil je podobný profilom, ktoré ste nedávno začali sledovať.",
"follow_suggestions.personalized_suggestion": "Prispôsobený návrh",
"follow_suggestions.popular_suggestion": "Obľúbený návrh",
"follow_suggestions.popular_suggestion_longer": "Populárne na {domain}",
"follow_suggestions.view_all": "Zobraziť všetky",
"follow_suggestions.who_to_follow": "Koho sledovať",
"followed_tags": "Sledované hashtagy",
@ -442,9 +444,11 @@
"notification.follow": "{name} vás sleduje",
"notification.follow_request": "{name} vás žiada sledovať",
"notification.mention": "{name} vás spomína",
"notification.moderation-warning.learn_more": "Zisti viac",
"notification.own_poll": "Vaša anketa sa skončila",
"notification.poll": "Anketa, v ktorej ste hlasovali, sa skončila",
"notification.reblog": "{name} zdieľa váš príspevok",
"notification.relationships_severance_event": "Stratené prepojenia s {name}",
"notification.relationships_severance_event.learn_more": "Zisti viac",
"notification.status": "{name} uverejňuje niečo nové",
"notification.update": "{name} upravuje príspevok",
@ -487,6 +491,7 @@
"notifications.policy.filter_new_accounts_title": "Nové účty",
"notifications.policy.filter_not_followers_title": "Ľudia, ktorí ťa nenasledujú",
"notifications.policy.filter_not_following_title": "Ľudia, ktorých nenasleduješ",
"notifications.policy.filter_private_mentions_title": "Nevyžiadané priame spomenutia",
"notifications.policy.title": "Filtrovať oznámenia od…",
"notifications_permission_banner.enable": "Povoliť upozornenia na ploche",
"notifications_permission_banner.how_to_control": "Ak chcete dostávať upozornenia, keď Mastodon nie je otvorený, povoľte upozornenia na ploche. Po ich zapnutí môžete presne kontrolovať, ktoré typy interakcií generujú upozornenia na ploche, a to prostredníctvom tlačidla {icon} vyššie.",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "Iako vaš nalog nije zaključan, osoblje {domain} smatra da biste možda želeli da ručno pregledate zahteve za praćenje sa ovih naloga.",
"follow_suggestions.curated_suggestion": "Izbor osoblja",
"follow_suggestions.dismiss": "Ne prikazuj ponovo",
"follow_suggestions.featured_longer": "Ručno odabrao tim {domain}",
"follow_suggestions.friends_of_friends_longer": "Popularno među ljudima koje pratite",
"follow_suggestions.hints.featured": "Ovaj profil je ručno izabrao tim {domain}.",
"follow_suggestions.hints.friends_of_friends": "Ovaj profil je popularan među ljudima koje pratite.",
"follow_suggestions.hints.most_followed": "Ovaj profil je jedan od najpraćenijih na {domain}.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Ovaj profil je sličan profilima koje ste nedavno zapratili.",
"follow_suggestions.personalized_suggestion": "Personalizovani predlog",
"follow_suggestions.popular_suggestion": "Popularni predlog",
"follow_suggestions.popular_suggestion_longer": "Popularno na {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Slično profilima koje ste nedavno zapratili",
"follow_suggestions.view_all": "Prikaži sve",
"follow_suggestions.who_to_follow": "Koga pratiti",
"followed_tags": "Praćene heš oznake",
@ -469,6 +473,15 @@
"notification.follow": "{name} vas je zapratio",
"notification.follow_request": "{name} je zatražio da vas prati",
"notification.mention": "{name} vas je pomenuo",
"notification.moderation-warning.learn_more": "Saznajte više",
"notification.moderation_warning": "Dobili ste moderatorsko upozorenje",
"notification.moderation_warning.action_delete_statuses": "Neke od vaših objava su uklonjene.",
"notification.moderation_warning.action_disable": "Vaš nalog je onemogućen.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Neke od vaših objava su obeležene kao osetljive.",
"notification.moderation_warning.action_none": "Vaš nalog je dobio moderatorsko upozorenje.",
"notification.moderation_warning.action_sensitive": "Vaše objave će ubuduće biti označene kao osetljive.",
"notification.moderation_warning.action_silence": "Vaš nalog je ograničen.",
"notification.moderation_warning.action_suspend": "Vaš nalog je suspendovan.",
"notification.own_poll": "Vaša anketa je završena",
"notification.poll": "Završena je anketa u kojoj ste glasali",
"notification.reblog": "{name} je podržao vašu objavu",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "Иако ваш налог није закључан, особље {domain} сматра да бисте можда желели да ручно прегледате захтеве за праћење са ових налога.",
"follow_suggestions.curated_suggestion": "Избор особља",
"follow_suggestions.dismiss": "Не приказуј поново",
"follow_suggestions.featured_longer": "Ручно одабрао тим {domain}",
"follow_suggestions.friends_of_friends_longer": "Популарно међу људима које пратите",
"follow_suggestions.hints.featured": "Овај профил је ручно изабрао тим {domain}.",
"follow_suggestions.hints.friends_of_friends": "Овај профил је популаран међу људима које пратите.",
"follow_suggestions.hints.most_followed": "Овај профил је један од најпраћенијих на {domain}.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Овај профил је сличан профилима које сте недавно запратили.",
"follow_suggestions.personalized_suggestion": "Персонализовани предлог",
"follow_suggestions.popular_suggestion": "Популарни предлог",
"follow_suggestions.popular_suggestion_longer": "Популарно на {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Слично профилима које сте недавно запратили",
"follow_suggestions.view_all": "Прикажи све",
"follow_suggestions.who_to_follow": "Кога пратити",
"followed_tags": "Праћене хеш ознаке",
@ -469,6 +473,15 @@
"notification.follow": "{name} вас је запратио",
"notification.follow_request": "{name} је затражио да вас прати",
"notification.mention": "{name} вас је поменуо",
"notification.moderation-warning.learn_more": "Сазнајте више",
"notification.moderation_warning": "Добили сте модераторско упозорење",
"notification.moderation_warning.action_delete_statuses": "Неке од ваших објава су уклоњене.",
"notification.moderation_warning.action_disable": "Ваш налог је онемогућен.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Неке од ваших објава су обележене као осетљиве.",
"notification.moderation_warning.action_none": "Ваш налог је добио модераторско упозорење.",
"notification.moderation_warning.action_sensitive": "Ваше објаве ће убудуће бити означене као осетљиве.",
"notification.moderation_warning.action_silence": "Ваш налог је ограничен.",
"notification.moderation_warning.action_suspend": "Ваш налог је суспендован.",
"notification.own_poll": "Ваша анкета је завршена",
"notification.poll": "Завршена је анкета у којој сте гласали",
"notification.reblog": "{name} је подржао вашу објаву",

View file

@ -297,6 +297,7 @@
"filter_modal.select_filter.subtitle": "Använd en befintlig kategori eller skapa en ny",
"filter_modal.select_filter.title": "Filtrera detta inlägg",
"filter_modal.title.status": "Filtrera ett inlägg",
"filtered_notifications_banner.mentions": "{count, plural, one {omnämning} other {omnämnanden}}",
"filtered_notifications_banner.pending_requests": "Aviseringar från {count, plural, =0 {ingen} one {en person} other {# personer}} du kanske känner",
"filtered_notifications_banner.title": "Filtrerade aviseringar",
"firehose.all": "Allt",
@ -307,6 +308,8 @@
"follow_requests.unlocked_explanation": "Även om ditt konto inte är låst tror {domain}-personalen att du kanske vill granska dessa följares förfrågningar manuellt.",
"follow_suggestions.curated_suggestion": "Utvald av personalen",
"follow_suggestions.dismiss": "Visa inte igen",
"follow_suggestions.featured_longer": "Handplockad av {domain}-teamet",
"follow_suggestions.friends_of_friends_longer": "Populärt bland personer du följer",
"follow_suggestions.hints.featured": "Denna profil är handplockad av {domain}-teamet.",
"follow_suggestions.hints.friends_of_friends": "Denna profil är populär bland de personer du följer.",
"follow_suggestions.hints.most_followed": "Denna profil är en av de mest följda på {domain}.",
@ -314,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Denna profil liknar de profiler som du nyligen har följt.",
"follow_suggestions.personalized_suggestion": "Personligt förslag",
"follow_suggestions.popular_suggestion": "Populärt förslag",
"follow_suggestions.popular_suggestion_longer": "Populärt på {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Liknar profiler du nyligen följde",
"follow_suggestions.view_all": "Visa alla",
"follow_suggestions.who_to_follow": "Rekommenderade profiler",
"followed_tags": "Följda hashtags",
@ -469,10 +474,14 @@
"notification.follow_request": "{name} har begärt att följa dig",
"notification.mention": "{name} nämnde dig",
"notification.moderation-warning.learn_more": "Läs mer",
"notification.moderation_warning": "Du har mottagit en modereringsvarning",
"notification.moderation_warning.action_delete_statuses": "Några av dina inlägg har tagits bort.",
"notification.moderation_warning.action_disable": "Ditt konto har inaktiverats.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Några av dina inlägg har markerats som känsliga.",
"notification.moderation_warning.action_none": "Ditt konto har mottagit en modereringsvarning.",
"notification.moderation_warning.action_sensitive": "Dina inlägg kommer markeras som känsliga från och med nu.",
"notification.moderation_warning.action_silence": "Ditt konto har begränsats.",
"notification.moderation_warning.action_suspend": "Ditt konto har stängts av.",
"notification.own_poll": "Din röstning har avslutats",
"notification.poll": "En omröstning du röstat i har avslutats",
"notification.reblog": "{name} boostade ditt inlägg",

View file

@ -308,13 +308,17 @@
"follow_requests.unlocked_explanation": "แม้ว่าไม่มีการล็อคบัญชีของคุณ พนักงานของ {domain} คิดว่าคุณอาจต้องการตรวจทานคำขอติดตามจากบัญชีเหล่านี้ด้วยตนเอง",
"follow_suggestions.curated_suggestion": "คัดสรรโดยพนักงาน",
"follow_suggestions.dismiss": "ไม่ต้องแสดงอีก",
"follow_suggestions.featured_longer": "คัดสรรโดยทีม {domain}",
"follow_suggestions.friends_of_friends_longer": "เป็นที่นิยมในหมู่ผู้คนที่คุณติดตาม",
"follow_suggestions.hints.featured": "โปรไฟล์นี้ได้รับการคัดสรรโดยทีม {domain}",
"follow_suggestions.hints.friends_of_friends": "โปรไฟล์นี้ได้รับความนิยมในหมู่ผู้คนที่คุณติดตาม",
"follow_suggestions.hints.friends_of_friends": "โปรไฟล์นี้เป็นที่นิยมในหมู่ผู้คนที่คุณติดตาม",
"follow_suggestions.hints.most_followed": "โปรไฟล์นี้เป็นหนึ่งในโปรไฟล์ที่ได้รับการติดตามมากที่สุดใน {domain}",
"follow_suggestions.hints.most_interactions": "โปรไฟล์นี้เพิ่งได้รับความสนใจอย่างมากใน {domain}",
"follow_suggestions.hints.similar_to_recently_followed": "โปรไฟล์นี้คล้ายกับโปรไฟล์ที่คุณได้ติดตามล่าสุด",
"follow_suggestions.personalized_suggestion": "ข้อเสนอแนะเฉพาะบุคคล",
"follow_suggestions.popular_suggestion": "ข้อเสนอแนะยอดนิยม",
"follow_suggestions.popular_suggestion_longer": "เป็นที่นิยมใน {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "คล้ายกับโปรไฟล์ที่คุณได้ติดตามล่าสุด",
"follow_suggestions.view_all": "ดูทั้งหมด",
"follow_suggestions.who_to_follow": "ติดตามใครดี",
"followed_tags": "แฮชแท็กที่ติดตาม",
@ -469,6 +473,15 @@
"notification.follow": "{name} ได้ติดตามคุณ",
"notification.follow_request": "{name} ได้ขอติดตามคุณ",
"notification.mention": "{name} ได้กล่าวถึงคุณ",
"notification.moderation-warning.learn_more": "เรียนรู้เพิ่มเติม",
"notification.moderation_warning": "คุณได้รับคำเตือนการกลั่นกรอง",
"notification.moderation_warning.action_delete_statuses": "เอาโพสต์บางส่วนของคุณออกแล้ว",
"notification.moderation_warning.action_disable": "ปิดใช้งานบัญชีของคุณแล้ว",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "ทำเครื่องหมายโพสต์บางส่วนของคุณว่าละเอียดอ่อนแล้ว",
"notification.moderation_warning.action_none": "บัญชีของคุณได้รับคำเตือนการกลั่นกรอง",
"notification.moderation_warning.action_sensitive": "จะทำเครื่องหมายโพสต์ของคุณว่าละเอียดอ่อนนับจากนี้ไป",
"notification.moderation_warning.action_silence": "จำกัดบัญชีของคุณแล้ว",
"notification.moderation_warning.action_suspend": "ระงับบัญชีของคุณแล้ว",
"notification.own_poll": "การสำรวจความคิดเห็นของคุณได้สิ้นสุดแล้ว",
"notification.poll": "การสำรวจความคิดเห็นที่คุณได้ลงคะแนนได้สิ้นสุดแล้ว",
"notification.reblog": "{name} ได้ดันโพสต์ของคุณ",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "Hesabınız kilitli olmasa da, {domain} personeli bu hesaplardan gelen takip isteklerini gözden geçirmek isteyebileceğinizi düşündü.",
"follow_suggestions.curated_suggestion": "Çalışanların seçtikleri",
"follow_suggestions.dismiss": "Tekrar gösterme",
"follow_suggestions.featured_longer": "{domain} takımı tarafından elle seçildi",
"follow_suggestions.friends_of_friends_longer": "Takip ettiğiniz kişiler arasında popüler",
"follow_suggestions.hints.featured": "Bu profil {domain} ekibi tarafından elle seçilmiştir.",
"follow_suggestions.hints.friends_of_friends": "Bu profil takip ettiğiniz insanlar arasında popülerdir.",
"follow_suggestions.hints.most_followed": "Bu, {domain} sunucusunda en fazla izlenen profildir.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Bu profil, son zamanlarda takip ettiğiniz profillere benziyor.",
"follow_suggestions.personalized_suggestion": "Kişiselleşmiş öneriler",
"follow_suggestions.popular_suggestion": "Popüler öneriler",
"follow_suggestions.popular_suggestion_longer": "{domain} üzerinde popüler",
"follow_suggestions.similar_to_recently_followed_longer": "Yakın zamanda takip ettiğiniz hesaplara benziyor",
"follow_suggestions.view_all": "Tümünü gör",
"follow_suggestions.who_to_follow": "Takip edebileceklerin",
"followed_tags": "Takip edilen etiketler",
@ -469,6 +473,15 @@
"notification.follow": "{name} seni takip etti",
"notification.follow_request": "{name} size takip isteği gönderdi",
"notification.mention": "{name} senden bahsetti",
"notification.moderation-warning.learn_more": "Daha fazlası",
"notification.moderation_warning": "Bir denetim uyarısı aldınız",
"notification.moderation_warning.action_delete_statuses": "Bazı gönderileriniz kaldırıldı.",
"notification.moderation_warning.action_disable": "Hesabınız devre dışı bırakıldı.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Bazı gönderileriniz hassas olarak işaretlendi.",
"notification.moderation_warning.action_none": "Hesabınız bir denetim uyarısı aldı.",
"notification.moderation_warning.action_sensitive": "Gönderileriniz artık hassas olarak işaretlenecek.",
"notification.moderation_warning.action_silence": "Hesabınız sınırlandırıldı.",
"notification.moderation_warning.action_suspend": "Hesabınız askıya alındı.",
"notification.own_poll": "Anketiniz sona erdi",
"notification.poll": "Oy verdiğiniz bir anket sona erdi",
"notification.reblog": "{name} gönderini yeniden paylaştı",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "Mặc dù tài khoản của bạn đang ở chế độ công khai, quản trị viên của {domain} vẫn tin rằng bạn sẽ muốn xem lại yêu cầu theo dõi từ những người khác.",
"follow_suggestions.curated_suggestion": "Gợi ý từ máy chủ",
"follow_suggestions.dismiss": "Không hiện lại",
"follow_suggestions.featured_longer": "Tuyển chọn bởi {domain}",
"follow_suggestions.friends_of_friends_longer": "Nổi tiếng với những người mà bạn theo dõi",
"follow_suggestions.hints.featured": "Người này được đội ngũ {domain} đề xuất.",
"follow_suggestions.hints.friends_of_friends": "Người này nổi tiếng với những người bạn theo dõi.",
"follow_suggestions.hints.most_followed": "Người này được theo dõi nhiều nhất trên {domain}.",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "Người này có nét giống những người mà bạn theo dõi gần đây.",
"follow_suggestions.personalized_suggestion": "Gợi ý cá nhân hóa",
"follow_suggestions.popular_suggestion": "Những người nổi tiếng",
"follow_suggestions.popular_suggestion_longer": "Nổi tiếng trên {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Tương tự những người mà bạn theo dõi gần đây",
"follow_suggestions.view_all": "Xem tất cả",
"follow_suggestions.who_to_follow": "Gợi ý theo dõi",
"followed_tags": "Hashtag theo dõi",
@ -469,6 +473,15 @@
"notification.follow": "{name} theo dõi bạn",
"notification.follow_request": "{name} yêu cầu theo dõi bạn",
"notification.mention": "{name} nhắc đến bạn",
"notification.moderation-warning.learn_more": "Tìm hiểu",
"notification.moderation_warning": "Bạn đã nhận một cảnh báo kiểm duyệt",
"notification.moderation_warning.action_delete_statuses": "Một vài tút của bạn bị gỡ.",
"notification.moderation_warning.action_disable": "Tài khoản của bạn đã bị vô hiệu hóa.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Vài tút bạn bị đánh dấu nhạy cảm.",
"notification.moderation_warning.action_none": "Bạn đã nhận một cảnh báo kiểm duyệt.",
"notification.moderation_warning.action_sensitive": "Tút của bạn sẽ bị đánh dấu nhạy cảm kể từ bây giờ.",
"notification.moderation_warning.action_silence": "Tài khoản của bạn đã bị hạn chế.",
"notification.moderation_warning.action_suspend": "Tài khoản của bạn đã bị vô hiệu hóa.",
"notification.own_poll": "Cuộc bình chọn của bạn đã kết thúc",
"notification.poll": "Cuộc bình chọn đã kết thúc",
"notification.reblog": "{name} đăng lại tút của bạn",

View file

@ -308,6 +308,8 @@
"follow_requests.unlocked_explanation": "即使您的帳號未上鎖,{domain} 的工作人員認為您可能會想手動審核來自這些帳號的追蹤請求。",
"follow_suggestions.curated_suggestion": "編輯精選",
"follow_suggestions.dismiss": "不再顯示",
"follow_suggestions.featured_longer": "{domain} 團隊精選",
"follow_suggestions.friends_of_friends_longer": "受你的追蹤對象歡迎",
"follow_suggestions.hints.featured": "這個人檔案是由 {domain} 團隊精挑細選。",
"follow_suggestions.hints.friends_of_friends": "這個人檔案在你追蹤的人當中很受歡迎。",
"follow_suggestions.hints.most_followed": "這個人檔案是在 {domain} 上最多追蹤之一。",
@ -315,6 +317,8 @@
"follow_suggestions.hints.similar_to_recently_followed": "這個人檔案與你最近追蹤的類似。",
"follow_suggestions.personalized_suggestion": "個人化推薦",
"follow_suggestions.popular_suggestion": "熱門推薦",
"follow_suggestions.popular_suggestion_longer": "{domain} 熱門",
"follow_suggestions.similar_to_recently_followed_longer": "與你最近追蹤的帳號相似",
"follow_suggestions.view_all": "查看所有",
"follow_suggestions.who_to_follow": "追蹤對象",
"followed_tags": "已追蹤標籤",
@ -469,6 +473,15 @@
"notification.follow": "{name} 開始追蹤你",
"notification.follow_request": "{name} 要求追蹤你",
"notification.mention": "{name} 提及你",
"notification.moderation-warning.learn_more": "了解更多",
"notification.moderation_warning": "你收到一則審核警告",
"notification.moderation_warning.action_delete_statuses": "你的部份帖文已被刪除。",
"notification.moderation_warning.action_disable": "你的帳號已被停用。",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "你某些帖文已被標記為敏感內容。",
"notification.moderation_warning.action_none": "你的帳號收到一則審核警告。",
"notification.moderation_warning.action_sensitive": "從現在起,你的帖文將被標記為敏感內容。",
"notification.moderation_warning.action_silence": "你的帳號已受到限制。",
"notification.moderation_warning.action_suspend": "你的帳號已被停權。",
"notification.own_poll": "你的投票已結束",
"notification.poll": "你參與過的一個投票已經結束",
"notification.reblog": "{name} 轉推你的文章",

View file

@ -50,6 +50,7 @@ export default function search(state = initialState, action) {
return state.set('hidden', true);
case SEARCH_FETCH_REQUEST:
return state.withMutations(map => {
map.set('results', ImmutableMap());
map.set('isLoading', true);
map.set('submitted', true);
map.set('type', action.searchType);

View file

@ -5896,7 +5896,7 @@ a.status-card {
user-select: text;
display: flex;
@media screen and (max-width: $no-gap-breakpoint) {
@media screen and (width <= 630px) {
margin-top: auto;
}
}
@ -10576,6 +10576,7 @@ noscript {
font-weight: 500;
font-size: 11px;
line-height: 16px;
word-break: keep-all;
&__badge {
background: $ui-button-background-color;

View file

@ -75,6 +75,9 @@ class Account < ApplicationRecord
MENTION_RE = %r{(?<![=/[:word:]])@((#{USERNAME_RE})(?:@[[:word:].-]+[[:word:]]+)?)}i
URL_PREFIX_RE = %r{\Ahttp(s?)://[^/]+}
USERNAME_ONLY_RE = /\A#{USERNAME_RE}\z/i
USERNAME_LENGTH_LIMIT = 30
DISPLAY_NAME_LENGTH_LIMIT = 30
NOTE_LENGTH_LIMIT = 500
include Attachmentable # Load prior to Avatar & Header concerns
@ -107,10 +110,10 @@ class Account < ApplicationRecord
validates :uri, presence: true, unless: :local?, on: :create
# Local user validations
validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' }
validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: USERNAME_LENGTH_LIMIT }, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' }
validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' }
validates :display_name, length: { maximum: 30 }, if: -> { local? && will_save_change_to_display_name? }
validates :note, note_length: { maximum: 500 }, if: -> { local? && will_save_change_to_note? }
validates :display_name, length: { maximum: DISPLAY_NAME_LENGTH_LIMIT }, if: -> { local? && will_save_change_to_display_name? }
validates :note, note_length: { maximum: NOTE_LENGTH_LIMIT }, if: -> { local? && will_save_change_to_note? }
validates :fields, length: { maximum: DEFAULT_FIELDS_SIZE }, if: -> { local? && will_save_change_to_fields? }
validates :uri, absence: true, if: :local?, on: :create
validates :inbox_url, absence: true, if: :local?, on: :create
@ -143,7 +146,6 @@ class Account < ApplicationRecord
scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat) }
scope :by_recent_status, -> { includes(:account_stat).merge(AccountStat.by_recent_status).references(:account_stat) }
scope :by_recent_activity, -> { left_joins(:user, :account_stat).order(coalesced_activity_timestamps.desc).order(id: :desc) }
scope :popular, -> { order('account_stats.followers_count desc') }
scope :by_domain_and_subdomains, ->(domain) { where(domain: Instance.by_domain_and_subdomains(domain).select(:domain)) }
scope :not_excluded_by_account, ->(account) { where.not(id: account.excluded_from_timeline_account_ids) }
scope :not_domain_blocked_by_account, ->(account) { where(arel_table[:domain].eq(nil).or(arel_table[:domain].not_in(account.excluded_from_timeline_domains))) }

View file

@ -22,4 +22,10 @@ class ApplicationRecord < ActiveRecord::Base
value
end
end
# Prevent implicit serialization in ActiveModel::Serializer or other code paths.
# This is a hardening step to avoid accidental leaking of attributes.
def as_json
raise NotImplementedError
end
end

View file

@ -81,7 +81,7 @@ module Account::Associations
has_many :aliases, class_name: 'AccountAlias', dependent: :destroy, inverse_of: :account
# Hashtags
has_and_belongs_to_many :tags
has_and_belongs_to_many :tags # rubocop:disable Rails/HasAndBelongsToMany
has_many :featured_tags, -> { includes(:tag) }, dependent: :destroy, inverse_of: :account
# Account deletion requests

View file

@ -0,0 +1,77 @@
# frozen_string_literal: true
# TODO: This file is here for legacy support during devise-two-factor upgrade.
# It should be removed after all records have been migrated.
module LegacyOtpSecret
extend ActiveSupport::Concern
private
# Decrypt and return the `encrypted_otp_secret` attribute which was used in
# prior versions of devise-two-factor
# @return [String] The decrypted OTP secret
def legacy_otp_secret
return nil unless self[:encrypted_otp_secret]
return nil unless self.class.otp_secret_encryption_key
hmac_iterations = 2000 # a default set by the Encryptor gem
key = self.class.otp_secret_encryption_key
salt = Base64.decode64(encrypted_otp_secret_salt)
iv = Base64.decode64(encrypted_otp_secret_iv)
raw_cipher_text = Base64.decode64(encrypted_otp_secret)
# The last 16 bytes of the ciphertext are the authentication tag - we use
# Galois Counter Mode which is an authenticated encryption mode
cipher_text = raw_cipher_text[0..-17]
auth_tag = raw_cipher_text[-16..-1] # rubocop:disable Style/SlicingWithRange
# this alrorithm lifted from
# https://github.com/attr-encrypted/encryptor/blob/master/lib/encryptor.rb#L54
# create an OpenSSL object which will decrypt the AES cipher with 256 bit
# keys in Galois Counter Mode (GCM). See
# https://ruby.github.io/openssl/OpenSSL/Cipher.html
cipher = OpenSSL::Cipher.new('aes-256-gcm')
# tell the cipher we want to decrypt. Symmetric algorithms use a very
# similar process for encryption and decryption, hence the same object can
# do both.
cipher.decrypt
# Use a Password-Based Key Derivation Function to generate the key actually
# used for encryptoin from the key we got as input.
cipher.key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(key, salt, hmac_iterations, cipher.key_len)
# set the Initialization Vector (IV)
cipher.iv = iv
# The tag must be set after calling Cipher#decrypt, Cipher#key= and
# Cipher#iv=, but before calling Cipher#final. After all decryption is
# performed, the tag is verified automatically in the call to Cipher#final.
#
# If the auth_tag does not verify, then #final will raise OpenSSL::Cipher::CipherError
cipher.auth_tag = auth_tag
# auth_data must be set after auth_tag has been set when decrypting See
# http://ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html#method-i-auth_data-3D
# we are not adding any authenticated data but OpenSSL docs say this should
# still be called.
cipher.auth_data = ''
# #update is (somewhat confusingly named) the method which actually
# performs the decryption on the given chunk of data. Our OTP secret is
# short so we only need to call it once.
#
# It is very important that we call #final because:
#
# 1. The authentication tag is checked during the call to #final
# 2. Block based cipher modes (e.g. CBC) work on fixed size chunks. We need
# to call #final to get it to process the last chunk properly. The output
# of #final should be appended to the decrypted value. This isn't
# required for streaming cipher modes but including it is a best practice
# so that your code will continue to function correctly even if you later
# change to a block cipher mode.
cipher.update(cipher_text) + cipher.final
end
end

View file

@ -32,6 +32,8 @@ class CustomFilter < ApplicationRecord
explore
).freeze
EXPIRATION_DURATIONS = [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week, 2.weeks, 1.month, 3.months].freeze
include Expireable
include Redisable
@ -53,10 +55,9 @@ class CustomFilter < ApplicationRecord
after_commit :invalidate_cache!
def expires_in
return @expires_in if defined?(@expires_in)
return nil if expires_at.nil?
[30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week, 2.weeks, 1.month, 3.months].find { |expires_in| expires_in.from_now >= expires_at }
EXPIRATION_DURATIONS.find { |expires_in| expires_in.from_now >= expires_at }
end
def irreversible=(value)

View file

@ -109,7 +109,7 @@ class Status < ApplicationRecord
has_many :local_emoji_reacted, -> { merge(Account.local) }, through: :emoji_reactions, source: :account
has_many :local_referenced, -> { merge(Account.local) }, through: :referenced_by_statuses, source: :account
has_and_belongs_to_many :tags
has_and_belongs_to_many :tags # rubocop:disable Rails/HasAndBelongsToMany
has_one :preview_cards_status, inverse_of: :status, dependent: :delete
@ -136,7 +136,9 @@ class Status < ApplicationRecord
scope :remote, -> { where(local: false).where.not(uri: nil) }
scope :local, -> { where(local: true).or(where(uri: nil)) }
scope :with_accounts, ->(ids) { where(id: ids).includes(:account) }
scope :without_replies, -> { where('statuses.reply = FALSE OR statuses.in_reply_to_account_id = statuses.account_id') }
scope :without_replies, -> { not_reply.or(reply_to_account) }
scope :not_reply, -> { where(reply: false) }
scope :reply_to_account, -> { where(arel_table[:in_reply_to_account_id].eq arel_table[:account_id]) }
scope :without_reblogs, -> { where(statuses: { reblog_of_id: nil }) }
scope :with_public_visibility, -> { where(visibility: [:public, :public_unlisted, :login]) }
scope :with_public_search_visibility, -> { merge(where(visibility: [:public, :public_unlisted, :login]).or(Status.where(searchability: [:public, :public_unlisted]))) }

View file

@ -21,8 +21,10 @@
class Tag < ApplicationRecord
include Paginable
# rubocop:disable Rails/HasAndBelongsToMany
has_and_belongs_to_many :statuses
has_and_belongs_to_many :accounts
# rubocop:enable Rails/HasAndBelongsToMany
has_many :passive_relationships, class_name: 'TagFollow', inverse_of: :tag, dependent: :destroy
has_many :featured_tags, dependent: :destroy, inverse_of: :tag

View file

@ -39,6 +39,7 @@
# role_id :bigint(8)
# settings :text
# time_zone :string
# otp_secret :string
#
class User < ApplicationRecord
@ -75,6 +76,8 @@ class User < ApplicationRecord
devise :two_factor_authenticatable,
otp_secret_encryption_key: Rails.configuration.x.otp_secret
include LegacyOtpSecret # Must be after the above `devise` line in order to override the legacy method
devise :two_factor_backupable,
otp_number_of_backup_codes: 10
@ -134,11 +137,6 @@ class User < ApplicationRecord
normalizes :time_zone, with: ->(time_zone) { ActiveSupport::TimeZone[time_zone].nil? ? nil : time_zone }
normalizes :chosen_languages, with: ->(chosen_languages) { chosen_languages.compact_blank.presence }
# This avoids a deprecation warning from Rails 5.1
# It seems possible that a future release of devise-two-factor will
# handle this itself, and this can be removed from our User class.
attribute :otp_secret
has_many :session_activations, dependent: :destroy
delegate :can?, to: :role

View file

@ -0,0 +1,7 @@
.fields-group
= form.input :text,
wrapper: :with_block_label
.fields-group
= form.input :hint,
wrapper: :with_block_label

View file

@ -1,14 +1,10 @@
- content_for :page_title do
= t('admin.rules.edit')
= simple_form_for @rule, url: admin_rule_path(@rule) do |f|
= simple_form_for @rule, url: admin_rule_path(@rule) do |form|
= render 'shared/error_messages', object: @rule
.fields-group
= f.input :text, wrapper: :with_block_label
.fields-group
= f.input :hint, wrapper: :with_block_label
= render form
.actions
= f.button :button, t('generic.save_changes'), type: :submit
= form.button :button, t('generic.save_changes'), type: :submit

View file

@ -6,17 +6,13 @@
%hr.spacer/
- if can? :create, :rule
= simple_form_for @rule, url: admin_rules_path do |f|
= simple_form_for @rule, url: admin_rules_path do |form|
= render 'shared/error_messages', object: @rule
.fields-group
= f.input :text, wrapper: :with_block_label
.fields-group
= f.input :hint, wrapper: :with_block_label
= render form
.actions
= f.button :button, t('admin.rules.add_new'), type: :submit
= form.button :button, t('admin.rules.add_new'), type: :submit
%hr.spacer/

View file

@ -0,0 +1,7 @@
.fields-group
= form.input :title,
wrapper: :with_block_label
.fields-group
= form.input :text,
wrapper: :with_block_label

View file

@ -1,14 +1,10 @@
- content_for :page_title do
= t('admin.warning_presets.edit_preset')
= simple_form_for @warning_preset, url: admin_warning_preset_path(@warning_preset) do |f|
= simple_form_for @warning_preset, url: admin_warning_preset_path(@warning_preset) do |form|
= render 'shared/error_messages', object: @warning_preset
.fields-group
= f.input :title, wrapper: :with_block_label
.fields-group
= f.input :text, wrapper: :with_block_label
= render form
.actions
= f.button :button, t('generic.save_changes'), type: :submit
= form.button :button, t('generic.save_changes'), type: :submit

View file

@ -2,17 +2,13 @@
= t('admin.warning_presets.title')
- if can? :create, :account_warning_preset
= simple_form_for @warning_preset, url: admin_warning_presets_path do |f|
= simple_form_for @warning_preset, url: admin_warning_presets_path do |form|
= render 'shared/error_messages', object: @warning_preset
.fields-group
= f.input :title, wrapper: :with_block_label
.fields-group
= f.input :text, wrapper: :with_block_label
= render form
.actions
= f.button :button, t('admin.warning_presets.add_new'), type: :submit
= form.button :button, t('admin.warning_presets.add_new'), type: :submit
%hr.spacer/

View file

@ -2,6 +2,6 @@
= t('admin.webhooks.edit')
= simple_form_for @webhook, url: admin_webhook_path(@webhook) do |form|
= render partial: 'form', object: form
= render form
.actions
= form.button :button, t('generic.save_changes'), type: :submit

View file

@ -2,6 +2,6 @@
= t('admin.webhooks.new')
= simple_form_for @webhook, url: admin_webhooks_path do |form|
= render partial: 'form', object: form
= render form
.actions
= form.button :button, t('admin.webhooks.add_new'), type: :submit

View file

@ -6,7 +6,7 @@
wrapper: :with_label
.fields-row__column.fields-row__column-6.fields-group
= f.input :expires_in,
collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week, 2.weeks, 1.month, 3.months].map(&:to_i),
collection: CustomFilter::EXPIRATION_DURATIONS.map(&:to_i),
include_blank: I18n.t('invites.expires_in_prompt'),
label_method: ->(i) { I18n.t("invites.expires_in.#{i}") },
wrapper: :with_label