Merge commit '0dac31dfd588e4cd866f382ed001a9535f06234a' into glitch-soc/merge-upstream
This commit is contained in:
commit
c8f365fd1d
@ -1,33 +1,65 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1Alpha::CollectionsController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
|
||||
render json: { error: ValidationErrorFormatter.new(e).as_json }, status: 422
|
||||
end
|
||||
|
||||
before_action :check_feature_enabled
|
||||
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:collections' }, only: [:create]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:collections' }, only: [:create, :update, :destroy]
|
||||
|
||||
before_action :require_user!, only: [:create]
|
||||
before_action :require_user!, only: [:create, :update, :destroy]
|
||||
|
||||
before_action :set_collection, only: [:show, :update, :destroy]
|
||||
|
||||
after_action :verify_authorized
|
||||
|
||||
def show
|
||||
cache_if_unauthenticated!
|
||||
@collection = Collection.find(params[:id])
|
||||
authorize @collection, :show?
|
||||
|
||||
render json: @collection, serializer: REST::CollectionSerializer
|
||||
end
|
||||
|
||||
def create
|
||||
@collection = CreateCollectionService.new.call(collection_params, current_user.account)
|
||||
authorize Collection, :create?
|
||||
|
||||
@collection = CreateCollectionService.new.call(collection_creation_params, current_user.account)
|
||||
|
||||
render json: @collection, serializer: REST::CollectionSerializer
|
||||
end
|
||||
|
||||
def update
|
||||
authorize @collection, :update?
|
||||
|
||||
@collection.update!(collection_update_params) # TODO: Create a service for this to federate changes
|
||||
|
||||
render json: @collection, serializer: REST::CollectionSerializer
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @collection, :destroy?
|
||||
|
||||
@collection.destroy
|
||||
|
||||
head 200
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def collection_params
|
||||
params.permit(:name, :description, :sensitive, :discoverable, :tag, account_ids: [])
|
||||
def set_collection
|
||||
@collection = Collection.find(params[:id])
|
||||
end
|
||||
|
||||
def collection_creation_params
|
||||
params.permit(:name, :description, :sensitive, :discoverable, :tag_name, account_ids: [])
|
||||
end
|
||||
|
||||
def collection_update_params
|
||||
params.permit(:name, :description, :sensitive, :discoverable, :tag_name)
|
||||
end
|
||||
|
||||
def check_feature_enabled
|
||||
|
||||
16
app/helpers/wrapstodon_helper.rb
Normal file
16
app/helpers/wrapstodon_helper.rb
Normal file
@ -0,0 +1,16 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module WrapstodonHelper
|
||||
def render_wrapstodon_share_data(report)
|
||||
json = ActiveModelSerializers::SerializableResource.new(
|
||||
AnnualReportsPresenter.new([report]),
|
||||
serializer: REST::AnnualReportsSerializer,
|
||||
scope: nil,
|
||||
scope_name: :current_user
|
||||
).to_json
|
||||
|
||||
# rubocop:disable Rails/OutputSafety
|
||||
content_tag(:script, json_escape(json).html_safe, type: 'application/json', id: 'wrapstodon-data')
|
||||
# rubocop:enable Rails/OutputSafety
|
||||
end
|
||||
end
|
||||
58
app/javascript/entrypoints/wrapstodon.tsx
Normal file
58
app/javascript/entrypoints/wrapstodon.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import { Provider as ReduxProvider } from 'react-redux';
|
||||
|
||||
import {
|
||||
importFetchedAccounts,
|
||||
importFetchedStatuses,
|
||||
} from '@/mastodon/actions/importer';
|
||||
import type { ApiAnnualReportResponse } from '@/mastodon/api/annual_report';
|
||||
import { Router } from '@/mastodon/components/router';
|
||||
import { WrapstodonShare } from '@/mastodon/features/annual_report/share';
|
||||
import { IntlProvider, loadLocale } from '@/mastodon/locales';
|
||||
import { loadPolyfills } from '@/mastodon/polyfills';
|
||||
import ready from '@/mastodon/ready';
|
||||
import { setReport } from '@/mastodon/reducers/slices/annual_report';
|
||||
import { store } from '@/mastodon/store';
|
||||
|
||||
function loaded() {
|
||||
const mountNode = document.getElementById('wrapstodon');
|
||||
if (!mountNode) {
|
||||
throw new Error('Mount node not found');
|
||||
}
|
||||
const propsNode = document.getElementById('wrapstodon-data');
|
||||
if (!propsNode) {
|
||||
throw new Error('Initial state prop not found');
|
||||
}
|
||||
|
||||
const initialState = JSON.parse(
|
||||
propsNode.textContent,
|
||||
) as ApiAnnualReportResponse;
|
||||
|
||||
const report = initialState.annual_reports[0];
|
||||
if (!report) {
|
||||
throw new Error('Initial state report not found');
|
||||
}
|
||||
store.dispatch(importFetchedAccounts(initialState.accounts));
|
||||
store.dispatch(importFetchedStatuses(initialState.statuses));
|
||||
|
||||
store.dispatch(setReport(report));
|
||||
|
||||
const root = createRoot(mountNode);
|
||||
root.render(
|
||||
<IntlProvider>
|
||||
<ReduxProvider store={store}>
|
||||
<Router>
|
||||
<WrapstodonShare />
|
||||
</Router>
|
||||
</ReduxProvider>
|
||||
</IntlProvider>,
|
||||
);
|
||||
}
|
||||
|
||||
loadPolyfills()
|
||||
.then(loadLocale)
|
||||
.then(() => ready(loaded))
|
||||
.catch((err: unknown) => {
|
||||
console.error(err);
|
||||
});
|
||||
@ -1,3 +1,5 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
import logo from '@/images/logo.svg';
|
||||
|
||||
export const WordmarkLogo: React.FC = () => (
|
||||
@ -7,8 +9,12 @@ export const WordmarkLogo: React.FC = () => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const IconLogo: React.FC = () => (
|
||||
<svg viewBox='0 0 79 79' className='logo logo--icon' role='img'>
|
||||
export const IconLogo: React.FC<{ className?: string }> = ({ className }) => (
|
||||
<svg
|
||||
viewBox='0 0 79 79'
|
||||
className={classNames('logo logo--icon', className)}
|
||||
role='img'
|
||||
>
|
||||
<title>Mastodon</title>
|
||||
<use xlinkHref='#logo-symbol-icon' />
|
||||
</svg>
|
||||
|
||||
@ -1,68 +1,64 @@
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import booster from '@/images/archetypes/booster.png';
|
||||
import lurker from '@/images/archetypes/lurker.png';
|
||||
import oracle from '@/images/archetypes/oracle.png';
|
||||
import pollster from '@/images/archetypes/pollster.png';
|
||||
import replier from '@/images/archetypes/replier.png';
|
||||
import type { Archetype as ArchetypeData } from 'mastodon/models/annual_report';
|
||||
import type { Archetype as ArchetypeData } from '@/mastodon/models/annual_report';
|
||||
|
||||
export const archetypeNames = defineMessages<ArchetypeData>({
|
||||
booster: {
|
||||
id: 'annual_report.summary.archetype.booster',
|
||||
defaultMessage: 'The cool-hunter',
|
||||
},
|
||||
replier: {
|
||||
id: 'annual_report.summary.archetype.replier',
|
||||
defaultMessage: 'The social butterfly',
|
||||
},
|
||||
pollster: {
|
||||
id: 'annual_report.summary.archetype.pollster',
|
||||
defaultMessage: 'The pollster',
|
||||
},
|
||||
lurker: {
|
||||
id: 'annual_report.summary.archetype.lurker',
|
||||
defaultMessage: 'The lurker',
|
||||
},
|
||||
oracle: {
|
||||
id: 'annual_report.summary.archetype.oracle',
|
||||
defaultMessage: 'The oracle',
|
||||
},
|
||||
});
|
||||
|
||||
export const Archetype: React.FC<{
|
||||
data: ArchetypeData;
|
||||
}> = ({ data }) => {
|
||||
let illustration, label;
|
||||
const intl = useIntl();
|
||||
let illustration;
|
||||
|
||||
switch (data) {
|
||||
case 'booster':
|
||||
illustration = booster;
|
||||
label = (
|
||||
<FormattedMessage
|
||||
id='annual_report.summary.archetype.booster'
|
||||
defaultMessage='The cool-hunter'
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case 'replier':
|
||||
illustration = replier;
|
||||
label = (
|
||||
<FormattedMessage
|
||||
id='annual_report.summary.archetype.replier'
|
||||
defaultMessage='The social butterfly'
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case 'pollster':
|
||||
illustration = pollster;
|
||||
label = (
|
||||
<FormattedMessage
|
||||
id='annual_report.summary.archetype.pollster'
|
||||
defaultMessage='The pollster'
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case 'lurker':
|
||||
illustration = lurker;
|
||||
label = (
|
||||
<FormattedMessage
|
||||
id='annual_report.summary.archetype.lurker'
|
||||
defaultMessage='The lurker'
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case 'oracle':
|
||||
illustration = oracle;
|
||||
label = (
|
||||
<FormattedMessage
|
||||
id='annual_report.summary.archetype.oracle'
|
||||
defaultMessage='The oracle'
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='annual-report__bento__box annual-report__summary__archetype'>
|
||||
<div className='annual-report__summary__archetype__label'>{label}</div>
|
||||
<div className='annual-report__summary__archetype__label'>
|
||||
{intl.formatMessage(archetypeNames[data])}
|
||||
</div>
|
||||
<img src={illustration} alt='' />
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,68 +1,38 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { defineMessage, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import {
|
||||
importFetchedStatuses,
|
||||
importFetchedAccounts,
|
||||
} from 'mastodon/actions/importer';
|
||||
import { apiRequestGet, apiRequestPost } from 'mastodon/api';
|
||||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||
import { me } from 'mastodon/initial_state';
|
||||
import type { Account } from 'mastodon/models/account';
|
||||
import type { AnnualReport as AnnualReportData } from 'mastodon/models/annual_report';
|
||||
import type { Status } from 'mastodon/models/status';
|
||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||
import { focusCompose, resetCompose } from '@/mastodon/actions/compose';
|
||||
import { closeModal } from '@/mastodon/actions/modal';
|
||||
import { Button } from '@/mastodon/components/button';
|
||||
import { LoadingIndicator } from '@/mastodon/components/loading_indicator';
|
||||
import { me } from '@/mastodon/initial_state';
|
||||
import type { AnnualReport as AnnualReportData } from '@/mastodon/models/annual_report';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { Archetype } from './archetype';
|
||||
import { Archetype, archetypeNames } from './archetype';
|
||||
import { Followers } from './followers';
|
||||
import { HighlightedPost } from './highlighted_post';
|
||||
import { MostUsedHashtag } from './most_used_hashtag';
|
||||
import { NewPosts } from './new_posts';
|
||||
import { Percentile } from './percentile';
|
||||
|
||||
interface AnnualReportResponse {
|
||||
annual_reports: AnnualReportData[];
|
||||
accounts: Account[];
|
||||
statuses: Status[];
|
||||
}
|
||||
const shareMessage = defineMessage({
|
||||
id: 'annual_report.summary.share_message',
|
||||
defaultMessage: 'I got the {archetype} archetype!',
|
||||
});
|
||||
|
||||
export const AnnualReport: React.FC<{
|
||||
year: string;
|
||||
}> = ({ year }) => {
|
||||
const [response, setResponse] = useState<AnnualReportResponse | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
// Share = false when using the embedded version of the report.
|
||||
export const AnnualReport: FC<{ share?: boolean }> = ({ share = true }) => {
|
||||
const currentAccount = useAppSelector((state) =>
|
||||
me ? state.accounts.get(me) : undefined,
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
const report = useAppSelector((state) => state.annualReport.report);
|
||||
|
||||
useEffect(() => {
|
||||
apiRequestGet<AnnualReportResponse>(`v1/annual_reports/${year}`)
|
||||
.then((data) => {
|
||||
dispatch(importFetchedStatuses(data.statuses));
|
||||
dispatch(importFetchedAccounts(data.accounts));
|
||||
|
||||
setResponse(data);
|
||||
setLoading(false);
|
||||
|
||||
return apiRequestPost(`v1/annual_reports/${year}/read`);
|
||||
})
|
||||
.catch(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, [dispatch, year, setResponse, setLoading]);
|
||||
|
||||
if (loading) {
|
||||
if (!report) {
|
||||
return <LoadingIndicator />;
|
||||
}
|
||||
|
||||
const report = response?.annual_reports[0];
|
||||
|
||||
if (!report || report.schema_version !== 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='annual-report'>
|
||||
<div className='annual-report__header'>
|
||||
@ -89,9 +59,37 @@ export const AnnualReport: React.FC<{
|
||||
total={currentAccount?.followers_count}
|
||||
/>
|
||||
<MostUsedHashtag data={report.data.top_hashtags} />
|
||||
<Percentile data={report.data.percentiles} />
|
||||
<NewPosts data={report.data.time_series} />
|
||||
{share && <ShareButton report={report} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ShareButton: FC<{ report: AnnualReportData }> = ({ report }) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const handleShareClick = useCallback(() => {
|
||||
// Generate the share message.
|
||||
const archetypeName = intl.formatMessage(
|
||||
archetypeNames[report.data.archetype],
|
||||
);
|
||||
const shareLines = [
|
||||
intl.formatMessage(shareMessage, {
|
||||
archetype: archetypeName,
|
||||
}),
|
||||
];
|
||||
// Share URL is only available for schema version 2.
|
||||
if (report.schema_version === 2 && report.share_url) {
|
||||
shareLines.push(report.share_url);
|
||||
}
|
||||
shareLines.push(`#Wrapstodon${report.year}`);
|
||||
|
||||
// Reset the composer and focus it with the share message, then close the modal.
|
||||
dispatch(resetCompose());
|
||||
dispatch(focusCompose(shareLines.join('\n\n')));
|
||||
dispatch(closeModal({ modalType: 'ANNUAL_REPORT', ignoreFocus: false }));
|
||||
}, [report, intl, dispatch]);
|
||||
|
||||
return <Button text='Share here' onClick={handleShareClick} />;
|
||||
};
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
.wrapper {
|
||||
max-width: 40rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 2rem;
|
||||
opacity: 0.6;
|
||||
}
|
||||
18
app/javascript/mastodon/features/annual_report/share.tsx
Normal file
18
app/javascript/mastodon/features/annual_report/share.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { IconLogo } from '@/mastodon/components/logo';
|
||||
|
||||
import { AnnualReport } from './index';
|
||||
import classes from './share.module.css';
|
||||
|
||||
export const WrapstodonShare: FC = () => {
|
||||
return (
|
||||
<main className={classes.wrapper}>
|
||||
<AnnualReport share={false} />
|
||||
<footer className={classes.footer}>
|
||||
<IconLogo className={classes.logo} />
|
||||
Generated with ♥ by the Mastodon team
|
||||
</footer>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
@ -1,7 +1,7 @@
|
||||
import { useCallback } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { showAlert } from '@/mastodon/actions/alerts';
|
||||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import {
|
||||
generateReport,
|
||||
selectWrapstodonYear,
|
||||
@ -20,12 +20,7 @@ export const AnnualReportTimeline: FC = () => {
|
||||
}, [dispatch]);
|
||||
|
||||
const handleOpen = useCallback(() => {
|
||||
dispatch(
|
||||
// TODO: Implement opening the annual report view when components are ready.
|
||||
showAlert({
|
||||
message: 'Not yet implemented.',
|
||||
}),
|
||||
);
|
||||
dispatch(openModal({ modalType: 'ANNUAL_REPORT', modalProps: {} }));
|
||||
}, [dispatch]);
|
||||
|
||||
if (!year || !state || state === 'ineligible') {
|
||||
|
||||
@ -3,16 +3,15 @@ import { useEffect } from 'react';
|
||||
import { AnnualReport } from 'mastodon/features/annual_report';
|
||||
|
||||
const AnnualReportModal: React.FC<{
|
||||
year: string;
|
||||
onChangeBackgroundColor: (arg0: string) => void;
|
||||
}> = ({ year, onChangeBackgroundColor }) => {
|
||||
onChangeBackgroundColor: (color: string) => void;
|
||||
}> = ({ onChangeBackgroundColor }) => {
|
||||
useEffect(() => {
|
||||
onChangeBackgroundColor('var(--indigo-1)');
|
||||
}, [onChangeBackgroundColor]);
|
||||
|
||||
return (
|
||||
<div className='modal-root__modal annual-report-modal'>
|
||||
<AnnualReport year={year} />
|
||||
<AnnualReport />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Апішыце гэта людзям з праблемамі са зрокам…",
|
||||
"alt_text_modal.done": "Гатова",
|
||||
"announcement.announcement": "Аб'ява",
|
||||
"annual_report.announcement.action_build": "Старыць мне Вынікадон",
|
||||
"annual_report.announcement.action_view": "Паглядзець мой Вынікадон",
|
||||
"annual_report.announcement.description": "Даведайцеся больш пра Вашыя ўзаемадзеянні ў Mastodon за апошні год.",
|
||||
"annual_report.announcement.title": "Вынікадон {year} ужо тут",
|
||||
"annual_report.summary.archetype.booster": "Паляўнічы на трэнды",
|
||||
"annual_report.summary.archetype.lurker": "Назіральнік",
|
||||
"annual_report.summary.archetype.oracle": "Аракул",
|
||||
|
||||
@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Descriviu això per a persones amb problemes visuals…",
|
||||
"alt_text_modal.done": "Fet",
|
||||
"announcement.announcement": "Anunci",
|
||||
"annual_report.announcement.action_build": "El meu Wrapstodon s'ha fet",
|
||||
"annual_report.announcement.action_view": "Vegeu el meu Wrapstodon",
|
||||
"annual_report.announcement.description": "Descobriu més sobre el vostre involucrament a Mastodon durant l'any passat.",
|
||||
"annual_report.announcement.title": "Ha arribat Wrapstodon {year}",
|
||||
"annual_report.summary.archetype.booster": "Sempre a la moda",
|
||||
"annual_report.summary.archetype.lurker": "Tot ho llegeix",
|
||||
"annual_report.summary.archetype.oracle": "L'Oracle",
|
||||
@ -131,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "publicacions noves",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Que us posa al</topLabel><percentage></percentage><bottomLabel>capdamunt dels usuaris de {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "No li ho direm al Bernie.",
|
||||
"annual_report.summary.share_message": "Tinc l'arquetip {archetype}!",
|
||||
"annual_report.summary.thanks": "Gràcies per formar part de Mastodon!",
|
||||
"attachments_list.unprocessed": "(sense processar)",
|
||||
"audio.hide": "Amaga l'àudio",
|
||||
@ -514,6 +519,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Mostra/amaga el text marcat com a sensible",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Mostra/amaga contingut",
|
||||
"keyboard_shortcuts.toot": "Escriu un nou tut",
|
||||
"keyboard_shortcuts.top": "Mou al capdamunt de la llista",
|
||||
"keyboard_shortcuts.translate": "per a traduir una publicació",
|
||||
"keyboard_shortcuts.unfocus": "Descentra l'àrea de composició de text/cerca",
|
||||
"keyboard_shortcuts.up": "Apuja a la llista",
|
||||
|
||||
@ -121,7 +121,7 @@
|
||||
"annual_report.summary.archetype.lurker": "Lureren",
|
||||
"annual_report.summary.archetype.oracle": "Oraklet",
|
||||
"annual_report.summary.archetype.pollster": "Afstemningsmageren",
|
||||
"annual_report.summary.archetype.replier": "Den social sommerfugl",
|
||||
"annual_report.summary.archetype.replier": "Den sociale sommerfugl",
|
||||
"annual_report.summary.followers.followers": "følgere",
|
||||
"annual_report.summary.followers.total": "{count} i alt",
|
||||
"annual_report.summary.here_it_is": "Her er dit {year} i sammendrag:",
|
||||
@ -135,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "nye indlæg",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Dermed er du i top</topLabel><percentage></percentage><bottomLabel>af {domain}-brugere.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Vi fortæller det ikke til nogen.",
|
||||
"annual_report.summary.share_message": "Min arketype er {archetype}!",
|
||||
"annual_report.summary.thanks": "Tak for at være en del af Mastodon!",
|
||||
"attachments_list.unprocessed": "(ubehandlet)",
|
||||
"audio.hide": "Skjul lyd",
|
||||
@ -613,7 +614,7 @@
|
||||
"notification.admin.report_statuses_other": "{name} anmeldte {target}",
|
||||
"notification.admin.sign_up": "{name} tilmeldte sig",
|
||||
"notification.admin.sign_up.name_and_others": "{name} og {count, plural, one {# anden} other {# andre}} tilmeldte sig",
|
||||
"notification.annual_report.message": "{year} #Wrapstodon venter! Afslør årets højdepunkter og mindeværdige øjeblikke på Mastodon!",
|
||||
"notification.annual_report.message": "Din {year} #Wrapstodon venter! Afslør årets højdepunkter og mindeværdige øjeblikke på Mastodon!",
|
||||
"notification.annual_report.view": "Vis #Wrapstodon",
|
||||
"notification.favourite": "{name} føjede dit indlæg til favoritter",
|
||||
"notification.favourite.name_and_others_with_link": "{name} og <a>{count, plural, one {# anden} other {# andre}}</a> føjede dit indlæg til favoritter",
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
"account.featured": "Vorgestellt",
|
||||
"account.featured.accounts": "Profile",
|
||||
"account.featured.hashtags": "Hashtags",
|
||||
"account.featured_tags.last_status_at": "Letzter Beitrag am {date}",
|
||||
"account.featured_tags.last_status_at": "Neuester Beitrag vom {date}",
|
||||
"account.featured_tags.last_status_never": "Keine Beiträge",
|
||||
"account.follow": "Folgen",
|
||||
"account.follow_back": "Ebenfalls folgen",
|
||||
@ -90,17 +90,17 @@
|
||||
"account.unmute": "Stummschaltung von @{name} aufheben",
|
||||
"account.unmute_notifications_short": "Stummschaltung der Benachrichtigungen aufheben",
|
||||
"account.unmute_short": "Stummschaltung aufheben",
|
||||
"account_note.placeholder": "Klicken, um Notiz hinzuzufügen",
|
||||
"admin.dashboard.daily_retention": "Verweildauer der Nutzer*innen pro Tag nach der Registrierung",
|
||||
"admin.dashboard.monthly_retention": "Verweildauer der Nutzer*innen pro Monat nach der Registrierung",
|
||||
"account_note.placeholder": "Klicken, um private Anmerkung hinzuzufügen",
|
||||
"admin.dashboard.daily_retention": "Verweildauer der Nutzer*innen pro Tag seit der Registrierung",
|
||||
"admin.dashboard.monthly_retention": "Verweildauer der Nutzer*innen pro Monat seit der Registrierung",
|
||||
"admin.dashboard.retention.average": "Durchschnitt",
|
||||
"admin.dashboard.retention.cohort": "Monat der Registrierung",
|
||||
"admin.dashboard.retention.cohort_size": "Neue Konten",
|
||||
"admin.impact_report.instance_accounts": "Profilkonten, die dadurch gelöscht würden",
|
||||
"admin.impact_report.instance_accounts": "Konten, die dadurch gelöscht würden",
|
||||
"admin.impact_report.instance_followers": "Follower, die unsere Nutzer*innen verlieren würden",
|
||||
"admin.impact_report.instance_follows": "Follower, die deren Nutzer*innen verlieren würden",
|
||||
"admin.impact_report.title": "Zusammenfassung der Auswirkung",
|
||||
"alert.rate_limited.message": "Bitte versuche es nach {retry_time, time, medium} erneut.",
|
||||
"alert.rate_limited.message": "Bitte versuche es um {retry_time, time, medium} erneut.",
|
||||
"alert.rate_limited.title": "Anfragelimit überschritten",
|
||||
"alert.unexpected.message": "Ein unerwarteter Fehler ist aufgetreten.",
|
||||
"alert.unexpected.title": "Ups!",
|
||||
@ -135,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "neue Beiträge",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Damit gehörst du zu den obersten</topLabel><percentage></percentage><bottomLabel>der Nutzer*innen auf {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Wir werden Bernie nichts verraten.",
|
||||
"annual_report.summary.share_message": "Ich habe den {archetype} Archetyp!",
|
||||
"annual_report.summary.thanks": "Danke, dass du Teil von Mastodon bist!",
|
||||
"attachments_list.unprocessed": "(ausstehend)",
|
||||
"audio.hide": "Audio ausblenden",
|
||||
@ -163,9 +164,9 @@
|
||||
"bundle_modal_error.retry": "Erneut versuchen",
|
||||
"carousel.current": "<sr>Seite</sr> {current, number}/{max, number}",
|
||||
"carousel.slide": "Seite {current, number} von {max, number}",
|
||||
"closed_registrations.other_server_instructions": "Da Mastodon dezentralisiert ist, kannst du ein Konto auf einem anderen Server erstellen und trotzdem mit diesem Server interagieren.",
|
||||
"closed_registrations.other_server_instructions": "Da Mastodon dezentralisiert ist, kannst du dich auch woanders im Fediverse registrieren und trotzdem mit diesem Server in Kontakt bleiben.",
|
||||
"closed_registrations_modal.description": "Das Anlegen eines Kontos auf {domain} ist derzeit nicht möglich, aber bedenke, dass du nicht zwingend auf {domain} ein Konto benötigst, um Mastodon nutzen zu können.",
|
||||
"closed_registrations_modal.find_another_server": "Einen anderen Server auswählen",
|
||||
"closed_registrations_modal.find_another_server": "Anderen Server suchen",
|
||||
"closed_registrations_modal.preamble": "Mastodon ist dezentralisiert, das heißt, unabhängig davon, wo du dein Konto erstellst, kannst du jedem Profil auf diesem Server folgen und mit ihm interagieren. Du kannst sogar deinen eigenen Mastodon-Server hosten!",
|
||||
"closed_registrations_modal.title": "Bei Mastodon registrieren",
|
||||
"column.about": "Über",
|
||||
@ -174,7 +175,7 @@
|
||||
"column.community": "Lokale Timeline",
|
||||
"column.create_list": "Liste erstellen",
|
||||
"column.direct": "Private Erwähnungen",
|
||||
"column.directory": "Profile durchsuchen",
|
||||
"column.directory": "Profile durchstöbern",
|
||||
"column.domain_blocks": "Blockierte Domains",
|
||||
"column.edit_list": "Liste bearbeiten",
|
||||
"column.favourites": "Favoriten",
|
||||
@ -288,8 +289,8 @@
|
||||
"copypaste.copied": "Kopiert",
|
||||
"copypaste.copy_to_clipboard": "In die Zwischenablage kopieren",
|
||||
"directory.federated": "Aus bekanntem Fediverse",
|
||||
"directory.local": "Nur von der Domain {domain}",
|
||||
"directory.new_arrivals": "Neue Benutzer*innen",
|
||||
"directory.local": "Nur von dieser Domain {domain}",
|
||||
"directory.new_arrivals": "Neue Profile",
|
||||
"directory.recently_active": "Kürzlich aktiv",
|
||||
"disabled_account_banner.account_settings": "Kontoeinstellungen",
|
||||
"disabled_account_banner.text": "Dein Konto {disabledAccount} ist derzeit deaktiviert.",
|
||||
@ -479,7 +480,7 @@
|
||||
"interaction_modal.action": "Melde dich auf deinem Mastodon-Server an, damit du mit dem Beitrag von {name} interagieren kannst.",
|
||||
"interaction_modal.go": "Los",
|
||||
"interaction_modal.no_account_yet": "Du hast noch kein Konto?",
|
||||
"interaction_modal.on_another_server": "Auf einem anderen Server",
|
||||
"interaction_modal.on_another_server": "Auf anderem Server",
|
||||
"interaction_modal.on_this_server": "Auf diesem Server",
|
||||
"interaction_modal.title": "Melde dich an, um fortzufahren",
|
||||
"interaction_modal.username_prompt": "z. B. {example}",
|
||||
|
||||
@ -135,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "νέες αναρτήσεις",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Αυτό σε βάζει στο </topLabel><percentage></percentage><bottomLabel>των κορυφαίων χρηστών του {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Δεν θα το πούμε στον Bernie.",
|
||||
"annual_report.summary.share_message": "Πήρα το αρχέτυπο {archetype}!",
|
||||
"annual_report.summary.thanks": "Ευχαριστούμε που συμμετέχεις στο Mastodon!",
|
||||
"attachments_list.unprocessed": "(μη επεξεργασμένο)",
|
||||
"audio.hide": "Απόκρυψη αρχείου ήχου",
|
||||
|
||||
@ -135,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "new posts",
|
||||
"annual_report.summary.percentile.text": "<topLabel>That puts you in the top</topLabel><percentage></percentage><bottomLabel>of {domain} users.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "We won't tell Bernie.",
|
||||
"annual_report.summary.share_message": "I got the {archetype} archetype!",
|
||||
"annual_report.summary.thanks": "Thanks for being part of Mastodon!",
|
||||
"attachments_list.unprocessed": "(unprocessed)",
|
||||
"audio.hide": "Hide audio",
|
||||
|
||||
@ -135,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "nuevos mensajes",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Eso te coloca en la cima del</topLabel><percentage></percentage><bottomLabel>de los usuarios de {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Queda entre nos.",
|
||||
"annual_report.summary.share_message": "¡Conseguí el arquetipo {archetype}!",
|
||||
"annual_report.summary.thanks": "¡Gracias por ser parte de Mastodon!",
|
||||
"attachments_list.unprocessed": "[sin procesar]",
|
||||
"audio.hide": "Ocultar audio",
|
||||
|
||||
@ -113,6 +113,7 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Describe esto para personas con discapacidad visual…",
|
||||
"alt_text_modal.done": "Hecho",
|
||||
"announcement.announcement": "Anuncio",
|
||||
"annual_report.announcement.action_build": "Preparar mi Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Ver mi Wrapstodon",
|
||||
"annual_report.announcement.description": "Descubre más sobre tu participación en Mastodon durante el último año.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} ha llegado",
|
||||
@ -134,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "nuevas publicaciones",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Eso te sitúa en el top</topLabel><percentage></percentage><bottomLabel>de usuarios de {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "No se lo diremos a Bernie.",
|
||||
"annual_report.summary.share_message": "¡Obtuve el arquetipo {archetype}!",
|
||||
"annual_report.summary.thanks": "¡Gracias por ser parte de Mastodon!",
|
||||
"attachments_list.unprocessed": "(sin procesar)",
|
||||
"audio.hide": "Ocultar audio",
|
||||
|
||||
@ -113,6 +113,7 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Descríbelo para personas con discapacidad visual…",
|
||||
"alt_text_modal.done": "Hecho",
|
||||
"announcement.announcement": "Comunicación",
|
||||
"annual_report.announcement.action_build": "Preparar mi Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Ver mi Wrapstodon",
|
||||
"annual_report.announcement.description": "Descubre más sobre tu participación en Mastodon durante el último año.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} ha llegado",
|
||||
@ -134,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "nuevas publicaciones",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Eso te coloca en el top</topLabel><percentage></percentage><bottomLabel>de usuarios de {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "No se lo diremos a Bernie.",
|
||||
"annual_report.summary.share_message": "¡Obtuve el arquetipo {archetype}!",
|
||||
"annual_report.summary.thanks": "¡Gracias por ser parte de Mastodon!",
|
||||
"attachments_list.unprocessed": "(sin procesar)",
|
||||
"audio.hide": "Ocultar audio",
|
||||
|
||||
@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Lýs hetta fyri fólk við tey, ið hava avmarkaða sjón…",
|
||||
"alt_text_modal.done": "Liðugt",
|
||||
"announcement.announcement": "Kunngerð",
|
||||
"annual_report.announcement.action_build": "Ger mítt Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Vís mítt Wrapstodon",
|
||||
"annual_report.announcement.description": "Fá meira at vita um títt virksemi á Mastodon seinasta árið.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} er komið",
|
||||
"annual_report.summary.archetype.booster": "Kuli jagarin",
|
||||
"annual_report.summary.archetype.lurker": "Lúrarin",
|
||||
"annual_report.summary.archetype.oracle": "Oraklið",
|
||||
|
||||
@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Décrire pour les personnes ayant des problèmes de vue…",
|
||||
"alt_text_modal.done": "Terminé",
|
||||
"announcement.announcement": "Annonce",
|
||||
"annual_report.announcement.action_build": "Générer mon Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Voir mon Wrapstodon",
|
||||
"annual_report.announcement.description": "En découvrir plus concernant votre activité sur Mastodon pour l'année écoulée.",
|
||||
"annual_report.announcement.title": "Le Wrapstodon {year} est arrivé",
|
||||
"annual_report.summary.archetype.booster": "Le chasseur de sang-froid",
|
||||
"annual_report.summary.archetype.lurker": "Le faucheur",
|
||||
"annual_report.summary.archetype.oracle": "L’oracle",
|
||||
@ -131,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "nouveaux messages",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Cela vous place dans le top</topLabel><percentage></percentage><bottomLabel>des utilisateurs de {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Nous ne le dirons pas à Bernie.",
|
||||
"annual_report.summary.share_message": "J’ai obtenu l’archétype {archetype} !",
|
||||
"annual_report.summary.thanks": "Merci de faire partie de Mastodon!",
|
||||
"attachments_list.unprocessed": "(non traité)",
|
||||
"audio.hide": "Masquer l'audio",
|
||||
@ -568,7 +573,7 @@
|
||||
"mute_modal.they_can_mention_and_follow": "Ils peuvent vous mentionner et vous suivre, mais vous ne les verrez pas.",
|
||||
"mute_modal.they_wont_know": "Ils ne sauront pas qu'ils ont été rendus silencieux.",
|
||||
"mute_modal.title": "Rendre cet utilisateur silencieux ?",
|
||||
"mute_modal.you_wont_see_mentions": "Vous ne verrez pas les publications qui le mentionne.",
|
||||
"mute_modal.you_wont_see_mentions": "Vous ne verrez pas les messages qui le mentionne.",
|
||||
"mute_modal.you_wont_see_posts": "Il peut toujours voir vos publications, mais vous ne verrez pas les siennes.",
|
||||
"navigation_bar.about": "À propos",
|
||||
"navigation_bar.account_settings": "Mot de passe et sécurité",
|
||||
@ -889,7 +894,7 @@
|
||||
"status.contains_quote": "Contient la citation",
|
||||
"status.context.loading": "Chargement de réponses supplémentaires",
|
||||
"status.context.loading_error": "Impossible de charger les nouvelles réponses",
|
||||
"status.context.loading_success": "Nouvelles réponses ont été chargées",
|
||||
"status.context.loading_success": "De nouvelles réponses ont été chargées",
|
||||
"status.context.more_replies_found": "Plus de réponses trouvées",
|
||||
"status.context.retry": "Réessayer",
|
||||
"status.context.show": "Montrer",
|
||||
|
||||
@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Décrire pour les personnes ayant des problèmes de vue…",
|
||||
"alt_text_modal.done": "Terminé",
|
||||
"announcement.announcement": "Annonce",
|
||||
"annual_report.announcement.action_build": "Générer mon Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Voir mon Wrapstodon",
|
||||
"annual_report.announcement.description": "En découvrir plus concernant votre activité sur Mastodon pour l'année écoulée.",
|
||||
"annual_report.announcement.title": "Le Wrapstodon {year} est arrivé",
|
||||
"annual_report.summary.archetype.booster": "Le chasseur de sang-froid",
|
||||
"annual_report.summary.archetype.lurker": "Le faucheur",
|
||||
"annual_report.summary.archetype.oracle": "L’oracle",
|
||||
@ -131,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "nouveaux messages",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Cela vous place dans le top</topLabel><percentage></percentage><bottomLabel>des utilisateurs de {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Nous ne le dirons pas à Bernie.",
|
||||
"annual_report.summary.share_message": "J’ai obtenu l’archétype {archetype} !",
|
||||
"annual_report.summary.thanks": "Merci de faire partie de Mastodon!",
|
||||
"attachments_list.unprocessed": "(non traité)",
|
||||
"audio.hide": "Masquer l'audio",
|
||||
@ -568,7 +573,7 @@
|
||||
"mute_modal.they_can_mention_and_follow": "Ils peuvent vous mentionner et vous suivre, mais vous ne les verrez pas.",
|
||||
"mute_modal.they_wont_know": "Ils ne sauront pas qu'ils ont été rendus silencieux.",
|
||||
"mute_modal.title": "Rendre cet utilisateur silencieux ?",
|
||||
"mute_modal.you_wont_see_mentions": "Vous ne verrez pas les publications qui le mentionne.",
|
||||
"mute_modal.you_wont_see_mentions": "Vous ne verrez pas les messages qui le mentionne.",
|
||||
"mute_modal.you_wont_see_posts": "Il peut toujours voir vos publications, mais vous ne verrez pas les siennes.",
|
||||
"navigation_bar.about": "À propos",
|
||||
"navigation_bar.account_settings": "Mot de passe et sécurité",
|
||||
@ -813,7 +818,7 @@
|
||||
"report.reasons.dislike": "Cela ne me plaît pas",
|
||||
"report.reasons.dislike_description": "Ce n'est pas quelque chose que vous voulez voir",
|
||||
"report.reasons.legal": "C'est illégal",
|
||||
"report.reasons.legal_description": "Vous pensez que cela viole la loi de votre pays ou celui du serveur",
|
||||
"report.reasons.legal_description": "Vous pensez que cela viole la loi de votre pays ou de celui du serveur",
|
||||
"report.reasons.other": "Pour une autre raison",
|
||||
"report.reasons.other_description": "Le problème ne correspond pas aux autres catégories",
|
||||
"report.reasons.spam": "C'est du spam",
|
||||
@ -889,7 +894,7 @@
|
||||
"status.contains_quote": "Contient la citation",
|
||||
"status.context.loading": "Chargement de réponses supplémentaires",
|
||||
"status.context.loading_error": "Impossible de charger les nouvelles réponses",
|
||||
"status.context.loading_success": "Nouvelles réponses ont été chargées",
|
||||
"status.context.loading_success": "De nouvelles réponses ont été chargées",
|
||||
"status.context.more_replies_found": "Plus de réponses trouvées",
|
||||
"status.context.retry": "Réessayer",
|
||||
"status.context.show": "Montrer",
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
{
|
||||
"about.blocks": "Freastalaithe faoi stiúir",
|
||||
"about.blocks": "Freastalaithe modhnaithe",
|
||||
"about.contact": "Teagmháil:",
|
||||
"about.default_locale": "Réamhshocrú",
|
||||
"about.disclaimer": "Bogearra foinse oscailte saor in aisce is ea Mastodon, agus is le Mastodon gGmbH an trádmharc.",
|
||||
"about.domain_blocks.no_reason_available": "Níl an fáth ar fáil",
|
||||
"about.domain_blocks.preamble": "Go hiondúil, tugann Mastadán cead duit a bheith ag plé le húsáideoirí as freastalaí ar bith eile sa chomhchruinne agus a gcuid inneachair a fheiceáil. Seo iad na heisceachtaí a rinneadh ar an bhfreastalaí áirithe seo.",
|
||||
"about.domain_blocks.no_reason_available": "Cúis nach bhfuil ar fáil",
|
||||
"about.domain_blocks.preamble": "Go ginearálta, tugann Mastodon deis duit ábhar a fheiceáil ó aon fhreastalaí eile sa fediverse agus idirghníomhú leo. Seo iad na heisceachtaí atá déanta ar an bhfreastalaí seo.",
|
||||
"about.domain_blocks.silenced.explanation": "Go hiondúil ní fheicfidh tú próifílí ná inneachar ón bhfreastalaí seo, ach amháin má bhíonn tú á lorg nó má ghlacann tú lena leanúint d'aon ghnó.",
|
||||
"about.domain_blocks.silenced.title": "Teoranta",
|
||||
"about.domain_blocks.suspended.explanation": "Ní dhéanfar aon sonra ón fhreastalaí seo a phróiseáil, a stóráil ná a mhalartú, rud a fhágann nach féidir aon teagmháil ná aon chumarsáid a dhéanamh le húsáideoirí ón fhreastalaí seo.",
|
||||
@ -15,17 +15,17 @@
|
||||
"about.rules": "Rialacha an fhreastalaí",
|
||||
"account.account_note_header": "Nóta pearsanta",
|
||||
"account.add_or_remove_from_list": "Cuir Le nó Bain De na liostaí",
|
||||
"account.badges.bot": "Bota",
|
||||
"account.badges.bot": "Uathoibrithe",
|
||||
"account.badges.group": "Grúpa",
|
||||
"account.block": "Déan cosc ar @{name}",
|
||||
"account.block": "Bac @{name}",
|
||||
"account.block_domain": "Bac ainm fearainn {domain}",
|
||||
"account.block_short": "Bloc",
|
||||
"account.block_short": "Bac",
|
||||
"account.blocked": "Bactha",
|
||||
"account.blocking": "Ag Blocáil",
|
||||
"account.cancel_follow_request": "Éirigh as iarratas leanta",
|
||||
"account.cancel_follow_request": "Cealaigh leanúint",
|
||||
"account.copy": "Cóipeáil nasc chuig an bpróifíl",
|
||||
"account.direct": "Luaigh @{name} go príobháideach",
|
||||
"account.disable_notifications": "Éirigh as ag cuir mé in eol nuair bpostálann @{name}",
|
||||
"account.disable_notifications": "Stop ag cur in iúl dom nuair a dhéanann @{name} postáil",
|
||||
"account.domain_blocking": "Fearann a bhlocáil",
|
||||
"account.edit_profile": "Cuir an phróifíl in eagar",
|
||||
"account.edit_profile_short": "Cuir in Eagar",
|
||||
@ -40,7 +40,7 @@
|
||||
"account.featured_tags.last_status_at": "Postáil is déanaí ar {date}",
|
||||
"account.featured_tags.last_status_never": "Gan aon phoist",
|
||||
"account.follow": "Lean",
|
||||
"account.follow_back": "Leanúint ar ais",
|
||||
"account.follow_back": "Lean ar ais",
|
||||
"account.follow_back_short": "Lean ar ais",
|
||||
"account.follow_request": "Iarratas chun leanúint",
|
||||
"account.follow_request_cancel": "Cealaigh an t-iarratas",
|
||||
@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Déan cur síos air seo do dhaoine a bhfuil lagú amhairc orthu…",
|
||||
"alt_text_modal.done": "Déanta",
|
||||
"announcement.announcement": "Fógra",
|
||||
"annual_report.announcement.action_build": "Tóg mo Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Féach ar mo Wrapstodon",
|
||||
"annual_report.announcement.description": "Faigh tuilleadh eolais faoi do rannpháirtíocht ar Mastodon le bliain anuas.",
|
||||
"annual_report.announcement.title": "Tá Wrapstodon {year} tagtha",
|
||||
"annual_report.summary.archetype.booster": "An sealgair fionnuar",
|
||||
"annual_report.summary.archetype.lurker": "An lurker",
|
||||
"annual_report.summary.archetype.oracle": "An oracal",
|
||||
|
||||
@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Describe isto para as persoas con dificultades visuais…",
|
||||
"alt_text_modal.done": "Feito",
|
||||
"announcement.announcement": "Anuncio",
|
||||
"annual_report.announcement.action_build": "Crear o meu Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Ver o meu Wrapstodon",
|
||||
"annual_report.announcement.description": "Olla o que andiveches facendo en Mastodon durante o último ano.",
|
||||
"annual_report.announcement.title": "Chegou o Wrapstodon de {year}",
|
||||
"annual_report.summary.archetype.booster": "O Telexornal",
|
||||
"annual_report.summary.archetype.lurker": "Volleur",
|
||||
"annual_report.summary.archetype.oracle": "Sabichón",
|
||||
@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Para mostrar o texto tras Aviso de Contido (CW)",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Para amosar/agochar contido multimedia",
|
||||
"keyboard_shortcuts.toot": "Para escribir unha nova publicación",
|
||||
"keyboard_shortcuts.top": "Mover arriba de todo",
|
||||
"keyboard_shortcuts.translate": "para traducir unha publicación",
|
||||
"keyboard_shortcuts.unfocus": "Para deixar de destacar a área de escritura/procura",
|
||||
"keyboard_shortcuts.up": "Para mover cara arriba na listaxe",
|
||||
|
||||
@ -135,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "הודעות חדשות",
|
||||
"annual_report.summary.percentile.text": "<topLabel>ממקם אותך באחוזון </topLabel><percentage></percentage><bottomLabel>של משמשי {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "לא נגלה לברני.",
|
||||
"annual_report.summary.share_message": "זוהיתי כדוגמא לטיפוס {archetype}!",
|
||||
"annual_report.summary.thanks": "תודה על היותך חלק ממסטודון!",
|
||||
"attachments_list.unprocessed": "(לא מעובד)",
|
||||
"audio.hide": "השתק",
|
||||
|
||||
@ -113,7 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Írd le a látássérültek számára…",
|
||||
"alt_text_modal.done": "Kész",
|
||||
"announcement.announcement": "Közlemény",
|
||||
"annual_report.announcement.action_view": "A Wrapstodon-om megtekintése",
|
||||
"annual_report.announcement.action_build": "Saját Wrapstodon összeállítása",
|
||||
"annual_report.announcement.action_view": "Saját Wrapstodon megtekintése",
|
||||
"annual_report.announcement.description": "Fedezz fel többet a Mastodonon az elmúlt évben végzett tevékenységeidről.",
|
||||
"annual_report.announcement.title": "A Wrapstodon {year} megérkezett",
|
||||
"annual_report.summary.archetype.booster": "A cool-vadász",
|
||||
"annual_report.summary.archetype.lurker": "A settenkedő",
|
||||
"annual_report.summary.archetype.oracle": "Az orákulum",
|
||||
@ -517,7 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Tartalmi figyelmeztetéssel ellátott szöveg megjelenítése/elrejtése",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Média megjelenítése/elrejtése",
|
||||
"keyboard_shortcuts.toot": "Új bejegyzés írása",
|
||||
"keyboard_shortcuts.top": "Ugorj a lista elejére",
|
||||
"keyboard_shortcuts.top": "Ugrás a lista elejére",
|
||||
"keyboard_shortcuts.translate": "Bejegyzés lefordítása",
|
||||
"keyboard_shortcuts.unfocus": "Szerkesztés/keresés fókuszból való kivétele",
|
||||
"keyboard_shortcuts.up": "Mozgás felfelé a listában",
|
||||
@ -611,7 +614,7 @@
|
||||
"notification.admin.sign_up": "{name} regisztrált",
|
||||
"notification.admin.sign_up.name_and_others": "{name} és {count, plural, one {# másik} other {# másik}} regisztrált",
|
||||
"notification.annual_report.message": "Vár a {year}. év #Wrapstodon jelentése! Fedd fel az éved jelentős eseményeit és emlékezetes pillanatait a Mastodonon!",
|
||||
"notification.annual_report.view": "#Wrapstodon Megtekintése",
|
||||
"notification.annual_report.view": "#Wrapstodon megtekintése",
|
||||
"notification.favourite": "{name} kedvencnek jelölte a bejegyzésedet",
|
||||
"notification.favourite.name_and_others_with_link": "{name} és <a>{count, plural, one {# másik} other {# másik}}</a> kedvencnek jelölte a bejegyzésedet",
|
||||
"notification.favourite_pm": "{name} kedvelte a privát említésedet",
|
||||
|
||||
@ -135,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "nýjar færslur",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Þetta setur þig á meðal</topLabel><percentage></percentage><bottomLabel>of {domain} virkustu notendanna.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Við förum ekkert að raupa um þetta.",
|
||||
"annual_report.summary.share_message": "Ég er víst {archetype}-týpan!",
|
||||
"annual_report.summary.thanks": "Takk fyrir að vera hluti af Mastodon-samfélaginu!",
|
||||
"attachments_list.unprocessed": "(óunnið)",
|
||||
"audio.hide": "Fela hljóð",
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
"account.followers_counter": "{count, plural, one {{counter} sekėjas} few {{counter} sekėjai} many {{counter} sekėjo} other {{counter} sekėjų}}",
|
||||
"account.followers_you_know_counter": "{counter} žinomas",
|
||||
"account.following": "Sekama",
|
||||
"account.following_counter": "{count, plural, one {{counter} sekimas} few {{counter} sekimai} many {{counter} sekimo} other {{counter} sekimų}}",
|
||||
"account.following_counter": "{count, plural, one {{counter} seka} few {{counter} seka} many {{counter} seka} other {{counter} seka}}",
|
||||
"account.follows.empty": "Šis naudotojas dar nieko neseka.",
|
||||
"account.follows_you": "Seka tave",
|
||||
"account.go_to_profile": "Eiti į profilį",
|
||||
@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Aprašykite tai regos sutrikimų turintiems asmenims…",
|
||||
"alt_text_modal.done": "Atlikta",
|
||||
"announcement.announcement": "Skelbimas",
|
||||
"annual_report.announcement.action_build": "Sukurti mano Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Peržiūrėti mano Wrapstodon",
|
||||
"annual_report.announcement.description": "Sužinokite daugiau apie savo aktyvumą Mastodon\"e per pastaruosius metus.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} jau čia",
|
||||
"annual_report.summary.archetype.booster": "Šaunus medžiotojas",
|
||||
"annual_report.summary.archetype.lurker": "Stebėtojas",
|
||||
"annual_report.summary.archetype.oracle": "Vydūnas",
|
||||
@ -131,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "nauji įrašai",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Tai reiškia, kad esate tarp</topLabel><percentage></percentage><bottomLabel>populiariausių {domain} naudotojų.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Mes nesakysime Bernie.",
|
||||
"annual_report.summary.share_message": "Aš gavau {archetype}!",
|
||||
"annual_report.summary.thanks": "Dėkojame, kad esate „Mastodon“ dalis!",
|
||||
"attachments_list.unprocessed": "(neapdorotas)",
|
||||
"audio.hide": "Slėpti garsą",
|
||||
@ -157,6 +162,7 @@
|
||||
"bundle_modal_error.close": "Uždaryti",
|
||||
"bundle_modal_error.message": "Įkeliant šį ekraną kažkas nutiko ne taip.",
|
||||
"bundle_modal_error.retry": "Bandyti dar kartą",
|
||||
"carousel.current": "<sr>Skirtukas</sr> {current, number} / {max, number}",
|
||||
"carousel.slide": "Rodoma {current, number} iš {max, number}",
|
||||
"closed_registrations.other_server_instructions": "Kadangi „Mastodon“ yra decentralizuotas, gali susikurti paskyrą kitame serveryje ir vis tiek bendrauti su šiuo serveriu.",
|
||||
"closed_registrations_modal.description": "Sukurti paskyrą serveryje {domain} šiuo metu neįmanoma, bet nepamiršk, kad norint naudotis „Mastodon“ nebūtina turėti paskyrą serveryje {domain}.",
|
||||
@ -640,6 +646,8 @@
|
||||
"notification.reblog": "{name} pakėlė tavo įrašą",
|
||||
"notification.reblog.name_and_others_with_link": "{name} ir <a>{count, plural,one {dar kažkas} few {# kiti} other {# kitų}}</a> paryškino tavo įrašą",
|
||||
"notification.relationships_severance_event": "Prarasti sąryšiai su {name}",
|
||||
"notification.relationships_severance_event.account_suspension": "Administratorius iš {from} sustabdė {target}, todėl jūs nebegalėsite gauti jų naujienų ar bendrauti su jais.",
|
||||
"notification.relationships_severance_event.domain_block": "Administratorius iš {from} užblokavo {target}, įskaitant {followersCount} iš tavo sekėjų ir {followingCount, plural,one {# žmogų, kurį} few {# žmones, kuriuos} other {# žmonių, kuriuos}} seki.",
|
||||
"notification.relationships_severance_event.learn_more": "Sužinoti daugiau",
|
||||
"notification.relationships_severance_event.user_domain_block": "Tu užblokavai {target}. Pašalinama {followersCount} savo sekėjų ir {followingCount, plural, one {# paskyrą} few {# paskyrai} many {# paskyros} other {# paskyrų}}, kurios seki.",
|
||||
"notification.status": "{name} ką tik paskelbė",
|
||||
@ -710,8 +718,10 @@
|
||||
"notifications.policy.filter_new_accounts.hint": "Sukurta per {days, plural, one {vieną dieną} few {# dienas} many {# dienos} other {# dienų}}",
|
||||
"notifications.policy.filter_new_accounts_title": "Naujos paskyros",
|
||||
"notifications.policy.filter_not_followers_hint": "Įskaitant žmones, kurie seka jus mažiau nei {days, plural, one {vieną dieną} few {# dienas} many {# dienų} other {# dienų}}",
|
||||
"notifications.policy.filter_not_followers_title": "Žmonės, kurie neseka tavęs",
|
||||
"notifications.policy.filter_not_following_hint": "Kol jų nepatvirtinsi rankiniu būdu",
|
||||
"notifications.policy.filter_not_following_title": "Žmonių, kuriuos neseki",
|
||||
"notifications.policy.filter_private_mentions_hint": "Filtruojama, išskyrus atsakymus į tavo paties paminėjimą arba jei seki siuntėją",
|
||||
"notifications.policy.filter_private_mentions_title": "Nepageidaujami privatūs paminėjimai",
|
||||
"notifications.policy.title": "Tvarkyti pranešimus iš…",
|
||||
"notifications_permission_banner.enable": "Įjungti darbalaukio pranešimus",
|
||||
@ -756,6 +766,7 @@
|
||||
"privacy.quote.disabled": "{visibility}, paminėjimai išjungti",
|
||||
"privacy.quote.limited": "{visibility}, paminėjimai apriboti",
|
||||
"privacy.unlisted.additional": "Tai veikia lygiai taip pat, kaip ir vieša, tik įrašas nebus rodomas tiesioginiuose srautuose, saitažodžiose, naršyme ar Mastodon paieškoje, net jei esi įtraukęs (-usi) visą paskyrą.",
|
||||
"privacy.unlisted.long": "Paslėptas nuo „Mastodon“ paieškos rezultatų, tendencijų ir viešų įrašų sienų",
|
||||
"privacy.unlisted.short": "Tyliai vieša",
|
||||
"privacy_policy.last_updated": "Paskutinį kartą atnaujinta {date}",
|
||||
"privacy_policy.title": "Privatumo politika",
|
||||
@ -836,6 +847,7 @@
|
||||
"report_notification.categories.violation": "Taisyklės pažeidimas",
|
||||
"report_notification.categories.violation_sentence": "taisyklės pažeidimas",
|
||||
"report_notification.open": "Atidaryti ataskaitą",
|
||||
"search.clear": "Išvalyti paiešką",
|
||||
"search.no_recent_searches": "Nėra naujausių paieškų.",
|
||||
"search.placeholder": "Paieška",
|
||||
"search.quick_action.account_search": "Profiliai, atitinkantys {x}",
|
||||
@ -880,9 +892,16 @@
|
||||
"status.cannot_quote": "Jums neleidžiama paminėti šio įrašo",
|
||||
"status.cannot_reblog": "Šis įrašas negali būti pakeltas.",
|
||||
"status.contains_quote": "Turi citatą",
|
||||
"status.context.loading": "Įkeliama daugiau atsakymų",
|
||||
"status.context.loading_error": "Nepavyko įkelti naujų atsakymų",
|
||||
"status.context.loading_success": "Įkelti nauji atsakymai",
|
||||
"status.context.more_replies_found": "Rasta daugiau atsakymų",
|
||||
"status.context.retry": "Kartoti",
|
||||
"status.context.show": "Rodyti",
|
||||
"status.continued_thread": "Tęsiama gijoje",
|
||||
"status.copy": "Kopijuoti nuorodą į įrašą",
|
||||
"status.delete": "Ištrinti",
|
||||
"status.delete.success": "Įrašas ištrintas",
|
||||
"status.detailed_status": "Išsami pokalbio peržiūra",
|
||||
"status.direct": "Privačiai paminėti @{name}",
|
||||
"status.direct_indicator": "Privatus paminėjimas",
|
||||
@ -957,6 +976,8 @@
|
||||
"subscribed_languages.target": "Keisti prenumeruojamas kalbas {target}",
|
||||
"tabs_bar.home": "Pagrindinis",
|
||||
"tabs_bar.notifications": "Pranešimai",
|
||||
"tabs_bar.publish": "Naujas įrašas",
|
||||
"tabs_bar.search": "Paieška",
|
||||
"terms_of_service.effective_as_of": "Įsigaliojo nuo {date}.",
|
||||
"terms_of_service.title": "Paslaugų sąlygos",
|
||||
"terms_of_service.upcoming_changes_on": "Numatomi pakeitimai {date}.",
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
"admin.dashboard.retention.cohort_size": "ਨਵੇਂ ਵਰਤੋਂਕਾਰ",
|
||||
"alert.unexpected.title": "ਓਹੋ!",
|
||||
"alt_text_badge.title": "ਬਦਲੀ ਲਿਖਤ",
|
||||
"alt_text_modal.add_alt_text": "ਬਦਲਵੀ ਲਿਖਤ ਜੋੜੋ",
|
||||
"alt_text_modal.add_alt_text": "ਬਦਲਵੀ ਲਿਖਤ ਨੂੰ ਜੋੜੋ",
|
||||
"alt_text_modal.cancel": "ਰੱਦ ਕਰੋ",
|
||||
"alt_text_modal.done": "ਮੁਕੰਮਲ",
|
||||
"announcement.announcement": "ਹੋਕਾ",
|
||||
@ -110,6 +110,7 @@
|
||||
"bundle_modal_error.retry": "ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰੋ",
|
||||
"carousel.current": "<sr>ਸਲਾਈਡ</sr> {current, number} / {max, number}",
|
||||
"carousel.slide": "{max, number} ਵਿੱਚੋਂ {current, number} ਸਲਾਈਡ",
|
||||
"closed_registrations_modal.find_another_server": "ਹੋਰ ਸਰਵਰ ਲੱਭੋ",
|
||||
"closed_registrations_modal.title": "Mastodon ਲਈ ਸਾਈਨ ਅੱਪ ਕਰੋ",
|
||||
"column.about": "ਸਾਡੇ ਬਾਰੇ",
|
||||
"column.blocks": "ਪਾਬੰਦੀ ਲਾਏ ਵਰਤੋਂਕਾਰ",
|
||||
@ -172,14 +173,20 @@
|
||||
"confirmations.delete_list.confirm": "ਹਟਾਓ",
|
||||
"confirmations.delete_list.message": "ਕੀ ਤੁਸੀਂ ਇਸ ਸੂਚੀ ਨੂੰ ਪੱਕੇ ਤੌਰ ਉੱਤੇ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?",
|
||||
"confirmations.delete_list.title": "ਸੂਚੀ ਨੂੰ ਹਟਾਉਣਾ ਹੈ?",
|
||||
"confirmations.discard_draft.confirm": "ਖ਼ਾਰਜ ਕਰਕੇ ਜਾਰੀ ਰੱਖੋ",
|
||||
"confirmations.discard_draft.edit.cancel": "ਸੋਧਣਾ ਜਾਰੀ ਰੱਖੋ",
|
||||
"confirmations.discard_draft.post.cancel": "ਖਰੜੇ ਉੱਤੇ ਕੰਮ ਜਾਰੀ ਰੱਖੋ",
|
||||
"confirmations.discard_edit_media.confirm": "ਰੱਦ ਕਰੋ",
|
||||
"confirmations.follow_to_list.confirm": "ਫ਼ਾਲੋ ਕਰੋ ਅਤੇ ਲਿਸਟ 'ਚ ਜੋੜੋ",
|
||||
"confirmations.follow_to_list.title": "ਵਰਤੋਂਕਾਰ ਨੂੰ ਫ਼ਾਲੋ ਕਰਨਾ ਹੈ?",
|
||||
"confirmations.logout.confirm": "ਬਾਹਰ ਹੋਵੋ",
|
||||
"confirmations.logout.message": "ਕੀ ਤੁਸੀਂ ਲਾਗ ਆਉਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?",
|
||||
"confirmations.logout.title": "ਲਾਗ ਆਉਟ ਕਰਨਾ ਹੈ?",
|
||||
"confirmations.missing_alt_text.confirm": "ਬਦਲਵੀ ਲਿਖਤ ਨੂੰ ਜੋੜੋ",
|
||||
"confirmations.missing_alt_text.secondary": "ਕਿਵੇਂ ਵੀ ਪੋਸਟ ਕਰੋ",
|
||||
"confirmations.missing_alt_text.title": "ਬਦਲਵੀ ਲਿਖਤ ਜੋੜਨੀ ਹੈ?",
|
||||
"confirmations.mute.confirm": "ਮੌਨ ਕਰੋ",
|
||||
"confirmations.private_quote_notify.cancel": "ਸੋਧ ਕਰਨ ਉੱਤੇ ਵਾਪਸ ਜਾਓ",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "ਮੈਨੂੰ ਇਹ ਸੁਨੇਹਾ ਫੇਰ ਨਾ ਦਿਖਾਓ",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "ਮੈਨੂੰ ਮੁੜ ਕੇ ਯਾਦ ਨਾ ਕਰਵਾਓ",
|
||||
"confirmations.quiet_post_quote_info.got_it": "ਸਮਝ ਗਏ",
|
||||
@ -260,6 +267,7 @@
|
||||
"filter_modal.select_filter.search": "ਖੋਜੋ ਜਾਂ ਬਣਾਓ",
|
||||
"filter_modal.select_filter.title": "ਇਸ ਪੋਸਟ ਨੂੰ ਫਿਲਟਰ ਕਰੋ",
|
||||
"filter_modal.title.status": "ਇੱਕ ਪੋਸਟ ਨੂੰ ਫਿਲਟਰ ਕਰੋ",
|
||||
"filtered_notifications_banner.title": "ਫਿਲਟਰ ਕੀਤੇ ਨੋਟੀਫਿਕੇਸ਼ਨ",
|
||||
"firehose.all": "ਸਭ",
|
||||
"firehose.local": "ਇਹ ਸਰਵਰ",
|
||||
"firehose.remote": "ਹੋਰ ਸਰਵਰ",
|
||||
@ -294,6 +302,7 @@
|
||||
"hashtag.column_settings.tag_mode.none": "ਇਹਨਾਂ ਵਿੱਚੋਂ ਕੋਈ ਨਹੀਂ",
|
||||
"hashtag.column_settings.tag_toggle": "Include additional tags in this column",
|
||||
"hashtag.follow": "ਹੈਸ਼ਟੈਗ ਨੂੰ ਫ਼ਾਲੋ ਕਰੋ",
|
||||
"hashtag.mute": "#{hashtag} ਨੂੰ ਮੌਨ ਕਰੋ",
|
||||
"hashtag.unfollow": "ਹੈਸ਼ਟੈਗ ਨੂੰ ਅਣ-ਫ਼ਾਲੋ ਕਰੋ",
|
||||
"hints.profiles.see_more_followers": "{domain} ਉੱਤੇ ਹੋਰ ਫ਼ਾਲੋਅਰ ਵੇਖੋ",
|
||||
"hints.profiles.see_more_follows": "{domain} ਉੱਤੇ ਹੋਰ ਫ਼ਾਲੋ ਨੂੰ ਵੇਖੋ",
|
||||
@ -310,6 +319,7 @@
|
||||
"interaction_modal.no_account_yet": "ਹਾਲੇ ਖਾਤਾ ਨਹੀਂ ਹੈ?",
|
||||
"interaction_modal.on_another_server": "ਵੱਖਰੇ ਸਰਵਰ ਉੱਤੇ",
|
||||
"interaction_modal.on_this_server": "ਇਸ ਸਰਵਰ ਉੱਤੇ",
|
||||
"interaction_modal.title": "ਜਾਰੀ ਰੱਖਣ ਲਈ ਸਾਈਨ ਇਨ ਕਰੋ",
|
||||
"interaction_modal.username_prompt": "ਜਿਵੇਂ {example}",
|
||||
"intervals.full.days": "{number, plural, one {# ਦਿਨ} other {# ਦਿਨ}}",
|
||||
"intervals.full.hours": "{number, plural, one {# ਘੰਟਾ} other {# ਘੰਟੇ}}",
|
||||
@ -380,6 +390,7 @@
|
||||
"loading_indicator.label": "ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ…",
|
||||
"media_gallery.hide": "ਲੁਕਾਓ",
|
||||
"mute_modal.hide_from_notifications": "ਨੋਟੀਫਿਕੇਸ਼ਨਾਂ ਵਿੱਚੋਂ ਲੁਕਾਓ",
|
||||
"mute_modal.hide_options": "ਚੋਣਾਂ ਨੂੰ ਲੁਕਾਓ",
|
||||
"mute_modal.show_options": "ਚੋਣਾਂ ਨੂੰ ਵੇਖਾਓ",
|
||||
"mute_modal.title": "ਵਰਤੋਂਕਾਰ ਨੂੰ ਮੌਨ ਕਰਨਾ ਹੈ?",
|
||||
"navigation_bar.about": "ਇਸ ਬਾਰੇ",
|
||||
@ -397,6 +408,8 @@
|
||||
"navigation_bar.followed_tags": "ਫ਼ਾਲੋ ਕੀਤੇ ਹੈਸ਼ਟੈਗ",
|
||||
"navigation_bar.follows_and_followers": "ਫ਼ਾਲੋ ਅਤੇ ਫ਼ਾਲੋ ਕਰਨ ਵਾਲੇ",
|
||||
"navigation_bar.lists": "ਸੂਚੀਆਂ",
|
||||
"navigation_bar.live_feed_local": "ਲਾਈਵ ਫੀਡ (ਲੋਕਲ)",
|
||||
"navigation_bar.live_feed_public": "ਲਾਈਵ ਫੀਡ (ਪਬਲਿਕ)",
|
||||
"navigation_bar.logout": "ਲਾਗ ਆਉਟ",
|
||||
"navigation_bar.more": "ਹੋਰ",
|
||||
"navigation_bar.mutes": "ਮੌਨ ਕੀਤੇ ਵਰਤੋਂਕਾਰ",
|
||||
@ -433,16 +446,21 @@
|
||||
"notification_requests.edit_selection": "ਸੋਧੋ",
|
||||
"notification_requests.exit_selection": "ਮੁਕੰਮਲ",
|
||||
"notification_requests.notifications_from": "{name} ਵਲੋਂ ਨੋਟੀਫਿਕੇਸ਼ਨ",
|
||||
"notification_requests.title": "ਫਿਲਟਰ ਕੀਤੇ ਨੋਟੀਫਿਕੇਸ਼ਨ",
|
||||
"notifications.clear": "ਸੂਚਨਾਵਾਂ ਨੂੰ ਮਿਟਾਓ",
|
||||
"notifications.clear_confirmation": "ਕੀ ਤੁਸੀਂ ਆਪਣੇ ਸਾਰੇ ਨੋਟੀਫਿਕੇਸ਼ਨਾਂ ਨੂੰ ਪੱਕੇ ਤੌਰ ਉੱਤੇ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?",
|
||||
"notifications.clear_title": "ਨੋਟਫਿਕੇਸ਼ਨਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?",
|
||||
"notifications.column_settings.admin.report": "ਨਵੀਆਂ ਰਿਪੋਰਟਾਂ:",
|
||||
"notifications.column_settings.alert": "ਡੈਸਕਟਾਪ ਸੂਚਨਾਵਾਂ",
|
||||
"notifications.column_settings.favourite": "ਮਨਪਸੰਦ:",
|
||||
"notifications.column_settings.filter_bar.advanced": "ਸਭ ਵਰਗਾਂ ਨੂੰ ਵੇਖਾਓ",
|
||||
"notifications.column_settings.filter_bar.category": "ਫੌਰੀ ਫਿਲਟਰ ਪੱਟੀ",
|
||||
"notifications.column_settings.follow": "ਨਵੇਂ ਫ਼ਾਲੋਅਰ:",
|
||||
"notifications.column_settings.follow_request": "ਨਵੀਆਂ ਫ਼ਾਲੋ ਬੇਨਤੀਆਂ:",
|
||||
"notifications.column_settings.group": "ਗਰੁੱਪ",
|
||||
"notifications.column_settings.mention": "ਜ਼ਿਕਰ:",
|
||||
"notifications.column_settings.poll": "ਪੋਲ ਦੇ ਨਤੀਜੇ:",
|
||||
"notifications.column_settings.push": "ਪੁਸ਼ ਨੋਟੀਫਿਕੇਸ਼ਨ",
|
||||
"notifications.column_settings.quote": "ਹਵਾਲੇ:",
|
||||
"notifications.column_settings.reblog": "ਬੂਸਟ:",
|
||||
"notifications.column_settings.show": "ਕਾਲਮ ਵਿੱਚ ਵੇਖਾਓ",
|
||||
@ -457,8 +475,10 @@
|
||||
"notifications.filter.follows": "ਫ਼ਾਲੋ",
|
||||
"notifications.filter.mentions": "ਜ਼ਿਕਰ",
|
||||
"notifications.filter.polls": "ਪੋਲ ਦੇ ਨਤੀਜੇ",
|
||||
"notifications.filter.statuses": "ਤੁਹਾਡੇ ਵਲੋਂ ਫ਼ਾਲੋ ਕੀਤੇ ਲੋਕਾਂ ਤੋਂ ਅੱਪਡੇਟ",
|
||||
"notifications.grant_permission": "ਇਜਾਜ਼ਤ ਦਿਓ।",
|
||||
"notifications.group": "{count} ਨੋਟੀਫਿਕੇਸ਼ਨ",
|
||||
"notifications.mark_as_read": "ਹਰ ਨੋਟੀਫਿਕੇਸ਼ਨ ਨੂੰ ਪੜ੍ਹੇ ਵਜੋਂ ਨਿਸ਼ਾਨੀ ਲਾਓ",
|
||||
"notifications.policy.accept": "ਮਨਜ਼ੂਰ",
|
||||
"notifications.policy.accept_hint": "ਨੋਟੀਫਿਕੇਸ਼ਨਾਂ ਵਿੱਚ ਵੇਖਾਓ",
|
||||
"notifications.policy.drop": "ਅਣਡਿੱਠਾ",
|
||||
@ -481,6 +501,7 @@
|
||||
"poll.voted": "ਤੁਸੀਂ ਇਸ ਜਵਾਬ ਲਈ ਵੋਟ ਕੀਤਾ",
|
||||
"privacy.change": "ਪੋਸਟ ਦੀ ਪਰਦੇਦਾਰੀ ਨੂੰ ਬਦਲੋ",
|
||||
"privacy.direct.long": "ਪੋਸਟ ਵਿੱਚ ਜ਼ਿਕਰ ਕੀਤੇ ਹਰ ਕੋਈ",
|
||||
"privacy.direct.short": "ਨਿੱਜੀ ਜ਼ਿਕਰ",
|
||||
"privacy.private.long": "ਸਿਰਫ਼ ਤੁਹਾਡੇ ਫ਼ਾਲੋਅਰ ਹੀ",
|
||||
"privacy.private.short": "ਫ਼ਾਲੋਅਰ",
|
||||
"privacy.public.short": "ਜਨਤਕ",
|
||||
@ -510,6 +531,7 @@
|
||||
"report.category.title_account": "ਪਰੋਫਾਈਲ",
|
||||
"report.category.title_status": "ਪੋਸਟ",
|
||||
"report.close": "ਮੁਕੰਮਲ",
|
||||
"report.forward": "{target} ਨੂੰ ਅੱਗੇ ਭੇਜੋ",
|
||||
"report.mute": "ਮੌਨ ਕਰੋ",
|
||||
"report.next": "ਅਗਲੀ",
|
||||
"report.placeholder": "ਵਧੀਕ ਟਿੱਪਣੀਆਂ",
|
||||
@ -527,6 +549,7 @@
|
||||
"report.unfollow": "@{name} ਨੂੰ ਅਣ-ਫ਼ਾਲੋ ਕਰੋ",
|
||||
"report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached",
|
||||
"report_notification.categories.legal": "ਕਨੂੰਨੀ",
|
||||
"report_notification.categories.legal_sentence": "ਗ਼ੈਰ-ਕਨੂੰਨੀ ਸਮੱਗਰੀ",
|
||||
"report_notification.categories.other": "ਬਾਕੀ",
|
||||
"report_notification.categories.other_sentence": "ਹੋਰ",
|
||||
"report_notification.categories.spam": "ਸਪੈਮ",
|
||||
@ -534,6 +557,7 @@
|
||||
"report_notification.categories.violation": "ਨਿਯਮ ਦੀ ਉਲੰਘਣਾ",
|
||||
"report_notification.categories.violation_sentence": "ਨਿਯਮ ਦੀ ਉਲੰਘਣਾ",
|
||||
"report_notification.open": "ਰਿਪੋਰਟ ਨੂੰ ਖੋਲ੍ਹੋ",
|
||||
"search.clear": "ਖੋਜ ਨੂੰ ਸਾਫ਼ ਕਰੋ",
|
||||
"search.no_recent_searches": "ਕੋਈ ਸੱਜਰੀ ਖੋਜ ਨਹੀਂ ਹੈ",
|
||||
"search.placeholder": "ਖੋਜੋ",
|
||||
"search.quick_action.go_to_account": "ਪਰੋਫਾਈਲ {x} ਉੱਤੇ ਜਾਓ",
|
||||
@ -550,6 +574,7 @@
|
||||
"search_results.no_results": "ਕੋਈ ਨਤੀਜੇ ਨਹੀਂ ਹਨ।",
|
||||
"search_results.see_all": "ਸਭ ਵੇਖੋ",
|
||||
"search_results.statuses": "ਪੋਸਟਾਂ",
|
||||
"search_results.title": "\"{q}\" ਨੂੰ ਖੋਜੋ",
|
||||
"server_banner.active_users": "ਸਰਗਰਮ ਵਰਤੋਂਕਾਰ",
|
||||
"sign_in_banner.create_account": "ਖਾਤਾ ਬਣਾਓ",
|
||||
"sign_in_banner.sign_in": "ਲਾਗਇਨ",
|
||||
@ -582,8 +607,10 @@
|
||||
"status.pin": "ਪਰੋਫਾਈਲ ਉੱਤੇ ਟੰਗੋ",
|
||||
"status.quote": "ਹਵਾਲਾ",
|
||||
"status.quote.cancel": "ਹਵਾਲੇ ਨੂੰ ਰੱਦ ਕਰੋ",
|
||||
"status.quotes_count": "{count, plural, one {{counter} ਹਵਾਲਾ} other {{counter} ਹਵਾਲੇ}}",
|
||||
"status.read_more": "ਹੋਰ ਪੜ੍ਹੋ",
|
||||
"status.reblog": "ਵਧਾਓ",
|
||||
"status.reblog": "ਬੂਸਟ",
|
||||
"status.reblog_or_quote": "ਬੂਸਟ ਜਾਂ ਹਵਾਲਾ",
|
||||
"status.reblogged_by": "{name} ਨੇ ਬੂਸਟ ਕੀਤਾ",
|
||||
"status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
|
||||
"status.redraft": "ਹਟਾਓ ਤੇ ਮੁੜ-ਡਰਾਫਟ",
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
"account.followers_you_know_counter": "jan {counter} pi kute sama",
|
||||
"account.following": "sina kute e jan ni",
|
||||
"account.following_counter": "{count, plural, other {ona li kute e jan {counter}}}",
|
||||
"account.follows.empty": "jan ni li kute e jan ala",
|
||||
"account.follows.empty": "jan ni li kute ala e jan",
|
||||
"account.follows_you": "ona li kute e sina",
|
||||
"account.go_to_profile": "o tawa lipu jan",
|
||||
"account.hide_reblogs": "o lukin ala e pana toki tan @{name}",
|
||||
@ -61,7 +61,7 @@
|
||||
"account.link_verified_on": "{date} la mi sona e ni: jan seme li jo e lipu ni",
|
||||
"account.locked_info": "sina wile kute e jan ni la ona o toki e ken",
|
||||
"account.media": "sitelen",
|
||||
"account.mention": "o mu e jan @{name}",
|
||||
"account.mention": "o mu e @{name}",
|
||||
"account.moved_to": "jan ni la lipu sin li ni:",
|
||||
"account.mute": "o len e @{name}",
|
||||
"account.mute_notifications_short": "o kute ala e mu tan jan ni",
|
||||
@ -74,20 +74,20 @@
|
||||
"account.posts": "toki suli",
|
||||
"account.posts_with_replies": "toki ale",
|
||||
"account.remove_from_followers": "sijelo kute la o weka e sijelo \"{name}\".",
|
||||
"account.report": "jan @{name} la o toki e ike tawa lawa",
|
||||
"account.requested_follow": "jan {name} li wile kute e sina",
|
||||
"account.report": "@{name} la o toki e jaki tawa lawa",
|
||||
"account.requested_follow": "{name} li wile kute e sina",
|
||||
"account.requests_to_follow_you": "jan ni li wile kute e sina",
|
||||
"account.share": "o pana e lipu jan @{name}",
|
||||
"account.share": "o pana e lipu tan @{name}",
|
||||
"account.show_reblogs": "o lukin e pana toki tan @{name}",
|
||||
"account.statuses_counter": "{count, plural, other {toki {counter}}}",
|
||||
"account.unblock": "o len ala e jan {name}",
|
||||
"account.unblock": "o len ala e {name}",
|
||||
"account.unblock_domain": "o len ala e ma {domain}",
|
||||
"account.unblock_domain_short": "o len ala e jan ni",
|
||||
"account.unblock_domain_short": "o len ala",
|
||||
"account.unblock_short": "o len ala",
|
||||
"account.unendorse": "lipu jan la o suli ala e ni",
|
||||
"account.unfollow": "o kute ala",
|
||||
"account.unmute": "o len ala e @{name}",
|
||||
"account.unmute_notifications_short": "o kute e mu tan jan ni",
|
||||
"account.unmute_notifications_short": "o kute e mu",
|
||||
"account.unmute_short": "o len ala",
|
||||
"account_note.placeholder": "o luka e ni la sona pi sina taso",
|
||||
"admin.dashboard.daily_retention": "nanpa pi awen jan lon tenpo suno",
|
||||
@ -133,7 +133,7 @@
|
||||
"annual_report.summary.thanks": "sina lon kulupu Mastodon la sina pona a!",
|
||||
"attachments_list.unprocessed": "(nasin open)",
|
||||
"audio.hide": "o len e kalama",
|
||||
"block_modal.remote_users_caveat": "mi pana e wile sina tawa ma {domain}. taso, o sona: ma li ken kepeken nasin len ante la pakala li ken lon. toki pi lukin ale la jan pi ma ala li ken lukin.",
|
||||
"block_modal.remote_users_caveat": "mi pana e wile sina tawa ma {domain}. taso ma li ken kepeken nasin ante la pakala li ken. jan li awen ken lukin e toki kepeken sijelo ala.",
|
||||
"block_modal.show_less": "o lili e toki",
|
||||
"block_modal.show_more": "o suli e toki",
|
||||
"block_modal.they_cant_mention": "ona li ken ala toki tawa sina li ken ala kute e sina.",
|
||||
@ -174,9 +174,9 @@
|
||||
"column.edit_list": "o ante e kulupu",
|
||||
"column.favourites": "ijo pona",
|
||||
"column.firehose": "toki pi tenpo ni",
|
||||
"column.firehose_local": "toki pi tenpo ni pi ma ni",
|
||||
"column.firehose_local": "ma ni la toki pi tenpo ni",
|
||||
"column.firehose_singular": "toki pi tenpo ni",
|
||||
"column.follow_requests": "wile alasa pi jan ante",
|
||||
"column.follow_requests": "wile kute",
|
||||
"column.home": "lipu open",
|
||||
"column.list_members": "o ante e kulupu jan",
|
||||
"column.lists": "kulupu lipu",
|
||||
@ -184,26 +184,26 @@
|
||||
"column.notifications": "mu pi sona sin",
|
||||
"column.pins": "toki sewi",
|
||||
"column.public": "toki pi ma poka ale",
|
||||
"column_back_button.label": "o tawa monsi",
|
||||
"column_header.hide_settings": "o len e lawa",
|
||||
"column_back_button.label": "o weka",
|
||||
"column_header.hide_settings": "o len e nasin lawa",
|
||||
"column_header.moveLeft_settings": "poki toki ni o tawa ni ←",
|
||||
"column_header.moveRight_settings": "poki toki ni o tawa ni →",
|
||||
"column_header.pin": "o sewi",
|
||||
"column_header.show_settings": "o lukin e lawa",
|
||||
"column_header.show_settings": "o lukin e nasin lawa",
|
||||
"column_header.unpin": "o sewi ala",
|
||||
"column_search.cancel": "o ala",
|
||||
"community.column_settings.local_only": "toki tan ni taso",
|
||||
"community.column_settings.media_only": "sitelen taso",
|
||||
"community.column_settings.remote_only": "toki tan ante taso",
|
||||
"compose.error.blank_post": "toki ken ala jo e ala.",
|
||||
"compose.error.blank_post": "toki li wile.",
|
||||
"compose.language.change": "o ante e nasin toki",
|
||||
"compose.language.search": "o alasa e nasin toki...",
|
||||
"compose.published.body": "toki li pana.",
|
||||
"compose.published.body": "mi pana e toki.",
|
||||
"compose.published.open": "o lukin",
|
||||
"compose.saved.body": "ilo li awen e ijo pana sina.",
|
||||
"compose_form.direct_message_warning_learn_more": "o kama sona",
|
||||
"compose.saved.body": "mi awen e toki sina.",
|
||||
"compose_form.direct_message_warning_learn_more": "o sona",
|
||||
"compose_form.encryption_warning": "ilo Mastodon la toki li len ala. o pana ala e sona suli pi ken pakala.",
|
||||
"compose_form.lock_disclaimer": "lipu sina li open, li {locked} ala. jan ale li ken kama kute e sina, li ken lukin e toki sama ni.",
|
||||
"compose_form.lock_disclaimer": "lipu sina li {locked} ala. jan ale li ken kama kute e sina li ken lukin e toki sama ni.",
|
||||
"compose_form.lock_disclaimer.lock": "pini",
|
||||
"compose_form.placeholder": "sina wile toki e seme?",
|
||||
"compose_form.poll.duration": "tenpo pana",
|
||||
|
||||
@ -15,6 +15,18 @@
|
||||
"account.cancel_follow_request": "ئەگىشىش ئىلتىماسىدىن ۋاز كەچ",
|
||||
"account.copy": "تەرجىمىھال ئۇلانمىسىنى كۆچۈر",
|
||||
"account.direct": "@{name} نى يوشۇرۇن ئاتا",
|
||||
"account.edit_profile_short": "تەھرىر",
|
||||
"account.follow_request_cancel_short": "ۋاز كەچ",
|
||||
"account.follow_request_short": "ئىلتىماس",
|
||||
"account.followers": "ئەگەشكۈچى",
|
||||
"account.followers.empty": "تېخى ھېچكىم بۇ كىشىگە ئەگەشمىدى.",
|
||||
"account.followers_counter": "{count, plural, one {{counter} ئەگەشكۈچى} other {{counter} ئەگەشكۈچى}}",
|
||||
"account.followers_you_know_counter": "تونۇيدىغىنىڭىز {counter}",
|
||||
"account.following": "ئەگىشىۋاتىدۇ",
|
||||
"account.following_counter": "{count, plural, one {{counter} ئەگىشىۋاتىدۇ} other {{counter} ئەگىشىۋاتىدۇ}}",
|
||||
"account.follows.empty": "بۇ ئىشلەتكۈچى تېخى ھېچكىمگە ئەگەشمىدى.",
|
||||
"account.follows_you": "سىزگە ئەگەشتى",
|
||||
"account.go_to_profile": "تەرجىمىھالغا يۆتكەل",
|
||||
"account.posts": "يازما",
|
||||
"account.posts_with_replies": "يازما ۋە ئىنكاس",
|
||||
"account.report": "@{name} نى پاش قىل",
|
||||
|
||||
@ -135,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "tút mới",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Bạn thuộc top</topLabel><percentage></percentage><bottomLabel>thành viên của {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Chúng tôi sẽ không kể cho Bernie.",
|
||||
"annual_report.summary.share_message": "Tôi là điển hình {archetype}!",
|
||||
"annual_report.summary.thanks": "Cảm ơn đã trở thành một phần của Mastodon!",
|
||||
"attachments_list.unprocessed": "(chưa xử lí)",
|
||||
"audio.hide": "Ẩn âm thanh",
|
||||
|
||||
@ -135,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "新嘟文",
|
||||
"annual_report.summary.percentile.text": "<topLabel>这使你跻身 {domain} 用户的前</topLabel><percentage></percentage><bottomLabel></bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": " ",
|
||||
"annual_report.summary.share_message": "我今年的画像是{archetype}!",
|
||||
"annual_report.summary.thanks": "感谢您成为 Mastodon 的一员!",
|
||||
"attachments_list.unprocessed": "(未处理)",
|
||||
"audio.hide": "隐藏音频",
|
||||
|
||||
@ -135,6 +135,7 @@
|
||||
"annual_report.summary.new_posts.new_posts": "新嘟文",
|
||||
"annual_report.summary.percentile.text": "<topLabel>這讓您成為前</topLabel><percentage></percentage><bottomLabel>{domain} 的使用者。</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "我們不會告訴 Bernie。",
|
||||
"annual_report.summary.share_message": "我獲得 {archetype} 稱號!",
|
||||
"annual_report.summary.thanks": "感謝您成為 Mastodon 的一份子!",
|
||||
"attachments_list.unprocessed": "(未處理)",
|
||||
"audio.hide": "隱藏音訊",
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
import {
|
||||
importFetchedAccounts,
|
||||
importFetchedStatuses,
|
||||
} from '@/mastodon/actions/importer';
|
||||
import { insertIntoTimeline } from '@/mastodon/actions/timelines';
|
||||
import type { ApiAnnualReportState } from '@/mastodon/api/annual_report';
|
||||
import {
|
||||
@ -25,7 +30,12 @@ interface AnnualReportState {
|
||||
const annualReportSlice = createSlice({
|
||||
name: 'annualReport',
|
||||
initialState: {} as AnnualReportState,
|
||||
reducers: {},
|
||||
reducers: {
|
||||
setReport(state, action: PayloadAction<AnnualReport>) {
|
||||
state.report = action.payload;
|
||||
state.state = 'available';
|
||||
},
|
||||
},
|
||||
extraReducers(builder) {
|
||||
builder
|
||||
.addCase(fetchReportState.fulfilled, (state, action) => {
|
||||
@ -43,6 +53,7 @@ const annualReportSlice = createSlice({
|
||||
});
|
||||
|
||||
export const annualReport = annualReportSlice.reducer;
|
||||
export const { setReport } = annualReportSlice.actions;
|
||||
|
||||
export const selectWrapstodonYear = createAppSelector(
|
||||
[(state) => state.server.getIn(['server', 'wrapstodon'])],
|
||||
@ -114,5 +125,9 @@ export const getReport = createDataLoadingThunk(
|
||||
}
|
||||
return apiGetAnnualReport(year);
|
||||
},
|
||||
(data) => data.annual_reports[0],
|
||||
(data, { dispatch }) => {
|
||||
dispatch(importFetchedStatuses(data.statuses));
|
||||
dispatch(importFetchedAccounts(data.accounts));
|
||||
return data.annual_reports[0];
|
||||
},
|
||||
);
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
var(--color-text-brand)
|
||||
);
|
||||
--color-text-on-brand-base: var(--color-white);
|
||||
--color-text-brand-on-inverted: var(--color-indigo-400);
|
||||
--color-text-error: var(--color-red-600);
|
||||
--color-text-on-error-base: var(--color-white);
|
||||
--color-text-warning: var(--color-yellow-600);
|
||||
|
||||
@ -10267,7 +10267,7 @@ noscript {
|
||||
background: transparent;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
color: var(--color-text-brand);
|
||||
color: var(--color-text-brand-on-inverted);
|
||||
font-weight: 700;
|
||||
border-radius: 4px;
|
||||
padding: 0 4px;
|
||||
@ -10751,7 +10751,7 @@ noscript {
|
||||
box-sizing: border-box;
|
||||
font-size: 14px;
|
||||
color: var(--color-text-secondary);
|
||||
background: var(--color-bg-tertiary);
|
||||
background: var(--color-bg-secondary);
|
||||
border: 1px solid var(--color-border-primary);
|
||||
border-top: 0;
|
||||
border-radius: 0 0 8px 8px;
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
var(--color-text-brand)
|
||||
);
|
||||
--color-text-on-brand-base: var(--color-white);
|
||||
--color-text-brand-on-inverted: var(--color-indigo-600);
|
||||
--color-text-error: var(--color-red-500);
|
||||
--color-text-on-error-base: var(--color-white);
|
||||
--color-text-warning: var(--color-yellow-400);
|
||||
@ -60,7 +61,7 @@
|
||||
|
||||
// Neutrals
|
||||
--color-bg-primary: var(--color-grey-950);
|
||||
--overlay-strength-secondary: 10%;
|
||||
--overlay-strength-secondary: 8%;
|
||||
--color-bg-secondary-base: var(--color-indigo-200);
|
||||
--color-bg-secondary: #{utils.css-alpha(
|
||||
var(--color-bg-secondary-base),
|
||||
|
||||
@ -22,7 +22,7 @@ class AnnualReport
|
||||
return unless Mastodon::Feature.wrapstodon_enabled?
|
||||
|
||||
datetime = Time.now.utc
|
||||
datetime.year if datetime.month == 12 && (10..31).cover?(datetime.day)
|
||||
datetime.year if datetime.month == 12 && (1..31).cover?(datetime.day)
|
||||
end
|
||||
|
||||
def initialize(account, year)
|
||||
|
||||
@ -26,12 +26,7 @@ class StatusCacheHydrator
|
||||
|
||||
def hydrate_non_reblog_payload(empty_payload, account_id, nested: false)
|
||||
empty_payload.tap do |payload|
|
||||
fill_status_payload(payload, @status, account_id, nested:)
|
||||
|
||||
if payload[:poll]
|
||||
payload[:poll][:voted] = @status.account_id == account_id
|
||||
payload[:poll][:own_votes] = []
|
||||
end
|
||||
fill_status_payload(payload, @status, account_id, fresh: !nested, nested:)
|
||||
end
|
||||
end
|
||||
|
||||
@ -45,18 +40,7 @@ class StatusCacheHydrator
|
||||
# used to create the status, we need to hydrate it here too
|
||||
payload[:reblog][:application] = payload_reblog_application if payload[:reblog][:application].nil? && @status.reblog.account_id == account_id
|
||||
|
||||
fill_status_payload(payload[:reblog], @status.reblog, account_id, nested:)
|
||||
|
||||
if payload[:reblog][:poll]
|
||||
if @status.reblog.account_id == account_id
|
||||
payload[:reblog][:poll][:voted] = true
|
||||
payload[:reblog][:poll][:own_votes] = []
|
||||
else
|
||||
own_votes = PollVote.where(poll_id: @status.reblog.poll_id, account_id: account_id).pluck(:choice)
|
||||
payload[:reblog][:poll][:voted] = !own_votes.empty?
|
||||
payload[:reblog][:poll][:own_votes] = own_votes
|
||||
end
|
||||
end
|
||||
fill_status_payload(payload[:reblog], @status.reblog, account_id, fresh: false, nested:)
|
||||
|
||||
payload[:filtered] = payload[:reblog][:filtered]
|
||||
payload[:favourited] = payload[:reblog][:favourited]
|
||||
@ -65,7 +49,7 @@ class StatusCacheHydrator
|
||||
end
|
||||
end
|
||||
|
||||
def fill_status_payload(payload, status, account_id, nested: false)
|
||||
def fill_status_payload(payload, status, account_id, nested: false, fresh: true)
|
||||
payload[:favourited] = Favourite.exists?(account_id: account_id, status_id: status.id)
|
||||
payload[:reblogged] = Status.exists?(account_id: account_id, reblog_of_id: status.id)
|
||||
payload[:muted] = ConversationMute.exists?(account_id: account_id, conversation_id: status.conversation_id)
|
||||
@ -76,6 +60,21 @@ class StatusCacheHydrator
|
||||
payload[:quote_approval][:current_user] = status.quote_policy_for_account(Account.find_by(id: account_id)) if payload[:quote_approval]
|
||||
payload[:quote] = hydrate_quote_payload(payload[:quote], status.quote, account_id, nested:) if payload[:quote]
|
||||
|
||||
if payload[:poll]
|
||||
if fresh
|
||||
# If the status is brand new, we don't need to look up votes in database
|
||||
payload[:poll][:voted] = status.account_id == account_id
|
||||
payload[:poll][:own_votes] = []
|
||||
elsif status.account_id == account_id
|
||||
payload[:poll][:voted] = true
|
||||
payload[:poll][:own_votes] = []
|
||||
else
|
||||
own_votes = PollVote.where(poll_id: status.poll_id, account_id: account_id).pluck(:choice)
|
||||
payload[:poll][:voted] = !own_votes.empty?
|
||||
payload[:poll][:own_votes] = own_votes
|
||||
end
|
||||
end
|
||||
|
||||
# Nested statuses are more likely to have a stale cache
|
||||
fill_status_stats(payload, status) if nested
|
||||
end
|
||||
|
||||
@ -50,12 +50,20 @@ class Collection < ApplicationRecord
|
||||
result
|
||||
end
|
||||
|
||||
def tag_name
|
||||
tag&.formatted_name
|
||||
end
|
||||
|
||||
def tag_name=(new_name)
|
||||
self.tag = Tag.find_or_create_by_names(new_name).first
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def tag_is_usable
|
||||
return if tag.blank?
|
||||
|
||||
errors.add(:tag, :unusable) unless tag.usable?
|
||||
errors.add(:tag_name, :unusable) unless tag.usable?
|
||||
end
|
||||
|
||||
def items_do_not_exceed_limit
|
||||
|
||||
@ -67,6 +67,8 @@ class Tag < ApplicationRecord
|
||||
}
|
||||
scope :matches_name, ->(term) { where(arel_table[:name].lower.matches(arel_table.lower("#{sanitize_sql_like(Tag.normalize(term))}%"), nil, true)) } # Search with case-sensitive to use B-tree index
|
||||
|
||||
normalizes :display_name, with: ->(value) { value.gsub(HASHTAG_INVALID_CHARS_RE, '') }
|
||||
|
||||
update_index('tags', :self)
|
||||
|
||||
def to_param
|
||||
@ -113,10 +115,7 @@ class Tag < ApplicationRecord
|
||||
|
||||
names.map do |(normalized_name, display_name)|
|
||||
tag = begin
|
||||
matching_name(normalized_name).first || create!(
|
||||
name: normalized_name,
|
||||
display_name: display_name.gsub(HASHTAG_INVALID_CHARS_RE, '')
|
||||
)
|
||||
matching_name(normalized_name).first || create!(name: normalized_name, display_name:)
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
find_normalized(normalized_name)
|
||||
end
|
||||
|
||||
29
app/policies/collection_policy.rb
Normal file
29
app/policies/collection_policy.rb
Normal file
@ -0,0 +1,29 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CollectionPolicy < ApplicationPolicy
|
||||
def index?
|
||||
true
|
||||
end
|
||||
|
||||
def show?
|
||||
true
|
||||
end
|
||||
|
||||
def create?
|
||||
user_signed_in?
|
||||
end
|
||||
|
||||
def update?
|
||||
owner?
|
||||
end
|
||||
|
||||
def destroy?
|
||||
owner?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def owner?
|
||||
current_account == record.account
|
||||
end
|
||||
end
|
||||
@ -2,9 +2,8 @@
|
||||
|
||||
class CreateCollectionService
|
||||
def call(params, account)
|
||||
tag = params.delete(:tag)
|
||||
account_ids = params.delete(:account_ids)
|
||||
@collection = Collection.new(params.merge({ account:, local: true, tag: find_or_create_tag(tag) }))
|
||||
@collection = Collection.new(params.merge({ account:, local: true }))
|
||||
build_items(account_ids)
|
||||
|
||||
@collection.save!
|
||||
@ -13,12 +12,6 @@ class CreateCollectionService
|
||||
|
||||
private
|
||||
|
||||
def find_or_create_tag(name)
|
||||
return nil if name.blank?
|
||||
|
||||
Tag.find_or_create_by_names(name).first
|
||||
end
|
||||
|
||||
def build_items(account_ids)
|
||||
return if account_ids.blank?
|
||||
|
||||
|
||||
@ -6,4 +6,7 @@
|
||||
= opengraph 'og:site_name', site_title
|
||||
= opengraph 'profile:username', acct(@account)[1..]
|
||||
|
||||
= render 'shared/web_app'
|
||||
= vite_typescript_tag 'wrapstodon.tsx', crossorigin: 'anonymous'
|
||||
|
||||
#wrapstodon
|
||||
= render_wrapstodon_share_data @generated_annual_report
|
||||
|
||||
@ -1784,16 +1784,22 @@ be:
|
||||
body: 'Вас згадаў %{name} у:'
|
||||
subject: Вас згадаў %{name}
|
||||
title: Новае згадванне
|
||||
moderation_warning:
|
||||
subject: Вы атрымалі папярэджанне ад мадэратараў
|
||||
poll:
|
||||
subject: Апытанне ад %{name} скончылася
|
||||
quote:
|
||||
body: 'Ваш допіс працытаваў карыстальнік %{name}:'
|
||||
subject: Карыстальнік %{name} працытаваў Ваш допіс
|
||||
title: Цытаваць
|
||||
quoted_update:
|
||||
subject: "%{name} адрэдагаваў допіс, як Вы цытавалі"
|
||||
reblog:
|
||||
body: "%{name} пашырыў(-ла) Ваш допіс:"
|
||||
subject: "%{name} пашырыў ваш допіс"
|
||||
title: Новае пашырэнне
|
||||
severed_relationships:
|
||||
subject: Вы страцілі сувязі праз рашэнне мадэратараў
|
||||
status:
|
||||
subject: Новы допіс ад %{name}
|
||||
update:
|
||||
|
||||
@ -1684,16 +1684,22 @@ ca:
|
||||
body: "%{name} t'ha mencionat en:"
|
||||
subject: "%{name} t'ha mencionat"
|
||||
title: Nova menció
|
||||
moderation_warning:
|
||||
subject: Heu rebut un avís de moderació
|
||||
poll:
|
||||
subject: Ha finalitzat l'enquesta de %{name}
|
||||
quote:
|
||||
body: 'La vostra publicació ha estat citada per %{name}:'
|
||||
subject: "%{name} ha citat la vostra publicació"
|
||||
title: Nova citació
|
||||
quoted_update:
|
||||
subject: "%{name} ha editat una publicació que heu citat"
|
||||
reblog:
|
||||
body: "%{name} ha impulsat el teu estat:"
|
||||
subject: "%{name} ha impulsat el teu estat"
|
||||
title: Nou impuls
|
||||
severed_relationships:
|
||||
subject: Heu perdut connexions degut a una decisió de moderació
|
||||
status:
|
||||
subject: "%{name} ha publicat"
|
||||
update:
|
||||
@ -2153,3 +2159,5 @@ ca:
|
||||
not_supported: Aquest navegador no suporta claus de seguretat
|
||||
otp_required: Per a usar claus de seguretat, activeu primer l'autenticació de dos factors.
|
||||
registered_on: Registrat en %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} per a %{name}
|
||||
|
||||
@ -2185,3 +2185,5 @@ da:
|
||||
not_supported: Denne browser understøtter ikke sikkerhedsnøgler
|
||||
otp_required: For at bruge sikkerhedsnøgler skal tofaktorgodkendelse først aktiveres.
|
||||
registered_on: Registreret d. %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} for %{name}
|
||||
|
||||
@ -1720,6 +1720,8 @@ de:
|
||||
body: 'Dein Beitrag wurde von %{name} geteilt:'
|
||||
subject: "%{name} teilte deinen Beitrag"
|
||||
title: Dein Beitrag wurde geteilt
|
||||
severed_relationships:
|
||||
subject: Du hast die Verbindung aufgrund einer Moderationsentscheidung verloren
|
||||
status:
|
||||
subject: "%{name} veröffentlichte gerade einen Beitrag"
|
||||
update:
|
||||
@ -2183,3 +2185,5 @@ de:
|
||||
not_supported: Dieser Browser unterstützt keine Sicherheitsschlüssel
|
||||
otp_required: Um Sicherheitsschlüssel zu verwenden, aktiviere zunächst die Zwei-Faktor-Authentisierung.
|
||||
registered_on: Registriert am %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} für %{name}
|
||||
|
||||
@ -2185,3 +2185,5 @@ el:
|
||||
not_supported: Αυτό το πρόγραμμα περιήγησης δεν υποστηρίζει κλειδιά ασφαλείας
|
||||
otp_required: Για να χρησιμοποιήσεις κλειδιά ασφαλείας, ενεργοποίησε πρώτα την ταυτοποίηση δύο παραγόντων.
|
||||
registered_on: Εγγραφή στις %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} για %{name}
|
||||
|
||||
@ -2185,3 +2185,5 @@ es-AR:
|
||||
not_supported: Este navegador web no soporta llaves de seguridad
|
||||
otp_required: Para usar llaves de seguridad, por favor, primero habilitá la autenticación de dos factores.
|
||||
registered_on: Registrado el %{date}
|
||||
wrapstodon:
|
||||
title: MastodonAnual %{year} para %{name}
|
||||
|
||||
@ -1720,6 +1720,8 @@ es-MX:
|
||||
body: 'Tu publicación fue impulsada por %{name}:'
|
||||
subject: "%{name} ha impulsado tu publicación"
|
||||
title: Nuevo impulso
|
||||
severed_relationships:
|
||||
subject: Has perdido conexiones debido a una decisión de moderación
|
||||
status:
|
||||
subject: "%{name} acaba de publicar"
|
||||
update:
|
||||
@ -2183,3 +2185,5 @@ es-MX:
|
||||
not_supported: Este navegador no soporta claves de seguridad
|
||||
otp_required: Para usar claves de seguridad, por favor habilite primero la autenticación de doble factor.
|
||||
registered_on: Registrado el %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} para %{name}
|
||||
|
||||
@ -1720,6 +1720,8 @@ es:
|
||||
body: 'Tu publicación fue impulsada por %{name}:'
|
||||
subject: "%{name} impulsó tu publicación"
|
||||
title: Nueva difusión
|
||||
severed_relationships:
|
||||
subject: Has perdido conexiones debido a una decisión de moderación
|
||||
status:
|
||||
subject: "%{name} acaba de publicar"
|
||||
update:
|
||||
@ -2183,3 +2185,5 @@ es:
|
||||
not_supported: Este navegador no soporta claves de seguridad
|
||||
otp_required: Para usar claves de seguridad, por favor habilite primero la autenticación de doble factor.
|
||||
registered_on: Registrado el %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} para %{name}
|
||||
|
||||
@ -1706,16 +1706,22 @@ fo:
|
||||
body: 'Tú var umrødd/ur av %{name} í:'
|
||||
subject: Tú var umrødd/ur av %{name}
|
||||
title: Nýggj umrøða
|
||||
moderation_warning:
|
||||
subject: Tú hevur móttikið eina umsjónarávaring
|
||||
poll:
|
||||
subject: Ein spurnarkanning hjá %{name} er endað
|
||||
quote:
|
||||
body: 'Postur tín var siteraður av %{name}:'
|
||||
subject: "%{name} siteraði postin hjá tær"
|
||||
title: Nýggj sitering
|
||||
quoted_update:
|
||||
subject: "%{name} rættaði ein post, sum tú hevur siterað"
|
||||
reblog:
|
||||
body: 'Postur tín var stimbraður av %{name}:'
|
||||
subject: "%{name} stimbraði tín post"
|
||||
title: Nýggj stimbran
|
||||
severed_relationships:
|
||||
subject: Tú hevur mist sambond vegna eina umsjónaravgerð
|
||||
status:
|
||||
subject: "%{name} hevur júst postað"
|
||||
update:
|
||||
@ -2179,3 +2185,5 @@ fo:
|
||||
not_supported: Hesin kagin stuðlar ikki uppundir trygdarlyklar
|
||||
otp_required: Fyri at brúka trygdarlyklar er neyðugt at gera váttan í tveimum stigum virkna fyrst.
|
||||
registered_on: Skrásett %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} fyri %{name}
|
||||
|
||||
@ -1709,16 +1709,22 @@ fr-CA:
|
||||
body: "%{name} vous a mentionné⋅e dans :"
|
||||
subject: "%{name} vous a mentionné·e"
|
||||
title: Nouvelle mention
|
||||
moderation_warning:
|
||||
subject: Vous avez reçu un avertissement de la modération
|
||||
poll:
|
||||
subject: Un sondage de %{name} est terminé
|
||||
quote:
|
||||
body: 'Votre message a été cité par %{name}:'
|
||||
subject: "%{name} a cité votre message"
|
||||
title: Nouvelle citation
|
||||
quoted_update:
|
||||
subject: "%{name} a modifié un message que vous avez cité"
|
||||
reblog:
|
||||
body: 'Votre message été partagé par %{name} :'
|
||||
subject: "%{name} a partagé votre message"
|
||||
title: Nouveau partage
|
||||
severed_relationships:
|
||||
subject: Vous avez perdu des relations à cause d’une décision de modération
|
||||
status:
|
||||
subject: "%{name} vient de publier"
|
||||
update:
|
||||
@ -2182,3 +2188,5 @@ fr-CA:
|
||||
not_supported: Ce navigateur ne prend pas en charge les clés de sécurité
|
||||
otp_required: Pour utiliser les clés de sécurité, veuillez d'abord activer l'authentification à deux facteurs.
|
||||
registered_on: Inscrit le %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} pour %{name}
|
||||
|
||||
@ -1709,16 +1709,22 @@ fr:
|
||||
body: "%{name} vous a mentionné⋅e dans :"
|
||||
subject: "%{name} vous a mentionné·e"
|
||||
title: Nouvelle mention
|
||||
moderation_warning:
|
||||
subject: Vous avez reçu un avertissement de la modération
|
||||
poll:
|
||||
subject: Un sondage de %{name} est terminé
|
||||
quote:
|
||||
body: 'Votre message a été cité par %{name}:'
|
||||
subject: "%{name} a cité votre message"
|
||||
title: Nouvelle citation
|
||||
quoted_update:
|
||||
subject: "%{name} a modifié un message que vous avez cité"
|
||||
reblog:
|
||||
body: 'Votre message été partagé par %{name} :'
|
||||
subject: "%{name} a partagé votre message"
|
||||
title: Nouveau partage
|
||||
severed_relationships:
|
||||
subject: Vous avez perdu des relations à cause d’une décision de modération
|
||||
status:
|
||||
subject: "%{name} vient de publier"
|
||||
update:
|
||||
@ -2182,3 +2188,5 @@ fr:
|
||||
not_supported: Ce navigateur ne prend pas en charge les clés de sécurité
|
||||
otp_required: Pour utiliser les clés de sécurité, veuillez d'abord activer l'authentification à deux facteurs.
|
||||
registered_on: Inscrit le %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} pour %{name}
|
||||
|
||||
@ -1825,16 +1825,22 @@ ga:
|
||||
body: 'Luaigh %{name} thú i:'
|
||||
subject: Luaigh %{name} thú
|
||||
title: Lua nua
|
||||
moderation_warning:
|
||||
subject: Tá rabhadh modhnóireachta faighte agat
|
||||
poll:
|
||||
subject: Tháinig deireadh le vótaíocht le %{name}
|
||||
quote:
|
||||
body: 'Luaigh %{name} do phost:'
|
||||
subject: Luaigh %{name} do phost
|
||||
title: Luachan nua
|
||||
quoted_update:
|
||||
subject: Chuir %{name} post in eagar a luaigh tú
|
||||
reblog:
|
||||
body: 'Treisíodh do phostáil le %{name}:'
|
||||
subject: Mhol %{name} do phostáil
|
||||
title: Moladh nua
|
||||
severed_relationships:
|
||||
subject: Tá naisc caillte agat mar gheall ar chinneadh modhnóireachta
|
||||
status:
|
||||
subject: Tá %{name} díreach postáilte
|
||||
update:
|
||||
@ -2313,3 +2319,5 @@ ga:
|
||||
not_supported: Ní thacaíonn an brabhsálaí seo le heochracha slándála
|
||||
otp_required: Chun eochracha slándála a úsáid cumasaigh fíordheimhniú dhá fhachtóir ar dtús.
|
||||
registered_on: Cláraithe ar %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} do %{name}
|
||||
|
||||
@ -1706,16 +1706,22 @@ gl:
|
||||
body: "%{name} mencionoute en:"
|
||||
subject: Foches mencionada por %{name}
|
||||
title: Nova mención
|
||||
moderation_warning:
|
||||
subject: Recibiches unha advertencia da moderación
|
||||
poll:
|
||||
subject: A enquisa de %{name} rematou
|
||||
quote:
|
||||
body: 'A túa publicación foi citada por %{name}:'
|
||||
subject: "%{name} citou a túa publicación"
|
||||
title: Nova cita
|
||||
quoted_update:
|
||||
subject: "%{name} editou unha publicación que citaches"
|
||||
reblog:
|
||||
body: 'A túa publicación promovida por %{name}:'
|
||||
subject: "%{name} promoveu a túa publicación"
|
||||
title: Nova promoción
|
||||
severed_relationships:
|
||||
subject: Perdeches algunhas relacións debido a decisións da moderación
|
||||
status:
|
||||
subject: "%{name} publicou"
|
||||
update:
|
||||
|
||||
@ -2273,3 +2273,5 @@ he:
|
||||
not_supported: דפדפן זה לא תומך במפתחות אבטחה
|
||||
otp_required: על מנת להשתמש במפתחות אבטחה אנא אפשר.י אימות דו-שלבי קודם.
|
||||
registered_on: נרשם ב %{date}
|
||||
wrapstodon:
|
||||
title: סיכומודון %{year} עבור %{name}
|
||||
|
||||
@ -1707,17 +1707,21 @@ hu:
|
||||
subject: "%{name} megemlített téged"
|
||||
title: Új említés
|
||||
moderation_warning:
|
||||
subject: Kaptál egy moderálási figyelmeztetést
|
||||
subject: Moderációs figyelmeztetést kaptál
|
||||
poll:
|
||||
subject: "%{name} szavazása véget ért"
|
||||
quote:
|
||||
body: 'A bejegyzésedet %{name} idézte:'
|
||||
subject: "%{name} idézte a bejegyzésedet"
|
||||
title: Új idézet
|
||||
quoted_update:
|
||||
subject: "%{name} szerkesztett egy bejegyzést, melyet idéztél"
|
||||
reblog:
|
||||
body: 'A bejegyzésedet %{name} megtolta:'
|
||||
subject: "%{name} megtolta a bejegyzésedet"
|
||||
title: Új megtolás
|
||||
severed_relationships:
|
||||
subject: Moderációs döntés miatt kapcsolatokat veszítettél
|
||||
status:
|
||||
subject: "%{name} bejegyzést írt"
|
||||
update:
|
||||
|
||||
@ -2189,3 +2189,5 @@ is:
|
||||
not_supported: Þessi vafri styður ekki öryggislykla
|
||||
otp_required: Til að nota öryggislykla skaltu fyrst virkja tveggja-þátta auðkenningu.
|
||||
registered_on: Skráði sig %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} fyrir %{name}
|
||||
|
||||
@ -1694,6 +1694,8 @@ ja:
|
||||
too_few_options: は複数必要です
|
||||
too_many_options: は%{max}個までです
|
||||
vote: 投票
|
||||
posting_defaults:
|
||||
explanation: これらの設定は投稿を新規作成するときにデフォルトとして使用されますが、作成画面で投稿ごとに変更できます。
|
||||
preferences:
|
||||
other: その他
|
||||
posting_defaults: デフォルトの投稿設定
|
||||
|
||||
@ -2186,3 +2186,5 @@ pt-BR:
|
||||
not_supported: Este navegador não tem suporte a chaves de segurança
|
||||
otp_required: Para usar chaves de segurança, ative a autenticação de dois fatores.
|
||||
registered_on: Registrado em %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon de %{year} para %{name}
|
||||
|
||||
@ -54,6 +54,7 @@ ja:
|
||||
password: 少なくとも8文字は入力してください
|
||||
phrase: 投稿内容の大文字小文字や閲覧注意に関係なく一致
|
||||
scopes: アプリの API に許可するアクセス権を選択してください。最上位のスコープを選択する場合、個々のスコープを選択する必要はありません。
|
||||
setting_advanced_layout: Mastodonを複数カラムのレイアウトで表示します。タイムライン、通知、そして好みのカラムを閲覧できます。小さい画面には非推奨です。
|
||||
setting_aggregate_reblogs: 最近ブーストされた投稿が新たにブーストされても表示しません (設定後受信したものにのみ影響)
|
||||
setting_always_send_emails: 通常、Mastodon からメール通知は行われません。
|
||||
setting_boost_modal: 有効にすると、ブーストによって、まず、ブーストの公開範囲を設定できる確認ダイアログが表示されます。
|
||||
|
||||
@ -54,6 +54,7 @@ lt:
|
||||
password: Naudok bent 8 simbolius
|
||||
phrase: Bus suderinta, neatsižvelgiant į teksto lygį arba įrašo turinio įspėjimą
|
||||
scopes: Prie kurių API programai bus leidžiama pasiekti. Pasirinkus aukščiausio lygio sritį, atskirų sričių pasirinkti nereikia.
|
||||
setting_advanced_layout: Rodykite „Mastodon“ kaip kelių stulpelių išdėstymą, leidžiantį peržiūrėti įrašų srautą, pranešimus ir trečiąjį stulpelį pagal savo pasirinkimą. Nerekomenduojama mažesniems ekranams.
|
||||
setting_aggregate_reblogs: Nerodyti naujų pakėlimų įrašams, kurie neseniai buvo pakelti (taikoma tik naujai gautiems pakėlimams).
|
||||
setting_always_send_emails: Paprastai el. laiško pranešimai nebus siunčiami, kai aktyviai naudoji Mastodon.
|
||||
setting_default_quote_policy_private: Tik sekėjams skirti įrašai, paskelbti platformoje „Mastodon“, negali būti cituojami kitų.
|
||||
|
||||
@ -2185,3 +2185,5 @@ tr:
|
||||
not_supported: Bu tarayıcı güvenlik anahtarlarını desteklemiyor
|
||||
otp_required: Güvenlik anahtarlarını kullanmak için lütfen önce iki adımlı kimlik doğrulamayı etkinleştirin.
|
||||
registered_on: "%{date} tarihinde kaydoldu"
|
||||
wrapstodon:
|
||||
title: "%{name} için %{year} Wrapstodon'u"
|
||||
|
||||
@ -2141,3 +2141,5 @@ vi:
|
||||
not_supported: Trình duyệt của bạn không hỗ trợ khóa bảo mật
|
||||
otp_required: Để dùng khóa bảo mật, trước tiên hãy kích hoạt xác thực 2 bước.
|
||||
registered_on: Đăng ký vào %{date}
|
||||
wrapstodon:
|
||||
title: Wrapstodon %{year} cho %{name}
|
||||
|
||||
@ -2141,3 +2141,5 @@ zh-CN:
|
||||
not_supported: 此浏览器不支持安全密钥
|
||||
otp_required: 要使用安全密钥,请先启用双因素认证。
|
||||
registered_on: 注册于 %{date}
|
||||
wrapstodon:
|
||||
title: "%{name}的%{year}年Wrapstodon年度回顾"
|
||||
|
||||
@ -2147,3 +2147,5 @@ zh-TW:
|
||||
not_supported: 此瀏覽器並不支援安全金鑰
|
||||
otp_required: 請先啟用兩階段驗證以使用安全金鑰。
|
||||
registered_on: 註冊於 %{date}
|
||||
wrapstodon:
|
||||
title: "%{name} 的 %{year} Mastodon 年度回顧 (Wrapstodon)"
|
||||
|
||||
@ -8,7 +8,7 @@ namespace :api, format: false do
|
||||
namespace :v1_alpha do
|
||||
resources :async_refreshes, only: :show
|
||||
|
||||
resources :collections, only: [:show, :create]
|
||||
resources :collections, only: [:show, :create, :update, :destroy]
|
||||
end
|
||||
|
||||
# JSON / REST API
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
"@formatjs/intl-pluralrules": "^5.4.4",
|
||||
"@gamestdio/websocket": "^0.3.2",
|
||||
"@github/webauthn-json": "^2.1.1",
|
||||
"@optimize-lodash/rollup-plugin": "^5.0.2",
|
||||
"@optimize-lodash/rollup-plugin": "^6.0.0",
|
||||
"@react-spring/web": "^9.7.5",
|
||||
"@reduxjs/toolkit": "^2.0.1",
|
||||
"@use-gesture/react": "^10.3.1",
|
||||
|
||||
@ -176,6 +176,28 @@ RSpec.describe StatusCacheHydrator do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the quoted post has a poll authored by the user' do
|
||||
let(:poll) { Fabricate(:poll, account: account) }
|
||||
let(:quoted_status) { Fabricate(:status, poll: poll, account: account) }
|
||||
|
||||
it 'renders the same attributes as a full render' do
|
||||
expect(subject).to eql(compare_to_hash)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the quoted post has been voted in' do
|
||||
let(:poll) { Fabricate(:poll, options: %w(Yellow Blue)) }
|
||||
let(:quoted_status) { Fabricate(:status, poll: poll) }
|
||||
|
||||
before do
|
||||
VoteService.new.call(account, poll, [0])
|
||||
end
|
||||
|
||||
it 'renders the same attributes as a full render' do
|
||||
expect(subject).to eql(compare_to_hash)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the quoted post matches account filters' do
|
||||
let(:quoted_status) { Fabricate(:status, text: 'this toot is about that banned word') }
|
||||
|
||||
|
||||
@ -72,4 +72,58 @@ RSpec.describe Collection do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#tag_name=' do
|
||||
context 'when the collection is new and has no tag' do
|
||||
subject { Fabricate.build(:collection) }
|
||||
|
||||
context 'when the tag exists' do
|
||||
let!(:tag) { Fabricate.create(:tag, name: 'people') }
|
||||
|
||||
it 'correctly assigns the existing tag' do
|
||||
subject.tag_name = '#people'
|
||||
|
||||
expect(subject.tag).to eq tag
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the tag does not exist' do
|
||||
it 'creates and assigns a new tag' do
|
||||
expect do
|
||||
subject.tag_name = '#people'
|
||||
end.to change(Tag, :count).by(1)
|
||||
|
||||
expect(subject.tag).to be_present
|
||||
expect(subject.tag.name).to eq 'people'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the collection is persisted and has a tag' do
|
||||
subject { Fabricate(:collection, tag:) }
|
||||
|
||||
let!(:tag) { Fabricate(:tag, name: 'people') }
|
||||
|
||||
context 'when the new tag is the same' do
|
||||
it 'does not change the object' do
|
||||
subject.tag_name = '#People'
|
||||
|
||||
expect(subject.tag).to eq tag
|
||||
expect(subject).to_not be_changed
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the new tag is different' do
|
||||
it 'creates and assigns a new tag' do
|
||||
expect do
|
||||
subject.tag_name = '#bots'
|
||||
end.to change(Tag, :count).by(1)
|
||||
|
||||
expect(subject.tag).to be_present
|
||||
expect(subject.tag.name).to eq 'bots'
|
||||
expect(subject).to be_changed
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -57,6 +57,11 @@ RSpec.describe Tag do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Normalizations' do
|
||||
it { is_expected.to normalize(:display_name).from('#HelloWorld').to('HelloWorld') }
|
||||
it { is_expected.to normalize(:display_name).from('Hello❤️World').to('HelloWorld') }
|
||||
end
|
||||
|
||||
describe 'HASHTAG_RE' do
|
||||
subject { described_class::HASHTAG_RE }
|
||||
|
||||
@ -251,17 +256,29 @@ RSpec.describe Tag do
|
||||
end
|
||||
|
||||
describe '.find_or_create_by_names' do
|
||||
let(:upcase_string) { 'abcABCabcABCやゆよ' }
|
||||
let(:downcase_string) { 'abcabcabcabcやゆよ' }
|
||||
context 'when called with a block' do
|
||||
let(:upcase_string) { 'abcABCabcABCやゆよ' }
|
||||
let(:downcase_string) { 'abcabcabcabcやゆよ' }
|
||||
let(:args) { [upcase_string, downcase_string] }
|
||||
|
||||
it 'runs a passed block once per tag regardless of duplicates' do
|
||||
count = 0
|
||||
|
||||
described_class.find_or_create_by_names([upcase_string, downcase_string]) do |_tag|
|
||||
count += 1
|
||||
it 'runs the block once per normalized tag regardless of duplicates' do
|
||||
expect { |block| described_class.find_or_create_by_names(args, &block) }
|
||||
.to yield_control.once
|
||||
end
|
||||
end
|
||||
|
||||
expect(count).to eq 1
|
||||
context 'when passed an array' do
|
||||
it 'creates multiples tags' do
|
||||
expect { described_class.find_or_create_by_names(%w(tips tags toes)) }
|
||||
.to change(described_class, :count).by(3)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when passed a string' do
|
||||
it 'creates a single tag' do
|
||||
expect { described_class.find_or_create_by_names('test') }
|
||||
.to change(described_class, :count).by(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -270,16 +287,10 @@ RSpec.describe Tag do
|
||||
tag_name_upper = 'Rails'
|
||||
tag_name_lower = 'rails'
|
||||
|
||||
threads = []
|
||||
|
||||
2.times do |i|
|
||||
threads << Thread.new do
|
||||
described_class.find_or_create_by_names(i.zero? ? tag_name_upper : tag_name_lower)
|
||||
end
|
||||
multi_threaded_execution(2) do |index|
|
||||
described_class.find_or_create_by_names(index.zero? ? tag_name_upper : tag_name_lower)
|
||||
end
|
||||
|
||||
threads.each(&:join)
|
||||
|
||||
tags = described_class.where('lower(name) = ?', tag_name_lower.downcase)
|
||||
expect(tags.count).to eq(1)
|
||||
expect(tags.first.name.downcase).to eq(tag_name_lower.downcase)
|
||||
|
||||
43
spec/policies/collection_policy_spec.rb
Normal file
43
spec/policies/collection_policy_spec.rb
Normal file
@ -0,0 +1,43 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe CollectionPolicy do
|
||||
let(:policy) { described_class }
|
||||
let(:collection) { Fabricate(:collection) }
|
||||
let(:owner) { collection.account }
|
||||
let(:other_user) { Fabricate(:account) }
|
||||
|
||||
permissions :index? do
|
||||
it 'permits everyone to index' do
|
||||
expect(policy).to permit(nil, Collection)
|
||||
expect(policy).to permit(owner, Collection)
|
||||
end
|
||||
end
|
||||
|
||||
permissions :show? do
|
||||
it 'permits everyone to show' do
|
||||
expect(policy).to permit(nil, collection)
|
||||
expect(policy).to permit(owner, collection)
|
||||
expect(policy).to permit(other_user, collection)
|
||||
end
|
||||
end
|
||||
|
||||
permissions :create? do
|
||||
it 'permits any user' do
|
||||
expect(policy).to_not permit(nil, Collection)
|
||||
|
||||
expect(policy).to permit(owner, Collection)
|
||||
expect(policy).to permit(other_user, Collection)
|
||||
end
|
||||
end
|
||||
|
||||
permissions :update?, :destroy? do
|
||||
it 'only permits the owner' do
|
||||
expect(policy).to_not permit(nil, collection)
|
||||
expect(policy).to_not permit(other_user, collection)
|
||||
|
||||
expect(policy).to permit(owner, collection)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -95,4 +95,103 @@ RSpec.describe 'Api::V1Alpha::Collections', feature: :collections do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH /api/v1_alpha/collections/:id' do
|
||||
subject do
|
||||
patch "/api/v1_alpha/collections/#{collection.id}", headers: headers, params: params
|
||||
end
|
||||
|
||||
let(:collection) { Fabricate(:collection) }
|
||||
let(:params) { {} }
|
||||
|
||||
context 'when user is not owner' do
|
||||
it 'returns http forbidden' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is the owner' do
|
||||
let(:collection) do
|
||||
Fabricate(:collection,
|
||||
account: user.account,
|
||||
name: 'Pople to follow',
|
||||
description: 'Cool pople',
|
||||
sensitive: true,
|
||||
discoverable: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read:collections'
|
||||
|
||||
context 'with valid params' do
|
||||
let(:params) do
|
||||
{
|
||||
name: 'People to follow',
|
||||
description: 'Cool people',
|
||||
sensitive: '0',
|
||||
discoverable: '1',
|
||||
}
|
||||
end
|
||||
|
||||
it 'updates the collection and returns http success' do
|
||||
subject
|
||||
collection.reload
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(collection.name).to eq 'People to follow'
|
||||
expect(collection.description).to eq 'Cool people'
|
||||
expect(collection.sensitive).to be false
|
||||
expect(collection.discoverable).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid params' do
|
||||
let(:params) { { name: '' } }
|
||||
|
||||
it 'returns http unprocessable content and detailed errors' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
expect(response.parsed_body).to include({
|
||||
'error' => a_hash_including({
|
||||
'details' => a_hash_including({
|
||||
'name' => [{ 'error' => 'ERR_BLANK', 'description' => "can't be blank" }],
|
||||
}),
|
||||
}),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1_alpha/collections/:id' do
|
||||
subject do
|
||||
delete "/api/v1_alpha/collections/#{collection.id}", headers: headers
|
||||
end
|
||||
|
||||
let(:collection) { Fabricate(:collection) }
|
||||
|
||||
context 'when user is not owner' do
|
||||
it 'returns http forbidden' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is the owner' do
|
||||
let(:collection) { Fabricate(:collection, account: user.account) }
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read:collections'
|
||||
|
||||
it 'deletes the collection and returns http success' do
|
||||
collection
|
||||
|
||||
expect { subject }.to change(Collection, :count).by(-1)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -45,7 +45,7 @@ RSpec.describe CreateCollectionService do
|
||||
end
|
||||
|
||||
context 'when given a tag' do
|
||||
let(:params) { base_params.merge(tag: '#people') }
|
||||
let(:params) { base_params.merge(tag_name: '#people') }
|
||||
|
||||
context 'when the tag exists' do
|
||||
let!(:tag) { Fabricate.create(:tag, name: 'people') }
|
||||
|
||||
@ -6,10 +6,10 @@ module ThreadingHelpers
|
||||
def multi_threaded_execution(thread_count)
|
||||
barrier = Concurrent::CyclicBarrier.new(thread_count)
|
||||
|
||||
threads = Array.new(thread_count) do
|
||||
threads = Array.new(thread_count) do |index|
|
||||
Thread.new do
|
||||
barrier.wait
|
||||
yield
|
||||
yield(index)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
20
yarn.lock
20
yarn.lock
@ -2723,7 +2723,7 @@ __metadata:
|
||||
"@formatjs/intl-pluralrules": "npm:^5.4.4"
|
||||
"@gamestdio/websocket": "npm:^0.3.2"
|
||||
"@github/webauthn-json": "npm:^2.1.1"
|
||||
"@optimize-lodash/rollup-plugin": "npm:^5.0.2"
|
||||
"@optimize-lodash/rollup-plugin": "npm:^6.0.0"
|
||||
"@react-spring/web": "npm:^9.7.5"
|
||||
"@reduxjs/toolkit": "npm:^2.0.1"
|
||||
"@storybook/addon-a11y": "npm:^10.0.6"
|
||||
@ -3027,25 +3027,25 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@optimize-lodash/rollup-plugin@npm:^5.0.2":
|
||||
version: 5.1.0
|
||||
resolution: "@optimize-lodash/rollup-plugin@npm:5.1.0"
|
||||
"@optimize-lodash/rollup-plugin@npm:^6.0.0":
|
||||
version: 6.0.0
|
||||
resolution: "@optimize-lodash/rollup-plugin@npm:6.0.0"
|
||||
dependencies:
|
||||
"@optimize-lodash/transform": "npm:3.0.6"
|
||||
"@optimize-lodash/transform": "npm:4.0.0"
|
||||
"@rollup/pluginutils": "npm:^5.1.0"
|
||||
peerDependencies:
|
||||
rollup: ">= 4.x"
|
||||
checksum: 10c0/cb15712b82164fb63d569caebc278fea4972577009040370b43534edd75069f57974c29e884b3dc59896eda7ed4f28dfcb422c0481d8ea0fe5dfc4546af70774
|
||||
checksum: 10c0/2332d642d3e48c5e58618d4b21e77b9b0d723dc8742ca8b49868dd85f931cdce222d0fe3a94948e435888731ed8d33ddc5d1374a200cef074693505c1c66ea15
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@optimize-lodash/transform@npm:3.0.6":
|
||||
version: 3.0.6
|
||||
resolution: "@optimize-lodash/transform@npm:3.0.6"
|
||||
"@optimize-lodash/transform@npm:4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "@optimize-lodash/transform@npm:4.0.0"
|
||||
dependencies:
|
||||
estree-walker: "npm:^2.0.2"
|
||||
magic-string: "npm:~0.30.11"
|
||||
checksum: 10c0/48a877a41e8cb642daccd3a9d815b05c55ac63fc2fdeea6f3e60239e8dcf46a3cd56f6699d67dfd0aebb2e2bb0f019fde6dd7880fb13a7a6db99a53392273578
|
||||
checksum: 10c0/8c32212f2ef49103894a75f91958aae43d0498d9db636fb2b7d043d87f241a5a747bff20d0bd5a1595b8704af92cc293806ce00f90836e86c21c1da02672cd48
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user