Compare commits

..

11 Commits

Author SHA1 Message Date
kouhai 4e52502719 th: things should build. please build.
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-07-04 11:02:49 -07:00
kouhai a126a2733f th: invite quota 2024-07-04 10:00:34 -07:00
kouhai 41adbcaa80 th: treehouse version
Co-authored-by: Ariadne Conill <ariadne@dereferenced.org>
2024-07-04 10:00:22 -07:00
kouhai 2f61b9a11e th: add config for unsafe throttle deactivation
Suggested-by: Ariadne Conill <ariadne@dereferenced.org>
2024-07-04 10:00:22 -07:00
kouhai c3cfa23eff th: automod 2024-07-04 10:00:21 -07:00
kouhai 8ce73ff257 th: fork docs and configuration
Co-authored-by: Rin <rin@rin.systems>
Co-authored-by: fox <fox@neko.business>
2024-07-04 10:00:15 -07:00
kouhai 0f4eee9c94 th: ci and image builds
Co-authored-by: Ariadne Conill <ariadne@dereferenced.org>
2024-07-04 09:57:55 -07:00
kouhai 097880191e th: packages and deps 2024-07-04 09:57:55 -07:00
kouhai da813d46db th: custom instance icons from th contributors
Co-authored-by: Ariadne Conill <ariadne@dereferenced.org>
Co-authored-by: treehouse contributors and staff <staff+contributors@treehouse.systems>
2024-07-04 09:57:33 -07:00
Ariadne Conill 86d566af3e th: config: CSP: allow unsafe-eval (script) and unsafe-inline (style)
th: config: CSP: add unsafe-eval for scripts

th: config: CSP: allow unsafe-inline for CSS

Rebased-by: kouhai <kouhai@treehouse.systems>
2024-07-04 09:56:51 -07:00
Ariadne Conill 61feb28111 th: quotes
Maintained-by: kouhai <kouhai@treehouse.systems>
2024-07-04 09:56:07 -07:00
208 changed files with 2190 additions and 2485 deletions

View File

@ -1,5 +1,5 @@
# This is a sample configuration file. You can generate your configuration
# with the `bundle exec rails mastodon:setup` interactive setup wizard, but to customize
# with the `rake mastodon:setup` interactive setup wizard, but to customize
# your setup even further, you'll need to edit it manually. This sample does
# not demonstrate all available configuration options. Please look at
# https://docs.joinmastodon.org/admin/config/ for the full documentation.
@ -69,7 +69,7 @@ DB_PORT=5432
# Secrets
# -------
# Generate each with the `RAILS_ENV=production bundle exec rails secret` task (`docker-compose run --rm web bundle exec rails secret` if you use docker compose)
# Generate each with the `RAILS_ENV=production bundle exec rake secret` task (`docker-compose run --rm web bundle exec rake secret` if you use docker compose)
# -------
SECRET_KEY_BASE=
OTP_SECRET=
@ -77,7 +77,7 @@ OTP_SECRET=
# Web Push
# --------
# Generate with `bundle exec rails mastodon:webpush:generate_vapid_key` (first is the private key, second is the public one)
# Generate with `rake mastodon:webpush:generate_vapid_key` (first is the private key, second is the public one)
# You should only generate this once per instance. If you later decide to change it, all push subscription will
# be invalidated, requiring the users to access the website again to resubscribe.
# --------

View File

@ -1,10 +1,8 @@
name: Bundler Audit
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
branches-ignore:
- 'dependabot/**'
paths:
- 'Gemfile*'
- '.ruby-version'

View File

@ -2,13 +2,9 @@ name: Check i18n
on:
push:
branches:
- 'main'
- 'stable-*'
branches: [main]
pull_request:
branches:
- 'main'
- 'stable-*'
branches: [main]
env:
RAILS_ENV: test

View File

@ -1,15 +1,11 @@
name: 'CodeQL'
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
branches: ['main']
pull_request:
branches:
- 'main'
- 'stable-*'
# The branches below must be a subset of the branches above
branches: ['main']
schedule:
- cron: '22 6 * * 1'

View File

@ -1,11 +1,9 @@
name: Crowdin / Upload translations
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
- main
paths:
- crowdin-glitch.yml
- app/javascript/flavours/glitch/locales/en.json

View File

@ -1,10 +1,6 @@
name: Check formatting
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
pull_request:
jobs:

View File

@ -1,10 +1,9 @@
name: CSS Linting
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
branches-ignore:
- 'dependabot/**'
- 'renovate/**'
paths:
- 'package.json'
- 'yarn.lock'

View File

@ -1,10 +1,9 @@
name: Haml Linting
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
branches-ignore:
- 'dependabot/**'
- 'renovate/**'
paths:
- '.github/workflows/haml-lint-problem-matcher.json'
- '.github/workflows/lint-haml.yml'

View File

@ -1,10 +1,9 @@
name: JavaScript Linting
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
branches-ignore:
- 'dependabot/**'
- 'renovate/**'
paths:
- 'package.json'
- 'yarn.lock'

View File

@ -1,10 +1,9 @@
name: Ruby Linting
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
branches-ignore:
- 'dependabot/**'
- 'renovate/**'
paths:
- 'Gemfile*'
- '.rubocop*.yml'

View File

@ -1,10 +1,9 @@
name: JavaScript Testing
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
branches-ignore:
- 'dependabot/**'
- 'renovate/**'
paths:
- 'package.json'
- 'yarn.lock'

View File

@ -1,29 +1,29 @@
name: Historical data migration test
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
paths:
- 'Gemfile*'
- '.ruby-version'
- '**/*.rb'
- '.github/workflows/test-migrations.yml'
- 'lib/tasks/tests.rake'
branches-ignore:
- 'dependabot/**'
- 'renovate/**'
pull_request:
paths:
- 'Gemfile*'
- '.ruby-version'
- '**/*.rb'
- '.github/workflows/test-migrations.yml'
- 'lib/tasks/tests.rake'
jobs:
pre_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
paths: '["Gemfile*", ".ruby-version", "**/*.rb", ".github/workflows/test-migrations.yml", "lib/tasks/tests.rake"]'
test:
runs-on: ubuntu-latest
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
strategy:
fail-fast: false

View File

@ -1,11 +1,10 @@
name: Ruby Testing
on:
merge_group:
push:
branches:
- 'main'
- 'stable-*'
branches-ignore:
- 'dependabot/**'
- 'renovate/**'
pull_request:
env:
@ -224,7 +223,7 @@ jobs:
- name: Load database schema
run: './bin/rails db:create db:schema:load db:seed'
- run: bin/rspec --tag attachment_processing
- run: bin/rspec --tag paperclip_processing
- name: Upload coverage reports to Codecov
if: matrix.ruby-version == '.ruby-version'

View File

@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-offense-counts --no-auto-gen-timestamp`
# using RuboCop version 1.65.0.
# using RuboCop version 1.64.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@ -14,7 +14,7 @@ Lint/NonLocalExitFromIterator:
Metrics/AbcSize:
Max: 90
# Configuration parameters: CountBlocks, CountModifierForms, Max.
# Configuration parameters: CountBlocks, Max.
Metrics/BlockNesting:
Exclude:
- 'lib/tasks/mastodon.rake'

View File

@ -1 +1 @@
3.3.4
3.3.3

893
.yarn/releases/yarn-4.1.0.cjs vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -8,4 +8,4 @@ logFilters:
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-4.3.1.cjs
yarnPath: .yarn/releases/yarn-4.1.0.cjs

View File

@ -12,7 +12,7 @@ ARG BUILDPLATFORM=${BUILDPLATFORM}
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.3.x"]
# renovate: datasource=docker depName=docker.io/ruby
ARG RUBY_VERSION="3.3.4"
ARG RUBY_VERSION="3.3.3"
# # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
# renovate: datasource=node-version depName=node
ARG NODE_MAJOR_VERSION="20"
@ -69,9 +69,7 @@ ENV \
# Optimize jemalloc 5.x performance
MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \
# Enable libvips, should not be changed
MASTODON_USE_LIBVIPS=true \
# Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes
MASTODON_SIDEKIQ_READY_FILENAME=sidekiq_process_has_started_and_will_begin_processing_jobs
MASTODON_USE_LIBVIPS=true
# Set default shell used for running commands
SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"]

View File

@ -159,7 +159,7 @@ GEM
case_transform (0.2)
activesupport
cbor (0.5.9.8)
charlock_holmes (0.7.9)
charlock_holmes (0.7.8)
chewy (7.6.0)
activesupport (>= 5.2)
elasticsearch (>= 7.14.0, < 8)
@ -180,7 +180,7 @@ GEM
css_parser (1.17.1)
addressable
csv (3.3.0)
database_cleaner-active_record (2.2.0)
database_cleaner-active_record (2.1.0)
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
@ -280,7 +280,7 @@ GEM
fog-openstack (1.1.3)
fog-core (~> 2.1)
fog-json (>= 1.0)
foreman (0.88.1)
foreman (0.87.2)
formatador (1.1.0)
fugit (1.10.1)
et-orbi (~> 1, >= 1.2.7)
@ -347,7 +347,7 @@ GEM
activesupport (>= 3.0)
nokogiri (>= 1.6)
io-console (0.7.2)
irb (1.14.0)
irb (1.13.2)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jmespath (1.6.2)
@ -584,15 +584,15 @@ GEM
orm_adapter (0.5.0)
ox (2.14.18)
parallel (1.25.1)
parser (3.3.4.0)
parser (3.3.3.0)
ast (~> 2.4.1)
racc
parslet (2.0.0)
pastel (0.8.0)
tty-color (~> 0.5)
pg (1.5.6)
pghero (3.6.0)
activerecord (>= 6.1)
pghero (3.5.0)
activerecord (>= 6)
premailer (1.23.0)
addressable
css_parser (>= 1.12.0)
@ -734,13 +734,13 @@ GEM
rspec-mocks (~> 3.0)
sidekiq (>= 5, < 8)
rspec-support (3.13.1)
rubocop (1.65.0)
rubocop (1.64.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.4, < 3.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.31.1, < 2.0)
ruby-progressbar (~> 1.7)
@ -757,7 +757,7 @@ GEM
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rspec (3.0.3)
rubocop-rspec (3.0.2)
rubocop (~> 1.61)
rubocop-rspec_rails (2.30.0)
rubocop (~> 1.61)
@ -794,10 +794,10 @@ GEM
redis (>= 4.5.0, < 5)
sidekiq-bulk (0.2.0)
sidekiq
sidekiq-scheduler (5.0.5)
sidekiq-scheduler (5.0.3)
rufus-scheduler (~> 3.2)
sidekiq (>= 6, < 8)
tilt (>= 1.4.0, < 3)
tilt (>= 1.4.0)
sidekiq-unique-jobs (7.1.33)
brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
concurrent-ruby (~> 1.0, >= 1.0.5)

View File

@ -28,14 +28,14 @@ class Api::V1::Notifications::RequestsController < Api::BaseController
end
def dismiss
@request.destroy!
@request.update!(dismissed: true)
render_empty
end
private
def load_requests
requests = NotificationRequest.where(account: current_account).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id(
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)
)
@ -68,4 +68,8 @@ class Api::V1::Notifications::RequestsController < Api::BaseController
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

@ -8,7 +8,7 @@ class Api::V1::Polls::VotesController < Api::BaseController
before_action :set_poll
def create
VoteService.new.call(current_account, @poll, vote_params)
VoteService.new.call(current_account, @poll, vote_params[:choices])
render json: @poll, serializer: REST::PollSerializer
end
@ -22,6 +22,6 @@ class Api::V1::Polls::VotesController < Api::BaseController
end
def vote_params
params.require(:choices)
params.permit(choices: [])
end
end

View File

@ -333,7 +333,7 @@ export function doodleSet(options) {
export function uploadCompose(files) {
return function (dispatch, getState) {
const uploadLimit = getState().getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments']);
const uploadLimit = 4;
const media = getState().getIn(['compose', 'media_attachments']);
const pending = getState().getIn(['compose', 'pending_media_attachments']);
const progress = new Array(files.length).fill(0);
@ -353,7 +353,7 @@ export function uploadCompose(files) {
dispatch(uploadComposeRequest());
for (const [i, f] of Array.from(files).entries()) {
if (media.size + i > (uploadLimit - 1)) break;
if (media.size + i > 3) break;
resizeImage(f).then(file => {
const data = new FormData();

View File

@ -131,7 +131,7 @@ const Account = ({ size = 46, account, onFollow, onBlock, onMute, onMuteNotifica
return (
<div className={classNames('account', { 'account--minimal': minimal })}>
<div className='account__wrapper'>
<Permalink key={account.get('id')} className='account__display-name' title={account.get('acct')} href={account.get('url')} to={`/@${account.get('acct')}`} data-hover-card-account={account.get('id')}>
<Permalink key={account.get('id')} className='account__display-name' title={account.get('acct')} href={account.get('url')} to={`/@${account.get('acct')}`}>
<div className='account__avatar-wrapper'>
<Avatar account={account} size={size} />
</div>

View File

@ -43,7 +43,6 @@ export const HoverCardController: React.FC = () => {
useEffect(() => {
let isScrolling = false;
let currentAnchor: HTMLElement | null = null;
let currentTitle: string | null = null;
const open = (target: HTMLElement) => {
target.setAttribute('aria-describedby', 'hover-card');
@ -76,9 +75,6 @@ export const HoverCardController: React.FC = () => {
currentAnchor?.removeAttribute('aria-describedby');
currentAnchor = target;
currentTitle = target.getAttribute('title');
target.removeAttribute('title');
setEnterTimeout(() => {
open(target);
}, enterDelay);
@ -94,20 +90,11 @@ export const HoverCardController: React.FC = () => {
};
const handleMouseLeave = (e: MouseEvent) => {
const { target } = e;
if (!currentAnchor) {
return;
}
if (
currentTitle &&
target instanceof HTMLElement &&
target === currentAnchor
)
target.setAttribute('title', currentTitle);
if (target === currentAnchor || target === cardRef.current) {
if (e.target === currentAnchor || e.target === cardRef.current) {
cancelEnterTimeout();
setLeaveTimeout(() => {

View File

@ -311,7 +311,7 @@ class MediaGallery extends PureComponent {
render () {
const { media, lang, intl, sensitive, letterbox, fullwidth, defaultWidth, autoplay } = this.props;
const { visible } = this.state;
const size = media.size;
const size = media.take(4).size;
const uncached = media.every(attachment => attachment.get('type') === 'unknown');
const width = this.state.width || defaultWidth;
@ -331,7 +331,7 @@ class MediaGallery extends PureComponent {
if (this.isStandaloneEligible()) {
children = <Item standalone autoplay={autoplay} onClick={this.handleClick} attachment={media.get(0)} lang={lang} displayWidth={width} visible={visible} />;
} else {
children = media.map((attachment, i) => <Item key={attachment.get('id')} autoplay={autoplay} onClick={this.handleClick} attachment={attachment} index={i} lang={lang} size={size} letterbox={letterbox} displayWidth={width} visible={visible || uncached} />);
children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} autoplay={autoplay} onClick={this.handleClick} attachment={attachment} index={i} lang={lang} size={size} letterbox={letterbox} displayWidth={width} visible={visible || uncached} />);
}
if (uncached) {

View File

@ -118,7 +118,7 @@ class StatusActionBar extends ImmutablePureComponent {
};
handleQuoteClick = () => {
const { signedIn } = this.props.identity;
const { signedIn } = this.context.identity;
if (signedIn) {
this.props.onQuote(this.props.status, this.props.history);

View File

@ -182,7 +182,7 @@ class StatusContent extends PureComponent {
if (mention) {
link.addEventListener('click', this.onMentionClick.bind(this, mention), false);
link.setAttribute('title', `@${mention.get('acct')}`);
link.removeAttribute('title');
link.setAttribute('data-hover-card-account', mention.get('id'));
if (rewriteMentions !== 'no') {
while (link.firstChild) link.removeChild(link.firstChild);

View File

@ -51,7 +51,6 @@ export default class StatusHeader extends PureComponent {
target='_blank'
onClick={this.handleAccountClick}
rel='noopener noreferrer'
title={status.getIn(['account', 'acct'])}
data-hover-card-account={status.getIn(['account', 'id'])}
>
<div className='status__avatar'>

View File

@ -257,6 +257,7 @@ class ComposeForm extends ImmutablePureComponent {
return (
<form className='compose-form' onSubmit={this.handleSubmit}>
<ReplyIndicator />
{/* <QuoteIndicatorContainer /> */}
{!withoutNavigation && <NavigationBar />}
<WarningContainer />

View File

@ -22,7 +22,6 @@ export const NavigationBar = () => {
const intl = useIntl();
const account = useSelector(state => state.getIn(['accounts', me]));
const isReplying = useSelector(state => !!state.getIn(['compose', 'in_reply_to']));
const isQuoting = useSelector(state => !!state.getIn(['compose', 'quote_id']));
const handleCancelClick = useCallback(() => {
dispatch(cancelReplyCompose());
@ -31,7 +30,7 @@ export const NavigationBar = () => {
return (
<div className='navigation-bar'>
<Account account={account} minimal />
{(isReplying || isQuoting) ? <IconButton title={intl.formatMessage(messages.cancel)} iconComponent={CloseIcon} onClick={handleCancelClick} /> : <ActionBar />}
{isReplying ? <IconButton title={intl.formatMessage(messages.cancel)} iconComponent={CloseIcon} onClick={handleCancelClick} /> : <ActionBar />}
</div>
);
};

View File

@ -0,0 +1,85 @@
// Package imports.
import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
import AttachmentList from 'flavours/glitch/components/attachment_list';
import { WithOptionalRouterPropTypes, withOptionalRouter } from 'flavours/glitch/utils/react_router';
import { Avatar } from '../../../components/avatar';
import { DisplayName } from '../../../components/display_name';
import { Icon } from '../../../components/icon';
import { IconButton } from '../../../components/icon_button';
// Messages.
const messages = defineMessages({
cancel: {
defaultMessage: 'Cancel',
id: 'quote_indicator.cancel',
},
});
class QuoteIndicator extends ImmutablePureComponent {
static propTypes = {
status: ImmutablePropTypes.map,
onCancel: PropTypes.func,
intl: PropTypes.object.isRequired,
...WithOptionalRouterPropTypes,
};
handleClick = () => {
this.props.onCancel();
};
handleAccountClick = (e) => {
if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault();
this.props.history?.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
}
}
// Rendering.
render () {
const { status, intl } = this.props;
if (!status) {
return null;
}
const content = { __html: status.get('contentHtml') };
// The result.
return (
<article className='quote-indicator'>
<header className='quote-indicator__header'>
<div className='quote-indicator__cancel'>
<IconButton title={intl.formatMessage(messages.cancel)} icon='times' iconComponent={CloseIcon} onClick={this.handleClick} inverted />
</div>
<a href={status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='quote-indicator__display-name' target='_blank' rel='noopener noreferrer'>
<div className='quote-indicator__display-avatar'><Avatar account={status.get('account')} size={24} /></div>
<DisplayName account={status.get('account')} inline />
</a>
</header>
<div className='quote-indicator__content translate' dangerouslySetInnerHTML={content} />
{status.get('media_attachments').size > 0 && (
<AttachmentList
compact
media={status.get('media_attachments')}
/>
)}
</article>
);
}
}
export default withOptionalRouter(injectIntl(QuoteIndicator));

View File

@ -4,7 +4,6 @@ import { useSelector } from 'react-redux';
import BarChart4BarsIcon from '@/material-icons/400-24px/bar_chart_4_bars.svg?react';
import PhotoLibraryIcon from '@/material-icons/400-24px/photo_library.svg?react';
import QuoteIcon from '@/material-icons/400-24px/format_quote-fill.svg?react';
import { Avatar } from 'flavours/glitch/components/avatar';
import { DisplayName } from 'flavours/glitch/components/display_name';
import { Icon } from 'flavours/glitch/components/icon';
@ -12,8 +11,7 @@ import { Permalink } from 'flavours/glitch/components/permalink';
export const ReplyIndicator = () => {
const inReplyToId = useSelector(state => state.getIn(['compose', 'in_reply_to']));
const quoteId = useSelector(state => state.getIn(['compose', 'quote_id']));
const status = useSelector(state => state.getIn(['statuses', inReplyToId || quoteId]));
const status = useSelector(state => state.getIn(['statuses', inReplyToId]));
const account = useSelector(state => state.getIn(['accounts', status?.get('account')]));
if (!status) {
@ -23,21 +21,14 @@ export const ReplyIndicator = () => {
const content = { __html: status.get('contentHtml') };
return (
<div className={'reply-indicator' + (quoteId ? ' reply-indicator__quote' : '')}>
{inReplyToId && (<div className='reply-indicator__line' />)}
<div className='reply-indicator'>
<div className='reply-indicator__line' />
<Permalink href={account.get('url')} to={`/@${account.get('acct')}`} className='detailed-status__display-avatar'>
<Avatar account={account} size={46} />
</Permalink>
<div className='reply-indicator__main'>
{quoteId && (
<Icon
fixedWidth
aria-hidden='true'
key='icon-quote-right'
icon={QuoteIcon} />
)}
<Permalink href={account.get('url')} to={`/@${account.get('acct')}`} className='detailed-status__display-name'>
<DisplayName account={account} />
</Permalink>

View File

@ -0,0 +1,31 @@
import { connect } from 'react-redux';
import { cancelQuoteCompose } from 'flavours/glitch/actions/compose';
import { makeGetStatus } from '../../../selectors';
import QuoteIndicator from '../components/quote_indicator';
const makeMapStateToProps = () => {
const getStatus = makeGetStatus();
const mapStateToProps = state => {
const statusId = state.getIn(['compose', 'quote_id'], null);
const editing = false;
return {
status: getStatus(state, { id: statusId }),
editing,
};
};
return mapStateToProps;
};
const mapDispatchToProps = dispatch => ({
onCancel () {
dispatch(cancelQuoteCompose());
},
});
export default connect(makeMapStateToProps, mapDispatchToProps)(QuoteIndicator);

View File

@ -10,7 +10,7 @@ const mapStateToProps = state => {
const readyAttachmentsSize = state.getIn(['compose', 'media_attachments']).size ?? 0;
const pendingAttachmentsSize = state.getIn(['compose', 'pending_media_attachments']).size ?? 0;
const attachmentsSize = readyAttachmentsSize + pendingAttachmentsSize;
const isOverLimit = attachmentsSize > state.getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments'])-1;
const isOverLimit = attachmentsSize > 3;
const hasVideoOrAudio = state.getIn(['compose', 'media_attachments']).some(m => ['video', 'audio'].includes(m.get('type')));
return {

View File

@ -130,7 +130,7 @@ export default class Card extends PureComponent {
const showAuthor = !!card.getIn(['authors', 0, 'accountId']);
const description = (
<div className='status-card__content' dir='auto'>
<div className='status-card__content'>
<span className='status-card__host'>
<span lang={language}>{provider}</span>
{card.get('published_at') && <> · <RelativeTimestamp timestamp={card.get('published_at')} /></>}

View File

@ -345,10 +345,10 @@ class Status extends ImmutablePureComponent {
handleQuoteClick = (status) => {
const { dispatch } = this.props;
const { signedIn } = this.props.identity;
const { signedIn } = this.context.identity;
if (signedIn) {
dispatch(quoteCompose(status, this.props.history));
dispatch(quoteCompose(status, this.context.router.history));
} else {
dispatch(openModal('INTERACTION', {
type: 'reply',

View File

@ -27,7 +27,7 @@ import { clearHeight } from '../../actions/height_cache';
import { expandNotifications, notificationsSetVisibility } from '../../actions/notifications';
import { fetchServer, fetchServerTranslationLanguages } from '../../actions/server';
import { expandHomeTimeline } from '../../actions/timelines';
import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding, disableHoverCards } from '../../initial_state';
import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding } from '../../initial_state';
import BundleColumnError from './components/bundle_column_error';
import Header from './components/header';
@ -651,7 +651,7 @@ class UI extends PureComponent {
{layout !== 'mobile' && <PictureInPicture />}
<NotificationsContainer />
{!disableHoverCards && <HoverCardController />}
<HoverCardController />
<LoadingBarContainer className='loading-bar' />
<ModalContainer />
<UploadArea active={draggingOver} onClose={this.closeUploadModal} />

View File

@ -17,7 +17,6 @@
* @property {boolean} crop_images
* @property {boolean=} delete_modal
* @property {boolean=} disable_swiping
* @property {boolean=} disable_hover_cards
* @property {string=} disabled_account_id
* @property {string} display_media
* @property {string} domain
@ -107,7 +106,6 @@ export const boostModal = getMeta('boost_modal');
export const cropImages = getMeta('crop_images');
export const deleteModal = getMeta('delete_modal');
export const disableSwiping = getMeta('disable_swiping');
export const disableHoverCards = getMeta('disable_hover_cards');
export const disabledAccountId = getMeta('disabled_account_id');
export const displayMedia = getMeta('display_media');
export const domain = getMeta('domain');

View File

@ -154,5 +154,6 @@
"status.in_reply_to": "Dieser Toot ist eine Antwort",
"status.is_poll": "Dieser Toot ist eine Umfrage",
"status.local_only": "Nur auf deiner Instanz sichtbar",
"status.uncollapse": "Ausklappen"
"status.uncollapse": "Ausklappen",
"suggestions.dismiss": "Vorschlag ablehnen"
}

View File

@ -155,5 +155,6 @@
"status.in_reply_to": "Esta publicación es una respuesta",
"status.is_poll": "Esta publicación es una encuesta",
"status.local_only": "Sólo visible para tu instancia",
"status.uncollapse": "Descolapsar"
"status.uncollapse": "Descolapsar",
"suggestions.dismiss": "Descartar sugerencia"
}

View File

@ -25,9 +25,6 @@
"compose.content-type.plain_meta": "고급 양식 없이 작성",
"compose.disable_threaded_mode": "글타래 모드 비활성화",
"compose.enable_threaded_mode": "글타래 모드 활성화",
"compose_form.sensitive.hide": "{count, plural, other {미디어를 민감함으로 표시}}",
"compose_form.sensitive.marked": "{count, plural, other {미디어가 민감함으로 표시되었습니다}}",
"compose_form.sensitive.unmarked": "{count, plural, other {미디어가 민감함으로 표시되지 않았습니다}}",
"confirmation_modal.do_not_ask_again": "다음부터 확인창을 띄우지 않기",
"confirmations.deprecated_settings.confirm": "마스토돈 설정 사용",
"confirmations.deprecated_settings.message": "사용하던 몇몇 기기별 글리치 {app_settings}은 마스토돈 {preferences}으로 대체되었습니다:",
@ -64,7 +61,6 @@
"notification_purge.btn_invert": "선택반전",
"notification_purge.btn_none": "전체선택해제",
"notification_purge.start": "알림 삭제모드로 들어가기",
"notifications.column_settings.filter_bar.show_bar": "필터 막대 표시",
"notifications.marked_clear": "선택된 알림 모두 삭제",
"notifications.marked_clear_confirmation": "정말로 선택된 알림들을 영구적으로 삭제할까요?",
"settings.always_show_spoilers_field": "열람주의 항목을 언제나 활성화",
@ -128,7 +124,6 @@
"settings.shared_settings_link": "사용자 설정",
"settings.show_action_bar": "접힌 글에 액션 버튼들 보이기",
"settings.show_content_type_choice": "글을 작성할 때 콘텐트 타입을 고를 수 있도록 합니다",
"settings.show_published_toast": "게시물을 게시/저장할 때 토스트 표시",
"settings.show_reply_counter": "대략적인 답글 개수를 표시합니다",
"settings.side_arm": "보조 작성 버튼:",
"settings.side_arm.none": "없음",

View File

@ -155,5 +155,6 @@
"status.in_reply_to": "此嘟文是回复",
"status.is_poll": "此嘟文是投票",
"status.local_only": "此嘟文仅本站可见",
"status.uncollapse": "展开"
"status.uncollapse": "展开",
"suggestions.dismiss": "关闭建议"
}

View File

@ -151,5 +151,6 @@
"status.in_reply_to": "貼文有回覆",
"status.is_poll": "貼文有投票",
"status.local_only": "只在此實例可見",
"status.uncollapse": "展開"
"status.uncollapse": "展開",
"suggestions.dismiss": "關閉建議"
}

View File

@ -409,25 +409,3 @@
color: $gold-star;
}
}
.batch-table__row--warn {
color: $warning-red;
}
.batch-table__row--warn .pending-account__header,
.batch-table__row--warn .accounts-table,
.batch-table__row--warn .name-tag {
&,
a,
strong {
color: $warning-red;
}
}
.batch-table__row--warn .accounts-table {
tbody td.accounts-table__extra,
&__count,
&__count small {
color: $warning-red;
}
}

View File

@ -572,10 +572,7 @@ body > [data-popper-placement] {
align-items: stretch;
&__border {
/*
background: url('~images/warning-stripes.svg') repeat-y;
*/
background: $ui-base-lighter-color;
width: 5px;
flex: 0 0 auto;
@ -1012,6 +1009,50 @@ body > [data-popper-placement] {
}
}
.quote-indicator,
.reply-indicator {
border-radius: 4px;
margin-bottom: 10px;
background: $ui-primary-color;
padding: 10px;
min-height: 23px;
overflow-y: auto;
flex: 0 2 auto;
}
.quote-indicator__header,
.reply-indicator__header {
margin-bottom: 5px;
overflow: hidden;
}
.quote-indicator__cancel,
.reply-indicator__cancel {
float: right;
line-height: 24px;
}
.quote-indicator__display-name,
.reply-indicator__display-name {
color: $inverted-text-color;
display: block;
max-width: 100%;
line-height: 24px;
overflow: hidden;
text-decoration: none;
& > .display-name {
line-height: unset;
height: unset;
}
}
.quote-indicator__display-avatar,
.reply-indicator__display-avatar {
float: left;
margin-inline-end: 5px;
}
.status__content--with-action {
cursor: pointer;
}
@ -1022,6 +1063,7 @@ body > [data-popper-placement] {
.status__content,
.edit-indicator__content,
.quote-indicator__content,
.reply-indicator__content {
position: relative;
word-wrap: break-word;
@ -1118,18 +1160,6 @@ body > [data-popper-placement] {
overflow: visible;
}
.status__quote {
margin-bottom: 0.5em;
.quote-display-name {
.icon {
margin-left: -3px;
margin-right: 3px;
margin-bottom: 2px;
vertical-align: middle;
}
}
}
.reply-indicator {
display: grid;
grid-template-columns: 46px minmax(0, 1fr);
@ -1209,11 +1239,6 @@ body > [data-popper-placement] {
}
}
.reply-indicator__quote {
padding-inline-start: 10px;
border-inline-start: 3px solid $darker-text-color;
}
.edit-indicator {
border-radius: 4px 4px 0 0;
background: lighten($ui-base-color, 4%);
@ -1440,6 +1465,7 @@ body > [data-popper-placement] {
}
.focusable {
&:hover,
&:focus {
outline: 0;
background: rgba($ui-highlight-color, 0.05);
@ -1451,8 +1477,6 @@ body > [data-popper-placement] {
min-height: 54px;
border-bottom: 1px solid var(--background-border-color);
cursor: auto;
opacity: 1;
animation: fade 150ms linear;
@keyframes fade {
0% {
@ -1464,6 +1488,9 @@ body > [data-popper-placement] {
}
}
opacity: 1;
animation: fade 150ms linear;
.media-gallery,
.video-player,
.audio-player,
@ -2299,7 +2326,9 @@ a .account__avatar {
}
}
.status__display-name,
a.status__display-name,
.quote-indicator__display-name,
.reply-indicator__display-name,
.detailed-status__display-name,
a.account__display-name {
&:hover .display-name strong {
@ -5219,10 +5248,8 @@ a.status-card {
&__menu {
@include search-popout;
& {
padding: 0;
background: $ui-secondary-color;
}
padding: 0;
background: $ui-secondary-color;
}
&__menu-list {
@ -11029,7 +11056,7 @@ noscript {
gap: 4px;
dt {
flex: 0 1 auto;
flex: 0 0 auto;
color: $dark-text-color;
min-width: 0;
overflow: hidden;

View File

@ -1,7 +1,21 @@
.compose-form {
.compose-form__modifiers {
.compose-form__upload {
&-description {
input {
&::placeholder {
opacity: 1;
}
}
}
}
}
}
.status__content a,
.reply-indicator__content a,
.edit-indicator__content a,
.link-footer a,
.quote-indicator__content a,
.reply-indicator__content a,
.status__content__read-more-button,
.status__content__translate-button {
text-decoration: underline;
@ -29,9 +43,7 @@
}
}
.status__content a,
.reply-indicator__content a,
.edit-indicator__content a {
.status__content a {
color: $highlight-text-color;
}
@ -39,10 +51,24 @@
color: $darker-text-color;
}
.report-dialog-modal__textarea::placeholder {
.compose-form__poll-wrapper .button.button-secondary,
.compose-form .autosuggest-textarea__textarea::placeholder,
.compose-form .spoiler-input__input::placeholder,
.report-dialog-modal__textarea::placeholder,
.language-dropdown__dropdown__results__item__common-name,
.compose-form .icon-button {
color: $inverted-text-color;
}
.text-icon-button.active {
color: $ui-highlight-color;
}
.language-dropdown__dropdown__results__item.active {
background: $ui-highlight-color;
font-weight: 500;
}
.link-button:disabled {
cursor: not-allowed;

View File

@ -21,6 +21,25 @@ html {
}
// Change default background colors of columns
.column > .scrollable,
.getting-started,
.column-inline-form,
.regeneration-indicator {
background: $white;
border: 1px solid lighten($ui-base-color, 8%);
border-top: 0;
}
.error-column {
border: 1px solid lighten($ui-base-color, 8%);
}
.column > .scrollable.about {
border-top: 1px solid lighten($ui-base-color, 8%);
}
.about__meta,
.about__section__title,
.interaction-modal {
background: $white;
border: 1px solid lighten($ui-base-color, 8%);
@ -34,6 +53,29 @@ html {
background: lighten($ui-base-color, 12%);
}
.filter-form {
background: $white;
border-bottom: 1px solid lighten($ui-base-color, 8%);
}
.column-back-button,
.column-header {
background: $white;
border: 1px solid lighten($ui-base-color, 8%);
@media screen and (max-width: $no-gap-breakpoint) {
border-top: 0;
}
&--slim-button {
top: -50px;
right: 0;
}
}
.column-header__back-button,
.column-header__button,
.column-header__button.active,
.account__header {
background: $white;
}
@ -45,13 +87,10 @@ html {
&:active,
&:focus {
color: $ui-highlight-color;
background: $white;
}
}
.icon-button:disabled {
color: darken($action-button-color, 25%);
}
.account__header__bar .avatar .account__avatar {
border-color: $white;
}
@ -74,6 +113,25 @@ html {
}
}
.column-subheading {
background: darken($ui-base-color, 4%);
border-bottom: 1px solid lighten($ui-base-color, 8%);
}
.getting-started,
.scrollable {
.column-link {
background: $white;
border-bottom: 1px solid lighten($ui-base-color, 8%);
&:hover,
&:active,
&:focus {
background: $ui-base-color;
}
}
}
.getting-started .navigation-bar {
border-top: 1px solid lighten($ui-base-color, 8%);
border-bottom: 1px solid lighten($ui-base-color, 8%);
@ -83,8 +141,11 @@ html {
}
}
.compose-form__autosuggest-wrapper,
.poll__option input[type='text'],
.compose-form .spoiler-input__input,
.compose-form__poll-wrapper select,
.search__input,
.search__popout,
.setting-text,
.report-dialog-modal__textarea,
.audio-player {
@ -107,6 +168,86 @@ html {
border-bottom: 0;
}
.compose-form__poll-wrapper select {
background: $simple-background-color
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14.933 18.467' height='19.698' width='15.929'><path d='M3.467 14.967l-3.393-3.5H14.86l-3.392 3.5c-1.866 1.925-3.666 3.5-4 3.5-.335 0-2.135-1.575-4-3.5zm.266-11.234L7.467 0 11.2 3.733l3.733 3.734H0l3.733-3.734z' fill='#{hex-color(lighten($ui-base-color, 8%))}'/></svg>")
no-repeat right 8px center / auto 16px;
}
.compose-form__poll-wrapper,
.compose-form__poll-wrapper .poll__footer {
border-top-color: lighten($ui-base-color, 8%);
}
.notification__filter-bar {
border: 1px solid lighten($ui-base-color, 8%);
border-top: 0;
}
.compose-form .compose-form__buttons-wrapper {
background: $ui-base-color;
border: 1px solid lighten($ui-base-color, 8%);
border-top: 0;
}
.drawer__header,
.drawer__inner {
background: $white;
border: 1px solid lighten($ui-base-color, 8%);
}
.drawer__inner__mastodon {
background: $white
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 234.80078 31.757813" width="234.80078" height="31.757812"><path d="M19.599609 0c-1.05 0-2.10039.375-2.90039 1.125L0 16.925781v14.832031h234.80078V17.025391l-16.5-15.900391c-1.6-1.5-4.20078-1.5-5.80078 0l-13.80078 13.099609c-1.6 1.5-4.19883 1.5-5.79883 0L179.09961 1.125c-1.6-1.5-4.19883-1.5-5.79883 0L159.5 14.224609c-1.6 1.5-4.20078 1.5-5.80078 0L139.90039 1.125c-1.6-1.5-4.20078-1.5-5.80078 0l-13.79883 13.099609c-1.6 1.5-4.20078 1.5-5.80078 0L100.69922 1.125c-1.600001-1.5-4.198829-1.5-5.798829 0l-13.59961 13.099609c-1.6 1.5-4.200781 1.5-5.800781 0L61.699219 1.125c-1.6-1.5-4.198828-1.5-5.798828 0L42.099609 14.224609c-1.6 1.5-4.198828 1.5-5.798828 0L22.5 1.125C21.7.375 20.649609 0 19.599609 0z" fill="#{hex-color($ui-base-color)}"/></svg>')
no-repeat bottom / 100% auto;
}
// Change the colors used in compose-form
.compose-form {
.compose-form__modifiers {
.compose-form__upload__actions .icon-button,
.compose-form__upload__warning .icon-button {
color: lighten($white, 7%);
&:active,
&:focus,
&:hover {
color: $white;
}
}
}
.compose-form__buttons-wrapper {
background: darken($ui-base-color, 6%);
}
.autosuggest-textarea__suggestions {
background: darken($ui-base-color, 6%);
}
.autosuggest-textarea__suggestions__item {
&:hover,
&:focus,
&:active,
&.selected {
background: lighten($ui-base-color, 4%);
}
}
}
.emoji-mart-bar {
border-color: lighten($ui-base-color, 4%);
&:first-child {
background: darken($ui-base-color, 6%);
}
}
.emoji-mart-search input {
background: rgba($ui-base-color, 0.3);
border-color: $ui-base-color;
}
.upload-progress__backdrop {
background: $ui-base-color;
}
@ -116,7 +257,13 @@ html {
background: lighten($white, 4%);
}
.detailed-status,
.detailed-status__action-bar {
background: $white;
}
// Change the background colors of status__content__spoiler-link
.quote-indicator__content .status__content__spoiler-link,
.reply-indicator__content .status__content__spoiler-link,
.status__content .status__content__spoiler-link {
background: $ui-base-color;
@ -127,11 +274,52 @@ html {
}
}
// Change the background colors of media and video spoilers
.media-spoiler,
.video-player__spoiler {
background: $ui-base-color;
}
.privacy-dropdown.active .privacy-dropdown__value.active .icon-button {
color: $white;
}
.account-gallery__item a {
background-color: $ui-base-color;
}
// Change the colors used in the dropdown menu
.dropdown-menu {
background: $white;
&__arrow::before {
background-color: $white;
}
&__item {
color: $darker-text-color;
&--dangerous {
color: $error-value-color;
}
a,
button {
background: $white;
}
}
}
// Change the text colors on inverted background
.privacy-dropdown__option.active,
.privacy-dropdown__option:hover,
.privacy-dropdown__option.active .privacy-dropdown__option__content,
.privacy-dropdown__option.active .privacy-dropdown__option__content strong,
.privacy-dropdown__option:hover .privacy-dropdown__option__content,
.privacy-dropdown__option:hover .privacy-dropdown__option__content strong,
.dropdown-menu__item:not(.dropdown-menu__item--dangerous) a:active,
.dropdown-menu__item:not(.dropdown-menu__item--dangerous) a:focus,
.dropdown-menu__item:not(.dropdown-menu__item--dangerous) a:hover,
.actions-modal ul li:not(:empty) a.active,
.actions-modal ul li:not(:empty) a.active button,
.actions-modal ul li:not(:empty) a:active,
@ -140,6 +328,7 @@ html {
.actions-modal ul li:not(:empty) a:focus button,
.actions-modal ul li:not(:empty) a:hover,
.actions-modal ul li:not(:empty) a:hover button,
.language-dropdown__dropdown__results__item.active,
.admin-wrapper .sidebar ul .simple-navigation-active-leaf a,
.simple_form .block-button,
.simple_form .button,
@ -147,6 +336,19 @@ html {
color: $white;
}
.language-dropdown__dropdown__results__item
.language-dropdown__dropdown__results__item__common-name {
color: lighten($ui-base-color, 8%);
}
.language-dropdown__dropdown__results__item.active
.language-dropdown__dropdown__results__item__common-name {
color: darken($ui-base-color, 12%);
}
.dropdown-menu__separator,
.dropdown-menu__item.edited-timestamp__history__item,
.dropdown-menu__container__header,
.compare-history-modal .report-modal__target,
.report-dialog-modal .poll__option.dialog-option {
border-bottom-color: lighten($ui-base-color, 4%);
@ -180,7 +382,10 @@ html {
.reactions-bar__item:hover,
.reactions-bar__item:focus,
.reactions-bar__item:active {
.reactions-bar__item:active,
.language-dropdown__dropdown__results__item:hover,
.language-dropdown__dropdown__results__item:focus,
.language-dropdown__dropdown__results__item:active {
background-color: $ui-base-color;
}
@ -218,7 +423,7 @@ html {
.column-header__collapsible-inner {
background: darken($ui-base-color, 4%);
border: 1px solid lighten($ui-base-color, 8%);
border-bottom: 0;
border-top: 0;
}
.column-settings__hashtags .column-select__option {
@ -268,11 +473,11 @@ html {
}
.react-toggle-track {
background: $ui-primary-color;
background: $ui-secondary-color;
}
.react-toggle:hover:not(.react-toggle--disabled) .react-toggle-track {
background: lighten($ui-primary-color, 10%);
background: darken($ui-secondary-color, 10%);
}
.react-toggle.react-toggle--checked:hover:not(.react-toggle--disabled)
@ -423,7 +628,14 @@ html {
}
}
.quote-indicator,
.reply-indicator {
background: transparent;
border: 1px solid lighten($ui-base-color, 8%);
}
.status__content,
.quote-indicator__content,
.reply-indicator__content {
a {
color: $highlight-text-color;
@ -444,8 +656,7 @@ html {
.directory__tag > div,
.card > a,
.page-header,
.compose-form,
.compose-form__warning {
.compose-form .compose-form__warning {
box-shadow: none;
}
@ -517,6 +728,13 @@ html {
}
}
.status.collapsed .status__content::after {
background: linear-gradient(
rgba(darken($ui-base-color, 13%), 0),
rgba(darken($ui-base-color, 13%), 1)
);
}
.drawer__inner__mastodon {
background: $white
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 234.80078 31.757813" width="234.80078" height="31.757812"><path d="M19.599609 0c-1.05 0-2.10039.375-2.90039 1.125L0 16.925781v14.832031h234.80078V17.025391l-16.5-15.900391c-1.6-1.5-4.20078-1.5-5.80078 0l-13.80078 13.099609c-1.6 1.5-4.19883 1.5-5.79883 0L179.09961 1.125c-1.6-1.5-4.19883-1.5-5.79883 0L159.5 14.224609c-1.6 1.5-4.20078 1.5-5.80078 0L139.90039 1.125c-1.6-1.5-4.20078-1.5-5.80078 0l-13.79883 13.099609c-1.6 1.5-4.20078 1.5-5.80078 0L100.69922 1.125c-1.600001-1.5-4.198829-1.5-5.798829 0l-13.59961 13.099609c-1.6 1.5-4.200781 1.5-5.800781 0L61.699219 1.125c-1.6-1.5-4.198828-1.5-5.798828 0L42.099609 14.224609c-1.6 1.5-4.198828 1.5-5.798828 0L22.5 1.125C21.7.375 20.649609 0 19.599609 0z" fill="#{hex-color($ui-base-color)}"/></svg>')
@ -526,47 +744,3 @@ html {
filter: contrast(75%) brightness(75%) !important;
}
}
.compose-form__actions .icon-button.active,
.dropdown-button.active,
.privacy-dropdown__option.active,
.privacy-dropdown__option:focus,
.language-dropdown__dropdown__results__item:focus,
.language-dropdown__dropdown__results__item.active,
.privacy-dropdown__option:focus .privacy-dropdown__option__content,
.privacy-dropdown__option:focus .privacy-dropdown__option__content strong,
.privacy-dropdown__option.active .privacy-dropdown__option__content,
.privacy-dropdown__option.active .privacy-dropdown__option__content strong,
.language-dropdown__dropdown__results__item:focus
.language-dropdown__dropdown__results__item__common-name,
.language-dropdown__dropdown__results__item.active
.language-dropdown__dropdown__results__item__common-name {
color: $white;
}
.compose-form .spoiler-input__input {
color: lighten($ui-highlight-color, 8%);
}
.compose-form .autosuggest-textarea__textarea,
.compose-form__highlightable,
.search__input,
.search__popout,
.emoji-mart-search input,
.language-dropdown__dropdown .emoji-mart-search input,
.poll__option input[type='text'] {
background: darken($ui-base-color, 10%);
}
.inline-follow-suggestions {
background-color: rgba($ui-highlight-color, 0.1);
border-bottom-color: rgba($ui-highlight-color, 0.3);
}
.inline-follow-suggestions__body__scrollable__card {
background: $white;
}
.inline-follow-suggestions__body__scroll-button__icon {
color: $white;
}

View File

@ -2,6 +2,7 @@
.status__content__text,
.e-content,
.edit-indicator__content,
.quote-indicator__content,
.reply-indicator__content {
pre,
blockquote {
@ -92,3 +93,11 @@
list-style-type: decimal;
}
}
.quote-indicator__content,
.reply-indicator__content {
blockquote {
border-inline-start-color: $inverted-text-color;
color: $inverted-text-color;
}
}

View File

@ -281,7 +281,7 @@ export function submitComposeFail(error) {
export function uploadCompose(files) {
return function (dispatch, getState) {
const uploadLimit = getState().getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments']);
const uploadLimit = 4;
const media = getState().getIn(['compose', 'media_attachments']);
const pending = getState().getIn(['compose', 'pending_media_attachments']);
const progress = new Array(files.length).fill(0);
@ -301,7 +301,7 @@ export function uploadCompose(files) {
dispatch(uploadComposeRequest());
for (const [i, file] of Array.from(files).entries()) {
if (media.size + i > (uploadLimit - 1)) break;
if (media.size + i > 3) break;
const data = new FormData();
data.append('file', file);

View File

@ -131,7 +131,7 @@ const Account = ({ size = 46, account, onFollow, onBlock, onMute, onMuteNotifica
return (
<div className={classNames('account', { 'account--minimal': minimal })}>
<div className='account__wrapper'>
<Link key={account.get('id')} className='account__display-name' title={account.get('acct')} to={`/@${account.get('acct')}`} data-hover-card-account={account.get('id')}>
<Link key={account.get('id')} className='account__display-name' title={account.get('acct')} to={`/@${account.get('acct')}`}>
<div className='account__avatar-wrapper'>
<Avatar account={account} size={size} />
</div>

View File

@ -43,7 +43,6 @@ export const HoverCardController: React.FC = () => {
useEffect(() => {
let isScrolling = false;
let currentAnchor: HTMLElement | null = null;
let currentTitle: string | null = null;
const open = (target: HTMLElement) => {
target.setAttribute('aria-describedby', 'hover-card');
@ -76,9 +75,6 @@ export const HoverCardController: React.FC = () => {
currentAnchor?.removeAttribute('aria-describedby');
currentAnchor = target;
currentTitle = target.getAttribute('title');
target.removeAttribute('title');
setEnterTimeout(() => {
open(target);
}, enterDelay);
@ -94,20 +90,11 @@ export const HoverCardController: React.FC = () => {
};
const handleMouseLeave = (e: MouseEvent) => {
const { target } = e;
if (!currentAnchor) {
return;
}
if (
currentTitle &&
target instanceof HTMLElement &&
target === currentAnchor
)
target.setAttribute('title', currentTitle);
if (target === currentAnchor || target === cardRef.current) {
if (e.target === currentAnchor || e.target === cardRef.current) {
cancelEnterTimeout();
setLeaveTimeout(() => {

View File

@ -305,13 +305,13 @@ class MediaGallery extends PureComponent {
style.aspectRatio = '3 / 2';
}
const size = media.size;
const size = media.take(4).size;
const uncached = media.every(attachment => attachment.get('type') === 'unknown');
if (this.isFullSizeEligible()) {
children = <Item standalone autoplay={autoplay} onClick={this.handleClick} attachment={media.get(0)} lang={lang} displayWidth={width} visible={visible} />;
} else {
children = media.map((attachment, i) => <Item key={attachment.get('id')} autoplay={autoplay} onClick={this.handleClick} attachment={attachment} index={i} lang={lang} size={size} displayWidth={width} visible={visible || uncached} />);
children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} autoplay={autoplay} onClick={this.handleClick} attachment={attachment} index={i} lang={lang} size={size} displayWidth={width} visible={visible || uncached} />);
}
if (uncached) {

View File

@ -562,7 +562,7 @@ class Status extends ImmutablePureComponent {
<RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
</a>
<a onClick={this.handleAccountClick} href={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} data-hover-card-account={status.getIn(['account', 'id'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>
<a onClick={this.handleAccountClick} href={`/@${status.getIn(['account', 'acct'])}`} data-hover-card-account={status.getIn(['account', 'id'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>
<div className='status__avatar'>
{statusAvatar}
</div>

View File

@ -116,7 +116,7 @@ class StatusContent extends PureComponent {
if (mention) {
link.addEventListener('click', this.onMentionClick.bind(this, mention), false);
link.setAttribute('title', `@${mention.get('acct')}`);
link.removeAttribute('title');
link.setAttribute('href', `/@${mention.get('acct')}`);
link.setAttribute('data-hover-card-account', mention.get('id'));
} else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) {

View File

@ -22,7 +22,6 @@ export const NavigationBar = () => {
const intl = useIntl();
const account = useSelector(state => state.getIn(['accounts', me]));
const isReplying = useSelector(state => !!state.getIn(['compose', 'in_reply_to']));
const isQuoting = useSelector(state => !!state.getIn(['compose', 'quote_id']));
const handleCancelClick = useCallback(() => {
dispatch(cancelReplyCompose());
@ -31,7 +30,7 @@ export const NavigationBar = () => {
return (
<div className='navigation-bar'>
<Account account={account} minimal />
{(isReplying || isQuoting) ? <IconButton title={intl.formatMessage(messages.cancel)} iconComponent={CloseIcon} onClick={handleCancelClick} /> : <ActionBar />}
{isReplying ? <IconButton title={intl.formatMessage(messages.cancel)} iconComponent={CloseIcon} onClick={handleCancelClick} /> : <ActionBar />}
</div>
);
};

View File

@ -6,15 +6,13 @@ import { useSelector } from 'react-redux';
import BarChart4BarsIcon from '@/material-icons/400-24px/bar_chart_4_bars.svg?react';
import PhotoLibraryIcon from '@/material-icons/400-24px/photo_library.svg?react';
import QuoteIcon from '@/material-icons/400-24px/format_quote-fill.svg?react';
import { Avatar } from 'mastodon/components/avatar';
import { DisplayName } from 'mastodon/components/display_name';
import { Icon } from 'mastodon/components/icon';
export const ReplyIndicator = () => {
const inReplyToId = useSelector(state => state.getIn(['compose', 'in_reply_to']));
const quoteId = useSelector(state => state.getIn(['compose', 'quote_id']));
const status = useSelector(state => state.getIn(['statuses', inReplyToId || quoteId]));
const status = useSelector(state => state.getIn(['statuses', inReplyToId]));
const account = useSelector(state => state.getIn(['accounts', status?.get('account')]));
if (!status) {
@ -24,22 +22,14 @@ export const ReplyIndicator = () => {
const content = { __html: status.get('contentHtml') };
return (
<div className={'reply-indicator' + (quoteId ? ' reply-indicator__quote' : '')}>
{inReplyToId && (<div className='reply-indicator__line' />)}
<div className='reply-indicator'>
<div className='reply-indicator__line' />
<Link to={`/@${account.get('acct')}`} className='detailed-status__display-avatar'>
<Avatar account={account} size={46} />
</Link>
<div className='reply-indicator__main'>
{quoteId && (
<Icon
fixedWidth
aria-hidden='true'
key='icon-quote-right'
icon={QuoteIcon} />
)}
<Link to={`/@${account.get('acct')}`} className='detailed-status__display-name'>
<DisplayName account={account} />
</Link>

View File

@ -9,7 +9,7 @@ const mapStateToProps = state => {
const readyAttachmentsSize = state.getIn(['compose', 'media_attachments']).size ?? 0;
const pendingAttachmentsSize = state.getIn(['compose', 'pending_media_attachments']).size ?? 0;
const attachmentsSize = readyAttachmentsSize + pendingAttachmentsSize;
const isOverLimit = attachmentsSize > state.getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments'])-1;
const isOverLimit = attachmentsSize > 3;
const hasVideoOrAudio = state.getIn(['compose', 'media_attachments']).some(m => ['video', 'audio'].includes(m.get('type')));
return {

View File

@ -435,7 +435,7 @@ class Notification extends ImmutablePureComponent {
const targetAccount = report.get('target_account');
const targetDisplayNameHtml = { __html: targetAccount.get('display_name_html') };
const targetLink = <bdi><Link className='notification__display-name' title={targetAccount.get('acct')} data-hover-card-account={targetAccount.get('id')} to={`/@${targetAccount.get('acct')}`} dangerouslySetInnerHTML={targetDisplayNameHtml} /></bdi>;
const targetLink = <bdi><Link className='notification__display-name' data-hover-card-account={targetAccount.get('id')} to={`/@${targetAccount.get('acct')}`} dangerouslySetInnerHTML={targetDisplayNameHtml} /></bdi>;
return (
<HotKeys handlers={this.getHandlers()}>
@ -458,7 +458,7 @@ class Notification extends ImmutablePureComponent {
const { notification } = this.props;
const account = notification.get('account');
const displayNameHtml = { __html: account.get('display_name_html') };
const link = <bdi><Link className='notification__display-name' href={`/@${account.get('acct')}`} title={account.get('acct')} data-hover-card-account={account.get('id')} to={`/@${account.get('acct')}`} dangerouslySetInnerHTML={displayNameHtml} /></bdi>;
const link = <bdi><Link className='notification__display-name' href={`/@${account.get('acct')}`} data-hover-card-account={account.get('id')} to={`/@${account.get('acct')}`} dangerouslySetInnerHTML={displayNameHtml} /></bdi>;
switch(notification.get('type')) {
case 'follow':

View File

@ -141,7 +141,7 @@ export default class Card extends PureComponent {
const showAuthor = !!card.getIn(['authors', 0, 'accountId']);
const description = (
<div className='status-card__content' dir='auto'>
<div className='status-card__content'>
<span className='status-card__host'>
<span lang={language}>{provider}</span>
{card.get('published_at') && <> · <RelativeTimestamp timestamp={card.get('published_at')} /></>}

View File

@ -25,7 +25,7 @@ import { clearHeight } from '../../actions/height_cache';
import { expandNotifications } from '../../actions/notifications';
import { fetchServer, fetchServerTranslationLanguages } from '../../actions/server';
import { expandHomeTimeline } from '../../actions/timelines';
import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding, disableHoverCards } from '../../initial_state';
import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding } from '../../initial_state';
import BundleColumnError from './components/bundle_column_error';
import Header from './components/header';
@ -588,7 +588,7 @@ class UI extends PureComponent {
{layout !== 'mobile' && <PictureInPicture />}
<NotificationsContainer />
{!disableHoverCards && <HoverCardController />}
<HoverCardController />
<LoadingBarContainer className='loading-bar' />
<ModalContainer />
<UploadArea active={draggingOver} onClose={this.closeUploadModal} />

View File

@ -15,7 +15,6 @@
* @property {boolean=} boost_modal
* @property {boolean=} delete_modal
* @property {boolean=} disable_swiping
* @property {boolean=} disable_hover_cards
* @property {string=} disabled_account_id
* @property {string} display_media
* @property {string} domain
@ -87,7 +86,6 @@ export const autoPlayGif = getMeta('auto_play_gif');
export const boostModal = getMeta('boost_modal');
export const deleteModal = getMeta('delete_modal');
export const disableSwiping = getMeta('disable_swiping');
export const disableHoverCards = getMeta('disable_hover_cards');
export const disabledAccountId = getMeta('disabled_account_id');
export const displayMedia = getMeta('display_media');
export const domain = getMeta('domain');

View File

@ -4,7 +4,7 @@
"about.disclaimer": "ماستدون برنامج حر ومفتوح المصدر وعلامة تجارية لـ Mastodon GmbH.",
"about.domain_blocks.no_reason_available": "السبب غير متوفر",
"about.domain_blocks.preamble": "يسمح لك ماستدون عموماً بعرض المحتوى من المستخدمين من أي خادم آخر في الفدرالية والتفاعل معهم. وهذه هي الاستثناءات التي وضعت على هذا الخادم بالذات.",
"about.domain_blocks.silenced.explanation": "لن تظهر لك ملفات التعريف الشخصية والمحتوى من هذا الخادوم، إلا إن بحثت عنه عمدًا أو تابعته.",
"about.domain_blocks.silenced.explanation": "عموماً، لن ترى ملفات التعريف والمحتوى من هذا الخادم، إلا إذا كنت تبحث عنه بشكل صريح أو تختار أن تتابعه.",
"about.domain_blocks.silenced.title": "محدود",
"about.domain_blocks.suspended.explanation": "لن يتم معالجة أي بيانات من هذا الخادم أو تخزينها أو تبادلها، مما يجعل أي تفاعل أو اتصال مع المستخدمين من هذا الخادم مستحيلا.",
"about.domain_blocks.suspended.title": "مُعلّق",
@ -21,7 +21,7 @@
"account.blocked": "محظور",
"account.browse_more_on_origin_server": "تصفح المزيد في الملف الشخصي الأصلي",
"account.cancel_follow_request": "إلغاء طلب المتابعة",
"account.copy": "نسخ الرابط إلى الملف الشخصي",
"account.copy": "نسخ الرابط إلى الحساب",
"account.direct": "إشارة خاصة لـ @{name}",
"account.disable_notifications": "توقف عن إشعاري عندما ينشر @{name}",
"account.domain_blocked": "اسم النِّطاق محظور",
@ -32,7 +32,7 @@
"account.featured_tags.last_status_never": "لا توجد رسائل",
"account.featured_tags.title": "وسوم {name} المميَّزة",
"account.follow": "متابعة",
"account.follow_back": "تابعهم بالمثل",
"account.follow_back": "رد المتابعة",
"account.followers": "مُتابِعون",
"account.followers.empty": "لا أحدَ يُتابع هذا المُستخدم إلى حد الآن.",
"account.following": "الاشتراكات",
@ -51,7 +51,7 @@
"account.mute_notifications_short": "كتم الإشعارات",
"account.mute_short": "اكتم",
"account.muted": "مَكتوم",
"account.mutual": "متبادلة",
"account.mutual": "متبادل",
"account.no_bio": "لم يتم تقديم وصف.",
"account.open_original_page": "افتح الصفحة الأصلية",
"account.posts": "منشورات",
@ -70,8 +70,8 @@
"account.unmute_notifications_short": "إلغاء كَتم الإشعارات",
"account.unmute_short": "إلغاء الكتم",
"account_note.placeholder": "اضغط لإضافة مُلاحظة",
"admin.dashboard.daily_retention": "معدّل بقاء المستخدمين بعد إنشاء الحسابات، بالأيام",
"admin.dashboard.monthly_retention": "معدّل بقاء المستخدمين بعد إنشاء الحسابات، بالشهور",
"admin.dashboard.daily_retention": "معدل الاحتفاظ بالمستخدم بعد التسجيل بيوم",
"admin.dashboard.monthly_retention": "معدل الاحتفاظ بالمستخدم بعد التسجيل بالشهور",
"admin.dashboard.retention.average": "المعدل",
"admin.dashboard.retention.cohort": "شهر التسجيل",
"admin.dashboard.retention.cohort_size": "المستخدمون الجدد",
@ -87,12 +87,12 @@
"attachments_list.unprocessed": "(غير معالَج)",
"audio.hide": "إخفاء المقطع الصوتي",
"block_modal.remote_users_caveat": "سوف نطلب من الخادم {domain} أن يحترم قرارك، لكن الالتزام غير مضمون لأن بعض الخواديم قد تتعامل مع نصوص الكتل بشكل مختلف. قد تظل المنشورات العامة مرئية للمستخدمين غير المسجلين الدخول.",
"block_modal.show_less": "تفاصيل أقلّ",
"block_modal.show_more": "تفاصيل أكثر",
"block_modal.show_less": "أظهر الأقل",
"block_modal.show_more": "أظهر المزيد",
"block_modal.they_cant_mention": "لن يستطيع ذِكرك أو متابعتك.",
"block_modal.they_cant_see_posts": "لن يستطيع مطالعة منشوراتك ولن تطالع منشوراته.",
"block_modal.they_will_know": "سيعلم أنه قد حُظِر.",
"block_modal.title": "أتريد حظر هذا المستخدم؟",
"block_modal.they_cant_see_posts": "لن يستطيع رؤية منشوراتك ولن ترى منشوراته.",
"block_modal.they_will_know": "يمكنه أن يرى أنه قد تم حظره.",
"block_modal.title": "أتريد حظر المستخدم؟",
"block_modal.you_wont_see_mentions": "لن تر المنشورات التي يُشار فيهم إليه.",
"boost_modal.combo": "يُمكنك الضّغط على {combo} لتخطي هذا في المرة المُقبلة",
"bundle_column_error.copy_stacktrace": "انسخ تقرير الخطأ",
@ -156,7 +156,7 @@
"compose_form.poll.single": "اختر واحدا",
"compose_form.poll.switch_to_multiple": "تغيِير الاستطلاع للسماح باِخيارات مُتعدِّدة",
"compose_form.poll.switch_to_single": "تغيِير الاستطلاع للسماح باِخيار واحد فقط",
"compose_form.poll.type": "الطراز",
"compose_form.poll.type": "الأسلوب",
"compose_form.publish": "نشر",
"compose_form.publish_form": "منشور جديد",
"compose_form.reply": "ردّ",

View File

@ -35,9 +35,7 @@
"account.follow_back": "Падпісацца ў адказ",
"account.followers": "Падпісчыкі",
"account.followers.empty": "Ніхто пакуль не падпісаны на гэтага карыстальніка.",
"account.followers_counter": "{count, plural, one {{counter} падпісчык} few {{counter} падпісчыкі} many {{counter} падпісчыкаў} other {{counter} падпісчыка}}",
"account.following": "Падпіскі",
"account.following_counter": "{count, plural, one {{counter} падпіска} few {{counter} падпіскі} many {{counter} падпісак} other {{counter} падпіскі}}",
"account.follows.empty": "Карыстальнік ні на каго не падпісаны.",
"account.go_to_profile": "Перайсці да профілю",
"account.hide_reblogs": "Схаваць пашырэнні ад @{name}",
@ -63,7 +61,6 @@
"account.requested_follow": "{name} адправіў запыт на падпіску",
"account.share": "Абагуліць профіль @{name}",
"account.show_reblogs": "Паказаць падштурхоўванні ад @{name}",
"account.statuses_counter": "{count, plural, one {{counter} допіс} few {{counter} допісы} many {{counter} допісаў} other {{counter} допісу}}",
"account.unblock": "Разблакіраваць @{name}",
"account.unblock_domain": "Разблакіраваць дамен {domain}",
"account.unblock_short": "Разблакіраваць",
@ -415,7 +412,6 @@
"limited_account_hint.title": "Гэты профіль быў схаваны мадэратарамі",
"link_preview.author": "Ад {name}",
"link_preview.more_from_author": "Больш ад {name}",
"link_preview.shares": "{count, plural, one {{counter} допіс} few {{counter} допісы} many {{counter} допісаў} other {{counter} допісу}}",
"lists.account.add": "Дадаць да спісу",
"lists.account.remove": "Выдаліць са спісу",
"lists.delete": "Выдаліць спіс",

View File

@ -35,9 +35,7 @@
"account.follow_back": "Последване взаимно",
"account.followers": "Последователи",
"account.followers.empty": "Още никой не следва потребителя.",
"account.followers_counter": "{count, plural, one {{counter} последовател} other {{counter} последователи}}",
"account.following": "Последвано",
"account.following_counter": "{count, plural, one {{counter} последван} other {{counter} последвани}}",
"account.follows.empty": "Потребителят още никого не следва.",
"account.go_to_profile": "Към профила",
"account.hide_reblogs": "Скриване на подсилвания от @{name}",
@ -63,7 +61,6 @@
"account.requested_follow": "{name} поиска да ви последва",
"account.share": "Споделяне на профила на @{name}",
"account.show_reblogs": "Показване на подсилвания от @{name}",
"account.statuses_counter": "{count, plural, one {{counter} публикация} other {{counter} публикации}}",
"account.unblock": "Отблокиране на @{name}",
"account.unblock_domain": "Отблокиране на домейн {domain}",
"account.unblock_short": "Отблокиране",

View File

@ -197,7 +197,7 @@
"copy_icon_button.copied": "Zkopírováno do schránky",
"copypaste.copied": "Zkopírováno",
"copypaste.copy_to_clipboard": "Zkopírovat do schránky",
"directory.federated": "Ze známého fediversu",
"directory.federated": "Ze známého fedivesmíru",
"directory.local": "Pouze z {domain}",
"directory.new_arrivals": "Nově příchozí",
"directory.recently_active": "Nedávno aktivní",
@ -213,7 +213,7 @@
"domain_block_modal.block_account_instead": "Raději blokovat @{name}",
"domain_block_modal.they_can_interact_with_old_posts": "Lidé z tohoto serveru mohou interagovat s vašimi starými příspěvky.",
"domain_block_modal.they_cant_follow": "Nikdo z tohoto serveru vás nemůže sledovat.",
"domain_block_modal.they_wont_know": "Nebude vědět, že je zablokován*a.",
"domain_block_modal.they_wont_know": "Nebude vědět, že je zablokován.",
"domain_block_modal.title": "Blokovat doménu?",
"domain_block_modal.you_will_lose_followers": "Všichni vaši sledující z tohoto serveru budou odstraněni.",
"domain_block_modal.you_wont_see_posts": "Neuvidíte příspěvky ani upozornění od uživatelů z tohoto serveru.",
@ -341,7 +341,7 @@
"hashtag.column_settings.tag_mode.any": "Jakýkoliv z těchto",
"hashtag.column_settings.tag_mode.none": "Žádný z těchto",
"hashtag.column_settings.tag_toggle": "Zahrnout v tomto sloupci další štítky",
"hashtag.counter_by_accounts": "{count, plural, one {{counter} účastník*ice} few {{counter} účastníci} other {{counter} účastníků}}",
"hashtag.counter_by_accounts": "{count, plural, one {{counter} účastník} few {{counter} účastníci} other {{counter} účastníků}}",
"hashtag.counter_by_uses": "{count, plural, one {{counter} příspěvek} few {{counter} příspěvky} other {{counter} příspěvků}}",
"hashtag.counter_by_uses_today": "Dnes {count, plural, one {{counter} příspěvek} few {{counter} příspěvky} other {{counter} příspěvků}}",
"hashtag.follow": "Sledovat hashtag",
@ -440,7 +440,7 @@
"mute_modal.show_options": "Zobrazit možnosti",
"mute_modal.they_can_mention_and_follow": "Mohou vás zmínit a sledovat, ale neuvidíte je.",
"mute_modal.they_wont_know": "Nebudou vědět, že byli skryti.",
"mute_modal.title": "Ztlumit uživatele*ku?",
"mute_modal.title": "Ztlumit uživatele?",
"mute_modal.you_wont_see_mentions": "Neuvidíte příspěvky, které je zmiňují.",
"mute_modal.you_wont_see_posts": "Stále budou moci vidět vaše příspěvky, ale vy jejich neuvidíte.",
"navigation_bar.about": "O aplikaci",
@ -566,8 +566,8 @@
"onboarding.share.message": "Jsem {username} na #Mastodonu! Pojď mě sledovat na {url}",
"onboarding.share.next_steps": "Možné další kroky:",
"onboarding.share.title": "Sdílejte svůj profil",
"onboarding.start.lead": "Nyní jste součástí Mastodonu, unikátní sociální sítě, kde vy - ne algoritmus - vytváří vaše vlastní prožitky. Začněte na této nové sociální platformě:",
"onboarding.start.skip": "Nepotřebujete pomoci začít?",
"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": "Dokázali jste to!",
"onboarding.steps.follow_people.body": "Mastodon je o sledování zajimavých lidí.",
"onboarding.steps.follow_people.title": "Přispůsobit vlastní domovský kanál",
@ -581,7 +581,7 @@
"onboarding.tips.accounts_from_other_servers": "<strong>Víte, že?</strong> Protože je Mastodon decentralizovaný, některé profily, na které narazíte, budou hostovány na jiných serverech, než je ten váš. A přesto s nimi můžete bezproblémově komunikovat! Jejich server se nachází v druhé polovině uživatelského jména!",
"onboarding.tips.migration": "<strong>Víte, že?</strong> Pokud máte pocit, že {domain} pro vás v budoucnu není vhodnou volbou, můžete se přesunout na jiný Mastodon server, aniž byste přišli o své sledující. Můžete dokonce hostovat svůj vlastní server!",
"onboarding.tips.verification": "<strong>Víte, že?</strong> Svůj účet můžete ověřit tak, že na své webové stránky umístíte odkaz na váš Mastodon profil a odkaz na stránku přidáte do svého profilu. Nejsou k tomu potřeba žádné poplatky ani dokumenty!",
"password_confirmation.exceeds_maxlength": "Potvrzení hesla překračuje maximální povolenou délku hesla",
"password_confirmation.exceeds_maxlength": "Potvrzení hesla překračuje maximální délku hesla",
"password_confirmation.mismatching": "Zadaná hesla se neshodují",
"picture_in_picture.restore": "Vrátit zpět",
"poll.closed": "Uzavřeno",
@ -665,7 +665,7 @@
"report.unfollow": "Přestat sledovat @{name}",
"report.unfollow_explanation": "Tento účet sledujete. Abyste už neviděli jeho příspěvky ve své domovské časové ose, přestaňte jej sledovat.",
"report_notification.attached_statuses": "{count, plural, one {{count} připojený příspěvek} few {{count} připojené příspěvky} many {{count} připojených příspěvků} other {{count} připojených příspěvků}}",
"report_notification.categories.legal": "Právní ustanovení",
"report_notification.categories.legal": "Zákonné",
"report_notification.categories.other": "Ostatní",
"report_notification.categories.spam": "Spam",
"report_notification.categories.violation": "Porušení pravidla",

View File

@ -411,7 +411,6 @@
"limited_account_hint.action": "構わず表示する",
"limited_account_hint.title": "このプロフィールは{domain}のモデレーターによって非表示にされています。",
"link_preview.author": "{name}",
"link_preview.more_from_author": "{name}さんの投稿をもっと読む",
"lists.account.add": "リストに追加",
"lists.account.remove": "リストから外す",
"lists.delete": "リストを削除",
@ -692,11 +691,8 @@
"server_banner.about_active_users": "過去30日間にこのサーバーを使用している人 (月間アクティブユーザー)",
"server_banner.active_users": "人のアクティブユーザー",
"server_banner.administered_by": "管理者",
"server_banner.is_one_of_many": "{domain} は、数々の独立したMastodonサーバーのうちのひとつです。サーバーに登録してFediverseのコミュニティに加わってみませんか。",
"server_banner.server_stats": "サーバーの情報",
"sign_in_banner.create_account": "アカウント作成",
"sign_in_banner.follow_anyone": "連合内の誰でもフォローして投稿を時系列で見ることができます。アルゴリズム、広告、クリックベイトはありません。",
"sign_in_banner.mastodon_is": "Mastodonに参加して、世界で起きていることを見つけよう。",
"sign_in_banner.sign_in": "ログイン",
"sign_in_banner.sso_redirect": "ログインまたは登録",
"status.admin_account": "@{name}さんのモデレーション画面を開く",

View File

@ -1,10 +1,6 @@
{
"about.blocks": "Ulac agbur",
"about.contact": "Anermis:",
"about.disclaimer": "Mastodon d aseɣẓan ilelli, d aseɣẓan n uɣbalu yeldin, d tnezzut n Mastodon gGmbH.",
"about.domain_blocks.preamble": "Maṣṭudun s umata yeḍmen-ak ad teẓreḍ agbur, ad tesdemreḍ akked yimseqdacen-nniḍen seg yal aqeddac deg fedivers. Ha-tent-an ɣur-k tsuraf i yellan deg uqeddac-agi.",
"about.domain_blocks.silenced.title": "Ɣur-s talast",
"about.domain_blocks.suspended.title": "Yeḥbes",
"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",
@ -28,12 +24,9 @@
"account.featured_tags.last_status_at": "Tasuffeɣt taneggarut ass n {date}",
"account.featured_tags.last_status_never": "Ulac tisuffaɣ",
"account.follow": "Ḍfer",
"account.follow_back": "Ḍfer-it ula d kečč·m",
"account.followers": "Imeḍfaren",
"account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.",
"account.followers_counter": "{count, plural, one {{counter} n umḍfar} other {{counter} n yimeḍfaren}}",
"account.following": "Yeṭṭafaṛ",
"account.following_counter": "{count, plural, one {{counter} yettwaḍfaren} other {{counter} yettwaḍfaren}}",
"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}",
@ -56,7 +49,6 @@
"account.requested_follow": "{name} yessuter ad k·m-yeḍfer",
"account.share": "Bḍu amaɣnu n @{name}",
"account.show_reblogs": "Ssken-d inebḍa n @{name}",
"account.statuses_counter": "{count, plural, one {{counter} n tsuffeɣt} other {{counter} n tsuffaɣ}}",
"account.unblock": "Serreḥ i @{name}",
"account.unblock_domain": "Ssken-d {domain}",
"account.unblock_short": "Serreḥ",
@ -174,7 +166,6 @@
"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.",
"domain_block_modal.block": "Sewḥel aqeddac",
"domain_block_modal.they_cant_follow": "Yiwen ur yezmir ad k·m-id-yeḍfer seg uqeddac-a.",
"domain_block_modal.title": "Sewḥel taɣult?",
"domain_pill.activitypub_like_language": "ActivityPub am tutlayt yettmeslay Mastodon d izeḍwan inmettiyen nniḍen.",
"domain_pill.server": "Aqeddac",
"domain_pill.username": "Isem n useqdac",
@ -223,7 +214,6 @@
"filter_modal.added.review_and_configure_title": "Iɣewwaṛen n imzizdig",
"filter_modal.added.settings_link": "asebter n yiɣewwaṛen",
"filter_modal.added.short_explanation": "Tasuffeɣt-a tettwarna ɣer taggayt-a n yimsizdegen: {title}.",
"filter_modal.added.title": "Yettwarna umsizdeg!",
"filter_modal.select_filter.expired": "yemmut",
"filter_modal.select_filter.prompt_new": "Taggayt tamaynutt : {name}",
"filter_modal.select_filter.search": "Nadi neɣ snulfu-d",
@ -234,9 +224,9 @@
"firehose.remote": "Iqeddacen nniḍen",
"follow_request.authorize": "Ssireg",
"follow_request.reject": "Agi",
"follow_suggestions.dismiss": "Dayen ur t-id-skan ara",
"follow_suggestions.dismiss": "Ur ttɛawad ara ad t-id-sekneṭ",
"follow_suggestions.view_all": "Wali-ten akk",
"follow_suggestions.who_to_follow": "Ad tḍefreḍ?",
"follow_suggestions.who_to_follow": "Menhu ara ḍefṛeḍ",
"followed_tags": "Ihacṭagen yettwaḍfaren",
"footer.about": "Ɣef",
"footer.directory": "Akaram n imeɣna",
@ -245,7 +235,6 @@
"footer.keyboard_shortcuts": "Inegzumen n unasiw",
"footer.privacy_policy": "Tasertit tabaḍnit",
"footer.source_code": "Wali tangalt taɣbalut",
"footer.status": "N tsuffeɣt",
"generic.saved": "Yettwasekles",
"getting_started.heading": "Bdu",
"hashtag.column_header.tag_mode.all": "d {additional}",
@ -324,14 +313,11 @@
"lightbox.previous": "Ɣer deffir",
"limited_account_hint.action": "Wali amaɣnu akken yebɣu yili",
"link_preview.author": "S-ɣur {name}",
"link_preview.more_from_author": "Ugar sɣur {name}",
"link_preview.shares": "{count, plural, one {{counter} post} other {{counter} posts}}",
"lists.account.add": "Rnu ɣer tebdart",
"lists.account.remove": "Kkes seg tebdart",
"lists.delete": "Kkes tabdart",
"lists.edit": "Ẓreg tabdart",
"lists.edit.submit": "Beddel azwel",
"lists.exclusive": "Ffer tisuffaɣ-a seg ugejdan",
"lists.new.create": "Rnu tabdart",
"lists.new.title_placeholder": "Azwel amaynut n tebdart",
"lists.replies_policy.followed": "Kra n useqdac i yettwaḍefren",
@ -352,7 +338,6 @@
"navigation_bar.bookmarks": "Ticraḍ",
"navigation_bar.community_timeline": "Tasuddemt tadigant",
"navigation_bar.compose": "Aru tajewwiqt tamaynut",
"navigation_bar.direct": "Tibdarin tusligin",
"navigation_bar.discover": "Ẓer",
"navigation_bar.domain_blocks": "Tiɣula yeffren",
"navigation_bar.explore": "Snirem",
@ -372,14 +357,9 @@
"navigation_bar.search": "Nadi",
"navigation_bar.security": "Taɣellist",
"not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.",
"notification.admin.report": "Yemla-t-id {name} {target}",
"notification.admin.sign_up": "Ijerred {name}",
"notification.favourite": "{name} yesmenyaf addad-ik·im",
"notification.follow": "iṭṭafar-ik·em-id {name}",
"notification.follow_request": "{name} yessuter-d ad k·m-yeḍfeṛ",
"notification.mention": "{name} yebder-ik-id",
"notification.moderation-warning.learn_more": "Issin ugar",
"notification.moderation_warning.action_suspend": "Yettwaseḥbes umiḍan-ik.",
"notification.own_poll": "Tafrant-ik·im tfuk",
"notification.poll": "Tfukk tefrant ideg tettekkaḍ",
"notification.reblog": "{name} yebḍa tajewwiqt-ik i tikelt-nniḍen",
@ -390,7 +370,6 @@
"notification_requests.notifications_from": "Ilɣa sɣur {name}",
"notifications.clear": "Sfeḍ tilɣa",
"notifications.clear_confirmation": "Tebɣiḍ s tidet ad tekkseḍ akk tilɣa-inek·em i lebda?",
"notifications.column_settings.admin.report": "Ineqqisen imaynuten:",
"notifications.column_settings.alert": "Tilɣa n tnarit",
"notifications.column_settings.favourite": "Imenyafen:",
"notifications.column_settings.filter_bar.advanced": "Sken-d akk taggayin",
@ -405,7 +384,6 @@
"notifications.column_settings.sound": "Rmed imesli",
"notifications.column_settings.status": "Tisuffaɣ timaynutin :",
"notifications.column_settings.unread_notifications.category": "Ilɣa ur nettwaɣra",
"notifications.column_settings.update": "Iẓreg:",
"notifications.filter.all": "Akk",
"notifications.filter.boosts": "Seǧhed",
"notifications.filter.favourites": "Imenyafen",
@ -435,7 +413,6 @@
"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": "Ttwassnen deg Mastodon",
"onboarding.profile.display_name": "Isem ara d-yettwaskanen",
"onboarding.profile.display_name_hint": "Isem-ik·im ummid neɣ isem-ik·im n uqeṣṣer…",
"onboarding.profile.note": "Tameddurt",
"onboarding.profile.note_hint": "Tzemreḍ ad d-@tbedreḍ imdanen niḍen neɣ #ihacṭagen …",
"onboarding.profile.save_and_continue": "Sekles, tkemmleḍ",
@ -464,7 +441,6 @@
"poll.total_votes": "{count, plural, one {# n udɣaṛ} other {# n yedɣaṛen}}",
"poll.vote": "Dɣeṛ",
"poll.voted": "Tdeɣṛeḍ ɣef tririt-ayi",
"poll.votes": "{votes, plural, one {# n udɣaṛ} other {# n yedɣaṛen}}",
"poll_button.add_poll": "Rnu asenqed",
"poll_button.remove_poll": "Kkes asenqed",
"privacy.change": "Seggem tabaḍnit n yizen",
@ -489,12 +465,9 @@
"relative_time.seconds": "{number}tas",
"relative_time.today": "assa",
"reply_indicator.cancel": "Sefsex",
"reply_indicator.poll": "Afmiḍi",
"report.block": "Sewḥel",
"report.categories.legal": "Azerfan",
"report.categories.other": "Tiyyaḍ",
"report.categories.spam": "Aspam",
"report.category.subtitle": "Fren amṣada akk ufrin",
"report.category.title_account": "ameɣnu",
"report.category.title_status": "tasuffeɣt",
"report.close": "Immed",
@ -503,25 +476,13 @@
"report.next": "Uḍfiṛ",
"report.placeholder": "Iwenniten-nniḍen",
"report.reasons.dislike": "Ur t-ḥemmleɣ ara",
"report.reasons.dislike_description": "D ayen akk ur bɣiɣ ara ad waliɣ",
"report.reasons.other": "D ayen nniḍen",
"report.reasons.other_description": "Ugur ur yemṣada ara akk d taggayin-nniḍen",
"report.reasons.spam": "D aspam",
"report.reasons.spam_description": "Yir iseɣwan, yir agman d tririyin i d-yettuɣalen",
"report.reasons.violation": "Truẓi n yilugan n uqeddac",
"report.reasons.violation_description": "Teẓriḍ y·tettruẓu kra n yilugan",
"report.rules.subtitle": "Fren ayen akk yemṣadan",
"report.rules.title": "Acu n yilugan i yettwarẓan?",
"report.statuses.subtitle": "Fren ayen akk yemṣadan",
"report.statuses.title": "Llant tsuffaɣ ara isdemren aneqqis-a?",
"report.submit": "Azen",
"report.target": "Mmel {target}",
"report.thanks.take_action_actionable": "Ideg nekkni nessenqad tuttra-inek•inem, tzemreḍ ad tḥadreḍ mgal @{name}:",
"report.thanks.title": "Ur tebɣiḍ ara ad twaliḍ aya?",
"report.thanks.title_actionable": "Tanemmirt ɣef uneqqis, ad nwali deg waya.",
"report.unfollow": "Seḥbes aḍfar n @{name}",
"report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached",
"report_notification.categories.legal": "Azerfan",
"report_notification.categories.other": "Ayen nniḍen",
"report_notification.categories.spam": "Aspam",
"report_notification.open": "Ldi aneqqis",
@ -536,7 +497,6 @@
"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.quick_actions": "Tigawin tiruradin",
"search_popout.recent": "Inadiyen ineggura",
"search_popout.user": "amseqdac",
"search_results.accounts": "Imeɣna",
@ -545,9 +505,7 @@
"search_results.see_all": "Wali-ten akk",
"search_results.statuses": "Tisuffaɣ",
"search_results.title": "Anadi ɣef {q}",
"server_banner.active_users": "iseqdacen urmiden",
"server_banner.administered_by": "Yettwadbel sɣur :",
"server_banner.server_stats": "Tidaddanin n uqeddac:",
"sign_in_banner.create_account": "Snulfu-d amiḍan",
"sign_in_banner.sign_in": "Qqen",
"sign_in_banner.sso_redirect": "Qqen neɣ jerred",
@ -558,21 +516,13 @@
"status.cannot_reblog": "Tasuffeɣt-a ur tezmir ara ad tettwabḍu tikelt-nniḍen",
"status.copy": "Nɣel assaɣ ɣer tasuffeɣt",
"status.delete": "Kkes",
"status.direct": "Bder-d @{name} weḥd-s",
"status.direct_indicator": "Abdar uslig",
"status.edit": "Ẓreg",
"status.edited_x_times": "Tettwaẓreg {count, plural, one {{count} n tikkelt} other {{count} n tikkal}}",
"status.embed": "Seddu",
"status.favourite": "Amenyaf",
"status.favourites": "{count, plural, one {n usmenyaf} other {n ismenyafen}}",
"status.filter": "Sizdeg tassufeɣt-a",
"status.filtered": "Yettwasizdeg",
"status.hide": "Ffer tasuffeɣt",
"status.history.created": "Yerna-t {name} {date}",
"status.history.edited": "Ibeddel-it {name} {date}",
"status.load_more": "Sali ugar",
"status.media.open": "Sit i ulday",
"status.media.show": "Sit i uskan",
"status.media_hidden": "Amidya yettwaffer",
"status.mention": "Bder-d @{name}",
"status.more": "Ugar",
@ -584,7 +534,6 @@
"status.read_more": "Issin ugar",
"status.reblog": "Bḍu",
"status.reblogged_by": "Yebḍa-tt {name}",
"status.reblogs": "{count, plural, one {n usnerni} other {n yisnernuyen}}",
"status.reblogs.empty": "Ula yiwen ur yebḍi tajewwiqt-agi ar tura. Ticki yebḍa-tt yiwen, ad d-iban da.",
"status.redraft": "Kkes tɛiwdeḍ tira",
"status.remove_bookmark": "Kkes tacreḍt",
@ -599,7 +548,6 @@
"status.show_less_all": "Semẓi akk tisuffɣin",
"status.show_more": "Ssken-d ugar",
"status.show_more_all": "Ẓerr ugar lebda",
"status.show_original": "Sken aɣbalu",
"status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}",
"status.translate": "Suqel",
"status.translated_from_with": "Yettwasuqel seg {lang} s {provider}",
@ -634,7 +582,6 @@
"upload_form.video_description": "Glem-d i yemdanen i yesɛan ugur deg tmesliwt neɣ deg yiẓri",
"upload_modal.analyzing_picture": "Tasleḍt n tugna tetteddu…",
"upload_modal.apply": "Snes",
"upload_modal.applying": "Asnas…",
"upload_modal.choose_image": "Fren tugna",
"upload_modal.description_placeholder": "Aberraɣ arurad ineggez nnig n uqjun amuṭṭis",
"upload_modal.detect_text": "Sefru-d aḍris seg tugna",
@ -642,7 +589,6 @@
"upload_modal.preparing_ocr": "Aheyyi n OCR…",
"upload_modal.preview_label": "Taskant ({ratio})",
"upload_progress.label": "Asali iteddu...",
"upload_progress.processing": "Asesfer…",
"username.taken": "Yettwaṭṭef yisem-a n useqdac. Ɛreḍ wayeḍ",
"video.close": "Mdel tabidyutt",
"video.download": "Sidered afaylu",

View File

@ -35,7 +35,6 @@
"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, zero {{count} sekotāju} one {{count} sekotājs} other {{count} sekotāji}}",
"account.following": "Seko",
"account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.",
"account.go_to_profile": "Doties uz profilu",
@ -313,9 +312,9 @@
"home.column_settings.show_reblogs": "Rādīt pastiprinātos ierakstus",
"home.column_settings.show_replies": "Rādīt atbildes",
"home.hide_announcements": "Slēpt paziņojumus",
"home.pending_critical_update.body": "Lūgums pēc iespējas drīzāk atjaunināt savu Mastodon serveri.",
"home.pending_critical_update.body": "Lūdzu, pēc iespējas ātrāk atjaunini savu Mastodon serveri!",
"home.pending_critical_update.link": "Skatīt jauninājumus",
"home.pending_critical_update.title": "Ir pieejams būtisks drošības atjauninājums.",
"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 lietotāja ierakstus savā mājas plūsmā.",

View File

@ -3,8 +3,6 @@
"about.contact": "Контакт:",
"about.disclaimer": "Mastodon є задарьнов проґрамов из удпертым кодом тай торговов значков Mastodon gGmbH.",
"about.domain_blocks.no_reason_available": "Причины не ясні",
"about.domain_blocks.preamble": "Майбульш Mastodon поволят вам позирати контент тай комуніковати из хосновачами из другых федерованых серверув. Туй лиш уняткы учинені про сись конкретный сервер.",
"about.domain_blocks.silenced.explanation": "Вы майбульш не будете видіти профілі тай контент из сього сервера, кидь не будете го самі глядати авадь пудпишете ся на нього.",
"about.domain_blocks.silenced.title": "Обмежено",
"about.domain_blocks.suspended.explanation": "Ниякі податкы из сього сервера не будут уброблені, усокочені ци поміняні, што чинит невозможнов хоть-яку інтеракцію ци зязок из хосновачами из сього сервера.",
"about.domain_blocks.suspended.title": "Заблоковано",
@ -22,7 +20,6 @@
"account.browse_more_on_origin_server": "Позирайте бульше на ориґіналнум профілю",
"account.cancel_follow_request": "Удмінити пудписку",
"account.copy": "Зкопіровати удкликованя на профіл",
"account.direct": "Пошептати @{name}",
"account.disable_notifications": "Бульше не сповіщати ми коли {name} пише",
"account.domain_blocked": "Домен заблокованый",
"account.edit_profile": "Управити профіл",
@ -42,10 +39,8 @@
"account.joined_short": "Датум прикапчованя",
"account.languages": "Поміняти убрані языкы",
"account.link_verified_on": "Властность сього удкликованя было звірено {date}",
"account.locked_info": "Сись профіл є замкнутый. Ґазда акаунта буде ручно провіряти тко го може зафоловити.",
"account.media": "Медіа",
"account.mention": "Спомянути @{name}",
"account.moved_to": "Хосновач {name} указав, ож новый профіл му є:",
"account.moved_to": "Хосновач {name} указав, ож новый профіл йим є:",
"account.mute": "Стишити {name}",
"account.mute_notifications_short": "Стишити голошіня",
"account.mute_short": "Стишити",
@ -65,12 +60,9 @@
"account.unblock_short": "Розблоковати",
"account.unendorse": "Не указовати на профілови",
"account.unfollow": "Удписати ся",
"account.unmute": "Указовати {name}",
"account.unmute_notifications_short": "Указовати голошіня",
"account.unmute_short": "Указовати",
"account_note.placeholder": "Клопкніт обы додати примітку",
"admin.dashboard.retention.average": "Середньоє",
"admin.dashboard.retention.cohort": "Місяць прикапчованя",
"admin.dashboard.retention.cohort_size": "Нові хосновачі",
"admin.impact_report.instance_accounts": "Профілі из акаунтув, котрі ся удалят",
"admin.impact_report.instance_followers": "Пудписникы, котрых стратят наші хосновачі",
@ -78,77 +70,11 @@
"admin.impact_report.title": "Вплыв цілком",
"alert.rate_limited.message": "Попробуйте зась по {retry_time, time, medium}.",
"alert.rate_limited.title": "Частота обмежена",
"alert.unexpected.message": "Стала ся нечекана хыба.",
"alert.unexpected.title": "Ийой!",
"announcement.announcement": "Голошіня",
"audio.hide": "Зпрятати звук",
"block_modal.remote_users_caveat": "Попросиме ґазду сервера {domain} честовати вашоє рішеня. Айбо не ґарантуєме повный соглас, бо даякі серверы можут брати блокованя по-инчакому. Публичні дописы годно быти видко незалоґованым хосновачам.",
"block_modal.show_less": "Указати менше",
"block_modal.show_more": "Указати бульше",
"block_modal.they_cant_mention": "Они не можут вас споминати авадь слідовати.",
"block_modal.they_cant_see_posts": "Они не можут видіти ваші публикації, тай наспак — вы йихні.",
"block_modal.they_will_know": "Они видят, ож сут заблоковані.",
"block_modal.title": "Заблоковати хосновача?",
"block_modal.you_wont_see_mentions": "Не будете видіти публикації тай споминкы сього хосновача.",
"boost_modal.combo": "Можете клынцнути {combo} другый раз обы сесе пропустити",
"bundle_column_error.copy_stacktrace": "Укопіровати звіт за хыбу",
"bundle_column_error.error.body": "Не годни сьме указати зажадану сторунку. Годно быти спозад хыбы у нашум сістемі, авадь проблемы зумісности бравзера.",
"bundle_column_error.error.title": "Ийой!",
"bundle_column_error.network.body": "Стала ся хыба як сьме пробовали напаровати сторунку. Годно ся йсе было стати спозад слабого споєня вашого інтернета, авадь сервера.",
"bundle_column_error.network.title": "Хыба споєня",
"bundle_column_error.retry": "Попробуйте зась",
"bundle_column_error.return": "Вернути ся на головну",
"bundle_column_error.routing.body": "Не можеме найти сяку сторунку. Бизувні сьте, ож URL у адресному шорикови є добрый?",
"bundle_column_error.routing.title": "404",
"bundle_modal_error.close": "Заперти",
"bundle_modal_error.message": "Штось ся показило, закидь сьме ладовали сись компонент.",
"bundle_modal_error.retry": "Попробовати зась",
"closed_registrations.other_server_instructions": "Mastodon є децентралізованов платформов, можете си учинити профіл и на другому серверови тай комуніковати из сим.",
"closed_registrations_modal.description": "Раз не мож учинити профіл на {domain}, айбо не мусите мати профіл ипен на серверови {domain} обы хосновати Mastodon.",
"closed_registrations_modal.find_another_server": "Найти другый сервер",
"column.about": "За сайт",
"column.blocks": "Заблоковані хосновачі",
"column.bookmarks": "Усокоченоє",
"column.direct": "Шептаня",
"column.directory": "Никати профілі",
"column.domain_blocks": "Заблоковані домены",
"column.favourites": "Убраноє",
"column.follow_requests": "Запросы на пудписку",
"column.lists": "Исписы",
"column.mutes": "Стишені хосновачі",
"column.notifications": "Убвіщеня",
"column.pins": "Закріплені публикації",
"column_back_button.label": "Назад",
"column_header.hide_settings": "Спрятати штімованя",
"column_header.moveLeft_settings": "Посунути колонку до ліва",
"column_header.moveRight_settings": "Посунути колонку до права",
"column_header.pin": "Закріпити",
"column_header.show_settings": "Указати штімованя",
"column_header.unpin": "Удкріпити",
"column_subheading.settings": "Штімованя",
"compose.language.change": "Поміняти язык",
"compose.language.search": "Глядати языкы...",
"compose.published.body": "Пост опубликованый.",
"compose.saved.body": "Пост усокоченый.",
"compose_form.direct_message_warning_learn_more": "Читайте бульше",
"compose_form.encryption_warning": "Публикації на Mastodon не шіфрувут ся. Не шырьте чутливу інформацію через Mastodon.",
"compose_form.hashtag_warning": "Сись пост не буде ся появляти у исписови по гештеґови, бо вун не є публичный. Лишек публичні посты буде видко за гештеґом.",
"compose_form.lock_disclaimer": "Ваш профіл є {locked}. Хоть-тко може ся на вас пудписати, обы видїти ваші ексклузівні посты.",
"compose_form.lock_disclaimer.lock": "замкнено",
"compose_form.placeholder": "Што нового?",
"compose_form.poll.duration": "Трывалость убзвідованя",
"compose_form.poll.multiple": "Дакулько варіантув",
"compose_form.poll.option_placeholder": "Варіант {number}",
"compose_form.poll.single": "Уберіт єден",
"compose_form.poll.switch_to_multiple": "Змінити убзвідованя обы поволити дакулько варіантув",
"compose_form.poll.switch_to_single": "Змінити убзвідованя обы поволити лишек єден варіант",
"compose_form.poll.type": "Стіл",
"compose_form.publish": "Публикація",
"compose_form.publish_form": "Нова публикація",
"compose_form.reply": "Удповідь",
"copypaste.copy_to_clipboard": "Копіровати у памнять",
"directory.recently_active": "Недавно актівні",
"disabled_account_banner.account_settings": "Штімованя акаунта",
"disabled_account_banner.text": "Ваш акаунт {disabledAccount} раз є неактівный.",
"dismissable_banner.community_timeline": "Туй сут недавні публикації уд профілув на серверови {domain}."
"closed_registrations.other_server_instructions": "Mastodon є децентралізованов платформов, можете си учинити профіл и на другому серверови тай комуніковати из сим."
}

View File

@ -32,7 +32,7 @@
"account.featured_tags.last_status_never": "Немає дописів",
"account.featured_tags.title": "{name} виділяє хештеґи",
"account.follow": "Підписатися",
"account.follow_back": "Стежити також",
"account.follow_back": "Підписатися взаємно",
"account.followers": "Підписники",
"account.followers.empty": "Ніхто ще не підписаний на цього користувача.",
"account.followers_counter": "{count, plural, one {{counter} підписник} few {{counter} підписники} many {{counter} підписників} other {{counter} підписники}}",
@ -217,18 +217,18 @@
"domain_block_modal.title": "Заблокувати домен?",
"domain_block_modal.you_will_lose_followers": "Усіх ваших підписників з цього сервера буде вилучено.",
"domain_block_modal.you_wont_see_posts": "Ви не бачитимете дописів і сповіщень від користувачів на цьому сервері.",
"domain_pill.activitypub_lets_connect": "Це дозволяє вам спілкуватися та взаємодіяти з людьми не лише на Mastodon, але й у різних соціальних застосунках.",
"domain_pill.activitypub_like_language": "ActivityPub - це як мова, якою Mastodon розмовляє з іншими соціальними мережами.",
"domain_pill.activitypub_lets_connect": "Це дозволяє вам спілкуватися та взаємодіяти з людьми не лише на Mastodon, але й у різних соціальних додатках.",
"domain_pill.activitypub_like_language": "ActivityPub - це як мова, якою Мастодонт розмовляє з іншими соціальними мережами.",
"domain_pill.server": "Сервер",
"domain_pill.their_handle": "Їхня адреса:",
"domain_pill.their_server": "Їхній цифровий дім, де живуть усі їхні дописи.",
"domain_pill.their_server": "Їхній цифровий дім, де живуть усі їхні пости.",
"domain_pill.their_username": "Їхній унікальний ідентифікатор на їхньому сервері. Ви можете знайти користувачів з однаковими іменами на різних серверах.",
"domain_pill.username": "Ім'я користувача",
"domain_pill.whats_in_a_handle": "Що є в адресі?",
"domain_pill.who_they_are": "Оскільки дескриптори вказують, хто це і де він знаходиться, ви можете взаємодіяти з людьми через соціальну мережу платформ на основі <button>ActivityPub</button>.",
"domain_pill.who_you_are": "Оскільки ваш нікнейм вказує, хто ви та де ви, люди можуть взаємодіяти з вами через соціальну мережу платформ на основі <button>ActivityPub</button>.",
"domain_pill.your_handle": "Ваша адреса:",
"domain_pill.your_server": "Ваш цифровий дім, де живуть усі ваші дописи. Не подобається цей? Перенесіть сервери в будь-який час і залучайте своїх підписників.",
"domain_pill.your_server": "Ваш цифровий дім, де живуть усі ваші публікації. Не подобається цей? Перенесіть сервери в будь-який час і залучайте своїх підписників.",
"domain_pill.your_username": "Ваш унікальний ідентифікатор на цьому сервері. Ви можете знайти користувачів з однаковими іменами на різних серверах.",
"embed.instructions": "Вбудуйте цей допис до вашого вебсайту, скопіювавши код нижче.",
"embed.preview": "Ось який вигляд це матиме:",
@ -489,9 +489,9 @@
"notification.reblog": "{name} поширює ваш допис",
"notification.relationships_severance_event": "Втрачено з'єднання з {name}",
"notification.relationships_severance_event.account_suspension": "Адміністратор з {from} призупинив {target}, що означає, що ви більше не можете отримувати оновлення від них або взаємодіяти з ними.",
"notification.relationships_severance_event.domain_block": "Адміністратор з {from} заблокував {target}, включаючи {followersCount} ваших підписників і {followingCount , plural, one {# обліковий запис} few {# облікові записи} many {# облікових записів} other {# обліковий запис}}, на які ви підписані.",
"notification.relationships_severance_event.learn_more": окладніше",
"notification.relationships_severance_event.user_domain_block": "Ви заблокували {target}, видаливши {followersCount} ваших підписників і {followingCount, plural, one {# обліковий запис} few {# облікові записи} many {# облікових записів} other {# обліковий запис}}, за якими ви стежите.",
"notification.relationships_severance_event.domain_block": "Адміністратор з {from} заблокував {target}, включаючи {followersCount} ваших підписників і {{followingCount, plural, one {# account} other {# accounts}}, на які ви підписані.",
"notification.relationships_severance_event.learn_more": ізнатися більше",
"notification.relationships_severance_event.user_domain_block": "Ви заблокували {target}, видаливши {followersCount} ваших підписників і {followingCount, plural, one {# account} other {# accounts}}, за якими ви стежите.",
"notification.status": "{name} щойно дописує",
"notification.update": "{name} змінює допис",
"notification_requests.accept": "Прийняти",

View File

@ -48,10 +48,6 @@ html {
}
}
.icon-button:disabled {
color: darken($action-button-color, 25%);
}
.account__header__bar .avatar .account__avatar {
border-color: $white;
}

View File

@ -1062,10 +1062,6 @@ body > [data-popper-placement] {
}
}
.status__quote {
margin-bottom: 0.5em;
}
.reply-indicator {
display: grid;
grid-template-columns: 46px minmax(0, 1fr);
@ -1145,11 +1141,6 @@ body > [data-popper-placement] {
}
}
.reply-indicator__quote {
padding-inline-start: 10px;
border-inline-start: 3px solid $darker-text-color;
}
.edit-indicator {
border-radius: 4px 4px 0 0;
background: lighten($ui-base-color, 4%);
@ -1375,8 +1366,6 @@ body > [data-popper-placement] {
min-height: 54px;
border-bottom: 1px solid var(--background-border-color);
cursor: auto;
opacity: 1;
animation: fade 150ms linear;
@keyframes fade {
0% {
@ -1388,6 +1377,9 @@ body > [data-popper-placement] {
}
}
opacity: 1;
animation: fade 150ms linear;
.media-gallery,
.video-player,
.audio-player,
@ -4859,10 +4851,8 @@ a.status-card {
&__menu {
@include search-popout;
& {
padding: 0;
background: $ui-secondary-color;
}
padding: 0;
background: $ui-secondary-color;
}
&__menu-list {
@ -10463,7 +10453,7 @@ noscript {
gap: 4px;
dt {
flex: 0 1 auto;
flex: 0 0 auto;
color: $dark-text-color;
min-width: 0;
overflow: hidden;

View File

@ -2503,7 +2503,6 @@ body {
background: $win95-tooltip-yellow;
border: 1px solid black;
padding: 4px;
margin-bottom: 24px;
h1, h1 small {
color:black;
@ -2511,6 +2510,8 @@ body {
text-overflow: unset;
}
margin-bottom: 24px;
&:after {
content: "";
display:block;

View File

@ -62,8 +62,7 @@ class LinkDetailsExtractor
end
def author_name
name = author['name']
name.is_a?(Array) ? name.join(', ') : name
author['name']
end
def author_url
@ -157,11 +156,11 @@ class LinkDetailsExtractor
end
def title
html_entities_decode(structured_data&.headline || opengraph_tag('og:title') || document.xpath('//title').map(&:content).first)&.strip
html_entities.decode(structured_data&.headline || opengraph_tag('og:title') || document.xpath('//title').map(&:content).first).strip
end
def description
html_entities_decode(structured_data&.description || opengraph_tag('og:description') || meta_tag('description'))
html_entities.decode(structured_data&.description || opengraph_tag('og:description') || meta_tag('description'))
end
def published_at
@ -181,7 +180,7 @@ class LinkDetailsExtractor
end
def provider_name
html_entities_decode(structured_data&.publisher_name || opengraph_tag('og:site_name'))
html_entities.decode(structured_data&.publisher_name || opengraph_tag('og:site_name'))
end
def provider_url
@ -189,7 +188,7 @@ class LinkDetailsExtractor
end
def author_name
html_entities_decode(structured_data&.author_name || opengraph_tag('og:author') || opengraph_tag('og:author:username'))
html_entities.decode(structured_data&.author_name || opengraph_tag('og:author') || opengraph_tag('og:author:username'))
end
def author_url
@ -258,7 +257,7 @@ class LinkDetailsExtractor
next if json_ld.blank?
structured_data = StructuredData.new(html_entities_decode(json_ld))
structured_data = StructuredData.new(html_entities.decode(json_ld))
next unless structured_data.valid?
@ -274,11 +273,10 @@ class LinkDetailsExtractor
end
def detect_encoding_and_parse_document
[detect_encoding, nil, header_encoding].uniq.each do |encoding|
[detect_encoding, nil, @html_charset, 'UTF-8'].uniq.each do |encoding|
document = Nokogiri::HTML(@html, nil, encoding)
return document if document.to_s.valid_encoding?
end
Nokogiri::HTML(@html, nil, 'UTF-8')
end
def detect_encoding
@ -286,28 +284,12 @@ class LinkDetailsExtractor
guess&.fetch(:confidence, 0).to_i > 60 ? guess&.fetch(:encoding, nil) : nil
end
def header_encoding
Encoding.find(@html_charset).name if @html_charset
rescue ArgumentError
# Encoding from HTTP header is not recognized by ruby
nil
end
def detector
@detector ||= CharlockHolmes::EncodingDetector.new.tap do |detector|
detector.strip_tags = true
end
end
def html_entities_decode(string)
return if string.nil?
unicode_string = string.to_s.encode('UTF-8')
raise EncodingError, 'cannot convert string to valid UTF-8' unless unicode_string.valid_encoding?
html_entities.decode(unicode_string)
end
def html_entities
@html_entities ||= HTMLEntities.new(:expanded)
end

View File

@ -103,10 +103,6 @@ module User::HasSettings
settings['web.disable_swiping']
end
def setting_disable_hover_cards
settings['web.disable_hover_cards']
end
def setting_always_send_emails
settings['always_send_emails']
end

View File

@ -31,6 +31,6 @@ class NotificationPolicy < ApplicationRecord
private
def pending_notification_requests
@pending_notification_requests ||= notification_requests.limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint'))
@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

@ -9,13 +9,12 @@
# from_account_id :bigint(8) not null
# last_status_id :bigint(8)
# 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
self.ignored_columns += %w(dismissed)
include Paginable
MAX_MEANINGFUL_COUNT = 100
@ -35,6 +34,8 @@ class NotificationRequest < ApplicationRecord
end
def reconsider_existence!
return if dismissed?
prepare_notifications_count
if notifications_count.positive?

View File

@ -46,11 +46,6 @@ class PreviewCard < ApplicationRecord
y_comp: 4,
}.freeze
# URL size limit to safely store in PosgreSQL's unique indexes
# Technically this is a byte-size limit but we use it as a
# character limit to work with length validation
URL_CHARACTER_LIMIT = 2692
self.inheritance_column = false
enum :type, { link: 0, photo: 1, video: 2, rich: 3 }
@ -68,7 +63,7 @@ class PreviewCard < ApplicationRecord
convert_options: { all: '-quality 90 +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' },
validate_media_type: false
validates :url, presence: true, uniqueness: true, url: true, length: { maximum: URL_CHARACTER_LIMIT }
validates :url, presence: true, uniqueness: true, url: true
validates_attachment_content_type :image, content_type: IMAGE_MIME_TYPES
validates_attachment_size :image, less_than: LIMIT
remotable_attachment :image, LIMIT

View File

@ -318,7 +318,7 @@ class Status < ApplicationRecord
else
map = media_attachments.index_by(&:id)
ordered_media_attachment_ids.filter_map { |media_attachment_id| map[media_attachment_id] }
end.take(MEDIA_ATTACHMENTS_LIMIT)
end
end
def replies_count

View File

@ -54,14 +54,12 @@ class StatusEdit < ApplicationRecord
def ordered_media_attachments
return @ordered_media_attachments if defined?(@ordered_media_attachments)
@ordered_media_attachments = begin
if ordered_media_attachment_ids.nil?
[]
else
map = status.media_attachments.index_by(&:id)
ordered_media_attachment_ids.map.with_index { |media_attachment_id, index| PreservedMediaAttachment.new(media_attachment: map[media_attachment_id], description: media_descriptions[index]) }
end
end.take(Status::MEDIA_ATTACHMENTS_LIMIT)
@ordered_media_attachments = if ordered_media_attachment_ids.nil?
[]
else
map = status.media_attachments.index_by(&:id)
ordered_media_attachment_ids.map.with_index { |media_attachment_id, index| PreservedMediaAttachment.new(media_attachment: map[media_attachment_id], description: media_descriptions[index]) }
end
end
def quote?

View File

@ -29,7 +29,6 @@ class UserSettings
setting :use_pending_items, default: false
setting :use_system_font, default: false
setting :disable_swiping, default: false
setting :disable_hover_cards, default: false
setting :delete_modal, default: true
setting :reblog_modal, default: false
setting :favourite_modal, default: false

View File

@ -39,7 +39,6 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:expand_spoilers] = object_account_user.setting_expand_spoilers
store[:reduce_motion] = object_account_user.setting_reduce_motion
store[:disable_swiping] = object_account_user.setting_disable_swiping
store[:disable_hover_cards] = object_account_user.setting_disable_hover_cards
store[:advanced_layout] = object_account_user.setting_advanced_layout
store[:use_blurhash] = object_account_user.setting_use_blurhash
store[:use_pending_items] = object_account_user.setting_use_pending_items

View File

@ -15,6 +15,9 @@ class FetchLinkCardService < BaseService
)
}iox
# URL size limit to safely store in PosgreSQL's unique indexes
BYTESIZE_LIMIT = 2692
def call(status)
@status = status
@original_url = parse_urls
@ -29,7 +32,7 @@ class FetchLinkCardService < BaseService
end
attach_card if @card&.persisted?
rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, EncodingError, ActiveRecord::RecordInvalid => e
rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Encoding::UndefinedConversionError => e
Rails.logger.debug { "Error fetching link #{@original_url}: #{e}" }
nil
end
@ -85,7 +88,7 @@ class FetchLinkCardService < BaseService
def bad_url?(uri)
# Avoid local instance URLs and invalid URLs
uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme)
uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme) || uri.to_s.bytesize > BYTESIZE_LIMIT
end
def mention_link?(anchor)

View File

@ -1,6 +1,4 @@
.batch-table__row{ class: [!account.unavailable? && account.user_pending? && 'batch-table__row--attention',
(account.unavailable? || account.user_unconfirmed?) && 'batch-table__row--muted',
(account.previous_strikes_count > 0) && 'batch-table__row--warn'] }
.batch-table__row{ class: [!account.unavailable? && account.user_pending? && 'batch-table__row--attention', (account.unavailable? || account.user_unconfirmed?) && 'batch-table__row--muted'] }
%label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox
= f.check_box :account_ids, { multiple: true, include_hidden: false }, account.id
.batch-table__row__content.batch-table__row__content--unpadded

View File

@ -48,7 +48,6 @@
= ff.input :'web.auto_play', wrapper: :with_label, recommended: true, label: I18n.t('simple_form.labels.defaults.setting_auto_play_gif')
= ff.input :'web.reduce_motion', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_reduce_motion')
= ff.input :'web.disable_swiping', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_disable_swiping')
= ff.input :'web.disable_hover_cards', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_disable_hover_cards')
= ff.input :'web.use_system_font', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_system_font_ui')
= ff.input :'web.use_system_emoji_font', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_system_emoji_font'), glitch_only: true

View File

@ -5,23 +5,6 @@ require_relative '../../lib/mastodon/sidekiq_middleware'
Sidekiq.configure_server do |config|
config.redis = REDIS_SIDEKIQ_PARAMS
# This is used in Kubernetes setups, to signal that the Sidekiq process has started and will begin processing jobs
# This comes from https://github.com/sidekiq/sidekiq/wiki/Kubernetes#sidekiq
ready_filename = ENV.fetch('MASTODON_SIDEKIQ_READY_FILENAME', nil)
if ready_filename
raise 'MASTODON_SIDEKIQ_READY_FILENAME is not a valid filename' if File.basename(ready_filename) != ready_filename
ready_path = Rails.root.join('tmp', ready_filename)
config.on(:startup) do
FileUtils.touch(ready_path)
end
config.on(:shutdown) do
FileUtils.rm_f(ready_path)
end
end
config.server_middleware do |chain|
chain.add Mastodon::SidekiqMiddleware
end

View File

@ -5,7 +5,7 @@ Rails.application.configure do
# You should only generate this once per instance. If you later decide to change it, all push subscription will
# be invalidated, requiring the users to access the website again to resubscribe.
#
# Generate with `bundle exec rails mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web bundle exec rails mastodon:webpush:generate_vapid_key` if you use docker compose)
# Generate with `rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose)
#
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html

View File

@ -8,7 +8,6 @@ ko:
setting_default_content_type_markdown: 게시물을 작성할 때, 형식을 지정하지 않았다면, 마크다운이라고 가정합니다
setting_default_content_type_plain: 게시물을 작성할 때, 형식을 지정하지 않았다면, 일반적인 텍스트라고 가정합니다. (마스토돈의 기본 동작)
setting_default_language: 작성하는 게시물의 언어는 자동으로 설정될 수 있습니다, 하지만 언제나 정확하지는 않습니다
setting_show_followers_count: 팔로워 카운트를 프로필에서 숨깁니다. 팔로워 수를 숨기면 나에게도 보이지 않으며 몇몇 앱에서는 팔로워 수가 음수로 표시될 수 있습니다.
setting_skin: 선택한 마스토돈 풍미의 스킨을 바꿉니다
labels:
defaults:
@ -17,7 +16,6 @@ ko:
setting_default_content_type_markdown: 마크다운
setting_default_content_type_plain: 일반 텍스트
setting_favourite_modal: 관심글을 지정할 때 확인 창을 띄웁니다(글리치 풍미에만 적용됨)
setting_show_followers_count: 팔로워 수 표시
setting_skin: 스킨
setting_system_emoji_font: 에모지에 시스템 기본 폰트 적용하기 (글리치 풍미에만 적용됨)
notification_emails:

