Merge commit '24319836de6046fb2985ec1a24c30ad7d47584d7' into glitch-soc/merge-upstream

Conflicts:
- `config/routes/api.rb`:
  glitch-soc has an extra `:destroy` action on notifications for historical reasons.
  Kept it for now, while otherwise updating as upstream did.
shrike
Claire 2024-03-11 17:29:07 +01:00
commit a5127d0ef8
232 changed files with 6162 additions and 2199 deletions

View File

@ -123,7 +123,7 @@ module.exports = defineConfig({
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
'react/self-closing-comp': 'error',
// recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/index.js
// recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/v6.8.0/src/index.js#L46
'jsx-a11y/accessible-emoji': 'warn',
'jsx-a11y/click-events-have-key-events': 'off',
'jsx-a11y/label-has-associated-control': 'off',
@ -176,7 +176,7 @@ module.exports = defineConfig({
},
],
// See https://github.com/import-js/eslint-plugin-import/blob/main/config/recommended.js
// See https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/config/recommended.js
'import/extensions': [
'error',
'always',

View File

@ -29,7 +29,7 @@ ARG MASTODON_VERSION_METADATA=""
# See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files
ARG RAILS_SERVE_STATIC_FILES="true"
# Allow to use YJIT compiler
# See: https://github.com/ruby/ruby/blob/master/doc/yjit/yjit.md
# See: https://github.com/ruby/ruby/blob/v3_2_3/doc/yjit/yjit.md
ARG RUBY_YJIT_ENABLE="1"
# Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin]
ARG TZ="Etc/UTC"

View File

@ -465,11 +465,11 @@ GEM
statsd-ruby (~> 1.4, >= 1.4.0)
oj (3.16.3)
bigdecimal (>= 3.0)
omniauth (2.1.1)
omniauth (2.1.2)
hashie (>= 3.4.6)
rack (>= 2.2.3)
rack-protection
omniauth-cas (3.0.0.beta.1)
omniauth-cas (3.0.0)
addressable (~> 2.8)
nokogiri (~> 1.12)
omniauth (~> 2.1)
@ -505,7 +505,7 @@ GEM
parslet (2.0.0)
pastel (0.8.0)
tty-color (~> 0.5)
pg (1.5.5)
pg (1.5.6)
pghero (3.4.1)
activerecord (>= 6)
posix-spawn (0.3.15)
@ -543,8 +543,9 @@ GEM
httpclient
json-jwt (>= 1.11.0)
rack (>= 2.1.0)
rack-protection (3.0.5)
rack
rack-protection (3.2.0)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
rack-proxy (0.7.6)
rack
rack-session (1.0.2)
@ -743,7 +744,7 @@ GEM
unicode-display_width (>= 1.1.1, < 3)
terrapin (1.0.1)
climate_control
test-prof (1.3.1)
test-prof (1.3.2)
thor (1.3.1)
tilt (2.3.0)
timeout (0.4.1)

View File

@ -53,7 +53,7 @@ module Admin
end
def resource_params
params.require(:rule).permit(:text, :priority)
params.require(:rule).permit(:text, :hint, :priority)
end
end
end

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
class Api::V1::Notifications::PoliciesController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, only: :show
before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, only: :update
before_action :require_user!
before_action :set_policy
def show
render json: @policy, serializer: REST::NotificationPolicySerializer
end
def update
@policy.update!(resource_params)
render json: @policy, serializer: REST::NotificationPolicySerializer
end
private
def set_policy
@policy = NotificationPolicy.find_or_initialize_by(account: current_account)
with_read_replica do
@policy.summarize!
end
end
def resource_params
params.permit(
:filter_not_following,
:filter_not_followers,
:filter_new_accounts,
:filter_private_mentions
)
end
end

View File

@ -0,0 +1,79 @@
# frozen_string_literal: true
class Api::V1::Notifications::RequestsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, only: :index
before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, except: :index
before_action :require_user!
before_action :set_request, except: :index
after_action :insert_pagination_headers, only: :index
def index
with_read_replica do
@requests = load_requests
@relationships = relationships
end
render json: @requests, each_serializer: REST::NotificationRequestSerializer, relationships: @relationships
end
def show
render json: @request, serializer: REST::NotificationRequestSerializer
end
def accept
AcceptNotificationRequestService.new.call(@request)
render_empty
end
def dismiss
@request.update!(dismissed: true)
render_empty
end
private
def load_requests
requests = NotificationRequest.where(account: current_account).where(dismissed: truthy_param?(:dismissed) || false).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params_slice(:max_id, :since_id, :min_id)
)
NotificationRequest.preload_cache_collection(requests) do |statuses|
cache_collection(statuses, Status)
end
end
def relationships
StatusRelationshipsPresenter.new(@requests.map(&:last_status), current_user&.account_id)
end
def set_request
@request = NotificationRequest.where(account: current_account).find(params[:id])
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
api_v1_notifications_requests_url pagination_params(max_id: pagination_max_id) unless @requests.empty?
end
def prev_path
api_v1_notifications_requests_url pagination_params(min_id: pagination_since_id) unless @requests.empty?
end
def pagination_max_id
@requests.last.id
end
def pagination_since_id
@requests.first.id
end
def pagination_params(core_params)
params.slice(:dismissed).permit(:dismissed).merge(core_params)
end
end

View File

@ -58,7 +58,8 @@ class Api::V1::NotificationsController < Api::BaseController
current_account.notifications.without_suspended.browserable(
types: Array(browserable_params[:types]),
exclude_types: Array(browserable_params[:exclude_types]),
from_account_id: browserable_params[:account_id]
from_account_id: browserable_params[:account_id],
include_filtered: truthy_param?(:include_filtered)
)
end
@ -87,10 +88,10 @@ class Api::V1::NotificationsController < Api::BaseController
end
def browserable_params
params.permit(:account_id, types: [], exclude_types: [])
params.permit(:account_id, :include_filtered, types: [], exclude_types: [])
end
def pagination_params(core_params)
params.slice(:limit, :account_id, :types, :exclude_types).permit(:limit, :account_id, types: [], exclude_types: []).merge(core_params)
params.slice(:limit, :account_id, :types, :exclude_types, :include_filtered).permit(:limit, :account_id, :include_filtered, types: [], exclude_types: []).merge(core_params)
end
end

View File

@ -198,6 +198,7 @@ module LanguagesHelper
ldn: ['Láadan', 'Láadan'].freeze,
lfn: ['Lingua Franca Nova', 'lingua franca nova'].freeze,
moh: ['Mohawk', 'Kanienʼkéha'].freeze,
nds: ['Low German', 'Plattdüütsch'].freeze,
pdc: ['Pennsylvania Dutch', 'Pennsilfaani-Deitsch'].freeze,
sco: ['Scots', 'Scots'].freeze,
sma: ['Southern Sami', 'Åarjelsaemien Gïele'].freeze,

View File

@ -788,11 +788,12 @@ export function addPollOption(title) {
};
}
export function changePollOption(index, title) {
export function changePollOption(index, title, maxOptions) {
return {
type: COMPOSE_POLL_OPTION_CHANGE,
index,
title,
maxOptions,
};
}

View File

@ -44,6 +44,38 @@ export const NOTIFICATIONS_MARK_AS_READ = 'NOTIFICATIONS_MARK_AS_READ';
export const NOTIFICATIONS_SET_BROWSER_SUPPORT = 'NOTIFICATIONS_SET_BROWSER_SUPPORT';
export const NOTIFICATIONS_SET_BROWSER_PERMISSION = 'NOTIFICATIONS_SET_BROWSER_PERMISSION';
export const NOTIFICATION_POLICY_FETCH_REQUEST = 'NOTIFICATION_POLICY_FETCH_REQUEST';
export const NOTIFICATION_POLICY_FETCH_SUCCESS = 'NOTIFICATION_POLICY_FETCH_SUCCESS';
export const NOTIFICATION_POLICY_FETCH_FAIL = 'NOTIFICATION_POLICY_FETCH_FAIL';
export const NOTIFICATION_REQUESTS_FETCH_REQUEST = 'NOTIFICATION_REQUESTS_FETCH_REQUEST';
export const NOTIFICATION_REQUESTS_FETCH_SUCCESS = 'NOTIFICATION_REQUESTS_FETCH_SUCCESS';
export const NOTIFICATION_REQUESTS_FETCH_FAIL = 'NOTIFICATION_REQUESTS_FETCH_FAIL';
export const NOTIFICATION_REQUESTS_EXPAND_REQUEST = 'NOTIFICATION_REQUESTS_EXPAND_REQUEST';
export const NOTIFICATION_REQUESTS_EXPAND_SUCCESS = 'NOTIFICATION_REQUESTS_EXPAND_SUCCESS';
export const NOTIFICATION_REQUESTS_EXPAND_FAIL = 'NOTIFICATION_REQUESTS_EXPAND_FAIL';
export const NOTIFICATION_REQUEST_FETCH_REQUEST = 'NOTIFICATION_REQUEST_FETCH_REQUEST';
export const NOTIFICATION_REQUEST_FETCH_SUCCESS = 'NOTIFICATION_REQUEST_FETCH_SUCCESS';
export const NOTIFICATION_REQUEST_FETCH_FAIL = 'NOTIFICATION_REQUEST_FETCH_FAIL';
export const NOTIFICATION_REQUEST_ACCEPT_REQUEST = 'NOTIFICATION_REQUEST_ACCEPT_REQUEST';
export const NOTIFICATION_REQUEST_ACCEPT_SUCCESS = 'NOTIFICATION_REQUEST_ACCEPT_SUCCESS';
export const NOTIFICATION_REQUEST_ACCEPT_FAIL = 'NOTIFICATION_REQUEST_ACCEPT_FAIL';
export const NOTIFICATION_REQUEST_DISMISS_REQUEST = 'NOTIFICATION_REQUEST_DISMISS_REQUEST';
export const NOTIFICATION_REQUEST_DISMISS_SUCCESS = 'NOTIFICATION_REQUEST_DISMISS_SUCCESS';
export const NOTIFICATION_REQUEST_DISMISS_FAIL = 'NOTIFICATION_REQUEST_DISMISS_FAIL';
export const NOTIFICATIONS_FOR_REQUEST_FETCH_REQUEST = 'NOTIFICATIONS_FOR_REQUEST_FETCH_REQUEST';
export const NOTIFICATIONS_FOR_REQUEST_FETCH_SUCCESS = 'NOTIFICATIONS_FOR_REQUEST_FETCH_SUCCESS';
export const NOTIFICATIONS_FOR_REQUEST_FETCH_FAIL = 'NOTIFICATIONS_FOR_REQUEST_FETCH_FAIL';
export const NOTIFICATIONS_FOR_REQUEST_EXPAND_REQUEST = 'NOTIFICATIONS_FOR_REQUEST_EXPAND_REQUEST';
export const NOTIFICATIONS_FOR_REQUEST_EXPAND_SUCCESS = 'NOTIFICATIONS_FOR_REQUEST_EXPAND_SUCCESS';
export const NOTIFICATIONS_FOR_REQUEST_EXPAND_FAIL = 'NOTIFICATIONS_FOR_REQUEST_EXPAND_FAIL';
defineMessages({
mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
group: { id: 'notifications.group', defaultMessage: '{count} notifications' },
@ -313,3 +345,264 @@ export function setBrowserPermission (value) {
value,
};
}
export const fetchNotificationPolicy = () => (dispatch, getState) => {
dispatch(fetchNotificationPolicyRequest());
api(getState).get('/api/v1/notifications/policy').then(({ data }) => {
dispatch(fetchNotificationPolicySuccess(data));
}).catch(err => {
dispatch(fetchNotificationPolicyFail(err));
});
};
export const fetchNotificationPolicyRequest = () => ({
type: NOTIFICATION_POLICY_FETCH_REQUEST,
});
export const fetchNotificationPolicySuccess = policy => ({
type: NOTIFICATION_POLICY_FETCH_SUCCESS,
policy,
});
export const fetchNotificationPolicyFail = error => ({
type: NOTIFICATION_POLICY_FETCH_FAIL,
error,
});
export const updateNotificationsPolicy = params => (dispatch, getState) => {
dispatch(fetchNotificationPolicyRequest());
api(getState).put('/api/v1/notifications/policy', params).then(({ data }) => {
dispatch(fetchNotificationPolicySuccess(data));
}).catch(err => {
dispatch(fetchNotificationPolicyFail(err));
});
};
export const fetchNotificationRequests = () => (dispatch, getState) => {
const params = {};
if (getState().getIn(['notificationRequests', 'isLoading'])) {
return;
}
if (getState().getIn(['notificationRequests', 'items'])?.size > 0) {
params.since_id = getState().getIn(['notificationRequests', 'items', 0, 'id']);
}
dispatch(fetchNotificationRequestsRequest());
api(getState).get('/api/v1/notifications/requests', { params }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data.map(x => x.account)));
dispatch(fetchNotificationRequestsSuccess(response.data, next ? next.uri : null));
}).catch(err => {
dispatch(fetchNotificationRequestsFail(err));
});
};
export const fetchNotificationRequestsRequest = () => ({
type: NOTIFICATION_REQUESTS_FETCH_REQUEST,
});
export const fetchNotificationRequestsSuccess = (requests, next) => ({
type: NOTIFICATION_REQUESTS_FETCH_SUCCESS,
requests,
next,
});
export const fetchNotificationRequestsFail = error => ({
type: NOTIFICATION_REQUESTS_FETCH_FAIL,
error,
});
export const expandNotificationRequests = () => (dispatch, getState) => {
const url = getState().getIn(['notificationRequests', 'next']);
if (!url || getState().getIn(['notificationRequests', 'isLoading'])) {
return;
}
dispatch(expandNotificationRequestsRequest());
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data.map(x => x.account)));
dispatch(expandNotificationRequestsSuccess(response.data, next?.uri));
}).catch(err => {
dispatch(expandNotificationRequestsFail(err));
});
};
export const expandNotificationRequestsRequest = () => ({
type: NOTIFICATION_REQUESTS_EXPAND_REQUEST,
});
export const expandNotificationRequestsSuccess = (requests, next) => ({
type: NOTIFICATION_REQUESTS_EXPAND_SUCCESS,
requests,
next,
});
export const expandNotificationRequestsFail = error => ({
type: NOTIFICATION_REQUESTS_EXPAND_FAIL,
error,
});
export const fetchNotificationRequest = id => (dispatch, getState) => {
const current = getState().getIn(['notificationRequests', 'current']);
if (current.getIn(['item', 'id']) === id || current.get('isLoading')) {
return;
}
dispatch(fetchNotificationRequestRequest(id));
api(getState).get(`/api/v1/notifications/requests/${id}`).then(({ data }) => {
dispatch(fetchNotificationRequestSuccess(data));
}).catch(err => {
dispatch(fetchNotificationRequestFail(id, err));
});
};
export const fetchNotificationRequestRequest = id => ({
type: NOTIFICATION_REQUEST_FETCH_REQUEST,
id,
});
export const fetchNotificationRequestSuccess = request => ({
type: NOTIFICATION_REQUEST_FETCH_SUCCESS,
request,
});
export const fetchNotificationRequestFail = (id, error) => ({
type: NOTIFICATION_REQUEST_FETCH_FAIL,
id,
error,
});
export const acceptNotificationRequest = id => (dispatch, getState) => {
dispatch(acceptNotificationRequestRequest(id));
api(getState).post(`/api/v1/notifications/requests/${id}/accept`).then(() => {
dispatch(acceptNotificationRequestSuccess(id));
}).catch(err => {
dispatch(acceptNotificationRequestFail(id, err));
});
};
export const acceptNotificationRequestRequest = id => ({
type: NOTIFICATION_REQUEST_ACCEPT_REQUEST,
id,
});
export const acceptNotificationRequestSuccess = id => ({
type: NOTIFICATION_REQUEST_ACCEPT_SUCCESS,
id,
});
export const acceptNotificationRequestFail = (id, error) => ({
type: NOTIFICATION_REQUEST_ACCEPT_FAIL,
id,
error,
});
export const dismissNotificationRequest = id => (dispatch, getState) => {
dispatch(dismissNotificationRequestRequest(id));
api(getState).post(`/api/v1/notifications/requests/${id}/dismiss`).then(() =>{
dispatch(dismissNotificationRequestSuccess(id));
}).catch(err => {
dispatch(dismissNotificationRequestFail(id, err));
});
};
export const dismissNotificationRequestRequest = id => ({
type: NOTIFICATION_REQUEST_DISMISS_REQUEST,
id,
});
export const dismissNotificationRequestSuccess = id => ({
type: NOTIFICATION_REQUEST_DISMISS_SUCCESS,
id,
});
export const dismissNotificationRequestFail = (id, error) => ({
type: NOTIFICATION_REQUEST_DISMISS_FAIL,
id,
error,
});
export const fetchNotificationsForRequest = accountId => (dispatch, getState) => {
const current = getState().getIn(['notificationRequests', 'current']);
const params = { account_id: accountId };
if (current.getIn(['item', 'account']) === accountId) {
if (current.getIn(['notifications', 'isLoading'])) {
return;
}
if (current.getIn(['notifications', 'items'])?.size > 0) {
params.since_id = current.getIn(['notifications', 'items', 0, 'id']);
}
}
dispatch(fetchNotificationsForRequestRequest());
api(getState).get('/api/v1/notifications', { params }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
dispatch(fetchNotificationsForRequestSuccess(response.data, next?.uri));
}).catch(err => {
dispatch(fetchNotificationsForRequestFail(err));
});
};
export const fetchNotificationsForRequestRequest = () => ({
type: NOTIFICATIONS_FOR_REQUEST_FETCH_REQUEST,
});
export const fetchNotificationsForRequestSuccess = (notifications, next) => ({
type: NOTIFICATIONS_FOR_REQUEST_FETCH_SUCCESS,
notifications,
next,
});
export const fetchNotificationsForRequestFail = (error) => ({
type: NOTIFICATIONS_FOR_REQUEST_FETCH_FAIL,
error,
});
export const expandNotificationsForRequest = () => (dispatch, getState) => {
const url = getState().getIn(['notificationRequests', 'current', 'notifications', 'next']);
if (!url || getState().getIn(['notificationRequests', 'current', 'notifications', 'isLoading'])) {
return;
}
dispatch(expandNotificationsForRequestRequest());
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
dispatch(expandNotificationsForRequestSuccess(response.data, next?.uri));
}).catch(err => {
dispatch(expandNotificationsForRequestFail(err));
});
};
export const expandNotificationsForRequestRequest = () => ({
type: NOTIFICATIONS_FOR_REQUEST_EXPAND_REQUEST,
});
export const expandNotificationsForRequestSuccess = (notifications, next) => ({
type: NOTIFICATIONS_FOR_REQUEST_EXPAND_SUCCESS,
notifications,
next,
});
export const expandNotificationsForRequestFail = (error) => ({
type: NOTIFICATIONS_FOR_REQUEST_EXPAND_FAIL,
error,
});

View File

@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import { PureComponent, useCallback } from 'react';
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
import { FormattedMessage, injectIntl, defineMessages, useIntl } from 'react-intl';
import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
@ -11,7 +11,7 @@ import ArrowBackIcon from '@/material-icons/400-24px/arrow_back.svg?react';
import ChevronLeftIcon from '@/material-icons/400-24px/chevron_left.svg?react';
import ChevronRightIcon from '@/material-icons/400-24px/chevron_right.svg?react';
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
import TuneIcon from '@/material-icons/400-24px/tune.svg?react';
import SettingsIcon from '@/material-icons/400-24px/settings.svg?react';
import { Icon } from 'mastodon/components/icon';
import { ButtonInTabsBar, useColumnsContext } from 'mastodon/features/ui/util/columns_context';
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
@ -23,10 +23,12 @@ const messages = defineMessages({
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
moveLeft: { id: 'column_header.moveLeft_settings', defaultMessage: 'Move column to the left' },
moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' },
back: { id: 'column_back_button.label', defaultMessage: 'Back' },
});
const BackButton = ({ pinned, show }) => {
const BackButton = ({ pinned, show, onlyIcon }) => {
const history = useAppHistory();
const intl = useIntl();
const { multiColumn } = useColumnsContext();
const handleBackClick = useCallback(() => {
@ -39,18 +41,20 @@ const BackButton = ({ pinned, show }) => {
const showButton = history && !pinned && ((multiColumn && history.location?.state?.fromMastodon) || show);
if(!showButton) return null;
return (<button onClick={handleBackClick} className='column-header__back-button'>
<Icon id='chevron-left' icon={ArrowBackIcon} className='column-back-button__icon' />
<FormattedMessage id='column_back_button.label' defaultMessage='Back' />
</button>);
if (!showButton) return null;
return (
<button onClick={handleBackClick} className={classNames('column-header__back-button', { 'compact': onlyIcon })} aria-label={intl.formatMessage(messages.back)}>
<Icon id='chevron-left' icon={ArrowBackIcon} className='column-back-button__icon' />
{!onlyIcon && <FormattedMessage id='column_back_button.label' defaultMessage='Back' />}
</button>
);
};
BackButton.propTypes = {
pinned: PropTypes.bool,
show: PropTypes.bool,
onlyIcon: PropTypes.bool,
};
class ColumnHeader extends PureComponent {
@ -145,27 +149,31 @@ class ColumnHeader extends PureComponent {
}
if (multiColumn && pinned) {
pinButton = <button key='pin-button' className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='times' icon={CloseIcon} /> <FormattedMessage id='column_header.unpin' defaultMessage='Unpin' /></button>;
pinButton = <button className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='times' icon={CloseIcon} /> <FormattedMessage id='column_header.unpin' defaultMessage='Unpin' /></button>;
moveButtons = (
<div key='move-buttons' className='column-header__setting-arrows'>
<div className='column-header__setting-arrows'>
<button title={formatMessage(messages.moveLeft)} aria-label={formatMessage(messages.moveLeft)} className='icon-button column-header__setting-btn' onClick={this.handleMoveLeft}><Icon id='chevron-left' icon={ChevronLeftIcon} /></button>
<button title={formatMessage(messages.moveRight)} aria-label={formatMessage(messages.moveRight)} className='icon-button column-header__setting-btn' onClick={this.handleMoveRight}><Icon id='chevron-right' icon={ChevronRightIcon} /></button>
</div>
);
} else if (multiColumn && this.props.onPin) {
pinButton = <button key='pin-button' className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='plus' icon={AddIcon} /> <FormattedMessage id='column_header.pin' defaultMessage='Pin' /></button>;
pinButton = <button className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='plus' icon={AddIcon} /> <FormattedMessage id='column_header.pin' defaultMessage='Pin' /></button>;
}
backButton = <BackButton pinned={pinned} show={showBackButton} />;
backButton = <BackButton pinned={pinned} show={showBackButton} onlyIcon={!!title} />;
const collapsedContent = [
extraContent,
];
if (multiColumn) {
collapsedContent.push(pinButton);
collapsedContent.push(moveButtons);
collapsedContent.push(
<div key='buttons' className='column-header__advanced-buttons'>
{pinButton}
{moveButtons}
</div>
);
}
if (this.context.identity.signedIn && (children || (multiColumn && this.props.onPin))) {
@ -177,7 +185,7 @@ class ColumnHeader extends PureComponent {
onClick={this.handleToggleClick}
>
<i className='icon-with-badge'>
<Icon id='sliders' icon={TuneIcon} />
<Icon id='sliders' icon={SettingsIcon} />
{collapseIssues && <i className='icon-with-badge__issue-badge' />}
</i>
</button>
@ -190,16 +198,19 @@ class ColumnHeader extends PureComponent {
<div className={wrapperClassName}>
<h1 className={buttonClassName}>
{hasTitle && (
<button onClick={this.handleTitleClick}>
<Icon id={icon} icon={iconComponent} className='column-header__icon' />
{title}
</button>
<>
{backButton}
<button onClick={this.handleTitleClick} className='column-header__title'>
{!showBackButton && <Icon id={icon} icon={iconComponent} className='column-header__icon' />}
{title}
</button>
</>
)}
{!hasTitle && backButton}
<div className='column-header__buttons'>
{hasTitle && backButton}
{extraButton}
{collapseButton}
</div>

View File

@ -9,7 +9,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { supportsPassiveEvents } from 'detect-passive-events';
import Overlay from 'react-overlays/Overlay';
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
import { CircularProgress } from 'mastodon/components/circular_progress';
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
@ -298,7 +297,7 @@ class Dropdown extends PureComponent {
}) : (
<IconButton
icon={!open ? icon : 'close'}
iconComponent={!open ? iconComponent : CloseIcon}
iconComponent={iconComponent}
title={title}
active={open}
disabled={disabled}

View File

@ -170,7 +170,8 @@ class About extends PureComponent {
<ol className='rules-list'>
{server.get('rules').map(rule => (
<li key={rule.get('id')}>
<span className='rules-list__text'>{rule.get('text')}</span>
<div className='rules-list__text'>{rule.get('text')}</div>
{rule.get('hint').length > 0 && (<div className='rules-list__hint'>{rule.get('hint')}</div>)}
</li>
))}
</ol>

View File

@ -22,6 +22,7 @@ import { CopyIconButton } from 'mastodon/components/copy_icon_button';
import { FollowersCounter, FollowingCounter, StatusesCounter } from 'mastodon/components/counters';
import { Icon } from 'mastodon/components/icon';
import { IconButton } from 'mastodon/components/icon_button';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import { ShortNumber } from 'mastodon/components/short_number';
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
import { autoPlayGif, me, domain } from 'mastodon/initial_state';
@ -289,7 +290,7 @@ class Header extends ImmutablePureComponent {
if (me !== account.get('id')) {
if (signedIn && !account.get('relationship')) { // Wait until the relationship is loaded
actionBtn = '';
actionBtn = <Button disabled><LoadingIndicator /></Button>;
} else if (account.getIn(['relationship', 'requested'])) {
actionBtn = <Button text={intl.formatMessage(messages.cancel_follow_request)} title={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />;
} else if (!account.getIn(['relationship', 'blocking'])) {
@ -426,15 +427,10 @@ class Header extends ImmutablePureComponent {
</a>
<div className='account__header__tabs__buttons'>
{!hidden && (
<>
{actionBtn}
{bellBtn}
{shareBtn}
</>
)}
{!hidden && bellBtn}
{!hidden && shareBtn}
<DropdownMenuContainer disabled={menu.length === 0} items={menu} icon='ellipsis-v' iconComponent={MoreHorizIcon} size={24} direction='right' />
{!hidden && actionBtn}
</div>
</div>

View File

@ -20,7 +20,7 @@ class ColumnSettings extends PureComponent {
const { settings, onChange } = this.props;
return (
<div>
<div className='column-settings'>
<div className='column-settings__row'>
<SettingToggle settings={settings} settingPath={['other', 'onlyMedia']} onChange={onChange} label={<FormattedMessage id='community.column_settings.media_only' defaultMessage='Media only' />} />
</div>

View File

@ -58,10 +58,11 @@ const Option = ({ multipleChoice, index, title, autoFocus }) => {
const dispatch = useDispatch();
const suggestions = useSelector(state => state.getIn(['compose', 'suggestions']));
const lang = useSelector(state => state.getIn(['compose', 'language']));
const maxOptions = useSelector(state => state.getIn(['server', 'server', 'configuration', 'polls', 'max_options']));
const handleChange = useCallback(({ target: { value } }) => {
dispatch(changePollOption(index, value));
}, [dispatch, index]);
dispatch(changePollOption(index, value, maxOptions));
}, [dispatch, index, maxOptions]);
const handleSuggestionsFetchRequested = useCallback(token => {
dispatch(fetchComposeSuggestions(token));

View File

@ -42,15 +42,17 @@ const ColumnSettings = () => {
);
return (
<div>
<div className='column-settings__row'>
<SettingToggle
settings={settings}
settingPath={['onlyMedia']}
onChange={onChange}
label={<FormattedMessage id='community.column_settings.media_only' defaultMessage='Media only' />}
/>
</div>
<div className='column-settings'>
<section>
<div className='column-settings__row'>
<SettingToggle
settings={settings}
settingPath={['onlyMedia']}
onChange={onChange}
label={<FormattedMessage id='community.column_settings.media_only' defaultMessage='Media only' />}
/>
</div>
</section>
</div>
);
};

View File

@ -107,28 +107,28 @@ class ColumnSettings extends PureComponent {
const { settings, onChange } = this.props;
return (
<div>
<div className='column-settings__row'>
<div className='setting-toggle'>
<Toggle id='hashtag.column_settings.tag_toggle' onChange={this.onToggle} checked={this.state.open} />
<div className='column-settings'>
<section>
<div className='column-settings__row'>
<SettingToggle settings={settings} settingPath={['local']} onChange={onChange} label={<FormattedMessage id='community.column_settings.local_only' defaultMessage='Local only' />} />
<span className='setting-toggle__label'>
<FormattedMessage id='hashtag.column_settings.tag_toggle' defaultMessage='Include additional tags in this column' />
</span>
<div className='setting-toggle'>
<Toggle id='hashtag.column_settings.tag_toggle' onChange={this.onToggle} checked={this.state.open} />
<span className='setting-toggle__label'>
<FormattedMessage id='hashtag.column_settings.tag_toggle' defaultMessage='Include additional tags in this column' />
</span>
</div>
</div>
</div>
{this.state.open && (
<div className='column-settings__hashtags'>
{this.modeSelect('any')}
{this.modeSelect('all')}
{this.modeSelect('none')}
</div>
)}
<div className='column-settings__row'>
<SettingToggle settings={settings} settingPath={['local']} onChange={onChange} label={<FormattedMessage id='community.column_settings.local_only' defaultMessage='Local only' />} />
</div>
{this.state.open && (
<div className='column-settings__hashtags'>
{this.modeSelect('any')}
{this.modeSelect('all')}
{this.modeSelect('none')}
</div>
)}
</section>
</div>
);
}

View File

@ -24,43 +24,36 @@ export const ColumnSettings: React.FC = () => {
);
return (
<div>
<span className='column-settings__section'>
<FormattedMessage
id='home.column_settings.basic'
defaultMessage='Basic'
/>
</span>
<div className='column-settings'>
<section>
<div className='column-settings__row'>
<SettingToggle
prefix='home_timeline'
settings={settings}
settingPath={['shows', 'reblog']}
onChange={onChange}
label={
<FormattedMessage
id='home.column_settings.show_reblogs'
defaultMessage='Show boosts'
/>
}
/>
<div className='column-settings__row'>
<SettingToggle
prefix='home_timeline'
settings={settings}
settingPath={['shows', 'reblog']}
onChange={onChange}
label={
<FormattedMessage
id='home.column_settings.show_reblogs'
defaultMessage='Show boosts'
/>
}
/>
</div>
<div className='column-settings__row'>
<SettingToggle
prefix='home_timeline'
settings={settings}
settingPath={['shows', 'reply']}
onChange={onChange}
label={
<FormattedMessage
id='home.column_settings.show_replies'
defaultMessage='Show replies'
/>
}
/>
</div>
<SettingToggle
prefix='home_timeline'
settings={settings}
settingPath={['shows', 'reply']}
onChange={onChange}
label={
<FormattedMessage
id='home.column_settings.show_replies'
defaultMessage='Show replies'
/>
}
/>
</div>
</section>
</div>
);
};

View File

@ -193,35 +193,38 @@ class ListTimeline extends PureComponent {
pinned={pinned}
multiColumn={multiColumn}
>
<div className='column-settings__row column-header__links'>
<button type='button' className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleEditClick}>
<Icon id='pencil' icon={EditIcon} /> <FormattedMessage id='lists.edit' defaultMessage='Edit list' />
</button>
<div className='column-settings'>
<section className='column-header__links'>
<button type='button' className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleEditClick}>
<Icon id='pencil' icon={EditIcon} /> <FormattedMessage id='lists.edit' defaultMessage='Edit list' />
</button>
<button type='button' className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleDeleteClick}>
<Icon id='trash' icon={DeleteIcon} /> <FormattedMessage id='lists.delete' defaultMessage='Delete list' />
</button>
</div>
<button type='button' className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleDeleteClick}>
<Icon id='trash' icon={DeleteIcon} /> <FormattedMessage id='lists.delete' defaultMessage='Delete list' />
</button>
</section>
<div className='setting-toggle'>
<Toggle id={`list-${id}-exclusive`} checked={isExclusive} onChange={this.onExclusiveToggle} />
<label htmlFor={`list-${id}-exclusive`} className='setting-toggle__label'>
<FormattedMessage id='lists.exclusive' defaultMessage='Hide these posts from home' />
</label>
</div>
{ replies_policy !== undefined && (
<div role='group' aria-labelledby={`list-${id}-replies-policy`}>
<span id={`list-${id}-replies-policy`} className='column-settings__section'>
<FormattedMessage id='lists.replies_policy.title' defaultMessage='Show replies to:' />
</span>
<div className='column-settings__row'>
{ ['none', 'list', 'followed'].map(policy => (
<RadioButton name='order' key={policy} value={policy} label={intl.formatMessage(messages[policy])} checked={replies_policy === policy} onChange={this.handleRepliesPolicyChange} />
))}
<section>
<div className='setting-toggle'>
<Toggle id={`list-${id}-exclusive`} checked={isExclusive} onChange={this.onExclusiveToggle} />
<label htmlFor={`list-${id}-exclusive`} className='setting-toggle__label'>
<FormattedMessage id='lists.exclusive' defaultMessage='Hide these posts from home' />
</label>
</div>
</div>
)}
</section>
{replies_policy !== undefined && (
<section aria-labelledby={`list-${id}-replies-policy`}>
<h3 id={`list-${id}-replies-policy`}><FormattedMessage id='lists.replies_policy.title' defaultMessage='Show replies to:' /></h3>
<div className='column-settings__row'>
{ ['none', 'list', 'followed'].map(policy => (
<RadioButton name='order' key={policy} value={policy} label={intl.formatMessage(messages[policy])} checked={replies_policy === policy} onChange={this.handleRepliesPolicyChange} />
))}
</div>
</section>
)}
</div>
</ColumnHeader>
<StatusListContainer

View File

@ -0,0 +1,31 @@
import PropTypes from 'prop-types';
import { useCallback } from 'react';
import Toggle from 'react-toggle';
export const CheckboxWithLabel = ({ checked, disabled, children, onChange }) => {
const handleChange = useCallback(({ target }) => {
onChange(target.checked);
}, [onChange]);
return (
<label className='app-form__toggle'>
<div className='app-form__toggle__label'>
{children}
</div>
<div className='app-form__toggle__toggle'>
<div>
<Toggle checked={checked} onChange={handleChange} disabled={disabled} />
</div>
</div>
</label>
);
};
CheckboxWithLabel.propTypes = {
checked: PropTypes.bool,
disabled: PropTypes.bool,
children: PropTypes.children,
onChange: PropTypes.func,
};

View File

@ -7,6 +7,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_REPORTS } from 'mastodon/permissions';
import { CheckboxWithLabel } from './checkbox_with_label';
import ClearColumnButton from './clear_column_button';
import GrantPermissionButton from './grant_permission_button';
import SettingToggle from './setting_toggle';
@ -26,18 +27,34 @@ export default class ColumnSettings extends PureComponent {
alertsEnabled: PropTypes.bool,
browserSupport: PropTypes.bool,
browserPermission: PropTypes.string,
notificationPolicy: ImmutablePropTypes.map,
onChangePolicy: PropTypes.func.isRequired,
};
onPushChange = (path, checked) => {
this.props.onChange(['push', ...path], checked);
};
handleFilterNotFollowing = checked => {
this.props.onChangePolicy('filter_not_following', checked);
};
handleFilterNotFollowers = checked => {
this.props.onChangePolicy('filter_not_followers', checked);
};
handleFilterNewAccounts = checked => {
this.props.onChangePolicy('filter_new_accounts', checked);
};
handleFilterPrivateMentions = checked => {
this.props.onChangePolicy('filter_private_mentions', checked);
};
render () {
const { settings, pushSettings, onChange, onClear, alertsEnabled, browserSupport, browserPermission, onRequestNotificationPermission } = this.props;
const { settings, pushSettings, onChange, onClear, alertsEnabled, browserSupport, browserPermission, onRequestNotificationPermission, notificationPolicy } = this.props;
const unreadMarkersShowStr = <FormattedMessage id='notifications.column_settings.unread_notifications.highlight' defaultMessage='Highlight unread notifications' />;
const filterBarShowStr = <FormattedMessage id='notifications.column_settings.filter_bar.show_bar' defaultMessage='Show filter bar' />;
const filterAdvancedStr = <FormattedMessage id='notifications.column_settings.filter_bar.advanced' defaultMessage='Display all categories' />;
const alertStr = <FormattedMessage id='notifications.column_settings.alert' defaultMessage='Desktop notifications' />;
const showStr = <FormattedMessage id='notifications.column_settings.show' defaultMessage='Show in column' />;
const soundStr = <FormattedMessage id='notifications.column_settings.sound' defaultMessage='Play sound' />;
@ -46,48 +63,59 @@ export default class ColumnSettings extends PureComponent {
const pushStr = showPushSettings && <FormattedMessage id='notifications.column_settings.push' defaultMessage='Push notifications' />;
return (
<div>
<div className='column-settings'>
{alertsEnabled && browserSupport && browserPermission === 'denied' && (
<div className='column-settings__row column-settings__row--with-margin'>
<span className='warning-hint'><FormattedMessage id='notifications.permission_denied' defaultMessage='Desktop notifications are unavailable due to previously denied browser permissions request' /></span>
</div>
<span className='warning-hint'><FormattedMessage id='notifications.permission_denied' defaultMessage='Desktop notifications are unavailable due to previously denied browser permissions request' /></span>
)}
{alertsEnabled && browserSupport && browserPermission === 'default' && (
<div className='column-settings__row column-settings__row--with-margin'>
<span className='warning-hint'>
<FormattedMessage id='notifications.permission_required' defaultMessage='Desktop notifications are unavailable because the required permission has not been granted.' /> <GrantPermissionButton onClick={onRequestNotificationPermission} />
</span>
</div>
<span className='warning-hint'>
<FormattedMessage id='notifications.permission_required' defaultMessage='Desktop notifications are unavailable because the required permission has not been granted.' /> <GrantPermissionButton onClick={onRequestNotificationPermission} />
</span>
)}
<div className='column-settings__row'>
<section>
<ClearColumnButton onClick={onClear} />
</div>
</section>
<div role='group' aria-labelledby='notifications-unread-markers'>
<span id='notifications-unread-markers' className='column-settings__section'>
<section>
<h3><FormattedMessage id='notifications.policy.title' defaultMessage='Filter out notifications from…' /></h3>
<div className='column-settings__row'>
<CheckboxWithLabel checked={notificationPolicy.get('filter_not_following')} onChange={this.handleFilterNotFollowing}>
<strong><FormattedMessage id='notifications.policy.filter_not_following_title' defaultMessage="People you don't follow" /></strong>
<span className='hint'><FormattedMessage id='notifications.policy.filter_not_following_hint' defaultMessage='Until you manually approve them' /></span>
</CheckboxWithLabel>
<CheckboxWithLabel checked={notificationPolicy.get('filter_not_followers')} onChange={this.handleFilterNotFollowers}>
<strong><FormattedMessage id='notifications.policy.filter_not_followers_title' defaultMessage='People not following you' /></strong>
<span className='hint'><FormattedMessage id='notifications.policy.filter_not_followers_hint' defaultMessage='Including people who have been following you fewer than {days, plural, one {one day} other {# days}}' values={{ days: 3 }} /></span>
</CheckboxWithLabel>
<CheckboxWithLabel checked={notificationPolicy.get('filter_new_accounts')} onChange={this.handleFilterNewAccounts}>
<strong><FormattedMessage id='notifications.policy.filter_new_accounts_title' defaultMessage='New accounts' /></strong>
<span className='hint'><FormattedMessage id='notifications.policy.filter_new_accounts.hint' defaultMessage='Created within the past {days, plural, one {one day} other {# days}}' values={{ days: 30 }} /></span>
</CheckboxWithLabel>
<CheckboxWithLabel checked={notificationPolicy.get('filter_private_mentions')} onChange={this.handleFilterPrivateMentions}>
<strong><FormattedMessage id='notifications.policy.filter_private_mentions_title' defaultMessage='Unsolicited private mentions' /></strong>
<span className='hint'><FormattedMessage id='notifications.policy.filter_private_mentions_hint' defaultMessage="Filtered unless it's in reply to your own mention or if you follow the sender" /></span>
</CheckboxWithLabel>
</div>
</section>
<section role='group' aria-labelledby='notifications-unread-markers'>
<h3 id='notifications-unread-markers'>
<FormattedMessage id='notifications.column_settings.unread_notifications.category' defaultMessage='Unread notifications' />
</span>
</h3>
<div className='column-settings__row'>
<SettingToggle id='unread-notification-markers' prefix='notifications' settings={settings} settingPath={['showUnread']} onChange={onChange} label={unreadMarkersShowStr} />
</div>
</div>
</section>
<div role='group' aria-labelledby='notifications-filter-bar'>
<span id='notifications-filter-bar' className='column-settings__section'>
<FormattedMessage id='notifications.column_settings.filter_bar.category' defaultMessage='Quick filter bar' />
</span>
<div className='column-settings__row'>
<SettingToggle id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'show']} onChange={onChange} label={filterBarShowStr} />
<SettingToggle id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'advanced']} onChange={onChange} label={filterAdvancedStr} />
</div>
</div>
<div role='group' aria-labelledby='notifications-follow'>
<span id='notifications-follow' className='column-settings__section'><FormattedMessage id='notifications.column_settings.follow' defaultMessage='New followers:' /></span>
<section role='group' aria-labelledby='notifications-follow'>
<h3 id='notifications-follow'><FormattedMessage id='notifications.column_settings.follow' defaultMessage='New followers:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'follow']} onChange={onChange} label={alertStr} />
@ -95,10 +123,10 @@ export default class ColumnSettings extends PureComponent {
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'follow']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'follow']} onChange={onChange} label={soundStr} />
</div>
</div>
</section>
<div role='group' aria-labelledby='notifications-follow-request'>
<span id='notifications-follow-request' className='column-settings__section'><FormattedMessage id='notifications.column_settings.follow_request' defaultMessage='New follow requests:' /></span>
<section role='group' aria-labelledby='notifications-follow-request'>
<h3 id='notifications-follow-request'><FormattedMessage id='notifications.column_settings.follow_request' defaultMessage='New follow requests:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'follow_request']} onChange={onChange} label={alertStr} />
@ -106,10 +134,10 @@ export default class ColumnSettings extends PureComponent {
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'follow_request']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'follow_request']} onChange={onChange} label={soundStr} />
</div>
</div>
</section>
<div role='group' aria-labelledby='notifications-favourite'>
<span id='notifications-favourite' className='column-settings__section'><FormattedMessage id='notifications.column_settings.favourite' defaultMessage='Favorites:' /></span>
<section role='group' aria-labelledby='notifications-favourite'>
<h3 id='notifications-favourite'><FormattedMessage id='notifications.column_settings.favourite' defaultMessage='Favorites:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'favourite']} onChange={onChange} label={alertStr} />
@ -117,10 +145,10 @@ export default class ColumnSettings extends PureComponent {
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'favourite']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'favourite']} onChange={onChange} label={soundStr} />
</div>
</div>
</section>
<div role='group' aria-labelledby='notifications-mention'>
<span id='notifications-mention' className='column-settings__section'><FormattedMessage id='notifications.column_settings.mention' defaultMessage='Mentions:' /></span>
<section role='group' aria-labelledby='notifications-mention'>
<h3 id='notifications-mention'><FormattedMessage id='notifications.column_settings.mention' defaultMessage='Mentions:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'mention']} onChange={onChange} label={alertStr} />
@ -128,10 +156,10 @@ export default class ColumnSettings extends PureComponent {
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'mention']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'mention']} onChange={onChange} label={soundStr} />
</div>
</div>
</section>
<div role='group' aria-labelledby='notifications-reblog'>
<span id='notifications-reblog' className='column-settings__section'><FormattedMessage id='notifications.column_settings.reblog' defaultMessage='Boosts:' /></span>
<section role='group' aria-labelledby='notifications-reblog'>
<h3 id='notifications-reblog'><FormattedMessage id='notifications.column_settings.reblog' defaultMessage='Boosts:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'reblog']} onChange={onChange} label={alertStr} />
@ -139,10 +167,10 @@ export default class ColumnSettings extends PureComponent {
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'reblog']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'reblog']} onChange={onChange} label={soundStr} />
</div>
</div>
</section>
<div role='group' aria-labelledby='notifications-poll'>
<span id='notifications-poll' className='column-settings__section'><FormattedMessage id='notifications.column_settings.poll' defaultMessage='Poll results:' /></span>
<section role='group' aria-labelledby='notifications-poll'>
<h3 id='notifications-poll'><FormattedMessage id='notifications.column_settings.poll' defaultMessage='Poll results:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'poll']} onChange={onChange} label={alertStr} />
@ -150,10 +178,10 @@ export default class ColumnSettings extends PureComponent {
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'poll']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'poll']} onChange={onChange} label={soundStr} />
</div>
</div>
</section>
<div role='group' aria-labelledby='notifications-status'>
<span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.status' defaultMessage='New posts:' /></span>
<section role='group' aria-labelledby='notifications-status'>
<h3 id='notifications-status'><FormattedMessage id='notifications.column_settings.status' defaultMessage='New posts:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'status']} onChange={onChange} label={alertStr} />
@ -161,10 +189,10 @@ export default class ColumnSettings extends PureComponent {
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'status']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'status']} onChange={onChange} label={soundStr} />
</div>
</div>
</section>
<div role='group' aria-labelledby='notifications-update'>
<span id='notifications-update' className='column-settings__section'><FormattedMessage id='notifications.column_settings.update' defaultMessage='Edits:' /></span>
<section role='group' aria-labelledby='notifications-update'>
<h3 id='notifications-update'><FormattedMessage id='notifications.column_settings.update' defaultMessage='Edits:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'update']} onChange={onChange} label={alertStr} />
@ -172,11 +200,11 @@ export default class ColumnSettings extends PureComponent {
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'update']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'update']} onChange={onChange} label={soundStr} />
</div>
</div>
</section>
{((this.context.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) && (
<div role='group' aria-labelledby='notifications-admin-sign-up'>
<span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.admin.sign_up' defaultMessage='New sign-ups:' /></span>
<section role='group' aria-labelledby='notifications-admin-sign-up'>
<h3 id='notifications-status'><FormattedMessage id='notifications.column_settings.admin.sign_up' defaultMessage='New sign-ups:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'admin.sign_up']} onChange={onChange} label={alertStr} />
@ -184,12 +212,12 @@ export default class ColumnSettings extends PureComponent {
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'admin.sign_up']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'admin.sign_up']} onChange={onChange} label={soundStr} />
</div>
</div>
</section>
)}
{((this.context.identity.permissions & PERMISSION_MANAGE_REPORTS) === PERMISSION_MANAGE_REPORTS) && (
<div role='group' aria-labelledby='notifications-admin-report'>
<span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.admin.report' defaultMessage='New reports:' /></span>
<section role='group' aria-labelledby='notifications-admin-report'>
<h3 id='notifications-status'><FormattedMessage id='notifications.column_settings.admin.report' defaultMessage='New reports:' /></h3>
<div className='column-settings__row'>
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'admin.report']} onChange={onChange} label={alertStr} />
@ -197,7 +225,7 @@ export default class ColumnSettings extends PureComponent {
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'admin.report']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'admin.report']} onChange={onChange} label={soundStr} />
</div>
</div>
</section>
)}
</div>
);

