Localization: Add more translations (#1112)

This commit is contained in:
Alexander Zinchuk 2021-05-24 13:10:09 +03:00
parent 01933bfcb1
commit d0dac76c8b
9 changed files with 51 additions and 80 deletions

View File

@ -94,7 +94,7 @@ const DeleteMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
<p>{lang('lng_delete_for_me_chat_hint')}</p> <p>{lang('lng_delete_for_me_chat_hint')}</p>
)} )}
{willDeleteForAll && ( {willDeleteForAll && (
<p>{lang('lng_delete_for_everyone_hint')}</p> <p>{lang('lng_delete_for_everyone_hint', 1, 'i')}</p>
)} )}
{canDeleteForAll && ( {canDeleteForAll && (
<Button color="danger" className="confirm-dialog-button" isText onClick={handleDeleteMessageForAll}> <Button color="danger" className="confirm-dialog-button" isText onClick={handleDeleteMessageForAll}>

View File

@ -65,24 +65,16 @@ const PinMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
const lang = useLang(); const lang = useLang();
function renderModalHeader() {
return (
<div className="modal-header">
<h3 className="modal-title">{lang('PinMessageAlertTitle')}</h3>
</div>
);
}
function renderMessage() { function renderMessage() {
if (isChannel) { if (isChannel) {
return <p>{lang('PinMessageAlertChannel')}</p>; return lang('PinMessageAlertChannel');
} }
if (isGroup || isSuperGroup) { if (isGroup || isSuperGroup) {
return <p>{lang('PinMessageAlert')}</p>; return lang('PinMessageAlert');
} }
return <p>{lang('PinMessageAlertChat')}</p>; return lang('PinMessageAlertChat');
} }
return ( return (
@ -90,15 +82,17 @@ const PinMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
isOpen={isOpen} isOpen={isOpen}
onClose={onClose} onClose={onClose}
className="pin" className="pin"
header={renderModalHeader()} title={lang('PinMessageAlertTitle')}
> >
{renderMessage()} <p>{renderMessage()}</p>
<Button className="confirm-dialog-button" isText onClick={handlePinMessage}> <Button className="confirm-dialog-button" isText onClick={handlePinMessage}>
{lang('DialogPin')} {lang('DialogPin')}
</Button> </Button>
{canPinForAll && ( {canPinForAll && (
<Button className="confirm-dialog-button" isText onClick={handlePinMessageForAll}> <Button className="confirm-dialog-button" isText onClick={handlePinMessageForAll}>
{contactName ? `Pin for me and ${contactName}` : 'Pin and notify all memebers'} {contactName
? lang('Conversation.PinMessagesFor', contactName)
: lang('Conversation.PinMessageAlert.PinAndNotifyMembers')}
</Button> </Button>
)} )}
<Button className="confirm-dialog-button" isText onClick={onClose}>{lang('Cancel')}</Button> <Button className="confirm-dialog-button" isText onClick={onClose}>{lang('Cancel')}</Button>

View File

@ -78,7 +78,7 @@ const StickerSetModal: FC<OwnProps & StateProps & DispatchProps> = ({
isOpen={isOpen} isOpen={isOpen}
onClose={onClose} onClose={onClose}
hasCloseButton hasCloseButton
title={stickerSet ? stickerSet.title : 'Sticker Set'} title={stickerSet ? stickerSet.title : lang('AccDescrStickerSet')}
> >
{stickerSet && stickerSet.stickers ? ( {stickerSet && stickerSet.stickers ? (
<> <>

View File

@ -1,7 +1,5 @@
import React, { FC, memo } from '../../lib/teact/teact'; import React, { FC, memo } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn';
import { selectPinnedIds } from '../../modules/selectors';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import Modal from '../ui/Modal'; import Modal from '../ui/Modal';
@ -10,42 +8,26 @@ import Button from '../ui/Button';
export type OwnProps = { export type OwnProps = {
isOpen: boolean; isOpen: boolean;
chatId?: number; chatId?: number;
pinnedMessagesCount?: number;
onClose: () => void; onClose: () => void;
onUnpin: () => void; onUnpin: () => void;
}; };
type StateProps = { const UnpinAllMessagesModal: FC<OwnProps> = ({
pinnedMessagesCount: number;
};
const UnpinAllMessagesModal: FC<OwnProps & StateProps> = ({
isOpen, isOpen,
pinnedMessagesCount, pinnedMessagesCount = 0,
onClose, onClose,
onUnpin, onUnpin,
}) => { }) => {
const lang = useLang(); const lang = useLang();
function renderModalHeader() {
return (
<div className="modal-header">
<h3 className="modal-title">{lang('UnpinAllMessages')}</h3>
</div>
);
}
function renderMessage() {
return <p>Do you want to unpin all {pinnedMessagesCount} messages in this chat?</p>;
}
return ( return (
<Modal <Modal
isOpen={isOpen} isOpen={isOpen}
onClose={onClose} onClose={onClose}
className="unpin-all" className="unpin-all"
header={renderModalHeader()} title={lang('Chat.PanelUnpinAllMessages')}
> >
{renderMessage()} <p>{lang('Chat.UnpinAllMessagesConfirmation', pinnedMessagesCount, 'i')}</p>
<Button className="confirm-dialog-button" isText onClick={onUnpin}> <Button className="confirm-dialog-button" isText onClick={onUnpin}>
{lang('DialogUnpin')} {lang('DialogUnpin')}
</Button> </Button>
@ -54,12 +36,4 @@ const UnpinAllMessagesModal: FC<OwnProps & StateProps> = ({
); );
}; };
export default memo(withGlobal<OwnProps>( export default memo(UnpinAllMessagesModal);
(global, { chatId }): StateProps => {
const pinnedIds = chatId ? selectPinnedIds(global, chatId) : [];
return {
pinnedMessagesCount: pinnedIds ? pinnedIds.length : 0,
};
},
)(UnpinAllMessagesModal));

View File

@ -78,7 +78,7 @@ const DeleteSelectedMessagesModal: FC<OwnProps & StateProps & DispatchProps> = (
onClose={onClose} onClose={onClose}
onEnter={canDeleteForAll ? undefined : handleDeleteMessageForSelf} onEnter={canDeleteForAll ? undefined : handleDeleteMessageForSelf}
className="delete" className="delete"
title="Delete Messages?" title={lang('Conversation.DeleteManyMessages')}
> >
<p>{lang('AreYouSureDeleteFewMessages')}</p> <p>{lang('AreYouSureDeleteFewMessages')}</p>
{willDeleteForCurrentUserOnly && ( {willDeleteForCurrentUserOnly && (
@ -89,12 +89,13 @@ const DeleteSelectedMessagesModal: FC<OwnProps & StateProps & DispatchProps> = (
)} )}
{canDeleteForAll && ( {canDeleteForAll && (
<Button color="danger" className="confirm-dialog-button" isText onClick={handleDeleteMessageForAll}> <Button color="danger" className="confirm-dialog-button" isText onClick={handleDeleteMessageForAll}>
Delete for {contactName ? 'me and ' : 'Everyone'} {contactName
{contactName && renderText(contactName)} ? lang('ChatList.DeleteForEveryone', renderText(contactName))
: lang('Conversation.DeleteMessagesForEveryone')}
</Button> </Button>
)} )}
<Button color="danger" className="confirm-dialog-button" isText onClick={handleDeleteMessageForSelf}> <Button color="danger" className="confirm-dialog-button" isText onClick={handleDeleteMessageForSelf}>
Delete{canDeleteForAll ? ' just for me' : ''} {lang(canDeleteForAll ? 'ChatList.DeleteForCurrentUser' : 'Delete')}
</Button> </Button>
<Button className="confirm-dialog-button" isText onClick={onClose}>{lang('Cancel')}</Button> <Button className="confirm-dialog-button" isText onClick={onClose}>{lang('Cancel')}</Button>
</Modal> </Modal>

View File

@ -58,6 +58,7 @@ type StateProps = {
canPost?: boolean; canPost?: boolean;
messageSendingRestrictionReason?: string; messageSendingRestrictionReason?: string;
hasPinnedOrAudioMessage?: boolean; hasPinnedOrAudioMessage?: boolean;
pinnedMessagesCount?: number;
customBackground?: string; customBackground?: string;
patternColor?: string; patternColor?: string;
isCustomBackgroundColor?: boolean; isCustomBackgroundColor?: boolean;
@ -85,6 +86,7 @@ const MiddleColumn: FC<StateProps & DispatchProps> = ({
canPost, canPost,
messageSendingRestrictionReason, messageSendingRestrictionReason,
hasPinnedOrAudioMessage, hasPinnedOrAudioMessage,
pinnedMessagesCount,
customBackground, customBackground,
patternColor, patternColor,
isCustomBackgroundColor, isCustomBackgroundColor,
@ -261,7 +263,7 @@ const MiddleColumn: FC<StateProps & DispatchProps> = ({
onClick={handleOpenUnpinModal} onClick={handleOpenUnpinModal}
> >
<i className="icon-unpin" /> <i className="icon-unpin" />
<span>{lang('Chat.PanelHidePinnedMessages')}</span> <span>{lang('Chat.Pinned.UnpinAll', pinnedMessagesCount, 'i')}</span>
</Button> </Button>
</div> </div>
)} )}
@ -296,6 +298,7 @@ const MiddleColumn: FC<StateProps & DispatchProps> = ({
<UnpinAllMessagesModal <UnpinAllMessagesModal
isOpen={isUnpinModalOpen} isOpen={isUnpinModalOpen}
chatId={chatId} chatId={chatId}
pinnedMessagesCount={pinnedMessagesCount}
onClose={closeUnpinModal} onClose={closeUnpinModal}
onUnpin={handleUnpinAllMessages} onUnpin={handleUnpinAllMessages}
/> />
@ -350,6 +353,7 @@ export default memo(withGlobal(
|| Boolean(pinnedIds && pinnedIds.length) || Boolean(pinnedIds && pinnedIds.length)
|| Boolean(audioChatId && audioMessageId) || Boolean(audioChatId && audioMessageId)
), ),
pinnedMessagesCount: pinnedIds ? pinnedIds.length : 0,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [ (setGlobal, actions): DispatchProps => pick(actions, [

View File

@ -149,11 +149,11 @@ const AttachmentModal: FC<OwnProps> = ({
let title = ''; let title = '';
if (areAllPhotos) { if (areAllPhotos) {
title = renderingAttachments.length === 1 ? 'Send Photo' : `Send ${renderingAttachments.length} Photos`; title = lang('PreviewSender.SendPhoto', renderingAttachments.length, 'i');
} else if (areAllVideos) { } else if (areAllVideos) {
title = renderingAttachments.length === 1 ? 'Send Video' : `Send ${renderingAttachments.length} Videos`; title = lang('PreviewSender.SendVideo', renderingAttachments.length, 'i');
} else { } else {
title = renderingAttachments.length === 1 ? 'Send File' : `Send ${renderingAttachments.length} Files`; title = lang('PreviewSender.SendFile', renderingAttachments.length, 'i');
} }
function renderHeader() { function renderHeader() {

View File

@ -46,6 +46,8 @@ const PollModal: FC<OwnProps> = ({ isOpen, onSend, onClear }) => {
const [correctOption, setCorrectOption] = useState<string>(); const [correctOption, setCorrectOption] = useState<string>();
const [hasErrors, setHasErrors] = useState<boolean>(false); const [hasErrors, setHasErrors] = useState<boolean>(false);
const lang = useLang();
const focusInput = useCallback((ref: RefObject<HTMLInputElement>) => { const focusInput = useCallback((ref: RefObject<HTMLInputElement>) => {
if (isOpen && ref.current) { if (isOpen && ref.current) {
ref.current.focus(); ref.current.focus();
@ -206,21 +208,19 @@ const PollModal: FC<OwnProps> = ({ isOpen, onSend, onClear }) => {
const getQuestionError = useCallback(() => { const getQuestionError = useCallback(() => {
if (hasErrors && !question.trim().length) { if (hasErrors && !question.trim().length) {
return 'Please enter the question'; return lang('lng_polls_choose_question');
} }
return undefined; return undefined;
}, [hasErrors, question]); }, [hasErrors, lang, question]);
const getOptionsError = useCallback((index: number) => { const getOptionsError = useCallback((index: number) => {
const optionsTrimmed = options.map((o) => o.trim()).filter((o) => o.length); const optionsTrimmed = options.map((o) => o.trim()).filter((o) => o.length);
if (hasErrors && optionsTrimmed.length < 2 && !options[index].trim().length) { if (hasErrors && optionsTrimmed.length < 2 && !options[index].trim().length) {
return 'Please enter at least two options'; return lang('lng_polls_choose_answers');
} }
return undefined; return undefined;
}, [hasErrors, options]); }, [hasErrors, lang, options]);
const lang = useLang();
function renderHeader() { function renderHeader() {
return ( return (
@ -246,8 +246,8 @@ const PollModal: FC<OwnProps> = ({ isOpen, onSend, onClear }) => {
<div className="option-wrapper"> <div className="option-wrapper">
<InputText <InputText
label={index !== options.length - 1 || options.length === MAX_OPTIONS_COUNT label={index !== options.length - 1 || options.length === MAX_OPTIONS_COUNT
? `Option ${index + 1}` ? lang('OptionHint')
: 'Add an Option'} : lang('CreatePoll.AddOption')}
error={getOptionsError(index)} error={getOptionsError(index)}
value={option} value={option}
onChange={(e) => updateOption(index, e.currentTarget.value)} onChange={(e) => updateOption(index, e.currentTarget.value)}
@ -259,7 +259,7 @@ const PollModal: FC<OwnProps> = ({ isOpen, onSend, onClear }) => {
round round
color="translucent" color="translucent"
size="smaller" size="smaller"
ariaLabel="Remove option" ariaLabel={lang('Delete')}
onClick={() => removeOption(index)} onClick={() => removeOption(index)}
> >
<i className="icon-close" /> <i className="icon-close" />
@ -278,9 +278,7 @@ const PollModal: FC<OwnProps> = ({ isOpen, onSend, onClear }) => {
const optionsTrimmed = options.map((o) => o.trim()).filter((o) => o.length); const optionsTrimmed = options.map((o) => o.trim()).filter((o) => o.length);
return isQuizMode && (!correctOption || !optionsTrimmed[Number(correctOption)]) && ( return isQuizMode && (!correctOption || !optionsTrimmed[Number(correctOption)]) && (
<p className="error"> <p className="error">{lang('lng_polls_choose_correct')}</p>
Please choose the correct answer
</p>
); );
} }
@ -341,9 +339,7 @@ const PollModal: FC<OwnProps> = ({ isOpen, onSend, onClear }) => {
contentEditable contentEditable
onChange={(e) => setSolution(e.currentTarget.innerHTML)} onChange={(e) => setSolution(e.currentTarget.innerHTML)}
/> />
<div className="note"> <div className="note">{lang('CreatePoll.ExplanationInfo')}</div>
Users will see this comment after choosing a wrong answer, good for educational purposes.
</div>
</> </>
)} )}
</div> </div>

View File

@ -167,12 +167,12 @@ const Invoice: FC<OwnProps & StateProps & GlobalStateProps & DispatchProps> = ({
onClose={handleErrorModalClose} onClose={handleErrorModalClose}
> >
<h4>{error.description || 'Error'}</h4> <h4>{error.description || 'Error'}</h4>
{error.description || 'Error'} <p>{error.description || 'Error'}</p>
<Button <Button
isText isText
onClick={clearPaymentError} onClick={clearPaymentError}
> >
OK {lang('OK')}
</Button> </Button>
</Modal> </Modal>
); );
@ -287,11 +287,11 @@ const Invoice: FC<OwnProps & StateProps & GlobalStateProps & DispatchProps> = ({
const buttonText = useMemo(() => { const buttonText = useMemo(() => {
switch (step) { switch (step) {
case PaymentStep.Checkout: case PaymentStep.Checkout:
return `Pay ${currencySign}${(totalPrice / 100).toFixed(2)}`; return lang('Checkout.PayPrice', `${currencySign}${(totalPrice / 100).toFixed(2)}`);
default: default:
return 'Next Step'; return lang('Next');
} }
}, [step, totalPrice, currencySign]); }, [step, lang, currencySign, totalPrice]);
if (isProviderError) { if (isProviderError) {
return ( return (
@ -300,13 +300,15 @@ const Invoice: FC<OwnProps & StateProps & GlobalStateProps & DispatchProps> = ({
isOpen={isOpen} isOpen={isOpen}
onClose={onClose} onClose={onClose}
> >
Sorry, Telegram T doesn&apos;t support payments with this provider yet. <p>
Please use one of our mobile apps to do this. Sorry, Telegram T doesn&apos;t support payments with this provider yet. <br />
Please use one of our mobile apps to do this.
</p>
<Button <Button
isText isText
onClick={onClose} onClick={onClose}
> >
OK {lang('OK')}
</Button> </Button>
</Modal> </Modal>
); );
@ -329,7 +331,7 @@ const Invoice: FC<OwnProps & StateProps & GlobalStateProps & DispatchProps> = ({
> >
<i className="icon-close" /> <i className="icon-close" />
</Button> </Button>
<h3>{ modalHeader }</h3> <h3>{modalHeader}</h3>
</div> </div>
{step !== undefined ? ( {step !== undefined ? (
<Transition name="slide" activeKey={step}> <Transition name="slide" activeKey={step}>