View File

@ -21,18 +21,6 @@ kab:
username:
invalid: ilaq ad ilin isekkilen, uṭṭunen d yijerriden n wadda kan
reserved: yettwaṭṭef
admin/webhook:
attributes:
url:
invalid: mačči d URL ameɣtu
doorkeeper/application:
attributes:
website:
invalid: mačči d URL ameɣtu
import:
attributes:
data:
malformed: yir amsal
status:
attributes:
reblog:
@ -40,20 +28,4 @@ kab:
user:
attributes:
email:
blocked: isseqdac asaǧǧaw n yimayl ur yettusirgen ara
unreachable: ur d-ttban ara d akken yella
role_id:
elevated: ur yezmir ara ad iεeddi tamlilt-ik tamirant
user_role:
attributes:
permissions_as_keys:
dangerous: deg-s tisirag tiriɣelsanin i temlilt tazadurt
elevated: ur yezmir ara ad yesεu tirirag ur nelli ara deg temlilit-ik tamirant
own_role: ur yezmir ara ad yettwabeddel s temlilt-ik tamirant
position:
elevated: ur yezmir ara ad iεeddi tamlilt-ik tamirant
own_role: ur yezmir ara ad yettwabeddel s temlilt-ik tamirant
webhook:
attributes:
events:
invalid_permissions: ur yezmir ara ad yesεu tidyanin iwumi ur tesεiḍ ara tisirag

