From 01d96998e4a9f39fdcbf2417eb056cd2a71da260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Wed, 25 Feb 2026 23:28:59 +0100 Subject: [PATCH] nicolium: random a11y improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-fe/src/components/account.tsx | 16 ++++++++-- .../components/authorize-reject-buttons.tsx | 13 ++++++++- .../pl-fe/src/components/preview-card.tsx | 13 ++++++++- .../auth-login/components/consumer-button.tsx | 1 + .../chats/components/chat-composer.tsx | 2 ++ .../components/chat-search/chat-search.tsx | 9 +++++- .../features/chats/components/chat-upload.tsx | 28 ++++++++++++------ .../chats-page/components/chats-page-chat.tsx | 2 ++ .../chats-page/components/chats-page-new.tsx | 2 ++ .../components/chats-page-settings.tsx | 2 ++ .../components/chats-page-shoutbox.tsx | 8 ++++- .../components/chats-page-sidebar.tsx | 4 +++ .../chats/components/shoutbox-composer.tsx | 1 + .../compose-event/tabs/edit-event.tsx | 12 +++++++- .../compose/editor/nodes/image-component.tsx | 4 +++ .../plugins/floating-link-editor-plugin.tsx | 29 ++++++++++++++++++- .../floating-text-format-toolbar-plugin.tsx | 4 ++- .../edit-profile/components/header-picker.tsx | 8 ++++- .../group/components/group-options-button.tsx | 2 ++ packages/pl-fe/src/locales/en.json | 18 ++++++++++++ .../pl-fe/src/pages/dashboard/reports.tsx | 2 ++ packages/pl-fe/src/pages/search/search.tsx | 2 ++ .../pages/settings/rss-feed-subscriptions.tsx | 2 ++ .../src/pages/timelines/remote-timeline.tsx | 8 ++++- 24 files changed, 172 insertions(+), 20 deletions(-) diff --git a/packages/pl-fe/src/components/account.tsx b/packages/pl-fe/src/components/account.tsx index 3de4f3f09..1fe176f2d 100644 --- a/packages/pl-fe/src/components/account.tsx +++ b/packages/pl-fe/src/components/account.tsx @@ -65,7 +65,14 @@ const InstanceFavicon: React.FC = ({ account, disabled }) => { const className = 'size-4 flex-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2'; if (disabled) { - return ; + return ( + {account.domain} + ); } return ( @@ -75,7 +82,12 @@ const InstanceFavicon: React.FC = ({ account, disabled }) => { disabled={disabled} title={intl.formatMessage(messages.timeline, { domain: account.domain })} > - + {account.domain} ); }; diff --git a/packages/pl-fe/src/components/authorize-reject-buttons.tsx b/packages/pl-fe/src/components/authorize-reject-buttons.tsx index 524f146f8..a65770f54 100644 --- a/packages/pl-fe/src/components/authorize-reject-buttons.tsx +++ b/packages/pl-fe/src/components/authorize-reject-buttons.tsx @@ -1,11 +1,16 @@ import clsx from 'clsx'; import React, { useEffect, useRef, useState } from 'react'; -import { FormattedMessage } from 'react-intl'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import HStack from '@/components/ui/hstack'; import IconButton from '@/components/ui/icon-button'; import Text from '@/components/ui/text'; +const messages = defineMessages({ + authorize: { id: 'authorize.action', defaultMessage: 'Approve' }, + reject: { id: 'reject.action', defaultMessage: 'Reject' }, +}); + interface IAuthorizeRejectButtons { onAuthorize(): Promise | unknown; onReject(): Promise | unknown; @@ -18,6 +23,7 @@ const AuthorizeRejectButtons: React.FC = ({ onReject, countdown, }) => { + const intl = useIntl(); const [state, setState] = useState< 'authorizing' | 'rejecting' | 'authorized' | 'rejected' | 'pending' >('pending'); @@ -129,6 +135,7 @@ const AuthorizeRejectButtons: React.FC = ({ isLoading={state === 'rejecting'} disabled={state === 'authorizing'} style={renderStyle('rejecting')} + title={intl.formatMessage(messages.reject)} /> = ({ isLoading={state === 'authorizing'} disabled={state === 'rejecting'} style={renderStyle('authorizing')} + title={intl.formatMessage(messages.authorize)} /> ); @@ -162,6 +170,7 @@ interface IAuthorizeRejectButton { isLoading?: boolean; disabled?: boolean; style: React.CSSProperties; + title?: string; } const AuthorizeRejectButton: React.FC = ({ @@ -171,6 +180,7 @@ const AuthorizeRejectButton: React.FC = ({ isLoading, style, disabled, + title, }) => (
= ({ 'text-danger-600': theme === 'danger', })} disabled={disabled} + title={title} />
diff --git a/packages/pl-fe/src/components/preview-card.tsx b/packages/pl-fe/src/components/preview-card.tsx index dee55b1a4..c3af67034 100644 --- a/packages/pl-fe/src/components/preview-card.tsx +++ b/packages/pl-fe/src/components/preview-card.tsx @@ -7,7 +7,7 @@ import { mediaAttachmentSchema, } from 'pl-api'; import React, { useState, useEffect } from 'react'; -import { FormattedMessage } from 'react-intl'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import * as v from 'valibot'; import Blurhash from '@/components/blurhash'; @@ -23,6 +23,12 @@ import Purify from '@/utils/url-purify'; import HoverAccountWrapper from './hover-account-wrapper'; import Avatar from './ui/avatar'; +const messages = defineMessages({ + play: { id: 'preview_card.play', defaultMessage: 'Play' }, + expand: { id: 'preview_card.expand', defaultMessage: 'Enlarge image' }, + externalLink: { id: 'preview_card.external_link', defaultMessage: 'Open in new tab' }, +}); + const domParser = new DOMParser(); const handleIframeUrl = (html: string, url: string, providerName: string) => { @@ -106,6 +112,7 @@ const PreviewCard: React.FC = ({ cacheWidth, onOpenMedia, }): React.JSX.Element => { + const intl = useIntl(); const { urlPrivacy: { clearLinksInContent, redirectLinksMode }, } = useSettings(); @@ -253,6 +260,9 @@ const PreviewCard: React.FC = ({ @@ -266,6 +276,7 @@ const PreviewCard: React.FC = ({ target='_blank' rel='noopener' className='text-gray-700 hover:text-gray-900 dark:text-gray-200 dark:hover:text-gray-100' + title={intl.formatMessage(messages.externalLink)} > = ({ provider }) => { iconClassName='h-6 w-6' src={icon} onClick={handleClick} + title={intl.formatMessage(messages.tooltip, { provider: capitalize(provider) })} /> ); diff --git a/packages/pl-fe/src/features/chats/components/chat-composer.tsx b/packages/pl-fe/src/features/chats/components/chat-composer.tsx index 18957dd8a..3e0bede28 100644 --- a/packages/pl-fe/src/features/chats/components/chat-composer.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-composer.tsx @@ -30,6 +30,7 @@ import type { MediaAttachment } from 'pl-api'; const messages = defineMessages({ placeholder: { id: 'chat.input.placeholder', defaultMessage: 'Type a message' }, + send: { id: 'chat.actions.send', defaultMessage: 'Send' }, unblockMessage: { id: 'chat_settings.unblock.message', defaultMessage: @@ -256,6 +257,7 @@ const ChatComposer = React.forwardRef className='text-primary-500' disabled={isSubmitDisabled} onClick={onSubmit} + title={intl.formatMessage(messages.send)} /> diff --git a/packages/pl-fe/src/features/chats/components/chat-search/chat-search.tsx b/packages/pl-fe/src/features/chats/components/chat-search/chat-search.tsx index b359708d9..9ff865a3c 100644 --- a/packages/pl-fe/src/features/chats/components/chat-search/chat-search.tsx +++ b/packages/pl-fe/src/features/chats/components/chat-search/chat-search.tsx @@ -21,6 +21,8 @@ import type { PlfeResponse } from '@/api'; const messages = defineMessages({ placeholder: { id: 'chat_search.placeholder', defaultMessage: 'Type a name' }, + clearSearch: { id: 'chat_search.clear', defaultMessage: 'Clear search' }, + search: { id: 'chat_search.search', defaultMessage: 'Search' }, }); interface IChatSearch { @@ -101,7 +103,12 @@ const ChatSearch: React.FC = ({ isMainPage = false }) => { outerClassName='mt-0' theme='search' append={ - -); +const RemoveButton: React.FC = ({ onClick }) => { + const intl = useIntl(); + + return ( + + ); +}; export { ChatUpload as default }; diff --git a/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-chat.tsx b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-chat.tsx index 1ff037c4b..7de81cfda 100644 --- a/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-chat.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-chat.tsx @@ -46,6 +46,7 @@ const messages = defineMessages({ blockUser: { id: 'chat_settings.options.block_user', defaultMessage: 'Block @{acct}' }, unblockUser: { id: 'chat_settings.options.unblock_user', defaultMessage: 'Unblock @{acct}' }, leaveChat: { id: 'chat_settings.options.leave_chat', defaultMessage: 'Leave chat' }, + back: { id: 'chats.back', defaultMessage: 'Back to chats' }, }); const ChatsPageChat = () => { @@ -129,6 +130,7 @@ const ChatsPageChat = () => { src={require('@phosphor-icons/core/regular/arrow-left.svg')} className='mr-2 size-7 sm:mr-0 sm:hidden rtl:rotate-180' onClick={() => navigate({ to: '/chats' })} + title={intl.formatMessage(messages.back)} /> diff --git a/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-new.tsx b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-new.tsx index a868d37a4..06fd4eeae 100644 --- a/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-new.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-new.tsx @@ -11,6 +11,7 @@ import ChatSearch from '../../chat-search/chat-search'; const messages = defineMessages({ title: { id: 'chat.new_message.title', defaultMessage: 'New Message' }, + back: { id: 'chats.back', defaultMessage: 'Back to chats' }, }); /** New message form to create a chat. */ @@ -26,6 +27,7 @@ const ChatsPageNew: React.FC = () => { src={require('@phosphor-icons/core/regular/arrow-left.svg')} className='mr-2 size-7 sm:mr-0 sm:hidden rtl:rotate-180' onClick={() => navigate({ to: '/chats' })} + title={intl.formatMessage(messages.back)} /> diff --git a/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-settings.tsx b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-settings.tsx index ad0fd4329..573100299 100644 --- a/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-settings.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-settings.tsx @@ -40,6 +40,7 @@ const messages = defineMessages({ defaultMessage: 'Chat settings updated successfully', }, fail: { id: 'settings.messages.fail', defaultMessage: 'Failed to update chat settings' }, + back: { id: 'chats.back', defaultMessage: 'Back to chats' }, }); const ChatsPageSettings = () => { @@ -78,6 +79,7 @@ const ChatsPageSettings = () => { src={require('@phosphor-icons/core/regular/arrow-left.svg')} className='mr-2 size-7 sm:mr-0 sm:hidden rtl:rotate-180' onClick={() => navigate({ to: '/chats' })} + title={intl.formatMessage(messages.back)} /> diff --git a/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-shoutbox.tsx b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-shoutbox.tsx index 6052ef6d6..fd5dbd3c6 100644 --- a/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-shoutbox.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-shoutbox.tsx @@ -1,6 +1,6 @@ import { useNavigate } from '@tanstack/react-router'; import React from 'react'; -import { FormattedMessage } from 'react-intl'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import Avatar from '@/components/ui/avatar'; import HStack from '@/components/ui/hstack'; @@ -12,8 +12,13 @@ import { useInstance } from '@/hooks/use-instance'; import Shoutbox from '../../shoutbox'; +const messages = defineMessages({ + back: { id: 'chats.back', defaultMessage: 'Back to chats' }, +}); + const ChatsPageShoutbox = () => { const navigate = useNavigate(); + const intl = useIntl(); const instance = useInstance(); const { logo } = useFrontendConfig(); @@ -26,6 +31,7 @@ const ChatsPageShoutbox = () => { src={require('@phosphor-icons/core/regular/arrow-left.svg')} className='mr-2 size-7 sm:mr-0 sm:hidden rtl:rotate-180' onClick={() => navigate({ to: '/chats' })} + title={intl.formatMessage(messages.back)} /> diff --git a/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-sidebar.tsx b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-sidebar.tsx index 26adba16b..66f7f3fcf 100644 --- a/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-sidebar.tsx +++ b/packages/pl-fe/src/features/chats/components/chats-page/components/chats-page-sidebar.tsx @@ -13,6 +13,8 @@ import type { Chat } from 'pl-api'; const messages = defineMessages({ title: { id: 'column.chats', defaultMessage: 'Chats' }, + settings: { id: 'chat_list_item.settings', defaultMessage: 'Chat settings' }, + newChat: { id: 'chat_pane.header.new_chat', defaultMessage: 'New chat' }, }); const ChatsPageSidebar = () => { @@ -49,12 +51,14 @@ const ChatsPageSidebar = () => { src={require('@phosphor-icons/core/regular/sliders-horizontal.svg')} iconClassName='h-5 w-5 text-gray-600' onClick={handleSettingsClick} + title={intl.formatMessage(messages.settings)} /> diff --git a/packages/pl-fe/src/features/chats/components/shoutbox-composer.tsx b/packages/pl-fe/src/features/chats/components/shoutbox-composer.tsx index 1fc8bc300..3670f803a 100644 --- a/packages/pl-fe/src/features/chats/components/shoutbox-composer.tsx +++ b/packages/pl-fe/src/features/chats/components/shoutbox-composer.tsx @@ -108,6 +108,7 @@ const ShoutboxComposer = React.forwardRef diff --git a/packages/pl-fe/src/features/compose-event/tabs/edit-event.tsx b/packages/pl-fe/src/features/compose-event/tabs/edit-event.tsx index b1e5b3460..a2279b7d7 100644 --- a/packages/pl-fe/src/features/compose-event/tabs/edit-event.tsx +++ b/packages/pl-fe/src/features/compose-event/tabs/edit-event.tsx @@ -57,6 +57,10 @@ const messages = defineMessages({ id: 'compose_event.header_description', defaultMessage: 'Add header alt text.', }, + eventHeaderDescriptionPlaceholder: { + id: 'compose_event.header_description_placeholder', + defaultMessage: 'Event banner', + }, }); interface IEditEvent { @@ -263,7 +267,13 @@ const EditEvent: React.FC = ({ statusId }) => {
{banner ? ( <> - + { diff --git a/packages/pl-fe/src/features/compose/editor/plugins/floating-link-editor-plugin.tsx b/packages/pl-fe/src/features/compose/editor/plugins/floating-link-editor-plugin.tsx index cf481b3af..a1f9b054e 100644 --- a/packages/pl-fe/src/features/compose/editor/plugins/floating-link-editor-plugin.tsx +++ b/packages/pl-fe/src/features/compose/editor/plugins/floating-link-editor-plugin.tsx @@ -19,6 +19,7 @@ import { import { useCallback, useEffect, useRef, useState } from 'react'; import * as React from 'react'; import { createPortal } from 'react-dom'; +import { defineMessages, useIntl } from 'react-intl'; import Icon from '@/components/ui/icon'; @@ -26,6 +27,11 @@ import { getSelectedNode } from '../utils/get-selected-node'; import { setFloatingElemPosition } from '../utils/set-floating-elem-position'; import { sanitizeUrl } from '../utils/url'; +const messages = defineMessages({ + editLink: { id: 'compose_form.lexical.edit_link', defaultMessage: 'Edit link' }, + removeLink: { id: 'compose_form.lexical.remove_link', defaultMessage: 'Remove link' }, +}); + const FloatingLinkEditor = ({ editor, anchorElem, @@ -39,6 +45,8 @@ const FloatingLinkEditor = ({ const [isEditMode, setEditMode] = useState(false); const [lastSelection, setLastSelection] = useState(null); + const intl = useIntl(); + const updateLinkEditor = useCallback(() => { const selection = $getSelection(); if ($isRangeSelection(selection)) { @@ -185,14 +193,25 @@ const FloatingLinkEditor = ({ className='absolute inset-y-0 right-0 flex w-9 cursor-pointer items-center justify-center' role='button' tabIndex={0} + aria-label={intl.formatMessage(messages.removeLink)} onMouseDown={(event) => { event.preventDefault(); }} onClick={() => { editor.dispatchCommand(TOGGLE_LINK_COMMAND, null); }} + onKeyDown={(event) => { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + editor.dispatchCommand(TOGGLE_LINK_COMMAND, null); + } + }} > - +
) : ( @@ -209,16 +228,24 @@ const FloatingLinkEditor = ({ className='absolute inset-y-0 right-0 flex w-9 cursor-pointer items-center justify-center' role='button' tabIndex={0} + aria-label={intl.formatMessage(messages.editLink)} onMouseDown={(event) => { event.preventDefault(); }} onClick={() => { setEditMode(true); }} + onKeyDown={(event) => { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + setEditMode(true); + } + }} > diff --git a/packages/pl-fe/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx b/packages/pl-fe/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx index 55297e361..6563e588f 100644 --- a/packages/pl-fe/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx +++ b/packages/pl-fe/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx @@ -62,6 +62,7 @@ const messages = defineMessages({ defaultMessage: 'Insert code block', }, insertLink: { id: 'compose_form.lexical.insert_link', defaultMessage: 'Insert link' }, + blockType: { id: 'compose_form.lexical.block_type', defaultMessage: 'Change block type' }, }); const blockTypeToIcon = { @@ -124,6 +125,7 @@ const BlockTypeDropdown = ({ icon: string; }) => { const { composeAllowHeadings } = useFeatures(); + const intl = useIntl(); const [showDropDown, setShowDropDown] = useState(false); @@ -201,7 +203,7 @@ const BlockTypeDropdown = ({ setShowDropDown(!showDropDown); }} className='relative flex cursor-pointer rounded-lg border-0 bg-none p-1 align-middle hover:bg-gray-100 disabled:cursor-not-allowed disabled:hover:bg-none dark:hover:bg-primary-700' - aria-label='' + aria-label={intl.formatMessage(messages.blockType)} type='button' > diff --git a/packages/pl-fe/src/features/edit-profile/components/header-picker.tsx b/packages/pl-fe/src/features/edit-profile/components/header-picker.tsx index ab4ac15ef..a08fabf7e 100644 --- a/packages/pl-fe/src/features/edit-profile/components/header-picker.tsx +++ b/packages/pl-fe/src/features/edit-profile/components/header-picker.tsx @@ -82,7 +82,13 @@ const HeaderPicker = React.forwardRef( title={intl.formatMessage(messages.title)} tabIndex={0} > - {src && } + {src && ( + {intl.formatMessage(messages.title)} + )} { iconClassName='h-5 w-5' className='self-stretch px-2.5' data-testid='dropdown-menu-button' + title={intl.formatMessage(messages.groupOptions)} /> ); diff --git a/packages/pl-fe/src/locales/en.json b/packages/pl-fe/src/locales/en.json index 17fbbd0e8..95965bf87 100644 --- a/packages/pl-fe/src/locales/en.json +++ b/packages/pl-fe/src/locales/en.json @@ -326,6 +326,7 @@ "auth.awaiting_approval": "Your account is awaiting approval", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", + "authorize.action": "Approve", "authorize.success": "Approved", "backups.actions.create": "Create backup", "backups.download": "Download", @@ -357,6 +358,7 @@ "bundle_column_error.retry": "Try again", "bundle_column_error.title": "Network error", "card.back.label": "Back", + "chat.actions.remove_attachment": "Remove attachment", "chat.actions.send": "Send", "chat.failed_to_send": "Message failed to send.", "chat.input.placeholder": "Type a message", @@ -387,9 +389,11 @@ "chat_pane.header.new_chat": "New chat", "chat_search.blankslate.body": "Search for someone to chat with.", "chat_search.blankslate.title": "Start a chat", + "chat_search.clear": "Clear search", "chat_search.empty_results_blankslate.body": "Try searching for another name.", "chat_search.empty_results_blankslate.title": "No matches found", "chat_search.placeholder": "Type a name", + "chat_search.search": "Search", "chat_search.title": "Messages", "chat_settings.block.confirm": "Block", "chat_settings.block.heading": "Block @{acct}", @@ -408,6 +412,7 @@ "chats.actions.delete": "Delete for both", "chats.actions.delete_for_me": "Delete for me", "chats.actions.more": "More", + "chats.back": "Back to chats", "chats.dividers.today": "Today", "chats.main.blankslate.new_chat": "Message someone", "chats.main.blankslate.subtitle": "Search for someone to chat with", @@ -441,6 +446,7 @@ "column.admin.moderation_log": "Moderation log", "column.admin.relays": "Instance relays", "column.admin.reports": "Reports", + "column.admin.reports.clear_filter": "Clear filter", "column.admin.reports.filter_message": "You are displaying reports {query}.", "column.admin.reports.filter_message.account": "from @{acct}", "column.admin.reports.filter_message.target_account": "targeting @{acct}", @@ -606,6 +612,7 @@ "compose_event.fields.start_time_label": "Event start date", "compose_event.fields.start_time_placeholder": "Event begins on…", "compose_event.header_description": "Add header alt text.", + "compose_event.header_description_placeholder": "Event banner", "compose_event.participation_requests.authorize": "Authorize", "compose_event.participation_requests.authorize.fail": "Failed to authorize event participation request", "compose_event.participation_requests.authorize.success": "Event participation request authorized successfully", @@ -628,13 +635,16 @@ "compose_form.event_placeholder": "Post to this event", "compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.", "compose_form.interaction_policy.label": "Manage interaction policy", + "compose_form.lexical.block_type": "Change block type", "compose_form.lexical.create_horizontal_line": "Create horizontal line", + "compose_form.lexical.edit_link": "Edit link", "compose_form.lexical.format_bold": "Format bold", "compose_form.lexical.format_italic": "Format italic", "compose_form.lexical.format_strikethrough": "Format strikethrough", "compose_form.lexical.format_underline": "Format underline", "compose_form.lexical.insert_code_block": "Insert code block", "compose_form.lexical.insert_link": "Insert link", + "compose_form.lexical.remove_link": "Remove link", "compose_form.lexical.upload_media": "Upload media", "compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.", "compose_form.lock_disclaimer.lock": "locked", @@ -1095,6 +1105,7 @@ "group.manage": "Manage group", "group.member.admin.limit.summary": "You can assign up to {count, plural, one {admin} other {admins}} for the group at this time.", "group.member.admin.limit.title": "Admin limit reached", + "group.options": "Group options", "group.popover.action": "View group", "group.popover.summary": "You must be a member of the group in order to reply to this status.", "group.popover.title": "Membership required", @@ -1583,6 +1594,9 @@ "preferences.options.privacy_followers_only": "Followers-only", "preferences.options.privacy_public": "Public", "preferences.options.privacy_unlisted": "Unlisted", + "preview_card.expand": "Enlarge image", + "preview_card.external_link": "Open in new tab", + "preview_card.play": "Play", "privacy.change": "Adjust post privacy", "privacy.circle.long": "Visible to members of a circle", "privacy.circle.short": "Circle only", @@ -1632,6 +1646,7 @@ "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", "registration.username_unavailable": "Username is already taken.", + "reject.action": "Reject", "reject.success": "Rejected", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", @@ -1662,6 +1677,7 @@ "remote_interaction.reply": "Proceed to reply", "remote_interaction.reply_title": "Reply to a post remotely", "remote_interaction.user_not_found_error": "Couldn't find given user", + "remote_timeline.close": "Close remote timeline", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancel", "reply_mentions.account.add": "Add to mentions", @@ -1702,6 +1718,7 @@ "rss_feed.label": "RSS Feed", "rss_feed_subscriptions.add.fail": "Failed to subsrcibe to RSS feed", "rss_feed_subscriptions.add.success": "Successfully subscribed to RSS feed", + "rss_feed_subscriptions.delete": "Delete feed", "rss_feed_subscriptions.list.heading": "Subscribed feeds", "rss_feed_subscriptions.new.create_title": "Subscribe", "rss_feed_subscriptions.new.heading": "Subscribe to a new RSS feed", @@ -1714,6 +1731,7 @@ "scheduled_status.cancel": "Cancel", "search.action": "Search for “{query}”", "search.clear": "Clear input", + "search.clear_account_filter": "Clear account filter", "search.placeholder": "Search", "search_results.accounts": "People", "search_results.filter_message": "You are searching for posts from @{acct}.", diff --git a/packages/pl-fe/src/pages/dashboard/reports.tsx b/packages/pl-fe/src/pages/dashboard/reports.tsx index a7353d87f..ce53d37e8 100644 --- a/packages/pl-fe/src/pages/dashboard/reports.tsx +++ b/packages/pl-fe/src/pages/dashboard/reports.tsx @@ -14,6 +14,7 @@ import { useReports } from '@/queries/admin/use-reports'; const messages = defineMessages({ heading: { id: 'column.admin.reports', defaultMessage: 'Reports' }, + clearFilter: { id: 'column.admin.reports.clear_filter', defaultMessage: 'Clear filter' }, }); const Reports: React.FC = () => { @@ -54,6 +55,7 @@ const Reports: React.FC = () => { iconClassName='h-5 w-5' src={require('@phosphor-icons/core/regular/x.svg')} onClick={handleUnsetAccounts} + title={intl.formatMessage(messages.clearFilter)} /> { iconClassName='h-5 w-5' src={require('@phosphor-icons/core/regular/x.svg')} onClick={handleUnsetAccount} + title={intl.formatMessage(messages.clearAccountFilter)} /> { disabled={isPending} className='size-8 text-gray-700 dark:text-gray-600' src={require('@phosphor-icons/core/regular/x.svg')} + title={intl.formatMessage(messages.deleteFeed)} /> } diff --git a/packages/pl-fe/src/pages/timelines/remote-timeline.tsx b/packages/pl-fe/src/pages/timelines/remote-timeline.tsx index e1367c1c1..c991ebc9c 100644 --- a/packages/pl-fe/src/pages/timelines/remote-timeline.tsx +++ b/packages/pl-fe/src/pages/timelines/remote-timeline.tsx @@ -1,6 +1,6 @@ import { useNavigate } from '@tanstack/react-router'; import React, { useEffect } from 'react'; -import { FormattedMessage } from 'react-intl'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { fetchPublicTimeline } from '@/actions/timelines'; import { useRemoteStream } from '@/api/hooks/streaming/use-remote-stream'; @@ -14,10 +14,15 @@ import { remoteTimelineRoute } from '@/features/ui/router'; import { useAppDispatch } from '@/hooks/use-app-dispatch'; import { useSettings } from '@/stores/settings'; +const messages = defineMessages({ + close: { id: 'remote_timeline.close', defaultMessage: 'Close remote timeline' }, +}); + /** View statuses from a remote instance. */ const RemoteTimelinePage: React.FC = () => { const { instance } = remoteTimelineRoute.useParams(); + const intl = useIntl(); const navigate = useNavigate(); const dispatch = useAppDispatch(); @@ -53,6 +58,7 @@ const RemoteTimelinePage: React.FC = () => { iconClassName='h-5 w-5' src={require('@phosphor-icons/core/regular/x.svg')} onClick={handleCloseClick} + title={intl.formatMessage(messages.close)} />