Merge commit '93f3c724aea4efe874054b2f546fff91f0bf731b' into glitch-soc/merge-upstream
Conflicts: - `spec/system/settings/preferences/appearance_spec.rb`: Upstream tests for changing themes in there, but glitch-soc has its own place for that. Updated upstream's change while skipping the theme test.pull/2955/head
commit
fcc5262f60
|
@ -10,6 +10,7 @@ services:
|
|||
RAILS_ENV: development
|
||||
NODE_ENV: development
|
||||
BIND: 0.0.0.0
|
||||
BOOTSNAP_CACHE_DIR: /tmp
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: '6379'
|
||||
DB_HOST: db
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# syntax=docker/dockerfile:1.12
|
||||
|
||||
# This file is designed for production server deployment, not local development work
|
||||
# For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/README.md#docker
|
||||
# For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/docs/DEVELOPMENT.md#docker
|
||||
|
||||
# Please see https://docs.docker.com/engine/reference/builder for information about
|
||||
# the extended buildx capabilities used in this file.
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -100,6 +100,8 @@ gem 'json-ld'
|
|||
gem 'json-ld-preloaded', '~> 3.2'
|
||||
gem 'rdf-normalize', '~> 0.5'
|
||||
|
||||
gem 'prometheus_exporter', '~> 2.2', require: false
|
||||
|
||||
gem 'opentelemetry-api', '~> 1.4.0'
|
||||
|
||||
group :opentelemetry do
|
||||
|
|
|
@ -557,7 +557,7 @@ GEM
|
|||
opentelemetry-api (~> 1.0)
|
||||
orm_adapter (0.5.0)
|
||||
ostruct (0.6.1)
|
||||
ox (2.14.20)
|
||||
ox (2.14.21)
|
||||
bigdecimal (>= 3.0)
|
||||
parallel (1.26.3)
|
||||
parser (3.3.7.0)
|
||||
|
@ -580,6 +580,8 @@ GEM
|
|||
net-smtp
|
||||
premailer (~> 1.7, >= 1.7.9)
|
||||
prettyprint (0.2.0)
|
||||
prometheus_exporter (2.2.0)
|
||||
webrick
|
||||
propshaft (1.1.0)
|
||||
actionpack (>= 7.0.0)
|
||||
activesupport (>= 7.0.0)
|
||||
|
@ -984,6 +986,7 @@ DEPENDENCIES
|
|||
pg (~> 1.5)
|
||||
pghero
|
||||
premailer-rails
|
||||
prometheus_exporter (~> 2.2)
|
||||
propshaft
|
||||
public_suffix (~> 6.0)
|
||||
puma (~> 6.3)
|
||||
|
|
|
@ -34,7 +34,8 @@ module Admin
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:admin_account_action).permit(:type, :report_id, :warning_preset_id, :text, :send_email_notification, :include_statuses)
|
||||
params
|
||||
.expect(admin_account_action: [:type, :report_id, :warning_preset_id, :text, :send_email_notification, :include_statuses])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,10 +29,8 @@ module Admin
|
|||
private
|
||||
|
||||
def resource_params
|
||||
params.require(:account_moderation_note).permit(
|
||||
:content,
|
||||
:target_account_id
|
||||
)
|
||||
params
|
||||
.expect(account_moderation_note: [:content, :target_account_id])
|
||||
end
|
||||
|
||||
def set_account_moderation_note
|
||||
|
|
|
@ -158,7 +158,8 @@ module Admin
|
|||
end
|
||||
|
||||
def form_account_batch_params
|
||||
params.require(:form_account_batch).permit(:action, account_ids: [])
|
||||
params
|
||||
.expect(form_account_batch: [:action, account_ids: []])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
|
|
|
@ -84,6 +84,7 @@ class Admin::AnnouncementsController < Admin::BaseController
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:announcement).permit(:text, :scheduled_at, :starts_at, :ends_at, :all_day)
|
||||
params
|
||||
.expect(announcement: [:text, :scheduled_at, :starts_at, :ends_at, :all_day])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,9 +41,8 @@ module Admin
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:user).permit(
|
||||
:unconfirmed_email
|
||||
)
|
||||
params
|
||||
.expect(user: [:unconfirmed_email])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -47,7 +47,8 @@ module Admin
|
|||
private
|
||||
|
||||
def resource_params
|
||||
params.require(:custom_emoji).permit(:shortcode, :image, :visible_in_picker)
|
||||
params
|
||||
.expect(custom_emoji: [:shortcode, :image, :visible_in_picker])
|
||||
end
|
||||
|
||||
def filtered_custom_emojis
|
||||
|
@ -77,7 +78,8 @@ module Admin
|
|||
end
|
||||
|
||||
def form_custom_emoji_batch_params
|
||||
params.require(:form_custom_emoji_batch).permit(:action, :category_id, :category_name, custom_emoji_ids: [])
|
||||
params
|
||||
.expect(form_custom_emoji_batch: [:action, :category_id, :category_name, custom_emoji_ids: []])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,6 +37,7 @@ class Admin::DomainAllowsController < Admin::BaseController
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:domain_allow).permit(:domain)
|
||||
params
|
||||
.expect(domain_allow: [:domain])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,7 +25,9 @@ module Admin
|
|||
rescue Mastodon::NotPermittedError
|
||||
flash[:alert] = I18n.t('admin.domain_blocks.not_permitted')
|
||||
else
|
||||
redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg')
|
||||
flash[:notice] = I18n.t('admin.domain_blocks.created_msg')
|
||||
ensure
|
||||
redirect_to admin_instances_path(limited: '1')
|
||||
end
|
||||
|
||||
def new
|
||||
|
@ -114,7 +116,12 @@ module Admin
|
|||
end
|
||||
|
||||
def form_domain_block_batch_params
|
||||
params.require(:form_domain_block_batch).permit(domain_blocks_attributes: [:enabled, :domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate])
|
||||
params
|
||||
.expect(
|
||||
form_domain_block_batch: [
|
||||
domain_blocks_attributes: [[:enabled, :domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate]],
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
|
|
|
@ -62,11 +62,13 @@ module Admin
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:email_domain_block).permit(:domain, :allow_with_approval, other_domains: [])
|
||||
params
|
||||
.expect(email_domain_block: [:domain, :allow_with_approval, other_domains: []])
|
||||
end
|
||||
|
||||
def form_email_domain_block_batch_params
|
||||
params.require(:form_email_domain_block_batch).permit(email_domain_block_ids: [])
|
||||
params
|
||||
.expect(form_email_domain_block_batch: [email_domain_block_ids: []])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
|
|
|
@ -37,7 +37,8 @@ module Admin
|
|||
end
|
||||
|
||||
def form_account_batch_params
|
||||
params.require(:form_account_batch).permit(:action, account_ids: [])
|
||||
params
|
||||
.expect(form_account_batch: [:action, account_ids: []])
|
||||
end
|
||||
|
||||
def filter_params
|
||||
|
|
|
@ -39,7 +39,8 @@ module Admin
|
|||
private
|
||||
|
||||
def resource_params
|
||||
params.require(:invite).permit(:max_uses, :expires_in)
|
||||
params
|
||||
.expect(invite: [:max_uses, :expires_in])
|
||||
end
|
||||
|
||||
def filtered_invites
|
||||
|
|
|
@ -44,7 +44,8 @@ module Admin
|
|||
private
|
||||
|
||||
def resource_params
|
||||
params.require(:ip_block).permit(:ip, :severity, :comment, :expires_in)
|
||||
params
|
||||
.expect(ip_block: [:ip, :severity, :comment, :expires_in])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
|
@ -52,7 +53,8 @@ module Admin
|
|||
end
|
||||
|
||||
def form_ip_block_batch_params
|
||||
params.require(:form_ip_block_batch).permit(ip_block_ids: [])
|
||||
params
|
||||
.expect(form_ip_block_batch: [ip_block_ids: []])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -57,7 +57,8 @@ module Admin
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:relay).permit(:inbox_url)
|
||||
params
|
||||
.expect(relay: [:inbox_url])
|
||||
end
|
||||
|
||||
def warn_signatures_not_enabled!
|
||||
|
|
|
@ -47,10 +47,8 @@ module Admin
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:report_note).permit(
|
||||
:content,
|
||||
:report_id
|
||||
)
|
||||
params
|
||||
.expect(report_note: [:content, :report_id])
|
||||
end
|
||||
|
||||
def set_report_note
|
||||
|
|
|
@ -61,7 +61,8 @@ module Admin
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:user_role).permit(:name, :color, :highlighted, :position, permissions_as_keys: [])
|
||||
params
|
||||
.expect(user_role: [:name, :color, :highlighted, :position, permissions_as_keys: []])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -53,7 +53,8 @@ module Admin
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:rule).permit(:text, :hint, :priority)
|
||||
params
|
||||
.expect(rule: [:text, :hint, :priority])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,7 +28,8 @@ module Admin
|
|||
end
|
||||
|
||||
def settings_params
|
||||
params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
|
||||
params
|
||||
.expect(form_admin_settings: [*Form::AdminSettings::KEYS])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -39,7 +39,8 @@ module Admin
|
|||
helper_method :batched_ordered_status_edits
|
||||
|
||||
def admin_status_batch_action_params
|
||||
params.require(:admin_status_batch_action).permit(status_ids: [])
|
||||
params
|
||||
.expect(admin_status_batch_action: [status_ids: []])
|
||||
end
|
||||
|
||||
def after_create_redirect_path
|
||||
|
|
|
@ -37,7 +37,8 @@ module Admin
|
|||
end
|
||||
|
||||
def tag_params
|
||||
params.require(:tag).permit(:name, :display_name, :trendable, :usable, :listable)
|
||||
params
|
||||
.expect(tag: [:name, :display_name, :trendable, :usable, :listable])
|
||||
end
|
||||
|
||||
def filtered_tags
|
||||
|
|
|
@ -31,6 +31,7 @@ class Admin::TermsOfService::DraftsController < Admin::BaseController
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:terms_of_service).permit(:text, :changelog)
|
||||
params
|
||||
.expect(terms_of_service: [:text, :changelog])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,6 +32,7 @@ class Admin::TermsOfService::GeneratesController < Admin::BaseController
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:terms_of_service_generator).permit(*TermsOfService::Generator::VARIABLES)
|
||||
params
|
||||
.expect(terms_of_service_generator: [*TermsOfService::Generator::VARIABLES])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -31,7 +31,8 @@ class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseControll
|
|||
end
|
||||
|
||||
def trends_preview_card_provider_batch_params
|
||||
params.require(:trends_preview_card_provider_batch).permit(:action, preview_card_provider_ids: [])
|
||||
params
|
||||
.expect(trends_preview_card_provider_batch: [:action, preview_card_provider_ids: []])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
|
|
|
@ -31,7 +31,8 @@ class Admin::Trends::LinksController < Admin::BaseController
|
|||
end
|
||||
|
||||
def trends_preview_card_batch_params
|
||||
params.require(:trends_preview_card_batch).permit(:action, preview_card_ids: [])
|
||||
params
|
||||
.expect(trends_preview_card_batch: [:action, preview_card_ids: []])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
|
|
|
@ -31,7 +31,8 @@ class Admin::Trends::StatusesController < Admin::BaseController
|
|||
end
|
||||
|
||||
def trends_status_batch_params
|
||||
params.require(:trends_status_batch).permit(:action, status_ids: [])
|
||||
params
|
||||
.expect(trends_status_batch: [:action, status_ids: []])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
|
|
|
@ -31,7 +31,8 @@ class Admin::Trends::TagsController < Admin::BaseController
|
|||
end
|
||||
|
||||
def trends_tag_batch_params
|
||||
params.require(:trends_tag_batch).permit(:action, tag_ids: [])
|
||||
params
|
||||
.expect(trends_tag_batch: [:action, tag_ids: []])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
|
|
|
@ -28,7 +28,8 @@ module Admin
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:user).permit(:role_id)
|
||||
params
|
||||
.expect(user: [:role_id])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -52,7 +52,8 @@ module Admin
|
|||
end
|
||||
|
||||
def warning_preset_params
|
||||
params.require(:account_warning_preset).permit(:title, :text)
|
||||
params
|
||||
.expect(account_warning_preset: [:title, :text])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -74,7 +74,8 @@ module Admin
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:webhook).permit(:url, :template, events: [])
|
||||
params
|
||||
.expect(webhook: [:url, :template, events: []])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -73,7 +73,7 @@ class Auth::SessionsController < Devise::SessionsController
|
|||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:email, :password, :otp_attempt, credential: {})
|
||||
params.expect(user: [:email, :password, :otp_attempt, credential: {}])
|
||||
end
|
||||
|
||||
def after_sign_in_path_for(resource)
|
||||
|
|
|
@ -24,6 +24,6 @@ module Admin::ExportControllerConcern
|
|||
end
|
||||
|
||||
def import_params
|
||||
params.require(:admin_import).permit(:data)
|
||||
params.expect(admin_import: [:data])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -58,6 +58,6 @@ module ChallengableConcern
|
|||
end
|
||||
|
||||
def challenge_params
|
||||
params.require(:form_challenge).permit(:current_password, :return_to)
|
||||
params.expect(form_challenge: [:current_password, :return_to])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -34,7 +34,7 @@ class Filters::StatusesController < ApplicationController
|
|||
end
|
||||
|
||||
def status_filter_batch_action_params
|
||||
params.require(:form_status_filter_batch_action).permit(status_filter_ids: [])
|
||||
params.expect(form_status_filter_batch_action: [status_filter_ids: []])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
|
|
|
@ -36,7 +36,7 @@ class RelationshipsController < ApplicationController
|
|||
end
|
||||
|
||||
def form_account_batch_params
|
||||
params.require(:form_account_batch).permit(:action, account_ids: [])
|
||||
params.expect(form_account_batch: [:action, account_ids: []])
|
||||
end
|
||||
|
||||
def following_relationship?
|
||||
|
|
|
@ -60,16 +60,12 @@ class Settings::ApplicationsController < Settings::BaseController
|
|||
end
|
||||
|
||||
def application_params
|
||||
params.require(:doorkeeper_application).permit(
|
||||
:name,
|
||||
:redirect_uri,
|
||||
:scopes,
|
||||
:website
|
||||
)
|
||||
params
|
||||
.expect(doorkeeper_application: [:name, :redirect_uri, :scopes, :website])
|
||||
end
|
||||
|
||||
def prepare_scopes
|
||||
scopes = params.fetch(:doorkeeper_application, {}).fetch(:scopes, nil)
|
||||
scopes = application_params.fetch(:doorkeeper_application, {}).fetch(:scopes, nil)
|
||||
params[:doorkeeper_application][:scopes] = scopes.join(' ') if scopes.is_a? Array
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,6 +19,6 @@ class Settings::Preferences::BaseController < Settings::BaseController
|
|||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:locale, :time_zone, chosen_languages: [], settings_attributes: UserSettings.keys)
|
||||
params.expect(user: [:locale, :time_zone, chosen_languages: [], settings_attributes: UserSettings.keys])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -38,7 +38,7 @@ module Settings
|
|||
private
|
||||
|
||||
def confirmation_params
|
||||
params.require(:form_two_factor_confirmation).permit(:otp_attempt)
|
||||
params.expect(form_two_factor_confirmation: [:otp_attempt])
|
||||
end
|
||||
|
||||
def prepare_two_factor_form
|
||||
|
|
|
@ -18,7 +18,7 @@ class Settings::VerificationsController < Settings::BaseController
|
|||
private
|
||||
|
||||
def account_params
|
||||
params.require(:account).permit(:attribution_domains).tap do |params|
|
||||
params.expect(account: [:attribution_domains]).tap do |params|
|
||||
params[:attribution_domains] = params[:attribution_domains].split if params[:attribution_domains]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -145,7 +145,6 @@ class Item extends PureComponent {
|
|||
srcSet={srcSet}
|
||||
sizes={sizes}
|
||||
alt={description}
|
||||
title={description}
|
||||
lang={lang}
|
||||
style={{ objectPosition: `${x}% ${y}%` }}
|
||||
onLoad={this.handleImageLoad}
|
||||
|
@ -167,7 +166,6 @@ class Item extends PureComponent {
|
|||
<video
|
||||
className='media-gallery__item-gifv-thumbnail'
|
||||
aria-label={description}
|
||||
title={description}
|
||||
lang={lang}
|
||||
role='application'
|
||||
src={attachment.get('url')}
|
||||
|
|
|
@ -93,7 +93,6 @@ export const MediaItem: React.FC<{
|
|||
<img
|
||||
src={previewUrl || avatarUrl}
|
||||
alt={description}
|
||||
title={description}
|
||||
lang={lang}
|
||||
onLoad={handleImageLoad}
|
||||
/>
|
||||
|
@ -113,7 +112,6 @@ export const MediaItem: React.FC<{
|
|||
<img
|
||||
src={previewUrl}
|
||||
alt={description}
|
||||
title={description}
|
||||
lang={lang}
|
||||
style={{ objectPosition: `${x}% ${y}%` }}
|
||||
onLoad={handleImageLoad}
|
||||
|
@ -131,7 +129,6 @@ export const MediaItem: React.FC<{
|
|||
<video
|
||||
className='media-gallery__item-gifv-thumbnail'
|
||||
aria-label={description}
|
||||
title={description}
|
||||
lang={lang}
|
||||
src={fullUrl}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
import { useState, useRef, useCallback, useId } from 'react';
|
||||
|
||||
import { FormattedMessage, useIntl, defineMessages } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Overlay from 'react-overlays/Overlay';
|
||||
|
||||
import QuestionMarkIcon from '@/material-icons/400-24px/question_mark.svg?react';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
|
||||
const messages = defineMessages({
|
||||
help: { id: 'info_button.label', defaultMessage: 'Help' },
|
||||
});
|
||||
|
||||
export const InfoButton: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const [open, setOpen] = useState(false);
|
||||
const triggerRef = useRef<HTMLButtonElement>(null);
|
||||
const accessibilityId = useId();
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
setOpen(!open);
|
||||
}, [open, setOpen]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type='button'
|
||||
className={classNames('help-button', { active: open })}
|
||||
ref={triggerRef}
|
||||
onClick={handleClick}
|
||||
aria-expanded={open}
|
||||
aria-controls={accessibilityId}
|
||||
aria-label={intl.formatMessage(messages.help)}
|
||||
>
|
||||
<Icon id='' icon={QuestionMarkIcon} />
|
||||
</button>
|
||||
|
||||
<Overlay
|
||||
show={open}
|
||||
rootClose
|
||||
placement='top'
|
||||
onHide={handleClick}
|
||||
offset={[5, 5]}
|
||||
target={triggerRef}
|
||||
>
|
||||
{({ props }) => (
|
||||
<div
|
||||
{...props}
|
||||
className='dialog-modal__popout prose dropdown-animation'
|
||||
id={accessibilityId}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='info_button.what_is_alt_text'
|
||||
defaultMessage='<h1>What is alt text?</h1>
|
||||
|
||||
<p>Alt text provides image descriptions for people with vision impairments, low-bandwidth connections, or those seeking extra context.</p>
|
||||
|
||||
<p>You can improve accessibility and understanding for everyone by writing clear, concise, and objective alt text.</p>
|
||||
|
||||
<ul>
|
||||
<li>Capture important elements</li>
|
||||
<li>Summarize text in images</li>
|
||||
<li>Use regular sentence structure</li>
|
||||
<li>Avoid redundant information</li>
|
||||
<li>Focus on trends and key findings in complex visuals (like diagrams or maps)</li>
|
||||
</ul>'
|
||||
values={{
|
||||
h1: (node) => <h1>{node}</h1>,
|
||||
p: (node) => <p>{node}</p>,
|
||||
ul: (node) => <ul>{node}</ul>,
|
||||
li: (node) => <li>{node}</li>,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Overlay>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -36,6 +36,8 @@ import type { MediaAttachment } from 'mastodon/models/media_attachment';
|
|||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||
import { assetHost } from 'mastodon/utils/config';
|
||||
|
||||
import { InfoButton } from './components/info_button';
|
||||
|
||||
const messages = defineMessages({
|
||||
placeholderVisual: {
|
||||
id: 'alt_text_modal.describe_for_people_with_visual_impairments',
|
||||
|
@ -504,6 +506,13 @@ export const AltTextModal = forwardRef<ModalRef, Props & Partial<RestoreProps>>(
|
|||
</div>
|
||||
|
||||
<div className='input__toolbar'>
|
||||
<CharacterCounter
|
||||
max={MAX_LENGTH}
|
||||
text={isDetecting ? '' : description}
|
||||
/>
|
||||
|
||||
<div className='spacer' />
|
||||
|
||||
<button
|
||||
className='link-button'
|
||||
onClick={handleDetectClick}
|
||||
|
@ -515,10 +524,7 @@ export const AltTextModal = forwardRef<ModalRef, Props & Partial<RestoreProps>>(
|
|||
/>
|
||||
</button>
|
||||
|
||||
<CharacterCounter
|
||||
max={MAX_LENGTH}
|
||||
text={isDetecting ? '' : description}
|
||||
/>
|
||||
<InfoButton />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -14,7 +14,6 @@ import AutosuggestInput from '../../../components/autosuggest_input';
|
|||
import AutosuggestTextarea from '../../../components/autosuggest_textarea';
|
||||
import { Button } from '../../../components/button';
|
||||
import EmojiPickerDropdown from '../containers/emoji_picker_dropdown_container';
|
||||
import LanguageDropdown from '../containers/language_dropdown_container';
|
||||
import PollButtonContainer from '../containers/poll_button_container';
|
||||
import PrivacyDropdownContainer from '../containers/privacy_dropdown_container';
|
||||
import SpoilerButtonContainer from '../containers/spoiler_button_container';
|
||||
|
@ -24,6 +23,7 @@ import { countableText } from '../util/counter';
|
|||
|
||||
import { CharacterCounter } from './character_counter';
|
||||
import { EditIndicator } from './edit_indicator';
|
||||
import { LanguageDropdown } from './language_dropdown';
|
||||
import { NavigationBar } from './navigation_bar';
|
||||
import { PollForm } from "./poll_form";
|
||||
import { ReplyIndicator } from './reply_indicator';
|
||||
|
|
|
@ -1,330 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import { PureComponent } from 'react';
|
||||
|
||||
import { injectIntl, defineMessages } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||
import fuzzysort from 'fuzzysort';
|
||||
import Overlay from 'react-overlays/Overlay';
|
||||
|
||||
import CancelIcon from '@/material-icons/400-24px/cancel-fill.svg?react';
|
||||
import SearchIcon from '@/material-icons/400-24px/search.svg?react';
|
||||
import TranslateIcon from '@/material-icons/400-24px/translate.svg?react';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { languages as preloadedLanguages } from 'mastodon/initial_state';
|
||||
|
||||
const messages = defineMessages({
|
||||
changeLanguage: { id: 'compose.language.change', defaultMessage: 'Change language' },
|
||||
search: { id: 'compose.language.search', defaultMessage: 'Search languages...' },
|
||||
clear: { id: 'emoji_button.clear', defaultMessage: 'Clear' },
|
||||
});
|
||||
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
|
||||
|
||||
class LanguageDropdownMenu extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
guess: PropTypes.string,
|
||||
frequentlyUsedLanguages: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
languages: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)),
|
||||
intl: PropTypes.object,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
languages: preloadedLanguages,
|
||||
};
|
||||
|
||||
state = {
|
||||
searchValue: '',
|
||||
};
|
||||
|
||||
handleDocumentClick = e => {
|
||||
if (this.node && !this.node.contains(e.target)) {
|
||||
this.props.onClose();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
document.addEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
|
||||
// Because of https://github.com/react-bootstrap/react-bootstrap/issues/2614 we need
|
||||
// to wait for a frame before focusing
|
||||
requestAnimationFrame(() => {
|
||||
if (this.node) {
|
||||
const element = this.node.querySelector('input[type="search"]');
|
||||
if (element) element.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
document.removeEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
}
|
||||
|
||||
setRef = c => {
|
||||
this.node = c;
|
||||
};
|
||||
|
||||
setListRef = c => {
|
||||
this.listNode = c;
|
||||
};
|
||||
|
||||
handleSearchChange = ({ target }) => {
|
||||
this.setState({ searchValue: target.value });
|
||||
};
|
||||
|
||||
search () {
|
||||
const { languages, value, frequentlyUsedLanguages, guess } = this.props;
|
||||
const { searchValue } = this.state;
|
||||
|
||||
if (searchValue === '') {
|
||||
return [...languages].sort((a, b) => {
|
||||
|
||||
if (guess && a[0] === guess) { // Push guessed language higher than current selection
|
||||
return -1;
|
||||
} else if (guess && b[0] === guess) {
|
||||
return 1;
|
||||
} else if (a[0] === value) { // Push current selection to the top of the list
|
||||
return -1;
|
||||
} else if (b[0] === value) {
|
||||
return 1;
|
||||
} else {
|
||||
// Sort according to frequently used languages
|
||||
|
||||
const indexOfA = frequentlyUsedLanguages.indexOf(a[0]);
|
||||
const indexOfB = frequentlyUsedLanguages.indexOf(b[0]);
|
||||
|
||||
return ((indexOfA > -1 ? indexOfA : Infinity) - (indexOfB > -1 ? indexOfB : Infinity));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return fuzzysort.go(searchValue, languages, {
|
||||
keys: ['0', '1', '2'],
|
||||
limit: 5,
|
||||
threshold: -10000,
|
||||
}).map(result => result.obj);
|
||||
}
|
||||
|
||||
handleClick = e => {
|
||||
const value = e.currentTarget.getAttribute('data-index');
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
this.props.onClose();
|
||||
this.props.onChange(value);
|
||||
};
|
||||
|
||||
handleKeyDown = e => {
|
||||
const { onClose } = this.props;
|
||||
const index = Array.from(this.listNode.childNodes).findIndex(node => node === e.currentTarget);
|
||||
|
||||
let element = null;
|
||||
|
||||
switch(e.key) {
|
||||
case 'Escape':
|
||||
onClose();
|
||||
break;
|
||||
case ' ':
|
||||
case 'Enter':
|
||||
this.handleClick(e);
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
element = this.listNode.childNodes[index + 1] || this.listNode.firstChild;
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
element = this.listNode.childNodes[index - 1] || this.listNode.lastChild;
|
||||
break;
|
||||
case 'Tab':
|
||||
if (e.shiftKey) {
|
||||
element = this.listNode.childNodes[index - 1] || this.listNode.lastChild;
|
||||
} else {
|
||||
element = this.listNode.childNodes[index + 1] || this.listNode.firstChild;
|
||||
}
|
||||
break;
|
||||
case 'Home':
|
||||
element = this.listNode.firstChild;
|
||||
break;
|
||||
case 'End':
|
||||
element = this.listNode.lastChild;
|
||||
break;
|
||||
}
|
||||
|
||||
if (element) {
|
||||
element.focus();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
handleSearchKeyDown = e => {
|
||||
const { onChange, onClose } = this.props;
|
||||
const { searchValue } = this.state;
|
||||
|
||||
let element = null;
|
||||
|
||||
switch(e.key) {
|
||||
case 'Tab':
|
||||
case 'ArrowDown':
|
||||
element = this.listNode.firstChild;
|
||||
|
||||
if (element) {
|
||||
element.focus();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
break;
|
||||
case 'Enter':
|
||||
element = this.listNode.firstChild;
|
||||
|
||||
if (element) {
|
||||
onChange(element.getAttribute('data-index'));
|
||||
onClose();
|
||||
}
|
||||
break;
|
||||
case 'Escape':
|
||||
if (searchValue !== '') {
|
||||
e.preventDefault();
|
||||
this.handleClear();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
handleClear = () => {
|
||||
this.setState({ searchValue: '' });
|
||||
};
|
||||
|
||||
renderItem = lang => {
|
||||
const { value } = this.props;
|
||||
|
||||
return (
|
||||
<div key={lang[0]} role='option' tabIndex={0} data-index={lang[0]} className={classNames('language-dropdown__dropdown__results__item', { active: lang[0] === value })} aria-selected={lang[0] === value} onClick={this.handleClick} onKeyDown={this.handleKeyDown}>
|
||||
<span className='language-dropdown__dropdown__results__item__native-name' lang={lang[0]}>{lang[2]}</span> <span className='language-dropdown__dropdown__results__item__common-name'>({lang[1]})</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
render () {
|
||||
const { intl } = this.props;
|
||||
const { searchValue } = this.state;
|
||||
const isSearching = searchValue !== '';
|
||||
const results = this.search();
|
||||
|
||||
return (
|
||||
<div ref={this.setRef}>
|
||||
<div className='emoji-mart-search'>
|
||||
<input type='search' value={searchValue} onChange={this.handleSearchChange} onKeyDown={this.handleSearchKeyDown} placeholder={intl.formatMessage(messages.search)} />
|
||||
<button type='button' className='emoji-mart-search-icon' disabled={!isSearching} aria-label={intl.formatMessage(messages.clear)} onClick={this.handleClear}><Icon icon={!isSearching ? SearchIcon : CancelIcon} /></button>
|
||||
</div>
|
||||
|
||||
<div className='language-dropdown__dropdown__results emoji-mart-scroll' role='listbox' ref={this.setListRef}>
|
||||
{results.map(this.renderItem)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class LanguageDropdown extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
frequentlyUsedLanguages: PropTypes.arrayOf(PropTypes.string),
|
||||
guess: PropTypes.string,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onChange: PropTypes.func,
|
||||
};
|
||||
|
||||
state = {
|
||||
open: false,
|
||||
placement: 'bottom',
|
||||
};
|
||||
|
||||
handleToggle = () => {
|
||||
if (this.state.open && this.activeElement) {
|
||||
this.activeElement.focus({ preventScroll: true });
|
||||
}
|
||||
|
||||
this.setState({ open: !this.state.open });
|
||||
};
|
||||
|
||||
handleClose = () => {
|
||||
if (this.state.open && this.activeElement) {
|
||||
this.activeElement.focus({ preventScroll: true });
|
||||
}
|
||||
|
||||
this.setState({ open: false });
|
||||
};
|
||||
|
||||
handleChange = value => {
|
||||
const { onChange } = this.props;
|
||||
onChange(value);
|
||||
};
|
||||
|
||||
setTargetRef = c => {
|
||||
this.target = c;
|
||||
};
|
||||
|
||||
findTarget = () => {
|
||||
return this.target;
|
||||
};
|
||||
|
||||
handleOverlayEnter = (state) => {
|
||||
this.setState({ placement: state.placement });
|
||||
};
|
||||
|
||||
render () {
|
||||
const { value, guess, intl, frequentlyUsedLanguages } = this.props;
|
||||
const { open, placement } = this.state;
|
||||
const current = preloadedLanguages.find(lang => lang[0] === value) ?? [];
|
||||
|
||||
return (
|
||||
<div ref={this.setTargetRef} onKeyDown={this.handleKeyDown}>
|
||||
<button
|
||||
type='button'
|
||||
title={intl.formatMessage(messages.changeLanguage)}
|
||||
aria-expanded={open}
|
||||
onClick={this.handleToggle}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onKeyDown={this.handleButtonKeyDown}
|
||||
className={classNames('dropdown-button', { active: open, warning: guess !== '' && guess !== value })}
|
||||
>
|
||||
<Icon icon={TranslateIcon} />
|
||||
<span className='dropdown-button__label'>{current[2] ?? value}</span>
|
||||
</button>
|
||||
|
||||
<Overlay show={open} offset={[5, 5]} placement={placement} flip target={this.findTarget} popperConfig={{ strategy: 'fixed', onFirstUpdate: this.handleOverlayEnter }}>
|
||||
{({ props, placement }) => (
|
||||
<div {...props}>
|
||||
<div className={`dropdown-animation language-dropdown__dropdown ${placement}`} >
|
||||
<LanguageDropdownMenu
|
||||
value={value}
|
||||
guess={guess}
|
||||
frequentlyUsedLanguages={frequentlyUsedLanguages}
|
||||
onClose={this.handleClose}
|
||||
onChange={this.handleChange}
|
||||
intl={intl}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Overlay>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default injectIntl(LanguageDropdown);
|
|
@ -0,0 +1,427 @@
|
|||
import { useCallback, useRef, useState, useEffect, useMemo } from 'react';
|
||||
|
||||
import { useIntl, defineMessages } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
|
||||
import fuzzysort from 'fuzzysort';
|
||||
import Overlay from 'react-overlays/Overlay';
|
||||
import type { State, Placement } from 'react-overlays/usePopper';
|
||||
|
||||
import CancelIcon from '@/material-icons/400-24px/cancel-fill.svg?react';
|
||||
import SearchIcon from '@/material-icons/400-24px/search.svg?react';
|
||||
import TranslateIcon from '@/material-icons/400-24px/translate.svg?react';
|
||||
import { changeComposeLanguage } from 'mastodon/actions/compose';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { languages as preloadedLanguages } from 'mastodon/initial_state';
|
||||
import type { RootState } from 'mastodon/store';
|
||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||
|
||||
import { debouncedGuess } from '../util/language_detection';
|
||||
|
||||
const messages = defineMessages({
|
||||
changeLanguage: {
|
||||
id: 'compose.language.change',
|
||||
defaultMessage: 'Change language',
|
||||
},
|
||||
search: {
|
||||
id: 'compose.language.search',
|
||||
defaultMessage: 'Search languages...',
|
||||
},
|
||||
clear: { id: 'emoji_button.clear', defaultMessage: 'Clear' },
|
||||
});
|
||||
|
||||
type Language = [string, string, string];
|
||||
|
||||
const getFrequentlyUsedLanguages = createSelector(
|
||||
[
|
||||
(state: RootState) =>
|
||||
(state.settings as ImmutableMap<string, unknown>).get(
|
||||
'frequentlyUsedLanguages',
|
||||
ImmutableMap(),
|
||||
) as ImmutableMap<string, number>,
|
||||
],
|
||||
(languageCounters) =>
|
||||
languageCounters
|
||||
.keySeq()
|
||||
.sort(
|
||||
(a, b) =>
|
||||
(languageCounters.get(a) ?? 0) - (languageCounters.get(b) ?? 0),
|
||||
)
|
||||
.reverse()
|
||||
.toArray(),
|
||||
);
|
||||
|
||||
const LanguageDropdownMenu: React.FC<{
|
||||
value: string;
|
||||
guess?: string;
|
||||
onClose: () => void;
|
||||
onChange: (arg0: string) => void;
|
||||
}> = ({ value, guess, onClose, onChange }) => {
|
||||
const languages = preloadedLanguages as Language[];
|
||||
const intl = useIntl();
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const nodeRef = useRef<HTMLDivElement>(null);
|
||||
const listNodeRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const frequentlyUsedLanguages = useAppSelector(getFrequentlyUsedLanguages);
|
||||
|
||||
const handleSearchChange = useCallback(
|
||||
({ target }: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchValue(target.value);
|
||||
},
|
||||
[setSearchValue],
|
||||
);
|
||||
|
||||
const handleClick = useCallback(
|
||||
(e: React.MouseEvent | React.KeyboardEvent) => {
|
||||
const value = e.currentTarget.getAttribute('data-index');
|
||||
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
onClose();
|
||||
onChange(value);
|
||||
},
|
||||
[onClose, onChange],
|
||||
);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: React.KeyboardEvent) => {
|
||||
if (!listNodeRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = Array.from(listNodeRef.current.childNodes).findIndex(
|
||||
(node) => node === e.currentTarget,
|
||||
);
|
||||
|
||||
let element = null;
|
||||
|
||||
switch (e.key) {
|
||||
case 'Escape':
|
||||
onClose();
|
||||
break;
|
||||
case ' ':
|
||||
case 'Enter':
|
||||
handleClick(e);
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
element =
|
||||
listNodeRef.current.childNodes[index + 1] ??
|
||||
listNodeRef.current.firstChild;
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
element =
|
||||
listNodeRef.current.childNodes[index - 1] ??
|
||||
listNodeRef.current.lastChild;
|
||||
break;
|
||||
case 'Tab':
|
||||
if (e.shiftKey) {
|
||||
element =
|
||||
listNodeRef.current.childNodes[index - 1] ??
|
||||
listNodeRef.current.lastChild;
|
||||
} else {
|
||||
element =
|
||||
listNodeRef.current.childNodes[index + 1] ??
|
||||
listNodeRef.current.firstChild;
|
||||
}
|
||||
break;
|
||||
case 'Home':
|
||||
element = listNodeRef.current.firstChild;
|
||||
break;
|
||||
case 'End':
|
||||
element = listNodeRef.current.lastChild;
|
||||
break;
|
||||
}
|
||||
|
||||
if (element && element instanceof HTMLElement) {
|
||||
element.focus();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
},
|
||||
[onClose, handleClick],
|
||||
);
|
||||
|
||||
const handleSearchKeyDown = useCallback(
|
||||
(e: React.KeyboardEvent) => {
|
||||
let element = null;
|
||||
|
||||
if (!listNodeRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.key) {
|
||||
case 'Tab':
|
||||
case 'ArrowDown':
|
||||
element = listNodeRef.current.firstChild;
|
||||
|
||||
if (element && element instanceof HTMLElement) {
|
||||
element.focus();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
break;
|
||||
case 'Enter':
|
||||
element = listNodeRef.current.firstChild;
|
||||
|
||||
if (element && element instanceof HTMLElement) {
|
||||
const value = element.getAttribute('data-index');
|
||||
|
||||
if (value) {
|
||||
onChange(value);
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Escape':
|
||||
if (searchValue !== '') {
|
||||
e.preventDefault();
|
||||
setSearchValue('');
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
[setSearchValue, onChange, onClose, searchValue],
|
||||
);
|
||||
|
||||
const handleClear = useCallback(() => {
|
||||
setSearchValue('');
|
||||
}, [setSearchValue]);
|
||||
|
||||
const isSearching = searchValue !== '';
|
||||
|
||||
useEffect(() => {
|
||||
const handleDocumentClick = (e: MouseEvent) => {
|
||||
if (
|
||||
nodeRef.current &&
|
||||
e.target instanceof HTMLElement &&
|
||||
!nodeRef.current.contains(e.target)
|
||||
) {
|
||||
onClose();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', handleDocumentClick, { capture: true });
|
||||
|
||||
// Because of https://github.com/react-bootstrap/react-bootstrap/issues/2614 we need
|
||||
// to wait for a frame before focusing
|
||||
requestAnimationFrame(() => {
|
||||
if (nodeRef.current) {
|
||||
const element = nodeRef.current.querySelector<HTMLInputElement>(
|
||||
'input[type="search"]',
|
||||
);
|
||||
if (element) element.focus();
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('click', handleDocumentClick);
|
||||
};
|
||||
}, [onClose]);
|
||||
|
||||
const results = useMemo(() => {
|
||||
if (searchValue === '') {
|
||||
return [...languages].sort((a, b) => {
|
||||
if (guess && a[0] === guess) {
|
||||
// Push guessed language higher than current selection
|
||||
return -1;
|
||||
} else if (guess && b[0] === guess) {
|
||||
return 1;
|
||||
} else if (a[0] === value) {
|
||||
// Push current selection to the top of the list
|
||||
return -1;
|
||||
} else if (b[0] === value) {
|
||||
return 1;
|
||||
} else {
|
||||
// Sort according to frequently used languages
|
||||
|
||||
const indexOfA = frequentlyUsedLanguages.indexOf(a[0]);
|
||||
const indexOfB = frequentlyUsedLanguages.indexOf(b[0]);
|
||||
|
||||
return (
|
||||
(indexOfA > -1 ? indexOfA : Infinity) -
|
||||
(indexOfB > -1 ? indexOfB : Infinity)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return fuzzysort
|
||||
.go(searchValue, languages, {
|
||||
keys: ['0', '1', '2'],
|
||||
limit: 5,
|
||||
threshold: -10000,
|
||||
})
|
||||
.map((result) => result.obj);
|
||||
}, [searchValue, languages, guess, frequentlyUsedLanguages, value]);
|
||||
|
||||
return (
|
||||
<div ref={nodeRef}>
|
||||
<div className='emoji-mart-search'>
|
||||
<input
|
||||
type='search'
|
||||
value={searchValue}
|
||||
onChange={handleSearchChange}
|
||||
onKeyDown={handleSearchKeyDown}
|
||||
placeholder={intl.formatMessage(messages.search)}
|
||||
/>
|
||||
<button
|
||||
type='button'
|
||||
className='emoji-mart-search-icon'
|
||||
disabled={!isSearching}
|
||||
aria-label={intl.formatMessage(messages.clear)}
|
||||
onClick={handleClear}
|
||||
>
|
||||
<Icon id='' icon={!isSearching ? SearchIcon : CancelIcon} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className='language-dropdown__dropdown__results emoji-mart-scroll'
|
||||
role='listbox'
|
||||
ref={listNodeRef}
|
||||
>
|
||||
{results.map((lang) => (
|
||||
<div
|
||||
key={lang[0]}
|
||||
role='option'
|
||||
tabIndex={0}
|
||||
data-index={lang[0]}
|
||||
className={classNames(
|
||||
'language-dropdown__dropdown__results__item',
|
||||
{ active: lang[0] === value },
|
||||
)}
|
||||
aria-selected={lang[0] === value}
|
||||
onClick={handleClick}
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<span
|
||||
className='language-dropdown__dropdown__results__item__native-name'
|
||||
lang={lang[0]}
|
||||
>
|
||||
{lang[2]}
|
||||
</span>{' '}
|
||||
<span className='language-dropdown__dropdown__results__item__common-name'>
|
||||
({lang[1]})
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const LanguageDropdown: React.FC = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [placement, setPlacement] = useState<Placement | undefined>('bottom');
|
||||
const [guess, setGuess] = useState('');
|
||||
const activeElementRef = useRef<HTMLElement | null>(null);
|
||||
const targetRef = useRef(null);
|
||||
|
||||
const intl = useIntl();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const value = useAppSelector(
|
||||
(state) => state.compose.get('language') as string,
|
||||
);
|
||||
const text = useAppSelector((state) => state.compose.get('text') as string);
|
||||
|
||||
const current =
|
||||
(preloadedLanguages as Language[]).find((lang) => lang[0] === value) ?? [];
|
||||
|
||||
const handleMouseDown = useCallback(() => {
|
||||
if (!open && document.activeElement instanceof HTMLElement) {
|
||||
activeElementRef.current = document.activeElement;
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const handleToggle = useCallback(() => {
|
||||
if (open && activeElementRef.current)
|
||||
activeElementRef.current.focus({ preventScroll: true });
|
||||
|
||||
setOpen(!open);
|
||||
}, [open, setOpen]);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
if (open && activeElementRef.current)
|
||||
activeElementRef.current.focus({ preventScroll: true });
|
||||
|
||||
setOpen(false);
|
||||
}, [open, setOpen]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(value: string) => {
|
||||
dispatch(changeComposeLanguage(value));
|
||||
},
|
||||
[dispatch],
|
||||
);
|
||||
|
||||
const handleOverlayEnter = useCallback(
|
||||
(state: Partial<State>) => {
|
||||
setPlacement(state.placement);
|
||||
},
|
||||
[setPlacement],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (text.length > 20) {
|
||||
debouncedGuess(text, setGuess);
|
||||
} else {
|
||||
setGuess('');
|
||||
}
|
||||
}, [text, setGuess]);
|
||||
|
||||
return (
|
||||
<div ref={targetRef}>
|
||||
<button
|
||||
type='button'
|
||||
title={intl.formatMessage(messages.changeLanguage)}
|
||||
aria-expanded={open}
|
||||
onClick={handleToggle}
|
||||
onMouseDown={handleMouseDown}
|
||||
className={classNames('dropdown-button', {
|
||||
active: open,
|
||||
warning: guess !== '' && guess !== value,
|
||||
})}
|
||||
>
|
||||
<Icon id='' icon={TranslateIcon} />
|
||||
<span className='dropdown-button__label'>{current[2] ?? value}</span>
|
||||
</button>
|
||||
|
||||
<Overlay
|
||||
show={open}
|
||||
offset={[5, 5]}
|
||||
placement={placement}
|
||||
flip
|
||||
target={targetRef}
|
||||
popperConfig={{ strategy: 'fixed', onFirstUpdate: handleOverlayEnter }}
|
||||
>
|
||||
{({ props, placement }) => (
|
||||
<div {...props}>
|
||||
<div
|
||||
className={`dropdown-animation language-dropdown__dropdown ${placement}`}
|
||||
>
|
||||
<LanguageDropdownMenu
|
||||
value={value}
|
||||
guess={guess}
|
||||
onClose={handleClose}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Overlay>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,23 +1,7 @@
|
|||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import lande from 'lande';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
import { changeComposeLanguage } from 'mastodon/actions/compose';
|
||||
|
||||
import LanguageDropdown from '../components/language_dropdown';
|
||||
import { urlRegex } from '../util/url_regex';
|
||||
|
||||
const getFrequentlyUsedLanguages = createSelector([
|
||||
state => state.getIn(['settings', 'frequentlyUsedLanguages'], ImmutableMap()),
|
||||
], languageCounters => (
|
||||
languageCounters.keySeq()
|
||||
.sort((a, b) => languageCounters.get(a) - languageCounters.get(b))
|
||||
.reverse()
|
||||
.toArray()
|
||||
));
|
||||
import { urlRegex } from './url_regex';
|
||||
|
||||
const ISO_639_MAP = {
|
||||
afr: 'af', // Afrikaans
|
||||
|
@ -72,47 +56,21 @@ const ISO_639_MAP = {
|
|||
vie: 'vi', // Vietnamese
|
||||
};
|
||||
|
||||
const debouncedLande = debounce((text) => {
|
||||
const guessLanguage = (text) => {
|
||||
text = text
|
||||
.replace(urlRegex, '')
|
||||
.replace(/(^|[^/\w])@(([a-z0-9_]+)@[a-z0-9.-]+[a-z0-9]+)/ig, '');
|
||||
|
||||
if (text.length <= 20)
|
||||
return undefined;
|
||||
|
||||
return lande(text);
|
||||
}, 500, { trailing: true });
|
||||
|
||||
const detectedLanguage = createSelector([
|
||||
state => state.getIn(['compose', 'text']),
|
||||
], text => {
|
||||
if (text.length > 20) {
|
||||
const guesses = debouncedLande(text);
|
||||
if (!guesses)
|
||||
return '';
|
||||
|
||||
const [lang, confidence] = guesses[0];
|
||||
|
||||
if (confidence > 0.8) {
|
||||
const [lang, confidence] = lande(text)[0];
|
||||
|
||||
if (confidence > 0.8)
|
||||
return ISO_639_MAP[lang];
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
frequentlyUsedLanguages: getFrequentlyUsedLanguages(state),
|
||||
value: state.getIn(['compose', 'language']),
|
||||
guess: detectedLanguage(state),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
|
||||
onChange (value) {
|
||||
dispatch(changeComposeLanguage(value));
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(LanguageDropdown);
|
||||
export const debouncedGuess = debounce((text, setGuess) => {
|
||||
setGuess(guessLanguage(text));
|
||||
}, 500, { leading: true, trailing: true });
|
|
@ -55,11 +55,11 @@ export const Card = ({ id, source }) => {
|
|||
</div>
|
||||
|
||||
<div className='explore__suggestions__card__body'>
|
||||
<Link to={`/@${account.get('acct')}`}><Avatar account={account} size={48} /></Link>
|
||||
<Link to={`/@${account.get('acct')}`} data-hover-card-account={account.id}><Avatar account={account} size={48} /></Link>
|
||||
|
||||
<div className='explore__suggestions__card__body__main'>
|
||||
<div className='explore__suggestions__card__body__main__name-button'>
|
||||
<Link className='explore__suggestions__card__body__main__name-button__name' to={`/@${account.get('acct')}`}><DisplayName account={account} /></Link>
|
||||
<Link className='explore__suggestions__card__body__main__name-button__name' to={`/@${account.get('acct')}`} data-hover-card-account={account.id}><DisplayName account={account} /></Link>
|
||||
<IconButton iconComponent={CloseIcon} onClick={handleDismiss} title={intl.formatMessage(messages.dismiss)} />
|
||||
<FollowButton accountId={account.get('id')} />
|
||||
</div>
|
||||
|
|
|
@ -145,13 +145,13 @@ const Card: React.FC<{
|
|||
/>
|
||||
|
||||
<div className='inline-follow-suggestions__body__scrollable__card__avatar'>
|
||||
<Link to={`/@${account?.acct}`}>
|
||||
<Link to={`/@${account?.acct}`} data-hover-card-account={account?.id}>
|
||||
<Avatar account={account} size={72} />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className='inline-follow-suggestions__body__scrollable__card__text-stack'>
|
||||
<Link to={`/@${account?.acct}`}>
|
||||
<Link to={`/@${account?.acct}`} data-hover-card-account={account?.id}>
|
||||
<DisplayName account={account} />
|
||||
</Link>
|
||||
{firstVerifiedField ? (
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
"alert.unexpected.message": "لقد طرأ خطأ غير متوقّع.",
|
||||
"alert.unexpected.title": "المعذرة!",
|
||||
"alt_text_badge.title": "نص بديل",
|
||||
"alt_text_modal.cancel": "إلغاء",
|
||||
"announcement.announcement": "إعلان",
|
||||
"annual_report.summary.archetype.booster": "The cool-hunter",
|
||||
"attachments_list.unprocessed": "(غير معالَج)",
|
||||
|
@ -120,13 +121,16 @@
|
|||
"column.blocks": "المُستَخدِمون المَحظورون",
|
||||
"column.bookmarks": "الفواصل المرجعية",
|
||||
"column.community": "الخيط الزمني المحلي",
|
||||
"column.create_list": "إنشاء القائمة",
|
||||
"column.direct": "الإشارات الخاصة",
|
||||
"column.directory": "تَصَفُّحُ المَلفات الشخصية",
|
||||
"column.domain_blocks": "النطاقات المحظورة",
|
||||
"column.edit_list": "تعديل القائمة",
|
||||
"column.favourites": "المفضلة",
|
||||
"column.firehose": "الموجزات الحية",
|
||||
"column.follow_requests": "طلبات المتابعة",
|
||||
"column.home": "الرئيسية",
|
||||
"column.list_members": "إدارة أعضاء القائمة",
|
||||
"column.lists": "القوائم",
|
||||
"column.mutes": "المُستَخدِمون المَكتومون",
|
||||
"column.notifications": "الإشعارات",
|
||||
|
@ -139,6 +143,7 @@
|
|||
"column_header.pin": "تثبيت",
|
||||
"column_header.show_settings": "إظهار الإعدادات",
|
||||
"column_header.unpin": "إلغاء التَّثبيت",
|
||||
"column_search.cancel": "إلغاء",
|
||||
"column_subheading.settings": "الإعدادات",
|
||||
"community.column_settings.local_only": "المحلي فقط",
|
||||
"community.column_settings.media_only": "الوسائط فقط",
|
||||
|
@ -157,6 +162,7 @@
|
|||
"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": "الطراز",
|
||||
|
@ -195,6 +201,7 @@
|
|||
"confirmations.unfollow.title": "إلغاء متابعة المستخدم؟",
|
||||
"content_warning.hide": "إخفاء المنشور",
|
||||
"content_warning.show": "إظهار على أي حال",
|
||||
"content_warning.show_more": "إظهار المزيد",
|
||||
"conversation.delete": "احذف المحادثة",
|
||||
"conversation.mark_as_read": "اعتبرها كمقروءة",
|
||||
"conversation.open": "اعرض المحادثة",
|
||||
|
@ -325,6 +332,7 @@
|
|||
"footer.privacy_policy": "سياسة الخصوصية",
|
||||
"footer.source_code": "الاطلاع على الشفرة المصدرية",
|
||||
"footer.status": "الحالة",
|
||||
"footer.terms_of_service": "شروط الخدمة",
|
||||
"generic.saved": "تم الحفظ",
|
||||
"getting_started.heading": "استعدّ للبدء",
|
||||
"hashtag.column_header.tag_mode.all": "و {additional}",
|
||||
|
@ -358,6 +366,7 @@
|
|||
"ignore_notifications_modal.ignore": "تجاهل الإشعارات",
|
||||
"ignore_notifications_modal.limited_accounts_title": "تجاهل الإشعارات من الحسابات التي هي تحت الإشراف؟",
|
||||
"ignore_notifications_modal.new_accounts_title": "تجاهل الإشعارات الصادرة من الحسابات الجديدة؟",
|
||||
"interaction_modal.no_account_yet": "لا تملك حساباً بعد؟",
|
||||
"interaction_modal.on_another_server": "على خادم مختلف",
|
||||
"interaction_modal.on_this_server": "على هذا الخادم",
|
||||
"interaction_modal.title.favourite": "إضافة منشور {name} إلى المفضلة",
|
||||
|
@ -408,11 +417,21 @@
|
|||
"limited_account_hint.title": "تم إخفاء هذا الملف الشخصي من قبل مشرفي {domain}.",
|
||||
"link_preview.author": "مِن {name}",
|
||||
"link_preview.more_from_author": "المزيد من {name}",
|
||||
"lists.add_member": "إضافة",
|
||||
"lists.add_to_list": "إضافة إلى القائمة",
|
||||
"lists.add_to_lists": "إضافة {name} إلى القوائم",
|
||||
"lists.create": "إنشاء",
|
||||
"lists.create_list": "إنشاء قائمة",
|
||||
"lists.delete": "احذف القائمة",
|
||||
"lists.done": "تمّ",
|
||||
"lists.edit": "عدّل القائمة",
|
||||
"lists.exclusive": "إخفاء الأعضاء في الصفحة الرئيسية",
|
||||
"lists.remove_member": "إزالة",
|
||||
"lists.replies_policy.followed": "أي مستخدم متابَع",
|
||||
"lists.replies_policy.list": "أعضاء القائمة",
|
||||
"lists.replies_policy.none": "لا أحد",
|
||||
"lists.save": "حفظ",
|
||||
"lists.search": "بحث",
|
||||
"load_pending": "{count, plural, one {# عنصر جديد} other {# عناصر جديدة}}",
|
||||
"loading_indicator.label": "جاري التحميل…",
|
||||
"media_gallery.hide": "إخفاء",
|
||||
|
@ -464,7 +483,7 @@
|
|||
"notification.label.private_reply": "رد خاص",
|
||||
"notification.label.reply": "ردّ",
|
||||
"notification.mention": "إشارة",
|
||||
"notification.mentioned_you": "{name} mentioned you",
|
||||
"notification.mentioned_you": "أشارَ إليك {name}",
|
||||
"notification.moderation-warning.learn_more": "اعرف المزيد",
|
||||
"notification.moderation_warning": "لقد تلقيت تحذيرًا بالإشراف",
|
||||
"notification.moderation_warning.action_delete_statuses": "تم حذف بعض من منشوراتك.",
|
||||
|
@ -740,6 +759,7 @@
|
|||
"subscribed_languages.target": "تغيير اللغات المشتركة لـ {target}",
|
||||
"tabs_bar.home": "الرئيسية",
|
||||
"tabs_bar.notifications": "الإشعارات",
|
||||
"terms_of_service.title": "شروط الخدمة",
|
||||
"time_remaining.days": "{number, plural, one {# يوم} other {# أيام}} متبقية",
|
||||
"time_remaining.hours": "{number, plural, one {# ساعة} other {# ساعات}} متبقية",
|
||||
"time_remaining.minutes": "{number, plural, one {# دقيقة} other {# دقائق}} متبقية",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "Възникна неочаквана грешка.",
|
||||
"alert.unexpected.title": "Опаа!",
|
||||
"alt_text_badge.title": "Алтернативен текст",
|
||||
"alt_text_modal.add_alt_text": "Добавяне на алтернативен текст",
|
||||
"alt_text_modal.add_text_from_image": "Добавяне на текст от образ",
|
||||
"alt_text_modal.cancel": "Отказ",
|
||||
"alt_text_modal.change_thumbnail": "Промяна на миниобраза",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Опишете това за хора със слухови увреждания…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Опишете това за хора със зрителни увреждания…",
|
||||
"alt_text_modal.done": "Готово",
|
||||
"announcement.announcement": "Оповестяване",
|
||||
"annual_report.summary.archetype.booster": "Якият подсилвател",
|
||||
"annual_report.summary.archetype.lurker": "Дебнещото",
|
||||
|
@ -407,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Пренебрегвате ли известията от хора, които не са ви последвали?",
|
||||
"ignore_notifications_modal.not_following_title": "Пренебрегвате ли известията от хора, които не сте последвали?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Пренебрегвате ли известия от непоискани лични споменавания?",
|
||||
"info_button.label": "Помощ",
|
||||
"info_button.what_is_alt_text": "<h1>Какво е алтернативен текст?</h1> <p>Алтернативният текст осигурява описания на изображение за хора със зрителни увреждания, връзки с ниска честотна лента или търсещите допълнителен контекст.</p> <p>Може да подобрите достъпността и разбираемостта за всеки, пишейки ясен, кратък и обективен алтернативен текст.</p> <ul> <li>Уловете важните елементи</li> <li>Обобщете текста в образите</li> <li>Употребявайте правилна структура на изречението</li> <li>Избягвайте излишна информация</li> <li>Съсредоточете се върху тенденциите и ключови констатации в сложни онагледявания (като диаграми и карти)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Трябва да направите любимо от акаунта си, за да продължите.",
|
||||
"interaction_modal.action.follow": "Трябва да последвате от акаунта си, за да продължите.",
|
||||
"interaction_modal.action.reblog": "Трябва да разпространите нечий блог от акаунта си, за да продължите.",
|
||||
|
|
|
@ -90,8 +90,8 @@
|
|||
"alt_text_modal.add_text_from_image": "Afegiu text d'una imatge",
|
||||
"alt_text_modal.cancel": "Cancel·la",
|
||||
"alt_text_modal.change_thumbnail": "Canvia la miniatura",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Descriu això per a persones amb problemes d'audició…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Descriu això per a persones amb problemes visuals…",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Descriviu això per a persones amb problemes d'audició…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Descriviu això per a persones amb problemes visuals…",
|
||||
"alt_text_modal.done": "Fet",
|
||||
"announcement.announcement": "Anunci",
|
||||
"annual_report.summary.archetype.booster": "Sempre a la moda",
|
||||
|
@ -414,6 +414,7 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Voleu ignorar les notificacions de qui no us segueix?",
|
||||
"ignore_notifications_modal.not_following_title": "Voleu ignorar les notificacions de qui no seguiu?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Voleu ignorar les notificacions de mencions privades no sol·licitades?",
|
||||
"info_button.label": "Ajuda",
|
||||
"interaction_modal.action.favourite": "Per a continuar heu d'afavorir des del vostre compte.",
|
||||
"interaction_modal.action.follow": "Per a continuar heu de seguir des del vostre compte.",
|
||||
"interaction_modal.action.reblog": "Per a continuar heu d'impulsar des del vostre compte.",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ignorér notifikationer fra folk, som ikke er følgere?",
|
||||
"ignore_notifications_modal.not_following_title": "Ignorér notifikationer fra folk, man ikke følger?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignorér notifikationer fra uopfordrede Private omtaler?",
|
||||
"info_button.label": "Hjælp",
|
||||
"info_button.what_is_alt_text": "<h1>Hvad er alt-tekst?</h1> <p>Alt-tekst leverer billedbeskrivelser til folk med synsnedsættelser, lav båndbredde-forbindelser eller med ønske om ekstra kontekst.</p> <p>Tilgængelighed og forståelse kan forbedres for alle ved at skrive klar, kortfattet og objektiv alt-tekst.</p> <ul> <li>Fang vigtige elementer</li> <li>Opsummér tekst i billeder</li> <li>Brug almindelig sætningsstruktur</li> <li>Undgå overflødig information</li> <li>Fokusér på tendenser og centrale resultater i kompleks grafik (såsom diagrammer eller kort)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "For at fortsætte, skal man vælge Gør til favorit fra sin konto.",
|
||||
"interaction_modal.action.follow": "For at fortsætte, skal man vælge Følg fra sin konto.",
|
||||
"interaction_modal.action.reblog": "For at fortsætte, skal man vælge Genblog fra sin konto.",
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"about.disclaimer": "Mastodon ist eine freie, quelloffene Software und eine Marke der Mastodon gGmbH.",
|
||||
"about.domain_blocks.no_reason_available": "Grund unbekannt",
|
||||
"about.domain_blocks.preamble": "Mastodon erlaubt es dir grundsätzlich, alle Inhalte von allen Nutzer*innen auf allen Servern im Fediverse zu sehen und mit ihnen zu interagieren. Für diesen Server gibt es aber ein paar Ausnahmen.",
|
||||
"about.domain_blocks.silenced.explanation": "Alle Inhalte und Profile dieses Servers werden zunächst nicht angezeigt. Du kannst die Profile und Inhalte aber dennoch sehen, wenn du explizit nach diesen suchst oder diesen folgst.",
|
||||
"about.domain_blocks.silenced.explanation": "Standardmäßig werden von diesem Server keine Inhalte oder Profile angezeigt. Du kannst die Profile und Inhalte aber dennoch sehen, wenn du explizit nach diesen suchst oder diesen folgst.",
|
||||
"about.domain_blocks.silenced.title": "Stummgeschaltet",
|
||||
"about.domain_blocks.suspended.explanation": "Es werden keine Daten von diesem Server verarbeitet, gespeichert oder ausgetauscht, sodass eine Interaktion oder Kommunikation mit Nutzer*innen dieses Servers nicht möglich ist.",
|
||||
"about.domain_blocks.suspended.title": "Gesperrt",
|
||||
|
@ -42,8 +42,8 @@
|
|||
"account.hide_reblogs": "Geteilte Beiträge von @{name} ausblenden",
|
||||
"account.in_memoriam": "Zum Andenken.",
|
||||
"account.joined_short": "Mitglied seit",
|
||||
"account.languages": "Ausgewählte Sprachen ändern",
|
||||
"account.link_verified_on": "Das Profil mit dieser E-Mail-Adresse wurde bereits am {date} bestätigt",
|
||||
"account.languages": "Sprache ändern.",
|
||||
"account.link_verified_on": "Das Profil mit dieser E-Mail-Adresse wurde bereits am {date} verifiziert",
|
||||
"account.locked_info": "Die Privatsphäre dieses Kontos wurde auf „geschützt“ gesetzt. Die Person bestimmt manuell, wer ihrem Profil folgen darf.",
|
||||
"account.media": "Medien",
|
||||
"account.mention": "@{name} erwähnen",
|
||||
|
@ -63,7 +63,7 @@
|
|||
"account.share": "Profil von @{name} teilen",
|
||||
"account.show_reblogs": "Geteilte Beiträge von @{name} anzeigen",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} Beitrag} other {{counter} Beiträge}}",
|
||||
"account.unblock": "Blockierung von @{name} aufheben",
|
||||
"account.unblock": "{name} nicht mehr blockieren",
|
||||
"account.unblock_domain": "Blockierung von {domain} aufheben",
|
||||
"account.unblock_short": "Blockierung aufheben",
|
||||
"account.unendorse": "Im Profil nicht mehr empfehlen",
|
||||
|
@ -72,12 +72,12 @@
|
|||
"account.unmute_notifications_short": "Stummschaltung der Benachrichtigungen aufheben",
|
||||
"account.unmute_short": "Stummschaltung aufheben",
|
||||
"account_note.placeholder": "Klicken, um Notiz hinzuzufügen",
|
||||
"admin.dashboard.daily_retention": "Verweildauer der Benutzer*innen pro Tag nach der Registrierung",
|
||||
"admin.dashboard.monthly_retention": "Verweildauer der Benutzer*innen pro Monat nach der Registrierung",
|
||||
"admin.dashboard.daily_retention": "Verweildauer der Nutzer*innen pro Tag nach der Registrierung",
|
||||
"admin.dashboard.monthly_retention": "Verweildauer der Nutzer*innen pro Monat nach der Registrierung",
|
||||
"admin.dashboard.retention.average": "Durchschnitt",
|
||||
"admin.dashboard.retention.cohort": "Monat der Registrierung",
|
||||
"admin.dashboard.retention.cohort_size": "Neue Konten",
|
||||
"admin.impact_report.instance_accounts": "Kontenprofile, die dadurch gelöscht würden",
|
||||
"admin.impact_report.instance_accounts": "Profilkonten, die dadurch gelöscht würden",
|
||||
"admin.impact_report.instance_followers": "Follower, die unsere Nutzer*innen verlieren würden",
|
||||
"admin.impact_report.instance_follows": "Follower, die deren Nutzer*innen verlieren würden",
|
||||
"admin.impact_report.title": "Zusammenfassung der Auswirkung",
|
||||
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Benachrichtigungen von Profilen ignorieren, die dir nicht folgen?",
|
||||
"ignore_notifications_modal.not_following_title": "Benachrichtigungen von Profilen ignorieren, denen du nicht folgst?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Benachrichtigungen von unerwünschten privaten Erwähnungen ignorieren?",
|
||||
"info_button.label": "Hilfe",
|
||||
"info_button.what_is_alt_text": "<h1>Was ist Alt-Text?</h1> <p>Alt-Text bietet Bildbeschreibungen für Personen mit einer Sehschwäche, einer schlechten Internetverbindung und für alle, die zusätzlichen Kontext möchten.</p> <p>Du kannst die Zugänglichkeit und die Verständlichkeit für alle verbessern, indem du eine klare, genaue und objektive Bildbeschreibung hinzufügst.</p> <ul> <li>Erfasse wichtige Elemente</li> <li>Fasse Text in Bildern zusammen</li> <li>Verwende einen korrekten Satzbau</li> <li>Vermeide unwichtige Informationen</li> <li>Konzentriere dich bei komplexen Darstellungen (z. B. Diagramme oder Karten) auf Trends und wichtige Erkenntnisse</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Du musst von deinem Konto aus favorisieren, um fortzufahren.",
|
||||
"interaction_modal.action.follow": "Du musst von deinem Konto aus folgen, um fortzufahren.",
|
||||
"interaction_modal.action.reblog": "Du musst von deinem Konto aus teilen, um fortzufahren.",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "Προέκυψε απροσδόκητο σφάλμα.",
|
||||
"alert.unexpected.title": "Ουπς!",
|
||||
"alt_text_badge.title": "Εναλλακτικό κείμενο",
|
||||
"alt_text_modal.add_alt_text": "Προσθήκη εναλλακτικού κειμένου",
|
||||
"alt_text_modal.add_text_from_image": "Προσθήκη κειμένου από εικόνα",
|
||||
"alt_text_modal.cancel": "Ακύρωση",
|
||||
"alt_text_modal.change_thumbnail": "Αλλαγή μικρογραφίας",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Περιέγραψε αυτό για άτομα με προβλήματα ακοής…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Περιέγραψε αυτό για άτομα με προβλήματα όρασης…",
|
||||
"alt_text_modal.done": "Ολοκληρώθηκε",
|
||||
"announcement.announcement": "Ανακοίνωση",
|
||||
"annual_report.summary.archetype.booster": "Ο κυνηγός των φοβερών",
|
||||
"annual_report.summary.archetype.lurker": "Ο διακριτικός",
|
||||
|
@ -407,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Αγνόηση ειδοποιήσεων από άτομα που δε σας ακολουθούν;",
|
||||
"ignore_notifications_modal.not_following_title": "Αγνόηση ειδοποιήσεων από άτομα που δεν ακολουθείς;",
|
||||
"ignore_notifications_modal.private_mentions_title": "Αγνόηση ειδοποιήσεων από μη ζητηθείσες ιδιωτικές αναφορές;",
|
||||
"info_button.label": "Βοήθεια",
|
||||
"info_button.what_is_alt_text": "Το εναλλακτικό κείμενο παρέχει περιγραφές εικόνας για άτομα με προβλήματα όρασης, διαδικτυακές συνδέσεις χαμηλής ταχύτητας ή για άτομα που αναζητούν επιπλέον περιεχόμενο.\\n\\nΜπορείς να βελτιώσεις την προσβασιμότητα και την κατανόηση για όλους, γράφοντας σαφές, συνοπτικό και αντικειμενικό εναλλακτικό κείμενο.\\n\\n<ul><li>Κατέγραψε σημαντικά στοιχεία</li>\\n<li>Συνόψισε το κείμενο στις εικόνες</li>\\n<li>Χρησιμοποίησε δομή κανονικής πρότασης</li>\\n<li>Απέφυγε περιττές πληροφορίες</li>\\n<li>Εστίασε στις τάσεις και τα βασικά ευρήματα σε σύνθετα οπτικά στοιχεία (όπως διαγράμματα ή χάρτες)</li></ul>",
|
||||
"interaction_modal.action.favourite": "Για να συνεχίσεις, θα πρέπει να αγαπήσεις από τον λογαριασμό σου.",
|
||||
"interaction_modal.action.follow": "Για να συνεχίσεις, θα πρέπει να ακολουθήσεις από τον λογαριασμό σου.",
|
||||
"interaction_modal.action.reblog": "Για να συνεχίσεις, θα πρέπει να αναδημοσιεύσεις από τον λογαριασμό σου.",
|
||||
|
@ -457,6 +466,7 @@
|
|||
"keyboard_shortcuts.toggle_hidden": "Εμφάνιση/απόκρυψη κειμένου πίσω από το CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Εμφάνιση/απόκρυψη πολυμέσων",
|
||||
"keyboard_shortcuts.toot": "Δημιουργία νέας ανάρτησης",
|
||||
"keyboard_shortcuts.translate": "να μεταφράσει μια δημοσίευση",
|
||||
"keyboard_shortcuts.unfocus": "Αποεστίαση του πεδίου σύνθεσης/αναζήτησης",
|
||||
"keyboard_shortcuts.up": "Μετακίνηση προς τα πάνω στη λίστα",
|
||||
"lightbox.close": "Κλείσιμο",
|
||||
|
@ -836,6 +846,7 @@
|
|||
"status.reblogs.empty": "Κανείς δεν ενίσχυσε αυτή την ανάρτηση ακόμα. Μόλις το κάνει κάποιος, θα εμφανιστεί εδώ.",
|
||||
"status.redraft": "Σβήσε & ξαναγράψε",
|
||||
"status.remove_bookmark": "Αφαίρεση σελιδοδείκτη",
|
||||
"status.remove_favourite": "Κατάργηση από τα αγαπημένα",
|
||||
"status.replied_in_thread": "Απαντήθηκε σε νήμα",
|
||||
"status.replied_to": "Απάντησε στον {name}",
|
||||
"status.reply": "Απάντησε",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "An unexpected error occurred.",
|
||||
"alert.unexpected.title": "Oops!",
|
||||
"alt_text_badge.title": "Alt text",
|
||||
"alt_text_modal.add_alt_text": "Add alt text",
|
||||
"alt_text_modal.add_text_from_image": "Add text from image",
|
||||
"alt_text_modal.cancel": "Cancel",
|
||||
"alt_text_modal.change_thumbnail": "Change thumbnail",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Describe this for people with hearing impairments…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Describe this for people with visual impairments…",
|
||||
"alt_text_modal.done": "Done",
|
||||
"announcement.announcement": "Announcement",
|
||||
"annual_report.summary.archetype.booster": "The cool-hunter",
|
||||
"annual_report.summary.archetype.lurker": "The lurker",
|
||||
|
@ -407,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ignore notifications from people not following you?",
|
||||
"ignore_notifications_modal.not_following_title": "Ignore notifications from people you don't follow?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignore notifications from unsolicited Private Mentions?",
|
||||
"info_button.label": "Help",
|
||||
"info_button.what_is_alt_text": "<h1>What is alt text?</h1> <p>Alt text provides image descriptions for people with vision impairments, low-bandwidth connections, or those seeking extra context.</p> <p>You can improve accessibility and understanding for everyone by writing clear, concise, and objective alt text.</p> <ul> <li>Capture important elements</li> <li>Summarise text in images</li> <li>Use regular sentence structure</li> <li>Avoid redundant information</li> <li>Focus on trends and key findings in complex visuals (like diagrams or maps)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "To continue, you need to favourite from your account.",
|
||||
"interaction_modal.action.follow": "To continue, you need to follow from your account.",
|
||||
"interaction_modal.action.reblog": "To continue, you need to reblog from your account.",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ignore notifications from people not following you?",
|
||||
"ignore_notifications_modal.not_following_title": "Ignore notifications from people you don't follow?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignore notifications from unsolicited Private Mentions?",
|
||||
"info_button.label": "Help",
|
||||
"info_button.what_is_alt_text": "<h1>What is alt text?</h1> <p>Alt text provides image descriptions for people with vision impairments, low-bandwidth connections, or those seeking extra context.</p> <p>You can improve accessibility and understanding for everyone by writing clear, concise, and objective alt text.</p> <ul> <li>Capture important elements</li> <li>Summarize text in images</li> <li>Use regular sentence structure</li> <li>Avoid redundant information</li> <li>Focus on trends and key findings in complex visuals (like diagrams or maps)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "To continue, you need to favorite from your account.",
|
||||
"interaction_modal.action.follow": "To continue, you need to follow from your account.",
|
||||
"interaction_modal.action.reblog": "To continue, you need to reblog from your account.",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ĉu ignori sciigojn de homoj, kiuj ne sekvas vin?",
|
||||
"ignore_notifications_modal.not_following_title": "Ĉu ignori sciigojn de homoj, kiujn vi ne sekvas?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ĉu ignori sciigojn de nepetitaj privataj mencioj?",
|
||||
"info_button.label": "Helpo",
|
||||
"info_button.what_is_alt_text": "<h1>Kio estas la alternativa teksto?</h1> <p>La alternativa teksto ofertas priskribojn de la bildoj por individuoj kun vidaj malfacilaĵoj, konektoj kun malalta larĝa bando aŭ kiuj serĉas plian kuntekston.</p> <p>Vi povas plibonigi alireblecon kaj komprenon por ĉiuj per skribado de klaraj, koncizaj, kaj objektivaj alternativaj tekstoj.</p><ul><li>Kaptu gravajn elementojn.</li><li> Resumu tekston en bildoj.</li> <li>Uzu regulan frazstrukturon.</li> <li>Evitu redundan informon.</li><li>Fokusu sur tendencoj kaj ĉefaj trovoj en kompleksaj visualoj (kiel diagramoj aŭ mapoj).</li></ul>",
|
||||
"interaction_modal.action.favourite": "Por daŭrigi, vi devas stelumi el via konto.",
|
||||
"interaction_modal.action.follow": "Por daŭrigi, vi devas sekvi el via konto.",
|
||||
"interaction_modal.action.reblog": "Por daŭrigi, vi devas diskonigi el via konto.",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de cuentas que no te siguen?",
|
||||
"ignore_notifications_modal.not_following_title": "¿Ignorar notificaciones de cuentas a las que no seguís?",
|
||||
"ignore_notifications_modal.private_mentions_title": "¿Ignorar notificaciones de menciones privadas no solicitadas?",
|
||||
"info_button.label": "Ayuda",
|
||||
"info_button.what_is_alt_text": "<h1>¿Qué es el texto alternativo?</h1> <p>El texto alternativo proporciona descripciones de las imágenes para personas con dificultades visuales, conexiones con escaso ancho de banda o que buscan un contexto adicional.</p> <p>Podés mejorar la accesibilidad y la comprensión para todos escribiendo un texto alternativo claro, conciso y objetivo.</p> <ul><li>Captura los elementos importantes.</li><li>Resumí el texto en imágenes.</li><li>Usá una estructura de frases normal.</li><li>Evitá la información redundante.</li><li>Focalizate en las tendencias y conclusiones clave de los elementos visuales complejos (como diagramas o mapas).</li></ul>",
|
||||
"interaction_modal.action.favourite": "Para continuar, tenés que marcar como favorito desde tu cuenta.",
|
||||
"interaction_modal.action.follow": "Para continuar, tenés que seguir desde tu cuenta.",
|
||||
"interaction_modal.action.reblog": "Para continuar, tenés que adherir desde tu cuenta.",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de personas que no te siguen?",
|
||||
"ignore_notifications_modal.not_following_title": "¿Ignorar notificaciones de personas a las que no sigues?",
|
||||
"ignore_notifications_modal.private_mentions_title": "¿Ignorar notificaciones de menciones privadas no solicitadas?",
|
||||
"info_button.label": "Ayuda",
|
||||
"info_button.what_is_alt_text": "<h1>¿Qué es el texto alternativo?</h1> <p>El texto alternativo ofrece descripciones de las imágenes para individuos con dificultades visuales, conexiones de bajo ancho de banda o que buscan un contexto adicional.</p> <p>Puedes mejorar la accesibilidad y la comprensión para todos redactando un texto alternativo claro, breve y objetivo.</p> <ul><li>Captura los elementos clave.</li><li>Resume el texto en imágenes.</li><li>Utiliza una estructura de oraciones estándar.</li><li>Evita la información repetitiva.</li><li>Enfócate en las tendencias y conclusiones principales de los elementos visuales complejos (como gráficos o mapas).</li></ul>",
|
||||
"interaction_modal.action.favourite": "Para continuar, debes marcar como favorito desde tu cuenta.",
|
||||
"interaction_modal.action.follow": "Para continuar, debes seguir desde tu cuenta.",
|
||||
"interaction_modal.action.reblog": "Para continuar, debes impulsar desde tu cuenta.",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de personas que no te siguen?",
|
||||
"ignore_notifications_modal.not_following_title": "¿Ignorar notificaciones de personas a las que no sigues?",
|
||||
"ignore_notifications_modal.private_mentions_title": "¿Ignorar notificaciones de menciones privadas no solicitadas?",
|
||||
"info_button.label": "Ayuda",
|
||||
"info_button.what_is_alt_text": "<h1>¿Qué es el texto alternativo?</h1> <p>El texto alternativo proporciona descripciones de las imágenes para personas con problemas de visión, conexiones con poco ancho de banda o que buscan un contexto adicional.</p> <p>Puedes mejorar la accesibilidad y la comprensión para todos escribiendo un texto alternativo claro, conciso y objetivo.</p> <ul><li>Captura los elementos importantes.</li><li>Resume el texto en imágenes.</li><li>Usa una estructura de frases normal.</li><li>Evita la información redundante.</li><li>Céntrate en las tendencias y conclusiones clave de los elementos visuales complejos (como diagramas o mapas).</li></ul>",
|
||||
"interaction_modal.action.favourite": "Para continuar, tienes que marcar como favorito desde tu cuenta.",
|
||||
"interaction_modal.action.follow": "Para continuar, tienes que seguir desde tu cuenta.",
|
||||
"interaction_modal.action.reblog": "Para continuar, tienes que impulsar desde tu cuenta.",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "Tekkis ootamatu viga.",
|
||||
"alert.unexpected.title": "Oih!",
|
||||
"alt_text_badge.title": "Alternatiivtekst",
|
||||
"alt_text_modal.add_alt_text": "Lisa alt-tekst",
|
||||
"alt_text_modal.add_text_from_image": "Lisa tekst pildilt",
|
||||
"alt_text_modal.cancel": "Tühista",
|
||||
"alt_text_modal.change_thumbnail": "Muuda pisipilti",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Kirjelda seda kuulmispuudega inimeste jaoks…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Kirjelda seda nägemispuudega inimeste jaoks…",
|
||||
"alt_text_modal.done": "Valmis",
|
||||
"announcement.announcement": "Teadaanne",
|
||||
"annual_report.summary.archetype.booster": "Ägesisu küttija",
|
||||
"annual_report.summary.archetype.lurker": "Hiilija",
|
||||
|
@ -407,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ignoreeri inimeste teavitusi, kes sind ei jälgi?",
|
||||
"ignore_notifications_modal.not_following_title": "Ignoreeri inimeste teavitusi, keda sa ei jälgi?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignoreeri soovimatute eraviisiliste mainimiste teateid?",
|
||||
"info_button.label": "Abi",
|
||||
"info_button.what_is_alt_text": "<h1>Mis on alt-tekst?</h1> <p>Alt-tekst pakub pildi kirjeldust nägemispuudega inimeste jaoks või neile, kel on aeglane internet või neile, kes otsivad lisaselgitust</p> <p>Saad parandada ligipääsetavust ja mõistmist kõigi jaoks, kirjutades selge, lühida ja objektiivse alt-teksti.</p> <ul> <li>Lisa tähtsad elemendid</li> <li>Tee pildil olevast tekstist kokkuvõte</li> <li>Kasuta reeglipärast lausestruktuuri</li> <li>Väldi ebaolulist infot</li> <li>Keskendu keerukate vaadete puhul (näiteks diagrammid ja kaardid) puhul trendidele ja põhiseostele</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Jätkamiseks pead oma konto alt lemmikuks märkima.",
|
||||
"interaction_modal.action.follow": "Jätkamiseks pead oma konto alt lemmikuks märkima.",
|
||||
"interaction_modal.action.reblog": "Jätkamiseks pead jagama oma konto alt.",
|
||||
|
@ -457,6 +466,7 @@
|
|||
"keyboard_shortcuts.toggle_hidden": "Näita/peida teksti hoiatuse taga",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Näita/peida meediat",
|
||||
"keyboard_shortcuts.toot": "Alusta uut postitust",
|
||||
"keyboard_shortcuts.translate": "postituse tõlkimiseks",
|
||||
"keyboard_shortcuts.unfocus": "Fookus tekstialalt/otsingult ära",
|
||||
"keyboard_shortcuts.up": "Liigu loetelus üles",
|
||||
"lightbox.close": "Sulge",
|
||||
|
|
|
@ -86,12 +86,18 @@
|
|||
"alert.unexpected.message": "Ustekabeko errore bat gertatu da.",
|
||||
"alert.unexpected.title": "Ene!",
|
||||
"alt_text_badge.title": "Testu alternatiboa",
|
||||
"alt_text_modal.add_alt_text": "Gehitu ordezko testua",
|
||||
"alt_text_modal.add_text_from_image": "Gehitu testua iruditik",
|
||||
"alt_text_modal.cancel": "Utzi",
|
||||
"alt_text_modal.change_thumbnail": "Aldatu koadro txikia",
|
||||
"alt_text_modal.done": "Egina",
|
||||
"announcement.announcement": "Iragarpena",
|
||||
"annual_report.summary.followers.followers": "jarraitzaileak",
|
||||
"annual_report.summary.followers.total": "{count} guztira",
|
||||
"annual_report.summary.highlighted_post.by_favourites": "egindako bidalketa gogokoena",
|
||||
"annual_report.summary.highlighted_post.by_reblogs": "egindako bidalketa zabalduena",
|
||||
"annual_report.summary.highlighted_post.by_replies": "erantzun gehien izan dituen bidalketa",
|
||||
"annual_report.summary.highlighted_post.possessive": "{name}-(r)ena",
|
||||
"annual_report.summary.most_used_app.most_used_app": "app erabiliena",
|
||||
"annual_report.summary.most_used_hashtag.most_used_hashtag": "traola erabiliena",
|
||||
"annual_report.summary.most_used_hashtag.none": "Bat ere ez",
|
||||
|
@ -120,6 +126,7 @@
|
|||
"bundle_column_error.routing.body": "Eskatutako orria ezin izan da aurkitu. Ziur helbide-barrako URLa zuzena dela?",
|
||||
"bundle_column_error.routing.title": "404",
|
||||
"bundle_modal_error.close": "Itxi",
|
||||
"bundle_modal_error.message": "Zerbait okerra gertatu da pantaila hau kargatzean.",
|
||||
"bundle_modal_error.retry": "Saiatu berriro",
|
||||
"closed_registrations.other_server_instructions": "Mastodon deszentralizatua denez, beste kontu bat sortu dezakezu beste zerbitzari batean eta honekin komunikatu.",
|
||||
"closed_registrations_modal.description": "Une honetan ezin da konturik sortu {domain} zerbitzarian, baina kontuan izan Mastodon erabiltzeko ez duzula zertan konturik izan zehazki {domain} zerbitzarian.",
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
"annual_report.summary.archetype.replier": "پاسخگو",
|
||||
"annual_report.summary.followers.followers": "دنبال کننده",
|
||||
"annual_report.summary.followers.total": "در مجموع {count}",
|
||||
"annual_report.summary.here_it_is": "بازبینی {year}تان:",
|
||||
"annual_report.summary.here_it_is": "بازبینی {year} تان:",
|
||||
"annual_report.summary.highlighted_post.by_favourites": "پرپسندترین فرسته",
|
||||
"annual_report.summary.highlighted_post.by_reblogs": "پرتقویتترین فرسته",
|
||||
"annual_report.summary.highlighted_post.by_replies": "پرپاسخترین فرسته",
|
||||
|
@ -175,7 +175,7 @@
|
|||
"community.column_settings.media_only": "فقط رسانه",
|
||||
"community.column_settings.remote_only": "تنها دوردست",
|
||||
"compose.language.change": "تغییر زبان",
|
||||
"compose.language.search": "جستوجوی زبانها…",
|
||||
"compose.language.search": "جستوجوی زبانها...",
|
||||
"compose.published.body": "فرسته منتشر شد.",
|
||||
"compose.published.open": "گشودن",
|
||||
"compose.saved.body": "فرسته ذخیره شد.",
|
||||
|
@ -256,7 +256,7 @@
|
|||
"domain_block_modal.they_cant_follow": "هیچکسی از این کارساز نمیتواند پیتان بگیرد.",
|
||||
"domain_block_modal.they_wont_know": "نخواهند دانست که مسدود شدهاند.",
|
||||
"domain_block_modal.title": "انسداد دامنه؟",
|
||||
"domain_block_modal.you_will_lose_num_followers": "تعداد {followersCount, plural,other {{followersCount}}} پیگیرنده و {followingCount, plural,other {{followingCount}}} شخص پیگرفته شده را از دست خواهید داد.",
|
||||
"domain_block_modal.you_will_lose_num_followers": "شما {followersCount, plural, one {{followersCountDisplay} پیگیرنده} other {{followersCountDisplay} پیگیرنده}} و {followingCount, plural, one {{followingCountDisplay} فرد پیگرفتهشده} other {{followingCountDisplay} فرد پیگرفتهشده}} را از دست خواهید داد.",
|
||||
"domain_block_modal.you_will_lose_relationships": "شما تمام پیگیرکنندگان و افرادی که از این کارساز پیگیری میکنید را از دست خواهید داد.",
|
||||
"domain_block_modal.you_wont_see_posts": "فرستهها یا آگاهیها از کاربران روی این کارساز را نخواهید دید.",
|
||||
"domain_pill.activitypub_lets_connect": "این به شما اجازه میدهد تا نه تنها در ماستودون، بلکه در برنامههای اجتماعی مختلف نیز با افراد ارتباط برقرار کرده و تعامل داشته باشید.",
|
||||
|
@ -304,7 +304,7 @@
|
|||
"empty_column.follow_requests": "شما هنوز هیچ درخواست پیگیریای ندارید. هنگامی که چنین درخواستی بگیرید، اینجا نشان داده خواهد شد.",
|
||||
"empty_column.followed_tags": "شما هیچ برچسبی را پینگرفتید. هنگامی که برچسبی را پیگیری کنید اینجا نمایان میشوند.",
|
||||
"empty_column.hashtag": "هنوز هیچ چیزی در این برچسب نیست.",
|
||||
"empty_column.home": "خط زمانی خانگیتان خالی است! برای پر کردنش، افراد بیشتری را پی بگیرید. {suggestions}",
|
||||
"empty_column.home": "خط زمانی خانگیتان خالی است! برای پر کردنش، افراد بیشتری را پی بگیرید.",
|
||||
"empty_column.list": "هنوز چیزی در این سیاهه نیست. هنگامی که اعضایش فرستههای جدیدی بفرستند، اینجا ظاهر خواهند شد.",
|
||||
"empty_column.mutes": "هنوز هیچ کاربری را خموش نکردهاید.",
|
||||
"empty_column.notification_requests": "همه چیز تمیز است! هیچچیزی اینجا نیست. هنگامی که آگاهیهای جدیدی دریافت کنید، بسته به تنظیماتتان اینجا ظاهر خواهند شد.",
|
||||
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "چشمپوشی از آگاهیهای افرادی که پیتان نمیگیرند؟",
|
||||
"ignore_notifications_modal.not_following_title": "چشمپوشی از آگاهیهای افرادی که پیشان نمیگیرید؟",
|
||||
"ignore_notifications_modal.private_mentions_title": "چشمپوشی از نامبریهای خصوصی ناخواسته؟",
|
||||
"info_button.label": "راهنما",
|
||||
"info_button.what_is_alt_text": "<h1>متن جایگزین چیست؟</h1> <p>متن جایگزین توضیحات تصویری را برای افراد دارای اختلالات بینایی، اتصالات با پهنای باند کم یا کسانی که به دنبال زمینه اضافی هستند ارائه می دهد.</p> <p>با نوشتن متن جایگزین واضح، مختصر و عینی می توانید دسترسی و درک را برای همه بهبود بخشید.</p> <ul> <li>عناصر مهم را ضبط کنید</li> <li>متن را در تصاویر خلاصه کنید</li> <li>از ساختار جمله منظم استفاده کنید</li> <li>از اطلاعات اضافی خودداری کنید</li> <li>روی روندها و یافته های کلیدی در تصاویر پیچیده (مانند نمودارها یا نقشه ها) تمرکز کنید.</li> </ul>",
|
||||
"interaction_modal.action.favourite": "برای ادامه، باید از حساب خود به دلخواه انتخاب کنید.",
|
||||
"interaction_modal.action.follow": "برای ادامه، باید از حساب کاربری خود دنبال کنید.",
|
||||
"interaction_modal.action.reblog": "برای ادامه، باید از حساب خود مجددا بلاگ کنید.",
|
||||
|
@ -551,7 +553,7 @@
|
|||
"notification.admin.report_statuses_other": "{name}، {target} را گزارش داد",
|
||||
"notification.admin.sign_up": "{name} ثبت نام کرد",
|
||||
"notification.admin.sign_up.name_and_others": "{name} و {count, plural, one {# نفر دیگر} other {# نفر دیگر}} ثبتنام کردند",
|
||||
"notification.annual_report.message": "آمار #Wrapstodon {year}تان منتظر است! لحظههای به یاد ماندنی و نقاط پررنگ سال را روی ماستودون رونمایی کنید!",
|
||||
"notification.annual_report.message": "آمار #Wrapstodon {year} تان منتظر است! لحظههای به یاد ماندنی و نقاط پررنگ سال را روی ماستودون رونمایی کنید!",
|
||||
"notification.annual_report.view": "دیدن #Wrapstodon",
|
||||
"notification.favourite": "{name} فرستهتان را برگزید",
|
||||
"notification.favourite.name_and_others_with_link": "{name} و <a>{count, plural, one {# نفر دیگر} other {# نفر دیگر}}</a> فرستهتان را برگزیدند",
|
||||
|
@ -799,7 +801,7 @@
|
|||
"server_banner.is_one_of_many": "{domain} یکی از بسیاری از سرورهای مستقل ماستودون است که می توانید از آن برای شرکت در fediverse استفاده کنید.",
|
||||
"server_banner.server_stats": "آمار کارساز:",
|
||||
"sign_in_banner.create_account": "ایجاد حساب",
|
||||
"sign_in_banner.follow_anyone": "هر کسی را در سراسر fediverse دنبال کنید و همه را به ترتیب زمانی ببینید. هیچ الگوریتم، تبلیغات یا طعمه کلیکی در چشم نیست.",
|
||||
"sign_in_banner.follow_anyone": "هر کسی را در سراسر فدیورس دنبال کنید و همه را به ترتیب زمانی ببینید. هیچ الگوریتم، تبلیغات یا طعمه کلیکی در چشم نیست.",
|
||||
"sign_in_banner.mastodon_is": "ماستودون بهترین راه برای پیگیری اتفاقات است.",
|
||||
"sign_in_banner.sign_in": "ورود",
|
||||
"sign_in_banner.sso_redirect": "ورود یا ثبت نام",
|
||||
|
@ -888,7 +890,7 @@
|
|||
"upload_form.drag_and_drop.on_drag_over": "پیوست رسانه {item} منتقل شد.",
|
||||
"upload_form.drag_and_drop.on_drag_start": "پیوست رسانه {item} برداشته شد.",
|
||||
"upload_form.edit": "ویرایش",
|
||||
"upload_progress.label": "در حال بارگذاری…",
|
||||
"upload_progress.label": "در حال بارگذاری...",
|
||||
"upload_progress.processing": "در حال پردازش…",
|
||||
"username.taken": "این نام کاربری گرفته شده. نام دیگری امتحان کنید",
|
||||
"video.close": "بستن ویدیو",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "Tapahtui odottamaton virhe.",
|
||||
"alert.unexpected.title": "Hups!",
|
||||
"alt_text_badge.title": "Vaihtoehtoinen teksti",
|
||||
"alt_text_modal.add_alt_text": "Lisää vaihtoehtoinen teksti",
|
||||
"alt_text_modal.add_text_from_image": "Lisää teksti kuvasta",
|
||||
"alt_text_modal.cancel": "Peruuta",
|
||||
"alt_text_modal.change_thumbnail": "Vaihda pikkukuva",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Kuvaile tätä kuulovammallisille ihmisille…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Kuvaile tätä näkövammallisille ihmisille…",
|
||||
"alt_text_modal.done": "Valmis",
|
||||
"announcement.announcement": "Tiedote",
|
||||
"annual_report.summary.archetype.booster": "Tehostaja",
|
||||
"annual_report.summary.archetype.lurker": "Lymyilijä",
|
||||
|
@ -407,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Sivuutetaanko ilmoitukset käyttäjiltä, jotka eivät seuraa sinua?",
|
||||
"ignore_notifications_modal.not_following_title": "Sivuutetaanko ilmoitukset käyttäjiltä, joita et seuraa?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Sivuutetaanko ilmoitukset pyytämättömistä yksityismaininnoista?",
|
||||
"info_button.label": "Ohje",
|
||||
"info_button.what_is_alt_text": "<h1>Mikä vaihtoehtoinen teksti on?</h1> <p>Vaihtoehtoinen teksti tarjoaa kuvauksen kuvista ihmisille, joilla on näkövamma tai matalan kaistanleveyden yhteys tai jotka kaipaavat lisäkontekstia.</p> <p>Voit parantaa saavutettavuutta ja ymmärrettävyyttä kaikkien näkökulmasta kirjoittamalla selkeän, tiiviin ja objektiivisen vaihtoehtoisen tekstin.</p> <ul> <li>Ota mukaan tärkeät elementit</li> <li>Tiivistä kuvissa oleva teksti</li> <li>Käytä tavallisia lauserakenteita</li> <li>Vältä turhaa tietoa</li> <li>Keskity trendeihin ja keskeisiin tuloksiin monimutkaisissa visuaalisissa esityksissä (kuten kaavioissa tai kartoissa)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Jotta voit jatkaa, sinun tulee lisätä julkaisu suosikiksesi omalta tililtäsi.",
|
||||
"interaction_modal.action.follow": "Jotta voit jatkaa, sinun tulee seurata käyttäjää omalta tililtäsi.",
|
||||
"interaction_modal.action.reblog": "Jotta voit jatkaa, sinun tulee uudelleenjulkaista omalta tililtäsi.",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Lat sum um tú ikki sær fráboðanir frá fólki, sum ikki fylgja tær?",
|
||||
"ignore_notifications_modal.not_following_title": "Lat sum um tú ikki sær fráboðanir frá fólki, sum tú ikki fylgir?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Lat sum um tú ikki sær fráboðanir frá óbiðnum privatum umrøðum?",
|
||||
"info_button.label": "Hjálp",
|
||||
"info_button.what_is_alt_text": "<h1>Hvat er alt tekstur?</h1> <p>Alt tekstur lýsir myndir fyri fólki, sum síggja illa, ella sum hava ringt net samband ella tey, sum vilja vita meira um samanhangin.</p> <p>Tú kanst bøta um atkomuna og fatanina hjá øllum við at skriva kláran, stuttan og objektivan alt tekst.</p> <ul> <li>Fanga týdningarmikil element</li> <li>Samanfata tekst í myndum</li> <li>Brúka reglubundnan setningsbygnað</li> <li>Lat vera við at siga ting upp í saman</li> <li>Fokusera á rák og høvuðsúrslit í kompleksum myndum (sosum diagrammir og kort)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Fyri at halda fram, so mást tú yndismerkja frá tínari kontu.",
|
||||
"interaction_modal.action.follow": "Fyri at halda fram, mást tú fylgja frá tínari kontu.",
|
||||
"interaction_modal.action.reblog": "Fyri at halda fram, mást tú endurblogga frá tínari kontu.",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ignorer les notifications provenant des personnes qui ne vous suivent pas ?",
|
||||
"ignore_notifications_modal.not_following_title": "Ignorer les notifications provenant des personnes que vous ne suivez pas ?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignorer les notifications issues des mentions privées non sollicitées ?",
|
||||
"info_button.label": "Aide",
|
||||
"info_button.what_is_alt_text": "<h1>Qu'est-ce que le texte alternatif ?</h1> <p>Un texte alternatif fournit une description de l'image aux personnes avec un handicap visuel ou une connexion limitée ou qui souhaitent avoir un contexte supplémentaire.</p> <p>Vous pouvez améliorer l'accessibilité et la compression de tout le monde en écrivant un texte alternatif clair, concis et objectif.</p> <ul> <li>Identifiez les éléments importants</li> <li>Résumez le texte présent à l'image</li> <li>Utilisez une structure de phrase normale</li> <li>Évitez les informations redondantes</li> <li>Pour les visuels complexes (tels que les diagrammes ou les cartes), indiquez les tendances ou points-clés</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Pour continuer, vous devez ajouter en favori depuis votre compte.",
|
||||
"interaction_modal.action.follow": "Pour continuer, vous devez suivre depuis votre compte.",
|
||||
"interaction_modal.action.reblog": "Pour continuer, vous devez booster depuis votre compte.",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ignorer les notifications provenant des personnes qui ne vous suivent pas ?",
|
||||
"ignore_notifications_modal.not_following_title": "Ignorer les notifications provenant des personnes que vous ne suivez pas ?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignorer les notifications issues des mentions privées non sollicitées ?",
|
||||
"info_button.label": "Aide",
|
||||
"info_button.what_is_alt_text": "<h1>Qu'est-ce que le texte alternatif ?</h1> <p>Un texte alternatif fournit une description de l'image aux personnes avec un handicap visuel ou une connexion limitée ou qui souhaitent avoir un contexte supplémentaire.</p> <p>Vous pouvez améliorer l'accessibilité et la compression de tout le monde en écrivant un texte alternatif clair, concis et objectif.</p> <ul> <li>Identifiez les éléments importants</li> <li>Résumez le texte présent à l'image</li> <li>Utilisez une structure de phrase normale</li> <li>Évitez les informations redondantes</li> <li>Pour les visuels complexes (tels que les diagrammes ou les cartes), indiquez les tendances ou points-clés</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Pour continuer, vous devez ajouter en favori depuis votre compte.",
|
||||
"interaction_modal.action.follow": "Pour continuer, vous devez suivre depuis votre compte.",
|
||||
"interaction_modal.action.reblog": "Pour continuer, vous devez booster depuis votre compte.",
|
||||
|
@ -549,7 +551,7 @@
|
|||
"notification.admin.report_account_other": "{name} a signalé {count, plural, one {un message} other {# messages}} depuis {target}",
|
||||
"notification.admin.report_statuses": "{name} a signalé {target} pour {category}",
|
||||
"notification.admin.report_statuses_other": "{name} a signalé {target}",
|
||||
"notification.admin.sign_up": "{name} s'est inscrit",
|
||||
"notification.admin.sign_up": "{name} s'est inscrit·e",
|
||||
"notification.admin.sign_up.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} se sont inscrit",
|
||||
"notification.annual_report.message": "Votre {year} #Wrapstodon attend ! Dévoilez les moments forts et mémorables de votre année sur Mastodon !",
|
||||
"notification.annual_report.view": "Voir #Wrapstodon",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ignorar notificacións de persoas que non te seguen?",
|
||||
"ignore_notifications_modal.not_following_title": "Ignorar notificacións de persoas que non segues?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignorar notificacións de Mencións Privadas non solicitadas?",
|
||||
"info_button.label": "Axuda",
|
||||
"info_button.what_is_alt_text": "<h1>Que é o Texto Alternativo?</h1> <p>O Text Alt proporciona a descrición das imaxes para as persoas con deficiencias visuais, conexións a internet de baixa calidade ou para engadir contexto ás mesmas.</p> <p>Podes mellorar a accesibilidade e a comprensión da publicación ao escribir un texto alternativo claro, conciso e obxectivo.</p> <ul> <li>Identifica os elementos importantes</li> <li>Inclúe o texto que apareza nas imaxes</li> <li>Utiliza sintaxe estándar nas frases</li> <li>Evita información redundante</li> <li>Céntrate nos elementos principais cando sexan imaxes complexas (como diagramas ou mapas)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Para continuar, debes favorecer desde a túa conta.",
|
||||
"interaction_modal.action.follow": "Para continuar, debes facer seguimento desde a túa conta.",
|
||||
"interaction_modal.action.reblog": "Para continuar, debes promover desde a túa conta.",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "להתעלם מהתראות מא.נשים שאינם עוקביך?",
|
||||
"ignore_notifications_modal.not_following_title": "להתעלם מהתראות מא.נשים שאינם נעקביך?",
|
||||
"ignore_notifications_modal.private_mentions_title": "להתעלם מהתראות מאיזכורים פרטיים?",
|
||||
"info_button.label": "עזרה",
|
||||
"info_button.what_is_alt_text": "<h1>מהו כיתוב חלופי?</h1> <p>כיתוב חלופי משמש תיאור מילולי של תמונות לסובלים ממגבלות ראיה, חיבורי רשת איטיים, או אלו הצריכים הקשר יותר מפורט לתוכן המולטימדיה המצורף.</p> <p>ניתן לשפר את הנגישות והבנת התוכן לכולם ע\"י כתיבת תיאור ברור, תמציתי ונטול פניות.</p> <ul> <li>כיסוי היסודות החשובים</li> <li>סיכום המלל שבתמונות</li> <li>שימוש במבנה משפטים רגיל</li> <li>יש להמנע מחזרה על מידע</li> <li>אם העזרים הויזואליים הם דיאגרמות או מפות, התמקדו במגמות וממצאים מרכזיים.</li> </ul>",
|
||||
"interaction_modal.action.favourite": "כדי להמשיך, עליך לחבב מחשבונך.",
|
||||
"interaction_modal.action.follow": "כדי להמשיך, עליך לעקוב מחשבונך.",
|
||||
"interaction_modal.action.reblog": "כדי להמשיך, עליך להדהד מחשבונך.",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "Váratlan hiba történt.",
|
||||
"alert.unexpected.title": "Hoppá!",
|
||||
"alt_text_badge.title": "Helyettesítő szöveg",
|
||||
"alt_text_modal.add_alt_text": "Helyettesítő szöveg hozzáadása",
|
||||
"alt_text_modal.add_text_from_image": "Szöveg hozzáadása a képből",
|
||||
"alt_text_modal.cancel": "Mégse",
|
||||
"alt_text_modal.change_thumbnail": "Bélyegkép megváltoztatása",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Írd le a hallássérültek számára…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Írd le a látássérültek számára…",
|
||||
"alt_text_modal.done": "Kész",
|
||||
"announcement.announcement": "Közlemény",
|
||||
"annual_report.summary.archetype.booster": "A cool-vadász",
|
||||
"annual_report.summary.archetype.lurker": "A settenkedő",
|
||||
|
@ -407,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Nem követőktől érkező értesítések figyelmen kívül hagyása?",
|
||||
"ignore_notifications_modal.not_following_title": "Nem követettektől érkező értesítések figyelmen kívül hagyása?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Figyelmen kívül hagyod a kéretlen privát említéseket?",
|
||||
"info_button.label": "Súgó",
|
||||
"info_button.what_is_alt_text": "<h1>Mi az alternatív szöveg?</h1> <p>Az alternatív szöveg képleírást biztosít a látássérültek, az alacsony sávszélességű kapcsolatokkal rendelkezők, illetve a bővebb kontextust keresők számára.</p> <p>Az egyértelmű, tömör és objektív alternatív szöveg megírásával mindenki számára akadálymentesebb és könnyebben érthető lesz.</p> <ul> <li>Rögzítsd a fontos elemeket.</li> <li>Foglald össze szövegesen a képeket.</li> <li>Használj szabályos mondatszerkezetet.</li> <li>Kerüld a felesleges információkat.</li> <li>Összetett vizuális ábrákon (például diagramokon vagy térképeken) összpontosíts a trendekre és a legfontosabb megállapításokra.</li> </ul>",
|
||||
"interaction_modal.action.favourite": "A folytatáshoz a fiókodból kell kedvencnek jelölnöd.",
|
||||
"interaction_modal.action.follow": "A folytatáshoz a fiókodból kell követned.",
|
||||
"interaction_modal.action.reblog": "A folytatáshoz a fiókodból kell megosztanod.",
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
"alt_text_modal.add_text_from_image": "Adder texto ab imagine",
|
||||
"alt_text_modal.cancel": "Cancellar",
|
||||
"alt_text_modal.change_thumbnail": "Cambiar le miniatura",
|
||||
"alt_text_modal.done": "Preste",
|
||||
"announcement.announcement": "Annuncio",
|
||||
"annual_report.summary.archetype.booster": "Le impulsator",
|
||||
"annual_report.summary.archetype.lurker": "Le lector",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "Upp kom óvænt villa.",
|
||||
"alert.unexpected.title": "Úbbs!",
|
||||
"alt_text_badge.title": "Hjálpartexti mynda",
|
||||
"alt_text_modal.add_alt_text": "Bæta við hjálpartexta",
|
||||
"alt_text_modal.add_text_from_image": "Bæta við texta úr mynd",
|
||||
"alt_text_modal.cancel": "Hætta við",
|
||||
"alt_text_modal.change_thumbnail": "Skipta um smámynd",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Lýstu þessu fyrir fólk með skerta heyrn…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Lýstu þessu fyrir fólk með skerta sjón…",
|
||||
"alt_text_modal.done": "Lokið",
|
||||
"announcement.announcement": "Auglýsing",
|
||||
"annual_report.summary.archetype.booster": "Svali gaurinn",
|
||||
"annual_report.summary.archetype.lurker": "Lurkurinn",
|
||||
|
@ -407,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Hunsa tilkynningar frá fólki sem fylgist ekki með þér?",
|
||||
"ignore_notifications_modal.not_following_title": "Hunsa tilkynningar frá fólki sem þú fylgist ekki með?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Hunsa tilkynningar frá óumbeðnum tilvísunum í einkaspjalli?",
|
||||
"info_button.label": "Hjálp",
|
||||
"info_button.what_is_alt_text": "<h1>Hvað er alt-texti?</h1> <p>Hjálpartexti eða ALT-myndatexti inniheldur lýsingu á myndefni fyrir fólk með ýmsar gerðir sjónskerðingar, fyrir tengingar með litla bandbreidd, eða til að gefa nánara samhengi fyrir myndefni.</p><p>Þú getur með þessu bætt almennt aðgengi og aukið skilning á efni sem þú birtir með því að skrifa skýran, skorinortan og hlutlægan alt-texta til vara.</p><ul><li>Lýstu mikilvægum atriðum</li>\\n<li>Hafðu yfirlit með þeim texta sem sést í myndum</li><li>Notaðu eðlilega setningaskipan</li><li>Forðastu óþarfar upplýsingar</li><li>Leggðu áherslu á aðalatriði í flóknu myndefni (eins og línuritum eða landakortum)</li></ul>",
|
||||
"interaction_modal.action.favourite": "Til að halda áfram þarftu að setja eitthvað í eftirlæti, verandi inni á aðgangnum þínum.",
|
||||
"interaction_modal.action.follow": "Til að halda áfram þarftu að fylgjast með einhverjum, verandi inni á aðgangnum þínum.",
|
||||
"interaction_modal.action.reblog": "Til að halda áfram þarftu að endurbirta frá einhverjum, verandi inni á aðgangnum þínum.",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"about.blocks": "Server moderati",
|
||||
"about.contact": "Contatto:",
|
||||
"about.contact": "Contatti:",
|
||||
"about.disclaimer": "Mastodon è un software libero e open-source e un marchio di Mastodon gGmbH.",
|
||||
"about.domain_blocks.no_reason_available": "Motivo non disponibile",
|
||||
"about.domain_blocks.preamble": "Mastodon, generalmente, ti consente di visualizzare i contenuti e interagire con gli utenti da qualsiasi altro server nel fediverso. Queste sono le eccezioni che sono state fatte su questo particolare server.",
|
||||
|
@ -39,7 +39,7 @@
|
|||
"account.following_counter": "{count, plural, one {{counter} segui} other {{counter} segui}}",
|
||||
"account.follows.empty": "Questo utente non segue ancora nessuno.",
|
||||
"account.go_to_profile": "Vai al profilo",
|
||||
"account.hide_reblogs": "Nascondi potenziamenti da @{name}",
|
||||
"account.hide_reblogs": "Nascondi condivisioni da @{name}",
|
||||
"account.in_memoriam": "In memoria.",
|
||||
"account.joined_short": "Iscritto",
|
||||
"account.languages": "Modifica le lingue d'iscrizione",
|
||||
|
@ -61,7 +61,7 @@
|
|||
"account.requested": "In attesa d'approvazione. Clicca per annullare la richiesta di seguire",
|
||||
"account.requested_follow": "{name} ha richiesto di seguirti",
|
||||
"account.share": "Condividi il profilo di @{name}",
|
||||
"account.show_reblogs": "Mostra potenziamenti da @{name}",
|
||||
"account.show_reblogs": "Mostra condivisioni da @{name}",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} post} other {{counter} post}}",
|
||||
"account.unblock": "Sblocca @{name}",
|
||||
"account.unblock_domain": "Sblocca il dominio {domain}",
|
||||
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ignorare le notifiche delle persone che non ti seguono?",
|
||||
"ignore_notifications_modal.not_following_title": "Ignorare le notifiche delle persone che non segui?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignorare le notifiche provenienti da menzioni private indesiderate?",
|
||||
"info_button.label": "Aiuto",
|
||||
"info_button.what_is_alt_text": "<h1>Cos'è il testo alternativo?</h1> <p>Il testo alternativo fornisce descrizioni delle immagini per le persone con disturbi della vista, connessioni a bassa larghezza di banda o per coloro che cercano un contesto aggiuntivo.</p> <p>È possibile migliorare l'accessibilità e la comprensione per tutti scrivendo un testo alt chiaro, conciso e obiettivo.</p> <ul> <li>Cattura elementi importanti</li> <li>Riassume il testo nelle immagini</li> <li>Usa la struttura delle frasi regolari</li> <li>Evita le informazioni ridondanti</li> <li>Concentrati sulle tendenze e i risultati chiave in immagini complesse (come diagrammi o mappe)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Per continuare, devi aggiungere ai preferiti il tuo account.",
|
||||
"interaction_modal.action.follow": "Per continuare, devi seguire dal tuo account.",
|
||||
"interaction_modal.action.reblog": "Per continuare, devi condividere dal tuo account.",
|
||||
|
@ -696,7 +698,7 @@
|
|||
"privacy.private.short": "Follower",
|
||||
"privacy.public.long": "Chiunque dentro e fuori Mastodon",
|
||||
"privacy.public.short": "Pubblico",
|
||||
"privacy.unlisted.additional": "Si comporta esattamente come pubblico, tranne per il fatto che il post non verrà visualizzato nei feed live o negli hashtag, nell'esplorazione o nella ricerca Mastodon, anche se hai attivato l'attivazione a livello di account.",
|
||||
"privacy.unlisted.additional": "",
|
||||
"privacy.unlisted.long": "Meno fanfare algoritmiche",
|
||||
"privacy.unlisted.short": "Pubblico silenzioso",
|
||||
"privacy_policy.last_updated": "Ultimo aggiornamento {date}",
|
||||
|
|
|
@ -86,6 +86,10 @@
|
|||
"alert.unexpected.message": "不明なエラーが発生しました。",
|
||||
"alert.unexpected.title": "エラー!",
|
||||
"alt_text_badge.title": "代替テキスト",
|
||||
"alt_text_modal.add_alt_text": "代替テキストを追加",
|
||||
"alt_text_modal.cancel": "キャンセル",
|
||||
"alt_text_modal.change_thumbnail": "サムネイルを変更",
|
||||
"alt_text_modal.done": "完了",
|
||||
"announcement.announcement": "お知らせ",
|
||||
"annual_report.summary.archetype.booster": "トレンドハンター",
|
||||
"annual_report.summary.archetype.lurker": "ROM専",
|
||||
|
@ -407,6 +411,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "本当に「フォローされていないアカウントからの通知」を無視するようにしますか?",
|
||||
"ignore_notifications_modal.not_following_title": "本当に「フォローしていないアカウントからの通知」を無視するようにしますか?",
|
||||
"ignore_notifications_modal.private_mentions_title": "本当に「外部からの非公開の返信」を無視するようにしますか?",
|
||||
"info_button.label": "ヘルプ",
|
||||
"info_button.what_is_alt_text": "<h1>代替テキストとは何ですか?</h1> <p>代替テキストは、視覚障害、低速ネットワーク接続の人や追加コンテンツを求める人に役立つ画像説明です。</p> <p>明確、簡潔、客観的に記述することでアクセシビリティが向上し、より多くの人に理解されるようになります。</p> <ul> <li>要点をとらえる</li> <li>画像内のテキストを要約する</li> <li>平易な文章で説明する</li> <li>情報の重複を避ける</li> <li>複雑な内容 (図や地図など) では傾向やポイントを見つける</li> </ul>",
|
||||
"interaction_modal.action.favourite": "お気に入り登録はあなたのアカウントがあるサーバーで行う必要があります。",
|
||||
"interaction_modal.action.follow": "ユーザーをフォローするには、あなたのアカウントがあるサーバーからフォローする必要があります。",
|
||||
"interaction_modal.action.reblog": "投稿をブーストするには、あなたのアカウントがあるサーバーでブーストする必要があります。",
|
||||
|
@ -836,6 +842,7 @@
|
|||
"status.reblogs.empty": "まだ誰もブーストしていません。ブーストされるとここに表示されます。",
|
||||
"status.redraft": "削除して下書きに戻す",
|
||||
"status.remove_bookmark": "ブックマークを削除",
|
||||
"status.remove_favourite": "お気に入りから削除",
|
||||
"status.replied_in_thread": "ほかのユーザーへ",
|
||||
"status.replied_to": "{name}さんへの返信",
|
||||
"status.reply": "返信",
|
||||
|
|
|
@ -74,7 +74,10 @@
|
|||
"alert.unexpected.message": "Yeḍra-d unezri ur netturaǧu ara.",
|
||||
"alert.unexpected.title": "Ayhuh!",
|
||||
"alt_text_badge.title": "Aḍris asegzan",
|
||||
"alt_text_modal.cancel": "Semmet",
|
||||
"alt_text_modal.done": "Immed",
|
||||
"announcement.announcement": "Ulɣu",
|
||||
"annual_report.summary.most_used_hashtag.none": "Ula yiwen",
|
||||
"audio.hide": "Ffer amesli",
|
||||
"block_modal.show_less": "Ssken-d drus",
|
||||
"block_modal.show_more": "Ssken-d ugar",
|
||||
|
@ -100,9 +103,11 @@
|
|||
"column.blocks": "Imiḍanen yettusḥebsen",
|
||||
"column.bookmarks": "Ticraḍ",
|
||||
"column.community": "Tasuddemt tadigant",
|
||||
"column.create_list": "Snulfu-d tabdart",
|
||||
"column.direct": "Tabdarin tusligin",
|
||||
"column.directory": "Inig deg imeɣna",
|
||||
"column.domain_blocks": "Taɣulin yeffren",
|
||||
"column.edit_list": "Ẓreg tabdart",
|
||||
"column.favourites": "Imenyafen",
|
||||
"column.follow_requests": "Isuturen n teḍfeṛt",
|
||||
"column.home": "Agejdan",
|
||||
|
@ -165,6 +170,7 @@
|
|||
"confirmations.unfollow.message": "Tetḥeqqeḍ belli tebɣiḍ ur teṭafaṛeḍ ara {name}?",
|
||||
"content_warning.hide": "Ffer tasuffeɣt",
|
||||
"content_warning.show": "Ssken-d akken tebɣu tili",
|
||||
"content_warning.show_more": "Sken-d ugar",
|
||||
"conversation.delete": "Kkes adiwenni",
|
||||
"conversation.mark_as_read": "Creḍ yettwaɣṛa",
|
||||
"conversation.open": "Ssken adiwenni",
|
||||
|
@ -325,11 +331,20 @@
|
|||
"link_preview.author": "S-ɣur {name}",
|
||||
"link_preview.more_from_author": "Ugar sɣur {name}",
|
||||
"link_preview.shares": "{count, plural, one {{counter} n tsuffeɣt} other {{counter} n tsuffaɣ}}",
|
||||
"lists.add_member": "Rnu",
|
||||
"lists.add_to_list": "Rnu ɣer tebdart",
|
||||
"lists.add_to_lists": "Rnu {name} ɣer tebdarin",
|
||||
"lists.create": "Snulfu-d",
|
||||
"lists.delete": "Kkes tabdart",
|
||||
"lists.edit": "Ẓreg tabdart",
|
||||
"lists.list_name": "Isem n tebdart",
|
||||
"lists.new_list_name": "Isem n tebdart tamaynut",
|
||||
"lists.remove_member": "Kkes",
|
||||
"lists.replies_policy.followed": "Kra n useqdac i yettwaḍefren",
|
||||
"lists.replies_policy.list": "Iɛeggalen n tebdart",
|
||||
"lists.replies_policy.none": "Ula yiwen·t",
|
||||
"lists.save": "Sekles",
|
||||
"lists.search": "Nadi",
|
||||
"load_pending": "{count, plural, one {# n uferdis amaynut} other {# n yiferdisen imaynuten}}",
|
||||
"loading_indicator.label": "Yessalay-d …",
|
||||
"media_gallery.hide": "Seggelmes",
|
||||
|
@ -399,6 +414,7 @@
|
|||
"notifications.column_settings.filter_bar.category": "Iri n usizdeg uzrib",
|
||||
"notifications.column_settings.follow": "Imeḍfaṛen imaynuten:",
|
||||
"notifications.column_settings.follow_request": "Isuturen imaynuten n teḍfeṛt:",
|
||||
"notifications.column_settings.group": "Agraw",
|
||||
"notifications.column_settings.mention": "Abdar:",
|
||||
"notifications.column_settings.poll": "Igemmaḍ n usenqed:",
|
||||
"notifications.column_settings.push": "Alɣuten yettudemmren",
|
||||
|
@ -429,6 +445,9 @@
|
|||
"notifications.policy.filter_private_mentions_title": "Abdar uslig ur yettwasferken ara",
|
||||
"notifications_permission_banner.enable": "Rmed alɣuten n tnarit",
|
||||
"notifications_permission_banner.title": "Ur zeggel acemma",
|
||||
"onboarding.follows.back": "Uɣal",
|
||||
"onboarding.follows.done": "Immed",
|
||||
"onboarding.follows.search": "Nadi",
|
||||
"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",
|
||||
|
@ -524,6 +543,7 @@
|
|||
"search_results.accounts": "Imeɣna",
|
||||
"search_results.all": "Akk",
|
||||
"search_results.hashtags": "Ihacṭagen",
|
||||
"search_results.no_results": "Ulac igemmaḍ.",
|
||||
"search_results.see_all": "Wali-ten akk",
|
||||
"search_results.statuses": "Tisuffaɣ",
|
||||
"server_banner.active_users": "iseqdacen urmiden",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "예상하지 못한 에러가 발생했습니다.",
|
||||
"alert.unexpected.title": "앗!",
|
||||
"alt_text_badge.title": "대체 문구",
|
||||
"alt_text_modal.add_alt_text": "대체 텍스트 추가",
|
||||
"alt_text_modal.add_text_from_image": "이미지에서 텍스트 추가",
|
||||
"alt_text_modal.cancel": "취소",
|
||||
"alt_text_modal.change_thumbnail": "썸네일 변경",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "청력 장애가 있는 사람들을 위한 설명을 작성하세요…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "시각 장애가 있는 사람들을 위한 설명을 작성하세요…",
|
||||
"alt_text_modal.done": "완료",
|
||||
"announcement.announcement": "공지사항",
|
||||
"annual_report.summary.archetype.booster": "연쇄부스트마",
|
||||
"annual_report.summary.archetype.lurker": "은둔자",
|
||||
|
@ -407,6 +414,13 @@
|
|||
"ignore_notifications_modal.not_followers_title": "나를 팔로우하지 않는 사람들의 알림을 무시할까요?",
|
||||
"ignore_notifications_modal.not_following_title": "내가 팔로우하지 않는 사람들의 알림을 무시할까요?",
|
||||
"ignore_notifications_modal.private_mentions_title": "요청하지 않은 개인 멘션 알림을 무시할까요?",
|
||||
"interaction_modal.action.favourite": "계속하려면 내 계정으로 즐겨찾기해야 합니다.",
|
||||
"interaction_modal.action.follow": "계속하려면 내 계정으로 팔로우해야 합니다.",
|
||||
"interaction_modal.action.reblog": "계속하려면 내 계정으로 리블로그해야 합니다.",
|
||||
"interaction_modal.action.reply": "계속하려면 내 계정으로 답장해야 합니다.",
|
||||
"interaction_modal.action.vote": "계속하려면 내 계정으로 투표해야 합니다.",
|
||||
"interaction_modal.go": "이동",
|
||||
"interaction_modal.no_account_yet": "아직 계정이 없나요?",
|
||||
"interaction_modal.on_another_server": "다른 서버에",
|
||||
"interaction_modal.on_this_server": "이 서버에서",
|
||||
"interaction_modal.title.favourite": "{name} 님의 게시물을 좋아하기",
|
||||
|
@ -830,6 +844,7 @@
|
|||
"status.reblogs.empty": "아직 아무도 이 게시물을 부스트하지 않았습니다. 부스트 한 사람들이 여기에 표시 됩니다.",
|
||||
"status.redraft": "지우고 다시 쓰기",
|
||||
"status.remove_bookmark": "북마크 삭제",
|
||||
"status.remove_favourite": "즐겨찾기에서 제거",
|
||||
"status.replied_in_thread": "글타래에 답장",
|
||||
"status.replied_to": "{name} 님에게",
|
||||
"status.reply": "답장",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "Įvyko netikėta klaida.",
|
||||
"alert.unexpected.title": "Ups!",
|
||||
"alt_text_badge.title": "Alternatyvus tekstas",
|
||||
"alt_text_modal.add_alt_text": "Pridėti alternatyvųjį tekstą",
|
||||
"alt_text_modal.add_text_from_image": "Pridėti tekstą iš vaizdo",
|
||||
"alt_text_modal.cancel": "Atšaukti",
|
||||
"alt_text_modal.change_thumbnail": "Keisti miniatiūrą",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Aprašykite tai klausos negalią turintiems asmenims…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Aprašykite tai regos sutrikimų turintiems asmenims…",
|
||||
"alt_text_modal.done": "Atlikta",
|
||||
"announcement.announcement": "Skelbimas",
|
||||
"annual_report.summary.archetype.booster": "Šaunus medžiotojas",
|
||||
"annual_report.summary.archetype.lurker": "Stebėtojas",
|
||||
|
@ -287,7 +294,7 @@
|
|||
"empty_column.community": "Vietinė laiko skalė yra tuščia. Parašyk ką nors viešai, kad pradėtum sąveikauti.",
|
||||
"empty_column.direct": "Dar neturi jokių privačių paminėjimų. Kai išsiųsi arba gausi vieną iš jų, jis bus rodomas čia.",
|
||||
"empty_column.domain_blocks": "Kol kas nėra užblokuotų serverių.",
|
||||
"empty_column.explore_statuses": "Šiuo metu niekas nėra tendencinga. Patikrink vėliau!",
|
||||
"empty_column.explore_statuses": "Šiuo metu niekas nėra tendencinga. Patikrinkite vėliau!",
|
||||
"empty_column.favourited_statuses": "Dar neturi mėgstamų įrašų. Kai vieną iš jų pamėgsi, jis bus rodomas čia.",
|
||||
"empty_column.favourites": "Šio įrašo dar niekas nepamėgo. Kai kas nors tai padarys, jie bus rodomi čia.",
|
||||
"empty_column.follow_requests": "Dar neturi jokių sekimo prašymų. Kai gausi tokį prašymą, jis bus rodomas čia.",
|
||||
|
@ -403,6 +410,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ignoruoti pranešimus iš žmonių, kurie tave neseka?",
|
||||
"ignore_notifications_modal.not_following_title": "Ignoruoti pranešimus iš žmonių, kuriuos neseki?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignoruoti pranešimus iš neprašytų privačių paminėjimų?",
|
||||
"info_button.label": "Žinynas",
|
||||
"info_button.what_is_alt_text": "<h1>Kas yra alternatyvusis tekstas?</h1> <p>Alternatyvusis tekstas pateikia vaizdų aprašymus asmenims su regos sutrikimais, turintiems mažo pralaidumo ryšį arba ieškantiems papildomo konteksto.</p> <p>Galite pagerinti prieinamumą ir suprantamumą visiems, jei parašysite aiškų, glaustą ir objektyvų alternatyvųjį tekstą.</p> <ul> <li>Užfiksuokite svarbiausius elementus.</li> <li>Apibendrinkite tekstą vaizduose.</li> <li>Naudokite įprasta sakinio struktūrą.</li> <li>Venkite nereikalingos informacijos.</li> <li>Sutelkite dėmesį į tendencijas ir pagrindines išvadas sudėtinguose vaizdiniuose (tokiuose kaip diagramos ar žemėlapiai).</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Kad tęstumėte, turite pamėgti iš savo paskyros.",
|
||||
"interaction_modal.action.follow": "Kad tęstumėte, turite sekti iš savo paskyros.",
|
||||
"interaction_modal.action.reblog": "Kad tęstumėte, turite pasidalinti iš savo paskyros.",
|
||||
|
@ -707,7 +716,7 @@
|
|||
"report.categories.violation": "Turinys pažeidžia vieną ar daugiau serverio taisyklių",
|
||||
"report.category.subtitle": "Pasirink geriausią atitikmenį.",
|
||||
"report.category.title": "Papasakok mums, kas vyksta su šiuo {type}",
|
||||
"report.category.title_account": "profilis",
|
||||
"report.category.title_account": "profiliu",
|
||||
"report.category.title_status": "įrašas",
|
||||
"report.close": "Atlikta",
|
||||
"report.comment.title": "Ar yra dar kas nors, ką, tavo manymu, turėtume žinoti?",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Meldingen negeren van mensen die jou niet volgen?",
|
||||
"ignore_notifications_modal.not_following_title": "Meldingen negeren van mensen die je niet volgt?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Meldingen negeren van ongevraagde privéberichten?",
|
||||
"info_button.label": "Help",
|
||||
"info_button.what_is_alt_text": "<h1>Wat is alt-tekst?</h1> <p>Alt-tekst biedt beschrijvingen van afbeeldingen voor mensen met een visuele beperking, voor verbindingen met lage internetsnelheid of mensen die op zoek zijn naar extra context.</p> <p>Je kunt de toegankelijkheid en de begrijpelijkheid voor iedereen verbeteren door heldere, beknopte en objectieve alt-teksten te schrijven.</p> <ul> <li>Leg belangrijke elementen vast</li> <li>Tekst in afbeeldingen samenvatten</li> <li>Een eenvoudige zinsbouw gebruiken</li> <li>Overbodige informatie vermijden</li> <li>Voor complexe diagrammen of kaarten alleen op trends en belangrijke bevindingen focussen</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Om verder te gaan, moet je vanaf je eigen account als favoriet markeren.",
|
||||
"interaction_modal.action.follow": "Om verder te gaan, moet je vanaf je eigen account volgen.",
|
||||
"interaction_modal.action.reblog": "Om verder te gaan, moet je vanaf je eigen account boosten.",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "Wystąpił nieoczekiwany błąd.",
|
||||
"alert.unexpected.title": "Ups!",
|
||||
"alt_text_badge.title": "Tekst alternatywny",
|
||||
"alt_text_modal.add_alt_text": "Dodaj tekst alternatywny",
|
||||
"alt_text_modal.add_text_from_image": "Dodaj tekst z obrazu",
|
||||
"alt_text_modal.cancel": "Anuluj",
|
||||
"alt_text_modal.change_thumbnail": "Zmień miniaturę",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Opisz to dla osób z wadą słuchu…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Opisz to dla osób z wadą wzroku…",
|
||||
"alt_text_modal.done": "Gotowe",
|
||||
"announcement.announcement": "Ogłoszenie",
|
||||
"annual_report.summary.archetype.booster": "Łowca treści",
|
||||
"annual_report.summary.archetype.lurker": "Czyhający",
|
||||
|
@ -103,6 +110,7 @@
|
|||
"annual_report.summary.most_used_hashtag.most_used_hashtag": "najczęściej używany hashtag",
|
||||
"annual_report.summary.most_used_hashtag.none": "Brak",
|
||||
"annual_report.summary.new_posts.new_posts": "nowe wpisy",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Plasuje Cię w czołówce</topLabel><percentage></percentage><bottomLabel> użytkowników {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "Nie powiemy Berniemu.",
|
||||
"annual_report.summary.thanks": "Dziękujemy, że jesteś częścią Mastodona!",
|
||||
"attachments_list.unprocessed": "(nieprzetworzone)",
|
||||
|
@ -408,6 +416,10 @@
|
|||
"ignore_notifications_modal.private_mentions_title": "Ignoruj powiadomienia o nieproszonych wzmiankach prywatnych?",
|
||||
"interaction_modal.action.favourite": "Aby kontynuować, musisz dodać do ulubionych na swoim koncie.",
|
||||
"interaction_modal.action.follow": "Aby kontynuować, musisz obserwować ze swojego konta.",
|
||||
"interaction_modal.action.reblog": "Aby kontynuować, musisz podać dalej ze swojego konta.",
|
||||
"interaction_modal.action.reply": "Aby kontynuować, musisz odpowiedzieć ze swojego konta.",
|
||||
"interaction_modal.action.vote": "Aby kontynuować, musisz zagłosować ze swojego konta.",
|
||||
"interaction_modal.go": "Dalej",
|
||||
"interaction_modal.no_account_yet": "Nie masz jeszcze konta?",
|
||||
"interaction_modal.on_another_server": "Na innym serwerze",
|
||||
"interaction_modal.on_this_server": "Na tym serwerze",
|
||||
|
@ -452,6 +464,7 @@
|
|||
"keyboard_shortcuts.toggle_hidden": "aby wyświetlić lub ukryć wpis spod CW",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Pokaż/ukryj multimedia",
|
||||
"keyboard_shortcuts.toot": "Stwórz nowy post",
|
||||
"keyboard_shortcuts.translate": "Aby przetłumaczyć post",
|
||||
"keyboard_shortcuts.unfocus": "aby opuścić pole wyszukiwania/pisania",
|
||||
"keyboard_shortcuts.up": "aby przejść na górę listy",
|
||||
"lightbox.close": "Zamknij",
|
||||
|
@ -690,6 +703,8 @@
|
|||
"privacy_policy.title": "Polityka prywatności",
|
||||
"recommended": "Zalecane",
|
||||
"refresh": "Odśwież",
|
||||
"regeneration_indicator.please_stand_by": "Proszę czekać.",
|
||||
"regeneration_indicator.preparing_your_home_feed": "Przygotowywanie Twojego kanału wiadomości...",
|
||||
"relative_time.days": "{number} dni",
|
||||
"relative_time.full.days": "{number, plural, one {# dzień} few {# dni} many {# dni} other {# dni}} temu",
|
||||
"relative_time.full.hours": "{number, plural, one {# godzinę} few {# godziny} many {# godzin} other {# godzin}} temu",
|
||||
|
|
|
@ -414,9 +414,11 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ignorar notificações de pessoas que não te seguem?",
|
||||
"ignore_notifications_modal.not_following_title": "Ignorar notificações de pessoas que não segues?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ignorar notificações de menções privadas não solicitadas?",
|
||||
"info_button.label": "Ajuda",
|
||||
"info_button.what_is_alt_text": "<h1>O que é texto alternativo?</h1> <p>O texto alternativo fornece descrições de imagens para pessoas com deficiências visuais, conexões de baixa largura de banda ou pessoas que procuram um contexto adicional.</p> <p>Podes melhorar a acessibilidade e a compreensão para todos escrevendo um texto alternativo claro, conciso e objetivo.</p> <ul> <li>Capta elementos importantes</li> <li>Resume o texto que aparece nas imagens</li> <li>Usa uma estrutura de frase regular</li> <li>Evita informações redundantes</li> <li>Centra-te nas tendências e nas principais conclusões em imagens complexas (como diagramas ou mapas)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Para continuar, tens de adicionar um favorito na tua conta.",
|
||||
"interaction_modal.action.follow": "Para continuar, tens de seguir alguém na tua conta.",
|
||||
"interaction_modal.action.reblog": "Para continuar, tens de fazer uma republicação na tua conta.",
|
||||
"interaction_modal.action.reblog": "Para continuar, tens de impulsionar desde a tua conta.",
|
||||
"interaction_modal.action.reply": "Para continuar, tens de fazer uma resposta na tua conta.",
|
||||
"interaction_modal.action.vote": "Para continuar é necessário votar a partir da tua conta.",
|
||||
"interaction_modal.go": "Ir",
|
||||
|
|
|
@ -409,6 +409,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Të shpërfillen njoftime nga persona që s’ju ndjekin?",
|
||||
"ignore_notifications_modal.not_following_title": "Të shpërfillen njoftime nga persona që s’i ndiqni?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Të shpërfillen njoftime nga Përmendje Private të pakërkuara?",
|
||||
"info_button.label": "Ndihmë",
|
||||
"info_button.what_is_alt_text": "<h1>Ç’është teksti alternativ?</h1> <p>Teksti alternativ jep përshkrime figurash për persona me mangësi në të parët, lidhje me gjerësi bande të ulët, ose për ata që duan kontekst shtesë.</p> <p>Mund të përmirësoni përdorimin nga persona me aftësi të kufizuara dhe kuptimin për këto, duke shkruar tekst alternativ të qartë, konciz dhe objektiv.</p> <ul> <li>Rrokni elementët e rëndësishëm</li> <li>Përmblidhni tekst në figura</li> <li>Përdorni strukturë të rregullt fjalish</li> <li>Shmangni përsëritje informacioni</li> <li>Në aspekte pamore të ndërlikuara (fjala vjen, diagrame ose harta) përqendrohuni te prirje dhe gjetje gjërash kyçe</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Që të vazhdoni, lypset t’i vini shenjë si i parapëlqyer që nga llogaria juaj.",
|
||||
"interaction_modal.action.follow": "Që të vazhdoni, lypset ta ndiqni që nga llogaria juaj.",
|
||||
"interaction_modal.action.reblog": "Që të vazhdoni, lypset ta riblogoni që nga llogaria juaj.",
|
||||
|
|
|
@ -523,7 +523,7 @@
|
|||
"navigation_bar.favourites": "Favoriter",
|
||||
"navigation_bar.filters": "Tystade ord",
|
||||
"navigation_bar.follow_requests": "Följförfrågningar",
|
||||
"navigation_bar.followed_tags": "Utvalda hashtags",
|
||||
"navigation_bar.followed_tags": "Följda hashtaggar",
|
||||
"navigation_bar.follows_and_followers": "Följer och följare",
|
||||
"navigation_bar.lists": "Listor",
|
||||
"navigation_bar.logout": "Logga ut",
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"about.blocks": "ma lawa",
|
||||
"about.contact": "toki:",
|
||||
"about.disclaimer": "ilo Masoton la, jan ale li ken kama jo e ona kepeken mani ala, li ken ante e toki ilo ona. kulupu esun Mastodon li jo e nimi ona. kulupu esun Mastodon li nasin lawa gGmbH.",
|
||||
"about.disclaimer": "ilo Masoton la jan ale li lawa e ona li pana e pona tawa ona. kulupu esun Mastodon gGmbH li lawa e nimi ona.",
|
||||
"about.domain_blocks.no_reason_available": "mi sona ala e tan",
|
||||
"about.domain_blocks.preamble": "ilo Masoton li ken e ni: sina lukin e toki jan pi ma ilo mute. sina ken toki tawa ona lon kulupu ma. taso, ma ni li ken ala e ni tawa ma ni:",
|
||||
"about.domain_blocks.silenced.explanation": "sina lukin ala e toki e jan tan ma ni. taso, sina wile la, sina ken ni.",
|
||||
"about.domain_blocks.silenced.title": "ken lili lukin",
|
||||
"about.domain_blocks.silenced.title": "ken lukin lili ",
|
||||
"about.domain_blocks.suspended.explanation": "sona ale pi ma ni li kama pali ala, li kama esun ala, li kama awen ala la sina ken ala toki tawa jan pi ma ni.",
|
||||
"about.domain_blocks.suspended.title": "weka",
|
||||
"about.not_available": "lon kulupu ni la sina ken alasa ala e sona ni.",
|
||||
"about.powered_by": "lipu kulupu pi jan lawa mute tan {mastodon}",
|
||||
|
@ -18,7 +19,7 @@
|
|||
"account.block_domain": "o weka e ma {domain}",
|
||||
"account.block_short": "o weka e jan tawa mi",
|
||||
"account.blocked": "jan li weka tawa mi",
|
||||
"account.cancel_follow_request": "o pini kute",
|
||||
"account.cancel_follow_request": "o kute ala",
|
||||
"account.copy": "o pali same e linja pi lipu jan",
|
||||
"account.direct": "len la o mu e @{name}",
|
||||
"account.disable_notifications": "@{name} li toki la o mu ala e mi",
|
||||
|
@ -50,74 +51,95 @@
|
|||
"account.mute": "o len e @{name}",
|
||||
"account.mute_notifications_short": "o kute ala e mu tan jan ni",
|
||||
"account.mute_short": "o kute ala",
|
||||
"account.muted": "sina len e jan ni",
|
||||
"account.muted": "sina kute ala e jan ni",
|
||||
"account.mutual": "jan pona sona",
|
||||
"account.no_bio": "lipu li weka",
|
||||
"account.no_bio": "lipu li weka.",
|
||||
"account.open_original_page": "o open e lipu open",
|
||||
"account.posts": "toki suli",
|
||||
"account.posts_with_replies": "toki ale",
|
||||
"account.report": "jan @{name} la o toki tawa lawa",
|
||||
"account.requested": "jan ni o ken e kute sina. sina pini wile kute la o luka e ni",
|
||||
"account.requested_follow": "{name} li wile kute e sina",
|
||||
"account.report": "jan @{name} la o toki e ike tawa lawa",
|
||||
"account.requested": "jan ni o ken e kute sina",
|
||||
"account.requested_follow": "jan {name} li wile kute e sina",
|
||||
"account.share": "o pana e lipu jan @{name}",
|
||||
"account.show_reblogs": "o lukin e pana toki tan @{name}",
|
||||
"account.statuses_counter": "{count, plural, other {toki {counter}}}",
|
||||
"account.unblock": "o weka ala e jan {name}",
|
||||
"account.unblock_domain": "o weka ala e ma {domain}",
|
||||
"account.unblock_short": "o pini weka",
|
||||
"account.unblock_short": "o weka ala",
|
||||
"account.unendorse": "lipu jan la o suli ala e ni",
|
||||
"account.unfollow": "o pini kute",
|
||||
"account.unfollow": "o kute ala",
|
||||
"account.unmute": "o len ala e @{name}",
|
||||
"account.unmute_notifications_short": "o kute e mu tan jan ni",
|
||||
"account.unmute_short": "o len ala",
|
||||
"account_note.placeholder": "o luka e ni la sona pi sina taso",
|
||||
"admin.dashboard.daily_retention": "nanpa pi awen jan lon tenpo suno",
|
||||
"admin.dashboard.monthly_retention": "nanpa pi awen jan lon tenpo mun",
|
||||
"admin.dashboard.retention.average": "sama",
|
||||
"admin.dashboard.retention.cohort": "tenpo mun open",
|
||||
"admin.dashboard.retention.cohort_size": "jan sin",
|
||||
"admin.impact_report.instance_accounts": "ni li pakala li weka e lipu jan ni",
|
||||
"admin.impact_report.instance_followers": "jan pi ma mi li weka tan jan kute ni",
|
||||
"admin.impact_report.instance_follows": "ma ante li weka tan jan kute ni",
|
||||
"admin.impact_report.title": "sona pi pakala kulupu",
|
||||
"alert.rate_limited.message": "tenpo {retry_time, time, medium} la o pali awen",
|
||||
"alert.rate_limited.title": "ilo ni li lili e ken sina",
|
||||
"alert.unexpected.message": "pakala li lon",
|
||||
"alert.unexpected.title": "pakala a!",
|
||||
"alt_text_badge.title": "toki sona sitelen",
|
||||
"alt_text_modal.add_alt_text": "o pana e toki pi sona lukin",
|
||||
"alt_text_modal.add_text_from_image": "o kama jo e toki sitelen tan sitelen ni",
|
||||
"alt_text_modal.cancel": "weka",
|
||||
"alt_text_modal.change_thumbnail": "o ante e sitelen lili",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "jan li ken ala kute la o pana e toki pi sona kalama…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "jan li ken ala lukin la o pana e toki pi sona lukin…",
|
||||
"alt_text_modal.done": "pini",
|
||||
"announcement.announcement": "toki suli",
|
||||
"annual_report.summary.archetype.booster": "jan ni li alasa e pona",
|
||||
"annual_report.summary.archetype.lurker": "jan ni li lukin taso",
|
||||
"annual_report.summary.archetype.oracle": "jan ni li sona suli",
|
||||
"annual_report.summary.archetype.pollster": "jan ni li wile sona e pilin jan",
|
||||
"annual_report.summary.archetype.replier": "jan ni li toki tawa jan mute",
|
||||
"annual_report.summary.followers.followers": "jan kute sina",
|
||||
"annual_report.summary.followers.total": "ale la {count}",
|
||||
"annual_report.summary.here_it_is": "toki lili la tenpo sike nanpa {year} li sama ni tawa sina:",
|
||||
"annual_report.summary.highlighted_post.by_favourites": "toki pi olin nanpa wan",
|
||||
"annual_report.summary.highlighted_post.by_reblogs": "toki pi sike nanpa wan",
|
||||
"annual_report.summary.highlighted_post.by_replies": "toki li jo e toki kama pi nanpa wan",
|
||||
"annual_report.summary.highlighted_post.possessive": "tan jan {name}",
|
||||
"annual_report.summary.most_used_hashtag.none": "ala",
|
||||
"annual_report.summary.new_posts.new_posts": "toki suli sin",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "mi toki ala e ni tawa jan Peni.",
|
||||
"annual_report.summary.percentile.text": "<topLabel>ni la sina nanpa sewi</topLabel><percentage></percentage><bottomLabel>pi jan ale lon {domain}.</bottomLabel>",
|
||||
"annual_report.summary.percentile.we_wont_tell_bernie": "sona ni li len tawa ale.",
|
||||
"annual_report.summary.thanks": "sina jan pi kulupu Masoton la sina pona a!",
|
||||
"attachments_list.unprocessed": "(nasin open)",
|
||||
"audio.hide": "o len e kalama",
|
||||
"block_modal.remote_users_caveat": "mi pana e wile sina tawa ma {domain}. taso, o sona: ma li ken kepeken nasin len ante la pakala li ken lon. toki pi lukin ale la jan pi ma ala li ken lukin.",
|
||||
"block_modal.show_less": "o lili e lukin",
|
||||
"block_modal.show_more": "o mute e lukin",
|
||||
"block_modal.they_cant_mention": "ona li ken ala toki e sina li ken ala alasa e sina",
|
||||
"block_modal.show_more": "o suli e lukin",
|
||||
"block_modal.they_cant_mention": "ona li ken ala toki tawa sina li ken ala kute e sina.",
|
||||
"block_modal.they_cant_see_posts": "ona li ken ala lukin e toki sina. sina ken ala lukin e toki ona.",
|
||||
"block_modal.they_will_know": "ona li sona e ni: sina ala e lukin ona.",
|
||||
"block_modal.they_will_know": "ona li sona e ni: sina weka e lukin ona.",
|
||||
"block_modal.title": "o weka ala weka e jan",
|
||||
"block_modal.you_wont_see_mentions": "nimi ona li lon toki suli la sina lukin ala e toki ni.",
|
||||
"block_modal.you_wont_see_mentions": "jan li toki e nimi ona la sina lukin ala e toki ni.",
|
||||
"boost_modal.combo": "sina ken luka e nena {combo} tawa ni: sina wile ala luka e nena lon tenpo kama",
|
||||
"boost_modal.reblog": "o wawa ala wawa e toki?",
|
||||
"boost_modal.undo_reblog": "o pini ala pini e wawa toki?",
|
||||
"boost_modal.undo_reblog": "o weka ala weka e wawa toki?",
|
||||
"bundle_column_error.copy_stacktrace": "o awen e sona pakala lon ilo sina",
|
||||
"bundle_column_error.error.body": "ilo li ken ala pana e lipu ni. ni li ken tan pakala ilo.",
|
||||
"bundle_column_error.error.title": "ike a!",
|
||||
"bundle_column_error.error.title": "pakala a!",
|
||||
"bundle_column_error.network.body": "mi lukin pana e lipu la, pakala li lon. ken la, pakala li tan ilo nanpa sina. ken la, pakala li tan ilo nanpa suli pi ma kulupu ni.",
|
||||
"bundle_column_error.network.title": "pakala la ilo sina li toki ala tawa ilo ante",
|
||||
"bundle_column_error.retry": "o ni sin",
|
||||
"bundle_column_error.return": "o tawa tomo",
|
||||
"bundle_column_error.retry": "o alasa sin",
|
||||
"bundle_column_error.return": "o tawa open",
|
||||
"bundle_column_error.routing.body": "ilo li sona ala e lipu wile. sina pana ala pana e nasin pona tawa lipu?",
|
||||
"bundle_column_error.routing.title": "pakala nanpa 404",
|
||||
"bundle_modal_error.close": "o pini",
|
||||
"bundle_modal_error.message": "ilo li wile kama e ijo ni, taso pakala li lon.",
|
||||
"bundle_modal_error.retry": "o ni sin",
|
||||
"closed_registrations.other_server_instructions": "kulupu Masoton li jo e jan lawa mute, la sina ken pali e sijelo lon ma ante, li ken lukin e ijo pi ma ni.",
|
||||
"bundle_modal_error.retry": "o alasa sin",
|
||||
"closed_registrations.other_server_instructions": "kulupu Masoton la lawa mute li lon. sina ken pali e sijelo lon ma ante la sina awen ken lukin e ijo pi ma ni.",
|
||||
"closed_registrations_modal.description": "tenpo ni la, sina ken ala pali e jan lon ma {domain}. taso sina wile kepeken ilo Masoton la, sina ken pali e jan lon ma ante lon ala ma {domain}.",
|
||||
"closed_registrations_modal.find_another_server": "o alasa e ma ante",
|
||||
"closed_registrations_modal.preamble": "ilo Masoton li lon ilo wan ala. sina kepeken ma ante la sina ken lukin li ken kute e jan pi ma ni. sina wile la, sina ken pali e ma sin!",
|
||||
"closed_registrations_modal.title": "sina kama lon kulupu Masoton",
|
||||
"column.about": "sona",
|
||||
"column.blocks": "kulupu pi jan weka",
|
||||
|
@ -137,8 +159,11 @@
|
|||
"column.mutes": "jan len",
|
||||
"column.notifications": "mu pi sona sin",
|
||||
"column.pins": "toki sewi",
|
||||
"column.public": "toki pi ma poka ale",
|
||||
"column_back_button.label": "o tawa monsi",
|
||||
"column_header.hide_settings": "o len e lawa",
|
||||
"column_header.moveLeft_settings": "poki toki ni o tawa ni ←",
|
||||
"column_header.moveRight_settings": "poki toki ni o tawa ni →",
|
||||
"column_header.pin": "o sewi",
|
||||
"column_header.show_settings": "o lukin e lawa",
|
||||
"column_header.unpin": "o sewi ala",
|
||||
|
@ -154,6 +179,8 @@
|
|||
"compose.saved.body": "ilo li awen e ijo pana sina.",
|
||||
"compose_form.direct_message_warning_learn_more": "o kama sona e ijo ante",
|
||||
"compose_form.encryption_warning": "toki li len ala lon ilo Masoton ꞏ o pana ala e sona suli len lon ilo Masoton",
|
||||
"compose_form.lock_disclaimer": "lipu sina li open, li {locked} ala. jan ale li ken kama kute e sina, li ken lukin e toki sama ni.",
|
||||
"compose_form.lock_disclaimer.lock": "pini",
|
||||
"compose_form.placeholder": "sina wile toki e seme?",
|
||||
"compose_form.poll.duration": "tenpo pana",
|
||||
"compose_form.poll.multiple": "pana mute",
|
||||
|
@ -169,7 +196,7 @@
|
|||
"compose_form.spoiler.marked": "o weka e toki pi ijo ike ken",
|
||||
"compose_form.spoiler.unmarked": "o pali e toki pi ijo ike ken",
|
||||
"compose_form.spoiler_placeholder": "toki pi ijo ike ken (sina ken ala e ni)",
|
||||
"confirmation_modal.cancel": "o pini",
|
||||
"confirmation_modal.cancel": "o weka",
|
||||
"confirmations.block.confirm": "o weka",
|
||||
"confirmations.delete.confirm": "o weka",
|
||||
"confirmations.delete.message": "sina wile ala wile weka e toki ni?",
|
||||
|
@ -182,22 +209,31 @@
|
|||
"confirmations.edit.confirm": "o ante",
|
||||
"confirmations.edit.message": "sina ante e toki sina la toki pali sina li weka. sina wile ala wile e ni?",
|
||||
"confirmations.edit.title": "o weka ala weka e toki? ni la, toki li kama toki sin.",
|
||||
"confirmations.follow_to_list.confirm": "o kute, o pana tawa lipu jan",
|
||||
"confirmations.follow_to_list.message": "sina wile pana e {name} tawa lipu jan la o kama kute e ona.",
|
||||
"confirmations.follow_to_list.title": "sina wile ala wile kute?",
|
||||
"confirmations.logout.confirm": "o weka",
|
||||
"confirmations.logout.message": "sina wile ala wile weka",
|
||||
"confirmations.logout.title": "o weka?",
|
||||
"confirmations.mute.confirm": "o len",
|
||||
"confirmations.redraft.confirm": "o weka o pali sin e toki",
|
||||
"confirmations.redraft.message": "pali sin e toki ni la sina wile ala wile weka e ona? sina ni la suli pi toki ni en wawa pi toki ni li weka. kin la toki lon toki ni li jo e mama ala.",
|
||||
"confirmations.redraft.title": "ni li weka li pali sin e toki ni.",
|
||||
"confirmations.reply.confirm": "toki lon toki ni",
|
||||
"confirmations.reply.message": "sina toki lon toki ni la toki pali sina li weka. sina wile ala wile e ni?",
|
||||
"confirmations.unfollow.confirm": "o pini kute",
|
||||
"confirmations.reply.title": "sina wile ala wile weka e toki lon?",
|
||||
"confirmations.unfollow.confirm": "o kute ala",
|
||||
"confirmations.unfollow.message": "sina o wile ala wile pini kute e jan {name}?",
|
||||
"confirmations.unfollow.title": "sina wile ala wile pini kute?",
|
||||
"content_warning.hide": "o len",
|
||||
"content_warning.show": "o lukin",
|
||||
"content_warning.show_more": "o lukin",
|
||||
"conversation.delete": "o weka e toki ni",
|
||||
"conversation.mark_as_read": "ni o sin ala",
|
||||
"conversation.open": "o lukin e toki",
|
||||
"conversation.with": "lon {names}",
|
||||
"copy_icon_button.copied": "toki li awen lon ilo sina",
|
||||
"copypaste.copied": "sina jo e toki",
|
||||
"copypaste.copy_to_clipboard": "o awen lon ilo sina",
|
||||
"directory.local": "tan {domain} taso",
|
||||
"directory.new_arrivals": "jan pi kama sin",
|
||||
|
@ -206,15 +242,24 @@
|
|||
"disabled_account_banner.text": "sina ken ala kepeken e lipu jan sina pi nimi {disabledAccount}.",
|
||||
"dismissable_banner.community_timeline": "ni li toki pi tenpo poka tawa ale tan jan lon ma lawa pi nimi {domain}.",
|
||||
"dismissable_banner.dismiss": "o weka",
|
||||
"dismissable_banner.explore_links": "tenpo suno ni la jan pi kulupu ale li toki e ijo sin ni. ijo sin pi jan ante mute li sewi lon lipu ni.",
|
||||
"domain_block_modal.block": "o weka e ma",
|
||||
"domain_block_modal.they_wont_know": "ona li sona ala e ni: sina weka e ona.",
|
||||
"domain_block_modal.title": "sina wile weka ala weka e ma?",
|
||||
"domain_block_modal.you_will_lose_num_followers": "{followersCount, plural, other {jan {followersCountDisplay}}} li kute e sina la, ona kama kute ala e sina. sina kute e {followingCount, plural,other {jan {followingCountDisplay}}} la, sina kama kute ala e ona.",
|
||||
"domain_block_modal.you_will_lose_relationships": "jan li lon kulupu ni la ona kute e sina la, ona li kama kute ala e sina. jan li lon kulupu ni la sina kute e ona la, sina kama kute ala e ona.",
|
||||
"domain_block_modal.you_wont_see_posts": "sina ken ala lukin e toki tan jan pi ma ni",
|
||||
"domain_pill.server": "ma",
|
||||
"domain_pill.their_handle": "nimi pi ona taso li ni:",
|
||||
"domain_pill.their_server": "ni li ma ona lon ilo. toki ale ona li lon ma ni.",
|
||||
"domain_pill.their_username": "ni li nimi ona lon ma ni. jan mute li lon ma ante la, nimi ona li ken sama.",
|
||||
"domain_pill.username": "nimi jan",
|
||||
"domain_pill.whats_in_a_handle": "seme li lon nimi?",
|
||||
"domain_pill.who_they_are": "nimi ilo la sona jan en sona ma li lon. ni la sina ken toki tawa jan ni lon <button>kulupu ma ale</button>.",
|
||||
"domain_pill.your_handle": "nimi sina:",
|
||||
"domain_pill.your_server": "ni li ma sina lon ilo. toki ale sina li lon ma ni. ma li ike tawa sina la, sina ken tawa ma ante. ni la jan kute sina li tawa sama.",
|
||||
"domain_pill.your_username": "ni li nimi sina. ma sina la, sina taso li jo e ona. jan mute li lon ma ante la, ona li ken jo e nimi sama.",
|
||||
"embed.instructions": "o pana e toki ni la, toki li lon lipu ante. ",
|
||||
"embed.preview": "ni li jo e sitelen ni:",
|
||||
"emoji_button.activity": "musi",
|
||||
"emoji_button.clear": "o weka",
|
||||
|
@ -225,6 +270,7 @@
|
|||
"emoji_button.not_found": "sitelen pilin ala li lon",
|
||||
"emoji_button.objects": "ijo",
|
||||
"emoji_button.people": "jan",
|
||||
"emoji_button.recent": "kepeken suli",
|
||||
"emoji_button.search": "o alasa...",
|
||||
"emoji_button.search_results": "ijo pi alasa ni",
|
||||
"emoji_button.symbols": "sitelen",
|
||||
|
@ -249,6 +295,7 @@
|
|||
"explore.title": "o alasa",
|
||||
"explore.trending_links": "sin",
|
||||
"explore.trending_statuses": "toki",
|
||||
"explore.trending_tags": "kulupu pi lipu suli",
|
||||
"filter_modal.added.settings_link": "lipu lawa",
|
||||
"filter_modal.select_filter.expired": "tenpo pini",
|
||||
"filter_modal.select_filter.search": "o alasa anu pali",
|
||||
|
@ -277,15 +324,23 @@
|
|||
"hashtag.column_settings.tag_mode.all": "ale ni",
|
||||
"hashtag.column_settings.tag_mode.any": "wan ni",
|
||||
"hashtag.column_settings.tag_mode.none": "ala ni",
|
||||
"hashtag.counter_by_accounts": "{count, plural, other {jan {counter}}}",
|
||||
"hashtag.counter_by_uses": "{count, plural, other {toki {counter}}}",
|
||||
"hashtag.follow": "o kute e kulupu lipu",
|
||||
"hashtag.unfollow": "o kute ala e kulupu lipu",
|
||||
"home.pending_critical_update.link": "o lukin e ijo ilo sin",
|
||||
"info_button.label": "sona",
|
||||
"interaction_modal.go": "o tawa ma ni",
|
||||
"interaction_modal.on_another_server": "lon ma ante",
|
||||
"interaction_modal.on_this_server": "lon ma ni",
|
||||
"interaction_modal.title.favourite": "o suli e toki {name}",
|
||||
"interaction_modal.title.follow": "o kute e {name}",
|
||||
"interaction_modal.title.reblog": "o wawa e toki {name}",
|
||||
"interaction_modal.title.reply": "o toki lon toki pi jan {name}",
|
||||
"interaction_modal.title.vote": "o pana tawa wile sona pi jan {name}",
|
||||
"interaction_modal.username_prompt": "ni li sama ni: {example}",
|
||||
"intervals.full.days": "{number, plural, other {suni #}}",
|
||||
"intervals.full.hours": "{number, plural, other {tenpo suli #}}",
|
||||
"keyboard_shortcuts.blocked": "o lukin e lipu sina pi jan weka",
|
||||
"keyboard_shortcuts.boost": "o pana sin e toki",
|
||||
"keyboard_shortcuts.down": "o tawa anpa lon lipu",
|
||||
|
@ -304,10 +359,17 @@
|
|||
"lightbox.previous": "monsi",
|
||||
"link_preview.author": "tan {name}",
|
||||
"lists.delete": "o weka e kulupu lipu",
|
||||
"lists.done": "ale li pini",
|
||||
"lists.edit": "o ante e kulupu lipu",
|
||||
"lists.list_members_count": "{count, plural, other {jan #}}",
|
||||
"lists.list_name": "nimi kulupu",
|
||||
"lists.new_list_name": "nimi pi kulupu sin",
|
||||
"lists.no_lists_yet": "kulupu li lon ala.",
|
||||
"lists.remove_member": "o weka",
|
||||
"lists.replies_policy.followed": "jan kute ale",
|
||||
"lists.replies_policy.list": "jan pi kulupu ni taso",
|
||||
"lists.replies_policy.none": "jan ala",
|
||||
"lists.search": "o alasa",
|
||||
"load_pending": "{count, plural, other {ijo sin #}}",
|
||||
"loading_indicator.label": "ni li kama…",
|
||||
"mute_modal.title": "sina wile ala wile kute e jan ni?",
|
||||
|
@ -368,7 +430,7 @@
|
|||
"report.category.title": "ike seme li lon {type} ni",
|
||||
"report.category.title_account": "lipu",
|
||||
"report.category.title_status": "toki",
|
||||
"report.close": "o pini",
|
||||
"report.close": "ale li pona",
|
||||
"report.mute": "o kute ala e ona",
|
||||
"report.mute_explanation": "sina kama ala lukin e ijo pana ona. ona li awen ken kute e sina li awen ken lukin e sina li sona ala e weka kute sina e weka lukin sina.",
|
||||
"report.next": "awen",
|
||||
|
@ -377,7 +439,7 @@
|
|||
"report.reasons.other": "ni li ike tan ante",
|
||||
"report.reasons.spam": "ni li ike tan toki mute",
|
||||
"report.thanks.title": "sina wile ala lukin e ni anu seme?",
|
||||
"report.unfollow": "o pini kute e {name}",
|
||||
"report.unfollow": "o kute ala e {name}",
|
||||
"report_notification.categories.legal": "ike tawa nasin lawa",
|
||||
"report_notification.categories.other": "ante",
|
||||
"search.no_recent_searches": "alasa ala li lon tenpo poka",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Takip etmeyen kişilerin bildirimlerini yoksay?",
|
||||
"ignore_notifications_modal.not_following_title": "Takip etmediğin kişilerin bildirimlerini yoksay?",
|
||||
"ignore_notifications_modal.private_mentions_title": "İstenmeyen özel bahsetmelerden gelen bildirimleri yoksay?",
|
||||
"info_button.label": "Yardım",
|
||||
"info_button.what_is_alt_text": "<h1>Alternatif metin nedir?</h1><p>Alternatif metin, görme bozukluğu olan, düşük bant genişliğine sahip bağlantıları olan veya ekstra bağlam arayan kişiler için görsel açıklamaları sağlar.</p><p>Net, sade ve nesnel alternatif metin yazarak herkes için erişilebilirliği ve anlaşılabilirliği iyileştirebilirsiniz.</p><ul><li>Önemlileri yakalayın</li><li>Resimlerdeki metni özetleyin</li><li>Düzenli cümle yapısı kullanın</li><li>Gereksiz bilgilerden kaçının</li><li>Karmaşık görsellerde (şemalar veya haritalar gibi) trendlere ve temel bulgulara odaklanın</li></ul>",
|
||||
"interaction_modal.action.favourite": "Devam etmek için, hesabınızı kullanarak beğenmelisiniz.",
|
||||
"interaction_modal.action.follow": "Devam etmek için, hesabınızı kullanarak takip etmelisiniz.",
|
||||
"interaction_modal.action.reblog": "Devam etmek için, hesabınızı kullanarak tekrar göndermelisiniz.",
|
||||
|
|
|
@ -87,7 +87,11 @@
|
|||
"alert.unexpected.title": "Ой!",
|
||||
"alt_text_badge.title": "Альтернативний текст",
|
||||
"alt_text_modal.add_alt_text": "Додати альтернативний текст",
|
||||
"alt_text_modal.add_text_from_image": "Додати текст із малюнку",
|
||||
"alt_text_modal.cancel": "Скасувати",
|
||||
"alt_text_modal.change_thumbnail": "Змінити мініатюру",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "Опишіть цю ідею для людей із порушеннями слуху…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "Опишіть цю ідею для людей із порушеннями зору…",
|
||||
"alt_text_modal.done": "Готово",
|
||||
"announcement.announcement": "Оголошення",
|
||||
"annual_report.summary.archetype.booster": "Мисливець на дописи",
|
||||
|
@ -410,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "Ігнорувати сповіщення від людей, які не підписані на вас?",
|
||||
"ignore_notifications_modal.not_following_title": "Ігнорувати сповіщення від людей, на яких ви не підписалися?",
|
||||
"ignore_notifications_modal.private_mentions_title": "Ігнорувати сповіщення від небажаних приватних згадок?",
|
||||
"info_button.label": "Довідка",
|
||||
"info_button.what_is_alt_text": "<h1>Що таке альтернативний текст?</h1> <p>Альтернативний текст містить описи зображень для людей з вадами зору, низькошвидкісними з'єднаннями або тих, хто шукає додатковий контекст.</p> <p>Ви можете покращити доступність і розуміння для всіх, написавши чіткий та лаконічний альтернативний текст.</p> <ul> <li>Позначайте важливі елементи</li> <li>Охоплюйте текст у картинках</li> <li>Використовуйте звичайну структуру речень</li> <li>Уникайте надлишкової інформації</li> <li>Зосередьтеся на тенденціях і ключових висновках у складних візуальних формах (наприклад, діаграмах або картах)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "Щоб продовжити, потрібно додати улюблене з вашого облікового запису.",
|
||||
"interaction_modal.action.follow": "Щоб іти далі, потрібно підписатися з вашого облікового запису.",
|
||||
"interaction_modal.action.reblog": "Щоб іти далі, потрібно зробити реблог з вашого облікового запису.",
|
||||
|
|
|
@ -86,6 +86,13 @@
|
|||
"alert.unexpected.message": "发生了意外错误。",
|
||||
"alert.unexpected.title": "哎呀!",
|
||||
"alt_text_badge.title": "替代文本",
|
||||
"alt_text_modal.add_alt_text": "添加替代文本",
|
||||
"alt_text_modal.add_text_from_image": "从图像中添加文本",
|
||||
"alt_text_modal.cancel": "取消",
|
||||
"alt_text_modal.change_thumbnail": "更改缩略图",
|
||||
"alt_text_modal.describe_for_people_with_hearing_impairments": "请为听力障碍人士描述此内容…",
|
||||
"alt_text_modal.describe_for_people_with_visual_impairments": "请为视力障碍人士描述此内容…",
|
||||
"alt_text_modal.done": "完成",
|
||||
"announcement.announcement": "公告",
|
||||
"annual_report.summary.archetype.booster": "潮流捕手",
|
||||
"annual_report.summary.archetype.lurker": "吃瓜群众",
|
||||
|
@ -109,7 +116,7 @@
|
|||
"attachments_list.unprocessed": "(未处理)",
|
||||
"audio.hide": "隐藏音频",
|
||||
"block_modal.remote_users_caveat": "我们将要求站点 {domain} 尊重你的决定。然而,我们无法保证对方一定遵从,因为某些站点可能会以不同的方案处理屏蔽操作。公开嘟文仍然可能对未登录用户可见。",
|
||||
"block_modal.show_less": "隐藏",
|
||||
"block_modal.show_less": "折叠",
|
||||
"block_modal.show_more": "显示更多",
|
||||
"block_modal.they_cant_mention": "他们不能提及或关注你。",
|
||||
"block_modal.they_cant_see_posts": "他们看不到你的嘟文,你也看不到他们的嘟文。",
|
||||
|
@ -221,8 +228,8 @@
|
|||
"confirmations.unfollow.confirm": "取消关注",
|
||||
"confirmations.unfollow.message": "你确定要取消关注 {name} 吗?",
|
||||
"confirmations.unfollow.title": "确定要取消关注用户?",
|
||||
"content_warning.hide": "隐藏",
|
||||
"content_warning.show": "展开",
|
||||
"content_warning.hide": "隐藏嘟文",
|
||||
"content_warning.show": "仍要显示",
|
||||
"content_warning.show_more": "展开",
|
||||
"conversation.delete": "删除对话",
|
||||
"conversation.mark_as_read": "标记为已读",
|
||||
|
@ -407,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "是否忽略未关注你的人的通知?",
|
||||
"ignore_notifications_modal.not_following_title": "是否忽略你未关注的人的通知?",
|
||||
"ignore_notifications_modal.private_mentions_title": "是否忽略不请自来的私下提及?",
|
||||
"info_button.label": "帮助",
|
||||
"info_button.what_is_alt_text": "<h1>什么是替代文本?</h1> <p>替代文本为视力障碍者、低带宽连接用户或需要额外背景信息的用户提供图像描述。</p> <p>通过编写清晰、简洁、客观的替代文本,可以提升所有人的可访问性和理解力。</p> <ul> <li>捕捉重要元素</li> <li>总结图像中的文本</li> <li>使用常规句子结构</li> <li>避免冗余信息</li> <li>关注复杂视觉内容(如图表或地图)中的趋势和关键信息</li> </ul>",
|
||||
"interaction_modal.action.favourite": "你需要切换到自己的账号,再发送喜欢。",
|
||||
"interaction_modal.action.follow": "你需要切换到自己的账号,再进行关注。",
|
||||
"interaction_modal.action.reblog": "你需要切换到自己的账号,再进行转嘟。",
|
||||
|
|
|
@ -414,6 +414,8 @@
|
|||
"ignore_notifications_modal.not_followers_title": "忽略來自未跟隨您帳號之推播通知?",
|
||||
"ignore_notifications_modal.not_following_title": "忽略來自您未跟隨帳號之推播通知?",
|
||||
"ignore_notifications_modal.private_mentions_title": "忽略來自不請自來私訊之推播通知?",
|
||||
"info_button.label": "幫助",
|
||||
"info_button.what_is_alt_text": "<h1>何謂 ALT 說明文字?</h1> <p>ALT 說明文字為視覺障礙者、低網路頻寬或尋求額外上下文語境的人們提供圖片描述。</p> <p>您可以透過撰寫清晰、簡潔及客觀的說明文字以替所有人改善無障礙特性與協助理解。</p> <ul> <li>掌握幾個重要元素</li> <li>替圖片提供文字摘要</li> <li>使用常規行文結構</li> <li>避免冗贅資訊</li> <li>聚焦於趨勢與複雜視覺中之關鍵(如圖表或地圖)</li> </ul>",
|
||||
"interaction_modal.action.favourite": "若欲繼續,您必須自您的帳號加入最愛。",
|
||||
"interaction_modal.action.follow": "若欲繼續,您必須自您的帳號跟隨。",
|
||||
"interaction_modal.action.reblog": "若欲繼續,您必須自您的帳號轉嘟。",
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M424-320q0-81 14.5-116.5T500-514q41-36 62.5-62.5T584-637q0-41-27.5-68T480-732q-51 0-77.5 31T365-638l-103-44q21-64 77-111t141-47q105 0 161.5 58.5T698-641q0 50-21.5 85.5T609-475q-49 47-59.5 71.5T539-320H424Zm56 240q-33 0-56.5-23.5T400-160q0-33 23.5-56.5T480-240q33 0 56.5 23.5T560-160q0 33-23.5 56.5T480-80Z"/></svg>
|
After Width: | Height: | Size: 411 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M424-320q0-81 14.5-116.5T500-514q41-36 62.5-62.5T584-637q0-41-27.5-68T480-732q-51 0-77.5 31T365-638l-103-44q21-64 77-111t141-47q105 0 161.5 58.5T698-641q0 50-21.5 85.5T609-475q-49 47-59.5 71.5T539-320H424Zm56 240q-33 0-56.5-23.5T400-160q0-33 23.5-56.5T480-240q33 0 56.5 23.5T560-160q0 33-23.5 56.5T480-80Z"/></svg>
|
After Width: | Height: | Size: 411 B |
|
@ -451,6 +451,15 @@
|
|||
background: darken($ui-base-color, 10%);
|
||||
}
|
||||
|
||||
.dropdown-button.warning {
|
||||
border-color: #b3261e;
|
||||
color: #b3261e;
|
||||
|
||||
&.active {
|
||||
background-color: #f9dedc;
|
||||
}
|
||||
}
|
||||
|
||||
.search__popout__menu__item {
|
||||
&:hover,
|
||||
&:active,
|
||||
|
|
|
@ -50,6 +50,34 @@
|
|||
}
|
||||
}
|
||||
|
||||
.help-button {
|
||||
background: $ui-button-background-color;
|
||||
border: 0;
|
||||
color: $ui-button-color;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&:active,
|
||||
&:focus,
|
||||
&:hover {
|
||||
background-color: $ui-button-focus-background-color;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: $ui-button-icon-focus-outline;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
background-color: $ui-button-background-color;
|
||||
border: 10px none;
|
||||
|
@ -6091,6 +6119,20 @@ a.status-card {
|
|||
}
|
||||
}
|
||||
|
||||
&__popout {
|
||||
background: var(--dropdown-background-color);
|
||||
backdrop-filter: var(--background-filter);
|
||||
border: 1px solid var(--dropdown-border-color);
|
||||
box-shadow: var(--dropdown-shadow);
|
||||
max-width: 320px;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
z-index: 9999 !important;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: $darker-text-color;
|
||||
}
|
||||
|
||||
.copy-paste-text {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
|
|
@ -83,9 +83,12 @@ code {
|
|||
&__toolbar {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
|
||||
.character-counter {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
|
@ -561,11 +564,14 @@ code {
|
|||
}
|
||||
|
||||
.stacked-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
button:not(.button, .link-button) {
|
||||
.btn {
|
||||
display: block;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
|
@ -582,8 +588,6 @@ code {
|
|||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
outline: 0;
|
||||
margin-bottom: 10px;
|
||||
margin-inline-end: 10px;
|
||||
|
||||
&:last-child {
|
||||
margin-inline-end: 0;
|
||||
|
|
|
@ -17,7 +17,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
|
|||
|
||||
options = serialization_options(options)
|
||||
serialized_hash = serializer.serializable_hash(options.merge(named_contexts: named_contexts, context_extensions: context_extensions))
|
||||
serialized_hash = serialized_hash.select { |k, _| options[:fields].include?(k) } if options[:fields]
|
||||
serialized_hash = serialized_hash.slice(*options[:fields]) if options[:fields]
|
||||
serialized_hash = self.class.transform_key_casing!(serialized_hash, instance_options)
|
||||
|
||||
{ '@context': serialized_context(named_contexts, context_extensions) }.merge(serialized_hash)
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
.fields-group
|
||||
= f.input :agreement,
|
||||
as: :boolean,
|
||||
label: t('auth.user_agreement_html', privacy_policy_path: privacy_policy_path, terms_of_service_path: terms_of_service_path),
|
||||
label: TermsOfService.live.exists? ? t('auth.user_agreement_html', privacy_policy_path: privacy_policy_path, terms_of_service_path: terms_of_service_path) : t('auth.user_privacy_agreement_html', privacy_policy_path: privacy_policy_path),
|
||||
required: false,
|
||||
wrapper: :with_label
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'prometheus_exporter' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
||||
|
||||
bundle_binstub = File.expand_path("bundle", __dir__)
|
||||
|
||||
if File.file?(bundle_binstub)
|
||||
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
||||
load(bundle_binstub)
|
||||
else
|
||||
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
||||
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
||||
end
|
||||
end
|
||||
|
||||
require "rubygems"
|
||||
require "bundler/setup"
|
||||
|
||||
load Gem.bin_path("prometheus_exporter", "prometheus_exporter")
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
if ENV['MASTODON_PROMETHEUS_EXPORTER_ENABLED'] == 'true'
|
||||
if ENV['MASTODON_PROMETHEUS_EXPORTER_LOCAL'] == 'true'
|
||||
require 'prometheus_exporter/server'
|
||||
require 'prometheus_exporter/client'
|
||||
|
||||
# bind is the address, on which the webserver will listen
|
||||
# port is the port that will provide the /metrics route
|
||||
server = PrometheusExporter::Server::WebServer.new bind: ENV.fetch('MASTODON_PROMETHEUS_EXPORTER_HOST', 'localhost'), port: ENV.fetch('MASTODON_PROMETHEUS_EXPORTER_PORT', '9394').to_i
|
||||
server.start
|
||||
|
||||
# wire up a default local client
|
||||
PrometheusExporter::Client.default = PrometheusExporter::LocalClient.new(collector: server.collector)
|
||||
end
|
||||
|
||||
if ENV['MASTODON_PROMETHEUS_EXPORTER_WEB_DETAILED_METRICS'] == 'true'
|
||||
# Optional, as those metrics might generate extra overhead and be redundant with what OTEL provides
|
||||
require 'prometheus_exporter/middleware'
|
||||
|
||||
# Per-action/controller request stats like HTTP status and timings
|
||||
Rails.application.middleware.unshift PrometheusExporter::Middleware
|
||||
end
|
||||
end
|
|
@ -22,6 +22,48 @@ Sidekiq.configure_server do |config|
|
|||
end
|
||||
end
|
||||
|
||||
if ENV['MASTODON_PROMETHEUS_EXPORTER_ENABLED'] == 'true'
|
||||
require 'prometheus_exporter'
|
||||
require 'prometheus_exporter/instrumentation'
|
||||
|
||||
config.on :startup do
|
||||
# Ruby process metrics (memory, GC, etc)
|
||||
PrometheusExporter::Instrumentation::Process.start type: 'sidekiq'
|
||||
|
||||
# Sidekiq process metrics (concurrency, busy, etc)
|
||||
PrometheusExporter::Instrumentation::SidekiqProcess.start
|
||||
|
||||
# ActiveRecord metrics (connection pool usage)
|
||||
PrometheusExporter::Instrumentation::ActiveRecord.start(
|
||||
custom_labels: { type: 'sidekiq' },
|
||||
config_labels: [:database, :host]
|
||||
)
|
||||
|
||||
if ENV['MASTODON_PROMETHEUS_EXPORTER_SIDEKIQ_DETAILED_METRICS'] == 'true'
|
||||
# Optional, as those metrics might generate extra overhead and be redundant with what OTEL provides
|
||||
|
||||
# Per-job metrics
|
||||
config.server_middleware do |chain|
|
||||
chain.add PrometheusExporter::Instrumentation::Sidekiq
|
||||
end
|
||||
config.death_handlers << PrometheusExporter::Instrumentation::Sidekiq.death_handler
|
||||
|
||||
# Per-queue metrics for queues handled by this process (size, latency, etc)
|
||||
# They will be reported by every process handling those queues, so do not sum them up
|
||||
PrometheusExporter::Instrumentation::SidekiqQueue.start
|
||||
|
||||
# Global Sidekiq metrics (size of the global queues, number of jobs, etc)
|
||||
# Will be the same for every Sidekiq process
|
||||
PrometheusExporter::Instrumentation::SidekiqStats.start
|
||||
end
|
||||
end
|
||||
|
||||
at_exit do
|
||||
# Wait for the latest metrics to be reported before shutting down
|
||||
PrometheusExporter::Client.default.stop(wait_timeout_seconds: 10)
|
||||
end
|
||||
end
|
||||
|
||||
config.server_middleware do |chain|
|
||||
chain.add Mastodon::SidekiqMiddleware
|
||||
end
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue