Merge branch 'kb_development' into kb-connect-7.2-to-development

This commit is contained in:
KMY 2023-10-17 08:01:28 +09:00
commit a8cc6c5712
137 changed files with 1644 additions and 1550 deletions

View file

@ -9,7 +9,6 @@ module.exports = {
'plugin:import/recommended',
'plugin:promise/recommended',
'plugin:jsdoc/recommended',
'plugin:prettier/recommended',
],
env: {
@ -63,7 +62,9 @@ module.exports = {
'consistent-return': 'error',
'dot-notation': 'error',
eqeqeq: ['error', 'always', { 'null': 'ignore' }],
'indent': ['error', 2],
'jsx-quotes': ['error', 'prefer-single'],
'semi': ['error', 'always'],
'no-case-declarations': 'off',
'no-catch-shadow': 'error',
'no-console': [

View file

@ -1,13 +1,13 @@
# This configuration was generated by
# `haml-lint --auto-gen-config`
# on 2023-10-03 08:32:28 -0400 using Haml-Lint version 0.51.0.
# on 2023-10-11 11:31:24 -0400 using Haml-Lint version 0.51.0.
# The point is for the user to remove these configuration records
# one by one as the lints are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of Haml-Lint, may require this file to be generated again.
linters:
# Offense count: 944
# Offense count: 946
LineLength:
enabled: false
@ -30,10 +30,6 @@ linters:
# Offense count: 15
InstanceVariables:
exclude:
- 'app/views/admin/reports/_actions.html.haml'
- 'app/views/auth/registrations/_status.html.haml'
- 'app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml'
- 'app/views/relationships/_account.html.haml'
- 'app/views/application/_sidebar.html.haml'
# Offense count: 2

View file

@ -180,7 +180,6 @@ RSpec/LetSetup:
- 'spec/controllers/api/v1/accounts/statuses_controller_spec.rb'
- 'spec/controllers/api/v1/admin/accounts_controller_spec.rb'
- 'spec/controllers/api/v1/filters_controller_spec.rb'
- 'spec/controllers/api/v1/followed_tags_controller_spec.rb'
- 'spec/controllers/api/v2/admin/accounts_controller_spec.rb'
- 'spec/controllers/api/v2/filters/keywords_controller_spec.rb'
- 'spec/controllers/api/v2/filters/statuses_controller_spec.rb'

View file

@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file.
### Fixed
- Fix duplicate reports being sent when reporting some remote posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27355))
- Fix clicking on already-opened thread post scrolling to the top of the thread ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27331), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27338), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27350))
- Fix some remote posts getting truncated ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27307))
- Fix some cases of infinite scroll code trying to fetch inaccessible posts in a loop ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27286))

View file

@ -146,7 +146,7 @@ GEM
net-http-persistent (~> 4.0)
nokogiri (~> 1, >= 1.10.8)
base64 (0.1.1)
bcrypt (3.1.18)
bcrypt (3.1.19)
better_errors (2.10.1)
erubi (>= 1.0.0)
rack (>= 0.9.0)
@ -210,17 +210,17 @@ GEM
database_cleaner-core (2.0.1)
date (3.3.3)
debug_inspector (1.1.0)
devise (4.9.2)
devise (4.9.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
devise-two-factor (4.1.0)
activesupport (< 7.1)
devise-two-factor (4.1.1)
activesupport (~> 7.0)
attr_encrypted (>= 1.3, < 5, != 2)
devise (~> 4.0)
railties (< 7.1)
railties (~> 7.0)
rotp (~> 6.0)
devise_pam_authenticatable2 (9.2.0)
devise (>= 4.0.0)
@ -412,12 +412,12 @@ GEM
llhttp-ffi (0.4.0)
ffi-compiler (~> 1.0)
rake (~> 13.0)
lograge (0.13.0)
lograge (0.14.0)
actionpack (>= 4)
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
loofah (2.21.3)
loofah (2.21.4)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@ -440,7 +440,7 @@ GEM
mime-types-data (3.2023.0808)
mini_mime (1.1.5)
mini_portile2 (2.8.4)
minitest (5.19.0)
minitest (5.20.0)
msgpack (1.7.1)
multi_json (1.15.0)
multipart-post (2.3.0)
@ -493,7 +493,7 @@ GEM
orm_adapter (0.5.0)
ox (2.14.17)
parallel (1.23.0)
parser (3.2.2.3)
parser (3.2.2.4)
ast (~> 2.4.1)
racc
parslet (2.0.0)
@ -554,7 +554,7 @@ GEM
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1)
rails-dom-testing (2.1.1)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
@ -583,10 +583,10 @@ GEM
redis (>= 4)
redlock (1.3.2)
redis (>= 3.0.0, < 6.0)
regexp_parser (2.8.1)
regexp_parser (2.8.2)
request_store (1.5.1)
rack (>= 1.4)
responders (3.1.0)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rexml (3.2.6)
@ -622,12 +622,12 @@ GEM
sidekiq (>= 5, < 8)
rspec-support (3.12.1)
rspec_chunked (0.6)
rubocop (1.56.4)
rubocop (1.57.1)
base64 (~> 0.1.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.2.2.3)
parser (>= 3.2.2.4)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
@ -673,7 +673,7 @@ GEM
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
semantic_range (3.0.0)
sidekiq (6.5.10)
sidekiq (6.5.12)
connection_pool (>= 2.2.5, < 3)
rack (~> 2.0)
redis (>= 4.5.0, < 5)
@ -791,7 +791,7 @@ GEM
xorcist (1.1.3)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.11)
zeitwerk (2.6.12)
PLATFORMS
ruby

View file

@ -5,6 +5,7 @@ module TwoFactorAuthenticationConcern
included do
prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
helper_method :webauthn_enabled?
end
def two_factor_enabled?
@ -87,4 +88,10 @@ module TwoFactorAuthenticationConcern
set_locale { render :two_factor }
end
protected
def webauthn_enabled?
@webauthn_enabled
end
end

View file

@ -56,4 +56,4 @@ export const showAlertForError = (error, skipNotFound = false) => {
title: messages.unexpectedTitle,
message: messages.unexpectedMessage,
});
}
};

View file

@ -213,9 +213,10 @@ export const deleteBookmarkCategoryFail = (id, error) => ({
export const fetchBookmarkCategoryStatuses = bookmarkCategoryId => (dispatch, getState) => {
dispatch(fetchBookmarkCategoryStatusesRequest(bookmarkCategoryId));
api(getState).get(`/api/v1/bookmark_categories/${bookmarkCategoryId}/statuses`, { params: { limit: 0 } }).then(({ data }) => {
dispatch(importFetchedStatuses(data));
dispatch(fetchBookmarkCategoryStatusesSuccess(bookmarkCategoryId, data));
api(getState).get(`/api/v1/bookmark_categories/${bookmarkCategoryId}/statuses`).then((response) => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data));
dispatch(fetchBookmarkCategoryStatusesSuccess(bookmarkCategoryId, response.data, next ? next.uri : null));
}).catch(err => dispatch(fetchBookmarkCategoryStatusesFail(bookmarkCategoryId, err)));
};

View file

@ -290,7 +290,7 @@ export function submitComposeWithCircleSuccess(status, circleId) {
type: COMPOSE_WITH_CIRCLE_SUCCESS,
status,
circleId,
}
};
}
export function submitComposeFail(error) {

View file

@ -121,7 +121,7 @@ export function normalizeStatus(status, normalOldStatus) {
normalStatus.media_attachments.forEach(item => {
const oldItem = list.find(i => i.get('id') === item.id);
if (oldItem && oldItem.get('description') === item.description) {
item.translation = oldItem.get('translation')
item.translation = oldItem.get('translation');
}
});
}
@ -165,13 +165,13 @@ export function normalizePoll(poll, normalOldPoll) {
...option,
voted: poll.own_votes && poll.own_votes.includes(index),
titleHtml: emojify(escapeTextContentForBrowser(option.title), emojiMap),
}
};
if (normalOldPoll && normalOldPoll.getIn(['options', index, 'title']) === option.title) {
normalOption.translation = normalOldPoll.getIn(['options', index, 'translation']);
}
return normalOption
return normalOption;
});
return normalPoll;

View file

@ -184,7 +184,7 @@ class CompactedStatus extends ImmutablePureComponent {
} else if (attachments.getIn([0, 'type']) === 'audio') {
return '16 / 9';
} else {
return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2'
return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2';
}
}

View file