View File

@ -1762,10 +1762,6 @@ ar:
webauthn_authentication: مفاتيح الأمان
severed_relationships:
download: تنزيل (%{count})
lost_followers: المتابعون المفقودون
lost_follows: المتابعات المفقودة
preamble: بحجبكم اسم نطاق قد تخسرون متابَعاتٍ، و كذلك إذا قرّر مديرو الخادوم حظر خادوم ما. و في هذه الحالات يكون بوسعكم تنزيل قائمة بالصلات المبتورة لمعاينتها، مع القدرة على استيرادها إلى خادوم آخر.
purged: حذف مدير خادومكم المعلومات عن هذا الخادوم.
statuses:
attached:
audio:
@ -1982,7 +1978,6 @@ ar:
edit_profile_title: قم بتخصيص ملفك التعريفي
explanation: ها هي بعض النصائح قبل بداية الاستخدام
feature_action: اعرف المزيد
feature_audience: يتيح لكم مًستُدون إدارة جمهوركم بلا وسطاء. فبتنصيب و تشغيل مَستُودون على بنيتكم التحتية تمكنكم متابعة مستخدمي مَستُدون من أيّ خادوم،كما يمكنهم متابعتكم، بلا تحكُّم من أي طرف ثالث.
feature_audience_title: اِبنوا جُمهورَكم بِثِقَة
feature_control: أنتم الأدرى بالمحتوى الذي تريدون أن تطالعوه في فيض المنشورات الرئيس. لا خوارزميات تتحكم فيما يظهر لكم ولا إعلانات تضيع وقتكم. بحساب واحد تمكنكم متابعة من تشاؤون على أيّ خادوم ماستدون، وتلقّى منشوراتهم بترتيبها الزمني، لتصنعوا ركنكم الأليف في الإنترنت.
feature_control_title: تحكَّموا في فيض المنشورات الخاص بكم

