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

This commit is contained in:
KMY 2024-12-09 17:49:49 +09:00
commit 6b6f145633
28 changed files with 571 additions and 324 deletions

2
.nvmrc
View file

@ -1 +1 @@
22.11 22.12

View file

@ -1,9 +1,5 @@
import api, { getLinks } from '../api'; import api, { getLinks } from '../api';
export const HASHTAG_FETCH_REQUEST = 'HASHTAG_FETCH_REQUEST';
export const HASHTAG_FETCH_SUCCESS = 'HASHTAG_FETCH_SUCCESS';
export const HASHTAG_FETCH_FAIL = 'HASHTAG_FETCH_FAIL';
export const FOLLOWED_HASHTAGS_FETCH_REQUEST = 'FOLLOWED_HASHTAGS_FETCH_REQUEST'; export const FOLLOWED_HASHTAGS_FETCH_REQUEST = 'FOLLOWED_HASHTAGS_FETCH_REQUEST';
export const FOLLOWED_HASHTAGS_FETCH_SUCCESS = 'FOLLOWED_HASHTAGS_FETCH_SUCCESS'; export const FOLLOWED_HASHTAGS_FETCH_SUCCESS = 'FOLLOWED_HASHTAGS_FETCH_SUCCESS';
export const FOLLOWED_HASHTAGS_FETCH_FAIL = 'FOLLOWED_HASHTAGS_FETCH_FAIL'; export const FOLLOWED_HASHTAGS_FETCH_FAIL = 'FOLLOWED_HASHTAGS_FETCH_FAIL';
@ -12,39 +8,6 @@ export const FOLLOWED_HASHTAGS_EXPAND_REQUEST = 'FOLLOWED_HASHTAGS_EXPAND_REQUES
export const FOLLOWED_HASHTAGS_EXPAND_SUCCESS = 'FOLLOWED_HASHTAGS_EXPAND_SUCCESS'; export const FOLLOWED_HASHTAGS_EXPAND_SUCCESS = 'FOLLOWED_HASHTAGS_EXPAND_SUCCESS';
export const FOLLOWED_HASHTAGS_EXPAND_FAIL = 'FOLLOWED_HASHTAGS_EXPAND_FAIL'; export const FOLLOWED_HASHTAGS_EXPAND_FAIL = 'FOLLOWED_HASHTAGS_EXPAND_FAIL';
export const HASHTAG_FOLLOW_REQUEST = 'HASHTAG_FOLLOW_REQUEST';
export const HASHTAG_FOLLOW_SUCCESS = 'HASHTAG_FOLLOW_SUCCESS';
export const HASHTAG_FOLLOW_FAIL = 'HASHTAG_FOLLOW_FAIL';
export const HASHTAG_UNFOLLOW_REQUEST = 'HASHTAG_UNFOLLOW_REQUEST';
export const HASHTAG_UNFOLLOW_SUCCESS = 'HASHTAG_UNFOLLOW_SUCCESS';
export const HASHTAG_UNFOLLOW_FAIL = 'HASHTAG_UNFOLLOW_FAIL';
export const fetchHashtag = name => (dispatch) => {
dispatch(fetchHashtagRequest());
api().get(`/api/v1/tags/${name}`).then(({ data }) => {
dispatch(fetchHashtagSuccess(name, data));
}).catch(err => {
dispatch(fetchHashtagFail(err));
});
};
export const fetchHashtagRequest = () => ({
type: HASHTAG_FETCH_REQUEST,
});
export const fetchHashtagSuccess = (name, tag) => ({
type: HASHTAG_FETCH_SUCCESS,
name,
tag,
});
export const fetchHashtagFail = error => ({
type: HASHTAG_FETCH_FAIL,
error,
});
export const fetchFollowedHashtags = () => (dispatch) => { export const fetchFollowedHashtags = () => (dispatch) => {
dispatch(fetchFollowedHashtagsRequest()); dispatch(fetchFollowedHashtagsRequest());
@ -116,57 +79,3 @@ export function expandFollowedHashtagsFail(error) {
error, error,
}; };
} }
export const followHashtag = name => (dispatch) => {
dispatch(followHashtagRequest(name));
api().post(`/api/v1/tags/${name}/follow`).then(({ data }) => {
dispatch(followHashtagSuccess(name, data));
}).catch(err => {
dispatch(followHashtagFail(name, err));
});
};
export const followHashtagRequest = name => ({
type: HASHTAG_FOLLOW_REQUEST,
name,
});
export const followHashtagSuccess = (name, tag) => ({
type: HASHTAG_FOLLOW_SUCCESS,
name,
tag,
});
export const followHashtagFail = (name, error) => ({
type: HASHTAG_FOLLOW_FAIL,
name,
error,
});
export const unfollowHashtag = name => (dispatch) => {
dispatch(unfollowHashtagRequest(name));
api().post(`/api/v1/tags/${name}/unfollow`).then(({ data }) => {
dispatch(unfollowHashtagSuccess(name, data));
}).catch(err => {
dispatch(unfollowHashtagFail(name, err));
});
};
export const unfollowHashtagRequest = name => ({
type: HASHTAG_UNFOLLOW_REQUEST,
name,
});
export const unfollowHashtagSuccess = (name, tag) => ({
type: HASHTAG_UNFOLLOW_SUCCESS,
name,
tag,
});
export const unfollowHashtagFail = (name, error) => ({
type: HASHTAG_UNFOLLOW_FAIL,
name,
error,
});

View file

@ -0,0 +1,17 @@
import { apiGetTag, apiFollowTag, apiUnfollowTag } from 'mastodon/api/tags';
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
export const fetchHashtag = createDataLoadingThunk(
'tags/fetch',
({ tagId }: { tagId: string }) => apiGetTag(tagId),
);
export const followHashtag = createDataLoadingThunk(
'tags/follow',
({ tagId }: { tagId: string }) => apiFollowTag(tagId),
);
export const unfollowHashtag = createDataLoadingThunk(
'tags/unfollow',
({ tagId }: { tagId: string }) => apiUnfollowTag(tagId),
);

View file

@ -0,0 +1,11 @@
import { apiRequestPost, apiRequestGet } from 'mastodon/api';
import type { ApiHashtagJSON } from 'mastodon/api_types/tags';
export const apiGetTag = (tagId: string) =>
apiRequestGet<ApiHashtagJSON>(`v1/tags/${tagId}`);
export const apiFollowTag = (tagId: string) =>
apiRequestPost<ApiHashtagJSON>(`v1/tags/${tagId}/follow`);
export const apiUnfollowTag = (tagId: string) =>
apiRequestPost<ApiHashtagJSON>(`v1/tags/${tagId}/unfollow`);

View file

@ -0,0 +1,13 @@
interface ApiHistoryJSON {
day: string;
accounts: string;
uses: string;
}
export interface ApiHashtagJSON {
id: string;
name: string;
url: string;
history: [ApiHistoryJSON, ...ApiHistoryJSON[]];
following?: boolean;
}

View file

@ -1,94 +0,0 @@
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import { Button } from 'mastodon/components/button';
import { ShortNumber } from 'mastodon/components/short_number';
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
import { withIdentity } from 'mastodon/identity_context';
import { PERMISSION_MANAGE_TAXONOMIES } from 'mastodon/permissions';
const messages = defineMessages({
followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' },
unfollowHashtag: { id: 'hashtag.unfollow', defaultMessage: 'Unfollow hashtag' },
adminModeration: { id: 'hashtag.admin_moderation', defaultMessage: 'Open moderation interface for #{name}' },
});
const usesRenderer = (displayNumber, pluralReady) => (
<FormattedMessage
id='hashtag.counter_by_uses'
defaultMessage='{count, plural, one {{counter} post} other {{counter} posts}}'
values={{
count: pluralReady,
counter: <strong>{displayNumber}</strong>,
}}
/>
);
const peopleRenderer = (displayNumber, pluralReady) => (
<FormattedMessage
id='hashtag.counter_by_accounts'
defaultMessage='{count, plural, one {{counter} participant} other {{counter} participants}}'
values={{
count: pluralReady,
counter: <strong>{displayNumber}</strong>,
}}
/>
);
const usesTodayRenderer = (displayNumber, pluralReady) => (
<FormattedMessage
id='hashtag.counter_by_uses_today'
defaultMessage='{count, plural, one {{counter} post} other {{counter} posts}} today'
values={{
count: pluralReady,
counter: <strong>{displayNumber}</strong>,
}}
/>
);
export const HashtagHeader = withIdentity(injectIntl(({ tag, intl, disabled, onClick, identity }) => {
if (!tag) {
return null;
}
const { signedIn, permissions } = identity;
const menu = [];
if (signedIn && (permissions & PERMISSION_MANAGE_TAXONOMIES) === PERMISSION_MANAGE_TAXONOMIES ) {
menu.push({ text: intl.formatMessage(messages.adminModeration, { name: tag.get("name") }), href: `/admin/tags/${tag.get('id')}` });
}
const [uses, people] = tag.get('history').reduce((arr, day) => [arr[0] + day.get('uses') * 1, arr[1] + day.get('accounts') * 1], [0, 0]);
const dividingCircle = <span aria-hidden>{' · '}</span>;
return (
<div className='hashtag-header'>
<div className='hashtag-header__header'>
<h1>#{tag.get('name')}</h1>
<div className='hashtag-header__header__buttons'>
{ menu.length > 0 && <DropdownMenuContainer disabled={menu.length === 0} items={menu} icon='ellipsis-v' iconComponent={MoreHorizIcon} size={24} direction='right' /> }
<Button onClick={onClick} text={intl.formatMessage(tag.get('following') ? messages.unfollowHashtag : messages.followHashtag)} disabled={disabled} />
</div>
</div>
<div>
<ShortNumber value={uses} renderer={usesRenderer} />
{dividingCircle}
<ShortNumber value={people} renderer={peopleRenderer} />
{dividingCircle}
<ShortNumber value={tag.getIn(['history', 0, 'uses']) * 1} renderer={usesTodayRenderer} />
</div>
</div>
);
}));
HashtagHeader.propTypes = {
tag: ImmutablePropTypes.map,
disabled: PropTypes.bool,
onClick: PropTypes.func,
intl: PropTypes.object,
};

View file