@ -132,7 +132,7 @@ class Poll extends ImmutablePureComponent {
handleReveal = () => {
this.setState({ revealed: true });
}
};
renderOption (option, optionIndex, showResults) {
const { poll, lang, disabled, intl } = this.props;

View file

@ -13,7 +13,7 @@ import AttachmentList from 'mastodon/components/attachment_list';
import { Icon } from 'mastodon/components/icon';
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
import CompactedStatusContainer from '../containers/compacted_status_container'
import CompactedStatusContainer from '../containers/compacted_status_container';
import Card from '../features/status/components/card';
// We use the component (and not the container) since we do not want
// to use the progress bar to show download progress
@ -213,7 +213,7 @@ class Status extends ImmutablePureComponent {
} else if (attachments.getIn([0, 'type']) === 'audio') {
return '16 / 9';
} else {
return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2'
return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2';
}
}
@ -628,7 +628,7 @@ class Status extends ImmutablePureComponent {
const withReference = (!withQuote && status.get('status_references_count') > 0) ? <span className='status__visibility-icon'><Icon id='link' title='Reference' /></span> : null;
const withExpiration = status.get('expires_at') ? <span className='status__visibility-icon'><Icon id='clock-o' title='Expiration' /></span> : null;
const quote = !muted && status.get('quote_id') && (['public', 'community'].includes(contextType) ? showQuoteInPublic : showQuoteInHome) && <CompactedStatusContainer id={status.get('quote_id')} />
const quote = !muted && status.get('quote_id') && (['public', 'community'].includes(contextType) ? showQuoteInPublic : showQuoteInHome) && <CompactedStatusContainer id={status.get('quote_id')} />;
return (
<HotKeys handlers={handlers}>

View file

@ -127,7 +127,7 @@ class About extends PureComponent {
const { multiColumn, intl, server, extendedDescription, domainBlocks } = this.props;
const isLoading = server.get('isLoading');
const fedibirdCapabilities = server.get('fedibird_capabilities');
const fedibirdCapabilities = server.get('fedibird_capabilities') || []; // thinking about isLoading is true
const isPublicUnlistedVisibility = fedibirdCapabilities.includes('kmyblue_visibility_public_unlisted');
const isEmojiReaction = fedibirdCapabilities.includes('emoji_reaction');

View file

@ -167,7 +167,7 @@ class AntennaSetting extends PureComponent {
handleEditAntennaClick = () => {
window.open(`/antennas/${this.props.params.id}/edit`, '_blank');
}
};
handleDeleteClick = () => {
const { dispatch, columnId, intl } = this.props;
@ -193,7 +193,7 @@ class AntennaSetting extends PureComponent {
handleTimelineClick = () => {
this.context.router.history.push(`/antennast/${this.props.params.id}`);
}
};
onStlToggle = ({ target }) => {
const { dispatch } = this.props;
@ -336,7 +336,7 @@ class AntennaSetting extends PureComponent {
</label>
</div>
</>
)
);
}
let stlAlert;
@ -369,7 +369,7 @@ class AntennaSetting extends PureComponent {
const contentRadioAlert = antenna.get(contentRadioValue.get('value') === 'tags' ? 'keywords_count' : 'tags_count') > 0;
const listOptions = lists.toArray().filter((list) => list.length >= 2 && list[1]).map((list) => {
return { value: list[1].get('id'), label: list[1].get('title') }
return { value: list[1].get('id'), label: list[1].get('title') };
});
return (

View file

@ -13,12 +13,12 @@ import { debounce } from 'lodash';
import { deleteBookmarkCategory, expandBookmarkCategoryStatuses, fetchBookmarkCategory, fetchBookmarkCategoryStatuses , setupBookmarkCategoryEditor } from 'mastodon/actions/bookmark_categories';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
import { openModal } from 'mastodon/actions/modal';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
import { Icon } from 'mastodon/components/icon';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import StatusList from 'mastodon/components/status_list';
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
import Column from 'mastodon/features/ui/components/column';
import { getBookmarkCategoryStatusList } from 'mastodon/selectors';
import EditBookmarkCategoryForm from './components/edit_bookmark_category_form';
@ -113,7 +113,7 @@ class BookmarkCategoryStatuses extends ImmutablePureComponent {
};
handleLoadMore = debounce(() => {
this.props.dispatch(expandBookmarkCategoryStatuses());
this.props.dispatch(expandBookmarkCategoryStatuses(this.props.params.id));
}, 300, { leading: true });
render () {

View file

@ -12,9 +12,9 @@ import { debounce } from 'lodash';
import { fetchBookmarkedStatuses, expandBookmarkedStatuses } from 'mastodon/actions/bookmarks';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
import StatusList from 'mastodon/components/status_list';
import Column from 'mastodon/features/ui/components/column';
import { getStatusList } from 'mastodon/selectors';
const messages = defineMessages({

View file

@ -13,12 +13,12 @@ import { debounce } from 'lodash';
import { deleteCircle, expandCircleStatuses, fetchCircle, fetchCircleStatuses } from 'mastodon/actions/circles';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
import { openModal } from 'mastodon/actions/modal';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
import { Icon } from 'mastodon/components/icon';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import StatusList from 'mastodon/components/status_list';
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
import Column from 'mastodon/features/ui/components/column';
import { getCircleStatusList } from 'mastodon/selectors';

View file

@ -20,7 +20,7 @@ export default class NavigationBar extends ImmutablePureComponent {
};
render () {
const username = this.props.account.get('acct')
const username = this.props.account.get('acct');
return (
<div className='navigation-bar'>
<Link to={`/@${username}`}>

View file

@ -57,17 +57,17 @@ class Search extends PureComponent {
};
defaultOptions = [
{ label: <><mark>has:</mark> <FormattedList type='disjunction' value={['media', 'poll', 'embed']} /></>, action: e => { e.preventDefault(); this._insertText('has:') } },
{ label: <><mark>is:</mark> <FormattedList type='disjunction' value={['reply', 'sensitive']} /></>, action: e => { e.preventDefault(); this._insertText('is:') } },
{ label: <><mark>my:</mark> <FormattedList type='disjunction' value={['favourited', 'bookmarked', 'boosted']} /></>, action: e => { e.preventDefault(); this._insertText('my:') } },
{ label: <><mark>language:</mark> <FormattedMessage id='search_popout.language_code' defaultMessage='ISO language code' /></>, action: e => { e.preventDefault(); this._insertText('language:') } },
{ label: <><mark>from:</mark> <FormattedMessage id='search_popout.user' defaultMessage='user' /></>, action: e => { e.preventDefault(); this._insertText('from:') } },
{ label: <><mark>domain:</mark> <FormattedMessage id='search_popout.domain' defaultMessage='domain' /></>, action: e => { e.preventDefault(); this._insertText('domain:') } },
{ label: <><mark>before:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('before:') } },
{ label: <><mark>during:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('during:') } },
{ label: <><mark>after:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('after:') } },
{ label: <><mark>in:</mark> <FormattedList type='disjunction' value={['all', 'library']} /></>, action: e => { e.preventDefault(); this._insertText('in:') } },
{ label: <><mark>order:</mark> <FormattedList type='disjunction' value={['desc', 'asc']} /></>, action: e => { e.preventDefault(); this._insertText('order:') } },
{ label: <><mark>has:</mark> <FormattedList type='disjunction' value={['media', 'poll', 'embed']} /></>, action: e => { e.preventDefault(); this._insertText('has:'); } },
{ label: <><mark>is:</mark> <FormattedList type='disjunction' value={['reply', 'sensitive']} /></>, action: e => { e.preventDefault(); this._insertText('is:'); } },
{ label: <><mark>my:</mark> <FormattedList type='disjunction' value={['favourited', 'bookmarked', 'boosted']} /></>, action: e => { e.preventDefault(); this._insertText('my:'); } },
{ label: <><mark>language:</mark> <FormattedMessage id='search_popout.language_code' defaultMessage='ISO language code' /></>, action: e => { e.preventDefault(); this._insertText('language:'); } },
{ label: <><mark>from:</mark> <FormattedMessage id='search_popout.user' defaultMessage='user' /></>, action: e => { e.preventDefault(); this._insertText('from:'); } },
{ label: <><mark>domain:</mark> <FormattedMessage id='search_popout.domain' defaultMessage='domain' /></>, action: e => { e.preventDefault(); this._insertText('domain:'); } },
{ label: <><mark>before:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('before:'); } },
{ label: <><mark>during:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('during:'); } },
{ label: <><mark>after:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('after:'); } },
{ label: <><mark>in:</mark> <FormattedList type='disjunction' value={['all', 'library']} /></>, action: e => { e.preventDefault(); this._insertText('in:'); } },
{ label: <><mark>order:</mark> <FormattedList type='disjunction' value={['desc', 'asc']} /></>, action: e => { e.preventDefault(); this._insertText('order:'); } },
];
setRef = c => {

View file

@ -12,9 +12,9 @@ import { debounce } from 'lodash';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
import { fetchEmojiReactedStatuses, expandEmojiReactedStatuses } from 'mastodon/actions/emoji_reactions';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
import StatusList from 'mastodon/components/status_list';
import Column from 'mastodon/features/ui/components/column';
const messages = defineMessages({
heading: { id: 'column.emoji_reactions', defaultMessage: 'Stamps' },

View file

@ -80,7 +80,7 @@ class Results extends PureComponent {
}
return null;
};
}
handleSelectAll = () => {
const { submittedType, dispatch } = this.props;
@ -116,7 +116,7 @@ class Results extends PureComponent {
}
this.setState({ type: 'hashtags' });
}
};
handleSelectStatuses = () => {
const { submittedType, dispatch } = this.props;
@ -128,7 +128,7 @@ class Results extends PureComponent {
}
this.setState({ type: 'statuses' });
}
};
handleLoadMoreAccounts = () => this._loadMore('accounts');
handleLoadMoreStatuses = () => this._loadMore('statuses');

View file

@ -12,9 +12,9 @@ import { debounce } from 'lodash';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
import { fetchFavouritedStatuses, expandFavouritedStatuses } from 'mastodon/actions/favourites';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
import StatusList from 'mastodon/components/status_list';
import Column from 'mastodon/features/ui/components/column';
import { getStatusList } from 'mastodon/selectors';
const messages = defineMessages({

View file

@ -199,7 +199,7 @@ const Firehose = ({ feedType, multiColumn }) => {
</Helmet>
</Column>
);
}
};
Firehose.propTypes = {
multiColumn: PropTypes.bool,

View file

@ -187,7 +187,7 @@ class LoginForm extends React.PureComponent {
setIFrameRef = (iframe) => {
this.iframeRef = iframe;
}
};
handleFocus = () => {
this.setState({ expanded: true });

View file

@ -59,7 +59,7 @@ class ReactionEmoji extends ImmutablePureComponent {
const html = { __html: emojify(emoji) };
content = (
<span dangerouslySetInnerHTML={html} />
)
);
}
return (

View file

@ -100,7 +100,7 @@ class ReactionDeck extends ImmutablePureComponent {
const newDeck = this.deckToArray();
newDeck.push('👍');
this.props.onChange(newDeck);
}
};
render () {
const { intl, deck, emojiMap, multiColumn } = this.props;

View file

@ -45,7 +45,7 @@ class Reblogs extends ImmutablePureComponent {
if (!this.props.accountIds) {
this.props.dispatch(fetchReblogs(this.props.params.statusId));
}
};
}
handleRefresh = () => {
this.props.dispatch(fetchReblogs(this.props.params.statusId));

View file

@ -104,7 +104,7 @@ const Comment = ({ comment, domain, statusIds, isRemote, isSubmitting, selectedD
</div>
</>
);
}
};
Comment.propTypes = {
comment: PropTypes.string.isRequired,

View file

@ -147,7 +147,7 @@ class DetailedStatus extends ImmutablePureComponent {
} else if (attachments.getIn([0, 'type']) === 'audio') {
return '16 / 9';
} else {
return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2'
return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2';
}
}

View file

@ -84,7 +84,7 @@ class Header extends PureComponent {
if (sso_redirect) {
content = (
<a href={sso_redirect} data-method='post' className='button button--block button-tertiary'><FormattedMessage id='sign_in_banner.sso_redirect' defaultMessage='Login or Register' /></a>
)
);
} else {
let signupButton;

View file

@ -127,7 +127,7 @@ export default class ModalRoot extends PureComponent {
<BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}>
{(SpecificComponent) => {
const ref = typeof SpecificComponent !== 'function' ? this.setModalRef : undefined;
return <SpecificComponent {...props} onChangeBackgroundColor={this.setBackgroundColor} onClose={this.handleClose} ref={ref} />
return <SpecificComponent {...props} onChangeBackgroundColor={this.setBackgroundColor} onClose={this.handleClose} ref={ref} />;
}}
</BundleContainer>

View file

@ -25,7 +25,7 @@ const SignInBanner = () => {
<p><FormattedMessage id='sign_in_banner.text' defaultMessage='Login to follow profiles or hashtags, favorite, share and reply to posts. You can also interact from your account on a different server.' /></p>
<a href={sso_redirect} data-method='post' className='button button--block button-tertiary'><FormattedMessage id='sign_in_banner.sso_redirect' defaultMessage='Login or Register' /></a>
</div>
)
);
}
if (registrationsOpen) {

View file

@ -1,6 +1,6 @@
{
"about.blocks": "Valvotut palvelimet",
"about.contact": "Yhteydenotto:",
"about.contact": "Ota yhteyttä:",
"about.disclaimer": "Mastodon on vapaa avoimen lähdekoodin ohjelmisto ja Mastodon gGmbH:n tavaramerkki.",
"about.domain_blocks.no_reason_available": "Syytä ei ole ilmoitettu",
"about.domain_blocks.preamble": "Mastodonin avulla voidaan yleensä tarkastella minkä tahansa fediversumiin kuuluvan palvelimen sisältöä ja vuorovaikuttaa eri palvelinten käyttäjien kanssa. Nämä ovat tälle palvelimelle määritetyt poikkeukset.",
@ -26,15 +26,15 @@
"account.domain_blocked": "Verkkotunnus estetty",
"account.edit_profile": "Muokkaa profiilia",
"account.enable_notifications": "Ilmoita minulle, kun @{name} julkaisee",
"account.endorse": "Suosittele profiilissasi",
"account.endorse": "Pidä esillä profiilissa",
"account.featured_tags.last_status_at": "Viimeisin julkaisu {date}",
"account.featured_tags.last_status_never": "Ei julkaisuja",
"account.featured_tags.title": "Käyttäjän {name} esille nostetut aihetunnisteet",
"account.featured_tags.title": "Käyttäjän {name} esillä pidettävät aihetunnisteet",
"account.follow": "Seuraa",
"account.followers": "seuraaja(t)",
"account.followers": "Seuraajat",
"account.followers.empty": "Kukaan ei seuraa tätä käyttäjää vielä.",
"account.followers_counter": "{count, plural, one {{counter} seuraaja} other {{counter} seuraajaa}}",
"account.following": "Seurataan",
"account.following": "Seuratut",
"account.following_counter": "{count, plural, one {{counter} seurattu} other {{counter} seurattua}}",
"account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.",
"account.follows_you": "Seuraa sinua",
@ -62,10 +62,10 @@
"account.share": "Jaa käyttäjän @{name} profiili",
"account.show_reblogs": "Näytä käyttäjän @{name} tehostukset",
"account.statuses_counter": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}",
"account.unblock": "Poista esto: @{name}",
"account.unblock_domain": "Salli palvelu {domain}",
"account.unblock": "Poista käyttäjän @{name} esto",
"account.unblock_domain": "Poista verkkotunnuksen {domain} esto",
"account.unblock_short": "Poista esto",
"account.unendorse": "Poista suosittelu profiilistasi",
"account.unendorse": "Älä pidä esillä profiilissa",
"account.unfollow": "Lopeta seuraaminen",
"account.unmute": "Poista käyttäjän @{name} mykistys",
"account.unmute_notifications_short": "Poista ilmoitusten mykistys",
@ -194,7 +194,7 @@
"copypaste.copied": "Kopioitu",
"copypaste.copy_to_clipboard": "Kopioi leikepöydälle",
"directory.federated": "Koko tunnettu fediversumi",
"directory.local": "Vain palvelusta {domain}",
"directory.local": "Vain palvelimelta {domain}",
"directory.new_arrivals": "Äskettäin saapuneet",
"directory.recently_active": "Hiljattain aktiiviset",
"disabled_account_banner.account_settings": "Tilin asetukset",
@ -225,12 +225,12 @@
"empty_column.account_suspended": "Tili jäädytetty",
"empty_column.account_timeline": "Ei viestejä täällä.",
"empty_column.account_unavailable": "Profiilia ei löydy",
"empty_column.blocks": "Et ole estänyt käyttäjiä.",
"empty_column.blocks": "Et ole vielä estänyt käyttäjiä.",
"empty_column.bookmarked_statuses": "Et ole vielä lisännyt julkaisuja kirjanmerkkeihisi. Kun lisäät yhden, se näkyy tässä.",
"empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista, niin homma lähtee käyntiin!",
"empty_column.direct": "Yksityisiä mainintoja ei vielä ole. Jos lähetät tai sinulle lähetetään sellaisia, näet ne täällä.",
"empty_column.domain_blocks": "Palveluita ei ole vielä estetty.",
"empty_column.explore_statuses": "Mikään ei trendaa nyt. Tarkista myöhemmin uudelleen!",
"empty_column.domain_blocks": "Verkkotunnuksia ei ole vielä estetty.",
"empty_column.explore_statuses": "Mikään ei ole nyt suosittua. Tarkista myöhemmin uudelleen!",
"empty_column.favourited_statuses": "Sinulla ei ole vielä yhtään suosikkijulkaisua. Kun lisäät sellaisen, näkyy se tässä.",
"empty_column.favourites": "Kukaan ei ole vielä lisännyt tätä julkaisua suosikkeihinsa. Kun joku tekee niin, tulee hän tähän näkyviin.",
"empty_column.follow_requests": "Et ole vielä vastaanottanut seuraamispyyntöjä. Saamasi pyynnöt näkyvät täällä.",
@ -266,7 +266,7 @@
"filter_modal.select_filter.context_mismatch": "ei sovellu tähän kontekstiin",
"filter_modal.select_filter.expired": "vanhentunut",
"filter_modal.select_filter.prompt_new": "Uusi luokka: {name}",
"filter_modal.select_filter.search": "Etsi tai luo",
"filter_modal.select_filter.search": "Hae tai luo",
"filter_modal.select_filter.subtitle": "Käytä olemassa olevaa luokkaa tai luo uusi",
"filter_modal.select_filter.title": "Suodata tämä julkaisu",
"filter_modal.title.status": "Suodata julkaisu",
@ -336,9 +336,9 @@
"keyboard_shortcuts.blocked": "Avaa estettyjen käyttäjien luettelo",
"keyboard_shortcuts.boost": "Tehosta julkaisua",
"keyboard_shortcuts.column": "Kohdista sarakkeeseen",
"keyboard_shortcuts.compose": "siirry tekstinsyöttöön",
"keyboard_shortcuts.compose": "Kohdista kirjoituskenttään",
"keyboard_shortcuts.description": "Kuvaus",
"keyboard_shortcuts.direct": "avataksesi yksityisten mainintojen sarakkeen",
"keyboard_shortcuts.direct": "Avaa yksityisten mainintojen sarake",
"keyboard_shortcuts.down": "Siirry listassa alaspäin",
"keyboard_shortcuts.enter": "Avaa julkaisu",
"keyboard_shortcuts.favourite": "Lisää julkaisu suosikkeihin",
@ -347,22 +347,22 @@
"keyboard_shortcuts.heading": "Pikanäppäimet",
"keyboard_shortcuts.home": "Avaa kotiaikajana",
"keyboard_shortcuts.hotkey": "Pikanäppäin",
"keyboard_shortcuts.legend": "Näytä tämä selite",
"keyboard_shortcuts.legend": "Näytä tämä ohje",
"keyboard_shortcuts.local": "Avaa paikallinen aikajana",
"keyboard_shortcuts.mention": "Mainitse julkaisija",
"keyboard_shortcuts.muted": "Avaa lista mykistetyistä käyttäjistä",
"keyboard_shortcuts.mention": "Mainitse kirjoittaja",
"keyboard_shortcuts.muted": "Avaa mykistettyjen käyttäjien luettelo",
"keyboard_shortcuts.my_profile": "Avaa profiilisi",
"keyboard_shortcuts.notifications": "Avaa ilmoitukset-valikko",
"keyboard_shortcuts.notifications": "Avaa ilmoitussarake",
"keyboard_shortcuts.open_media": "Avaa media",
"keyboard_shortcuts.pinned": "Avaa kiinnitettyjen julkaisujen luettelo",
"keyboard_shortcuts.profile": "Avaa kirjoittajan profiili",
"keyboard_shortcuts.reply": "Vastaa julkaisuun",
"keyboard_shortcuts.requests": "Avaa seuraamispyyntöjen luettelo",
"keyboard_shortcuts.search": "siirry hakukenttään",
"keyboard_shortcuts.search": "Kohdista hakukenttään",
"keyboard_shortcuts.spoilers": "Näytä/piilota sisältövaroituskenttä",
"keyboard_shortcuts.start": "avaa \"Aloitus\"",
"keyboard_shortcuts.toggle_hidden": "näytä/piilota sisältövaroituksella merkitty teksti",
"keyboard_shortcuts.toggle_sensitivity": "näytä/piilota media",
"keyboard_shortcuts.start": "Avaa Näin pääset alkuun -sarake",
"keyboard_shortcuts.toggle_hidden": "Näytä/piilota sisältövaroituksella merkitty teksti",
"keyboard_shortcuts.toggle_sensitivity": "Näytä/piilota media",
"keyboard_shortcuts.toot": "Luo uusi julkaisu",
"keyboard_shortcuts.unfocus": "Poistu teksti-/hakukentästä",
"keyboard_shortcuts.up": "Siirry listassa ylöspäin",
@ -414,12 +414,12 @@
"navigation_bar.lists": "Listat",
"navigation_bar.logout": "Kirjaudu ulos",
"navigation_bar.mutes": "Mykistetyt käyttäjät",
"navigation_bar.opened_in_classic_interface": "Julkaisut, profiilit ja tietyt muut sivut avautuvat oletuksena perinteiseen web-käyttöliittymään.",
"navigation_bar.opened_in_classic_interface": "Julkaisut, profiilit ja tietyt muut sivut avautuvat oletuksena perinteiseen selainkäyttöliittymään.",
"navigation_bar.personal": "Henkilökohtainen",
"navigation_bar.pins": "Kiinnitetyt julkaisut",
"navigation_bar.preferences": "Asetukset",
"navigation_bar.public_timeline": "Yleinen aikajana",
"navigation_bar.search": "Haku",
"navigation_bar.search": "Hae",
"navigation_bar.security": "Turvallisuus",
"not_signed_in_indicator.not_signed_in": "Sinun on kirjauduttava sisään käyttääksesi resurssia.",
"notification.admin.report": "{name} teki ilmoituksen käytäjästä {target}",
@ -472,14 +472,14 @@
"notifications_permission_banner.title": "Älä anna minkään mennä ohi",
"onboarding.action.back": "Palaa takaisin",
"onboarding.actions.back": "Palaa takaisin",
"onboarding.actions.go_to_explore": "Siirry suosituimpien aiheiden syötteeseen",
"onboarding.actions.go_to_explore": "Siirry suosittujen aiheiden syötteeseen",
"onboarding.actions.go_to_home": "Siirry kotisyötteeseeni",
"onboarding.compose.template": "Tervehdys #Mastodon!",
"onboarding.follows.empty": "Valitettavasti tuloksia ei voida näyttää juuri nyt. Voit kokeilla hakua tai selata tutustumissivua löytääksesi seurattavaa, tai yrittää myöhemmin uudelleen.",
"onboarding.follows.empty": "Valitettavasti tuloksia ei voida näyttää juuri nyt. Voit kokeilla hakua tai selata tutustumissivua löytääksesi seurattavaa tai yrittää myöhemmin uudelleen.",
"onboarding.follows.lead": "Kokoat oman kotisyötteesi itse. Mitä enemmän ihmisiä seuraat, sitä aktiivisempi ja kiinnostavampi syöte on. Nämä profiilit voivat olla alkuun hyvä lähtökohta — voit aina lopettaa niiden seuraamisen myöhemmin!",
"onboarding.follows.title": "Mukauta kotisyötettäsi",
"onboarding.share.lead": "Kerro ihmisille, kuinka he voivat löytää sinut Mastodonista!",
"onboarding.share.message": "Olen {username} #Mastodon'issa! Seuraa minua osoitteessa {url}",
"onboarding.share.message": "Olen {username} #Mastodonissa! Seuraa minua osoitteessa {url}",
"onboarding.share.next_steps": "Mahdolliset seuraavat vaiheet:",
"onboarding.share.title": "Jaa profiilisi",
"onboarding.start.lead": "Uusi Mastodon-tilisi on nyt valmiina käyttöön. Kyseessä on ainutlaatuinen, hajautettu sosiaalisen median alusta, jolla sinä itse algoritmin sijaan määrität käyttökokemuksesi. Näin hyödyt Mastodonista eniten:",
@ -537,7 +537,7 @@
"relative_time.today": "tänään",
"reply_indicator.cancel": "Peruuta",
"report.block": "Estä",
"report.block_explanation": "Et näe hänen viestejään, eikä hän voi nähdä viestejäsi tai seurata sinua. Hän näkevät, että olet estänyt hänet.",
"report.block_explanation": "Et näe hänen viestejään, eikä hän voi nähdä viestejäsi tai seurata sinua. Hän näkee, että olet estänyt hänet.",
"report.categories.legal": "Lakiasiat",
"report.categories.other": "Muu",
"report.categories.spam": "Roskaposti",
@ -584,17 +584,17 @@
"report_notification.open": "Avaa raportti",
"search.no_recent_searches": "Ei viimeaikaisia hakuja",
"search.placeholder": "Hae",
"search.quick_action.account_search": "Profiilit, jotka vastaavat hakua {x}",
"search.quick_action.go_to_account": "Avaa profiili {x}",
"search.quick_action.account_search": "Profiilit haulla {x}",
"search.quick_action.go_to_account": "Siirry profiiliin {x}",
"search.quick_action.go_to_hashtag": "Siirry aihetunnisteeseen {x}",
"search.quick_action.open_url": "Avaa URL-osoite Mastodonissa",
"search.quick_action.status_search": "Julkaisut haulla {x}",
"search.search_or_paste": "Etsi tai kirjoita URL-osoite",
"search.search_or_paste": "Hae tai kirjoita URL-osoite",
"search_popout.full_text_search_disabled_message": "Ei saatavilla palvelimella {domain}.",
"search_popout.language_code": "ISO-kielikoodi",
"search_popout.options": "Haun asetukset",
"search_popout.quick_actions": "Pikatoiminnot",
"search_popout.recent": "Viime haut",
"search_popout.recent": "Viimeaikaiset haut",
"search_popout.specific_date": "tietty päivämäärä",
"search_popout.user": "käyttäjä",
"search_results.accounts": "Profiilit",
@ -637,7 +637,7 @@
"status.history.created": "{name} luotu {date}",
"status.history.edited": "{name} muokkasi {date}",
"status.load_more": "Lataa lisää",
"status.media.open": "Napsauta avataksesi",
"status.media.open": "Avaa napsauttamalla",
"status.media.show": "Napsauta näyttääksesi",
"status.media_hidden": "Media piilotettu",
"status.mention": "Mainitse @{name}",
@ -654,7 +654,7 @@
"status.reblogs.empty": "Kukaan ei ole vielä tehostanut tätä julkaisua. Kun joku tekee niin, tulee hän tähän näkyviin.",
"status.redraft": "Poista ja palauta muokattavaksi",
"status.remove_bookmark": "Poista kirjanmerkki",
"status.replied_to": "Vastattu {name}",
"status.replied_to": "Vastaus käyttäjälle {name}",
"status.reply": "Vastaa",
"status.replyAll": "Vastaa ketjuun",
"status.report": "Raportoi @{name}",
@ -694,7 +694,7 @@
"units.short.thousand": "{count} t.",
"upload_area.title": "Lataa raahaamalla ja pudottamalla tähän",
"upload_button.label": "Lisää kuvia, video tai äänitiedosto",
"upload_error.limit": "Tiedostolatauksien raja ylitetty.",
"upload_error.limit": "Tiedostolatauksien rajoitus ylitetty.",
"upload_error.poll": "Tiedoston lataaminen ei ole sallittua äänestyksissä.",
"upload_form.audio_description": "Kuvaile sisältöä kuuroille ja kuulorajoitteisille",
"upload_form.description": "Kuvaile sisältöä sokeille ja näkörajoitteisille",
@ -715,7 +715,7 @@
"upload_modal.preview_label": "Esikatselu ({ratio})",
"upload_progress.label": "Ladataan...",
"upload_progress.processing": "Käsitellään…",
"username.taken": "Käyttäjätunnus on jo varattu. Kokeile toista",
"username.taken": "Käyttäjänimi on jo varattu. Kokeile toista",
"video.close": "Sulje video",
"video.download": "Lataa tiedosto",
"video.exit_fullscreen": "Poistu koko näytön tilasta",

View file

@ -7,7 +7,7 @@
"about.domain_blocks.silenced.explanation": "San fharsaingeachd, chan fhaic thu pròifilean agus susbaint an fhrithealaiche seo ach ma nì thu lorg no ma tha thu ga leantainn.",
"about.domain_blocks.silenced.title": "Cuingichte",
"about.domain_blocks.suspended.explanation": "Cha dèid dàta sam bith on fhrithealaiche seo a phròiseasadh, a stòradh no iomlaid agus chan urrainn do na cleachdaichean on fhrithealaiche sin conaltradh no eadar-ghnìomh a ghabhail an-seo.",
"about.domain_blocks.suspended.title": "Na dhàil",
"about.domain_blocks.suspended.title": "À rèim",
"about.not_available": "Cha deach am fiosrachadh seo a sholar air an fhrithealaiche seo.",
"about.powered_by": "Lìonra sòisealta sgaoilte le cumhachd {mastodon}",
"about.rules": "Riaghailtean an fhrithealaiche",

View file

@ -340,7 +340,7 @@
"errors.unexpected_crash.report_issue": "問題を報告",
"explore.search_results": "検索結果",
"explore.suggested_follows": "ユーザー",
"explore.title": "エクスプローラー",
"explore.title": "探索する",
"explore.trending_links": "ニュース",
"explore.trending_statuses": "投稿",
"explore.trending_tags": "ハッシュタグ",

View file

@ -65,6 +65,7 @@
"account.unendorse": "Mostrar pas pel perfil",
"account.unfollow": "Quitar de sègre",
"account.unmute": "Quitar de rescondre @{name}",
"account.unmute_notifications_short": "Restablir las notificacions",
"account.unmute_short": "Tornar afichar",
"account_note.placeholder": "Clicar per ajustar una nòta",
"admin.dashboard.retention.average": "Mejana",
@ -97,6 +98,8 @@
"column.direct": "Mencions privadas",
"column.directory": "Percórrer los perfils",
"column.domain_blocks": "Domenis resconduts",
"column.favourites": "Favorits",
"column.firehose": "Tuts en dirèct",
"column.follow_requests": "Demandas dabonament",
"column.home": "Acuèlh",
"column.lists": "Listas",
@ -117,6 +120,7 @@
"community.column_settings.remote_only": "Sonque alonhat",
"compose.language.change": "Cambiar de lenga",
"compose.language.search": "Recercar de lengas...",
"compose.published.body": "Tut publicat.",
"compose.published.open": "Dobrir",
"compose.saved.body": "Publicacion enregistrada.",
"compose_form.direct_message_warning_learn_more": "Ne saber mai",
@ -170,6 +174,7 @@
"conversation.open": "Veire la conversacion",
"conversation.with": "Amb {names}",
"copypaste.copied": "Copiat",
"copypaste.copy_to_clipboard": "Copiar al quichapapièr",
"directory.federated": "Del fediverse conegut",
"directory.local": "Solament de {domain}",
"directory.new_arrivals": "Nòus-venguts",
@ -220,6 +225,7 @@
"errors.unexpected_crash.copy_stacktrace": "Copiar las traças al quichapapièrs",
"errors.unexpected_crash.report_issue": "Senhalar un problèma",
"explore.search_results": "Resultats de recèrca",
"explore.suggested_follows": "Personas",
"explore.title": "Explorar",
"explore.trending_links": "Novèlas",
"explore.trending_statuses": "Publicacions",
@ -234,6 +240,7 @@
"filter_modal.select_filter.search": "Cercar o crear",
"filter_modal.select_filter.title": "Filtrar aquesta publicacion",
"filter_modal.title.status": "Filtrar una publicacion",
"firehose.local": "Aqueste servidor",
"follow_request.authorize": "Acceptar",
"follow_request.reject": "Regetar",
"follow_requests.unlocked_explanation": "Encara que vòstre compte siasque pas verrolhat, la còla de {domain} pensèt que volriatz benlèu repassar las demandas dabonament daquestes comptes.",
@ -257,12 +264,19 @@
"hashtag.column_settings.tag_mode.any": "Un daquestes",
"hashtag.column_settings.tag_mode.none": "Cap daquestes",
"hashtag.column_settings.tag_toggle": "Inclure las etiquetas suplementàrias dins aquesta colomna",
"hashtag.counter_by_accounts": "{count, plural, one {{counter} participant} other {{counter} participants}}",
"hashtag.counter_by_uses": "{count, plural, one {{counter} tut} other {{counter} tuts}}",
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} tut} other {{counter} tuts}} uèi",
"hashtag.follow": "Sègre letiqueta",
"hashtag.unfollow": "Quitar de sègre letiqueta",
"hashtags.and_other": "…e {count, plural, one {}other {# de mai}}",
"home.actions.go_to_explore": "Agachatz las tendéncias",
"home.actions.go_to_suggestions": "Trobatz de monde de sègre",
"home.column_settings.basic": "Basic",
"home.column_settings.show_reblogs": "Mostrar los partatges",
"home.column_settings.show_replies": "Mostrar las responsas",
"home.hide_announcements": "Rescondre las anóncias",
"home.pending_critical_update.link": "Veire las mesas a jorn",
"home.show_announcements": "Mostrar las anóncias",
"interaction_modal.on_another_server": "Sus un autre servidor",
"interaction_modal.on_this_server": "Sus aqueste servidor",
@ -332,14 +346,17 @@
"mute_modal.hide_notifications": "Rescondre las notificacions daquesta persona?",
"mute_modal.indefinite": "Cap de data de fin",
"navigation_bar.about": "A prepaus",
"navigation_bar.advanced_interface": "Dobrir linterfàcia web avançada",
"navigation_bar.blocks": "Personas blocadas",
"navigation_bar.bookmarks": "Marcadors",
"navigation_bar.community_timeline": "Flux public local",
"navigation_bar.compose": "Escriure un nòu tut",
"navigation_bar.direct": "Mencions privadas",
"navigation_bar.discover": "Trobar",
"navigation_bar.domain_blocks": "Domenis resconduts",
"navigation_bar.edit_profile": "Modificar lo perfil",
"navigation_bar.explore": "Explorar",
"navigation_bar.favourites": "Favorits",
"navigation_bar.filters": "Mots ignorats",
"navigation_bar.follow_requests": "Demandas dabonament",
"navigation_bar.followed_tags": "Etiquetas seguidas",
@ -369,6 +386,7 @@
"notifications.column_settings.admin.report": "Senhalaments novèls:",
"notifications.column_settings.admin.sign_up": "Nòus inscrits:",
"notifications.column_settings.alert": "Notificacions localas",
"notifications.column_settings.favourite": "Favorits :",
"notifications.column_settings.filter_bar.advanced": "Mostrar totas las categorias",
"notifications.column_settings.filter_bar.category": "Barra de recèrca rapida",
"notifications.column_settings.filter_bar.show_bar": "Afichar la barra de filtres",
@ -386,6 +404,7 @@
"notifications.column_settings.update": "Modificacions:",
"notifications.filter.all": "Totas",
"notifications.filter.boosts": "Partages",
"notifications.filter.favourites": "Favorits",
"notifications.filter.follows": "Seguiments",
"notifications.filter.mentions": "Mencions",
"notifications.filter.polls": "Resultats del sondatge",
@ -399,15 +418,21 @@
"notifications_permission_banner.enable": "Activar las notificacions burèu",
"notifications_permission_banner.how_to_control": "Per recebre las notificacions de Mastodon quand es pas dobèrt, activatz las notificacions de burèu. Podètz precisar quin tipe de notificacion generarà una notificacion de burèu via lo boton {icon} dessús un còp activadas.",
"notifications_permission_banner.title": "Manquetz pas jamai res",
"onboarding.action.back": "Tornar en rèire",
"onboarding.actions.back": "Tornar en rèire",
"onboarding.actions.go_to_explore": "See what's trending",
"onboarding.actions.go_to_home": "Go to your home feed",
"onboarding.compose.template": "Adiu #Mastodon !",
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
"onboarding.follows.title": "Popular on Mastodon",
"onboarding.share.title": "Partejar vòstre perfil",
"onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:",
"onboarding.start.skip": "Want to skip right ahead?",
"onboarding.start.title": "Tot es prèst !",
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
"onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}",
"onboarding.steps.publish_status.body": "Say hello to the world.",
"onboarding.steps.publish_status.title": "Escrivètz vòstre primièr tut",
"onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.",
"onboarding.steps.setup_profile.title": "Customize your profile",
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!",
@ -415,6 +440,7 @@
"picture_in_picture.restore": "Lo tornar",
"poll.closed": "Tampat",
"poll.refresh": "Actualizar",
"poll.reveal": "Veire los resultats",
"poll.total_people": "{count, plural, one {# persona} other {# personas}}",
"poll.total_votes": "{count, plural, one {# vòte} other {# vòtes}}",
"poll.vote": "Votar",
@ -482,11 +508,17 @@
"report_notification.open": "Dobrir lo senhalament",
"search.placeholder": "Recercar",
"search.search_or_paste": "Recercar o picar una URL",
"search_popout.language_code": "Còdi ISO de lenga",
"search_popout.options": "Opcions de recèrca",
"search_popout.quick_actions": "Accions rapidas",
"search_popout.recent": "Recèrcas recentas",
"search_popout.specific_date": "data especifica",
"search_popout.user": "utilizaire",
"search_results.accounts": "Perfils",
"search_results.all": "Tot",
"search_results.hashtags": "Etiquetas",
"search_results.nothing_found": "Cap de resultat per aquestes tèrmes de recèrca",
"search_results.see_all": "O veire tot",
"search_results.statuses": "Tuts",
"search_results.title": "Recèrca: {q}",
"server_banner.active_users": "utilizaires actius",
@ -506,16 +538,20 @@
"status.copy": "Copiar lo ligam de lestatut",
"status.delete": "Escafar",
"status.detailed_status": "Vista detalhada de la convèrsa",
"status.direct_indicator": "Mencion privada",
"status.edit": "Modificar",
"status.edited": "Modificat {date}",
"status.edited_x_times": "Modificat {count, plural, un {{count} còp} other {{count} còps}}",
"status.embed": "Embarcar",
"status.favourite": "Apondre als favorits",
"status.filter": "Filtrar aquesta publicacion",
"status.filtered": "Filtrat",
"status.hide": "Amagar la publicacion",
"status.history.created": "{name} o creèt lo {date}",
"status.history.edited": "{name} o modifiquèt lo {date}",
"status.load_more": "Cargar mai",
"status.media.open": "Clicar per dobrir",
"status.media.show": "Clicar per mostar",
"status.media_hidden": "Mèdia rescondut",
"status.mention": "Mencionar",
"status.more": "Mai",
@ -546,6 +582,7 @@
"status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}",
"status.translate": "Traduire",
"status.translated_from_with": "Traduch del {lang} amb {provider}",
"status.uncached_media_warning": "Apercebut indisponible",
"status.unmute_conversation": "Tornar mostrar la conversacion",
"status.unpin": "Tirar del perfil",
"subscribed_languages.lead": "Sonque las publicacions dins las lengas seleccionadas apreissaràn dins vòstre acuèlh e linha cronologica aprèp aqueste cambiament. Seleccionatz pas res per recebre las publicacions en quina lenga que siá.",

View file

@ -218,7 +218,10 @@
"home.hide_announcements": "නිවේදන සඟවන්න",
"home.pending_critical_update.link": "යාවත්කාල බලන්න",
"home.show_announcements": "නිවේදන පෙන්වන්න",
"interaction_modal.login.action": "මුලට ගෙනයන්න",
"interaction_modal.on_this_server": "මෙම සේවාදායකයෙහි",
"interaction_modal.title.favourite": "{name}ගේ ලිපිය ප්‍රිය කරන්න",
"interaction_modal.title.follow": "{name} අනුගමනය",
"intervals.full.days": "{number, plural, one {දවස් #} other {දවස් #}}",
"intervals.full.hours": "{number, plural, one {පැය #} other {පැය #}}",
"intervals.full.minutes": "{number, plural, one {විනාඩි #} other {විනාඩි #}}",
@ -319,6 +322,7 @@
"notifications.mark_as_read": "සියළු දැනුම්දීම් කියවූ බව යොදන්න",
"notifications_permission_banner.enable": "වැඩතල දැනුම්දීම් සබල කරන්න",
"notifications_permission_banner.title": "කිසිවක් අතපසු නොකරන්න",
"onboarding.actions.go_to_explore": "නැගී එන දෑ වෙත ගෙනයන්න",
"onboarding.compose.template": "ආයුබෝ #මාස්ටඩන්!",
"onboarding.share.title": "ඔබගේ පැතිකඩ බෙදාගන්න",
"onboarding.steps.publish_status.title": "පළමු ලිපිය පළ කරන්න",
@ -358,6 +362,7 @@
"report.categories.other": "වෙනත්",
"report.categories.spam": "ආයාචිත",
"report.categories.violation": "අන්තර්ගතය නිසා සේවාදායකයේ නීතියක් හෝ කිහිපයක් කඩ වේ",
"report.category.subtitle": "හොඳම ගැලපීම තෝරන්න",
"report.category.title": "මෙම {type}සමඟ සිදුවන්නේ කුමක්දැයි අපට කියන්න",
"report.category.title_account": "පැතිකඩ",
"report.category.title_status": "ලිපිය",
@ -394,14 +399,25 @@
"report_notification.categories.spam": "ආයාචිත",
"report_notification.categories.violation": "නීතිය කඩ කිරීම",
"report_notification.open": "විවෘත වාර්තාව",
"search.no_recent_searches": "මෑත සෙවීම් නැත",
"search.placeholder": "සොයන්න",
"search.quick_action.account_search": "ගැළපෙන පැතිකඩ {x}",
"search.quick_action.go_to_account": "{x} පැතිකඩ වෙත යන්න",
"search.quick_action.open_url": "ලිපිනය මාස්ටඩන්හි අරින්න",
"search.quick_action.status_search": "ගැළපෙන ලිපි {x}",
"search.search_or_paste": "සොයන්න හෝ ඒ.ස.නි. අලවන්න",
"search_popout.options": "සෙවුම් විකල්ප",
"search_popout.quick_actions": "ඉක්මන් ක්‍රියාමාර්ග",
"search_popout.recent": "මෑත සෙවීම්",
"search_popout.specific_date": "නිශ්චිත දිනයකට",
"search_popout.user": "පරිශ්‍රීලකයා",
"search_results.accounts": "පැතිකඩ",
"search_results.all": "සියල්ල",
"search_results.nothing_found": "මෙම සෙවුම් පද සඳහා කිසිවක් සොයාගත නොහැකි විය",
"search_results.see_all": "සියල්ල බලන්න",
"search_results.statuses": "ලිපි",
"search_results.title": "{q} සොයන්න",
"server_banner.active_users": "සක්‍රිය පරිශ්‍රීලකයින්",
"server_banner.learn_more": "තව දැනගන්න",
"sign_in_banner.create_account": "ගිණුමක් සාදන්න",
"sign_in_banner.sign_in": "පිවිසෙන්න",

View file

@ -409,7 +409,7 @@
"navigation_bar.favourites": "最愛",
"navigation_bar.filters": "已靜音的關鍵字",
"navigation_bar.follow_requests": "跟隨請求",
"navigation_bar.followed_tags": "已跟隨主題標籤",
"navigation_bar.followed_tags": "已跟隨主題標籤",
"navigation_bar.follows_and_followers": "跟隨中與跟隨者",
"navigation_bar.lists": "列表",
"navigation_bar.logout": "登出",

View file

@ -83,7 +83,7 @@ const prependToCircleStatusById = (state, circleId, statusId) => {
map.updateIn(['statuses', 'items'], list => ImmutableOrderedSet([statusId]).union(list));
}
}));
}
};
export default function circles(state = initialState, action) {
switch(action.type) {

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';

View file

@ -631,12 +631,10 @@ class Status < ApplicationRecord
self.searchability = if %w(public public_unlisted login unlisted).include?(visibility)
searchability
elsif visibility == 'limited'
:limited
elsif visibility == 'limited' || visibility == 'direct'
searchability == 'limited' ? :limited : :direct
elsif visibility == 'private'
searchability == 'public' || searchability == 'public_unlisted' ? :private : searchability
elsif visibility == 'direct'
searchability == 'limited' ? :limited : :direct
else
:direct
end

View file

@ -16,11 +16,18 @@ class ManifestSerializer < ActiveModel::Serializer
512
).freeze
attributes :name, :short_name,
attributes :id, :name, :short_name,
:icons, :theme_color, :background_color,
:display, :start_url, :scope,
:share_target, :shortcuts
def id
# This is set to `/home` because that was the old value of `start_url` and
# thus the fallback ID computed by Chrome:
# https://developer.chrome.com/blog/pwa-manifest-id/
'/home'
end
def name
object.title
end
@ -53,7 +60,7 @@ class ManifestSerializer < ActiveModel::Serializer
end
def start_url
'/home'
'/'
end
def scope

View file

@ -5,7 +5,7 @@ class REST::Admin::DomainBlockSerializer < ActiveModel::Serializer
:reject_media, :reject_favourite, :reject_reply, :reject_reports,
:reject_send_not_public_searchability, :reject_reply_exclude_followers,
:reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive,
:reject_hashtag, :reject_straight_follow, :reject_new_follow, :detect_invalid_subscription,
:reject_hashtag, :reject_straight_follow, :reject_new_follow, :reject_friend, :detect_invalid_subscription,
:private_comment, :public_comment, :obfuscate
def id

View file

@ -38,7 +38,13 @@ class UpdateAccountService < BaseService
end
def check_links(account)
VerifyAccountLinksWorker.perform_async(account.id) if account.fields.any?(&:requires_verification?)
return unless account.fields.any?(&:requires_verification?)
if account.local?
VerifyAccountLinksWorker.perform_async(account.id)
else
VerifyAccountLinksWorker.perform_in(rand(10.minutes.to_i), account.id)
end
end
def process_hashtags(account)

View file

@ -1,11 +1,11 @@
= form_tag preview_admin_report_actions_path(@report), method: :post do
= form_tag preview_admin_report_actions_path(report), method: :post do
.report-actions
.report-actions__item
.report-actions__item__button
= link_to t('admin.reports.mark_as_resolved'), resolve_admin_report_path(@report), method: :post, class: 'button'
= link_to t('admin.reports.mark_as_resolved'), resolve_admin_report_path(report), method: :post, class: 'button'
.report-actions__item__description
= t('admin.reports.actions.resolve_description_html')
- if @statuses.any? { |status| (status.with_media? || status.with_preview_card?) && !status.discarded? }
- if statuses.any? { |status| (status.with_media? || status.with_preview_card?) && !status.discarded? }
.report-actions__item
.report-actions__item__button
= button_tag t('admin.reports.mark_as_sensitive'), name: :mark_as_sensitive, class: 'button'
@ -33,6 +33,6 @@
= t('admin.reports.actions.suspend_description_html')
.report-actions__item
.report-actions__item__button
= link_to t('admin.accounts.custom'), new_admin_account_action_path(@report.target_account_id, report_id: @report.id), class: 'button'
= link_to t('admin.accounts.custom'), new_admin_account_action_path(report.target_account_id, report_id: report.id), class: 'button'
.report-actions__item__description
= t('admin.reports.actions.other_description_html')

View file

@ -179,7 +179,7 @@
%p#actions= t(@report.target_account.local? ? 'admin.reports.actions_description_html' : 'admin.reports.actions_description_remote_html')
= render partial: 'admin/reports/actions'
= render partial: 'admin/reports/actions', locals: { report: @report, statuses: @statuses }
- unless @action_logs.empty?
%hr.spacer/

View file

@ -1,30 +1,30 @@
- if !@user.confirmed?
- if !user.confirmed?
.flash-message.warning
= t('auth.status.confirming')
= link_to t('auth.didnt_get_confirmation'), new_user_confirmation_path
- elsif !@user.approved?
- elsif !user.approved?
.flash-message.warning
= t('auth.status.pending')
- elsif @user.account.moved_to_account_id.present?
- elsif user.account.moved_to_account_id.present?
.flash-message.warning
= t('auth.status.redirecting_to', acct: @user.account.moved_to_account.pretty_acct)
= t('auth.status.redirecting_to', acct: user.account.moved_to_account.pretty_acct)
= link_to t('migrations.cancel'), settings_migration_path
%h3= t('auth.status.account_status')
%p.hint
- if @user.account.suspended?
- if user.account.suspended?
%span.negative-hint= t('user_mailer.warning.explanation.suspend')
- elsif @user.disabled?
- elsif user.disabled?
%span.negative-hint= t('user_mailer.warning.explanation.disable')
- elsif @user.account.silenced?
- elsif user.account.silenced?
%span.warning-hint= t('user_mailer.warning.explanation.silence')
- else
%span.positive-hint= t('auth.status.functional')
= render partial: 'account_warning', collection: @strikes
= render partial: 'account_warning', collection: strikes
- if @user.account.strikes.exists?
- if user.account.strikes.exists?
%hr.spacer/
%p.muted-hint

View file

@ -1,7 +1,7 @@
- content_for :page_title do
= t('settings.account_settings')
= render 'status'
= render partial: 'status', locals: { user: @user, strikes: @strikes }
%h3= t('auth.security')

View file

@ -3,7 +3,7 @@
= javascript_pack_tag 'two_factor_authentication', crossorigin: 'anonymous'
- if @webauthn_enabled
- if webauthn_enabled?
= render partial: 'auth/sessions/two_factor/webauthn_form', locals: { hidden: @scheme_type != 'webauthn' }
= render partial: 'auth/sessions/two_factor/otp_authentication_form', locals: { hidden: @scheme_type != 'totp' }

View file

@ -13,6 +13,6 @@
- if Setting.site_contact_email.present?
%p.hint.subtle-hint= t('users.otp_lost_help_html', email: mail_to(Setting.site_contact_email, nil))
- if @webauthn_enabled
- if webauthn_enabled?
.form-footer
= link_to(t('auth.link_to_webauth'), '#', id: 'link-to-webauthn')

View file

@ -6,7 +6,7 @@
%tbody
%tr
%td.accounts-table__interrelationships
= interrelationships_icon(@relationships, account.id)
= interrelationships_icon(relationships, account.id)
%td= account_link_to account
%td.accounts-table__count.optional
= friendly_number_to_human account.statuses_count

View file

@ -53,6 +53,6 @@
- if @accounts.empty?
= nothing_here 'nothing-here--under-tabs'
- else
= render partial: 'account', collection: @accounts, locals: { f: f }
= render partial: 'account', collection: @accounts, locals: { f: f, relationships: @relationships }
= paginate @accounts

View file

@ -3,9 +3,9 @@
enabled = ENV['ES_ENABLED'] == 'true'
host = ENV.fetch('ES_HOST') { 'localhost' }
port = ENV.fetch('ES_PORT') { 9200 }
user = ENV.fetch('ES_USER') { nil }
password = ENV.fetch('ES_PASS') { nil }
fallback_prefix = ENV.fetch('REDIS_NAMESPACE') { nil }
user = ENV.fetch('ES_USER', nil).presence
password = ENV.fetch('ES_PASS', nil).presence
fallback_prefix = ENV.fetch('REDIS_NAMESPACE', nil).presence
prefix = ENV.fetch('ES_PREFIX') { fallback_prefix }
Chewy.settings = {

View file

@ -394,7 +394,7 @@ Devise.setup do |config|
config.check_at_sign = true
config.pam_default_suffix = ENV.fetch('PAM_EMAIL_DOMAIN') { ENV['LOCAL_DOMAIN'] }
config.pam_default_service = ENV.fetch('PAM_DEFAULT_SERVICE') { 'rpam' }
config.pam_controlled_service = ENV.fetch('PAM_CONTROLLED_SERVICE') { nil }
config.pam_controlled_service = ENV.fetch('PAM_CONTROLLED_SERVICE', nil).presence
end
if ENV['LDAP_ENABLED'] == 'true'

View file

@ -10,7 +10,7 @@ fi:
locale: Alue
password: Salasana
user/account:
username: Käyttäjätunnus
username: Käyttäjänimi
user/invite_request:
text: Syy
errors:

View file

@ -118,11 +118,11 @@ fi:
write: Vain kirjoitusoikeus
title:
accounts: Tilit
admin/accounts: Tilien hallinta
admin/accounts: Tilien hallinnointi
admin/all: Kaikki hallinnolliset toiminnot
admin/reports: Raporttien hallinta
admin/reports: Raporttien hallinnointi
all: Täysi pääsy Mastodon-tiliisi
blocks: Torjutut
blocks: Estot
bookmarks: Kirjanmerkit
conversations: Keskustelut
crypto: Päästä päähän -salaus

View file

@ -27,10 +27,10 @@ fi:
title: Suorita valvontatoimi käyttäjälle %{acct}
account_moderation_notes:
create: Jätä muistiinpano
created_msg: Valvontamerkinnän luonti onnistui!
destroyed_msg: Valvontamerkinnän poisto onnistui!
created_msg: Valvontamuistiinpanon luonti onnistui!
destroyed_msg: Valvontamuistiinpanon poisto onnistui!
accounts:
add_email_domain_block: Estä sähköpostidomain
add_email_domain_block: Estä sähköpostiverkkotunnus
approve: Hyväksy
approved_msg: Käyttäjän %{username} liittymishakemus hyväksyttiin
are_you_sure: Oletko varma?
@ -95,10 +95,10 @@ fi:
silenced: Rajoitettu
suspended: Jäädytetty
title: Valvonta
moderation_notes: Valvontamerkinnät
moderation_notes: Valvontamuistiinpanot
most_recent_activity: Viimeisin toiminta
most_recent_ip: Viimeisin IP
no_account_selected: Yhtään tiliä ei muutettu, koska mitään ei valittu
no_account_selected: Tilejä ei muutettu, koska yhtään ei ollut valittuna
no_limits_imposed: Rajoituksia ei ole asetettu
no_role_assigned: Roolia ei ole määritetty
not_subscribed: Ei tilaaja
@ -117,7 +117,7 @@ fi:
reject: Hylkää
rejected_msg: Käyttäjän %{username} rekisteröitymishakemus hylättiin
remote_suspension_irreversible: Tämän tilin tiedot on poistettu peruuttamattomasti.
remote_suspension_reversible_hint_html: Tili on jäädytetty heidän palvelimellaan, ja kaikki tiedot poistetaan %{date}. Sitä ennen etäpalvelin voi palauttaa tilin ongelmitta. Jos haluat poistaa kaikki tilin tiedot heti, onnistuu se alta.
remote_suspension_reversible_hint_html: Tili on jäädytetty omalla palvelimellaan, ja kaikki tiedot poistetaan %{date}. Sitä ennen etäpalvelin voi palauttaa tilin ongelmitta. Jos haluat poistaa kaikki tilin tiedot heti, onnistuu se alta.
remove_avatar: Poista profiilikuva
remove_header: Poista otsakekuva
removed_avatar_msg: Käyttäjän %{username} avatar-kuva poistettu onnistuneesti
@ -162,7 +162,7 @@ fi:
unsilenced_msg: Tilin %{username} rajoituksen kumoaminen onnistui
unsubscribe: Lopeta tilaus
unsuspended_msg: Tilin %{username} jäädytyksen kumoaminen onnistui
username: Käyttäjätunnus
username: Käyttäjänimi
view_domain: Näytä verkkotunnuksen yhteenveto
warn: Varoita
web: Verkko
@ -181,7 +181,7 @@ fi:
create_custom_emoji: Luo mukautettu emoji
create_domain_allow: Luo verkkotunnuksen salliminen
create_domain_block: Luo verkkotunnuksen esto
create_email_domain_block: Luo sähköpostin verkkotunnuksen esto
create_email_domain_block: Luo sähköpostiverkkotunnuksen esto
create_ip_block: Luo IP-sääntö
create_unavailable_domain: Luo ei-saatavilla oleva verkkotunnus
create_user_role: Luo rooli
@ -191,7 +191,7 @@ fi:
destroy_custom_emoji: Poista mukautettu emoji
destroy_domain_allow: Poista verkkotunnuksen salliminen
destroy_domain_block: Poista verkkotunnuksen esto
destroy_email_domain_block: Poista sähköpostin verkkotunnuksen esto
destroy_email_domain_block: Poista sähköpostiverkkotunnuksen esto
destroy_instance: Tyhjennä verkkotunnus
destroy_ip_block: Poista IP-sääntö
destroy_status: Poista julkaisu
@ -236,21 +236,21 @@ fi:
confirm_user_html: "%{name} vahvisti käyttäjän %{target} sähköpostiosoitteen"
create_account_warning_html: "%{name} lähetti varoituksen käyttäjälle %{target}"
create_announcement_html: "%{name} loi uuden tiedotteen %{target}"
create_canonical_email_block_html: "%{name} esti sähköpostin hashilla %{target}"
create_canonical_email_block_html: "%{name} esti sähköpostin tiivisteellä %{target}"
create_custom_emoji_html: "%{name} lähetti uuden emojin %{target}"
create_domain_allow_html: "%{name} salli federoinnin verkkotunnuksen %{target} kanssa"
create_domain_block_html: "%{name} esti verkkotunnuksen %{target}"
create_email_domain_block_html: "%{name} esti sähköpostin %{target}"
create_email_domain_block_html: "%{name} esti sähköpostiverkkotunnuksen %{target}"
create_ip_block_html: "%{name} loi IP-säännön %{target}"
create_unavailable_domain_html: "%{name} pysäytti toimituksen verkkotunnukseen %{target}"
create_user_role_html: "%{name} loi roolin %{target}"
demote_user_html: "%{name} alensi käyttäjän %{target}"
destroy_announcement_html: "%{name} poisti tiedotteen %{target}"
destroy_canonical_email_block_html: "%{name} poisti sähköpostieston hashilla %{target}"
destroy_canonical_email_block_html: "%{name} poisti sähköpostin eston tiivisteellä %{target}"
destroy_custom_emoji_html: "%{name} poisti emojin %{target}"
destroy_domain_allow_html: "%{name} kielsi federoinnin verkkotunnuksen %{target} kanssa"
destroy_domain_block_html: "%{name} poisti verkkotunnuksen %{target} eston"
destroy_email_domain_block_html: "%{name} poisti sähköpostin verkkotunnuksen %{target} eston"
destroy_email_domain_block_html: "%{name} poisti sähköpostiverkkotunnuksen %{target} eston"
destroy_instance_html: "%{name} tyhjensi verkkotunnuksen %{target}"
destroy_ip_block_html: "%{name} poisti IP-säännön %{target}"
destroy_status_html: "%{name} poisti käyttäjän %{target} julkaisun"
@ -331,7 +331,7 @@ fi:
listed: Listalla
new:
title: Lisää uusi mukautettu emoji
no_emoji_selected: Emojeita ei muutettu, koska yhtään ei valittu
no_emoji_selected: Emojeita ei muutettu, koska yhtään ei ollut valittuna
not_permitted: Sinulla ei ole oikeutta suorittaa tätä toimintoa
overwrite: Korvaa
shortcode: Lyhennekoodi
@ -381,7 +381,7 @@ fi:
import: Tuo
undo: Estä liitto verkkotunnukselle
domain_blocks:
add_new: Lisää uusi
add_new: Lisää uusi verkkotunnuksen esto
confirm_suspension:
cancel: Peruuta
confirm: Jäädytä
@ -408,7 +408,7 @@ fi:
silence: Rajoita
suspend: Jäädytä
title: Uusi verkkotunnuksen esto
no_domain_block_selected: Verkkoalue-estoihin ei tehty muutoksia, koska valintoja ei tehty
no_domain_block_selected: Verkkotunnusten estoja ei muutettu, koska yhtään ei ollut valittuna
not_permitted: Nykyiset käyttöoikeutesi eivät kata tätä toimintoa
obfuscate: Peitä verkkotunnuksen nimi
obfuscate_hint: Peitä verkkotunnus osittain luettelossa, jos julkinen verkkotunnusten rajoitusluettelo on käytössä
@ -420,14 +420,14 @@ fi:
reject_media_hint: Poistaa paikallisesti tallennetut mediatiedostot eikä lataa niitä enää jatkossa. Ei merkitystä jäähyn kohdalla
reject_reports: Hylkää raportit
reject_reports_hint: Ohita kaikki tästä verkkotunnuksesta tulevat raportit. Erottamisen kannalta ei merkitystä
undo: Peru
undo: Peru verkkotunnuksen esto
view: Näytä verkkotunnuksen esto
email_domain_blocks:
add_new: Lisää uusi
attempts_over_week:
one: "%{count} yritystä viimeisen viikon aikana"
other: "%{count} rekisteröitymisyritystä viimeisen viikon aikana"
created_msg: Sähköpostiverkkotunnuksen lisäys estolistalle onnistui
created_msg: Sähköpostiverkkotunnus estetty onnistuneesti
delete: Poista
dns:
types:
@ -436,26 +436,26 @@ fi:
new:
create: Lisää verkkotunnus
resolve: Ratkaise verkkotunnus
title: Uusi sähköpostiestolistan merkintä
no_email_domain_block_selected: Sähköpostin verkkotunnuksia ei muutettu, koska yhtään ei valittu
title: Estä uusi sähköpostiverkkotunnus
no_email_domain_block_selected: Sähköpostin verkkotunnuksia ei muutettu, koska yhtään ei ollut valittuna
not_permitted: Ei sallittu
resolved_dns_records_hint_html: Verkkotunnuksen nimi määräytyy seuraaviin MX-verkkotunnuksiin, jotka ovat viime kädessä vastuussa sähköpostin vastaanottamisesta. MX-verkkotunnuksen estäminen estää kirjautumisen mistä tahansa sähköpostiosoitteesta, joka käyttää samaa MX-verkkotunnusta, vaikka näkyvä verkkotunnuksen nimi olisikin erilainen. <strong>Varo estämästä suuria sähköpostin palveluntarjoajia.</strong>
resolved_through_html: Ratkaistu %{domain} kautta
title: Sähköpostiestolista
title: Estetyt sähköpostiverkkotunnukset
export_domain_allows:
new:
title: Tuo sallitut verkkoalueet
title: Tuo sallittuja verkkotunnuksia
no_file: Yhtäkään tiedostoa ei ole valittu
export_domain_blocks:
import:
description_html: Olet tuomassa verkkotunnusten estoluetteloa. Tarkista luettelo huolella etenkin, jos et ole laatinut sitä itse.
existing_relationships_warning: Olemassa olevat seuraussuhteet
private_comment_description_html: 'Tuodun estolistan alkuperän selvillä pitämiseksi, lisätään tietojen yhteyteen seuraava yksityinen kommentti: <q>%{comment}</q>'
private_comment_template: Tuotu lähteestä %{source}, pvm %{date}
title: Tuo luettelo verkkoalue-estoista
invalid_domain_block: 'Yksi tai useampi verkkotunnuksen lohko ohitettiin seuraavien virheiden vuoksi: %{error}'
private_comment_description_html: 'Seurataksesi tuotujen estojen alkuperää lisätään estojen yhteyteen seuraava yksityinen kommentti: <q>%{comment}</q>'
private_comment_template: Tuotu lähteestä %{source} %{date}
title: Tuo verkkotunnusten estoja
invalid_domain_block: 'Yksi tai useampi verkkotunnuksen esto ohitettiin seuraavien virheiden vuoksi: %{error}'
new:
title: Tuo luettelo verkkoalue-estoista
title: Tuo verkkotunnusten estoja
no_file: Yhtäkään tiedostoa ei ole valittu
follow_recommendations:
description_html: "<strong>Seuraamissuositukset auttavat uusia käyttäjiä löytämään nopeasti kiinnostavaa sisältöä</strong>. Kun käyttäjä ei ole ollut tarpeeksi vuorovaikutuksessa muiden kanssa, jotta hänelle olisi muodostunut henkilökohtaisia seuraamissuosituksia, suositellaan niiden sijaan näitä tilejä. Ne lasketaan päivittäin uudelleen yhdistelmästä tilejä, jotka ovat viime aikoina olleet aktiivisimmin sitoutuneita ja joilla on suurimmat paikalliset seuraajamäärät tietyllä kielellä."
@ -481,9 +481,9 @@ fi:
back_to_limited: Rajoitettu
back_to_warning: Varoitus
by_domain: Verkkotunnus
confirm_purge: Oletko varma, että haluat pysyvästi poistaa tiedot tältä verkkotunnukselta?
confirm_purge: Haluatko varmasti poistaa pysyvästi tämän verkkotunnuksen tiedot?
content_policies:
comment: Sisäinen huomautus
comment: Sisäinen muistiinpano
description_html: Voit määrittää sisältökäytännöt, joita sovelletaan kaikkiin tämän verkkotunnuksen ja sen aliverkkotunnuksien tileihin.
limited_federation_mode_description_html: Voit valita sallitaanko federointi tällä verkkotunnuksella.
policies:
@ -527,7 +527,7 @@ fi:
purge: Tyhjennä
purge_description_html: Jos uskot, että tämä verkkotunnus on offline-tilassa tarkoituksella, voit poistaa kaikki verkkotunnuksen tilitietueet ja niihin liittyvät tiedot tallennustilastasi. Tämä voi kestää jonkin aikaa.
title: Federointi
total_blocked_by_us: Estetty meidän toimesta
total_blocked_by_us: Estämämme
total_followed_by_them: Heidän seuraama
total_followed_by_us: Meidän seuraama
total_reported: Niitä koskevat raportit
@ -554,7 +554,7 @@ fi:
'94670856': 3 vuotta
new:
title: Luo uusi IP-sääntö
no_ip_block_selected: IP-sääntöjä ei muutettu, koska yhtään ei ole valittuna
no_ip_block_selected: IP-sääntöjä ei muutettu, koska yhtään ei ollut valittuna
title: IP-säännöt
relationships:
title: "%{acct}n suhteet"
@ -575,13 +575,13 @@ fi:
status: Tila
title: Välittäjät
report_notes:
created_msg: Muistiinpano onnistuneesti lisätty raporttiin!
destroyed_msg: Muistiinpano onnistuneesti poistettu raportista!
created_msg: Muistiinpano lisätty raporttiin onnistuneesti!
destroyed_msg: Muistiinpano poistettu raportista onnistuneesti!
reports:
account:
notes:
one: "%{count} ilmoitus"
other: "%{count} ilmoitusta"
one: "%{count} muistiinpano"
other: "%{count} muistiinpanoa"
action_log: Tarkastusloki
action_taken_by: Toimen tehnyt
actions:
@ -620,8 +620,8 @@ fi:
create_and_unresolve: Avaa uudelleen ja lisää muistiinpano
delete: Poista
placeholder: Kuvaile mitä toimia on tehty tai muita päivityksiä tähän raporttiin…
title: Merkinnät
notes_description_html: Tarkastele ja jätä merkintöjä muille valvojille ja itsellesi tulevaisuuteen
title: Muistiinpanot
notes_description_html: Tarkastele ja jätä muistiinpanoja muille valvojille ja itsellesi tulevaisuuteen
processed_msg: 'Raportti #%{id} käsitelty'
quick_actions_description_html: 'Suorita nopea toiminto tai vieritä alas nähdäksesi raportoitu sisältö:'
remote_user_placeholder: etäkäyttäjä instanssista %{instance}
@ -707,7 +707,7 @@ fi:
manage_settings: Hallitse asetuksia
manage_settings_description: Sallii käyttäjien muuttaa sivuston asetuksia
manage_taxonomies: Hallitse luokittelua
manage_taxonomies_description: Sallii käyttäjien tarkistaa nousussa olevan sisällön ja päivittää aihetunnisteiden asetuksia
manage_taxonomies_description: Sallii käyttäjien tarkistaa suositun sisällön ja päivittää aihetunnisteiden asetuksia
manage_user_access: Hallitse käyttäjäoikeuksia
manage_user_access_description: Sallii käyttäjien poistaa muiden käyttäjien kaksivaiheinen todennus käytöstä, vaihtaa heidän sähköpostiosoitteensa ja nollata heidän salasanansa
manage_users: Hallitse käyttäjiä
@ -735,10 +735,10 @@ fi:
rules_hint: On olemassa erityinen alue sääntöjä, joita käyttäjien odotetaan noudattavan.
title: Tietoja
appearance:
preamble: Mukauta Mastodonin verkkokäyttöliittymää.
preamble: Mukauta Mastodonin selainkäyttöliittymää.
title: Ulkoasu
branding:
preamble: Palvelimesi brändäys erottaa sen muista verkon palvelimista. Nämä tiedot voivat näkyä monissa eri ympäristöissä, kuten Mastodonin verkkokäyttöliittymässä, natiivisovelluksissa, linkkien esikatseluissa muilla sivustoilla, viestintäsovelluksissa ja niin edelleen. Siksi nämä tiedot kannattaa pitää selkeinä, lyhyinä ja ytimekkäinä.
preamble: Palvelimesi brändäys erottaa sen muista verkon palvelimista. Nämä tiedot voivat näkyä monissa eri ympäristöissä, kuten Mastodonin selainkäyttöliittymässä, natiivisovelluksissa, linkkien esikatseluissa muilla sivustoilla, viestintäsovelluksissa ja niin edelleen. Siksi nämä tiedot kannattaa pitää selkeinä, lyhyinä ja ytimekkäinä.
title: Brändäys
captcha_enabled:
desc_html: Tämä perustuu ulkoisiin skripteihin hCaptchasta, mikä voi olla turvallisuus- ja yksityisyysongelma. Lisäksi <strong>tämä voi tehdä rekisteröinnin ihmisille huomattavasti (erityisesti vammaisten) helpommaksi</strong>. Harkitse vaihtoehtoisia toimenpiteitä, kuten hyväksymisperusteista tai kutsupohjaista rekisteröintiä.
@ -807,13 +807,13 @@ fi:
media:
title: Media
metadata: Metadata
no_status_selected: Julkaisuja ei muutettu, koska yhtään ei ole valittuna
no_status_selected: Julkaisuja ei muutettu, koska yhtään ei ollut valittuna
open: Avaa julkaisu
original_status: Alkuperäinen julkaisu
reblogs: Edelleen jako
status_changed: Julkaisua muutettu
title: Tilin tilat
trending: Nousussa
trending: Suosituttua
visibility: Näkyvyys
with_media: Sisältää mediaa
strikes:
@ -832,7 +832,7 @@ fi:
database_schema_check:
message_html: Tietokannan siirto on vireillä. Suorita ne varmistaaksesi, että sovellus toimii odotetulla tavalla
elasticsearch_health_red:
message_html: Elasticsearch-klusteri on vikatilassa (punainen tila); hakuominaisuudet eivät ole käytettävissä
message_html: Elasticsearch-klusteri on vikatilassa (punainen tila), joten hakuominaisuudet eivät ole käytettävissä
elasticsearch_health_yellow:
message_html: Elasticsearch-klusteri on häiriötilassa (keltainen tila), joten suosittelemme tutkimaan syyn
elasticsearch_index_mismatch:
@ -842,13 +842,13 @@ fi:
message_html: Elasticsearch-klusterissa on useampi kuin yksi solmu, mutta Mastodonia ei ole määritetty käyttämään niitä.
elasticsearch_preset_single_node:
action: Katso käyttöohjeet
message_html: Elasticsearch-klusterissa on vain yksi solmu, <code>ES_PRESET</code> tulisi asettaa arvoon <code>single_node_cluster</code>.
message_html: Elasticsearch-klusterissa on vain yksi solmu. <code>ES_PRESET</code> tulisi asettaa arvoon <code>single_node_cluster</code>.
elasticsearch_reset_chewy:
message_html: Elasticsearch-järjestelmäindeksi on vanhentunut asetusmuutoksen vuoksi. Suorita <code>tootctl search deploy --reset-chewy</code> päivittääksesi sen.
elasticsearch_running_check:
message_html: Ei saatu yhteyttä Elasticsearch. Tarkista, että se on käynnissä tai poista kokotekstihaku käytöstä
message_html: Ei saatu yhteyttä Elasticsearchiin. Tarkista, että se on käynnissä tai poista kokotekstihaku käytöstä
elasticsearch_version_check:
message_html: 'Yhteensopimaton Elasticsearch versio: %{value}'
message_html: 'Yhteensopimaton Elasticsearch-versio: %{value}'
version_comparison: Elasticsearch %{running_version} on käynnissä, kun %{required_version} vaaditaan
rules_check:
action: Hallitse palvelimen sääntöjä
@ -881,9 +881,9 @@ fi:
description_html: Nämä ovat linkkejä, joita jaetaan tällä hetkellä paljon tileillä, joilta palvelimesi näkee viestejä. Se voi auttaa käyttäjiäsi saamaan selville, mitä maailmassa tapahtuu. Linkkejä ei näytetä julkisesti, ennen kuin hyväksyt julkaisijan. Voit myös sallia tai hylätä yksittäiset linkit.
disallow: Hylkää linkki
disallow_provider: Estä julkaisija
no_link_selected: Yhtään linkkiä ei muutettu, koska yhtään ei valittu
no_link_selected: Linkkejä ei muutettu, koska yhtään ei ollut valittuna
publishers:
no_publisher_selected: Julkaisijoita ei muutettu, koska yhtään ei valittu
no_publisher_selected: Julkaisijoita ei muutettu, koska yhtään ei ollut valittuna
shared_by_over_week:
one: Yksi henkilö jakanut viimeisen viikon aikana
other: Jakanut %{count} henkilöä viimeisen viikon aikana
@ -904,7 +904,7 @@ fi:
description_html: Nämä ovat julkaisuja, joita palvelimesi tietää jaettavan ja lisättävän suosikkeihin paljon tällä hetkellä. Listaus voi auttaa uusia ja palaavia käyttäjiäsi löytämään lisää seurattavia. Julkaisut eivät näy julkisesti ennen kuin hyväksyt niiden julkaisijan ja julkaisija sallii tilinsä ehdottamisen. Voit myös sallia tai hylätä yksittäisiä julkaisuja.
disallow: Kiellä julkaisu
disallow_account: Estä tekijä
no_status_selected: Suosittuja julkaisuja ei muutettu, koska yhtään ei ole valittuna
no_status_selected: Suosittuja julkaisuja ei muutettu, koska yhtään ei ollut valittuna
not_discoverable: Tekijä ei ole ilmoittanut olevansa löydettävissä
shared_by:
one: Jaettu tai lisätty suosikkeihin kerran
@ -920,21 +920,21 @@ fi:
tag_uses_measure: käyttökerrat
description_html: Nämä ovat aihetunnisteita, jotka näkyvät tällä hetkellä monissa julkaisuissa, jotka palvelimesi näkee. Tämä voi auttaa käyttäjiäsi selvittämään, mistä ihmiset puhuvat eniten tällä hetkellä. Mitään aihetunnisteita ei näytetä julkisesti, ennen kuin hyväksyt ne.
listable: Voidaan ehdottaa
no_tag_selected: Yhtään tagia ei muutettu, koska yhtään ei valittu
no_tag_selected: Tunnisteita ei muutettu, koska yhtään ei ollut valittuna
not_listable: Ei tulla ehdottamaan
not_trendable: Ei näy trendien alla
not_usable: Ei voida käyttää
peaked_on_and_decaying: Saavutti huipun %{date}, nyt hiipuu
title: Suositut aihetunnisteet
trendable: Voi näkyä trendien alla
trending_rank: 'Nousussa #%{rank}'
trending_rank: 'Suosittua #%{rank}'
usable: Voidaan käyttää
usage_comparison: Käytetty %{today} kertaa tänään, verrattuna %{yesterday} eiliseen
used_by_over_week:
one: Yhden henkilön käyttämä viime viikon aikana
other: Käyttänyt %{count} henkilöä viimeisen viikon aikana
title: Trendit
trending: Nousussa
trending: Suosittua
warning_presets:
add_new: Lisää uusi
delete: Poista
@ -994,8 +994,8 @@ fi:
new_trending_statuses:
title: Suositut julkaisut
new_trending_tags:
no_approved_tags: Tällä hetkellä ei ole hyväksyttyjä trendikkäitä aihetunnisteita.
requirements: 'Mikä tahansa näistä ehdokkaista voisi ylittää #%{rank} hyväksytyn trendikkään aihetunnisteen, joka on tällä hetkellä #%{lowest_tag_name} arvosanalla %{lowest_tag_score}.'
no_approved_tags: Tällä hetkellä ei ole hyväksyttyjä suosittuja aihetunnisteita.
requirements: 'Mikä tahansa näistä ehdokkaista voisi ylittää #%{rank} hyväksytyn suositun aihetunnisteen, joka on tällä hetkellä #%{lowest_tag_name} %{lowest_tag_score} pisteellä.'
title: Suositut aihetunnisteet
subject: Uusia trendejä tarkistettavaksi instanssissa %{instance}
aliases:
@ -1007,7 +1007,7 @@ fi:
remove: Poista aliaksen linkitys
appearance:
advanced_web_interface: Edistynyt selainkäyttöliittymä
advanced_web_interface_hint: 'Jos haluat hyödyntää näytön koko leveyttä, edistyneen webkäyttöliittymän avulla voit määrittää useita erilaisia sarakkeita, niin näet kerralla niin paljon tietoa kuin haluat: kotisyöte, ilmoitukset, yleinen aikajana, mikä tahansa määrä listoja ja aihetunnisteita.'
advanced_web_interface_hint: 'Jos haluat hyödyntää näytön koko leveyttä, edistyneen selainkäyttöliittymän avulla voit määrittää useita erilaisia sarakkeita, niin näet kerralla niin paljon tietoa kuin haluat: kotisyöte, ilmoitukset, yleinen aikajana, mikä tahansa määrä listoja ja aihetunnisteita.'
animations_and_accessibility: Animaatiot ja saavutettavuus
confirmation_dialogs: Vahvistusvalinnat
discovery: Löytäminen
@ -1088,7 +1088,7 @@ fi:
new_confirmation_instructions_sent: Saat uuden vahvistuslinkin sisältävän sähköpostiviestin muutamassa minuutissa!
title: Tarkista sähköpostilaatikkosi
sign_in:
preamble_html: Kirjaudu <strong>%{domain}</strong>-tunnuksellasi. Jos tilisi sijaitsee eri palvelimella, et voi kirjautua täällä.
preamble_html: Kirjaudu <strong>%{domain}</strong>-tunnuksellasi. Jos tilisi sijaitsee eri palvelimella, et voi kirjautua tässä.
title: Kirjaudu palvelimelle %{domain}
sign_up:
manual_review: Palvelimen %{domain} valvojat tarkistavat rekisteröitymiset käsin. Helpottaaksesi rekisteröitymisesi käsittelyä kerro hieman itsestäsi ja miksi haluat luoda käyttäjätilin palvelimelle %{domain}.
@ -1219,8 +1219,8 @@ fi:
featured_tags:
add_new: Lisää uusi
errors:
limit: Olet jo nostanut esille enimmäismäärän aihetunnisteita
hint_html: "<strong>Mitä ovat näkyvillä olevat hashtagit eli aihetunnisteet?</strong> Ne ovat näkyvissä julkisessa profiilissasi ja niiden avulla ihmiset voivat selata julkisia viestejäsi nimenomaan näiden aihetunnisteiden alla. Ne auttavat esimerkiksi luovan työn tai pitkäaikaisten projektien seurannassa."
limit: Pidät jo esillä aihetunnisteiden enimmäismäärää
hint_html: "<strong>Pidä tärkeimpiä aihetunnisteitasi esillä profiilissasi.</strong> Erinomainen työkalu, jolla pidät kirjaa luovista teoksistasi ja pitkäaikaisista projekteistasi. Esillä pitämäsi aihetunnisteet ovat näyttävällä paikalla profiilissasi ja mahdollistavat nopean pääsyn omiin julkaisuihisi."
filters:
contexts:
account: Profiilit
@ -1235,7 +1235,7 @@ fi:
statuses_hint_html: Tämä suodatin koskee yksittäisten julkaisujen valintaa riippumatta siitä, vastaavatko ne alla olevia avainsanoja. <a href="%{path}">Tarkista tai poista julkaisut suodattimesta</a>.
title: Muokkaa suodatinta
errors:
deprecated_api_multiple_keywords: Näitä parametreja ei voi muuttaa tästä sovelluksesta, koska ne koskevat useampaa kuin yhtä suodattimen avainsanaa. Käytä uudempaa sovellusta tai verkkokäyttöliittymää.
deprecated_api_multiple_keywords: Näitä parametreja ei voi muuttaa tästä sovelluksesta, koska ne koskevat useampaa kuin yhtä suodattimen avainsanaa. Käytä uudempaa sovellusta tai selainkäyttöliittymää.
invalid_context: Ei sisältöä tai se on virheellinen
index:
contexts: Suodattimet %{contexts}
@ -1261,7 +1261,7 @@ fi:
batch:
remove: Poista suodattimista
index:
hint: Tämä suodatin koskee yksittäisten julkaisujen valintaa muista kriteereistä riippumatta. Voit lisätä lisää julkaisuja tähän suodattimeen verkkokäyttöliittymästä.
hint: Tämä suodatin koskee yksittäisten julkaisujen valintaa muista kriteereistä riippumatta. Voit lisätä lisää julkaisuja tähän suodattimeen selainkäyttöliittymästä.
title: Suodatetut julkaisut
generic:
all: Kaikki
@ -1270,7 +1270,7 @@ fi:
other: Kaikki <strong>%{count}</strong> kohdetta tällä sivulla on valittu.
all_matching_items_selected_html:
one: "<strong>%{count}</strong> kohde, joka vastaa hakuasi."
other: Kaikki <strong>%{count}</strong> kohdetta, jotka vastaavat hakuasi.
other: Kaikki <strong>%{count}</strong> hakuasi vastaavaa kohdetta.
cancel: Peruuta
changes_saved_msg: Muutosten tallennus onnistui!
confirm: Vahvista
@ -1282,7 +1282,7 @@ fi:
save_changes: Tallenna muutokset
select_all_matching_items:
one: Valitse %{count} kohde, joka vastaa hakuasi.
other: Valitse kaikki %{count} kohdetta, jotka vastaavat hakuasi.
other: Valitse kaikki %{count} hakuasi vastaavaa kohdetta.
today: tänään
validation_errors:
one: Kaikki ei ole aivan oikein! Tarkasta alla oleva virhe
@ -1290,7 +1290,7 @@ fi:
imports:
errors:
empty: Tyhjä CSV-tiedosto
incompatible_type: Yhteensopimaton valitun tuontilajin kanssa
incompatible_type: Yhteensopimaton valitun tuontityypin kanssa
invalid_csv_file: 'Epäkelpo CSV-tiedosto. Virhe: %{error}'
over_rows_processing_limit: sisältää yli %{count} riviä
too_large: Tiedosto on liian suuri
@ -1331,8 +1331,8 @@ fi:
bookmarks: Tuodaan kirjanmerkkejä
domain_blocking: Tuodaan estettyjä verkkotunnuksia
following: Tuodaan seurattuja tilejä
lists: Listojen tuonti
muting: Tuodaan hiljennettyjä tilejä
lists: Tuodaan listoja
muting: Tuodaan mykistettyjä tilejä
type: Tuonnin tyyppi
type_groups:
constructive: Seuratut ja kirjanmerkit
@ -1340,7 +1340,7 @@ fi:
types:
blocking: Estoluettelo
bookmarks: Kirjanmerkit
domain_blocking: Verkkotunnuksen estoluettelo
domain_blocking: Verkkotunnusten estoluettelo
following: Seurattujen luettelo
lists: Listat
muting: Mykistettyjen luettelo
@ -1402,7 +1402,7 @@ fi:
not_ready: Ei voi liittää tiedostoja, joiden käsittely on kesken. Yritä hetken kuluttua uudelleen!
too_many: Tiedostoja voi liittää enintään 4
migrations:
acct: uuden tilin käyttäjätunnus@verkkotunnus
acct: Muuttanut tunnukselle
cancel: Peruuta uudelleenohjaus
cancel_explanation: Uudelleenohjauksen peruuttaminen aktivoi uudelleen nykyisen tilisi, mutta ei palauta seuraajia, jotka on siirretty kyseiselle tilille.
cancelled_msg: Uudelleenohjaus peruttu onnistuneesti.
@ -1436,7 +1436,7 @@ fi:
title: Valvonta
move_handler:
carry_blocks_over_text: Tämä käyttäjä siirtyi paikasta %{acct}, jonka olit estänyt.
carry_mutes_over_text: Tämä käyttäjä siirtyi paikasta %{acct}, jonka mykistit.
carry_mutes_over_text: Tämä käyttäjä siirtyi tililtä %{acct}, jonka olet mykistänyt.
copy_account_note_text: 'Tämä käyttäjä siirtyi paikasta %{acct}, tässä olivat aiemmat muistiinpanosi niistä:'
navigation:
toggle_menu: Avaa/sulje valikko
@ -1525,7 +1525,7 @@ fi:
privacy_hint_html: Määritä, kuinka paljon muita avustavia tietoja haluat paljastaa. Käyttäjät löytävät kiinnostavia profiileja ja hienoja sovelluksia, kun he selaavat toisten seuraamia käyttäjiä ja kun he näkevät, millä sovelluksilla nämä julkaisevat. Saatat kuitenkin haluta piilottaa nämä tiedot.
reach: Tavoittavuus
reach_hint_html: Määritä, haluatko tulla uusien käyttäjien löytämäksi ja seuraamaksi. Haluatko julkaisujesi näkyvän Selaa-sivulla? Haluatko muiden käyttäjien näkevän sinut seuraamissuosituksissaan? Haluatko hyväksyä kaikki uudet seuraajat automaattisesti vai päättää jokaisesta erikseen?
search: Haku
search: Hae
search_hint_html: Määritä, kuinka haluat tulla löydetyksi. Haluatko, että ihmiset löytävät sinut julkisten julkaisujesi perusteella? Haluatko, että ihmiset Mastodonin ulkopuolella löytävät profiilisi tehdessään hakuja verkossa? Otathan huomioon, ettei julkisten tietojen täyttä kaikista hakukoneista poisjäämistä voi taata.
title: Yksityisyys ja tavoittavuus
privacy_policy:
@ -1625,7 +1625,7 @@ fi:
development: Kehitys
edit_profile: Muokkaa profiilia
export: Vie tietoja
featured_tags: Esiteltävät aihetunnisteet
featured_tags: Esillä pidettävät aihetunnisteet
import: Tuo
import_and_export: Tuonti ja vienti
migrate: Tilin muutto muualle

View file

@ -1866,11 +1866,11 @@ ja:
private: フォロワー限定
private_long: フォロワーにのみ表示されます
public: 公開
public_long: 誰でも見ることができ、かつ連合・ローカルタイムラインに表示されます
public_long: 誰でも見ることができ、かつ公開タイムラインに表示されます
public_unlisted: ローカル公開
public_unlisted_long: 誰でも見ることができますが、連合タイムラインには表示されません
unlisted: 収載
unlisted_long: 誰でも見ることができますが、連合・ローカルタイムラインには表示されません
public_unlisted_long: 誰でも見ることができますが、他のサーバーの連合タイムラインには表示されません
unlisted: 収載
unlisted_long: 誰でも見ることができますが、公開タイムラインには表示されません
unset: 設定なし
unset_long: デフォルトの挙動に従います
statuses_cleanup:

View file

@ -878,9 +878,9 @@ ko:
only_allowed: 허용된 것만
pending_review: 심사 대기
preview_card_providers:
allowed: 이 발행처의 링크는 유행록에 실릴 수 있음
allowed: 이 발행처의 링크는 유행록에 실릴 수 있음
description_html: 당신의 서버에서 많은 링크가 공유되고 있는 도메인들입니다. 링크의 도메인이 승인되기 전까지는 링크들은 공개적으로 트렌드에 게시되지 않습니다. 당신의 승인(또는 거절)은 서브도메인까지 확장됩니다.
rejected: 이 발행처의 링크는 유행록에 실리지 않음
rejected: 이 발행처의 링크는 유행록에 실리지 않음
title: 발행처
rejected: 거부됨
statuses:
@ -903,15 +903,15 @@ ko:
tag_servers_measure: 다른 서버들
tag_uses_measure: 총 사용
description_html: 현재 서버에서 볼 수 있는 게시물에서 많이 공유되고 있는 해시태그들입니다. 현재 사람들이 무슨 이야기를 하고 있는지 사용자들이 파악할 수 있도록 도움이 됩니다. 승인하지 않는 한 해시태그는 공개적으로 게시되지 않습니다.
listable: 추천될 수 있습니다
listable: 추천될 수 있
no_tag_selected: 아무 것도 선택 되지 않아 어떤 태그도 바뀌지 않았습니다
not_listable: 추천될 수 없습니다
not_trendable: 유행 목록에 나타나지 않습니다
not_usable: 사용불가
peaked_on_and_decaying: '%{date}에 고점을 찍고, 떨어지고 있습니다'
not_listable: 추천하지 않음
not_trendable: 유행 목록에 나타내지 않음
not_usable: 이용할 수 없음
peaked_on_and_decaying: "%{date}에 고점을 찍고, 떨어지고 있습니다"
title: 유행하는 해시태그
trendable: 유행 목록에 나타날 수 있습니다
trending_rank: '#%{rank}위로 유행 중'
trendable: 유행 목록에 나타날 수 있
trending_rank: "#%{rank}위로 유행 중"
usable: 사용 가능
usage_comparison: 오늘은 %{today}회 쓰였고, 어제는 %{yesterday}회 쓰임
used_by_over_week:

View file

@ -298,7 +298,7 @@ si:
updated_msg: ඉමොජි සාර්ථකව යාවත්කාලීන කරන ලදී!
upload: උඩුගත කරන්න
dashboard:
active_users: ක්රියාකාරී පරිශීලකයන්
active_users: ක්රිය පරිශ්‍රීලකයන්
interactions: අන්තර්ක්රියා
media_storage: මාධ්‍ය ආචයනය
new_users: නව පරිශ්‍රීලකයින්

View file

@ -42,7 +42,7 @@ fi:
bot: Tämä tili suorittaa enimmäkseen automaattisia toimintoja eikä sitä ehkä valvota
context: Ainakin yksi konteksti, jossa suodattimen pitäisi olla voimassa
current_password: Turvallisuussyistä kirjoita nykyisen tilin salasana
current_username: Vahvista kirjoittamalla nykyisen tilin käyttäjätunnus
current_username: Vahvista kirjoittamalla nykyisen tilin käyttäjänimi
digest: Lähetetään vain pitkän poissaolon jälkeen ja vain, jos olet saanut suoria viestejä poissaolosi aikana
email: Sinulle lähetetään vahvistussähköposti
header: PNG, GIF tai JPG. Enintään %{size}. Skaalataan kokoon %{dimensions} px
@ -77,11 +77,11 @@ fi:
form_admin_settings:
activity_api_enabled: Paikallisesti julkaistujen julkaisujen, aktiivisten käyttäjien ja rekisteröitymisten viikoittainen määrä
backups_retention_period: Säilytä luodut arkistot määritetyn määrän päiviä.
bootstrap_timeline_accounts: Nämä tilit kiinnitetään uusien käyttäjien suositusten yläpuolelle.
bootstrap_timeline_accounts: Nämä tilit kiinnitetään uusien käyttäjien seuraamissuositusten yläpuolelle.
closed_registrations_message: Näkyy, kun ilmoittautuminen on suljettu
content_cache_retention_period: Viestit muilta palvelimilta poistetaan määritetyn määrän päiviä jälkeen, kun arvo on asetettu positiiviseksi. Tämä voi olla peruuttamatonta.
custom_css: Voit käyttää mukautettuja tyylejä Mastodonin verkkoversiossa.
mascot: Ohittaa kuvituksen edistyneessä käyttöliittymässä.
mascot: Ohittaa kuvituksen edistyneessä selainkäyttöliittymässä.
media_cache_retention_period: Ladatut mediatiedostot poistetaan määritetyn määrän päiviä jälkeen, kun arvo on positiivinen ja ladataan uudelleen pyynnöstä.
peers_api_enabled: Luettelo verkkotunnuksista, jotka tämä palvelin on kohdannut fediversumissa. Se ei kerro, oletko liitossa tietyn palvelimen kanssa, vaan että palvelimesi on ylipäätään tietoinen siitä. Tätä tietoa käytetään palveluissa, jotka keräävät tilastoja liittoutumisesta yleisellä tasolla.
profile_directory: Profiilihakemisto lueteloi kaikki käyttäjät, jotka ovat ilmoittaneet olevansa löydettävissä.
@ -108,7 +108,7 @@ fi:
ip_block:
comment: Valinnainen. Muista miksi lisäsit tämän säännön.
expires_in: IP-osoitteet ovat rajallinen resurssi, joskus niitä jaetaan ja vaihtavat usein omistajaa. Tästä syystä epämääräisiä IP-lohkoja ei suositella.
ip: Kirjoita IPv4- tai IPv6-osoite. Voit estää kokonaisia alueita käyttämällä CIDR-syntaksia. Varo, että et lukitse itseäsi!
ip: Kirjoita IPv4- tai IPv6-osoite. Voit estää kokonaisia alueita käyttämällä CIDR-syntaksia. Varo, että et lukitse itseäsi ulos!
severities:
no_access: Estä pääsy kaikkiin resursseihin
sign_up_block: Uudet kirjautumiset eivät ole mahdollisia
@ -139,7 +139,7 @@ fi:
url: Mihin tapahtumat lähetetään
labels:
account:
discoverable: Nosta profiili ja julkaisut esille löytämisalgoritmeissa
discoverable: Pidä profiiliasi ja julkaisujasi esillä löytämisalgoritmeissa
fields:
name: Nimike
value: Sisältö
@ -147,9 +147,9 @@ fi:
show_collections: Näytä seuratut ja seuraajat profiilissa
unlocked: Hyväksy uudet seuraajat automaattisesti
account_alias:
acct: Vanhan tilin käyttäjätunnus
acct: Vanhan tilin käyttäjänimi
account_migration:
acct: Uuden tilin käyttäjätunnus
acct: Uuden tilin käyttäjänimi
account_warning_preset:
text: Esiasetettu teksti
title: Nimi
@ -162,8 +162,8 @@ fi:
disable: Poista kirjautuminen käytöstä
none: Älä tee mitään
sensitive: Arkaluonteinen
silence: Hiljennä
suspend: Poista käytöstä ja tuhoa käyttäjätunnuksen tiedot peruuttamattomasti
silence: Rajoita
suspend: Jäädytä
warning_preset_id: Käytä varoitusmallia
announcement:
all_day: Koko päivän kestävä tapahtuma
@ -224,9 +224,9 @@ fi:
severity: Vakavuus
sign_in_token_attempt: Turvakoodi
title: Nimi
type: Tuontilaji
type: Tuontityyppi
username: Käyttäjänimi
username_or_email: Käyttäjänimi tai sähköposti
username_or_email: Käyttäjänimi tai sähköpostiosoite
whole_word: Koko sana
email_domain_block:
with_dns_records: Sisällytä toimialueen MX tietueet ja IP-osoite
@ -249,10 +249,10 @@ fi:
profile_directory: Ota profiilihakemisto käyttöön
registrations_mode: Kuka voi rekisteröityä
require_invite_text: Vaadi syy liittyä
show_domain_blocks: Näytä domainestot
show_domain_blocks: Näytä verkkotunnusten estot
show_domain_blocks_rationale: Näytä miksi verkkotunnukset on estetty
site_contact_email: Ota yhteyttä sähköpostilla
site_contact_username: Kontaktin käyttäjänimi
site_contact_username: Yhteyshenkilön käyttäjänimi
site_extended_description: Laajennettu kuvaus
site_short_description: Palvelimen kuvaus
site_terms: Tietosuojakäytäntö
@ -277,7 +277,7 @@ fi:
ip: IP-osoite
severities:
no_access: Estä pääsy
sign_up_block: Estä kirjautumiset
sign_up_block: Estä rekisteröitymiset
sign_up_requires_approval: Rajoita rekisteröitymisiä
severity: Sääntö
notification_emails:

View file

@ -16,37 +16,63 @@ describe Rack::Attack, type: :request do
# https://github.com/rack/rack-attack/blob/v6.6.1/lib/rack/attack/cache.rb#L64-L66
# So we want to minimize `Time.now.to_i % period`
travel_to Time.zone.at((Time.now.to_i / period.seconds).to_i * period.seconds)
travel_to Time.zone.at(counter_prefix * period.seconds)
end
context 'when the number of requests is lower than the limit' do
it 'does not change the request status' do
limit.times do
request.call
expect(response).to_not have_http_status(429)
before do
below_limit.times { increment_counter }
end
it 'does not change the request status' do
expect { request.call }.to change { throttle_count }.by(1)
expect(response).to_not have_http_status(429)
end
end
context 'when the number of requests is higher than the limit' do
it 'returns http too many requests after limit and returns to normal status after period' do
(limit * 2).times do |i|
request.call
expect(response).to have_http_status(429) if i > limit
before do
above_limit.times { increment_counter }
end
it 'returns http too many requests after limit and returns to normal status after period' do
expect { request.call }.to change { throttle_count }.by(1)
expect(response).to have_http_status(429)
travel period
request.call
expect { request.call }.to change { throttle_count }.by(1)
expect(response).to_not have_http_status(429)
end
end
def below_limit
limit - 1
end
def above_limit
limit * 2
end
def throttle_count
described_class.cache.read("#{counter_prefix}:#{throttle}:#{remote_ip}") || 0
end
def counter_prefix
(Time.now.to_i / period.seconds).to_i
end
def increment_counter
described_class.cache.count("#{throttle}:#{remote_ip}", period)
end
end
let(:remote_ip) { '1.2.3.5' }
describe 'throttle excessive sign-up requests by IP address' do
context 'when accessed through the website' do
let(:throttle) { 'throttle_sign_up_attempts/ip' }
let(:limit) { 25 }
let(:period) { 5.minutes }
let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } }
@ -65,6 +91,7 @@ describe Rack::Attack, type: :request do
end
context 'when accessed through the API' do
let(:throttle) { 'throttle_api_sign_up' }
let(:limit) { 5 }
let(:period) { 30.minutes }
let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } }
@ -87,6 +114,7 @@ describe Rack::Attack, type: :request do
end
describe 'throttle excessive sign-in requests by IP address' do
let(:throttle) { 'throttle_login_attempts/ip' }
let(:limit) { 25 }
let(:period) { 5.minutes }
let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } }

View file

@ -14,11 +14,8 @@ RSpec.describe Api::OEmbedController do
get :show, params: { url: short_account_status_url(alice, status) }, format: :json
end
it 'returns http success' do
it 'returns private cache control headers', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns private cache control headers' do
expect(response.headers['Cache-Control']).to include('private, no-store')
end
end

View file

@ -41,11 +41,9 @@ describe Api::V1::Accounts::CredentialsController do
}
end
it 'returns http success' do
it 'updates account info', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'updates account info' do
user.reload
user.account.reload
@ -55,9 +53,7 @@ describe Api::V1::Accounts::CredentialsController do
expect(user.account.header).to exist
expect(user.setting_default_privacy).to eq('unlisted')
expect(user.setting_default_sensitive).to be(true)
end
it 'queues up an account update distribution' do
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(user.account_id)
end
end

View file

@ -18,23 +18,19 @@ describe Api::V1::Accounts::FollowerAccountsController do
end
describe 'GET #index' do
it 'returns http success' do
it 'returns accounts following the given account', :aggregate_failures do
get :index, params: { account_id: account.id, limit: 2 }
expect(response).to have_http_status(200)
end
it 'returns accounts following the given account' do
get :index, params: { account_id: account.id, limit: 2 }
expect(body_as_json.size).to eq 2
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
end
it 'does not return blocked users' do
it 'does not return blocked users', :aggregate_failures do
user.account.block!(bob)
get :index, params: { account_id: account.id, limit: 2 }
expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1
expect(body_as_json[0][:id]).to eq alice.id.to_s
end

View file

@ -18,23 +18,19 @@ describe Api::V1::Accounts::FollowingAccountsController do
end
describe 'GET #index' do
it 'returns http success' do
it 'returns accounts followed by the given account', :aggregate_failures do
get :index, params: { account_id: account.id, limit: 2 }
expect(response).to have_http_status(200)
end
it 'returns accounts followed by the given account' do
get :index, params: { account_id: account.id, limit: 2 }
expect(body_as_json.size).to eq 2
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
end
it 'does not return blocked users' do
it 'does not return blocked users', :aggregate_failures do
user.account.block!(bob)
get :index, params: { account_id: account.id, limit: 2 }
expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1
expect(body_as_json[0][:id]).to eq alice.id.to_s
end

View file

@ -19,30 +19,24 @@ describe Api::V1::Accounts::NotesController do
post :create, params: { account_id: account.id, comment: comment }
end
context 'when account note has reasonable length' do
context 'when account note has reasonable length', :aggregate_failures do
let(:comment) { 'foo' }
it 'returns http success' do
subject
expect(response).to have_http_status(200)
end
it 'updates account note' do
subject
expect(response).to have_http_status(200)
expect(AccountNote.find_by(account_id: user.account.id, target_account_id: account.id).comment).to eq comment
end
end
context 'when account note exceeds allowed length' do
context 'when account note exceeds allowed length', :aggregate_failures do
let(:comment) { 'a' * 2_001 }
it 'returns 422' do
subject
expect(response).to have_http_status(422)
end
it 'does not create account note' do
subject
expect(response).to have_http_status(422)
expect(AccountNote.where(account_id: user.account.id, target_account_id: account.id)).to_not exist
end
end