View File

@ -118,7 +118,7 @@ cs:
promote: Povýšit
protocol: Protokol
public: Veřejný
push_subscription_expires: Odebírání PuSH vyprší
push_subscription_expires: Odebírání PuSH expiruje
redownload: Obnovit profil
redownloaded_msg: Profil účtu %{username} byl úspěšně obnoven ze zdroje
reject: Zamítnout

View File

@ -12,7 +12,6 @@ kab:
last_attempt: Γur-k yiwen n uɛraḍ-nniḍen kan send ad yettucekkel umiḍan-ik.
locked: Amiḍan-ik yettwargel.
not_found_in_database: Tella tuccḍa deg %{authentication_keys} neγ deg wawal uffir.
omniauth_user_creation_failure: Tuccḍa lawan n tmerna n umiḍan i timagit-a.
pending: Amiḍan-inek mazal-it deg ɛiwed n tmuγli.
timeout: Tiɣimit n tuqqna tezri. Ma ulac aɣilif ɛiwed tuqqna akken ad tkemmleḍ.
unauthenticated: Ilaq ad teqqneḍ neɣ ad tjerrḍeḍ akken ad tkemmelḍ.
@ -48,41 +47,21 @@ kab:
subject: 'Mastodon: Iwellihen n uwennez n wawal uffir'
title: Aɛiwed n wawal uffir
two_factor_disabled:
explanation: Tuqqna tella tura s useqdec n tansa n yimayl tasuft d wawal n uεeddi.
subject: 'Mastodon: Asesteb s snat n tarrayin yensa'
subtitle: Asesteb s snat tarrayin i umiḍan-ik yensan.
title: Asesteb s snat n tarrayin insa
two_factor_enabled:
explanation: Ajuṭu yettusirwen s usnas TOTP yeqqnen ilaq i wakken ad teqqneḍ.
subject: 'Mastodon: Asesteb s snat n tarrayin yermed'
subtitle: Asesteb s snat tarrayin yettwarmed i umiḍan-ik.
title: Asesteb s snat n tarrayin irmed
two_factor_recovery_codes_changed:
explanation: Tangalt n tuɣalin tettwaḥbes sakin nesnulfa-d yiwet d tamaynut.
subject: 'Mastodon: Tingalin n tuɣalin n snat n tarayin ttwarnanat i tikkelt-nniḍen'
subtitle: Tangalt n tuɣalin tettwaḥbes sakin nesnulfa-d yiwet d tamaynut.
title: Tangalt n tuɣalin 2FA tettwabeddel
unlock_instructions:
subject: 'Mastodon: iwelihhen n userreḥ'
webauthn_credential:
added:
explanation: Tasarut-a n tɣellist tettwarna ɣer umiḍan-ik·im
subject: 'Maṣṭudun : Tasarutt tamaynutt n tɣellist'
title: Tasarut tamaynutt n tɣellist tamaynut tettwarna
deleted:
explanation: Tasarut-a n tɣellist tettwakkes seg umiḍan-ik·im
subject: 'Mastodon: Tasarut n tɣellsit tettwakkes'
title: Yiwet seg tsura-k·m n tɣellist tettwakkes
webauthn_disabled:
explanation: Yensa usesteb s tsura n tɣellist i umiḍan-ik.
extra: Tzemreḍ ad tkecmeḍ tura s useqdec asuf n ujuṭu yettwasran s usnas TOPTP yeqqnen.
subject: 'Mastodon: Asesteb s tsura n tɣellist yensa'
title: Tisura n tɣellist nsant
webauthn_enabled:
explanation: Asesteb n tsarut n tɣellist tettwarmed i umiḍan-ik.
extra: Tasarut-ik n tɣellist tezmer tura ad tettuseqdec i unekcum.
subject: 'Mastodon: Asesteb n tsarut n tɣellist yermed'
title: Tisura n tɣellist remdent
omniauth_callbacks:
failure: Ur nezmir ara ad ak·akem-nsesṭeb seg %{kind} acku "%{reason}".
success: Asesṭeb idda akken iwata seg umiḍan %{kind}.