@ -0,0 +1,188 @@
import { useCallback, useMemo, useState, useEffect } from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { isFulfilled } from '@reduxjs/toolkit';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import {
fetchHashtag,
followHashtag,
unfollowHashtag,
} from 'mastodon/actions/tags_typed';
import type { ApiHashtagJSON } from 'mastodon/api_types/tags';
import { Button } from 'mastodon/components/button';
import { ShortNumber } from 'mastodon/components/short_number';
import DropdownMenu from 'mastodon/containers/dropdown_menu_container';
import { useIdentity } from 'mastodon/identity_context';
import { PERMISSION_MANAGE_TAXONOMIES } from 'mastodon/permissions';
import { useAppDispatch } from 'mastodon/store';
const messages = defineMessages({
followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' },
unfollowHashtag: {
id: 'hashtag.unfollow',
defaultMessage: 'Unfollow hashtag',
},
adminModeration: {
id: 'hashtag.admin_moderation',
defaultMessage: 'Open moderation interface for #{name}',
},
});
const usesRenderer = (displayNumber: React.ReactNode, pluralReady: number) => (
<FormattedMessage
id='hashtag.counter_by_uses'
defaultMessage='{count, plural, one {{counter} post} other {{counter} posts}}'
values={{
count: pluralReady,
counter: <strong>{displayNumber}</strong>,
}}
/>
);
const peopleRenderer = (
displayNumber: React.ReactNode,
pluralReady: number,
) => (
<FormattedMessage
id='hashtag.counter_by_accounts'
defaultMessage='{count, plural, one {{counter} participant} other {{counter} participants}}'
values={{
count: pluralReady,
counter: <strong>{displayNumber}</strong>,
}}
/>
);
const usesTodayRenderer = (
displayNumber: React.ReactNode,
pluralReady: number,
) => (
<FormattedMessage
id='hashtag.counter_by_uses_today'
defaultMessage='{count, plural, one {{counter} post} other {{counter} posts}} today'
values={{
count: pluralReady,
counter: <strong>{displayNumber}</strong>,
}}
/>
);
export const HashtagHeader: React.FC<{
tagId: string;
}> = ({ tagId }) => {
const intl = useIntl();
const { signedIn, permissions } = useIdentity();
const dispatch = useAppDispatch();
const [tag, setTag] = useState<ApiHashtagJSON>();
useEffect(() => {
void dispatch(fetchHashtag({ tagId })).then((result) => {
if (isFulfilled(result)) {
setTag(result.payload);
}
return '';
});
}, [dispatch, tagId, setTag]);
const menu = useMemo(() => {
const tmp = [];
if (
tag &&
signedIn &&
(permissions & PERMISSION_MANAGE_TAXONOMIES) ===
PERMISSION_MANAGE_TAXONOMIES
) {
tmp.push({
text: intl.formatMessage(messages.adminModeration, { name: tag.id }),
href: `/admin/tags/${tag.id}`,
});
}
return tmp;
}, [signedIn, permissions, intl, tag]);
const handleFollow = useCallback(() => {
if (!signedIn || !tag) {
return;
}
if (tag.following) {
setTag((hashtag) => hashtag && { ...hashtag, following: false });
void dispatch(unfollowHashtag({ tagId })).then((result) => {
if (isFulfilled(result)) {
setTag(result.payload);
}
return '';
});
} else {
setTag((hashtag) => hashtag && { ...hashtag, following: true });
void dispatch(followHashtag({ tagId })).then((result) => {
if (isFulfilled(result)) {
setTag(result.payload);
}
return '';
});
}
}, [dispatch, setTag, signedIn, tag, tagId]);
if (!tag) {
return null;
}
const [uses, people] = tag.history.reduce(
(arr, day) => [
arr[0] + parseInt(day.uses),
arr[1] + parseInt(day.accounts),
],
[0, 0],
);
const dividingCircle = <span aria-hidden>{' · '}</span>;
return (
<div className='hashtag-header'>
<div className='hashtag-header__header'>
<h1>#{tag.name}</h1>
<div className='hashtag-header__header__buttons'>
{menu.length > 0 && (
<DropdownMenu
disabled={menu.length === 0}
items={menu}
icon='ellipsis-v'
iconComponent={MoreHorizIcon}
size={24}
direction='right'
/>
)}
<Button
onClick={handleFollow}
text={intl.formatMessage(
tag.following ? messages.unfollowHashtag : messages.followHashtag,
)}
disabled={!signedIn}
/>
</div>
</div>
<div>
<ShortNumber value={uses} renderer={usesRenderer} />
{dividingCircle}
<ShortNumber value={people} renderer={peopleRenderer} />
{dividingCircle}
<ShortNumber
value={parseInt(tag.history[0].uses)}
renderer={usesTodayRenderer}
/>
</div>
</div>
);
};

View file