View file

@ -15,14 +15,11 @@ RSpec.describe Api::V1::Accounts::PinsController do
describe 'POST #create' do
subject { post :create, params: { account_id: kevin.account.id } }
it 'returns 200' do
expect(response).to have_http_status(200)
end
it 'creates account_pin' do
it 'creates account_pin', :aggregate_failures do
expect do
subject
end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(1)
expect(response).to have_http_status(200)
end
end
@ -33,14 +30,11 @@ RSpec.describe Api::V1::Accounts::PinsController do
Fabricate(:account_pin, account: john.account, target_account: kevin.account)
end
it 'returns 200' do
expect(response).to have_http_status(200)
end
it 'destroys account_pin' do
it 'destroys account_pin', :aggregate_failures do
expect do
subject
end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(-1)
expect(response).to have_http_status(200)
end
end
end

View file

@ -26,13 +26,10 @@ describe Api::V1::Accounts::RelationshipsController do
get :index, params: { id: simon.id }
end
it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'returns JSON with correct data' do
it 'returns JSON with correct data', :aggregate_failures do
json = body_as_json
expect(response).to have_http_status(200)
expect(json).to be_a Enumerable
expect(json.first[:following]).to be true
expect(json.first[:followed_by]).to be false
@ -51,11 +48,14 @@ describe Api::V1::Accounts::RelationshipsController do
context 'when there is returned JSON data' do
let(:json) { body_as_json }
it 'returns an enumerable json' do
it 'returns an enumerable json with correct elements', :aggregate_failures do
expect(json).to be_a Enumerable
expect_simon_item_one
expect_lewis_item_two
end
it 'returns a correct first element' do
def expect_simon_item_one
expect(json.first[:id]).to eq simon.id.to_s
expect(json.first[:following]).to be true
expect(json.first[:showing_reblogs]).to be true
@ -65,7 +65,7 @@ describe Api::V1::Accounts::RelationshipsController do
expect(json.first[:domain_blocking]).to be false
end
it 'returns a correct second element' do
def expect_lewis_item_two
expect(json.second[:id]).to eq lewis.id.to_s
expect(json.second[:following]).to be false
expect(json.second[:showing_reblogs]).to be false

