Invite via Link: Use new translations (#6451)

This commit is contained in:
zubiden 2025-11-11 14:37:48 +01:00 committed by Alexander Zinchuk
parent 9192eb10fe
commit 833db81897
4 changed files with 93 additions and 71 deletions

View File

@ -2315,4 +2315,19 @@
"UserNoteHint" = "only visible to you";
"EditUserNoteHint" = "Notes are only visible to you.";
"AriaStoryTogglerOpen" = "Open Story List";
"InviteBlockedTitle" = "Invite via Link";
"InviteBlockedOneMessage" = "This user restricts adding them to groups. You can send an invite link in a private message instead.";
"InviteBlockedManyMessage" = "Some users restrict adding them to groups. You can send these people an invite link in a private message instead.";
"InviteBlockedOr" = "or";
"InviteBlockedNoLinkTitle" = "You can't create a link";
"InviteBlockedPremiumTitle" = "Upgrade to Premium";
"InviteBlockedPremiumButton" = "Subscribe to Telegram Premium";
"InviteRestrictedPremiumReason" = "available only to Premium users";
"InviteRestrictedUsers_one" = "**{count} user** can only be invited via link, but you don't have permission to share invite links to this group.";
"InviteRestrictedUsers_other" = "**{count} users** can only be invited via link, but you don't have permission to share invite links to this group.";
"InviteViaLinkButton" = "Send Invite Link";
"InviteRestrictedPremiumReasonSingle" = "**{user}** accepts invitations to groups from contacts and **Premium** users.";
"InviteRestrictedPremiumReasonMultiple" = "{list} only accept invitations to groups from contacts and **Premium** users.";
"InviteRestrictedPremiumReasonMultipleMore_one" = "{list} and **{count} more** person only accept invitations to groups from contacts and **Premium** users.";
"InviteRestrictedPremiumReasonMultipleMore_other" = "{list} and **{count} more** people only accept invitations to groups from contacts and **Premium** users.";
"StoryUnsupported" = "This story is not supported in Telegram Web A. Try viewing it in the Telegram app.";

View File

@ -4,13 +4,6 @@
align-items: center;
}
.closeButton {
position: absolute;
z-index: 1;
top: 0.5rem;
left: 0.5rem;
}
.contentText {
color: var(--color-text-secondary);
text-align: center !important;

View File

@ -1,6 +1,5 @@
import type { FC } from '../../../lib/teact/teact';
import {
memo, useCallback,
memo,
useEffect,
useMemo, useState,
} from '../../../lib/teact/teact';
@ -10,16 +9,14 @@ import type { ApiChat } from '../../../api/types';
import type { TabState } from '../../../global/types';
import { getUserFullName } from '../../../global/helpers';
import { selectChat } from '../../../global/selectors';
import { selectChat, selectUser } from '../../../global/selectors';
import { partition } from '../../../util/iteratees';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import renderText from '../../common/helpers/renderText';
import useLang from '../../../hooks/useLang';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import AvatarList from '../../common/AvatarList';
import Icon from '../../common/icons/Icon';
import PeerPicker from '../../common/pickers/PeerPicker';
import Button from '../../ui/Button';
import Modal from '../../ui/Modal';
@ -35,14 +32,14 @@ type StateProps = {
chat?: ApiChat;
};
const InviteViaLinkModal: FC<OwnProps & StateProps> = ({
const InviteViaLinkModal = ({
modal,
chat,
}) => {
}: OwnProps & StateProps) => {
const { sendInviteMessages, closeInviteViaLinkModal, openPremiumModal } = getActions();
const { missingUsers } = modal || {};
const lang = useOldLang();
const lang = useLang();
const [selectedMemberIds, setSelectedMemberIds] = useState<string[]>([]);
const userIds = useMemo(() => missingUsers?.map((user) => user.id) || MEMO_EMPTY_ARRAY, [missingUsers]);
@ -52,35 +49,27 @@ const InviteViaLinkModal: FC<OwnProps & StateProps> = ({
return [requirePremiumIds.map((user) => user.id), regularIds.map((user) => user.id)];
}, [missingUsers]);
const invitableWithPremiumIds = useMemo(() => {
const invitableWithPremiumPeers = useMemo(() => {
const global = getGlobal();
return missingUsers?.filter((user) => user.isRequiringPremiumToInvite || user.isRequiringPremiumToMessage)
.map((user) => user.id);
.map((user) => selectUser(global, user.id))
.filter(Boolean);
}, [missingUsers]);
const isEveryPremiumBlocksPm = useMemo(() => {
if (!missingUsers) return undefined;
return !missingUsers.some((user) => user.isRequiringPremiumToInvite && !user.isRequiringPremiumToMessage);
}, [missingUsers]);
const topListPeers = useMemo(() => {
const users = getGlobal().users.byId;
return invitableWithPremiumIds?.map((id) => users[id]);
}, [invitableWithPremiumIds]);
useEffect(() => {
setSelectedMemberIds(selectableIds);
}, [selectableIds]);
const handleClose = useLastCallback(() => closeInviteViaLinkModal());
const handleSendInviteLink = useCallback(() => {
const handleSendInviteLink = useLastCallback(() => {
sendInviteMessages({ chatId: chat!.id, userIds: selectedMemberIds });
closeInviteViaLinkModal();
}, [selectedMemberIds, chat]);
});
const handleOpenPremiumModal = useCallback(() => {
const handleOpenPremiumModal = useLastCallback(() => {
openPremiumModal();
}, []);
});
const canSendInviteLink = useMemo(() => {
if (!chat) return undefined;
@ -90,77 +79,80 @@ const InviteViaLinkModal: FC<OwnProps & StateProps> = ({
const inviteSectionText = useMemo(() => {
return canSendInviteLink
? lang(missingUsers?.length === 1 ? 'InviteBlockedOneMessage' : 'InviteBlockedManyMessage')
: lang('InviteRestrictedUsers2', missingUsers?.length);
: lang('InviteRestrictedUsers', { count: missingUsers?.length }, {
pluralValue: missingUsers?.length || 0,
withMarkdown: true,
withNodes: true,
});
}, [canSendInviteLink, lang, missingUsers?.length]);
const premiumSectionText = useMemo(() => {
if (!invitableWithPremiumIds?.length || !topListPeers?.length) return undefined;
const prefix = isEveryPremiumBlocksPm ? 'InviteMessagePremiumBlocked' : 'InvitePremiumBlocked';
let langKey = `${prefix}One`;
let params = [getUserFullName(topListPeers[0])];
if (invitableWithPremiumIds.length === 2) {
langKey = `${prefix}Two`;
params = [getUserFullName(topListPeers[0]), getUserFullName(topListPeers[1])];
} else if (invitableWithPremiumIds.length === 3) {
langKey = `${prefix}Three`;
params = [getUserFullName(topListPeers[0]), getUserFullName(topListPeers[1]), getUserFullName(topListPeers[2])];
} else if (invitableWithPremiumIds.length > 3) {
langKey = `${prefix}Many`;
params = [
getUserFullName(topListPeers[0]),
getUserFullName(topListPeers[1]),
(invitableWithPremiumIds.length - 2).toString(),
];
if (!invitableWithPremiumPeers?.length) return undefined;
if (invitableWithPremiumPeers.length === 1) {
return lang('InviteRestrictedPremiumReasonSingle', { user: getUserFullName(invitableWithPremiumPeers[0]) }, {
withMarkdown: true,
withNodes: true,
});
}
return lang(langKey, params, undefined, topListPeers.length);
}, [invitableWithPremiumIds, isEveryPremiumBlocksPm, lang, topListPeers]);
if (invitableWithPremiumPeers.length <= 3) {
const list = lang.conjunction(invitableWithPremiumPeers.map((peer) => getUserFullName(peer)).filter(Boolean));
return lang('InviteRestrictedPremiumReasonMultiple', { list }, {
withMarkdown: true,
withNodes: true,
});
}
const hasPremiumSection = Boolean(topListPeers?.length);
if (invitableWithPremiumPeers.length > 3) {
const moreCount = invitableWithPremiumPeers.length - 2;
const peers = invitableWithPremiumPeers.slice(0, 2);
const list = lang.conjunction(peers.map((peer) => getUserFullName(peer)).filter(Boolean));
return lang('InviteRestrictedPremiumReasonMultipleMore', { list, count: moreCount }, {
pluralValue: moreCount,
withMarkdown: true,
withNodes: true,
});
}
return undefined;
}, [invitableWithPremiumPeers, lang]);
const hasPremiumSection = Boolean(invitableWithPremiumPeers?.length);
const hasSelectableSection = Boolean(selectableIds?.length);
return (
<Modal
isOpen={Boolean(userIds && chat)}
contentClassName={styles.content}
hasAbsoluteCloseButton
onClose={handleClose}
isSlim
>
<Button
round
color="translucent"
size="smaller"
className={styles.closeButton}
ariaLabel={lang('Close')}
onClick={handleClose}
>
<Icon name="close" />
</Button>
{premiumSectionText && (
{hasPremiumSection && (
<>
<AvatarList
className={styles.avatarList}
peers={topListPeers}
peers={invitableWithPremiumPeers}
size="large"
/>
<h3 className={styles.title}>
{canSendInviteLink ? lang('InvitePremiumBlockedTitle') : lang('ChannelInviteViaLinkRestricted')}
{canSendInviteLink ? lang('InviteBlockedPremiumTitle') : lang('InviteBlockedNoLinkTitle')}
</h3>
<p className={styles.contentText}>
{renderText(premiumSectionText, ['simple_markdown'])}
{premiumSectionText}
</p>
<Button
withPremiumGradient
isShiny
onClick={handleOpenPremiumModal}
>
{lang('InvitePremiumBlockedSubscribe')}
{lang('InviteBlockedPremiumButton')}
</Button>
</>
)}
{hasPremiumSection && hasSelectableSection && (
<Separator className={styles.separator}>
{lang('InvitePremiumBlockedOr')}
{lang('InviteBlockedOr')}
</Separator>
)}
{hasSelectableSection && (
@ -174,7 +166,7 @@ const InviteViaLinkModal: FC<OwnProps & StateProps> = ({
itemIds={userIds}
selectedIds={selectedMemberIds}
lockedUnselectedIds={unselectableIds}
lockedUnselectedSubtitle={lang('InvitePremiumBlockedUser')}
lockedUnselectedSubtitle={lang('InviteRestrictedPremiumReason')}
onSelectedIdsChange={setSelectedMemberIds}
isViewOnly={!canSendInviteLink}
allowMultiple
@ -187,7 +179,7 @@ const InviteViaLinkModal: FC<OwnProps & StateProps> = ({
onClick={handleSendInviteLink}
disabled={!selectedMemberIds.length}
>
{lang('SendInviteLink.ActionInvite')}
{lang('InviteViaLinkButton')}
</Button>
)}
</>

View File

@ -1729,6 +1729,15 @@ export interface LangPair {
'UserNoteHint': undefined;
'EditUserNoteHint': undefined;
'AriaStoryTogglerOpen': undefined;
'InviteBlockedTitle': undefined;
'InviteBlockedOneMessage': undefined;
'InviteBlockedManyMessage': undefined;
'InviteBlockedOr': undefined;
'InviteBlockedNoLinkTitle': undefined;
'InviteBlockedPremiumTitle': undefined;
'InviteBlockedPremiumButton': undefined;
'InviteRestrictedPremiumReason': undefined;
'InviteViaLinkButton': undefined;
'StoryUnsupported': undefined;
}
@ -2985,6 +2994,12 @@ export interface LangPairWithVariables<V = LangVariable> {
'ActionStarGiftPrepaidUpgraded': {
'user': V;
};
'InviteRestrictedPremiumReasonSingle': {
'user': V;
};
'InviteRestrictedPremiumReasonMultiple': {
'list': V;
};
}
export interface LangPairPlural {
@ -3334,6 +3349,13 @@ export interface LangPairPluralWithVariables<V = LangVariable> {
'points': V;
'link': V;
};
'InviteRestrictedUsers': {
'count': V;
};
'InviteRestrictedPremiumReasonMultipleMore': {
'list': V;
'count': V;
};
}
export type RegularLangKey = keyof LangPair;
export type RegularLangKeyWithVariables = keyof LangPairWithVariables;