@ -5,7 +5,6 @@ import { FormattedMessage } from 'react-intl';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
@ -13,7 +12,6 @@ import { isEqual } from 'lodash';
import TagIcon from '@/material-icons/400-24px/tag.svg?react'; import TagIcon from '@/material-icons/400-24px/tag.svg?react';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns'; import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
import { connectHashtagStream } from 'mastodon/actions/streaming'; import { connectHashtagStream } from 'mastodon/actions/streaming';
import { fetchHashtag, followHashtag, unfollowHashtag } from 'mastodon/actions/tags';
import { expandHashtagTimeline, clearTimeline } from 'mastodon/actions/timelines'; import { expandHashtagTimeline, clearTimeline } from 'mastodon/actions/timelines';
import Column from 'mastodon/components/column'; import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header'; import ColumnHeader from 'mastodon/components/column_header';
@ -26,7 +24,6 @@ import ColumnSettingsContainer from './containers/column_settings_container';
const mapStateToProps = (state, props) => ({ const mapStateToProps = (state, props) => ({
hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}${props.params.local ? ':local' : ''}`, 'unread']) > 0, hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}${props.params.local ? ':local' : ''}`, 'unread']) > 0,
tag: state.getIn(['tags', props.params.id]),
}); });
class HashtagTimeline extends PureComponent { class HashtagTimeline extends PureComponent {
@ -38,7 +35,6 @@ class HashtagTimeline extends PureComponent {
columnId: PropTypes.string, columnId: PropTypes.string,
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
hasUnread: PropTypes.bool, hasUnread: PropTypes.bool,
tag: ImmutablePropTypes.map,
multiColumn: PropTypes.bool, multiColumn: PropTypes.bool,
}; };
@ -130,7 +126,6 @@ class HashtagTimeline extends PureComponent {
this._subscribe(dispatch, id, tags, local); this._subscribe(dispatch, id, tags, local);
dispatch(expandHashtagTimeline(id, { tags, local })); dispatch(expandHashtagTimeline(id, { tags, local }));
dispatch(fetchHashtag(id));
} }
componentDidMount () { componentDidMount () {
@ -162,27 +157,10 @@ class HashtagTimeline extends PureComponent {
dispatch(expandHashtagTimeline(id, { maxId, tags, local })); dispatch(expandHashtagTimeline(id, { maxId, tags, local }));
}; };
handleFollow = () => {
const { dispatch, params, tag } = this.props;
const { id } = params;
const { signedIn } = this.props.identity;
if (!signedIn) {
return;
}
if (tag.get('following')) {
dispatch(unfollowHashtag(id));
} else {
dispatch(followHashtag(id));
}
};
render () { render () {
const { hasUnread, columnId, multiColumn, tag } = this.props; const { hasUnread, columnId, multiColumn } = this.props;
const { id, local } = this.props.params; const { id, local } = this.props.params;
const pinned = !!columnId; const pinned = !!columnId;
const { signedIn } = this.props.identity;
return ( return (
<Column bindToDocument={!multiColumn} ref={this.setRef} label={`#${id}`}> <Column bindToDocument={!multiColumn} ref={this.setRef} label={`#${id}`}>
@ -202,7 +180,7 @@ class HashtagTimeline extends PureComponent {
</ColumnHeader> </ColumnHeader>
<StatusListContainer <StatusListContainer
prepend={pinned ? null : <HashtagHeader tag={tag} disabled={!signedIn} onClick={this.handleFollow} />} prepend={pinned ? null : <HashtagHeader tagId={id} />}
alwaysPrepend alwaysPrepend
trackScroll={!pinned} trackScroll={!pinned}
scrollKey={`hashtag_timeline-${columnId}`} scrollKey={`hashtag_timeline-${columnId}`}

View file

@ -546,8 +546,8 @@
"notification.admin.report_statuses_other": "{name} denunciou a {target}", "notification.admin.report_statuses_other": "{name} denunciou a {target}",
"notification.admin.sign_up": "{name} rexistrouse", "notification.admin.sign_up": "{name} rexistrouse",
"notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# máis} other {# máis}} crearon unha conta", "notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# máis} other {# máis}} crearon unha conta",
"notification.annual_report.message": "A #VidaEnMastodon de {year} agarda por ti! Desvela os momentos máis destacados e historias reseñables en Mastodon!", "notification.annual_report.message": "#Wrapstodon de {year} agarda por ti! Desvela os momentos máis destacados e historias reseñables en Mastodon!",
"notification.annual_report.view": "Ver #VidaEnMastodon", "notification.annual_report.view": "Ver #Wrapstodon",
"notification.favourite": "{name} marcou como favorita a túa publicación", "notification.favourite": "{name} marcou como favorita a túa publicación",
"notification.favourite.name_and_others_with_link": "{name} e <a>{count, plural, one {# máis} other {# máis}}</a> favoreceron a túa publicación", "notification.favourite.name_and_others_with_link": "{name} e <a>{count, plural, one {# máis} other {# máis}}</a> favoreceron a túa publicación",
"notification.follow": "{name} comezou a seguirte", "notification.follow": "{name} comezou a seguirte",

View file

@ -20,10 +20,13 @@
"account.block_short": "封鎖", "account.block_short": "封鎖",
"account.blocked": "Hőng封鎖", "account.blocked": "Hőng封鎖",
"account.cancel_follow_request": "取消跟tuè", "account.cancel_follow_request": "取消跟tuè",
"account.copy": "Khóo-pih kàu個人資料ê連結",
"account.direct": "私人提起 @{name}",
"account.follow_back": "Tuè tńg去", "account.follow_back": "Tuè tńg去",
"annual_report.summary.percentile.text": "<topLabel>Tse 予lí變做 {domain} ê用戶ê </topLabel><percentage></percentage><bottomLabel></bottomLabel>", "annual_report.summary.percentile.text": "<topLabel>Tse 予lí變做 {domain} ê用戶ê </topLabel><percentage></percentage><bottomLabel></bottomLabel>",
"block_modal.show_less": "看khah少", "block_modal.show_less": "看khah少",
"compose.language.change": "換語言", "compose.language.change": "換語言",
"confirmations.follow_to_list.confirm": "跟tuè加入kàu列單", "confirmations.follow_to_list.confirm": "跟tuè加入kàu列單",
"search_popout.language_code": "ISO語言代碼" "search_popout.language_code": "ISO語言代碼",
"status.translated_from_with": "用 {provider} 翻譯 {lang}"
} }

View file

@ -0,0 +1,7 @@
import type { ApiHashtagJSON } from 'mastodon/api_types/tags';
export type Hashtag = ApiHashtagJSON;
export const createHashtag = (serverJSON: ApiHashtagJSON): Hashtag => ({
...serverJSON,
});

View file

@ -40,7 +40,6 @@ import settings from './settings';
import status_lists from './status_lists'; import status_lists from './status_lists';
import statuses from './statuses'; import statuses from './statuses';
import { suggestionsReducer } from './suggestions'; import { suggestionsReducer } from './suggestions';
import tags from './tags';
import timelines from './timelines'; import timelines from './timelines';
import trends from './trends'; import trends from './trends';
import user_lists from './user_lists'; import user_lists from './user_lists';
@ -83,7 +82,6 @@ const reducers = {
markers: markersReducer, markers: markersReducer,
picture_in_picture: pictureInPictureReducer, picture_in_picture: pictureInPictureReducer,
history, history,
tags,
followed_tags, followed_tags,
reaction_deck, reaction_deck,
notificationPolicy: notificationPolicyReducer, notificationPolicy: notificationPolicyReducer,

View file

@ -1,26 +0,0 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import {
HASHTAG_FETCH_SUCCESS,
HASHTAG_FOLLOW_REQUEST,
HASHTAG_FOLLOW_FAIL,
HASHTAG_UNFOLLOW_REQUEST,
HASHTAG_UNFOLLOW_FAIL,
} from 'mastodon/actions/tags';
const initialState = ImmutableMap();
export default function tags(state = initialState, action) {
switch(action.type) {
case HASHTAG_FETCH_SUCCESS:
return state.set(action.name, fromJS(action.tag));
case HASHTAG_FOLLOW_REQUEST:
case HASHTAG_UNFOLLOW_FAIL:
return state.setIn([action.name, 'following'], true);
case HASHTAG_FOLLOW_FAIL:
case HASHTAG_UNFOLLOW_REQUEST:
return state.setIn([action.name, 'following'], false);
default:
return state;
}
}

View file

@ -192,9 +192,11 @@ bg:
create_user_role: Създаване на роля create_user_role: Създаване на роля
demote_user: Понижаване на потребител demote_user: Понижаване на потребител
destroy_announcement: Изтриване на оповестяване destroy_announcement: Изтриване на оповестяване
destroy_canonical_email_block: Изтриване на блокиране за е-поща
destroy_custom_emoji: Изтриване на персонализирано емоджи destroy_custom_emoji: Изтриване на персонализирано емоджи
destroy_domain_allow: Изтриване на позволението за домейн destroy_domain_allow: Изтриване на позволението за домейн
destroy_domain_block: Изтриване на блокирането за домейна destroy_domain_block: Изтриване на блокирането за домейна
destroy_email_domain_block: Изтриване на блокиране на домейн на е-поща
destroy_instance: Чистка на домейна destroy_instance: Чистка на домейна
destroy_ip_block: Изтриване на правило за IP destroy_ip_block: Изтриване на правило за IP
destroy_status: Изтриване на публикация destroy_status: Изтриване на публикация

View file

@ -455,6 +455,7 @@ eo:
title: Bloki novan retpoŝtan domajnon title: Bloki novan retpoŝtan domajnon
no_email_domain_block_selected: Neniuj domajn blokoj ŝanĝiĝis ĉar nenio estis elektita no_email_domain_block_selected: Neniuj domajn blokoj ŝanĝiĝis ĉar nenio estis elektita
not_permitted: Ne permesita not_permitted: Ne permesita
resolved_dns_records_hint_html: La nomo de la domajno almontras la sekvajn MX-domajnojn, kiuj estas fine responsaj por akcepti retpoŝton. Blokas MX-domajnon blokus enskribadojn el retpoŝtadreso ajn, kiu uzas la saman MX-domajnon, eĉ se la videbla domajnnomo estas malsama. <strong> Gardemu ne bloki maĵorajn provizistojn de retpoŝto.</strong>
resolved_through_html: Solvis tra %{domain} resolved_through_html: Solvis tra %{domain}
title: Blokis retpoŝtajn domajnojn title: Blokis retpoŝtajn domajnojn
export_domain_allows: export_domain_allows:
@ -483,6 +484,7 @@ eo:
instances: instances:
audit_log: audit_log:
title: Novaj Protokoloj Pri Ekzamenoj title: Novaj Protokoloj Pri Ekzamenoj
view_all: Vidu la tutan protokolon de revizio
availability: availability:
description_html: description_html:
one: Se sendo la domajno malsukcesis por <strong>%{count} dio</strong>, ne estas sendprovo plu escepte <em>de</em> la dojmano. one: Se sendo la domajno malsukcesis por <strong>%{count} dio</strong>, ne estas sendprovo plu escepte <em>de</em> la dojmano.
@ -609,6 +611,7 @@ eo:
resolve_description_html: Nenio okazotas al la raportita konto kaj la raporto fermotas. resolve_description_html: Nenio okazotas al la raportita konto kaj la raporto fermotas.
silence_description_html: La konto estos videbla al nur personoj kiu jam sekvis ĝin au permane serĉo ĝin, ege limigante ĝian atingon. Malfermi ciujn raportojn kontra ĉi tiun konton. silence_description_html: La konto estos videbla al nur personoj kiu jam sekvis ĝin au permane serĉo ĝin, ege limigante ĝian atingon. Malfermi ciujn raportojn kontra ĉi tiun konton.
suspend_description_html: La konto kaj ciuj ĝiaj enhavoj estos neatingebla kaj poŝte forigitas, kaj interagi per ĝi estos neebla. Malfermi ciujn raportojn kontra ĉi tiu konto. suspend_description_html: La konto kaj ciuj ĝiaj enhavoj estos neatingebla kaj poŝte forigitas, kaj interagi per ĝi estos neebla. Malfermi ciujn raportojn kontra ĉi tiu konto.
actions_description_html: Elektu kiun agon fari por ripari ĉi tiun raporton. Se vi punus la raportitan uzanton, sciigon de retpoŝto sendos al ri, krom kiam la <strong>Spamo</strong> kategorio estas elektita.
actions_description_remote_html: Decidu kiun klopodon por solvi ĉi tiun raporton. Ĉi tiu efikas kiel nur <strong>via</strong> servilo komuniki per ĉi tiu fora konto kaj trakti ĝian enhavon. actions_description_remote_html: Decidu kiun klopodon por solvi ĉi tiun raporton. Ĉi tiu efikas kiel nur <strong>via</strong> servilo komuniki per ĉi tiu fora konto kaj trakti ĝian enhavon.
actions_no_posts: Ĉi tiu raporto havas neniujn rilatajn afiŝojn por forigi actions_no_posts: Ĉi tiu raporto havas neniujn rilatajn afiŝojn por forigi
add_to_report: Aldoni pli al raporto add_to_report: Aldoni pli al raporto
@ -630,6 +633,7 @@ eo:
created_at: Signalita created_at: Signalita
delete_and_resolve: Forigi afiŝojn delete_and_resolve: Forigi afiŝojn
forwarded: Plusendita forwarded: Plusendita
forwarded_replies_explanation: Ĉi tiu raporto estas de malproksima uzanto kaj estas pri malproksima enhavo. Ĝi plusendis al vi ĉar la raportita enhavo estas rediraĵo je unu el viaj uzantoj.
forwarded_to: Plusendita al %{domain} forwarded_to: Plusendita al %{domain}
mark_as_resolved: Marki solvita mark_as_resolved: Marki solvita
mark_as_sensitive: Marki kiel tiklan mark_as_sensitive: Marki kiel tiklan
@ -673,6 +677,7 @@ eo:
delete_data_html: Forigi profilon kaj enhavojn de <strong>@%{acct}</strong> post 30 tagoj se ili ne malsuspenditas dum la dauro delete_data_html: Forigi profilon kaj enhavojn de <strong>@%{acct}</strong> post 30 tagoj se ili ne malsuspenditas dum la dauro
preview_preamble_html: "<strong>@%{acct}</strong> akiros averton kun ĉi tiuj enhavoj:" preview_preamble_html: "<strong>@%{acct}</strong> akiros averton kun ĉi tiuj enhavoj:"
record_strike_html: Rekordu admonon kontra <strong>@%{acct}</strong> por helpi vi plikontroli estontajn malobservojn de ĉi tiu konto record_strike_html: Rekordu admonon kontra <strong>@%{acct}</strong> por helpi vi plikontroli estontajn malobservojn de ĉi tiu konto
send_email_html: Sendu <strong>@%{acct}</strong> retpoŝto de averto
warning_placeholder: Nedeviga aldona kialo por la moderigadago. warning_placeholder: Nedeviga aldona kialo por la moderigadago.
target_origin: Origino de raportita konto target_origin: Origino de raportita konto
title: Signaloj title: Signaloj
@ -712,6 +717,7 @@ eo:
manage_appeals: Administri Apelaciojn manage_appeals: Administri Apelaciojn
manage_appeals_description: Rajtigas al uzantoj kontroli apelaciojn kontraǔ kontrolaj agoj manage_appeals_description: Rajtigas al uzantoj kontroli apelaciojn kontraǔ kontrolaj agoj
manage_blocks: Administri Blokojn manage_blocks: Administri Blokojn
manage_blocks_description: Permesas uzantojn bloki provizistojn de retpoŝto kaj IP adresojn
manage_custom_emojis: Administri propajn emoĝiojn manage_custom_emojis: Administri propajn emoĝiojn
manage_custom_emojis_description: Permesi uzantojn administri propajn emoĝiojn ĉe la servilo manage_custom_emojis_description: Permesi uzantojn administri propajn emoĝiojn ĉe la servilo
manage_federation: Administri Federacion manage_federation: Administri Federacion
@ -729,6 +735,7 @@ eo:
manage_taxonomies: Administri kategoriarojn manage_taxonomies: Administri kategoriarojn
manage_taxonomies_description: Permesi uzantojn kontroli popularan enhavon kaj ĝisdatigi kradvortopciojn manage_taxonomies_description: Permesi uzantojn kontroli popularan enhavon kaj ĝisdatigi kradvortopciojn
manage_user_access: Administri uzantoaliron manage_user_access: Administri uzantoaliron
manage_user_access_description: Permesas uzantojn invalidi la du-faktoran aŭtentigon de aliaj uzantoj, ŝanĝi siajn retpoŝtadresojn, kaj restarigi siajn pasvorton
manage_users: Administri uzantojn manage_users: Administri uzantojn
manage_users_description: Permesi uzantaojn vidi detalojn de aliaj uzantoj kaj administri ilin manage_users_description: Permesi uzantaojn vidi detalojn de aliaj uzantoj kaj administri ilin
manage_webhooks: Administri rethokojn manage_webhooks: Administri rethokojn
@ -791,15 +798,19 @@ eo:
approved: Bezonas aprobi por aliĝi approved: Bezonas aprobi por aliĝi
none: Neniu povas aliĝi none: Neniu povas aliĝi
open: Iu povas aliĝi open: Iu povas aliĝi
warning_hint: Ni rekomendas uzi "Konsento neprigas por enskribiĝi" krom se vi memcertas, ke via teamo de moderistoj povas ellabori spamon kaj malignajn registradojn rapide.
security: security:
authorized_fetch: Devigi aŭtentigon de frataraj serviloj authorized_fetch: Devigi aŭtentigon de frataraj serviloj
authorized_fetch_hint: Neprigante aŭtentigon por federataj serviloj permesas pli striktan devigon de ambaŭ uzanto-nivelaj kaj servilo-nivelaj blokoj. Tamen, ĉi tiu uzas pli risurcojn, reduktas la ĝisiradon de viaj respondoj, kaj povas enkonduki aferoj, pri kongruoj. Plu, ĉi tiu ne preventos homojn el alporti viajn afiŝojn kaj uzantojn.
authorized_fetch_overridden_hint: Vi nuntempe ne povas ŝanĝi ĉi tiun agordon ĉar ĝi estas anstataŭita de mediovariablo. authorized_fetch_overridden_hint: Vi nuntempe ne povas ŝanĝi ĉi tiun agordon ĉar ĝi estas anstataŭita de mediovariablo.
federation_authentication: Devigado de la aŭtentigo de la federacio
title: Agordoj de la servilo title: Agordoj de la servilo
site_uploads: site_uploads:
delete: Forigi elŝutitan dosieron delete: Forigi elŝutitan dosieron
destroyed_msg: Reteja alŝuto sukcese forigita! destroyed_msg: Reteja alŝuto sukcese forigita!
software_updates: software_updates:
critical_update: Kritika — bonvolu ĝisdatiĝi rapide critical_update: Kritika — bonvolu ĝisdatiĝi rapide
description: Ni rekomendas ĝisdatigadi vian instalaĵon de Mastodon por deutili la plej ĵusajn riparojn kaj trajtojn. Plu, estas kelkajfoje grava ĝisdati Mastodon rapide por eviti problemojn pri sekureco. Tial, Mastodon kontrolas por ĝisdataĵoj ĉiuj 30 minutoj, kaj sciigos vin laŭ viaj agordoj pri retpoŝtaj sciigoj.
documentation_link: Lerni pli documentation_link: Lerni pli
release_notes: Eldono-notoj release_notes: Eldono-notoj
title: Disponeblaj ĝisdatigoj title: Disponeblaj ĝisdatigoj
@ -815,6 +826,7 @@ eo:
back_to_account: Reveni al konta paĝo back_to_account: Reveni al konta paĝo
back_to_report: Reveni al raportpaĝo back_to_report: Reveni al raportpaĝo
batch: batch:
add_to_report: 'Aldoni al raporto #%{id}'
remove_from_report: Forigi de raporto remove_from_report: Forigi de raporto
report: Raporti report: Raporti
contents: Enhavoj contents: Enhavoj
@ -833,6 +845,7 @@ eo:
reblogs: Reblogaĵoj reblogs: Reblogaĵoj
replied_to_html: Respondis al %{acct_link} replied_to_html: Respondis al %{acct_link}
status_changed: Afiŝo ŝanĝiĝis status_changed: Afiŝo ŝanĝiĝis
status_title: Afiŝo de @%{name}
title: Afiŝoj de konto - @%{name} title: Afiŝoj de konto - @%{name}
trending: Popularaĵoj trending: Popularaĵoj
view_publicly: Vidu publike view_publicly: Vidu publike
@ -853,10 +866,20 @@ eo:
system_checks: system_checks:
database_schema_check: database_schema_check:
message_html: Estas pritraktataj datumbazaj migradoj. Bonvolu ekzekuti ilin por certigi, ke la apliko kondutas kiel atendite message_html: Estas pritraktataj datumbazaj migradoj. Bonvolu ekzekuti ilin por certigi, ke la apliko kondutas kiel atendite
elasticsearch_health_red:
message_html: Elasticsearch peniko estas malsana (ruĝa statuso), trajtoj de serĉo malhaveblas
elasticsearch_health_yellow:
message_html: Peniko de Elasticsearch malsana (flava status), vi eble povas enketi la kialon
elasticsearch_index_mismatch:
message_html: Bildigoj de enhavtabelo de Elasticsearch posttempas. Bonvolu, rulu <code>tootctl search deploy --only=%{value}</code>
elasticsearch_preset: elasticsearch_preset:
action: Legi dokumentaron action: Legi dokumentaron
message_html: Via peniko de Elasticsearch havas pli ol unu verticon, sed Mastodon ne estas agordita uzi ilin.
elasticsearch_preset_single_node: elasticsearch_preset_single_node:
action: Vidi dokumentadon action: Vidi dokumentadon
message_html: Via peniko de Elasticsearch havas nur unu verticon, <code>ES_PRESET</code> devus munti al <code>single_node_cluster</code>.
elasticsearch_reset_chewy:
message_html: Via enhavtabelo de la sistemo de Elasticsearch posttempas pro ŝanĝo de agordoj. Bonvolu, rulu <code>tootctl search deploy --reset-chewy</code> por ĝisdatigi ĝin.
elasticsearch_running_check: elasticsearch_running_check:
message_html: Ne eblas konekti Elasticsearch. Bonvolu kontroli ke ĝi funkcias, aǔ malŝaltu plentekstan serĉon message_html: Ne eblas konekti Elasticsearch. Bonvolu kontroli ke ĝi funkcias, aǔ malŝaltu plentekstan serĉon
elasticsearch_version_check: elasticsearch_version_check:
@ -875,6 +898,7 @@ eo:
message_html: Grava ĝisdatigo de Mastodon disponeblas, bonvolu ĝisdatigi kiel eble plej rapide. message_html: Grava ĝisdatigo de Mastodon disponeblas, bonvolu ĝisdatigi kiel eble plej rapide.
software_version_patch_check: software_version_patch_check:
action: Vidi disponeblajn ĝisdatigojn action: Vidi disponeblajn ĝisdatigojn
message_html: Ĝisdataĵo de Mastodon pri cimriparo haveblas.
upload_check_privacy_error: upload_check_privacy_error:
action: Klaku ĉi tie por pliaj informoj action: Klaku ĉi tie por pliaj informoj
message_html: "<strong>Via retservilo estas misagordita. La privateco de viaj uzantoj estas en risko.</strong>" message_html: "<strong>Via retservilo estas misagordita. La privateco de viaj uzantoj estas en risko.</strong>"
@ -883,10 +907,13 @@ eo:
message_html: "<strong>Via objektostokado estas misagordita. La privateco de viaj uzantoj estas en risko.</strong>" message_html: "<strong>Via objektostokado estas misagordita. La privateco de viaj uzantoj estas en risko.</strong>"
tags: tags:
moderation: moderation:
not_trendable: Ne modebla
not_usable: Ne uzebla not_usable: Ne uzebla
pending_review: Pendata superrigardo
review_requested: Revizio petita review_requested: Revizio petita
reviewed: Reviziita reviewed: Reviziita
title: Stato title: Stato
trendable: Modebla
unreviewed: Nereviziita unreviewed: Nereviziita
usable: Uzebla usable: Uzebla
name: Nomo name: Nomo
@ -935,7 +962,9 @@ eo:
statuses: statuses:
allow: Permesi afiŝon allow: Permesi afiŝon
allow_account: Permesi aŭtoron allow_account: Permesi aŭtoron
confirm_allow: Ĉu vi certas, ke vi volas permesi elektitajn statusojn?
confirm_allow_account: Ĉu vi certas, ke vi volas permesi elektitajn kontojn? confirm_allow_account: Ĉu vi certas, ke vi volas permesi elektitajn kontojn?
confirm_disallow: Ĉu vi certas, ke vi volas malpermesi elektitajn statusojn?
confirm_disallow_account: Ĉu vi certas, ke vi volas malpermesi elektitajn kontojn? confirm_disallow_account: Ĉu vi certas, ke vi volas malpermesi elektitajn kontojn?
description_html: Oni multe diskonigas kaj stelumas ĉi tiujn mesaĝojn nuntempe laŭ via servilo. Tio povas helpi novajn kaj revenantajn uzantojn trovi pli da homoj por sekvi. Mesaĝo estas montrita publike nur se vi aprobis la aŭtoron kaj se la aŭtoro aprobis ke ties konto estu proponita al aliaj. Vi ankaŭ povas permesi aŭ malakcepti specifajn mesaĝojn. description_html: Oni multe diskonigas kaj stelumas ĉi tiujn mesaĝojn nuntempe laŭ via servilo. Tio povas helpi novajn kaj revenantajn uzantojn trovi pli da homoj por sekvi. Mesaĝo estas montrita publike nur se vi aprobis la aŭtoron kaj se la aŭtoro aprobis ke ties konto estu proponita al aliaj. Vi ankaŭ povas permesi aŭ malakcepti specifajn mesaĝojn.
disallow: Malpermesi afiŝon disallow: Malpermesi afiŝon
@ -976,6 +1005,7 @@ eo:
delete: Forigi delete: Forigi
edit_preset: Redakti avertan antaŭagordon edit_preset: Redakti avertan antaŭagordon
empty: Vi ankoraŭ ne difinis iun ajn antaŭagordon de averto. empty: Vi ankoraŭ ne difinis iun ajn antaŭagordon de averto.
title: Antaŭdifinoj de averto
webhooks: webhooks:
add_new: Aldoni finpunkton add_new: Aldoni finpunkton
delete: Forigi delete: Forigi
@ -997,6 +1027,9 @@ eo:
title: Rethokoj title: Rethokoj
webhook: Rethoko webhook: Rethoko
admin_mailer: admin_mailer:
auto_close_registrations:
body: Pro seneco de ĵusaj aktivaĵoj de moderistoj, enskribadojn en %{instance} aŭtomate ŝanĝis al mana superrigardo, por eviti %{instance} estas uzita por eblaj fiuloj. Vi povas reŝanĝi ĝin al malfermaj enskribadoj iam ajn.
subject: Enskribadoj por %{instance} aŭtomate ŝanĝis al mana konsento
new_appeal: new_appeal:
actions: actions:
delete_statuses: por forigi iliajn afiŝojn delete_statuses: por forigi iliajn afiŝojn
@ -1011,6 +1044,7 @@ eo:
subject: "%{username} apelacias kontroldecidon ĉe %{instance}" subject: "%{username} apelacias kontroldecidon ĉe %{instance}"
new_critical_software_updates: new_critical_software_updates:
body: Novaj gravaj versioj de Mastodon estis publikigitaj, vi eble volas ĝisdatigi kiel eble plej baldaŭ! body: Novaj gravaj versioj de Mastodon estis publikigitaj, vi eble volas ĝisdatigi kiel eble plej baldaŭ!
subject: Sojlaj ĝisdataĵoj de Mastodon haveblas por %{instance}!
new_pending_account: new_pending_account:
body: La detaloj de la nova konto estas ĉi-sube. Vi povas akcepti aŭ malakcepti tiun aliĝilon. body: La detaloj de la nova konto estas ĉi-sube. Vi povas akcepti aŭ malakcepti tiun aliĝilon.
subject: Nova konto atendas por recenzo en %{instance} (%{username}) subject: Nova konto atendas por recenzo en %{instance} (%{username})
@ -1071,10 +1105,12 @@ eo:
hint_html: Nur unu plia afero! Ni devas konfirmi, ke vi estas homo (tio estas por ke ni povu konservi la spamon ekstere!). Solvu la CAPTCHA sube kaj alklaku "Daŭrigu". hint_html: Nur unu plia afero! Ni devas konfirmi, ke vi estas homo (tio estas por ke ni povu konservi la spamon ekstere!). Solvu la CAPTCHA sube kaj alklaku "Daŭrigu".
title: Sekureckontrolo title: Sekureckontrolo
confirmations: confirmations:
awaiting_review: Via retpoŝtadreso estas konfirmita! La teamo de %{domain} nun superrigardas vian enskribiĝon. Vi ricevos retpoŝton, se ili aprobos vian konton!
awaiting_review_title: Via registriĝo estas reviziita awaiting_review_title: Via registriĝo estas reviziita
clicking_this_link: alklakante ĉi tiun ligilon clicking_this_link: alklakante ĉi tiun ligilon
login_link: ensaluti login_link: ensaluti
proceed_to_login_html: Vi nun povas iri al %{login_link}. proceed_to_login_html: Vi nun povas iri al %{login_link}.
redirect_to_app_html: Vi devus sendigi al la <strong>%{app_name}</strong> aplikaĵo. Se tion ne okazis, provu %{clicking_this_link} aŭ mane reiras al la aplikaĵo.
registration_complete: Via registriĝo sur %{domain} nun finiĝis! registration_complete: Via registriĝo sur %{domain} nun finiĝis!
welcome_title: Bonvenon, %{name}! welcome_title: Bonvenon, %{name}!
wrong_email_hint: Se tiu retadreso ne estas ĝusta, vi povas ŝanĝi ĝin en kontagordoj. wrong_email_hint: Se tiu retadreso ne estas ĝusta, vi povas ŝanĝi ĝin en kontagordoj.
@ -1120,6 +1156,8 @@ eo:
security: Sekureco security: Sekureco
set_new_password: Elekti novan pasvorton set_new_password: Elekti novan pasvorton
setup: setup:
email_below_hint_html: Kontrolu vian spam-dosierujon aŭ petu novan. Se necese, vi povas korekti vian retadreson.
email_settings_hint_html: Enklaku la ligilon, ke ni sendis al vi por kontroli %{email}. Ni estos tien.
link_not_received: Ĉu vi ne ricevis ligilon? link_not_received: Ĉu vi ne ricevis ligilon?
new_confirmation_instructions_sent: Vi ricevos novan retpoŝton kun la konfirma ligilo post kelkaj minutoj! new_confirmation_instructions_sent: Vi ricevos novan retpoŝton kun la konfirma ligilo post kelkaj minutoj!
title: Kontrolu vian retpoŝta enirkesto title: Kontrolu vian retpoŝta enirkesto
@ -1127,13 +1165,16 @@ eo:
preamble_html: Ensalutu per via detaloj de <strong>%{domain}</strong>. Se via konto gastigantigas sur malsama servilo, vi ne povas ensaluti ĉi tie. preamble_html: Ensalutu per via detaloj de <strong>%{domain}</strong>. Se via konto gastigantigas sur malsama servilo, vi ne povas ensaluti ĉi tie.
title: Saluti en %{domain} title: Saluti en %{domain}
sign_up: sign_up:
manual_review: Enskriboj en %{domain} havas manan superrigardon, farita de niaj moderistoj. Por helpi nin por procezi vian enskribon, skribu ion pri vi mem, kaj kial vi volas konton en %{domain}.
preamble: Per konto ĉe ĉi tiu Mastodon-servilo, vi povas sekvi ajn personojn en la reto. preamble: Per konto ĉe ĉi tiu Mastodon-servilo, vi povas sekvi ajn personojn en la reto.
title: Ni pretigu vin ĉe %{domain}. title: Ni pretigu vin ĉe %{domain}.
status: status:
account_status: Statuso de la konto account_status: Statuso de la konto
confirming: Atendante ke retpoŝta konfirmo estos kompletigita. confirming: Atendante ke retpoŝta konfirmo estos kompletigita.
functional: Via konto estas tute funkcia. functional: Via konto estas tute funkcia.
pending: Via apliko estas superrigardata de niaj teamo. Ĉi tiu povas bezoni iom da tempo. Vi ricevos retpoŝton, se via apliko estas konsentita.
redirecting_to: Via konto estas neaktiva ĉar ĝi nun alidirektas al %{acct}. redirecting_to: Via konto estas neaktiva ĉar ĝi nun alidirektas al %{acct}.
self_destruct: Pro %{domain} ekfermas, vi povos nur havi malvastan atingon al via konto.
view_strikes: Vidi antauaj admonoj kontra via konto view_strikes: Vidi antauaj admonoj kontra via konto
too_fast: Formularo sendita tro rapide, klopodu denove. too_fast: Formularo sendita tro rapide, klopodu denove.
use_security_key: Uzi sekurecan ŝlosilon use_security_key: Uzi sekurecan ŝlosilon
@ -1183,6 +1224,7 @@ eo:
data_removal: Viaj afiŝoj kaj aliaj informoj estos forigita por eterne data_removal: Viaj afiŝoj kaj aliaj informoj estos forigita por eterne
email_change_html: Vi povas <a href="%{path}">ŝanĝi vian retadreson</a> sen forigi vian konton email_change_html: Vi povas <a href="%{path}">ŝanĝi vian retadreson</a> sen forigi vian konton
email_contact_html: Se ĝi ankoraŭ ne alvenas, vi povas retpoŝti al <a href="mailto:%{email}">%{email}</a> por helpo email_contact_html: Se ĝi ankoraŭ ne alvenas, vi povas retpoŝti al <a href="mailto:%{email}">%{email}</a> por helpo
email_reconfirmation_html: Se vi ne ricevas la konfirmretpoŝton, vi povas <a href="%{path}">denove peti</a>
irreversible: Vi ne povas regajni au reaktivigi vian konton irreversible: Vi ne povas regajni au reaktivigi vian konton
more_details_html: Por pli da detaloj, vidi la <a href="%{terms_path}">privatecan politikon</a>. more_details_html: Por pli da detaloj, vidi la <a href="%{terms_path}">privatecan politikon</a>.
username_available: Via uzantnomo iĝos denove disponebla username_available: Via uzantnomo iĝos denove disponebla
@ -1219,6 +1261,7 @@ eo:
your_appeal_rejected: Via apelacio malakceptitas your_appeal_rejected: Via apelacio malakceptitas
edit_profile: edit_profile:
basic_information: Baza informo basic_information: Baza informo
hint_html: "<strong>Personigi, kion homoj vidi en via publika profilo kaj apud viaj afiŝoj. </strong> Aliaj homoj estas pli probable resekvi vin kaj interagi kun vi se vi havus finigitan profilon kaj profilan foton."
other: Alia other: Alia
errors: errors:
'400': La peto kiun vi sendis estas nevalida au malformas. '400': La peto kiun vi sendis estas nevalida au malformas.
@ -1341,6 +1384,44 @@ eo:
merge_long: Konservi ekzistajn registrojn kaj aldoni novajn merge_long: Konservi ekzistajn registrojn kaj aldoni novajn
overwrite: Anstataŭigi overwrite: Anstataŭigi
overwrite_long: Anstataŭigi la nunajn registrojn per la novaj overwrite_long: Anstataŭigi la nunajn registrojn per la novaj
overwrite_preambles:
blocking_html:
one: Vi tuj <strong>anstataŭas vian blokliston</strong>, kun ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
other: Vi tuj <strong>anstataŭas vian blokliston</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
bookmarks_html:
one: Vi tuj <strong>anstataŭas viajn legosignojn</strong> kun ĝis <strong>%{count} afiŝoj</strong> de <strong>%{filename}</strong>.
other: Vi tuj <strong>anstataŭas viajn legosignojn</strong> kun ĝis <strong>%{count} afiŝoj</strong> de <strong>%{filename}</strong>.
domain_blocking_html:
one: Vi tuj <strong>anstataŭas vian domajnan blokliston</strong> kun ĝis <strong>%{count} domajnoj</strong> de <strong>%{filename}</strong>.
other: Vi tuj <strong>anstataŭas vian domajnan blokliston</strong> kun ĝis <strong>%{count} domajnoj</strong> de <strong>%{filename}</strong>.
following_html:
one: Vi tuj <strong>sekvos</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong> kaj <strong>ĉesos sekvi iun alian</strong>.
other: Vi tuj <strong>sekvos</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong> kaj <strong>ĉesos sekvi iun alian</strong>.
lists_html:
one: Vi tuj <strong>anstataŭos viajn listojn</strong> kun enhavo de <strong>%{filename}</strong>. Ĝis <strong>%{count} kontoj</strong> estos aldonitaj al novaj listoj.
other: Vi tuj <strong>anstataŭos viajn listojn</strong> kun enhavo de <strong>%{filename}</strong>. Ĝis <strong>%{count} kontoj</strong> estos aldonitaj al novaj listoj.
muting_html:
one: Vi tuj <strong>anstataŭas viajn listojn de silentigitaj kontoj</strong> kun ĝis<strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
other: Vi tuj <strong>anstataŭas viajn listojn de silentigitaj kontoj</strong> kun ĝis<strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
preambles:
blocking_html:
one: Vi tuj <strong>blokas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
other: Vi tuj <strong>blokas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
bookmarks_html:
one: Vi tuj aldonas ĝis <strong>%{count} afiŝojn</strong> de <strong>%{filename}</strong> al viaj <strong>legosignoj</strong>.
other: Vi tuj aldonas ĝis <strong>%{count} afiŝojn</strong> de <strong>%{filename}</strong> al viaj <strong>legosignoj</strong>.
domain_blocking_html:
one: Vi tuj <strong>blokas</strong> ĝis <strong>%{count} domajnoj</strong> de <strong>%{filename}</strong>.
other: Vi tuj <strong>blokas</strong> ĝis <strong>%{count} domajnoj</strong> de <strong>%{filename}</strong>.
following_html:
one: Vi tuj <strong>sekvas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
other: Vi tuj <strong>sekvas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
lists_html:
one: Vi tuj aldonas ĝis <strong>%{count} kontojn</strong> de <strong>%{filename}</strong> al viaj <strong>listoj</strong>. Novaj listoj estos kreitaj se ne estas listo por aldoni.
other: Vi tuj aldonas ĝis <strong>%{count} kontojn</strong> de <strong>%{filename}</strong> al viaj <strong>listoj</strong>. Novaj listoj estos kreitaj se ne estas listo por aldoni.
muting_html:
one: Vi tuj<strong>silentas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
other: Vi tuj<strong>silentas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
preface: Vi povas importi datumojn, kiujn vi eksportis el alia servilo, kiel liston de homoj, kiujn vi sekvas aŭ blokas. preface: Vi povas importi datumojn, kiujn vi eksportis el alia servilo, kiel liston de homoj, kiujn vi sekvas aŭ blokas.
recent_imports: Lastatempaj importoj recent_imports: Lastatempaj importoj
states: states:
@ -1352,6 +1433,9 @@ eo:
success: Viaj datumoj estis sukcese alŝutitaj kaj estos traktitaj kiel planite success: Viaj datumoj estis sukcese alŝutitaj kaj estos traktitaj kiel planite
time_started: Komencis je time_started: Komencis je
titles: titles:
blocking: Enportante blokitajn kontojn
bookmarks: Enportante legosignojn
domain_blocking: Enportante blokitajn domajnojn
following: Importado de sekvaj kontoj following: Importado de sekvaj kontoj
lists: Importi listojn lists: Importi listojn
muting: Importado de silentigitaj kontoj muting: Importado de silentigitaj kontoj
@ -1408,13 +1492,21 @@ eo:
unsubscribe: unsubscribe:
action: Jes, malabonu action: Jes, malabonu
complete: Malabonita complete: Malabonita
confirmation_html: Ĉu vi certas, ke vi volas malaboni je ricevi %{type} por Mastodon ĉe %{domain} al via retpoŝto ĉe %{email}? Vi ĉiam povas reaboni de viaj <a href="%{settings_path}">retpoŝtaj sciigaj agordoj</a>.
emails: emails:
notification_emails: notification_emails:
favourite: sciigoj retpoŝtaj de ŝatataj
follow: sciigoj retpoŝtaj de sekvoj
follow_request: retpoŝtajn petoj de sekvado follow_request: retpoŝtajn petoj de sekvado
mention: sciigoj retpoŝtaj de mencioj
reblog: sciigoj retpoŝtaj de stimuloj
resubscribe_html: Se vi malabonis erare, vi povas reaboni de viaj <a href="%{settings_path}">retpoŝtaj sciigaj agordoj</a>.
success_html: Vi ne plu ricevos %{type} por Mastodon ĉe %{domain} al via retpoŝto ĉe %{email}.
title: Malaboni title: Malaboni
media_attachments: media_attachments:
validations: validations:
images_and_video: Aldoni videon al mesaĝo, kiu jam havas bildojn ne eblas images_and_video: Aldoni videon al mesaĝo, kiu jam havas bildojn ne eblas
not_found: Dosiero %{ids} ne trovis aŭ jam alteniĝis al alia afiŝo
not_ready: Ne povas aldoni dosieron kiu ne finas procezitis. not_ready: Ne povas aldoni dosieron kiu ne finas procezitis.
too_many: Aldoni pli ol 4 dosierojn ne eblas too_many: Aldoni pli ol 4 dosierojn ne eblas
migrations: migrations:
@ -1491,6 +1583,8 @@ eo:
update: update:
subject: "%{name} redaktis afiŝon" subject: "%{name} redaktis afiŝon"
notifications: notifications:
administration_emails: Sciigoj retpoŝtaj de administacio
email_events: Eventoj por retpoŝtaj sciigoj
email_events_hint: 'Elekti la eventojn pri kioj vi volas ricevi sciigojn:' email_events_hint: 'Elekti la eventojn pri kioj vi volas ricevi sciigojn:'
number: number:
human: human:
@ -1584,6 +1678,7 @@ eo:
scheduled_statuses: scheduled_statuses:
over_daily_limit: Vi transpasis la limigon al %{limit} samtage planitaj mesaĝoj over_daily_limit: Vi transpasis la limigon al %{limit} samtage planitaj mesaĝoj
over_total_limit: Vi transpasis la limigon al %{limit} planitaj mesaĝoj over_total_limit: Vi transpasis la limigon al %{limit} planitaj mesaĝoj
too_soon: dato devas esti en la futuro
self_destruct: self_destruct:
lead_html: Bedaŭrinde, <strong>%{domain}</strong> konstante fermiĝas. Se vi havis konton tie, vi ne povos daŭrigi uzi ĝin, sed vi ankoraŭ povas peti sekurkopion de viaj datumoj. lead_html: Bedaŭrinde, <strong>%{domain}</strong> konstante fermiĝas. Se vi havis konton tie, vi ne povos daŭrigi uzi ĝin, sed vi ankoraŭ povas peti sekurkopion de viaj datumoj.
title: Ĉi tiu servilo fermiĝas title: Ĉi tiu servilo fermiĝas
@ -1652,6 +1747,7 @@ eo:
preferences: Preferoj preferences: Preferoj
profile: Profilo profile: Profilo
relationships: Sekvatoj kaj sekvantoj relationships: Sekvatoj kaj sekvantoj
severed_relationships: Finitaj rilatoj
statuses_cleanup: Automata mesaĝforigo statuses_cleanup: Automata mesaĝforigo
strikes: Kontroladmonoj strikes: Kontroladmonoj
two_factor_authentication: Dufaktora aŭtentigo two_factor_authentication: Dufaktora aŭtentigo
@ -1659,8 +1755,13 @@ eo:
severed_relationships: severed_relationships:
download: Elŝuti (%{count}) download: Elŝuti (%{count})
event_type: event_type:
account_suspension: Suspendado de konto (%{target_name})
domain_block: Suspendado de servilo (%{target_name})
user_domain_block: Vi blokis %{target_name} user_domain_block: Vi blokis %{target_name}
lost_followers: Perditaj sekvantoj lost_followers: Perditaj sekvantoj
lost_follows: Perditaj sekvantoj
preamble: Vi eble perdos sekvojn kaj sekvantojn, kiam vi blockus domajnon aŭ kiam viaj moderantoj elektus suspendi malproksiman servilon. Kiam tio okazas, vi povus elŝulti registrojn de finitaj rilatoj, por inspektiĝi kaj eble enporti en alia servilo.
purged: Informo pri ĉi tiu servilo foriĝis de la administracio de via servilo.
type: Evento type: Evento
statuses: statuses:
attached: attached:
@ -1775,19 +1876,24 @@ eo:
action: Konto-agordoj action: Konto-agordoj
explanation: La apelacio de la admono kontra via konto je %{strike_date} pri sendodato %{appeal_date} aprobitas. explanation: La apelacio de la admono kontra via konto je %{strike_date} pri sendodato %{appeal_date} aprobitas.
subject: Via apelacio de %{date} aprobitas subject: Via apelacio de %{date} aprobitas
subtitle: Via konto estas denove bone.
title: Apelacio estis aprobita title: Apelacio estis aprobita
appeal_rejected: appeal_rejected:
explanation: La apelacio je %{strike_date} pri dato %{appeal_date} malakceptitas. explanation: La apelacio je %{strike_date} pri dato %{appeal_date} malakceptitas.
subject: Via apelacio de %{date} estis malaprobita subject: Via apelacio de %{date} estis malaprobita
subtitle: Via revizio negiĝis.
title: Apelacio estis malaprobita title: Apelacio estis malaprobita
backup_ready: backup_ready:
explanation: Vi petis por tuta rezervo de via Mastodon-a konto.
extra: Estas nun preta por elŝuto! extra: Estas nun preta por elŝuto!
subject: Via arkivo estas preta por elŝutado subject: Via arkivo estas preta por elŝutado
title: Arkiva elŝuto title: Arkiva elŝuto
failed_2fa: failed_2fa:
details: 'Jen detaloj de la provaĵo de ensaluti:'
explanation: Iu provis ensaluti al via konto sed provizis nevalidan duan aŭtentikigfaktoron. explanation: Iu provis ensaluti al via konto sed provizis nevalidan duan aŭtentikigfaktoron.
further_actions_html: Se ĉi tio ne estis vi, ni rekomendas ke vi %{action} tuj ĉar ĝi povas esti endanĝerigita. further_actions_html: Se ĉi tio ne estis vi, ni rekomendas ke vi %{action} tuj ĉar ĝi povas esti endanĝerigita.
subject: Malsukceso dum la dua aŭtentikigfaktoro subject: Malsukceso dum la dua aŭtentikigfaktoro
title: Du-faktora aŭtentigo malsukcesis
suspicious_sign_in: suspicious_sign_in:
change_password: ŝanĝi vian pasvorton change_password: ŝanĝi vian pasvorton
details: 'Ĉi-sube estas detaloj pri la saluto:' details: 'Ĉi-sube estas detaloj pri la saluto:'
@ -1831,13 +1937,24 @@ eo:
apps_ios_action: Elŝutu ĉe la App Store apps_ios_action: Elŝutu ĉe la App Store
apps_step: Elŝutu niajn oficialajn aplikaĵojn. apps_step: Elŝutu niajn oficialajn aplikaĵojn.
apps_title: Aplikaĵoj de Mastodon apps_title: Aplikaĵoj de Mastodon
checklist_subtitle: 'Nin eku vin en ĉi tiu nova socia rando:'
checklist_title: Bonvenan Markolisto checklist_title: Bonvenan Markolisto
edit_profile_action: Agordi edit_profile_action: Agordi
edit_profile_step: Plibonigi viajn interagojn per havas finitan profilon.
edit_profile_title: Agordi vian profilon edit_profile_title: Agordi vian profilon
explanation: Jen kelkaj konsiloj por helpi vin komenci explanation: Jen kelkaj konsiloj por helpi vin komenci
feature_action: Lerni pli feature_action: Lerni pli
feature_audience: Mastodon provizas vin per unika eblo por administri vian sekvantaron sen perantoj. Mastodon disponigita en via propra infrastrukturo ebligas al vi sekvi kaj esti sekvita de alia ajn Mastodon-servilo kaj estas tute sub via kontrolo nure.
feature_audience_title: Konstruu vian spektantaron memfide
feature_control: Vi scias plej bone, kion vi volas vidi en via hejmtemplinio. Neniaj algoritmoj nek reklamoj por malŝpari vian tempon. Sekvu iun ajn trans Mastodon-servilo ajn el unu konto kaj ricevu iliajn afiŝojn kronologie, kaj igu vian ejon de reto iom pli kiel vi.
feature_control_title: Havu la kontrolon de via propra templinio
feature_creativity: Mastodon subtenas aŭdaj, videajn kaj bildajn afiŝojn, priskribojn alireblecajn, enketojn, avertojn pri enhavo, animitajn bildetojn, personajn emoĝiojn, stucan kontrolon de bildetoj, kaj pli, por helpi al vi esprimi vin rete. Ĉu vi publikigas vian arton, vian muzikon, aŭ viajn podkastojn, Mastodon estas por vi.
feature_creativity_title: Senkompara kreemeco
feature_moderation: Mastodon denove donas al vi decidpovon. Ĉiu servilo kreas siajn proprajn regulojn kaj gvidliniojn, kiuj estas devigitaj loke kaj ne desupre kiel en firmaaj sociaj retejoj, igante ĝin la plej agordebla respondante al la bezonoj de malsamaj aroj de homoj. Aliĝu servilon kun la reguloj, kun kiuj vi konsentas, aŭ gastigu vian propran.
feature_moderation_title: Moderante kiel ĝi devus esti
follow_action: Sekvi follow_action: Sekvi
follow_step: Sekvi interesajn homojn estas pri kio Mastodon temas. follow_step: Sekvi interesajn homojn estas pri kio Mastodon temas.
follow_title: Personigu vian hejmtemplinion
follows_subtitle: Sekvu konatajn kontojn follows_subtitle: Sekvu konatajn kontojn
follows_title: Kiun sekvi follows_title: Kiun sekvi
follows_view_more: Rigardu pli da homoj por sekvi follows_view_more: Rigardu pli da homoj por sekvi
@ -1862,6 +1979,7 @@ eo:
invalid_otp_token: Nevalida kodo de dufaktora aŭtentigo invalid_otp_token: Nevalida kodo de dufaktora aŭtentigo
otp_lost_help_html: Se vi perdas aliron al ambaŭ, vi povas kontakti %{email} otp_lost_help_html: Se vi perdas aliron al ambaŭ, vi povas kontakti %{email}
rate_limited: Estas tro multaj aŭtentigaj provoj, reprovu poste. rate_limited: Estas tro multaj aŭtentigaj provoj, reprovu poste.
seamless_external_login: Vi estas ensalutinta per ekstera servo, do pasvortaj kaj retpoŝtaj agordoj ne estas disponeblaj.
signed_in_as: 'Salutinta kiel:' signed_in_as: 'Salutinta kiel:'
verification: verification:
extra_instructions_html: <strong>Konsilo:</strong> La ligilo en via retejo povas esti nevidebla. La grava parto estas <code>rel="me"</code>, kiu evitas identoŝtelon en retejoj kun enhavo generita de uzantoj. Vi povas eĉ uzi <code>link</code>-etikedon en la <code>header</code> de la paĝo anstataŭ <code>a</code>, sed la HTML devas esti atingebla sen plenumado de JavaScript. extra_instructions_html: <strong>Konsilo:</strong> La ligilo en via retejo povas esti nevidebla. La grava parto estas <code>rel="me"</code>, kiu evitas identoŝtelon en retejoj kun enhavo generita de uzantoj. Vi povas eĉ uzi <code>link</code>-etikedon en la <code>header</code> de la paĝo anstataŭ <code>a</code>, sed la HTML devas esti atingebla sen plenumado de JavaScript.

View file

@ -1069,11 +1069,11 @@ es-MX:
created_msg: El nuevo alias se ha creado correctamente. Ahora puedes empezar el traslado desde la cuenta antigua. created_msg: El nuevo alias se ha creado correctamente. Ahora puedes empezar el traslado desde la cuenta antigua.
deleted_msg: Elimina el alias correctamente. El traslado de esa cuenta a esta ya no será posible. deleted_msg: Elimina el alias correctamente. El traslado de esa cuenta a esta ya no será posible.
empty: No tienes ningún alias. empty: No tienes ningún alias.
hint_html: Si quieres migrar de otra cuenta a esta, aquí puedes crear un alias, es necesario proceder antes de empezar a mover seguidores de la cuenta anterior a esta. Esta acción por sí misma es <strong>inofensiva y reversible</strong>. <strong>La migración de la cuenta se inicia desde la cuenta antigua</strong>. hint_html: Si deseas migrar de otra cuenta a esta, aquí puedes crear un alias, que es necesario para poder mover seguidores de la cuenta anterior a esta. Esta acción por sí misma es <strong>inofensiva y reversible</strong>. <strong>La migración de la cuenta se inicia desde la cuenta anterior</strong>.
remove: Desvincular alias remove: Desvincular alias
appearance: appearance:
advanced_web_interface: Interfaz web avanzada advanced_web_interface: Interfaz web avanzada
advanced_web_interface_hint: 'Si quieres aprovechar todo el ancho de tu pantalla, la interfaz web avanzada te permite configurar muchas columnas diferentes para ver toda la información que quieras al mismo tiempo: Inicio, notificaciones, cronología federada, cualquier número de listas y etiquetas.' advanced_web_interface_hint: 'Si deseas aprovechar todo el ancho de tu pantalla, la interfaz web avanzada te permite configurar muchas columnas diferentes para ver toda la información que quieras al mismo tiempo: inicio, notificaciones, cronología federada, cualquier número de listas y etiquetas.'
animations_and_accessibility: Animaciones y accesibilidad animations_and_accessibility: Animaciones y accesibilidad
confirmation_dialogs: Diálogos de confirmación confirmation_dialogs: Diálogos de confirmación
discovery: Descubrir discovery: Descubrir

View file

@ -1 +1,16 @@
---
nan: nan:
admin:
instances:
dashboard:
instance_languages_dimension: Tsia̍p用ê語言
statuses:
language: 語言
trends:
tags:
dashboard:
tag_languages_dimension: Tsia̍p用ê語言
scheduled_statuses:
too_soon: Tio̍h用未來ê日期。
statuses:
default_language: Kap界面ê語言sio kâng

View file

@ -60,6 +60,7 @@ eo:
setting_display_media_default: Kaŝi plurmediojn markitajn kiel tiklaj setting_display_media_default: Kaŝi plurmediojn markitajn kiel tiklaj
setting_display_media_hide_all: Ĉiam kaŝi la plurmediojn setting_display_media_hide_all: Ĉiam kaŝi la plurmediojn
setting_display_media_show_all: Ĉiam montri la plurmediojn setting_display_media_show_all: Ĉiam montri la plurmediojn
setting_system_scrollbars_ui: Aplikas nur por surtablaj retumiloj baziĝas de Safari kaj Chrome
setting_use_blurhash: Transirojn estas bazita sur la koloroj de la kaŝitaj aŭdovidaĵoj sed ne montri iun ajn detalon setting_use_blurhash: Transirojn estas bazita sur la koloroj de la kaŝitaj aŭdovidaĵoj sed ne montri iun ajn detalon
setting_use_pending_items: Kaŝi tempoliniajn ĝisdatigojn malantaŭ klako anstataŭ aŭtomate rulumi la fluon setting_use_pending_items: Kaŝi tempoliniajn ĝisdatigojn malantaŭ klako anstataŭ aŭtomate rulumi la fluon
username: Vi povas uzi literojn, ciferojn kaj substrekojn username: Vi povas uzi literojn, ciferojn kaj substrekojn
@ -223,6 +224,7 @@ eo:
setting_hide_network: Kaŝi viajn sekvantojn kaj sekvatojn setting_hide_network: Kaŝi viajn sekvantojn kaj sekvatojn
setting_reduce_motion: Redukti la movecojn de la animacioj setting_reduce_motion: Redukti la movecojn de la animacioj
setting_system_font_ui: Uzi la dekomencan tiparon de la sistemo setting_system_font_ui: Uzi la dekomencan tiparon de la sistemo
setting_system_scrollbars_ui: Uzu la defaŭltan rulumilon de la sistemo
setting_theme: Etoso de la retejo setting_theme: Etoso de la retejo
setting_trends: Montri hodiaŭajn furoraĵojn setting_trends: Montri hodiaŭajn furoraĵojn
setting_unfollow_modal: Montri konfirman fenestron antaŭ ol ĉesi sekvi iun setting_unfollow_modal: Montri konfirman fenestron antaŭ ol ĉesi sekvi iun

View file

@ -16,43 +16,6 @@ def redirect_with_vary(path)
end end
Rails.application.routes.draw do Rails.application.routes.draw do
# Paths of routes on the web app that to not require to be indexed or
# have alternative format representations requiring separate controllers
web_app_paths = %w(
/getting-started
/keyboard-shortcuts
/home
/public
/public/local
/public/local/fixed
/public/remote
/conversations
/lists/(*any)
/antennas/(*any)
/circles/(*any)
/links/(*any)
/notifications/(*any)
/notifications_v2/(*any)
/favourites
/emoji_reactions
/bookmarks
/bookmark_categories/(*any)
/pinned
/reaction_deck
/start/(*any)
/directory
/explore/(*any)
/search
/publish
/follow_requests
/blocks
/domain_blocks
/mutes
/followed_tags
/statuses/(*any)
/deck/(*any)
).freeze
root 'home#index' root 'home#index'
mount LetterOpenerWeb::Engine, at: 'letter_opener' if Rails.env.development? mount LetterOpenerWeb::Engine, at: 'letter_opener' if Rails.env.development?
@ -236,9 +199,7 @@ Rails.application.routes.draw do
draw(:api) draw(:api)
web_app_paths.each do |path| draw(:web_app)
get path, to: 'home#index'
end
get '/web/(*any)', to: redirect('/%{any}', status: 302), as: :web, defaults: { any: '' }, format: false get '/web/(*any)', to: redirect('/%{any}', status: 302), as: :web, defaults: { any: '' }, format: false
get '/about', to: 'about#show' get '/about', to: 'about#show'

40
config/routes/web_app.rb Normal file
View file

@ -0,0 +1,40 @@
# frozen_string_literal: true
# Paths handled by the React application, which do not:
# - Require indexing
# - Have alternative format representations
%w(
/antennas/(*any)
/blocks
/bookmarks
/bookmark_categories/(*any)
/circles/(*any)
/conversations
/deck/(*any)
/directory
/domain_blocks
/emoji_reactions
/explore/(*any)
/favourites
/follow_requests
/followed_tags
/getting-started
/home
/keyboard-shortcuts
/links/(*any)
/lists/(*any)
/mutes
/notifications_v2/(*any)
/notifications/(*any)
/pinned
/public
/public/local
/public/local/fixed
/public/remote
/publish
/reaction_deck
/search
/start/(*any)
/statuses/(*any)
).each { |path| get path, to: 'home#index' }

View file

@ -8,6 +8,22 @@ class RemoveLegacyUserSettingsData < ActiveRecord::Migration[7.2]
thing_type IS NOT NULL thing_type IS NOT NULL
AND thing_id IS NOT NULL AND thing_id IS NOT NULL
SQL SQL
# When running these migrations on mastodon.social, we saw 'notification_emails'
# and 'interactions' records that were not associated to a user and caused a
# migration issue.
# While I have not been able to pinpoint the exact cause of the issue, it is likely
# related to the settings system changes made in b11fdc3ae3f90731c01149a5a36dc64e065d4ea2.
# So, delete a few user settings that should already have been deleted.
connection.execute(<<~SQL.squish)
DELETE FROM settings
WHERE var IN (
'notification_emails', 'interactions', 'boost_modal', 'auto_play_gif',
'delete_modal', 'system_font_ui', 'default_sensitive', 'unfollow_modal',
'reduce_motion', 'display_sensitive_media', 'hide_network', 'expand_spoilers',
'display_media', 'aggregate_reblogs', 'show_application', 'advanced_layout',
'use_blurhash', 'use_pending_items')
SQL
end end
def down def down

View file

@ -0,0 +1,28 @@
# frozen_string_literal: true
class AddMissingDeleteCascadeWebauthnCredentials < ActiveRecord::Migration[7.2]
def up
safety_assured do
execute <<~SQL.squish
ALTER TABLE webauthn_credentials
DROP CONSTRAINT fk_rails_a4355aef77,
ADD CONSTRAINT fk_rails_a4355aef77
FOREIGN KEY (user_id)
REFERENCES users(id)
ON DELETE CASCADE
SQL
end
end
def down
safety_assured do
execute <<~SQL.squish
ALTER TABLE webauthn_credentials
DROP CONSTRAINT fk_rails_a4355aef77,
ADD CONSTRAINT fk_rails_a4355aef77
FOREIGN KEY (user_id)
REFERENCES users(id)
SQL
end
end
end

View file

@ -0,0 +1,45 @@
# frozen_string_literal: true
class AddMissingDeleteCascadeAccountModerationNotes < ActiveRecord::Migration[7.2]
def up
safety_assured do
execute <<~SQL.squish
ALTER TABLE account_moderation_notes
DROP CONSTRAINT fk_rails_3f8b75089b,
ADD CONSTRAINT fk_rails_3f8b75089b
FOREIGN KEY (account_id)
REFERENCES accounts(id)
ON DELETE CASCADE
SQL
execute <<~SQL.squish
ALTER TABLE account_moderation_notes
DROP CONSTRAINT fk_rails_dd62ed5ac3,
ADD CONSTRAINT fk_rails_dd62ed5ac3
FOREIGN KEY (target_account_id)
REFERENCES accounts(id)
ON DELETE CASCADE
SQL
end
end
def down
safety_assured do
execute <<~SQL.squish
ALTER TABLE account_moderation_notes
DROP CONSTRAINT fk_rails_3f8b75089b,
ADD CONSTRAINT fk_rails_3f8b75089b
FOREIGN KEY (account_id)
REFERENCES accounts(id)
SQL
execute <<~SQL.squish
ALTER TABLE account_moderation_notes
DROP CONSTRAINT fk_rails_dd62ed5ac3,
ADD CONSTRAINT fk_rails_dd62ed5ac3
FOREIGN KEY (target_account_id)
REFERENCES accounts(id)
SQL
end
end
end

View file

@ -15,6 +15,22 @@ class RemoveLegacyUserSettingsColumns < ActiveRecord::Migration[7.2]
AND thing_id IS NOT NULL AND thing_id IS NOT NULL
SQL SQL
# When running these migrations on mastodon.social, we saw 'notification_emails'
# and 'interactions' records that were not associated to a user and caused a
# migration issue.
# While I have not been able to pinpoint the exact cause of the issue, it is likely
# related to the settings system changes made in b11fdc3ae3f90731c01149a5a36dc64e065d4ea2.
# So, delete a few user settings that should already have been deleted.
connection.execute(<<~SQL.squish)
DELETE FROM settings
WHERE var IN (
'notification_emails', 'interactions', 'boost_modal', 'auto_play_gif',
'delete_modal', 'system_font_ui', 'default_sensitive', 'unfollow_modal',
'reduce_motion', 'display_sensitive_media', 'hide_network', 'expand_spoilers',
'display_media', 'aggregate_reblogs', 'show_application', 'advanced_layout',
'use_blurhash', 'use_pending_items')
SQL
add_index :settings, :var, unique: true, algorithm: :concurrently add_index :settings, :var, unique: true, algorithm: :concurrently
remove_index :settings, [:thing_type, :thing_id, :var], name: :index_settings_on_thing_type_and_thing_id_and_var, unique: true remove_index :settings, [:thing_type, :thing_id, :var], name: :index_settings_on_thing_type_and_thing_id_and_var, unique: true

View file

@ -1606,8 +1606,8 @@ ActiveRecord::Schema[7.2].define(version: 2024_12_08_232829) do
add_foreign_key "account_domain_blocks", "accounts", name: "fk_206c6029bd", on_delete: :cascade add_foreign_key "account_domain_blocks", "accounts", name: "fk_206c6029bd", on_delete: :cascade
add_foreign_key "account_migrations", "accounts", column: "target_account_id", on_delete: :nullify add_foreign_key "account_migrations", "accounts", column: "target_account_id", on_delete: :nullify
add_foreign_key "account_migrations", "accounts", on_delete: :cascade add_foreign_key "account_migrations", "accounts", on_delete: :cascade
add_foreign_key "account_moderation_notes", "accounts" add_foreign_key "account_moderation_notes", "accounts", column: "target_account_id", on_delete: :cascade
add_foreign_key "account_moderation_notes", "accounts", column: "target_account_id" add_foreign_key "account_moderation_notes", "accounts", on_delete: :cascade
add_foreign_key "account_notes", "accounts", column: "target_account_id", on_delete: :cascade add_foreign_key "account_notes", "accounts", column: "target_account_id", on_delete: :cascade
add_foreign_key "account_notes", "accounts", on_delete: :cascade add_foreign_key "account_notes", "accounts", on_delete: :cascade
add_foreign_key "account_pins", "accounts", column: "target_account_id", on_delete: :cascade add_foreign_key "account_pins", "accounts", column: "target_account_id", on_delete: :cascade
@ -1764,7 +1764,7 @@ ActiveRecord::Schema[7.2].define(version: 2024_12_08_232829) do
add_foreign_key "web_push_subscriptions", "oauth_access_tokens", column: "access_token_id", on_delete: :cascade add_foreign_key "web_push_subscriptions", "oauth_access_tokens", column: "access_token_id", on_delete: :cascade
add_foreign_key "web_push_subscriptions", "users", on_delete: :cascade add_foreign_key "web_push_subscriptions", "users", on_delete: :cascade
add_foreign_key "web_settings", "users", name: "fk_11910667b2", on_delete: :cascade add_foreign_key "web_settings", "users", name: "fk_11910667b2", on_delete: :cascade
add_foreign_key "webauthn_credentials", "users" add_foreign_key "webauthn_credentials", "users", on_delete: :cascade
create_view "instances", materialized: true, sql_definition: <<-SQL create_view "instances", materialized: true, sql_definition: <<-SQL
WITH domain_counts(domain, accounts_count) AS ( WITH domain_counts(domain, accounts_count) AS (

View file

@ -10,8 +10,14 @@ RSpec.describe 'Custom CSS' do
it 'returns empty stylesheet' do it 'returns empty stylesheet' do
get '/custom.css' get '/custom.css'
expect(response.content_type).to include('text/css') expect(response)
expect(response.body.presence).to be_nil .to have_http_status(200)
.and have_cacheable_headers
.and have_attributes(
content_type: match('text/css')
)
expect(response.body.presence)
.to be_nil
end end
end end
@ -23,8 +29,14 @@ RSpec.describe 'Custom CSS' do
it 'returns stylesheet from settings' do it 'returns stylesheet from settings' do
get '/custom.css' get '/custom.css'
expect(response.content_type).to include('text/css') expect(response)
expect(response.body.strip).to eq(expected_css) .to have_http_status(200)
.and have_cacheable_headers
.and have_attributes(
content_type: match('text/css')
)
expect(response.body.strip)
.to eq(expected_css)
end end
def expected_css def expected_css
@ -44,8 +56,14 @@ RSpec.describe 'Custom CSS' do
it 'returns stylesheet from settings' do it 'returns stylesheet from settings' do
get '/custom.css' get '/custom.css'
expect(response.content_type).to include('text/css') expect(response)
expect(response.body.strip).to eq(expected_css) .to have_http_status(200)
.and have_cacheable_headers
.and have_attributes(
content_type: match('text/css')
)
expect(response.body.strip)
.to eq(expected_css)
end end
def expected_css def expected_css

View file

@ -1,18 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Custom stylesheets' do
describe 'GET /custom.css' do
before { get '/custom.css' }
it 'returns http success' do
expect(response)
.to have_http_status(200)
.and have_cacheable_headers
.and have_attributes(
content_type: match('text/css')
)
end
end
end

View file

@ -1372,8 +1372,8 @@ __metadata:
linkType: hard linkType: hard
"@babel/preset-react@npm:^7.12.5, @babel/preset-react@npm:^7.22.3": "@babel/preset-react@npm:^7.12.5, @babel/preset-react@npm:^7.22.3":
version: 7.25.9 version: 7.26.3
resolution: "@babel/preset-react@npm:7.25.9" resolution: "@babel/preset-react@npm:7.26.3"
dependencies: dependencies:
"@babel/helper-plugin-utils": "npm:^7.25.9" "@babel/helper-plugin-utils": "npm:^7.25.9"
"@babel/helper-validator-option": "npm:^7.25.9" "@babel/helper-validator-option": "npm:^7.25.9"
@ -1383,7 +1383,7 @@ __metadata:
"@babel/plugin-transform-react-pure-annotations": "npm:^7.25.9" "@babel/plugin-transform-react-pure-annotations": "npm:^7.25.9"
peerDependencies: peerDependencies:
"@babel/core": ^7.0.0-0 "@babel/core": ^7.0.0-0
checksum: 10c0/c294b475ee741f01f63ea0d828862811c453fabc6023f01814ce983bc316388e9d73290164d2b1384c2684db9c330803a3d4d2170285b105dcbacd483329eb93 checksum: 10c0/b470dcba11032ef6c832066f4af5c75052eaed49feb0f445227231ef1b5c42aacd6e216988c0bd469fd5728cd27b6b059ca307c9ecaa80c6bb5da4bf1c833e12
languageName: node languageName: node
linkType: hard linkType: hard
@ -1972,8 +1972,8 @@ __metadata:
linkType: hard linkType: hard
"@dnd-kit/core@npm:^6.1.0": "@dnd-kit/core@npm:^6.1.0":
version: 6.3.0 version: 6.3.1
resolution: "@dnd-kit/core@npm:6.3.0" resolution: "@dnd-kit/core@npm:6.3.1"
dependencies: dependencies:
"@dnd-kit/accessibility": "npm:^3.1.1" "@dnd-kit/accessibility": "npm:^3.1.1"
"@dnd-kit/utilities": "npm:^3.2.2" "@dnd-kit/utilities": "npm:^3.2.2"
@ -1981,7 +1981,7 @@ __metadata:
peerDependencies: peerDependencies:
react: ">=16.8.0" react: ">=16.8.0"
react-dom: ">=16.8.0" react-dom: ">=16.8.0"
checksum: 10c0/7b6ebae619921ac27a367b5f168cf66729ab2f5041a5376bb05399cdfd05e03c8fac5d218632ee04fe7c1e049bde9222930c6e8ee1dbb0ca8bde38038f1a1a48 checksum: 10c0/196db95d81096d9dc248983533eab91ba83591770fa5c894b1ac776f42af0d99522b3fd5bb3923411470e4733fcfa103e6ee17adc17b9b7eb54c7fbec5ff7c52
languageName: node languageName: node
linkType: hard linkType: hard
@ -8501,8 +8501,8 @@ __metadata:
linkType: hard linkType: hard
"express@npm:^4.17.1, express@npm:^4.18.2": "express@npm:^4.17.1, express@npm:^4.18.2":
version: 4.21.1 version: 4.21.2
resolution: "express@npm:4.21.1" resolution: "express@npm:4.21.2"
dependencies: dependencies:
accepts: "npm:~1.3.8" accepts: "npm:~1.3.8"
array-flatten: "npm:1.1.1" array-flatten: "npm:1.1.1"
@ -8523,7 +8523,7 @@ __metadata:
methods: "npm:~1.1.2" methods: "npm:~1.1.2"
on-finished: "npm:2.4.1" on-finished: "npm:2.4.1"
parseurl: "npm:~1.3.3" parseurl: "npm:~1.3.3"
path-to-regexp: "npm:0.1.10" path-to-regexp: "npm:0.1.12"
proxy-addr: "npm:~2.0.7" proxy-addr: "npm:~2.0.7"
qs: "npm:6.13.0" qs: "npm:6.13.0"
range-parser: "npm:~1.2.1" range-parser: "npm:~1.2.1"
@ -8535,7 +8535,7 @@ __metadata:
type-is: "npm:~1.6.18" type-is: "npm:~1.6.18"
utils-merge: "npm:1.0.1" utils-merge: "npm:1.0.1"
vary: "npm:~1.1.2" vary: "npm:~1.1.2"
checksum: 10c0/0c287867e5f6129d3def1edd9b63103a53c40d4dc8628839d4b6827e35eb8f0de5a4656f9d85f4457eba584f9871ebb2ad26c750b36bd75d9bbb8bcebdc4892c checksum: 10c0/38168fd0a32756600b56e6214afecf4fc79ec28eca7f7a91c2ab8d50df4f47562ca3f9dee412da7f5cea6b1a1544b33b40f9f8586dbacfbdada0fe90dbb10a1f
languageName: node languageName: node
linkType: hard linkType: hard
@ -13104,10 +13104,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"path-to-regexp@npm:0.1.10": "path-to-regexp@npm:0.1.12":
version: 0.1.10 version: 0.1.12
resolution: "path-to-regexp@npm:0.1.10" resolution: "path-to-regexp@npm:0.1.12"
checksum: 10c0/34196775b9113ca6df88e94c8d83ba82c0e1a2063dd33bfe2803a980da8d49b91db8104f49d5191b44ea780d46b8670ce2b7f4a5e349b0c48c6779b653f1afe4 checksum: 10c0/1c6ff10ca169b773f3bba943bbc6a07182e332464704572962d277b900aeee81ac6aa5d060ff9e01149636c30b1f63af6e69dd7786ba6e0ddb39d4dee1f0645b
languageName: node languageName: node
linkType: hard linkType: hard