Groups: Make strings localizable

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
environments/review-mastodon-g-0qbqe2/deployments/1773
marcin mikołajczak 2022-12-17 00:33:07 +01:00
rodzic 0d617d4de8
commit fd6e3f4032
7 zmienionych plików z 93 dodań i 37 usunięć

Wyświetl plik

@ -1,5 +1,5 @@
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
import { Avatar, HStack, Icon, Stack, Text } from './ui';
@ -31,23 +31,23 @@ const GroupCard: React.FC<IGroupCard> = ({ group }) => {
{group.relationship?.role === 'admin' ? (
<HStack space={1} alignItems='center'>
<Icon className='h-4 w-4' src={require('@tabler/icons/users.svg')} />
<span>Owner</span>
<span><FormattedMessage id='group.role.owner' defaultMessage='Owner' /></span>
</HStack>
) : group.relationship?.role === 'moderator' && (
<HStack space={1} alignItems='center'>
<Icon className='h-4 w-4' src={require('@tabler/icons/gavel.svg')} />
<span>Moderator</span>
<span><FormattedMessage id='group.role.moderator' defaultMessage='Moderator' /></span>
</HStack>
)}
{group.locked ? (
<HStack space={1} alignItems='center'>
<Icon className='h-4 w-4' src={require('@tabler/icons/lock.svg')} />
<span>Private</span>
<span><FormattedMessage id='group.privacy.locked' defaultMessage='Private' /></span>
</HStack>
) : (
<HStack space={1} alignItems='center'>
<Icon className='h-4 w-4' src={require('@tabler/icons/world.svg')} />
<span>Public</span>
<span><FormattedMessage id='group.privacy.public' defaultMessage='Public' /></span>
</HStack>
)}
</HStack>

Wyświetl plik

@ -13,6 +13,9 @@ import type { Group } from 'soapbox/types/entities';
const messages = defineMessages({
header: { id: 'group.header.alt', defaultMessage: 'Group header' },
confirmationHeading: { id: 'confirmations.leave_group.heading', defaultMessage: 'Leave group' },
confirmationMessage: { id: 'confirmations.leave_group.message', defaultMessage: 'You are about to leave the group. Do you want to continue?' },
confirmationConfirm: { id: 'confirmations.leave_group.confirm', defaultMessage: 'Leave' },
});
interface IGroupHeader {
@ -49,9 +52,9 @@ const GroupHeader: React.FC<IGroupHeader> = ({ group }) => {
const onLeaveGroup = () => {
dispatch(openModal('CONFIRM', {
heading: 'Leave group',
message: 'You are about to leave the group. Do you want to continue?',
confirm: 'Leave',
heading: intl.formatMessage(messages.confirmationHeading),
message: intl.formatMessage(messages.confirmationMessage),
confirm: intl.formatMessage(messages.confirmationConfirm),
onConfirm: () => {
dispatch(leaveGroup(group.id));
},
@ -99,7 +102,7 @@ const GroupHeader: React.FC<IGroupHeader> = ({ group }) => {
theme='primary'
onClick={onJoinGroup}
>
{group.locked ? 'Request to join group' : 'Join group'}
{group.locked ? <FormattedMessage id='group.request_join' defaultMessage='Request to join group' /> : <FormattedMessage id='group.join' defaultMessage='Join group' />}
</Button>
);
}
@ -110,7 +113,7 @@ const GroupHeader: React.FC<IGroupHeader> = ({ group }) => {
theme='secondary'
onClick={onEditGroup}
>
<FormattedMessage id='group.manage' defaultMessage='Edit group' />
<FormattedMessage id='group.manage' defaultMessage='Edit group' />
</Button>
);
}
@ -120,7 +123,7 @@ const GroupHeader: React.FC<IGroupHeader> = ({ group }) => {
theme='secondary'
onClick={onLeaveGroup}
>
<FormattedMessage id='group.leave' defaultMessage='Leave group' />
<FormattedMessage id='group.leave' defaultMessage='Leave group' />
</Button>
);
};
@ -153,23 +156,23 @@ const GroupHeader: React.FC<IGroupHeader> = ({ group }) => {
{group.relationship?.role === 'admin' ? (
<HStack space={1} alignItems='center'>
<Icon className='h-4 w-4' src={require('@tabler/icons/users.svg')} />
<span>Owner</span>
<span><FormattedMessage id='group.role.owner' defaultMessage='Owner' /></span>
</HStack>
) : group.relationship?.role === 'moderator' && (
<HStack space={1} alignItems='center'>
<Icon className='h-4 w-4' src={require('@tabler/icons/gavel.svg')} />
<span>Moderator</span>
<span><FormattedMessage id='group.role.moderator' defaultMessage='Moderator' /></span>
</HStack>
)}
{group.locked ? (
<HStack space={1} alignItems='center'>
<Icon className='h-4 w-4' src={require('@tabler/icons/lock.svg')} />
<span>Private</span>
<span><FormattedMessage id='group.privacy.locked' defaultMessage='Private' /></span>
</HStack>
) : (
<HStack space={1} alignItems='center'>
<Icon className='h-4 w-4' src={require('@tabler/icons/world.svg')} />
<span>Public</span>
<span><FormattedMessage id='group.privacy.public' defaultMessage='Public' /></span>
</HStack>
)}
</HStack>

Wyświetl plik

@ -17,7 +17,6 @@ interface IGroupMembers {
}
const messages = defineMessages({
heading: { id: 'column.group_members', defaultMessage: 'Group members' },
adminSubheading: { id: 'groups.admin_subheading', defaultMessage: 'Group administrators' },
moderatorSubheading: { id: 'groups.moderator_subheading', defaultMessage: 'Group moderators' },
userSubheading: { id: 'groups.user_subheading', defaultMessage: 'Users' },

Wyświetl plik

@ -30,7 +30,7 @@ const getOrderedGroups = createSelector([
.sort((a, b) => a.display_name.localeCompare(b.display_name));
});
const Lists: React.FC = () => {
const Groups: React.FC = () => {
const dispatch = useDispatch();
const groups = useAppSelector((state) => getOrderedGroups(state));
@ -69,7 +69,7 @@ const Lists: React.FC = () => {
return (
<ScrollableList
scrollKey='lists'
scrollKey='groups'
emptyMessage={emptyMessage}
itemClassName='py-3 last:pb-0'
>
@ -82,4 +82,4 @@ const Lists: React.FC = () => {
);
};
export default Lists;
export default Groups;

Wyświetl plik

@ -27,25 +27,27 @@ const PrivacyStep = () => {
</Stack>
<Form>
<FormGroup
labelText='Privacy settings'
labelText={<FormattedMessage id='manage_group.privacy.label' defaultMessage='Privacy settings' />}
>
<List>
<ListItem
label='Public'
hint='Discoverable. Anyone can join.'
label={<FormattedMessage id='manage_group.privacy.public.label' defaultMessage='Public' />}
hint={<FormattedMessage id='manage_group.privacy.public.hint' defaultMessage='Discoverable. Anyone can join.' />}
onSelect={() => onChangePrivacy(false)}
isSelected={!locked}
/>
<ListItem
label='Private (Owner approval required)'
hint='Discoverable. Users can join after their request is approved.'
label={<FormattedMessage id='manage_group.privacy.private.label' defaultMessage='Private (Owner approval required)' />}
hint={<FormattedMessage id='manage_group.privacy.private.hint' defaultMessage='Discoverable. Users can join after their request is approved.' />}
onSelect={() => onChangePrivacy(true)}
isSelected={locked}
/>
</List>
</FormGroup>
<Text size='sm' theme='muted' align='center'>These settings cannot be changed later.</Text>
<Text size='sm' theme='muted' align='center'>
<FormattedMessage id='manage_group.privacy.hint' defaultMessage='These settings cannot be changed later.' />
</Text>
</Form>
</>
);

Wyświetl plik

@ -457,6 +457,9 @@
"confirmations.domain_block.message": "Czy na pewno chcesz zablokować całą domenę {domain}? Zwykle lepszym rozwiązaniem jest blokada lub wyciszenie kilku użytkowników.",
"confirmations.leave_event.confirm": "Opuść wydarzenie",
"confirmations.leave_event.message": "Jeśli będziesz chciał(a) dołączyć do wydarzenia jeszcze raz, prośba będzie musiała zostać ponownie zatwierdzona. Czy chcesz kontynuować?",
"confirmations.leave_group.confirm": "Opuść",
"confirmations.leave_group.message": "Czy na pewno chcesz opuścić tę grupę?",
"confirmations.leave_group.heading": "Opuść grupę",
"confirmations.mute.confirm": "Wycisz",
"confirmations.mute.heading": "Wycisz @{name}",
"confirmations.mute.message": "Czy na pewno chcesz wyciszyć {name}?",
@ -611,6 +614,7 @@
"empty_column.filters": "Nie wyciszyłeś(-aś) jeszcze żadnego słowa.",
"empty_column.follow_recommendations": "Wygląda na to, że nie można wygenerować dla Ciebie sugestii kont do obserwacji. Możesz spróbować użyć wyszukiwania aby odnaleźć ciekawe profile, lub przejrzeć trendujące hashtagi.",
"empty_column.follow_requests": "Nie masz żadnych próśb o możliwość obserwacji. Kiedy ktoś utworzy ją, pojawi się tutaj.",
"empty_column.group": "Nie ma wpisów w tej grupie.",
"empty_column.hashtag": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy(-a)!",
"empty_column.home": "Możesz też odwiedzić {public}, aby znaleźć innych użytkowników.",
"empty_column.home.local_tab": "zakładkę {site_title}",
@ -626,6 +630,7 @@
"empty_column.remote": "Tu nic nie ma! Zaobserwuj użytkowników {instance}, aby wypełnić tę oś.",
"empty_column.scheduled_statuses": "Nie masz żadnych zaplanowanych wpisów. Kiedy dodasz jakiś, pojawi się on tutaj.",
"empty_column.search.accounts": "Brak wyników wyszukiwania osób dla „{term}”",
"empty_column.search.groups": "Brak wyników wyszukiwania grup dla „{term}”",
"empty_column.search.hashtags": "Brak wyników wyszukiwania hashtagów dla „{term}”",
"empty_column.search.statuses": "Brak wyników wyszukiwania wpisów dla „{term}”",
"empty_column.test": "Testowa oś czasu jest pusta.",
@ -695,6 +700,22 @@
"gdpr.message": "{siteTitle} korzysta z ciasteczek sesji, które są niezbędne dla działania strony.",
"gdpr.title": "{siteTitle} korzysta z ciasteczek",
"getting_started.open_source_notice": "{code_name} jest oprogramowaniem o otwartym źródle. Możesz pomóc w rozwoju lub zgłaszać błędy na GitLabie tutaj: {code_link} (v{code_version}).",
"groups.admin_subheading": "Administratorzy grupy",
"groups.empty.title": "Brak grup",
"groups.empty.subtitle": "Odkrywaj grupy do których możesz dołączyć lub utwórz własną.",
"groups.moderator_subheading": "Moderatorzy grupy",
"groups.user_subheading": "Członkowie grupy",
"group.header.alt": "Nagłówek grupy",
"group.join": "Dołącz do grupy",
"group.leave": "Opuść grupę",
"group.manage": "Edytuj grupę",
"group.request_join": "Poproś o dołączenie do grupy",
"group.role.owner": "Właściciel",
"group.role.moderator": "Moderator",
"group.privacy.locked": "Prywatna",
"group.privacy.public": "Publiczna",
"group.tabs.all": "Wszystko",
"group.tabs.members": "Członkowie",
"hashtag.column_header.tag_mode.all": "i {additional}",
"hashtag.column_header.tag_mode.any": "lub {additional}",
"hashtag.column_header.tag_mode.none": "bez {additional}",
@ -798,6 +819,21 @@
"login_external.errors.instance_fail": "Instancja zwróciła błąd.",
"login_external.errors.network_fail": "Połączenie nie powiodło się. Czy jest blokowane przez wtyczkę do przeglądarki?",
"login_form.header": "Zaloguj się",
"manage_group.create": "Utwórz",
"manage_group.fields.name_label": "Nazwa grupy (wymagana)",
"manage_group.fields.name_placeholder": "Nazwa grupy",
"manage_group.fields.description_label": "Opis",
"manage_group.fields.description_placeholder": "Opis",
"manage_group.get_started": "Rozpocznijmy!",
"manage_group.next": "Dalej",
"manage_group.privacy.hint": "To ustawienie nie może zostać później zmienione.",
"manage_group.privacy.label": "Ustawienia prywatności",
"manage_group.privacy.public.hint": "Widoczna w mechanizmach odkrywania. Każdy może dołączyć.",
"manage_group.privacy.public.label": "Publiczna",
"manage_group.privacy.private.hint": "Widoczna w mechanizmach odkrywania. Użytkownicy mogą dołączyć po zatwierdzeniu ich prośby.",
"manage_group.privacy.private.label": "Prywatna (wymaga zatwierdzenia przez właściciela)",
"manage_group.tagline": "Grupy pozwalają łączyć ludzi o podobnych zainteresowaniach.",
"manage_group.update": "Aktualizuj",
"media_panel.empty_message": "Nie znaleziono mediów.",
"media_panel.title": "Media",
"mfa.confirm.success_message": "Potwierdzono MFA",
@ -864,6 +900,7 @@
"navigation_bar.compose_quote": "Cytuj wpis",
"navigation_bar.compose_reply": "Odpowiedz na wpis",
"navigation_bar.create_event": "Utwórz nowe wydarzenie",
"navigation_bar.create_group": "Utwórz grupę",
"navigation_bar.domain_blocks": "Ukryte domeny",
"navigation_bar.favourites": "Ulubione",
"navigation_bar.filters": "Wyciszone słowa",
@ -872,10 +909,14 @@
"navigation_bar.in_reply_to": "W odpowiedzi do",
"navigation_bar.invites": "Zaproszenia",
"navigation_bar.logout": "Wyloguj",
"navigation_bar.manage_group": "Zarządzaj grupą",
"navigation_bar.mutes": "Wyciszeni użytkownicy",
"navigation_bar.preferences": "Preferencje",
"navigation_bar.profile_directory": "Katalog profilów",
"navigation_bar.soapbox_config": "Konfiguracja Soapbox",
"new_group_panel.action": "Utwórz grupę",
"new_group_panel.subtitle": "Nie możesz znaleźć tego, czego szukasz? Utwórz własną prywatną lub publiczną grupę.",
"new_group_panel.title": "Utwórz nową grupę",
"notification.favourite": "{name} dodał(a) Twój wpis do ulubionych",
"notification.follow": "{name} zaczął(-ęła) Cię obserwować",
"notification.follow_request": "{name} poprosił(a) Cię o możliwość obserwacji",
@ -1103,6 +1144,7 @@
"search.placeholder": "Szukaj",
"search_results.accounts": "Ludzie",
"search_results.filter_message": "Szukasz wpisów autorstwa @{acct}.",
"search_results.groups": "Grupy",
"search_results.hashtags": "Hashtagi",
"search_results.statuses": "Wpisy",
"security.codes.fail": "Nie udało się uzyskać zapasowych kodów",
@ -1291,6 +1333,7 @@
"tabs_bar.chats": "Rozmowy",
"tabs_bar.dashboard": "Panel administracyjny",
"tabs_bar.fediverse": "Fediwersum",
"tabs_bar.groups": "Grupy",
"tabs_bar.home": "Strona główna",
"tabs_bar.local": "Lokalna",
"tabs_bar.more": "Więcej",

Wyświetl plik

@ -1,4 +1,5 @@
import React, { useCallback, useEffect } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useRouteMatch } from 'react-router-dom';
import { fetchGroup } from 'soapbox/actions/groups';
@ -16,6 +17,11 @@ import { makeGetGroup } from 'soapbox/selectors';
import { Tabs } from '../components/ui';
const messages = defineMessages({
all: { id: 'group.tabs.all', defaultMessage: 'All' },
members: { id: 'group.tabs.members', defaultMessage: 'Members' },
});
interface IGroupPage {
params?: {
id?: string,
@ -24,6 +30,7 @@ interface IGroupPage {
/** Page to display a group. */
const GroupPage: React.FC<IGroupPage> = ({ params, children }) => {
const intl = useIntl();
const match = useRouteMatch();
const dispatch = useAppDispatch();
@ -43,6 +50,19 @@ const GroupPage: React.FC<IGroupPage> = ({ params, children }) => {
);
}
const items = [
{
text: intl.formatMessage(messages.all),
to: `/groups/${group?.id}`,
name: '/groups/:id',
},
{
text: intl.formatMessage(messages.members),
to: `/groups/${group?.id}/members`,
name: '/groups/:id/members',
},
]
return (
<>
<Layout.Main>
@ -50,18 +70,7 @@ const GroupPage: React.FC<IGroupPage> = ({ params, children }) => {
<GroupHeader group={group} />
<Tabs
items={[
{
text: 'All',
to: `/groups/${group?.id}`,
name: '/groups/:id',
},
{
text: 'Members',
to: `/groups/${group?.id}/members`,
name: '/groups/:id/members',
},
]}
items={items}
activeItem={match.path}
/>