mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-13 07:49:29 +00:00
Merge pull request #3303 from ClearlyClaire/glitch-soc/merge-upstream
Merge upstream changes up to b3b5bf26d1
This commit is contained in:
@@ -135,8 +135,8 @@ GEM
|
||||
racc
|
||||
browser (6.2.0)
|
||||
builder (3.3.0)
|
||||
bundler-audit (0.9.2)
|
||||
bundler (>= 1.2.0, < 3)
|
||||
bundler-audit (0.9.3)
|
||||
bundler (>= 1.2.0)
|
||||
thor (~> 1.0)
|
||||
capybara (3.40.0)
|
||||
addressable
|
||||
|
||||
@@ -5,6 +5,15 @@ module Admin
|
||||
def index
|
||||
authorize :custom_emoji, :index?
|
||||
|
||||
# If filtering by local emojis, remove by_domain filter.
|
||||
params.delete(:by_domain) if params[:local].present?
|
||||
|
||||
# If filtering by domain, ensure remote filter is set.
|
||||
if params[:by_domain].present?
|
||||
params.delete(:local)
|
||||
params[:remote] = '1'
|
||||
end
|
||||
|
||||
@custom_emojis = filtered_custom_emojis.eager_load(:local_counterpart).page(params[:page])
|
||||
@form = Form::CustomEmojiBatch.new
|
||||
end
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::AnnualReportsController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, only: :index
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, except: :index
|
||||
include AsyncRefreshesConcern
|
||||
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, except: [:read, :generate]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:read, :generate]
|
||||
before_action :require_user!
|
||||
before_action :set_annual_report, except: :index
|
||||
before_action :set_annual_report, only: [:show, :read]
|
||||
|
||||
def index
|
||||
with_read_replica do
|
||||
@@ -28,14 +30,59 @@ class Api::V1::AnnualReportsController < Api::BaseController
|
||||
relationships: @relationships
|
||||
end
|
||||
|
||||
def state
|
||||
render json: { state: report_state }
|
||||
end
|
||||
|
||||
def generate
|
||||
return render_empty unless year == AnnualReport.current_campaign
|
||||
return render_empty if GeneratedAnnualReport.exists?(account_id: current_account.id, year: year)
|
||||
|
||||
async_refresh = AsyncRefresh.new(refresh_key)
|
||||
|
||||
if async_refresh.running?
|
||||
add_async_refresh_header(async_refresh, retry_seconds: 2)
|
||||
return head 202
|
||||
end
|
||||
|
||||
add_async_refresh_header(AsyncRefresh.create(refresh_key), retry_seconds: 2)
|
||||
|
||||
GenerateAnnualReportWorker.perform_async(current_account.id, year)
|
||||
|
||||
head 202
|
||||
end
|
||||
|
||||
def read
|
||||
@annual_report.view!
|
||||
render_empty
|
||||
end
|
||||
|
||||
def refresh_key
|
||||
"wrapstodon:#{current_account.id}:#{year}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def report_state
|
||||
return 'available' if GeneratedAnnualReport.exists?(account_id: current_account.id, year: year)
|
||||
|
||||
async_refresh = AsyncRefresh.new(refresh_key)
|
||||
|
||||
if async_refresh.running?
|
||||
add_async_refresh_header(async_refresh, retry_seconds: 2)
|
||||
'generating'
|
||||
elsif AnnualReport.current_campaign == year && AnnualReport.new(current_account, year).eligible?
|
||||
'eligible'
|
||||
else
|
||||
'ineligible'
|
||||
end
|
||||
end
|
||||
|
||||
def year
|
||||
params[:id]&.to_i
|
||||
end
|
||||
|
||||
def set_annual_report
|
||||
@annual_report = GeneratedAnnualReport.find_by!(account_id: current_account.id, year: params[:id])
|
||||
@annual_report = GeneratedAnnualReport.find_by!(account_id: current_account.id, year: year)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,7 +9,14 @@ class Api::V1Alpha::CollectionsController < Api::BaseController
|
||||
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:collections' }, only: [:create]
|
||||
|
||||
before_action :require_user!
|
||||
before_action :require_user!, only: [:create]
|
||||
|
||||
def show
|
||||
cache_if_unauthenticated!
|
||||
@collection = Collection.find(params[:id])
|
||||
|
||||
render json: @collection, serializer: REST::CollectionSerializer
|
||||
end
|
||||
|
||||
def create
|
||||
@collection = CreateCollectionService.new.call(collection_params, current_user.account)
|
||||
|
||||
@@ -135,7 +135,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
||||
@accept_token = session[:accept_token] = SecureRandom.hex
|
||||
@invite_code = invite_code
|
||||
|
||||
set_locale { render :rules }
|
||||
render :rules
|
||||
end
|
||||
|
||||
def is_flashing_format? # rubocop:disable Naming/PredicatePrefix
|
||||
|
||||
23
app/controllers/wrapstodon_controller.rb
Normal file
23
app/controllers/wrapstodon_controller.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class WrapstodonController < ApplicationController
|
||||
include WebAppControllerConcern
|
||||
include Authorization
|
||||
include AccountOwnedConcern
|
||||
|
||||
vary_by 'Accept, Accept-Language, Cookie'
|
||||
|
||||
before_action :set_generated_annual_report
|
||||
|
||||
skip_before_action :require_functional!, only: :show, unless: :limited_federation_mode?
|
||||
|
||||
def show
|
||||
expires_in 10.seconds, public: true if current_account.nil?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_generated_annual_report
|
||||
@generated_annual_report = GeneratedAnnualReport.find_by!(account: @account, year: params[:year], share_key: params[:share_key])
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1,5 @@
|
||||
import { checkAnnualReport } from '@/flavours/glitch/reducers/slices/annual_report';
|
||||
|
||||
import api from '../api';
|
||||
|
||||
import { importFetchedAccount } from './importer';
|
||||
@@ -29,6 +31,9 @@ export const fetchServer = () => (dispatch, getState) => {
|
||||
.get('/api/v2/instance').then(({ data }) => {
|
||||
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
|
||||
dispatch(fetchServerSuccess(data));
|
||||
if (data.wrapstodon) {
|
||||
void dispatch(checkAnnualReport());
|
||||
}
|
||||
}).catch(err => dispatch(fetchServerFail(err)));
|
||||
};
|
||||
|
||||
|
||||
@@ -85,6 +85,8 @@ export function fetchStatus(id, {
|
||||
dispatch(fetchStatusSuccess(skipLoading));
|
||||
}).catch(error => {
|
||||
dispatch(fetchStatusFail(id, error, skipLoading, parentQuotePostId));
|
||||
if (error.status === 404)
|
||||
dispatch(deleteFromTimelines(id));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
38
app/javascript/flavours/glitch/api/annual_report.ts
Normal file
38
app/javascript/flavours/glitch/api/annual_report.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import api, { apiRequestGet, getAsyncRefreshHeader } from '../api';
|
||||
import type { ApiAccountJSON } from '../api_types/accounts';
|
||||
import type { ApiStatusJSON } from '../api_types/statuses';
|
||||
import type { AnnualReport } from '../models/annual_report';
|
||||
|
||||
export type ApiAnnualReportState =
|
||||
| 'available'
|
||||
| 'generating'
|
||||
| 'eligible'
|
||||
| 'ineligible';
|
||||
|
||||
export const apiGetAnnualReportState = async (year: number) => {
|
||||
const response = await api().get<{ state: ApiAnnualReportState }>(
|
||||
`/api/v1/annual_reports/${year}/state`,
|
||||
);
|
||||
|
||||
return {
|
||||
state: response.data.state,
|
||||
refresh: getAsyncRefreshHeader(response),
|
||||
};
|
||||
};
|
||||
|
||||
export const apiRequestGenerateAnnualReport = async (year: number) => {
|
||||
const response = await api().post(`/api/v1/annual_reports/${year}/generate`);
|
||||
|
||||
return {
|
||||
refresh: getAsyncRefreshHeader(response),
|
||||
};
|
||||
};
|
||||
|
||||
export interface ApiAnnualReportResponse {
|
||||
annual_reports: AnnualReport[];
|
||||
accounts: ApiAccountJSON[];
|
||||
statuses: ApiStatusJSON[];
|
||||
}
|
||||
|
||||
export const apiGetAnnualReport = (year: number) =>
|
||||
apiRequestGet<ApiAnnualReportResponse>(`v1/annual_reports/${year}`);
|
||||
@@ -1,8 +1,9 @@
|
||||
// See app/serializers/rest/account_serializer.rb
|
||||
// See app/serializers/rest/custom_emoji_serializer.rb
|
||||
export interface ApiCustomEmojiJSON {
|
||||
shortcode: string;
|
||||
static_url: string;
|
||||
url: string;
|
||||
category?: string;
|
||||
featured?: boolean;
|
||||
visible_in_picker: boolean;
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ const hotkeyMatcherMap = {
|
||||
openProfile: just('p'),
|
||||
moveDown: just('j'),
|
||||
moveUp: just('k'),
|
||||
moveToTop: just('0'),
|
||||
toggleHidden: just('x'),
|
||||
toggleSensitive: just('h'),
|
||||
toggleComposeSpoilers: optionPlus('x'),
|
||||
|
||||
@@ -198,7 +198,7 @@ export const HandledLink: FC<HandledLinkProps & ComponentProps<'a'>> = ({
|
||||
title={href}
|
||||
className={classNames('unhandled-link', className)}
|
||||
target='_blank'
|
||||
rel='noreferrer noopener'
|
||||
rel='noopener'
|
||||
translate='no'
|
||||
ref={linkRef}
|
||||
>
|
||||
|
||||
@@ -8,6 +8,8 @@ import { debounce } from 'lodash';
|
||||
import { TIMELINE_GAP, TIMELINE_SUGGESTIONS } from 'flavours/glitch/actions/timelines';
|
||||
import { RegenerationIndicator } from 'flavours/glitch/components/regeneration_indicator';
|
||||
import { InlineFollowSuggestions } from 'flavours/glitch/features/home_timeline/components/inline_follow_suggestions';
|
||||
import { AnnualReportTimeline } from 'flavours/glitch/features/annual_report/timeline';
|
||||
import { TIMELINE_WRAPSTODON } from '@/flavours/glitch/reducers/slices/annual_report';
|
||||
|
||||
import { StatusQuoteManager } from '../components/status_quoted';
|
||||
|
||||
@@ -64,10 +66,12 @@ export default class StatusList extends ImmutablePureComponent {
|
||||
switch(statusId) {
|
||||
case TIMELINE_SUGGESTIONS:
|
||||
return (
|
||||
<InlineFollowSuggestions
|
||||
key='inline-follow-suggestions'
|
||||
/>
|
||||
<InlineFollowSuggestions key={TIMELINE_SUGGESTIONS} />
|
||||
);
|
||||
case TIMELINE_WRAPSTODON:
|
||||
return (
|
||||
<AnnualReportTimeline key={TIMELINE_WRAPSTODON} />
|
||||
)
|
||||
case TIMELINE_GAP:
|
||||
return (
|
||||
<LoadGap
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-vite';
|
||||
import { fn } from 'storybook/test';
|
||||
|
||||
import { AnnualReportAnnouncement } from '.';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/AnnualReportAnnouncement',
|
||||
component: AnnualReportAnnouncement,
|
||||
args: {
|
||||
hasData: false,
|
||||
isLoading: false,
|
||||
year: '2025',
|
||||
onRequestBuild: fn(),
|
||||
onOpen: fn(),
|
||||
},
|
||||
} satisfies Meta<typeof AnnualReportAnnouncement>;
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
render: (args) => <AnnualReportAnnouncement {...args} />,
|
||||
};
|
||||
|
||||
export const Loading: Story = {
|
||||
args: {
|
||||
isLoading: true,
|
||||
},
|
||||
render: Default.render,
|
||||
};
|
||||
|
||||
export const WithData: Story = {
|
||||
args: {
|
||||
hasData: true,
|
||||
},
|
||||
render: Default.render,
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Button } from '@/flavours/glitch/components/button';
|
||||
|
||||
import styles from './styles.module.scss';
|
||||
|
||||
export const AnnualReportAnnouncement: React.FC<{
|
||||
year: string;
|
||||
hasData: boolean;
|
||||
isLoading: boolean;
|
||||
onRequestBuild: () => void;
|
||||
onOpen: () => void;
|
||||
}> = ({ year, hasData, isLoading, onRequestBuild, onOpen }) => {
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id='annual_report.announcement.title'
|
||||
defaultMessage='Wrapstodon {year} has arrived'
|
||||
values={{ year }}
|
||||
/>
|
||||
</h2>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id='annual_report.announcement.description'
|
||||
defaultMessage='Discover more about your engagement on Mastodon over the past year.'
|
||||
/>
|
||||
</p>
|
||||
{hasData ? (
|
||||
<Button onClick={onOpen}>
|
||||
<FormattedMessage
|
||||
id='annual_report.announcement.action_view'
|
||||
defaultMessage='View my Wrapstodon'
|
||||
/>
|
||||
</Button>
|
||||
) : (
|
||||
<Button loading={isLoading} onClick={onRequestBuild}>
|
||||
<FormattedMessage
|
||||
id='annual_report.announcement.action_build'
|
||||
defaultMessage='Build my Wrapstodon'
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 40px 60px;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
color: var(--color-text-on-media);
|
||||
background: var(--color-bg-media-base);
|
||||
background:
|
||||
radial-gradient(at 40% 87%, #240c9a99 0, transparent 50%),
|
||||
radial-gradient(at 19% 10%, #6b0c9a99 0, transparent 50%),
|
||||
radial-gradient(at 90% 27%, #9a0c8299 0, transparent 50%),
|
||||
radial-gradient(at 16% 95%, #1e948299 0, transparent 50%)
|
||||
var(--color-bg-media-base);
|
||||
border-bottom: 1px solid var(--color-border-primary);
|
||||
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ export const AnnualReport: React.FC<{
|
||||
|
||||
const report = response?.annual_reports[0];
|
||||
|
||||
if (!report) {
|
||||
if (!report || report.schema_version !== 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { useCallback } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { showAlert } from '@/flavours/glitch/actions/alerts';
|
||||
import {
|
||||
generateReport,
|
||||
selectWrapstodonYear,
|
||||
} from '@/flavours/glitch/reducers/slices/annual_report';
|
||||
import { useAppDispatch, useAppSelector } from '@/flavours/glitch/store';
|
||||
|
||||
import { AnnualReportAnnouncement } from './announcement';
|
||||
|
||||
export const AnnualReportTimeline: FC = () => {
|
||||
const { state } = useAppSelector((state) => state.annualReport);
|
||||
const year = useAppSelector(selectWrapstodonYear);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const handleBuildRequest = useCallback(() => {
|
||||
void dispatch(generateReport());
|
||||
}, [dispatch]);
|
||||
|
||||
const handleOpen = useCallback(() => {
|
||||
dispatch(
|
||||
// TODO: Implement opening the annual report view when components are ready.
|
||||
showAlert({
|
||||
message: 'Not yet implemented.',
|
||||
}),
|
||||
);
|
||||
}, [dispatch]);
|
||||
|
||||
if (!year || !state || state === 'ineligible') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<AnnualReportAnnouncement
|
||||
year={year.toString()}
|
||||
hasData={state === 'available'}
|
||||
isLoading={state === 'generating'}
|
||||
onRequestBuild={handleBuildRequest}
|
||||
onOpen={handleOpen}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -99,13 +99,17 @@ class KeyboardShortcuts extends ImmutablePureComponent {
|
||||
<td><FormattedMessage id='keyboard_shortcuts.down' defaultMessage='to move down in the list' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><kbd>l</kbd></td>
|
||||
<td><FormattedMessage id='keyboard_shortcuts.load_more' defaultMessage='Focus "Load more" button' /></td>
|
||||
<td><kbd>0</kbd></td>
|
||||
<td><FormattedMessage id='keyboard_shortcuts.top' defaultMessage='Move to top of list' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><kbd>1</kbd>-<kbd>9</kbd></td>
|
||||
<td><FormattedMessage id='keyboard_shortcuts.column' defaultMessage='to focus a status in one of the columns' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><kbd>l</kbd></td>
|
||||
<td><FormattedMessage id='keyboard_shortcuts.load_more' defaultMessage='Focus "Load more" button' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><kbd>n</kbd></td>
|
||||
<td><FormattedMessage id='keyboard_shortcuts.compose' defaultMessage='to focus the compose textarea' /></td>
|
||||
|
||||
@@ -4,9 +4,10 @@ import { connect } from 'react-redux';
|
||||
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
import { scrollTopTimeline, loadPending } from '../../../actions/timelines';
|
||||
import StatusList from '../../../components/status_list';
|
||||
import { me } from '../../../initial_state';
|
||||
import { scrollTopTimeline, loadPending, TIMELINE_SUGGESTIONS } from '@/flavours/glitch/actions/timelines';
|
||||
import StatusList from '@/flavours/glitch/components/status_list';
|
||||
import { me } from '@/flavours/glitch/initial_state';
|
||||
import { TIMELINE_WRAPSTODON } from '@/flavours/glitch/reducers/slices/annual_report';
|
||||
|
||||
const getRegex = createSelector([
|
||||
(state, { regex }) => regex,
|
||||
@@ -28,7 +29,7 @@ const makeGetStatusIds = (pending = false) => createSelector([
|
||||
getRegex,
|
||||
], (columnSettings, statusIds, statuses, regex) => {
|
||||
return statusIds.filter(id => {
|
||||
if (id === null || id === 'inline-follow-suggestions') return true;
|
||||
if (id === null || id === TIMELINE_SUGGESTIONS || id === TIMELINE_WRAPSTODON) return true;
|
||||
|
||||
const statusForId = statuses.get(id);
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ import {
|
||||
Quotes,
|
||||
} from './util/async-components';
|
||||
import { ColumnsContextProvider } from './util/columns_context';
|
||||
import { focusColumn, getFocusedItemIndex, focusItemSibling } from './util/focusUtils';
|
||||
import { focusColumn, getFocusedItemIndex, focusItemSibling, focusFirstItem } from './util/focusUtils';
|
||||
import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers';
|
||||
|
||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||
@@ -495,20 +495,21 @@ class UI extends PureComponent {
|
||||
};
|
||||
|
||||
handleHotkeyFocusColumn = e => {
|
||||
focusColumn({index: e.key * 1});
|
||||
focusColumn(e.key * 1);
|
||||
};
|
||||
|
||||
handleHotkeyLoadMore = () => {
|
||||
document.querySelector('.load-more')?.focus();
|
||||
};
|
||||
|
||||
handleMoveToTop = () => {
|
||||
focusFirstItem();
|
||||
};
|
||||
|
||||
handleMoveUp = () => {
|
||||
const currentItemIndex = getFocusedItemIndex();
|
||||
if (currentItemIndex === -1) {
|
||||
focusColumn({
|
||||
index: 1,
|
||||
focusItem: 'first-visible',
|
||||
});
|
||||
focusColumn(1);
|
||||
} else {
|
||||
focusItemSibling(currentItemIndex, -1);
|
||||
}
|
||||
@@ -517,10 +518,7 @@ class UI extends PureComponent {
|
||||
handleMoveDown = () => {
|
||||
const currentItemIndex = getFocusedItemIndex();
|
||||
if (currentItemIndex === -1) {
|
||||
focusColumn({
|
||||
index: 1,
|
||||
focusItem: 'first-visible',
|
||||
});
|
||||
focusColumn(1);
|
||||
} else {
|
||||
focusItemSibling(currentItemIndex, 1);
|
||||
}
|
||||
@@ -615,6 +613,7 @@ class UI extends PureComponent {
|
||||
focusLoadMore: this.handleHotkeyLoadMore,
|
||||
moveDown: this.handleMoveDown,
|
||||
moveUp: this.handleMoveUp,
|
||||
moveToTop: this.handleMoveToTop,
|
||||
back: this.handleHotkeyBack,
|
||||
goToHome: this.handleHotkeyGoToHome,
|
||||
goToNotifications: this.handleHotkeyGoToNotifications,
|
||||
|
||||
@@ -1,16 +1,30 @@
|
||||
interface FocusColumnOptions {
|
||||
index?: number;
|
||||
focusItem?: 'first' | 'first-visible';
|
||||
/**
|
||||
* Out of a list of elements, return the first one whose top edge
|
||||
* is inside of the viewport, and return the element and its BoundingClientRect.
|
||||
*/
|
||||
function findFirstVisibleWithRect(
|
||||
items: HTMLElement[],
|
||||
): { item: HTMLElement; rect: DOMRect } | null {
|
||||
const viewportHeight =
|
||||
window.innerHeight || document.documentElement.clientHeight;
|
||||
|
||||
for (const item of items) {
|
||||
const rect = item.getBoundingClientRect();
|
||||
const isVisible = rect.top >= 0 && rect.top < viewportHeight;
|
||||
|
||||
if (isVisible) {
|
||||
return { item, rect };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move focus to the column of the passed index (1-based).
|
||||
* Can either focus the topmost item or the first one in the viewport
|
||||
* Focus is placed on the topmost visible item
|
||||
*/
|
||||
export function focusColumn({
|
||||
index = 1,
|
||||
focusItem = 'first',
|
||||
}: FocusColumnOptions = {}) {
|
||||
export function focusColumn(index = 1) {
|
||||
// Skip the leftmost drawer in multi-column mode
|
||||
const isMultiColumnLayout = !!document.querySelector(
|
||||
'body.layout-multiple-columns',
|
||||
@@ -27,33 +41,28 @@ export function focusColumn({
|
||||
|
||||
if (!container) return;
|
||||
|
||||
let itemToFocus: HTMLElement | null = null;
|
||||
const focusableItems = Array.from(
|
||||
container.querySelectorAll<HTMLElement>(
|
||||
'.focusable:not(.status__quote .focusable)',
|
||||
),
|
||||
);
|
||||
|
||||
if (focusItem === 'first-visible') {
|
||||
const focusableItems = Array.from(
|
||||
container.querySelectorAll<HTMLElement>(
|
||||
'.focusable:not(.status__quote .focusable)',
|
||||
),
|
||||
);
|
||||
|
||||
const viewportHeight =
|
||||
window.innerHeight || document.documentElement.clientHeight;
|
||||
|
||||
// Find first item visible in the viewport
|
||||
itemToFocus =
|
||||
focusableItems.find((item) => {
|
||||
const { top } = item.getBoundingClientRect();
|
||||
return top >= 0 && top < viewportHeight;
|
||||
}) ?? null;
|
||||
} else {
|
||||
itemToFocus = container.querySelector('.focusable');
|
||||
}
|
||||
// Find first item visible in the viewport
|
||||
const itemToFocus = findFirstVisibleWithRect(focusableItems);
|
||||
|
||||
if (itemToFocus) {
|
||||
if (container.scrollTop > itemToFocus.offsetTop) {
|
||||
itemToFocus.scrollIntoView(true);
|
||||
const viewportWidth =
|
||||
window.innerWidth || document.documentElement.clientWidth;
|
||||
const { item, rect } = itemToFocus;
|
||||
|
||||
if (
|
||||
container.scrollTop > item.offsetTop ||
|
||||
rect.right > viewportWidth ||
|
||||
rect.left < 0
|
||||
) {
|
||||
itemToFocus.item.scrollIntoView(true);
|
||||
}
|
||||
itemToFocus.focus();
|
||||
itemToFocus.item.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +80,26 @@ export function getFocusedItemIndex() {
|
||||
return items.indexOf(focusedItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the topmost item of the column that currently has focus,
|
||||
* or the first column if none
|
||||
*/
|
||||
export function focusFirstItem() {
|
||||
const focusedElement = document.activeElement;
|
||||
const container =
|
||||
focusedElement?.closest('.scrollable') ??
|
||||
document.querySelector('.scrollable');
|
||||
|
||||
if (!container) return;
|
||||
|
||||
const itemToFocus = container.querySelector<HTMLElement>('.focusable');
|
||||
|
||||
if (itemToFocus) {
|
||||
container.scrollTo(0, 0);
|
||||
itemToFocus.focus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the item next to the one with the provided index
|
||||
*/
|
||||
|
||||
@@ -37,8 +37,30 @@ interface AnnualReportV1 {
|
||||
archetype: Archetype;
|
||||
}
|
||||
|
||||
export interface AnnualReport {
|
||||
year: number;
|
||||
schema_version: number;
|
||||
data: AnnualReportV1;
|
||||
interface AnnualReportV2 {
|
||||
archetype: Archetype;
|
||||
time_series: TimeSeriesMonth[];
|
||||
top_hashtags: NameAndCount[];
|
||||
top_statuses: TopStatuses;
|
||||
most_used_apps: NameAndCount[];
|
||||
type_distribution: {
|
||||
total: number;
|
||||
reblogs: number;
|
||||
replies: number;
|
||||
standalone: number;
|
||||
};
|
||||
}
|
||||
|
||||
export type AnnualReport = {
|
||||
year: number;
|
||||
} & (
|
||||
| {
|
||||
schema_version: 1;
|
||||
data: AnnualReportV1;
|
||||
}
|
||||
| {
|
||||
schema_version: 2;
|
||||
data: AnnualReportV2;
|
||||
share_url: string | null;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ export const CustomEmojiFactory = ImmutableRecord<CustomEmojiShape>({
|
||||
static_url: '',
|
||||
url: '',
|
||||
category: '',
|
||||
featured: false,
|
||||
visible_in_picker: false,
|
||||
});
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import { relationshipsReducer } from './relationships';
|
||||
import { searchReducer } from './search';
|
||||
import server from './server';
|
||||
import settings from './settings';
|
||||
import { sliceReducers } from './slices';
|
||||
import status_lists from './status_lists';
|
||||
import statuses from './statuses';
|
||||
import { suggestionsReducer } from './suggestions';
|
||||
@@ -82,6 +83,7 @@ const reducers = {
|
||||
notificationPolicy: notificationPolicyReducer,
|
||||
notificationRequests: notificationRequestsReducer,
|
||||
navigation: navigationReducer,
|
||||
...sliceReducers,
|
||||
};
|
||||
|
||||
// We want the root state to be an ImmutableRecord, which is an object with a defined list of keys,
|
||||
|
||||
118
app/javascript/flavours/glitch/reducers/slices/annual_report.ts
Normal file
118
app/javascript/flavours/glitch/reducers/slices/annual_report.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
import { insertIntoTimeline } from '@/flavours/glitch/actions/timelines';
|
||||
import type { ApiAnnualReportState } from '@/flavours/glitch/api/annual_report';
|
||||
import {
|
||||
apiGetAnnualReport,
|
||||
apiGetAnnualReportState,
|
||||
apiRequestGenerateAnnualReport,
|
||||
} from '@/flavours/glitch/api/annual_report';
|
||||
import type { AnnualReport } from '@/flavours/glitch/models/annual_report';
|
||||
|
||||
import {
|
||||
createAppSelector,
|
||||
createAppThunk,
|
||||
createDataLoadingThunk,
|
||||
} from '../../store/typed_functions';
|
||||
|
||||
export const TIMELINE_WRAPSTODON = 'inline-wrapstodon';
|
||||
|
||||
interface AnnualReportState {
|
||||
state?: ApiAnnualReportState;
|
||||
report?: AnnualReport;
|
||||
}
|
||||
|
||||
const annualReportSlice = createSlice({
|
||||
name: 'annualReport',
|
||||
initialState: {} as AnnualReportState,
|
||||
reducers: {},
|
||||
extraReducers(builder) {
|
||||
builder
|
||||
.addCase(fetchReportState.fulfilled, (state, action) => {
|
||||
state.state = action.payload;
|
||||
})
|
||||
.addCase(generateReport.pending, (state) => {
|
||||
state.state = 'generating';
|
||||
})
|
||||
.addCase(getReport.fulfilled, (state, action) => {
|
||||
if (action.payload) {
|
||||
state.report = action.payload;
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const annualReport = annualReportSlice.reducer;
|
||||
|
||||
export const selectWrapstodonYear = createAppSelector(
|
||||
[(state) => state.server.getIn(['server', 'wrapstodon'])],
|
||||
(year: unknown) => (typeof year === 'number' && year > 2000 ? year : null),
|
||||
);
|
||||
|
||||
// This kicks everything off, and is called after fetching the server info.
|
||||
export const checkAnnualReport = createAppThunk(
|
||||
`${annualReportSlice.name}/checkAnnualReport`,
|
||||
async (_arg: unknown, { dispatch, getState }) => {
|
||||
const year = selectWrapstodonYear(getState());
|
||||
if (!year) {
|
||||
return;
|
||||
}
|
||||
const state = await dispatch(fetchReportState());
|
||||
if (
|
||||
state.meta.requestStatus === 'fulfilled' &&
|
||||
state.payload !== 'ineligible'
|
||||
) {
|
||||
dispatch(insertIntoTimeline('home', TIMELINE_WRAPSTODON, 1));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const fetchReportState = createDataLoadingThunk(
|
||||
`${annualReportSlice.name}/fetchReportState`,
|
||||
async (_arg: unknown, { getState }) => {
|
||||
const year = selectWrapstodonYear(getState());
|
||||
if (!year) {
|
||||
throw new Error('Year is not set');
|
||||
}
|
||||
return apiGetAnnualReportState(year);
|
||||
},
|
||||
({ state, refresh }, { dispatch }) => {
|
||||
if (state === 'generating' && refresh) {
|
||||
window.setTimeout(() => {
|
||||
void dispatch(fetchReportState());
|
||||
}, 1_000 * refresh.retry);
|
||||
} else if (state === 'available') {
|
||||
void dispatch(getReport());
|
||||
}
|
||||
|
||||
return state;
|
||||
},
|
||||
{ useLoadingBar: false },
|
||||
);
|
||||
|
||||
// Triggers the generation of the annual report.
|
||||
export const generateReport = createDataLoadingThunk(
|
||||
`${annualReportSlice.name}/generateReport`,
|
||||
async (_arg: unknown, { getState }) => {
|
||||
const year = selectWrapstodonYear(getState());
|
||||
if (!year) {
|
||||
throw new Error('Year is not set');
|
||||
}
|
||||
return apiRequestGenerateAnnualReport(year);
|
||||
},
|
||||
(_arg: unknown, { dispatch }) => {
|
||||
void dispatch(fetchReportState());
|
||||
},
|
||||
);
|
||||
|
||||
export const getReport = createDataLoadingThunk(
|
||||
`${annualReportSlice.name}/getReport`,
|
||||
async (_arg: unknown, { getState }) => {
|
||||
const year = selectWrapstodonYear(getState());
|
||||
if (!year) {
|
||||
throw new Error('Year is not set');
|
||||
}
|
||||
return apiGetAnnualReport(year);
|
||||
},
|
||||
(data) => data.annual_reports[0],
|
||||
);
|
||||
5
app/javascript/flavours/glitch/reducers/slices/index.ts
Normal file
5
app/javascript/flavours/glitch/reducers/slices/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { annualReport } from './annual_report';
|
||||
|
||||
export const sliceReducers = {
|
||||
annualReport,
|
||||
};
|
||||
@@ -65,6 +65,10 @@ const statusTranslateUndo = (state, id) => {
|
||||
});
|
||||
};
|
||||
|
||||
const removeStatusStub = (state, id) => {
|
||||
return state.getIn([id, 'id']) ? state.deleteIn([id, 'isLoading']) : state.delete(id);
|
||||
}
|
||||
|
||||
|
||||
/** @type {ImmutableMap<string, import('flavours/glitch/models/status').Status>} */
|
||||
const initialState = ImmutableMap();
|
||||
@@ -92,11 +96,10 @@ export default function statuses(state = initialState, action) {
|
||||
return state.setIn([action.id, 'isLoading'], true);
|
||||
case STATUS_FETCH_FAIL: {
|
||||
if (action.parentQuotePostId && action.error.status === 404) {
|
||||
return state
|
||||
.delete(action.id)
|
||||
return removeStatusStub(state, action.id)
|
||||
.setIn([action.parentQuotePostId, 'quote', 'state'], 'deleted')
|
||||
} else {
|
||||
return state.delete(action.id);
|
||||
return removeStatusStub(state, action.id);
|
||||
}
|
||||
}
|
||||
case STATUS_IMPORT:
|
||||
|
||||
@@ -205,7 +205,7 @@ export function createDataLoadingThunk<LoadDataResult, Args extends ArgsType>(
|
||||
thunkOptions?: AppThunkOptions<Args>,
|
||||
): ReturnType<typeof createAsyncThunk<Args, void>>;
|
||||
|
||||
// Overload when the `onData` method returns nothing, then the mayload is the `onData` result
|
||||
// Overload when the `onData` method returns nothing, then the payload is the `onData` result
|
||||
export function createDataLoadingThunk<LoadDataResult, Args extends ArgsType>(
|
||||
name: string,
|
||||
loadData: LoadData<Args, LoadDataResult>,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
@use 'variables' as *;
|
||||
|
||||
html {
|
||||
color: var(--color-text-primary);
|
||||
background: var(--color-bg-ambient);
|
||||
}
|
||||
|
||||
html.has-modal {
|
||||
&,
|
||||
body {
|
||||
|
||||
@@ -5,20 +5,26 @@ export function setupLinkListeners() {
|
||||
|
||||
// We don't want to target links with data-confirm here, as those are handled already.
|
||||
on('click', 'a[data-method]:not([data-confirm])', handleMethodLink);
|
||||
|
||||
// We also want to target buttons with data-confirm that are not inside forms.
|
||||
on('click', ':not(form) button[data-confirm]:not([form])', handleConfirmLink);
|
||||
}
|
||||
|
||||
function handleConfirmLink(event: MouseEvent) {
|
||||
const anchor = event.currentTarget;
|
||||
if (!(anchor instanceof HTMLAnchorElement)) {
|
||||
const target = event.currentTarget;
|
||||
if (
|
||||
!(target instanceof HTMLAnchorElement) &&
|
||||
!(target instanceof HTMLButtonElement)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const message = anchor.dataset.confirm;
|
||||
const message = target.dataset.confirm;
|
||||
if (!message || !window.confirm(message)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (anchor.dataset.method) {
|
||||
if (target.dataset.method) {
|
||||
handleMethodLink(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { checkAnnualReport } from '@/mastodon/reducers/slices/annual_report';
|
||||
|
||||
import api from '../api';
|
||||
|
||||
import { importFetchedAccount } from './importer';
|
||||
@@ -29,6 +31,9 @@ export const fetchServer = () => (dispatch, getState) => {
|
||||
.get('/api/v2/instance').then(({ data }) => {
|
||||
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
|
||||
dispatch(fetchServerSuccess(data));
|
||||
if (data.wrapstodon) {
|
||||
void dispatch(checkAnnualReport());
|
||||
}
|
||||
}).catch(err => dispatch(fetchServerFail(err)));
|
||||
};
|
||||
|
||||
|
||||
@@ -85,6 +85,8 @@ export function fetchStatus(id, {
|
||||
dispatch(fetchStatusSuccess(skipLoading));
|
||||
}).catch(error => {
|
||||
dispatch(fetchStatusFail(id, error, skipLoading, parentQuotePostId));
|
||||
if (error.status === 404)
|
||||
dispatch(deleteFromTimelines(id));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
38
app/javascript/mastodon/api/annual_report.ts
Normal file
38
app/javascript/mastodon/api/annual_report.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import api, { apiRequestGet, getAsyncRefreshHeader } from '../api';
|
||||
import type { ApiAccountJSON } from '../api_types/accounts';
|
||||
import type { ApiStatusJSON } from '../api_types/statuses';
|
||||
import type { AnnualReport } from '../models/annual_report';
|
||||
|
||||
export type ApiAnnualReportState =
|
||||
| 'available'
|
||||
| 'generating'
|
||||
| 'eligible'
|
||||
| 'ineligible';
|
||||
|
||||
export const apiGetAnnualReportState = async (year: number) => {
|
||||
const response = await api().get<{ state: ApiAnnualReportState }>(
|
||||
`/api/v1/annual_reports/${year}/state`,
|
||||
);
|
||||
|
||||
return {
|
||||
state: response.data.state,
|
||||
refresh: getAsyncRefreshHeader(response),
|
||||
};
|
||||
};
|
||||
|
||||
export const apiRequestGenerateAnnualReport = async (year: number) => {
|
||||
const response = await api().post(`/api/v1/annual_reports/${year}/generate`);
|
||||
|
||||
return {
|
||||
refresh: getAsyncRefreshHeader(response),
|
||||
};
|
||||
};
|
||||
|
||||
export interface ApiAnnualReportResponse {
|
||||
annual_reports: AnnualReport[];
|
||||
accounts: ApiAccountJSON[];
|
||||
statuses: ApiStatusJSON[];
|
||||
}
|
||||
|
||||
export const apiGetAnnualReport = (year: number) =>
|
||||
apiRequestGet<ApiAnnualReportResponse>(`v1/annual_reports/${year}`);
|
||||
@@ -1,8 +1,9 @@
|
||||
// See app/serializers/rest/account_serializer.rb
|
||||
// See app/serializers/rest/custom_emoji_serializer.rb
|
||||
export interface ApiCustomEmojiJSON {
|
||||
shortcode: string;
|
||||
static_url: string;
|
||||
url: string;
|
||||
category?: string;
|
||||
featured?: boolean;
|
||||
visible_in_picker: boolean;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ const hotkeyMatcherMap = {
|
||||
openProfile: just('p'),
|
||||
moveDown: just('j'),
|
||||
moveUp: just('k'),
|
||||
moveToTop: just('0'),
|
||||
toggleHidden: just('x'),
|
||||
toggleSensitive: just('h'),
|
||||
toggleComposeSpoilers: optionPlus('x'),
|
||||
|
||||
@@ -75,7 +75,7 @@ export const HandledLink: FC<HandledLinkProps & ComponentProps<'a'>> = ({
|
||||
title={href}
|
||||
className={classNames('unhandled-link', className)}
|
||||
target='_blank'
|
||||
rel='noreferrer noopener'
|
||||
rel='noopener'
|
||||
translate='no'
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -8,6 +8,8 @@ import { debounce } from 'lodash';
|
||||
import { TIMELINE_GAP, TIMELINE_SUGGESTIONS } from 'mastodon/actions/timelines';
|
||||
import { RegenerationIndicator } from 'mastodon/components/regeneration_indicator';
|
||||
import { InlineFollowSuggestions } from 'mastodon/features/home_timeline/components/inline_follow_suggestions';
|
||||
import { AnnualReportTimeline } from 'mastodon/features/annual_report/timeline';
|
||||
import { TIMELINE_WRAPSTODON } from '@/mastodon/reducers/slices/annual_report';
|
||||
|
||||
import { StatusQuoteManager } from '../components/status_quoted';
|
||||
|
||||
@@ -63,10 +65,12 @@ export default class StatusList extends ImmutablePureComponent {
|
||||
switch(statusId) {
|
||||
case TIMELINE_SUGGESTIONS:
|
||||
return (
|
||||
<InlineFollowSuggestions
|
||||
key='inline-follow-suggestions'
|
||||
/>
|
||||
<InlineFollowSuggestions key={TIMELINE_SUGGESTIONS} />
|
||||
);
|
||||
case TIMELINE_WRAPSTODON:
|
||||
return (
|
||||
<AnnualReportTimeline key={TIMELINE_WRAPSTODON} />
|
||||
)
|
||||
case TIMELINE_GAP:
|
||||
return (
|
||||
<LoadGap
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-vite';
|
||||
import { fn } from 'storybook/test';
|
||||
|
||||
import { AnnualReportAnnouncement } from '.';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/AnnualReportAnnouncement',
|
||||
component: AnnualReportAnnouncement,
|
||||
args: {
|
||||
hasData: false,
|
||||
isLoading: false,
|
||||
year: '2025',
|
||||
onRequestBuild: fn(),
|
||||
onOpen: fn(),
|
||||
},
|
||||
} satisfies Meta<typeof AnnualReportAnnouncement>;
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
render: (args) => <AnnualReportAnnouncement {...args} />,
|
||||
};
|
||||
|
||||
export const Loading: Story = {
|
||||
args: {
|
||||
isLoading: true,
|
||||
},
|
||||
render: Default.render,
|
||||
};
|
||||
|
||||
export const WithData: Story = {
|
||||
args: {
|
||||
hasData: true,
|
||||
},
|
||||
render: Default.render,
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Button } from '@/mastodon/components/button';
|
||||
|
||||
import styles from './styles.module.scss';
|
||||
|
||||
export const AnnualReportAnnouncement: React.FC<{
|
||||
year: string;
|
||||
hasData: boolean;
|
||||
isLoading: boolean;
|
||||
onRequestBuild: () => void;
|
||||
onOpen: () => void;
|
||||
}> = ({ year, hasData, isLoading, onRequestBuild, onOpen }) => {
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id='annual_report.announcement.title'
|
||||
defaultMessage='Wrapstodon {year} has arrived'
|
||||
values={{ year }}
|
||||
/>
|
||||
</h2>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id='annual_report.announcement.description'
|
||||
defaultMessage='Discover more about your engagement on Mastodon over the past year.'
|
||||
/>
|
||||
</p>
|
||||
{hasData ? (
|
||||
<Button onClick={onOpen}>
|
||||
<FormattedMessage
|
||||
id='annual_report.announcement.action_view'
|
||||
defaultMessage='View my Wrapstodon'
|
||||
/>
|
||||
</Button>
|
||||
) : (
|
||||
<Button loading={isLoading} onClick={onRequestBuild}>
|
||||
<FormattedMessage
|
||||
id='annual_report.announcement.action_build'
|
||||
defaultMessage='Build my Wrapstodon'
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 40px 60px;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
color: var(--color-text-on-media);
|
||||
background: var(--color-bg-media-base);
|
||||
background:
|
||||
radial-gradient(at 40% 87%, #240c9a99 0, transparent 50%),
|
||||
radial-gradient(at 19% 10%, #6b0c9a99 0, transparent 50%),
|
||||
radial-gradient(at 90% 27%, #9a0c8299 0, transparent 50%),
|
||||
radial-gradient(at 16% 95%, #1e948299 0, transparent 50%)
|
||||
var(--color-bg-media-base);
|
||||
border-bottom: 1px solid var(--color-border-primary);
|
||||
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ export const AnnualReport: React.FC<{
|
||||
|
||||
const report = response?.annual_reports[0];
|
||||
|
||||
if (!report) {
|
||||
if (!report || report.schema_version !== 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
44
app/javascript/mastodon/features/annual_report/timeline.tsx
Normal file
44
app/javascript/mastodon/features/annual_report/timeline.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import { useCallback } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { showAlert } from '@/mastodon/actions/alerts';
|
||||
import {
|
||||
generateReport,
|
||||
selectWrapstodonYear,
|
||||
} from '@/mastodon/reducers/slices/annual_report';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { AnnualReportAnnouncement } from './announcement';
|
||||
|
||||
export const AnnualReportTimeline: FC = () => {
|
||||
const { state } = useAppSelector((state) => state.annualReport);
|
||||
const year = useAppSelector(selectWrapstodonYear);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const handleBuildRequest = useCallback(() => {
|
||||
void dispatch(generateReport());
|
||||
}, [dispatch]);
|
||||
|
||||
const handleOpen = useCallback(() => {
|
||||
dispatch(
|
||||
// TODO: Implement opening the annual report view when components are ready.
|
||||
showAlert({
|
||||
message: 'Not yet implemented.',
|
||||
}),
|
||||
);
|
||||
}, [dispatch]);
|
||||
|
||||
if (!year || !state || state === 'ineligible') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<AnnualReportAnnouncement
|
||||
year={year.toString()}
|
||||
hasData={state === 'available'}
|
||||
isLoading={state === 'generating'}
|
||||
onRequestBuild={handleBuildRequest}
|
||||
onOpen={handleOpen}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -95,13 +95,17 @@ class KeyboardShortcuts extends ImmutablePureComponent {
|
||||
<td><FormattedMessage id='keyboard_shortcuts.down' defaultMessage='to move down in the list' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><kbd>l</kbd></td>
|
||||
<td><FormattedMessage id='keyboard_shortcuts.load_more' defaultMessage='Focus "Load more" button' /></td>
|
||||
<td><kbd>0</kbd></td>
|
||||
<td><FormattedMessage id='keyboard_shortcuts.top' defaultMessage='Move to top of list' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><kbd>1</kbd>-<kbd>9</kbd></td>
|
||||
<td><FormattedMessage id='keyboard_shortcuts.column' defaultMessage='to focus a status in one of the columns' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><kbd>l</kbd></td>
|
||||
<td><FormattedMessage id='keyboard_shortcuts.load_more' defaultMessage='Focus "Load more" button' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><kbd>n</kbd></td>
|
||||
<td><FormattedMessage id='keyboard_shortcuts.compose' defaultMessage='to focus the compose textarea' /></td>
|
||||
|
||||
@@ -4,9 +4,10 @@ import { connect } from 'react-redux';
|
||||
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
import { scrollTopTimeline, loadPending } from '../../../actions/timelines';
|
||||
import StatusList from '../../../components/status_list';
|
||||
import { me } from '../../../initial_state';
|
||||
import { scrollTopTimeline, loadPending, TIMELINE_SUGGESTIONS } from '@/mastodon/actions/timelines';
|
||||
import StatusList from '@/mastodon/components/status_list';
|
||||
import { me } from '@/mastodon/initial_state';
|
||||
import { TIMELINE_WRAPSTODON } from '@/mastodon/reducers/slices/annual_report';
|
||||
|
||||
const makeGetStatusIds = (pending = false) => createSelector([
|
||||
(state, { type }) => state.getIn(['settings', type], ImmutableMap()),
|
||||
@@ -14,7 +15,7 @@ const makeGetStatusIds = (pending = false) => createSelector([
|
||||
(state) => state.get('statuses'),
|
||||
], (columnSettings, statusIds, statuses) => {
|
||||
return statusIds.filter(id => {
|
||||
if (id === null || id === 'inline-follow-suggestions') return true;
|
||||
if (id === null || id === TIMELINE_SUGGESTIONS || id === TIMELINE_WRAPSTODON) return true;
|
||||
|
||||
const statusForId = statuses.get(id);
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ import {
|
||||
Quotes,
|
||||
} from './util/async-components';
|
||||
import { ColumnsContextProvider } from './util/columns_context';
|
||||
import { focusColumn, getFocusedItemIndex, focusItemSibling } from './util/focusUtils';
|
||||
import { focusColumn, getFocusedItemIndex, focusItemSibling, focusFirstItem } from './util/focusUtils';
|
||||
import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers';
|
||||
|
||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||
@@ -449,20 +449,21 @@ class UI extends PureComponent {
|
||||
};
|
||||
|
||||
handleHotkeyFocusColumn = e => {
|
||||
focusColumn({index: e.key * 1});
|
||||
focusColumn(e.key * 1);
|
||||
};
|
||||
|
||||
handleHotkeyLoadMore = () => {
|
||||
document.querySelector('.load-more')?.focus();
|
||||
};
|
||||
|
||||
handleMoveToTop = () => {
|
||||
focusFirstItem();
|
||||
};
|
||||
|
||||
handleMoveUp = () => {
|
||||
const currentItemIndex = getFocusedItemIndex();
|
||||
if (currentItemIndex === -1) {
|
||||
focusColumn({
|
||||
index: 1,
|
||||
focusItem: 'first-visible',
|
||||
});
|
||||
focusColumn(1);
|
||||
} else {
|
||||
focusItemSibling(currentItemIndex, -1);
|
||||
}
|
||||
@@ -471,10 +472,7 @@ class UI extends PureComponent {
|
||||
handleMoveDown = () => {
|
||||
const currentItemIndex = getFocusedItemIndex();
|
||||
if (currentItemIndex === -1) {
|
||||
focusColumn({
|
||||
index: 1,
|
||||
focusItem: 'first-visible',
|
||||
});
|
||||
focusColumn(1);
|
||||
} else {
|
||||
focusItemSibling(currentItemIndex, 1);
|
||||
}
|
||||
@@ -562,6 +560,7 @@ class UI extends PureComponent {
|
||||
focusLoadMore: this.handleHotkeyLoadMore,
|
||||
moveDown: this.handleMoveDown,
|
||||
moveUp: this.handleMoveUp,
|
||||
moveToTop: this.handleMoveToTop,
|
||||
back: this.handleHotkeyBack,
|
||||
goToHome: this.handleHotkeyGoToHome,
|
||||
goToNotifications: this.handleHotkeyGoToNotifications,
|
||||
|
||||
@@ -1,16 +1,30 @@
|
||||
interface FocusColumnOptions {
|
||||
index?: number;
|
||||
focusItem?: 'first' | 'first-visible';
|
||||
/**
|
||||
* Out of a list of elements, return the first one whose top edge
|
||||
* is inside of the viewport, and return the element and its BoundingClientRect.
|
||||
*/
|
||||
function findFirstVisibleWithRect(
|
||||
items: HTMLElement[],
|
||||
): { item: HTMLElement; rect: DOMRect } | null {
|
||||
const viewportHeight =
|
||||
window.innerHeight || document.documentElement.clientHeight;
|
||||
|
||||
for (const item of items) {
|
||||
const rect = item.getBoundingClientRect();
|
||||
const isVisible = rect.top >= 0 && rect.top < viewportHeight;
|
||||
|
||||
if (isVisible) {
|
||||
return { item, rect };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move focus to the column of the passed index (1-based).
|
||||
* Can either focus the topmost item or the first one in the viewport
|
||||
* Focus is placed on the topmost visible item
|
||||
*/
|
||||
export function focusColumn({
|
||||
index = 1,
|
||||
focusItem = 'first',
|
||||
}: FocusColumnOptions = {}) {
|
||||
export function focusColumn(index = 1) {
|
||||
// Skip the leftmost drawer in multi-column mode
|
||||
const isMultiColumnLayout = !!document.querySelector(
|
||||
'body.layout-multiple-columns',
|
||||
@@ -27,33 +41,28 @@ export function focusColumn({
|
||||
|
||||
if (!container) return;
|
||||
|
||||
let itemToFocus: HTMLElement | null = null;
|
||||
const focusableItems = Array.from(
|
||||
container.querySelectorAll<HTMLElement>(
|
||||
'.focusable:not(.status__quote .focusable)',
|
||||
),
|
||||
);
|
||||
|
||||
if (focusItem === 'first-visible') {
|
||||
const focusableItems = Array.from(
|
||||
container.querySelectorAll<HTMLElement>(
|
||||
'.focusable:not(.status__quote .focusable)',
|
||||
),
|
||||
);
|
||||
|
||||
const viewportHeight =
|
||||
window.innerHeight || document.documentElement.clientHeight;
|
||||
|
||||
// Find first item visible in the viewport
|
||||
itemToFocus =
|
||||
focusableItems.find((item) => {
|
||||
const { top } = item.getBoundingClientRect();
|
||||
return top >= 0 && top < viewportHeight;
|
||||
}) ?? null;
|
||||
} else {
|
||||
itemToFocus = container.querySelector('.focusable');
|
||||
}
|
||||
// Find first item visible in the viewport
|
||||
const itemToFocus = findFirstVisibleWithRect(focusableItems);
|
||||
|
||||
if (itemToFocus) {
|
||||
if (container.scrollTop > itemToFocus.offsetTop) {
|
||||
itemToFocus.scrollIntoView(true);
|
||||
const viewportWidth =
|
||||
window.innerWidth || document.documentElement.clientWidth;
|
||||
const { item, rect } = itemToFocus;
|
||||
|
||||
if (
|
||||
container.scrollTop > item.offsetTop ||
|
||||
rect.right > viewportWidth ||
|
||||
rect.left < 0
|
||||
) {
|
||||
itemToFocus.item.scrollIntoView(true);
|
||||
}
|
||||
itemToFocus.focus();
|
||||
itemToFocus.item.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +80,26 @@ export function getFocusedItemIndex() {
|
||||
return items.indexOf(focusedItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the topmost item of the column that currently has focus,
|
||||
* or the first column if none
|
||||
*/
|
||||
export function focusFirstItem() {
|
||||
const focusedElement = document.activeElement;
|
||||
const container =
|
||||
focusedElement?.closest('.scrollable') ??
|
||||
document.querySelector('.scrollable');
|
||||
|
||||
if (!container) return;
|
||||
|
||||
const itemToFocus = container.querySelector<HTMLElement>('.focusable');
|
||||
|
||||
if (itemToFocus) {
|
||||
container.scrollTo(0, 0);
|
||||
itemToFocus.focus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the item next to the one with the provided index
|
||||
*/
|
||||
|
||||
@@ -516,6 +516,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Паказаць/схаваць тэкст за папярэджаннем пра кантэнт",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Паказаць/схаваць медыя",
|
||||
"keyboard_shortcuts.toot": "Стварыць новы допіс",
|
||||
"keyboard_shortcuts.top": "Перайсці да вяршыні спіса",
|
||||
"keyboard_shortcuts.translate": "каб перакласці допіс",
|
||||
"keyboard_shortcuts.unfocus": "Расфакусіраваць тэкставую вобласць/пошукавы радок",
|
||||
"keyboard_shortcuts.up": "Перамясціцца ўверх па спісе",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Beskriv dette for personer med nedsat syn…",
|
||||
"alt_text_modal.done": "Færdig",
|
||||
"announcement.announcement": "Bekendtgørelse",
|
||||
"annual_report.announcement.action_build": "Byg min Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Vis min Wrapstodon",
|
||||
"annual_report.announcement.description": "Få mere at vide om dit engagement på Mastodon i det forgangne år.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} er her",
|
||||
"annual_report.summary.archetype.booster": "Fremhæveren",
|
||||
"annual_report.summary.archetype.lurker": "Lureren",
|
||||
"annual_report.summary.archetype.oracle": "Oraklet",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Vis/skjul tekst bag indholdsadvarsel",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Vis/skjul medier",
|
||||
"keyboard_shortcuts.toot": "Påbegynd nyt indlæg",
|
||||
"keyboard_shortcuts.top": "Flyt til toppen af listen",
|
||||
"keyboard_shortcuts.translate": "for at oversætte et indlæg",
|
||||
"keyboard_shortcuts.unfocus": "Fjern fokus fra tekstskrivningsområde/søgning",
|
||||
"keyboard_shortcuts.up": "Flyt opad på listen",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"about.blocks": "Moderierte Server",
|
||||
"about.blocks": "Eingeschränkte Server",
|
||||
"about.contact": "Kontakt:",
|
||||
"about.default_locale": "Standard",
|
||||
"about.disclaimer": "Mastodon ist eine freie, quelloffene Software und eine Marke der Mastodon gGmbH.",
|
||||
"about.domain_blocks.no_reason_available": "Grund unbekannt",
|
||||
"about.domain_blocks.no_reason_available": "Keinen Grund angegeben",
|
||||
"about.domain_blocks.preamble": "Mastodon erlaubt es dir grundsätzlich, alle Inhalte von allen Nutzer*innen auf allen Servern im Fediverse zu sehen und mit ihnen zu interagieren. Für diesen Server gibt es aber ein paar Ausnahmen.",
|
||||
"about.domain_blocks.silenced.explanation": "Standardmäßig werden von diesem Server keine Inhalte oder Profile angezeigt. Du kannst die Profile und Inhalte aber dennoch sehen, wenn du explizit nach diesen suchst oder diesen folgst.",
|
||||
"about.domain_blocks.silenced.title": "Ausgeblendet",
|
||||
"about.domain_blocks.suspended.explanation": "Es werden keine Daten von diesem Server verarbeitet, gespeichert oder ausgetauscht, sodass eine Interaktion oder Kommunikation mit Nutzer*innen dieses Servers nicht möglich ist.",
|
||||
"about.domain_blocks.silenced.title": "Stummgeschaltet",
|
||||
"about.domain_blocks.suspended.explanation": "Es werden keine Daten von diesem Server verarbeitet, gespeichert oder ausgetauscht, sodass eine Interaktion oder Kommunikation mit Profilen dieses Servers nicht möglich ist.",
|
||||
"about.domain_blocks.suspended.title": "Gesperrt",
|
||||
"about.language_label": "Sprache",
|
||||
"about.not_available": "Diese Informationen sind auf diesem Server nicht verfügbar.",
|
||||
@@ -15,21 +15,21 @@
|
||||
"about.rules": "Serverregeln",
|
||||
"account.account_note_header": "Persönliche Notiz",
|
||||
"account.add_or_remove_from_list": "Hinzufügen oder Entfernen von Listen",
|
||||
"account.badges.bot": "Automatisiert",
|
||||
"account.badges.bot": "Bot",
|
||||
"account.badges.group": "Gruppe",
|
||||
"account.block": "@{name} blockieren",
|
||||
"account.block_domain": "{domain} sperren",
|
||||
"account.block_domain": "{domain} blockieren",
|
||||
"account.block_short": "Blockieren",
|
||||
"account.blocked": "Blockiert",
|
||||
"account.blocking": "Blockiert",
|
||||
"account.cancel_follow_request": "Follower-Anfrage zurückziehen",
|
||||
"account.cancel_follow_request": "Anfrage zurückziehen",
|
||||
"account.copy": "Link zum Profil kopieren",
|
||||
"account.direct": "@{name} privat erwähnen",
|
||||
"account.disable_notifications": "Höre auf mich zu benachrichtigen wenn @{name} etwas postet",
|
||||
"account.disable_notifications": "Benachrichtige mich nicht mehr, wenn @{name} etwas veröffentlicht",
|
||||
"account.domain_blocking": "Domain blockiert",
|
||||
"account.edit_profile": "Profil bearbeiten",
|
||||
"account.edit_profile_short": "Bearbeiten",
|
||||
"account.enable_notifications": "Benachrichtige mich wenn @{name} etwas postet",
|
||||
"account.enable_notifications": "Benachrichtige mich, wenn @{name} etwas veröffentlicht",
|
||||
"account.endorse": "Im Profil vorstellen",
|
||||
"account.familiar_followers_many": "Gefolgt von {name1}, {name2} und {othersCount, plural, one {einem weiteren Profil, das dir bekannt ist} other {# weiteren Profilen, die dir bekannt sind}}",
|
||||
"account.familiar_followers_one": "Gefolgt von {name1}",
|
||||
@@ -41,9 +41,9 @@
|
||||
"account.featured_tags.last_status_never": "Keine Beiträge",
|
||||
"account.follow": "Folgen",
|
||||
"account.follow_back": "Ebenfalls folgen",
|
||||
"account.follow_back_short": "Ebenfalls folgen",
|
||||
"account.follow_back_short": "Zurückfolgen",
|
||||
"account.follow_request": "Anfrage zum Folgen",
|
||||
"account.follow_request_cancel": "Anfrage abbrechen",
|
||||
"account.follow_request_cancel": "Anfrage zurückziehen",
|
||||
"account.follow_request_cancel_short": "Abbrechen",
|
||||
"account.follow_request_short": "Anfragen",
|
||||
"account.followers": "Follower",
|
||||
@@ -58,8 +58,8 @@
|
||||
"account.hide_reblogs": "Geteilte Beiträge von @{name} ausblenden",
|
||||
"account.in_memoriam": "Zum Andenken.",
|
||||
"account.joined_short": "Mitglied seit",
|
||||
"account.languages": "Sprache ändern.",
|
||||
"account.link_verified_on": "Das Profil mit dieser E-Mail-Adresse wurde bereits am {date} verifiziert",
|
||||
"account.languages": "Ausgewählte Sprachen ändern",
|
||||
"account.link_verified_on": "Das Profil mit dieser E-Mail-Adresse wurde bereits am {date} bestätigt",
|
||||
"account.locked_info": "Die Privatsphäre dieses Kontos wurde auf „geschützt“ gesetzt. Die Person bestimmt manuell, wer ihrem Profil folgen darf.",
|
||||
"account.media": "Medien",
|
||||
"account.mention": "@{name} erwähnen",
|
||||
@@ -73,7 +73,7 @@
|
||||
"account.no_bio": "Keine Beschreibung verfügbar.",
|
||||
"account.open_original_page": "Ursprüngliche Seite öffnen",
|
||||
"account.posts": "Beiträge",
|
||||
"account.posts_with_replies": "Beiträge und Antworten",
|
||||
"account.posts_with_replies": "Beiträge & Antworten",
|
||||
"account.remove_from_followers": "{name} als Follower entfernen",
|
||||
"account.report": "@{name} melden",
|
||||
"account.requested_follow": "{name} möchte dir folgen",
|
||||
@@ -81,9 +81,9 @@
|
||||
"account.share": "Profil von @{name} teilen",
|
||||
"account.show_reblogs": "Geteilte Beiträge von @{name} anzeigen",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} Beitrag} other {{counter} Beiträge}}",
|
||||
"account.unblock": "{name} nicht mehr blockieren",
|
||||
"account.unblock": "Blockierung von {name} aufheben",
|
||||
"account.unblock_domain": "Blockierung von {domain} aufheben",
|
||||
"account.unblock_domain_short": "Entsperren",
|
||||
"account.unblock_domain_short": "Blockierung aufheben",
|
||||
"account.unblock_short": "Blockierung aufheben",
|
||||
"account.unendorse": "Im Profil nicht mehr vorstellen",
|
||||
"account.unfollow": "Entfolgen",
|
||||
@@ -103,21 +103,25 @@
|
||||
"alert.rate_limited.message": "Bitte versuche es nach {retry_time, time, medium} erneut.",
|
||||
"alert.rate_limited.title": "Anfragelimit überschritten",
|
||||
"alert.unexpected.message": "Ein unerwarteter Fehler ist aufgetreten.",
|
||||
"alert.unexpected.title": "Oha!",
|
||||
"alert.unexpected.title": "Ups!",
|
||||
"alt_text_badge.title": "Bildbeschreibung",
|
||||
"alt_text_modal.add_alt_text": "Bildbeschreibung hinzufügen",
|
||||
"alt_text_modal.add_text_from_image": "Text aus Bild hinzufügen",
|
||||
"alt_text_modal.cancel": "Abbrechen",
|
||||
"alt_text_modal.change_thumbnail": "Vorschaubild ändern",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Beschreibe den Inhalt für Menschen mit Schwerhörigkeit …",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Beschreibe den Inhalt für Menschen, die taub oder hörbehindert sind …",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Beschreibe den Inhalt für Menschen, die blind oder sehbehindert sind …",
|
||||
"alt_text_modal.done": "Fertig",
|
||||
"announcement.announcement": "Ankündigung",
|
||||
"annual_report.announcement.action_build": "Erstelle mein Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Mein Wrapstodon anschauen",
|
||||
"annual_report.announcement.description": "Erfahre mehr über deine Aktivitäten auf Mastodon im vergangenen Jahr.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} ist fertiggestellt",
|
||||
"annual_report.summary.archetype.booster": "Trendjäger*in",
|
||||
"annual_report.summary.archetype.lurker": "Beobachter*in",
|
||||
"annual_report.summary.archetype.oracle": "Universaltalent",
|
||||
"annual_report.summary.archetype.pollster": "Meinungsforscher*in",
|
||||
"annual_report.summary.archetype.replier": "Sozialer Schmetterling",
|
||||
"annual_report.summary.archetype.replier": "Gesellige*r",
|
||||
"annual_report.summary.followers.followers": "Follower",
|
||||
"annual_report.summary.followers.total": "{count} insgesamt",
|
||||
"annual_report.summary.here_it_is": "Dein Jahresrückblick für {year}:",
|
||||
@@ -148,7 +152,7 @@
|
||||
"bundle_column_error.copy_stacktrace": "Fehlerbericht kopieren",
|
||||
"bundle_column_error.error.body": "Die angeforderte Seite konnte nicht dargestellt werden. Dies könnte auf einen Fehler in unserem Code oder auf ein Browser-Kompatibilitätsproblem zurückzuführen sein.",
|
||||
"bundle_column_error.error.title": "Oh nein!",
|
||||
"bundle_column_error.network.body": "Beim Versuch, diese Seite zu laden, ist ein Fehler aufgetreten. Dies könnte auf ein vorübergehendes Problem mit Ihrer Internetverbindung oder diesem Server zurückzuführen sein.",
|
||||
"bundle_column_error.network.body": "Beim Versuch, diese Seite zu laden, ist ein Fehler aufgetreten. Dies könnte auf ein vorübergehendes Problem mit deiner Internetverbindung oder diesem Server zurückzuführen sein.",
|
||||
"bundle_column_error.network.title": "Netzwerkfehler",
|
||||
"bundle_column_error.retry": "Erneut versuchen",
|
||||
"bundle_column_error.return": "Zurück zur Startseite",
|
||||
@@ -160,9 +164,9 @@
|
||||
"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_modal.description": "Das Anlegen eines Kontos auf {domain} ist derzeit nicht möglich, aber bedenke, dass du kein extra Konto auf {domain} benötigst, um Mastodon nutzen zu können.",
|
||||
"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.preamble": "Mastodon ist dezentralisiert, das heißt, unabhängig davon, wo du dein Konto erstellt hast, kannst du jedem Profil auf diesem Server folgen und mit ihm interagieren. Du kannst sogar deinen eigenen Server hosten!",
|
||||
"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",
|
||||
"column.blocks": "Blockierte Profile",
|
||||
@@ -175,7 +179,7 @@
|
||||
"column.edit_list": "Liste bearbeiten",
|
||||
"column.favourites": "Favoriten",
|
||||
"column.firehose": "Live-Feeds",
|
||||
"column.firehose_local": "Live-Feed für diesen Server",
|
||||
"column.firehose_local": "Live-Feed dieses Servers",
|
||||
"column.firehose_singular": "Live-Feed",
|
||||
"column.follow_requests": "Follower-Anfragen",
|
||||
"column.home": "Startseite",
|
||||
@@ -203,7 +207,7 @@
|
||||
"compose.published.open": "Öffnen",
|
||||
"compose.saved.body": "Beitrag gespeichert.",
|
||||
"compose_form.direct_message_warning_learn_more": "Mehr erfahren",
|
||||
"compose_form.encryption_warning": "Beiträge auf Mastodon sind nicht Ende-zu-Ende-verschlüsselt. Teile keine sensiblen Informationen über Mastodon.",
|
||||
"compose_form.encryption_warning": "Beiträge auf Mastodon sind nicht Ende-zu-Ende-verschlüsselt. Teile keine sensiblen Informationen über Mastodon, auch nicht als „private Erwähnung“.",
|
||||
"compose_form.hashtag_warning": "Dieser Beitrag wird unter keinem Hashtag sichtbar sein, weil er nicht öffentlich ist. Nur öffentliche Beiträge können nach Hashtags durchsucht werden.",
|
||||
"compose_form.lock_disclaimer": "Dein Profil ist nicht {locked}. Andere können dir folgen und deine Beiträge sehen, die nur für Follower bestimmt sind.",
|
||||
"compose_form.lock_disclaimer.lock": "geschützt",
|
||||
@@ -267,8 +271,8 @@
|
||||
"confirmations.revoke_quote.confirm": "Zitat entfernen",
|
||||
"confirmations.revoke_quote.message": "Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"confirmations.revoke_quote.title": "Zitieren meines Beitrags entfernen?",
|
||||
"confirmations.unblock.confirm": "Nicht mehr blockieren",
|
||||
"confirmations.unblock.title": "{name} nicht mehr blockieren?",
|
||||
"confirmations.unblock.confirm": "Blockierung aufheben",
|
||||
"confirmations.unblock.title": "Blockierung von {name} aufheben?",
|
||||
"confirmations.unfollow.confirm": "Entfolgen",
|
||||
"confirmations.unfollow.title": "{name} entfolgen?",
|
||||
"confirmations.withdraw_request.confirm": "Anfrage zurückziehen",
|
||||
@@ -336,7 +340,7 @@
|
||||
"empty_column.account_featured.other": "{acct} hat bisher noch nichts vorgestellt. Wusstest du, dass du deine häufig verwendeten Hashtags und sogar Profile von Freund*innen vorstellen kannst?",
|
||||
"empty_column.account_featured_other.unknown": "Dieses Profil hat bisher noch nichts vorgestellt.",
|
||||
"empty_column.account_hides_collections": "Das Konto hat sich dazu entschieden, diese Information nicht zu veröffentlichen",
|
||||
"empty_column.account_suspended": "Konto gesperrt",
|
||||
"empty_column.account_suspended": "Konto dauerhaft gesperrt",
|
||||
"empty_column.account_timeline": "Keine Beiträge vorhanden!",
|
||||
"empty_column.account_unavailable": "Profil nicht verfügbar",
|
||||
"empty_column.blocks": "Du hast bisher keine Profile blockiert.",
|
||||
@@ -349,14 +353,14 @@
|
||||
"empty_column.favourited_statuses": "Du hast noch keine Beiträge favorisiert. Sobald du einen favorisierst, wird er hier erscheinen.",
|
||||
"empty_column.favourites": "Diesen Beitrag hat bisher noch niemand favorisiert. Sobald es jemand tut, wird das Profil hier erscheinen.",
|
||||
"empty_column.follow_requests": "Es liegen derzeit keine Follower-Anfragen vor. Sobald du eine erhältst, wird sie hier erscheinen.",
|
||||
"empty_column.followed_tags": "Du folgst noch keinen Hashtags. Wenn du dies tust, werden sie hier erscheinen.",
|
||||
"empty_column.followed_tags": "Du folgst noch keinen Hashtags. Sobald du Hashtags abonniert hast, werden sie hier angezeigt.",
|
||||
"empty_column.hashtag": "Unter diesem Hashtag gibt es noch nichts.",
|
||||
"empty_column.home": "Die Timeline deiner Startseite ist leer! Folge mehr Leuten, um sie zu füllen.",
|
||||
"empty_column.list": "Diese Liste ist derzeit leer. Wenn Konten auf dieser Liste neue Beiträge veröffentlichen, werden sie hier erscheinen.",
|
||||
"empty_column.mutes": "Du hast keine Profile stummgeschaltet.",
|
||||
"empty_column.notification_requests": "Alles klar! Hier gibt es nichts. Wenn Sie neue Mitteilungen erhalten, werden diese entsprechend Ihren Einstellungen hier angezeigt.",
|
||||
"empty_column.notifications": "Du hast noch keine Benachrichtigungen. Sobald andere Personen mit dir interagieren, wirst du hier darüber informiert.",
|
||||
"empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Profilen von anderen Servern, um die Timeline aufzufüllen",
|
||||
"empty_column.public": "Hier ist nichts zu sehen! Schreibe einen öffentlichen Beitrag oder folge Profilen von anderen Servern im Fediverse, um die Timeline zu füllen",
|
||||
"error.no_hashtag_feed_access": "Registriere dich oder melde dich an, um den Hashtag anzusehen und ihm zu folgen.",
|
||||
"error.unexpected_crash.explanation": "Wegen eines Fehlers in unserem Code oder aufgrund einer Browser-Inkompatibilität kann diese Seite nicht korrekt angezeigt werden.",
|
||||
"error.unexpected_crash.explanation_addons": "Diese Seite konnte nicht korrekt angezeigt werden. Dieser Fehler wird wahrscheinlich durch ein Browser-Add-on oder automatische Übersetzungswerkzeuge verursacht.",
|
||||
@@ -388,7 +392,7 @@
|
||||
"filter_modal.select_filter.subtitle": "Einem vorhandenen Filter hinzufügen oder einen neuen erstellen",
|
||||
"filter_modal.select_filter.title": "Diesen Beitrag filtern",
|
||||
"filter_modal.title.status": "Beitrag per Filter ausblenden",
|
||||
"filter_warning.matches_filter": "Ausgeblendet wegen des Filters „<span>{title}</span>“",
|
||||
"filter_warning.matches_filter": "Ausgeblendet wegen deines Filters „<span>{title}</span>“",
|
||||
"filtered_notifications_banner.pending_requests": "Von {count, plural, =0 {keinem Profil, das dir möglicherweise bekannt ist} one {einem Profil, das dir möglicherweise bekannt ist} other {# Profilen, die dir möglicherweise bekannt sind}}",
|
||||
"filtered_notifications_banner.title": "Gefilterte Benachrichtigungen",
|
||||
"firehose.all": "Alle Server",
|
||||
@@ -412,7 +416,7 @@
|
||||
"follow_suggestions.similar_to_recently_followed_longer": "Ähnlich zu Profilen, denen du seit kurzem folgst",
|
||||
"follow_suggestions.view_all": "Alle anzeigen",
|
||||
"follow_suggestions.who_to_follow": "Empfohlene Profile",
|
||||
"followed_tags": "Gefolgte Hashtags",
|
||||
"followed_tags": "Abonnierte Hashtags",
|
||||
"footer.about": "Über",
|
||||
"footer.about_this_server": "Über",
|
||||
"footer.directory": "Profilverzeichnis",
|
||||
@@ -440,10 +444,10 @@
|
||||
"hashtag.counter_by_uses": "{count, plural, one {{counter} Beitrag} other {{counter} Beiträge}}",
|
||||
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} Beitrag} other {{counter} Beiträge}} heute",
|
||||
"hashtag.feature": "Im Profil vorstellen",
|
||||
"hashtag.follow": "Hashtag folgen",
|
||||
"hashtag.follow": "Abonnieren",
|
||||
"hashtag.mute": "#{hashtag} stummschalten",
|
||||
"hashtag.unfeature": "Im Profil nicht mehr vorstellen",
|
||||
"hashtag.unfollow": "Hashtag entfolgen",
|
||||
"hashtag.unfollow": "Abbestellen",
|
||||
"hashtags.and_other": "… und {count, plural, one{# weiterer} other {# weitere}}",
|
||||
"hints.profiles.followers_may_be_missing": "Möglicherweise werden für dieses Profil nicht alle Follower angezeigt.",
|
||||
"hints.profiles.follows_may_be_missing": "Möglicherweise werden für dieses Profil nicht alle gefolgten Profile angezeigt.",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Beitragstext hinter der Inhaltswarnung anzeigen/ausblenden",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Medien anzeigen/ausblenden",
|
||||
"keyboard_shortcuts.toot": "Neuen Beitrag erstellen",
|
||||
"keyboard_shortcuts.top": "Zum Listenanfang springen",
|
||||
"keyboard_shortcuts.translate": "Beitrag übersetzen",
|
||||
"keyboard_shortcuts.unfocus": "Eingabefeld/Suche nicht mehr fokussieren",
|
||||
"keyboard_shortcuts.up": "Ansicht nach oben bewegen",
|
||||
@@ -581,7 +586,7 @@
|
||||
"navigation_bar.favourites": "Favoriten",
|
||||
"navigation_bar.filters": "Stummgeschaltete Wörter",
|
||||
"navigation_bar.follow_requests": "Follower-Anfragen",
|
||||
"navigation_bar.followed_tags": "Gefolgte Hashtags",
|
||||
"navigation_bar.followed_tags": "Abonnierte Hashtags",
|
||||
"navigation_bar.follows_and_followers": "Follower und Folge ich",
|
||||
"navigation_bar.import_export": "Importieren und exportieren",
|
||||
"navigation_bar.lists": "Listen",
|
||||
@@ -596,9 +601,9 @@
|
||||
"navigation_bar.privacy_and_reach": "Datenschutz und Reichweite",
|
||||
"navigation_bar.search": "Suche",
|
||||
"navigation_bar.search_trends": "Suche / Angesagt",
|
||||
"navigation_panel.collapse_followed_tags": "Menü für gefolgte Hashtags schließen",
|
||||
"navigation_panel.collapse_followed_tags": "Menü für abonnierte Hashtags schließen",
|
||||
"navigation_panel.collapse_lists": "Listen-Menü schließen",
|
||||
"navigation_panel.expand_followed_tags": "Menü für gefolgte Hashtags öffnen",
|
||||
"navigation_panel.expand_followed_tags": "Menü für abonnierte Hashtags öffnen",
|
||||
"navigation_panel.expand_lists": "Listen-Menü öffnen",
|
||||
"not_signed_in_indicator.not_signed_in": "Du musst dich anmelden, um auf diesen Inhalt zugreifen zu können.",
|
||||
"notification.admin.report": "{name} meldete {target}",
|
||||
@@ -849,7 +854,7 @@
|
||||
"search.quick_action.go_to_hashtag": "Hashtag {x} aufrufen",
|
||||
"search.quick_action.open_url": "URL in Mastodon öffnen",
|
||||
"search.quick_action.status_search": "Beiträge passend zu {x}",
|
||||
"search.search_or_paste": "Suchen oder URL einfügen",
|
||||
"search.search_or_paste": "Suche eingeben oder URL einfügen",
|
||||
"search_popout.full_text_search_disabled_message": "Auf {domain} nicht verfügbar.",
|
||||
"search_popout.full_text_search_logged_out_message": "Nur verfügbar, wenn angemeldet.",
|
||||
"search_popout.language_code": "ISO-Sprachcode",
|
||||
@@ -1003,7 +1008,7 @@
|
||||
"upload_form.drag_and_drop.on_drag_start": "Der Medienanhang {item} wurde aufgenommen.",
|
||||
"upload_form.edit": "Bearbeiten",
|
||||
"upload_progress.label": "Wird hochgeladen …",
|
||||
"upload_progress.processing": "Wird verarbeitet…",
|
||||
"upload_progress.processing": "Wird verarbeitet …",
|
||||
"username.taken": "Dieser Profilname ist vergeben. Versuche einen anderen",
|
||||
"video.close": "Video schließen",
|
||||
"video.download": "Datei herunterladen",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Περιέγραψε αυτό για άτομα με προβλήματα όρασης…",
|
||||
"alt_text_modal.done": "Ολοκληρώθηκε",
|
||||
"announcement.announcement": "Ανακοίνωση",
|
||||
"annual_report.announcement.action_build": "Φτιάξε το Wrapstodon μου",
|
||||
"annual_report.announcement.action_view": "Προβολή του Wrapstodon μου",
|
||||
"annual_report.announcement.description": "Ανακαλύψτε περισσότερα για την αλληλεπίδραση σας στο Mastodon κατά τη διάρκεια του περασμένου έτους.",
|
||||
"annual_report.announcement.title": "Το Wrapstodon του {year} έφτασε",
|
||||
"annual_report.summary.archetype.booster": "Ο κυνηγός των φοβερών",
|
||||
"annual_report.summary.archetype.lurker": "Ο διακριτικός",
|
||||
"annual_report.summary.archetype.oracle": "Η Πυθία",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Εμφάνιση/απόκρυψη κειμένου πίσω από το CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Εμφάνιση/απόκρυψη πολυμέσων",
|
||||
"keyboard_shortcuts.toot": "Δημιουργία νέας ανάρτησης",
|
||||
"keyboard_shortcuts.top": "Μετακίνηση στην κορυφή της λίστας",
|
||||
"keyboard_shortcuts.translate": "για να μεταφραστεί μια ανάρτηση",
|
||||
"keyboard_shortcuts.unfocus": "Αποεστίαση του πεδίου σύνθεσης/αναζήτησης",
|
||||
"keyboard_shortcuts.up": "Μετακίνηση προς τα πάνω στη λίστα",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Describe this for people with visual impairments…",
|
||||
"alt_text_modal.done": "Done",
|
||||
"announcement.announcement": "Announcement",
|
||||
"annual_report.announcement.action_build": "Build my Wrapstodon",
|
||||
"annual_report.announcement.action_view": "View my Wrapstodon",
|
||||
"annual_report.announcement.description": "Discover more about your engagement on Mastodon over the past year.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} has arrived",
|
||||
"annual_report.summary.archetype.booster": "The cool-hunter",
|
||||
"annual_report.summary.archetype.lurker": "The lurker",
|
||||
"annual_report.summary.archetype.oracle": "The oracle",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Show/hide media",
|
||||
"keyboard_shortcuts.toot": "to start a brand new post",
|
||||
"keyboard_shortcuts.top": "Move to top of list",
|
||||
"keyboard_shortcuts.translate": "to translate a post",
|
||||
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
|
||||
"keyboard_shortcuts.up": "Move up in the list",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Describe this for people with visual impairments…",
|
||||
"alt_text_modal.done": "Done",
|
||||
"announcement.announcement": "Announcement",
|
||||
"annual_report.announcement.action_build": "Build my Wrapstodon",
|
||||
"annual_report.announcement.action_view": "View my Wrapstodon",
|
||||
"annual_report.announcement.description": "Discover more about your engagement on Mastodon over the past year.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} has arrived",
|
||||
"annual_report.summary.archetype.booster": "The cool-hunter",
|
||||
"annual_report.summary.archetype.lurker": "The lurker",
|
||||
"annual_report.summary.archetype.oracle": "The oracle",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Show/hide text behind CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Show/hide media",
|
||||
"keyboard_shortcuts.toot": "Start a new post",
|
||||
"keyboard_shortcuts.top": "Move to top of list",
|
||||
"keyboard_shortcuts.translate": "to translate a post",
|
||||
"keyboard_shortcuts.unfocus": "Unfocus compose textarea/search",
|
||||
"keyboard_shortcuts.up": "Move up in the list",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Describí esto para personas con dificultades visuales…",
|
||||
"alt_text_modal.done": "Listo",
|
||||
"announcement.announcement": "Anuncio",
|
||||
"annual_report.announcement.action_build": "Construir mi MastodonAnual",
|
||||
"annual_report.announcement.action_view": "Ver mi MastodonAnual",
|
||||
"annual_report.announcement.description": "Descubrí más sobre tu participación en Mastodon durante el último año.",
|
||||
"annual_report.announcement.title": "Llegó MastodonAnual {year}",
|
||||
"annual_report.summary.archetype.booster": "Corrió la voz",
|
||||
"annual_report.summary.archetype.lurker": "El acechador",
|
||||
"annual_report.summary.archetype.oracle": "El oráculo",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Mostrar/ocultar texto detrás de la advertencia de contenido (\"CW\")",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Mostrar/ocultar medios",
|
||||
"keyboard_shortcuts.toot": "Comenzar un mensaje nuevo",
|
||||
"keyboard_shortcuts.top": "Mover al principio de la lista",
|
||||
"keyboard_shortcuts.translate": "para traducir un mensaje",
|
||||
"keyboard_shortcuts.unfocus": "Quitar el foco del área de texto de redacción o de búsqueda",
|
||||
"keyboard_shortcuts.up": "Subir en la lista",
|
||||
|
||||
@@ -113,6 +113,9 @@
|
||||
"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_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",
|
||||
"annual_report.summary.archetype.booster": "El cazador de tendencias",
|
||||
"annual_report.summary.archetype.lurker": "El merodeador",
|
||||
"annual_report.summary.archetype.oracle": "El oráculo",
|
||||
@@ -516,6 +519,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Mostrar/ocultar texto detrás de AC",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Mostrar/ocultar multimedia",
|
||||
"keyboard_shortcuts.toot": "Comenzar una nueva publicación",
|
||||
"keyboard_shortcuts.top": "Mover al principio de la lista",
|
||||
"keyboard_shortcuts.translate": "para traducir una publicación",
|
||||
"keyboard_shortcuts.unfocus": "Desenfocar área de redacción/búsqueda",
|
||||
"keyboard_shortcuts.up": "Ascender en la lista",
|
||||
|
||||
@@ -113,6 +113,9 @@
|
||||
"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_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",
|
||||
"annual_report.summary.archetype.booster": "El cazador de tendencias",
|
||||
"annual_report.summary.archetype.lurker": "El acechador",
|
||||
"annual_report.summary.archetype.oracle": "El oráculo",
|
||||
@@ -516,6 +519,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Mostrar/ocultar texto tras aviso de contenido (CW)",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Mostrar/ocultar multimedia",
|
||||
"keyboard_shortcuts.toot": "Comenzar una nueva publicación",
|
||||
"keyboard_shortcuts.top": "Mover al principio de la lista",
|
||||
"keyboard_shortcuts.translate": "para traducir una publicación",
|
||||
"keyboard_shortcuts.unfocus": "Quitar el foco de la caja de redacción/búsqueda",
|
||||
"keyboard_shortcuts.up": "Moverse hacia arriba en la lista",
|
||||
|
||||
@@ -516,6 +516,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Näita/peida teksti hoiatuse taga",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Näita/peida meediat",
|
||||
"keyboard_shortcuts.toot": "Alusta uut postitust",
|
||||
"keyboard_shortcuts.top": "Tõsta loendi algusesse",
|
||||
"keyboard_shortcuts.translate": "postituse tõlkimiseks",
|
||||
"keyboard_shortcuts.unfocus": "Fookus tekstialalt/otsingult ära",
|
||||
"keyboard_shortcuts.up": "Liigu loetelus üles",
|
||||
|
||||
@@ -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": "کشف بیشتر دربارهٔ درگیریتان روی ماستودون در سال گذشته.",
|
||||
"annual_report.announcement.title": "خلاصهٔ ماستودون {year} اینجاست",
|
||||
"annual_report.summary.archetype.booster": "باحالیاب",
|
||||
"annual_report.summary.archetype.lurker": "کمپیدا",
|
||||
"annual_report.summary.archetype.oracle": "غیبگو",
|
||||
@@ -357,6 +361,7 @@
|
||||
"empty_column.notification_requests": "همه چیز تمیز است! هیچچیزی اینجا نیست. هنگامی که آگاهیهای جدیدی دریافت کنید، بسته به تنظیماتتان اینجا ظاهر خواهند شد.",
|
||||
"empty_column.notifications": "هنوز هیچ آگاهیای ندارید. هنگامی که دیگران با شما برهمکنش داشته باشند، اینجا خواهید دیدش.",
|
||||
"empty_column.public": "اینجا هنوز چیزی نیست! خودتان چیزی بنویسید یا کاربران کارسازهای دیگر را پیگیری کنید تا اینجا پُر شود",
|
||||
"error.no_hashtag_feed_access": "پیوستن یا ورود برای مشاهده و پیگیری این برچسب.",
|
||||
"error.unexpected_crash.explanation": "به خاطر اشکالی در کدهای ما یا ناسازگاری با مرورگر شما، این صفحه به درستی نمایش نیافت.",
|
||||
"error.unexpected_crash.explanation_addons": "این صفحه نمیتواند درست نشان داده شود. احتمالاً این خطا ناشی از یک افزونهٔ مرورگر یا ابزار ترجمهٔ خودکار است.",
|
||||
"error.unexpected_crash.next_steps": "لطفاً صفحه را دوباره باز کنید. اگر کمکی نکرد، شاید همچنان بتوانید با ماستودون از راه یک مرورگر دیگر یا با یکی از کارههای آن کار کنید.",
|
||||
@@ -515,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "نمایش/نهفتن نوشتهٔ پشت هشدار محتوا",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "نمایش/نهفتن رسانه",
|
||||
"keyboard_shortcuts.toot": "شروع یک فرستهٔ جدید",
|
||||
"keyboard_shortcuts.top": "جابهجایی به بالای سیاهه",
|
||||
"keyboard_shortcuts.translate": "برای ترجمه یک پست",
|
||||
"keyboard_shortcuts.unfocus": "برداشتن تمرکز از ناحیهٔ نوشتن یا جستوجو",
|
||||
"keyboard_shortcuts.up": "بالا بردن در سیاهه",
|
||||
@@ -607,8 +613,8 @@
|
||||
"notification.admin.report_statuses_other": "{name}، {target} را گزارش داد",
|
||||
"notification.admin.sign_up": "{name} ثبت نام کرد",
|
||||
"notification.admin.sign_up.name_and_others": "{name} و {count, plural, one {# نفر دیگر} other {# نفر دیگر}} ثبتنام کردند",
|
||||
"notification.annual_report.message": "آمار #Wrapstodon {year} تان منتظر است! لحظههای به یاد ماندنی و نقاط پررنگ سال را روی ماستودون رونمایی کنید!",
|
||||
"notification.annual_report.view": "دیدن #Wrapstodon",
|
||||
"notification.annual_report.message": "#خلاصه_ماستودون {year} منتظرتان است! رونمایی از لحظههای به یاد ماندنی و نقاط پررنگ سال روی ماستودون!",
|
||||
"notification.annual_report.view": "دیدن #خلاصه_ماستودون",
|
||||
"notification.favourite": "{name} فرستهتان را برگزید",
|
||||
"notification.favourite.name_and_others_with_link": "{name} و <a>{count, plural, one {# نفر دیگر} other {# نفر دیگر}}</a> فرستهتان را برگزیدند",
|
||||
"notification.favourite_pm": "{name} اشارهٔ خصوصیتان را برگزید",
|
||||
@@ -903,6 +909,7 @@
|
||||
"status.edited_x_times": "{count, plural, one {{count} مرتبه} other {{count} مرتبه}} ویرایش شد",
|
||||
"status.embed": "گرفتن کد تعبیه",
|
||||
"status.favourite": "برگزیده",
|
||||
"status.favourites_count": "{count, plural, one {{counter} برگزیدن} other {{counter} برگزیدن}}",
|
||||
"status.filter": "پالایش این فرسته",
|
||||
"status.history.created": "توسط {name} در {date} ایجاد شد",
|
||||
"status.history.edited": "توسط {name} در {date} ویرایش شد",
|
||||
@@ -937,12 +944,14 @@
|
||||
"status.quotes.empty": "هنوز کسی این فرسته را نقل نکرده. وقتی کسی چنین کند اینجا نشان داده خواهد شد.",
|
||||
"status.quotes.local_other_disclaimer": "نقلهایی که به دست نگارنده رد شده باشند نشان داده نخواهند شد.",
|
||||
"status.quotes.remote_other_disclaimer": "تنها نقلها از {domain} تضمین نمایش در اینجا را دارند. نقلهای رد شده به دست نگاره نشان داده نخواهند شد.",
|
||||
"status.quotes_count": "{count, plural, one {{counter} نقل} other {{counter} نقل}}",
|
||||
"status.read_more": "بیشتر بخوانید",
|
||||
"status.reblog": "تقویت",
|
||||
"status.reblog_or_quote": "نقل یا تقویت",
|
||||
"status.reblog_private": "همرسانی دوباره با پیگیرانتان",
|
||||
"status.reblogged_by": "{name} تقویت کرد",
|
||||
"status.reblogs.empty": "هنوز هیچ کسی این فرسته را تقویت نکرده است. وقتی کسی چنین کاری کند، اینجا نمایش داده خواهد شد.",
|
||||
"status.reblogs_count": "{count, plural, one {{counter} تقویت} other {{counter} تقویت}}",
|
||||
"status.redraft": "حذف و بازنویسی",
|
||||
"status.remove_bookmark": "برداشتن نشانک",
|
||||
"status.remove_favourite": "حذف از موارد دلخواه",
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
"account.requests_to_follow_you": "Pyynnöt seurata sinua",
|
||||
"account.share": "Jaa käyttäjän @{name} profiili",
|
||||
"account.show_reblogs": "Näytä käyttäjän @{name} tehostukset",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}",
|
||||
"account.unblock": "Kumoa käyttäjän @{name} esto",
|
||||
"account.unblock_domain": "Kumoa verkkotunnuksen {domain} esto",
|
||||
"account.unblock_domain_short": "Kumoa esto",
|
||||
@@ -100,7 +100,7 @@
|
||||
"admin.impact_report.instance_followers": "Seuraajat, jotka käyttäjämme menettäisivät",
|
||||
"admin.impact_report.instance_follows": "Seuraajat, jotka heidän käyttäjänsä menettäisivät",
|
||||
"admin.impact_report.title": "Vaikutusten yhteenveto",
|
||||
"alert.rate_limited.message": "Yritä uudelleen {retry_time, time, medium} jälkeen.",
|
||||
"alert.rate_limited.message": "Yritä uudelleen kello {retry_time, time, medium} jälkeen.",
|
||||
"alert.rate_limited.title": "Pyyntömäärää rajoitettu",
|
||||
"alert.unexpected.message": "Tapahtui odottamaton virhe.",
|
||||
"alert.unexpected.title": "Hups!",
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Kuvaile tätä näkövammallisille ihmisille…",
|
||||
"alt_text_modal.done": "Valmis",
|
||||
"announcement.announcement": "Tiedote",
|
||||
"annual_report.announcement.action_build": "Koosta oma Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Näytä oma Wrapstodon",
|
||||
"annual_report.announcement.description": "Tutustu toimintaasi Mastodonissa kuluneen vuoden aikana.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} on täällä",
|
||||
"annual_report.summary.archetype.booster": "Tehostaja",
|
||||
"annual_report.summary.archetype.lurker": "Lymyilijä",
|
||||
"annual_report.summary.archetype.oracle": "Oraakkeli",
|
||||
@@ -202,7 +206,7 @@
|
||||
"compose.published.body": "Julkaisu lähetetty.",
|
||||
"compose.published.open": "Avaa",
|
||||
"compose.saved.body": "Julkaisu tallennettu.",
|
||||
"compose_form.direct_message_warning_learn_more": "Lisätietoja",
|
||||
"compose_form.direct_message_warning_learn_more": "Lue lisää",
|
||||
"compose_form.encryption_warning": "Mastodonin julkaisut eivät ole päästä päähän salattuja. Älä jaa arkaluonteisia tietoja Mastodonissa.",
|
||||
"compose_form.hashtag_warning": "Tätä julkaisua ei voi liittää aihetunnisteisiin, koska se ei ole julkinen. Vain näkyvyydeltään julkisiksi määritettyjä julkaisuja voidaan hakea aihetunnisteiden avulla.",
|
||||
"compose_form.lock_disclaimer": "Tilisi ei ole {locked}. Kuka tahansa voi seurata tiliäsi ja nähdä vain seuraajille rajaamasi julkaisut.",
|
||||
@@ -298,7 +302,7 @@
|
||||
"domain_block_modal.they_cant_follow": "Kukaan tältä palvelimelta ei voi seurata sinua.",
|
||||
"domain_block_modal.they_wont_know": "Hän ei saa tietää tulleensa estetyksi.",
|
||||
"domain_block_modal.title": "Estetäänkö verkkotunnus?",
|
||||
"domain_block_modal.you_will_lose_num_followers": "Menetät {followersCount, plural, one {{followersCountDisplay} seuraajasi} other {{followersCountDisplay} seuraajaasi}} ja {followingCount, plural, one {{followingCountDisplay} seurattavasi} other {{followingCountDisplay} seurattavaasi}}.",
|
||||
"domain_block_modal.you_will_lose_num_followers": "Menetät {followersCount, plural, one {{followersCountDisplay}:n seuraajasi} other {{followersCountDisplay} seuraajaasi}} ja {followingCount, plural, one {{followingCountDisplay}:n seurattavasi} other {{followingCountDisplay} seurattavaasi}}.",
|
||||
"domain_block_modal.you_will_lose_relationships": "Menetät kaikki tämän palvelimen seuraajasi ja seurattavasi.",
|
||||
"domain_block_modal.you_wont_see_posts": "Et enää näe julkaisuja etkä ilmoituksia tämän palvelimen käyttäjiltä.",
|
||||
"domain_pill.activitypub_lets_connect": "Sen avulla voit muodostaa yhteyden ja olla vuorovaikutuksessa ihmisten kanssa, ei vain Mastodonissa vaan myös muissa sosiaalisissa sovelluksissa.",
|
||||
@@ -338,7 +342,7 @@
|
||||
"empty_column.account_hides_collections": "Käyttäjä on päättänyt pitää nämä tiedot yksityisinä",
|
||||
"empty_column.account_suspended": "Tili jäädytetty",
|
||||
"empty_column.account_timeline": "Ei julkaisuja täällä!",
|
||||
"empty_column.account_unavailable": "Profiilia ei ole saatavilla",
|
||||
"empty_column.account_unavailable": "Profiili ei saatavilla",
|
||||
"empty_column.blocks": "Et ole vielä estänyt käyttäjiä.",
|
||||
"empty_column.bookmarked_statuses": "Et ole vielä lisännyt julkaisuja kirjanmerkkeihisi. Kun lisäät yhden, se näkyy tässä.",
|
||||
"empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista, niin homma lähtee käyntiin!",
|
||||
@@ -436,15 +440,15 @@
|
||||
"hashtag.column_settings.tag_mode.any": "Mikä tahansa näistä",
|
||||
"hashtag.column_settings.tag_mode.none": "Ei mitään näistä",
|
||||
"hashtag.column_settings.tag_toggle": "Sisällytä lisätunnisteet tähän sarakkeeseen",
|
||||
"hashtag.counter_by_accounts": "{count, plural, one {{counter} osallistuja} other {{counter} osallistujaa}}",
|
||||
"hashtag.counter_by_uses": "{count, plural, one{{counter} julkaisu} other {{counter} julkaisua}}",
|
||||
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}} tänään",
|
||||
"hashtag.counter_by_accounts": "{count, plural, one {{counter} osallistuja} other {{counter} osallistujaa}}",
|
||||
"hashtag.counter_by_uses": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}",
|
||||
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}} tänään",
|
||||
"hashtag.feature": "Suosittele profiilissa",
|
||||
"hashtag.follow": "Seuraa aihetunnistetta",
|
||||
"hashtag.mute": "Mykistä #{hashtag}",
|
||||
"hashtag.unfeature": "Kumoa suosittelu profiilissa",
|
||||
"hashtag.unfollow": "Lopeta aihetunnisteen seuraaminen",
|
||||
"hashtags.and_other": "…ja {count, plural, other {# lisää}}",
|
||||
"hashtags.and_other": "…ja {count, plural, other {# lisää}}",
|
||||
"hints.profiles.followers_may_be_missing": "Tämän profiilin seuraajia saattaa puuttua.",
|
||||
"hints.profiles.follows_may_be_missing": "Tämän profiilin seurattavia saattaa puuttua.",
|
||||
"hints.profiles.posts_may_be_missing": "Tämän profiilin julkaisuja saattaa puuttua.",
|
||||
@@ -479,9 +483,9 @@
|
||||
"interaction_modal.on_this_server": "Tällä palvelimella",
|
||||
"interaction_modal.title": "Jatka kirjautumalla sisään",
|
||||
"interaction_modal.username_prompt": "Esim. {example}",
|
||||
"intervals.full.days": "{number, plural, one {# päivä} other {# päivää}}",
|
||||
"intervals.full.hours": "{number, plural, one {# tunti} other {# tuntia}}",
|
||||
"intervals.full.minutes": "{number, plural, one {# minuutti} other {# minuuttia}}",
|
||||
"intervals.full.days": "{number, plural, one {# päivä} other {# päivää}}",
|
||||
"intervals.full.hours": "{number, plural, one {# tunti} other {# tuntia}}",
|
||||
"intervals.full.minutes": "{number, plural, one {# minuutti} other {# minuuttia}}",
|
||||
"keyboard_shortcuts.back": "Siirry takaisin",
|
||||
"keyboard_shortcuts.blocked": "Avaa estettyjen käyttäjien luettelo",
|
||||
"keyboard_shortcuts.boost": "Tehosta julkaisua",
|
||||
@@ -498,7 +502,7 @@
|
||||
"keyboard_shortcuts.home": "Avaa kotiaikajana",
|
||||
"keyboard_shortcuts.hotkey": "Pikanäppäin",
|
||||
"keyboard_shortcuts.legend": "Näytä tämä ohje",
|
||||
"keyboard_shortcuts.load_more": "Kohdista ”Lataa lisää” -painikkeeseen",
|
||||
"keyboard_shortcuts.load_more": "Kohdista ”Lataa lisää” -painikkeeseen",
|
||||
"keyboard_shortcuts.local": "Avaa paikallinen aikajana",
|
||||
"keyboard_shortcuts.mention": "Mainitse tekijä",
|
||||
"keyboard_shortcuts.muted": "Avaa mykistettyjen käyttäjien luettelo",
|
||||
@@ -512,10 +516,11 @@
|
||||
"keyboard_shortcuts.requests": "Avaa seurantapyyntöjen luettelo",
|
||||
"keyboard_shortcuts.search": "Kohdista hakukenttään",
|
||||
"keyboard_shortcuts.spoilers": "Näytä tai piilota sisältövaroituskenttä",
|
||||
"keyboard_shortcuts.start": "Avaa Näin pääset alkuun -sarake",
|
||||
"keyboard_shortcuts.start": "Avaa ”Näin pääset alkuun” -sarake",
|
||||
"keyboard_shortcuts.toggle_hidden": "Näytä tai piilota sisältövaroituksella merkitty teksti",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Näytä tai piilota media",
|
||||
"keyboard_shortcuts.toot": "Luo uusi julkaisu",
|
||||
"keyboard_shortcuts.top": "Siirry luettelon alkuun",
|
||||
"keyboard_shortcuts.translate": "Käännä julkaisu",
|
||||
"keyboard_shortcuts.unfocus": "Poistu kirjoitus- tai hakukentästä",
|
||||
"keyboard_shortcuts.up": "Siirry luettelossa taaksepäin",
|
||||
@@ -530,7 +535,7 @@
|
||||
"limited_account_hint.title": "Palvelimen {domain} moderaattorit ovat piilottaneet tämän profiilin.",
|
||||
"link_preview.author": "Tehnyt {name}",
|
||||
"link_preview.more_from_author": "Lisää tekijältä {name}",
|
||||
"link_preview.shares": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}",
|
||||
"link_preview.shares": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}",
|
||||
"lists.add_member": "Lisää",
|
||||
"lists.add_to_list": "Lisää listaan",
|
||||
"lists.add_to_lists": "Lisää {name} listaan",
|
||||
@@ -543,7 +548,7 @@
|
||||
"lists.exclusive": "Piilota jäsenet kotisyötteestä",
|
||||
"lists.exclusive_hint": "Jos joku on tässä listassa, piilota hänet kotisyötteestäsi, jotta et näe hänen julkaisujaan kahteen kertaan.",
|
||||
"lists.find_users_to_add": "Etsi lisättäviä käyttäjiä",
|
||||
"lists.list_members_count": "{count, plural, one {# jäsen} other {# jäsentä}}",
|
||||
"lists.list_members_count": "{count, plural, one {# jäsen} other {# jäsentä}}",
|
||||
"lists.list_name": "Listan nimi",
|
||||
"lists.new_list_name": "Uuden listan nimi",
|
||||
"lists.no_lists_yet": "Ei vielä listoja.",
|
||||
@@ -556,7 +561,7 @@
|
||||
"lists.save": "Tallenna",
|
||||
"lists.search": "Haku",
|
||||
"lists.show_replies_to": "Sisällytä listan jäsenten vastaukset kohteeseen",
|
||||
"load_pending": "{count, plural, one {# uusi kohde} other {# uutta kohdetta}}",
|
||||
"load_pending": "{count, plural, one {# uusi kohde} other {# uutta kohdetta}}",
|
||||
"loading_indicator.label": "Ladataan…",
|
||||
"media_gallery.hide": "Piilota",
|
||||
"moved_to_account_banner.text": "Tilisi {disabledAccount} on tällä hetkellä poissa käytöstä, koska teit siirron tiliin {movedToAccount}.",
|
||||
@@ -615,7 +620,7 @@
|
||||
"notification.favourite_pm": "{name} lisäsi yksityismainintasi suosikkeihinsa",
|
||||
"notification.favourite_pm.name_and_others_with_link": "{name} ja <a>{count, plural, one {# muu} other {# muuta}}</a> lisäsivät yksityismainintasi suosikkeihinsa",
|
||||
"notification.follow": "{name} seurasi sinua",
|
||||
"notification.follow.name_and_others": "{name} ja <a>{count, plural, one {# muu} other {# muuta}}</a> seurasivat sinua",
|
||||
"notification.follow.name_and_others": "{name} ja <a>{count, plural, one {# muu} other {# muuta}}</a> seurasivat sinua",
|
||||
"notification.follow_request": "{name} on pyytänyt lupaa seurata sinua",
|
||||
"notification.follow_request.name_and_others": "{name} ja {count, plural, one {# muu} other {# muuta}} pyysivät saada seurata sinua",
|
||||
"notification.label.mention": "Maininta",
|
||||
@@ -638,7 +643,7 @@
|
||||
"notification.poll": "Äänestys, johon osallistuit, on päättynyt",
|
||||
"notification.quoted_update": "{name} muokkasi lainaamaasi julkaisua",
|
||||
"notification.reblog": "{name} tehosti julkaisuasi",
|
||||
"notification.reblog.name_and_others_with_link": "{name} ja <a>{count, plural, one {# muu} other {# muuta}}</a> tehostivat julkaisuasi",
|
||||
"notification.reblog.name_and_others_with_link": "{name} ja <a>{count, plural, one {# muu} other {# muuta}}</a> tehostivat julkaisuasi",
|
||||
"notification.relationships_severance_event": "Menetettiin yhteydet palvelimeen {name}",
|
||||
"notification.relationships_severance_event.account_suspension": "Palvelimen {from} ylläpitäjä on jäädyttänyt palvelimen {target} vuorovaikutuksen. Enää et voi siis vastaanottaa päivityksiä heiltä tai olla yhteyksissä heidän kanssaan.",
|
||||
"notification.relationships_severance_event.domain_block": "Palvelimen {from} ylläpitäjä on estänyt palvelimen {target} vuorovaikutuksen – mukaan lukien {followersCount} seuraajistasi ja {followingCount, plural, one {# seurattavistasi} other {# seurattavistasi}}.",
|
||||
@@ -647,7 +652,7 @@
|
||||
"notification.status": "{name} julkaisi juuri",
|
||||
"notification.update": "{name} muokkasi julkaisua",
|
||||
"notification_requests.accept": "Hyväksy",
|
||||
"notification_requests.accept_multiple": "{count, plural, one {Hyväksy # pyyntö…} other {Hyväksy # pyyntöä…}}",
|
||||
"notification_requests.accept_multiple": "{count, plural, one {Hyväksy # pyyntö…} other {Hyväksy # pyyntöä…}}",
|
||||
"notification_requests.confirm_accept_multiple.button": "{count, plural, one {Hyväksy pyyntö} other {Hyväksy pyynnöt}}",
|
||||
"notification_requests.confirm_accept_multiple.message": "Olet aikeissa hyväksyä {count, plural, one {ilmoituspyynnön} other {# ilmoituspyyntöä}}. Haluatko varmasti jatkaa?",
|
||||
"notification_requests.confirm_accept_multiple.title": "Hyväksytäänkö ilmoituspyynnöt?",
|
||||
@@ -711,7 +716,7 @@
|
||||
"notifications.policy.filter_limited_accounts_title": "Moderoidut tilit",
|
||||
"notifications.policy.filter_new_accounts.hint": "Luotu {days, plural, one {viime päivän} other {viimeisen # päivän}} aikana",
|
||||
"notifications.policy.filter_new_accounts_title": "Uudet tilit",
|
||||
"notifications.policy.filter_not_followers_hint": "Mukaan lukien alle {days, plural, one {päivän} other {# päivää}} sinua seuranneet",
|
||||
"notifications.policy.filter_not_followers_hint": "Mukaan lukien alle {days, plural, one {päivän} other {# päivää}} sinua seuranneet",
|
||||
"notifications.policy.filter_not_followers_title": "Käyttäjät, jotka eivät seuraa sinua",
|
||||
"notifications.policy.filter_not_following_hint": "Kunnes hyväksyt heidät manuaalisesti",
|
||||
"notifications.policy.filter_not_following_title": "Käyttäjät, joita et seuraa",
|
||||
@@ -742,11 +747,11 @@
|
||||
"poll.closed": "Päättynyt",
|
||||
"poll.refresh": "Päivitä",
|
||||
"poll.reveal": "Näytä tulokset",
|
||||
"poll.total_people": "{count, plural, one {# käyttäjä} other {# käyttäjää}}",
|
||||
"poll.total_votes": "{count, plural, one {# ääni} other {# ääntä}}",
|
||||
"poll.total_people": "{count, plural, one {# käyttäjä} other {# käyttäjää}}",
|
||||
"poll.total_votes": "{count, plural, one {# ääni} other {# ääntä}}",
|
||||
"poll.vote": "Äänestä",
|
||||
"poll.voted": "Äänestit tätä vastausta",
|
||||
"poll.votes": "{votes, plural, one {# ääni} other {# ääntä}}",
|
||||
"poll.votes": "{votes, plural, one {# ääni} other {# ääntä}}",
|
||||
"poll_button.add_poll": "Lisää äänestys",
|
||||
"poll_button.remove_poll": "Poista äänestys",
|
||||
"privacy.change": "Muuta julkaisun näkyvyyttä",
|
||||
@@ -756,7 +761,7 @@
|
||||
"privacy.private.short": "Seuraajat",
|
||||
"privacy.public.long": "Kuka tahansa Mastodonissa ja sen ulkopuolella",
|
||||
"privacy.public.short": "Julkinen",
|
||||
"privacy.quote.anyone": "{visibility}, kuka vain voi lainata",
|
||||
"privacy.quote.anyone": "{visibility}, kuka tahansa voi lainata",
|
||||
"privacy.quote.disabled": "{visibility}, lainaukset poissa käytöstä",
|
||||
"privacy.quote.limited": "{visibility}, lainauksia rajoitettu",
|
||||
"privacy.unlisted.additional": "Tämä toimii muuten kuin julkinen, mutta julkaisut eivät näy livesyöte-, aihetunniste- tai selausnäkymissä eivätkä Mastodonin hakutuloksissa, vaikka ne olisivat käyttäjätililläsi yleisesti sallittuina.",
|
||||
@@ -765,7 +770,7 @@
|
||||
"privacy_policy.last_updated": "Päivitetty viimeksi {date}",
|
||||
"privacy_policy.title": "Tietosuojakäytäntö",
|
||||
"quote_error.edit": "Lainauksia ei voi lisätä julkaisua muokattaessa.",
|
||||
"quote_error.poll": "Äänestysten lainaaminen ei ole sallittua.",
|
||||
"quote_error.poll": "Lainaaminen äänestyksen ohessa ei ole sallittua.",
|
||||
"quote_error.private_mentions": "Lainaaminen ei ole sallittua yksityismaininnoissa.",
|
||||
"quote_error.quote": "Vain yksi lainaus kerrallaan on sallittu.",
|
||||
"quote_error.unauthorized": "Sinulla ei ole valtuuksia lainata tätä julkaisua.",
|
||||
@@ -774,21 +779,21 @@
|
||||
"refresh": "Päivitä",
|
||||
"regeneration_indicator.please_stand_by": "Ole valmiina.",
|
||||
"regeneration_indicator.preparing_your_home_feed": "Kotisyötettäsi valmistellaan…",
|
||||
"relative_time.days": "{number} pv",
|
||||
"relative_time.full.days": "{number, plural, one {# päivä} other {# päivää}} sitten",
|
||||
"relative_time.full.hours": "{number, plural, one {# tunti} other {# tuntia}} sitten",
|
||||
"relative_time.days": "{number} pv",
|
||||
"relative_time.full.days": "{number, plural, one {# päivä} other {# päivää}} sitten",
|
||||
"relative_time.full.hours": "{number, plural, one {# tunti} other {# tuntia}} sitten",
|
||||
"relative_time.full.just_now": "juuri nyt",
|
||||
"relative_time.full.minutes": "{number, plural, one {# minuutti} other {# minuuttia}} sitten",
|
||||
"relative_time.full.seconds": "{number, plural, one {# sekunti} other {# sekuntia}} sitten",
|
||||
"relative_time.hours": "{number} t",
|
||||
"relative_time.full.minutes": "{number, plural, one {# minuutti} other {# minuuttia}} sitten",
|
||||
"relative_time.full.seconds": "{number, plural, one {# sekunti} other {# sekuntia}} sitten",
|
||||
"relative_time.hours": "{number} t",
|
||||
"relative_time.just_now": "nyt",
|
||||
"relative_time.minutes": "{number} min",
|
||||
"relative_time.seconds": "{number} s",
|
||||
"relative_time.minutes": "{number} min",
|
||||
"relative_time.seconds": "{number} s",
|
||||
"relative_time.today": "tänään",
|
||||
"remove_quote_hint.button_label": "Selvä",
|
||||
"remove_quote_hint.message": "Voit tehdä sen {icon}-valikosta.",
|
||||
"remove_quote_hint.title": "Haluatko poistaa lainatun julkaisusi?",
|
||||
"reply_indicator.attachments": "{count, plural, one {# liite} other {# liitettä}}",
|
||||
"reply_indicator.attachments": "{count, plural, one {# liite} other {# liitettä}}",
|
||||
"reply_indicator.cancel": "Peruuta",
|
||||
"reply_indicator.poll": "Äänestys",
|
||||
"report.block": "Estä",
|
||||
@@ -831,7 +836,7 @@
|
||||
"report.thanks.title_actionable": "Kiitos raportista – tutkimme asiaa.",
|
||||
"report.unfollow": "Lopeta käyttäjän @{name} seuraaminen",
|
||||
"report.unfollow_explanation": "Seuraat tätä tiliä. Jotta et enää näkisi sen julkaisuja kotisyötteessäsi, lopeta tilin seuraaminen.",
|
||||
"report_notification.attached_statuses": "{count, plural, one {{count} julkaisu} other {{count} julkaisua}} liitteenä",
|
||||
"report_notification.attached_statuses": "{count, plural, one {{count} julkaisu} other {{count} julkaisua}} liitteenä",
|
||||
"report_notification.categories.legal": "Lakiseikat",
|
||||
"report_notification.categories.legal_sentence": "laiton sisältö",
|
||||
"report_notification.categories.other": "Muu",
|
||||
@@ -847,11 +852,11 @@
|
||||
"search.quick_action.account_search": "Profiilit haulla {x}",
|
||||
"search.quick_action.go_to_account": "Siirry profiiliin {x}",
|
||||
"search.quick_action.go_to_hashtag": "Siirry aihetunnisteeseen {x}",
|
||||
"search.quick_action.open_url": "Avaa URL-osoite Mastodonissa",
|
||||
"search.quick_action.open_url": "Avaa URL-osoite Mastodonissa",
|
||||
"search.quick_action.status_search": "Julkaisut haulla {x}",
|
||||
"search.search_or_paste": "Hae tai liitä URL-osoite",
|
||||
"search.search_or_paste": "Hae tai liitä URL-osoite",
|
||||
"search_popout.full_text_search_disabled_message": "Ei saatavilla palvelimella {domain}.",
|
||||
"search_popout.full_text_search_logged_out_message": "Käytettävissä vain sisäänkirjautuneena.",
|
||||
"search_popout.full_text_search_logged_out_message": "Saatavilla vain sisäänkirjautuneena.",
|
||||
"search_popout.language_code": "ISO-kielikoodi",
|
||||
"search_popout.options": "Hakuvalinnat",
|
||||
"search_popout.quick_actions": "Pikatoiminnot",
|
||||
@@ -862,7 +867,7 @@
|
||||
"search_results.all": "Kaikki",
|
||||
"search_results.hashtags": "Aihetunnisteet",
|
||||
"search_results.no_results": "Ei tuloksia.",
|
||||
"search_results.no_search_yet": "Kokeile hakea julkaisuja, profiileja tai aihetunnisteita.",
|
||||
"search_results.no_search_yet": "Koeta hakea julkaisuja, profiileja tai aihetunnisteita.",
|
||||
"search_results.see_all": "Näytä kaikki",
|
||||
"search_results.statuses": "Julkaisut",
|
||||
"search_results.title": "Haku ”{q}”",
|
||||
@@ -901,10 +906,10 @@
|
||||
"status.direct_indicator": "Yksityismaininta",
|
||||
"status.edit": "Muokkaa",
|
||||
"status.edited": "Viimeksi muokattu {date}",
|
||||
"status.edited_x_times": "Muokattu {count, plural, one {{count} kerran} other {{count} kertaa}}",
|
||||
"status.edited_x_times": "Muokattu {count, plural, one {{count} kerran} other {{count} kertaa}}",
|
||||
"status.embed": "Hanki upotuskoodi",
|
||||
"status.favourite": "Suosikki",
|
||||
"status.favourites_count": "{count, plural, one {{counter} suosikki} other {{counter} suosikkia}}",
|
||||
"status.favourites_count": "{count, plural, one {{counter} suosikki} other {{counter} suosikkia}}",
|
||||
"status.filter": "Suodata tämä julkaisu",
|
||||
"status.history.created": "{name} loi {date}",
|
||||
"status.history.edited": "{name} muokkasi {date}",
|
||||
@@ -939,14 +944,14 @@
|
||||
"status.quotes.empty": "Kukaan ei ole vielä lainannut tätä julkaisua. Kun joku tekee niin, se tulee tähän näkyviin.",
|
||||
"status.quotes.local_other_disclaimer": "Tekijän hylkäämiä lainauksia ei näytetä.",
|
||||
"status.quotes.remote_other_disclaimer": "Vain palvelimen {domain} lainaukset näkyvät taatusti tässä. Tekijän hylkäämiä lainauksia ei näytetä.",
|
||||
"status.quotes_count": "{count, plural, one {{counter} lainaus} other {{counter} lainausta}}",
|
||||
"status.quotes_count": "{count, plural, one {{counter} lainaus} other {{counter} lainausta}}",
|
||||
"status.read_more": "Näytä enemmän",
|
||||
"status.reblog": "Tehosta",
|
||||
"status.reblog_or_quote": "Tehosta tai lainaa",
|
||||
"status.reblog_private": "Jaa uudelleen seuraajiesi kanssa",
|
||||
"status.reblogged_by": "{name} tehosti",
|
||||
"status.reblogs.empty": "Kukaan ei ole vielä tehostanut tätä julkaisua. Kun joku tekee niin, tulee hän tähän näkyviin.",
|
||||
"status.reblogs_count": "{count, plural, one {{counter} tehostus} other {{counter} tehostusta}}",
|
||||
"status.reblogs_count": "{count, plural, one {{counter} tehostus} other {{counter} tehostusta}}",
|
||||
"status.redraft": "Poista ja palauta muokattavaksi",
|
||||
"status.remove_bookmark": "Poista kirjanmerkki",
|
||||
"status.remove_favourite": "Poista suosikeista",
|
||||
@@ -963,10 +968,10 @@
|
||||
"status.show_less_all": "Näytä kaikista vähemmän",
|
||||
"status.show_more_all": "Näytä kaikista enemmän",
|
||||
"status.show_original": "Näytä alkuperäinen",
|
||||
"status.title.with_attachments": "{user} liitti {attachmentCount, plural, one {{attachmentCount} tiedoston} other {{attachmentCount} tiedostoa}}",
|
||||
"status.title.with_attachments": "{user} julkaisi {attachmentCount, plural, one {liitteen} other {{attachmentCount} liitettä}}",
|
||||
"status.translate": "Käännä",
|
||||
"status.translated_from_with": "Käännetty kielestä {lang} käyttäen palvelua {provider}",
|
||||
"status.uncached_media_warning": "Esikatselu ei ole käytettävissä",
|
||||
"status.translated_from_with": "Käännetty kielestä {lang} palvelulla {provider}",
|
||||
"status.uncached_media_warning": "Esikatselu ei saatavilla",
|
||||
"status.unmute_conversation": "Kumoa keskustelun mykistys",
|
||||
"status.unpin": "Irrota profiilista",
|
||||
"subscribed_languages.lead": "Vain valituilla kielillä kirjoitetut julkaisut näkyvät koti- ja lista-aikajanoillasi muutoksen jälkeen. Älä valitse mitään, jos haluat nähdä julkaisuja kaikilla kielillä.",
|
||||
@@ -980,17 +985,17 @@
|
||||
"terms_of_service.effective_as_of": "Tulee voimaan {date}",
|
||||
"terms_of_service.title": "Käyttöehdot",
|
||||
"terms_of_service.upcoming_changes_on": "Tulevia muutoksia {date}",
|
||||
"time_remaining.days": "{number, plural, one {# päivä} other {# päivää}} jäljellä",
|
||||
"time_remaining.hours": "{number, plural, one {# tunti} other {# tuntia}} jäljellä",
|
||||
"time_remaining.minutes": "{number, plural, one {# minuutti} other {# minuuttia}} jäljellä",
|
||||
"time_remaining.days": "{number, plural, one {# päivä} other {# päivää}} jäljellä",
|
||||
"time_remaining.hours": "{number, plural, one {# tunti} other {# tuntia}} jäljellä",
|
||||
"time_remaining.minutes": "{number, plural, one {# minuutti} other {# minuuttia}} jäljellä",
|
||||
"time_remaining.moments": "Hetkiä jäljellä",
|
||||
"time_remaining.seconds": "{number, plural, one {# sekunti} other {# sekuntia}} jäljellä",
|
||||
"time_remaining.seconds": "{number, plural, one {# sekunti} other {# sekuntia}} jäljellä",
|
||||
"trends.counter_by_accounts": "{count, plural, one {{counter} käyttäjä} other {{counter} käyttäjää}} {days, plural, one {viime päivänä} other {viimeisenä {days} päivänä}}",
|
||||
"trends.trending_now": "Suosittua nyt",
|
||||
"ui.beforeunload": "Luonnos häviää, jos poistut Mastodonista.",
|
||||
"units.short.billion": "{count} mrd.",
|
||||
"units.short.million": "{count} milj.",
|
||||
"units.short.thousand": "{count} t.",
|
||||
"units.short.billion": "{count} mrd.",
|
||||
"units.short.million": "{count} milj.",
|
||||
"units.short.thousand": "{count} t.",
|
||||
"upload_area.title": "Lähetä raahaamalla ja pudottamalla tähän",
|
||||
"upload_button.label": "Lisää kuvia, video tai äänitiedosto",
|
||||
"upload_error.limit": "Tiedostolähetysten rajoitus ylitetty.",
|
||||
|
||||
@@ -516,6 +516,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Vís/fjal tekst handan CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Vís ella fjal innihald",
|
||||
"keyboard_shortcuts.toot": "Byrja nýggjan post",
|
||||
"keyboard_shortcuts.top": "Flyt til ovast á listanum",
|
||||
"keyboard_shortcuts.translate": "at umseta ein post",
|
||||
"keyboard_shortcuts.unfocus": "Tak skrivi-/leiti-økið úr miðdeplinum",
|
||||
"keyboard_shortcuts.up": "Flyt upp á listanum",
|
||||
|
||||
@@ -357,6 +357,7 @@
|
||||
"empty_column.notification_requests": "C'est fini ! Il n'y a plus rien ici. Lorsque vous recevez de nouvelles notifications, elles apparaitront ici conformément à vos préférences.",
|
||||
"empty_column.notifications": "Vous n'avez pas encore de notifications. Quand d'autres personnes interagissent avec vous, vous en verrez ici.",
|
||||
"empty_column.public": "Il n’y a rien ici! Écrivez quelque chose publiquement, ou bien suivez manuellement des personnes d’autres serveurs pour remplir le fil public",
|
||||
"error.no_hashtag_feed_access": "Rejoindre ou se connecter pour voir et suivre cet hashtag.",
|
||||
"error.unexpected_crash.explanation": "En raison d’un bogue dans notre code ou d’un problème de compatibilité avec votre navigateur, cette page n’a pas pu être affichée correctement.",
|
||||
"error.unexpected_crash.explanation_addons": "Cette page n’a pas pu être affichée correctement. Cette erreur est probablement causée par une extension de navigateur ou des outils de traduction automatique.",
|
||||
"error.unexpected_crash.next_steps": "Essayez de rafraîchir la page. Si cela n’aide pas, vous pouvez toujours utiliser Mastodon via un autre navigateur ou une application native.",
|
||||
@@ -515,6 +516,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Déplier/replier texte derrière avertissement",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Afficher/cacher médias",
|
||||
"keyboard_shortcuts.toot": "Commencer un nouveau message",
|
||||
"keyboard_shortcuts.top": "Mettre en tête de liste",
|
||||
"keyboard_shortcuts.translate": "traduire un message",
|
||||
"keyboard_shortcuts.unfocus": "Ne plus se concentrer sur la zone de rédaction/barre de recherche",
|
||||
"keyboard_shortcuts.up": "Monter dans la liste",
|
||||
|
||||
@@ -357,6 +357,7 @@
|
||||
"empty_column.notification_requests": "C'est fini ! Il n'y a plus rien ici. Lorsque vous recevez de nouvelles notifications, elles apparaitront ici conformément à vos préférences.",
|
||||
"empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres personnes pour débuter la conversation.",
|
||||
"empty_column.public": "Il n’y a rien ici ! Écrivez quelque chose publiquement, ou bien suivez manuellement des personnes d’autres serveurs pour remplir le fil public",
|
||||
"error.no_hashtag_feed_access": "Rejoindre ou se connecter pour voir et suivre cet hashtag.",
|
||||
"error.unexpected_crash.explanation": "En raison d’un bug dans notre code ou d’un problème de compatibilité avec votre navigateur, cette page n’a pas pu être affichée correctement.",
|
||||
"error.unexpected_crash.explanation_addons": "Cette page n’a pas pu être affichée correctement. Cette erreur est probablement causée par une extension de navigateur ou des outils de traduction automatique.",
|
||||
"error.unexpected_crash.next_steps": "Essayez de rafraîchir la page. Si cela n’aide pas, vous pouvez toujours utiliser Mastodon via un autre navigateur ou une application native.",
|
||||
@@ -365,7 +366,7 @@
|
||||
"errors.unexpected_crash.report_issue": "Signaler le problème",
|
||||
"explore.suggested_follows": "Personnes",
|
||||
"explore.title": "Tendances",
|
||||
"explore.trending_links": "Nouvelles",
|
||||
"explore.trending_links": "Actualités",
|
||||
"explore.trending_statuses": "Messages",
|
||||
"explore.trending_tags": "Hashtags",
|
||||
"featured_carousel.current": "<sr>Message</sr> {current, number} / {max, number}",
|
||||
@@ -515,6 +516,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Déplier/replier le texte derrière un CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Afficher/cacher les médias",
|
||||
"keyboard_shortcuts.toot": "Commencer un nouveau message",
|
||||
"keyboard_shortcuts.top": "Mettre en tête de liste",
|
||||
"keyboard_shortcuts.translate": "traduire un message",
|
||||
"keyboard_shortcuts.unfocus": "Quitter la zone de rédaction/barre de recherche",
|
||||
"keyboard_shortcuts.up": "Monter dans la liste",
|
||||
|
||||
@@ -516,6 +516,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Taispeáin/folaigh an téacs taobh thiar de CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Taispeáin / cuir i bhfolach meáin",
|
||||
"keyboard_shortcuts.toot": "Cuir tús le postáil nua",
|
||||
"keyboard_shortcuts.top": "Bog go barr an liosta",
|
||||
"keyboard_shortcuts.translate": "post a aistriú",
|
||||
"keyboard_shortcuts.unfocus": "Unfocus cum textarea/search",
|
||||
"keyboard_shortcuts.up": "Bog suas ar an liosta",
|
||||
|
||||
@@ -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": "ללמוד עוד על דבפוסי השימוש שלך במסטודון לאורך השנה החולפת.",
|
||||
"annual_report.announcement.title": "סיכומודון {year} הגיע",
|
||||
"annual_report.summary.archetype.booster": "ההד-וניסט(ית)",
|
||||
"annual_report.summary.archetype.lurker": "השורץ.ת השקט.ה",
|
||||
"annual_report.summary.archetype.oracle": "כבוד הרב.ה",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "הצגת/הסתרת טקסט מוסתר מאחורי אזהרת תוכן",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "הצגת/הסתרת מדיה",
|
||||
"keyboard_shortcuts.toot": "להתחיל חיצרוץ חדש",
|
||||
"keyboard_shortcuts.top": "העברה לראש הרשימה",
|
||||
"keyboard_shortcuts.translate": "לתרגם הודעה",
|
||||
"keyboard_shortcuts.unfocus": "לצאת מתיבת חיבור/חיפוש",
|
||||
"keyboard_shortcuts.up": "לנוע במעלה הרשימה",
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
"about.domain_blocks.silenced.title": "सीमित",
|
||||
"about.domain_blocks.suspended.explanation": "इस सर्वर से कोई डेटा संसाधित, संग्रहीत या आदान-प्रदान नहीं किया जाएगा, जिससे इस सर्वर से उपयोगकर्ताओं के साथ कोई भी बातचीत या संचार असंभव हो जाएगा",
|
||||
"about.domain_blocks.suspended.title": "सस्पेंड किआ गया है!",
|
||||
"about.language_label": "भाषा",
|
||||
"about.not_available": "यह जानकारी इस सर्वर पर उपलब्ध नहीं कराई गई है।",
|
||||
"about.powered_by": "{mastodon} द्वारा संचालित डेसेंट्रलीसेड सोशल मीडिया प्लैटफ़ॉर्म!",
|
||||
"about.rules": "सर्वर के नियम",
|
||||
"account.account_note_header": "व्यक्तिगत नोंध",
|
||||
"account.add_or_remove_from_list": "सूची में जोड़ें या हटाए",
|
||||
"account.badges.bot": "बॉट",
|
||||
"account.badges.group": "समूह",
|
||||
@@ -19,17 +21,31 @@
|
||||
"account.block_domain": "{domain} के सारी चीज़े छुपाएं",
|
||||
"account.block_short": "ब्लॉक किया गया",
|
||||
"account.blocked": "ब्लॉक",
|
||||
"account.blocking": "प्रतिबंधित करना",
|
||||
"account.cancel_follow_request": "फॉलो रिक्वेस्ट वापस लें",
|
||||
"account.copy": "प्रोफाइल पर लिंक कॉपी करें",
|
||||
"account.direct": "निजि तरीके से उल्लेख करे @{name}",
|
||||
"account.disable_notifications": "@{name} पोस्ट के लिए मुझे सूचित मत करो",
|
||||
"account.domain_blocking": "डोमेन ब्लॉक करें",
|
||||
"account.edit_profile": "प्रोफ़ाइल संपादित करें",
|
||||
"account.edit_profile_short": "संपादित करें",
|
||||
"account.enable_notifications": "जब @{name} पोस्ट मौजूद हो सूचित करें",
|
||||
"account.endorse": "प्रोफ़ाइल पर दिखाए",
|
||||
"account.familiar_followers_many": "{name1}{name2} और {othersCount, plural, one {एक और जिन्हे आप जानते है} other {# और जिन्हे आप जानते है}}",
|
||||
"account.familiar_followers_one": "{name1} ने अनुसरण किया है",
|
||||
"account.familiar_followers_two": "{name1} और {name2} ने अनुसरण किया है",
|
||||
"account.featured": "प्रचलित",
|
||||
"account.featured.accounts": "प्रोफ़ाइल",
|
||||
"account.featured.hashtags": "हैशटैग्स",
|
||||
"account.featured_tags.last_status_at": "{date} का अंतिम पोस्ट",
|
||||
"account.featured_tags.last_status_never": "कोई पोस्ट नहीं है",
|
||||
"account.follow": "फॉलो करें",
|
||||
"account.follow_back": "फॉलो करें",
|
||||
"account.follow_back_short": "वापस अनुसरण करें",
|
||||
"account.follow_request": "अनुसरण करने की बिनती करें",
|
||||
"account.follow_request_cancel": "अनुरोध रद्द करें",
|
||||
"account.follow_request_cancel_short": "रद्द करें",
|
||||
"account.follow_request_short": "अनुरोध करें",
|
||||
"account.followers": "फॉलोवर",
|
||||
"account.followers.empty": "कोई भी इस यूज़र् को फ़ॉलो नहीं करता है",
|
||||
"account.following": "फॉलोइंग",
|
||||
|
||||
@@ -113,6 +113,7 @@
|
||||
"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.summary.archetype.booster": "A cool-vadász",
|
||||
"annual_report.summary.archetype.lurker": "A settenkedő",
|
||||
"annual_report.summary.archetype.oracle": "Az orákulum",
|
||||
@@ -516,6 +517,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.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",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Lýstu þessu fyrir fólk með skerta sjón…",
|
||||
"alt_text_modal.done": "Lokið",
|
||||
"announcement.announcement": "Auglýsing",
|
||||
"annual_report.announcement.action_build": "Byggja Wrapstodon fyrir mig",
|
||||
"annual_report.announcement.action_view": "Skoða minn Wrapstodon",
|
||||
"annual_report.announcement.description": "Skoðaðu meira um virkni þína á Mastodon á síðastliðnu ári.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} er komið",
|
||||
"annual_report.summary.archetype.booster": "Svali gaurinn",
|
||||
"annual_report.summary.archetype.lurker": "Lurkurinn",
|
||||
"annual_report.summary.archetype.oracle": "Völvan",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Birta/fela texta á bak við aðvörun vegna efnis",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Birta/fela myndir",
|
||||
"keyboard_shortcuts.toot": "Byrja nýja færslu",
|
||||
"keyboard_shortcuts.top": "Færa efst á listann",
|
||||
"keyboard_shortcuts.translate": "að þýða færslu",
|
||||
"keyboard_shortcuts.unfocus": "Taka virkni úr textainnsetningarreit eða leit",
|
||||
"keyboard_shortcuts.up": "Fara ofar í listanum",
|
||||
|
||||
@@ -516,6 +516,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Mostra/Nasconde il testo dietro CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Mostra/Nasconde media",
|
||||
"keyboard_shortcuts.toot": "Crea un nuovo post",
|
||||
"keyboard_shortcuts.top": "Sposta all'inizio della lista",
|
||||
"keyboard_shortcuts.translate": "Traduce un post",
|
||||
"keyboard_shortcuts.unfocus": "Rimuove il focus sull'area di composizione testuale/ricerca",
|
||||
"keyboard_shortcuts.up": "Scorre in su nell'elenco",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"about.blocks": "Prižiūrimi serveriai",
|
||||
"about.contact": "Kontaktai:",
|
||||
"about.default_locale": "Numatyta",
|
||||
"about.disclaimer": "„Mastodon“ – tai nemokama atvirojo kodo programinė įranga ir „Mastodon gGmbH“ prekės ženklas.",
|
||||
"about.domain_blocks.no_reason_available": "Priežastis nepateikta",
|
||||
"about.domain_blocks.preamble": "„Mastodon“ paprastai leidžia peržiūrėti turinį ir bendrauti su naudotojais iš bet kurio kito fediverse esančio serverio. Šios yra išimtys, kurios buvo padarytos šiame konkrečiame serveryje.",
|
||||
@@ -8,6 +9,7 @@
|
||||
"about.domain_blocks.silenced.title": "Apribota",
|
||||
"about.domain_blocks.suspended.explanation": "Jokie duomenys iš šio serverio nebus apdorojami, saugomi ar keičiami, todėl bet kokia sąveika ar bendravimas su šio serverio naudotojais bus neįmanomas.",
|
||||
"about.domain_blocks.suspended.title": "Pristabdyta",
|
||||
"about.language_label": "Kalba",
|
||||
"about.not_available": "Ši informacija nebuvo pateikta šiame serveryje.",
|
||||
"about.powered_by": "Decentralizuota socialinė medija, veikianti pagal „{mastodon}“",
|
||||
"about.rules": "Serverio taisyklės",
|
||||
@@ -26,8 +28,12 @@
|
||||
"account.disable_notifications": "Nustoti man pranešti, kai @{name} paskelbia",
|
||||
"account.domain_blocking": "Blokuoti domeną",
|
||||
"account.edit_profile": "Redaguoti profilį",
|
||||
"account.edit_profile_short": "Redaguoti",
|
||||
"account.enable_notifications": "Pranešti man, kai @{name} paskelbia",
|
||||
"account.endorse": "Rodyti profilyje",
|
||||
"account.familiar_followers_many": "Sekama {name1}, {name2}, ir {othersCount, plural, one {dar vieno} few {# dar keleto} many {# dar kelių} other {# kitų pažystąmų}}",
|
||||
"account.familiar_followers_one": "Seka {name1}",
|
||||
"account.familiar_followers_two": "{name1} ir {name2} seka",
|
||||
"account.featured": "Rodomi",
|
||||
"account.featured.accounts": "Profiliai",
|
||||
"account.featured.hashtags": "Saitažodžiai",
|
||||
@@ -35,9 +41,15 @@
|
||||
"account.featured_tags.last_status_never": "Nėra įrašų",
|
||||
"account.follow": "Sekti",
|
||||
"account.follow_back": "Sekti atgal",
|
||||
"account.follow_back_short": "Sekti atgal",
|
||||
"account.follow_request": "Prašyti sekti",
|
||||
"account.follow_request_cancel": "Atšaukti prašymą",
|
||||
"account.follow_request_cancel_short": "Atšaukti",
|
||||
"account.follow_request_short": "Prašymas",
|
||||
"account.followers": "Sekėjai",
|
||||
"account.followers.empty": "Šio naudotojo dar niekas neseka.",
|
||||
"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.follows.empty": "Šis naudotojas dar nieko neseka.",
|
||||
@@ -145,6 +157,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.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}.",
|
||||
"closed_registrations_modal.find_another_server": "Rasti kitą serverį",
|
||||
@@ -161,6 +174,8 @@
|
||||
"column.edit_list": "Redaguoti sąrašą",
|
||||
"column.favourites": "Mėgstami",
|
||||
"column.firehose": "Tiesioginiai srautai",
|
||||
"column.firehose_local": "Tiesioginis srautas iš šio serverio",
|
||||
"column.firehose_singular": "Tiesioginis srautas",
|
||||
"column.follow_requests": "Sekimo prašymai",
|
||||
"column.home": "Pagrindinis",
|
||||
"column.list_members": "Tvarkyti sąrašo narius",
|
||||
@@ -180,6 +195,7 @@
|
||||
"community.column_settings.local_only": "Tik vietinis",
|
||||
"community.column_settings.media_only": "Tik medija",
|
||||
"community.column_settings.remote_only": "Tik nuotolinis",
|
||||
"compose.error.blank_post": "Įrašas negali būti tuščias.",
|
||||
"compose.language.change": "Keisti kalbą",
|
||||
"compose.language.search": "Ieškoti kalbų...",
|
||||
"compose.published.body": "Įrašas paskelbtas.",
|
||||
@@ -212,6 +228,13 @@
|
||||
"confirmations.delete_list.confirm": "Ištrinti",
|
||||
"confirmations.delete_list.message": "Ar tikrai nori negrįžtamai ištrinti šį sąrašą?",
|
||||
"confirmations.delete_list.title": "Ištrinti sąrašą?",
|
||||
"confirmations.discard_draft.confirm": "Išsaugoti ir tęsti",
|
||||
"confirmations.discard_draft.edit.cancel": "Tęsti redagavimą",
|
||||
"confirmations.discard_draft.edit.message": "Tęsdami, jūs prarasite visus pakeitimus, kuriuos padarėte šiuo metu redaguojamame įraše.",
|
||||
"confirmations.discard_draft.edit.title": "Atmesti pakeitimus savo įraše?",
|
||||
"confirmations.discard_draft.post.cancel": "Tęsti juodraščio redagavimą",
|
||||
"confirmations.discard_draft.post.message": "Tęsdami ištrinsite šiuo metu kuriamą įrašą.",
|
||||
"confirmations.discard_draft.post.title": "Atmesti savo įrašo juodraštį?",
|
||||
"confirmations.discard_edit_media.confirm": "Atmesti",
|
||||
"confirmations.discard_edit_media.message": "Turi neišsaugotų medijos aprašymo ar peržiūros pakeitimų. Vis tiek juos atmesti?",
|
||||
"confirmations.follow_to_list.confirm": "Sekti ir pridėti prie sąrašo",
|
||||
@@ -225,13 +248,30 @@
|
||||
"confirmations.missing_alt_text.secondary": "Siųsti vis tiek",
|
||||
"confirmations.missing_alt_text.title": "Pridėti alternatyvųjį tekstą?",
|
||||
"confirmations.mute.confirm": "Nutildyti",
|
||||
"confirmations.private_quote_notify.cancel": "Grįžti prie redagavimo",
|
||||
"confirmations.private_quote_notify.confirm": "Paskelbti įrašą",
|
||||
"confirmations.private_quote_notify.do_not_show_again": "Neberodyti šio pranešimo dar kartą",
|
||||
"confirmations.private_quote_notify.message": "Asmuo, kurį paminite, ir kiti paminėti asmenys bus informuoti ir galės peržiūrėti jūsų įrašą, net jei jie neseka jūsų.",
|
||||
"confirmations.private_quote_notify.title": "Dalytis su sekėjais ir paminėtais vartotojais?",
|
||||
"confirmations.quiet_post_quote_info.dismiss": "Daugiau man nepriminti",
|
||||
"confirmations.quiet_post_quote_info.got_it": "Supratau",
|
||||
"confirmations.quiet_post_quote_info.message": "Kai norite paminėti tylų viešą įrašą, jūsų įrašas bus paslėptas Tendencijų sąrašuose.",
|
||||
"confirmations.quiet_post_quote_info.title": "Kai paminite tylius viešus įrašus",
|
||||
"confirmations.redraft.confirm": "Ištrinti ir iš naujo parengti",
|
||||
"confirmations.redraft.message": "Ar tikrai nori ištrinti šį įrašą ir parengti jį iš naujo? Bus prarasti mėgstami ir pasidalinimai, o atsakymai į originalų įrašą bus panaikinti.",
|
||||
"confirmations.redraft.title": "Ištrinti ir iš naujo parengti įrašą?",
|
||||
"confirmations.remove_from_followers.confirm": "Šalinti sekėją",
|
||||
"confirmations.remove_from_followers.message": "{name} nustos jus sekti. Ar tikrai norite tęsti?",
|
||||
"confirmations.remove_from_followers.title": "Šalinti sekėją?",
|
||||
"confirmations.revoke_quote.confirm": "Pašalinti įrašą",
|
||||
"confirmations.revoke_quote.message": "Šio veiksmo negalima anuliuoti.",
|
||||
"confirmations.revoke_quote.title": "Pašalinti įrašą?",
|
||||
"confirmations.unblock.confirm": "Atblokuoti",
|
||||
"confirmations.unblock.title": "Atblokuoti {name}?",
|
||||
"confirmations.unfollow.confirm": "Nebesekti",
|
||||
"confirmations.unfollow.title": "Nebesekti {name}?",
|
||||
"confirmations.withdraw_request.confirm": "Atšaukti prašymą",
|
||||
"confirmations.withdraw_request.title": "Atšaukti prašymą sekti {name}?",
|
||||
"content_warning.hide": "Slėpti įrašą",
|
||||
"content_warning.show": "Rodyti vis tiek",
|
||||
"content_warning.show_more": "Rodyti daugiau",
|
||||
@@ -250,6 +290,7 @@
|
||||
"disabled_account_banner.text": "Tavo paskyra {disabledAccount} šiuo metu išjungta.",
|
||||
"dismissable_banner.community_timeline": "Tai – naujausi vieši įrašai iš žmonių, kurių paskyros talpinamos {domain}.",
|
||||
"dismissable_banner.dismiss": "Atmesti",
|
||||
"dismissable_banner.public_timeline": "Tai yra naujausi vieši įrašai iš fediverse, kuriuos seka {domain} vartotojai.",
|
||||
"domain_block_modal.block": "Blokuoti serverį",
|
||||
"domain_block_modal.block_account_instead": "Blokuoti @{name} vietoj to",
|
||||
"domain_block_modal.they_can_interact_with_old_posts": "Žmonės iš šio serverio gali bendrauti su tavo senomis įrašomis.",
|
||||
@@ -272,6 +313,7 @@
|
||||
"domain_pill.your_handle": "Tavo socialinis medijos vardas:",
|
||||
"domain_pill.your_server": "Tavo skaitmeniniai namai, kuriuose saugomi visi tavo įrašai. Nepatinka šis? Bet kada perkelk serverius ir atsivesk ir savo sekėjus.",
|
||||
"domain_pill.your_username": "Tavo unikalus identifikatorius šiame serveryje. Skirtinguose serveriuose galima rasti naudotojų su tuo pačiu naudotojo vardu.",
|
||||
"dropdown.empty": "Pasirinkite variantą",
|
||||
"embed.instructions": "Įterpk šį įrašą į savo svetainę nukopijuojant toliau pateiktą kodą.",
|
||||
"embed.preview": "Štai kaip tai atrodys:",
|
||||
"emoji_button.activity": "Veikla",
|
||||
@@ -289,6 +331,8 @@
|
||||
"emoji_button.search_results": "Paieškos rezultatai",
|
||||
"emoji_button.symbols": "Simboliai",
|
||||
"emoji_button.travel": "Kelionės ir vietos",
|
||||
"empty_column.account_featured.me": "Jūs dar nieko neparyškinote. Ar žinojote, kad savo profilyje galite parodyti dažniausiai naudojamas žymes ir netgi savo draugų paskyras?",
|
||||
"empty_column.account_featured.other": "{acct} dar nieko neparyškino. Ar žinojote, kad savo profilyje galite pateikti dažniausiai naudojamus žymes ir netgi savo draugų paskyras?",
|
||||
"empty_column.account_featured_other.unknown": "Ši paskyra dar nieko neparodė.",
|
||||
"empty_column.account_hides_collections": "Šis (-i) naudotojas (-a) pasirinko nepadaryti šią informaciją prieinamą.",
|
||||
"empty_column.account_suspended": "Paskyra pristabdyta.",
|
||||
@@ -298,6 +342,7 @@
|
||||
"empty_column.bookmarked_statuses": "Dar neturi nė vienos įrašo pridėtos žymės. Kai vieną iš jų pridėsi į žymes, jis bus rodomas čia.",
|
||||
"empty_column.community": "Vietinė laiko skalė yra tuščia. Parašyk ką nors viešai, kad pradėtum sąveikauti.",
|
||||
"empty_column.direct": "Dar neturi jokių privačių paminėjimų. Kai išsiųsi arba gausi vieną iš jų, jis bus rodomas čia.",
|
||||
"empty_column.disabled_feed": "Šis srautas buvo išjungtas jūsų serverio administratorių.",
|
||||
"empty_column.domain_blocks": "Kol kas nėra užblokuotų serverių.",
|
||||
"empty_column.explore_statuses": "Šiuo metu niekas nėra tendencinga. Patikrinkite vėliau!",
|
||||
"empty_column.favourited_statuses": "Dar neturi mėgstamų įrašų. Kai vieną iš jų pamėgsi, jis bus rodomas čia.",
|
||||
@@ -306,11 +351,12 @@
|
||||
"empty_column.followed_tags": "Dar neseki jokių saitažodžių. Kai tai padarysi, jie bus rodomi čia.",
|
||||
"empty_column.hashtag": "Nėra nieko šiame saitažodyje kol kas.",
|
||||
"empty_column.home": "Tavo pagrindinio laiko skalė tuščia. Sek daugiau žmonių, kad ją užpildytum.",
|
||||
"empty_column.list": "Nėra nieko šiame sąraše kol kas. Kai šio sąrašo nariai paskelbs naujų įrašų, jie bus rodomi čia.",
|
||||
"empty_column.list": "Šiame sąraše dar nieko nėra. Kai šio sąrašo nariai paskelbs naujus įrašus, jie bus rodomi čia.",
|
||||
"empty_column.mutes": "Dar nesi nutildęs (-usi) nė vieno naudotojo.",
|
||||
"empty_column.notification_requests": "Viskas švaru! Čia nieko nėra. Kai gausi naujų pranešimų, jie bus rodomi čia pagal tavo nustatymus.",
|
||||
"empty_column.notifications": "Dar neturi jokių pranešimų. Kai kiti žmonės su tavimi sąveikaus, matysi tai čia.",
|
||||
"empty_column.public": "Čia nieko nėra. Parašyk ką nors viešai arba rankiniu būdu sek naudotojus iš kitų serverių, kad jį užpildytum.",
|
||||
"error.no_hashtag_feed_access": "Registruokitės arba prisijunkite, kad galėtumėte peržiūrėti ir sekti šį žymę.",
|
||||
"error.unexpected_crash.explanation": "Dėl mūsų kodo riktos arba naršyklės suderinamumo problemos šis puslapis negalėjo būti rodomas teisingai.",
|
||||
"error.unexpected_crash.explanation_addons": "Šį puslapį nepavyko parodyti teisingai. Šią klaidą greičiausiai sukėlė naršyklės priedas arba automatinio vertimo įrankiai.",
|
||||
"error.unexpected_crash.next_steps": "Pabandyk atnaujinti puslapį. Jei tai nepadeda, galbūt vis dar galėsi naudotis Mastodon per kitą naršyklę arba savąją programėlę.",
|
||||
@@ -318,9 +364,13 @@
|
||||
"errors.unexpected_crash.copy_stacktrace": "Kopijuoti dėklo eigą į iškarpinę",
|
||||
"errors.unexpected_crash.report_issue": "Pranešti apie problemą",
|
||||
"explore.suggested_follows": "Žmonės",
|
||||
"explore.title": "Populiaru",
|
||||
"explore.trending_links": "Naujienos",
|
||||
"explore.trending_statuses": "Įrašai",
|
||||
"explore.trending_tags": "Saitažodžiai",
|
||||
"featured_carousel.current": "<sr>Įrašas</sr> {current, number} / {max, number}",
|
||||
"featured_carousel.header": "{count, plural, one {Iškeltas įrašas} few {Iškelti įrašai} many {Iškeltų įrašų} other {Iškelti įrašai}}",
|
||||
"featured_carousel.slide": "Įrašas {current, number} iš {max, number}",
|
||||
"filter_modal.added.context_mismatch_explanation": "Ši filtro kategorija netaikoma kontekstui, kuriame peržiūrėjai šį įrašą. Jei nori, kad įrašas būtų filtruojamas ir šiame kontekste, turėsi redaguoti filtrą.",
|
||||
"filter_modal.added.context_mismatch_title": "Konteksto neatitikimas.",
|
||||
"filter_modal.added.expired_explanation": "Ši filtro kategorija nustojo galioti. Kad ji būtų taikoma, turėsi pakeisti galiojimo datą.",
|
||||
@@ -363,6 +413,7 @@
|
||||
"follow_suggestions.who_to_follow": "Ką sekti",
|
||||
"followed_tags": "Sekami saitažodžiai",
|
||||
"footer.about": "Apie",
|
||||
"footer.about_this_server": "Apie",
|
||||
"footer.directory": "Profilių katalogas",
|
||||
"footer.get_app": "Gauti programėlę",
|
||||
"footer.keyboard_shortcuts": "Spartieji klavišai",
|
||||
@@ -373,6 +424,8 @@
|
||||
"generic.saved": "Išsaugota",
|
||||
"getting_started.heading": "Kaip pradėti",
|
||||
"hashtag.admin_moderation": "Atverti prižiūrėjimo sąsają saitažodžiui #{name}",
|
||||
"hashtag.browse": "Naršyti įrašus su #{hashtag}",
|
||||
"hashtag.browse_from_account": "Naršyti @{name} įrašus su žyma #{hashtag}",
|
||||
"hashtag.column_header.tag_mode.all": "ir {additional}",
|
||||
"hashtag.column_header.tag_mode.any": "ar {additional}",
|
||||
"hashtag.column_header.tag_mode.none": "be {additional}",
|
||||
@@ -385,7 +438,10 @@
|
||||
"hashtag.counter_by_accounts": "{count, plural, one {{counter} dalyvis} few {{counter} dalyviai} many {{counter} dalyvio} other {{counter} dalyvių}}",
|
||||
"hashtag.counter_by_uses": "{count, plural, one {{counter} įrašas} few {{counter} įrašai} many {{counter} įrašo} other {{counter} įrašų}}",
|
||||
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} įrašas} few {{counter} įrašai} many {{counter} įrašo} other {{counter} įrašų}} šiandien",
|
||||
"hashtag.feature": "Rodyti profilyje",
|
||||
"hashtag.follow": "Sekti saitažodį",
|
||||
"hashtag.mute": "Nutildyti žymą #{hashtag}",
|
||||
"hashtag.unfeature": "Neberodyti profilyje",
|
||||
"hashtag.unfollow": "Nebesekti saitažodį",
|
||||
"hashtags.and_other": "…ir {count, plural, one {# daugiau} few {# daugiau} many {# daugiau}other {# daugiau}}",
|
||||
"hints.profiles.followers_may_be_missing": "Sekėjai šiai profiliui gali būti nepateikti.",
|
||||
@@ -394,6 +450,7 @@
|
||||
"hints.profiles.see_more_followers": "Žiūrėti daugiau sekėjų serveryje {domain}",
|
||||
"hints.profiles.see_more_follows": "Žiūrėti daugiau sekimų serveryje {domain}",
|
||||
"hints.profiles.see_more_posts": "Žiūrėti daugiau įrašų serveryje {domain}",
|
||||
"home.column_settings.show_quotes": "Rodyti paminėjimus",
|
||||
"home.column_settings.show_reblogs": "Rodyti pakėlimus",
|
||||
"home.column_settings.show_replies": "Rodyti atsakymus",
|
||||
"home.hide_announcements": "Slėpti skelbimus",
|
||||
@@ -414,10 +471,12 @@
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignoruoti pranešimus iš neprašytų privačių paminėjimų?",
|
||||
"info_button.label": "Žinynas",
|
||||
"info_button.what_is_alt_text": "<h1>Kas yra alternatyvusis tekstas?</h1> <p>Alternatyvusis tekstas pateikia vaizdų aprašymus asmenims su regos sutrikimais, turintiems mažo pralaidumo ryšį arba ieškantiems papildomo konteksto.</p> <p>Galite pagerinti prieinamumą ir suprantamumą visiems, jei parašysite aiškų, glaustą ir objektyvų alternatyvųjį tekstą.</p> <ul> <li>Užfiksuokite svarbiausius elementus.</li> <li>Apibendrinkite tekstą vaizduose.</li> <li>Naudokite įprasta sakinio struktūrą.</li> <li>Venkite nereikalingos informacijos.</li> <li>Sutelkite dėmesį į tendencijas ir pagrindines išvadas sudėtinguose vaizdiniuose (tokiuose kaip diagramos ar žemėlapiai).</li> </ul>",
|
||||
"interaction_modal.action": "Norėdami bendrauti su {name} įrašu, turite prisijungti prie savo paskyros bet kuriame Mastodon serveryje, kurį naudojate.",
|
||||
"interaction_modal.go": "Eiti",
|
||||
"interaction_modal.no_account_yet": "Dar neturite paskyros?",
|
||||
"interaction_modal.on_another_server": "Kitame serveryje",
|
||||
"interaction_modal.on_this_server": "Šiame serveryje",
|
||||
"interaction_modal.title": "Jei norite tęsti, prisijunkite",
|
||||
"interaction_modal.username_prompt": "Pvz., {example}",
|
||||
"intervals.full.days": "{number, plural, one {# diena} few {# dienos} many {# dienos} other {# dienų}}",
|
||||
"intervals.full.hours": "{number, plural, one {# valanda} few {# valandos} many {# valandos} other {# valandų}}",
|
||||
@@ -438,6 +497,7 @@
|
||||
"keyboard_shortcuts.home": "Atidaryti pagrindinį laiko skalę",
|
||||
"keyboard_shortcuts.hotkey": "Spartusis klavišas",
|
||||
"keyboard_shortcuts.legend": "Rodyti šią legendą",
|
||||
"keyboard_shortcuts.load_more": "Fokusuoti „Įkelti daugiau“ mygtuką",
|
||||
"keyboard_shortcuts.local": "Atidaryti vietinę laiko skalę",
|
||||
"keyboard_shortcuts.mention": "Paminėti autorių (-ę)",
|
||||
"keyboard_shortcuts.muted": "Atidaryti nutildytų naudotojų sąrašą",
|
||||
@@ -446,6 +506,7 @@
|
||||
"keyboard_shortcuts.open_media": "Atidaryti mediją",
|
||||
"keyboard_shortcuts.pinned": "Atverti prisegtų įrašų sąrašą",
|
||||
"keyboard_shortcuts.profile": "Atidaryti autoriaus (-ės) profilį",
|
||||
"keyboard_shortcuts.quote": "Paminėti įrašą",
|
||||
"keyboard_shortcuts.reply": "Atsakyti į įrašą",
|
||||
"keyboard_shortcuts.requests": "Atidaryti sekimo prašymų sąrašą",
|
||||
"keyboard_shortcuts.search": "Fokusuoti paieškos juostą",
|
||||
@@ -454,9 +515,12 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Rodyti / slėpti tekstą po TĮ",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Rodyti / slėpti mediją",
|
||||
"keyboard_shortcuts.toot": "Pradėti naują įrašą",
|
||||
"keyboard_shortcuts.top": "Perkelti į sąrašo viršų",
|
||||
"keyboard_shortcuts.translate": "išversti įrašą",
|
||||
"keyboard_shortcuts.unfocus": "Nebefokusuoti rengykles teksto sritį / paiešką",
|
||||
"keyboard_shortcuts.up": "Perkelti į viršų sąraše",
|
||||
"learn_more_link.got_it": "Supratau",
|
||||
"learn_more_link.learn_more": "Sužinoti daugiau",
|
||||
"lightbox.close": "Uždaryti",
|
||||
"lightbox.next": "Kitas",
|
||||
"lightbox.previous": "Ankstesnis",
|
||||
@@ -506,8 +570,10 @@
|
||||
"mute_modal.you_wont_see_mentions": "Nematysi įrašus, kuriuose jie paminimi.",
|
||||
"mute_modal.you_wont_see_posts": "Jie vis tiek gali matyti tavo įrašus, bet tu nematysi jų.",
|
||||
"navigation_bar.about": "Apie",
|
||||
"navigation_bar.account_settings": "Slaptažodis ir saugumas",
|
||||
"navigation_bar.administration": "Administravimas",
|
||||
"navigation_bar.advanced_interface": "Atidaryti išplėstinę žiniatinklio sąsają",
|
||||
"navigation_bar.automated_deletion": "Automatinis įrašų ištrynimas",
|
||||
"navigation_bar.blocks": "Užblokuoti naudotojai",
|
||||
"navigation_bar.bookmarks": "Žymės",
|
||||
"navigation_bar.direct": "Privatūs paminėjimai",
|
||||
@@ -517,13 +583,23 @@
|
||||
"navigation_bar.follow_requests": "Sekimo prašymai",
|
||||
"navigation_bar.followed_tags": "Sekami saitažodžiai",
|
||||
"navigation_bar.follows_and_followers": "Sekimai ir sekėjai",
|
||||
"navigation_bar.import_export": "Importas ir eksportas",
|
||||
"navigation_bar.lists": "Sąrašai",
|
||||
"navigation_bar.live_feed_local": "Tiesioginis srautas (vietinis)",
|
||||
"navigation_bar.live_feed_public": "Tiesioginis srautas (viešas)",
|
||||
"navigation_bar.logout": "Atsijungti",
|
||||
"navigation_bar.moderation": "Prižiūrėjimas",
|
||||
"navigation_bar.more": "Daugiau",
|
||||
"navigation_bar.mutes": "Nutildyti naudotojai",
|
||||
"navigation_bar.opened_in_classic_interface": "Įrašai, paskyros ir kiti konkretūs puslapiai pagal numatytuosius nustatymus atidaromi klasikinėje žiniatinklio sąsajoje.",
|
||||
"navigation_bar.preferences": "Nuostatos",
|
||||
"navigation_bar.privacy_and_reach": "Privatumas ir pasiekiamumas",
|
||||
"navigation_bar.search": "Ieškoti",
|
||||
"navigation_bar.search_trends": "Paieška / Populiaru",
|
||||
"navigation_panel.collapse_followed_tags": "Sutraukti sekamų žymių meniu",
|
||||
"navigation_panel.collapse_lists": "Sutraukti sąrašo meniu",
|
||||
"navigation_panel.expand_followed_tags": "Išskleisti sekamų žymių meniu",
|
||||
"navigation_panel.expand_lists": "Išskleisti sąrašo meniu",
|
||||
"not_signed_in_indicator.not_signed_in": "Norint pasiekti šį išteklį, reikia prisijungti.",
|
||||
"notification.admin.report": "{name} pranešė {target}",
|
||||
"notification.admin.report_account": "{name} pranešė {count, plural, one {# įrašą} few {# įrašus} many {# įrašo} other {# įrašų}} iš {target} kategorijai {category}",
|
||||
@@ -535,13 +611,17 @@
|
||||
"notification.annual_report.message": "Jūsų laukia {year} #Wrapstodon! Atskleiskite savo metų svarbiausius įvykius ir įsimintinas akimirkas platformoje „Mastodon“.",
|
||||
"notification.annual_report.view": "Peržiūrėti #Wrapstodon",
|
||||
"notification.favourite": "{name} pamėgo tavo įrašą",
|
||||
"notification.favourite.name_and_others_with_link": "{name} ir <a>{count, plural,one {dar kažkas} few {# kiti} other {# kitų}}</a> pamėgo tavo įrašą",
|
||||
"notification.favourite_pm": "{name} pamėgo jūsų privatų paminėjimą",
|
||||
"notification.favourite_pm.name_and_others_with_link": "{name} ir <a>{count, plural,one {dar kažkas} few {# kiti} other {# kitų}}</a> pamėgo tavo privatų paminėjimą",
|
||||
"notification.follow": "{name} seka tave",
|
||||
"notification.follow.name_and_others": "{name} ir <a>{count, plural, one {# kitas} few {# kiti} many {# kito} other {# kitų}}</a> seka tave",
|
||||
"notification.follow_request": "{name} paprašė tave sekti",
|
||||
"notification.follow_request.name_and_others": "{name} ir {count, plural,one {dar kažkas} few {# kiti} other {# kitų}} pradėjo tave sekti",
|
||||
"notification.label.mention": "Paminėjimas",
|
||||
"notification.label.private_mention": "Privatus paminėjimas",
|
||||
"notification.label.private_reply": "Privatus atsakymas",
|
||||
"notification.label.quote": "{name} paminėjo jūsų įrašą",
|
||||
"notification.label.reply": "Atsakymas",
|
||||
"notification.mention": "Paminėjimas",
|
||||
"notification.mentioned_you": "{name} paminėjo jus",
|
||||
@@ -556,7 +636,9 @@
|
||||
"notification.moderation_warning.action_suspend": "Tavo paskyra buvo sustabdyta.",
|
||||
"notification.own_poll": "Tavo apklausa baigėsi",
|
||||
"notification.poll": "Baigėsi apklausa, kurioje balsavai",
|
||||
"notification.quoted_update": "{name} redagavo jūsų cituotą įrašą",
|
||||
"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.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.",
|
||||
@@ -596,6 +678,7 @@
|
||||
"notifications.column_settings.mention": "Paminėjimai:",
|
||||
"notifications.column_settings.poll": "Balsavimo rezultatai:",
|
||||
"notifications.column_settings.push": "Tiesioginiai pranešimai",
|
||||
"notifications.column_settings.quote": "Paminėjimai:",
|
||||
"notifications.column_settings.reblog": "Pakėlimai:",
|
||||
"notifications.column_settings.show": "Rodyti stulpelyje",
|
||||
"notifications.column_settings.sound": "Paleisti garsą",
|
||||
@@ -623,9 +706,10 @@
|
||||
"notifications.policy.filter": "Filtruoti",
|
||||
"notifications.policy.filter_hint": "Siųsti į filtruotų pranešimų gautiejus",
|
||||
"notifications.policy.filter_limited_accounts_hint": "Apribota serverio prižiūrėtojų",
|
||||
"notifications.policy.filter_limited_accounts_title": "Prižiūrėmi paskyrai",
|
||||
"notifications.policy.filter_limited_accounts_title": "Moderuojamos paskyros",
|
||||
"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_following_hint": "Kol jų nepatvirtinsi rankiniu būdu",
|
||||
"notifications.policy.filter_not_following_title": "Žmonių, kuriuos neseki",
|
||||
"notifications.policy.filter_private_mentions_title": "Nepageidaujami privatūs paminėjimai",
|
||||
@@ -668,10 +752,19 @@
|
||||
"privacy.private.short": "Sekėjai",
|
||||
"privacy.public.long": "Bet kas iš Mastodon ir ne Mastodon",
|
||||
"privacy.public.short": "Vieša",
|
||||
"privacy.quote.anyone": "{visibility}, kiekvienas gali cituoti",
|
||||
"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.short": "Tyliai vieša",
|
||||
"privacy_policy.last_updated": "Paskutinį kartą atnaujinta {date}",
|
||||
"privacy_policy.title": "Privatumo politika",
|
||||
"quote_error.edit": "Paminėjimai negali būti pridedami, kai keičiamas įrašas.",
|
||||
"quote_error.poll": "Cituoti apklausose negalima.",
|
||||
"quote_error.private_mentions": "Cituoti privačius paminėjus nėra leidžiama.",
|
||||
"quote_error.quote": "Leidžiama pateikti tik vieną citatą vienu metu.",
|
||||
"quote_error.unauthorized": "Jums neleidžiama cituoti šio įrašo.",
|
||||
"quote_error.upload": "Cituoti ir pridėti papildomas bylas negalima.",
|
||||
"recommended": "Rekomenduojama",
|
||||
"refresh": "Atnaujinti",
|
||||
"regeneration_indicator.please_stand_by": "Laukite.",
|
||||
@@ -687,6 +780,9 @@
|
||||
"relative_time.minutes": "{number} min.",
|
||||
"relative_time.seconds": "{number} sek.",
|
||||
"relative_time.today": "šiandien",
|
||||
"remove_quote_hint.button_label": "Supratau",
|
||||
"remove_quote_hint.message": "Tai galite padaryti iš {icon} parinkčių meniu.",
|
||||
"remove_quote_hint.title": "Norite pašalinti savo citatą?",
|
||||
"reply_indicator.attachments": "{count, plural, one {# priedas} few {# priedai} many {# priedo} other {# priedų}}",
|
||||
"reply_indicator.cancel": "Atšaukti",
|
||||
"reply_indicator.poll": "Apklausa",
|
||||
@@ -748,7 +844,7 @@
|
||||
"search.quick_action.open_url": "Atidaryti URL adresą Mastodon",
|
||||
"search.quick_action.status_search": "Pranešimai, atitinkantys {x}",
|
||||
"search.search_or_paste": "Ieškoti arba įklijuoti URL",
|
||||
"search_popout.full_text_search_disabled_message": "Nepasiekima {domain}.",
|
||||
"search_popout.full_text_search_disabled_message": "Paieška {domain} įrašuose išjungta.",
|
||||
"search_popout.full_text_search_logged_out_message": "Pasiekiama tik prisijungus.",
|
||||
"search_popout.language_code": "ISO kalbos kodas",
|
||||
"search_popout.options": "Paieškos nustatymai",
|
||||
@@ -777,10 +873,13 @@
|
||||
"status.admin_account": "Atidaryti prižiūrėjimo sąsają @{name}",
|
||||
"status.admin_domain": "Atidaryti prižiūrėjimo sąsają {domain}",
|
||||
"status.admin_status": "Atidaryti šį įrašą prižiūrėjimo sąsajoje",
|
||||
"status.all_disabled": "Įrašo pakėlimai ir paminėjimai išjungti",
|
||||
"status.block": "Blokuoti @{name}",
|
||||
"status.bookmark": "Pridėti į žymės",
|
||||
"status.cancel_reblog_private": "Nebepasidalinti",
|
||||
"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.continued_thread": "Tęsiama gijoje",
|
||||
"status.copy": "Kopijuoti nuorodą į įrašą",
|
||||
"status.delete": "Ištrinti",
|
||||
@@ -790,6 +889,7 @@
|
||||
"status.edit": "Redaguoti",
|
||||
"status.edited": "Paskutinį kartą redaguota {date}",
|
||||
"status.edited_x_times": "Redaguota {count, plural, one {{count} kartą} few {{count} kartus} many {{count} karto} other {{count} kartų}}",
|
||||
"status.embed": "Gaukite įterpimo kodą",
|
||||
"status.favourite": "Pamėgti",
|
||||
"status.filter": "Filtruoti šį įrašą",
|
||||
"status.history.created": "{name} sukurta {date}",
|
||||
@@ -804,18 +904,43 @@
|
||||
"status.mute_conversation": "Nutildyti pokalbį",
|
||||
"status.open": "Išplėsti šį įrašą",
|
||||
"status.pin": "Prisegti prie profilio",
|
||||
"status.quote": "Paminėjimai",
|
||||
"status.quote.cancel": "Atšaukti paminėjimą",
|
||||
"status.quote_error.blocked_account_hint.title": "Šis įrašas yra paslėptas, nes jūs esate užblokavę @{name}.",
|
||||
"status.quote_error.blocked_domain_hint.title": "Šis įrašas yra paslėptas, nes jūs užblokavote {domain}.",
|
||||
"status.quote_error.filtered": "Paslėpta dėl vieno iš jūsų filtrų",
|
||||
"status.quote_error.limited_account_hint.action": "Vis tiek rodyti",
|
||||
"status.quote_error.limited_account_hint.title": "Šis paskyra buvo paslėpta {domain} moderatorių.",
|
||||
"status.quote_error.muted_account_hint.title": "Šis įrašas yra paslėptas, nes jūs esate užtildę @{name}.",
|
||||
"status.quote_error.not_available": "Įrašas nepasiekiamas",
|
||||
"status.quote_error.pending_approval": "Įrašas peržiūrimas",
|
||||
"status.quote_error.pending_approval_popout.body": "„Mastodon“ galite kontroliuoti, ar kas nors gali jus cituoti (paminėti). Šis įrašas bus laukimo būsenoje, kol gausite originalaus įrašo autoriaus sutikimą.",
|
||||
"status.quote_error.revoked": "Autorius pašalino įrašą",
|
||||
"status.quote_followers_only": "Tik sekėjai gali cituoti šį įrašą",
|
||||
"status.quote_manual_review": "Autorius atskirai įvertins paskelbimą",
|
||||
"status.quote_noun": "Paminėjimas",
|
||||
"status.quote_policy_change": "Keisti, kas gali cituoti",
|
||||
"status.quote_post_author": "Paminėjo įrašą iš @{name}",
|
||||
"status.quote_private": "Privačių įrašų negalima cituoti",
|
||||
"status.quotes.empty": "Šio įrašo dar niekas nepaminėjo. Kai kas nors tai padarys, jie bus rodomi čia.",
|
||||
"status.quotes.local_other_disclaimer": "Autoriaus atmesti įrašo paminėjimai nebus rodomi.",
|
||||
"status.quotes.remote_other_disclaimer": "Čia bus rodoma tik paminėjimai iš {domain}. Autoriaus atmesti įrašo paminėjimai nebus rodomi.",
|
||||
"status.read_more": "Skaityti daugiau",
|
||||
"status.reblog": "Pakelti",
|
||||
"status.reblog_or_quote": "Paryškinti arba cituoti",
|
||||
"status.reblogged_by": "{name} pakėlė",
|
||||
"status.reblogs.empty": "Šio įrašo dar niekas nepakėlė. Kai kas nors tai padarys, jie bus rodomi čia.",
|
||||
"status.redraft": "Ištrinti ir parengti iš naujo",
|
||||
"status.remove_bookmark": "Pašalinti žymę",
|
||||
"status.remove_favourite": "Šalinti iš mėgstamų",
|
||||
"status.remove_quote": "Pašalinti",
|
||||
"status.replied_in_thread": "Atsakyta gijoje",
|
||||
"status.replied_to": "Atsakyta į {name}",
|
||||
"status.reply": "Atsakyti",
|
||||
"status.replyAll": "Atsakyti į giją",
|
||||
"status.report": "Pranešti apie @{name}",
|
||||
"status.request_quote": "Citavimo sutikimas",
|
||||
"status.revoke_quote": "Pašalinti mano įrašo citavimą iš @{name}’s įrašo",
|
||||
"status.sensitive_warning": "Jautrus turinys",
|
||||
"status.share": "Bendrinti",
|
||||
"status.show_less_all": "Rodyti mažiau visiems",
|
||||
@@ -850,6 +975,7 @@
|
||||
"upload_button.label": "Pridėti vaizdų, vaizdo įrašą arba garso failą",
|
||||
"upload_error.limit": "Viršyta failo įkėlimo riba.",
|
||||
"upload_error.poll": "Failų įkėlimas neleidžiamas su apklausomis.",
|
||||
"upload_error.quote": "Paminint įrašą bylos įkėlimas negalimas.",
|
||||
"upload_form.drag_and_drop.instructions": "Kad paimtum medijos priedą, paspausk tarpo arba įvedimo klavišą. Tempant naudok rodyklių klavišus, kad perkeltum medijos priedą bet kuria kryptimi. Dar kartą paspausk tarpo arba įvedimo klavišą, kad nuleistum medijos priedą naujoje vietoje, arba paspausk grįžimo klavišą, kad atšauktum.",
|
||||
"upload_form.drag_and_drop.on_drag_cancel": "Nutempimas buvo atšauktas. Medijos priedas {item} buvo nuleistas.",
|
||||
"upload_form.drag_and_drop.on_drag_end": "Medijos priedas {item} buvo nuleistas.",
|
||||
@@ -868,5 +994,15 @@
|
||||
"video.mute": "Išjungti garsą",
|
||||
"video.pause": "Pristabdyti",
|
||||
"video.play": "Leisti",
|
||||
"video.skip_backward": "Praleisti atgal"
|
||||
"video.skip_backward": "Praleisti atgal",
|
||||
"visibility_modal.direct_quote_warning.text": "Jei išsaugosite dabartinius nustatymus, įterpta citata bus konvertuota į nuorodą.",
|
||||
"visibility_modal.direct_quote_warning.title": "Cituojami įrašai negali būti įterpiami į privačius paminėjimus",
|
||||
"visibility_modal.helper.direct_quoting": "Privatūs paminėjimai, parašyti platformoje „Mastodon“, negali būti cituojami kitų.",
|
||||
"visibility_modal.helper.privacy_private_self_quote": "Privačių įrašų paminėjimai negali būti skelbiami viešai.",
|
||||
"visibility_modal.helper.private_quoting": "Tik sekėjams skirti įrašai, parašyti platformoje „Mastodon“, negali būti cituojami kitų.",
|
||||
"visibility_modal.helper.unlisted_quoting": "Kai žmonės jus cituos, jų įrašai taip pat bus paslėpti iš populiariausių naujienų srauto.",
|
||||
"visibility_modal.quote_followers": "Tik sekėjai",
|
||||
"visibility_modal.quote_label": "Kas gali cituoti",
|
||||
"visibility_modal.quote_nobody": "Tik aš",
|
||||
"visibility_modal.quote_public": "Visi"
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"account.badges.bot": "機器lâng",
|
||||
"account.badges.group": "群組",
|
||||
"account.block": "封鎖 @{name}",
|
||||
"account.block_domain": "封鎖網域 {domain}",
|
||||
"account.block_domain": "封鎖域名 {domain}",
|
||||
"account.block_short": "封鎖",
|
||||
"account.blocked": "Hőng封鎖",
|
||||
"account.blocking": "Teh封鎖",
|
||||
@@ -26,7 +26,7 @@
|
||||
"account.copy": "Khóo-pih個人資料ê連結",
|
||||
"account.direct": "私人提起 @{name}",
|
||||
"account.disable_notifications": "停止佇 {name} PO文ê時通知我",
|
||||
"account.domain_blocking": "Teh封鎖ê網域",
|
||||
"account.domain_blocking": "Teh封鎖ê域名",
|
||||
"account.edit_profile": "編輯個人資料",
|
||||
"account.edit_profile_short": "編輯",
|
||||
"account.enable_notifications": "佇 {name} PO文ê時通知我",
|
||||
@@ -344,7 +344,7 @@
|
||||
"empty_column.community": "本站時間線是空ê。緊來公開PO文oh!",
|
||||
"empty_column.direct": "Lí iáu無任何ê私人訊息。Nā是lí送á是收著私人訊息,ē佇tsia顯示。.",
|
||||
"empty_column.disabled_feed": "Tsit ê feed已經hōo lí ê服侍器ê管理員停用。",
|
||||
"empty_column.domain_blocks": "Iáu無封鎖任何網域。",
|
||||
"empty_column.domain_blocks": "Iáu無封鎖任何域名。",
|
||||
"empty_column.explore_statuses": "目前iáu無有流行ê趨勢,請sió等tsi̍t-ē,koh確認。",
|
||||
"empty_column.favourited_statuses": "Lí iáu無加添任何收藏 ê PO文。Nā是lí加收藏,伊ē佇tsia顯示。",
|
||||
"empty_column.favourites": "Iáu無lâng收藏tsit篇PO文。Nā是有lâng收藏,ē佇tsia顯示。",
|
||||
@@ -516,6 +516,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "顯示/隱藏內容警告後壁ê PO文",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "顯示/tshàng媒體",
|
||||
"keyboard_shortcuts.toot": "PO新PO文",
|
||||
"keyboard_shortcuts.top": "Súa kàu列單ê頭",
|
||||
"keyboard_shortcuts.translate": "kā PO文翻譯",
|
||||
"keyboard_shortcuts.unfocus": "離開輸入框仔/tshiau-tshuē格仔",
|
||||
"keyboard_shortcuts.up": "佇列單內kā suá khah面頂",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Beschrijf dit voor blinden en slechtzienden…",
|
||||
"alt_text_modal.done": "Klaar",
|
||||
"announcement.announcement": "Mededeling",
|
||||
"annual_report.announcement.action_build": "Bouw mijn Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Bekijk mijn Wrapstodon",
|
||||
"annual_report.announcement.description": "Ontdek meer over jouw engagement op Mastodon over het afgelopen jaar.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} is gearriveerd",
|
||||
"annual_report.summary.archetype.booster": "De cool-hunter",
|
||||
"annual_report.summary.archetype.lurker": "De lurker",
|
||||
"annual_report.summary.archetype.oracle": "Het orakel",
|
||||
@@ -357,6 +361,7 @@
|
||||
"empty_column.notification_requests": "Helemaal leeg! Er is hier niets. Wanneer je nieuwe meldingen ontvangt, verschijnen deze hier volgens jouw instellingen.",
|
||||
"empty_column.notifications": "Je hebt nog geen meldingen. Begin met iemand een gesprek.",
|
||||
"empty_column.public": "Er is hier helemaal niks! Plaatst een openbaar bericht of volg mensen van andere servers om het te vullen",
|
||||
"error.no_hashtag_feed_access": "Registreren of inloggen om de hashtag te bekijken of te volgen.",
|
||||
"error.unexpected_crash.explanation": "Als gevolg van een bug in onze broncode of als gevolg van een compatibiliteitsprobleem met jouw webbrowser, kan deze pagina niet goed worden weergegeven.",
|
||||
"error.unexpected_crash.explanation_addons": "Deze pagina kon niet correct geladen worden. Deze fout wordt waarschijnlijk door een browser-add-on of een automatische vertalingshulpmiddel veroorzaakt.",
|
||||
"error.unexpected_crash.next_steps": "Probeer deze pagina te vernieuwen. Wanneer dit niet helpt is het nog steeds mogelijk om Mastodon in een andere webbrowser of mobiele app te gebruiken.",
|
||||
@@ -515,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Inhoudswaarschuwing tonen/verbergen",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Media tonen/verbergen",
|
||||
"keyboard_shortcuts.toot": "Nieuw bericht schrijven",
|
||||
"keyboard_shortcuts.top": "Naar het begin van de lijst verplaatsen",
|
||||
"keyboard_shortcuts.translate": "om een bericht te vertalen",
|
||||
"keyboard_shortcuts.unfocus": "Tekst- en zoekveld ontfocussen",
|
||||
"keyboard_shortcuts.up": "Naar boven in de lijst bewegen",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Skriv ei skildring for menneske med synsnedsetjingar…",
|
||||
"alt_text_modal.done": "Ferdig",
|
||||
"announcement.announcement": "Kunngjering",
|
||||
"annual_report.announcement.action_build": "Set saman min Årstodon",
|
||||
"annual_report.announcement.action_view": "Sjå min Årstodon",
|
||||
"annual_report.announcement.description": "Sjå meir om kva du har gjort på Mastodon siste året.",
|
||||
"annual_report.announcement.title": "Årstodon {year} er her",
|
||||
"annual_report.summary.archetype.booster": "Den som jaktar på noko kult",
|
||||
"annual_report.summary.archetype.lurker": "Den som heng på hjørnet",
|
||||
"annual_report.summary.archetype.oracle": "Orakelet",
|
||||
@@ -332,8 +336,8 @@
|
||||
"emoji_button.search_results": "Søkeresultat",
|
||||
"emoji_button.symbols": "Symbol",
|
||||
"emoji_button.travel": "Reise & stader",
|
||||
"empty_column.account_featured.me": "Du har ikkje valt ut noko enno. Visste du at du kan velja ut merkelappar du bruker mykje, og til og med venekontoar på profilen din?",
|
||||
"empty_column.account_featured.other": "{acct} har ikkje valt ut noko enno. Visste du at du kan velja ut merkelappar du bruker mykje, og til og med venekontoar på profilen din?",
|
||||
"empty_column.account_featured.me": "Du har ikkje valt ut noko enno. Visste du at du kan velja ut emneknaggar du bruker mykje, og til og med venekontoar på profilen din?",
|
||||
"empty_column.account_featured.other": "{acct} har ikkje valt ut noko enno. Visste du at du kan velja ut emneknaggar du bruker mykje, og til og med venekontoar på profilen din?",
|
||||
"empty_column.account_featured_other.unknown": "Denne kontoen har ikkje valt ut noko enno.",
|
||||
"empty_column.account_hides_collections": "Denne brukaren har valt å ikkje gjere denne informasjonen tilgjengeleg",
|
||||
"empty_column.account_suspended": "Kontoen er utestengd",
|
||||
@@ -357,6 +361,7 @@
|
||||
"empty_column.notification_requests": "Ferdig! Her er det ingenting. Når du får nye varsel, kjem dei opp her slik du har valt.",
|
||||
"empty_column.notifications": "Du har ingen varsel enno. Kommuniser med andre for å starte samtalen.",
|
||||
"empty_column.public": "Det er ingenting her! Skriv noko offentleg, eller fylg brukarar frå andre tenarar manuelt for å få meir her",
|
||||
"error.no_hashtag_feed_access": "Bli medlem eller logg inn for å sjå og fylgja denne emneknaggen.",
|
||||
"error.unexpected_crash.explanation": "På grunn av eit nettlesarkompatibilitetsproblem eller ein feil i koden vår, kunne ikkje denne sida bli vist slik den skal.",
|
||||
"error.unexpected_crash.explanation_addons": "Denne sida kunne ikkje visast som den skulle. Feilen kjem truleg frå ei nettleserutviding eller frå automatiske omsetjingsverktøy.",
|
||||
"error.unexpected_crash.next_steps": "Prøv å lasta inn sida på nytt. Hjelper ikkje dette kan du framleis nytta Mastodon i ein annan nettlesar eller app.",
|
||||
@@ -515,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Vis/gøym tekst bak innhaldsvarsel",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Vis/gøym media",
|
||||
"keyboard_shortcuts.toot": "Lag nytt tut",
|
||||
"keyboard_shortcuts.top": "Flytt til toppen av lista",
|
||||
"keyboard_shortcuts.translate": "å omsetje eit innlegg",
|
||||
"keyboard_shortcuts.unfocus": "for å fokusere vekk skrive-/søkefeltet",
|
||||
"keyboard_shortcuts.up": "Flytt opp på lista",
|
||||
@@ -595,9 +601,9 @@
|
||||
"navigation_bar.privacy_and_reach": "Personvern og rekkjevidd",
|
||||
"navigation_bar.search": "Søk",
|
||||
"navigation_bar.search_trends": "Søk / Populært",
|
||||
"navigation_panel.collapse_followed_tags": "Gøym menyen over merkelappar du fylgjer",
|
||||
"navigation_panel.collapse_followed_tags": "Gøym menyen over emneknaggar du fylgjer",
|
||||
"navigation_panel.collapse_lists": "Gøym listemenyen",
|
||||
"navigation_panel.expand_followed_tags": "Utvid menyen over merkelappar du fylgjer",
|
||||
"navigation_panel.expand_followed_tags": "Utvid menyen over emneknaggar du fylgjer",
|
||||
"navigation_panel.expand_lists": "Utvid listemenyen",
|
||||
"not_signed_in_indicator.not_signed_in": "Du må logga inn for å få tilgang til denne ressursen.",
|
||||
"notification.admin.report": "{name} rapporterte {target}",
|
||||
@@ -758,7 +764,7 @@
|
||||
"privacy.quote.anyone": "{visibility}, alle kan sitera",
|
||||
"privacy.quote.disabled": "{visibility}, ingen kan sitera",
|
||||
"privacy.quote.limited": "{visibility}, avgrensa sitat",
|
||||
"privacy.unlisted.additional": "Dette er akkurat som offentleg, bortsett frå at innlegga ikkje dukkar opp i direktestraumar eller merkelappar, i oppdagingar eller Mastodon-søk, sjølv om du har sagt ja til at kontoen skal vera synleg.",
|
||||
"privacy.unlisted.additional": "Dette er akkurat som offentleg, bortsett frå at innlegga ikkje dukkar opp i direktestraumar eller emneknaggar, i oppdagingar eller Mastodon-søk, sjølv om du har sagt ja til at kontoen skal vera synleg.",
|
||||
"privacy.unlisted.long": "Gøymt frå søkjeresultata på Mastodon, og frå populære og offentlege tidsliner",
|
||||
"privacy.unlisted.short": "Stille offentleg",
|
||||
"privacy_policy.last_updated": "Sist oppdatert {date}",
|
||||
@@ -861,7 +867,7 @@
|
||||
"search_results.all": "Alt",
|
||||
"search_results.hashtags": "Emneknaggar",
|
||||
"search_results.no_results": "Ingen resultat.",
|
||||
"search_results.no_search_yet": "Prøv å søkja etter innlegg, profilar eller merkelappar.",
|
||||
"search_results.no_search_yet": "Prøv å søkja etter innlegg, profilar eller emneknaggar.",
|
||||
"search_results.see_all": "Sjå alle",
|
||||
"search_results.statuses": "Tut",
|
||||
"search_results.title": "Søk etter \"{q}\"",
|
||||
|
||||
@@ -55,11 +55,11 @@
|
||||
"account.follows.empty": "Nada aqui.",
|
||||
"account.follows_you": "Segue você",
|
||||
"account.go_to_profile": "Ir ao perfil",
|
||||
"account.hide_reblogs": "Ocultar boosts de @{name}",
|
||||
"account.hide_reblogs": "Ocultar impulsionamentos de @{name}",
|
||||
"account.in_memoriam": "Em memória.",
|
||||
"account.joined_short": "Entrou",
|
||||
"account.languages": "Mudar idiomas inscritos",
|
||||
"account.link_verified_on": "link verificado em {date}",
|
||||
"account.link_verified_on": "A propriedade deste link foi verificada em {date}",
|
||||
"account.locked_info": "Trancado. Seguir requer aprovação manual do perfil.",
|
||||
"account.media": "Mídia",
|
||||
"account.mention": "Mencionar @{name}",
|
||||
@@ -79,7 +79,7 @@
|
||||
"account.requested_follow": "{name} quer te seguir",
|
||||
"account.requests_to_follow_you": "Pediu para seguir você",
|
||||
"account.share": "Compartilhar perfil de @{name}",
|
||||
"account.show_reblogs": "Mostrar boosts de @{name}",
|
||||
"account.show_reblogs": "Mostrar impulsionamentos de @{name}",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} publicação} other {{counter} publicações}}",
|
||||
"account.unblock": "Desbloquear @{name}",
|
||||
"account.unblock_domain": "Desbloquear domínio {domain}",
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Descreva isto para pessoas com deficiências visuais…",
|
||||
"alt_text_modal.done": "Feito",
|
||||
"announcement.announcement": "Comunicados",
|
||||
"annual_report.announcement.action_build": "Gerar meu Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Ver meu Wrapstodon",
|
||||
"annual_report.announcement.description": "Descubra mais sobre seu engajamento no Mastodon ao longo do último ano.",
|
||||
"annual_report.announcement.title": "Chegou o Wrapstodon de {year}",
|
||||
"annual_report.summary.archetype.booster": "Caçador legal",
|
||||
"annual_report.summary.archetype.lurker": "O espreitador",
|
||||
"annual_report.summary.archetype.oracle": "O oráculo",
|
||||
@@ -142,9 +146,9 @@
|
||||
"block_modal.they_will_know": "Poderá ver que você bloqueou.",
|
||||
"block_modal.title": "Bloquear usuário?",
|
||||
"block_modal.you_wont_see_mentions": "Você não verá publicações que mencionem o usuário.",
|
||||
"boost_modal.combo": "Pressione {combo} para pular isso na próxima vez",
|
||||
"boost_modal.combo": "Pressione {combo} para pular isto na próxima vez",
|
||||
"boost_modal.reblog": "Impulsionar a publicação?",
|
||||
"boost_modal.undo_reblog": "Retirar o impulsionamento do post?",
|
||||
"boost_modal.undo_reblog": "Retirar o impulso do post?",
|
||||
"bundle_column_error.copy_stacktrace": "Copiar relatório do erro",
|
||||
"bundle_column_error.error.body": "A página solicitada não pôde ser renderizada. Pode ser devido a um erro no nosso código, ou um problema de compatibilidade do seu navegador.",
|
||||
"bundle_column_error.error.title": "Ah, não!",
|
||||
@@ -259,7 +263,7 @@
|
||||
"confirmations.quiet_post_quote_info.message": "Ao citar uma publicação pública silenciosa, sua postagem será oculta das linhas de tempo em tendência.",
|
||||
"confirmations.quiet_post_quote_info.title": "Citando publicações públicas silenciadas",
|
||||
"confirmations.redraft.confirm": "Excluir e rascunhar",
|
||||
"confirmations.redraft.message": "Você tem certeza de que quer apagar essa postagem e rascunhá-la? Favoritos e impulsos serão perdidos, e respostas à postagem original ficarão órfãs.",
|
||||
"confirmations.redraft.message": "Você tem certeza de que quer apagar essa publicação e rascunhá-la? Favoritos e impulsos serão perdidos, e respostas à postagem original ficarão órfãs.",
|
||||
"confirmations.redraft.title": "Excluir e rascunhar publicação?",
|
||||
"confirmations.remove_from_followers.confirm": "Remover seguidor",
|
||||
"confirmations.remove_from_followers.message": "{name} vai parar de te seguir. Tem certeza de que deseja continuar?",
|
||||
@@ -293,7 +297,7 @@
|
||||
"dismissable_banner.dismiss": "Dispensar",
|
||||
"dismissable_banner.public_timeline": "Estas são as publicações mais recentes das pessoas no fediverso que as pessoas do {domain} seguem.",
|
||||
"domain_block_modal.block": "Bloquear servidor",
|
||||
"domain_block_modal.block_account_instead": "Bloquear @{name}",
|
||||
"domain_block_modal.block_account_instead": "Bloquear @{name} em vez disso",
|
||||
"domain_block_modal.they_can_interact_with_old_posts": "Pessoas deste servidor podem interagir com suas publicações antigas.",
|
||||
"domain_block_modal.they_cant_follow": "Ninguém deste servidor pode lhe seguir.",
|
||||
"domain_block_modal.they_wont_know": "Eles não saberão que foram bloqueados.",
|
||||
@@ -452,7 +456,7 @@
|
||||
"hints.profiles.see_more_follows": "Ver mais seguidos no {domain}",
|
||||
"hints.profiles.see_more_posts": "Ver mais publicações em {domain}",
|
||||
"home.column_settings.show_quotes": "Mostrar citações",
|
||||
"home.column_settings.show_reblogs": "Mostrar boosts",
|
||||
"home.column_settings.show_reblogs": "Mostrar impulsos",
|
||||
"home.column_settings.show_replies": "Mostrar respostas",
|
||||
"home.hide_announcements": "Ocultar comunicados",
|
||||
"home.pending_critical_update.body": "Por favor, atualize o seu servidor Mastodon o mais rápido possível!",
|
||||
@@ -484,7 +488,7 @@
|
||||
"intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}",
|
||||
"keyboard_shortcuts.back": "voltar",
|
||||
"keyboard_shortcuts.blocked": "abrir usuários bloqueados",
|
||||
"keyboard_shortcuts.boost": "dar boost",
|
||||
"keyboard_shortcuts.boost": "Impulsionar a publicação",
|
||||
"keyboard_shortcuts.column": "focar na coluna",
|
||||
"keyboard_shortcuts.compose": "focar no compositor",
|
||||
"keyboard_shortcuts.description": "Descrição",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "expandir/ocultar aviso de conteúdo",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "mostrar/ocultar mídia",
|
||||
"keyboard_shortcuts.toot": "compor novo toot",
|
||||
"keyboard_shortcuts.top": "Mover para o topo da lista",
|
||||
"keyboard_shortcuts.translate": "Para traduzir um post",
|
||||
"keyboard_shortcuts.unfocus": "desfocar de tudo",
|
||||
"keyboard_shortcuts.up": "mover para cima",
|
||||
@@ -608,7 +613,7 @@
|
||||
"notification.admin.report_statuses_other": "{name} denunciou {target}",
|
||||
"notification.admin.sign_up": "{name} se inscreveu",
|
||||
"notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# other} other {# outros}}",
|
||||
"notification.annual_report.message": "O #Wrapstodon do seu {year} está esperando! Desvende seus destaques do ano e momentos memoráveis no Mastodon!",
|
||||
"notification.annual_report.message": "O seu #Wrapstodon de {year} está esperando! Desvende seus destaques do ano e momentos memoráveis no Mastodon!",
|
||||
"notification.annual_report.view": "Ver #Wrapstodon",
|
||||
"notification.favourite": "{name} favoritou sua publicação",
|
||||
"notification.favourite.name_and_others_with_link": "{name} e <a>{count, plural, one {# outro} other {# others}}</a> favoritaram a publicação",
|
||||
@@ -637,7 +642,7 @@
|
||||
"notification.own_poll": "Sua enquete terminou",
|
||||
"notification.poll": "Uma enquete que você votou terminou",
|
||||
"notification.quoted_update": "{name} editou uma pulicação que você citou",
|
||||
"notification.reblog": "{name} deu boost no teu toot",
|
||||
"notification.reblog": "{name} impulsionou sua publicação",
|
||||
"notification.reblog.name_and_others_with_link": "{name} e <a>{count, plural, one {# outra} other {# outras}}</a> impulsionaram a publicação",
|
||||
"notification.relationships_severance_event": "Conexões perdidas com {name}",
|
||||
"notification.relationships_severance_event.account_suspension": "Um administrador de {from} suspendeu {target}, o que significa que você não pode mais receber atualizações deles ou interagir com eles.",
|
||||
@@ -681,7 +686,7 @@
|
||||
"notifications.column_settings.poll": "Enquetes:",
|
||||
"notifications.column_settings.push": "Notificações push",
|
||||
"notifications.column_settings.quote": "Citações:",
|
||||
"notifications.column_settings.reblog": "Boosts:",
|
||||
"notifications.column_settings.reblog": "Impulsos:",
|
||||
"notifications.column_settings.show": "Mostrar na coluna",
|
||||
"notifications.column_settings.sound": "Tocar som",
|
||||
"notifications.column_settings.status": "Novos toots:",
|
||||
@@ -689,7 +694,7 @@
|
||||
"notifications.column_settings.unread_notifications.highlight": "Destacar notificações não lidas",
|
||||
"notifications.column_settings.update": "Editar:",
|
||||
"notifications.filter.all": "Tudo",
|
||||
"notifications.filter.boosts": "Boosts",
|
||||
"notifications.filter.boosts": "Impulsionamentos",
|
||||
"notifications.filter.favourites": "Favoritos",
|
||||
"notifications.filter.follows": "Seguidores",
|
||||
"notifications.filter.mentions": "Menções",
|
||||
@@ -879,12 +884,12 @@
|
||||
"status.admin_account": "Abrir interface de moderação para @{name}",
|
||||
"status.admin_domain": "Abrir interface de moderação para {domain}",
|
||||
"status.admin_status": "Abrir este toot na interface de moderação",
|
||||
"status.all_disabled": "Acelerações e citações estão desabilitados",
|
||||
"status.all_disabled": "Impulsos e citações estão desabilitados",
|
||||
"status.block": "Bloquear @{name}",
|
||||
"status.bookmark": "Salvar",
|
||||
"status.cancel_reblog_private": "Desfazer boost",
|
||||
"status.cancel_reblog_private": "Desfazer impulso",
|
||||
"status.cannot_quote": "Você não tem permissão para citar esta publicação",
|
||||
"status.cannot_reblog": "Este toot não pode receber boost",
|
||||
"status.cannot_reblog": "Esta publicação não pode ser impulsionada",
|
||||
"status.contains_quote": "Contém citação",
|
||||
"status.context.loading": "Carregando mais respostas",
|
||||
"status.context.loading_error": "Não foi possível carregar novas respostas",
|
||||
@@ -903,7 +908,7 @@
|
||||
"status.edited": "Última edição em {date}",
|
||||
"status.edited_x_times": "Editado {count, plural, one {{count} hora} other {{count} vezes}}",
|
||||
"status.embed": "Obter código de incorporação",
|
||||
"status.favourite": "Favorita",
|
||||
"status.favourite": "Favoritar",
|
||||
"status.favourites_count": "{count, plural, one {{counter} favorito} other {{counter} favoritos}}",
|
||||
"status.filter": "Filtrar esta publicação",
|
||||
"status.history.created": "{name} criou {date}",
|
||||
@@ -941,12 +946,12 @@
|
||||
"status.quotes.remote_other_disclaimer": "Apenas citações do {domain} têm a garantia de serem exibidas aqui. Citações rejeitadas pelo autor não serão exibidas.",
|
||||
"status.quotes_count": "{count, plural, one {{counter} citação} other {{counter} citações}}",
|
||||
"status.read_more": "Ler mais",
|
||||
"status.reblog": "Dar boost",
|
||||
"status.reblog_or_quote": "Dar boost ou citar",
|
||||
"status.reblog": "Impulsionar",
|
||||
"status.reblog_or_quote": "Impulsionar ou citar",
|
||||
"status.reblog_private": "Compartilhar novamente com seus seguidores",
|
||||
"status.reblogged_by": "{name} deu boost",
|
||||
"status.reblogs.empty": "Nada aqui. Quando alguém der boost, o usuário aparecerá aqui.",
|
||||
"status.reblogs_count": "{count, plural, one {{counter} boost} other {{counter} boosts}}",
|
||||
"status.reblogged_by": "{name} impulsionou",
|
||||
"status.reblogs.empty": "Ninguém impulsionou esta publicação ainda. Quando alguém o fizer, o usuário aparecerá aqui.",
|
||||
"status.reblogs_count": "{count, plural, one {{counter} impulso} other {{counter} impulsos}}",
|
||||
"status.redraft": "Excluir e rascunhar",
|
||||
"status.remove_bookmark": "Remover do Salvos",
|
||||
"status.remove_favourite": "Remover dos favoritos",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Descreve isto para pessoas com problemas de visão…",
|
||||
"alt_text_modal.done": "Concluído",
|
||||
"announcement.announcement": "Mensagem de manutenção",
|
||||
"annual_report.announcement.action_build": "Criar o meu Wrapstodon",
|
||||
"annual_report.announcement.action_view": "Ver o meu Wrapstodon",
|
||||
"annual_report.announcement.description": "Descobre mais sobre o teu envolvimento com o Mastodon durante o último ano.",
|
||||
"annual_report.announcement.title": "Chegou o Wrapstodon {year}",
|
||||
"annual_report.summary.archetype.booster": "O caçador de tendências",
|
||||
"annual_report.summary.archetype.lurker": "O espreitador",
|
||||
"annual_report.summary.archetype.oracle": "O oráculo",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "mostrar / esconder texto atrás do aviso de conteúdo",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "mostrar / ocultar multimédia",
|
||||
"keyboard_shortcuts.toot": "criar uma nova publicação",
|
||||
"keyboard_shortcuts.top": "Mover para o topo da lista",
|
||||
"keyboard_shortcuts.translate": "traduzir uma publicação",
|
||||
"keyboard_shortcuts.unfocus": "remover o foco da área de texto / pesquisa",
|
||||
"keyboard_shortcuts.up": "mover para cima na lista",
|
||||
|
||||
@@ -512,6 +512,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Për shfaqje/fshehje teksti pas CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Për shfaqje/fshehje mediash",
|
||||
"keyboard_shortcuts.toot": "Për të filluar një mesazh të ri",
|
||||
"keyboard_shortcuts.top": "Shpjere në krye të listës",
|
||||
"keyboard_shortcuts.translate": "për të përkthyer një postim",
|
||||
"keyboard_shortcuts.unfocus": "Për heqjen e fokusit nga fusha e hartimit të mesazheve apo kërkimeve",
|
||||
"keyboard_shortcuts.up": "Për ngjitje sipër nëpër listë",
|
||||
|
||||
@@ -516,6 +516,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "Visa/gömma text bakom CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Visa/gömma media",
|
||||
"keyboard_shortcuts.toot": "Starta nytt inlägg",
|
||||
"keyboard_shortcuts.top": "Flytta till början av listan",
|
||||
"keyboard_shortcuts.translate": "för att översätta ett inlägg",
|
||||
"keyboard_shortcuts.unfocus": "Avfokusera skrivfält/sökfält",
|
||||
"keyboard_shortcuts.up": "Flytta uppåt i listan",
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
"about.default_locale": "ante ala",
|
||||
"about.disclaimer": "ilo Mastodon la jan ale li lawa e ona li pana e pona tawa ona. kulupu esun Mastodon gGmbH li lawa e nimi ona.",
|
||||
"about.domain_blocks.no_reason_available": "mi sona ala e tan",
|
||||
"about.domain_blocks.preamble": "ilo Masoton li ken e ni: sina lukin e toki jan pi ma ilo mute. sina ken toki tawa ona lon kulupu ma. taso, ma ni li ken ala e ni tawa ma ni:",
|
||||
"about.domain_blocks.preamble": "ilo Mastodon li ken e ni: sina lukin e toki jan pi ma ilo mute. sina ken toki tawa ona lon kulupu ma. taso, ma ni li ken ala e ni tawa ma ni:",
|
||||
"about.domain_blocks.silenced.explanation": "sina lukin ala e toki e jan tan ma ni. taso, sina wile la, sina ken ni.",
|
||||
"about.domain_blocks.silenced.title": "ken lukin lili ",
|
||||
"about.domain_blocks.suspended.explanation": "sona ale pi ma ni li kama pali ala, li kama esun ala, li kama awen ala la sina ken ala toki tawa jan pi ma ni.",
|
||||
"about.domain_blocks.suspended.explanation": "sona ale pi ma ni li kama pali ala, li kama esun ala, li kama awen ala la, sina ken ala toki tawa jan pi ma ni.",
|
||||
"about.domain_blocks.suspended.title": "weka",
|
||||
"about.language_label": "toki",
|
||||
"about.not_available": "lon kulupu ni la sina ken alasa ala e sona ni.",
|
||||
@@ -24,12 +24,12 @@
|
||||
"account.blocking": "mi len e jan ni",
|
||||
"account.cancel_follow_request": "o kute ala",
|
||||
"account.copy": "o pali same e linja pi lipu jan",
|
||||
"account.direct": "len la o mu e @{name}",
|
||||
"account.direct": "o mu len e @{name}",
|
||||
"account.disable_notifications": "@{name} li toki la o mu ala e mi",
|
||||
"account.domain_blocking": "mi len e ma ni",
|
||||
"account.edit_profile": "o ante e lipu mi",
|
||||
"account.edit_profile_short": "o ante",
|
||||
"account.enable_notifications": "@{name} li toki la o toki e toki ona tawa mi",
|
||||
"account.enable_notifications": "@{name} li toki la o mu e mi",
|
||||
"account.endorse": "lipu jan la o suli e ni",
|
||||
"account.familiar_followers_many": "{name1} en {name2} en {othersCount, plural, other {jan ante #}} li kute e jan ni",
|
||||
"account.familiar_followers_one": "{name1} li kute e jan ni",
|
||||
@@ -41,10 +41,10 @@
|
||||
"account.featured_tags.last_status_never": "toki ala li lon",
|
||||
"account.follow": "o kute",
|
||||
"account.follow_back": "jan ni li kute e sina. o kute",
|
||||
"account.follow_back_short": "jan ni li kute e sina. o kute",
|
||||
"account.follow_request": "toki e wile kute",
|
||||
"account.follow_request_cancel": "toki ala e wile kute",
|
||||
"account.follow_request_cancel_short": "ala",
|
||||
"account.follow_back_short": "o kute",
|
||||
"account.follow_request": "o wile kute",
|
||||
"account.follow_request_cancel": "o wile ala kute",
|
||||
"account.follow_request_cancel_short": "o wile ala kute",
|
||||
"account.followers": "jan kute",
|
||||
"account.followers.empty": "jan ala li kute e jan ni",
|
||||
"account.followers_counter": "{count, plural, other {jan {counter} li kute e ona}}",
|
||||
@@ -120,17 +120,17 @@
|
||||
"annual_report.summary.followers.followers": "jan kute sina",
|
||||
"annual_report.summary.followers.total": "ale la {count}",
|
||||
"annual_report.summary.here_it_is": "toki lili la tenpo sike nanpa {year} li sama ni tawa sina:",
|
||||
"annual_report.summary.highlighted_post.by_favourites": "toki pi pona suli",
|
||||
"annual_report.summary.highlighted_post.by_reblogs": "toki pi pana suli",
|
||||
"annual_report.summary.highlighted_post.by_replies": "toki li jo e toki kama pi nanpa wan",
|
||||
"annual_report.summary.highlighted_post.possessive": "tan jan {name}",
|
||||
"annual_report.summary.highlighted_post.by_favourites": "toki ni li pona suli tawa jan",
|
||||
"annual_report.summary.highlighted_post.by_reblogs": "jan ante li pana suli e toki ni",
|
||||
"annual_report.summary.highlighted_post.by_replies": "la jan ante li toki suli tan toki ni",
|
||||
"annual_report.summary.highlighted_post.possessive": "{name}",
|
||||
"annual_report.summary.most_used_app.most_used_app": "ilo pi kepeken suli",
|
||||
"annual_report.summary.most_used_hashtag.most_used_hashtag": "kulupu toki pi kepeken suli",
|
||||
"annual_report.summary.most_used_hashtag.none": "ala",
|
||||
"annual_report.summary.new_posts.new_posts": "toki suli sin",
|
||||
"annual_report.summary.percentile.text": "<topLabel>ni la sina nanpa sewi</topLabel><percentage></percentage><bottomLabel>pi jan ale lon {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "sona ni li len tawa ale.",
|
||||
"annual_report.summary.thanks": "sina jan pi kulupu Mastodon la sina pona a!",
|
||||
"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.",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Bunu görme bozukluğu yaşayan kişiler için betimleyin…",
|
||||
"alt_text_modal.done": "Tamamlandı",
|
||||
"announcement.announcement": "Duyuru",
|
||||
"annual_report.announcement.action_build": "Wrapstodon'umu Oluştur",
|
||||
"annual_report.announcement.action_view": "Wrapstodon'umu Görüntüle",
|
||||
"annual_report.announcement.description": "Mastodon'daki geçen yıldaki etkileşimleriniz hakkında daha fazlasını öğrenin.",
|
||||
"annual_report.announcement.title": "{year} Wrapstodon'u yayında",
|
||||
"annual_report.summary.archetype.booster": "Trend takipçisi",
|
||||
"annual_report.summary.archetype.lurker": "Gizli meraklı",
|
||||
"annual_report.summary.archetype.oracle": "Kahin",
|
||||
@@ -357,6 +361,7 @@
|
||||
"empty_column.notification_requests": "Hepsi tamam! Burada yeni bir şey yok. Yeni bildirim aldığınızda, ayarlarınıza göre burada görüntülenecekler.",
|
||||
"empty_column.notifications": "Henüz bildiriminiz yok. Sohbete başlamak için başkalarıyla etkileşim kurun.",
|
||||
"empty_column.public": "Burada hiçbir şey yok! Herkese açık bir şeyler yazın veya burayı doldurmak için diğer sunuculardaki kullanıcıları takip edin",
|
||||
"error.no_hashtag_feed_access": "Bu etiketi görüntülemek ve takip etmek için katılın veya giriş yapın.",
|
||||
"error.unexpected_crash.explanation": "Bizim kodumuzdaki bir hatadan ya da tarayıcı uyumluluk sorunundan dolayı, bu sayfa düzgün görüntülenemedi.",
|
||||
"error.unexpected_crash.explanation_addons": "Bu sayfa doğru görüntülenemedi. Bu hata büyük olasılıkla bir tarayıcı eklentisinden veya otomatik çeviri araçlarından kaynaklanır.",
|
||||
"error.unexpected_crash.next_steps": "Sayfayı yenilemeyi deneyin. Eğer bu yardımcı olmazsa, Mastodon'u farklı bir tarayıcı ya da yerel uygulama üzerinden kullanabilirsiniz.",
|
||||
@@ -515,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "CW'den önceki yazıyı göstermek/gizlemek için",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Medyayı göstermek/gizlemek için",
|
||||
"keyboard_shortcuts.toot": "Yeni bir gönderi başlat",
|
||||
"keyboard_shortcuts.top": "Listenin üstüne taşı",
|
||||
"keyboard_shortcuts.translate": "bir gönderiyi çevirmek için",
|
||||
"keyboard_shortcuts.unfocus": "Aramada bir gönderiye odaklanmamak için",
|
||||
"keyboard_shortcuts.up": "Listede yukarıya çıkmak için",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Mô tả cho người khiếm thị…",
|
||||
"alt_text_modal.done": "Xong",
|
||||
"announcement.announcement": "Có gì mới?",
|
||||
"annual_report.announcement.action_build": "Tạo Wrapstodon của tôi",
|
||||
"annual_report.announcement.action_view": "Xem Wrapstodon của tôi",
|
||||
"annual_report.announcement.description": "Tìm hiểu thêm về mức độ tương tác của bạn trên Mastodon trong năm qua.",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} đã đến",
|
||||
"annual_report.summary.archetype.booster": "Hiệp sĩ ngầu",
|
||||
"annual_report.summary.archetype.lurker": "Kẻ rình mò",
|
||||
"annual_report.summary.archetype.oracle": "Nhà tiên tri",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "ẩn/hiện nội dung ẩn",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "ẩn/hiện ảnh hoặc video",
|
||||
"keyboard_shortcuts.toot": "soạn tút mới",
|
||||
"keyboard_shortcuts.top": "Chuyển đến đầu danh sách",
|
||||
"keyboard_shortcuts.translate": "dịch tút",
|
||||
"keyboard_shortcuts.unfocus": "đưa con trỏ ra khỏi ô soạn thảo hoặc ô tìm kiếm",
|
||||
"keyboard_shortcuts.up": "di chuyển lên trên danh sách",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "请为视力障碍人士描述此内容…",
|
||||
"alt_text_modal.done": "完成",
|
||||
"announcement.announcement": "公告",
|
||||
"annual_report.announcement.action_build": "构建我的 Wrapstodon 年度回顾",
|
||||
"annual_report.announcement.action_view": "查看我的 Wrapstodon 年度回顾",
|
||||
"annual_report.announcement.description": "探索更多关于您过去一年在 Mastodon 上的互动情况。",
|
||||
"annual_report.announcement.title": "Wrapstodon {year} 年度回顾来啦",
|
||||
"annual_report.summary.archetype.booster": "潮流捕手",
|
||||
"annual_report.summary.archetype.lurker": "吃瓜群众",
|
||||
"annual_report.summary.archetype.oracle": "未卜先知",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "显示或隐藏被折叠的正文",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "显示/隐藏媒体",
|
||||
"keyboard_shortcuts.toot": "发送新嘟文",
|
||||
"keyboard_shortcuts.top": "移动到列表顶部",
|
||||
"keyboard_shortcuts.translate": "翻译嘟文",
|
||||
"keyboard_shortcuts.unfocus": "取消输入/搜索",
|
||||
"keyboard_shortcuts.up": "在列表中让光标上移",
|
||||
|
||||
@@ -113,6 +113,10 @@
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "替視覺障礙人士描述...",
|
||||
"alt_text_modal.done": "完成",
|
||||
"announcement.announcement": "公告",
|
||||
"annual_report.announcement.action_build": "建立我的 Mastodon 年度回顧 (Wrapstodon)",
|
||||
"annual_report.announcement.action_view": "檢視我的 Mastodon 年度回顧 (Wrapstodon)",
|
||||
"annual_report.announcement.description": "探索更多關於您過去一年於 Mastodon 上的互動情況。",
|
||||
"annual_report.announcement.title": "您的 Mastodon 年度回顧 {year} 已抵達",
|
||||
"annual_report.summary.archetype.booster": "酷炫獵人",
|
||||
"annual_report.summary.archetype.lurker": "潛水高手",
|
||||
"annual_report.summary.archetype.oracle": "先知",
|
||||
@@ -516,6 +520,7 @@
|
||||
"keyboard_shortcuts.toggle_hidden": "顯示或隱藏於內容警告之後的嘟文",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "顯示或隱藏媒體",
|
||||
"keyboard_shortcuts.toot": "發個新嘟文",
|
||||
"keyboard_shortcuts.top": "移至列表最上方",
|
||||
"keyboard_shortcuts.translate": "翻譯嘟文",
|
||||
"keyboard_shortcuts.unfocus": "跳離文字撰寫區塊或搜尋框",
|
||||
"keyboard_shortcuts.up": "向上移動",
|
||||
|
||||
@@ -37,8 +37,30 @@ interface AnnualReportV1 {
|
||||
archetype: Archetype;
|
||||
}
|
||||
|
||||
export interface AnnualReport {
|
||||
year: number;
|
||||
schema_version: number;
|
||||
data: AnnualReportV1;
|
||||
interface AnnualReportV2 {
|
||||
archetype: Archetype;
|
||||
time_series: TimeSeriesMonth[];
|
||||
top_hashtags: NameAndCount[];
|
||||
top_statuses: TopStatuses;
|
||||
most_used_apps: NameAndCount[];
|
||||
type_distribution: {
|
||||
total: number;
|
||||
reblogs: number;
|
||||
replies: number;
|
||||
standalone: number;
|
||||
};
|
||||
}
|
||||
|
||||
export type AnnualReport = {
|
||||
year: number;
|
||||
} & (
|
||||
| {
|
||||
schema_version: 1;
|
||||
data: AnnualReportV1;
|
||||
}
|
||||
| {
|
||||
schema_version: 2;
|
||||
data: AnnualReportV2;
|
||||
share_url: string | null;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ export const CustomEmojiFactory = ImmutableRecord<CustomEmojiShape>({
|
||||
static_url: '',
|
||||
url: '',
|
||||
category: '',
|
||||
featured: false,
|
||||
visible_in_picker: false,
|
||||
});
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import { relationshipsReducer } from './relationships';
|
||||
import { searchReducer } from './search';
|
||||
import server from './server';
|
||||
import settings from './settings';
|
||||
import { sliceReducers } from './slices';
|
||||
import status_lists from './status_lists';
|
||||
import statuses from './statuses';
|
||||
import { suggestionsReducer } from './suggestions';
|
||||
@@ -80,6 +81,7 @@ const reducers = {
|
||||
notificationPolicy: notificationPolicyReducer,
|
||||
notificationRequests: notificationRequestsReducer,
|
||||
navigation: navigationReducer,
|
||||
...sliceReducers,
|
||||
};
|
||||
|
||||
// We want the root state to be an ImmutableRecord, which is an object with a defined list of keys,
|
||||
|
||||
118
app/javascript/mastodon/reducers/slices/annual_report.ts
Normal file
118
app/javascript/mastodon/reducers/slices/annual_report.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
import { insertIntoTimeline } from '@/mastodon/actions/timelines';
|
||||
import type { ApiAnnualReportState } from '@/mastodon/api/annual_report';
|
||||
import {
|
||||
apiGetAnnualReport,
|
||||
apiGetAnnualReportState,
|
||||
apiRequestGenerateAnnualReport,
|
||||
} from '@/mastodon/api/annual_report';
|
||||
import type { AnnualReport } from '@/mastodon/models/annual_report';
|
||||
|
||||
import {
|
||||
createAppSelector,
|
||||
createAppThunk,
|
||||
createDataLoadingThunk,
|
||||
} from '../../store/typed_functions';
|
||||
|
||||
export const TIMELINE_WRAPSTODON = 'inline-wrapstodon';
|
||||
|
||||
interface AnnualReportState {
|
||||
state?: ApiAnnualReportState;
|
||||
report?: AnnualReport;
|
||||
}
|
||||
|
||||
const annualReportSlice = createSlice({
|
||||
name: 'annualReport',
|
||||
initialState: {} as AnnualReportState,
|
||||
reducers: {},
|
||||
extraReducers(builder) {
|
||||
builder
|
||||
.addCase(fetchReportState.fulfilled, (state, action) => {
|
||||
state.state = action.payload;
|
||||
})
|
||||
.addCase(generateReport.pending, (state) => {
|
||||
state.state = 'generating';
|
||||
})
|
||||
.addCase(getReport.fulfilled, (state, action) => {
|
||||
if (action.payload) {
|
||||
state.report = action.payload;
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const annualReport = annualReportSlice.reducer;
|
||||
|
||||
export const selectWrapstodonYear = createAppSelector(
|
||||
[(state) => state.server.getIn(['server', 'wrapstodon'])],
|
||||
(year: unknown) => (typeof year === 'number' && year > 2000 ? year : null),
|
||||
);
|
||||
|
||||
// This kicks everything off, and is called after fetching the server info.
|
||||
export const checkAnnualReport = createAppThunk(
|
||||
`${annualReportSlice.name}/checkAnnualReport`,
|
||||
async (_arg: unknown, { dispatch, getState }) => {
|
||||
const year = selectWrapstodonYear(getState());
|
||||
if (!year) {
|
||||
return;
|
||||
}
|
||||
const state = await dispatch(fetchReportState());
|
||||
if (
|
||||
state.meta.requestStatus === 'fulfilled' &&
|
||||
state.payload !== 'ineligible'
|
||||
) {
|
||||
dispatch(insertIntoTimeline('home', TIMELINE_WRAPSTODON, 1));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const fetchReportState = createDataLoadingThunk(
|
||||
`${annualReportSlice.name}/fetchReportState`,
|
||||
async (_arg: unknown, { getState }) => {
|
||||
const year = selectWrapstodonYear(getState());
|
||||
if (!year) {
|
||||
throw new Error('Year is not set');
|
||||
}
|
||||
return apiGetAnnualReportState(year);
|
||||
},
|
||||
({ state, refresh }, { dispatch }) => {
|
||||
if (state === 'generating' && refresh) {
|
||||
window.setTimeout(() => {
|
||||
void dispatch(fetchReportState());
|
||||
}, 1_000 * refresh.retry);
|
||||
} else if (state === 'available') {
|
||||
void dispatch(getReport());
|
||||
}
|
||||
|
||||
return state;
|
||||
},
|
||||
{ useLoadingBar: false },
|
||||
);
|
||||
|
||||
// Triggers the generation of the annual report.
|
||||
export const generateReport = createDataLoadingThunk(
|
||||
`${annualReportSlice.name}/generateReport`,
|
||||
async (_arg: unknown, { getState }) => {
|
||||
const year = selectWrapstodonYear(getState());
|
||||
if (!year) {
|
||||
throw new Error('Year is not set');
|
||||
}
|
||||
return apiRequestGenerateAnnualReport(year);
|
||||
},
|
||||
(_arg: unknown, { dispatch }) => {
|
||||
void dispatch(fetchReportState());
|
||||
},
|
||||
);
|
||||
|
||||
export const getReport = createDataLoadingThunk(
|
||||
`${annualReportSlice.name}/getReport`,
|
||||
async (_arg: unknown, { getState }) => {
|
||||
const year = selectWrapstodonYear(getState());
|
||||
if (!year) {
|
||||
throw new Error('Year is not set');
|
||||
}
|
||||
return apiGetAnnualReport(year);
|
||||
},
|
||||
(data) => data.annual_reports[0],
|
||||
);
|
||||
5
app/javascript/mastodon/reducers/slices/index.ts
Normal file
5
app/javascript/mastodon/reducers/slices/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { annualReport } from './annual_report';
|
||||
|
||||
export const sliceReducers = {
|
||||
annualReport,
|
||||
};
|
||||
@@ -65,6 +65,10 @@ const statusTranslateUndo = (state, id) => {
|
||||
});
|
||||
};
|
||||
|
||||
const removeStatusStub = (state, id) => {
|
||||
return state.getIn([id, 'id']) ? state.deleteIn([id, 'isLoading']) : state.delete(id);
|
||||
}
|
||||
|
||||
|
||||
/** @type {ImmutableMap<string, import('mastodon/models/status').Status>} */
|
||||
const initialState = ImmutableMap();
|
||||
@@ -92,11 +96,10 @@ export default function statuses(state = initialState, action) {
|
||||
return state.setIn([action.id, 'isLoading'], true);
|
||||
case STATUS_FETCH_FAIL: {
|
||||
if (action.parentQuotePostId && action.error.status === 404) {
|
||||
return state
|
||||
.delete(action.id)
|
||||
return removeStatusStub(state, action.id)
|
||||
.setIn([action.parentQuotePostId, 'quote', 'state'], 'deleted')
|
||||
} else {
|
||||
return state.delete(action.id);
|
||||
return removeStatusStub(state, action.id);
|
||||
}
|
||||
}
|
||||
case STATUS_IMPORT:
|
||||
|
||||
@@ -205,7 +205,7 @@ export function createDataLoadingThunk<LoadDataResult, Args extends ArgsType>(
|
||||
thunkOptions?: AppThunkOptions<Args>,
|
||||
): ReturnType<typeof createAsyncThunk<Args, void>>;
|
||||
|
||||
// Overload when the `onData` method returns nothing, then the mayload is the `onData` result
|
||||
// Overload when the `onData` method returns nothing, then the payload is the `onData` result
|
||||
export function createDataLoadingThunk<LoadDataResult, Args extends ArgsType>(
|
||||
name: string,
|
||||
loadData: LoadData<Args, LoadDataResult>,
|
||||
|
||||
@@ -5,20 +5,26 @@ export function setupLinkListeners() {
|
||||
|
||||
// We don't want to target links with data-confirm here, as those are handled already.
|
||||
on('click', 'a[data-method]:not([data-confirm])', handleMethodLink);
|
||||
|
||||
// We also want to target buttons with data-confirm that are not inside forms.
|
||||
on('click', ':not(form) button[data-confirm]:not([form])', handleConfirmLink);
|
||||
}
|
||||
|
||||
function handleConfirmLink(event: MouseEvent) {
|
||||
const anchor = event.currentTarget;
|
||||
if (!(anchor instanceof HTMLAnchorElement)) {
|
||||
const target = event.currentTarget;
|
||||
if (
|
||||
!(target instanceof HTMLAnchorElement) &&
|
||||
!(target instanceof HTMLButtonElement)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const message = anchor.dataset.confirm;
|
||||
const message = target.dataset.confirm;
|
||||
if (!message || !window.confirm(message)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (anchor.dataset.method) {
|
||||
if (target.dataset.method) {
|
||||
handleMethodLink(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
@use 'variables' as *;
|
||||
|
||||
html {
|
||||
color: var(--color-text-primary);
|
||||
background: var(--color-bg-ambient);
|
||||
}
|
||||
|
||||
html.has-modal {
|
||||
&,
|
||||
body {
|
||||
|
||||
@@ -18,11 +18,24 @@ class AnnualReport
|
||||
'annual_report_'
|
||||
end
|
||||
|
||||
def self.current_campaign
|
||||
return unless Mastodon::Feature.wrapstodon_enabled?
|
||||
|
||||
datetime = Time.now.utc
|
||||
datetime.year if datetime.month == 12 && (10..31).cover?(datetime.day)
|
||||
end
|
||||
|
||||
def initialize(account, year)
|
||||
@account = account
|
||||
@year = year
|
||||
end
|
||||
|
||||
def eligible?
|
||||
with_read_replica do
|
||||
SOURCES.all? { |klass| klass.new(@account, @year).eligible? }
|
||||
end
|
||||
end
|
||||
|
||||
def generate
|
||||
return if GeneratedAnnualReport.exists?(account: @account, year: @year)
|
||||
|
||||
@@ -30,7 +43,8 @@ class AnnualReport
|
||||
account: @account,
|
||||
year: @year,
|
||||
schema_version: SCHEMA,
|
||||
data: data
|
||||
data: data,
|
||||
share_key: SecureRandom.hex(8)
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -12,6 +12,10 @@ class AnnualReport::Source
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def eligible?
|
||||
true
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def report_statuses
|
||||
|
||||
@@ -15,6 +15,10 @@ class AnnualReport::TopHashtags < AnnualReport::Source
|
||||
}
|
||||
end
|
||||
|
||||
def eligible?
|
||||
report_statuses.joins(:tags).exists?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def top_hashtags
|
||||
|
||||
@@ -11,6 +11,10 @@ class AnnualReport::TopStatuses < AnnualReport::Source
|
||||
}
|
||||
end
|
||||
|
||||
def eligible?
|
||||
report_statuses.public_visibility.exists?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def status_identifier(status)
|
||||
|
||||
@@ -38,10 +38,18 @@ class Collection < ApplicationRecord
|
||||
validate :tag_is_usable
|
||||
validate :items_do_not_exceed_limit
|
||||
|
||||
scope :with_items, -> { includes(:collection_items).merge(CollectionItem.with_accounts) }
|
||||
|
||||
def remote?
|
||||
!local?
|
||||
end
|
||||
|
||||
def items_for(account = nil)
|
||||
result = collection_items.with_accounts
|
||||
result = result.not_blocked_by(account) unless account.nil?
|
||||
result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def tag_is_usable
|
||||
|
||||
@@ -33,6 +33,8 @@ class CollectionItem < ApplicationRecord
|
||||
validates :object_uri, presence: true, if: -> { account.nil? }
|
||||
|
||||
scope :ordered, -> { order(position: :asc) }
|
||||
scope :with_accounts, -> { includes(account: [:account_stat, :user]) }
|
||||
scope :not_blocked_by, ->(account) { where.not(accounts: { id: account.blocking }) }
|
||||
|
||||
def local_item_with_remote_account?
|
||||
local? && account&.remote?
|
||||
|
||||
@@ -17,7 +17,7 @@ class Conversation < ApplicationRecord
|
||||
|
||||
has_many :statuses, dependent: nil
|
||||
|
||||
belongs_to :parent_status, class_name: 'Status', optional: true, inverse_of: :conversation
|
||||
belongs_to :parent_status, class_name: 'Status', optional: true, inverse_of: :owned_conversation
|
||||
belongs_to :parent_account, class_name: 'Account', optional: true
|
||||
|
||||
scope :local, -> { where(uri: nil) }
|
||||
|
||||
@@ -69,6 +69,10 @@ class CustomEmoji < ApplicationRecord
|
||||
:emoji
|
||||
end
|
||||
|
||||
def featured?
|
||||
category&.featured_emoji_id == id
|
||||
end
|
||||
|
||||
def copy!
|
||||
copy = self.class.find_or_initialize_by(domain: nil, shortcode: shortcode)
|
||||
copy.image = image
|
||||
|
||||
@@ -4,14 +4,16 @@
|
||||
#
|
||||
# Table name: custom_emoji_categories
|
||||
#
|
||||
# id :bigint(8) not null, primary key
|
||||
# name :string
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# id :bigint(8) not null, primary key
|
||||
# name :string
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# featured_emoji_id :bigint(8)
|
||||
#
|
||||
|
||||
class CustomEmojiCategory < ApplicationRecord
|
||||
has_many :emojis, class_name: 'CustomEmoji', foreign_key: 'category_id', inverse_of: :category, dependent: nil
|
||||
belongs_to :featured_emoji, class_name: 'CustomEmoji', optional: true, inverse_of: :category
|
||||
|
||||
validates :name, presence: true, uniqueness: true
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
# Table name: generated_annual_reports
|
||||
#
|
||||
# id :bigint(8) not null, primary key
|
||||
# account_id :bigint(8) not null
|
||||
# year :integer not null
|
||||
# data :jsonb not null
|
||||
# schema_version :integer not null
|
||||
# share_key :string
|
||||
# viewed_at :datetime
|
||||
# year :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :bigint(8) not null
|
||||
#
|
||||
|
||||
class GeneratedAnnualReport < ApplicationRecord
|
||||
@@ -28,7 +29,12 @@ class GeneratedAnnualReport < ApplicationRecord
|
||||
end
|
||||
|
||||
def account_ids
|
||||
data['most_reblogged_accounts'].pluck('account_id') + data['commonly_interacted_with_accounts'].pluck('account_id')
|
||||
case schema_version
|
||||
when 1
|
||||
data['most_reblogged_accounts'].pluck('account_id') + data['commonly_interacted_with_accounts'].pluck('account_id')
|
||||
when 2
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def status_ids
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user