View file

@ -14,15 +14,10 @@ describe Api::V1::Accounts::StatusesController do
end
describe 'GET #index' do
it 'returns http success' do
it 'returns expected headers', :aggregate_failures do
get :index, params: { account_id: user.account.id, limit: 1 }
expect(response).to have_http_status(200)
end
it 'returns expected headers' do
get :index, params: { account_id: user.account.id, limit: 1 }
expect(response.headers['Link'].links.size).to eq(2)
end
@ -44,14 +39,11 @@ describe Api::V1::Accounts::StatusesController do
get :index, params: { account_id: user.account.id, exclude_replies: true }
end
it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'returns posts along with self replies' do
it 'returns posts along with self replies', :aggregate_failures do
json = body_as_json
post_ids = json.map { |item| item[:id].to_i }.sort
expect(response).to have_http_status(200)
expect(post_ids).to eq [status.id, status_self_reply.id]
end
end

View file

@ -25,15 +25,10 @@ RSpec.describe Api::V1::AccountsController do
context 'when given truthy agreement' do
let(:agreement) { 'true' }
it 'returns http success' do
it 'creates a user', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns a new access token as JSON' do
expect(body_as_json[:access_token]).to_not be_blank
end
it 'creates a user' do
user = User.find_by(email: 'hello@world.tld')
expect(user).to_not be_nil
expect(user.created_by_application_id).to eq app.id
@ -65,18 +60,14 @@ RSpec.describe Api::V1::AccountsController do
context 'with unlocked account' do
let(:locked) { false }
it 'returns http success' do
it 'creates a following relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns JSON with following=true and requested=false' do
json = body_as_json
expect(json[:following]).to be true
expect(json[:requested]).to be false
end
it 'creates a following relation between user and target user' do
expect(user.account.following?(other_account)).to be true
end
@ -86,18 +77,14 @@ RSpec.describe Api::V1::AccountsController do
context 'with locked account' do
let(:locked) { true }
it 'returns http success' do
it 'creates a follow request relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns JSON with following=false and requested=true' do
json = body_as_json
expect(json[:following]).to be false
expect(json[:requested]).to be true
end
it 'creates a follow request relation between user and target user' do
expect(user.account.requested?(other_account)).to be true
end
@ -177,11 +164,8 @@ RSpec.describe Api::V1::AccountsController do
post :unfollow, params: { id: other_account.id }
end
it 'returns http success' do
it 'removes the following relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes the following relation between user and target user' do
expect(user.account.following?(other_account)).to be false
end
@ -197,11 +181,8 @@ RSpec.describe Api::V1::AccountsController do
post :remove_from_followers, params: { id: other_account.id }
end
it 'returns http success' do
it 'removes the followed relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes the followed relation between user and target user' do
expect(user.account.followed_by?(other_account)).to be false
end
@ -217,15 +198,9 @@ RSpec.describe Api::V1::AccountsController do
post :block, params: { id: other_account.id }
end
it 'returns http success' do
it 'creates a blocking relation', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes the following relation between user and target user' do
expect(user.account.following?(other_account)).to be false
end
it 'creates a blocking relation' do
expect(user.account.blocking?(other_account)).to be true
end
@ -241,11 +216,8 @@ RSpec.describe Api::V1::AccountsController do
post :unblock, params: { id: other_account.id }
end
it 'returns http success' do
it 'removes the blocking relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes the blocking relation between user and target user' do
expect(user.account.blocking?(other_account)).to be false
end
@ -261,19 +233,10 @@ RSpec.describe Api::V1::AccountsController do
post :mute, params: { id: other_account.id }
end
it 'returns http success' do
it 'mutes notifications', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'does not remove the following relation between user and target user' do
expect(user.account.following?(other_account)).to be true
end
it 'creates a muting relation' do
expect(user.account.muting?(other_account)).to be true
end
it 'mutes notifications' do
expect(user.account.muting_notifications?(other_account)).to be true
end
@ -289,19 +252,10 @@ RSpec.describe Api::V1::AccountsController do
post :mute, params: { id: other_account.id, notifications: false }
end
it 'returns http success' do
it 'does not mute notifications', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'does not remove the following relation between user and target user' do
expect(user.account.following?(other_account)).to be true
end
it 'creates a muting relation' do
expect(user.account.muting?(other_account)).to be true
end
it 'does not mute notifications' do
expect(user.account.muting_notifications?(other_account)).to be false
end
@ -317,19 +271,10 @@ RSpec.describe Api::V1::AccountsController do
post :mute, params: { id: other_account.id, duration: 300 }
end
it 'returns http success' do
it 'mutes notifications', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'does not remove the following relation between user and target user' do
expect(user.account.following?(other_account)).to be true
end
it 'creates a muting relation' do
expect(user.account.muting?(other_account)).to be true
end
it 'mutes notifications' do
expect(user.account.muting_notifications?(other_account)).to be true
end
@ -345,11 +290,8 @@ RSpec.describe Api::V1::AccountsController do
post :unmute, params: { id: other_account.id }
end
it 'returns http success' do
it 'removes the muting relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes the muting relation between user and target user' do
expect(user.account.muting?(other_account)).to be false
end

