Merge pull request #3136 from ClearlyClaire/glitch-soc/merge-upstream

Merge upstream changes up to 19626ad89f
This commit is contained in:
Claire
2025-07-21 22:40:28 +02:00
committed by GitHub
19 changed files with 219 additions and 189 deletions

View File

@@ -1 +1 @@
3.4.4
3.4.5

View File

@@ -13,7 +13,7 @@ ARG BASE_REGISTRY="docker.io"
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.4.x"]
# renovate: datasource=docker depName=docker.io/ruby
ARG RUBY_VERSION="3.4.4"
ARG RUBY_VERSION="3.4.5"
# # Node.js version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
# renovate: datasource=node-version depName=node
ARG NODE_MAJOR_VERSION="22"

View File

@@ -224,7 +224,7 @@ GEM
mail (~> 2.7)
email_validator (2.2.4)
activemodel
erb (5.0.1)
erb (5.0.2)
erubi (1.13.1)
et-orbi (1.2.11)
tzinfo
@@ -315,7 +315,7 @@ GEM
http_accept_language (2.1.1)
httpclient (2.9.0)
mutex_m
httplog (1.7.0)
httplog (1.7.1)
rack (>= 2.0)
rainbow (>= 2.0.0)
i18n (1.14.7)
@@ -335,7 +335,7 @@ GEM
inline_svg (1.10.0)
activesupport (>= 3.0)
nokogiri (>= 1.6)
io-console (0.8.0)
io-console (0.8.1)
irb (1.15.2)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
@@ -627,11 +627,10 @@ GEM
prism (1.4.0)
prometheus_exporter (2.2.0)
webrick
propshaft (1.1.0)
propshaft (1.2.0)
actionpack (>= 7.0.0)
activesupport (>= 7.0.0)
rack
railties (>= 7.0.0)
psych (5.2.6)
date
stringio
@@ -708,7 +707,7 @@ GEM
link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.7.0)
rdf (~> 3.3)
rdoc (6.14.1)
rdoc (6.14.2)
erb
psych (>= 4.0.0)
redcarpet (3.6.1)

View File

@@ -122,98 +122,93 @@ export const PolicyControls: React.FC = () => {
value={notificationPolicy.for_not_following}
onChange={handleFilterNotFollowing}
options={options}
>
<strong>
label={
<FormattedMessage
id='notifications.policy.filter_not_following_title'
defaultMessage="People you don't follow"
/>
</strong>
<span className='hint'>
}
hint={
<FormattedMessage
id='notifications.policy.filter_not_following_hint'
defaultMessage='Until you manually approve them'
/>
</span>
</SelectWithLabel>
}
/>
<SelectWithLabel
value={notificationPolicy.for_not_followers}
onChange={handleFilterNotFollowers}
options={options}
>
<strong>
label={
<FormattedMessage
id='notifications.policy.filter_not_followers_title'
defaultMessage='People not following you'
/>
</strong>
<span className='hint'>
}
hint={
<FormattedMessage
id='notifications.policy.filter_not_followers_hint'
defaultMessage='Including people who have been following you fewer than {days, plural, one {one day} other {# days}}'
values={{ days: 3 }}
/>
</span>
</SelectWithLabel>
}
/>
<SelectWithLabel
value={notificationPolicy.for_new_accounts}
onChange={handleFilterNewAccounts}
options={options}
>
<strong>
label={
<FormattedMessage
id='notifications.policy.filter_new_accounts_title'
defaultMessage='New accounts'
/>
</strong>
<span className='hint'>
}
hint={
<FormattedMessage
id='notifications.policy.filter_new_accounts.hint'
defaultMessage='Created within the past {days, plural, one {one day} other {# days}}'
values={{ days: 30 }}
/>
</span>
</SelectWithLabel>
}
/>
<SelectWithLabel
value={notificationPolicy.for_private_mentions}
onChange={handleFilterPrivateMentions}
options={options}
>
<strong>
label={
<FormattedMessage
id='notifications.policy.filter_private_mentions_title'
defaultMessage='Unsolicited private mentions'
/>
</strong>
<span className='hint'>
}
hint={
<FormattedMessage
id='notifications.policy.filter_private_mentions_hint'
defaultMessage="Filtered unless it's in reply to your own mention or if you follow the sender"
/>
</span>
</SelectWithLabel>
}
/>
<SelectWithLabel
value={notificationPolicy.for_limited_accounts}
onChange={handleFilterLimitedAccounts}
options={options}
>
<strong>
label={
<FormattedMessage
id='notifications.policy.filter_limited_accounts_title'
defaultMessage='Moderated accounts'
/>
</strong>
<span className='hint'>
}
hint={
<FormattedMessage
id='notifications.policy.filter_limited_accounts_hint'
defaultMessage='Limited by server moderators'
/>
</span>
</SelectWithLabel>
}
/>
</div>
</section>
);