View File

@ -5,7 +5,6 @@ kab:
doorkeeper/application:
name: Isem n usnas
redirect_uri: URI n uwelleh
scopes: Tinerfadin
website: Asmel web n usnas
errors:
models:
@ -40,7 +39,6 @@ kab:
empty: Ulac ɣur-k·m isnasen.
name: Isem
new: Asnas amaynut
scopes: Tinerfadin
show: Ẓer
title: Isnasen-ik·im
new:
@ -49,8 +47,6 @@ kab:
actions: Tigawin
application_id: ID n usnas
callback_urls: URL n tririt n wawal
scopes: Tinerfadin
secret: Tuffirt n umsaɣ
title: 'Asnas: %{name}'
authorizations:
buttons:
@ -59,7 +55,6 @@ kab:
error:
title: Tella-d tuccḍa
new:
review_permissions: Asenqed n tsirag
title: Tlaq tsiregt
show:
title: Nɣel tangalt n wurag sakkin senteḍ-itt deg usnas.
@ -69,12 +64,8 @@ kab:
confirmations:
revoke: Tetḥeqqeḍ?
index:
authorized_at: Yettwasireg ɣef %{date}
description_html: Ha-t-an yisnasen i izemren ad kecmen ɣer umiḍan-ik·im, s useqdec n API. Ma llan yisnasen ur teεqileḍ ara da, neɣ kra n wesnas ur iteddu ara akken ilaq, tzemreḍ ad tekkseḍ anekcum-is.
last_used_at: Yettwaseqdec i tikkelt taneggarut ass n %{date}
never_used: Urǧin yettwaseqdac
scopes: Tisirag
superapp: Adigan
title: Isnasen-ik·im yettusirgen
errors:
messages:
@ -91,28 +82,13 @@ kab:
destroy:
notice: Yettwaḥwi wesnas.
grouped_scopes:
access:
read: Anekcum i tɣuri kan
read/write: Anekcum i tɣuri d tira
write: Anekcum i tira kan
title:
accounts: Imiḍanen
admin/accounts: Tadbelt n imiḍan
admin/all: Akk timahilin tinebdalin
admin/reports: Tadbelt n yineqqisen
blocks: Yewḥel
bookmarks: Ticraḍ
conversations: Idiwenniyen
crypto: Awgelhen seg yixef ɣer yixef
favourites: Imenyafen
filters: Imzizdigen
follow: Aḍfar, asgugem akked usewḥel
follows: Aḍfar
lists: Tibdarin
media: Imeddayen n umidya
mutes: Yeggugem
notifications: Tilɣa
profile: Amaɣnu-k Mastodon
push: Tilɣa yettudemmren
reports: Ineqqisen
search: Nadi

View File

@ -31,7 +31,7 @@ ko:
form:
error: 이런! 오류를 확인하세요
help:
native_redirect_uri: "%{native_redirect_uri}를 이용해 로컬 테스트를 할 수 있습니다"
native_redirect_uri: "%{native_redirect_uri}에서 로컬 테스트를 할 수 있습니다."
redirect_uri: 한 줄에 하나의 URI를 작성하세요
scopes: 스페이스로 범위를 구분하세요. 빈 칸으로 놔두면 기본 범위를 사용합니다.
index:

View File

@ -25,7 +25,7 @@ lv:
edit: Labot
submit: Apstiprināt
confirmations:
destroy: Vai tiešām?
destroy: Vai esi pārliecināts?
edit:
title: Labot lietotni
form:
@ -69,7 +69,7 @@ lv:
buttons:
revoke: Atsaukt
confirmations:
revoke: Vai tiešām?
revoke: Vai esi pārliecināts?
index:
authorized_at: Autorizētas %{date}
description_html: Šīs ir lietotnes, kas var piekļūt Tavam kontam ar API. Ja šeit ir lietotnes, kuras neatpazīsti, vai lietotne darbojas ne tā, kā paredzēts, vari atsaukt tās piekļuvi.
@ -135,7 +135,6 @@ lv:
media: Multividesu pielikumi
mutes: Apklusinātie
notifications: Paziņojumi
profile: Tavs Mastodon profils
push: Uznirstošie paziņojumi
reports: Ziņojumi
search: Meklēt
@ -166,7 +165,6 @@ lv:
admin:write:reports: veikt moderācijas darbības pārskatos
crypto: lieto pilnīgu šifrēšanu
follow: mainīt konta attiecības
profile: lasīt tikai Tava konta profila informāciju
push: saņemt savus push paziņojumus
read: lasīt visus sava konta datus
read:accounts: apskatīt kontu informāciju

View File

@ -31,18 +31,18 @@ gl:
created_msg: Nota de moderación creada correctamente!
destroyed_msg: Nota de moderación eliminada de xeito correcto!
accounts:
add_email_domain_block: Bloquear o dominio do enderezo
add_email_domain_block: Bloquear o dominio do email
approve: Aprobar
approved_msg: Aprobada a solicitude de rexistro de %{username}
are_you_sure: Está segura?
avatar: Imaxe de perfil
by_domain: Dominio
change_email:
changed_msg: Correo cambiado de xeito correcto!
current_email: Enderezo actual
label: Cambiar de enderezo
new_email: Novo enderezo
submit: Cambiar de enderezo
changed_msg: Email mudado de xeito correcto!
current_email: Email actual
label: Mudar email
new_email: Novo email
submit: Mudar email
title: Mudar email de %{username}
change_role:
changed_msg: Rol mudado correctamente!
@ -64,10 +64,10 @@ gl:
display_name: Nome a amosar
domain: Dominio
edit: Editar
email: Enderezo de correo
email_status: Estado do correo
email: Email
email_status: Estado do email
enable: Activar
enable_sign_in_token_auth: Activar autenticación cun token no correo
enable_sign_in_token_auth: Activar autenticación cun token no email
enabled: Activado
enabled_msg: Desbloqueada a conta de %{username}
followers: Seguidoras
@ -132,7 +132,7 @@ gl:
resubscribe: Resubscribir
role: Rol
search: Procurar
search_same_email_domain: Outras usuarias co mesmo dominio de correo
search_same_email_domain: Outras usuarias co mesmo dominio de email
search_same_ip: Outras usuarias co mesmo IP
security: Seguridade
security_measures:
@ -154,9 +154,9 @@ gl:
suspension_irreversible: Elimináronse de xeito irreversible os datos desta conta. Podes reactivar a conta para facela usable novamente pero non recuperará os datos eliminados.
suspension_reversible_hint_html: Esta conta foi suspendida, e os datos serán totalmente eliminados o %{date}. Ata entón, a conta pode ser restaurada sen danos. Se desexas eliminar agora mesmo todos os datos da conta, podes facelo aquí embaixo.
title: Contas
unblock_email: Desbloquear enderezo de correo
unblocked_email_msg: Enderezo de correo de %{username} desbloqueado
unconfirmed_email: Enderezo de correo sen confirmar
unblock_email: Desbloquear enderezo de email
unblocked_email_msg: Enderezo de email de %{username} desbloqueado
unconfirmed_email: Email non confirmado
undo_sensitized: Desmarcar como sensible
undo_silenced: Desfacer acalar
undo_suspension: Desfacer suspensión
@ -173,12 +173,12 @@ gl:
approve_appeal: Aprobar apelación
approve_user: Aprobar Usuaria
assigned_to_self_report: Asignar denuncia
change_email_user: Editar correo electrónico da usuaria
change_email_user: Editar email da usuaria
change_role_user: Cambiar Rol da Usuaria
confirm_user: Confirmar usuaria
create_account_warning: Crear aviso
create_announcement: Crear anuncio
create_canonical_email_block: Crear Bloqueo de correo electrónico
create_canonical_email_block: Crear Bloqueo de email
create_custom_emoji: Crear emoticonas personalizadas
create_domain_allow: Crear Dominio Permitido
create_domain_block: Crear bloquedo do Dominio
@ -188,7 +188,7 @@ gl:
create_user_role: Crear Rol
demote_user: Degradar usuaria
destroy_announcement: Eliminar anuncio
destroy_canonical_email_block: Eliminar Bloqueo de correo electrónico
destroy_canonical_email_block: Eliminar Bloqueo de email
destroy_custom_emoji: Eliminar emoticona personalizada
destroy_domain_allow: Eliminar Dominio permitido
destroy_domain_block: Eliminar bloqueo do Dominio
@ -200,7 +200,7 @@ gl:
destroy_user_role: Eliminar Rol
disable_2fa_user: Desactivar 2FA
disable_custom_emoji: Desactivar emoticona personalizada
disable_sign_in_token_auth_user: Desactivar Autenticación con token no correo para Usuaria
disable_sign_in_token_auth_user: Desactivar Autenticación por token no email para Usuaria
disable_user: Desactivar usuaria
enable_custom_emoji: Activar emoticona personalizada
enable_sign_in_token_auth_user: Activar Autenticación con token no email para Usuaria
@ -211,14 +211,14 @@ gl:
reject_user: Rexeitar Usuaria
remove_avatar_user: Eliminar avatar
reopen_report: Reabrir denuncia
resend_user: Reenviar o correo de confirmación
resend_user: Reenviar o email de confirmación
reset_password_user: Restabelecer contrasinal
resolve_report: Resolver denuncia
sensitive_account: Marca o multimedia da túa conta como sensible
silence_account: Silenciar conta
suspend_account: Suspender conta
unassigned_report: Desasignar denuncia
unblock_email_account: Desbloquear enderezo de correo
unblock_email_account: Desbloquear enderezo de email
unsensitive_account: Retira a marca de sensible do multimedia da conta
unsilence_account: Deixar de silenciar conta
unsuspend_account: Retirar suspensión de conta
@ -660,7 +660,7 @@ gl:
delete_data_html: Eliminar o perfil e contidos de <strong>@%{acct}</strong> para os próximos 30 días a non ser que sexa suspendida nese período
preview_preamble_html: "<strong>@%{acct}</strong> vai recibir un aviso co seguinte contido:"
record_strike_html: Anotar un aviso contra <strong>@%{acct}</strong> para axudarche a xestionar futuros problemas con esta conta
send_email_html: Enviar un correo de aviso a <strong>@%{acct}</strong>
send_email_html: Enviar un email de aviso a <strong>@%{acct}</strong>
warning_placeholder: Razóns adicionais optativas para a acción de moderación.
target_origin: Orixe da conta denunciada
title: Denuncias
@ -1060,7 +1060,7 @@ gl:
redirect_to_app_html: Ímoste redirixir á app <strong>%{app_name}</strong>. Se iso non acontece, proba %{clicking_this_link} ou volve ti manualmente á app.
registration_complete: Completouse a creación da conta en %{domain}!
welcome_title: Benvida, %{name}!
wrong_email_hint: Se o enderezo de correo non é correcto, podes cambialo nos axustes da conta.
wrong_email_hint: Se o enderezo de email non é correcto, podes cambialo nos axustes da conta.
delete_account: Eliminar conta
delete_account_html: Se queres eliminar a túa conta, podes <a href="%{path}">facelo aquí</a>. Deberás confirmar a acción.
description:

View File

@ -1741,7 +1741,7 @@ ko:
contrast: 마스토돈 (고대비)
default: 마스토돈 (어두움)
mastodon-light: 마스토돈 (밝음)
system: 자동 (시스템 테마 사용)
system: 자동 선택 (시스템 테마 이용)
time:
formats:
default: "%Y-%m-%d %H:%M"

View File

@ -116,8 +116,6 @@ ro:
redownloaded_msg: S-a reîmprospătat cu succes profilul %{username} de la origine
reject: Respinge
rejected_msg: S-a respins cu succes cererea de înregistrare a utilizatorului %{username}
remote_suspension_irreversible: Datele acestui cont au fost șterse în mod ireversibil.
remote_suspension_reversible_hint_html: Contul a fost suspendat pe server-ul respectiv, iar datele vor fi șterse complet pe %{date}. Până atunci, server-ul remote poate restabili acest cont fără consecințe negative. Dacă dorești să elimini toate datele contului numaidecât, poți face acest lucru mai jos.
remove_avatar: Elimină avatar
remove_header: Elimină antet
removed_avatar_msg: S-a îndepărtat cu succes poza de profil a utilizatorului %{username}

View File

@ -1,21 +1 @@
---
ry:
accounts:
follow: Пудписати ся
following: Пудпискы
posts:
few: Публикації
one: Публикація
other: Публикації
posts_tab_heading: Публикації
imports:
titles:
following: Імпортованя пудписок
types:
following: Испис пудписок
notification_mailer:
follow:
body: "%{name} ся пудписує ся на вас!"
subject: "%{name} ся пудписує ся на вас"
relationships:
following: Пудпискы

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