View file

@ -44,11 +44,9 @@ RSpec.describe Api::V1::Admin::AccountsController do
context "when called with #{params.inspect}" do
let(:params) { params }
it 'returns http success' do
it "returns the correct accounts (#{expected_results.inspect})", :aggregate_failures do
expect(response).to have_http_status(200)
end
it "returns the correct accounts (#{expected_results.inspect})" do
json = body_as_json
expect(json.map { |a| a[:id].to_i }).to eq(expected_results.map { |symbol| send(symbol).id })
@ -79,15 +77,10 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
it 'approves user', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'approves user' do
expect(account.reload.user_approved?).to be true
end
it 'logs action' do
log_item = Admin::ActionLog.last
expect(log_item).to_not be_nil
@ -106,15 +99,10 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
it 'removes user', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes user' do
expect(User.where(id: account.user.id).count).to eq 0
end
it 'logs action' do
log_item = Admin::ActionLog.last
expect(log_item).to_not be_nil
@ -133,11 +121,8 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
it 'enables user', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'enables user' do
expect(account.reload.user_disabled?).to be false
end
end
@ -151,11 +136,8 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
it 'unsuspends account', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'unsuspends account' do
expect(account.reload.suspended?).to be false
end
end
@ -169,11 +151,8 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
it 'unsensitizes account', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'unsensitizes account' do
expect(account.reload.sensitized?).to be false
end
end
@ -187,11 +166,8 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
it 'unsilences account', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'unsilences account' do
expect(account.reload.silenced?).to be false
end
end

View file

@ -1,52 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
describe Api::V1::Admin::Trends::LinksController do
render_views
let(:role) { UserRole.find_by(name: 'Admin') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:account) { Fabricate(:account) }
let(:preview_card) { Fabricate(:preview_card) }
before do
allow(controller).to receive(:doorkeeper_token) { token }
end
describe 'GET #index' do
it 'returns http success' do
get :index, params: { account_id: account.id, limit: 2 }
expect(response).to have_http_status(200)
end
end
describe 'POST #approve' do
before do
post :approve, params: { id: preview_card.id }
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
end
end
describe 'POST #reject' do
before do
post :reject, params: { id: preview_card.id }
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
end
end
end

View file

@ -25,11 +25,8 @@ RSpec.describe Api::V1::Announcements::ReactionsController do
put :update, params: { announcement_id: announcement.id, id: '😂' }
end
it 'returns http success' do
it 'creates reaction', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'creates reaction' do
expect(announcement.announcement_reactions.find_by(name: '😂', account: user.account)).to_not be_nil
end
end
@ -53,11 +50,8 @@ RSpec.describe Api::V1::Announcements::ReactionsController do
delete :destroy, params: { announcement_id: announcement.id, id: '😂' }
end
it 'returns http success' do
it 'creates reaction', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'creates reaction' do
expect(announcement.announcement_reactions.find_by(name: '😂', account: user.account)).to be_nil
end
end

View file

@ -47,11 +47,8 @@ RSpec.describe Api::V1::AnnouncementsController do
post :dismiss, params: { id: announcement.id }
end
it 'returns http success' do
it 'dismisses announcement', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'dismisses announcement' do
expect(announcement.announcement_mutes.find_by(account: user.account)).to_not be_nil
end
end

View file

@ -12,45 +12,48 @@ RSpec.describe Api::V1::BlocksController do
before { allow(controller).to receive(:doorkeeper_token) { token } }
describe 'GET #index' do
it 'limits according to limit parameter' do
it 'limits according to limit parameter', :aggregate_failures do
Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { limit: 1 }
expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1
end
it 'queries blocks in range according to max_id' do
it 'queries blocks in range according to max_id', :aggregate_failures do
blocks = Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { max_id: blocks[1] }
expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1
expect(body_as_json[0][:id]).to eq blocks[0].target_account_id.to_s
end
it 'queries blocks in range according to since_id' do
it 'queries blocks in range according to since_id', :aggregate_failures do
blocks = Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { since_id: blocks[0] }
expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1
expect(body_as_json[0][:id]).to eq blocks[1].target_account_id.to_s
end
it 'sets pagination header for next path' do
it 'sets pagination header for next path', :aggregate_failures do
blocks = Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { limit: 1, since_id: blocks[0] }
expect(response).to have_http_status(200)
expect(response.headers['Link'].find_link(%w(rel next)).href).to eq api_v1_blocks_url(limit: 1, max_id: blocks[1])
end
it 'sets pagination header for previous path' do
it 'sets pagination header for previous path', :aggregate_failures do
block = Fabricate(:block, account: user.account)
get :index
expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq api_v1_blocks_url(since_id: block)
end
it 'returns http success' do
get :index
expect(response).to have_http_status(200)
expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq api_v1_blocks_url(since_id: block)
end
context 'with wrong scopes' do

View file

@ -21,17 +21,14 @@ RSpec.describe Api::V1::ConversationsController do
PostStatusService.new.call(user.account, text: 'Hey, nobody here', visibility: 'direct')
end
it 'returns http success' do
get :index
expect(response).to have_http_status(200)
end
it 'returns pagination headers' do
it 'returns pagination headers', :aggregate_failures do
get :index, params: { limit: 1 }
expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
end
it 'returns conversations' do
it 'returns conversations', :aggregate_failures do
get :index
json = body_as_json
expect(json.size).to eq 2

View file

@ -1,80 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Api::V1::FavouritesController do
render_views
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') }
describe 'GET #index' do
context 'without token' do
it 'returns http unauthorized' do
get :index
expect(response).to have_http_status 401
end
end
context 'with token' do
context 'without read scope' do
before do
allow(controller).to receive(:doorkeeper_token) do
Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: '')
end
end
it 'returns http forbidden' do
get :index
expect(response).to have_http_status 403
end
end
context 'without valid resource owner' do
before do
token = Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read')
user.destroy!
allow(controller).to receive(:doorkeeper_token) { token }
end
it 'returns http unprocessable entity' do
get :index
expect(response).to have_http_status 422
end
end
context 'with read scope and valid resource owner' do
before do
allow(controller).to receive(:doorkeeper_token) do
Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:favourites')
end
end
it 'shows favourites owned by the user' do
favourite_by_user = Fabricate(:favourite, account: user.account)
favourite_by_others = Fabricate(:favourite)
get :index
expect(assigns(:statuses)).to contain_exactly(favourite_by_user.status)
end
it 'adds pagination headers if necessary' do
favourite = Fabricate(:favourite, account: user.account)
get :index, params: { limit: 1 }
expect(response.headers['Link'].find_link(%w(rel next)).href).to eq "http://test.host/api/v1/favourites?limit=1&max_id=#{favourite.id}"
expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq "http://test.host/api/v1/favourites?limit=1&min_id=#{favourite.id}"
end
it 'does not add pagination headers if not necessary' do
get :index
expect(response.headers['Link']).to be_nil
end
end
end
end
end

View file

@ -31,12 +31,10 @@ RSpec.describe Api::V1::FiltersController do
post :create, params: { phrase: 'magic', context: %w(home), irreversible: irreversible, whole_word: whole_word }
end
it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'creates a filter' do
it 'creates a filter', :aggregate_failures do
filter = user.account.custom_filters.first
expect(response).to have_http_status(200)
expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]]
expect(filter.context).to eq %w(home)
@ -48,12 +46,10 @@ RSpec.describe Api::V1::FiltersController do
let(:irreversible) { false }
let(:whole_word) { true }
it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'creates a filter' do
it 'creates a filter', :aggregate_failures do
filter = user.account.custom_filters.first
expect(response).to have_http_status(200)
expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]]
expect(filter.context).to eq %w(home)
@ -83,11 +79,8 @@ RSpec.describe Api::V1::FiltersController do
put :update, params: { id: keyword.id, phrase: 'updated' }
end
it 'returns http success' do
it 'updates the filter', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'updates the filter' do
expect(keyword.reload.phrase).to eq 'updated'
end
end
@ -101,11 +94,8 @@ RSpec.describe Api::V1::FiltersController do
delete :destroy, params: { id: keyword.id }
end
it 'returns http success' do
it 'removes the filter', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes the filter' do
expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound
end
end

View file

@ -1,25 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Api::V1::FollowedTagsController do
render_views
let(:user) { Fabricate(:user) }
let(:scopes) { 'read:follows' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
before { allow(controller).to receive(:doorkeeper_token) { token } }
describe 'GET #index' do
let!(:tag_follows) { Fabricate.times(5, :tag_follow, account: user.account) }
before do
get :index, params: { limit: 1 }
end
it 'returns http success' do
expect(response).to have_http_status(:success)
end
end
end

View file

@ -5,7 +5,7 @@ require 'rails_helper'
describe Api::V1::Instances::TranslationLanguagesController do
describe 'GET #show' do
context 'when no translation service is configured' do
it 'returns empty language matrix' do
it 'returns empty language matrix', :aggregate_failures do
get :show
expect(response).to have_http_status(200)
@ -19,7 +19,7 @@ describe Api::V1::Instances::TranslationLanguagesController do
allow(TranslationService).to receive_messages(configured?: true, configured: service)
end
it 'returns language matrix' do
it 'returns language matrix', :aggregate_failures do
get :show
expect(response).to have_http_status(200)

View file

@ -35,11 +35,8 @@ describe Api::V1::Lists::AccountsController do
post :create, params: { list_id: list.id, account_ids: [bob.id] }
end
it 'returns http success' do
it 'adds account to the list', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'adds account to the list' do
expect(list.accounts.include?(bob)).to be true
end
end
@ -50,11 +47,8 @@ describe Api::V1::Lists::AccountsController do
post :create, params: { list_id: list.id, account_ids: [bob.id] }
end
it 'returns http success' do
it 'adds account to the list', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'adds account to the list' do
expect(list.accounts.include?(bob)).to be true
end
end
@ -64,11 +58,8 @@ describe Api::V1::Lists::AccountsController do
post :create, params: { list_id: list.id, account_ids: [bob.id] }
end
it 'returns http not found' do
it 'does not add the account to the list', :aggregate_failures do
expect(response).to have_http_status(404)
end
it 'does not add the account to the list' do
expect(list.accounts.include?(bob)).to be false
end
end
@ -81,11 +72,8 @@ describe Api::V1::Lists::AccountsController do
delete :destroy, params: { list_id: list.id, account_ids: [list.accounts.first.id] }
end
it 'returns http success' do
it 'removes account from the list', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes account from the list' do
expect(list.accounts.count).to eq 0
end
end

View file

@ -18,13 +18,10 @@ RSpec.describe Api::V1::MarkersController do
get :index, params: { timeline: %w(home notifications) }
end
it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'returns markers' do
it 'returns markers', :aggregate_failures do
json = body_as_json
expect(response).to have_http_status(200)
expect(json.key?(:home)).to be true
expect(json[:home][:last_read_id]).to eq '123'
expect(json.key?(:notifications)).to be true
@ -38,11 +35,8 @@ RSpec.describe Api::V1::MarkersController do
post :create, params: { home: { last_read_id: '69420' } }
end
it 'returns http success' do
it 'creates a marker', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'creates a marker' do
expect(user.markers.first.timeline).to eq 'home'
expect(user.markers.first.last_read_id).to eq 69_420
end
@ -54,11 +48,8 @@ RSpec.describe Api::V1::MarkersController do
post :create, params: { home: { last_read_id: '70120' } }
end
it 'returns http success' do
it 'updates a marker', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'updates a marker' do
expect(user.markers.first.timeline).to eq 'home'
expect(user.markers.first.last_read_id).to eq 70_120
end

View file

@ -38,19 +38,10 @@ RSpec.describe Api::V1::MediaController do
post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
end
it 'returns http success' do
it 'creates a media attachment', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'creates a media attachment' do
expect(MediaAttachment.first).to_not be_nil
end
it 'uploads a file' do
expect(MediaAttachment.first).to have_attached_file(:file)
end
it 'returns media ID in JSON' do
expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
end
end
@ -60,19 +51,10 @@ RSpec.describe Api::V1::MediaController do
post :create, params: { file: fixture_file_upload('attachment.gif', 'image/gif') }
end
it 'returns http success' do
it 'creates a media attachment', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'creates a media attachment' do
expect(MediaAttachment.first).to_not be_nil
end
it 'uploads a file' do
expect(MediaAttachment.first).to have_attached_file(:file)
end
it 'returns media ID in JSON' do
expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
end
end
@ -82,17 +64,10 @@ RSpec.describe Api::V1::MediaController do
post :create, params: { file: fixture_file_upload('attachment.webm', 'video/webm') }
end
it do
# returns http success
it 'creates a media attachment', :aggregate_failures do
expect(response).to have_http_status(200)
# creates a media attachment
expect(MediaAttachment.first).to_not be_nil
# uploads a file
expect(MediaAttachment.first).to have_attached_file(:file)
# returns media ID in JSON
expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
end
end

View file

@ -18,18 +18,13 @@ RSpec.describe Api::V1::Polls::VotesController do
post :create, params: { poll_id: poll.id, choices: %w(1) }
end
it 'returns http success' do
it 'creates a vote', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'creates a vote' do
vote = poll.votes.where(account: user.account).first
expect(vote).to_not be_nil
expect(vote.choice).to eq 1
end
it 'updates poll tallies' do
expect(poll.reload.cached_tallies).to eq [0, 1]
end
end

View file

@ -1,75 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Api::V1::ReportsController do
render_views
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
before do
allow(controller).to receive(:doorkeeper_token) { token }
end
describe 'POST #create' do
let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let(:scopes) { 'write:reports' }
let(:status) { Fabricate(:status) }
let(:target_account) { status.account }
let(:category) { nil }
let(:forward) { nil }
let(:rule_ids) { nil }
before do
post :create, params: { status_ids: [status.id], account_id: target_account.id, comment: 'reasons', category: category, rule_ids: rule_ids, forward: forward }
end
it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'creates a report' do
expect(target_account.targeted_reports).to_not be_empty
end
it 'saves comment' do
expect(target_account.targeted_reports.first.comment).to eq 'reasons'
end
it 'sends e-mails to admins' do
expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email])
end
context 'when a status does not belong to the reported account' do
let(:target_account) { Fabricate(:account) }
it 'returns http not found' do
expect(response).to have_http_status(404)
end
end
context 'when a category is chosen' do
let(:category) { 'spam' }
it 'saves category' do
expect(target_account.targeted_reports.first.spam?).to be true
end
end
context 'when violated rules are chosen' do
let(:rule) { Fabricate(:rule) }
let(:category) { 'violation' }
let(:rule_ids) { [rule.id] }
it 'saves category' do
expect(target_account.targeted_reports.first.violation?).to be true
end
it 'saves rule_ids' do
expect(target_account.targeted_reports.first.rule_ids).to contain_exactly(rule.id)
end
end
end
end

View file

@ -21,11 +21,8 @@ describe Api::V1::Statuses::MutesController do
post :create, params: { status_id: status.id }
end
it 'returns http success' do
it 'creates a conversation mute', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'creates a conversation mute' do
expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to_not be_nil
end
end
@ -38,11 +35,8 @@ describe Api::V1::Statuses::MutesController do
post :destroy, params: { status_id: status.id }
end
it 'returns http success' do
it 'destroys the conversation mute', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'destroys the conversation mute' do
expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to be_nil
end
end

View file

@ -24,14 +24,12 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController do
Fabricate(:status, account: bob, reblog_of_id: status.id)
end
it 'returns http success' do
it 'returns accounts who reblogged the status', :aggregate_failures do
get :index, params: { status_id: status.id, limit: 2 }
expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
end
it 'returns accounts who reblogged the status' do
get :index, params: { status_id: status.id, limit: 2 }
expect(body_as_json.size).to eq 2
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
end

View file

@ -28,19 +28,13 @@ describe Api::V1::Statuses::ReblogsController do
end
context 'with public status' do
it 'returns http success' do
it 'reblogs the status', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 1
end
it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be true
end
it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:reblog][:id]).to eq status.id.to_s
@ -67,19 +61,13 @@ describe Api::V1::Statuses::ReblogsController do
post :destroy, params: { status_id: status.id }
end
it 'returns http success' do
it 'destroys the reblog', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 0
end
it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be false
end
it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s
@ -97,19 +85,13 @@ describe Api::V1::Statuses::ReblogsController do
post :destroy, params: { status_id: status.id }
end
it 'returns http success' do
it 'destroys the reblog', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 0
end
it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be false
end
it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s

View file

@ -1,29 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
describe Api::V1::Statuses::SourcesController do
render_views
let(:user) { Fabricate(:user) }
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses', application: app) }
context 'with an oauth token' do
before do
allow(controller).to receive(:doorkeeper_token) { token }
end
describe 'GET #show' do
let(:status) { Fabricate(:status, account: user.account) }
before do
get :show, params: { status_id: status.id }
end
it 'returns http success' do
expect(response).to have_http_status(200)
end
end
end
end

View file

@ -30,14 +30,11 @@ RSpec.describe Api::V1::StatusesController do
user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide, keywords_attributes: [{ keyword: 'banned' }, { keyword: 'irrelevant' }])
end
it 'returns http success' do
get :show, params: { id: status.id }
expect(response).to have_http_status(200)
end
it 'returns filter information' do
it 'returns filter information', :aggregate_failures do
get :show, params: { id: status.id }
json = body_as_json
expect(response).to have_http_status(200)
expect(json[:filtered][0]).to include({
filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s,
@ -57,14 +54,11 @@ RSpec.describe Api::V1::StatusesController do
filter.statuses.create!(status_id: status.id)
end
it 'returns http success' do
get :show, params: { id: status.id }
expect(response).to have_http_status(200)
end
it 'returns filter information' do
it 'returns filter information', :aggregate_failures do
get :show, params: { id: status.id }
json = body_as_json
expect(response).to have_http_status(200)
expect(json[:filtered][0]).to include({
filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s,
@ -83,14 +77,11 @@ RSpec.describe Api::V1::StatusesController do
user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide, keywords_attributes: [{ keyword: 'banned' }, { keyword: 'irrelevant' }])
end
it 'returns http success' do
get :show, params: { id: status.id }
expect(response).to have_http_status(200)
end
it 'returns filter information' do
it 'returns filter information', :aggregate_failures do
get :show, params: { id: status.id }
json = body_as_json
expect(response).to have_http_status(200)
expect(json[:reblog][:filtered][0]).to include({
filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s,
@ -125,11 +116,8 @@ RSpec.describe Api::V1::StatusesController do
post :create, params: { status: 'Hello world' }
end
it 'returns http success' do
it 'returns rate limit headers', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns rate limit headers' do
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
expect(response.headers['X-RateLimit-Remaining']).to eq (RateLimiter::FAMILIES[:statuses][:limit] - 1).to_s
end
@ -143,11 +131,8 @@ RSpec.describe Api::V1::StatusesController do
post :create, params: { status: '@alice hm, @bob is really annoying lately', allowed_mentions: [alice.id] }
end
it 'returns http unprocessable entity' do
it 'returns serialized extra accounts in body', :aggregate_failures do
expect(response).to have_http_status(422)
end
it 'returns serialized extra accounts in body' do
expect(body_as_json[:unexpected_accounts].map { |a| a.slice(:id, :acct) }).to eq [{ id: bob.id.to_s, acct: bob.acct }]
end
end
@ -157,11 +142,8 @@ RSpec.describe Api::V1::StatusesController do
post :create, params: {}
end
it 'returns http unprocessable entity' do
it 'returns rate limit headers', :aggregate_failures do
expect(response).to have_http_status(422)
end
it 'returns rate limit headers' do
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
end
end
@ -173,11 +155,8 @@ RSpec.describe Api::V1::StatusesController do
post :create, params: { status: 'Hello world' }
end
it 'returns http too many requests' do
it 'returns rate limit headers', :aggregate_failures do
expect(response).to have_http_status(429)
end
it 'returns rate limit headers' do
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
expect(response.headers['X-RateLimit-Remaining']).to eq '0'
end
@ -192,11 +171,8 @@ RSpec.describe Api::V1::StatusesController do
post :destroy, params: { id: status.id }
end
it 'returns http success' do
it 'removes the status', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes the status' do
expect(Status.find_by(id: status.id)).to be_nil
end
end
@ -209,11 +185,8 @@ RSpec.describe Api::V1::StatusesController do
put :update, params: { id: status.id, status: 'I am updated' }
end
it 'returns http success' do
it 'updates the status', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'updates the status' do
expect(status.reload.text).to eq 'I am updated'
end
end

View file

@ -1,71 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
describe Api::V1::Timelines::TagController do
render_views
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }
before do
allow(controller).to receive(:doorkeeper_token) { token }
end
describe 'GET #show' do
subject do
get :show, params: { id: 'test' }
end
before do
PostStatusService.new.call(user.account, text: 'It is a #test')
end
context 'when the instance allows public preview' do
context 'when the user is not authenticated' do
let(:token) { nil }
it 'returns http success', :aggregate_failures do
subject
expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
end
end
context 'when the user is authenticated' do
it 'returns http success', :aggregate_failures do
subject
expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
end
end
end
context 'when the instance does not allow public preview' do
before do
Form::AdminSettings.new(timeline_preview: false).save
end
context 'when the user is not authenticated' do
let(:token) { nil }
it 'returns http unauthorized' do
subject
expect(response).to have_http_status(401)
end
end
context 'when the user is authenticated' do
it 'returns http success', :aggregate_failures do
subject
expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
end
end
end
end
end

View file

@ -44,14 +44,14 @@ RSpec.describe Api::V2::Admin::AccountsController do
context "when called with #{params.inspect}" do
let(:params) { params }
it 'returns http success' do
it "returns the correct accounts (#{expected_results.inspect})" do
expect(response).to have_http_status(200)
expect(body_json_ids).to eq(expected_results.map { |symbol| send(symbol).id })
end
it "returns the correct accounts (#{expected_results.inspect})" do
json = body_as_json
expect(json.map { |a| a[:id].to_i }).to eq(expected_results.map { |symbol| send(symbol).id })
def body_json_ids
body_as_json.map { |a| a[:id].to_i }
end
end
end

View file

@ -40,17 +40,13 @@ RSpec.describe Api::V2::Filters::KeywordsController do
post :create, params: { filter_id: filter_id, keyword: 'magic', whole_word: false }
end
it 'returns http success' do
it 'creates a filter', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns a keyword' do
json = body_as_json
expect(json[:keyword]).to eq 'magic'
expect(json[:whole_word]).to be false
end
it 'creates a keyword' do
filter = user.account.custom_filters.first
expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword)).to eq ['magic']
@ -73,11 +69,9 @@ RSpec.describe Api::V2::Filters::KeywordsController do
get :show, params: { id: keyword.id }
end
it 'returns http success' do
it 'responds with the keyword', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns expected data' do
json = body_as_json
expect(json[:keyword]).to eq 'foo'
expect(json[:whole_word]).to be false
@ -100,11 +94,9 @@ RSpec.describe Api::V2::Filters::KeywordsController do
get :update, params: { id: keyword.id, keyword: 'updated' }
end
it 'returns http success' do
it 'updates the keyword', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'updates the keyword' do
expect(keyword.reload.keyword).to eq 'updated'
end
@ -125,11 +117,9 @@ RSpec.describe Api::V2::Filters::KeywordsController do
delete :destroy, params: { id: keyword.id }
end
it 'returns http success' do
it 'destroys the keyword', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes the filter' do
expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound
end

View file

@ -41,16 +41,12 @@ RSpec.describe Api::V2::Filters::StatusesController do
post :create, params: { filter_id: filter_id, status_id: status.id }
end
it 'returns http success' do
it 'creates a filter', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns a status filter' do
json = body_as_json
expect(json[:status_id]).to eq status.id.to_s
end
it 'creates a status filter' do
filter = user.account.custom_filters.first
expect(filter).to_not be_nil
expect(filter.statuses.pluck(:status_id)).to eq [status.id]
@ -73,11 +69,9 @@ RSpec.describe Api::V2::Filters::StatusesController do
get :show, params: { id: status_filter.id }
end
it 'returns http success' do
it 'responds with the filter', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns expected data' do
json = body_as_json
expect(json[:status_id]).to eq status_filter.status_id.to_s
end
@ -99,11 +93,9 @@ RSpec.describe Api::V2::Filters::StatusesController do
delete :destroy, params: { id: status_filter.id }
end
it 'returns http success' do
it 'destroys the filter', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'removes the filter' do
expect { status_filter.reload }.to raise_error ActiveRecord::RecordNotFound
end

View file

@ -0,0 +1,81 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'Admin::Accounts' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
sign_in current_user
end
describe 'Performing batch updates' do
let(:unapproved_user_account) { Fabricate(:account) }
let(:approved_user_account) { Fabricate(:account) }
before do
unapproved_user_account.user.update(approved: false)
approved_user_account.user.update(approved: true)
visit admin_accounts_path
end
context 'without selecting any accounts' do
it 'displays a notice about account selection' do
click_on button_for_suspend
expect(page).to have_content(selection_error_text)
end
end
context 'with action of `suspend`' do
it 'suspends the account' do
batch_checkbox_for(approved_user_account).check
click_on button_for_suspend
expect(approved_user_account.reload).to be_suspended
end
end
context 'with action of `approve`' do
it 'approves the account user' do
batch_checkbox_for(unapproved_user_account).check
click_on button_for_approve
expect(unapproved_user_account.reload.user).to be_approved
end
end
context 'with action of `reject`' do
it 'rejects and removes the account' do
batch_checkbox_for(unapproved_user_account).check
click_on button_for_reject
expect { unapproved_user_account.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end
def button_for_suspend
I18n.t('admin.accounts.perform_full_suspension')
end
def button_for_approve
I18n.t('admin.accounts.approve')
end
def button_for_reject
I18n.t('admin.accounts.reject')
end
def selection_error_text
I18n.t('admin.accounts.no_account_selected')
end
def batch_checkbox_for(account)
find("#form_account_batch_account_ids_#{account.id}")
end
end
end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'Admin::CustomEmojis' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
sign_in current_user
end
describe 'Performing batch updates' do
before do
visit admin_custom_emojis_path
end
context 'without selecting any records' do
it 'displays a notice about selection' do
click_on button_for_enable
expect(page).to have_content(selection_error_text)
end
end
def button_for_enable
I18n.t('admin.custom_emojis.enable')
end
def selection_error_text
I18n.t('admin.custom_emojis.no_emoji_selected')
end
end
end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'Admin::EmailDomainBlocks' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
sign_in current_user
end
describe 'Performing batch updates' do
before do
visit admin_email_domain_blocks_path
end
context 'without selecting any records' do
it 'displays a notice about selection' do
click_on button_for_delete
expect(page).to have_content(selection_error_text)
end
end
def button_for_delete
I18n.t('admin.email_domain_blocks.delete')
end
def selection_error_text
I18n.t('admin.email_domain_blocks.no_email_domain_block_selected')
end
end
end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'Admin::IpBlocks' do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
sign_in current_user
end
describe 'Performing batch updates' do
before do
visit admin_ip_blocks_path
end
context 'without selecting any records' do
it 'displays a notice about selection' do
click_on button_for_delete
expect(page).to have_content(selection_error_text)
end
end
def button_for_delete
I18n.t('admin.ip_blocks.delete')
end
def selection_error_text
I18n.t('admin.ip_blocks.no_ip_block_selected')
end
end
end

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