View File

@ -0,0 +1,49 @@
import { useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import ArchiveIcon from '@/material-icons/400-24px/archive.svg?react';
import { fetchNotificationPolicy } from 'mastodon/actions/notifications';
import { Icon } from 'mastodon/components/icon';
import { toCappedNumber } from 'mastodon/utils/numbers';
export const FilteredNotificationsBanner = () => {
const dispatch = useDispatch();
const policy = useSelector(state => state.get('notificationPolicy'));
useEffect(() => {
dispatch(fetchNotificationPolicy());
const interval = setInterval(() => {
dispatch(fetchNotificationPolicy());
}, 120000);
return () => {
clearInterval(interval);
};
}, [dispatch]);
if (policy === null || policy.getIn(['summary', 'pending_notifications_count']) * 1 === 0) {
return null;
}
return (
<Link className='filtered-notifications-banner' to='/notifications/requests'>
<Icon icon={ArchiveIcon} />
<div className='filtered-notifications-banner__text'>
<strong><FormattedMessage id='filtered_notifications_banner.title' defaultMessage='Filtered notifications' /></strong>
<span><FormattedMessage id='filtered_notifications_banner.pending_requests' defaultMessage='Notifications from {count, plural, =0 {no} one {one person} other {# people}} you may know' values={{ count: policy.getIn(['summary', 'pending_requests_count']) }} /></span>
</div>
<div className='filtered-notifications-banner__badge'>
{toCappedNumber(policy.getIn(['summary', 'pending_notifications_count']))}
</div>
</Link>
);
};

View File

@ -0,0 +1,65 @@
import PropTypes from 'prop-types';
import { useCallback } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { Link } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import DoneIcon from '@/material-icons/400-24px/done.svg?react';
import VolumeOffIcon from '@/material-icons/400-24px/volume_off.svg?react';
import { acceptNotificationRequest, dismissNotificationRequest } from 'mastodon/actions/notifications';
import { Avatar } from 'mastodon/components/avatar';
import { IconButton } from 'mastodon/components/icon_button';
import { makeGetAccount } from 'mastodon/selectors';
import { toCappedNumber } from 'mastodon/utils/numbers';
const getAccount = makeGetAccount();
const messages = defineMessages({
accept: { id: 'notification_requests.accept', defaultMessage: 'Accept' },
dismiss: { id: 'notification_requests.dismiss', defaultMessage: 'Dismiss' },
});
export const NotificationRequest = ({ id, accountId, notificationsCount }) => {
const dispatch = useDispatch();
const account = useSelector(state => getAccount(state, accountId));
const intl = useIntl();
const handleDismiss = useCallback(() => {
dispatch(dismissNotificationRequest(id));
}, [dispatch, id]);
const handleAccept = useCallback(() => {
dispatch(acceptNotificationRequest(id));
}, [dispatch, id]);
return (
<div className='notification-request'>
<Link to={`/notifications/requests/${id}`} className='notification-request__link'>
<Avatar account={account} size={36} />
<div className='notification-request__name'>
<div className='notification-request__name__display-name'>
<bdi><strong dangerouslySetInnerHTML={{ __html: account?.get('display_name_html') }} /></bdi>
<span className='filtered-notifications-banner__badge'>{toCappedNumber(notificationsCount)}</span>
</div>
<span>@{account?.get('acct')}</span>
</div>
</Link>
<div className='notification-request__actions'>
<IconButton iconComponent={VolumeOffIcon} onClick={handleDismiss} title={intl.formatMessage(messages.dismiss)} />
<IconButton iconComponent={DoneIcon} onClick={handleAccept} title={intl.formatMessage(messages.accept)} />
</div>
</div>
);
};
NotificationRequest.propTypes = {
id: PropTypes.string.isRequired,
accountId: PropTypes.string.isRequired,
notificationsCount: PropTypes.string.isRequired,
};

View File

@ -4,7 +4,7 @@ import { connect } from 'react-redux';
import { showAlert } from '../../../actions/alerts';
import { openModal } from '../../../actions/modal';
import { setFilter, clearNotifications, requestBrowserPermission } from '../../../actions/notifications';
import { setFilter, clearNotifications, requestBrowserPermission, updateNotificationsPolicy } from '../../../actions/notifications';
import { changeAlerts as changePushNotifications } from '../../../actions/push_notifications';
import { changeSetting } from '../../../actions/settings';
import ColumnSettings from '../components/column_settings';
@ -21,6 +21,7 @@ const mapStateToProps = state => ({
alertsEnabled: state.getIn(['settings', 'notifications', 'alerts']).includes(true),
browserSupport: state.getIn(['notifications', 'browserSupport']),
browserPermission: state.getIn(['notifications', 'browserPermission']),
notificationPolicy: state.get('notificationPolicy'),
});
const mapDispatchToProps = (dispatch, { intl }) => ({
@ -73,6 +74,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
dispatch(requestBrowserPermission());
},
onChangePolicy (param, checked) {
dispatch(updateNotificationsPolicy({
[param]: checked,
}));
},
});
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ColumnSettings));

View File

@ -5,7 +5,7 @@ import FilterBar from '../components/filter_bar';
const makeMapStateToProps = state => ({
selectedFilter: state.getIn(['settings', 'notifications', 'quickFilter', 'active']),
advancedMode: state.getIn(['settings', 'notifications', 'quickFilter', 'advanced']),
advancedMode: false,
});
const mapDispatchToProps = (dispatch) => ({

View File

@ -33,6 +33,7 @@ import ColumnHeader from '../../components/column_header';
import { LoadGap } from '../../components/load_gap';
import ScrollableList from '../../components/scrollable_list';
import { FilteredNotificationsBanner } from './components/filtered_notifications_banner';
import NotificationsPermissionBanner from './components/notifications_permission_banner';
import ColumnSettingsContainer from './containers/column_settings_container';
import FilterBarContainer from './containers/filter_bar_container';
@ -65,7 +66,6 @@ const getNotifications = createSelector([
});
const mapStateToProps = state => ({
showFilterBar: state.getIn(['settings', 'notifications', 'quickFilter', 'show']),
notifications: getNotifications(state),
isLoading: state.getIn(['notifications', 'isLoading'], 0) > 0,
isUnread: state.getIn(['notifications', 'unread']) > 0 || state.getIn(['notifications', 'pendingItems']).size > 0,
@ -85,7 +85,6 @@ class Notifications extends PureComponent {
static propTypes = {
columnId: PropTypes.string,
notifications: ImmutablePropTypes.list.isRequired,
showFilterBar: PropTypes.bool.isRequired,
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
isLoading: PropTypes.bool,
@ -188,14 +187,14 @@ class Notifications extends PureComponent {
};
render () {
const { intl, notifications, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, showFilterBar, lastReadId, canMarkAsRead, needsNotificationPermission } = this.props;
const { intl, notifications, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, lastReadId, canMarkAsRead, needsNotificationPermission } = this.props;
const pinned = !!columnId;
const emptyMessage = <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. When other people interact with you, you will see it here." />;
const { signedIn } = this.context.identity;
let scrollableContent = null;
const filterBarContainer = (signedIn && showFilterBar)
const filterBarContainer = signedIn
? (<FilterBarContainer />)
: null;
@ -285,6 +284,9 @@ class Notifications extends PureComponent {
</ColumnHeader>
{filterBarContainer}
<FilteredNotificationsBanner />
{scrollContainer}
<Helmet>

View File

@ -0,0 +1,144 @@
import PropTypes from 'prop-types';
import { useRef, useCallback, useEffect } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { Helmet } from 'react-helmet';
import { useSelector, useDispatch } from 'react-redux';
import ArchiveIcon from '@/material-icons/400-24px/archive.svg?react';
import DoneIcon from '@/material-icons/400-24px/done.svg?react';
import VolumeOffIcon from '@/material-icons/400-24px/volume_off.svg?react';
import { fetchNotificationRequest, fetchNotificationsForRequest, expandNotificationsForRequest, acceptNotificationRequest, dismissNotificationRequest } from 'mastodon/actions/notifications';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
import { IconButton } from 'mastodon/components/icon_button';
import ScrollableList from 'mastodon/components/scrollable_list';
import NotificationContainer from './containers/notification_container';
const messages = defineMessages({
title: { id: 'notification_requests.notifications_from', defaultMessage: 'Notifications from {name}' },
accept: { id: 'notification_requests.accept', defaultMessage: 'Accept' },
dismiss: { id: 'notification_requests.dismiss', defaultMessage: 'Dismiss' },
});
const selectChild = (ref, index, alignTop) => {
const container = ref.current.node;
const element = container.querySelector(`article:nth-of-type(${index + 1}) .focusable`);
if (element) {
if (alignTop && container.scrollTop > element.offsetTop) {
element.scrollIntoView(true);
} else if (!alignTop && container.scrollTop + container.clientHeight < element.offsetTop + element.offsetHeight) {
element.scrollIntoView(false);
}
element.focus();
}
};
export const NotificationRequest = ({ multiColumn, params: { id } }) => {
const columnRef = useRef();
const intl = useIntl();
const dispatch = useDispatch();
const notificationRequest = useSelector(state => state.getIn(['notificationRequests', 'current', 'item', 'id']) === id ? state.getIn(['notificationRequests', 'current', 'item']) : null);
const accountId = notificationRequest?.get('account');
const account = useSelector(state => state.getIn(['accounts', accountId]));
const notifications = useSelector(state => state.getIn(['notificationRequests', 'current', 'notifications', 'items']));
const isLoading = useSelector(state => state.getIn(['notificationRequests', 'current', 'notifications', 'isLoading']));
const hasMore = useSelector(state => !!state.getIn(['notificationRequests', 'current', 'notifications', 'next']));
const removed = useSelector(state => state.getIn(['notificationRequests', 'current', 'removed']));
const handleHeaderClick = useCallback(() => {
columnRef.current?.scrollTop();
}, [columnRef]);
const handleLoadMore = useCallback(() => {
dispatch(expandNotificationsForRequest());
}, [dispatch]);
const handleDismiss = useCallback(() => {
dispatch(dismissNotificationRequest(id));
}, [dispatch, id]);
const handleAccept = useCallback(() => {
dispatch(acceptNotificationRequest(id));
}, [dispatch, id]);
const handleMoveUp = useCallback(id => {
const elementIndex = notifications.findIndex(item => item !== null && item.get('id') === id) - 1;
selectChild(columnRef, elementIndex, true);
}, [columnRef, notifications]);
const handleMoveDown = useCallback(id => {
const elementIndex = notifications.findIndex(item => item !== null && item.get('id') === id) + 1;
selectChild(columnRef, elementIndex, false);
}, [columnRef, notifications]);
useEffect(() => {
dispatch(fetchNotificationRequest(id));
}, [dispatch, id]);
useEffect(() => {
if (accountId) {
dispatch(fetchNotificationsForRequest(accountId));
}
}, [dispatch, accountId]);
const columnTitle = intl.formatMessage(messages.title, { name: account?.get('display_name') });
return (
<Column bindToDocument={!multiColumn} ref={columnRef} label={columnTitle}>
<ColumnHeader
icon='archive'
iconComponent={ArchiveIcon}
title={columnTitle}
onClick={handleHeaderClick}
multiColumn={multiColumn}
showBackButton
extraButton={!removed && (
<>
<IconButton className='column-header__button' iconComponent={VolumeOffIcon} onClick={handleDismiss} title={intl.formatMessage(messages.dismiss)} />
<IconButton className='column-header__button' iconComponent={DoneIcon} onClick={handleAccept} title={intl.formatMessage(messages.accept)} />
</>
)}
/>
<ScrollableList
scrollKey={`notification_requests/${id}`}
trackScroll={!multiColumn}
bindToDocument={!multiColumn}
isLoading={isLoading}
showLoading={isLoading && notifications.size === 0}
hasMore={hasMore}
onLoadMore={handleLoadMore}
>
{notifications.map(item => (
item && <NotificationContainer
key={item.get('id')}
notification={item}
accountId={item.get('account')}
onMoveUp={handleMoveUp}
onMoveDown={handleMoveDown}
/>
))}
</ScrollableList>
<Helmet>
<title>{columnTitle}</title>
<meta name='robots' content='noindex' />
</Helmet>
</Column>
);
};
NotificationRequest.propTypes = {
multiColumn: PropTypes.bool,
params: PropTypes.shape({
id: PropTypes.string.isRequired,
}),
};
export default NotificationRequest;

View File

@ -0,0 +1,85 @@
import PropTypes from 'prop-types';
import { useRef, useCallback, useEffect } from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { Helmet } from 'react-helmet';
import { useSelector, useDispatch } from 'react-redux';
import ArchiveIcon from '@/material-icons/400-24px/archive.svg?react';
import { fetchNotificationRequests, expandNotificationRequests } from 'mastodon/actions/notifications';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
import ScrollableList from 'mastodon/components/scrollable_list';
import { NotificationRequest } from './components/notification_request';
const messages = defineMessages({
title: { id: 'notification_requests.title', defaultMessage: 'Filtered notifications' },
});
export const NotificationRequests = ({ multiColumn }) => {
const columnRef = useRef();
const intl = useIntl();
const dispatch = useDispatch();
const isLoading = useSelector(state => state.getIn(['notificationRequests', 'isLoading']));
const notificationRequests = useSelector(state => state.getIn(['notificationRequests', 'items']));
const hasMore = useSelector(state => !!state.getIn(['notificationRequests', 'next']));
const handleHeaderClick = useCallback(() => {
columnRef.current?.scrollTop();
}, [columnRef]);
const handleLoadMore = useCallback(() => {
dispatch(expandNotificationRequests());
}, [dispatch]);
useEffect(() => {
dispatch(fetchNotificationRequests());
}, [dispatch]);
return (
<Column bindToDocument={!multiColumn} ref={columnRef} label={intl.formatMessage(messages.title)}>
<ColumnHeader
icon='archive'
iconComponent={ArchiveIcon}
title={intl.formatMessage(messages.title)}
onClick={handleHeaderClick}
multiColumn={multiColumn}
showBackButton
/>
<ScrollableList
scrollKey='notification_requests'
trackScroll={!multiColumn}
bindToDocument={!multiColumn}
isLoading={isLoading}
showLoading={isLoading && notificationRequests.size === 0}
hasMore={hasMore}
onLoadMore={handleLoadMore}
emptyMessage={<FormattedMessage id='empty_column.notification_requests' defaultMessage='All clear! There is nothing here. When you receive new notifications, they will appear here according to your settings.' />}
>
{notificationRequests.map(request => (
<NotificationRequest
key={request.get('id')}
id={request.get('id')}
accountId={request.get('account')}
notificationsCount={request.get('notifications_count')}
/>
))}
</ScrollableList>
<Helmet>
<title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content='noindex' />
</Helmet>
</Column>
);
};
NotificationRequests.propTypes = {
multiColumn: PropTypes.bool,
};
export default NotificationRequests;

View File

@ -20,11 +20,13 @@ class ColumnSettings extends PureComponent {
const { settings, onChange } = this.props;
return (
<div>
<div className='column-settings__row'>
<SettingToggle settings={settings} settingPath={['other', 'onlyMedia']} onChange={onChange} label={<FormattedMessage id='community.column_settings.media_only' defaultMessage='Media only' />} />
<SettingToggle settings={settings} settingPath={['other', 'onlyRemote']} onChange={onChange} label={<FormattedMessage id='community.column_settings.remote_only' defaultMessage='Remote only' />} />
</div>
<div className='column-settings'>
<section>
<div className='column-settings__row'>
<SettingToggle settings={settings} settingPath={['other', 'onlyMedia']} onChange={onChange} label={<FormattedMessage id='community.column_settings.media_only' defaultMessage='Media only' />} />
<SettingToggle settings={settings} settingPath={['other', 'onlyRemote']} onChange={onChange} label={<FormattedMessage id='community.column_settings.remote_only' defaultMessage='Remote only' />} />
</div>
</section>
</div>
);
}

View File

@ -1,27 +1,30 @@
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { NavLink } from 'react-router-dom';
import { useRouteMatch, NavLink } from 'react-router-dom';
import { Icon } from 'mastodon/components/icon';
const ColumnLink = ({ icon, iconComponent, text, to, href, method, badge, transparent, ...other }) => {
const ColumnLink = ({ icon, activeIcon, iconComponent, activeIconComponent, text, to, href, method, badge, transparent, ...other }) => {
const match = useRouteMatch(to);
const className = classNames('column-link', { 'column-link--transparent': transparent });
const badgeElement = typeof badge !== 'undefined' ? <span className='column-link__badge'>{badge}</span> : null;
const iconElement = (typeof icon === 'string' || iconComponent) ? <Icon id={icon} icon={iconComponent} className='column-link__icon' /> : icon;
const activeIconElement = activeIcon ?? (activeIconComponent ? <Icon id={icon} icon={activeIconComponent} className='column-link__icon' /> : iconElement);
const active = match?.isExact;
if (href) {
return (
<a href={href} className={className} data-method={method} title={text} {...other}>
{iconElement}
{active ? activeIconElement : iconElement}
<span>{text}</span>
{badgeElement}
</a>
);
} else {
return (
<NavLink to={to} className={className} title={text} {...other}>
{iconElement}
<NavLink to={to} className={className} title={text} exact {...other}>
{active ? activeIconElement : iconElement}
<span>{text}</span>
{badgeElement}
</NavLink>
@ -32,6 +35,8 @@ const ColumnLink = ({ icon, iconComponent, text, to, href, method, badge, transp
ColumnLink.propTypes = {
icon: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
iconComponent: PropTypes.func,
activeIcon: PropTypes.node,
activeIconComponent: PropTypes.func,
text: PropTypes.string.isRequired,
to: PropTypes.string,
href: PropTypes.string,

View File

@ -1,55 +0,0 @@
import PropTypes from 'prop-types';
import { Component } from 'react';
import { injectIntl, defineMessages } from 'react-intl';
import { List as ImmutableList } from 'immutable';
import { connect } from 'react-redux';
import PersonAddIcon from '@/material-icons/400-24px/person_add.svg?react';
import { fetchFollowRequests } from 'mastodon/actions/accounts';
import { IconWithBadge } from 'mastodon/components/icon_with_badge';
import ColumnLink from 'mastodon/features/ui/components/column_link';
const messages = defineMessages({
text: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
});
const mapStateToProps = state => ({
count: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
});
class FollowRequestsColumnLink extends Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
count: PropTypes.number.isRequired,
intl: PropTypes.object.isRequired,
};
componentDidMount () {
const { dispatch } = this.props;
dispatch(fetchFollowRequests());
}
render () {
const { count, intl } = this.props;
if (count === 0) {
return null;
}
return (
<ColumnLink
transparent
to='/follow_requests'
icon={<IconWithBadge className='column-link__icon' id='user-plus' icon={PersonAddIcon} count={count} />}
text={intl.formatMessage(messages.text)}
/>
);
}
}
export default injectIntl(connect(mapStateToProps)(FollowRequestsColumnLink));

View File

@ -1,10 +1,9 @@
import PropTypes from 'prop-types';
import { useEffect } from 'react';
import { createSelector } from '@reduxjs/toolkit';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import ListAltActiveIcon from '@/material-icons/400-24px/list_alt-fill.svg?react';
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
import { fetchLists } from 'mastodon/actions/lists';
@ -18,40 +17,25 @@ const getOrderedLists = createSelector([state => state.get('lists')], lists => {
return lists.toList().filter(item => !!item).sort((a, b) => a.get('title').localeCompare(b.get('title'))).take(4);
});
const mapStateToProps = state => ({
lists: getOrderedLists(state),
});
export const ListPanel = () => {
const dispatch = useDispatch();
const lists = useSelector(state => getOrderedLists(state));
class ListPanel extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,
lists: ImmutablePropTypes.list,
};
componentDidMount () {
const { dispatch } = this.props;
useEffect(() => {
dispatch(fetchLists());
}, [dispatch]);
if (!lists || lists.isEmpty()) {
return null;
}
render () {
const { lists } = this.props;
return (
<div className='list-panel'>
<hr />
if (!lists || lists.isEmpty()) {
return null;
}
return (
<div className='list-panel'>
<hr />
{lists.map(list => (
<ColumnLink icon='list-ul' iconComponent={ListAltIcon} key={list.get('id')} strict text={list.get('title')} to={`/lists/${list.get('id')}`} transparent />
))}
</div>
);
}
}
export default connect(mapStateToProps)(ListPanel);
{lists.map(list => (
<ColumnLink icon='list-ul' key={list.get('id')} iconComponent={ListAltIcon} activeIconComponent={ListAltActiveIcon} text={list.get('title')} to={`/lists/${list.get('id')}`} transparent />
))}
</div>
);
};

View File

@ -1,20 +1,33 @@
import PropTypes from 'prop-types';
import { Component } from 'react';
import { Component, useEffect } from 'react';
import { defineMessages, injectIntl } from 'react-intl';
import { defineMessages, injectIntl, useIntl } from 'react-intl';
import { Link } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
import BookmarksIcon from '@/material-icons/400-24px/bookmarks-fill.svg?react';
import BookmarksActiveIcon from '@/material-icons/400-24px/bookmarks-fill.svg?react';
import BookmarksIcon from '@/material-icons/400-24px/bookmarks.svg?react';
import ExploreIcon from '@/material-icons/400-24px/explore.svg?react';
import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react';
import HomeActiveIcon from '@/material-icons/400-24px/home-fill.svg?react';
import HomeIcon from '@/material-icons/400-24px/home.svg?react';
import ListAltActiveIcon from '@/material-icons/400-24px/list_alt-fill.svg?react';
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import NotificationsActiveIcon from '@/material-icons/400-24px/notifications-fill.svg?react';
import NotificationsIcon from '@/material-icons/400-24px/notifications.svg?react';
import PersonAddActiveIcon from '@/material-icons/400-24px/person_add-fill.svg?react';
import PersonAddIcon from '@/material-icons/400-24px/person_add.svg?react';
import PublicIcon from '@/material-icons/400-24px/public.svg?react';
import SearchIcon from '@/material-icons/400-24px/search.svg?react';
import SettingsIcon from '@/material-icons/400-24px/settings-fill.svg?react';
import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
import SettingsIcon from '@/material-icons/400-24px/settings.svg?react';
import StarActiveIcon from '@/material-icons/400-24px/star-fill.svg?react';
import StarIcon from '@/material-icons/400-24px/star.svg?react';
import { fetchFollowRequests } from 'mastodon/actions/accounts';
import { IconWithBadge } from 'mastodon/components/icon_with_badge';
import { WordmarkLogo } from 'mastodon/components/logo';
import { NavigationPortal } from 'mastodon/components/navigation_portal';
import { timelinePreview, trendsEnabled } from 'mastodon/initial_state';
@ -22,9 +35,7 @@ import { transientSingleColumn } from 'mastodon/is_mobile';
import ColumnLink from './column_link';
import DisabledAccountBanner from './disabled_account_banner';
import FollowRequestsColumnLink from './follow_requests_column_link';
import ListPanel from './list_panel';
import NotificationsCounterIcon from './notifications_counter_icon';
import { ListPanel } from './list_panel';
import SignInBanner from './sign_in_banner';
const messages = defineMessages({
@ -42,8 +53,48 @@ const messages = defineMessages({
search: { id: 'navigation_bar.search', defaultMessage: 'Search' },
advancedInterface: { id: 'navigation_bar.advanced_interface', defaultMessage: 'Open in advanced web interface' },
openedInClassicInterface: { id: 'navigation_bar.opened_in_classic_interface', defaultMessage: 'Posts, accounts, and other specific pages are opened by default in the classic web interface.' },
followRequests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
});
const NotificationsLink = () => {
const count = useSelector(state => state.getIn(['notifications', 'unread']));
const intl = useIntl();
return (
<ColumnLink
transparent
to='/notifications'
icon={<IconWithBadge icon={NotificationsIcon} count={count} className='column-link__icon' />}
activeIcon={<IconWithBadge icon={NotificationsActiveIcon} count={count} className='column-link__icon' />}
text={intl.formatMessage(messages.notifications)}
/>
);
};
const FollowRequestsLink = () => {
const count = useSelector(state => state.getIn(['user_lists', 'follow_requests', 'items'])?.size ?? 0);
const intl = useIntl();
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchFollowRequests());
}, [dispatch]);
if (count === 0) {
return null;
}
return (
<ColumnLink
transparent
to='/follow_requests'
icon={<IconWithBadge icon={PersonAddIcon} count={count} className='column-link__icon' />}
activeIcon={<IconWithBadge icon={PersonAddActiveIcon} count={count} className='column-link__icon' />}
text={intl.formatMessage(messages.followRequests)}
/>
);
};
class NavigationPanel extends Component {
static contextTypes = {
@ -87,9 +138,9 @@ class NavigationPanel extends Component {
{signedIn && (
<>
<ColumnLink transparent to='/home' icon='home' iconComponent={HomeIcon} text={intl.formatMessage(messages.home)} />
<ColumnLink transparent to='/notifications' icon={<NotificationsCounterIcon className='column-link__icon' />} text={intl.formatMessage(messages.notifications)} />
<FollowRequestsColumnLink />
<ColumnLink transparent to='/home' icon='home' iconComponent={HomeIcon} activeIconComponent={HomeActiveIcon} text={intl.formatMessage(messages.home)} />
<NotificationsLink />
<FollowRequestsLink />
</>
)}
@ -113,9 +164,9 @@ class NavigationPanel extends Component {
{signedIn && (
<>
<ColumnLink transparent to='/conversations' icon='at' iconComponent={AlternateEmailIcon} text={intl.formatMessage(messages.direct)} />
<ColumnLink transparent to='/bookmarks' icon='bookmarks' iconComponent={BookmarksIcon} text={intl.formatMessage(messages.bookmarks)} />
<ColumnLink transparent to='/favourites' icon='star' iconComponent={StarIcon} text={intl.formatMessage(messages.favourites)} />
<ColumnLink transparent to='/lists' icon='list-ul' iconComponent={ListAltIcon} text={intl.formatMessage(messages.lists)} />
<ColumnLink transparent to='/bookmarks' icon='bookmarks' iconComponent={BookmarksIcon} activeIconComponent={BookmarksActiveIcon} text={intl.formatMessage(messages.bookmarks)} />
<ColumnLink transparent to='/favourites' icon='star' iconComponent={StarIcon} activeIconComponent={StarActiveIcon} text={intl.formatMessage(messages.favourites)} />
<ColumnLink transparent to='/lists' icon='list-ul' iconComponent={ListAltIcon} activeIconComponent={ListAltActiveIcon} text={intl.formatMessage(messages.lists)} />
<ListPanel />

View File

@ -1,13 +0,0 @@
import { connect } from 'react-redux';
import NotificationsIcon from '@/material-icons/400-24px/notifications-fill.svg?react';
import { IconWithBadge } from 'mastodon/components/icon_with_badge';
const mapStateToProps = state => ({
count: state.getIn(['notifications', 'unread']),
id: 'bell',
icon: NotificationsIcon,
});
export default connect(mapStateToProps)(IconWithBadge);

View File

@ -48,6 +48,8 @@ import {
DirectTimeline,
HashtagTimeline,
Notifications,
NotificationRequests,
NotificationRequest,
FollowRequests,
FavouritedStatuses,
BookmarkedStatuses,
@ -80,7 +82,6 @@ const mapStateToProps = state => ({
hasComposingText: state.getIn(['compose', 'text']).trim().length !== 0,
hasMediaAttachments: state.getIn(['compose', 'media_attachments']).size > 0,
canUploadMore: !state.getIn(['compose', 'media_attachments']).some(x => ['audio', 'video'].includes(x.get('type'))) && state.getIn(['compose', 'media_attachments']).size < 4,
dropdownMenuIsOpen: state.dropdownMenu.openId !== null,
firstLaunch: state.getIn(['settings', 'introductionVersion'], 0) < INTRODUCTION_VERSION,
username: state.getIn(['accounts', me, 'username']),
});
@ -204,7 +205,9 @@ class SwitchingColumnsArea extends PureComponent {
<WrappedRoute path={['/conversations', '/timelines/direct']} component={DirectTimeline} content={children} />
<WrappedRoute path='/tags/:id' component={HashtagTimeline} content={children} />
<WrappedRoute path='/lists/:id' component={ListTimeline} content={children} />
<WrappedRoute path='/notifications' component={Notifications} content={children} />
<WrappedRoute path='/notifications' component={Notifications} content={children} exact />
<WrappedRoute path='/notifications/requests' component={NotificationRequests} content={children} exact />
<WrappedRoute path='/notifications/requests/:id' component={NotificationRequest} content={children} exact />
<WrappedRoute path='/favourites' component={FavouritedStatuses} content={children} />
<WrappedRoute path='/bookmarks' component={BookmarkedStatuses} content={children} />
@ -262,7 +265,6 @@ class UI extends PureComponent {
hasMediaAttachments: PropTypes.bool,
canUploadMore: PropTypes.bool,
intl: PropTypes.object.isRequired,
dropdownMenuIsOpen: PropTypes.bool,
layout: PropTypes.string.isRequired,
firstLaunch: PropTypes.bool,
username: PropTypes.string,
@ -555,7 +557,7 @@ class UI extends PureComponent {
render () {
const { draggingOver } = this.state;
const { children, isComposing, location, dropdownMenuIsOpen, layout } = this.props;
const { children, isComposing, location, layout } = this.props;
const handlers = {
help: this.handleHotkeyToggleHelp,
@ -581,7 +583,7 @@ class UI extends PureComponent {
return (
<HotKeys keyMap={keyMap} handlers={handlers} ref={this.setHotkeysRef} attach={window} focused>
<div className={classNames('ui', { 'is-composing': isComposing })} ref={this.setRef} style={{ pointerEvents: dropdownMenuIsOpen ? 'none' : null }}>
<div className={classNames('ui', { 'is-composing': isComposing })} ref={this.setRef}>
<Header />
<SwitchingColumnsArea location={location} singleColumn={layout === 'mobile' || layout === 'single-column'}>

View File

@ -189,3 +189,11 @@ export function About () {
export function PrivacyPolicy () {
return import(/*webpackChunkName: "features/privacy_policy" */'../../privacy_policy');
}
export function NotificationRequests () {
return import(/*webpackChunkName: "features/notifications/requests" */'../../notifications/requests');
}
export function NotificationRequest () {
return import(/*webpackChunkName: "features/notifications/request" */'../../notifications/request');
}

View File

@ -277,7 +277,13 @@
"follow_request.authorize": "ترخيص",
"follow_request.reject": "رفض",
"follow_requests.unlocked_explanation": "حتى وإن كان حسابك غير مقفل، يعتقد فريق {domain} أنك قد ترغب في مراجعة طلبات المتابعة من هذه الحسابات يدوياً.",
"follow_suggestions.curated_suggestion": "اختيار الموظفين",
"follow_suggestions.dismiss": "لا تُظهرها مجدّدًا",
"follow_suggestions.hints.featured": "تم اختيار هذا الملف الشخصي يدوياً من قبل فريق {domain}.",
"follow_suggestions.hints.friends_of_friends": "هذا الملف الشخصي مشهور بين الأشخاص الذين تتابعهم.",
"follow_suggestions.hints.most_followed": "هذا الملف الشخصي هو واحد من الأكثر متابعة على {domain}.",
"follow_suggestions.hints.most_interactions": "هذا الملف الشخصي قد حصل مؤخرا على الكثير من الاهتمام على {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "هذا الملف الشخصي مشابه للملفات الشخصية التي تابعتها مؤخرا.",
"follow_suggestions.personalized_suggestion": "توصية مخصصة",
"follow_suggestions.popular_suggestion": "توصية رائجة",
"follow_suggestions.view_all": "عرض الكل",

View File

@ -480,7 +480,7 @@
"onboarding.action.back": "Върнете ме обратно",
"onboarding.actions.back": "Върнете ме обратно",
"onboarding.actions.go_to_explore": "Виж тенденции",
"onboarding.actions.go_to_home": "Към началния ви инфоканал",
"onboarding.actions.go_to_home": "Към началния ми инфоканал",
"onboarding.compose.template": "Здравейте, #Mastodon!",
"onboarding.follows.empty": "За съжаление, в момента не могат да бъдат показани резултати. Може да опитате да търсите или да разгледате, за да намерите кого да последвате, или опитайте отново по-късно.",
"onboarding.follows.lead": "Може да бъдете куратор на началния си инфоканал. Последвайки повече хора, по-деен и по-интересен ще става. Тези профили може да са добра начална точка, от която винаги по-късно да спрете да следвате!",
@ -504,7 +504,7 @@
"onboarding.start.skip": "Желаете ли да прескочите?",
"onboarding.start.title": "Успяхте!",
"onboarding.steps.follow_people.body": "Може да бъдете куратор на инфоканала си. Хайде да го запълним с интересни хора.",
"onboarding.steps.follow_people.title": оследвайте {count, plural, one {един човек} other {# души}}",
"onboarding.steps.follow_people.title": ерсонализиране на началния ви инфоканал",
"onboarding.steps.publish_status.body": "Поздравете целия свят.",
"onboarding.steps.publish_status.title": "Направете първата си публикация",
"onboarding.steps.setup_profile.body": "Други са по-вероятно да взаимодействат с вас с попълнения профил.",

View File

@ -113,6 +113,7 @@
"column.directory": "Mont a-dreuz ar profiloù",
"column.domain_blocks": "Domani berzet",
"column.favourites": "Muiañ-karet",
"column.firehose": "Redoù war-eeun",
"column.follow_requests": "Rekedoù heuliañ",
"column.home": "Degemer",
"column.lists": "Listennoù",
@ -143,6 +144,8 @@
"compose_form.lock_disclaimer.lock": "prennet",
"compose_form.placeholder": "Petra emaoc'h o soñjal e-barzh ?",
"compose_form.poll.duration": "Pad ar sontadeg",
"compose_form.poll.multiple": "Meur a choaz",
"compose_form.poll.option_placeholder": "Choaz {number}",
"compose_form.poll.single": "Dibabit unan",
"compose_form.poll.switch_to_multiple": "Kemmañ ar sontadeg evit aotren meur a zibab",
"compose_form.poll.switch_to_single": "Kemmañ ar sontadeg evit aotren un dibab hepken",
@ -441,7 +444,7 @@
"onboarding.action.back": "Distreiñ",
"onboarding.actions.back": "Distreiñ",
"onboarding.actions.go_to_explore": "See what's trending",
"onboarding.actions.go_to_home": "Go to your home feed",
"onboarding.actions.go_to_home": "Mont d'ho red degemer",
"onboarding.compose.template": "Salud #Mastodon!",
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
"onboarding.follows.title": "Popular on Mastodon",

View File

@ -151,7 +151,7 @@
"compose_form.poll.single": "Einfachauswahl",
"compose_form.poll.switch_to_multiple": "Mehrfachauswahl erlauben",
"compose_form.poll.switch_to_single": "Nur Einfachauswahl erlauben",
"compose_form.poll.type": "Stil",
"compose_form.poll.type": "Art",
"compose_form.publish": "Veröffentlichen",
"compose_form.publish_form": "Neuer Beitrag",
"compose_form.reply": "Antworten",
@ -277,7 +277,7 @@
"follow_request.authorize": "Genehmigen",
"follow_request.reject": "Ablehnen",
"follow_requests.unlocked_explanation": "Auch wenn dein Konto öffentlich bzw. nicht geschützt ist, haben die Moderator*innen von {domain} gedacht, dass du diesen Follower lieber manuell bestätigen solltest.",
"follow_suggestions.curated_suggestion": "Vom Server empfohlen",
"follow_suggestions.curated_suggestion": "Vom Server-Team empfohlen",
"follow_suggestions.dismiss": "Nicht mehr anzeigen",
"follow_suggestions.hints.featured": "Dieses Profil wurde vom {domain}-Team ausgewählt.",
"follow_suggestions.hints.friends_of_friends": "Dieses Profil ist bei deinen Followern beliebt.",

View File

@ -241,6 +241,7 @@
"empty_column.list": "There is nothing in this list yet. When members of this list publish new posts, they will appear here.",
"empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.",
"empty_column.mutes": "You haven't muted any users yet.",
"empty_column.notification_requests": "All clear! There is nothing here. When you receive new notifications, they will appear here according to your settings.",
"empty_column.notifications": "You don't have any notifications yet. When other people interact with you, you will see it here.",
"empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up",
"error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.",
@ -271,6 +272,8 @@
"filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
"filter_modal.select_filter.title": "Filter this post",
"filter_modal.title.status": "Filter a post",
"filtered_notifications_banner.pending_requests": "Notifications from {count, plural, =0 {no} one {one person} other {# people}} you may know",
"filtered_notifications_banner.title": "Filtered notifications",
"firehose.all": "All",
"firehose.local": "This server",
"firehose.remote": "Other servers",
@ -314,7 +317,6 @@
"hashtag.follow": "Follow hashtag",
"hashtag.unfollow": "Unfollow hashtag",
"hashtags.and_other": "…and {count, plural, other {# more}}",
"home.column_settings.basic": "Basic",
"home.column_settings.show_reblogs": "Show boosts",
"home.column_settings.show_replies": "Show replies",
"home.hide_announcements": "Hide announcements",
@ -440,15 +442,16 @@
"notification.reblog": "{name} boosted your post",
"notification.status": "{name} just posted",
"notification.update": "{name} edited a post",
"notification_requests.accept": "Accept",
"notification_requests.dismiss": "Dismiss",
"notification_requests.notifications_from": "Notifications from {name}",
"notification_requests.title": "Filtered notifications",
"notifications.clear": "Clear notifications",
"notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?",
"notifications.column_settings.admin.report": "New reports:",
"notifications.column_settings.admin.sign_up": "New sign-ups:",
"notifications.column_settings.alert": "Desktop notifications",
"notifications.column_settings.favourite": "Favorites:",
"notifications.column_settings.filter_bar.advanced": "Display all categories",
"notifications.column_settings.filter_bar.category": "Quick filter bar",
"notifications.column_settings.filter_bar.show_bar": "Show filter bar",
"notifications.column_settings.follow": "New followers:",
"notifications.column_settings.follow_request": "New follow requests:",
"notifications.column_settings.mention": "Mentions:",
@ -474,6 +477,15 @@
"notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request",
"notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before",
"notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.",
"notifications.policy.filter_new_accounts.hint": "Created within the past {days, plural, one {one day} other {# days}}",
"notifications.policy.filter_new_accounts_title": "New accounts",
"notifications.policy.filter_not_followers_hint": "Including people who have been following you fewer than {days, plural, one {one day} other {# days}}",
"notifications.policy.filter_not_followers_title": "People not following you",
"notifications.policy.filter_not_following_hint": "Until you manually approve them",
"notifications.policy.filter_not_following_title": "People you don't follow",
"notifications.policy.filter_private_mentions_hint": "Filtered unless it's in reply to your own mention or if you follow the sender",
"notifications.policy.filter_private_mentions_title": "Unsolicited private mentions",
"notifications.policy.title": "Filter out notifications from…",
"notifications_permission_banner.enable": "Enable desktop notifications",
"notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.",
"notifications_permission_banner.title": "Never miss a thing",

View File

@ -271,7 +271,7 @@
"filter_modal.select_filter.subtitle": "Usar una categoría existente o crear una nueva",
"filter_modal.select_filter.title": "Filtrar este mensaje",
"filter_modal.title.status": "Filtrar un mensaje",
"firehose.all": "Todas",
"firehose.all": "Todos",
"firehose.local": "Este servidor",
"firehose.remote": "Otros servidores",
"follow_request.authorize": "Autorizar",

View File

@ -279,15 +279,15 @@
"follow_requests.unlocked_explanation": "A pesar de que tu cuenta no es privada, el personal de {domain} ha pensado que quizás deberías revisar manualmente las solicitudes de seguimiento de estas cuentas.",
"follow_suggestions.curated_suggestion": "Recomendaciones del equipo",
"follow_suggestions.dismiss": "No mostrar de nuevo",
"follow_suggestions.hints.featured": "Este perfil ha sido elegido a mano por el equipo de {domain}.",
"follow_suggestions.hints.featured": "Este perfil ha sido seleccionado a mano por el equipo de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Este perfil es popular entre las personas que sigues.",
"follow_suggestions.hints.most_followed": "Este perfil es uno de los más seguidos en {domain}.",
"follow_suggestions.hints.most_interactions": "Este perfil ha estado recibiendo recientemente mucha atención en {domain}.",
"follow_suggestions.hints.most_interactions": "Este perfil ha estado recibiendo mucha atención en {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Este perfil es similar a los perfiles que has seguido recientemente.",
"follow_suggestions.personalized_suggestion": "Sugerencia personalizada",
"follow_suggestions.popular_suggestion": "Sugerencia popular",
"follow_suggestions.view_all": "Ver todo",
"follow_suggestions.who_to_follow": "A quién seguir",
"follow_suggestions.who_to_follow": "Recomendamos seguir",
"followed_tags": "Hashtags seguidos",
"footer.about": "Acerca de",
"footer.directory": "Directorio de perfiles",

View File

@ -529,15 +529,15 @@
"poll_button.add_poll": "Añadir una encuesta",
"poll_button.remove_poll": "Eliminar encuesta",
"privacy.change": "Ajustar privacidad",
"privacy.direct.long": "Todos los mencionados en el post",
"privacy.direct.long": "Visible únicamente por los mencionados en la publicación",
"privacy.direct.short": "Personas específicas",
"privacy.private.long": "Solo tus seguidores",
"privacy.private.long": "Visible únicamente por tus seguidores",
"privacy.private.short": "Seguidores",
"privacy.public.long": "Cualquiera dentro y fuera de Mastodon",
"privacy.public.short": "Público",
"privacy.unlisted.additional": "Esto se comporta exactamente igual que el público, excepto que la publicación no aparecerá en la cronología en directo o en las etiquetas, la exploración o búsqueda de Mastodon, incluso si está optado por activar la cuenta de usuario.",
"privacy.unlisted.long": "Menos fanfares algorítmicos",
"privacy.unlisted.short": "Público tranquilo",
"privacy.public.long": "Visible por todo el mundo, dentro y fuera de Mastodon",
"privacy.public.short": "Pública",
"privacy.unlisted.additional": "Se comporta exactamente igual que la visibilidad pública, excepto que la publicación no aparecerá en las cronologías públicas o en las etiquetas, la sección de Explorar o la búsqueda de Mastodon, incluso si has habilitado la opción de búsqueda en tu perfil.",
"privacy.unlisted.long": "Sin algoritmos de descubrimiento",
"privacy.unlisted.short": "Pública silenciosa",
"privacy_policy.last_updated": "Actualizado por última vez {date}",
"privacy_policy.title": "Política de Privacidad",
"recommended": "Recomendado",

View File

@ -21,7 +21,7 @@
"account.blocked": "Blokeeritud",
"account.browse_more_on_origin_server": "Vaata rohkem algsel profiilil",
"account.cancel_follow_request": "Võta jälgimistaotlus tagasi",
"account.copy": "Kopeeri link profiili",
"account.copy": "Kopeeri profiili link",
"account.direct": "Maini privaatselt @{name}",
"account.disable_notifications": "Peata teavitused @{name} postitustest",
"account.domain_blocked": "Domeen peidetud",
@ -277,6 +277,17 @@
"follow_request.authorize": "Autoriseeri",
"follow_request.reject": "Hülga",
"follow_requests.unlocked_explanation": "Kuigi su konto pole lukustatud, soovitab {domain} personal siiski nende kontode jälgimistaotlused käsitsi üle vaadata.",
"follow_suggestions.curated_suggestion": "Teiste valitud",
"follow_suggestions.dismiss": "Ära enam näita",
"follow_suggestions.hints.featured": "Selle kasutajaprofiili on soovitanud {domain} kasutajad.",
"follow_suggestions.hints.friends_of_friends": "See kasutajaprofiil on jälgitavate seas populaarne.",
"follow_suggestions.hints.most_followed": "See on {domain} enim jälgitud kasutajaprofiil.",
"follow_suggestions.hints.most_interactions": "See on {domain} viimasel ajal enim tähelepanu saanud kasutajaprofiil.",
"follow_suggestions.hints.similar_to_recently_followed": "See kasutajaprofiil sarnaneb neile, mida oled hiljuti jälgima asunud.",
"follow_suggestions.personalized_suggestion": "Isikupärastatud soovitus",
"follow_suggestions.popular_suggestion": "Popuplaarne soovitus",
"follow_suggestions.view_all": "Vaata kõiki",
"follow_suggestions.who_to_follow": "Keda jälgida",
"followed_tags": "Jälgitavad märksõnad",
"footer.about": "Teave",
"footer.directory": "Profiilikataloog",
@ -473,7 +484,7 @@
"onboarding.compose.template": "Tere, #Mastodon!",
"onboarding.follows.empty": "Kahjuks ei saa hetkel tulemusi näidata. Proovi kasutada otsingut või lehitse uurimise lehte, et leida inimesi, keda jälgida, või proovi hiljem uuesti.",
"onboarding.follows.lead": "Haldad ise oma koduvoogu. Mida rohkemaid inimesi jälgid, seda aktiivsem ja huvitavam see on. Need profiilid võiksid olla head alustamiskohad — saad nende jälgimise alati lõpetada!",
"onboarding.follows.title": "Populaarne Mastodonis",
"onboarding.follows.title": "Isikupärasta oma koduvoogu",
"onboarding.profile.discoverable": "Muuda mu profiil avastatavaks",
"onboarding.profile.discoverable_hint": "Kui nõustud enda avastamisega Mastodonis, võivad sinu postitused ilmuda otsingutulemustes ja trendides ning sinu profiili võidakse soovitada sinuga sarnaste huvidega inimestele.",
"onboarding.profile.display_name": "Näidatav nimi",
@ -493,11 +504,11 @@
"onboarding.start.skip": "Soovid kohe edasi hüpata?",
"onboarding.start.title": "Said valmis!",
"onboarding.steps.follow_people.body": "Haldad oma koduvoogu. Täida see huvitavate inimestega.",
"onboarding.steps.follow_people.title": "Jälgi {count, plural, one {üht inimest} other {# inimest}}",
"onboarding.steps.follow_people.title": "Isikupärasta oma koduvoogu",
"onboarding.steps.publish_status.body": "Ütle maailmale tere.",
"onboarding.steps.publish_status.title": "Tee oma esimene postitus",
"onboarding.steps.setup_profile.body": "Täidetud profiili korral suhtlevad teised sinuga tõenäolisemalt.",
"onboarding.steps.setup_profile.title": "Kohanda oma profiili",
"onboarding.steps.setup_profile.title": "Isikupärasta oma profiili",
"onboarding.steps.share_profile.body": "Anna sõpradele teada, kuidas sind Mastodonist leida!",
"onboarding.steps.share_profile.title": "Jaga oma profiili",
"onboarding.tips.2fa": "<strong>Kas sa teadsid?</strong> Saad oma kontot muuta turvalisemaks valides konto seadetes kaheastmelise autoriseerimise. See töötab mistahes sinu valitud TOTP-äpiga, telefoninumbrit pole vaja!",
@ -524,6 +535,7 @@
"privacy.private.short": "Jälgijad",
"privacy.public.long": "Nii kasutajad kui mittekasutajad",
"privacy.public.short": "Avalik",
"privacy.unlisted.additional": "See on olemuselt küll avalik, aga postitus ei ilmu voogudes ega märksõnades, lehitsedes ega Mastodoni otsingus, isegi kui konto on seadistustes avalik.",
"privacy.unlisted.long": "Vähem algoritmilisi teavitusi",
"privacy.unlisted.short": "Vaikselt avalik",
"privacy_policy.last_updated": "Viimati uuendatud {date}",

View File

@ -201,9 +201,9 @@
"disabled_account_banner.text": "Tilisi {disabledAccount} on tällä hetkellä poissa käytöstä.",
"dismissable_banner.community_timeline": "Nämä ovat tuoreimpia julkaisuja käyttäjiltä, joiden tili on palvelimella {domain}.",
"dismissable_banner.dismiss": "Hylkää",
"dismissable_banner.explore_links": "Näitä uutisia jaetaan tänään sosiaalisessa verkossa eniten. Uusimmat ja eri käyttäjien eniten lähettämät uutiset nousevat listauksessa korkeimmalle.",
"dismissable_banner.explore_statuses": "Tänään nämä sosiaalisen verkon julkaisut keräävät eniten huomiota. Uusimmat, tehostetuimmat ja suosikeiksi lisätyimmät julkaisut nousevat listauksessa korkeammalle.",
"dismissable_banner.explore_tags": "Nämä sosiaalisen verkon aihetunnisteet keräävät tänään eniten huomiota. Useimman käyttäjän käyttämät aihetunnisteet nousevat listauksessa korkeimmalle.",
"dismissable_banner.explore_links": "Näitä uutisia jaetaan tänään sosiaalisessa verkossa eniten. Uusimmat ja eri käyttäjien eniten lähettämät uutiset nousevat listauksessa korkeammalle.",
"dismissable_banner.explore_statuses": "Nämä sosiaalisen verkon julkaisut keräävät tänään eniten huomiota. Uusimmat, tehostetuimmat ja suosikeiksi lisätyimmät julkaisut nousevat listauksessa korkeammalle.",
"dismissable_banner.explore_tags": "Nämä sosiaalisen verkon aihetunnisteet keräävät tänään eniten huomiota. Useimman käyttäjän käyttämät aihetunnisteet nousevat listauksessa korkeammalle.",
"dismissable_banner.public_timeline": "Nämä ovat viimeisimpiä julkaisuja sosiaalisen verkon käyttäjiltä, joita seurataan palvelimella {domain}.",
"embed.instructions": "Upota julkaisu verkkosivullesi kopioimalla alla oleva koodi.",
"embed.preview": "Tältä se näyttää:",
@ -284,7 +284,7 @@
"follow_suggestions.hints.most_followed": "Tämä profiili on yksi seuratuimmista palvelimella {domain}.",
"follow_suggestions.hints.most_interactions": "Tämä profiili on viime aikoina saanut paljon huomiota palvelimella {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Tämä profiili on samankaltainen kuin profiilit, joita olet viimeksi seurannut.",
"follow_suggestions.personalized_suggestion": "Personoitu ehdotus",
"follow_suggestions.personalized_suggestion": "Mukautettu ehdotus",
"follow_suggestions.popular_suggestion": "Suosittu ehdotus",
"follow_suggestions.view_all": "Näytä kaikki",
"follow_suggestions.who_to_follow": "Ehdotuksia seurattavaksi",
@ -504,7 +504,7 @@
"onboarding.start.skip": "Haluatko hypätä suoraan eteenpäin ilman alkuunpääsyohjeistuksia?",
"onboarding.start.title": "Olet tehnyt sen!",
"onboarding.steps.follow_people.body": "Mastodon perustuu sinua kiinnostavien henkilöjen julkaisujen seuraamiseen.",
"onboarding.steps.follow_people.title": "Mukauta kotisyötteesi",
"onboarding.steps.follow_people.title": "Mukauta kotisyötettäsi",
"onboarding.steps.publish_status.body": "Tervehdi maailmaa sanoin, kuvin tai äänestyksin {emoji}",
"onboarding.steps.publish_status.title": "Laadi ensimmäinen julkaisusi",
"onboarding.steps.setup_profile.body": "Täydentämällä profiilisi tietoja tehostat vuorovaikutteisuutta.",
@ -657,7 +657,7 @@
"status.filter": "Suodata tämä julkaisu",
"status.filtered": "Suodatettu",
"status.hide": "Piilota julkaisu",
"status.history.created": "{name} luotu {date}",
"status.history.created": "{name} loi {date}",
"status.history.edited": "{name} muokkasi {date}",
"status.load_more": "Lataa lisää",
"status.media.open": "Avaa napsauttamalla",

View File

@ -145,10 +145,10 @@
"compose_form.lock_disclaimer": "Chan eil an cunntas agad {locked}. S urrainn do dhuine sam bith gad leantainn is na postaichean agad a tha ag amas air an luchd-leantainn agad a-mhàin a shealltainn.",
"compose_form.lock_disclaimer.lock": "glaiste",
"compose_form.placeholder": "Dè tha air d aire?",
"compose_form.poll.duration": "Faide a chunntais-bheachd",
"compose_form.poll.multiple": "Iomadh roghainn",
"compose_form.poll.duration": "Faide a chunntais",
"compose_form.poll.multiple": "Iomadh-roghainn",
"compose_form.poll.option_placeholder": "Roghainn {number}",
"compose_form.poll.single": "Tagh aonan",
"compose_form.poll.single": "Aonan",
"compose_form.poll.switch_to_multiple": "Atharraich an cunntas-bheachd ach an gabh iomadh roghainn a thaghadh",
"compose_form.poll.switch_to_single": "Atharraich an cunntas-bheachd gus nach gabh ach aon roghainn a thaghadh",
"compose_form.poll.type": "Stoidhle",
@ -277,7 +277,13 @@
"follow_request.authorize": "Ùghdarraich",
"follow_request.reject": "Diùlt",
"follow_requests.unlocked_explanation": "Ged nach eil an cunntas agad glaiste, tha sgioba {domain} dhen bheachd gum b fheàirrde thu lèirmheas a dhèanamh air na h-iarrtasan leantainn o na cunntasan seo a làimh.",
"follow_suggestions.curated_suggestion": "Roghainn an sgioba",
"follow_suggestions.dismiss": "Na seall seo a-rithist",
"follow_suggestions.hints.featured": "Chaidh a phròifil seo a thaghadh le sgioba {domain} a làimh.",
"follow_suggestions.hints.friends_of_friends": "Tha fèill mhòr air a phròifil seo am measg nan daoine a leanas tu.",
"follow_suggestions.hints.most_followed": "Tha a phròifil seo am measg an fheadhainn a leanar as trice air {domain}.",
"follow_suggestions.hints.most_interactions": "Chaidh mòran aire a thoirt air a phròifil seo air {domain} o chionn goirid.",
"follow_suggestions.hints.similar_to_recently_followed": "Tha a phròifil seo coltach ris na pròifilean air an lean thu o chionn goirid.",
"follow_suggestions.personalized_suggestion": "Moladh pearsanaichte",
"follow_suggestions.popular_suggestion": "Moladh air a bheil fèill mhòr",
"follow_suggestions.view_all": "Seall na h-uile",
@ -479,9 +485,11 @@
"onboarding.follows.empty": "Gu mì-fhortanach, chan urrainn dhuinn toradh a shealltainn an-dràsta. Feuch gleus an luirg no duilleag an rùrachaidh airson daoine ri leantainn a lorg no feuch ris a-rithist an ceann tamaill.",
"onboarding.follows.lead": "S e do prìomh-doras do Mhastodon a th ann san dachaigh. Mar as motha an t-uiread de dhaoine a leanas tu s ann nas beòthaile inntinniche a bhios i. Seo moladh no dhà dhut airson tòiseachadh:",
"onboarding.follows.title": "Cuir dreach pearsanta air do dhachaigh",
"onboarding.profile.discoverable": "Bu mhath leam gun gabh a phròifil agam a lorg",
"onboarding.profile.discoverable": "Bu mhath leam gun gabh a phròifil agam a rùrachadh",
"onboarding.profile.discoverable_hint": "Ma chuir thu romhad gun gabh a phròifil agad a rùrachadh air Mastodon, faodaidh na postaichean agad nochdadh ann an toraidhean luirg agus treandaichean agus dhfhaoidte gun dèid a phròifil agad a mholadh dhan fheadhainn aig a bheil ùidhean coltach ri d ùidhean-sa.",
"onboarding.profile.display_name": "Ainm-taisbeanaidh",
"onboarding.profile.display_name_hint": "D ainm slàn no spòrsail…",
"onboarding.profile.lead": "S urrainn dhut seo a choileanadh uair sam bith eile sna roghainnean far am bi roghainnean gnàthachaidh eile ri làimh dhut cuideachd.",
"onboarding.profile.note": "Cunntas-beatha",
"onboarding.profile.note_hint": "S urrainn dhut @iomradh a thoirt air càch no air #tagaicheanHais…",
"onboarding.profile.save_and_continue": "Sàbhail s lean air adhart",
@ -527,6 +535,8 @@
"privacy.private.short": "Luchd-leantainn",
"privacy.public.long": "Duine sam bith taobh a-staigh no a-muigh Mhastodon",
"privacy.public.short": "Poblach",
"privacy.unlisted.additional": "Tha seo coltach ris an fhaicsinneachd phoblach ach cha nochd am post air loidhnichean-ama an t-saoghail phoblaich, nan tagaichean hais no an rùrachaidh no ann an toraidhean luirg Mhastodon fiù s ma thug thu ro-aonta airson sin seachad.",
"privacy.unlisted.long": "Ìre bheag an algairim",
"privacy.unlisted.short": "Poblach ach sàmhach",
"privacy_policy.last_updated": "An t-ùrachadh mu dheireadh {date}",
"privacy_policy.title": "Poileasaidh prìobhaideachd",

View File

@ -197,6 +197,7 @@
"firehose.all": "Toto",
"firehose.local": "Iste servitor",
"firehose.remote": "Altere servitores",
"follow_request.reject": "Rejectar",
"follow_suggestions.dismiss": "Non monstrar novemente",
"follow_suggestions.personalized_suggestion": "Suggestion personalisate",
"follow_suggestions.popular_suggestion": "Suggestion personalisate",
@ -204,6 +205,7 @@
"footer.about": "A proposito de",
"footer.directory": "Directorio de profilos",
"footer.get_app": "Obtene le application",
"footer.invite": "Invitar personas",
"footer.keyboard_shortcuts": "Accessos directe de claviero",
"footer.privacy_policy": "Politica de confidentialitate",
"footer.source_code": "Vider le codice fonte",
@ -244,6 +246,7 @@
"keyboard_shortcuts.muted": "Aperir lista de usatores silentiate",
"keyboard_shortcuts.my_profile": "Aperir tu profilo",
"keyboard_shortcuts.notifications": "Aperir columna de notificationes",
"keyboard_shortcuts.open_media": "Aperir medio",
"keyboard_shortcuts.profile": "Aperir le profilo del autor",
"keyboard_shortcuts.reply": "Responder al message",
"keyboard_shortcuts.spoilers": "Monstrar/celar le campo CW",
@ -273,9 +276,11 @@
"navigation_bar.blocks": "Usatores blocate",
"navigation_bar.bookmarks": "Marcapaginas",
"navigation_bar.community_timeline": "Chronologia local",
"navigation_bar.compose": "Componer un nove message",
"navigation_bar.direct": "Mentiones private",
"navigation_bar.discover": "Discoperir",
"navigation_bar.domain_blocks": "Dominios blocate",
"navigation_bar.explore": "Explorar",
"navigation_bar.favourites": "Favoritos",
"navigation_bar.filters": "Parolas silentiate",
"navigation_bar.lists": "Listas",

View File

@ -1,5 +1,8 @@
{
"about.contact": "Anermis:",
"about.disclaimer": "Mastodon d aseɣẓan ilelli, d aseɣẓan n uɣbalu yeldin, d tnezzut n Mastodon gGmbH.",
"about.not_available": "Talɣut-a ur tettwabder ara deg uqeddac-a.",
"about.powered_by": "Azeṭṭa inmetti yettwasɣelsen sɣur {mastodon}",
"about.rules": "Ilugan n uqeddac",
"account.account_note_header": "Tazmilt",
"account.add_or_remove_from_list": "Rnu neɣ kkes seg tebdarin",
@ -10,13 +13,15 @@
"account.block_short": "Sewḥel",
"account.blocked": "Yettusewḥel",
"account.browse_more_on_origin_server": "Snirem ugar deg umeɣnu aneẓli",
"account.cancel_follow_request": "Withdraw follow request",
"account.cancel_follow_request": "Sefsex taḍfart",
"account.copy": "Nɣel assaɣ ɣer umaɣnu",
"account.direct": "Bder-d @{name} weḥd-s",
"account.disable_notifications": "Ḥbes ur iyi-d-ttazen ara ilɣa mi ara d-isuffeɣ @{name}",
"account.domain_blocked": "Taɣult yeffren",
"account.edit_profile": "Ẓreg amaɣnu",
"account.enable_notifications": "Azen-iyi-d ilɣa mi ara d-isuffeɣ @{name}",
"account.endorse": "Welleh fell-as deg umaɣnu-inek",
"account.featured_tags.last_status_at": "Tasuffeɣt taneggarut ass n {date}",
"account.featured_tags.last_status_never": "Ulac tisuffaɣ",
"account.follow": "Ḍfer",
"account.followers": "Imeḍfaren",
@ -27,14 +32,17 @@
"account.follows.empty": "Ar tura, amseqdac-agi ur yeṭṭafaṛ yiwen.",
"account.go_to_profile": "Ddu ɣer umaɣnu",
"account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}",
"account.joined_short": "Izeddi da",
"account.joined_short": "Izeddi da seg ass n",
"account.link_verified_on": "Taɣara n useɣwen-a tettwasenqed ass n {date}",
"account.locked_info": "Amiḍan-agi uslig isekweṛ. D bab-is kan i izemren ad yeǧǧ, s ufus-is, win ara t-iḍefṛen.",
"account.media": "Timidyatin",
"account.mention": "Bder-d @{name}",
"account.moved_to": "{name} yenna-d dakken amiḍan-is amaynut yuɣal :",
"account.mute": "Sgugem @{name}",
"account.mute_notifications_short": "Susem ilɣa",
"account.mute_short": "Sgugem",
"account.muted": "Yettwasgugem",
"account.no_bio": "Ulac aglam i d-yettunefken.",
"account.open_original_page": "Ldi asebter anasli",
"account.posts": "Tisuffaɣ",
"account.posts_with_replies": "Tisuffaɣ d tririyin",
@ -69,6 +77,7 @@
"bundle_modal_error.close": "Mdel",
"bundle_modal_error.message": "Tella-d kra n tuccḍa mi d-yettali ugbur-agi.",
"bundle_modal_error.retry": "Ɛreḍ tikelt-nniḍen",
"closed_registrations_modal.description": "Asnulfu n umiḍan deg {domain} mačči d ayen izemren ad yili, maca ttxil-k·m, err deg lbal-ik·im belli ur teḥwaǧeḍ ara amiḍan s wudem ibanen ɣef {domain} akken ad tesqedceḍ Mastodon.",
"closed_registrations_modal.find_another_server": "Aff-d aqeddac nniḍen",
"closed_registrations_modal.title": "Ajerred deg Masṭudun",
"column.about": "Ɣef",
@ -99,6 +108,7 @@
"community.column_settings.remote_only": "Anmeggag kan",
"compose.language.change": "Beddel tutlayt",
"compose.language.search": "Nadi tutlayin …",
"compose.published.body": "Yeffeɣ-d yizen-nni.",
"compose.published.open": "Ldi",
"compose.saved.body": "Tettwasekles tsuffeɣt.",
"compose_form.direct_message_warning_learn_more": "Issin ugar",
@ -111,6 +121,7 @@
"compose_form.poll.multiple": "Aṭas n ufran",
"compose_form.poll.option_placeholder": "Taxtiṛt {number}",
"compose_form.poll.single": "Fren yiwen",
"compose_form.poll.type": "Aɣanib",
"compose_form.publish": "Suffeɣ",
"compose_form.publish_form": "Tasuffeɣt tamaynut",
"compose_form.reply": "Err",
@ -128,6 +139,7 @@
"confirmations.discard_edit_media.confirm": "Sefsex",
"confirmations.domain_block.confirm": "Ffer taɣult meṛṛa",
"confirmations.edit.confirm": "Ẓreg",
"confirmations.edit.message": "Abeddel tura ad d-yaru izen-nni i d-tegreḍ akka tura. Tetḥeqqeḍ tebɣiḍ ad tkemmleḍ?",
"confirmations.logout.confirm": "Ffeɣ",
"confirmations.logout.message": "D tidet tebɣiḍ ad teffɣeḍ?",
"confirmations.mute.confirm": "Sgugem",
@ -142,14 +154,18 @@
"conversation.mark_as_read": "Creḍ yettwaɣṛa",
"conversation.open": "Ssken adiwenni",
"conversation.with": "Akked {names}",
"copy_icon_button.copied": "Yettwanɣel ɣer ufus",
"copypaste.copied": "Yettwanɣel",
"copypaste.copy_to_clipboard": "Nɣel ɣer afus",
"directory.federated": "Deg fedivers yettwasnen",
"directory.local": "Seg {domain} kan",
"directory.new_arrivals": "Imaynuten id yewḍen",
"directory.recently_active": "Yermed xas melmi kan",
"disabled_account_banner.account_settings": "Iɣewwaṛen n umiḍan",
"dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
"dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
"dismissable_banner.dismiss": "Agi",
"dismissable_banner.explore_links": "D tiqsiḍin n yisallen i yettwabḍan ass-a deg web inmetti. Tiqsiḍin n yisallen timaynutin i d-yettwassufɣen s wugar n medden yemgaraden, d tid i d-yufraren ugar.",
"dismissable_banner.explore_statuses": "Ti d tisufaɣ seg uzeṭṭa anmetti i d-yettawin tamyigawt ass-a. Tisufaɣ timaynutin yesεan aṭas n lǧehd d tid iḥemmlen s waṭas, ttwaεlayit d timezwura.",
"dismissable_banner.explore_tags": "D wiyi i d ihacṭagen i d-yettawin tamyigawt deg web anmetti ass-a. Ihacṭagen i sseqdacen ugar n medden, εlayit d imezwura.",
"embed.instructions": "Ẓẓu addad-agi deg usmel-inek s wenγal n tangalt yellan sdaw-agi.",
"embed.preview": "Akka ara d-iban:",
"emoji_button.activity": "Aqeddic",
@ -221,19 +237,28 @@
"hashtag.column_settings.tag_mode.any": "Yiwen seg-sen",
"hashtag.column_settings.tag_mode.none": "Yiwen ala seg-sen",
"hashtag.column_settings.tag_toggle": "Glu-d s yihacṭagen imerna i ujgu-agi",
"hashtag.counter_by_accounts": "{count, plural, one {{counter} imtekki} other {{counter} n imtekkiyen}}",
"hashtag.counter_by_uses": "{count, plural, one {{counter} n tsuffeɣt} other {{counter} n tsuffaɣ}}",
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} n tsuffeɣt} other {{counter} n tsuffaɣ}} assa",
"hashtag.follow": "Ḍfeṛ ahacṭag",
"hashtags.and_other": "…d {count, plural, one {}other {# nniḍen}}",
"home.column_settings.basic": "Igejdanen",
"home.column_settings.show_reblogs": "Ssken-d beṭṭu",
"home.column_settings.show_replies": "Ssken-d tiririyin",
"home.hide_announcements": "Ffer ulɣuyen",
"home.pending_critical_update.body": "Ma ulac aɣilif, leqqem aqeddac-ik Mastodon akken kan tzemreḍ !",
"home.show_announcements": "Ssken-d ulɣuyen",
"interaction_modal.description.favourite": "S umiḍan ɣef Mastodon, tzemreḍ ad tesmenyifeḍ tasuffeɣt-a akken ad teǧǧeḍ amaru ad iẓer belli tḥemmleḍ-tt u ad tt-id-tsellkeḍ i ticki.",
"interaction_modal.description.follow": "S umiḍan deg Mastodon, tzemreḍ ad tḍefreḍ {name} akken ad d-teṭṭfeḍ iznan-is deg lxiḍ-ik·im agejdan.",
"interaction_modal.description.reblog": "S umiḍan deg Mastodon, tzemreḍ ad tesnerniḍ tasuffeɣt-a akken ad tt-tebḍuḍ d yineḍfaren-ik·im.",
"interaction_modal.description.reply": "S umiḍan deg Mastodon, tzemreḍ ad d-terreḍ ɣef tsuffeɣt-a.",
"interaction_modal.login.action": "Awi-yi ɣer uqeddac-iw",
"interaction_modal.login.prompt": "Taɣult n uqeddac-ik·im agejdan, amedya mastodon.social",
"interaction_modal.no_account_yet": "Ulac-ik·ikem deg Maṣṭudun?",
"interaction_modal.on_another_server": "Deg uqeddac nniḍen",
"interaction_modal.on_this_server": "Deg uqeddac-ayi",
"interaction_modal.sign_in": "Ur tekcimeḍ ara ɣer uqeddac-a. Anda yella umiḍan-ik·im ?",
"interaction_modal.sign_in_hint": "Ihi : Wa d asmel ideg tjerdeḍ. Ma ur tecfiḍ ara, nadi imayl n ummager deg tenkult-ik·im. Tzemreḍ daɣen ad d-tefkeḍ isem-ik·im n useqdac ummid ! (amedya @Mastodon@mastodon.social)",
"interaction_modal.title.follow": "Ḍfer {name}",
"intervals.full.days": "{number, plural, one {# n wass} other {# n wussan}}",
"intervals.full.hours": "{number, plural, one {# n usarag} other {# n yesragen}}",
@ -311,6 +336,7 @@
"navigation_bar.lists": "Tibdarin",
"navigation_bar.logout": "Ffeɣ",
"navigation_bar.mutes": "Iseqdacen yettwasusmen",
"navigation_bar.opened_in_classic_interface": "Tisuffaɣ, imiḍanen akked isebtar-nniḍen igejdanen ldin-d s wudem amezwer deg ugrudem web aklasiki.",
"navigation_bar.personal": "Udmawan",
"navigation_bar.pins": "Tisuffaɣ yettwasenṭḍen",
"navigation_bar.preferences": "Imenyafen",
@ -361,12 +387,18 @@
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
"onboarding.follows.title": "Popular on Mastodon",
"onboarding.profile.display_name": "Isem ara d-yettwaskanen",
"onboarding.profile.note_hint": "Tzemreḍ ad d-@tbedreḍ imdanen niḍen neɣ #ihacṭagen …",
"onboarding.profile.save_and_continue": "Sekles, tkemmleḍ",
"onboarding.profile.title": "Asbadu n umaɣnu",
"onboarding.profile.upload_avatar": "Sali tugna n umaɣnu",
"onboarding.profile.upload_header": "Sali tacacit n umaɣnu",
"onboarding.share.lead": "Ini-asen i medden amek ara k·m-id-afen deg Mastodon!",
"onboarding.share.message": "Nekk d {username} deg #Mastodon! Ḍfer iyi-d sya {url}",
"onboarding.share.title": "Bḍu amaɣnu-inek·inem",
"onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:",
"onboarding.start.skip": "Want to skip right ahead?",
"onboarding.start.title": "Tseggmeḍ-tt !",
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
"onboarding.steps.follow_people.body": "Aḍfer n medden yelhan, d tikti n Mastodon.",
"onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}",
"onboarding.steps.publish_status.body": "Say hello to the world.",
"onboarding.steps.publish_status.title": "Aru tasuffeɣt-inek·inem tamezwarutt",
@ -377,6 +409,7 @@
"picture_in_picture.restore": "Err-it amkan-is",
"poll.closed": "Tfukk",
"poll.refresh": "Smiren",
"poll.reveal": "Wali igmaḍ",
"poll.total_people": "{count, plural, one {# n wemdan} other {# n yemdanen}}",
"poll.total_votes": "{count, plural, one {# n udɣaṛ} other {# n yedɣaṛen}}",
"poll.vote": "Dɣeṛ",
@ -385,10 +418,13 @@
"poll_button.remove_poll": "Kkes asenqed",
"privacy.change": "Seggem tabaḍnit n yizen",
"privacy.direct.long": "Wid akk i d-yettwabdaren deg tuffeɣt",
"privacy.direct.short": "Imdanen ulmisen",
"privacy.private.long": "Ala wid i k-yeṭṭafaṛen",
"privacy.private.short": "Imeḍfaren",
"privacy.public.long": "Kra n win yellan deg Masṭudun neɣ berra-s",
"privacy.public.short": "Azayez",
"privacy.unlisted.long": "Kra kan n ilguritmen",
"privacy_policy.last_updated": "Aleqqem aneggaru {date}",
"privacy_policy.title": "Tasertit tabaḍnit",
"refresh": "Smiren",
"regeneration_indicator.label": "Yessalay-d…",
@ -412,9 +448,11 @@
"report.next": "Uḍfiṛ",
"report.placeholder": "Iwenniten-nniḍen",
"report.reasons.dislike": "Ur t-ḥemmleɣ ara",
"report.reasons.other": "D ayen nniḍen",
"report.reasons.spam": "D aspam",
"report.submit": "Azen",
"report.target": "Mmel {target}",
"report.thanks.title": "Ur tebɣiḍ ara ad twaliḍ aya?",
"report.unfollow": "Seḥbes aḍfar n @{name}",
"report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached",
"report_notification.categories.other": "Ayen nniḍen",
@ -422,7 +460,13 @@
"report_notification.open": "Ldi aneqqis",
"search.no_recent_searches": "Ulac inadiyen ineggura",
"search.placeholder": "Nadi",
"search.quick_action.account_search": "Imaɣnuten mṣadan d {x}",
"search.quick_action.go_to_account": "Ddu ɣer umaɣnu {x}",
"search.quick_action.go_to_hashtag": "Ddu ɣer uhacṭag {x}",
"search.quick_action.open_url": "Ldi tansa URL deg Mastodon",
"search.quick_action.status_search": "Tisuffaɣ mṣadan d {x}",
"search.search_or_paste": "Nadi neɣ senṭeḍ URL",
"search_popout.full_text_search_disabled_message": "Ur yelli ara deg {domain}.",
"search_popout.language_code": "Tangalt ISO n tutlayt",
"search_popout.options": "Iwellihen n unadi",
"search_popout.recent": "Inadiyen ineggura",
@ -471,6 +515,7 @@
"status.report": "Cetki ɣef @{name}",
"status.sensitive_warning": "Agbur amḥulfu",
"status.share": "Bḍu",
"status.show_filter_reason": "Ssken-d akken yebɣu yili",
"status.show_less": "Ssken-d drus",
"status.show_less_all": "Semẓi akk tisuffɣin",
"status.show_more": "Ssken-d ugar",
@ -516,6 +561,7 @@
"upload_modal.preparing_ocr": "Aheyyi n OCR…",
"upload_modal.preview_label": "Taskant ({ratio})",
"upload_progress.label": "Asali iteddu...",
"username.taken": "Yettwaṭṭef yisem-a n useqdac. Ɛreḍ wayeḍ",
"video.close": "Mdel tabidyutt",
"video.download": "Sidered afaylu",
"video.exit_fullscreen": "Ffeɣ seg ugdil ačuran",

View File

@ -27,8 +27,8 @@
"account.domain_blocked": "Užblokuotas domenas",
"account.edit_profile": "Redaguoti profilį",
"account.enable_notifications": "Pranešti man, kai @{name} paskelbia",
"account.endorse": "Rekomenduoti profilyje",
"account.featured_tags.last_status_at": "Paskutinį kartą paskelbta {date}",
"account.endorse": "Rodyti profilyje",
"account.featured_tags.last_status_at": "Paskutinis įrašas {date}",
"account.featured_tags.last_status_never": "Nėra įrašų",
"account.featured_tags.title": "{name} rekomenduojami saitažodžiai",
"account.follow": "Sekti",
@ -53,7 +53,7 @@
"account.mute_notifications_short": "Nutildyti pranešimus",
"account.mute_short": "Nutildyti",
"account.muted": "Nutildytas",
"account.mutual": "Abipusis",
"account.mutual": "Bendri",
"account.no_bio": "Nėra pateikto aprašymo.",
"account.open_original_page": "Atidaryti originalinį puslapį",
"account.posts": "Įrašai",
@ -72,7 +72,7 @@
"account.unmute": "Atšaukti nutildymą @{name}",
"account.unmute_notifications_short": "Atšaukti nutildymą pranešimams",
"account.unmute_short": "Atšaukti nutildymą",
"account_note.placeholder": "Spustelėk norėdamas (-a) pridėti pastabą",
"account_note.placeholder": "Spustelėk norint pridėti pastabą.",
"admin.dashboard.daily_retention": "Naudotojų pasilikimo rodiklis pagal dieną po registracijos",
"admin.dashboard.monthly_retention": "Naudotojų pasilikimo rodiklis pagal mėnesį po registracijos",
"admin.dashboard.retention.average": "Vidurkis",
@ -89,21 +89,21 @@
"announcement.announcement": "Skelbimas",
"attachments_list.unprocessed": "(neapdorotas)",
"audio.hide": "Slėpti garsą",
"boost_modal.combo": "Gali paspausti {combo}, kad praleisti kitą kartą",
"boost_modal.combo": "Galima paspausti {combo}, kad praleisti kitą kartą.",
"bundle_column_error.copy_stacktrace": "Kopijuoti klaidos ataskaitą",
"bundle_column_error.error.body": "Užklausos puslapio nepavyko atvaizduoti. Tai gali būti dėl mūsų kodo klaidos arba naršyklės suderinamumo problemos.",
"bundle_column_error.error.body": "Paprašytos puslapio nepavyko atvaizduoti. Tai gali būti dėl mūsų kodo klaidos arba naršyklės suderinamumo problemos.",
"bundle_column_error.error.title": "O, ne!",
"bundle_column_error.network.body": "Bandant užkrauti šį puslapį įvyko klaida. Tai galėjo atsitikti dėl laikinos tavo interneto ryšio arba šio serverio problemos.",
"bundle_column_error.network.title": "Tinklo klaida",
"bundle_column_error.retry": "Bandyti dar kartą",
"bundle_column_error.return": "Grįžti į pradžią",
"bundle_column_error.return": "Grįžti į pagrindinį",
"bundle_column_error.routing.body": "Prašyto puslapio nepavyko rasti. Ar esi tikras (-a), kad adreso juostoje nurodytas URL adresas yra teisingas?",
"bundle_column_error.routing.title": "404",
"bundle_modal_error.close": "Uždaryti",
"bundle_modal_error.message": "Kraunant šį komponentą kažkas nepavyko.",
"bundle_modal_error.retry": "Bandyti dar kartą",
"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ą {domain} šiuo metu neįmanoma, tačiau nepamiršk, kad norint naudotis Mastodon nebūtina turėti paskyrą domene {domain}.",
"closed_registrations_modal.description": "Sukurti paskyrą {domain} šiuo metu neįmanoma, bet nepamiršk, kad norint naudotis Mastodon nebūtina turėti paskyrą domene {domain}.",
"closed_registrations_modal.find_another_server": "Rasti kitą serverį",
"closed_registrations_modal.preamble": "Mastodon yra decentralizuotas, todėl nesvarbu, kur susikursi paskyrą, galėsi sekti ir bendrauti su bet kuriuo šiame serveryje esančiu asmeniu. Jį gali net savarankiškai talpinti!",
"closed_registrations_modal.title": "Užsiregistruoti Mastodon",
@ -116,7 +116,7 @@
"column.domain_blocks": "Užblokuoti domenai",
"column.favourites": "Mėgstamiausi",
"column.firehose": "Tiesioginiai srautai",
"column.follow_requests": "Sekimo prašymus",
"column.follow_requests": "Sekimo prašymai",
"column.home": "Pagrindinis",
"column.lists": "Sąrašai",
"column.mutes": "Nutildyti naudotojai",
@ -131,7 +131,7 @@
"column_header.show_settings": "Rodyti nustatymus",
"column_header.unpin": "Atsegti",
"column_subheading.settings": "Nustatymai",
"community.column_settings.local_only": "Tik vietinis",
"community.column_settings.local_only": "Tik vietinė",
"community.column_settings.media_only": "Tik medija",
"community.column_settings.remote_only": "Tik nuotolinis",
"compose.language.change": "Keisti kalbą",
@ -140,17 +140,17 @@
"compose.published.open": "Atidaryti",
"compose.saved.body": "Įrašas išsaugotas.",
"compose_form.direct_message_warning_learn_more": "Sužinoti daugiau",
"compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
"compose_form.encryption_warning": "Mastodon įrašai nėra šifruojami nuo galo iki galo. Per Mastodon nesidalyk jokia slapta informacija.",
"compose_form.hashtag_warning": "Šis įrašas nebus įtraukta į jokį saitažodį, nes ji nėra vieša. Tik viešų įrašų galima ieškoti pagal saitažodį.",
"compose_form.lock_disclaimer": "Tavo paskyra nėra {locked}. Bet kas gali sekti tave ir peržiūrėti tik sekėjams skirtus įrašus.",
"compose_form.lock_disclaimer.lock": "užrakinta",
"compose_form.placeholder": "Kas tavo mintyse?",
"compose_form.poll.duration": "Apklausos trukmė",
"compose_form.poll.multiple": "Keli pasirinkimai",
"compose_form.poll.option_placeholder": "{number} pasirinkimas",
"compose_form.poll.option_placeholder": "{number} parinktis",
"compose_form.poll.single": "Pasirinkti vieną",
"compose_form.poll.switch_to_multiple": "Keisti apklausą, kad būtų galima pasirinkti kelis pasirinkimus",
"compose_form.poll.switch_to_single": "Pakeisti apklausą, kad būtų galima pasirinkti vieną variantą",
"compose_form.poll.switch_to_multiple": "Keisti apklausą, kad būtų galima pasirinkti kelis pasirinkimus.",
"compose_form.poll.switch_to_single": "Keisti apklausą, kad būtų galima pasirinkti vieną pasirinkimą",
"compose_form.poll.type": "Stilius",
"compose_form.publish": "Skelbti",
"compose_form.publish_form": "Naujas įrašas",
@ -166,24 +166,26 @@
"confirmations.cancel_follow_request.confirm": "Atšaukti prašymą",
"confirmations.cancel_follow_request.message": "Ar tikrai nori atšaukti savo prašymą sekti {name}?",
"confirmations.delete.confirm": "Ištrinti",
"confirmations.delete.message": "Are you sure you want to delete this status?",
"confirmations.delete.message": "Ar tikrai nori ištrinti šį įrašą?",
"confirmations.delete_list.confirm": "Ištrinti",
"confirmations.delete_list.message": "Ar tikrai nori visam laikui ištrinti šį sąrašą?",
"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.domain_block.confirm": "Hide entire domain",
"confirmations.domain_block.confirm": "Blokuoti visą domeną",
"confirmations.domain_block.message": "Ar tikrai, tikrai nori užblokuoti visą {domain}? Daugeliu atvejų užtenka kelių tikslinių blokavimų arba nutildymų. Šio domeno turinio nematysi jokiose viešose laiko skalėse ar pranešimuose. Tavo sekėjai iš to domeno bus pašalinti.",
"confirmations.edit.confirm": "Redaguoti",
"confirmations.edit.message": "Redaguojant dabar, bus perrašyta šiuo metu kuriama žinutė. Ar tikrai nori tęsti?",
"confirmations.logout.confirm": "Atsijungti",
"confirmations.logout.message": "Ar tikrai nori atsijungti?",
"confirmations.mute.confirm": "Nutildyti",
"confirmations.mute.explanation": "Tai paslėps jų įrašus ir įrašus, kuriuose jie menėmi, tačiau jie vis tiek galės matyti tavo įrašus ir sekti.",
"confirmations.mute.message": "Ar tikrai norite nutildyti {name}?",
"confirmations.redraft.confirm": "Ištrinti ir perrašyti",
"confirmations.mute.explanation": "Tai paslėps jų įrašus ir įrašus, kuriuose jie menėmi, bet jie vis tiek galės matyti tavo įrašus ir sekti.",
"confirmations.mute.message": "Ar tikrai nori nutildyti {name}?",
"confirmations.redraft.confirm": "Ištrinti ir parengti iš naujo",
"confirmations.redraft.message": "Ar tikrai nori ištrinti šį įrašą ir parengti jį iš naujo kaip juodraštį? Bus prarastos mėgstamiausios ir pakėlimai, o atsakymai į originalinį įrašą taps liekamojais.",
"confirmations.reply.confirm": "Atsakyti",
"confirmations.reply.message": "Atsakant dabar, bus perrašyta metu kuriama žinutė. Ar tikrai nori tęsti?",
"confirmations.unfollow.confirm": "Nebesekti",
"confirmations.unfollow.message": "Ar tikrai norite atsisakyti sekimo {name}?",
"confirmations.unfollow.message": "Ar tikrai nori nebesekti {name}?",
"conversation.delete": "Ištrinti pokalbį",
"conversation.mark_as_read": "Žymėti kaip skaitytą",
"conversation.open": "Peržiūrėti pokalbį",
@ -191,87 +193,94 @@
"copy_icon_button.copied": "Nukopijuota į iškarpinę",
"copypaste.copied": "Nukopijuota",
"copypaste.copy_to_clipboard": "Kopijuoti į iškarpinę",
"directory.local": "Iš {domain} tik",
"directory.new_arrivals": "Naujos prekės",
"directory.recently_active": "Neseniai aktyvus",
"directory.federated": "Iš žinomų fediversų",
"directory.local": "Tik iš {domain}",
"directory.new_arrivals": "Nauji atvykėliai",
"directory.recently_active": "Neseniai aktyvus (-i)",
"disabled_account_banner.account_settings": "Paskyros nustatymai",
"disabled_account_banner.text": "Jūsų paskyra {disabledAccount} šiuo metu yra išjungta.",
"disabled_account_banner.text": "Tavo paskyra {disabledAccount} šiuo metu išjungta.",
"dismissable_banner.community_timeline": "Tai naujausi vieši įrašai, kuriuos paskelbė žmonės, kurių paskyros talpinamos {domain}.",
"dismissable_banner.dismiss": "Atmesti",
"dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
"dismissable_banner.explore_statuses": "Tai įrašai iš viso socialinio tinklo, kurie šiandien sulaukia vis daugiau dėmesio. Naujesni įrašai, turintys daugiau boosts ir mėgstamiausių įrašų, yra vertinami aukščiau.",
"dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
"embed.instructions": "Embed this status on your website by copying the code below.",
"embed.preview": "Štai kaip tai atrodys:",
"dismissable_banner.explore_links": "Tai naujienos, kuriomis šiandien daugiausiai bendrinamasi socialiniame žiniatinklyje. Naujesnės naujienų istorijos, kurias paskelbė daugiau skirtingų žmonių, vertinamos aukščiau.",
"dismissable_banner.explore_statuses": "Tai įrašai iš viso socialinio žiniatinklio, kurie šiandien sulaukia daug dėmesio. Naujesni įrašai, turintys daugiau pakėlimų ir mėgstamų, vertinami aukščiau.",
"dismissable_banner.explore_tags": "Tai saitažodžiai, kurie šiandien sulaukia daug dėmesio socialiniame žiniatinklyje. Saitažodžiai, kuriuos naudoja daugiau skirtingų žmonių, vertinami aukščiau.",
"dismissable_banner.public_timeline": "Tai naujausi vieši įrašai, kuriuos socialiniame žiniatinklyje paskelbė žmonės, sekantys {domain}.",
"embed.instructions": "Įterpk šį įrašą į savo svetainę nukopijavus (-usi) toliau pateiktą kodą.",
"embed.preview": "Štai, kaip tai atrodys:",
"emoji_button.activity": "Veikla",
"emoji_button.clear": "Išvalyti",
"emoji_button.custom": "Pasirinktinis",
"emoji_button.flags": "Vėliavos",
"emoji_button.food": "Maistas ir Gėrimai",
"emoji_button.food": "Maistas ir gėrimai",
"emoji_button.label": "Įterpti veidelius",
"emoji_button.nature": "Gamta",
"emoji_button.not_found": "Nerasta jokių tinkamų jaustukų",
"emoji_button.not_found": "Nerasta jokių tinkamų jaustukų.",
"emoji_button.objects": "Objektai",
"emoji_button.people": "Žmonės",
"emoji_button.recent": "Dažniausiai naudojama",
"emoji_button.search": "Paieška...",
"emoji_button.recent": "Dažniausiai naudojami",
"emoji_button.search": "Ieškoti...",
"emoji_button.search_results": "Paieškos rezultatai",
"emoji_button.symbols": "Simboliai",
"emoji_button.travel": "Kelionės ir Vietos",
"empty_column.account_hides_collections": "Šis naudotojas (-a) pasirinko nepadaryti šią informaciją prieinamą",
"empty_column.account_suspended": "Paskyra sustabdyta",
"empty_column.account_timeline": "No toots here!",
"empty_column.account_unavailable": "Profilis neprieinamas",
"empty_column.blocks": "Dar neužblokavote nė vieno naudotojo.",
"empty_column.bookmarked_statuses": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.",
"empty_column.community": "Vietinė laiko juosta yra tuščia. Parašykite ką nors viešai, kad pradėtumėte veikti!",
"empty_column.direct": "Dar neturite jokių privačių paminėjimų. Kai išsiųsite arba gausite tokį pranešimą, jis bus rodomas čia.",
"empty_column.domain_blocks": "There are no hidden domains yet.",
"empty_column.favourited_statuses": "Dar neturite mėgstamiausių įrašų. Kai vieną iš jų pamėgsite, jis bus rodomas čia.",
"empty_column.follow_requests": "Dar neturite jokių sekimo užklausų. Kai gausite tokį prašymą, jis bus rodomas čia.",
"empty_column.followed_tags": "Dar nesekėte jokių grotažymių. Kai tai padarysite, jie bus rodomi čia.",
"emoji_button.travel": "Kelionės ir vietos",
"empty_column.account_hides_collections": "Šis (-i) naudotojas (-a) pasirinko nepadaryti šią informaciją prieinamą.",
"empty_column.account_suspended": "Paskyra sustabdyta.",
"empty_column.account_timeline": "Nėra įrašų čia.",
"empty_column.account_unavailable": "Profilis neprieinamas.",
"empty_column.blocks": "Dar neužblokavai nė vieno naudotojo.",
"empty_column.bookmarked_statuses": "Dar neturi nė vienos įrašo žymės. Kai vieną iš jų pridėsi į žymes, jis bus rodomas čia.",
"empty_column.community": "Vietinė laiko skalė tuščia. Parašyk ką nors viešai, kad pradėtum bendrauti!",
"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.domain_blocks": "Dar nėra užblokuotų domenų.",
"empty_column.explore_statuses": "Šiuo metu niekas nėra tendencinga. Patikrink vėliau.",
"empty_column.favourited_statuses": "Dar neturi mėgstamų įrašų. Kai vieną iš jų pamėgsi, jis bus rodomas čia.",
"empty_column.favourites": "Šio įrašo dar niekas nepamėgo. Kai kas nors tai padarys, jie bus rodomi čia.",
"empty_column.follow_requests": "Dar neturi jokių sekimo prašymų. Kai gausi tokį prašymą, jis bus rodomas čia.",
"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": "Your home timeline is empty! Follow more people to fill it up. {suggestions}",
"empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
"empty_column.lists": "Dar neturite jokių sąrašų. Kai jį sukursite, jis bus rodomas čia.",
"empty_column.mutes": "Dar nesate nutildę nė vieno naudotojo.",
"empty_column.notifications": "Dar neturite jokių pranešimų. Kai kiti žmonės su jumis bendraus, matysite tai čia.",
"empty_column.public": "Čia nieko nėra! Parašykite ką nors viešai arba rankiniu būdu sekite naudotojus iš kitų serverių, kad jį užpildytumėte",
"error.unexpected_crash.explanation": "Dėl mūsų kodo klaidos arba naršyklės suderinamumo problemos šis puslapis negalėjo būti rodomas teisingai.",
"error.unexpected_crash.explanation_addons": "Šį puslapį nepavyko teisingai parodyti. Šią klaidą greičiausiai sukėlė naršyklės priedas arba automatinio vertimo įrankiai.",
"error.unexpected_crash.next_steps": "Pabandykite atnaujinti puslapį. Jei tai nepadeda, galbūt vis dar galėsite naudotis \"Mastodon\" naudodami kitą naršyklę arba vietinę programėlę.",
"error.unexpected_crash.next_steps_addons": "Pabandykite juos išjungti ir atnaujinti puslapį. Jei tai nepadeda, galbūt vis dar galėsite naudotis \"Mastodon\" naudodami kitą naršyklę arba vietinę programėlę.",
"errors.unexpected_crash.report_issue": "Pranešti apie triktį",
"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.lists": "Dar neturi jokių sąrašų. Kai jį sukursi, jis bus rodomas čia.",
"empty_column.mutes": "Dar nesi nutildęs (-usi) nė vieno naudotojo.",
"empty_column.notifications": "Dar neturi jokių pranešimų. Kai kiti žmonės su tavimi bendraus, 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.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ę.",
"error.unexpected_crash.next_steps_addons": "Pabandyk juos išjungti ir atnaujinti puslapį. Jei tai nepadeda, galbūt vis dar galėsi naudotis Mastodon per kitą naršyklę arba savąją programėlę.",
"errors.unexpected_crash.copy_stacktrace": "Kopijuoti dėklo eigą į iškarpinę",
"errors.unexpected_crash.report_issue": "Pranešti apie problemą",
"explore.search_results": "Paieškos rezultatai",
"explore.suggested_follows": "Žmonės",
"explore.title": "Naršyti",
"explore.trending_links": "Naujienos",
"explore.trending_statuses": "Įrašai",
"explore.trending_tags": "Saitažodžiai",
"filter_modal.added.context_mismatch_explanation": "Ši filtro kategorija netaikoma kontekste, kuriame peržiūrėjote šį pranešimą. Jei norite, kad pranešimas būtų filtruojamas ir šiame kontekste, turėsite 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ėsite pakeisti galiojimo datą.",
"filter_modal.added.expired_title": "Pasibaigė filtro galiojimo laikas!",
"filter_modal.added.review_and_configure": "Norėdami peržiūrėti ir toliau konfigūruoti šią filtro kategoriją, eikite į {settings_link}.",
"filter_modal.added.review_and_configure_title": "Filtro nuostatos",
"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ą.",
"filter_modal.added.expired_title": "Baigėsi filtro galiojimas.",
"filter_modal.added.review_and_configure": "Norint peržiūrėti ir toliau konfigūruoti šią filtro kategoriją, eik į nuorodą {settings_link}.",
"filter_modal.added.review_and_configure_title": "Filtro nustatymai",
"filter_modal.added.settings_link": "nustatymų puslapis",
"filter_modal.added.short_explanation": "Šis pranešimas buvo įtrauktas į šią filtro kategoriją: {title}.",
"filter_modal.added.title": "Pridėtas filtras!",
"filter_modal.select_filter.context_mismatch": "netaikoma šiame kontekste",
"filter_modal.select_filter.expired": "nebegalioja",
"filter_modal.added.short_explanation": "Šis įrašas buvo pridėtas į šią filtro kategoriją: {title}.",
"filter_modal.added.title": "Pridėtas filtras.",
"filter_modal.select_filter.context_mismatch": "netaikoma šiame kontekste.",
"filter_modal.select_filter.expired": "nebegalioja.",
"filter_modal.select_filter.prompt_new": "Nauja kategorija: {name}",
"filter_modal.select_filter.search": "Ieškoti arba sukurti",
"filter_modal.select_filter.subtitle": "Naudoti esamą kategoriją arba sukurti naują",
"filter_modal.select_filter.subtitle": "Naudok esamą kategoriją arba sukurk naują.",
"filter_modal.select_filter.title": "Filtruoti šį įrašą",
"filter_modal.title.status": "Filtruoti šį įrašą",
"filter_modal.title.status": "Filtruoti įrašą",
"firehose.all": "Visi",
"firehose.local": "Šis serveris",
"firehose.remote": "Kiti serveriai",
"follow_request.authorize": "Autorizuoti",
"follow_request.authorize": "Leisti",
"follow_request.reject": "Atmesti",
"follow_requests.unlocked_explanation": "Nors tavo paskyra neužrakinta, {domain} personalas mano, kad galbūt norėsi rankiniu būdu patikrinti šių paskyrų sekimo užklausas.",
"follow_requests.unlocked_explanation": "Nors tavo paskyra neužrakinta, {domain} personalas mano, kad galbūt norėsi rankiniu būdu patikrinti šių paskyrų sekimo prašymus.",
"follow_suggestions.curated_suggestion": "Personalo pasirinkimai",
"follow_suggestions.dismiss": "Daugiau nerodyti",
"follow_suggestions.hints.friends_of_friends": "Šis profilis yra populiarus tarp žmonių, kuriuos sekei.",
"follow_suggestions.hints.featured": "Šį profilį atrinko {domain} komanda.",
"follow_suggestions.hints.friends_of_friends": "Šis profilis yra populiarus tarp žmonių, kuriuos seki.",
"follow_suggestions.hints.most_followed": "Šis profilis yra vienas iš labiausiai sekamų {domain}.",
"follow_suggestions.hints.most_interactions": "Pastaruoju metu šis profilis sulaukia daug dėmesio šiame {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Šis profilis panašus į profilius, kuriuos neseniai sekei.",
@ -279,7 +288,7 @@
"follow_suggestions.popular_suggestion": "Populiarus pasiūlymas",
"follow_suggestions.view_all": "Peržiūrėti viską",
"follow_suggestions.who_to_follow": "Ką sekti",
"followed_tags": "Sekamos saitažodžiai",
"followed_tags": "Sekami saitažodžiai",
"footer.about": "Apie",
"footer.directory": "Profilių katalogas",
"footer.get_app": "Gauti programėlę",
@ -289,214 +298,243 @@
"footer.source_code": "Peržiūrėti šaltinio kodą",
"footer.status": "Būsena",
"generic.saved": "Išsaugoti",
"getting_started.heading": "Pradedant",
"getting_started.heading": "Kaip pradėti",
"hashtag.column_header.tag_mode.all": "ir {additional}",
"hashtag.column_header.tag_mode.any": "ar {additional}",
"hashtag.column_header.tag_mode.none": "be {additional}",
"hashtag.column_settings.select.no_options_message": "Pasiūlymų nerasta",
"hashtag.column_settings.select.placeholder": "Įvesti grotažymes…",
"hashtag.column_settings.select.no_options_message": "Pasiūlymų nerasta.",
"hashtag.column_settings.select.placeholder": "Įvesti saitažodžius…",
"hashtag.column_settings.tag_mode.all": "Visi šie",
"hashtag.column_settings.tag_mode.any": "Bet kuris šių",
"hashtag.column_settings.tag_mode.any": "Bet kuris šių",
"hashtag.column_settings.tag_mode.none": "Nė vienas iš šių",
"hashtag.column_settings.tag_toggle": "Include additional tags in this column",
"hashtag.counter_by_accounts": "{count, plural,one {{counter} dalyvis}other {{counter} dalyviai}}",
"hashtag.counter_by_uses": "{count, plural, one {{counter} įrašas} other {{counter} įrašų}}",
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} įrašas} other {{counter} įrašų}} šiandien",
"hashtag.follow": "Sekti grotažymę",
"hashtag.unfollow": "Nesekti grotažymės",
"hashtags.and_other": "…ir{count, plural,other {#daugiau}}",
"home.column_settings.basic": "Pagrindinis",
"home.column_settings.show_reblogs": "Rodyti \"boosts\"",
"hashtag.column_settings.tag_toggle": "Įtraukti papildomas šio stulpelio žymes",
"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.follow": "Sekti saitažodį",
"hashtag.unfollow": "Nebesekti saitažodį",
"hashtags.and_other": "…ir {count, plural, one {# daugiau} few {# daugiau} many {# daugiau}other {# daugiau}}",
"home.column_settings.basic": "Paprastas",
"home.column_settings.show_reblogs": "Rodyti pakėlimus",
"home.column_settings.show_replies": "Rodyti atsakymus",
"home.hide_announcements": "Slėpti skelbimus",
"home.pending_critical_update.link": "Žiūrėti atnaujinimus",
"home.pending_critical_update.title": "Galimas kritinis saugumo atnaujinimas!",
"home.pending_critical_update.body": "Kuo greičiau atnaujink savo Mastodon serverį!",
"home.pending_critical_update.link": "Žiūrėti naujinimus",
"home.pending_critical_update.title": "Galimas kritinis saugumo naujinimas.",
"home.show_announcements": "Rodyti skelbimus",
"interaction_modal.description.favourite": "Su Mastodon paskyra gali pamėgti šį įrašą, kad autorius (-ė) žinotų, jog vertinti tai ir išsaugoti jį vėliau.",
"interaction_modal.description.follow": "Su Mastodon paskyra gali sekti {name}, kad gautum jų įrašus į pagrindinį srautą.",
"interaction_modal.description.reblog": "Su Mastodon paskyra gali pakelti šią įrašą ir pasidalyti juo su savo sekėjais.",
"interaction_modal.description.reply": "Su Mastodon paskyra gali atsakyti į šį įrašą.",
"interaction_modal.login.action": "Į pagrindinį puslapį",
"interaction_modal.login.prompt": "Tavo pagrindinio serverio domenas, pvz., mastodon.social.",
"interaction_modal.no_account_yet": "Nesi Mastodon?",
"interaction_modal.on_another_server": "Kitame serveryje",
"interaction_modal.on_this_server": "Šiame serveryje",
"interaction_modal.sign_in": "Nesi prisijungęs (-usi) prie šio serverio. Kur yra laikoma tavo paskyra?",
"interaction_modal.sign_in": "Nesi prisijungęs (-usi) prie šio serverio. Kur yra talpinama tavo paskyra?",
"interaction_modal.sign_in_hint": "Patarimas: tai svetainė, kurioje užsiregistravai. Jei neprisimeni, ieškok sveikinimo el. laiško savo pašto dėžutėje. Taip pat gali įvesti visą savo naudotojo vardą (pvz., @Mastodon@mastodon.social).",
"interaction_modal.title.favourite": "Mėgstamiausias {name} įrašas",
"interaction_modal.title.favourite": "Pamėgti {name} įrašą",
"interaction_modal.title.follow": "Sekti {name}",
"keyboard_shortcuts.back": "to navigate back",
"keyboard_shortcuts.blocked": "to open blocked users list",
"keyboard_shortcuts.boost": "to boost",
"keyboard_shortcuts.column": "to focus a status in one of the columns",
"keyboard_shortcuts.compose": "to focus the compose textarea",
"keyboard_shortcuts.direct": "to open direct messages column",
"keyboard_shortcuts.down": "to move down in the list",
"keyboard_shortcuts.enter": "to open status",
"keyboard_shortcuts.federated": "to open federated timeline",
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
"keyboard_shortcuts.home": "to open home timeline",
"interaction_modal.title.reblog": "Pakelti {name} įrašą",
"interaction_modal.title.reply": "Atsakyti į {name} įrašą",
"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ų}}",
"intervals.full.minutes": "{number, plural, one {# minutė} few {# minutes} many {# minutės} other {# minučių}}",
"keyboard_shortcuts.back": "Naršyti atgal",
"keyboard_shortcuts.blocked": "Atidaryti užblokuotų naudotojų sąrašą",
"keyboard_shortcuts.boost": "Pakelti įrašą",
"keyboard_shortcuts.column": "Fokusuoti stulpelį",
"keyboard_shortcuts.compose": "Fokusuoti rengykles teksto sritį",
"keyboard_shortcuts.description": "Aprašymas",
"keyboard_shortcuts.direct": "atidaryti privačių paminėjimų stulpelį",
"keyboard_shortcuts.down": "Perkelti žemyn sąraše",
"keyboard_shortcuts.enter": "Atidaryti įrašą",
"keyboard_shortcuts.favourite": "Pamėgti įrašą",
"keyboard_shortcuts.favourites": "Atidaryti mėgstamųjų sąrašą",
"keyboard_shortcuts.federated": "Atidaryti federacinę laiko skalę",
"keyboard_shortcuts.heading": "Spartieji klavišai",
"keyboard_shortcuts.home": "Atidaryti pagrindinį laiko skalę",
"keyboard_shortcuts.hotkey": "Spartusis klavišas",
"keyboard_shortcuts.legend": "to display this legend",
"keyboard_shortcuts.local": "to open local timeline",
"keyboard_shortcuts.mention": "to mention author",
"keyboard_shortcuts.muted": "to open muted users list",
"keyboard_shortcuts.my_profile": "to open your profile",
"keyboard_shortcuts.notifications": "to open notifications column",
"keyboard_shortcuts.legend": "Rodyti šią legendą",
"keyboard_shortcuts.local": "Atidaryti vietinę laiko skalę",
"keyboard_shortcuts.mention": "Paminėti autorių (-ę)",
"keyboard_shortcuts.muted": "Atidaryti nutildytų naudotojų sąrašą",
"keyboard_shortcuts.my_profile": "Atidaryti savo profilį",
"keyboard_shortcuts.notifications": "Atidaryti pranešimų stulpelį",
"keyboard_shortcuts.open_media": "Atidaryti mediją",
"keyboard_shortcuts.pinned": "to open pinned toots list",
"keyboard_shortcuts.profile": "to open author's profile",
"keyboard_shortcuts.reply": "to reply",
"keyboard_shortcuts.requests": "to open follow requests list",
"keyboard_shortcuts.search": "to focus search",
"keyboard_shortcuts.spoilers": "to show/hide CW field",
"keyboard_shortcuts.start": "to open \"get started\" column",
"keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.pinned": "Atidaryti prisegtų įrašų sąrašą",
"keyboard_shortcuts.profile": "Atidaryti autoriaus (-ės) profilį",
"keyboard_shortcuts.reply": "Atsakyti į įrašą",
"keyboard_shortcuts.requests": "Atidaryti sekimo prašymų sąrašą",
"keyboard_shortcuts.search": "Fokusuoti paieškos juostą",
"keyboard_shortcuts.spoilers": "Rodyti / slėpti TĮ lauką",
"keyboard_shortcuts.start": "Atidarykite stulpelį Kaip pradėti",
"keyboard_shortcuts.toggle_hidden": "Rodyti / slėpti tekstą po TĮ",
"keyboard_shortcuts.toggle_sensitivity": "Rodyti / slėpti mediją",
"keyboard_shortcuts.toot": "to start a brand new toot",
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"keyboard_shortcuts.toot": "Pradėti naują įrašą",
"keyboard_shortcuts.unfocus": "Nebefokusuoti rengykles teksto sritį / paiešką",
"keyboard_shortcuts.up": "Perkelti į viršų sąraše",
"lightbox.close": "Uždaryti",
"lightbox.compress": "Suspausti vaizdo peržiūros langelį",
"lightbox.expand": "Išplėsti vaizdo peržiūros langelį",
"lightbox.next": "Kitas",
"lightbox.previous": "Ankstesnis",
"limited_account_hint.action": "Vis tiek rodyti profilį",
"limited_account_hint.title": "Šį profilį paslėpė {domain} moderatoriai.",
"limited_account_hint.title": "Šį profilį paslėpė {domain} prižiūrėtojai.",
"link_preview.author": "Sukūrė {name}",
"lists.account.add": "Pridėti į sąrašą",
"lists.account.remove": "Pašalinti iš sąrašo",
"lists.delete": "Ištrinti sąrašą",
"lists.edit": "Redaguoti sąrašą",
"lists.edit.submit": "Prierašo pakeitimas",
"lists.edit.submit": "Keisti pavadinimą",
"lists.exclusive": "Slėpti šiuos įrašus iš pagrindinio",
"lists.new.create": "Pridėti sąrašą",
"lists.new.title_placeholder": "Naujas sąrašo pavadinimas",
"lists.replies_policy.followed": "Bet kuris sekamas naudotojas",
"lists.replies_policy.list": "Sąrašo nariai",
"lists.replies_policy.none": "Nei vienas",
"lists.replies_policy.followed": "Bet kuriam sekamam naudotojui",
"lists.replies_policy.list": "Sąrašo nariams",
"lists.replies_policy.none": "Nei vienam",
"lists.replies_policy.title": "Rodyti atsakymus:",
"lists.search": "Ieškoti tarp sekamų žmonių",
"lists.subheading": "Jūsų sąrašai",
"lists.subheading": "Tavo sąrašai",
"load_pending": "{count, plural, one {# naujas elementas} few {# nauji elementai} many {# naujo elemento} other {# naujų elementų}}",
"loading_indicator.label": "Kraunama…",
"media_gallery.toggle_visible": "{number, plural, one {Slėpti vaizdą} few {Slėpti vaizdus} many {Slėpti vaizdo} other {Slėpti vaizdų}}",
"moved_to_account_banner.text": "Tavo paskyra {disabledAccount} šiuo metu yra išjungta, nes persikėlei į {movedToAccount}.",
"moved_to_account_banner.text": "Tavo paskyra {disabledAccount} šiuo metu išjungta, nes persikėlei į {movedToAccount}.",
"mute_modal.duration": "Trukmė",
"mute_modal.hide_notifications": "Slėpti šio naudotojo pranešimus?",
"mute_modal.indefinite": "Neribotas",
"mute_modal.indefinite": "Neribota",
"navigation_bar.about": "Apie",
"navigation_bar.advanced_interface": "Atidarykite išplėstinę žiniatinklio sąsają",
"navigation_bar.advanced_interface": "Atidaryti išplėstinę žiniatinklio sąsają",
"navigation_bar.blocks": "Užblokuoti naudotojai",
"navigation_bar.bookmarks": "Žymės",
"navigation_bar.compose": "Compose new toot",
"navigation_bar.community_timeline": "Vietinė laiko skalė",
"navigation_bar.compose": "Sukurti naują įrašą",
"navigation_bar.direct": "Privatūs paminėjimai",
"navigation_bar.discover": "Atrasti",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.domain_blocks": "Užblokuoti domenai",
"navigation_bar.explore": "Naršyti",
"navigation_bar.favourites": "Mėgstamiausi",
"navigation_bar.filters": "Nutyti žodžiai",
"navigation_bar.follow_requests": "Sekti prašymus",
"navigation_bar.followed_tags": "Sekti grotažymę",
"navigation_bar.favourites": "Mėgstami",
"navigation_bar.filters": "Nutildyti žodžiai",
"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.lists": "Sąrašai",
"navigation_bar.logout": "Atsijungti",
"navigation_bar.mutes": "tildyti naudotojai",
"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.personal": "Asmeninis",
"navigation_bar.pins": "Pinned toots",
"navigation_bar.pins": "Prisegti įrašai",
"navigation_bar.preferences": "Nuostatos",
"navigation_bar.public_timeline": "Federuota laiko juosta",
"navigation_bar.public_timeline": "Federacinė laiko skalė",
"navigation_bar.search": "Ieškoti",
"navigation_bar.security": "Apsauga",
"not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.",
"notification.admin.report": "{name} pranešė.{target}",
"not_signed_in_indicator.not_signed_in": "Norint pasiekti šį išteklį, reikia prisijungti.",
"notification.admin.report": "{name} pranešė {target}",
"notification.admin.sign_up": "{name} užsiregistravo",
"notification.favourite": "{name} pamėgo jūsų įrašą",
"notification.follow": "{name} pradėjo jus sekti",
"notification.follow_request": "{name} nori tapti jūsų sekėju",
"notification.mention": "{name} paminėjo jus",
"notification.favourite": "{name} pamėgo tavo įrašą",
"notification.follow": "{name} seka tave",
"notification.follow_request": "{name} paprašė tave sekti",
"notification.mention": "{name} paminėjo tave",
"notification.own_poll": "Tavo apklausa baigėsi",
"notification.poll": "Apklausa, kurioje balsavai, pasibaigė",
"notification.reblog": "{name} boosted your status",
"notification.reblog": "{name} pakėlė tavo įrašą",
"notification.status": "{name} ką tik paskelbė",
"notification.update": "{name} redagavo įrašą",
"notifications.clear": "Išvalyti pranešimus",
"notifications.clear_confirmation": "Ar tikrai nori visam laikui išvalyti visus pranešimus?",
"notifications.column_settings.admin.report": "Nauji ataskaitos:",
"notifications.column_settings.admin.sign_up": "Nauji prisiregistravimai:",
"notifications.column_settings.admin.report": "Naujos ataskaitos:",
"notifications.column_settings.admin.sign_up": "Naujos registracijos:",
"notifications.column_settings.alert": "Darbalaukio pranešimai",
"notifications.column_settings.favourite": "Mėgstamiausi:",
"notifications.column_settings.favourite": "Mėgstami:",
"notifications.column_settings.filter_bar.advanced": "Rodyti visas kategorijas",
"notifications.column_settings.filter_bar.category": "Greito filtro juosta",
"notifications.column_settings.filter_bar.category": "Spartaus filtro juosta",
"notifications.column_settings.filter_bar.show_bar": "Rodyti filtro juostą",
"notifications.column_settings.follow": "Nauji sekėjai:",
"notifications.column_settings.follow_request": "Nauji prašymai sekti:",
"notifications.column_settings.follow_request": "Nauji sekimo prašymai:",
"notifications.column_settings.mention": "Paminėjimai:",
"notifications.column_settings.poll": "Balsavimo rezultatai:",
"notifications.column_settings.push": "\"Push\" pranešimai",
"notifications.column_settings.push": "Stumdomieji pranešimai",
"notifications.column_settings.reblog": "Pakėlimai:",
"notifications.column_settings.show": "Rodyti stulpelyje",
"notifications.column_settings.sound": "Paleisti garsą",
"notifications.column_settings.status": "New toots:",
"notifications.column_settings.status": "Nauji įrašai:",
"notifications.column_settings.unread_notifications.category": "Neperskaityti pranešimai",
"notifications.column_settings.unread_notifications.highlight": "Paryškinti neperskaitytus pranešimus",
"notifications.column_settings.update": "Redagavimai:",
"notifications.filter.all": "Visi",
"notifications.filter.boosts": "\"Boost\" kiekis",
"notifications.filter.favourites": "Mėgstamiausi",
"notifications.filter.boosts": "Pakėlimai",
"notifications.filter.favourites": "Mėgstami",
"notifications.filter.follows": "Sekimai",
"notifications.filter.mentions": "Paminėjimai",
"notifications.filter.polls": "Balsavimo rezultatai",
"notifications.filter.statuses": "Atnaujinimai iš žmonių kuriuos sekate",
"notifications.filter.statuses": "Naujinimai iš žmonių, kuriuos seki",
"notifications.grant_permission": "Suteikti leidimą.",
"notifications.group": "{count} pranešimai",
"notifications.mark_as_read": "Pažymėti kiekvieną pranešimą kaip perskaitytą",
"notifications.permission_denied": "Darbalaukio pranešimai nepasiekiami dėl anksčiau atmestos naršyklės leidimų užklausos",
"notifications.permission_denied_alert": "Negalima įjungti darbalaukio pranešimų, nes prieš tai naršyklės leidimas buvo atmestas",
"notifications.permission_required": "Darbalaukio pranešimai nepasiekiami, nes nesuteiktas reikiamas leidimas.",
"notifications.permission_denied": "Darbalaukio pranešimai nepasiekiami dėl anksčiau atmestos naršyklės leidimų užklausos.",
"notifications.permission_denied_alert": "Negalima įjungti darbalaukio pranešimų, nes prieš tai naršyklės leidimas buvo atmestas.",
"notifications.permission_required": "Darbalaukio pranešimai nepasiekiami, nes nebuvo suteiktas reikiamas leidimas.",
"notifications_permission_banner.enable": "Įjungti darbalaukio pranešimus",
"notifications_permission_banner.how_to_control": "Jei norite gauti pranešimus, kai \"Mastodon\" nėra atidarytas, įjunkite darbalaukio pranešimus. Įjungę darbalaukio pranešimus, galite tiksliai valdyti, kokių tipų sąveikos generuoja darbalaukio pranešimus, naudodamiesi pirmiau esančiu mygtuku {icon}.",
"notifications_permission_banner.title": "Niekada nieko nepraleiskite",
"onboarding.action.back": "Gražinkite mane atgal",
"onboarding.actions.back": "Gražinkite mane atgal",
"onboarding.actions.go_to_explore": "See what's trending",
"onboarding.actions.go_to_home": "Go to your home feed",
"notifications_permission_banner.how_to_control": "Jei nori gauti pranešimus, kai Mastodon nėra atidarytas, įjunk darbalaukio pranešimus. Įjungęs (-usi) darbalaukio pranešimus, gali tiksliai valdyti, kokių tipų sąveikos generuoja darbalaukio pranešimus, naudojant pirmiau esančiu mygtuku {icon}.",
"notifications_permission_banner.title": "Niekada nieko nepraleisk",
"onboarding.action.back": "Grąžinti mane atgal",
"onboarding.actions.back": "Grąžinti mane atgal",
"onboarding.actions.go_to_explore": "Į tendencijų puslapį",
"onboarding.actions.go_to_home": "Į mano pagrindinį srautų puslapį",
"onboarding.compose.template": "Sveiki #Mastodon!",
"onboarding.follows.empty": "Deja, šiuo metu jokių rezultatų parodyti negalima. Galite pabandyti naudoti paiešką arba naršyti atradimo puslapyje, kad surastumėte žmonių, kuriuos norite sekti, arba pabandyti vėliau.",
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
"onboarding.follows.title": "Popular on Mastodon",
"onboarding.follows.empty": "Deja, šiuo metu jokių rezultatų parodyti negalima. Gali pabandyti naudoti paiešką arba naršyti atradimo puslapį, kad surastum žmonių, kuriuos nori sekti, arba bandyti vėliau.",
"onboarding.follows.lead": "Tavo pagrindinis srautas pagrindinis būdas patirti Mastodon. Kuo daugiau žmonių seksi, tuo jis bus aktyvesnis ir įdomesnis. Norint pradėti, pateikiame keletą pasiūlymų:",
"onboarding.follows.title": "Suasmenink savo pagrindinį srautą",
"onboarding.profile.discoverable": "Padaryti mano profilį atrandamą",
"onboarding.profile.discoverable_hint": "Kai pasirenki Mastodon atrandamumą, tavo įrašai gali būti rodomi paieškos rezultatuose ir trendose, o profilis gali būti siūlomas panašių interesų turintiems žmonėms.",
"onboarding.profile.discoverable_hint": "Kai pasirenki Mastodon atrandamumą, tavo įrašai gali būti rodomi paieškos rezultatuose ir tendencijose, o profilis gali būti siūlomas panašių pomėgių turintiems žmonėms.",
"onboarding.profile.display_name": "Rodomas vardas",
"onboarding.profile.display_name_hint": "Tavo pilnas vardas arba linksmas vardas…",
"onboarding.profile.lead": "Gali visada tai užbaigti vėliau nustatymuose, kur yra dar daugiau pritaikymo parinkčių.",
"onboarding.profile.note": "Biografija",
"onboarding.profile.note_hint": "Gali @paminėti kitus žmones arba #saitažodžius…",
"onboarding.profile.save_and_continue": "Išsaugoti ir tęsti",
"onboarding.profile.title": "Profilio konfigūravimas",
"onboarding.profile.title": "Profilio sąranka",
"onboarding.profile.upload_avatar": "Įkelti profilio nuotrauką",
"onboarding.profile.upload_header": "Įkelti profilio antraštę",
"onboarding.share.lead": "Praneškite žmonėms, kaip jus rasti \"Mastodon\"!",
"onboarding.share.message": "Aš {username} #Mastodon! Ateik sekti manęs adresu {url}",
"onboarding.share.lead": "Leisk žmonėms sužinoti, kaip tave rasti Mastodon!",
"onboarding.share.message": "Aš {username}, esant #Mastodon! Ateik sekti manęs adresu {url}.",
"onboarding.share.next_steps": "Galimi kiti žingsniai:",
"onboarding.share.title": "Bendrinkite savo profilį",
"onboarding.start.lead": "Dabar esi Mastodon dalis unikalios decentralizuotos socialinės žiniasklaidos platformos, kurioje tu, o ne algoritmas, pats nustatai savo patirtį. Pradėkime tavo kelionę šioje naujoje socialinėje erdvėje:",
"onboarding.start.skip": "Want to skip right ahead?",
"onboarding.start.title": "Jums pavyko!",
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
"onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}",
"onboarding.steps.publish_status.body": "Say hello to the world.",
"onboarding.steps.publish_status.title": "Susikūrk savo pirmąjį įrašą",
"onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.",
"onboarding.steps.setup_profile.title": "Customize your profile",
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!",
"onboarding.steps.share_profile.title": "Share your profile",
"picture_in_picture.restore": "Padėkite jį atgal",
"poll.closed": "Uždaryti",
"onboarding.share.title": "Bendrink savo profilį",
"onboarding.start.lead": "Dabar esi Mastodon dalis unikalios decentralizuotos socialinės medijos platformos, kurioje tu, o ne algoritmas, pats nustatai savo patirtį. Pradėkime tavo kelionę šioje naujoje socialinėje erdvėje:",
"onboarding.start.skip": "Nereikia pagalbos pradėti?",
"onboarding.start.title": "Tau pavyko!",
"onboarding.steps.follow_people.body": "Sekti įdomius žmones tai, kas yra Mastodon.",
"onboarding.steps.follow_people.title": "Suasmenink savo pagrindinį srautą",
"onboarding.steps.publish_status.body": "Sakyk labas pasauliui tekstu, nuotraukomis, vaizdo įrašais arba apklausomis {emoji}.",
"onboarding.steps.publish_status.title": "Sukūrk savo pirmąjį įrašą",
"onboarding.steps.setup_profile.body": "Padidink savo sąveiką turint išsamų profilį.",
"onboarding.steps.setup_profile.title": "Suasmenink savo profilį",
"onboarding.steps.share_profile.body": "Leisk draugams sužinoti, kaip tave rasti Mastodon.",
"onboarding.steps.share_profile.title": "Bendrink savo Mastodon profilį",
"onboarding.tips.2fa": "<strong>Ar žinojai?</strong> Savo paskyrą gali apsaugoti nustatęs (-usi) dviejų veiksnių tapatybės nustatymą paskyros nustatymuose. Jis veikia su bet kuria pasirinkta TOTP programėle, telefono numeris nebūtinas.",
"onboarding.tips.accounts_from_other_servers": "<strong>Ar žinojai?</strong> Kadangi Mastodon decentralizuotas, kai kurie profiliai, su kuriais susidursi, bus talpinami ne tavo, o kituose serveriuose. Ir vis tiek galėsi su jais sklandžiai bendrauti! Jų serveris yra antroje naudotojo vardo pusėje.",
"onboarding.tips.migration": "<strong>Ar žinojai?</strong> Jei manai, kad {domain} serveris ateityje tau netiks, gali persikelti į kitą Mastodon serverį neprarandant savo sekėjų. Gali net talpinti savo paties serverį.",
"onboarding.tips.verification": "<strong>Ar žinojai?</strong> Savo paskyrą gali patvirtinti pateikęs (-usi) nuorodą į Mastodon profilį savo interneto svetainėje ir pridėjęs (-usi) svetainę prie savo profilio. Nereikia jokių mokesčių ar dokumentų.",
"password_confirmation.exceeds_maxlength": "Slaptažodžio patvirtinimas viršija maksimalų slaptažodžio ilgį.",
"password_confirmation.mismatching": "Slaptažodžio patvirtinimas nesutampa.",
"picture_in_picture.restore": "Padėti jį atgal",
"poll.closed": "Uždaryta",
"poll.refresh": "Atnaujinti",
"poll.reveal": "Peržiūrėti rezultatus",
"poll.total_people": "{count, plural, one {# žmogus} few {# žmonės} many {# žmogus} other {# žmonių}}",
"poll.total_votes": "{count, plural, one {# balsas} few {# balsai} many {# balso} other {# balsų}}",
"poll.vote": "Balsuoti",
"poll.voted": "Tu balsavai už šį atsakymą",
"poll.votes": "{votes, plural, one {# balsas} few {# balsai} many {# balso} other {# balsų}}",
"poll_button.add_poll": "Pridėti apklausą",
"poll_button.remove_poll": "Šalinti apklausą",
"privacy.change": "Adjust status privacy",
"poll_button.remove_poll": "Pašalinti apklausą",
"privacy.change": "Keisti įrašo privatumą",
"privacy.direct.long": "Visus, paminėtus įraše",
"privacy.direct.short": "Konkretūs žmonės",
"privacy.private.long": "Tik sekėjams",
"privacy.private.short": "Sekėjai",
"privacy.public.long": "Bet kas iš Mastodon ir ne Mastodon",
"privacy.public.short": "Viešas",
"privacy.public.short": "Vieša",
"privacy.unlisted.additional": "Tai veikia lygiai taip pat, kaip ir vieša, tik įrašas nebus rodomas tiesioginiuose srautuose, saitažodžiose, naršyme ar Mastodon paieškoje, net jei esi įtraukęs (-usi) visą paskyrą.",
"privacy.unlisted.long": "Mažiau algoritminių fanfarų",
"privacy.unlisted.short": "Tyliai vieša",
@ -504,8 +542,14 @@
"privacy_policy.title": "Privatumo politika",
"recommended": "Rekomenduojama",
"refresh": "Atnaujinti",
"regeneration_indicator.label": "Kraunasi…",
"regeneration_indicator.label": "Kraunama…",
"regeneration_indicator.sublabel": "Ruošiamas tavo pagrindinis srautas!",
"relative_time.days": "{number} d.",
"relative_time.full.days": "prieš {number, plural, one {# dieną} few {# dienas} many {# dienos} other {# dienų}}",
"relative_time.full.hours": "prieš {number, plural, one {# valandą} few {# valandas} many {# valandos} other {# valandų}}",
"relative_time.full.just_now": "ką tik",
"relative_time.full.minutes": "prieš {number, plural, one {# minutę} few {# minutes} many {# minutės} other {# minučių}}",
"relative_time.full.seconds": "prieš {number, plural, one {# sekundę} few {# sekundes} many {# sekundės} other {# sekundžių}}",
"relative_time.hours": "{number} val.",
"relative_time.just_now": "dabar",
"relative_time.minutes": "{number} min.",
@ -515,15 +559,20 @@
"reply_indicator.cancel": "Atšaukti",
"reply_indicator.poll": "Apklausa",
"report.block": "Blokuoti",
"report.categories.legal": "Legalus",
"report.block_explanation": "Jų įrašų nematysi. Jie negalės matyti tavo įrašų ar sekti tavęs. Jie galės pamatyti, kad yra užblokuoti.",
"report.categories.legal": "Teisinės",
"report.categories.other": "Kita",
"report.categories.spam": "Šlamštas",
"report.categories.violation": "Turinys pažeidžia vieną ar daugiau serverio taisyklių",
"report.category.subtitle": "Pasirinkite tinkamiausią variantą",
"report.category.subtitle": "Pasirink geriausią atitikmenį.",
"report.category.title": "Papasakok mums, kas vyksta su šiuo {type}",
"report.category.title_account": "profilis",
"report.category.title_status": "įrašas",
"report.close": "Atlikta",
"report.comment.title": "Ar yra dar kas nors, ką, jūsų manymu, turėtume žinoti?",
"report.comment.title": "Ar yra dar kas nors, ką, tavo manymu, turėtume žinoti?",
"report.forward": "Persiųsti į {target}",
"report.forward_hint": "Paskyra yra iš kito serverio. Siųsti anoniminę šios ataskaitos kopiją ir ten?",
"report.mute": "Nutildyti",
"report.mute_explanation": "Jų įrašų nematysi. Jie vis tiek gali tave sekti ir matyti įrašus, bet nežinos, kad jie nutildyti.",
"report.next": "Tęsti",
"report.placeholder": "Papildomi komentarai",
@ -532,41 +581,42 @@
"report.reasons.legal": "Tai nelegalu",
"report.reasons.legal_description": "Manai, kad tai pažeidžia tavo arba serverio šalies įstatymus",
"report.reasons.other": "Tai kažkas kita",
"report.reasons.other_description": "Šis klausimas neatitinka kitų kategorijų",
"report.reasons.other_description": "Problema netinka kitoms kategorijoms",
"report.reasons.spam": "Tai šlamštas",
"report.reasons.spam_description": "Kenkėjiškos nuorodos, netikras įsitraukimas arba pasikartojantys atsakymai",
"report.reasons.violation": "Tai pažeidžia serverio taisykles",
"report.reasons.violation_description": "Žinai, kad tai pažeidžia konkrečias taisykles",
"report.rules.subtitle": "Pasirink viską, kas tinka",
"report.rules.subtitle": "Pasirink viską, kas tinka.",
"report.rules.title": "Kokios taisyklės pažeidžiamos?",
"report.statuses.subtitle": "Pasirinkti viską, kas tinka",
"report.statuses.title": "Ar yra kokių nors įrašų, patvirtinančių šį pranešimą?",
"report.statuses.subtitle": "Pasirink viską, kas tinka.",
"report.statuses.title": "Ar yra kokių nors įrašų, patvirtinančių šį ataskaitą?",
"report.submit": "Pateikti",
"report.target": "Report {target}",
"report.thanks.take_action": "Čia pateikiamos galimybės kontroliuoti, ką matote \"Mastodon\":",
"report.thanks.take_action_actionable": "Kol tai peržiūrėsime, galite imtis veiksmų prieš @{name}:",
"report.thanks.title": "Nenorite to matyti?",
"report.thanks.title_actionable": "Ačiū, kad pranešėte, mes tai išnagrinėsime.",
"report.target": "Pranešama apie {target}",
"report.thanks.take_action": "Štai parinktys, kaip kontroliuoti, ką matai Mastodon:",
"report.thanks.take_action_actionable": "Kol peržiūrėsime, gali imtis veiksmų prieš {name}:",
"report.thanks.title": "Nenori to matyti?",
"report.thanks.title_actionable": "Ačiū, kad pranešei, mes tai išnagrinėsime.",
"report.unfollow": "Nebesekti @{name}",
"report.unfollow_explanation": "Jūs sekate šią paskyrą. Norėdami nebematyti jų įrašų savo pagrindiniame kanale, panaikinkite jų sekimą.",
"report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached",
"report_notification.categories.legal": "Legalus",
"report.unfollow_explanation": "Tu seki šią paskyrą. Jei nori nebematyti jų įrašų savo pagrindiniame sraute, nebesek jų.",
"report_notification.attached_statuses": "Pridėti {count, plural, one {{count} įrašas} few {{count} įrašai} many {{count} įrašo} other {{count} įrašų}}",
"report_notification.categories.legal": "Teisinės",
"report_notification.categories.other": "Kita",
"report_notification.categories.spam": "Šlamštas",
"report_notification.categories.violation": "Taisyklės pažeidimas",
"search.no_recent_searches": "Paieškos įrašų nėra",
"report_notification.open": "Atidaryti ataskaitą",
"search.no_recent_searches": "Nėra naujausių paieškų.",
"search.placeholder": "Paieška",
"search.quick_action.account_search": "Profiliai, atitinkantys {x}",
"search.quick_action.go_to_account": "Eiti į profilį {x}",
"search.quick_action.go_to_hashtag": "Eiti į hashtag {x}",
"search.quick_action.go_to_hashtag": "Eiti į saitažodį {x}",
"search.quick_action.open_url": "Atidaryti URL adresą Mastodon",
"search.quick_action.status_search": "Pranešimai, atitinkantys {x}",
"search.search_or_paste": "Ieškok arba įklijuok URL",
"search.search_or_paste": "Ieškoti arba įklijuoti URL",
"search_popout.full_text_search_disabled_message": "Nepasiekima {domain}.",
"search_popout.full_text_search_logged_out_message": "Pasiekiama tik prisijungus.",
"search_popout.language_code": "ISO kalbos kodas",
"search_popout.options": "Paieškos nustatymai",
"search_popout.quick_actions": "Greiti veiksmai",
"search_popout.quick_actions": "Spartūs veiksmai",
"search_popout.recent": "Naujausios paieškos",
"search_popout.specific_date": "konkreti data",
"search_popout.user": "naudotojas",
@ -575,23 +625,25 @@
"search_results.hashtags": "Saitažodžiai",
"search_results.nothing_found": "Nepavyko rasti nieko pagal šiuos paieškos terminus.",
"search_results.see_all": "Žiūrėti viską",
"search_results.statuses": "Toots",
"search_results.statuses": "Įrašai",
"search_results.title": "Ieškoti {q}",
"server_banner.about_active_users": "Žmonės, kurie naudojosi šiuo serveriu per pastarąsias 30 dienų (mėnesio aktyvūs naudotojai)",
"server_banner.active_users": "aktyvūs naudotojai",
"server_banner.administered_by": "Administruoja:",
"server_banner.introduction": "{domain} yra decentralizuoto socialinio tinklo, kurį valdo {mastodon}, dalis.",
"server_banner.introduction": "{domain} decentralizuoto socialinio tinklo dalis, kurį palaiko {mastodon}.",
"server_banner.learn_more": "Sužinoti daugiau",
"server_banner.server_stats": "Serverio statistika:",
"sign_in_banner.create_account": "Sukurti paskyrą",
"sign_in_banner.sign_in": "Prisijungimas",
"sign_in_banner.sso_redirect": "Prisijungti arba Registruotis",
"sign_in_banner.sso_redirect": "Prisijungti arba užsiregistruoti",
"sign_in_banner.text": "Prisijunk, kad galėtum sekti profilius arba saitažodžius, mėgsti, bendrinti ir atsakyti į įrašus. Taip pat gali bendrauti iš savo paskyros kitame serveryje.",
"status.admin_account": "Atvira moderavimo sąsaja @{name}",
"status.admin_domain": "Atvira moderavimo sąsaja {domain}",
"status.admin_status": "Open this status in the moderation interface",
"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.block": "Blokuoti @{name}",
"status.bookmark": "Žymė",
"status.bookmark": "Pridėti į žymės",
"status.cancel_reblog_private": "Nebepakelti",
"status.cannot_reblog": "Šis įrašas negali būti pakeltas.",
"status.copy": "Kopijuoti nuorodą į įrašą",
"status.delete": "Ištrinti",
"status.detailed_status": "Išsami pokalbio peržiūra",
@ -599,15 +651,15 @@
"status.direct_indicator": "Privatus paminėjimas",
"status.edit": "Redaguoti",
"status.edited": "Redaguota {date}",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
"status.embed": "Įterptas",
"status.favourite": "Mėgstamiausias",
"status.edited_x_times": "Redaguota {count, plural, one {{count} kartą} few {{count} kartus} many {{count} karto} other {{count} kartų}}",
"status.embed": "Įterpti",
"status.favourite": "Pamėgti",
"status.filter": "Filtruoti šį įrašą",
"status.filtered": "Filtruota",
"status.hide": "Slėpti įrašą",
"status.history.created": "{name} sukurtas {date}",
"status.history.edited": "{name} redaguotas {date}",
"status.load_more": "Pakrauti daugiau",
"status.history.created": "{name} sukurta {date}",
"status.history.edited": "{name} redaguota {date}",
"status.load_more": "Krauti daugiau",
"status.media.open": "Spausk, kad atidaryti",
"status.media.show": "Spausk, kad matyti",
"status.media_hidden": "Paslėpta medija",
@ -615,15 +667,20 @@
"status.more": "Daugiau",
"status.mute": "Nutildyti @{name}",
"status.mute_conversation": "Nutildyti pokalbį",
"status.open": "Expand this status",
"status.open": "Išplėsti šį įrašą",
"status.pin": "Prisegti prie profilio",
"status.pinned": "Prisegtas įrašas",
"status.read_more": "Skaityti daugiau",
"status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
"status.redraft": "Ištrinti ir iš naujo parengti juodraštį",
"status.reblog": "Pakelti",
"status.reblog_private": "Pakelti su originaliu matomumu",
"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.replied_to": "Atsakyta į {name}",
"status.reply": "Atsakyti",
"status.replyAll": "Atsakyti į giją",
"status.report": "Pranešti @{name}",
"status.report": "Pranešti apie @{name}",
"status.sensitive_warning": "Jautrus turinys",
"status.share": "Bendrinti",
"status.show_filter_reason": "Rodyti vis tiek",
@ -632,37 +689,62 @@
"status.show_more": "Rodyti daugiau",
"status.show_more_all": "Rodyti daugiau visiems",
"status.show_original": "Rodyti originalą",
"status.title.with_attachments": "{user}{attachmentCount, plural, one {priedas} few {{attachmentCount} priedai} many {{attachmentCount} priedo} other {{attachmentCount} priedų}}",
"status.title.with_attachments": "{user} paskelbė {attachmentCount, plural, one {priedą} few {{attachmentCount} priedus} many {{attachmentCount} priedo} other {{attachmentCount} priedų}}",
"status.translate": "Versti",
"status.translated_from_with": "Išversta iš {lang} naudojant {provider}",
"status.uncached_media_warning": "Peržiūra nepasiekiama",
"subscribed_languages.lead": "Po pakeitimo tavo pagrindinėje ir sąrašo laiko juostose bus rodomi tik įrašai pasirinktomis kalbomis. Jei nori gauti įrašus visomis kalbomis, pasirink nė vieno.",
"tabs_bar.home": "Pradžia",
"status.translated_from_with": "Išversta iš {lang} naudojant {provider}.",
"status.uncached_media_warning": "Peržiūra nepasiekiama.",
"status.unmute_conversation": "Atšaukti pokalbio nutildymą",
"status.unpin": "Atsegti iš profilio",
"subscribed_languages.lead": "Po pakeitimo tavo pagrindinėje ir sąrašo laiko skalėje bus rodomi tik įrašai pasirinktomis kalbomis. Jei nori gauti įrašus visomis kalbomis, pasirink nė vieno.",
"subscribed_languages.save": "Išsaugoti pakeitimus",
"subscribed_languages.target": "Keisti prenumeruojamas kalbas {target}",
"tabs_bar.home": "Pagrindinis",
"tabs_bar.notifications": "Pranešimai",
"time_remaining.days": "Liko {number, plural, one {# diena} few {# dienos} many {# dieno} other {# dienų}}",
"timeline_hint.remote_resource_not_displayed": "{resource} iš kitų serverių nerodomas.",
"time_remaining.days": "liko {number, plural, one {# diena} few {# dienos} many {# dienos} other {# dienų}}",
"time_remaining.hours": "liko {number, plural, one {# valanda} few {# valandos} many {# valandos} other {# valandų}}",
"time_remaining.minutes": "liko {number, plural, one {# minutė} few {# minutės} many {# minutės} other {# minučių}}",
"time_remaining.moments": "liko akimirkos",
"time_remaining.seconds": "liko {number, plural, one {# sekundė} few {# sekundės} many {# sekundės} other {# sekundžių}}",
"timeline_hint.remote_resource_not_displayed": "{resource} iš kitų serverių nerodomi.",
"timeline_hint.resources.followers": "Sekėjai",
"timeline_hint.resources.follows": "Seka",
"timeline_hint.resources.statuses": "Senesni įrašai",
"trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} in the past {days, plural, one {day} other {# days}}",
"trends.counter_by_accounts": "{count, plural, one {{counter} žmogus} few {{counter} žmonės} many {{counter} žmogus} other {{counter} žmonių}} per {days, plural, one {dieną} few {{days} dienas} many {{days} dienas} other {{days} dienų}}",
"trends.trending_now": "Tendencinga dabar",
"ui.beforeunload": "Jei paliksi Mastodon, tavo juodraštis bus prarastas.",
"units.short.billion": "{count} mlrd.",
"units.short.million": "{count} mln.",
"units.short.thousand": "{count} tūkst.",
"upload_form.audio_description": "Describe for people with hearing loss",
"upload_form.description": "Describe for the visually impaired",
"upload_area.title": "Nuvilk, kad įkeltum",
"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_form.audio_description": "Aprašyk žmonėms, kurie yra kurtieji ar neprigirdintys.",
"upload_form.description": "Aprašyk žmonėms, kurie yra aklieji arba silpnaregiai.",
"upload_form.edit": "Redaguoti",
"upload_form.video_description": "Describe for people with hearing loss or visual impairment",
"upload_form.thumbnail": "Keisti miniatiūrą",
"upload_form.video_description": "Aprašyk žmonėms, kurie yra kurtieji, neprigirdintys, aklieji ar silpnaregiai.",
"upload_modal.analyzing_picture": "Analizuojamas vaizdas…",
"upload_modal.apply": "Taikyti",
"upload_modal.applying": "Pritaikoma…",
"upload_modal.choose_image": "Pasirinkti vaizdą",
"upload_modal.description_placeholder": "Greita rudoji lapė peršoka tinginį šunį",
"upload_modal.detect_text": "Aptikti tekstą iš nuotraukos",
"upload_modal.edit_media": "Redaguoti mediją",
"upload_modal.hint": "Spustelėk arba nuvilk apskritimą peržiūroje, kad pasirinktum centrinį tašką, kuris visada bus matomas visose miniatiūrose.",
"upload_modal.preparing_ocr": "Rengimas OCR…",
"upload_modal.preview_label": "Peržiūra ({ratio})",
"upload_progress.label": "Įkeliama...",
"upload_progress.processing": "Apdorojama…",
"username.taken": "Šis naudotojo vardas užimtas. Pabandyk kitą.",
"video.close": "Uždaryti vaizdo įrašą",
"video.download": "Atsisiųsti failą",
"video.exit_fullscreen": "Išeiti iš viso ekrano",
"video.expand": "Išplėsti vaizdo įrašą",
"video.fullscreen": "Visas ekranas",
"video.hide": "Slėpti vaizdo įrašą",
"video.mute": "Nutildyti garsą",
"video.mute": "Išjungti garsą",
"video.pause": "Pristabdyti",
"video.play": "Leisti",
"video.unmute": "Atitildyti garsą"
"video.unmute": "Įjungti garsą"
}

View File

@ -21,24 +21,26 @@
"account.blocked": "Bloķēts",
"account.browse_more_on_origin_server": "Pārlūkot vairāk sākotnējā profilā",
"account.cancel_follow_request": "Atsaukt sekošanas pieprasījumu",
"account.copy": "Ievietot saiti uz profilu starpliktuvē",
"account.direct": "Pieminēt @{name} privāti",
"account.disable_notifications": "Pārtraukt man paziņot, kad @{name} publicē ierakstu",
"account.domain_blocked": "Domēns ir bloķēts",
"account.edit_profile": "Rediģēt profilu",
"account.edit_profile": "Labot profilu",
"account.enable_notifications": "Paziņot man, kad @{name} publicē ierakstu",
"account.endorse": "Izcelts profilā",
"account.featured_tags.last_status_at": "Beidzamā ziņa {date}",
"account.featured_tags.last_status_never": "Ierakstu nav",
"account.featured_tags.title": "{name} izceltie tēmturi",
"account.follow": "Sekot",
"account.follow_back": "Sekot atpakaļ",
"account.followers": "Sekotāji",
"account.followers.empty": "Šim lietotājam vēl nav sekotāju.",
"account.followers_counter": "{count, plural, one {{counter} Sekotājs} other {{counter} Sekotāji}}",
"account.followers_counter": "{count, plural, zero {{counter} sekotāju} one {{counter} sekotājs} other {{counter} sekotāji}}",
"account.following": "Seko",
"account.following_counter": "{count, plural, one {{counter} sekojamais} other {{counter} sekojamie}}",
"account.following_counter": "{count, plural, zero{{counter} sekojamo} one {{counter} sekojamais} other {{counter} sekojamie}}",
"account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.",
"account.go_to_profile": "Doties uz profilu",
"account.hide_reblogs": "Slēpt @{name} izceltas ziņas",
"account.hide_reblogs": "Paslēpt @{name} pastiprinātos ierakstus",
"account.in_memoriam": "Piemiņai.",
"account.joined_short": "Pievienojās",
"account.languages": "Mainīt abonētās valodas",
@ -51,13 +53,14 @@
"account.mute_notifications_short": "Izslēgt paziņojumu skaņu",
"account.mute_short": "Apklusināt",
"account.muted": "Apklusināts",
"account.mutual": "Savstarpējs",
"account.no_bio": "Apraksts nav sniegts.",
"account.open_original_page": "Atvērt oriģinālo lapu",
"account.posts": "Ieraksti",
"account.posts_with_replies": "Ieraksti un atbildes",
"account.report": "Sūdzēties par @{name}",
"account.requested": "Gaida apstiprinājumu. Nospied, lai atceltu sekošanas pieparasījumu",
"account.requested_follow": "{name} nosūtīja tev sekošanas pieprasījumu",
"account.requested_follow": "{name} nosūtīja Tev sekošanas pieprasījumu",
"account.share": "Dalīties ar @{name} profilu",
"account.show_reblogs": "Parādīt @{name} pastiprinātos ierakstus",
"account.statuses_counter": "{count, plural, zero {{counter} ierakstu} one {{counter} ieraksts} other {{counter} ieraksti}}",
@ -97,18 +100,18 @@
"bundle_column_error.routing.body": "Pieprasīto lapu nevarēja atrast. Vai esi pārliecināts, ka URL adreses joslā ir pareizs?",
"bundle_column_error.routing.title": "404",
"bundle_modal_error.close": "Aizvērt",
"bundle_modal_error.message": "Kaut kas nogāja greizi, ielādējot šo komponenti.",
"bundle_modal_error.message": "Kaut kas nogāja greizi šīs sastāvdaļas ielādēšanas laikā.",
"bundle_modal_error.retry": "Mēģināt vēlreiz",
"closed_registrations.other_server_instructions": "Tā kā Mastodon ir decentralizēts, tu vari izveidot kontu citā serverī un joprojām mijiedarboties ar šo.",
"closed_registrations_modal.description": "Pašlaik nav iespējams izveidot kontu domēnā {domain}, taču ņem vērā, ka tev nav nepieciešams konts tieši {domain}, lai lietotu Mastodon.",
"closed_registrations_modal.description": "Pašlaik nav iespējams izveidot kontu {domain}, bet, lūdzu, ņem vērā, ka Tev nav nepieciešams tieši {domain} konts, lai lietotu Mastodon!",
"closed_registrations_modal.find_another_server": "Atrast citu serveri",
"closed_registrations_modal.preamble": "Mastodon ir decentralizēts, tāpēc neatkarīgi no tā, kur tu izveido savu kontu, varēsi sekot līdzi un sazināties ar ikvienu šajā serverī. Tu pat vari vadīt to pats!",
"closed_registrations_modal.preamble": "Mastodon ir decentralizēts, tāpēc neatkarīgi no tā, kur Tu izveido savu kontu, varēsi sekot un mijiedarboties ar ikvienu šajā serverī. Tu pat vari to pašizvietot!",
"closed_registrations_modal.title": "Reģistrēšanās Mastodon",
"column.about": "Par",
"column.blocks": "Bloķētie lietotāji",
"column.bookmarks": "Grāmatzīmes",
"column.community": "Vietējā laika līnija",
"column.direct": "Privāti pieminēti",
"column.direct": "Privātas pieminēšanas",
"column.directory": "Pārlūkot profilus",
"column.domain_blocks": "Bloķētie domēni",
"column.favourites": "Iecienītie",
@ -133,21 +136,28 @@
"community.column_settings.remote_only": "Tikai attālinātie",
"compose.language.change": "Mainīt valodu",
"compose.language.search": "Meklēt valodas...",
"compose.published.body": "Ziņa publicēta.",
"compose.published.body": "Ieraksts publicēta.",
"compose.published.open": "Atvērt",
"compose.saved.body": "Ziņa saglabāta.",
"compose_form.direct_message_warning_learn_more": "Uzzināt vairāk",
"compose_form.encryption_warning": "Ziņas vietnē Mastodon nav pilnībā šifrētas. Nedalies ar sensitīvu informāciju caur Mastodon.",
"compose_form.encryption_warning": "Mastodon ieraksti nav pilnībā šifrēti. Nedalies ar jebkādu jutīgu informāciju caur Mastodon!",
"compose_form.hashtag_warning": "Šī ziņa netiks norādīta zem nevienas atsauces, jo tā nav publiska. Tikai publiskās ziņās var meklēt pēc atsauces.",
"compose_form.lock_disclaimer": "Tavs konts nav {locked}. Ikviens var tev piesekot un redzēt tikai sekotājiem paredzētos ziņojumus.",
"compose_form.lock_disclaimer": "Tavs konts nav {locked}. Ikviens var Tev sekot, lai redzētu tikai sekotājiem paredzētos ierakstus.",
"compose_form.lock_disclaimer.lock": "slēgts",
"compose_form.placeholder": "Kas tev padomā?",
"compose_form.placeholder": "Kas Tev padomā?",
"compose_form.poll.duration": "Aptaujas ilgums",
"compose_form.poll.multiple": "Vairākas izvēles iespējas",
"compose_form.poll.option_placeholder": "Izvēle {number}",
"compose_form.poll.single": "Jāizvēlas viens",
"compose_form.poll.switch_to_multiple": "Mainīt aptaujas veidu, lai atļautu vairākas izvēles",
"compose_form.poll.switch_to_single": "Mainīt aptaujas veidu, lai atļautu vienu izvēli",
"compose_form.publish": "Iesūtīt",
"compose_form.publish_form": "Jauns ieraksts",
"compose_form.reply": "Atbildēt",
"compose_form.save_changes": "Atjaunināt",
"compose_form.spoiler.marked": "Noņemt satura brīdinājumu",
"compose_form.spoiler.unmarked": "Pievienot satura brīdinājumu",
"compose_form.spoiler_placeholder": "Satura brīdinājums (pēc izvēles)",
"confirmation_modal.cancel": "Atcelt",
"confirmations.block.block_and_report": "Bloķēt un ziņot",
"confirmations.block.confirm": "Bloķēt",
@ -157,28 +167,29 @@
"confirmations.delete.confirm": "Dzēst",
"confirmations.delete.message": "Vai tiešām vēlies dzēst šo ierakstu?",
"confirmations.delete_list.confirm": "Dzēst",
"confirmations.delete_list.message": "Vai tiešam vēlies neatgriezeniski dzēst šo sarakstu?",
"confirmations.delete_list.message": "Vai tiešām neatgriezeniski izdzēst šo sarakstu?",
"confirmations.discard_edit_media.confirm": "Atmest",
"confirmations.discard_edit_media.message": "Tev ir nesaglabātas izmaiņas multivides aprakstā vai priekšskatījumā. Vēlies tās atmest?",
"confirmations.discard_edit_media.message": "Ir nesaglabātas izmaiņas informācijas nesēja aprakstā vai priekšskatījumā. Vēlies tās atmest tik un tā?",
"confirmations.domain_block.confirm": "Bloķēt visu domēnu",
"confirmations.domain_block.message": "Vai tu tiešām vēlies bloķēt visu domēnu {domain}? Parasti pietiek, ja nobloķē vai apklusini kādu. Tu neredzēsi saturu vai paziņojumus no šī domēna nevienā laika līnijā. Tavi sekotāji no šī domēna tiks noņemti.",
"confirmations.edit.confirm": "Rediģēt",
"confirmations.edit.confirm": "Labot",
"confirmations.edit.message": "Rediģējot, tiks pārrakstīts ziņojums, kuru tu šobrīd raksti. Vai tiešām vēlies turpināt?",
"confirmations.logout.confirm": "Iziet",
"confirmations.logout.message": "Vai tiešām vēlies izrakstīties?",
"confirmations.mute.confirm": "Apklusināt",
"confirmations.mute.explanation": "Šādi no viņiem tiks slēptas ziņas un ziņas, kurās viņi tiek pieminēti, taču viņi joprojām varēs redzēt tavas ziņas un sekot tev.",
"confirmations.mute.explanation": "Šādi tiks slēpti ieraksti no viņiem un ieraksti, kuros viņi tiek pieminēti, taču viņi joprojām varēs redzēt Tavus ierakstus un sekot Tev.",
"confirmations.mute.message": "Vai tiešām vēlies apklusināt {name}?",
"confirmations.redraft.confirm": "Dzēst un pārrakstīt",
"confirmations.redraft.message": "Vai tiešām vēlies dzēst šo ziņu un no jauna noformēt to? Izlase un pastiprinājumi tiks zaudēti, un atbildes uz sākotnējo ziņu tiks atstātas bez autoratlīdzības.",
"confirmations.reply.confirm": "Atbildēt",
"confirmations.reply.message": "Ja tagad atbildēsi, tavs ziņas uzmetums tiks dzēsts. Vai tiešām vēlies turpināt?",
"confirmations.reply.message": "Tūlītēja atbildēšana pārrakstīs pašlaik sastādīto ziņu. Vai tiešām turpināt?",
"confirmations.unfollow.confirm": "Pārstāt sekot",
"confirmations.unfollow.message": "Vai tiešam vairs nevēlies sekot lietotājam {name}?",
"conversation.delete": "Dzēst sarunu",
"conversation.mark_as_read": "Atzīmēt kā izlasītu",
"conversation.open": "Skatīt sarunu",
"conversation.with": "Ar {names}",
"copy_icon_button.copied": "Ievietots starpliktuvē",
"copypaste.copied": "Nokopēts",
"copypaste.copy_to_clipboard": "Kopēt uz starpliktuvi",
"directory.federated": "No pazīstamas federācijas",
@ -187,12 +198,12 @@
"directory.recently_active": "Nesen aktīvie",
"disabled_account_banner.account_settings": "Konta iestatījumi",
"disabled_account_banner.text": "Tavs konts {disabledAccount} pašlaik ir atspējots.",
"dismissable_banner.community_timeline": īs ir jaunākās publiskās ziņas no personām, kuru kontus mitina {domain}.",
"dismissable_banner.community_timeline": ie ir jaunākie publiskie ieraksti no cilvēkiem, kuru konti ir mitināti {domain}.",
"dismissable_banner.dismiss": "Atcelt",
"dismissable_banner.explore_links": "Par šiem jaunumiem šobrīd runā cilvēki šajā un citos decentralizētā tīkla serveros.",
"dismissable_banner.explore_statuses": "Ieraksti, kas šobrīd gūst arvien lielāku ievērību visā sociālajā tīklā. Augstāk tiek kārtoti neseni ieraksti, kas pastiprināti un pievienoti izlasēm.",
"dismissable_banner.explore_statuses": "Šie ir ieraksti, kas šodien gūst arvien lielāku ievērību visā sociālajā tīklā. Augstāk tiek kārtoti jaunāki ieraksti, kuri tiek vairāk pastiprināti un ievietoti izlasēs.",
"dismissable_banner.explore_tags": "Šie tēmturi šobrīd kļūst arvien populārāki cilvēku vidū šajā un citos decentralizētā tīkla serveros.",
"dismissable_banner.public_timeline": īs ir jaunākās publiskās ziņas no lietotājiem sociālajā tīmeklī, kurām seko lietotāji domēnā {domain}.",
"dismissable_banner.public_timeline": ie ir jaunākie publiskie ieraksti no lietotājiem sociālajā tīmeklī, kuriem {domain} seko cilvēki.",
"embed.instructions": "Iestrādā šo ziņu savā mājaslapā, kopējot zemāk redzamo kodu.",
"embed.preview": "Tas izskatīsies šādi:",
"emoji_button.activity": "Aktivitāte",
@ -215,22 +226,22 @@
"empty_column.account_timeline": "Šeit ziņojumu nav!",
"empty_column.account_unavailable": "Profils nav pieejams",
"empty_column.blocks": "Pašreiz tu neesi nevienu bloķējis.",
"empty_column.bookmarked_statuses": "Pašreiz tev nav neviena grāmatzīmēm pievienota ieraksta. Kad tādu pievienosi, tas parādīsies šeit.",
"empty_column.bookmarked_statuses": "Pašlaik Tev nav neviena grāmatzīmēs pievienota ieraksta. Kad tādu pievienosi, tas parādīsies šeit.",
"empty_column.community": "Vietējā laika līnija ir tukša. Uzraksti kaut ko publiski, lai viss notiktu!",
"empty_column.direct": "Jums vēl nav nevienas privātas pieminēšanas. Nosūtot vai saņemot to, tas tiks parādīts šeit.",
"empty_column.direct": "Tev vēl nav privātu pieminēšanu. Kad Tu nosūtīsi vai saņemsi kādu, tā pārādīsies šeit.",
"empty_column.domain_blocks": "Vēl nav neviena bloķēta domēna.",
"empty_column.explore_statuses": "Pašlaik nekā aktuāla nav. Pārbaudi vēlāk!",
"empty_column.favourited_statuses": "Tev vēl nav nevienas iecienītākās ziņas. Kad iecienīsi kādu, tas tiks parādīts šeit.",
"empty_column.explore_statuses": "Pašlaik nav nekā aktuāla. Ieskaties šeit vēlāk!",
"empty_column.favourited_statuses": "Tev vēl nav iecienītāko ierakstu. Kad pievienosi kādu izlasei, tas tiks parādīts šeit.",
"empty_column.favourites": "Šo ziņu neviens vēl nav pievienojis izlasei. Kad kāds to izdarīs, tas parādīsies šeit.",
"empty_column.follow_requests": "Šobrīd tev nav sekošanas pieprasījumu. Kad kāds pieteiksies tev sekot, pieprasījums parādīsies šeit.",
"empty_column.follow_requests": "Šobrīd Tev nav sekošanas pieprasījumu. Kad saņemsi kādu, tas parādīsies šeit.",
"empty_column.followed_tags": "Tu vēl neesi sekojis nevienam tēmturim. Kad to izdarīsi, tie tiks parādīti šeit.",
"empty_column.hashtag": "Ar šo tēmturi nekas nav atrodams.",
"empty_column.home": "Tava mājas laikrinda ir tukša! Lai to aizpildītu, pieseko vairāk cilvēkiem.",
"empty_column.list": "Šis saraksts pašreiz ir tukšs. Kad šī saraksta dalībnieki publicēs jaunas ziņas, tās parādīsies šeit.",
"empty_column.lists": "Pašreiz tev nav neviena saraksta. Kad tādu izveidosi, tas parādīsies šeit.",
"empty_column.home": "Tava mājas laikjosla ir tukša. Seko vairāk cilvēkiem, lai to piepildītu!",
"empty_column.list": "Pagaidām šajā sarakstā nekā nav. Kad šī saraksta dalībnieki ievietos jaunus ierakstus, tie parādīsies šeit.",
"empty_column.lists": "Pašlaik Tev nav neviena saraksta. Kad tādu izveidosi, tas parādīsies šeit.",
"empty_column.mutes": "Neviens lietotājs vēl nav apklusināts.",
"empty_column.notifications": "Tev vēl nav paziņojumu. Kad citi cilvēki ar tevi mijiedarbosies, tu to redzēsi šeit.",
"empty_column.public": "Šeit vēl nekā nav! Ieraksti ko publiski vai pieseko lietotājiem no citiem serveriem",
"empty_column.notifications": "Tev vēl nav paziņojumu. Kad citi cilvēki ar Tevi mijiedarbosies, Tu to redzēsi šeit.",
"empty_column.public": "Šeit nekā nav! Ieraksti kaut ko publiski vai seko lietotājiem no citiem serveriem, lai iegūtu saturu",
"error.unexpected_crash.explanation": "Koda kļūdas vai pārlūkprogrammas saderības problēmas dēļ šo lapu nevarēja parādīt pareizi.",
"error.unexpected_crash.explanation_addons": "Šo lapu nevarēja parādīt pareizi. Šo kļūdu, iespējams, izraisīja pārlūkprogrammas papildinājums vai automātiskās tulkošanas rīki.",
"error.unexpected_crash.next_steps": "Mēģini atsvaidzināt lapu. Ja tas nepalīdz, iespējams, varēsi lietot Mastodon, izmantojot citu pārlūkprogrammu vai lietotni.",
@ -239,13 +250,13 @@
"errors.unexpected_crash.report_issue": "Ziņot par problēmu",
"explore.search_results": "Meklēšanas rezultāti",
"explore.suggested_follows": "Cilvēki",
"explore.title": "Pārlūkot",
"explore.title": "Izpētīt",
"explore.trending_links": "Jaunumi",
"explore.trending_statuses": "Ziņas",
"explore.trending_statuses": "Ieraksti",
"explore.trending_tags": "Tēmturi",
"filter_modal.added.context_mismatch_explanation": "Šī filtra kategorija neattiecas uz kontekstu, kurā esi piekļuvis šai ziņai. Ja vēlies, lai ziņa tiktu filtrēta arī šajā kontekstā, tev būs jārediģē filtrs.",
"filter_modal.added.context_mismatch_explanation": "Šī atlases kategorija neattiecas uz kontekstu, kurā esi piekļuvis šim ierakstam. Ja vēlies, lai ieraksts tiktu atlasīts arī šajā kontekstā, Tev būs jālabo atlase.",
"filter_modal.added.context_mismatch_title": "Konteksta neatbilstība!",
"filter_modal.added.expired_explanation": "Šai filtra kategorijai ir beidzies derīguma termiņš. Lai to lietotu, tev būs jāmaina derīguma termiņš.",
"filter_modal.added.expired_explanation": "Šai atlases kategorijai ir beidzies derīguma termiņš. Lai to lietotu, Tev būs jāmaina derīguma termiņš.",
"filter_modal.added.expired_title": "Filtra termiņš beidzies!",
"filter_modal.added.review_and_configure": "Lai pārskatītu un tālāk konfigurētu šo filtru kategoriju, dodies uz {settings_link}.",
"filter_modal.added.review_and_configure_title": "Filtra iestatījumi",
@ -255,7 +266,7 @@
"filter_modal.select_filter.context_mismatch": "neattiecas uz šo kontekstu",
"filter_modal.select_filter.expired": "beidzies",
"filter_modal.select_filter.prompt_new": "Jauna kategorija: {name}",
"filter_modal.select_filter.search": "Meklē vai izveido",
"filter_modal.select_filter.search": "Meklēt vai izveidot",
"filter_modal.select_filter.subtitle": "Izmanto esošu kategoriju vai izveido jaunu",
"filter_modal.select_filter.title": "Filtrēt šo ziņu",
"filter_modal.title.status": "Filtrēt ziņu",
@ -264,7 +275,11 @@
"firehose.remote": "Citi serveri",
"follow_request.authorize": "Autorizēt",
"follow_request.reject": "Noraidīt",
"follow_requests.unlocked_explanation": "Lai gan tavs konts nav bloķēts, {domain} darbinieki iedomājās, ka, iespējams, vēlēsies pārskatīt pieprasījumus no šiem kontiem.",
"follow_requests.unlocked_explanation": "Lai gan Tavs konts nav slēgts, {domain} darbinieki iedomājās, ka Tu varētu vēlēties pašrocīgi pārskatīt sekošanas pieprasījumus no šiem kontiem.",
"follow_suggestions.curated_suggestion": "Darbinieku izvēle",
"follow_suggestions.dismiss": "Vairs nerādīt",
"follow_suggestions.view_all": "Skatīt visu",
"follow_suggestions.who_to_follow": "Kam sekot",
"followed_tags": "Sekojamie tēmturi",
"footer.about": "Par",
"footer.directory": "Profilu direktorija",
@ -286,8 +301,8 @@
"hashtag.column_settings.tag_mode.none": "Neviens no šiem",
"hashtag.column_settings.tag_toggle": "Pievienot kolonnai papildu tēmturus",
"hashtag.counter_by_accounts": "{count, plural, one {{counter} dalībnieks} other {{counter} dalībnieki}}",
"hashtag.counter_by_uses": "{count, plural, zero {{counter} ziņa} one {{counter} ieraksts} other {{counter} ziņas}}",
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} ziņa} other {{counter} ziņas}} šodien",
"hashtag.counter_by_uses": "{count, plural, zero {{counter} ierakstu} one {{counter} ieraksts} other {{counter} ieraksti}}",
"hashtag.counter_by_uses_today": "{count, plural, zero {{counter} ierakstu} one {{counter} ieraksts} other {{counter} ieraksti}} šodien",
"hashtag.follow": "Sekot tēmturim",
"hashtag.unfollow": "Pārstāt sekot tēmturim",
"hashtags.and_other": "..un {count, plural, other {# vairāk}}",
@ -300,16 +315,16 @@
"home.pending_critical_update.title": "Pieejams kritisks drošības jauninājums!",
"home.show_announcements": "Rādīt paziņojumus",
"interaction_modal.description.favourite": "Ar Mastodon kontu tu vari pievienot šo ziņu izlasei, lai informētu autoru, ka to novērtē, un saglabātu to vēlākai lasīšanai.",
"interaction_modal.description.follow": "Ar Mastodon kontu tu vari sekot {name}, lai saņemtu viņu ziņas savā mājas plūsmā.",
"interaction_modal.description.reblog": "Izmantojot kontu Mastodon, tu vari izcelt šo ziņu, lai kopīgotu to ar saviem sekotājiem.",
"interaction_modal.description.follow": "Ar Mastodon kontu Tu vari sekot {name}, lai saņemtu lietotāja ierakstus savā mājas plūsmā.",
"interaction_modal.description.reblog": "Ar Mastodon kontu Tu vari izvirzīt šo ierakstu, lai kopīgotu to ar saviem sekotājiem.",
"interaction_modal.description.reply": "Ar Mastodon kontu tu vari atbildēt uz šo ziņu.",
"interaction_modal.login.action": "Nogādā mani mājās",
"interaction_modal.login.action": "Nogādāt mani mājās",
"interaction_modal.login.prompt": "Tavas mājvietas servera domēns, piem., mastodon.social",
"interaction_modal.no_account_yet": "Neesi Mastodon?",
"interaction_modal.on_another_server": "Citā serverī",
"interaction_modal.on_this_server": "Šajā serverī",
"interaction_modal.sign_in": "Tu neesi pieteicies šajā serverī. Kur tiek mitināts tavs konts?",
"interaction_modal.sign_in_hint": "Padoms: Šī ir vietne, kurā tu piereģistrējies. Ja neatceries, meklē sveiciena e-pastu savā iesūtnē. Vari arī ievadīt pilnu lietotājvārdu! (piem., @Mastodon@mastodon.social)",
"interaction_modal.sign_in": "Tu neesi pieteicies šajā serverī. Kur tiek mitināts Tavs konts?",
"interaction_modal.sign_in_hint": "Padoms: tā ir tīmekļvietne, kurā Tu reģistrējies. Ja neatceries, jāmeklē sveiciena e-pasts savā iesūtnē. Vari arī ievadīt pilnu lietotājvārdu (piem., @Mastodon@mastodon.social).",
"interaction_modal.title.favourite": "Pievienot {name} ziņu izlasei",
"interaction_modal.title.follow": "Sekot {name}",
"interaction_modal.title.reblog": "Pastiprināt {name} ierakstu",
@ -361,12 +376,12 @@
"link_preview.author": "Pēc {name}",
"lists.account.add": "Pievienot sarakstam",
"lists.account.remove": "Noņemt no saraksta",
"lists.delete": "Dzēst sarakstu",
"lists.edit": "Rediģēt sarakstu",
"lists.delete": "Izdzēst sarakstu",
"lists.edit": "Labot sarakstu",
"lists.edit.submit": "Mainīt virsrakstu",
"lists.exclusive": "Paslēpt šīs ziņas no mājvietas",
"lists.exclusive": "Nerādīt šos ierakstus sākumā",
"lists.new.create": "Pievienot sarakstu",
"lists.new.title_placeholder": "Jaunais saraksta nosaukums",
"lists.new.title_placeholder": "Jaunā saraksta nosaukums",
"lists.replies_policy.followed": "Jebkuram sekotajam lietotājam",
"lists.replies_policy.list": "Saraksta dalībniekiem",
"lists.replies_policy.none": "Nevienam",
@ -374,8 +389,9 @@
"lists.search": "Meklēt starp cilvēkiem, kuriem tu seko",
"lists.subheading": "Tavi saraksti",
"load_pending": "{count, plural, one {# jauna lieta} other {# jaunas lietas}}",
"loading_indicator.label": "Ielādē…",
"media_gallery.toggle_visible": "{number, plural, one {Slēpt attēlu} other {Slēpt attēlus}}",
"moved_to_account_banner.text": "Tavs konts {disabledAccount} pašlaik ir atspējots, jo pārcēlies uz kontu {movedToAccount}.",
"moved_to_account_banner.text": "Tavs konts {disabledAccount} pašlaik ir atspējots, jo Tu pārcēlies uz kontu {movedToAccount}.",
"mute_modal.duration": "Ilgums",
"mute_modal.hide_notifications": "Slēpt paziņojumus no šī lietotāja?",
"mute_modal.indefinite": "Beztermiņa",
@ -385,10 +401,10 @@
"navigation_bar.bookmarks": "Grāmatzīmes",
"navigation_bar.community_timeline": "Vietējā laika līnija",
"navigation_bar.compose": "Veidot jaunu ziņu",
"navigation_bar.direct": "Privāti pieminēti",
"navigation_bar.direct": "Privātas pieminēšanas",
"navigation_bar.discover": "Atklāt",
"navigation_bar.domain_blocks": "Bloķētie domēni",
"navigation_bar.explore": "Pārlūkot",
"navigation_bar.explore": "Izpētīt",
"navigation_bar.favourites": "Izlase",
"navigation_bar.filters": "Apklusinātie vārdi",
"navigation_bar.follow_requests": "Sekošanas pieprasījumi",
@ -397,23 +413,23 @@
"navigation_bar.lists": "Saraksti",
"navigation_bar.logout": "Iziet",
"navigation_bar.mutes": "Apklusinātie lietotāji",
"navigation_bar.opened_in_classic_interface": "Ziņas, konti un citas noteiktas lapas pēc noklusējuma tiek atvērtas klasiskajā tīmekļa saskarnē.",
"navigation_bar.opened_in_classic_interface": "Ieraksti, konti un citas noteiktas lapas pēc noklusējuma tiek atvērtas klasiskajā tīmekļa saskarnē.",
"navigation_bar.personal": "Personīgie",
"navigation_bar.pins": "Piespraustās ziņas",
"navigation_bar.preferences": "Iestatījumi",
"navigation_bar.public_timeline": "Apvienotā laika līnija",
"navigation_bar.search": "Meklēt",
"navigation_bar.security": "Drošība",
"not_signed_in_indicator.not_signed_in": "Lai piekļūtu šim resursam, tev ir jāpierakstās.",
"not_signed_in_indicator.not_signed_in": "Ir jāpiesakās, lai piekļūtu šim resursam.",
"notification.admin.report": "{name} ziņoja par {target}",
"notification.admin.sign_up": "{name} ir pierakstījies",
"notification.favourite": "{name} pievienoja tavu ziņu izlasei",
"notification.follow": "{name} uzsāka tev sekot",
"notification.follow_request": "{name} nosūtīja tev sekošanas pieprasījumu",
"notification.mention": "{name} pieminēja tevi",
"notification.follow": "{name} uzsāka Tev sekot",
"notification.follow_request": "{name} nosūtīja Tev sekošanas pieprasījumu",
"notification.mention": "{name} pieminēja Tevi",
"notification.own_poll": "Tava aptauja ir noslēgusies",
"notification.poll": "Aptauja, kurā tu piedalījies, ir noslēgusies",
"notification.reblog": "{name} pastiprināja tavu ierakstu",
"notification.reblog": "{name} pastiprināja Tavu ierakstu",
"notification.status": "{name} tikko publicēja",
"notification.update": "{name} rediģēja ierakstu",
"notifications.clear": "Notīrīt paziņojumus",
@ -427,7 +443,7 @@
"notifications.column_settings.filter_bar.show_bar": "Rādīt filtru joslu",
"notifications.column_settings.follow": "Jauni sekotāji:",
"notifications.column_settings.follow_request": "Jauni sekošanas pieprasījumi:",
"notifications.column_settings.mention": "Pieminējumi:",
"notifications.column_settings.mention": "Pieminēšanas:",
"notifications.column_settings.poll": "Aptaujas rezultāti:",
"notifications.column_settings.push": "Uznirstošie paziņojumi",
"notifications.column_settings.reblog": "Pastiprinātie ieraksti:",
@ -441,7 +457,7 @@
"notifications.filter.boosts": "Pastiprinātie ieraksti",
"notifications.filter.favourites": "Izlases",
"notifications.filter.follows": "Seko",
"notifications.filter.mentions": "Pieminējumi",
"notifications.filter.mentions": "Pieminēšanas",
"notifications.filter.polls": "Aptaujas rezultāti",
"notifications.filter.statuses": "Jaunumi no cilvēkiem, kuriem tu seko",
"notifications.grant_permission": "Piešķirt atļauju.",
@ -458,27 +474,36 @@
"onboarding.actions.go_to_explore": "Skatīt tendences",
"onboarding.actions.go_to_home": "Dodieties uz manu mājas plūsmu",
"onboarding.compose.template": "Sveiki, #Mastodon!",
"onboarding.follows.empty": "Diemžēl pašlaik nevar parādīt rezultātus. Vari mēģināt izmantot meklēšanu vai pārlūkot izpētes lapu, lai atrastu personas, kurām sekot, vai mēģināt vēlreiz vēlāk.",
"onboarding.follows.empty": "Diemžēl pašlaik nevar parādīt rezultātus. Vari mēģināt izmantot meklēšanu vai pārlūkot izpētes lapu, lai atrastu cilvēkus, kuriem sekot, vai vēlāk mēģināt vēlreiz.",
"onboarding.follows.lead": "Tava mājas plūsma ir galvenais veids, kā izbaudīt Mastodon. Jo vairāk cilvēku sekosi, jo aktīvāk un interesantāk tas būs. Lai sāktu, šeit ir daži ieteikumi:",
"onboarding.follows.title": "Populārs Mastodon",
"onboarding.share.lead": "Paziņo citiem, kā viņi tevi var atrast Mastodon!",
"onboarding.profile.discoverable": "Padarīt manu profilu atklājamu",
"onboarding.profile.display_name": "Attēlojamais vārds",
"onboarding.profile.display_name_hint": "Tavs pilnais vārds vai Tavs joku vārds…",
"onboarding.profile.note": "Apraksts",
"onboarding.profile.note_hint": "Tu vari @pieminēt citus cilvēkus vai #tēmturus…",
"onboarding.profile.save_and_continue": "Saglabāt un turpināt",
"onboarding.profile.title": "Profila iestatīšana",
"onboarding.profile.upload_avatar": "Augšupielādēt profila attēlu",
"onboarding.profile.upload_header": "Augšupielādēt profila galveni",
"onboarding.share.lead": "Dari cilvēkiem zināmu, ka viņi var Tevi atrast Mastodon!",
"onboarding.share.message": "Es esmu {username} #Mastodon! Nāc sekot man uz {url}",
"onboarding.share.next_steps": "Iespējamie nākamie soļi:",
"onboarding.share.title": "Kopīgo savu profilu",
"onboarding.start.lead": "Tagad tu esat daļa no Mastodon — unikālas, decentralizētas sociālo mediju platformas, kurā tu, nevis algoritms, veido savu pieredzi. Sāksim darbu šajā jaunajā sociālajā jomā:",
"onboarding.start.lead": "Tagad Tu esi daļa no Mastodon — vienreizējas, decentralizētas sociālās mediju platformas, kurā Tu, nevis algoritms, veido Tavu pieredzi. Sāksim darbu šajā jaunajā sociālajā jomā:",
"onboarding.start.skip": "Nav nepieciešama palīdzība darba sākšanai?",
"onboarding.start.title": "Tev tas izdevās!",
"onboarding.steps.follow_people.body": "Tu pats veido savu plūsmu. Piepildīsim to ar interesantiem cilvēkiem.",
"onboarding.steps.follow_people.title": "Sekot {count, plural, one {one person} other {# cilvēkiem}}",
"onboarding.steps.publish_status.body": "Sveicini pasauli ar tekstu, fotoattēliem, video, vai aptaujām {emoji}",
"onboarding.steps.publish_status.title": "Izveido savu pirmo ziņu",
"onboarding.steps.setup_profile.body": "Citi, visticamāk, sazināsies ar tevi, izmantojot aizpildītu profilu.",
"onboarding.steps.setup_profile.body": "Palielini mijiedarbību ar aptverošu profilu!",
"onboarding.steps.setup_profile.title": "Pielāgo savu profilu",
"onboarding.steps.share_profile.body": "Paziņo saviem draugiem, kā tevi atrast Mastodon!",
"onboarding.steps.share_profile.body": "Dari saviem draugiem zināmu, kā Tevi atrast Mastodon!",
"onboarding.steps.share_profile.title": "Kopīgo savu Mastodon profilu",
"onboarding.tips.2fa": "<strong>Vai zināji?</strong> Tu vari aizsargāt savu kontu, konta iestatījumos iestatot divu faktoru autentifikāciju. Tas darbojas ar jebkuru tevis izvēlētu TOTP lietotni, nav nepieciešams tālruņa numurs!",
"onboarding.tips.2fa": "<strong>Vai zināji?</strong> Tu vari aizsargāt savu kontu, konta iestatījumos iestatot divpakāpju autentifikāciju. Tas darbojas ar jebkuru Tevis izvēlētu TOTP lietotni, nav nepieciešams tālruņa numurs!",
"onboarding.tips.accounts_from_other_servers": "<strong>Vai zināji?</strong> Tā kā Mastodon ir decentralizēts, daži profili, ar kuriem saskaraties, tiks mitināti citos, nevis tavos serveros. Un tomēr tu varat sazināties ar viņiem nevainojami! Viņu serveris atrodas viņu lietotājvārda otrajā pusē!",
"onboarding.tips.migration": "<strong>Vai zināji?</strong> Ja uzskati, ka {domain} nākotnē nav lieliska servera izvēle, vari pāriet uz citu Mastodon serveri, nezaudējot savus sekotājus. Tu pat vari mitināt savu personīgo serveri!",
"onboarding.tips.migration": "<strong>Vai zināji?</strong> Ja uzskati, ka {domain} nākotnē nav lieliska servera izvēle, vari pāriet uz citu Mastodon serveri, nezaudējot savus sekotājus. Tu pat vari mitināt savu serveri!",
"onboarding.tips.verification": "<strong>Vai zināji?</strong> Tu vari verificēt savu kontu, ievietojot saiti uz savu Mastodon profilu savā vietnē un pievienojot vietni savam profilam. Nav nepieciešami nekādi maksājumi vai dokumenti!",
"password_confirmation.exceeds_maxlength": "Paroles apstiprināšana pārsniedz maksimālo paroles garumu",
"password_confirmation.mismatching": "Paroles apstiprinājums neatbilst",
@ -494,9 +519,14 @@
"poll_button.add_poll": "Pievienot aptauju",
"poll_button.remove_poll": "Noņemt aptauju",
"privacy.change": "Mainīt ieraksta privātumu",
"privacy.direct.long": "Visi ierakstā pieminētie",
"privacy.direct.short": "Noteikti cilvēki",
"privacy.private.long": "Tikai Tavi sekotāji",
"privacy.private.short": "Sekotāji",
"privacy.public.short": "Publiska",
"privacy_policy.last_updated": "Pēdējo reizi atjaunināta {date}",
"privacy_policy.title": "Privātuma politika",
"recommended": "Ieteicams",
"refresh": "Atsvaidzināt",
"regeneration_indicator.label": "Ielādē…",
"regeneration_indicator.sublabel": "Tiek gatavota tava plūsma!",
@ -512,8 +542,9 @@
"relative_time.seconds": "{number}s",
"relative_time.today": "šodien",
"reply_indicator.cancel": "Atcelt",
"reply_indicator.poll": "Aptauja",
"report.block": "Bloķēt",
"report.block_explanation": "Tu neredzēsi viņu ziņas. Viņi nevarēs redzēt tavas ziņas vai sekot tev. Viņi varēs saprast, ka ir bloķēti.",
"report.block_explanation": "Tu neredzēsi viņu ierakstus. Viņi nevarēs redzēt Tavus ierakstus vai sekot tev. Viņi varēs saprast, ka ir bloķēti.",
"report.categories.legal": "Tiesisks",
"report.categories.other": "Citi",
"report.categories.spam": "Spams",
@ -527,7 +558,7 @@
"report.forward": "Pārsūtīt {target}",
"report.forward_hint": "Konts ir no cita servera. Vai nosūtīt anonimizētu sūdzības kopiju arī tam?",
"report.mute": "Apklusināt",
"report.mute_explanation": "Tu neredzēsi viņu ziņas. Viņi joprojām var tev sekot un redzēt tavas ziņas un nezinās, ka viņi ir apklusināti.",
"report.mute_explanation": "Tu neredzēsi viņu ierakstus. Viņi joprojām var Tev sekot un redzēt Tavus ierakstus un nezinās, ka viņi ir apklusināti.",
"report.next": "Tālāk",
"report.placeholder": "Papildu komentāri",
"report.reasons.dislike": "Man tas nepatīk",
@ -543,15 +574,15 @@
"report.rules.subtitle": "Atlasi visus atbilstošos",
"report.rules.title": "Kuri noteikumi tiek pārkāpti?",
"report.statuses.subtitle": "Atlasi visus atbilstošos",
"report.statuses.title": "Vai ir kādi ieraksti, kas atbalsta šo sūdzību?",
"report.statuses.title": "Vai ir kādi ieraksti, kas apstiprina šo ziņojumu?",
"report.submit": "Iesniegt",
"report.target": "Ziņošana par: {target}",
"report.thanks.take_action": "Tālāk ir norādītas iespējas, kā kontrolēt Mastodon redzamo saturu:",
"report.thanks.take_action": "Šeit ir iespējas, lai pārvaldītu Mastodon redzamo saturu:",
"report.thanks.take_action_actionable": "Kamēr mēs to izskatām, tu vari veikt darbības pret @{name}:",
"report.thanks.title": "Vai nevēlies to redzēt?",
"report.thanks.title_actionable": "Paldies, ka ziņoji, mēs to izskatīsim.",
"report.unfollow": "Pārtraukt sekot @{name}",
"report.unfollow_explanation": "Tu seko šim kontam. Lai vairs neredzētu viņu ziņas savā mājas plūsmā, pārtrauc viņiem sekot.",
"report.unfollow_explanation": "Tu seko šim kontam. Lai vairs neredzētu tā ierakstus savā mājas plūsmā, pārtrauc sekot tam!",
"report_notification.attached_statuses": "Pievienoti {count, plural,one {{count} sūtījums} other {{count} sūtījumi}}",
"report_notification.categories.legal": "Tiesisks",
"report_notification.categories.other": "Cita",
@ -564,19 +595,20 @@
"search.quick_action.go_to_account": "Doties uz profilu {x}",
"search.quick_action.go_to_hashtag": "Doties uz tēmturi {x}",
"search.quick_action.open_url": "Atvērt URL Mastodonā",
"search.quick_action.status_search": "Ziņas atbilst {x}",
"search.search_or_paste": "Meklē vai iekopē URL",
"search.quick_action.status_search": "Ieraksti, kas atbilst {x}",
"search.search_or_paste": "Meklēt vai ielīmēt URL",
"search_popout.full_text_search_disabled_message": "Nav pieejams {domain}.",
"search_popout.full_text_search_logged_out_message": "Pieejams tikai pēc pieteikšanās.",
"search_popout.language_code": "ISO valodas kods",
"search_popout.options": "Meklēšanas iespējas",
"search_popout.quick_actions": "Ātrās darbības",
"search_popout.recent": "Nesen meklētais",
"search_popout.specific_date": "konkts datums",
"search_popout.specific_date": "noteikts datums",
"search_popout.user": "lietotājs",
"search_results.accounts": "Profili",
"search_results.all": "Visi",
"search_results.hashtags": "Tēmturi",
"search_results.nothing_found": "Nevarēja atrast neko šiem meklēšanas vienumiem",
"search_results.nothing_found": "Nevarēja atrast neko, kas atbilstu šim meklēšanas vaicājumam",
"search_results.see_all": "Skatīt visus",
"search_results.statuses": "Ieraksti",
"search_results.title": "Meklēt {q}",
@ -587,9 +619,9 @@
"server_banner.learn_more": "Uzzināt vairāk",
"server_banner.server_stats": "Servera statistika:",
"sign_in_banner.create_account": "Izveidot kontu",
"sign_in_banner.sign_in": "Pierakstīties",
"sign_in_banner.sign_in": "Pieteikties",
"sign_in_banner.sso_redirect": "Piesakies vai Reģistrējies",
"sign_in_banner.text": "Pieraksties, lai sekotu profiliem vai atsaucēm, pievienotu izlasei, kopīgotu ziņas un atbildētu uz tām. Vari arī mijiedarboties no sava konta citā serverī.",
"sign_in_banner.text": "Jāpiesakās, lai sekotu profiliem vai tēmturiem, pievienotu izlasei, kopīgotu ierakstus un atbildētu uz tiem. Vari arī mijiedarboties ar savu kontu citā serverī.",
"status.admin_account": "Atvērt @{name} moderēšanas saskarni",
"status.admin_domain": "Atvērt {domain} moderēšanas saskarni",
"status.admin_status": "Atvērt šo ziņu moderācijas saskarnē",
@ -602,16 +634,16 @@
"status.detailed_status": "Detalizēts sarunas skats",
"status.direct": "Pieminēt @{name} privāti",
"status.direct_indicator": "Pieminēts privāti",
"status.edit": "Rediģēt",
"status.edited": "Rediģēts {date}",
"status.edited_x_times": "Rediģēts {count, plural, one {{count} reize} other {{count} reizes}}",
"status.edit": "Labot",
"status.edited": "Labots {date}",
"status.edited_x_times": "Labots {count, plural, one {{count} reizi} other {{count} reizes}}",
"status.embed": "Iestrādāt",
"status.favourite": "Iecienīts",
"status.filter": "Filtrē šo ziņu",
"status.filtered": "Filtrēts",
"status.hide": "Slēpt ierakstu",
"status.history.created": "{name} izveidoja {date}",
"status.history.edited": "{name} rediģēja {date}",
"status.history.edited": "{name} laboja {date}",
"status.load_more": "Ielādēt vairāk",
"status.media.open": "Noklikšķini, lai atvērtu",
"status.media.show": "Noklikšķini, lai parādītu",
@ -648,7 +680,7 @@
"status.uncached_media_warning": "Priekšskatījums nav pieejams",
"status.unmute_conversation": "Noņemt sarunas apklusinājumu",
"status.unpin": "Noņemt profila piespraudumu",
"subscribed_languages.lead": "Pēc izmaiņu veikšanas tavā mājas un sarakstu laika līnijā tiks rādītas tikai ziņas atlasītajās valodās. Neatlasi nevienu, lai saņemtu ziņas visās valodās.",
"subscribed_languages.lead": "Pēc izmaiņu veikšanas Tavā mājas un sarakstu laika līnijā tiks rādīti tikai tie ieraksti atlasītajās valodās. Neatlasīt nevienu, lai saņemtu ierakstus visās valodās.",
"subscribed_languages.save": "Saglabāt izmaiņas",
"subscribed_languages.target": "Mainīt abonētās valodas priekš {target}",
"tabs_bar.home": "Sākums",
@ -662,8 +694,8 @@
"timeline_hint.resources.followers": "Sekotāji",
"timeline_hint.resources.follows": "Seko",
"timeline_hint.resources.statuses": "Vecāki ieraksti",
"trends.counter_by_accounts": "{count, plural, one {{counter} persona} other {{counter} cilvēki}} par {days, plural, one {# dienu} other {{days} dienām}}",
"trends.trending_now": "Aktuālās tendences",
"trends.counter_by_accounts": "{count, plural, zero {{counter} cilvēku} one {{counter} cilvēks} other {{counter} cilvēki}} {days, plural, one {{day} dienā} other {{days} dienās}}",
"trends.trending_now": "Pašlaik populāri",
"ui.beforeunload": "Ja pametīsit Mastodonu, jūsu melnraksts tiks zaudēts.",
"units.short.billion": "{count}Mjd",
"units.short.million": "{count}M",
@ -674,7 +706,7 @@
"upload_error.poll": "Datņu augšupielādes aptaujās nav atļautas.",
"upload_form.audio_description": "Pievieno aprakstu cilvēkiem ar dzirdes zudumu",
"upload_form.description": "Pievieno aprakstu vājredzīgajiem",
"upload_form.edit": "Rediģēt",
"upload_form.edit": "Labot",
"upload_form.thumbnail": "Nomainīt sīktēlu",
"upload_form.video_description": "Pievieno aprakstu cilvēkiem ar dzirdes vai redzes traucējumiem",
"upload_modal.analyzing_picture": "Analizē attēlu…",
@ -683,7 +715,7 @@
"upload_modal.choose_image": "Izvēlēties attēlu",
"upload_modal.description_placeholder": "Raibais runcis rīgā ratu rumbā rūc",
"upload_modal.detect_text": "Noteikt tekstu no attēla",
"upload_modal.edit_media": "Rediģēt multividi",
"upload_modal.edit_media": "Labot informācijas nesēju",
"upload_modal.hint": "Noklikšķini vai velc apli priekšskatījumā, lai izvēlētos fokusa punktu, kas vienmēr būs redzams visos sīktēlos.",
"upload_modal.preparing_ocr": "Sagatavo OCR…",
"upload_modal.preview_label": "Priekšskatīt ({ratio})",

View File

@ -530,7 +530,7 @@
"poll_button.remove_poll": "Peiling verwijderen",
"privacy.change": "Zichtbaarheid van bericht aanpassen",
"privacy.direct.long": "Alleen voor mensen die specifiek in het bericht worden vermeld",
"privacy.direct.short": "Specifieke mensen",
"privacy.direct.short": "Privébericht",
"privacy.private.long": "Alleen jouw volgers",
"privacy.private.short": "Volgers",
"privacy.public.long": "Iedereen op Mastodon en daarbuiten",
@ -666,7 +666,7 @@
"status.mention": "@{name} vermelden",
"status.more": "Meer",
"status.mute": "@{name} negeren",
"status.mute_conversation": "Negeer gesprek",
"status.mute_conversation": "Gesprek negeren",
"status.open": "Volledig bericht tonen",
"status.pin": "Aan profielpagina vastmaken",
"status.pinned": "Vastgemaakt bericht",

View File

@ -277,6 +277,7 @@
"follow_request.authorize": "Autoriser",
"follow_request.reject": "Avvis",
"follow_requests.unlocked_explanation": "Selv om kontoen din ikke er låst, tror {domain} ansatte at du kanskje vil gjennomgå forespørsler fra disse kontoene manuelt.",
"follow_suggestions.view_all": "Vis alle",
"followed_tags": "Fulgte emneknagger",
"footer.about": "Om",
"footer.directory": "Profilkatalog",

View File

@ -375,7 +375,7 @@
"lightbox.previous": "Назад",
"limited_account_hint.action": "Все равно показать профиль",
"limited_account_hint.title": "Этот профиль был скрыт модераторами {domain}.",
"link_preview.author": "По алфавиту",
"link_preview.author": "Автор: {name}",
"lists.account.add": "Добавить в список",
"lists.account.remove": "Убрать из списка",
"lists.delete": "Удалить список",

View File

@ -1 +1,19 @@
{}
{
"about.blocks": "Модеровані серверы",
"about.contact": "Контакт:",
"about.disclaimer": "Mastodon є задарьнов проґрамов из удпертым кодом тай торговов значков Mastodon gGmbH.",
"about.domain_blocks.no_reason_available": "Причины не ясні",
"about.domain_blocks.silenced.title": "Обмежено",
"about.domain_blocks.suspended.explanation": "Ниякі податкы из сього сервера не будут уброблені, усокочені ци поміняні, што чинит невозможнов хоть-яку інтеракцію ци зязок из хосновачами из сього сервера.",
"about.domain_blocks.suspended.title": "Заблоковано",
"about.rules": "Правила сервера",
"account.account_note_header": "Примітка",
"account.add_or_remove_from_list": "Дати авадь забрати из исписа",
"account.badges.bot": "Автоматічно",
"account.badges.group": "Ґрупа",
"account.block": "Заблоковати @{name}",
"account.block_domain": "Заблоковати домен {domain}",
"account.block_short": "Заблоковати",
"account.blocked": "Заблоковано",
"account.browse_more_on_origin_server": "Позирайте бульше на ориґіналнум профілю"
}

File diff suppressed because it is too large Load Diff

View File

@ -277,7 +277,13 @@
"follow_request.authorize": "Odobri",
"follow_request.reject": "Odbij",
"follow_requests.unlocked_explanation": "Iako vaš nalog nije zaključan, osoblje {domain} smatra da biste možda želeli da ručno pregledate zahteve za praćenje sa ovih naloga.",
"follow_suggestions.curated_suggestion": "Izbor osoblja",
"follow_suggestions.dismiss": "Ne prikazuj ponovo",
"follow_suggestions.hints.featured": "Ovaj profil je ručno izabrao tim {domain}.",
"follow_suggestions.hints.friends_of_friends": "Ovaj profil je popularan među ljudima koje pratite.",
"follow_suggestions.hints.most_followed": "Ovaj profil je jedan od najpraćenijih na {domain}.",
"follow_suggestions.hints.most_interactions": "Ovaj profil je nedavno dobio veliku pažnju na {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Ovaj profil je sličan profilima koje ste nedavno zapratili.",
"follow_suggestions.personalized_suggestion": "Personalizovani predlog",
"follow_suggestions.popular_suggestion": "Popularni predlog",
"follow_suggestions.view_all": "Prikaži sve",

View File

@ -277,6 +277,7 @@
"follow_request.authorize": "Одобри",
"follow_request.reject": "Одбиј",
"follow_requests.unlocked_explanation": "Иако ваш налог није закључан, особље {domain} сматра да бисте можда желели да ручно прегледате захтеве за праћење са ових налога.",
"follow_suggestions.curated_suggestion": "Избор особља",
"follow_suggestions.dismiss": "Не приказуј поново",
"follow_suggestions.hints.featured": "Овај профил је ручно изабрао тим {domain}.",
"follow_suggestions.hints.friends_of_friends": "Овај профил је популаран међу људима које пратите.",
@ -507,7 +508,7 @@
"onboarding.steps.publish_status.body": "Поздравите свет текстом, сликама, видео снимцима или анкетама {emoji}",
"onboarding.steps.publish_status.title": "Напишите своју прву објаву",
"onboarding.steps.setup_profile.body": "Појачајте своје интеракције тако што ћете имати свеобухватан профил.",
"onboarding.steps.setup_profile.title": "Персонализујтее свој профил",
"onboarding.steps.setup_profile.title": "Персонализујте свој профил",
"onboarding.steps.share_profile.body": "Нека ваши пријатељи знају како да вас пронађу на Mastodon-у!",
"onboarding.steps.share_profile.title": "Поделите свој Mastodon профил",
"onboarding.tips.2fa": "<strong>Да ли сте знали?</strong> Можете да заштитите свој налог подешавањем двоструке потврде идентитета у подешавањима налога. Ради са било којом TOTP апликацијом по вашем избору, није потребан број телефона!",

View File

@ -119,6 +119,7 @@
"compose_form.save_changes": "o sin e ni",
"compose_form.spoiler.marked": "o weka e toki pi ijo ike ken",
"confirmation_modal.cancel": "o pini",
"confirmations.block.block_and_report": "o weka e jan o toki e jan tawa lawa",
"confirmations.block.confirm": "o weka",
"confirmations.block.message": "sina o wile ala wile weka e jan {name}?",
"confirmations.cancel_follow_request.confirm": "o weka e wile sina",
@ -132,20 +133,24 @@
"confirmations.domain_block.confirm": "o weka.",
"confirmations.domain_block.message": "sina wile ala a wile a len e ma {domain} ꞏ ken suli la len jan taso li pona ꞏ len pi ma ni la sina ken ala lukin e ijo pi ma ni lon lipu toki ale anu lukin toki ꞏ len ni la jan kute sina pi ma ni li weka",
"confirmations.edit.confirm": "o ante",
"confirmations.edit.message": "sina ante e toki sina la toki pali sina li weka. sina wile ala wile e ni?",
"confirmations.logout.confirm": "o weka",
"confirmations.logout.message": "sina wile ala wile weka",
"confirmations.mute.confirm": "o len",
"confirmations.mute.explanation": "ni la sina lukin ala e toki ona e toki kepeken nimi ona. taso la ona li ken lukin e toki sina li ken kute e ona.",
"confirmations.mute.message": "sina awen ala awen wile kute ala e {name}?",
"confirmations.redraft.confirm": "o weka o pali sin e toki",
"confirmations.redraft.message": "pali sin e toki ni la sina wile ala wile weka e ona? sina ni la suli pi toki ni en wawa pi toki ni li weka. kin la toki lon toki ni li jo e mama ala.",
"confirmations.reply.confirm": "toki lon toki ni",
"confirmations.reply.message": "toki tawa ona li weka e toki pali sina ꞏ sina wile ala wile ni",
"confirmations.reply.message": "sina toki lon toki ni la toki pali sina li weka. sina wile ala wile e ni?",
"confirmations.unfollow.confirm": "o pini kute",
"confirmations.unfollow.message": "sina o wile ala wile pini kute e jan {name}?",
"conversation.delete": "o weka e toki ni",
"conversation.mark_as_read": "ni o sin ala",
"conversation.open": "o lukin e toki",
"conversation.with": "lon {names}",
"copy_icon_button.copied": "toki li awen lon ilo sina",
"copypaste.copy_to_clipboard": "o awen lon ilo sina",
"directory.local": "tan {domain} taso",
"directory.new_arrivals": "jan pi kama sin",
"directory.recently_active": "jan lon tenpo poka",
@ -154,6 +159,9 @@
"dismissable_banner.community_timeline": "ni li toki pi tenpo poka tawa ale tan jan lon ma lawa pi nimi {domain}.",
"dismissable_banner.dismiss": "o weka",
"dismissable_banner.explore_links": "ni li toki pi ijo sin ꞏ jan mute li pana e ni lon tenpo suno ni ꞏ sin la jan mute li pana la ni li kama suli",
"dismissable_banner.explore_statuses": "suni ni la jan mute li lukin e toki ni. jan mute li wawa e toki li suli e toki la toki ni li lon sewi. toki li sin la toki ni li lon sewi.",
"dismissable_banner.explore_tags": "suni ni la jan mute li lukin e toki pi toki ni. jan mute li kepeken toki la toki ni li lon sewi.",
"dismissable_banner.public_timeline": "toki ni li sin. jan li pali e toki ni la jan ante mute pi ma {domain} li kute e jan ni.",
"embed.preview": "ni li jo e sitelen ni:",
"emoji_button.activity": "musi",
"emoji_button.flags": "len ma",
@ -171,15 +179,25 @@
"empty_column.account_timeline": "toki ala li lon!",
"empty_column.account_unavailable": "ken ala lukin e lipu jan",
"empty_column.blocks": "jan ala li weka tawa sina.",
"empty_column.direct": "jan ala li toki len e sina. jan li toki len e sina la sina ken lukin e ni lon ni.",
"empty_column.domain_blocks": "ma ala li weka tawa sina.",
"empty_column.favourited_statuses": "sina suli ala e toki. sina suli e toki la sina ken lukin e toki ni lon ni.",
"empty_column.favourites": "jan ala li suli e toki ni. jan li suli e toki ni la sina ken lukin e ona lon ni.",
"empty_column.follow_requests": "jan ala li toki pi wile kute tawa sina. jan li toki pi wile kute tawa sina la sina ken lukin e toki ni lon ni.",
"empty_column.followed_tags": "sina alasa ala e toki ꞏ sina alasa e toki la toki li lon ni",
"empty_column.hashtag": "ala li lon toki ni",
"empty_column.home": "ala a li lon lipu open sina! sina wile lon e ijo lon ni la o kute e jan pi toki suli.",
"empty_column.list": "ala li lon kulupu lipu ni. jan pi kulupu lipu ni li toki sin la toki ni li lon ni.",
"empty_column.lists": "sina jo ala e kulupu lipu. sina pali sin e kulupu lipu la ona li lon ni.",
"empty_column.mutes": "jan ala li len tawa sina.",
"error.unexpected_crash.explanation": "ilo li ken ala pana e lipu ni. ni li ken tan pakala mi tan pakala pi ilo sina.",
"errors.unexpected_crash.report_issue": "o toki e pakala tawa lawa",
"explore.search_results": "ijo pi alasa ni",
"explore.suggested_follows": "jan",
"explore.title": "o alasa",
"explore.trending_links": "sin",
"explore.trending_statuses": "toki",
"filter_modal.added.settings_link": "lipu lawa",
"filter_modal.select_filter.expired": "tenpo pini",
"filter_modal.select_filter.search": "o alasa anu pali",
"firehose.all": "ale",
@ -187,6 +205,10 @@
"firehose.remote": "kulupu ante",
"follow_request.authorize": "o ken",
"follow_request.reject": "o ala",
"follow_suggestions.hints.friends_of_friends": "jan kute sina li lukin mute e toki pi jan ni.",
"follow_suggestions.hints.most_followed": "jan mute lon ma {domain} li kute e jan ni.",
"follow_suggestions.hints.most_interactions": "tenpo poka la jan mute pi ma {domain} li lukin mute e toki pi jan ni.",
"follow_suggestions.hints.similar_to_recently_followed": "sina kute e jan lon tenpo poka la jan ni li sama ona.",
"follow_suggestions.view_all": "o lukin e ale",
"follow_suggestions.who_to_follow": "sina o kute e ni",
"footer.about": "sona",
@ -203,11 +225,14 @@
"hashtag.column_settings.tag_mode.any": "wan ni",
"hashtag.column_settings.tag_mode.none": "ala ni",
"home.pending_critical_update.link": "o lukin e ijo ilo sin",
"interaction_modal.login.action": "o lon tomo",
"interaction_modal.on_another_server": "lon ma ante",
"interaction_modal.on_this_server": "lon ma ni",
"interaction_modal.title.favourite": "o suli e toki {name}",
"interaction_modal.title.follow": "o kute e {name}",
"interaction_modal.title.reblog": "o wawa e toki {name}",
"interaction_modal.title.reply": "o toki lon toki pi jan {name}",
"intervals.full.days": "{number, plural, other {suni #}}",
"keyboard_shortcuts.blocked": "o lukin e lipu sina pi jan weka",
"keyboard_shortcuts.boost": "o pana sin e toki",
"keyboard_shortcuts.down": "o tawa anpa lon lipu",
@ -253,25 +278,42 @@
"navigation_bar.pins": "toki sewi",
"navigation_bar.preferences": "wile sina",
"navigation_bar.search": "o alasa",
"notification.admin.report": "jan {name} li toki e jan {target} tawa lawa",
"notification.admin.sign_up": "{name} li kama",
"notification.favourite": "{name} li suli e toki sina",
"notification.follow": " {name} li kute e sina",
"notification.follow_request": "{name} li wile kute e sina",
"notification.mention": "jan {name} li toki e sina",
"notification.poll": "sina pana lon pana la pana ni li pini",
"notification.reblog": "{name} li wawa e toki sina",
"notification.status": "{name} li toki",
"notification.update": "{name} li ante e toki",
"notifications.column_settings.follow": "jan kute sin",
"notifications.column_settings.poll": "pana lon pana ni:",
"notifications.column_settings.reblog": "wawa:",
"notifications.column_settings.update": "ante toki:",
"notifications.filter.all": "ale",
"notifications.filter.polls": "pana lon pana ni",
"onboarding.compose.template": "toki a, #Mastodon o!",
"onboarding.profile.display_name": "nimi tawa jan ante",
"onboarding.share.lead": "o toki lon nasin Masoton pi alasa sina tawa jan",
"onboarding.share.message": "ilo #Mastodon la mi jan {username} a! o kute e mi lon ni: {url}",
"onboarding.start.title": "sina o kama pona a!",
"onboarding.tips.migration": "<strong>sina sona ala sona e ni?</strong> tenpo kama la sina pilin ike tawa ma {domain} la, sina ken tawa ma ante lon ilo Masoton. jan li kute e sina la jan ni li awen kute e sina. kin la sina ken lawa e ma pi sina taso a!",
"poll.total_people": "{count, plural, other {jan #}}",
"poll.total_votes": "{count, plural, other {pana #}}",
"poll.vote": "o pana",
"poll.voted": "sina pana e ni",
"poll.votes": "{votes, plural, other {pana #}}",
"privacy.direct.long": "jan ale lon toki",
"privacy.public.short": "tawa ale",
"relative_time.full.just_now": "tenpo ni",
"relative_time.just_now": "tenpo ni",
"relative_time.today": "tenpo suno ni",
"report.block": "o weka e jan",
"report.block_explanation": "sina kama lukin ala e toki ona. ona li kama ala ken lukin e toki sina li kama ala ken kute e sina. ona li ken sona e kama ni.",
"report.categories.other": "ante",
"report.categories.spam": "ike tan toki mute",
"report.category.title": "ike seme li lon {type} ni",
"report.category.title_account": "lipu",
"report.category.title_status": "toki",

View File

@ -6,7 +6,7 @@
"about.domain_blocks.preamble": "Mastodon 基本上允許您瀏覽聯邦宇宙中任何伺服器的內容並與使用者互動。以下是在本伺服器上設定的例外。",
"about.domain_blocks.silenced.explanation": "一般來說您不會看到來自這個伺服器的個人檔案和內容,除非您明確搜尋或主動跟隨對方。",
"about.domain_blocks.silenced.title": "已受限",
"about.domain_blocks.suspended.explanation": "來自此伺服器的資料都不會被處理、儲存或交換,也無法與此伺服器上的使用者互動或交流。",
"about.domain_blocks.suspended.explanation": "來自此伺服器的資料都不會被處理、儲存或交換,也無法和此伺服器上的使用者互動與交流。",
"about.domain_blocks.suspended.title": "已停權",
"about.not_available": "無法於本伺服器上使用此資訊。",
"about.powered_by": "由 {mastodon} 提供的去中心化社群媒體",
@ -212,7 +212,7 @@
"emoji_button.custom": "自訂",
"emoji_button.flags": "旗幟",
"emoji_button.food": "食物 & 飲料",
"emoji_button.label": "插入表情符號",
"emoji_button.label": "插入 emoji 表情符號",
"emoji_button.nature": "自然",
"emoji_button.not_found": "啊就沒這表情符號吼!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "物件",
@ -227,7 +227,7 @@
"empty_column.account_timeline": "這裡還沒有嘟文!",
"empty_column.account_unavailable": "無法取得個人檔案",
"empty_column.blocks": "您還沒有封鎖任何使用者。",
"empty_column.bookmarked_statuses": "您還沒有建立任何書籤。當您建立書籤時,它將於此顯示。",
"empty_column.bookmarked_statuses": "您還沒有新增任何書籤。當您新增書籤時,它將於此顯示。",
"empty_column.community": "本站時間軸是空的。快公開嘟些文搶頭香啊!",
"empty_column.direct": "您還沒有收到任何私訊。當您私訊別人或收到私訊時,它將於此顯示。",
"empty_column.domain_blocks": "尚未封鎖任何網域。",
@ -239,7 +239,7 @@
"empty_column.hashtag": "這個主題標籤下什麼也沒有。",
"empty_column.home": "您的首頁時間軸是空的!跟隨更多人來將它填滿吧!",
"empty_column.list": "這份列表下什麼也沒有。當此列表的成員嘟出新的嘟文時,它們將顯示於此。",
"empty_column.lists": "您還沒有建立任何列表。當您建立列表時,它將於此顯示。",
"empty_column.lists": "您還沒有新增任何列表。當您新增列表時,它將於此顯示。",
"empty_column.mutes": "您尚未靜音任何使用者。",
"empty_column.notifications": "您還沒有收到任何通知,當您與別人開始互動時,它將於此顯示。",
"empty_column.public": "這裡什麼都沒有!嘗試寫些公開的嘟文,或者跟隨其他伺服器的使用者後,就會有嘟文出現了",
@ -322,10 +322,10 @@
"home.pending_critical_update.link": "檢視更新內容",
"home.pending_critical_update.title": "有可取得的重要安全性更新!",
"home.show_announcements": "顯示公告",
"interaction_modal.description.favourite": "在 Mastodon 上有個帳號的話,您可以將此嘟文加入最愛以讓作者知道您欣賞它且將它儲存下來。",
"interaction_modal.description.follow": "在 Mastodon 上有個帳號的話,您可以跟隨 {name} 以於首頁時間軸接收他們的嘟文。",
"interaction_modal.description.reblog": "在 Mastodon 上有個帳號的話,您可以轉嘟此嘟文以分享給您的跟隨者們。",
"interaction_modal.description.reply": "在 Mastodon 上有個帳號的話,您可以回覆此嘟文。",
"interaction_modal.description.favourite": "若於 Mastodon 上有個帳號,您可以將此嘟文加入最愛使作者知道您欣賞它且將它儲存下來。",
"interaction_modal.description.follow": "若於 Mastodon 上有個帳號,您可以跟隨 {name} 以於首頁時間軸接收他們的嘟文。",
"interaction_modal.description.reblog": "若於 Mastodon 上有個帳號,您可以轉嘟此嘟文以分享給您的跟隨者們。",
"interaction_modal.description.reply": "若於 Mastodon 上有個帳號,您可以回覆此嘟文。",
"interaction_modal.login.action": "返回首頁",
"interaction_modal.login.prompt": "您帳號所屬伺服器之網域例如mastodon.social",
"interaction_modal.no_account_yet": "還沒有 Mastodon 帳號嗎?",
@ -347,7 +347,7 @@
"keyboard_shortcuts.compose": "將游標移至文字撰寫區塊",
"keyboard_shortcuts.description": "說明",
"keyboard_shortcuts.direct": "開啟私訊對話欄",
"keyboard_shortcuts.down": "下移動",
"keyboard_shortcuts.down": "下移動",
"keyboard_shortcuts.enter": "檢視嘟文",
"keyboard_shortcuts.favourite": "加到最愛",
"keyboard_shortcuts.favourites": "開啟最愛列表",
@ -373,7 +373,7 @@
"keyboard_shortcuts.toggle_sensitivity": "顯示或隱藏媒體",
"keyboard_shortcuts.toot": "發個新嘟文",
"keyboard_shortcuts.unfocus": "跳離文字撰寫區塊或搜尋框",
"keyboard_shortcuts.up": "上移動",
"keyboard_shortcuts.up": "上移動",
"lightbox.close": "關閉",
"lightbox.compress": "折疊圖片檢視框",
"lightbox.expand": "展開圖片檢視框",
@ -483,7 +483,7 @@
"onboarding.actions.go_to_home": "前往您的首頁時間軸",
"onboarding.compose.template": "哈囉 #Mastodon",
"onboarding.follows.empty": "很遺憾,目前未能顯示任何結果。您可以嘗試使用搜尋、瀏覽探索頁面以找尋人們跟隨、或稍候再試。",
"onboarding.follows.lead": "您的首頁時間軸是 Mastodon 的核心體驗。若您跟隨更多人的話,它將會變得更活躍有趣。這些個人檔案也許是個好起點,您可以隨時取消跟隨他們!",
"onboarding.follows.lead": "您的首頁時間軸是 Mastodon 的核心體驗。若您跟隨更多人,它將會變得更活躍有趣。這些個人檔案也許是個好起點,您可以隨時取消跟隨他們!",
"onboarding.follows.title": "客製化您的首頁時間軸",
"onboarding.profile.discoverable": "使我的個人檔案可以被找到",
"onboarding.profile.discoverable_hint": "當您於 Mastodon 上選擇加入可發現性時,您的嘟文可能會出現於搜尋結果與趨勢中。您的個人檔案可能會被推薦給與您志趣相投的人。",
@ -505,7 +505,7 @@
"onboarding.start.title": "噹噹!完成啦!",
"onboarding.steps.follow_people.body": "Mastodon 的趣味就是跟隨些有趣的人們!",
"onboarding.steps.follow_people.title": "客製化您的首頁時間軸",
"onboarding.steps.publish_status.body": "向新世界打聲招呼吧。",
"onboarding.steps.publish_status.body": "透過文字、照片、影片或投票 {emoji} 向新世界打聲招呼吧。",
"onboarding.steps.publish_status.title": "撰寫您第一則嘟文",
"onboarding.steps.setup_profile.body": "若您完整填寫個人檔案,其他人比較願意與您互動。",
"onboarding.steps.setup_profile.title": "客製化您的個人檔案",
@ -526,7 +526,7 @@
"poll.vote": "投票",
"poll.voted": "您已對此問題投票",
"poll.votes": "{votes, plural, one {# 張票} other {# 張票}}",
"poll_button.add_poll": "建立投票",
"poll_button.add_poll": "新增投票",
"poll_button.remove_poll": "移除投票",
"privacy.change": "調整嘟文隱私狀態",
"privacy.direct.long": "此嘟文提及之所有人",
@ -716,7 +716,7 @@
"units.short.million": "{count}M",
"units.short.thousand": "{count}K",
"upload_area.title": "拖放來上傳",
"upload_button.label": "上傳圖片、影片、或者音檔案",
"upload_button.label": "上傳圖片、影片、或者音檔案",
"upload_error.limit": "已達到檔案上傳限制。",
"upload_error.poll": "不允許於投票時上傳檔案。",
"upload_form.audio_description": "為聽障人士增加文字說明",

View File

@ -280,12 +280,12 @@ const updateSuggestionTags = (state, token) => {
});
};
const updatePoll = (state, index, value) => state.updateIn(['poll', 'options'], options => {
const updatePoll = (state, index, value, maxOptions) => state.updateIn(['poll', 'options'], options => {
const tmp = options.set(index, value).filterNot(x => x.trim().length === 0);
if (tmp.size === 0) {
return tmp.push('').push('');
} else if (tmp.size < 4) {
} else if (tmp.size < maxOptions) {
return tmp.push('');
}
@ -529,7 +529,7 @@ export default function compose(state = initialState, action) {
case COMPOSE_POLL_REMOVE:
return state.set('poll', null);
case COMPOSE_POLL_OPTION_CHANGE:
return updatePoll(state, action.index, action.title);
return updatePoll(state, action.index, action.title, action.maxOptions);
case COMPOSE_POLL_SETTINGS_CHANGE:
return state.update('poll', poll => poll.set('expires_in', action.expiresIn).set('multiple', action.isMultiple));
case COMPOSE_LANGUAGE_CHANGE:

View File

@ -27,6 +27,8 @@ import media_attachments from './media_attachments';
import meta from './meta';
import { modalReducer } from './modal';
import mutes from './mutes';
import { notificationPolicyReducer } from './notification_policy';
import { notificationRequestsReducer } from './notification_requests';
import notifications from './notifications';
import picture_in_picture from './picture_in_picture';
import polls from './polls';
@ -84,6 +86,8 @@ const reducers = {
history,
tags,
followed_tags,
notificationPolicy: notificationPolicyReducer,
notificationRequests: notificationRequestsReducer,
};
// We want the root state to be an ImmutableRecord, which is an object with a defined list of keys,

View File

@ -0,0 +1,12 @@
import { fromJS } from 'immutable';
import { NOTIFICATION_POLICY_FETCH_SUCCESS } from 'mastodon/actions/notifications';
export const notificationPolicyReducer = (state = null, action) => {
switch(action.type) {
case NOTIFICATION_POLICY_FETCH_SUCCESS:
return fromJS(action.policy);
default:
return state;
}
};

View File

@ -0,0 +1,96 @@
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
import {
NOTIFICATION_REQUESTS_EXPAND_REQUEST,
NOTIFICATION_REQUESTS_EXPAND_SUCCESS,
NOTIFICATION_REQUESTS_EXPAND_FAIL,
NOTIFICATION_REQUESTS_FETCH_REQUEST,
NOTIFICATION_REQUESTS_FETCH_SUCCESS,
NOTIFICATION_REQUESTS_FETCH_FAIL,
NOTIFICATION_REQUEST_FETCH_REQUEST,
NOTIFICATION_REQUEST_FETCH_SUCCESS,
NOTIFICATION_REQUEST_FETCH_FAIL,
NOTIFICATION_REQUEST_ACCEPT_REQUEST,
NOTIFICATION_REQUEST_DISMISS_REQUEST,
NOTIFICATIONS_FOR_REQUEST_FETCH_REQUEST,
NOTIFICATIONS_FOR_REQUEST_FETCH_SUCCESS,
NOTIFICATIONS_FOR_REQUEST_FETCH_FAIL,
NOTIFICATIONS_FOR_REQUEST_EXPAND_REQUEST,
NOTIFICATIONS_FOR_REQUEST_EXPAND_SUCCESS,
NOTIFICATIONS_FOR_REQUEST_EXPAND_FAIL,
} from 'mastodon/actions/notifications';
import { notificationToMap } from './notifications';
const initialState = ImmutableMap({
items: ImmutableList(),
isLoading: false,
next: null,
current: ImmutableMap({
isLoading: false,
item: null,
removed: false,
notifications: ImmutableMap({
items: ImmutableList(),
isLoading: false,
next: null,
}),
}),
});
const normalizeRequest = request => fromJS({
...request,
account: request.account.id,
});
const removeRequest = (state, id) => {
if (state.getIn(['current', 'item', 'id']) === id) {
state = state.setIn(['current', 'removed'], true);
}
return state.update('items', list => list.filterNot(item => item.get('id') === id));
};
export const notificationRequestsReducer = (state = initialState, action) => {
switch(action.type) {
case NOTIFICATION_REQUESTS_FETCH_SUCCESS:
return state.withMutations(map => {
map.update('items', list => ImmutableList(action.requests.map(normalizeRequest)).concat(list));
map.set('isLoading', false);
map.update('next', next => next ?? action.next);
});
case NOTIFICATION_REQUESTS_EXPAND_SUCCESS:
return state.withMutations(map => {
map.update('items', list => list.concat(ImmutableList(action.requests.map(normalizeRequest))));
map.set('isLoading', false);
map.set('next', action.next);
});
case NOTIFICATION_REQUESTS_EXPAND_REQUEST:
case NOTIFICATION_REQUESTS_FETCH_REQUEST:
return state.set('isLoading', true);
case NOTIFICATION_REQUESTS_EXPAND_FAIL:
case NOTIFICATION_REQUESTS_FETCH_FAIL:
return state.set('isLoading', false);
case NOTIFICATION_REQUEST_ACCEPT_REQUEST:
case NOTIFICATION_REQUEST_DISMISS_REQUEST:
return removeRequest(state, action.id);
case NOTIFICATION_REQUEST_FETCH_REQUEST:
return state.set('current', initialState.get('current').set('isLoading', true));
case NOTIFICATION_REQUEST_FETCH_SUCCESS:
return state.update('current', map => map.set('isLoading', false).set('item', normalizeRequest(action.request)));
case NOTIFICATION_REQUEST_FETCH_FAIL:
return state.update('current', map => map.set('isLoading', false));
case NOTIFICATIONS_FOR_REQUEST_FETCH_REQUEST:
case NOTIFICATIONS_FOR_REQUEST_EXPAND_REQUEST:
return state.setIn(['current', 'notifications', 'isLoading'], true);
case NOTIFICATIONS_FOR_REQUEST_FETCH_SUCCESS:
return state.updateIn(['current', 'notifications'], map => map.set('isLoading', false).update('items', list => ImmutableList(action.notifications.map(notificationToMap)).concat(list)).update('next', next => next ?? action.next));
case NOTIFICATIONS_FOR_REQUEST_EXPAND_SUCCESS:
return state.updateIn(['current', 'notifications'], map => map.set('isLoading', false).update('items', list => list.concat(ImmutableList(action.notifications.map(notificationToMap)))).set('next', action.next));
case NOTIFICATIONS_FOR_REQUEST_FETCH_FAIL:
case NOTIFICATIONS_FOR_REQUEST_EXPAND_FAIL:
return state.setIn(['current', 'notifications', 'isLoading'], false);
default:
return state;
}
};

View File

@ -48,7 +48,7 @@ const initialState = ImmutableMap({
browserPermission: 'default',
});
const notificationToMap = notification => ImmutableMap({
export const notificationToMap = notification => ImmutableMap({
id: notification.id,
type: notification.type,
account: notification.account.id,

View File

@ -69,3 +69,11 @@ export function pluralReady(
export function roundTo10(num: number): number {
return Math.round(num * 0.1) / 0.1;
}
export function toCappedNumber(num: string): string {
if (parseInt(num) > 99) {
return '99+';
} else {
return num;
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m480-240 160-160-56-56-64 64v-168h-80v168l-64-64-56 56 160 160ZM200-120q-33 0-56.5-23.5T120-200v-499q0-14 4.5-27t13.5-24l50-61q11-14 27.5-21.5T250-840h460q18 0 34.5 7.5T772-811l50 61q9 11 13.5 24t4.5 27v499q0 33-23.5 56.5T760-120H200Zm16-600h528l-34-40H250l-34 40Z"/></svg>

After

Width:  |  Height:  |  Size: 370 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m480-240 160-160-56-56-64 64v-168h-80v168l-64-64-56 56 160 160ZM200-640v440h560v-440H200Zm0 520q-33 0-56.5-23.5T120-200v-499q0-14 4.5-27t13.5-24l50-61q11-14 27.5-21.5T250-840h460q18 0 34.5 7.5T772-811l50 61q9 11 13.5 24t4.5 27v499q0 33-23.5 56.5T760-120H200Zm16-600h528l-34-40H250l-34 40Zm264 300Z"/></svg>

After

Width:  |  Height:  |  Size: 403 B

View File

@ -53,4 +53,10 @@ $fluid-breakpoint: $maximum-width + 20px;
border-bottom: 0;
}
}
&__hint {
font-size: 14px;
font-weight: 400;
color: $darker-text-color;
}
}

View File

@ -3289,12 +3289,13 @@ $ui-header-height: 55px;
border: 0;
border-bottom: 1px solid lighten($ui-base-color, 8%);
text-align: unset;
padding: 15px;
padding: 13px;
margin: 0;
z-index: 3;
outline: 0;
display: flex;
align-items: center;
gap: 5px;
&:hover {
text-decoration: underline;
@ -3304,6 +3305,7 @@ $ui-header-height: 55px;
.column-header__back-button {
display: flex;
align-items: center;
gap: 5px;
background: $ui-base-color;
border: 0;
font-family: inherit;
@ -3311,23 +3313,19 @@ $ui-header-height: 55px;
cursor: pointer;
white-space: nowrap;
font-size: 16px;
padding: 0 5px 0 0;
padding: 13px;
z-index: 3;
&:hover {
text-decoration: underline;
}
&:last-child {
padding: 0 15px 0 0;
&.compact {
padding-inline-end: 5px;
flex: 0 0 auto;
}
}
.column-back-button__icon {
display: inline-block;
margin-inline-end: 5px;
}
.react-toggle {
display: inline-block;
position: relative;
@ -4013,7 +4011,7 @@ a.status-card {
z-index: 2;
outline: 0;
& > button {
&__title {
display: flex;
align-items: center;
gap: 5px;
@ -4035,8 +4033,18 @@ a.status-card {
}
}
& > .column-header__back-button {
.column-header__back-button + &__title {
padding-inline-start: 0;
}
.column-header__back-button {
flex: 1;
color: $highlight-text-color;
&.compact {
flex: 0 0 auto;
color: $primary-text-color;
}
}
&.active {
@ -4050,6 +4058,18 @@ a.status-card {
&:active {
outline: 0;
}
&__advanced-buttons {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px;
padding-top: 0;
&:first-child {
padding-top: 16px;
}
}
}
.column-header__buttons {
@ -4136,7 +4156,6 @@ a.status-card {
.column-header__collapsible-inner {
background: $ui-base-color;
padding: 15px;
}
.column-header__setting-btn {
@ -4158,20 +4177,8 @@ a.status-card {
}
.column-header__setting-arrows {
float: right;
.column-header__setting-btn {
padding: 5px;
&:first-child {
padding-inline-end: 7px;
}
&:last-child {
padding-inline-start: 7px;
margin-inline-start: 5px;
}
}
display: flex;
align-items: center;
}
.text-btn {
@ -4408,24 +4415,56 @@ a.status-card {
text-align: center;
}
.column-settings__outer {
background: lighten($ui-base-color, 8%);
padding: 15px;
}
.column-settings {
display: flex;
flex-direction: column;
.column-settings__section {
color: $darker-text-color;
cursor: default;
display: block;
font-weight: 500;
margin-bottom: 10px;
}
&__section {
// FIXME: Legacy
color: $darker-text-color;
cursor: default;
display: block;
font-weight: 500;
}
.column-settings__row--with-margin {
margin-bottom: 15px;
.column-header__links {
margin: 0;
}
section {
padding: 16px;
border-bottom: 1px solid lighten($ui-base-color, 8%);
&:last-child {
border-bottom: 0;
}
}
h3 {
font-size: 16px;
line-height: 24px;
letter-spacing: 0.5px;
font-weight: 500;
color: $primary-text-color;
margin-bottom: 16px;
}
&__row {
display: flex;
flex-direction: column;
gap: 12px;
}
.app-form__toggle {
&__toggle > div {
border: 0;
}
}
}
.column-settings__hashtags {
margin-top: 15px;
.column-settings__row {
margin-bottom: 15px;
}
@ -4549,16 +4588,13 @@ a.status-card {
}
.setting-toggle {
display: block;
line-height: 24px;
display: flex;
align-items: center;
gap: 8px;
}
.setting-toggle__label {
color: $darker-text-color;
display: inline-block;
margin-bottom: 14px;
margin-inline-start: 8px;
vertical-align: middle;
}
.limited-account-hint {
@ -6949,29 +6985,33 @@ a.status-card {
background: $ui-base-color;
&__column {
padding: 10px 15px;
padding-bottom: 0;
display: flex;
flex-direction: column;
gap: 15px;
padding: 15px;
}
.radio-button {
display: block;
display: flex;
}
}
.column-settings__row .radio-button {
display: block;
display: flex;
}
.radio-button {
font-size: 14px;
position: relative;
display: inline-block;
padding: 6px 0;
display: inline-flex;
align-items: center;
line-height: 18px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
gap: 10px;
color: $secondary-text-color;
input[type='radio'],
input[type='checkbox'] {
@ -6979,21 +7019,29 @@ a.status-card {
}
&__input {
display: inline-block;
display: block;
position: relative;
border: 1px solid $ui-primary-color;
border: 2px solid $secondary-text-color;
box-sizing: border-box;
width: 18px;
height: 18px;
flex: 0 0 auto;
margin-inline-end: 10px;
top: -1px;
border-radius: 50%;
vertical-align: middle;
&.checked {
border-color: lighten($ui-highlight-color, 4%);
background: lighten($ui-highlight-color, 4%);
border-color: $secondary-text-color;
&::before {
position: absolute;
left: 2px;
top: 2px;
content: '';
display: block;
border-radius: 50%;
width: 10px;
height: 10px;
background: $secondary-text-color;
}
}
}
}
@ -7455,10 +7503,7 @@ noscript {
.button {
flex-shrink: 1;
white-space: nowrap;
@media screen and (max-width: $no-gap-breakpoint) {
min-width: 0;
}
min-width: 80px;
}
.icon-button {
@ -9591,3 +9636,110 @@ noscript {
}
}
}
.filtered-notifications-banner {
display: flex;
align-items: center;
background: $ui-base-color;
border-bottom: 1px solid lighten($ui-base-color, 8%);
padding: 15px;
gap: 15px;
color: $darker-text-color;
text-decoration: none;
&:hover,
&:active,
&:focus {
color: $secondary-text-color;
.filtered-notifications-banner__badge {
background: $secondary-text-color;
}
}
.icon {
width: 24px;
height: 24px;
}
&__text {
flex: 1 1 auto;
font-style: 14px;
line-height: 20px;
strong {
font-size: 16px;
line-height: 24px;
display: block;
}
}
&__badge {
background: $darker-text-color;
color: $ui-base-color;
border-radius: 100px;
padding: 2px 8px;
font-weight: 500;
font-size: 11px;
line-height: 16px;
}
}
.notification-request {
display: flex;
align-items: center;
gap: 16px;
padding: 15px;
border-bottom: 1px solid lighten($ui-base-color, 8%);
&__link {
display: flex;
align-items: center;
gap: 12px;
flex: 1 1 auto;
text-decoration: none;
color: inherit;
overflow: hidden;
.account__avatar {
flex-shrink: 0;
}
}
&__name {
flex: 1 1 auto;
color: $darker-text-color;
font-style: 14px;
line-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
&__display-name {
display: flex;
align-items: center;
gap: 6px;
font-size: 16px;
letter-spacing: 0.5px;
line-height: 24px;
color: $secondary-text-color;
}
.filtered-notifications-banner__badge {
background-color: $highlight-text-color;
border-radius: 4px;
padding: 1px 6px;
}
}
&__actions {
display: flex;
align-items: center;
gap: 8px;
.icon-button {
border-radius: 4px;
border: 1px solid lighten($ui-base-color, 8%);
padding: 5px;
}
}
}

View File

@ -1313,6 +1313,12 @@ code {
font-weight: 600;
}
.hint {
display: block;
font-size: 14px;
color: $darker-text-color;
}
.recommended {
position: absolute;
margin: 0 4px;

View File

@ -2,15 +2,15 @@
class Admin::Metrics::Dimension
DIMENSIONS = {
languages: Admin::Metrics::Dimension::LanguagesDimension,
sources: Admin::Metrics::Dimension::SourcesDimension,
servers: Admin::Metrics::Dimension::ServersDimension,
space_usage: Admin::Metrics::Dimension::SpaceUsageDimension,
software_versions: Admin::Metrics::Dimension::SoftwareVersionsDimension,
tag_servers: Admin::Metrics::Dimension::TagServersDimension,
tag_languages: Admin::Metrics::Dimension::TagLanguagesDimension,
instance_accounts: Admin::Metrics::Dimension::InstanceAccountsDimension,
instance_languages: Admin::Metrics::Dimension::InstanceLanguagesDimension,
languages: LanguagesDimension,
sources: SourcesDimension,
servers: ServersDimension,
space_usage: SpaceUsageDimension,
software_versions: SoftwareVersionsDimension,
tag_servers: TagServersDimension,
tag_languages: TagLanguagesDimension,
instance_accounts: InstanceAccountsDimension,
instance_languages: InstanceLanguagesDimension,
}.freeze
def self.retrieve(dimension_keys, start_at, end_at, limit, params)

View File

@ -2,20 +2,20 @@
class Admin::Metrics::Measure
MEASURES = {
active_users: Admin::Metrics::Measure::ActiveUsersMeasure,
new_users: Admin::Metrics::Measure::NewUsersMeasure,
interactions: Admin::Metrics::Measure::InteractionsMeasure,
opened_reports: Admin::Metrics::Measure::OpenedReportsMeasure,
resolved_reports: Admin::Metrics::Measure::ResolvedReportsMeasure,
tag_accounts: Admin::Metrics::Measure::TagAccountsMeasure,
tag_uses: Admin::Metrics::Measure::TagUsesMeasure,
tag_servers: Admin::Metrics::Measure::TagServersMeasure,
instance_accounts: Admin::Metrics::Measure::InstanceAccountsMeasure,
instance_media_attachments: Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure,
instance_reports: Admin::Metrics::Measure::InstanceReportsMeasure,
instance_statuses: Admin::Metrics::Measure::InstanceStatusesMeasure,
instance_follows: Admin::Metrics::Measure::InstanceFollowsMeasure,
instance_followers: Admin::Metrics::Measure::InstanceFollowersMeasure,
active_users: ActiveUsersMeasure,
new_users: NewUsersMeasure,
interactions: InteractionsMeasure,
opened_reports: OpenedReportsMeasure,
resolved_reports: ResolvedReportsMeasure,
tag_accounts: TagAccountsMeasure,
tag_uses: TagUsesMeasure,
tag_servers: TagServersMeasure,
instance_accounts: InstanceAccountsMeasure,
instance_media_attachments: InstanceMediaAttachmentsMeasure,
instance_reports: InstanceReportsMeasure,
instance_statuses: InstanceStatusesMeasure,
instance_follows: InstanceFollowsMeasure,
instance_followers: InstanceFollowersMeasure,
}.freeze
def self.retrieve(measure_keys, start_at, end_at, params)

View File

@ -15,10 +15,15 @@ module Account::Associations
has_many :favourites, inverse_of: :account, dependent: :destroy
has_many :bookmarks, inverse_of: :account, dependent: :destroy
has_many :mentions, inverse_of: :account, dependent: :destroy
has_many :notifications, inverse_of: :account, dependent: :destroy
has_many :conversations, class_name: 'AccountConversation', dependent: :destroy, inverse_of: :account
has_many :scheduled_statuses, inverse_of: :account, dependent: :destroy
# Notifications
has_many :notifications, inverse_of: :account, dependent: :destroy
has_one :notification_policy, inverse_of: :account, dependent: :destroy
has_many :notification_permissions, inverse_of: :account, dependent: :destroy
has_many :notification_requests, inverse_of: :account, dependent: :destroy
# Pinned statuses
has_many :status_pins, inverse_of: :account, dependent: :destroy
has_many :pinned_statuses, -> { reorder('status_pins.created_at DESC') }, through: :status_pins, class_name: 'Status', source: :status

View File

@ -178,7 +178,7 @@ module Account::Interactions
end
def unblock_domain!(other_domain)
block = domain_blocks.find_by(domain: other_domain)
block = domain_blocks.find_by(domain: normalized_domain(other_domain))
block&.destroy
end
@ -300,4 +300,8 @@ module Account::Interactions
domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, id),
})
end
def normalized_domain(domain)
TagManager.instance.normalize_domain(domain)
end
end

View File

@ -12,6 +12,7 @@
# account_id :bigint(8) not null
# from_account_id :bigint(8) not null
# type :string
# filtered :boolean default(FALSE), not null
#
class Notification < ApplicationRecord
@ -89,7 +90,7 @@ class Notification < ApplicationRecord
end
class << self
def browserable(types: [], exclude_types: [], from_account_id: nil)
def browserable(types: [], exclude_types: [], from_account_id: nil, include_filtered: false)
requested_types = if types.empty?
TYPES
else
@ -99,6 +100,7 @@ class Notification < ApplicationRecord
requested_types -= exclude_types.map(&:to_sym)
all.tap do |scope|
scope.merge!(where(filtered: false)) unless include_filtered || from_account_id.present?
scope.merge!(where(from_account_id: from_account_id)) if from_account_id.present?
scope.merge!(where(type: requested_types)) unless requested_types.size == TYPES.size
end
@ -144,6 +146,8 @@ class Notification < ApplicationRecord
after_initialize :set_from_account
before_validation :set_from_account
after_destroy :remove_from_notification_request
private
def set_from_account
@ -158,4 +162,9 @@ class Notification < ApplicationRecord
self.from_account_id = activity&.id
end
end
def remove_from_notification_request
notification_request = NotificationRequest.find_by(account_id: account_id, from_account_id: from_account_id)
notification_request&.reconsider_existence!
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: notification_permissions
#
# id :bigint(8) not null, primary key
# account_id :bigint(8) not null
# from_account_id :bigint(8) not null
# created_at :datetime not null
# updated_at :datetime not null
#
class NotificationPermission < ApplicationRecord
belongs_to :account
belongs_to :from_account, class_name: 'Account'
end

View File

@ -0,0 +1,36 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: notification_policies
#
# id :bigint(8) not null, primary key
# account_id :bigint(8) not null
# filter_not_following :boolean default(FALSE), not null
# filter_not_followers :boolean default(FALSE), not null
# filter_new_accounts :boolean default(FALSE), not null
# filter_private_mentions :boolean default(TRUE), not null
# created_at :datetime not null
# updated_at :datetime not null
#
class NotificationPolicy < ApplicationRecord
belongs_to :account
has_many :notification_requests, primary_key: :account_id, foreign_key: :account_id, dependent: nil, inverse_of: false
attr_reader :pending_requests_count, :pending_notifications_count
MAX_MEANINGFUL_COUNT = 100
def summarize!
@pending_requests_count = pending_notification_requests.first
@pending_notifications_count = pending_notification_requests.last
end
private
def pending_notification_requests
@pending_notification_requests ||= notification_requests.where(dismissed: false).limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint'))
end
end

View File

@ -0,0 +1,53 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: notification_requests
#
# id :bigint(8) not null, primary key
# account_id :bigint(8) not null
# from_account_id :bigint(8) not null
# last_status_id :bigint(8) not null
# notifications_count :bigint(8) default(0), not null
# dismissed :boolean default(FALSE), not null
# created_at :datetime not null
# updated_at :datetime not null
#
class NotificationRequest < ApplicationRecord
include Paginable
MAX_MEANINGFUL_COUNT = 100
belongs_to :account
belongs_to :from_account, class_name: 'Account'
belongs_to :last_status, class_name: 'Status'
before_save :prepare_notifications_count
def self.preload_cache_collection(requests)
cached_statuses_by_id = yield(requests.filter_map(&:last_status)).index_by(&:id) # Call cache_collection in block
requests.each do |request|
request.last_status = cached_statuses_by_id[request.last_status_id] unless request.last_status_id.nil?
end
end
def reconsider_existence!
return if dismissed?
prepare_notifications_count
if notifications_count.positive?
save
else
destroy
end
end
private
def prepare_notifications_count
self.notifications_count = Notification.where(account: account, from_account: from_account, filtered: true).limit(MAX_MEANINGFUL_COUNT).count
end
end

View File

@ -10,6 +10,7 @@
# text :text default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
# hint :text default(""), not null
#
class Rule < ApplicationRecord
include Discard::Model

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class REST::NotificationPolicySerializer < ActiveModel::Serializer
attributes :filter_not_following,
:filter_not_followers,
:filter_new_accounts,
:filter_private_mentions,
:summary
def summary
{
pending_requests_count: object.pending_requests_count.to_s,
pending_notifications_count: object.pending_notifications_count.to_s,
}
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class REST::NotificationRequestSerializer < ActiveModel::Serializer
attributes :id, :created_at, :updated_at, :notifications_count
belongs_to :from_account, key: :account, serializer: REST::AccountSerializer
belongs_to :last_status, serializer: REST::StatusSerializer
def id
object.id.to_s
end
def notifications_count
object.notifications_count.to_s
end
end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
class REST::RuleSerializer < ActiveModel::Serializer
attributes :id, :text
attributes :id, :text, :hint
def id
object.id.to_s

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
class AcceptNotificationRequestService < BaseService
def call(request)
NotificationPermission.create!(account: request.account, from_account: request.from_account)
UnfilterNotificationsWorker.perform_async(request.id)
end
end

View File

@ -11,126 +11,195 @@ class NotifyService < BaseService
status
).freeze
class DismissCondition
def initialize(notification)
@recipient = notification.account
@sender = notification.from_account
@notification = notification
end
def dismiss?
blocked = @recipient.unavailable?
blocked ||= from_self? && @notification.type != :poll
return blocked if message? && from_staff?
blocked ||= domain_blocking?
blocked ||= @recipient.blocking?(@sender)
blocked ||= @recipient.muting_notifications?(@sender)
blocked ||= conversation_muted?
blocked ||= blocked_mention? if message?
blocked
end
private
def blocked_mention?
FeedManager.instance.filter?(:mentions, @notification.target_status, @recipient)
end
def message?
@notification.type == :mention
end
def from_staff?
@sender.local? && @sender.user.present? && @sender.user_role&.overrides?(@recipient.user_role)
end
def from_self?
@recipient.id == @sender.id
end
def domain_blocking?
@recipient.domain_blocking?(@sender.domain) && !following_sender?
end
def conversation_muted?
@notification.target_status && @recipient.muting_conversation?(@notification.target_status.conversation)
end
def following_sender?
@recipient.following?(@sender)
end
end
class FilterCondition
NEW_ACCOUNT_THRESHOLD = 30.days.freeze
NEW_FOLLOWER_THRESHOLD = 3.days.freeze
def initialize(notification)
@notification = notification
@recipient = notification.account
@sender = notification.from_account
@policy = NotificationPolicy.find_or_initialize_by(account: @recipient)
end
def filter?
return false if override_for_sender?
from_limited? ||
filtered_by_not_following_policy? ||
filtered_by_not_followers_policy? ||
filtered_by_new_accounts_policy? ||
filtered_by_private_mentions_policy?
end
private
def filtered_by_not_following_policy?
@policy.filter_not_following? && not_following?
end
def filtered_by_not_followers_policy?
@policy.filter_not_followers? && not_follower?
end
def filtered_by_new_accounts_policy?
@policy.filter_new_accounts? && new_account?
end
def filtered_by_private_mentions_policy?
@policy.filter_private_mentions? && not_following? && private_mention_not_in_response?
end
def not_following?
!@recipient.following?(@sender)
end
def not_follower?
follow = Follow.find_by(account: @sender, target_account: @recipient)
follow.nil? || follow.created_at > NEW_FOLLOWER_THRESHOLD.ago
end
def new_account?
@sender.created_at > NEW_ACCOUNT_THRESHOLD.ago
end
def override_for_sender?
NotificationPermission.exists?(account: @recipient, from_account: @sender)
end
def from_limited?
@sender.silenced? && not_following?
end
def private_mention_not_in_response?
@notification.type == :mention && @notification.target_status.direct_visibility? && !response_to_recipient?
end
def response_to_recipient?
return false if @notification.target_status.in_reply_to_id.nil?
statuses_that_mention_sender.positive?
end
def statuses_that_mention_sender
Status.count_by_sql([<<-SQL.squish, id: @notification.target_status.in_reply_to_id, recipient_id: @recipient.id, sender_id: @sender.id, depth_limit: 100])
WITH RECURSIVE ancestors(id, in_reply_to_id, mention_id, path, depth) AS (
SELECT s.id, s.in_reply_to_id, m.id, ARRAY[s.id], 0
FROM statuses s
LEFT JOIN mentions m ON m.silent = FALSE AND m.account_id = :sender_id AND m.status_id = s.id
WHERE s.id = :id
UNION ALL
SELECT s.id, s.in_reply_to_id, m.id, st.path || s.id, st.depth + 1
FROM ancestors st
JOIN statuses s ON s.id = st.in_reply_to_id
LEFT JOIN mentions m ON m.silent = FALSE AND m.account_id = :sender_id AND m.status_id = s.id
WHERE st.mention_id IS NULL AND NOT s.id = ANY(path) AND st.depth < :depth_limit
)
SELECT COUNT(*)
FROM ancestors st
JOIN statuses s ON s.id = st.id
WHERE st.mention_id IS NOT NULL AND s.visibility = 3
SQL
end
end
def call(recipient, type, activity)
return if recipient.user.nil?
@recipient = recipient
@activity = activity
@notification = Notification.new(account: @recipient, type: type, activity: @activity)
return if recipient.user.nil? || blocked?
# For certain conditions we don't need to create a notification at all
return if dismiss?
@notification.filtered = filter?
@notification.save!
# It's possible the underlying activity has been deleted
# between the save call and now
return if @notification.activity.nil?
push_notification!
push_to_conversation! if direct_message?
send_email! if email_needed?
if @notification.filtered?
update_notification_request!
else
push_notification!
push_to_conversation! if direct_message?
send_email! if email_needed?
end
rescue ActiveRecord::RecordInvalid
nil
end
private
def blocked_mention?
FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient)
def dismiss?
DismissCondition.new(@notification).dismiss?
end
def following_sender?
return @following_sender if defined?(@following_sender)
@following_sender = @recipient.following?(@notification.from_account) || @recipient.requested?(@notification.from_account)
def filter?
FilterCondition.new(@notification).filter?
end
def optional_non_follower?
@recipient.user.settings['interactions.must_be_follower'] && !@notification.from_account.following?(@recipient)
end
def update_notification_request!
return unless @notification.type == :mention
def optional_non_following?
@recipient.user.settings['interactions.must_be_following'] && !following_sender?
end
def message?
@notification.type == :mention
end
def direct_message?
message? && @notification.target_status.direct_visibility?
end
# Returns true if the sender has been mentioned by the recipient up the thread
def response_to_recipient?
return false if @notification.target_status.in_reply_to_id.nil?
# Using an SQL CTE to avoid unneeded back-and-forth with SQL server in case of long threads
!Status.count_by_sql([<<-SQL.squish, id: @notification.target_status.in_reply_to_id, recipient_id: @recipient.id, sender_id: @notification.from_account.id, depth_limit: 100]).zero?
WITH RECURSIVE ancestors(id, in_reply_to_id, mention_id, path, depth) AS (
SELECT s.id, s.in_reply_to_id, m.id, ARRAY[s.id], 0
FROM statuses s
LEFT JOIN mentions m ON m.silent = FALSE AND m.account_id = :sender_id AND m.status_id = s.id
WHERE s.id = :id
UNION ALL
SELECT s.id, s.in_reply_to_id, m.id, st.path || s.id, st.depth + 1
FROM ancestors st
JOIN statuses s ON s.id = st.in_reply_to_id
LEFT JOIN mentions m ON m.silent = FALSE AND m.account_id = :sender_id AND m.status_id = s.id
WHERE st.mention_id IS NULL AND NOT s.id = ANY(path) AND st.depth < :depth_limit
)
SELECT COUNT(*)
FROM ancestors st
JOIN statuses s ON s.id = st.id
WHERE st.mention_id IS NOT NULL AND s.visibility = 3
SQL
end
def from_staff?
@notification.from_account.local? && @notification.from_account.user.present? && @notification.from_account.user_role&.overrides?(@recipient.user_role)
end
def optional_non_following_and_direct?
direct_message? &&
@recipient.user.settings['interactions.must_be_following_dm'] &&
!following_sender? &&
!response_to_recipient?
end
def hellbanned?
@notification.from_account.silenced? && !following_sender?
end
def from_self?
@recipient.id == @notification.from_account.id
end
def domain_blocking?
@recipient.domain_blocking?(@notification.from_account.domain) && !following_sender?
end
def blocked?
blocked = @recipient.unavailable?
blocked ||= from_self? && @notification.type != :poll
return blocked if message? && from_staff?
blocked ||= domain_blocking?
blocked ||= @recipient.blocking?(@notification.from_account)
blocked ||= @recipient.muting_notifications?(@notification.from_account)
blocked ||= hellbanned?
blocked ||= optional_non_follower?
blocked ||= optional_non_following?
blocked ||= optional_non_following_and_direct?
blocked ||= conversation_muted?
blocked ||= blocked_mention? if @notification.type == :mention
blocked
end
def conversation_muted?
if @notification.target_status
@recipient.muting_conversation?(@notification.target_status.conversation)
else
false
end
notification_request = NotificationRequest.find_or_initialize_by(account_id: @recipient.id, from_account_id: @notification.from_account_id)
notification_request.last_status_id = @notification.target_status.id
notification_request.save
end
def push_notification!
@ -150,6 +219,10 @@ class NotifyService < BaseService
AccountConversation.add_status(@recipient, @notification.target_status)
end
def direct_message?
@notification.type == :mention && @notification.target_status.direct_visibility?
end
def push_to_web_push_subscriptions!
::Web::PushNotificationWorker.push_bulk(web_push_subscriptions.select { |subscription| subscription.pushable?(@notification) }) { |subscription| [subscription.id, @notification.id] }
end

View File

@ -7,5 +7,8 @@
.fields-group
= f.input :text, wrapper: :with_block_label
.fields-group
= f.input :hint, wrapper: :with_block_label
.actions
= f.button :button, t('generic.save_changes'), type: :submit

View File

@ -12,6 +12,9 @@
.fields-group
= f.input :text, wrapper: :with_block_label
.fields-group
= f.input :hint, wrapper: :with_block_label
.actions
= f.button :button, t('admin.rules.add_new'), type: :submit

View File

@ -20,6 +20,7 @@
- @rules.each do |rule|
%li
.rules-list__text= rule.text
.rules-list__hint= rule.hint
.stacked-actions
- accept_path = @invite_code.present? ? public_invite_url(invite_code: @invite_code, accept: @accept_token) : new_user_registration_path(accept: @accept_token)

View File

@ -42,11 +42,3 @@
label_method: ->(setting) { I18n.t("simple_form.labels.notification_emails.software_updates.#{setting}") },
label: I18n.t('simple_form.labels.notification_emails.software_updates.label'),
wrapper: :with_label
%h4= t 'notifications.other_settings'
.fields-group
= f.simple_fields_for :settings, current_user.settings do |ff|
= ff.input :'interactions.must_be_follower', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_follower')
= ff.input :'interactions.must_be_following', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_following')
= ff.input :'interactions.must_be_following_dm', wrapper: :with_label, label: I18n.t('simple_form.labels.interactions.must_be_following_dm')

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
class UnfilterNotificationsWorker
include Sidekiq::Worker
def perform(notification_request_id)
@notification_request = NotificationRequest.find(notification_request_id)
push_to_conversations!
unfilter_notifications!
remove_request!
rescue ActiveRecord::RecordNotFound
true
end
private
def push_to_conversations!
notifications_with_private_mentions.find_each { |notification| AccountConversation.add_status(@notification_request.account, notification.target_status) }
end
def unfilter_notifications!
filtered_notifications.in_batches.update_all(filtered: false)
end
def remove_request!
@notification_request.destroy!
end
def filtered_notifications
Notification.where(account: @notification_request.account, from_account: @notification_request.from_account, filtered: true)
end
def notifications_with_private_mentions
filtered_notifications.joins(mention: :status).merge(Status.where(visibility: :direct)).includes(mention: :status)
end
end

View File

@ -1,10 +1,7 @@
# frozen_string_literal: true
# TODO
# Starting with Rails 7.0, the framework default here is to set this true.
# However, we have a location in devise that redirects where we don't have an
# easy ability to override the method or set a config option, and where the
# redirect does not supply this option itself.
# https://github.com/heartcombo/devise/blob/v4.9.2/app/controllers/devise/confirmations_controller.rb#L28
# Once a solution is found, this line can be removed.
# TODO: Starting with Rails 7.0, the framework default is true for this setting.
# This location in devise redirects and we can't hook in or override:
# https://github.com/heartcombo/devise/blob/v4.9.3/app/controllers/devise/confirmations_controller.rb#L28
# When solution is found, this setting can go back to default.
Rails.application.config.action_controller.raise_on_open_redirects = false

View File

@ -19,7 +19,7 @@ kab:
account:
attributes:
username:
invalid: isekkilen, uṭṭunen d yijerriden n wadda kan
invalid: ilaq ad ilin isekkilen, uṭṭunen d yijerriden n wadda kan
reserved: yettwaṭṭef
status:
attributes:

View File

@ -7,11 +7,11 @@ sk:
options: Voľby
user:
agreement: Dohoda o poskytovaní služieb
email: Emailová adresa
email: E-mailová adresa
locale: Jazyk
password: Heslo
user/account:
username: Meno používateľa
username: Používateľské meno
user/invite_request:
text: Dôvod
errors:
@ -41,9 +41,9 @@ sk:
attributes:
email:
blocked: používa nepovoleného poskytovateľa e-mailu
unreachable: zdá sa, že neexistuje
unreachable: vyzerá, že neexistuje
role_id:
elevated: nemôže byť vyššia ako vaša súčasná rola
elevated: nemôže byť viac ako vaša súčasná rola
user_role:
attributes:
permissions_as_keys:
@ -51,9 +51,9 @@ sk:
elevated: nemôže obsahovať povolenia, ktoré vaša aktuálna rola nemá
own_role: nie je možné zmeniť s vašou aktuálnou rolou
position:
elevated: nemôže byť vyššia ako vaša súčasná rola
elevated: nemôže byť viac ako vaša súčasná rola
own_role: nie je možné zmeniť s vašou aktuálnou rolou
webhook:
attributes:
events:
invalid_permissions: nemožno zahrnúť udalosti, ku ktorým nemáte práva
invalid_permissions: nemôže zahrnúť udalosti, ku ktorým nemáte práva

View File

@ -173,5 +173,3 @@ af:
warning:
title:
silence: Rekening beperk
welcome:
edit_profile_action: Stel profiel op

View File

@ -1288,7 +1288,6 @@ an:
notifications:
email_events: Eventos pa notificacions per correu electronico
email_events_hint: 'Tría los eventos pa los quals deseyas recibir notificacions:'
other_settings: Atros achustes de notificacions
number:
human:
decimal_units:
@ -1597,8 +1596,6 @@ an:
silence: Cuenta limitada
suspend: Cuenta suspendida
welcome:
edit_profile_action: Configurar lo perfil
edit_profile_step: Puetz personalizar lo tuyo perfil puyando una foto de perfil, cambiando lo tuyo nombre d'usuario y muito mas. Puetz optar per revisar a los nuevos seguidores antes que puedan seguir-te.
explanation: Aquí i hai qualques consellos pa empecipiar
subject: Bienveniu a Mastodon
title: Te damos la bienvenida a bordo, %{name}!

View File

@ -1594,7 +1594,6 @@ ar:
administration_emails: إشعارات البريد الإلكتروني الإدارية
email_events: الأحداث للإشعارات عبر البريد الإلكتروني
email_events_hint: 'اختر الأحداث التي تريد أن تصِلَك اشعارات عنها:'
other_settings: إعدادات أخرى للإشعارات
number:
human:
decimal_units:
@ -1966,8 +1965,6 @@ ar:
silence: الحساب محدود
suspend: الحساب مُعلَّق
welcome:
edit_profile_action: تهيئة الملف التعريفي
edit_profile_step: يمكنك تخصيص ملفك الشخصي عن طريق رفع صورة ملفك الشخصي, تغيير اسم العرض الخاص بك والمزيد. يمكنك اختيار مراجعة المتابعين الجدد قبل السماح لهم بمتابعتك.
explanation: ها هي بعض النصائح قبل بداية الاستخدام
subject: أهلًا بك على ماستدون
title: أهلاً بك، %{name}!

View File

@ -695,7 +695,6 @@ ast:
notifications:
email_events: Unviu d'avisos per corréu electrónicu
email_events_hint: 'Seleiciona los eventos de los que quies recibir avisos:'
other_settings: Configuración d'otros avisos
number:
human:
decimal_units:
@ -900,8 +899,6 @@ ast:
none: Alvertencia
suspend: Cuenta suspendida
welcome:
edit_profile_action: Configurar el perfil
edit_profile_step: Pues personalizar el perfil pente la xuba d'una semeya, el cambéu del nome visible ya muncho más. Tamién, si lo prefieres, pues revisar los perfiles nuevos enantes de que puedan siguite.
explanation: Equí tienes dalgunos conseyos pa que comiences
subject: Afáyate en Mastodon
title: "¡Afáyate, %{name}!"

View File

@ -1547,7 +1547,6 @@ be:
administration_emails: Апавяшчэнні эл. пошты для адміністратара
email_events: Падзеі для апавяшчэнняў эл. пошты
email_events_hint: 'Выберыце падзеі, аб якіх вы хочаце атрымліваць апавяшчэнні:'
other_settings: Іншыя налады апавяшчэнняў
number:
human:
decimal_units:
@ -1907,9 +1906,42 @@ be:
silence: Уліковы запіс абмежаваны
suspend: Уліковы запіс выключаны
welcome:
edit_profile_action: Наладзіць профіль
edit_profile_step: Вы можаце наладзіць свой профіль, запампаваўшы выяву профілю, змяніўшы адлюстраванае імя і іншае. Вы можаце праглядаць новых падпісчыкаў, перш чым ім будзе дазволена падпісацца на вас.
apps_android_action: Спампаваць з Google Play
apps_ios_action: Спампваваць з App Store
apps_step: Спампуйце нашыя афіцыйныя праграмы.
apps_title: Кліенты Mastodon
checklist_subtitle: 'Давайце паспрабуем разабрацца ў гэтай новай сацыяльнай сетцы:'
checklist_title: З чаго пачаць
edit_profile_action: Персаналізаваць
edit_profile_step: Узмацніце ўзаемадзеянне, запоўніўшы поўны профіль.
edit_profile_title: Наладзьце свой профіль
explanation: Вось некаторыя парады каб пачаць
feature_action: Даведацца больш
feature_audience: Mastodon дае ўнікальную магчымасць кіраваць сваёй аўдыторыяй без пасрэднікаў. Маючы сервер Mastodon, разгорнуты на ўласнай інфраструктуры, яго карыстальнікі могуць узаемадзейнічаць з любым іншым серверам Mastodon, не аддаючы кантроль у чужыя рукі.
feature_audience_title: Фармуйце сваю аўдыторыю з упэўненасцю
feature_control: Толькі вы дакладна ведаеце, што хочаце бачыць на сваім серверы. Ніякіх алгарытмаў або рэкламы, якія марнуюць ваш час. Сачыце за любым серверам Mastodon з аднаго ўліковага запісу і атрымлівайце паведамленні ў храналагічным парадку, каб ваш куток Інтэрнэту быў крыху падобны на вас.
feature_control_title: Кіруйце сваёй стужкай
feature_creativity: Mastodon падтрымлівае публікацыі з аўдыя, відэа і малюнкамі, апісаннем даступнасці, апытаннямі, папярэджаннямі аб змесце, аніміраванымі аватарамі, карыстальніцкімі эмодзі, мініяцюрамі, элементамі кіравання абрэзкай мініяцюр і іншым. Незалежна ад таго, дзеліцеся вы сваім мастацтвам, музыкай або падкастам, Mastodon тут для вас.
feature_creativity_title: Неабмежаваны творчы патэнцыял
feature_moderation: Mastodon вяртае прыняцце рашэнняў у вашыя рукі. У адрозненне ад сацыяльных сетак, якія належаць карпарацыям, якія спускаюць свае правілы зверху, кожны сервер Mastodon усталёўвае свае правілы і нормы, якія выконваюцца на мясцовым узроўні, што робіць іх найболей гнуткімі ў задавальненні запатрабаванняў розных груп людзей. Далучайцеся да сервера з правіламі, з якімі вы згодны, ці стварыце свой уласны.
feature_moderation_title: Мадэрацыя, якой яна павінна быць
follow_action: Падпісацца
follow_step: Падпіска на цікавых людзей - гэта галоўнае ў Mastodon.
follow_title: Наладзьце сваю хатнюю стужку
follows_subtitle: Падпішыцеся на папулярных карыстальнікаў
follows_title: На каго падпісацца
follows_view_more: Прагледзець больш людзей, на якіх варта падпісацца
hashtags_recent_count: "%{people} людзей за апошнія %{days} дні"
hashtags_subtitle: Даведайцеся што было папулярна ў апошнія 2 дні
hashtags_title: Папулярныя хэштэгі
hashtags_view_more: Прагледзець іншыя папулярныя хэштэгі
post_action: Стварыць
post_step: Скажыце ўсім прывітанне з дапамогай тэксту, фатаграфій, відэа і апытанняў.
post_title: Стварыце свой першы допіс
share_action: Абагуліць
share_step: Няхай вашыя сябры ведаюць, як знайсці вас у Mastodon.
share_title: Абагульце ваш профіль у Mastodon
sign_in_action: Увайсці
subject: Вітаем у Mastodon
title: Рады вітаць вас, %{name}!
users:

View File

@ -767,6 +767,7 @@ bg:
disabled: До никого
users: До влезнали локални потребители
registrations:
moderation_recommandation: Уверете се, че имате адекватен и реактивен модераторски екип преди да отворите регистриранията за всеки!
preamble: Управлява кой може да създава акаунт на сървъра ви.
title: Регистрации
registrations_mode:
@ -774,6 +775,7 @@ bg:
approved: Изисква се одобрение за регистриране
none: Никой не може да се регистрира
open: Всеки може да се регистрира
warning_hint: Препоръчваме употребата на „Изисква се одобрение за регистриране“, освен ако сте уверени, че екипът ви за модериране може да се справи със спама и зловредните регистрирания своевременно.
security:
authorized_fetch: Изисква се удостоверяване от федеративни сървъри
authorized_fetch_hint: Изискването удостоверяване от феративните сървъри позволява по-строго прилагане на блокирания както на ниво потребител, така и на ниво сървър. Това обаче снижава производителността, намалява обхвата на вашите отговори и може да възникнат проблеми със съвместимостта с някои федеративни услуги. Освен това, то не пречи на посветени участници да извличат вашите обществени публикации и акаунти.
@ -966,6 +968,9 @@ bg:
title: Уебкуки
webhook: Уебкука
admin_mailer:
auto_close_registrations:
body: Поради липса на скорошна дейност по модериране, регистрациите на %{instance} бяха самодейно превключени в режим, изискващ ръчна проверка, за да се предотврати употребата на %{instance} като платформа за потенциални зложелатели. Може да превключите обратно в режим „отворено регистриране“ по всяко време.
subject: Регистриранията за %{instance} са самодейно превключени към изискване на одобрение
new_appeal:
actions:
delete_statuses: за изтриване на публикациите им
@ -1009,7 +1014,7 @@ bg:
remove: Разкачвне на псевдонима
appearance:
advanced_web_interface: Разширен уеб интерфейс
advanced_web_interface_hint: 'Ако желаете да се възползвате от цялата ширина на своя екран, разширеният уеб интерфейс ще ви позволи да настроите няколко различни колони, за да виждате едновременно различна информация: Начало, известия, федерирана хронология, множество списъци и хаштагове.'
advanced_web_interface_hint: 'Ако искате да употребявате цялата ширина на екрана си, разширеният уеб интерфейс ви позволява да настроите най-различни колони, за да виждате едновременно множество сведения, колкото искате: Начало, известия, федеративен инфоканал, произволен брой списъци и хаштагове.'
animations_and_accessibility: Анимация и достъпност
confirmation_dialogs: Диалогов прозорец за потвърждение
discovery: Откриване
@ -1490,7 +1495,6 @@ bg:
administration_emails: Администраторски известия по имейла
email_events: Събития за известия по имейл
email_events_hint: 'Изберете събития, за които искате да получавате известия:'
other_settings: Настройки за други известия
number:
human:
decimal_units:
@ -1838,9 +1842,42 @@ bg:
silence: Акаунтът има ограничение
suspend: Акаунтът е спрян
welcome:
edit_profile_action: Настройване на профила
edit_profile_step: Може да настроите профила си, качвайки снимката на профила, променяйки показваното си име и други неща. Може да се включите за преглед на нови последователи преди да бъдат позволени да ви последват.
apps_android_action: Вземане от Google Play
apps_ios_action: Изтегляне в App Store
apps_step: Изтегляне на служебните ни приложения.
apps_title: Приложения на Mastodon
checklist_subtitle: 'Нека започнем приключение в тази нова социална граница:'
checklist_title: Добре дошли при контролния списък
edit_profile_action: Персонализиране
edit_profile_step: Подсилете взаимодействията си, изграждайки цялостен профил.
edit_profile_title: Пригодете профила си
explanation: Ето няколко стъпки за начало
feature_action: Научете повече
feature_audience: Mastodon ви осигурява с неповторимата възможност на управление на публиката ви без посредници. Mastodon се разгръща на ваша собствена инфраструктура, позволяваща ви да следвате и да бъдете последвани от всеки друг сървър на Mastodon в мрежата и не е под ничий контрол освен ваш.
feature_audience_title: Изградете публиката си с увереност
feature_control: Вие знаете най-добре какво искате да виждате на началния си инфоканал. Няма алгоритми или реклами, за да ви губят времето. Последвате всекиго през всеки сървър на Mastodon от един акаунт и получавате публикациите им в хронологичен ред, а и правете свое кътче в интернет малко по-подобно на вас.
feature_control_title: Поддържайте управлението на часовата си ос
feature_creativity: Mastodon поддържа публикации със звук, картина и видео, описания на достъпността, анкети, предупреждения за съдържание, анимирани аватари, потребителски емоджита, контрол на изрязване на миниобрази и още, за да ви помогнат да се изразите в мрежата. Независимо дали публикувате свое изкуство, музика или свой подкаст, то Mastodon е там за вас.
feature_creativity_title: Несравнимо творчество
feature_moderation: Mastodon връща вземането на решения в ръцете ви. Всеки сървър сътворява свои правила и регулации, прилагащи се локално, а не отгоре надолу като корпоративна социална медия, което го прави най-гъвкав в отговор на нуждите на различни групи хора. Присъединете се към сървър, с който сте съгласни, или пък си хоствайте свой.
feature_moderation_title: Модерирайте начина, по който трябва да е
follow_action: Последване
follow_step: Последването на интересни хора е основната цел на Mastodon.
follow_title: Персонализиране на началния ви инфоканал
follows_subtitle: Следвайте добре известни акаунти
follows_title: Кого да се последва
follows_view_more: Преглед на още хора за последване
hashtags_recent_count: "%{people} души за последните %{days} дни"
hashtags_subtitle: Проучете какво изгрява от последните 2 дни
hashtags_title: Изгряващи хаштагове
hashtags_view_more: Преглед на още изгряващи хаштагове
post_action: Съставяне
post_step: Поздравете света с текст, снимки, видео или анкети.
post_title: Направете първата си публикация
share_action: Споделяне
share_step: Позволете на приятелите си да знаят как да ви намират в Mastodon.
share_title: Споделете профила си в Mastodon
sign_in_action: Вход
subject: Добре дошли в Mastodon
title: Добре дошли на борда, %{name}!
users:

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