Skip to content

Commit

Permalink
Use ICU number/plural formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
jamiebuilds-signal committed Apr 3, 2023
1 parent aba8882 commit da24cc5
Show file tree
Hide file tree
Showing 30 changed files with 254 additions and 222 deletions.
184 changes: 120 additions & 64 deletions _locales/en/messages.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions ts/components/AddGroupMemberErrorDialog.tsx
Expand Up @@ -38,7 +38,7 @@ export function AddGroupMemberErrorDialog(props: PropsType): JSX.Element {
const { maximumNumberOfContacts } = props;
title = i18n('icu:chooseGroupMembers__maximum-group-size__title');
body = i18n('icu:chooseGroupMembers__maximum-group-size__body', {
max: maximumNumberOfContacts.toString(),
max: maximumNumberOfContacts,
});
break;
}
Expand All @@ -50,7 +50,7 @@ export function AddGroupMemberErrorDialog(props: PropsType): JSX.Element {
body = i18n(
'icu:chooseGroupMembers__maximum-recommended-group-size__body',
{
max: recommendedMaximumNumberOfContacts.toString(),
max: recommendedMaximumNumberOfContacts,
}
);
break;
Expand Down
2 changes: 1 addition & 1 deletion ts/components/ChatColorPicker.tsx
Expand Up @@ -349,7 +349,7 @@ function CustomColorBubble({
title={i18n('icu:ChatColorPicker__delete--title')}
>
{i18n('icu:ChatColorPicker__delete--message', {
num: String(confirmDeleteCount),
num: confirmDeleteCount,
})}
</ConfirmationDialog>
) : null}
Expand Down
2 changes: 1 addition & 1 deletion ts/components/ConversationList.tsx
Expand Up @@ -360,7 +360,7 @@ export function ConversationList({
get(lastMessage, 'text') ||
i18n('icu:ConversationList__last-message-undefined'),
title,
unreadCount: String(unreadCount),
unreadCount,
})}
>
<ConversationListItem
Expand Down
10 changes: 1 addition & 9 deletions ts/components/GroupV2JoinDialog.tsx
Expand Up @@ -49,12 +49,6 @@ export const GroupV2JoinDialog = React.memo(function GroupV2JoinDialogInner(
const joinString = approvalRequired
? i18n('icu:GroupV2--join--request-to-join-button')
: i18n('icu:GroupV2--join--join-button');
const memberString =
memberCount === 1
? i18n('icu:GroupV2--join--member-count--single')
: i18n('icu:GroupV2--join--member-count--multiple', {
count: memberCount.toString(),
});

const wrappedJoin = React.useCallback(() => {
setIsWorking(true);
Expand Down Expand Up @@ -93,9 +87,7 @@ export const GroupV2JoinDialog = React.memo(function GroupV2JoinDialogInner(
</div>
<div className="module-group-v2-join-dialog__title">{title}</div>
<div className="module-group-v2-join-dialog__metadata">
{i18n('icu:GroupV2--join--group-metadata', {
memberCount: memberString,
})}
{i18n('icu:GroupV2--join--group-metadata--full', { memberCount })}
</div>
{groupDescription && (
<div className="module-group-v2-join-dialog__description">
Expand Down
2 changes: 1 addition & 1 deletion ts/components/IncomingCallBar.tsx
Expand Up @@ -150,7 +150,7 @@ function GroupCallMessage({
ringer: ringerNode,
first,
second,
remaining: String(otherMembersRung.length - 2),
remaining: otherMembersRung.length - 2,
}}
/>
);
Expand Down
9 changes: 3 additions & 6 deletions ts/components/NewlyCreatedGroupInvitedContactsDialog.tsx
Expand Up @@ -27,12 +27,10 @@ export function NewlyCreatedGroupInvitedContactsDialog({
onClose,
theme,
}: PropsType): JSX.Element {
let title: string;
let body: ReactNode;
if (contacts.length === 1) {
const contact = contacts[0];

title = i18n('icu:NewlyCreatedGroupInvitedContactsDialog--title--one');
body = (
<>
<GroupDialog.Paragraph>
Expand All @@ -50,9 +48,6 @@ export function NewlyCreatedGroupInvitedContactsDialog({
</>
);
} else {
title = i18n('icu:NewlyCreatedGroupInvitedContactsDialog--title--many', {
count: contacts.length.toString(),
});
body = (
<>
<GroupDialog.Paragraph>
Expand Down Expand Up @@ -89,7 +84,9 @@ export function NewlyCreatedGroupInvitedContactsDialog({
);
}}
onClose={onClose}
title={title}
title={i18n('icu:NewlyCreatedGroupInvitedContactsDialog--title', {
count: contacts.length,
})}
>
{body}
</GroupDialog>
Expand Down
12 changes: 3 additions & 9 deletions ts/components/Preferences.tsx
Expand Up @@ -883,15 +883,9 @@ export function Preferences({
<SettingsRow>
<Control
left={i18n('icu:Preferences--blocked')}
right={
blockedCount === 1
? i18n('icu:Preferences--blocked-count-singular', {
num: String(blockedCount),
})
: i18n('icu:Preferences--blocked-count-plural', {
num: String(blockedCount || 0),
})
}
right={i18n('icu:Preferences--blocked-count', {
num: blockedCount,
})}
/>
</SettingsRow>
<SettingsRow title={i18n('icu:Preferences--messaging')}>
Expand Down
8 changes: 5 additions & 3 deletions ts/components/ProfileEditor.tsx
Expand Up @@ -643,15 +643,17 @@ export function ProfileEditor({
<div className="ProfileEditor__info">
<Intl
i18n={i18n}
id="icu:ProfileEditor--info"
id="icu:ProfileEditor--info--link"
components={{
learnMore: (
// This is a render prop, not a component
// eslint-disable-next-line react/no-unstable-nested-components
learnMoreLink: parts => (
<a
href="https://support.signal.org/hc/en-us/articles/360007459591"
target="_blank"
rel="noreferrer"
>
{i18n('icu:ProfileEditor--learnMore')}
{parts}
</a>
),
}}
Expand Down
2 changes: 1 addition & 1 deletion ts/components/SharedGroupNames.tsx
Expand Up @@ -37,7 +37,7 @@ export function SharedGroupNames({
group1: firstThreeGroups[0],
group2: firstThreeGroups[1],
group3: firstThreeGroups[2],
remainingCount: remainingCount.toString(),
remainingCount,
}}
/>
);
Expand Down
12 changes: 6 additions & 6 deletions ts/components/StoriesSettingsModal.tsx
Expand Up @@ -816,28 +816,28 @@ export function EditMyStoryPrivacy({
toggleSignalConnectionsModal,
signalConnectionsCount,
}: EditMyStoryPrivacyPropsType): JSX.Element {
const learnMore = (
const learnMoreLink = (parts: Array<JSX.Element | string>) => (
<button
className="StoriesSettingsModal__disclaimer__learn-more"
onClick={toggleSignalConnectionsModal}
type="button"
>
{i18n('icu:StoriesSettings__mine__disclaimer--learn-more')}
{parts}
</button>
);
const disclaimerElement = (
<div className="StoriesSettingsModal__disclaimer">
{kind === 'mine' ? (
<Intl
components={{ learnMore }}
components={{ learnMoreLink }}
i18n={i18n}
id="icu:StoriesSettings__mine__disclaimer"
id="icu:StoriesSettings__mine__disclaimer--link"
/>
) : (
<Intl
components={{ learnMore }}
components={{ learnMoreLink }}
i18n={i18n}
id="icu:SendStoryModal__privacy-disclaimer"
id="icu:SendStoryModal__privacy-disclaimer--link"
/>
)}
</div>
Expand Down
47 changes: 18 additions & 29 deletions ts/components/StoryViewer.tsx
Expand Up @@ -54,6 +54,10 @@ import { useRetryStorySend } from '../hooks/useRetryStorySend';
import { resolveStorySendStatus } from '../util/resolveStorySendStatus';
import { strictAssert } from '../util/assert';

function renderStrong(parts: Array<JSX.Element | string>) {
return <strong>{parts}</strong>;
}

export type PropsType = {
currentIndex: number;
deleteGroupStoryReply: (id: string) => void;
Expand Down Expand Up @@ -851,36 +855,21 @@ export function StoryViewer({
{isSent && !hasViewReceiptSetting && !replyCount && (
<>{i18n('icu:StoryViewer__views-off')}</>
)}
{isSent &&
hasViewReceiptSetting &&
(viewCount === 1 ? (
<Intl
i18n={i18n}
id="icu:MyStories__views--singular"
components={{ num: <strong>{viewCount}</strong> }}
/>
) : (
<Intl
i18n={i18n}
id="icu:MyStories__views--plural"
components={{ num: <strong>{viewCount}</strong> }}
/>
))}
{isSent && hasViewReceiptSetting && (
<Intl
i18n={i18n}
id="icu:MyStories__views--strong"
components={{ viewCount, strong: renderStrong }}
/>
)}
{(isSent || viewCount > 0) && replyCount > 0 && ' '}
{replyCount > 0 &&
(replyCount === 1 ? (
<Intl
i18n={i18n}
id="icu:MyStories__replies--singular"
components={{ num: <strong>{replyCount}</strong> }}
/>
) : (
<Intl
i18n={i18n}
id="icu:MyStories__replies--plural"
components={{ num: <strong>{replyCount}</strong> }}
/>
))}
{replyCount > 0 && (
<Intl
i18n={i18n}
id="icu:MyStories__replies"
components={{ replyCount, strong: renderStrong }}
/>
)}
</span>
) : null}
{!isSent && !replyCount && (
Expand Down
2 changes: 1 addition & 1 deletion ts/components/ToastFileSize.stories.tsx
Expand Up @@ -20,7 +20,7 @@ export default {
};

export const _ToastFileSize = (): JSX.Element => (
<ToastFileSize {...defaultProps} limit="100" units="MB" />
<ToastFileSize {...defaultProps} limit={100} units="MB" />
);

_ToastFileSize.story = {
Expand Down
2 changes: 1 addition & 1 deletion ts/components/ToastFileSize.tsx
Expand Up @@ -6,7 +6,7 @@ import type { LocalizerType } from '../types/Util';
import { Toast } from './Toast';

export type ToastPropsType = {
limit: string;
limit: number;
units: string;
};

Expand Down
2 changes: 1 addition & 1 deletion ts/components/conversation/CallingNotification.tsx
Expand Up @@ -141,7 +141,7 @@ function renderCallingNotificationButton(
disabledTooltipText = i18n(
'icu:calling__call-notification__button__call-full-tooltip',
{
max: String(deviceCount),
max: deviceCount,
}
);
onClick = noop;
Expand Down
2 changes: 1 addition & 1 deletion ts/components/conversation/ContactSpoofingReviewDialog.tsx
Expand Up @@ -253,7 +253,7 @@ export function ContactSpoofingReviewDialog(props: PropsType): JSX.Element {
<>
<p>
{i18n('icu:ContactSpoofingReviewDialog__group__description', {
count: conversationInfos.length.toString(),
count: conversationInfos.length,
})}
</p>
<h2>
Expand Down
26 changes: 15 additions & 11 deletions ts/components/conversation/GroupV1DisabledActions.tsx
Expand Up @@ -21,18 +21,22 @@ export function GroupV1DisabledActions({
<p className="module-group-v1-disabled-actions__message">
<Intl
i18n={i18n}
id="icu:GroupV1--Migration--disabled"
id="icu:GroupV1--Migration--disabled--link"
components={{
learnMore: (
<a
href="https://support.signal.org/hc/articles/360007319331"
target="_blank"
rel="noreferrer"
className="module-group-v1-disabled-actions__message__learn-more"
>
{i18n('icu:MessageRequests--learn-more')}
</a>
),
// This is a render prop, not a component
// eslint-disable-next-line react/no-unstable-nested-components
learnMoreLink: (...parts) => {
return (
<a
href="https://support.signal.org/hc/articles/360007319331"
target="_blank"
rel="noreferrer"
className="module-group-v1-disabled-actions__message__learn-more"
>
{parts}
</a>
);
},
}}
/>
</p>
Expand Down
4 changes: 1 addition & 3 deletions ts/components/conversation/LastSeenIndicator.tsx
Expand Up @@ -15,9 +15,7 @@ export const LastSeenIndicator = forwardRef<HTMLDivElement, Props>(
const message =
count === 1
? i18n('icu:unreadMessage')
: i18n('icu:unreadMessages', {
count: String(count),
});
: i18n('icu:unreadMessages', { count });

return (
<div className="module-last-seen-indicator" ref={ref}>
Expand Down
30 changes: 15 additions & 15 deletions ts/components/conversation/MandatoryProfileSharingActions.tsx
Expand Up @@ -27,6 +27,17 @@ export type Props = {
| 'deleteConversation'
>;

const learnMoreLink = (parts: Array<JSX.Element | string>) => (
<a
href="https://support.signal.org/hc/articles/360007459591"
target="_blank"
rel="noreferrer"
className="module-message-request-actions__message__learn-more"
>
{parts}
</a>
);

export function MandatoryProfileSharingActions({
acceptConversation,
blockAndReportSpam,
Expand All @@ -49,17 +60,6 @@ export function MandatoryProfileSharingActions({
</strong>
);

const learnMore = (
<a
href="https://support.signal.org/hc/articles/360007459591"
target="_blank"
rel="noreferrer"
className="module-message-request-actions__message__learn-more"
>
{i18n('icu:MessageRequests--learn-more')}
</a>
);

return (
<>
{mrState !== MessageRequestState.default ? (
Expand All @@ -85,14 +85,14 @@ export function MandatoryProfileSharingActions({
{conversationType === 'direct' ? (
<Intl
i18n={i18n}
id="icu:MessageRequests--profile-sharing--direct"
components={{ firstName: firstNameContact, learnMore }}
id="icu:MessageRequests--profile-sharing--direct--link"
components={{ firstName: firstNameContact, learnMoreLink }}
/>
) : (
<Intl
i18n={i18n}
id="icu:MessageRequests--profile-sharing--group"
components={{ firstName: firstNameContact, learnMore }}
id="icu:MessageRequests--profile-sharing--group--link"
components={{ firstName: firstNameContact, learnMoreLink }}
/>
)}
</p>
Expand Down

0 comments on commit da24cc5

Please sign in to comment.