Merge pull request #332 from glitch-soc/merge-upstream
Merge in home feed regeneration changes from upstream
This commit is contained in:
commit
477fbec714
51 changed files with 570 additions and 89 deletions
|
@ -9,7 +9,11 @@ class Api::V1::Timelines::HomeController < Api::BaseController
|
|||
|
||||
def show
|
||||
@statuses = load_statuses
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||
|
||||
render json: @statuses,
|
||||
each_serializer: REST::StatusSerializer,
|
||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||
status: regeneration_in_progress? ? 206 : 200
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -57,4 +61,8 @@ class Api::V1::Timelines::HomeController < Api::BaseController
|
|||
def pagination_since_id
|
||||
@statuses.first.id
|
||||
end
|
||||
|
||||
def regeneration_in_progress?
|
||||
Redis.current.exists("account:#{current_account.id}:regeneration")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,13 +19,14 @@ export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
|
|||
|
||||
export const TIMELINE_CONTEXT_UPDATE = 'CONTEXT_UPDATE';
|
||||
|
||||
export function refreshTimelineSuccess(timeline, statuses, skipLoading, next) {
|
||||
export function refreshTimelineSuccess(timeline, statuses, skipLoading, next, partial) {
|
||||
return {
|
||||
type: TIMELINE_REFRESH_SUCCESS,
|
||||
timeline,
|
||||
statuses,
|
||||
skipLoading,
|
||||
next,
|
||||
partial,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -88,7 +89,7 @@ export function refreshTimeline(timelineId, path, params = {}) {
|
|||
return function (dispatch, getState) {
|
||||
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
|
||||
|
||||
if (timeline.get('isLoading') || timeline.get('online')) {
|
||||
if (timeline.get('isLoading') || (timeline.get('online') && !timeline.get('isPartial'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -104,8 +105,12 @@ export function refreshTimeline(timelineId, path, params = {}) {
|
|||
dispatch(refreshTimelineRequest(timelineId, skipLoading));
|
||||
|
||||
api(getState).get(path, { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null));
|
||||
if (response.status === 206) {
|
||||
dispatch(refreshTimelineSuccess(timelineId, [], skipLoading, null, true));
|
||||
} else {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null, false));
|
||||
}
|
||||
}).catch(error => {
|
||||
dispatch(refreshTimelineFail(timelineId, error, skipLoading));
|
||||
});
|
||||
|
|
|
@ -2,9 +2,14 @@ import React from 'react';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
const MissingIndicator = () => (
|
||||
<div className='missing-indicator'>
|
||||
<div className='regeneration-indicator missing-indicator'>
|
||||
<div>
|
||||
<FormattedMessage id='missing_indicator.label' defaultMessage='Not found' />
|
||||
<div className='regeneration-indicator__figure' />
|
||||
|
||||
<div className='regeneration-indicator__label'>
|
||||
<FormattedMessage id='missing_indicator.label' tagName='strong' defaultMessage='Not found' />
|
||||
<FormattedMessage id='missing_indicator.sublabel' defaultMessage='This resource could not be found' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
|||
import StatusContainer from 'flavours/glitch/containers/status_container';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ScrollableList from './scrollable_list';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
export default class StatusList extends ImmutablePureComponent {
|
||||
|
||||
|
@ -16,6 +17,7 @@ export default class StatusList extends ImmutablePureComponent {
|
|||
trackScroll: PropTypes.bool,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
isLoading: PropTypes.bool,
|
||||
isPartial: PropTypes.bool,
|
||||
hasMore: PropTypes.bool,
|
||||
prepend: PropTypes.node,
|
||||
emptyMessage: PropTypes.node,
|
||||
|
@ -48,8 +50,23 @@ export default class StatusList extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { statusIds, ...other } = this.props;
|
||||
const { isLoading } = other;
|
||||
const { statusIds, ...other } = this.props;
|
||||
const { isLoading, isPartial } = other;
|
||||
|
||||
if (isPartial) {
|
||||
return (
|
||||
<div className='regeneration-indicator'>
|
||||
<div>
|
||||
<div className='regeneration-indicator__figure' />
|
||||
|
||||
<div className='regeneration-indicator__label'>
|
||||
<FormattedMessage id='regeneration_indicator.label' tagName='strong' defaultMessage='Loading…' />
|
||||
<FormattedMessage id='regeneration_indicator.sublabel' defaultMessage='Your home feed is being prepared!' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const scrollableContent = (isLoading || statusIds.size > 0) ? (
|
||||
statusIds.map((statusId) => (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { expandHomeTimeline } from 'flavours/glitch/actions/timelines';
|
||||
import { expandHomeTimeline, refreshHomeTimeline } from 'flavours/glitch/actions/timelines';
|
||||
import PropTypes from 'prop-types';
|
||||
import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container';
|
||||
import Column from 'flavours/glitch/components/column';
|
||||
|
@ -16,6 +16,7 @@ const messages = defineMessages({
|
|||
|
||||
const mapStateToProps = state => ({
|
||||
hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0,
|
||||
isPartial: state.getIn(['timelines', 'home', 'isPartial'], false),
|
||||
});
|
||||
|
||||
@connect(mapStateToProps)
|
||||
|
@ -26,6 +27,7 @@ export default class HomeTimeline extends React.PureComponent {
|
|||
dispatch: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
hasUnread: PropTypes.bool,
|
||||
isPartial: PropTypes.bool,
|
||||
columnId: PropTypes.string,
|
||||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
@ -57,6 +59,39 @@ export default class HomeTimeline extends React.PureComponent {
|
|||
this.props.dispatch(expandHomeTimeline());
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this._checkIfReloadNeeded(false, this.props.isPartial);
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
this._checkIfReloadNeeded(prevProps.isPartial, this.props.isPartial);
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
this._stopPolling();
|
||||
}
|
||||
|
||||
_checkIfReloadNeeded (wasPartial, isPartial) {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
if (wasPartial === isPartial) {
|
||||
return;
|
||||
} else if (!wasPartial && isPartial) {
|
||||
this.polling = setInterval(() => {
|
||||
dispatch(refreshHomeTimeline());
|
||||
}, 3000);
|
||||
} else if (wasPartial && !isPartial) {
|
||||
this._stopPolling();
|
||||
}
|
||||
}
|
||||
|
||||
_stopPolling () {
|
||||
if (this.polling) {
|
||||
clearInterval(this.polling);
|
||||
this.polling = null;
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { intl, hasUnread, columnId, multiColumn } = this.props;
|
||||
const pinned = !!columnId;
|
||||
|
|
|
@ -120,13 +120,17 @@ export default class ListTimeline extends React.PureComponent {
|
|||
if (typeof list === 'undefined') {
|
||||
return (
|
||||
<Column>
|
||||
<LoadingIndicator />
|
||||
<div className='scrollable'>
|
||||
<LoadingIndicator />
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
} else if (list === false) {
|
||||
return (
|
||||
<Column>
|
||||
<MissingIndicator />
|
||||
<div className='scrollable'>
|
||||
<MissingIndicator />
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ const makeMapStateToProps = () => {
|
|||
const mapStateToProps = (state, { timelineId }) => ({
|
||||
statusIds: getStatusIds(state, { type: timelineId }),
|
||||
isLoading: state.getIn(['timelines', timelineId, 'isLoading'], true),
|
||||
isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false),
|
||||
hasMore: !!state.getIn(['timelines', timelineId, 'next']),
|
||||
});
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 11 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 8.3 KiB |
|
@ -30,7 +30,7 @@ const initialTimeline = ImmutableMap({
|
|||
items: ImmutableList(),
|
||||
});
|
||||
|
||||
const normalizeTimeline = (state, timeline, statuses, next) => {
|
||||
const normalizeTimeline = (state, timeline, statuses, next, isPartial) => {
|
||||
const oldIds = state.getIn([timeline, 'items'], ImmutableList());
|
||||
const ids = ImmutableList(statuses.map(status => status.get('id'))).filter(newId => !oldIds.includes(newId));
|
||||
const wasLoaded = state.getIn([timeline, 'loaded']);
|
||||
|
@ -41,6 +41,7 @@ const normalizeTimeline = (state, timeline, statuses, next) => {
|
|||
mMap.set('isLoading', false);
|
||||
if (!hadNext) mMap.set('next', next);
|
||||
mMap.set('items', wasLoaded ? ids.concat(oldIds) : ids);
|
||||
mMap.set('isPartial', isPartial);
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -125,7 +126,7 @@ export default function timelines(state = initialState, action) {
|
|||
case TIMELINE_EXPAND_FAIL:
|
||||
return state.update(action.timeline, initialTimeline, map => map.set('isLoading', false));
|
||||
case TIMELINE_REFRESH_SUCCESS:
|
||||
return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next);
|
||||
return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial);
|
||||
case TIMELINE_EXPAND_SUCCESS:
|
||||
return appendNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next);
|
||||
case TIMELINE_UPDATE:
|
||||
|
|
|
@ -838,21 +838,10 @@
|
|||
}
|
||||
|
||||
.missing-indicator {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: lighten($ui-base-color, 16%);
|
||||
background: $ui-base-color;
|
||||
cursor: default;
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 20px + 48px;
|
||||
|
||||
& > div {
|
||||
background: url('~images/mastodon-not-found.png') no-repeat center -50px;
|
||||
padding-top: 210px;
|
||||
width: 100%;
|
||||
.regeneration-indicator__figure {
|
||||
background-image: url('~flavours/glitch/images/elephant_ui_disappointed.svg');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1162,6 +1151,7 @@ noscript {
|
|||
@import 'metadata';
|
||||
@import 'composer';
|
||||
@import 'columns';
|
||||
@import 'regeneration_indicator';
|
||||
@import 'search';
|
||||
@import 'emoji';
|
||||
@import 'doodle';
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
.regeneration-indicator {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: lighten($ui-base-color, 16%);
|
||||
background: $ui-base-color;
|
||||
cursor: default;
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
|
||||
& > div {
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&__figure {
|
||||
background: url('~flavours/glitch/images/elephant_ui_working.svg') no-repeat center 0;
|
||||
width: 100%;
|
||||
height: 160px;
|
||||
background-size: contain;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
&.missing-indicator {
|
||||
padding-top: 20px + 48px;
|
||||
|
||||
.regeneration-indicator__figure {
|
||||
background-image: url('~flavours/glitch/images/elephant_ui_disappointed.svg');
|
||||
}
|
||||
}
|
||||
|
||||
&__label {
|
||||
margin-top: 200px;
|
||||
|
||||
strong {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
color: lighten($ui-base-color, 34%);
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 24 KiB |
1
app/javascript/images/elephant_ui_disappointed.svg
Normal file
1
app/javascript/images/elephant_ui_disappointed.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 11 KiB |
1
app/javascript/images/elephant_ui_working.svg
Normal file
1
app/javascript/images/elephant_ui_working.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 8.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 19 KiB |
|
@ -19,13 +19,14 @@ export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
|
|||
|
||||
export const TIMELINE_CONTEXT_UPDATE = 'CONTEXT_UPDATE';
|
||||
|
||||
export function refreshTimelineSuccess(timeline, statuses, skipLoading, next) {
|
||||
export function refreshTimelineSuccess(timeline, statuses, skipLoading, next, partial) {
|
||||
return {
|
||||
type: TIMELINE_REFRESH_SUCCESS,
|
||||
timeline,
|
||||
statuses,
|
||||
skipLoading,
|
||||
next,
|
||||
partial,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -88,7 +89,7 @@ export function refreshTimeline(timelineId, path, params = {}) {
|
|||
return function (dispatch, getState) {
|
||||
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
|
||||
|
||||
if (timeline.get('isLoading') || timeline.get('online')) {
|
||||
if (timeline.get('isLoading') || (timeline.get('online') && !timeline.get('isPartial'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -104,8 +105,12 @@ export function refreshTimeline(timelineId, path, params = {}) {
|
|||
dispatch(refreshTimelineRequest(timelineId, skipLoading));
|
||||
|
||||
api(getState).get(path, { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null));
|
||||
if (response.status === 206) {
|
||||
dispatch(refreshTimelineSuccess(timelineId, [], skipLoading, null, true));
|
||||
} else {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null, false));
|
||||
}
|
||||
}).catch(error => {
|
||||
dispatch(refreshTimelineFail(timelineId, error, skipLoading));
|
||||
});
|
||||
|
|
|
@ -2,9 +2,14 @@ import React from 'react';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
const MissingIndicator = () => (
|
||||
<div className='missing-indicator'>
|
||||
<div className='regeneration-indicator missing-indicator'>
|
||||
<div>
|
||||
<FormattedMessage id='missing_indicator.label' defaultMessage='Not found' />
|
||||
<div className='regeneration-indicator__figure' />
|
||||
|
||||
<div className='regeneration-indicator__label'>
|
||||
<FormattedMessage id='missing_indicator.label' tagName='strong' defaultMessage='Not found' />
|
||||
<FormattedMessage id='missing_indicator.sublabel' defaultMessage='This resource could not be found' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
|||
import StatusContainer from '../containers/status_container';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ScrollableList from './scrollable_list';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
export default class StatusList extends ImmutablePureComponent {
|
||||
|
||||
|
@ -16,6 +17,7 @@ export default class StatusList extends ImmutablePureComponent {
|
|||
trackScroll: PropTypes.bool,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
isLoading: PropTypes.bool,
|
||||
isPartial: PropTypes.bool,
|
||||
hasMore: PropTypes.bool,
|
||||
prepend: PropTypes.node,
|
||||
emptyMessage: PropTypes.node,
|
||||
|
@ -48,8 +50,23 @@ export default class StatusList extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { statusIds, ...other } = this.props;
|
||||
const { isLoading } = other;
|
||||
const { statusIds, ...other } = this.props;
|
||||
const { isLoading, isPartial } = other;
|
||||
|
||||
if (isPartial) {
|
||||
return (
|
||||
<div className='regeneration-indicator'>
|
||||
<div>
|
||||
<div className='regeneration-indicator__figure' />
|
||||
|
||||
<div className='regeneration-indicator__label'>
|
||||
<FormattedMessage id='regeneration_indicator.label' tagName='strong' defaultMessage='Loading…' />
|
||||
<FormattedMessage id='regeneration_indicator.sublabel' defaultMessage='Your home feed is being prepared!' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const scrollableContent = (isLoading || statusIds.size > 0) ? (
|
||||
statusIds.map((statusId) => (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { expandHomeTimeline } from '../../actions/timelines';
|
||||
import { expandHomeTimeline, refreshHomeTimeline } from '../../actions/timelines';
|
||||
import PropTypes from 'prop-types';
|
||||
import StatusListContainer from '../ui/containers/status_list_container';
|
||||
import Column from '../../components/column';
|
||||
|
@ -16,6 +16,7 @@ const messages = defineMessages({
|
|||
|
||||
const mapStateToProps = state => ({
|
||||
hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0,
|
||||
isPartial: state.getIn(['timelines', 'home', 'isPartial'], false),
|
||||
});
|
||||
|
||||
@connect(mapStateToProps)
|
||||
|
@ -26,6 +27,7 @@ export default class HomeTimeline extends React.PureComponent {
|
|||
dispatch: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
hasUnread: PropTypes.bool,
|
||||
isPartial: PropTypes.bool,
|
||||
columnId: PropTypes.string,
|
||||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
@ -57,6 +59,39 @@ export default class HomeTimeline extends React.PureComponent {
|
|||
this.props.dispatch(expandHomeTimeline());
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this._checkIfReloadNeeded(false, this.props.isPartial);
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
this._checkIfReloadNeeded(prevProps.isPartial, this.props.isPartial);
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
this._stopPolling();
|
||||
}
|
||||
|
||||
_checkIfReloadNeeded (wasPartial, isPartial) {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
if (wasPartial === isPartial) {
|
||||
return;
|
||||
} else if (!wasPartial && isPartial) {
|
||||
this.polling = setInterval(() => {
|
||||
dispatch(refreshHomeTimeline());
|
||||
}, 3000);
|
||||
} else if (wasPartial && !isPartial) {
|
||||
this._stopPolling();
|
||||
}
|
||||
}
|
||||
|
||||
_stopPolling () {
|
||||
if (this.polling) {
|
||||
clearInterval(this.polling);
|
||||
this.polling = null;
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { intl, hasUnread, columnId, multiColumn } = this.props;
|
||||
const pinned = !!columnId;
|
||||
|
|
|
@ -120,13 +120,17 @@ export default class ListTimeline extends React.PureComponent {
|
|||
if (typeof list === 'undefined') {
|
||||
return (
|
||||
<Column>
|
||||
<LoadingIndicator />
|
||||
<div className='scrollable'>
|
||||
<LoadingIndicator />
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
} else if (list === false) {
|
||||
return (
|
||||
<Column>
|
||||
<MissingIndicator />
|
||||
<div className='scrollable'>
|
||||
<MissingIndicator />
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ const makeMapStateToProps = () => {
|
|||
const mapStateToProps = (state, { timelineId }) => ({
|
||||
statusIds: getStatusIds(state, { type: timelineId }),
|
||||
isLoading: state.getIn(['timelines', timelineId, 'isLoading'], true),
|
||||
isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false),
|
||||
hasMore: !!state.getIn(['timelines', timelineId, 'next']),
|
||||
});
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
"column_header.unpin": "Desafixar",
|
||||
"column_subheading.navigation": "Navegação",
|
||||
"column_subheading.settings": "Configurações",
|
||||
"compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.",
|
||||
"compose_form.hashtag_warning": "Esse toot não será listado em nenhuma hashtag por ser não listado. Somente toots públicos podem ser pesquisados por hashtag.",
|
||||
"compose_form.lock_disclaimer": "A sua conta não está {locked}. Qualquer pessoa pode te seguir e visualizar postagens direcionadas a apenas seguidores.",
|
||||
"compose_form.lock_disclaimer.lock": "trancada",
|
||||
"compose_form.placeholder": "No que você está pensando?",
|
||||
|
@ -223,7 +223,7 @@
|
|||
"status.media_hidden": "Mídia escondida",
|
||||
"status.mention": "Mencionar @{name}",
|
||||
"status.more": "Mais",
|
||||
"status.mute": "Mute @{name}",
|
||||
"status.mute": "Silenciar @{name}",
|
||||
"status.mute_conversation": "Silenciar conversa",
|
||||
"status.open": "Expandir",
|
||||
"status.pin": "Fixar no perfil",
|
||||
|
|
|
@ -195,8 +195,8 @@
|
|||
"privacy.private.short": "Iba sledujúci",
|
||||
"privacy.public.long": "Pošli všetkým",
|
||||
"privacy.public.short": "Verejne",
|
||||
"privacy.unlisted.long": "Neposielať verejne",
|
||||
"privacy.unlisted.short": "Nie je v zozname",
|
||||
"privacy.unlisted.long": "Neposielať do verejných časových osí",
|
||||
"privacy.unlisted.short": "Verejne mimo osí",
|
||||
"relative_time.days": "{number}d",
|
||||
"relative_time.hours": "{number}h",
|
||||
"relative_time.just_now": "now",
|
||||
|
|
|
@ -30,7 +30,7 @@ const initialTimeline = ImmutableMap({
|
|||
items: ImmutableList(),
|
||||
});
|
||||
|
||||
const normalizeTimeline = (state, timeline, statuses, next) => {
|
||||
const normalizeTimeline = (state, timeline, statuses, next, isPartial) => {
|
||||
const oldIds = state.getIn([timeline, 'items'], ImmutableList());
|
||||
const ids = ImmutableList(statuses.map(status => status.get('id'))).filter(newId => !oldIds.includes(newId));
|
||||
const wasLoaded = state.getIn([timeline, 'loaded']);
|
||||
|
@ -41,6 +41,7 @@ const normalizeTimeline = (state, timeline, statuses, next) => {
|
|||
mMap.set('isLoading', false);
|
||||
if (!hadNext) mMap.set('next', next);
|
||||
mMap.set('items', wasLoaded ? ids.concat(oldIds) : ids);
|
||||
mMap.set('isPartial', isPartial);
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -124,7 +125,7 @@ export default function timelines(state = initialState, action) {
|
|||
case TIMELINE_EXPAND_FAIL:
|
||||
return state.update(action.timeline, initialTimeline, map => map.set('isLoading', false));
|
||||
case TIMELINE_REFRESH_SUCCESS:
|
||||
return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next);
|
||||
return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial);
|
||||
case TIMELINE_EXPAND_SUCCESS:
|
||||
return appendNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next);
|
||||
case TIMELINE_UPDATE:
|
||||
|
|
|
@ -2303,7 +2303,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.missing-indicator {
|
||||
.regeneration-indicator {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
|
@ -2314,11 +2314,46 @@
|
|||
flex: 1 1 auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
|
||||
& > div {
|
||||
background: url('~images/mastodon-not-found.png') no-repeat center -50px;
|
||||
padding-top: 210px;
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&__figure {
|
||||
background: url('~images/elephant_ui_working.svg') no-repeat center 0;
|
||||
width: 100%;
|
||||
height: 160px;
|
||||
background-size: contain;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
&.missing-indicator {
|
||||
padding-top: 20px + 48px;
|
||||
|
||||
.regeneration-indicator__figure {
|
||||
background-image: url('~images/elephant_ui_disappointed.svg');
|
||||
}
|
||||
}
|
||||
|
||||
&__label {
|
||||
margin-top: 200px;
|
||||
|
||||
strong {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
color: lighten($ui-base-color, 34%);
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2749,7 +2784,6 @@
|
|||
@keyframes heartbeat {
|
||||
from {
|
||||
transform: scale(1);
|
||||
transform-origin: center center;
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
|
||||
|
@ -2775,6 +2809,7 @@
|
|||
}
|
||||
|
||||
.pulse-loading {
|
||||
transform-origin: center center;
|
||||
animation: heartbeat 1.5s ease-in-out infinite both;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class NotifyService < BaseService
|
|||
end
|
||||
|
||||
def response_to_recipient?
|
||||
@notification.target_status.in_reply_to_account_id == @recipient.id
|
||||
@notification.target_status.in_reply_to_account_id == @recipient.id && @notification.target_status.thread&.direct_visibility?
|
||||
end
|
||||
|
||||
def optional_non_following_and_direct?
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
class PrecomputeFeedService < BaseService
|
||||
def call(account)
|
||||
FeedManager.instance.populate_feed(account)
|
||||
Redis.current.del("account:#{account.id}:regeneration")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
class RegenerationWorker
|
||||
include Sidekiq::Worker
|
||||
|
||||
sidekiq_options queue: 'pull', backtrace: true, unique: :until_executed
|
||||
sidekiq_options unique: :until_executed
|
||||
|
||||
def perform(account_id, _ = :home)
|
||||
account = Account.find(account_id)
|
||||
|
|
|
@ -265,12 +265,18 @@ ca:
|
|||
unresolved: No resolt
|
||||
view: Visualització
|
||||
settings:
|
||||
activity_api_enabled:
|
||||
desc_html: Compte d'estatus publicats localment, usuaris actius i registres nous en cubs setmanals
|
||||
title: Publica estadístiques agregades sobre l'activitat de l'usuari
|
||||
bootstrap_timeline_accounts:
|
||||
desc_html: Separa diversos noms d'usuari amb comes. Només funcionaran els comptes locals i desbloquejats. El valor predeterminat quan està buit és tots els administradors locals..
|
||||
title: El seguiment per defecte per als nous usuaris
|
||||
contact_information:
|
||||
email: Introdueix una adreça de correu electrònic pùblica
|
||||
username: Introdueix un nom d'usuari
|
||||
peers_api_enabled:
|
||||
desc_html: Els noms de domini que ha trobat aquesta instància al fediverse
|
||||
title: Publica la llista d'instàncies descobertes
|
||||
registrations:
|
||||
closed_message:
|
||||
desc_html: Apareix en la primera pàgina quan es tanquen els registres<br>Pots utilitzar etiquetes HTML
|
||||
|
@ -345,7 +351,7 @@ ca:
|
|||
warning: Aneu amb compte amb aquestes dades. No ho compartiu mai amb ningú!
|
||||
your_token: El token d'accés
|
||||
auth:
|
||||
agreement_html: En inscriure't, acceptes <a href="%{rules_path}">els nostres termes del servei</a> i <a href="%{terms_path}">la nostra política de privadesa</a>.
|
||||
agreement_html: En inscriure't, acceptes seguir <a href="%{rules_path}">els nostres termes del servei</a> i <a href="%{terms_path}">la nostra política de privadesa</a>.
|
||||
change_password: Canvia la contrasenya
|
||||
delete_account: Esborra el compte
|
||||
delete_account_html: Si vols esborrar el teu compte pots <a href="%{path}">fer-ho aquí</a>. Se't demanarà confirmació.
|
||||
|
@ -546,12 +552,14 @@ ca:
|
|||
blackberry: Blackberry
|
||||
chrome: Chrome
|
||||
edge: Microsoft Edge
|
||||
electron: Electron
|
||||
firefox: Firefox
|
||||
generic: Navegador desconegut
|
||||
ie: Internet Explorer
|
||||
micro_messenger: MicroMessenger
|
||||
nokia: Nokia S40 Ovi Browser
|
||||
opera: Opera
|
||||
otter: Altre
|
||||
phantom_js: PhantomJS
|
||||
qq: QQ Browser
|
||||
safari: Safari
|
||||
|
@ -596,7 +604,7 @@ ca:
|
|||
open_in_web: Obre en la web
|
||||
over_character_limit: Límit de caràcters de %{max} superat
|
||||
pin_errors:
|
||||
limit: S'han fixat massa toots
|
||||
limit: Ja has fixat el màxim nombre de toots
|
||||
ownership: El toot d'algú altre no es pot fixar
|
||||
private: No es pot fixar el toot no públic
|
||||
reblog: No es pot fixar un impuls
|
||||
|
|
|
@ -17,11 +17,32 @@ ca:
|
|||
unconfirmed: Has de confirmar l'adreça de correu electrònic abans de continuar.
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
action: Verificar l'adreça de correu
|
||||
explanation: Has creat un compte a %{host} amb aquesta adreça de correu electrònic. Estàs a un sol clic de l'activació. Si no fos així, ignora aquest correu electrònic.
|
||||
extra_html: Si us plau consulta també <a href="%{terms_path}"> les regles de la instància</a> i <a href="%{policy_path}"> les nostres condicions de servei</a>.
|
||||
subject: 'Mastodon: Instruccions de confirmació'
|
||||
title: Verifica l'adreça de correu
|
||||
email_changed:
|
||||
explanation: 'L''adreça de correu del teu compte s''està canviant a:'
|
||||
extra: Si no has canviat el teu correu electrònic, és probable que algú hagi accedit al teu compte. Si us plau, canvia la contrasenya immediatament o posa't en contacte amb l'administrador de l'instància si no pots accedir al teu compte.
|
||||
subject: 'Mastodon: s''ha canviat l''adreça electrònica'
|
||||
title: Nova adreça de correu electrònic
|
||||
password_change:
|
||||
explanation: S'ha canviat la contrasenya del teu compte.
|
||||
extra: Si no has canviat el teu correu electrònic, és probable que algú hagi accedit al teu compte. Si us plau, canvia la contrasenya immediatament o posa't en contacte amb l'administrador de l'instància si no pots accedir al teu compte.
|
||||
subject: 'Mastodon: Contrasenya canviada'
|
||||
title: Contrasenya canviada
|
||||
reconfirmation_instructions:
|
||||
explanation: Confirma la nova adreça per canviar el teu correu electrònic.
|
||||
extra: Si no has iniciat aquest canvi, ignora aquest correu electrònic. L'adreça electrònica del compte de Mastodon no canviarà fins que accedeixis a l'enllaç de dalt.
|
||||
subject: 'Mastodon: Confirma el correu electrònic per a %{instance}'
|
||||
title: Verifica l'adreça de correu electrònic
|
||||
reset_password_instructions:
|
||||
action: Canviar contrasenya
|
||||
explanation: Has sol·licitat una contrasenya nova per al teu compte.
|
||||
extra: Si no ho has sol·licitat, ignora aquest correu electrònic. La teva contrasenya no canviarà fins que accedeixis a l'enllaç de dalt i creis un de nou.
|
||||
subject: 'Mastodon: Instruccions per a reiniciar contrassenya'
|
||||
title: Contrasenya restablerta
|
||||
unlock_instructions:
|
||||
subject: 'Mastodon: Instruccions per a desblocar'
|
||||
omniauth_callbacks:
|
||||
|
|
|
@ -18,8 +18,12 @@ gl:
|
|||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: 'Mastodon: Instruccións de confirmación para %{instance}'
|
||||
email_changed:
|
||||
subject: 'Mastodon: email cambiado'
|
||||
password_change:
|
||||
subject: 'Mastodon: contrasinal cambiado'
|
||||
reconfirmation_instructions:
|
||||
subject: 'Mastodon: Confirme email para %{instance}'
|
||||
reset_password_instructions:
|
||||
subject: 'Mastodon: Instruccións para restablecer o contrasinal'
|
||||
unlock_instructions:
|
||||
|
|
|
@ -17,15 +17,32 @@ ja:
|
|||
unconfirmed: 続行するにはメールアドレスを確認する必要があります。
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
action: メールアドレスの確認
|
||||
explanation: このメールアドレスで%{host}にアカウントを作成しました。有効にするまであと一歩です。もし心当たりがない場合、申し訳ありませんがこのメールを無視してください。
|
||||
extra_html: また <a href="%{terms_path}">インスタンスのルール</a> と <a href="%{policy_path}">利用規約</a> もお読みください。
|
||||
subject: 'Mastodon: メールアドレスの確認'
|
||||
title: メールアドレスの確認
|
||||
email_changed:
|
||||
explanation: 'アカウントのメールアドレスは以下のように変更されます:'
|
||||
extra: メールアドレスの変更を行っていない場合、他の誰かがあなたのアカウントにアクセスした可能性があります。すぐにパスワードを変更するか、アカウントがロックされている場合はインスタンス管理者に連絡してください。
|
||||
subject: 'Mastodon: メールアドレスの変更'
|
||||
title: 新しいメールアドレス
|
||||
password_change:
|
||||
explanation: パスワードが変更されました。
|
||||
extra: パスワードの変更を行っていない場合、他の誰かがあなたのアカウントにアクセスした可能性があります。すぐにパスワードを変更するか、アカウントがロックされている場合はインスタンス管理者に連絡してください。
|
||||
subject: 'Mastodon: パスワードが変更されました'
|
||||
title: パスワードの変更
|
||||
reconfirmation_instructions:
|
||||
explanation: メールアドレスを変更するため新しいアドレスを確認してください。
|
||||
extra: この変更に心当たりがない場合、このメールを無視してください。上記リンク先にアクセスするまでアカウントのメールアドレスは変更されません。
|
||||
subject: 'Mastodon: %{instance}のメールを確認する'
|
||||
title: メールアドレスの確認
|
||||
reset_password_instructions:
|
||||
action: パスワードの変更
|
||||
explanation: あなたのアカウントに対しパスワードの再発行が要求されました。
|
||||
extra: この要求に心当たりがない場合、このメールを無視してください。上記リンク先にアクセスし新しいものを作成するまでパスワードは変更されません。
|
||||
subject: 'Mastodon: パスワード再発行'
|
||||
title: パスワード再発行
|
||||
unlock_instructions:
|
||||
subject: 'Mastodon: アカウントのロックの解除'
|
||||
omniauth_callbacks:
|
||||
|
|
|
@ -19,8 +19,12 @@ nl:
|
|||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: 'Mastodon: E-mail bevestigen voor %{instance}'
|
||||
email_changed:
|
||||
subject: 'Mastodon: E-mailadres is veranderd'
|
||||
password_change:
|
||||
subject: 'Mastodon: Wachtwoord veranderd'
|
||||
reconfirmation_instructions:
|
||||
subject: 'Mastodon: Bevestig het e-mailadres voor %{instance}'
|
||||
reset_password_instructions:
|
||||
subject: 'Mastodon: Wachtwoord opnieuw instellen'
|
||||
unlock_instructions:
|
||||
|
|
|
@ -17,15 +17,32 @@ pl:
|
|||
unconfirmed: Zweryfikuj adres e-mail, aby kontynuować.
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
action: Zweryfikuj adres e-mail
|
||||
explanation: Utworzyłeś konto na %{host} podając ten adres e-mail. Jedno kliknięcie dzieli Cię od aktywacji tego konta. Jeżeli to nie Ty, zignoruj ten e-mail.
|
||||
extra_html: Przeczytaj też <a href="%{terms_path}">regulamin instancji</a> i <a href="%{policy_path}">nasze zasady użytkowania</a>.
|
||||
subject: 'Mastodon: Instrukcje weryfikacji adresu e-mail'
|
||||
title: Zweryfikuj adres e-mail
|
||||
email_changed:
|
||||
explanation: 'Adres e-mail dla Twojego konta zostanie zmieniony na:'
|
||||
extra: Jeżeli nie próbowałeś zmienić adresu e-mail, prawdopodobnie ktoś uzyskał dostęp do Twojego konta. Zmień natychmiastowo hasło lub skontaktuj się z administratorem isntancji, jeżeli nie masz dostępu do konta.
|
||||
subject: 'Mastodon: Zmieniono adres e-mail'
|
||||
title: Nowy adres e-mail
|
||||
password_change:
|
||||
explanation: Hasło do Twojego konta zostało zmienione.
|
||||
extra: Jeżeli nie zmieniałeś hasła, prawdopodobnie ktoś uzyskał dostęp do Twojego konta. Zmień hasło natychmiastowo lub skontaktuj się z administratorem instancji, jeżeli nie masz dostępu do konta.
|
||||
subject: 'Mastodon: Zmieniono hasło'
|
||||
title: Zmieniono hasło
|
||||
reconfirmation_instructions:
|
||||
explanation: Potwierdź nowy adres aby zmienić e-mail.
|
||||
extra: Jeżeli nie próbowałeś zmienić e-maila, zignoruj tą wiadomość. Adres e-mail przypisany do konta Mastodona nie ulegnie zmianie, jeżeli nie użyjesz powyższego odnośniku.
|
||||
subject: 'Mastodon: Potwierdź adres e-mail na &{instance}'
|
||||
title: Zweryfikuj adres e-mail
|
||||
reset_password_instructions:
|
||||
action: Zmień hasło
|
||||
explanation: Próbowałeś uzyskać nowe hasło do swojego konta.
|
||||
extra: Jeżeli to nie Ty, zignoruj tą wiadomość. Twoje hasło nie ulegnie zmianie, jeżeli nie wykorzystasz powyższego odnośnika i nie utworzysz nowego hasła.
|
||||
subject: 'Mastodon: Instrukcje ustawienia nowego hasła'
|
||||
title: Przywracanie hasła
|
||||
unlock_instructions:
|
||||
subject: 'Mastodon: Instrukcje odblokowania konta'
|
||||
omniauth_callbacks:
|
||||
|
@ -38,7 +55,7 @@ pl:
|
|||
updated: Twoje hasło zostało zmienione. Jesteś zalogowany/a.
|
||||
updated_not_active: Twoje hasło zostało zmienione.
|
||||
registrations:
|
||||
destroyed: Twoje konto zostało anulowane. Mamy jednak nadzieję, że do nas wrócisz. Do zobaczenia!
|
||||
destroyed: Twoje konto zostało zawieszone. Mamy jednak nadzieję, że do nas wrócisz. Do zobaczenia!
|
||||
signed_up: Twoje konto zostało utworzone. Witamy!
|
||||
signed_up_but_inactive: Twoje konto zostało utworzone. Nie mogliśmy Cię jednak zalogować, ponieważ konto nie zostało jeszcze aktywowane.
|
||||
signed_up_but_locked: Twoje konto zostało utworzone. Nie mogliśmy Cię jednak zalogować, ponieważ konto jest zablokowane.
|
||||
|
|
|
@ -18,8 +18,12 @@ pt-BR:
|
|||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: 'Mastodon: Instruções de confirmação'
|
||||
email_changed:
|
||||
subject: 'Mastodon: Email alterado'
|
||||
password_change:
|
||||
subject: 'Mastodon: Senha modificada'
|
||||
reconfirmation_instructions:
|
||||
subject: 'Mastodon: Confirmar emai para %{instance}'
|
||||
reset_password_instructions:
|
||||
subject: 'Mastodon: Instruções para mudança de senha'
|
||||
unlock_instructions:
|
||||
|
|
|
@ -83,7 +83,7 @@ pl:
|
|||
invalid_grant: Grant uwierzytelnienia jest niepoprawny, przeterminowany, unieważniony, nie pasuje do URI przekierowwania użytego w żądaniu uwierzytelnienia, lub został wystawiony przez innego klienta.
|
||||
invalid_redirect_uri: URI przekierowania jest nieprawidłowy.
|
||||
invalid_request: 'Żądanie jest nieprawidłowe: brakujący parametr, niewspierana wartość parametru, lub inny błąd.'
|
||||
invalid_resource_owner: Dostarczone dane uwierzytelniające właściciela zasobu są niepoprawne, lub właściciel zasobu nie może zostać znaleziony.
|
||||
invalid_resource_owner: Dostarczone dane uwierzytelniające właściciela zasobu są niepoprawne, lub właściciel zasobu nie może zostać znaleziony
|
||||
invalid_scope: Zakres żądania jest niepoprawny, nieznany, lub błędnie zbudowany.
|
||||
invalid_token:
|
||||
expired: Token dostępowy wygasł
|
||||
|
|
|
@ -265,12 +265,18 @@ gl:
|
|||
unresolved: Non resolto
|
||||
view: Vista
|
||||
settings:
|
||||
activity_api_enabled:
|
||||
desc_html: Conta de estados publicados localmente, usuarias activas, e novos rexistros por semana
|
||||
title: Publicar estatísticas agregadas sobre a actividade da usuaria
|
||||
bootstrap_timeline_accounts:
|
||||
desc_html: Separar múltiples nomes de usuaria con vírgulas. Só funcionarán as contas locais non bloqueadas. Si baldeiro, por omisión son todos os local admin.
|
||||
title: Seguimentos por omisión para novas usuarias
|
||||
contact_information:
|
||||
email: e-mail de traballo
|
||||
username: Nome de usuaria de contacto
|
||||
peers_api_enabled:
|
||||
desc_html: Nome de dominio que esta instancia atopou no fediverso
|
||||
title: Publicar lista de instancias descubertas
|
||||
registrations:
|
||||
closed_message:
|
||||
desc_html: Mostrado na páxina de portada cando o rexistro está pechado. Pode utilizar etiquetas HTML
|
||||
|
@ -509,6 +515,7 @@ gl:
|
|||
quadrillion: Q
|
||||
thousand: K
|
||||
trillion: T
|
||||
unit: " "
|
||||
pagination:
|
||||
next: Seguinte
|
||||
prev: Previo
|
||||
|
|
|
@ -338,10 +338,13 @@ ja:
|
|||
body: "%{reporter} が %{target} を通報しました"
|
||||
subject: "%{instance} の新しい通報 (#%{id})"
|
||||
application_mailer:
|
||||
notification_preferences: メール設定の変更
|
||||
salutation: "%{name} さん"
|
||||
settings: 'メール設定の変更: %{link}'
|
||||
signature: Mastodon %{instance} インスタンスからの通知
|
||||
view: 'リンク:'
|
||||
view_profile: プロフィールを表示
|
||||
view_status: トゥートを表示
|
||||
applications:
|
||||
created: アプリが作成されました
|
||||
destroyed: アプリが削除されました
|
||||
|
@ -491,29 +494,38 @@ ja:
|
|||
title: モデレーション
|
||||
notification_mailer:
|
||||
digest:
|
||||
action: 全ての通知を表示
|
||||
body: "%{instance} での最後のログインからの出来事:"
|
||||
mention: "%{name} さんがあなたに返信しました:"
|
||||
new_followers_summary:
|
||||
one: 新たなフォロワーを獲得しました!
|
||||
other: "%{count} 人の新たなフォロワーを獲得しました!"
|
||||
one: また、離れている間に新たなフォロワーを獲得しました!
|
||||
other: また、離れている間に%{count} 人の新たなフォロワーを獲得しました!
|
||||
subject:
|
||||
one: "新しい1件の通知 \U0001F418"
|
||||
other: "新しい%{count}件の通知 \U0001F418"
|
||||
title: 不在の間に…
|
||||
favourite:
|
||||
body: "%{name} さんにお気に入り登録された、あなたのトゥートがあります:"
|
||||
subject: "%{name} さんにお気に入りに登録されました"
|
||||
title: 新たなお気に入り登録
|
||||
follow:
|
||||
body: "%{name} さんにフォローされています!"
|
||||
subject: "%{name} さんにフォローされています"
|
||||
title: 新たなフォロワー
|
||||
follow_request:
|
||||
action: フォローリクエストの管理
|
||||
body: "%{name} さんがあなたにフォローをリクエストしました"
|
||||
subject: "%{name} さんからのフォローリクエスト"
|
||||
title: 新たなフォローリクエスト
|
||||
mention:
|
||||
action: 返信
|
||||
body: "%{name} さんから返信がありました:"
|
||||
subject: "%{name} さんに返信されました"
|
||||
title: 新たな返信
|
||||
reblog:
|
||||
body: "%{name} さんにブーストされた、あなたのトゥートがあります:"
|
||||
subject: "%{name} さんにブーストされました"
|
||||
title: 新たなブースト
|
||||
number:
|
||||
human:
|
||||
decimal_units:
|
||||
|
|
|
@ -265,12 +265,18 @@ nl:
|
|||
unresolved: Onopgelost
|
||||
view: Weergeven
|
||||
settings:
|
||||
activity_api_enabled:
|
||||
desc_html: Wekelijks overzicht van de hoeveelheid lokale toots, actieve gebruikers en nieuwe registraties
|
||||
title: Statistieken over gebruikersactiviteit publiceren
|
||||
bootstrap_timeline_accounts:
|
||||
desc_html: Meerdere gebruikersnamen met komma's scheiden. Alleen lokale en niet opgeschorte accounts werken. Laat leeg voor alle lokale beheerders.
|
||||
title: Standaard te volgen accounts voor nieuwe gebruikers
|
||||
contact_information:
|
||||
email: Vul een openbaar gebruikt e-mailadres in
|
||||
username: Vul een gebruikersnaam in
|
||||
peers_api_enabled:
|
||||
desc_html: Domeinnamen die deze server in de fediverse is tegengekomen
|
||||
title: Lijst van bekende servers publiceren
|
||||
registrations:
|
||||
closed_message:
|
||||
desc_html: Wordt op de voorpagina weergegeven wanneer registratie van nieuwe accounts is uitgeschakeld<br>En ook hier kan je HTML gebruiken
|
||||
|
@ -476,11 +482,11 @@ nl:
|
|||
title: Moderatie
|
||||
notification_mailer:
|
||||
digest:
|
||||
body: 'Hier is een korte samenvatting van wat je hebt gemist op %{instance} sinds jouw laatste bezoek op %{since}:'
|
||||
body: Hier is een korte samenvatting van de berichten die je sinds jouw laatste bezoek op %{since} hebt gemist
|
||||
mention: "%{name} vermeldde jou in:"
|
||||
new_followers_summary:
|
||||
one: Jij hebt een nieuwe volger! Hoera!
|
||||
other: Jij hebt %{count} nieuwe volgers! Prachtig!
|
||||
one: Je hebt trouwens sinds je weg was er ook een nieuwe volger bijgekregen! Hoera!
|
||||
other: Je hebt trouwens sinds je weg was er ook %{count} nieuwe volgers bijgekregen! Fantastisch!
|
||||
subject:
|
||||
one: "1 nieuwe melding sinds jouw laatste bezoek \U0001F418"
|
||||
other: "%{count} nieuwe meldingen sinds jouw laatste bezoek \U0001F418"
|
||||
|
|
|
@ -46,7 +46,7 @@ pl:
|
|||
posts: Wpisy
|
||||
posts_with_replies: Wpisy z odpowiedziami
|
||||
remote_follow: Śledź zdalnie
|
||||
reserved_username: Ta nazwa użytkownika jest zarezerwowana.
|
||||
reserved_username: Ta nazwa użytkownika jest zarezerwowana
|
||||
roles:
|
||||
admin: Administrator
|
||||
moderator: Moderator
|
||||
|
@ -183,7 +183,7 @@ pl:
|
|||
title: Niestandardowe emoji
|
||||
unlisted: Niewidoczne
|
||||
update_failed_msg: Nie udało się zaktualizować emoji
|
||||
updated_msg: Pomyślnie zaktualizowano emoji
|
||||
updated_msg: Pomyślnie zaktualizowano emoji!
|
||||
upload: Dodaj
|
||||
domain_blocks:
|
||||
add_new: Dodaj nową
|
||||
|
@ -194,7 +194,7 @@ pl:
|
|||
create: Utwórz blokadę
|
||||
hint: Blokada domen nie zabroni tworzenia wpisów kont w bazie danych, ale pozwoli na automatyczną moderację kont do nich należących.
|
||||
severity:
|
||||
desc_html: "<strong>Wyciszenie</strong> uczyni wpisy użytkownika widoczne tylko dla osób, które go śledzą. <strong>Zawieszenie</strong> spowoduje usunięcie całej zawartości dodanej przez użytkownika."
|
||||
desc_html: "<strong>Wyciszenie</strong> uczyni wpisy użytkownika widoczne tylko dla osób, które go śledzą. <strong>Zawieszenie</strong> spowoduje usunięcie całej zawartości dodanej przez użytkownika. Użyj <strong>Żadne</strong>, jeżeli chcesz jedynie odrzucać zawartość multimedialną."
|
||||
noop: Nic nie rób
|
||||
silence: Wycisz
|
||||
suspend: Zawieś
|
||||
|
@ -305,7 +305,7 @@ pl:
|
|||
title: Niestandardowe zasady użytkowania
|
||||
site_title: Nazwa instancji
|
||||
thumbnail:
|
||||
desc_html: 'Używana w podglądzie przez OpenGraph i API. Zalecany rozmiar: 1200x630 pikseli.'
|
||||
desc_html: 'Używana w podglądzie przez OpenGraph i API. Zalecany rozmiar: 1200x630 pikseli'
|
||||
title: Miniatura instancji
|
||||
timeline_preview:
|
||||
desc_html: Wyświetlaj publiczną oś czasu na stronie widocznej dla niezalogowanych
|
||||
|
@ -339,10 +339,12 @@ pl:
|
|||
body: Użytkownik %{reporter} zgłosił %{target}
|
||||
subject: Nowe zgłoszenie na %{instance} (#%{id})
|
||||
application_mailer:
|
||||
notification_preferences: Zmień ustawienia e-maili
|
||||
salutation: "%{name},"
|
||||
settings: 'Zmień ustawienia powiadamiania: %{link}'
|
||||
signature: Powiadomienie Mastodona z instancji %{instance}
|
||||
view: 'Zobacz:'
|
||||
view_status: Wyświetl wpis
|
||||
applications:
|
||||
created: Pomyślnie utworzono aplikację
|
||||
destroyed: Pomyślnie usunięto aplikację
|
||||
|
@ -494,33 +496,42 @@ pl:
|
|||
title: Moderacja
|
||||
notification_mailer:
|
||||
digest:
|
||||
body: 'Oto krótkie podsumowanie co Cię ominęło na %{instance} od Twojej ostatniej wizyty (%{since}):'
|
||||
action: Wyświetl wszystkie powiadomienia
|
||||
body: Oto krótkie podsumowanie wiadomości, które ominęły Cię od Twojej ostatniej wizyty (%{since})
|
||||
mention: "%{name} wspomniał o Tobie w:"
|
||||
new_followers_summary:
|
||||
few: "(%{count}) nowe osoby śledzą Cię!"
|
||||
many: "(%{count}) nowych osób Cię śledzi! Wspaniale!"
|
||||
one: Śledzi Cię nowa osoba! Gratulacje!
|
||||
other: "(%{count}) nowych osób Cię śledzi! Wspaniale!"
|
||||
one: Dodatkowo, w czasie nieobecności zaczęła śledzić Cię jedna osoba Gratulacje!
|
||||
other: Dodatkowo, zaczęło Cię śledzić %{count} nowych osób! Wspaniale!
|
||||
subject:
|
||||
few: "%{count} nowe powiadomienia od Twojej ostatniej wizyty \U0001F418"
|
||||
many: "%{count} nowych powiadomień od Twojej ostatniej wizyty \U0001F418"
|
||||
one: "1 nowe powiadomienie od Twojej ostatniej wizyty \U0001F418"
|
||||
other: "%{count} nowych powiadomień od Twojej ostatniej wizyty \U0001F418"
|
||||
title: W trakcie Twojej nieobecności…
|
||||
favourite:
|
||||
body: 'Twój wpis został polubiony przez %{name}:'
|
||||
subject: "%{name} lubi Twój wpis"
|
||||
title: Nowe polubienie
|
||||
follow:
|
||||
body: "%{name} Cię śledzi!"
|
||||
subject: "%{name} Cię śledzi"
|
||||
title: Nowy śledzący
|
||||
follow_request:
|
||||
action: Zarządzaj prośbami o możliwość śledzenia
|
||||
body: "%{name} poprosił o możliwość śledzenia Cię"
|
||||
subject: 'Prośba o możliwość śledzenia: %{name}'
|
||||
title: Nowa prośba o możliwość śledzenia
|
||||
mention:
|
||||
action: Odpowiedz
|
||||
body: "%{name} wspomniał o Tobie w:"
|
||||
subject: "%{name} wspomniał o Tobie"
|
||||
title: Nowe wspomnienie o Tobie
|
||||
reblog:
|
||||
body: 'Twój wpis został podbity przez %{name}:'
|
||||
subject: Twój wpis został podbity przez %{name}
|
||||
title: Nowe podbicie
|
||||
number:
|
||||
human:
|
||||
decimal_units:
|
||||
|
@ -568,12 +579,14 @@ pl:
|
|||
blackberry: Blackberry
|
||||
chrome: Chrome
|
||||
edge: Microsoft Edge
|
||||
electron: Electron
|
||||
firefox: Firefox
|
||||
generic: nieznana przeglądarka
|
||||
ie: Internet Explorer
|
||||
micro_messenger: MicroMessenger
|
||||
nokia: Nokia S40 Ovi Browser
|
||||
opera: Opera
|
||||
otter: Przeglądarka Otter
|
||||
phantom_js: PhantomJS
|
||||
qq: QQ Browser
|
||||
safari: Safari
|
||||
|
|
|
@ -265,12 +265,18 @@ pt-BR:
|
|||
unresolved: Não resolvido
|
||||
view: Visualizar
|
||||
settings:
|
||||
activity_api_enabled:
|
||||
desc_html: Contagem de status postados localmente, usuários ativos e novos cadastros filtrados semanalmente
|
||||
title: Publicar estatísticas agregadas sobre atividade de usuários
|
||||
bootstrap_timeline_accounts:
|
||||
desc_html: Separe nomes de usuário através de vírgulas. Funciona apenas com contas locais e destrancadas. O padrão quando vazio são todos os administradores locais.
|
||||
title: Usuários a serem seguidos por padrão por novas contas
|
||||
contact_information:
|
||||
email: E-mail
|
||||
username: Contate usuário
|
||||
peers_api_enabled:
|
||||
desc_html: Nomes de domínio que essa instância encontrou no fediverso
|
||||
title: Publicar lista de instâncias descobertas
|
||||
registrations:
|
||||
closed_message:
|
||||
desc_html: Exibido na página inicial quando cadastros estão fechados. Você pode usar tags HTML
|
||||
|
@ -285,7 +291,7 @@ pt-BR:
|
|||
desc_html: Permitir que qualquer um crie uma conta
|
||||
title: Cadastro aberto
|
||||
show_staff_badge:
|
||||
desc_html: Mostrar uma insígnia de equipe na página de usuário
|
||||
desc_html: Mostrar uma insígnia de Equipe na página de usuário
|
||||
title: Mostrar insígnia de equipe
|
||||
site_description:
|
||||
desc_html: Parágrafo introdutório na página inicial e em meta tags. Você pode usar tags HTML, em especial <code><a></code> e <code><em></code>.
|
||||
|
@ -345,7 +351,7 @@ pt-BR:
|
|||
warning: Tenha cuidado com estes dados. Nunca compartilhe com alguém!
|
||||
your_token: Seu token de acesso
|
||||
auth:
|
||||
agreement_html: Cadastrando-se você concorda em seguir <a href="%{rules_path}">as regras da instância</a> e <a href="%{terms_path}">os nossos termos de serviço</a>.
|
||||
agreement_html: Ao se cadastrar você concorda em seguir <a href="%{rules_path}">as regras da instância</a> e <a href="%{terms_path}">os nossos termos de serviço</a>.
|
||||
change_password: Segurança
|
||||
delete_account: Excluir conta
|
||||
delete_account_html: Se você deseja excluir a sua conta, você pode <a href="%{path}">prosseguir para cá</a>. Uma confirmação será requisitada.
|
||||
|
@ -596,7 +602,7 @@ pt-BR:
|
|||
open_in_web: Abrir na web
|
||||
over_character_limit: limite de caracteres de %{max} excedido
|
||||
pin_errors:
|
||||
limit: Você já fixou o máximo de toots possíveis
|
||||
limit: Você já fixou a quantidade máxima de toots
|
||||
ownership: Toots de outras pessoas não podem ser fixados
|
||||
private: Toot não-público não pode ser fixado
|
||||
reblog: Um compartilhamento não pode ser fixado
|
||||
|
|
|
@ -49,6 +49,7 @@ ru:
|
|||
reserved_username: Имя пользователя зарезервировано
|
||||
roles:
|
||||
admin: Администратор
|
||||
moderator: Мод
|
||||
unfollow: Отписаться
|
||||
admin:
|
||||
account_moderation_notes:
|
||||
|
@ -71,6 +72,8 @@ ru:
|
|||
domain: Домен
|
||||
edit: Изменить
|
||||
email: E-mail
|
||||
enable: Включить
|
||||
enabled: Включен
|
||||
feed_url: URL фида
|
||||
followers: Подписчики
|
||||
followers_url: URL подписчиков
|
||||
|
@ -336,10 +339,12 @@ ru:
|
|||
body: "%{reporter} подал(а) жалобу на %{target}"
|
||||
subject: Новая жалоба, узел %{instance} (#%{id})
|
||||
application_mailer:
|
||||
notification_preferences: Изменить настройки e-mail
|
||||
salutation: "%{name},"
|
||||
settings: 'Изменить настройки e-mail: %{link}'
|
||||
signature: Уведомления Mastodon от %{instance}
|
||||
view: 'Просмотр:'
|
||||
view_status: Просмотреть статус
|
||||
applications:
|
||||
created: Приложение успешно создано
|
||||
destroyed: Приложение успешно удалено
|
||||
|
@ -349,7 +354,7 @@ ru:
|
|||
warning: Будьте очень внимательны с этими данными. Не делитесь ими ни с кем!
|
||||
your_token: Ваш токен доступа
|
||||
auth:
|
||||
agreement_html: Создавая аккаунт, вы соглашаетесь с <a href="%{rules_path}">нашими правилами поведения</a> и <a href="%{terms_path}">политикой конфиденциальности</a>.
|
||||
agreement_html: Создавая аккаунт, вы соглашаетесь с <a href="%{rules_path}">правилами узла</a> и <a href="%{terms_path}">нашими условиями обслуживания</a>.
|
||||
change_password: Изменить пароль
|
||||
delete_account: Удалить аккаунт
|
||||
delete_account_html: Если Вы хотите удалить свой аккаунт, вы можете <a href="%{path}">перейти сюда</a>. У Вас будет запрошено подтверждение.
|
||||
|
@ -554,6 +559,7 @@ ru:
|
|||
blackberry: Blackberry
|
||||
chrome: Chrome
|
||||
edge: Microsoft Edge
|
||||
electron: Electron
|
||||
firefox: Firefox
|
||||
generic: Неизвестный браузер
|
||||
ie: Internet Explorer
|
||||
|
|
|
@ -4,7 +4,7 @@ ca:
|
|||
hints:
|
||||
defaults:
|
||||
avatar: PNG, GIF o JPG. Màxim 2MB. Serà escalat a 120x120px
|
||||
digest: S'envia després d'un llarg període d'inactivitat amb un resum de les mencions que has rebut en la teva absència
|
||||
digest: Només s'envia després d'un llarg període d'inactivitat amb un resum de les mencions que has rebut en la teva absència
|
||||
display_name:
|
||||
one: <span class="name-counter">1</span> càracter
|
||||
other: <span class="name-counter">%{count}</span> càracters
|
||||
|
|
|
@ -4,7 +4,7 @@ fr:
|
|||
hints:
|
||||
defaults:
|
||||
avatar: Au format PNG, GIF ou JPG. 2 Mo maximum. Sera réduit à 120x120px
|
||||
digest: Envoyé après une longue période d’inactivité et contient un résumé des notifications que vous avez reçues pendant votre absence
|
||||
digest: Uniquement envoyé après une longue période d’inactivité et uniquement si vous avez reçu des messages personnels pendant votre absence
|
||||
display_name:
|
||||
one: <span class="name-counter">1</span> caractère restant
|
||||
other: <span class="name-counter">%{count}</span> caractères restants
|
||||
|
|
|
@ -4,7 +4,7 @@ ja:
|
|||
hints:
|
||||
defaults:
|
||||
avatar: 2MBまでのPNGやGIF、JPGが利用可能です。120x120pxまで縮小されます
|
||||
digest: 長期間ログインしなかった際、その期間に受け取った返信の要約を受け取ることができます
|
||||
digest: 長期間使用していない場合と不在時に返信を受けた場合のみ送信されます
|
||||
display_name: あと<span class="name-counter">%{count}</span>文字入力できます。
|
||||
header: 2MBまでのPNGやGIF、JPGが利用可能です。 700x335pxまで縮小されます
|
||||
locked: フォロワーを手動で承認する必要があります
|
||||
|
|
|
@ -4,27 +4,27 @@ pl:
|
|||
hints:
|
||||
defaults:
|
||||
avatar: PNG, GIF lub JPG. Maksymalnie 2MB. Zostanie zmniejszony do 120x120px
|
||||
digest: Wysyłane po długiej nieaktywności, zawiera podsumowanie wspomnień o Twoich profilu
|
||||
digest: Wysyłane tylko po długiej nieaktywności, jeżeli w tym czasie otrzymaleś jakąś wiadomość bezpośrednią
|
||||
display_name:
|
||||
few: Pozostały <span class="name-counter">%{count}</span> znaki.
|
||||
many: Pozostało <span class="name-counter">%{count}</span> znaków
|
||||
one: Pozostał <span class="name-counter">1</span> znak.
|
||||
one: Pozostał <span class="name-counter">1</span> znak
|
||||
other: Pozostało <span class="name-counter">%{count}</span> znaków
|
||||
header: PNG, GIF lub JPG. Maksymalnie 2MB. Zostanie zmniejszony do 700x335px
|
||||
locked: Musisz akceptować prośby o śledzenie
|
||||
note:
|
||||
few: Pozostały <span class="name-counter">%{count}</span> znaki.
|
||||
many: Pozostało <span class="name-counter">%{count}</span> znaków
|
||||
one: Pozostał <span class="name-counter">1</span> znak.
|
||||
one: Pozostał <span class="name-counter">1</span> znak
|
||||
other: Pozostało <span class="name-counter">%{count}</span> znaków
|
||||
setting_noindex: Wpływa na widoczność strony profilu i Twoich wpisów
|
||||
setting_skin: Zmienia wygląd używanej odmiany Mastodona
|
||||
imports:
|
||||
data: Plik CSV wyeksportowany z innej instancji Mastodona
|
||||
sessions:
|
||||
otp: Wprowadź kod weryfikacji dwuetapowej z telefonu lub wykorzystaj jeden z kodów zapasowych
|
||||
otp: Wprowadź kod weryfikacji dwuetapowej z telefonu lub wykorzystaj jeden z kodów zapasowych.
|
||||
user:
|
||||
filtered_languages: Wpisy w wybranych językach nie będą wyświetlać się na publicznych osiach czasu.
|
||||
filtered_languages: Wpisy w wybranych językach nie będą wyświetlać się na publicznych osiach czasu
|
||||
labels:
|
||||
defaults:
|
||||
avatar: Awatar
|
||||
|
|
|
@ -30,10 +30,12 @@ sk:
|
|||
data: Dáta
|
||||
display_name: Meno
|
||||
email: Emailová adresa
|
||||
expires_in: Expirovať po
|
||||
filtered_languages: Filtrované jazyky
|
||||
header: Obrázok v hlavičke
|
||||
locale: Jazyk
|
||||
locked: Zamknúť účet
|
||||
max_uses: Maximálny počet použití
|
||||
new_password: Nové heslo
|
||||
note: O vás
|
||||
otp_attempt: Dvoj-faktorový (2FA) kód
|
||||
|
@ -44,6 +46,7 @@ sk:
|
|||
setting_default_sensitive: Označiť každý obrázok/video/súbor ako chúlostivý
|
||||
setting_delete_modal: Zobrazovať potvrdzovacie okno pred zmazaním toot-u
|
||||
setting_noindex: Nezaradzovať vaše príspevky do indexácie pre vyhľadávanie
|
||||
setting_reduce_motion: Redukovať pohyb v animáciách
|
||||
setting_system_font_ui: Použiť štandardný systémový font
|
||||
setting_theme: Vzhľad
|
||||
setting_unfollow_modal: Zobrazovať potvrdzovacie okno pred skončením sledovania iného používateľa
|
||||
|
@ -53,6 +56,7 @@ sk:
|
|||
interactions:
|
||||
must_be_follower: Blokovať notifikácie pod používateľov, ktorí vás nesledujú
|
||||
must_be_following: Blokovať notifikácie od ľudí ktorý vás nesledujú
|
||||
must_be_following_dm: Blokovať priame správy od ľudí ktorých nesleduješ
|
||||
notification_emails:
|
||||
digest: Posielať súhrnné emaily
|
||||
favourite: Poslať email ak niekto označí váš príspevok ako obľúbený
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
sk:
|
||||
about:
|
||||
about_hashtag_html: Toto sú verejné tooty otagované <strong>#%{tagom}</strong>. Ak máš účet niekde vo fediverse, môžeš ich používať.
|
||||
about_mastodon_html: Mastodon je sociálna sieť založená na otvorených webových protokoloch. Jej zrojový kód je otvorený a je decentralizovaná podobne ako email.
|
||||
about_this: Info
|
||||
closed_registrations: Registrácie sú momentálne uzatvorené. Avšak, existujú ďalšie Mastodon inštancie kde si môžete založiť účet a získať prístup do tejto siete od nich.
|
||||
|
@ -38,6 +39,7 @@ sk:
|
|||
followers: Sledujúci
|
||||
following: Sleduje
|
||||
media: Médiá
|
||||
moved_html: "%{name} účet bol presunutý na %{new_profile_link}:"
|
||||
nothing_here: Nič tu nie je!
|
||||
people_followed_by: Ľudia, ktorých %{name} sleduje
|
||||
people_who_follow: Ľudia sledujúci %{name}
|
||||
|
@ -47,17 +49,31 @@ sk:
|
|||
reserved_username: Prihlasovacie meno je rezervované
|
||||
roles:
|
||||
admin: Admin
|
||||
moderator: Mod
|
||||
unfollow: Prestať sledovať
|
||||
admin:
|
||||
account_moderation_notes:
|
||||
account: Moderátor
|
||||
create: Vytvoriť
|
||||
created_at: Dátum
|
||||
created_msg: Poznámka moderátora bola úspešne vytvorená!
|
||||
delete: Zmazať
|
||||
destroyed_msg: Poznámka moderátora bola úspešne zmazaná!
|
||||
accounts:
|
||||
are_you_sure: Ste si istý?
|
||||
by_domain: Doména
|
||||
confirm: Potvrdiť
|
||||
confirmed: Potvrdený
|
||||
demote: Degradovať
|
||||
disable: Zablokovať
|
||||
disable_two_factor_authentication: Zakázať 2FA
|
||||
disabled: Blokovaný
|
||||
display_name: Zobraziť meno
|
||||
domain: Doména
|
||||
edit: Upraviť
|
||||
email: Email
|
||||
enable: Povoliť
|
||||
enabled: Povolený
|
||||
feed_url: URL časovej osi
|
||||
followers: Sledujúci
|
||||
followers_url: URL sledujúcich
|
||||
|
@ -69,12 +85,15 @@ sk:
|
|||
local: Lokálne
|
||||
remote: Federované
|
||||
title: Lokácia
|
||||
login_status: Status prihlásenia
|
||||
media_attachments: Prílohy
|
||||
memorialize: Zmeniť na "Navždy budeme spomínať"
|
||||
moderation:
|
||||
all: Všetko
|
||||
silenced: Umlčané
|
||||
suspended: Suspendované
|
||||
title: Moderácia
|
||||
moderation_notes: Moderátorské poznámky
|
||||
most_recent_activity: Posledná aktivita
|
||||
most_recent_ip: Posledná IP
|
||||
not_subscribed: Nezaregistrované
|
||||
|
@ -85,6 +104,7 @@ sk:
|
|||
outbox_url: URL poslaných
|
||||
perform_full_suspension: Suspendovať
|
||||
profile_url: URL profilu
|
||||
promote: Povýšiť
|
||||
protocol: Protokol
|
||||
public: Verejná os
|
||||
push_subscription_expires: PuSH odoberanie expiruje
|
||||
|
@ -92,6 +112,12 @@ sk:
|
|||
reset: Reset
|
||||
reset_password: Obnoviť heslo
|
||||
resubscribe: Znovu odoberať
|
||||
role: Oprávnenia
|
||||
roles:
|
||||
admin: Administrátor
|
||||
moderator: Moderátor
|
||||
staff: Člen
|
||||
user: Používateľ
|
||||
salmon_url: Salmon URL
|
||||
search: Hľadať
|
||||
shared_inbox_url: URL zdieľanej schránky
|
||||
|
@ -108,17 +134,56 @@ sk:
|
|||
unsubscribe: Prestať odoberať
|
||||
username: Používateľske meno
|
||||
web: Web
|
||||
action_logs:
|
||||
actions:
|
||||
confirm_user: "%{name} potvrdil e-mailovú adresu používateľa %{target}"
|
||||
create_custom_emoji: "%{name} nahral nový emoji %{target}"
|
||||
create_domain_block: "%{name} zablokoval doménu %{target}"
|
||||
create_email_domain_block: "%{name} pridal e-mailovú doménu %{target} na zoznam zakázaných"
|
||||
demote_user: "%{name} degradoval používateľa %{target}"
|
||||
destroy_domain_block: "%{name} povolil doménu %{target}"
|
||||
destroy_email_domain_block: "%{name} pridal e-mailovú doménu %{target} na zoznam povolených"
|
||||
destroy_status: "%{name} zmazal status %{target}"
|
||||
disable_2fa_user: "%{name} zakázal 2FA pre používateľa %{target}"
|
||||
disable_custom_emoji: "%{name} zakázal emoji %{target}"
|
||||
disable_user: "%{name} zakázal prihlásenie pre používateľa %{target}"
|
||||
enable_custom_emoji: "%{name} povolil emoji %{target}"
|
||||
enable_user: "%{name} povolil prihlásenie pre používateľa %{target}"
|
||||
memorialize_account: '%{name} zmenil účet %{target} na stránku "Navždy budeme spomínať"'
|
||||
promote_user: "%{name} povýšil používateľa %{target}"
|
||||
reset_password_user: "%{name} resetoval heslo pre používateľa %{target}"
|
||||
resolve_report: "%{name} zamietol nahlásenie %{target}"
|
||||
silence_account: "%{name} stíšil účet %{target}"
|
||||
suspend_account: "%{name} suspendoval účet používateľa %{target}"
|
||||
unsilence_account: "%{name} zrušil stíšenie účtu používateľa %{target}"
|
||||
unsuspend_account: "%{name} zrušil suspendáciu účtu používateľa %{target}"
|
||||
update_custom_emoji: "%{name} aktualizoval emoji %{target}"
|
||||
update_status: "%{name} aktualizoval status %{target}"
|
||||
title: Audit log
|
||||
custom_emojis:
|
||||
by_domain: Doména
|
||||
copied_msg: Lokálna kópia emoji úspešne vytvorená
|
||||
copy: Kopírovať
|
||||
copy_failed_msg: Nebolo možné vytvoriť lokálnu kópiu tohto emoji
|
||||
created_msg: Emoji úspešne vytvorené!
|
||||
delete: Zmazať
|
||||
destroyed_msg: Emojo úspešne zničený!
|
||||
disable: Zakázať
|
||||
disabled_msg: Emoji bolo úspešne zakázané
|
||||
emoji: Emoji
|
||||
enable: Povoliť
|
||||
enabled_msg: Emoji bolo úspešne povolené
|
||||
image_hint: PNG do 50KB
|
||||
listed: V zozname
|
||||
new:
|
||||
title: Pridať vlastný emoji
|
||||
title: Pridať nový vlastný emoji
|
||||
overwrite: Prepísať
|
||||
shortcode: Skratka
|
||||
shortcode_hint: Aspoň 2 znaky, povolené sú alfanumerické alebo podčiarkovník
|
||||
title: Vlastné emoji
|
||||
unlisted: Nie je na zozname
|
||||
update_failed_msg: Nebolo možné aktualizovať toto emoji
|
||||
updated_msg: Emoji bolo úspešne aktualizované!
|
||||
upload: Nahrať
|
||||
domain_blocks:
|
||||
add_new: Pridať nový
|
||||
|
@ -129,16 +194,43 @@ sk:
|
|||
create: Blokovať doménu
|
||||
hint: Blokovanie domény stále dovolí vytvárať nové účty v databáze, ale tieto budú automaticky moderované.
|
||||
severity:
|
||||
desc_html: "<strong>Stíšenie</strong> urobí všetky príspevky účtu neviditeľné pre všetkých ktorý nesledujú tento účet. <strong>Suspendácia</strong> zmaže všetky príspevky, médiá a profilové informácie. Použi <strong>Nič</strong> ak chceš iba neprijímať súbory médií."
|
||||
noop: Nič
|
||||
silence: Stíšiť
|
||||
suspend: Suspendovať
|
||||
title: Nové blokovanie domény
|
||||
reject_media: Odmietať súbory s obrázkami alebo videami
|
||||
reject_media_hint: Zmaže lokálne uložené súbory médií a odmietne ich sťahovanie v budúcnosti. Irelevantné pre suspendáciu
|
||||
severities:
|
||||
noop: Nič
|
||||
silence: Stíšiť
|
||||
suspend: Suspendovať
|
||||
severity: Závažnosť
|
||||
show:
|
||||
affected_accounts:
|
||||
one: Jeden účet v databáze ovplyvnený
|
||||
other: "%{count} účtov v databáze ovplyvnených"
|
||||
retroactive:
|
||||
silence: Zrušiť stíšenie všetkých existujúcich účtov z tejto domény
|
||||
suspend: Zrušiť suspendáciu všetkých existujúcich účtov z tejto domény
|
||||
title: Zrušiť blokovanie domény pre %{domain}
|
||||
undo: Vrátiť späť
|
||||
title: Blokovanie domén
|
||||
undo: Späť
|
||||
email_domain_blocks:
|
||||
add_new: Pridať nový
|
||||
created_msg: Emailová doména bola úspešne pridaná do zoznamu zakázaných
|
||||
delete: Zmazať
|
||||
destroyed_msg: Emailová doména bola úspešne vymazaná zo zoznamu zakázaných
|
||||
domain: Doména
|
||||
new:
|
||||
create: Pridať doménu
|
||||
auth:
|
||||
login: Prihlásenie
|
||||
settings:
|
||||
authorized_apps: Autorizované aplikácie
|
||||
back: Naspäť na stránku
|
||||
users:
|
||||
invalid_email: Emailová adresa je neplatná
|
||||
invalid_otp_token: Neplatný 2FA kód
|
||||
signed_in_as: 'Prihlásený ako:'
|
||||
|
|
|
@ -43,15 +43,39 @@ describe ApplicationController, type: :controller do
|
|||
expect_updated_sign_in_at(user)
|
||||
end
|
||||
|
||||
it 'regenerates feed when sign in is older than two weeks' do
|
||||
allow(RegenerationWorker).to receive(:perform_async)
|
||||
user.update(current_sign_in_at: 3.weeks.ago)
|
||||
sign_in user, scope: :user
|
||||
get :show
|
||||
describe 'feed regeneration' do
|
||||
before do
|
||||
alice = Fabricate(:account)
|
||||
bob = Fabricate(:account)
|
||||
|
||||
expect_updated_sign_in_at(user)
|
||||
expect(Redis.current.get("account:#{user.account_id}:regeneration")).to eq 'true'
|
||||
expect(RegenerationWorker).to have_received(:perform_async)
|
||||
user.account.follow!(alice)
|
||||
user.account.follow!(bob)
|
||||
|
||||
Fabricate(:status, account: alice, text: 'hello world')
|
||||
Fabricate(:status, account: bob, text: 'yes hello')
|
||||
Fabricate(:status, account: user.account, text: 'test')
|
||||
|
||||
user.update(last_sign_in_at: 'Tue, 04 Jul 2017 14:45:56 UTC +00:00', current_sign_in_at: 'Wed, 05 Jul 2017 22:10:52 UTC +00:00')
|
||||
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
it 'sets a regeneration marker while regenerating' do
|
||||
allow(RegenerationWorker).to receive(:perform_async)
|
||||
get :show
|
||||
|
||||
expect_updated_sign_in_at(user)
|
||||
expect(Redis.current.get("account:#{user.account_id}:regeneration")).to eq 'true'
|
||||
expect(RegenerationWorker).to have_received(:perform_async)
|
||||
end
|
||||
|
||||
it 'regenerates feed when sign in is older than two weeks' do
|
||||
get :show
|
||||
|
||||
expect_updated_sign_in_at(user)
|
||||
expect(Redis.current.zcard(FeedManager.instance.key(:home, user.account_id))).to eq 3
|
||||
expect(Redis.current.get("account:#{user.account_id}:regeneration")).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
def expect_updated_sign_in_at(user)
|
||||
|
|
|
@ -82,10 +82,19 @@ RSpec.describe NotifyService do
|
|||
is_expected.to_not change(Notification, :count)
|
||||
end
|
||||
|
||||
context 'if the message chain initiated by recipient' do
|
||||
context 'if the message chain initiated by recipient, but is not direct message' do
|
||||
let(:reply_to) { Fabricate(:status, account: recipient) }
|
||||
let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, visibility: :direct, thread: reply_to)) }
|
||||
|
||||
it 'does not notify' do
|
||||
is_expected.to_not change(Notification, :count)
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the message chain initiated by recipient and is direct message' do
|
||||
let(:reply_to) { Fabricate(:status, account: recipient, visibility: :direct) }
|
||||
let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, visibility: :direct, thread: reply_to)) }
|
||||
|
||||
it 'does notify' do
|
||||
is_expected.to change(Notification, :count)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue