Localization: Respect locale number format for floats (#5863)
This commit is contained in:
parent
b3c6ae2089
commit
29ec767eb2
@ -6,6 +6,7 @@ import { getAllNotificationsCount } from '../../util/folderManager';
|
|||||||
import { formatIntegerCompact } from '../../util/textFormat';
|
import { formatIntegerCompact } from '../../util/textFormat';
|
||||||
|
|
||||||
import { useFolderManagerForUnreadCounters } from '../../hooks/useFolderManager';
|
import { useFolderManagerForUnreadCounters } from '../../hooks/useFolderManager';
|
||||||
|
import useLang from '../../hooks/useLang';
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
isForAppBadge?: boolean;
|
isForAppBadge?: boolean;
|
||||||
@ -15,6 +16,8 @@ const UnreadCounter: FC<OwnProps> = ({ isForAppBadge }) => {
|
|||||||
useFolderManagerForUnreadCounters();
|
useFolderManagerForUnreadCounters();
|
||||||
const unreadNotificationsCount = getAllNotificationsCount();
|
const unreadNotificationsCount = getAllNotificationsCount();
|
||||||
|
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isForAppBadge) {
|
if (isForAppBadge) {
|
||||||
updateAppBadge(unreadNotificationsCount);
|
updateAppBadge(unreadNotificationsCount);
|
||||||
@ -26,7 +29,7 @@ const UnreadCounter: FC<OwnProps> = ({ isForAppBadge }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="unread-count active">{formatIntegerCompact(unreadNotificationsCount)}</div>
|
<div className="unread-count active">{formatIntegerCompact(lang, unreadNotificationsCount)}</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -69,7 +69,7 @@ const SavedGift = ({
|
|||||||
const ribbonText = gift.isPinned && gift.gift.type === 'starGiftUnique'
|
const ribbonText = gift.isPinned && gift.gift.type === 'starGiftUnique'
|
||||||
? lang('GiftSavedNumber', { number: gift.gift.number })
|
? lang('GiftSavedNumber', { number: gift.gift.number })
|
||||||
: totalIssued
|
: totalIssued
|
||||||
? lang('ActionStarGiftLimitedRibbon', { total: formatIntegerCompact(totalIssued) })
|
? lang('ActionStarGiftLimitedRibbon', { total: formatIntegerCompact(lang, totalIssued) })
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
@ -118,7 +118,7 @@ const Archive: FC<OwnProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
<Badge
|
<Badge
|
||||||
className={styles.unreadCount}
|
className={styles.unreadCount}
|
||||||
text={archiveUnreadCount ? formatIntegerCompact(archiveUnreadCount) : undefined}
|
text={archiveUnreadCount ? formatIntegerCompact(lang, archiveUnreadCount) : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -143,7 +143,7 @@ const Archive: FC<OwnProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
<Badge
|
<Badge
|
||||||
className={styles.unreadCount}
|
className={styles.unreadCount}
|
||||||
text={archiveUnreadCount ? formatIntegerCompact(archiveUnreadCount) : undefined}
|
text={archiveUnreadCount ? formatIntegerCompact(lang, archiveUnreadCount) : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import { formatIntegerCompact } from '../../../util/textFormat';
|
|||||||
import { extractCurrentThemeParams } from '../../../util/themeStyle';
|
import { extractCurrentThemeParams } from '../../../util/themeStyle';
|
||||||
|
|
||||||
import useDerivedState from '../../../hooks/useDerivedState';
|
import useDerivedState from '../../../hooks/useDerivedState';
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
import useOldLang from '../../../hooks/useOldLang';
|
import useOldLang from '../../../hooks/useOldLang';
|
||||||
|
|
||||||
@ -52,6 +53,7 @@ const ChatBadge: FC<OwnProps> = ({
|
|||||||
const { requestMainWebView } = getActions();
|
const { requestMainWebView } = getActions();
|
||||||
|
|
||||||
const oldLang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
unreadMentionsCount = 0, unreadReactionsCount = 0,
|
unreadMentionsCount = 0, unreadReactionsCount = 0,
|
||||||
@ -136,7 +138,7 @@ const ChatBadge: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const unreadCountElement = (hasUnreadMark || unreadCount) ? (
|
const unreadCountElement = (hasUnreadMark || unreadCount) ? (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
{!hasUnreadMark && <AnimatedCounter text={formatIntegerCompact(unreadCount!)} />}
|
{!hasUnreadMark && <AnimatedCounter text={formatIntegerCompact(lang, unreadCount!)} />}
|
||||||
</div>
|
</div>
|
||||||
) : undefined;
|
) : undefined;
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import { formatIntegerCompact } from '../../util/textFormat';
|
|||||||
|
|
||||||
import useFlag from '../../hooks/useFlag';
|
import useFlag from '../../hooks/useFlag';
|
||||||
import useInfiniteScroll from '../../hooks/useInfiniteScroll';
|
import useInfiniteScroll from '../../hooks/useInfiniteScroll';
|
||||||
|
import useLang from '../../hooks/useLang';
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import useOldLang from '../../hooks/useOldLang';
|
import useOldLang from '../../hooks/useOldLang';
|
||||||
|
|
||||||
@ -67,7 +68,8 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
|
|||||||
const chatsById = getGlobal().chats.byId;
|
const chatsById = getGlobal().chats.byId;
|
||||||
const usersById = getGlobal().users.byId;
|
const usersById = getGlobal().users.byId;
|
||||||
|
|
||||||
const lang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
|
const lang = useLang();
|
||||||
const [isClosing, startClosing, stopClosing] = useFlag(false);
|
const [isClosing, startClosing, stopClosing] = useFlag(false);
|
||||||
const [chosenTab, setChosenTab] = useState<ApiReaction | undefined>(undefined);
|
const [chosenTab, setChosenTab] = useState<ApiReaction | undefined>(undefined);
|
||||||
const canShowFilters = reactors && reactions && reactors.count >= MIN_REACTIONS_COUNT_FOR_FILTERS
|
const canShowFilters = reactors && reactions && reactors.count >= MIN_REACTIONS_COUNT_FOR_FILTERS
|
||||||
@ -143,11 +145,11 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
|
|||||||
isOpen={isOpen && !isClosing}
|
isOpen={isOpen && !isClosing}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
className="ReactorListModal narrow"
|
className="ReactorListModal narrow"
|
||||||
title={lang('Reactions')}
|
title={oldLang('Reactions')}
|
||||||
onCloseAnimationEnd={handleCloseAnimationEnd}
|
onCloseAnimationEnd={handleCloseAnimationEnd}
|
||||||
>
|
>
|
||||||
{canShowFilters && (
|
{canShowFilters && (
|
||||||
<div className="Reactions" dir={lang.isRtl ? 'rtl' : undefined}>
|
<div className="Reactions" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||||
<Button
|
<Button
|
||||||
className={buildClassName(!chosenTab && 'chosen')}
|
className={buildClassName(!chosenTab && 'chosen')}
|
||||||
size="tiny"
|
size="tiny"
|
||||||
@ -156,7 +158,7 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
|
|||||||
onClick={() => setChosenTab(undefined)}
|
onClick={() => setChosenTab(undefined)}
|
||||||
>
|
>
|
||||||
<Icon name="heart" />
|
<Icon name="heart" />
|
||||||
{Boolean(reactors?.count) && formatIntegerCompact(reactors.count)}
|
{Boolean(reactors?.count) && formatIntegerCompact(lang, reactors.count)}
|
||||||
</Button>
|
</Button>
|
||||||
{allReactions.map((reaction) => {
|
{allReactions.map((reaction) => {
|
||||||
const count = reactions?.results
|
const count = reactions?.results
|
||||||
@ -175,14 +177,14 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
|
|||||||
className="reaction-filter-emoji"
|
className="reaction-filter-emoji"
|
||||||
availableReactions={availableReactions}
|
availableReactions={availableReactions}
|
||||||
/>
|
/>
|
||||||
{Boolean(count) && formatIntegerCompact(count)}
|
{Boolean(count) && formatIntegerCompact(lang, count)}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div dir={lang.isRtl ? 'rtl' : undefined} className="reactor-list-wrapper">
|
<div dir={oldLang.isRtl ? 'rtl' : undefined} className="reactor-list-wrapper">
|
||||||
{viewportIds?.length ? (
|
{viewportIds?.length ? (
|
||||||
<InfiniteScroll
|
<InfiniteScroll
|
||||||
className="reactor-list custom-scroll"
|
className="reactor-list custom-scroll"
|
||||||
@ -212,7 +214,7 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
|
|||||||
<FullNameTitle peer={peer} withEmojiStatus />
|
<FullNameTitle peer={peer} withEmojiStatus />
|
||||||
<span className="status" dir="auto">
|
<span className="status" dir="auto">
|
||||||
<Icon name="heart-outline" className="status-icon" />
|
<Icon name="heart-outline" className="status-icon" />
|
||||||
{formatDateAtTime(lang, r.addedDate * 1000)}
|
{formatDateAtTime(oldLang, r.addedDate * 1000)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{r.reaction && (
|
{r.reaction && (
|
||||||
@ -238,7 +240,7 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
|
|||||||
userId={peerId}
|
userId={peerId}
|
||||||
noStatusOrTyping
|
noStatusOrTyping
|
||||||
avatarSize="medium"
|
avatarSize="medium"
|
||||||
status={seenByUser ? formatDateAtTime(lang, seenByUser * 1000) : undefined}
|
status={seenByUser ? formatDateAtTime(oldLang, seenByUser * 1000) : undefined}
|
||||||
statusIcon="message-read"
|
statusIcon="message-read"
|
||||||
/>
|
/>
|
||||||
</ListItem>,
|
</ListItem>,
|
||||||
@ -255,7 +257,7 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
|
|||||||
isText
|
isText
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
>
|
>
|
||||||
{lang('Close')}
|
{oldLang('Close')}
|
||||||
</Button>
|
</Button>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import buildClassName from '../../util/buildClassName';
|
|||||||
import { formatIntegerCompact } from '../../util/textFormat';
|
import { formatIntegerCompact } from '../../util/textFormat';
|
||||||
|
|
||||||
import useContextMenuHandlers from '../../hooks/useContextMenuHandlers';
|
import useContextMenuHandlers from '../../hooks/useContextMenuHandlers';
|
||||||
|
import useLang from '../../hooks/useLang';
|
||||||
import useOldLang from '../../hooks/useOldLang';
|
import useOldLang from '../../hooks/useOldLang';
|
||||||
|
|
||||||
import Icon from '../common/icons/Icon';
|
import Icon from '../common/icons/Icon';
|
||||||
@ -33,7 +34,8 @@ const ScrollDownButton: FC<OwnProps> = ({
|
|||||||
onReadAll,
|
onReadAll,
|
||||||
className,
|
className,
|
||||||
}) => {
|
}) => {
|
||||||
const lang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
@ -52,11 +54,11 @@ const ScrollDownButton: FC<OwnProps> = ({
|
|||||||
className={styles.button}
|
className={styles.button}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onContextMenu={handleContextMenu}
|
onContextMenu={handleContextMenu}
|
||||||
ariaLabel={lang(ariaLabelLang)}
|
ariaLabel={oldLang(ariaLabelLang)}
|
||||||
>
|
>
|
||||||
<Icon name={icon} className={styles.icon} />
|
<Icon name={icon} className={styles.icon} />
|
||||||
</Button>
|
</Button>
|
||||||
{Boolean(unreadCount) && <div className={styles.unreadCount}>{formatIntegerCompact(unreadCount)}</div>}
|
{Boolean(unreadCount) && <div className={styles.unreadCount}>{formatIntegerCompact(lang, unreadCount)}</div>}
|
||||||
{onReadAll && (
|
{onReadAll && (
|
||||||
<Menu
|
<Menu
|
||||||
isOpen={isContextMenuOpen}
|
isOpen={isContextMenuOpen}
|
||||||
@ -66,7 +68,7 @@ const ScrollDownButton: FC<OwnProps> = ({
|
|||||||
positionX="right"
|
positionX="right"
|
||||||
positionY="bottom"
|
positionY="bottom"
|
||||||
>
|
>
|
||||||
<MenuItem icon="readchats" onClick={onReadAll}>{lang('MarkAllAsRead')}</MenuItem>
|
<MenuItem icon="readchats" onClick={onReadAll}>{oldLang('MarkAllAsRead')}</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { selectIsCurrentUserFrozen, selectPeer } from '../../../global/selectors
|
|||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import { formatIntegerCompact } from '../../../util/textFormat';
|
import { formatIntegerCompact } from '../../../util/textFormat';
|
||||||
|
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
import useOldLang from '../../../hooks/useOldLang';
|
import useOldLang from '../../../hooks/useOldLang';
|
||||||
import useAsyncRendering from '../../right/hooks/useAsyncRendering';
|
import useAsyncRendering from '../../right/hooks/useAsyncRendering';
|
||||||
@ -40,7 +41,8 @@ const CommentButton: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const shouldRenderLoading = useAsyncRendering([isLoading], SHOW_LOADER_DELAY);
|
const shouldRenderLoading = useAsyncRendering([isLoading], SHOW_LOADER_DELAY);
|
||||||
|
|
||||||
const lang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
|
const lang = useLang();
|
||||||
const {
|
const {
|
||||||
originMessageId, chatId, messagesCount, lastMessageId, lastReadInboxMessageId, recentReplierIds, originChannelId,
|
originMessageId, chatId, messagesCount, lastMessageId, lastReadInboxMessageId, recentReplierIds, originChannelId,
|
||||||
} = threadInfo;
|
} = threadInfo;
|
||||||
@ -76,7 +78,7 @@ const CommentButton: FC<OwnProps> = ({
|
|||||||
function renderRecentRepliers() {
|
function renderRecentRepliers() {
|
||||||
return (
|
return (
|
||||||
Boolean(recentRepliers?.length) && (
|
Boolean(recentRepliers?.length) && (
|
||||||
<div className="recent-repliers" dir={lang.isRtl ? 'rtl' : 'ltr'}>
|
<div className="recent-repliers" dir={oldLang.isRtl ? 'rtl' : 'ltr'}>
|
||||||
{recentRepliers!.map((peer) => (
|
{recentRepliers!.map((peer) => (
|
||||||
<Avatar
|
<Avatar
|
||||||
key={peer.id}
|
key={peer.id}
|
||||||
@ -91,16 +93,16 @@ const CommentButton: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const hasUnread = Boolean(lastReadInboxMessageId && lastMessageId && lastReadInboxMessageId < lastMessageId);
|
const hasUnread = Boolean(lastReadInboxMessageId && lastMessageId && lastReadInboxMessageId < lastMessageId);
|
||||||
|
|
||||||
const commentsText = messagesCount ? (lang('CommentsCount', '%COMMENTS_COUNT%', undefined, messagesCount) as string)
|
const commentsText = messagesCount ? (oldLang('CommentsCount', '%COMMENTS_COUNT%', undefined, messagesCount))
|
||||||
.split('%')
|
.split('%')
|
||||||
.map((s) => {
|
.map((s) => {
|
||||||
return (s === 'COMMENTS_COUNT' ? <AnimatedCounter text={formatIntegerCompact(messagesCount)} /> : s);
|
return (s === 'COMMENTS_COUNT' ? <AnimatedCounter text={formatIntegerCompact(lang, messagesCount)} /> : s);
|
||||||
})
|
})
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-cnt={formatIntegerCompact(messagesCount)}
|
data-cnt={formatIntegerCompact(lang, messagesCount)}
|
||||||
className={buildClassName(
|
className={buildClassName(
|
||||||
'CommentButton',
|
'CommentButton',
|
||||||
hasUnread && 'has-unread',
|
hasUnread && 'has-unread',
|
||||||
@ -109,7 +111,7 @@ const CommentButton: FC<OwnProps> = ({
|
|||||||
isLoading && 'loading',
|
isLoading && 'loading',
|
||||||
asActionButton && 'as-action-button',
|
asActionButton && 'as-action-button',
|
||||||
)}
|
)}
|
||||||
dir={lang.isRtl ? 'rtl' : 'ltr'}
|
dir={oldLang.isRtl ? 'rtl' : 'ltr'}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
@ -124,7 +126,7 @@ const CommentButton: FC<OwnProps> = ({
|
|||||||
{!recentRepliers?.length && <Icon name="comments" />}
|
{!recentRepliers?.length && <Icon name="comments" />}
|
||||||
{renderRecentRepliers()}
|
{renderRecentRepliers()}
|
||||||
<div className="label" dir="auto">
|
<div className="label" dir="auto">
|
||||||
{messagesCount ? commentsText : lang('LeaveAComment')}
|
{messagesCount ? commentsText : oldLang('LeaveAComment')}
|
||||||
</div>
|
</div>
|
||||||
<div className="CommentButton_right">
|
<div className="CommentButton_right">
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
|
|||||||
@ -112,10 +112,14 @@ const MessageMeta: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const viewsTitle = useMemo(() => {
|
const viewsTitle = useMemo(() => {
|
||||||
if (!message.viewsCount) return undefined;
|
if (!message.viewsCount) return undefined;
|
||||||
let text = lang('MessageTooltipViews', { count: message.viewsCount }, { pluralValue: message.viewsCount });
|
let text = lang('MessageTooltipViews', {
|
||||||
|
count: lang.number(message.viewsCount),
|
||||||
|
}, { pluralValue: message.viewsCount });
|
||||||
if (message.forwardsCount) {
|
if (message.forwardsCount) {
|
||||||
text += '\n';
|
text += '\n';
|
||||||
text += lang('MessageTooltipForwards', { count: message.forwardsCount }, { pluralValue: message.forwardsCount });
|
text += lang('MessageTooltipForwards', {
|
||||||
|
count: lang.number(message.forwardsCount),
|
||||||
|
}, { pluralValue: message.forwardsCount });
|
||||||
}
|
}
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
@ -160,7 +164,7 @@ const MessageMeta: FC<OwnProps> = ({
|
|||||||
{Boolean(message.viewsCount) && (
|
{Boolean(message.viewsCount) && (
|
||||||
<>
|
<>
|
||||||
<span className="message-views" title={viewsTitle}>
|
<span className="message-views" title={viewsTitle}>
|
||||||
{formatIntegerCompact(message.viewsCount!)}
|
{formatIntegerCompact(lang, message.viewsCount!)}
|
||||||
</span>
|
</span>
|
||||||
<Icon name="channelviews" />
|
<Icon name="channelviews" />
|
||||||
</>
|
</>
|
||||||
@ -168,7 +172,7 @@ const MessageMeta: FC<OwnProps> = ({
|
|||||||
{!noReplies && Boolean(repliesThreadInfo?.messagesCount) && (
|
{!noReplies && Boolean(repliesThreadInfo?.messagesCount) && (
|
||||||
<span onClick={handleOpenThread} className="message-replies-wrapper" title={repliesTitle}>
|
<span onClick={handleOpenThread} className="message-replies-wrapper" title={repliesTitle}>
|
||||||
<span className="message-replies">
|
<span className="message-replies">
|
||||||
<AnimatedCounter text={formatIntegerCompact(repliesThreadInfo!.messagesCount!)} />
|
<AnimatedCounter text={formatIntegerCompact(lang, repliesThreadInfo!.messagesCount!)} />
|
||||||
</span>
|
</span>
|
||||||
<Icon name="reply-filled" />
|
<Icon name="reply-filled" />
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import useTimeout from '../../../hooks/schedulers/useTimeout';
|
|||||||
import useAverageColor from '../../../hooks/useAverageColor';
|
import useAverageColor from '../../../hooks/useAverageColor';
|
||||||
import useFlag from '../../../hooks/useFlag';
|
import useFlag from '../../../hooks/useFlag';
|
||||||
import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
|
import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
import useOldLang from '../../../hooks/useOldLang';
|
import useOldLang from '../../../hooks/useOldLang';
|
||||||
|
|
||||||
@ -203,13 +204,14 @@ const SimilarChannels = ({
|
|||||||
function SimilarChannel({ channel }: { channel: ApiChat }) {
|
function SimilarChannel({ channel }: { channel: ApiChat }) {
|
||||||
const { openChat } = getActions();
|
const { openChat } = getActions();
|
||||||
const color = useAverageColor(channel, DEFAULT_BADGE_COLOR);
|
const color = useAverageColor(channel, DEFAULT_BADGE_COLOR);
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.item} onClick={() => openChat({ id: channel.id })}>
|
<div className={styles.item} onClick={() => openChat({ id: channel.id })}>
|
||||||
<Avatar className={styles.avatar} key={channel.id} size="large" peer={channel} />
|
<Avatar className={styles.avatar} key={channel.id} size="large" peer={channel} />
|
||||||
<div style={`background: ${color}`} className={styles.badge}>
|
<div style={`background: ${color}`} className={styles.badge}>
|
||||||
<Icon name="user-filled" className={styles.icon} />
|
<Icon name="user-filled" className={styles.icon} />
|
||||||
<span className={styles.membersCount}>{formatIntegerCompact(channel?.membersCount || 0)}
|
<span className={styles.membersCount}>{formatIntegerCompact(lang, channel?.membersCount || 0)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span className={styles.channelTitle}>{channel.title}</span>
|
<span className={styles.channelTitle}>{channel.title}</span>
|
||||||
|
|||||||
@ -145,7 +145,9 @@ const StarGiftAction = ({
|
|||||||
{action.gift.availabilityTotal && (
|
{action.gift.availabilityTotal && (
|
||||||
<GiftRibbon
|
<GiftRibbon
|
||||||
color={backgroundColor || 'blue'}
|
color={backgroundColor || 'blue'}
|
||||||
text={lang('ActionStarGiftLimitedRibbon', { total: formatIntegerCompact(action.gift.availabilityTotal) })}
|
text={lang('ActionStarGiftLimitedRibbon', {
|
||||||
|
total: formatIntegerCompact(lang, action.gift.availabilityTotal),
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className={styles.info}>
|
<div className={styles.info}>
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import { REM } from '../../../common/helpers/mediaDimensions';
|
|||||||
import useSelector from '../../../../hooks/data/useSelector';
|
import useSelector from '../../../../hooks/data/useSelector';
|
||||||
import useContextMenuHandlers from '../../../../hooks/useContextMenuHandlers';
|
import useContextMenuHandlers from '../../../../hooks/useContextMenuHandlers';
|
||||||
import useEffectWithPrevDeps from '../../../../hooks/useEffectWithPrevDeps';
|
import useEffectWithPrevDeps from '../../../../hooks/useEffectWithPrevDeps';
|
||||||
|
import useLang from '../../../../hooks/useLang';
|
||||||
import useLastCallback from '../../../../hooks/useLastCallback';
|
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||||
import usePrevious from '../../../../hooks/usePrevious';
|
import usePrevious from '../../../../hooks/usePrevious';
|
||||||
import useShowTransition from '../../../../hooks/useShowTransition';
|
import useShowTransition from '../../../../hooks/useShowTransition';
|
||||||
@ -76,6 +77,8 @@ const ReactionButton = ({
|
|||||||
const counterRef = useRef<HTMLSpanElement>(null);
|
const counterRef = useRef<HTMLSpanElement>(null);
|
||||||
const animationRef = useRef<Animation>();
|
const animationRef = useRef<Animation>();
|
||||||
|
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
const isPaid = reaction.reaction.type === 'paid';
|
const isPaid = reaction.reaction.type === 'paid';
|
||||||
|
|
||||||
const starsState = useSelector(selectStarsState);
|
const starsState = useSelector(selectStarsState);
|
||||||
@ -198,7 +201,7 @@ const ReactionButton = ({
|
|||||||
{shouldRenderPaidCounter && (
|
{shouldRenderPaidCounter && (
|
||||||
<AnimatedCounter
|
<AnimatedCounter
|
||||||
ref={counterRef}
|
ref={counterRef}
|
||||||
text={`+${formatIntegerCompact(reaction.localAmount || prevAmount!)}`}
|
text={`+${formatIntegerCompact(lang, reaction.localAmount || prevAmount!)}`}
|
||||||
className={styles.paidCounter}
|
className={styles.paidCounter}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -216,7 +219,7 @@ const ReactionButton = ({
|
|||||||
<AvatarList size="mini" peers={recentReactors} />
|
<AvatarList size="mini" peers={recentReactors} />
|
||||||
) : (
|
) : (
|
||||||
<AnimatedCounter
|
<AnimatedCounter
|
||||||
text={formatIntegerCompact(reaction.count + (reaction.localAmount || 0))}
|
text={formatIntegerCompact(lang, reaction.count + (reaction.localAmount || 0))}
|
||||||
className={styles.counter}
|
className={styles.counter}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import buildClassName from '../../../util/buildClassName';
|
|||||||
import { formatIntegerCompact } from '../../../util/textFormat';
|
import { formatIntegerCompact } from '../../../util/textFormat';
|
||||||
import { extractCurrentThemeParams } from '../../../util/themeStyle';
|
import { extractCurrentThemeParams } from '../../../util/themeStyle';
|
||||||
|
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
|
|
||||||
import PeerBadge from '../../common/PeerBadge';
|
import PeerBadge from '../../common/PeerBadge';
|
||||||
@ -33,6 +34,8 @@ function WebAppGridItem({ user, isPopularApp }: OwnProps & StateProps) {
|
|||||||
requestMainWebView,
|
requestMainWebView,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
const handleClick = useLastCallback(() => {
|
const handleClick = useLastCallback(() => {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return;
|
return;
|
||||||
@ -55,7 +58,7 @@ function WebAppGridItem({ user, isPopularApp }: OwnProps & StateProps) {
|
|||||||
|
|
||||||
const title = user?.firstName;
|
const title = user?.firstName;
|
||||||
const activeUserCount = user?.botActiveUsers;
|
const activeUserCount = user?.botActiveUsers;
|
||||||
const badgeText = activeUserCount && isPopularApp ? formatIntegerCompact(activeUserCount) : undefined;
|
const badgeText = activeUserCount && isPopularApp ? formatIntegerCompact(lang, activeUserCount) : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import buildClassName from '../../../util/buildClassName';
|
|||||||
import { formatFullDate } from '../../../util/dates/dateFormat';
|
import { formatFullDate } from '../../../util/dates/dateFormat';
|
||||||
import { formatInteger, formatIntegerCompact } from '../../../util/textFormat';
|
import { formatInteger, formatIntegerCompact } from '../../../util/textFormat';
|
||||||
|
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
import useOldLang from '../../../hooks/useOldLang';
|
import useOldLang from '../../../hooks/useOldLang';
|
||||||
|
|
||||||
import Icon from '../../common/icons/Icon';
|
import Icon from '../../common/icons/Icon';
|
||||||
@ -121,7 +122,8 @@ const StatisticsOverview: FC<OwnProps> = ({
|
|||||||
className,
|
className,
|
||||||
subtitle,
|
subtitle,
|
||||||
}) => {
|
}) => {
|
||||||
const lang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
const renderOverviewItemValue = ({ change, percentage }: StatisticsOverviewItem) => {
|
const renderOverviewItemValue = ({ change, percentage }: StatisticsOverviewItem) => {
|
||||||
if (!change) {
|
if (!change) {
|
||||||
@ -132,7 +134,9 @@ const StatisticsOverview: FC<OwnProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={buildClassName(styles.value, isChangeNegative && styles.negative)}>
|
<span className={buildClassName(styles.value, isChangeNegative && styles.negative)}>
|
||||||
{isChangeNegative ? `-${formatIntegerCompact(Math.abs(change))}` : `+${formatIntegerCompact(change)}`}
|
{isChangeNegative
|
||||||
|
? `-${formatIntegerCompact(lang, Math.abs(change))}`
|
||||||
|
: `+${formatIntegerCompact(lang, change)}`}
|
||||||
{percentage && (
|
{percentage && (
|
||||||
<>
|
<>
|
||||||
{' '}
|
{' '}
|
||||||
@ -156,7 +160,7 @@ const StatisticsOverview: FC<OwnProps> = ({
|
|||||||
<span className={styles.tableHeading}>
|
<span className={styles.tableHeading}>
|
||||||
≈ ${integerUsdPart}<span className={styles.decimalUsdPart}>.{decimalUsdPart}</span>
|
≈ ${integerUsdPart}<span className={styles.decimalUsdPart}>.{decimalUsdPart}</span>
|
||||||
</span>
|
</span>
|
||||||
<h3 className={styles.tableHeading}>{lang(text)}</h3>
|
<h3 className={styles.tableHeading}>{oldLang(text)}</h3>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -177,7 +181,7 @@ const StatisticsOverview: FC<OwnProps> = ({
|
|||||||
|
|
||||||
{period && (
|
{period && (
|
||||||
<div className={styles.caption}>
|
<div className={styles.caption}>
|
||||||
{formatFullDate(lang, period.minDate * 1000)} — {formatFullDate(lang, period.maxDate * 1000)}
|
{formatFullDate(oldLang, period.minDate * 1000)} — {formatFullDate(oldLang, period.maxDate * 1000)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -202,7 +206,7 @@ const StatisticsOverview: FC<OwnProps> = ({
|
|||||||
<b className={styles.tableValue}>
|
<b className={styles.tableValue}>
|
||||||
{`${cell.isApproximate ? '≈' : ''}${formatInteger(field)}`}
|
{`${cell.isApproximate ? '≈' : ''}${formatInteger(field)}`}
|
||||||
</b>
|
</b>
|
||||||
<h3 className={styles.tableHeading}>{lang(cell.title)}</h3>
|
<h3 className={styles.tableHeading}>{oldLang(cell.title)}</h3>
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -218,7 +222,7 @@ const StatisticsOverview: FC<OwnProps> = ({
|
|||||||
<span className={cell.withAbsoluteValue ? styles.tableSecondaryValue : styles.tableValue}>
|
<span className={cell.withAbsoluteValue ? styles.tableSecondaryValue : styles.tableValue}>
|
||||||
{field.percentage}%
|
{field.percentage}%
|
||||||
</span>
|
</span>
|
||||||
<h3 className={styles.tableHeading}>{lang(cell.title)}</h3>
|
<h3 className={styles.tableHeading}>{oldLang(cell.title)}</h3>
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -226,11 +230,11 @@ const StatisticsOverview: FC<OwnProps> = ({
|
|||||||
return (
|
return (
|
||||||
<td className={styles.tableCell}>
|
<td className={styles.tableCell}>
|
||||||
<b className={styles.tableValue}>
|
<b className={styles.tableValue}>
|
||||||
{formatIntegerCompact(field.current)}
|
{formatIntegerCompact(lang, field.current)}
|
||||||
</b>
|
</b>
|
||||||
{' '}
|
{' '}
|
||||||
{renderOverviewItemValue(field)}
|
{renderOverviewItemValue(field)}
|
||||||
<h3 className={styles.tableHeading}>{lang(cell.title)}</h3>
|
<h3 className={styles.tableHeading}>{oldLang(cell.title)}</h3>
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import type { StatisticsMessageInteractionCounter, StatisticsStoryInteractionCou
|
|||||||
|
|
||||||
import { formatIntegerCompact } from '../../../util/textFormat';
|
import { formatIntegerCompact } from '../../../util/textFormat';
|
||||||
|
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
import useOldLang from '../../../hooks/useOldLang';
|
import useOldLang from '../../../hooks/useOldLang';
|
||||||
|
|
||||||
import Icon from '../../common/icons/Icon';
|
import Icon from '../../common/icons/Icon';
|
||||||
@ -15,25 +16,26 @@ interface OwnProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function StatisticsRecentPostMeta({ postStatistic }: OwnProps) {
|
function StatisticsRecentPostMeta({ postStatistic }: OwnProps) {
|
||||||
const lang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
|
const lang = useLang();
|
||||||
return (
|
return (
|
||||||
<div className={styles.meta}>
|
<div className={styles.meta}>
|
||||||
{postStatistic.reactionsCount > 0 && (
|
{postStatistic.reactionsCount > 0 && (
|
||||||
<span className={styles.metaWithIcon}>
|
<span className={styles.metaWithIcon}>
|
||||||
<Icon name="heart-outline" className={styles.metaIcon} />
|
<Icon name="heart-outline" className={styles.metaIcon} />
|
||||||
{formatIntegerCompact(postStatistic.reactionsCount)}
|
{formatIntegerCompact(lang, postStatistic.reactionsCount)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{postStatistic.forwardsCount > 0 && (
|
{postStatistic.forwardsCount > 0 && (
|
||||||
<span className={styles.metaWithIcon}>
|
<span className={styles.metaWithIcon}>
|
||||||
<Icon name="forward" className={styles.metaIcon} />
|
<Icon name="forward" className={styles.metaIcon} />
|
||||||
{formatIntegerCompact(postStatistic.forwardsCount)}
|
{formatIntegerCompact(lang, postStatistic.forwardsCount)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!postStatistic.forwardsCount && !postStatistic.reactionsCount
|
{!postStatistic.forwardsCount && !postStatistic.reactionsCount
|
||||||
&& lang('ChannelStats.SharesCount_ZeroValueHolder')}
|
&& oldLang('ChannelStats.SharesCount_ZeroValueHolder')}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
export const clamp = (num: number, min: number, max: number) => (Math.min(max, Math.max(min, num)));
|
export const clamp = (num: number, min: number, max: number) => (Math.min(max, Math.max(min, num)));
|
||||||
export const isBetween = (num: number, min: number, max: number) => (num >= min && num <= max);
|
export const isBetween = (num: number, min: number, max: number) => (num >= min && num <= max);
|
||||||
export const round = (num: number, decimals: number = 0) => Math.round(num * 10 ** decimals) / 10 ** decimals;
|
export const round = (num: number, decimals: number = 0) => Math.round(num * 10 ** decimals) / 10 ** decimals;
|
||||||
|
export const ceil = (num: number, decimals: number = 0) => Math.ceil(num * 10 ** decimals) / 10 ** decimals;
|
||||||
|
export const floor = (num: number, decimals: number = 0) => Math.floor(num * 10 ** decimals) / 10 ** decimals;
|
||||||
export const lerp = (start: number, end: number, interpolationRatio: number) => {
|
export const lerp = (start: number, end: number, interpolationRatio: number) => {
|
||||||
return (1 - interpolationRatio) * start + interpolationRatio * end;
|
return (1 - interpolationRatio) * start + interpolationRatio * end;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,32 +1,25 @@
|
|||||||
import type { OldLangFn } from '../hooks/useOldLang';
|
import type { OldLangFn } from '../hooks/useOldLang';
|
||||||
|
import type { LangFn } from './localization';
|
||||||
|
|
||||||
import EMOJI_REGEX from '../lib/twemojiRegex';
|
import EMOJI_REGEX from '../lib/twemojiRegex';
|
||||||
import fixNonStandardEmoji from './emoji/fixNonStandardEmoji';
|
import fixNonStandardEmoji from './emoji/fixNonStandardEmoji';
|
||||||
|
import { floor } from './math';
|
||||||
import withCache from './withCache';
|
import withCache from './withCache';
|
||||||
|
|
||||||
export function formatInteger(value: number) {
|
export function formatInteger(value: number) {
|
||||||
return String(value).replace(/\d(?=(\d{3})+$)/g, '$& ');
|
return String(value).replace(/\d(?=(\d{3})+$)/g, '$& ');
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatFixedNumber(number: number) {
|
export function formatIntegerCompact(lang: LangFn, views: number) {
|
||||||
const fixed = String(number.toFixed(1));
|
|
||||||
if (fixed.substr(-2) === '.0') {
|
|
||||||
return Math.floor(number);
|
|
||||||
}
|
|
||||||
|
|
||||||
return number.toFixed(1).replace('.', ',');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatIntegerCompact(views: number) {
|
|
||||||
if (views < 1e3) {
|
if (views < 1e3) {
|
||||||
return views.toString();
|
return lang.number(views);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (views < 1e6) {
|
if (views < 1e6) {
|
||||||
return `${formatFixedNumber(views / 1e3)}K`;
|
return `${lang.number(floor(views / 1e3, 1))}K`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${formatFixedNumber(views / 1e6)}M`;
|
return `${lang.number(floor(views / 1e6, 1))}M`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatPercent(value: number, fractionDigits = 1) {
|
export function formatPercent(value: number, fractionDigits = 1) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user