View File

@@ -1,5 +1,5 @@
import type { PropsWithChildren } from 'react';
import { useCallback, useState, useRef } from 'react';
import { useCallback, useState, useRef, useId } from 'react';
import classNames from 'classnames';
@@ -16,6 +16,8 @@ interface DropdownProps {
options: SelectItem[];
disabled?: boolean;
onChange: (value: string) => void;
'aria-labelledby': string;
'aria-describedby'?: string;
placement?: Placement;
}
@@ -24,51 +26,33 @@ const Dropdown: React.FC<DropdownProps> = ({
options,
disabled,
onChange,
'aria-labelledby': ariaLabelledBy,
'aria-describedby': ariaDescribedBy,
placement: initialPlacement = 'bottom-end',
}) => {
const activeElementRef = useRef<Element | null>(null);
const containerRef = useRef(null);
const containerRef = useRef<HTMLDivElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
const [isOpen, setOpen] = useState<boolean>(false);
const [placement, setPlacement] = useState<Placement>(initialPlacement);
const handleToggle = useCallback(() => {
if (
isOpen &&
activeElementRef.current &&
activeElementRef.current instanceof HTMLElement
) {
activeElementRef.current.focus({ preventScroll: true });
}
setOpen(!isOpen);
}, [isOpen, setOpen]);
const handleMouseDown = useCallback(() => {
if (!isOpen) activeElementRef.current = document.activeElement;
}, [isOpen]);
const handleKeyDown = useCallback(
(e: React.KeyboardEvent) => {
switch (e.key) {
case ' ':
case 'Enter':
if (!isOpen) activeElementRef.current = document.activeElement;
break;
}
},
[isOpen],
);
const uniqueId = useId();
const menuId = `${uniqueId}-menu`;
const buttonLabelId = `${uniqueId}-button`;
const handleClose = useCallback(() => {
if (
isOpen &&
activeElementRef.current &&
activeElementRef.current instanceof HTMLElement
)
activeElementRef.current.focus({ preventScroll: true });
if (isOpen && buttonRef.current) {
buttonRef.current.focus({ preventScroll: true });
}
setOpen(false);
}, [isOpen]);
const handleToggle = useCallback(() => {
if (isOpen) {
handleClose();
} else {
setOpen(true);
}
}, [isOpen, handleClose]);
const handleOverlayEnter = useCallback(
(state: Partial<PopperState>) => {
if (state.placement) setPlacement(state.placement);
@@ -82,13 +66,18 @@ const Dropdown: React.FC<DropdownProps> = ({
<div ref={containerRef}>
<button
type='button'
ref={buttonRef}
onClick={handleToggle}
onMouseDown={handleMouseDown}
onKeyDown={handleKeyDown}
disabled={disabled}
aria-expanded={isOpen}
aria-controls={menuId}
aria-labelledby={`${ariaLabelledBy} ${buttonLabelId}`}
aria-describedby={ariaDescribedBy}
className={classNames('dropdown-button', { active: isOpen })}
>
<span className='dropdown-button__label'>{valueOption?.text}</span>
<span id={buttonLabelId} className='dropdown-button__label'>
{valueOption?.text}
</span>
<Icon id='down' icon={ArrowDropDownIcon} />
</button>
@@ -101,7 +90,7 @@ const Dropdown: React.FC<DropdownProps> = ({
popperConfig={{ strategy: 'fixed', onFirstUpdate: handleOverlayEnter }}
>
{({ props, placement }) => (
<div {...props}>
<div {...props} id={menuId}>
<div
className={`dropdown-animation privacy-dropdown__dropdown ${placement}`}
>
@@ -123,6 +112,8 @@ const Dropdown: React.FC<DropdownProps> = ({
interface Props {
value: string;
options: SelectItem[];
label: string | React.ReactElement;
hint: string | React.ReactElement;
disabled?: boolean;
onChange: (value: string) => void;
}
@@ -130,13 +121,26 @@ interface Props {
export const SelectWithLabel: React.FC<PropsWithChildren<Props>> = ({
value,
options,
label,
hint,
disabled,
children,
onChange,
}) => {
const uniqueId = useId();
const labelId = `${uniqueId}-label`;
const descId = `${uniqueId}-desc`;
return (
// This label is only used for its click-forwarding behaviour,
// accessible names are assigned manually
// eslint-disable-next-line jsx-a11y/label-has-associated-control
<label className='app-form__toggle'>
<div className='app-form__toggle__label'>{children}</div>
<div className='app-form__toggle__label'>
<strong id={labelId}>{label}</strong>
<span className='hint' id={descId}>
{hint}
</span>
</div>
<div className='app-form__toggle__toggle'>
<div>
@@ -144,6 +148,8 @@ export const SelectWithLabel: React.FC<PropsWithChildren<Props>> = ({
value={value}
onChange={onChange}
disabled={disabled}
aria-labelledby={labelId}
aria-describedby={descId}
options={options}
/>
</div>

View File

@@ -122,98 +122,93 @@ export const PolicyControls: React.FC = () => {
value={notificationPolicy.for_not_following}
onChange={handleFilterNotFollowing}
options={options}
>
<strong>
label={
<FormattedMessage
id='notifications.policy.filter_not_following_title'
defaultMessage="People you don't follow"
/>
</strong>
<span className='hint'>
}
hint={
<FormattedMessage
id='notifications.policy.filter_not_following_hint'
defaultMessage='Until you manually approve them'
/>
</span>
</SelectWithLabel>
}
/>
<SelectWithLabel
value={notificationPolicy.for_not_followers}
onChange={handleFilterNotFollowers}
options={options}
>
<strong>
label={
<FormattedMessage
id='notifications.policy.filter_not_followers_title'
defaultMessage='People not following you'
/>
</strong>
<span className='hint'>
}
hint={
<FormattedMessage
id='notifications.policy.filter_not_followers_hint'
defaultMessage='Including people who have been following you fewer than {days, plural, one {one day} other {# days}}'
values={{ days: 3 }}
/>
</span>
</SelectWithLabel>
}
/>
<SelectWithLabel
value={notificationPolicy.for_new_accounts}
onChange={handleFilterNewAccounts}
options={options}
>
<strong>
label={
<FormattedMessage
id='notifications.policy.filter_new_accounts_title'
defaultMessage='New accounts'
/>
</strong>
<span className='hint'>
}
hint={
<FormattedMessage
id='notifications.policy.filter_new_accounts.hint'
defaultMessage='Created within the past {days, plural, one {one day} other {# days}}'
values={{ days: 30 }}
/>
</span>
</SelectWithLabel>
}
/>
<SelectWithLabel
value={notificationPolicy.for_private_mentions}
onChange={handleFilterPrivateMentions}
options={options}
>
<strong>
label={
<FormattedMessage
id='notifications.policy.filter_private_mentions_title'
defaultMessage='Unsolicited private mentions'
/>
</strong>
<span className='hint'>
}
hint={
<FormattedMessage
id='notifications.policy.filter_private_mentions_hint'
defaultMessage="Filtered unless it's in reply to your own mention or if you follow the sender"
/>
</span>
</SelectWithLabel>
}
/>
<SelectWithLabel
value={notificationPolicy.for_limited_accounts}
onChange={handleFilterLimitedAccounts}
options={options}
>
<strong>
label={
<FormattedMessage
id='notifications.policy.filter_limited_accounts_title'
defaultMessage='Moderated accounts'
/>
</strong>
<span className='hint'>
}
hint={
<FormattedMessage
id='notifications.policy.filter_limited_accounts_hint'
defaultMessage='Limited by server moderators'
/>
</span>
</SelectWithLabel>
}
/>
</div>
</section>
);

View File

@@ -1,5 +1,5 @@
import type { PropsWithChildren } from 'react';
import { useCallback, useState, useRef } from 'react';
import { useCallback, useState, useRef, useId } from 'react';
import classNames from 'classnames';
@@ -16,6 +16,8 @@ interface DropdownProps {
options: SelectItem[];
disabled?: boolean;
onChange: (value: string) => void;
'aria-labelledby': string;
'aria-describedby'?: string;
placement?: Placement;
}
@@ -24,51 +26,33 @@ const Dropdown: React.FC<DropdownProps> = ({
options,
disabled,
onChange,
'aria-labelledby': ariaLabelledBy,
'aria-describedby': ariaDescribedBy,
placement: initialPlacement = 'bottom-end',
}) => {
const activeElementRef = useRef<Element | null>(null);
const containerRef = useRef(null);
const containerRef = useRef<HTMLDivElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
const [isOpen, setOpen] = useState<boolean>(false);
const [placement, setPlacement] = useState<Placement>(initialPlacement);
const handleToggle = useCallback(() => {
if (
isOpen &&
activeElementRef.current &&
activeElementRef.current instanceof HTMLElement
) {
activeElementRef.current.focus({ preventScroll: true });
}
setOpen(!isOpen);
}, [isOpen, setOpen]);
const handleMouseDown = useCallback(() => {
if (!isOpen) activeElementRef.current = document.activeElement;
}, [isOpen]);
const handleKeyDown = useCallback(
(e: React.KeyboardEvent) => {
switch (e.key) {
case ' ':
case 'Enter':
if (!isOpen) activeElementRef.current = document.activeElement;
break;
}
},
[isOpen],
);
const uniqueId = useId();
const menuId = `${uniqueId}-menu`;
const buttonLabelId = `${uniqueId}-button`;
const handleClose = useCallback(() => {
if (
isOpen &&
activeElementRef.current &&
activeElementRef.current instanceof HTMLElement
)
activeElementRef.current.focus({ preventScroll: true });
if (isOpen && buttonRef.current) {
buttonRef.current.focus({ preventScroll: true });
}
setOpen(false);
}, [isOpen]);
const handleToggle = useCallback(() => {
if (isOpen) {
handleClose();
} else {
setOpen(true);
}
}, [isOpen, handleClose]);
const handleOverlayEnter = useCallback(
(state: Partial<PopperState>) => {
if (state.placement) setPlacement(state.placement);
@@ -82,13 +66,18 @@ const Dropdown: React.FC<DropdownProps> = ({
<div ref={containerRef}>
<button
type='button'
ref={buttonRef}
onClick={handleToggle}
onMouseDown={handleMouseDown}
onKeyDown={handleKeyDown}
disabled={disabled}
aria-expanded={isOpen}
aria-controls={menuId}
aria-labelledby={`${ariaLabelledBy} ${buttonLabelId}`}
aria-describedby={ariaDescribedBy}
className={classNames('dropdown-button', { active: isOpen })}
>
<span className='dropdown-button__label'>{valueOption?.text}</span>
<span id={buttonLabelId} className='dropdown-button__label'>
{valueOption?.text}
</span>
<Icon id='down' icon={ArrowDropDownIcon} />
</button>
@@ -101,7 +90,7 @@ const Dropdown: React.FC<DropdownProps> = ({
popperConfig={{ strategy: 'fixed', onFirstUpdate: handleOverlayEnter }}
>
{({ props, placement }) => (
<div {...props}>
<div {...props} id={menuId}>
<div
className={`dropdown-animation privacy-dropdown__dropdown ${placement}`}
>
@@ -123,6 +112,8 @@ const Dropdown: React.FC<DropdownProps> = ({
interface Props {
value: string;
options: SelectItem[];
label: string | React.ReactElement;
hint: string | React.ReactElement;
disabled?: boolean;
onChange: (value: string) => void;
}
@@ -130,13 +121,26 @@ interface Props {
export const SelectWithLabel: React.FC<PropsWithChildren<Props>> = ({
value,
options,
label,
hint,
disabled,
children,
onChange,
}) => {
const uniqueId = useId();
const labelId = `${uniqueId}-label`;
const descId = `${uniqueId}-desc`;
return (
// This label is only used for its click-forwarding behaviour,
// accessible names are assigned manually
// eslint-disable-next-line jsx-a11y/label-has-associated-control
<label className='app-form__toggle'>
<div className='app-form__toggle__label'>{children}</div>
<div className='app-form__toggle__label'>
<strong id={labelId}>{label}</strong>
<span className='hint' id={descId}>
{hint}
</span>
</div>
<div className='app-form__toggle__toggle'>
<div>
@@ -144,6 +148,8 @@ export const SelectWithLabel: React.FC<PropsWithChildren<Props>> = ({
value={value}
onChange={onChange}
disabled={disabled}
aria-labelledby={labelId}
aria-describedby={descId}
options={options}
/>
</div>

View File

@@ -617,7 +617,7 @@
"notification.reblog": "{name} продвинул(а) ваш пост",
"notification.reblog.name_and_others_with_link": "{name} и ещё <a>{count, plural, one {# пользователь} few {# пользователя} other {# пользователей}}</a> продвинули ваш пост",
"notification.relationships_severance_event": "Разорвана связь с {name}",
"notification.relationships_severance_event.account_suspension": "Администратор сервера {from} заблокировал сервер {target}, поэтому вы больше не сможете получать обновления от людей с этого сервера или взаимодействовать с ними.",
"notification.relationships_severance_event.account_suspension": "Администратор сервера {from} заблокировал сервер {target}, поэтому вы больше не сможете получать обновления от людей с этого сервера и взаимодействовать с ними.",
"notification.relationships_severance_event.domain_block": "Администратор сервера {from} заблокировал сервер {target}, где размещены учётные записи {followersCount} ваших подписчиков и {followingCount, plural, one {# пользователя, на которого вы подписаны} other {# пользователей, на которых вы подписаны}}.",
"notification.relationships_severance_event.learn_more": "Узнать больше",
"notification.relationships_severance_event.user_domain_block": "Вы заблокировали сервер {target}, где размещены учётные записи {followersCount} ваших подписчиков и {followingCount, plural, one {# пользователя, на которого вы подписаны} other {# пользователей, на которых вы подписаны}}.",
@@ -707,7 +707,7 @@
"onboarding.profile.display_name": "Отображаемое имя",
"onboarding.profile.display_name_hint": "Ваше полное имя или псевдоним…",
"onboarding.profile.note": "О себе",
"onboarding.profile.note_hint": "Вы можете @упоминать других людей или использовать #хештеги…",
"onboarding.profile.note_hint": "Вы можете @упоминать других людей, а также использовать #хештеги…",
"onboarding.profile.save_and_continue": "Сохранить и продолжить",
"onboarding.profile.title": "Создайте свой профиль",
"onboarding.profile.upload_avatar": "Загрузить фото профиля",
@@ -741,16 +741,16 @@
"refresh": "Обновить",
"regeneration_indicator.please_stand_by": "Пожалуйста, подождите.",
"regeneration_indicator.preparing_your_home_feed": "Готовим вашу ленту…",
"relative_time.days": "{number} д",
"relative_time.days": "{number} д.",
"relative_time.full.days": "{number, plural, one {# день} many {# дней} other {# дня}} назад",
"relative_time.full.hours": "{number, plural, one {# час} many {# часов} other {# часа}} назад",
"relative_time.full.just_now": "только что",
"relative_time.full.minutes": "{number, plural, one {# минуту} many {# минут} other {# минуты}} назад",
"relative_time.full.seconds": "{number, plural, one {# секунду} many {# секунд} other {# секунды}} назад",
"relative_time.hours": "{number} ч",
"relative_time.hours": "{number} ч.",
"relative_time.just_now": "только что",
"relative_time.minutes": "{number} мин",
"relative_time.seconds": "{number} с",
"relative_time.minutes": "{number} мин.",
"relative_time.seconds": "{number} с.",
"relative_time.today": "сегодня",
"reply_indicator.attachments": "{count, plural, one {# вложение} few {# вложения} other {# вложений}}",
"reply_indicator.cancel": "Отмена",
@@ -836,7 +836,7 @@
"server_banner.is_one_of_many": "{domain} — это один из многих независимых серверов Mastodon, которые вы можете использовать, чтобы присоединиться к сети Fediverse.",
"server_banner.server_stats": "Статистика сервера:",
"sign_in_banner.create_account": "Зарегистрироваться",
"sign_in_banner.follow_anyone": "Подписывайтесь на кого угодно в федивёрсе и читайте ленту в хронологическом порядке. Никаких алгоритмов, рекламы или кликбейта.",
"sign_in_banner.follow_anyone": "Подписывайтесь на кого угодно в федивёрсе и читайте ленту в хронологическом порядке. Никаких алгоритмов, рекламы и кликбейта.",
"sign_in_banner.mastodon_is": "Mastodon — лучший способ быть в курсе всего происходящего.",
"sign_in_banner.sign_in": "Войти",
"sign_in_banner.sso_redirect": "Вход/Регистрация",

View File

@@ -1349,6 +1349,8 @@ fa:
basic_information: اطلاعات پایه
hint_html: "<strong>شخصی‌سازی آن چه مردم روی نمایهٔ عمومیتان و کنار فرسته‌هایتان می‌بینند.</strong> هنگامی که نمایه‌ای کامل و یک تصویر نمایه داشته باشید،‌ احتمال پی‌گیری متقابل و تعامل با شما بیش‌تر است."
other: سایر
emoji_styles:
auto: خودکار
errors:
'400': درخواستی که فرستادید نامعتبر یا اشتباه بود.
'403': شما اجازهٔ دیدن این صفحه را ندارید.

View File

@@ -354,7 +354,7 @@ ru:
enable: Включить
enabled: Включён
enabled_msg: Эмодзи включён
image_hint: Поддерживаются файлы PNG или GIF размером не более %{size}
image_hint: Поддерживаются файлы PNG и GIF размером не более %{size}
list: В список
listed: В списке
new:
@@ -1280,7 +1280,7 @@ ru:
confirm: Продолжить
hint_html: "<strong>Подсказка:</strong> В течение часа вам не придётся снова вводить свой пароль."
invalid_password: Неверный пароль
prompt: Введите пароль для продолжения
prompt: Введите пароль, чтобы продолжить
crypto:
errors:
invalid_key: должен быть действительным Ed25519- или Curve25519-ключом
@@ -1290,35 +1290,35 @@ ru:
with_month_name: "%d %B %Y"
datetime:
distance_in_words:
about_x_hours: "%{count}ч"
about_x_months: "%{count}мес"
about_x_years: "%{count}г"
almost_x_years: "%{count}г"
about_x_hours: "%{count} ч."
about_x_months: "%{count} мес."
about_x_years: "%{count} г."
almost_x_years: "%{count} г."
half_a_minute: Только что
less_than_x_minutes: "%{count}мин"
less_than_x_minutes: "%{count} мин."
less_than_x_seconds: Только что
over_x_years: "%{count}г"
x_days: "%{count}д"
x_minutes: "%{count}мин"
x_months: "%{count}мес"
x_seconds: "%{count}сек"
over_x_years: "%{count} г."
x_days: "%{count} д."
x_minutes: "%{count} мин."
x_months: "%{count} мес."
x_seconds: "%{count} с."
deletes:
challenge_not_passed: Введённая вами информация некорректна
confirm_password: Введите свой пароль, чтобы подтвердить, что вы — это вы, и никто другой
challenge_not_passed: Данные введены неверно
confirm_password: Введите свой пароль, чтобы подтвердить, что это ваша учётная запись
confirm_username: Введите своё имя пользователя для подтверждения
proceed: Удалить учётную запись
success_msg: Ваша учётная запись была успешно удалена
success_msg: Ваша учётная запись удалена
warning:
before: 'Внимательно прочитайте следующую информацию перед началом:'
caches: Некоторые данные, обработанные другими узлами, однако, могут храниться ещё какое-то время
data_removal: Все ваши золотые посты, шикарный профиль и прочие данные будут безвозвратно уничтожены
before: 'Внимательно ознакомьтесь со следующими замечаниями перед тем как продолжить:'
caches: На других серверах могут остаться сохранённые в кэше данные
data_removal: Все ваши посты и другие ваши данные будут безвозвратно уничтожены
email_change_html: Вы можете <a href="%{path}">изменить свой адрес электронной почты</a>, не удаляя свою учетную запись
email_contact_html: Если оно все еще не пришло, вы можете обратиться за помощью по электронной почте <a href="mailto:%{email}">%{email}</a>
email_reconfirmation_html: Если вы не получили подтверждение по электронной почте, вы можете <a href="%{path}">запросить его снова</a>
irreversible: После удаления восстановить или повторно активировать учётную запись не получится
more_details_html: За всеми подробностями, изучите <a href="%{terms_path}">политику конфиденциальности</a>.
irreversible: После удаления вы больше не сможете ни восстановить, ни повторно активировать свою учётную запись
more_details_html: За более подробной информацией вы можете обратиться к <a href="%{terms_path}">политике конфиденциальности</a>.
username_available: Ваше имя пользователя снова станет доступным
username_unavailable: Ваше имя пользователя останется недоступным для использования
username_unavailable: Зарегистрироваться с вашим именем пользователя будет невозможно
disputes:
strikes:
action_taken: Предпринятые меры
@@ -1353,6 +1353,10 @@ ru:
basic_information: Основная информация
hint_html: "<strong>Настройте то, что люди видят в вашем публичном профиле и рядом с вашими сообщениями.</strong> Другие люди с большей вероятностью подпишутся на Вас и будут взаимодействовать с вами, если у Вас заполнен профиль и добавлено изображение."
other: Прочее
emoji_styles:
auto: Автоматически
native: Как в системе
twemoji: Twemoji
errors:
'400': Ваш запрос был недействительным или неправильным.
'403': У Вас нет доступа к просмотру этой страницы.
@@ -2136,17 +2140,17 @@ ru:
webauthn_credentials:
add: Добавить новый электронный ключ
create:
error: Возникла проблема с добавлением ключа безопасности. Пожалуйста, попробуйте еще раз.
error: При добавлении электронного ключа произошла ошибка. Попробуйте ещё раз.
success: Ваш электронный ключ добавлен.
delete: Удалить
delete_confirmation: Вы действительно хотите удалить этот электронный ключ?
description_html: Если вы включите <strong>аутентификацию по электронным ключам</strong>, для входа в учётную запись вам будет предложено использовать один из ваших ключей.
destroy:
error: Произошла ошибка при удалении ключа безопасности. Пожалуйста, попробуйте еще раз.
error: При удалении электронного ключа произошла ошибка. Попробуйте ещё раз.
success: Ваш электронный ключ удалён.
invalid_credential: Неверный электронный ключ
nickname_hint: Введите название для нового электронного ключа
not_enabled: Вы еще не включили WebAuthn
not_supported: Этот браузер не поддерживает ключи безопасности
otp_required: Чтобы использовать ключи безопасности, сначала включите двухфакторную аутентификацию.
not_supported: В этом браузере отсутствует поддержка электронных ключей
otp_required: Чтобы использовать электронные ключи, сначала включите двухфакторную аутентификацию.
registered_on: Зарегистрирован %{date}

View File

@@ -149,6 +149,9 @@ ca:
min_age: No hauria de ser inferior a l'edat mínima exigida per la llei de la vostra jurisdicció.
user:
chosen_languages: Quan estigui marcat, només es mostraran els tuts de les llengües seleccionades en les línies de temps públiques
date_of_birth:
one: Ens hem d'assegurar que teniu com a mínim %{count} any per a fer servir %{domain}. No ho desarem.
other: Ens hem d'assegurar que teniu com a mínim %{count} anys per a fer servir %{domain}. No ho desarem.
role: El rol controla quins permisos té l'usuari.
user_role:
color: Color que s'usarà per al rol a tota la interfície d'usuari, com a RGB en format hexadecimal

View File

@@ -150,6 +150,11 @@ cs:
min_age: Neměla by být pod minimálním věkem požadovaným zákony vaší jurisdikce.
user:
chosen_languages: Po zaškrtnutí budou ve veřejných časových osách zobrazeny pouze příspěvky ve zvolených jazycích
date_of_birth:
few: Musíme se ujistit, že je Vám alespoň %{count}, abyste mohli používat %{domain}. Nebudeme to ukládat.
many: Musíme se ujistit, že je Vám alespoň %{count} let, abyste mohli používat %{domain}. Nebudeme to ukládat.
one: Musíme se ujistit, že je Vám alespoň %{count} rok, abyste mohli používat %{domain}. Nebudeme to ukládat.
other: Musíme se ujistit, že je Vám alespoň %{count}, abyste mohli používat %{domain}. Nebudeme to ukládat.
role: Role určuje, která oprávnění uživatel má.
user_role:
color: Barva, která má být použita pro roli v celém UI, jako RGB v hex formátu

View File

@@ -151,8 +151,8 @@ da:
user:
chosen_languages: Når markeret, vil kun indlæg på de valgte sprog fremgå på offentlige tidslinjer
date_of_birth:
one: Vi skal sikre os, at du er mindst %{count} for at kunne bruge %{domain}. Vi gemmer ikke dette.
other: Vi skal sikre os, at du er mindst %{count} for at kunne bruge %{domain}. Vi gemmer ikke dette.
one: Vi skal sikre os, at du er mindst %{count} for at kunne bruge %{domain}. Informationen gemmes ikke.
other: Vi skal sikre os, at du er mindst %{count} for at kunne bruge %{domain}. Informationen gemmes ikke.
role: Rollen styrer, hvilke tilladelser brugeren er tildelt.
user_role:
color: Farven, i RGB hex-format, der skal bruges til rollen i hele UI'en

View File

@@ -150,6 +150,9 @@ fo:
min_age: Eigur ikki at vera undir lægsta aldri, sum lógirnar í tínum rættarøki krevja.
user:
chosen_languages: Tá hetta er valt, verða einans postar í valdum málum vístir á almennum tíðarlinjum
date_of_birth:
one: Vit mugu tryggja okkum, at tú er í minsta lagi %{count} fyri at brúka %{domain}. Vit goyma ikki hesar upplýsingar.
other: Vit mugu tryggja okkum, at tú er í minsta lagi %{count} ár fyri at brúka %{domain}. Vit goyma ikki hesar upplýsingar.
role: Leikluturin stýrir hvørji rættindi, brúkarin hevur.
user_role:
color: Litur, sum leikluturin hevur í øllum brúkaramarkamótinum, sum RGB og upplýst sum sekstandatal

View File

@@ -150,6 +150,9 @@ fy:
min_age: Mei net leger wêze as de minimale fereaske leeftiid neffens de wetten fan jo jurisdiksje.
user:
chosen_languages: Allinnich berjochten yn de selektearre talen wurde op de iepenbiere tiidline toand
date_of_birth:
one: Wy moatte derfoar soargje dat jo op syn minst %{count} binne om %{domain} brûke te meien. Dit wurdt net bewarre.
other: Wy moatte derfoar soargje dat jo op syn minst %{count} binne om %{domain} brûke te meien. Dit wurdt net bewarre.
role: De rol bepaalt hokker rjochten in brûker hat.
user_role:
color: Kleur dyt brûkt wurdt foar de rol yn de UI, as RGB yn heksadesimaal formaat

View File

@@ -150,6 +150,9 @@ gl:
min_age: Non debería ser inferior á idade mínima requerida polas leis da túa xurisdición.
user:
chosen_languages: Se ten marca, só as publicacións nos idiomas seleccionados serán mostrados en cronoloxías públicas
date_of_birth:
one: Temos que confirmar que tes %{count} anos polo menos para usar %{domain}. Non gardamos este dato.
other: Temos que confirmar que tes %{count} anos polo menos para usar %{domain}. Non gardamos este dato.
role: Os roles establecen os permisos que ten a usuaria.
user_role:
color: Cor que se usará para o rol a través da IU, como RGB en formato hex

View File

@@ -150,6 +150,9 @@ is:
min_age: Ætti ekki að vera lægri en sá lágmarksaldur sek kveðið er á um í lögum þíns lögsagnarumdæmis.
user:
chosen_languages: Þegar merkt er við þetta, birtast einungis færslur á völdum tungumálum á opinberum tímalínum
date_of_birth:
one: Við verðum að ganga úr skugga um að þú hafir náð %{count} aldri til að nota %{domain}. Við munum ekki geyma þessar upplýsingar.
other: Við verðum að ganga úr skugga um að þú hafir náð %{count} aldri til að nota %{domain}. Við munum ekki geyma þessar upplýsingar.
role: Hlutverk stýrir hvaða heimildir notandinn hefur.
user_role:
color: Litur sem notaður er fyrir hlutverkið allsstaðar í viðmótinu, sem RGB-gildi á hex-sniði

View File

@@ -150,6 +150,9 @@ it:
min_age: Non si dovrebbe avere un'età inferiore a quella minima richiesta, dalle leggi della tua giurisdizione.
user:
chosen_languages: Quando una o più lingue sono contrassegnate, nelle timeline pubbliche vengono mostrati solo i toot nelle lingue selezionate
date_of_birth:
one: Dobbiamo assicurarci che tu abbia almeno %{count} anni per utilizzare %{domain}. Non memorizzeremo questo dato.
other: Dobbiamo assicurarci che tu abbia almeno %{count} anni per utilizzare %{domain}. Non memorizzeremo questo dato.
role: Il ruolo controlla quali permessi ha l'utente.
user_role:
color: Colore da usare per il ruolo in tutta l'UI, come RGB in formato esadecimale

View File

@@ -8,7 +8,7 @@ ru:
display_name: Ваше полное имя или псевдоним.
fields: Домашняя страница, местоимения, возраст — всё что угодно.
indexable: Отметьте флажок, чтобы ваши публичные посты могли быть найдены при помощи поиска в Mastodon. Люди, которые взаимодействовали с вашими постами, смогут их найти вне зависимости от этой настройки.
note: 'Вы можете @упоминать других людей или использовать #хештеги.'
note: 'Вы можете @упоминать других людей, а также использовать #хештеги.'
show_collections: Отметьте флажок, чтобы кто угодно мог просматривать списки ваших подписок и подписчиков. Люди, на которых вы подписаны, будут знать о том, что вы на них подписаны, вне зависимости от этой настройки.
unlocked: 'Отметьте флажок, чтобы на вас можно было подписаться, не запрашивая подтверждения. Снимите флажок, чтобы вы могли просматривать запросы на подписку и выбирать: принять или отклонить новых подписчиков.'
account_alias: