Localization: Various fixes (#6178)
This commit is contained in:
parent
794e442d8b
commit
8b8c94b715
@ -76,6 +76,7 @@
|
||||
"PremiumLimitAccountsNoPremium" = "You have reached your current limit of connected accounts. You can free one more place by subscribing to Telegram Premium.";
|
||||
"PremiumLimitAccounts" = "You have reached your current limit of connected accounts. You can free one more place by subscribing to Telegram Premium with one of these connected accounts.";
|
||||
"SendMessage" = "Send Message";
|
||||
"MessageUnsupported" = "This message is not supported on the web version of Telegram";
|
||||
"ConversationDefaultRestrictedMedia" = "Sending media isn't allowed in this group.";
|
||||
"AccDescrVoiceMessage" = "Record voice message";
|
||||
"BotSettings" = "Settings";
|
||||
@ -87,7 +88,7 @@
|
||||
"ContextCopySelected" = "Copy Selected Text";
|
||||
"ContextCopyText" = "Copy Text";
|
||||
"ContextArchiveCollapse" = "Collapse";
|
||||
"ContextArchiveExpand" = "Collapse";
|
||||
"ContextArchiveExpand" = "Expand";
|
||||
"ContextArchiveToMenu" = "Move to Main Menu";
|
||||
"CallMessageVideoIncomingDeclined" = "Declined Video Call";
|
||||
"CallMessageVideoOutgoingMissed" = "Canceled Video Call";
|
||||
@ -129,6 +130,7 @@
|
||||
"UserRestrictionsNoChangeInfo" = "can't change Info";
|
||||
"UserRestrictionsInviteUsers" = "Add Users";
|
||||
"UserRestrictionsPinMessages" = "Pin Messages";
|
||||
"ChatPermissionNotAvailable" = "This permission is not available in public groups.";
|
||||
"StatsMessageInteractionsTitle" = "INTERACTIONS";
|
||||
"StatsGroupGrowthTitle" = "GROWTH";
|
||||
"StatsGroupMembersTitle" = "GROUP MEMBERS";
|
||||
@ -474,6 +476,7 @@
|
||||
"AlwaysShareWith" = "Always Share With";
|
||||
"NeverShareWith" = "Never Share With";
|
||||
"SessionsTitle" = "Active Sessions";
|
||||
"SessionTerminate" = "Terminate";
|
||||
"OtherWebSessions" = "Connected Websites";
|
||||
"BlockedUsers" = "Blocked Users";
|
||||
"TwoStepVerification" = "Two-Step Verification";
|
||||
@ -522,7 +525,7 @@
|
||||
"WhoCanCallMe" = "Who can call me";
|
||||
"PrivacyP2P" = "Peer-to-Peer Calls";
|
||||
"PrivacyForwardsTitle" = "Who can add a link to my account when forwarding my messages?";
|
||||
"WhoCanAddMe" = "Who can add me to group chats?";
|
||||
"WhoCanAddMe" = "Who can add me to groups and channels?";
|
||||
"NewChatsFromNonContacts" = "New chats from unknown users";
|
||||
"ArchiveAndMute" = "Archive and Mute";
|
||||
"ArchiveAndMuteInfo" = "Automatically archive and mute new chats, groups and channels from non-contacts.";
|
||||
@ -689,6 +692,7 @@
|
||||
"SettingsPerformanceStickerEffects" = "Sticker Effects";
|
||||
"SettingsPerformanceAutoplayGif" = "Autoplay GIFs";
|
||||
"SettingsPerformanceAutoplayVideo" = "Autoplay Videos";
|
||||
"SettingsPerformanceGranularTitle" = "Resource-Intensive Processes";
|
||||
"FavoriteStickers" = "Favorites";
|
||||
"PremiumStickers" = "Premium Stickers";
|
||||
"GroupStickers" = "Group Stickers";
|
||||
@ -711,7 +715,6 @@
|
||||
"ErrorUnspecified" = "Error";
|
||||
"NoStickers" = "No stickers yet";
|
||||
"ClearRecentEmoji" = "Clear recent emoji?";
|
||||
"TextFormatAddLinkTitle" = "Add Link";
|
||||
"Save" = "Save";
|
||||
"ConversationEmptyPlaceholder" = "No messages here yet...";
|
||||
"ConversationGreetingText" = "Send a message or tap on the greeting below.";
|
||||
@ -957,8 +960,16 @@
|
||||
"ChannelPermissionsHeader" = "What can members of this group do?";
|
||||
"UserRestrictionsSend" = "Send Messages";
|
||||
"UserRestrictionsSendMedia" = "Send Media";
|
||||
"UserRestrictionsSendStickers" = "Send Stickers & GIFs";
|
||||
"UserRestrictionsSendPolls" = "Send Polls";
|
||||
"UserRestrictionsCreateTopics" = "Create Topics";
|
||||
"SendMediaPermissionFiles" = "Files";
|
||||
"SendMediaPermissionPhotos" = "Photos";
|
||||
"SendMediaPermissionVideos" = "Videos";
|
||||
"SendMediaPermissionStickersGifs" = "Stickers & GIFs";
|
||||
"SendMediaPermissionAudios" = "Music";
|
||||
"SendMediaPermissionVoices" = "Voice Messages";
|
||||
"SendMediaPermissionRoundVideos" = "Video Messages";
|
||||
"SendMediaPermissionWebPages" = "Embed Links";
|
||||
"SendMediaPermissionPolls" = "Polls";
|
||||
"UserRestrictionsEmbedLinks" = "Embed Links";
|
||||
"UserRestrictionsChangeInfo" = "Change Chat Info";
|
||||
"ChannelAddException" = "Add Exception";
|
||||
@ -1089,12 +1100,14 @@
|
||||
"ChannelPersmissionDeniedSendMessagesForever" = "The admins of this group have restricted your ability to send messages.";
|
||||
"ChannelPersmissionDeniedSendMessagesDefaultRestrictedText" = "Sending messages is not allowed in this group.";
|
||||
"Chats" = "Chats";
|
||||
"ChatsPlural_one" = "{count} chat";
|
||||
"ChatsPlural_other" = "{count} chats";
|
||||
"NewDiscussionChatTitle" = "{name} Chat";
|
||||
"FilterBots" = "Bots";
|
||||
"FilterContacts" = "Contacts";
|
||||
"FilterNonContacts" = "Non-Contacts";
|
||||
"FromYou" = "You";
|
||||
"InDlgAlbum" = "Album";
|
||||
"Album" = "Album";
|
||||
"AttachPhoto" = "Photo";
|
||||
"AttachGif" = "GIF";
|
||||
"AttachVideo" = "Video";
|
||||
@ -1102,8 +1115,12 @@
|
||||
"AttachMusic" = "Music";
|
||||
"AttachContact" = "Contact";
|
||||
"AttachStory" = "Story";
|
||||
"MessageLocation" = "Location";
|
||||
"MessageLiveLocation" = "Live Location";
|
||||
"AttachInvoice" = "Invoice: {description}";
|
||||
"AttachLocation" = "Location";
|
||||
"AttachLiveLocation" = "Live Location";
|
||||
"AttachGiveaway" = "Giveaway";
|
||||
"AttachGiveawayResults" = "Giveaway Results";
|
||||
"AttachTodo" = "Checklist";
|
||||
"ServiceNotifications" = "service notifications";
|
||||
"Bot" = "bot";
|
||||
"ALongTimeAgo" = "last seen a long time ago";
|
||||
@ -1277,6 +1294,7 @@
|
||||
"SettingsPasscodeStart1" = "When you set up an additional passcode, a lock icon will appear on the chats page.\nTap it to lock and unlock your Telegram Web A.";
|
||||
"SettingsPasscodeStart2" = "Note: if you forget your local passcode, you'll need to log out of Telegram Web A and log in again.";
|
||||
"CurrentPasswordPlaceholder" = "Current password";
|
||||
"ChangeYourProfilePicture" = "Change your profile picture";
|
||||
"TooManyTabsTitle" = "Such error, many tabs";
|
||||
"TooManyTabsDescription" = "Telegram supports only one active tab with the app.\nPlease reload this page to continue using this tab or close it.";
|
||||
"TooManyTabsReload" = "Reload app";
|
||||
@ -1338,6 +1356,7 @@
|
||||
"FormattingMonospaceAria" = "Monospace text";
|
||||
"FormattingUnderlineAria" = "Underlined text";
|
||||
"FormattingStrikethroughAria" = "Strikethrough text";
|
||||
"FormattingAddLinkAria" = "Add Link";
|
||||
"FormattingEnterUrl" = "Enter URL...";
|
||||
"PreviewWebPageClose" = "Clear Webpage Preview";
|
||||
"MediaLocaltionImageAlt" = "Location on a map";
|
||||
@ -1395,6 +1414,12 @@
|
||||
"ProfileOpenAppAbout" = "By launching this mini app, you agree to the {terms}.";
|
||||
"ProfileOpenAppTerms" = "Terms of Service for Mini Apps";
|
||||
"ProfileBotOpenAppInfoLink" = "https://telegram.org/tos/mini-apps";
|
||||
"ProfileBirthday" = "Date of birth";
|
||||
"ProfileBirthdayToday" = "Birthday today";
|
||||
"ProfileBirthdayValue" = "{date}";
|
||||
"ProfileBirthdayValueYear" = "{date} ({age} years old)";
|
||||
"ProfileBirthdayTodayValue" = "🎂 {date}";
|
||||
"ProfileBirthdayTodayValueYear" = "🎂 {date} ({age} years old)";
|
||||
"MonetizationInfoTONTitle" = "What is 💎 TON?";
|
||||
"ChannelEarnLearnCoinAbout" = "TON is a blockchain platform and cryptocurrency that Telegram uses for its high speed and low commissions on transactions. {link}";
|
||||
"MonetizationBalanceZeroInfo" = "You will be able to collect rewards using Fragment, a third-party platform used by advertisers to pay for ads. {link}";
|
||||
@ -1544,6 +1569,7 @@
|
||||
"StarsReactionTerms" = "By sending Stars you agree to the {link}";
|
||||
"StarsReactionLinkText" = "Terms of Service";
|
||||
"StarsReactionLink" = "https://telegram.org/tos/stars";
|
||||
"AriaMiniApp" = "{bot} Mini App";
|
||||
"MiniAppsMoreTabs_one" = "{botName} & {count} Other";
|
||||
"MiniAppsMoreTabs_other" = "{botName} & {count} Others";
|
||||
"PrizeCredits2_one" = "Your prize is {count} Star.";
|
||||
@ -1645,6 +1671,9 @@
|
||||
"SearchTabVoice" = "Voice";
|
||||
"SearchTabMessages" = "Messages";
|
||||
"SearchTabPublicPosts" = "Posts";
|
||||
"SearchResultTopics" = "Topics";
|
||||
"SearchResultMyChannels" = "Channels you joined";
|
||||
"SearchResultRecommendedChannels" = "Similar Channels";
|
||||
"StarsTransactionsAll" = "All Transactions";
|
||||
"StarsTransactionsIncoming" = "Incoming";
|
||||
"StarsTransactionsOutgoing" = "Outgoing";
|
||||
@ -1701,6 +1730,8 @@
|
||||
"CheckPasswordTitle" = "Enter Password";
|
||||
"CheckPasswordPlaceholder" = "Password";
|
||||
"CheckPasswordDescription" = "Please enter your password to continue.";
|
||||
"PasswordFormPlaceholder" = "Password";
|
||||
"PasswordFormSubmit" = "Next";
|
||||
"ActionFallbackUser" = "User";
|
||||
"ActionFallbackChat" = "Chat";
|
||||
"ActionFallbackChannel" = "Channel";
|
||||
@ -1921,8 +1952,8 @@
|
||||
"GiftPremiumPayWithStarsAcc" = "Pay with stars";
|
||||
"GetMoreStarsLinkText" = "Get More Stars >";
|
||||
"GiftPremiumDescriptionYourBalance" = "Your balance is **{stars}**. {link}";
|
||||
"StarsGiftCompleted"= "Gift sent!";
|
||||
"GiftSent"= "Gift sent!";
|
||||
"StarsGiftCompleted" = "Gift sent!";
|
||||
"GiftSent" = "Gift sent!";
|
||||
"PrivacyDescriptionMessagesContactsAndPremium" = "You can restrict messages from users who are not in your contacts and don't have Premium.";
|
||||
"PrivacyChargeForMessages" = "Charge for Messages";
|
||||
"PrivacyDescriptionChargeForMessages" = "Charge a fee for messages from people outside your contacts or those you haven't messaged first.";
|
||||
@ -1948,7 +1979,7 @@
|
||||
"MessageSentPaidToastText" = "You paid {amount}";
|
||||
"ButtonUndo" = "Undo";
|
||||
"ActionPaidOneMessageOutgoing" = "You paid {amount} to send a message";
|
||||
"ActionPaidOneMessageIncoming" = "You received {amount} from {user}";
|
||||
"ActionPaidOneMessageIncoming" = "{user} paid {amount} to send a message";
|
||||
"PaneMessagePaidMessageCharge" = "{peer} must pay {amount} for each message to you.";
|
||||
"ConfirmRemoveMessageFee" = "Yes";
|
||||
"ConfirmDialogMessageRemoveFee" = "Are you sure you want to allow **{peer}** to message you for free?";
|
||||
@ -1967,7 +1998,7 @@
|
||||
"ComposerSubtitleFrozenAccount" = "Tap to view details";
|
||||
"DescriptionRestrictedMedia" = "Posting media content is not allowed in this group.";
|
||||
"DescriptionScheduledPaidMediaNotAllowed" = "Posting scheduled paid media content is not allowed";
|
||||
"DescriptionScheduledPaidMessagesNotAllowed" = "Scheduled paid messages is not allowed";
|
||||
"DescriptionScheduledPaidMessagesNotAllowed" = "Paid messages can't be scheduled";
|
||||
"GroupMessagesChargePrice" = "Charge Stars for Messages";
|
||||
"RightsChargeStarsAbout" = "If you turn this on, regular members of the group will have to pay Stars to send messages.";
|
||||
"SetPriceGroupDescription" = "Your group will receive {percent} of the selected fee (~{amount}) for each incoming messages.";
|
||||
@ -1996,7 +2027,7 @@
|
||||
"GiftRibbonSale" = "sale";
|
||||
"ButtonBuyGift" = "Buy for {stars}";
|
||||
"GiftInfoBuyGift" = "{user} is selling this gift and you can buy it.";
|
||||
"StarsGiftBought"= "You bought gift!";
|
||||
"StarsGiftBought" = "You bought a gift!";
|
||||
"ButtonSellGift" = "Sell for {stars}";
|
||||
"GiftSellTitle" = "Sell Gift";
|
||||
"Sell" = "Sell";
|
||||
@ -2035,7 +2066,7 @@
|
||||
"SendInStandardQuality" = "Send In Standard Quality";
|
||||
"SendInHighQuality" = "Send In High Quality";
|
||||
"MonoforumBadge" = "DIRECT";
|
||||
"MonoforumStatus" = "Channel messages";
|
||||
"MonoforumStatus" = "Direct messages";
|
||||
"MonoforumComposerPlaceholder" = "Choose a message to reply";
|
||||
"ChannelSendMessage" = "Direct Messages";
|
||||
"AutomaticTranslation" = "Automatic Translation";
|
||||
@ -2043,7 +2074,7 @@
|
||||
"ComposerEmbeddedMessageSuggestedPostDescription" = "Tap to offer a price for publishing";
|
||||
"TitleSuggestedPostAmountForAnyTime" = "{amount} for publishing anytime";
|
||||
"ActionSuggestedPostOutgoing" = "**You** suggest to post this message.";
|
||||
"ActionSuggestedPostIncoming" = "**{user}** suggest to post this message.";
|
||||
"ActionSuggestedPostIncoming" = "**{user}** suggested to post this message.";
|
||||
"ActionSuggestedChangesPrice" = "price";
|
||||
"ActionSuggestedChangesText" = "text";
|
||||
"ActionSuggestedChangesTime" = "time";
|
||||
@ -2063,7 +2094,7 @@
|
||||
"SuggestMessageTimeDescription" = "{hint} The post will remain available for at least {duration} from this date.";
|
||||
"SuggestMessageAnytime" = "Anytime";
|
||||
"ButtonOfferAmount" = "Offer {amount}";
|
||||
"ButtonOfferFree" = "Offer Free";
|
||||
"ButtonOfferFree" = "Offer for Free";
|
||||
"ButtonUpdateTerms" = "Update Terms";
|
||||
"InputPlaceholderPrice" = "Enter Price";
|
||||
"SuggestedPostApprove" = "Approve";
|
||||
@ -2079,10 +2110,10 @@
|
||||
"SuggestedPostPublishedYou" = "📅 Your post was automatically published on {peer} **{date}**.";
|
||||
"SuggestedPostCharged" = "💰 {user} has been charged {amount}.";
|
||||
"SuggestedPostChargedYou" = "💰 You have been charged {amount}.";
|
||||
"SuggestedPostReceiveAmount" = "⏳ {peer} will receive the {currency} once the post has been live for {duration}.";
|
||||
"SuggestedPostReceiveAmountYou" = "⏳ {peer} will receive your {currency} once the post has been live for {duration}.";
|
||||
"SuggestedPostReceiveAmount" = "⏳ {peer} will receive the payment once the post has been live for {duration}.";
|
||||
"SuggestedPostReceiveAmountYou" = "⏳ {peer} will receive your payment once the post has been live for {duration}.";
|
||||
"SuggestedPostRefund" = "🔄 If {peer} removes the post before it has been live for {duration}, payment will be refunded.";
|
||||
"SuggestedPostRefundYou" = "🔄 If {peer} removes the post before it has been live for {duration}, your {currency} will be refunded.";
|
||||
"SuggestedPostRefundYou" = "🔄 If {peer} removes the post before it has been live for {duration}, your payment will be refunded.";
|
||||
"SuggestedPostBalanceTooLow" = "⚠️ **Transaction failed** because {peer} didn't have enough {currency}.";
|
||||
"SuggestedPostRefundedByUser" = "{channel} will not receive {amount} because {user} requested a refund.";
|
||||
"SuggestedPostRefundedByChannel" = "{amount} was returned to {peer} because {channel} deleted the message.";
|
||||
@ -2092,8 +2123,8 @@
|
||||
"DeclinePostDialogQuestion" = "Do you want to decline this post from **{sender}**?";
|
||||
"SuggestedPostRejected" = "**{peer}** rejected this message.";
|
||||
"SuggestedPostRejectedYou" = "You rejected this message.";
|
||||
"SuggestedPostRejectedWithReason" = "**{peer}** rejected this message with the comment.";
|
||||
"SuggestedPostRejectedWithReasonYou" = "You rejected this message with the comment.";
|
||||
"SuggestedPostRejectedWithReason" = "**{peer}** rejected this message with the comment:";
|
||||
"SuggestedPostRejectedWithReasonYou" = "You rejected this message with the comment:";
|
||||
"SuggestedPostRejectedComment" = "\"{comment}\"";
|
||||
"ActionSuggestedPostSuccess" = "{channel} has received {amount} for publishing post";
|
||||
"ComposerPlaceholderCaption" = "Caption";
|
||||
@ -2101,15 +2132,15 @@
|
||||
"SuggestedPostConfirmTitle" = "Accept Terms";
|
||||
"SuggestedPostConfirmMessage" = "Do you want to publish this post from **{peer}**?";
|
||||
"SuggestedPostConfirmDetailsAdmin" = "You will receive **{amount}** ({commission}%) for publishing this post. It must remain visible for at least {duration} after publication.";
|
||||
"SuggestedPostConfirmDetailsUser" = "You will pay **{amount}** ({commission}%) for publishing this post. It must remain visible for at least {duration} after publication.";
|
||||
"SuggestedPostConfirmDetailsUser" = "You will pay **{amount}** for publishing this post. It must remain visible for at least {duration} after publication.";
|
||||
"SuggestedPostConfirmDetailsWithTimeAdmin" = "You will receive **{amount}** ({commission}%) for publishing this post **{time}**. It must remain visible for at least {duration} after publication.";
|
||||
"SuggestedPostConfirmDetailsWithTimeUser" = "You will pay **{amount}** ({commission}%) for publishing this post **{time}**. It must remain visible for at least {duration} after publication.";
|
||||
"SuggestedPostConfirmDetailsWithTimeUser" = "You will pay **{amount}** for publishing this post **{time}**. It must remain visible for at least {duration} after publication.";
|
||||
"ButtonPublish" = "Publish";
|
||||
"ButtonPublishAtTime" = "Publish {time}";
|
||||
"ButtonPublishAtTime" = "Post {time}";
|
||||
"PublishNow" = "Publish Now";
|
||||
"TitleNewToDoList" = "New Checklist";
|
||||
"TitleEditToDoList" = "Edit Checklist";
|
||||
"TitleAppendToDoList" = "Append Checklist";
|
||||
"TitleAppendToDoList" = "Add Task";
|
||||
"InputTitle" = "Title";
|
||||
"TitleToDoList" = "Checklist";
|
||||
"TitleTask" = "Task";
|
||||
@ -2139,16 +2170,17 @@
|
||||
"PremiumMore" = "More";
|
||||
"SubscribeToTelegramPremiumForToggleTask" = "Subscribe to **Telegram Premium** to toggle tasks";
|
||||
"SubscribeToTelegramPremiumForCreateToDo" = "Subscribe to **Telegram Premium** to create Checklists";
|
||||
"SubscribeToTelegramPremiumForAppendToDo" = "Subscribe to **Telegram Premium** to append Checklists";
|
||||
"HintTodoListTasksCount" = "You can add {count} more tasks";
|
||||
"SubscribeToTelegramPremiumForAppendToDo" = "Subscribe to **Telegram Premium** to add tasks";
|
||||
"HintTodoListTasksCount2_one" = "You can add {count} more task";
|
||||
"HintTodoListTasksCount2_other" = "You can add {count} more tasks";
|
||||
"ToDoListErrorChooseTitle" = "Please enter a title.";
|
||||
"ToDoListErrorChooseTasks" = "Please enter at least one task.";
|
||||
"GiftInfoCollectibleBy" = "Collectible #{number} by **{owner}**";
|
||||
"PremiumPreviewTodo" = "Checklists";
|
||||
"DescriptionAboutTon" = "Offer TON to submit post suggestions to channels on Telegram.";
|
||||
"ButtonTopUpViaFragment" = "Top-Up Via Fragment";
|
||||
"TonModalHint" = "You can top-up your TON using Fragment.";
|
||||
"TonGiftReceived" = "TON Top-Up";
|
||||
"ButtonTopUpViaFragment" = "Top Up Via Fragment";
|
||||
"TonModalHint" = "You can top up your TON using Fragment.";
|
||||
"TonGiftReceived" = "TON Top Up";
|
||||
"MediaSpoilerSensitive" = "18+";
|
||||
"TitleSensitiveModal" = "{years}+ content";
|
||||
"TextSensitiveModal" = "This media may contain sensitive content suitable only for adults. Do you still want to view it?";
|
||||
@ -2162,9 +2194,11 @@
|
||||
"TitleAgeCheckSuccess" = "Age Check Success";
|
||||
"ButtonAgeVerification" = "Verify My Age";
|
||||
"GiftRibbonPremium" = "premium";
|
||||
"NotificationGiftsLimit" = "You've already sent {count} of these gifts, and it's the limit.";
|
||||
"NotificationGiftsLimit2_one" = "You've already sent **one** of these gifts, and it's the limit.";
|
||||
"NotificationGiftsLimit2_other" = "You've already sent {count} of these gifts, and it's the limit.";
|
||||
"PremiumGiftHeader" = "Premium Gift";
|
||||
"DescriptionGiftPremiumRequired" = "Subscribe to **Telegram Premium** to send up to **{count}** of these gifts and unlock access to multiple additional features.";
|
||||
"DescriptionGiftPremiumRequired2_one" = "Subscribe to **Telegram Premium** to send **one** of these gifts and unlock powerful features.";
|
||||
"DescriptionGiftPremiumRequired2_other" = "Subscribe to **Telegram Premium** to send up to **{count}** of these gifts and unlock powerful features.";
|
||||
"PriceInStars" = "Price in Stars";
|
||||
"PriceInTON" = "Price in TON";
|
||||
"DescriptionComposerGiftMinimumCurrencyPrice" = "Minimum price is **{amount}**.";
|
||||
@ -2199,7 +2233,7 @@
|
||||
"PublicPostsPremiumFeatureSubtitle" = "Global search is a Premium feature.";
|
||||
"PublicPostsSubscribeToPremium" = "Subscribe to Premium";
|
||||
"NotificationPaidExtraSearch" = "{stars} spent on extra search.";
|
||||
"PostsSearchTransaction" = "Posts Search";
|
||||
"PostsSearchTransaction" = "Public Post Search";
|
||||
"TitleRating" = "Rating";
|
||||
"RatingReflectsActivity" = "This rating reflects {name}'s activity on Telegram. It is based on:";
|
||||
"RatingYourReflectsActivity" = "This rating reflects your activity on Telegram. It is based on:";
|
||||
@ -2218,4 +2252,7 @@
|
||||
"DescriptionFutureRating_one" = "This will be your rating in {time}, after {points} point is added. {link}";
|
||||
"DescriptionFutureRating_other" = "This will be your rating in {time}, after {points} points are added. {link}";
|
||||
"LinkDescriptionRatingBack" = "Back >";
|
||||
"LinkDescriptionRatingPreview" = "Preview >";
|
||||
"LinkDescriptionRatingPreview" = "Preview >";
|
||||
"ErrorFocusInaccessibleMessage" = "Unfortunately, you can't access this message. You aren't a member of the chat where it was posted.";
|
||||
"ContextMenuHintMouse" = "To edit or reply, close this menu. Then right click on a message.";
|
||||
"ContextMenuHintTouch" = "To edit or reply, close this menu. Then long tap on a message.";
|
||||
|
||||
@ -36,7 +36,7 @@ const AuthPassword: FC<StateProps> = ({
|
||||
<h1>{lang('LoginHeaderPassword')}</h1>
|
||||
<p className="note">{lang('LoginEnterPasswordDescription')}</p>
|
||||
<PasswordForm
|
||||
clearError={clearAuthErrorKey}
|
||||
onClearError={clearAuthErrorKey}
|
||||
error={authErrorKey && lang.withRegular(authErrorKey)}
|
||||
hint={authHint}
|
||||
isLoading={authIsLoading}
|
||||
|
||||
@ -22,7 +22,7 @@ import { selectPeerStory, selectPollFromMessage } from '../../global/selectors';
|
||||
import trimText from '../../util/trimText';
|
||||
import renderText from './helpers/renderText';
|
||||
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
import useLang from '../../hooks/useLang';
|
||||
|
||||
import ActionMessageText from '../middle/message/ActionMessageText';
|
||||
import MessageText from './MessageText';
|
||||
@ -59,7 +59,7 @@ function MessageSummary({
|
||||
observeIntersectionForLoading,
|
||||
observeIntersectionForPlaying,
|
||||
}: OwnProps & StateProps) {
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
const extractedText = extractMessageText(message, inChatList);
|
||||
const hasPoll = Boolean(getMessagePollId(message));
|
||||
const isAction = isActionMessage(message);
|
||||
|
||||
@ -7,11 +7,11 @@ import type { ObserveFn } from '../../hooks/useIntersectionObserver';
|
||||
import type { ThreadId } from '../../types';
|
||||
import { ApiMessageEntityTypes } from '../../api/types';
|
||||
|
||||
import { CONTENT_NOT_SUPPORTED } from '../../config';
|
||||
import { extractMessageText, stripCustomEmoji } from '../../global/helpers';
|
||||
import trimText from '../../util/trimText';
|
||||
import { insertTextEntity, renderTextWithEntities } from './helpers/renderTextWithEntities';
|
||||
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useSyncEffect from '../../hooks/useSyncEffect';
|
||||
import useUniqueId from '../../hooks/useUniqueId';
|
||||
|
||||
@ -67,6 +67,8 @@ function MessageText({
|
||||
|
||||
const textCacheBusterRef = useRef(0);
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
const formattedText = translatedText || extractMessageText(messageOrStory, inChatList);
|
||||
const adaptedFormattedText = isForAnimation && formattedText ? stripCustomEmoji(formattedText) : formattedText;
|
||||
const { text, entities } = adaptedFormattedText || {};
|
||||
@ -106,7 +108,7 @@ function MessageText({
|
||||
}, [entitiesWithFocusedQuote]) || 0;
|
||||
|
||||
if (!text && !canBeEmpty) {
|
||||
return <span className="content-unsupported">{CONTENT_NOT_SUPPORTED}</span>;
|
||||
return <span className="content-unsupported">{lang('MessageUnsupported')}</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -13,7 +13,7 @@ import stopEvent from '../../util/stopEvent';
|
||||
|
||||
import useTimeout from '../../hooks/schedulers/useTimeout';
|
||||
import useAppLayout from '../../hooks/useAppLayout';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
import useLang from '../../hooks/useLang';
|
||||
|
||||
import Button from '../ui/Button';
|
||||
import Icon from './icons/Icon';
|
||||
@ -29,8 +29,8 @@ type OwnProps = {
|
||||
shouldShowSubmit?: boolean;
|
||||
shouldResetValue?: boolean;
|
||||
isPasswordVisible?: boolean;
|
||||
clearError: NoneToVoidFunction;
|
||||
noRipple?: boolean;
|
||||
onClearError: NoneToVoidFunction;
|
||||
onChangePasswordVisibility: (state: boolean) => void;
|
||||
onInputChange?: (password: string) => void;
|
||||
onSubmit?: (password: string) => void;
|
||||
@ -41,20 +41,21 @@ const PasswordForm: FC<OwnProps> = ({
|
||||
isPasswordVisible,
|
||||
error,
|
||||
hint,
|
||||
placeholder = 'Password',
|
||||
submitLabel = 'Next',
|
||||
placeholder,
|
||||
submitLabel,
|
||||
description,
|
||||
shouldShowSubmit,
|
||||
shouldResetValue,
|
||||
shouldDisablePasswordManager = false,
|
||||
noRipple = false,
|
||||
clearError,
|
||||
onClearError,
|
||||
onChangePasswordVisibility,
|
||||
onInputChange,
|
||||
onSubmit,
|
||||
}) => {
|
||||
const inputRef = useRef<HTMLInputElement>();
|
||||
const lang = useOldLang();
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
const { isMobile } = useAppLayout();
|
||||
const [password, setPassword] = useState('');
|
||||
@ -84,7 +85,7 @@ const PasswordForm: FC<OwnProps> = ({
|
||||
|
||||
function onPasswordChange(e: ChangeEvent<HTMLInputElement>) {
|
||||
if (error) {
|
||||
clearError();
|
||||
onClearError();
|
||||
}
|
||||
|
||||
const { target } = e;
|
||||
@ -141,14 +142,14 @@ const PasswordForm: FC<OwnProps> = ({
|
||||
maxLength={256}
|
||||
dir="auto"
|
||||
/>
|
||||
<label>{error || hint || placeholder}</label>
|
||||
<label>{error || hint || placeholder || lang('PasswordFormPlaceholder')}</label>
|
||||
<div
|
||||
className="div-button toggle-password"
|
||||
onClick={togglePasswordVisibility}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
title="Toggle password visibility"
|
||||
aria-label="Toggle password visibility"
|
||||
title={lang('AriaPasswordToggle')}
|
||||
aria-label={lang('AriaPasswordToggle')}
|
||||
>
|
||||
<Icon name={isPasswordVisible ? 'eye' : 'eye-crossed'} />
|
||||
</div>
|
||||
@ -156,7 +157,7 @@ const PasswordForm: FC<OwnProps> = ({
|
||||
{description && <p className="description">{description}</p>}
|
||||
{onSubmit && (canSubmit || shouldShowSubmit) && (
|
||||
<Button type="submit" ripple={!noRipple} isLoading={isLoading} disabled={!canSubmit}>
|
||||
{submitLabel}
|
||||
{submitLabel || lang('PasswordFormSubmit')}
|
||||
</Button>
|
||||
)}
|
||||
</form>
|
||||
|
||||
@ -73,7 +73,7 @@ const VerificationMonetizationModal = ({
|
||||
placeholder={lang('CheckPasswordPlaceholder')}
|
||||
error={renderingModal?.errorKey && lang.withRegular(renderingModal.errorKey)}
|
||||
description={lang('CheckPasswordDescription')}
|
||||
clearError={handleClearError}
|
||||
onClearError={handleClearError}
|
||||
isLoading={renderingModal?.isLoading}
|
||||
hint={passwordHint}
|
||||
isPasswordVisible={shouldShowPassword}
|
||||
|
||||
@ -6,7 +6,8 @@ import type { ObserveFn } from '../../hooks/useIntersectionObserver';
|
||||
import type { TextPart } from '../../types';
|
||||
|
||||
import {
|
||||
getFirstLinkInMessage, getMessageText,
|
||||
getFirstLinkInMessage,
|
||||
getMessageTextWithFallback,
|
||||
} from '../../global/helpers';
|
||||
import { selectWebPageFromMessage } from '../../global/selectors';
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
@ -15,6 +16,7 @@ import trimText from '../../util/trimText';
|
||||
import { renderMessageSummary } from './helpers/renderMessageText';
|
||||
import renderText from './helpers/renderText';
|
||||
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
|
||||
@ -45,7 +47,8 @@ type StateProps = {
|
||||
const WebLink = ({
|
||||
message, webPage, senderTitle, isProtected, observeIntersection, onMessageClick,
|
||||
}: OwnProps & StateProps) => {
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
const oldLang = useOldLang();
|
||||
|
||||
let linkData: ApiWebPageWithFormatted | undefined = webPage;
|
||||
|
||||
@ -57,7 +60,7 @@ const WebLink = ({
|
||||
linkData = {
|
||||
siteName: domain.replace(/^www./, ''),
|
||||
url: url.includes('://') ? url : url.includes('@') ? `mailto:${url}` : `http://${url}`,
|
||||
formattedDescription: getMessageText(message)?.text !== url
|
||||
formattedDescription: getMessageTextWithFallback(lang, message)?.text !== url
|
||||
? renderMessageSummary(lang, message, undefined, undefined, MAX_TEXT_LENGTH)
|
||||
: undefined,
|
||||
} as ApiWebPageWithFormatted;
|
||||
@ -125,7 +128,7 @@ const WebLink = ({
|
||||
onClick={handleMessageClick}
|
||||
isRtl={lang.isRtl}
|
||||
>
|
||||
{formatPastTimeShort(lang, message.date * 1000)}
|
||||
{formatPastTimeShort(oldLang, message.date * 1000)}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -11,7 +11,7 @@ import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||
import type { ChatTranslatedMessages } from '../../../types';
|
||||
import type { IconName } from '../../../types/icons';
|
||||
|
||||
import { CONTENT_NOT_SUPPORTED, TON_CURRENCY_CODE } from '../../../config';
|
||||
import { TON_CURRENCY_CODE } from '../../../config';
|
||||
import {
|
||||
getMessageIsSpoiler,
|
||||
getMessageRoundVideo,
|
||||
@ -213,8 +213,8 @@ const EmbeddedMessage: FC<OwnProps> = ({
|
||||
|
||||
function renderMediaContentType(media?: MediaContainer) {
|
||||
if (!media || media.content.text) return NBSP;
|
||||
const description = getMediaContentTypeDescription(oldLang, media.content, {});
|
||||
if (!description || description === CONTENT_NOT_SUPPORTED) return NBSP;
|
||||
const description = getMediaContentTypeDescription(lang, media.content, {});
|
||||
if (!description) return NBSP;
|
||||
return (
|
||||
<span>
|
||||
{renderText(description)}
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
import { getGlobal } from '../../../global';
|
||||
|
||||
import type { ApiMessage, ApiSponsoredMessage } from '../../../api/types';
|
||||
import type { OldLangFn } from '../../../hooks/useOldLang';
|
||||
import type { TextPart, ThreadId } from '../../../types';
|
||||
import { ApiMessageEntityTypes } from '../../../api/types';
|
||||
|
||||
import {
|
||||
getMessageStatefulContent,
|
||||
getMessageText,
|
||||
getMessageTextWithFallback,
|
||||
} from '../../../global/helpers';
|
||||
import {
|
||||
getMessageSummaryDescription,
|
||||
@ -16,6 +15,7 @@ import {
|
||||
TRUNCATED_SUMMARY_LENGTH,
|
||||
} from '../../../global/helpers/messageSummary';
|
||||
import { getMessageKey } from '../../../util/keys/messageKey';
|
||||
import { getTranslationFn, type LangFn } from '../../../util/localization';
|
||||
import trimText from '../../../util/trimText';
|
||||
import renderText from './renderText';
|
||||
import { renderTextWithEntities } from './renderTextWithEntities';
|
||||
@ -48,7 +48,7 @@ export function renderMessageText({
|
||||
const { text, entities } = message.content.text || {};
|
||||
|
||||
if (!text) {
|
||||
const contentNotSupportedText = getMessageText(message)?.text;
|
||||
const contentNotSupportedText = getMessageTextWithFallback(getTranslationFn(), message)?.text;
|
||||
return contentNotSupportedText ? [trimText(contentNotSupportedText, truncateLength)] : undefined;
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ export function renderMessageText({
|
||||
|
||||
// TODO Use Message Summary component instead
|
||||
export function renderMessageSummary(
|
||||
lang: OldLangFn,
|
||||
lang: LangFn,
|
||||
message: ApiMessage,
|
||||
noEmoji = false,
|
||||
highlight?: string,
|
||||
|
||||
@ -19,8 +19,8 @@ import renderText from '../helpers/renderText';
|
||||
|
||||
import useTimeout from '../../../hooks/schedulers/useTimeout';
|
||||
import useFlag from '../../../hooks/useFlag';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
|
||||
import ListItem from '../../ui/ListItem';
|
||||
import StickerView from '../StickerView';
|
||||
@ -58,7 +58,7 @@ const UserBirthday = ({
|
||||
const animationPlayedRef = useRef(false);
|
||||
const [isPlayingAnimation, playAnimation, stopAnimation] = useFlag();
|
||||
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
const {
|
||||
formattedDate,
|
||||
@ -139,7 +139,17 @@ const UserBirthday = ({
|
||||
}
|
||||
}, [isInSettings, isPlayingAnimation]);
|
||||
|
||||
const valueKey = `ProfileBirthday${isToday ? 'Today' : ''}Value${age ? 'Year' : ''}`;
|
||||
const value = useMemo(() => {
|
||||
if (age) {
|
||||
return lang(
|
||||
`ProfileBirthday${isToday ? 'Today' : ''}ValueYear`,
|
||||
{ date: formattedDate, age },
|
||||
{ pluralValue: age },
|
||||
);
|
||||
}
|
||||
|
||||
return lang(`ProfileBirthday${isToday ? 'Today' : ''}Value`, { date: formattedDate });
|
||||
}, [age, formattedDate, isToday, lang]);
|
||||
|
||||
const canGiftPremium = isToday && !user.isPremium && !user.isSelf && !isPremiumPurchaseBlocked;
|
||||
|
||||
@ -175,7 +185,7 @@ const UserBirthday = ({
|
||||
onSecondaryIconClick={handleOpenGiftModal}
|
||||
>
|
||||
<div className="title" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
{renderText(lang(valueKey, [formattedDate, age], undefined, age))}
|
||||
{renderText(value)}
|
||||
</div>
|
||||
<span className="subtitle">{lang(isToday ? 'ProfileBirthdayToday' : 'ProfileBirthday')}</span>
|
||||
</ListItem>
|
||||
|
||||
@ -6,7 +6,6 @@ import type {
|
||||
ApiChat, ApiMessage, ApiMessageOutgoingStatus,
|
||||
ApiUser,
|
||||
} from '../../../api/types';
|
||||
import type { OldLangFn } from '../../../hooks/useOldLang';
|
||||
|
||||
import {
|
||||
getMessageIsSpoiler,
|
||||
@ -18,11 +17,13 @@ import {
|
||||
import { selectChat, selectUser } from '../../../global/selectors';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { formatPastTimeShort } from '../../../util/dates/dateFormat';
|
||||
import { type LangFn } from '../../../util/localization';
|
||||
import { renderMessageSummary } from '../../common/helpers/renderMessageText';
|
||||
|
||||
import useMessageMediaHash from '../../../hooks/media/useMessageMediaHash';
|
||||
import useThumbnail from '../../../hooks/media/useThumbnail';
|
||||
import useAppLayout from '../../../hooks/useAppLayout';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useMedia from '../../../hooks/useMedia';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
@ -68,7 +69,8 @@ const ChatMessage: FC<OwnProps & StateProps> = ({
|
||||
focusMessage({ chatId, messageId: message.id, shouldReplaceHistory: true });
|
||||
});
|
||||
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
const oldLang = useOldLang();
|
||||
|
||||
const buttonRef = useSelectWithEnter(handleClick);
|
||||
|
||||
@ -98,7 +100,7 @@ const ChatMessage: FC<OwnProps & StateProps> = ({
|
||||
/>
|
||||
<div className="message-date">
|
||||
<Link className="date">
|
||||
{formatPastTimeShort(lang, message.date * 1000)}
|
||||
{formatPastTimeShort(oldLang, message.date * 1000)}
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@ -114,7 +116,7 @@ const ChatMessage: FC<OwnProps & StateProps> = ({
|
||||
};
|
||||
|
||||
function renderSummary(
|
||||
lang: OldLangFn, message: ApiMessage, blobUrl?: string, searchQuery?: string, isRoundVideo?: boolean,
|
||||
lang: LangFn, message: ApiMessage, blobUrl?: string, searchQuery?: string, isRoundVideo?: boolean,
|
||||
) {
|
||||
if (!blobUrl) {
|
||||
return renderMessageSummary(lang, message, undefined, searchQuery);
|
||||
|
||||
@ -12,7 +12,7 @@ import { throttle } from '../../../util/schedulers';
|
||||
import { renderMessageSummary } from '../../common/helpers/renderMessageText';
|
||||
|
||||
import useAppLayout from '../../../hooks/useAppLayout';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
|
||||
import NothingFound from '../../common/NothingFound';
|
||||
import InfiniteScroll from '../../ui/InfiniteScroll';
|
||||
@ -53,7 +53,7 @@ const ChatMessageResults: FC<OwnProps & StateProps> = ({
|
||||
}) => {
|
||||
const { searchMessagesGlobal, openThread } = getActions();
|
||||
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
const { isMobile } = useAppLayout();
|
||||
|
||||
const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {
|
||||
@ -133,14 +133,14 @@ const ChatMessageResults: FC<OwnProps & StateProps> = ({
|
||||
{nothingFound && (
|
||||
<NothingFound
|
||||
withSticker
|
||||
text={lang('ChatList.Search.NoResults')}
|
||||
description={lang('ChatList.Search.NoResultsDescription')}
|
||||
text={lang('ChatListSearchNoResults')}
|
||||
description={lang('ChatListSearchNoResultsDescription')}
|
||||
/>
|
||||
)}
|
||||
{Boolean(foundTopicIds?.length) && (
|
||||
<div className="pb-2">
|
||||
<h3 className="section-heading topic-search-heading" dir={lang.isRtl ? 'auto' : undefined}>
|
||||
{lang('Topics')}
|
||||
{lang('SearchResultTopics')}
|
||||
</h3>
|
||||
{foundTopicIds.map((id) => {
|
||||
return (
|
||||
|
||||
@ -31,7 +31,6 @@ import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
|
||||
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
|
||||
import Icon from '../../common/icons/Icon';
|
||||
import NothingFound from '../../common/NothingFound';
|
||||
@ -102,7 +101,6 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
const containerRef = useRef<HTMLDivElement>();
|
||||
const chatSelectionRef = useRef<HTMLDivElement>();
|
||||
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
const { isMobile } = useAppLayout();
|
||||
@ -318,7 +316,7 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
function renderFoundMessage(message: ApiMessage) {
|
||||
const chatsById = getGlobal().chats.byId;
|
||||
|
||||
const text = renderMessageSummary(oldLang, message);
|
||||
const text = renderMessageSummary(lang, message);
|
||||
const chat = chatsById[message.chatId];
|
||||
|
||||
if (!text || !chat) {
|
||||
@ -375,14 +373,14 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
{nothingFound && (
|
||||
<NothingFound
|
||||
withSticker
|
||||
text={oldLang('ChatList.Search.NoResults')}
|
||||
description={oldLang('ChatList.Search.NoResultsDescription')}
|
||||
text={lang('ChatListSearchNoResults')}
|
||||
description={lang('ChatListSearchNoResultsDescription')}
|
||||
/>
|
||||
)}
|
||||
{Boolean(localResults.length) && !isChannelList && (
|
||||
<div
|
||||
className="chat-selection no-scrollbar"
|
||||
dir={oldLang.isRtl ? 'rtl' : undefined}
|
||||
dir={lang.isRtl ? 'rtl' : undefined}
|
||||
ref={chatSelectionRef}
|
||||
>
|
||||
{localResults.map((id) => (
|
||||
@ -397,13 +395,13 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
)}
|
||||
{Boolean(localResults.length) && (
|
||||
<div className="search-section">
|
||||
<h3 className="section-heading" dir={oldLang.isRtl ? 'auto' : undefined}>
|
||||
<h3 className="section-heading" dir={lang.isRtl ? 'auto' : undefined}>
|
||||
{localResults.length > LESS_LIST_ITEMS_AMOUNT && (
|
||||
<Link className="Link" onClick={handleClickShowMoreLocal}>
|
||||
{oldLang(shouldShowMoreLocal ? 'ChatList.Search.ShowLess' : 'ChatList.Search.ShowMore')}
|
||||
{lang(shouldShowMoreLocal ? 'ChatListSearchShowLess' : 'ChatListSearchShowMore')}
|
||||
</Link>
|
||||
)}
|
||||
{oldLang(isChannelList ? 'SearchMyChannels' : 'DialogList.SearchSectionDialogs')}
|
||||
{lang(isChannelList ? 'SearchResultMyChannels' : 'DialogListSearchSectionDialogs')}
|
||||
</h3>
|
||||
{localResults.map((id, index) => {
|
||||
if (!shouldShowMoreLocal && index >= LESS_LIST_ITEMS_AMOUNT) {
|
||||
@ -422,13 +420,13 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
)}
|
||||
{Boolean(globalResults.length) && (
|
||||
<div className="search-section">
|
||||
<h3 className="section-heading" dir={oldLang.isRtl ? 'auto' : undefined}>
|
||||
<h3 className="section-heading" dir={lang.isRtl ? 'auto' : undefined}>
|
||||
{globalResults.length > LESS_LIST_ITEMS_AMOUNT && (
|
||||
<Link className="Link" onClick={handleClickShowMoreGlobal}>
|
||||
{oldLang(shouldShowMoreGlobal ? 'ChatList.Search.ShowLess' : 'ChatList.Search.ShowMore')}
|
||||
{lang(shouldShowMoreGlobal ? 'ChatListSearchShowLess' : 'ChatListSearchShowMore')}
|
||||
</Link>
|
||||
)}
|
||||
{oldLang('DialogList.SearchSectionGlobal')}
|
||||
{lang('DialogListSearchSectionGlobal')}
|
||||
</h3>
|
||||
{sponsoredPeer && (
|
||||
<LeftSearchResultSponsored sponsoredPeer={sponsoredPeer} observeIntersection={observe} />
|
||||
@ -450,8 +448,8 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
)}
|
||||
{Boolean(suggestedChannelIds?.length) && !searchQuery && (
|
||||
<div className="search-section">
|
||||
<h3 className="section-heading" dir={oldLang.isRtl ? 'auto' : undefined}>
|
||||
{oldLang('SearchRecommendedChannels')}
|
||||
<h3 className="section-heading" dir={lang.isRtl ? 'auto' : undefined}>
|
||||
{lang('SearchResultRecommendedChannels')}
|
||||
</h3>
|
||||
{suggestedChannelIds.map((id) => {
|
||||
return (
|
||||
@ -468,7 +466,7 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
{renderContextMenu()}
|
||||
{shouldRenderMessagesSection && (
|
||||
<div className="search-section">
|
||||
<h3 className="section-heading" dir={oldLang.isRtl ? 'auto' : undefined}>
|
||||
<h3 className="section-heading" dir={lang.isRtl ? 'auto' : undefined}>
|
||||
{!isChannelList && (
|
||||
<Link className="Link menuTrigger dropDownLink" onClick={handleClickContext}>
|
||||
{lang('SearchContextCaption', {
|
||||
@ -489,7 +487,7 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
</Transition>
|
||||
</Link>
|
||||
)}
|
||||
{oldLang('SearchMessages')}
|
||||
{lang('SearchMessages')}
|
||||
</h3>
|
||||
{actualFoundIds.map(renderFoundMessage)}
|
||||
</div>
|
||||
|
||||
@ -16,7 +16,6 @@ import { renderMessageSummary } from '../../common/helpers/renderMessageText';
|
||||
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
|
||||
import NothingFound from '../../common/NothingFound';
|
||||
import InfiniteScroll from '../../ui/InfiniteScroll';
|
||||
@ -53,7 +52,6 @@ const PublicPostsResults = ({
|
||||
const { searchMessagesGlobal } = getActions();
|
||||
|
||||
const lang = useLang();
|
||||
const oldLang = useOldLang();
|
||||
|
||||
const handleSearch = useLastCallback(() => {
|
||||
if (!searchQuery) return;
|
||||
@ -90,7 +88,7 @@ const PublicPostsResults = ({
|
||||
function renderFoundMessage(message: ApiMessage) {
|
||||
const chatsById = getGlobal().chats.byId;
|
||||
|
||||
const text = renderMessageSummary(oldLang, message);
|
||||
const text = renderMessageSummary(lang, message);
|
||||
const chat = chatsById[message.chatId];
|
||||
|
||||
if (!text || !chat) {
|
||||
@ -130,8 +128,8 @@ const PublicPostsResults = ({
|
||||
>
|
||||
{isNothingFound && (
|
||||
<NothingFound
|
||||
text={oldLang('ChatList.Search.NoResults')}
|
||||
description={oldLang('ChatList.Search.NoResultsDescription')}
|
||||
text={lang('ChatListSearchNoResults')}
|
||||
description={lang('ChatListSearchNoResultsDescription')}
|
||||
withSticker
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -9,7 +9,7 @@ import { formatDateTimeToString } from '../../../util/dates/dateFormat';
|
||||
import getSessionIcon from './helpers/getSessionIcon';
|
||||
|
||||
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
|
||||
import Icon from '../../common/icons/Icon';
|
||||
import Button from '../../ui/Button';
|
||||
@ -33,7 +33,7 @@ const SettingsActiveSession: FC<OwnProps & StateProps> = ({
|
||||
isOpen, session, onClose,
|
||||
}) => {
|
||||
const { changeSessionSettings, terminateAuthorization } = getActions();
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
const renderingSession = useCurrentOrPrev(session, true);
|
||||
|
||||
@ -66,13 +66,13 @@ const SettingsActiveSession: FC<OwnProps & StateProps> = ({
|
||||
<Button round color="translucent" size="smaller" ariaLabel={lang('Close')} onClick={onClose}>
|
||||
<Icon name="close" />
|
||||
</Button>
|
||||
<div className="modal-title">{lang('SessionPreview.Title')}</div>
|
||||
<div className="modal-title">{lang('SessionPreviewTitle')}</div>
|
||||
<Button
|
||||
color="danger"
|
||||
onClick={handleTerminateSessionClick}
|
||||
className={buildClassName('modal-action-button', styles.headerButton)}
|
||||
>
|
||||
{lang('SessionPreview.TerminateSession')}
|
||||
{lang('SessionPreviewTerminateSession')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
@ -91,12 +91,12 @@ const SettingsActiveSession: FC<OwnProps & StateProps> = ({
|
||||
)}
|
||||
/>
|
||||
<h3 className={styles.title} dir="auto">{renderingSession?.deviceModel}</h3>
|
||||
<div className={styles.date} aria-label={lang('PrivacySettings.LastSeen')}>
|
||||
<div className={styles.date} aria-label={lang('PrivacySettingsLastSeen')}>
|
||||
{formatDateTimeToString(renderingSession.dateActive * 1000, lang.code)}
|
||||
</div>
|
||||
|
||||
<dl className={styles.box}>
|
||||
<dt>{lang('SessionPreview.App')}</dt>
|
||||
<dt>{lang('SessionPreviewApp')}</dt>
|
||||
<dd>
|
||||
{renderingSession?.appName}
|
||||
{' '}
|
||||
@ -107,20 +107,23 @@ const SettingsActiveSession: FC<OwnProps & StateProps> = ({
|
||||
{' '}
|
||||
{renderingSession?.systemVersion}
|
||||
</dd>
|
||||
{renderingSession?.ip && (
|
||||
<>
|
||||
<dt>{lang('SessionPreviewIp')}</dt>
|
||||
<dd>{renderingSession.ip}</dd>
|
||||
</>
|
||||
)}
|
||||
|
||||
<dt>{lang('SessionPreview.Ip')}</dt>
|
||||
<dd>{renderingSession?.ip}</dd>
|
||||
|
||||
<dt>{lang('SessionPreview.Location')}</dt>
|
||||
<dt>{lang('SessionPreviewLocation')}</dt>
|
||||
<dd>{renderingSession && getLocation(renderingSession)}</dd>
|
||||
</dl>
|
||||
|
||||
<p className={styles.note}>{lang('SessionPreview.IpDesc')}</p>
|
||||
<p className={styles.note}>{lang('SessionPreviewIpDesc')}</p>
|
||||
|
||||
<h4 className={styles.actionHeader}>{lang('AuthSessions.View.AcceptTitle')}</h4>
|
||||
<h4 className={styles.actionHeader}>{lang('AuthSessionsViewAcceptTitle')}</h4>
|
||||
|
||||
<ListItem onClick={handleSecretChatsStateChange}>
|
||||
<span className={styles.actionName}>{lang('SessionPreview.Accept.Secret')}</span>
|
||||
<span className={styles.actionName}>{lang('SessionPreviewAcceptSecret')}</span>
|
||||
<Switcher
|
||||
id="accept_secrets"
|
||||
label="On"
|
||||
@ -128,7 +131,7 @@ const SettingsActiveSession: FC<OwnProps & StateProps> = ({
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem onClick={handleCallsStateChange}>
|
||||
<span className={styles.actionName}>{lang('SessionPreview.Accept.Calls')}</span>
|
||||
<span className={styles.actionName}>{lang('SessionPreviewAcceptCalls')}</span>
|
||||
<Switcher
|
||||
id="accept_calls"
|
||||
label="On"
|
||||
|
||||
@ -11,6 +11,7 @@ import getSessionIcon from './helpers/getSessionIcon';
|
||||
|
||||
import useFlag from '../../../hooks/useFlag';
|
||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
|
||||
import ConfirmDialog from '../../ui/ConfirmDialog';
|
||||
@ -44,7 +45,8 @@ const SettingsActiveSessions: FC<OwnProps & StateProps> = ({
|
||||
changeSessionTtl,
|
||||
} = getActions();
|
||||
|
||||
const lang = useOldLang();
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
const [isConfirmTerminateAllDialogOpen, openConfirmTerminateAllDialog, closeConfirmTerminateAllDialog] = useFlag();
|
||||
const [openedSessionHash, setOpenedSessionHash] = useState<string | undefined>();
|
||||
const [isModalOpen, openModal, closeModal] = useFlag();
|
||||
@ -80,21 +82,21 @@ const SettingsActiveSessions: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const AUTO_TERMINATE_OPTIONS = useMemo(() => {
|
||||
const options = [{
|
||||
label: lang('Weeks', 1, 'i'),
|
||||
label: lang('Weeks', { count: 1 }, { pluralValue: 1 }),
|
||||
value: '7',
|
||||
}, {
|
||||
label: lang('Months', 1, 'i'),
|
||||
label: lang('Months', { count: 1 }, { pluralValue: 1 }),
|
||||
value: '30',
|
||||
}, {
|
||||
label: lang('Months', 3, 'i'),
|
||||
label: lang('Months', { count: 3 }, { pluralValue: 3 }),
|
||||
value: '90',
|
||||
}, {
|
||||
label: lang('Months', 6, 'i'),
|
||||
label: lang('Months', { count: 6 }, { pluralValue: 6 }),
|
||||
value: '183',
|
||||
}];
|
||||
if (ttlDays && ttlDays >= 365) {
|
||||
options.push({
|
||||
label: lang('Years', 1, 'i'),
|
||||
label: lang('Years', { count: 1 }, { pluralValue: 1 }),
|
||||
value: '365',
|
||||
});
|
||||
}
|
||||
@ -144,7 +146,7 @@ const SettingsActiveSessions: FC<OwnProps & StateProps> = ({
|
||||
return (
|
||||
<div className="settings-item">
|
||||
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
{lang('AuthSessions.CurrentSession')}
|
||||
{lang('AuthSessionsCurrentSession')}
|
||||
</h4>
|
||||
|
||||
<ListItem narrow inactive icon={`device-${getSessionIcon(session)}`} iconClassName="icon-device">
|
||||
@ -224,7 +226,7 @@ const SettingsActiveSessions: FC<OwnProps & StateProps> = ({
|
||||
ripple
|
||||
narrow
|
||||
contextActions={[{
|
||||
title: 'Terminate',
|
||||
title: lang('SessionTerminate'),
|
||||
icon: 'stop',
|
||||
destructive: true,
|
||||
handler: () => {
|
||||
@ -236,7 +238,7 @@ const SettingsActiveSessions: FC<OwnProps & StateProps> = ({
|
||||
onClick={() => { handleOpenSessionModal(session.hash); }}
|
||||
>
|
||||
<div className="multiline-item full-size" dir="auto">
|
||||
<span className="date">{formatPastTimeShort(lang, session.dateActive * 1000)}</span>
|
||||
<span className="date">{formatPastTimeShort(oldLang, session.dateActive * 1000)}</span>
|
||||
<span className="title">{session.deviceModel}</span>
|
||||
<span className="subtitle black tight">
|
||||
{session.appName}
|
||||
|
||||
@ -2,7 +2,7 @@ import type { FC } from '../../../lib/teact/teact';
|
||||
import { memo, useCallback, useState } from '../../../lib/teact/teact';
|
||||
|
||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
|
||||
import PasswordForm from '../../common/PasswordForm';
|
||||
import PasswordMonkey from '../../common/PasswordMonkey';
|
||||
@ -15,46 +15,44 @@ type OwnProps = {
|
||||
placeholder?: string;
|
||||
hint?: string;
|
||||
submitLabel?: string;
|
||||
clearError?: NoneToVoidFunction;
|
||||
onSubmit: (password: string) => void;
|
||||
isActive?: boolean;
|
||||
onSubmit: (password: string) => void;
|
||||
onClearError?: NoneToVoidFunction;
|
||||
onReset: () => void;
|
||||
};
|
||||
|
||||
const EQUAL_PASSWORD_ERROR = 'Passwords Should Be Equal';
|
||||
|
||||
const SettingsPasswordForm: FC<OwnProps> = ({
|
||||
isActive,
|
||||
onReset,
|
||||
error,
|
||||
isLoading,
|
||||
shouldDisablePasswordManager,
|
||||
expectedPassword,
|
||||
placeholder = 'Current Password',
|
||||
placeholder,
|
||||
hint,
|
||||
submitLabel,
|
||||
clearError,
|
||||
onSubmit,
|
||||
onClearError,
|
||||
onReset,
|
||||
}) => {
|
||||
const [validationError, setValidationError] = useState<string>('');
|
||||
const [shouldShowPassword, setShouldShowPassword] = useState(false);
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
const handleSubmit = useCallback((newPassword) => {
|
||||
if (expectedPassword && newPassword !== expectedPassword) {
|
||||
setValidationError(EQUAL_PASSWORD_ERROR);
|
||||
setValidationError(lang('SettingsPasswordEqual'));
|
||||
} else {
|
||||
onSubmit(newPassword);
|
||||
}
|
||||
}, [onSubmit, expectedPassword]);
|
||||
}, [onSubmit, expectedPassword, lang]);
|
||||
|
||||
const handleClearError = useCallback(() => {
|
||||
if (clearError) {
|
||||
clearError();
|
||||
if (onClearError) {
|
||||
onClearError();
|
||||
}
|
||||
setValidationError('');
|
||||
}, [clearError]);
|
||||
|
||||
const lang = useOldLang();
|
||||
}, [onClearError]);
|
||||
|
||||
useHistoryBack({
|
||||
isActive,
|
||||
@ -71,10 +69,10 @@ const SettingsPasswordForm: FC<OwnProps> = ({
|
||||
<PasswordForm
|
||||
error={validationError || error}
|
||||
hint={hint}
|
||||
placeholder={placeholder}
|
||||
placeholder={placeholder || lang('CurrentPasswordPlaceholder')}
|
||||
shouldDisablePasswordManager={shouldDisablePasswordManager}
|
||||
submitLabel={submitLabel || lang('Next')}
|
||||
clearError={handleClearError}
|
||||
submitLabel={submitLabel}
|
||||
onClearError={handleClearError}
|
||||
isLoading={isLoading}
|
||||
isPasswordVisible={shouldShowPassword}
|
||||
shouldResetValue={isActive}
|
||||
|
||||
@ -182,7 +182,7 @@ function SettingsPerformance({
|
||||
</div>
|
||||
|
||||
<div className="settings-item-simple settings-item__with-shifted-dropdown">
|
||||
<h3 className="settings-item-header" dir="auto">Resource-Intensive Processes</h3>
|
||||
<h3 className="settings-item-header" dir="auto">{lang('SettingsPerformanceGranularTitle')}</h3>
|
||||
|
||||
{PERFORMANCE_OPTIONS.map(([sectionName, options], index) => {
|
||||
return (
|
||||
|
||||
@ -20,7 +20,7 @@ import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEn
|
||||
|
||||
import { useFolderManagerForChatsCount } from '../../../../hooks/useFolderManager';
|
||||
import useHistoryBack from '../../../../hooks/useHistoryBack';
|
||||
import useOldLang from '../../../../hooks/useOldLang';
|
||||
import useLang from '../../../../hooks/useLang';
|
||||
import usePreviousDeprecated from '../../../../hooks/usePreviousDeprecated';
|
||||
|
||||
import AnimatedIconWithPreview from '../../../common/AnimatedIconWithPreview';
|
||||
@ -117,7 +117,7 @@ const SettingsFoldersMain: FC<OwnProps & StateProps> = ({
|
||||
onCreateFolder();
|
||||
}, [foldersById, maxFolders, onCreateFolder, openLimitReachedModal]);
|
||||
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
useHistoryBack({
|
||||
isActive,
|
||||
@ -226,7 +226,7 @@ const SettingsFoldersMain: FC<OwnProps & StateProps> = ({
|
||||
|
||||
{canCreateNewFolder && (
|
||||
<Button
|
||||
// TODO: Refactor button component to handle icon placemenet with props
|
||||
// TODO: Move icon into button prop
|
||||
className="settings-button with-icon"
|
||||
color="primary"
|
||||
pill
|
||||
@ -349,7 +349,7 @@ const SettingsFoldersMain: FC<OwnProps & StateProps> = ({
|
||||
);
|
||||
}) : userFolders && !userFolders.length ? (
|
||||
<p className="settings-item-description my-4" dir="auto">
|
||||
You have no folders yet.
|
||||
{lang('SettingsFoldersEmpty')}
|
||||
</p>
|
||||
) : <Loading />}
|
||||
</div>
|
||||
|
||||
@ -160,7 +160,7 @@ const SettingsPasscode: FC<OwnProps & StateProps> = ({
|
||||
<SettingsPasscodeForm
|
||||
shouldDisablePasswordManager
|
||||
error={error}
|
||||
clearError={clearPasscodeError}
|
||||
onClearError={clearPasscodeError}
|
||||
placeholder={lang('PasscodeController.Current.Placeholder')}
|
||||
onSubmit={handleChangePasswordCurrent}
|
||||
isActive={isActive || [
|
||||
@ -206,7 +206,7 @@ const SettingsPasscode: FC<OwnProps & StateProps> = ({
|
||||
<SettingsPasscodeForm
|
||||
shouldDisablePasswordManager
|
||||
error={error ? lang(error) : undefined}
|
||||
clearError={clearPasscodeError}
|
||||
onClearError={clearPasscodeError}
|
||||
placeholder={lang('PasscodeController.Current.Placeholder')}
|
||||
onSubmit={handleTurnOff}
|
||||
isActive={isActive}
|
||||
|
||||
@ -5,7 +5,7 @@ import { STICKER_SIZE_PASSCODE } from '../../../../config';
|
||||
import { LOCAL_TGS_URLS } from '../../../common/helpers/animatedAssets';
|
||||
|
||||
import useHistoryBack from '../../../../hooks/useHistoryBack';
|
||||
import useOldLang from '../../../../hooks/useOldLang';
|
||||
import useLang from '../../../../hooks/useLang';
|
||||
|
||||
import AnimatedIconWithPreview from '../../../common/AnimatedIconWithPreview';
|
||||
import Button from '../../../ui/Button';
|
||||
@ -13,15 +13,15 @@ import Button from '../../../ui/Button';
|
||||
import lockPreviewUrl from '../../../../assets/lock.png';
|
||||
|
||||
type OwnProps = {
|
||||
onStart: NoneToVoidFunction;
|
||||
isActive?: boolean;
|
||||
onStart: NoneToVoidFunction;
|
||||
onReset: () => void;
|
||||
};
|
||||
|
||||
const SettingsPasscodeStart: FC<OwnProps> = ({
|
||||
isActive, onReset, onStart,
|
||||
}) => {
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
useHistoryBack({ isActive, onBack: onReset });
|
||||
|
||||
@ -36,11 +36,10 @@ const SettingsPasscodeStart: FC<OwnProps> = ({
|
||||
/>
|
||||
|
||||
<p className="settings-item-description" dir="auto">
|
||||
When you set up an additional passcode, a lock icon will appear on the chats page.
|
||||
Tap it to lock and unlock your Telegram Web A.
|
||||
{lang('SettingsPasscodeStart1', undefined, { withNodes: true, renderTextFilters: ['br'] })}
|
||||
</p>
|
||||
<p className="settings-item-description mb-3" dir="auto">
|
||||
Note: if you forget your local passcode, you'll need to log out of Telegram Web A and log in again.
|
||||
{lang('SettingsPasscodeStart2', undefined, { withNodes: true, renderTextFilters: ['br'] })}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@ -284,7 +284,7 @@ const SettingsTwoFa: FC<OwnProps & StateProps> = ({
|
||||
<SettingsTwoFaPassword
|
||||
isLoading={isLoading}
|
||||
error={errorKey && lang.withRegular(errorKey)}
|
||||
clearError={clearTwoFaError}
|
||||
onClearError={clearTwoFaError}
|
||||
hint={hint}
|
||||
onSubmit={handleChangePasswordCurrent}
|
||||
isActive={isActive || [
|
||||
@ -344,7 +344,7 @@ const SettingsTwoFa: FC<OwnProps & StateProps> = ({
|
||||
<SettingsTwoFaPassword
|
||||
isLoading={isLoading}
|
||||
error={errorKey && lang.withRegular(errorKey)}
|
||||
clearError={clearTwoFaError}
|
||||
onClearError={clearTwoFaError}
|
||||
hint={hint}
|
||||
onSubmit={handleTurnOff}
|
||||
isActive={isActive}
|
||||
@ -357,7 +357,7 @@ const SettingsTwoFa: FC<OwnProps & StateProps> = ({
|
||||
<SettingsTwoFaPassword
|
||||
isLoading={isLoading}
|
||||
error={errorKey && lang.withRegular(errorKey)}
|
||||
clearError={clearTwoFaError}
|
||||
onClearError={clearTwoFaError}
|
||||
hint={hint}
|
||||
onSubmit={handleRecoveryEmailCurrentPassword}
|
||||
isActive={isActive || [
|
||||
|
||||
@ -132,7 +132,7 @@ const LockScreen: FC<OwnProps & StateProps> = ({
|
||||
error={validationError}
|
||||
placeholder={lang('Passcode.EnterPasscodePlaceholder')}
|
||||
submitLabel={lang('Next')}
|
||||
clearError={handleClearError}
|
||||
onClearError={handleClearError}
|
||||
isPasswordVisible={shouldShowPasscode}
|
||||
noRipple
|
||||
onChangePasswordVisibility={setShouldShowPasscode}
|
||||
|
||||
@ -12,8 +12,8 @@ import { selectChat, selectChatFullInfo } from '../../global/selectors';
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
import stopEvent from '../../util/stopEvent';
|
||||
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
|
||||
import Checkbox from '../ui/Checkbox';
|
||||
|
||||
@ -61,7 +61,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const { isForum } = chat || {};
|
||||
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
const isPublic = useMemo(() => chat && isChatPublic(chat), [chat]);
|
||||
const shouldDisablePermissionForPublicGroup = hasLinkedChat || isPublic;
|
||||
@ -81,7 +81,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
|
||||
const handleDisabledClick = useLastCallback(() => {
|
||||
showNotification({ message: lang('lng_rights_permission_unavailable') });
|
||||
showNotification({ message: lang('ChatPermissionNotAvailable') });
|
||||
});
|
||||
|
||||
return (
|
||||
@ -119,7 +119,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="sendPhotos"
|
||||
checked={!permissions.sendPhotos}
|
||||
label={lang('UserRestrictionsSendPhotos')}
|
||||
label={lang('SendMediaPermissionPhotos')}
|
||||
blocking
|
||||
permissionGroup={permissionGroup}
|
||||
onChange={handlePermissionChange}
|
||||
@ -131,7 +131,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="sendVideos"
|
||||
checked={!permissions.sendVideos}
|
||||
label={lang('UserRestrictionsSendVideos')}
|
||||
label={lang('SendMediaPermissionVideos')}
|
||||
blocking
|
||||
permissionGroup={permissionGroup}
|
||||
onChange={handlePermissionChange}
|
||||
@ -143,7 +143,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="sendStickers"
|
||||
checked={!permissions.sendStickers && !permissions.sendGifs}
|
||||
label={lang('UserRestrictionsSendStickers')}
|
||||
label={lang('SendMediaPermissionStickersGifs')}
|
||||
blocking
|
||||
permissionGroup={permissionGroup}
|
||||
onChange={handlePermissionChange}
|
||||
@ -155,7 +155,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="sendAudios"
|
||||
checked={!permissions.sendAudios}
|
||||
label={lang('UserRestrictionsSendMusic')}
|
||||
label={lang('SendMediaPermissionAudios')}
|
||||
blocking
|
||||
permissionGroup={permissionGroup}
|
||||
onChange={handlePermissionChange}
|
||||
@ -167,7 +167,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="sendDocs"
|
||||
checked={!permissions.sendDocs}
|
||||
label={lang('UserRestrictionsSendFiles')}
|
||||
label={lang('SendMediaPermissionFiles')}
|
||||
blocking
|
||||
permissionGroup={permissionGroup}
|
||||
onChange={handlePermissionChange}
|
||||
@ -179,7 +179,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="sendVoices"
|
||||
checked={!permissions.sendVoices}
|
||||
label={lang('UserRestrictionsSendVoices')}
|
||||
label={lang('SendMediaPermissionVoices')}
|
||||
blocking
|
||||
permissionGroup={permissionGroup}
|
||||
onChange={handlePermissionChange}
|
||||
@ -191,7 +191,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="sendRoundvideos"
|
||||
checked={!permissions.sendRoundvideos}
|
||||
label={lang('UserRestrictionsSendRound')}
|
||||
label={lang('SendMediaPermissionRoundVideos')}
|
||||
blocking
|
||||
permissionGroup={permissionGroup}
|
||||
onChange={handlePermissionChange}
|
||||
@ -203,7 +203,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="embedLinks"
|
||||
checked={!permissions.embedLinks}
|
||||
label={lang('UserRestrictionsEmbedLinks')}
|
||||
label={lang('SendMediaPermissionWebPages')}
|
||||
blocking
|
||||
permissionGroup={permissionGroup}
|
||||
onChange={handlePermissionChange}
|
||||
@ -215,7 +215,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="sendPolls"
|
||||
checked={!permissions.sendPolls}
|
||||
label={lang('UserRestrictionsSendPolls')}
|
||||
label={lang('SendMediaPermissionPolls')}
|
||||
blocking
|
||||
permissionGroup={permissionGroup}
|
||||
onChange={handlePermissionChange}
|
||||
@ -271,7 +271,7 @@ const PermissionCheckboxList: FC<OwnProps & StateProps> = ({
|
||||
<Checkbox
|
||||
name="manageTopics"
|
||||
checked={!permissions.manageTopics}
|
||||
label={lang('CreateTopicsPermission')}
|
||||
label={lang('UserRestrictionsCreateTopics')}
|
||||
blocking
|
||||
permissionGroup={permissionGroup}
|
||||
onChange={handlePermissionChange}
|
||||
|
||||
@ -321,9 +321,10 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
|
||||
function getHeaderDescription() {
|
||||
if (gift) {
|
||||
const perUserTotal = gift.type !== 'starGiftUnique' ? gift.perUserTotal : 0;
|
||||
return lang('DescriptionGiftPremiumRequired', { count: perUserTotal });
|
||||
if (gift && gift.type !== 'starGiftUnique' && gift.perUserTotal) {
|
||||
return lang('DescriptionGiftPremiumRequired2', { count: gift.perUserTotal }, {
|
||||
pluralValue: gift.perUserTotal,
|
||||
});
|
||||
}
|
||||
|
||||
if (isGift) {
|
||||
|
||||
@ -6,6 +6,7 @@ import buildClassName from '../../../util/buildClassName';
|
||||
|
||||
import useEffectOnce from '../../../hooks/useEffectOnce';
|
||||
import useFlag from '../../../hooks/useFlag';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useResizeObserver from '../../../hooks/useResizeObserver';
|
||||
|
||||
@ -23,6 +24,8 @@ const DropTarget: FC<OwnProps> = ({ isQuick, isGeneric, onFileSelect }) => {
|
||||
const ref = useRef<HTMLDivElement>();
|
||||
const svgRef = useRef<SVGSVGElement>();
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
const [isHovered, markHovered, unmarkHovered] = useFlag();
|
||||
|
||||
const handleDragLeave = useLastCallback((e: React.DragEvent<HTMLDivElement>) => {
|
||||
@ -65,13 +68,17 @@ const DropTarget: FC<OwnProps> = ({ isQuick, isGeneric, onFileSelect }) => {
|
||||
onDragLeave={handleDragLeave}
|
||||
data-dropzone
|
||||
>
|
||||
<svg className="target-outline-container">
|
||||
<svg className="target-outline-container" ref={svgRef}>
|
||||
<rect className="target-outline" x="0" y="0" width="100%" height="100%" rx="8" />
|
||||
</svg>
|
||||
<div className="target-content">
|
||||
<Icon name={isQuick ? 'photo' : 'document'} />
|
||||
<div className="title">Drop files here to send them</div>
|
||||
{!isGeneric && <div className="description">{isQuick ? 'in a quick way' : 'without compression'}</div>}
|
||||
<div className="title">{lang('FileDropZoneTitle')}</div>
|
||||
{!isGeneric && (
|
||||
<div className="description">
|
||||
{isQuick ? lang('FileDropZoneQuick') : lang('FileDropZoneNoCompression')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -16,8 +16,8 @@ import stopEvent from '../../../util/stopEvent';
|
||||
import { INPUT_CUSTOM_EMOJI_SELECTOR } from './helpers/customEmoji';
|
||||
|
||||
import useFlag from '../../../hooks/useFlag';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
|
||||
import useVirtualBackdrop from '../../../hooks/useVirtualBackdrop';
|
||||
|
||||
@ -71,6 +71,8 @@ const TextFormatter: FC<OwnProps> = ({
|
||||
const [inputClassName, setInputClassName] = useState<string | undefined>();
|
||||
const [selectedTextFormats, setSelectedTextFormats] = useState<ISelectedTextFormats>({});
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
useEffect(() => (isOpen ? captureEscKeyListener(onClose) : undefined), [isOpen, onClose]);
|
||||
useVirtualBackdrop(
|
||||
isOpen,
|
||||
@ -338,7 +340,7 @@ const TextFormatter: FC<OwnProps> = ({
|
||||
document.execCommand(
|
||||
'insertHTML',
|
||||
false,
|
||||
`<a href=${formattedLinkUrl} class="text-entity-link" dir="auto">${text}</a>`,
|
||||
`<a href="${formattedLinkUrl}" class="text-entity-link" dir="auto">${text}</a>`,
|
||||
);
|
||||
onClose();
|
||||
});
|
||||
@ -377,10 +379,9 @@ const TextFormatter: FC<OwnProps> = ({
|
||||
return () => document.removeEventListener('keydown', handleKeyDown);
|
||||
}, [isOpen, handleKeyDown]);
|
||||
|
||||
const lang = useOldLang();
|
||||
|
||||
function handleContainerKeyDown(e: React.KeyboardEvent<HTMLDivElement>) {
|
||||
if (e.key === 'Enter' && isLinkControlOpen) {
|
||||
if (!linkUrl.trim()) return;
|
||||
handleLinkUrlConfirm();
|
||||
e.preventDefault();
|
||||
}
|
||||
@ -417,7 +418,7 @@ const TextFormatter: FC<OwnProps> = ({
|
||||
<div className="TextFormatter-buttons">
|
||||
<Button
|
||||
color="translucent"
|
||||
ariaLabel="Spoiler text"
|
||||
ariaLabel={lang('FormattingSpoilerAria')}
|
||||
className={getFormatButtonClassName('spoiler')}
|
||||
onClick={handleSpoilerText}
|
||||
>
|
||||
@ -426,7 +427,7 @@ const TextFormatter: FC<OwnProps> = ({
|
||||
<div className="TextFormatter-divider" />
|
||||
<Button
|
||||
color="translucent"
|
||||
ariaLabel="Bold text"
|
||||
ariaLabel={lang('FormattingBoldAria')}
|
||||
className={getFormatButtonClassName('bold')}
|
||||
onClick={handleBoldText}
|
||||
>
|
||||
@ -434,7 +435,7 @@ const TextFormatter: FC<OwnProps> = ({
|
||||
</Button>
|
||||
<Button
|
||||
color="translucent"
|
||||
ariaLabel="Italic text"
|
||||
ariaLabel={lang('FormattingItalicAria')}
|
||||
className={getFormatButtonClassName('italic')}
|
||||
onClick={handleItalicText}
|
||||
>
|
||||
@ -442,7 +443,7 @@ const TextFormatter: FC<OwnProps> = ({
|
||||
</Button>
|
||||
<Button
|
||||
color="translucent"
|
||||
ariaLabel="Underlined text"
|
||||
ariaLabel={lang('FormattingUnderlineAria')}
|
||||
className={getFormatButtonClassName('underline')}
|
||||
onClick={handleUnderlineText}
|
||||
>
|
||||
@ -450,7 +451,7 @@ const TextFormatter: FC<OwnProps> = ({
|
||||
</Button>
|
||||
<Button
|
||||
color="translucent"
|
||||
ariaLabel="Strikethrough text"
|
||||
ariaLabel={lang('FormattingStrikethroughAria')}
|
||||
className={getFormatButtonClassName('strikethrough')}
|
||||
onClick={handleStrikethroughText}
|
||||
>
|
||||
@ -458,14 +459,14 @@ const TextFormatter: FC<OwnProps> = ({
|
||||
</Button>
|
||||
<Button
|
||||
color="translucent"
|
||||
ariaLabel="Monospace text"
|
||||
ariaLabel={lang('FormattingMonospaceAria')}
|
||||
className={getFormatButtonClassName('monospace')}
|
||||
onClick={handleMonospaceText}
|
||||
>
|
||||
<Icon name="monospace" />
|
||||
</Button>
|
||||
<div className="TextFormatter-divider" />
|
||||
<Button color="translucent" ariaLabel={lang('TextFormat.AddLinkTitle')} onClick={openLinkControl}>
|
||||
<Button color="translucent" ariaLabel={lang('FormattingAddLinkAria')} onClick={openLinkControl}>
|
||||
<Icon name="link" />
|
||||
</Button>
|
||||
</div>
|
||||
@ -485,7 +486,7 @@ const TextFormatter: FC<OwnProps> = ({
|
||||
className="TextFormatter-link-url-input"
|
||||
type="text"
|
||||
value={linkUrl}
|
||||
placeholder="Enter URL..."
|
||||
placeholder={lang('FormattingEnterUrl')}
|
||||
autoComplete="off"
|
||||
inputMode="url"
|
||||
dir="auto"
|
||||
|
||||
@ -340,6 +340,8 @@ const ToDoListModal = ({
|
||||
});
|
||||
}
|
||||
|
||||
const moreTasksCount = maxItemsCount - items.length - (isAddTaskMode && editingTodo ? editingTodo.items.length : 0);
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClear} header={renderHeader()} className="ToDoListModal">
|
||||
{!isAddTaskMode && (
|
||||
@ -369,8 +371,10 @@ const ToDoListModal = ({
|
||||
</div>
|
||||
|
||||
<div className="items-count-hint">
|
||||
{lang('HintTodoListTasksCount', {
|
||||
count: maxItemsCount - items.length - (isAddTaskMode && editingTodo ? editingTodo.items.length : 0),
|
||||
{lang('HintTodoListTasksCount2', {
|
||||
count: moreTasksCount,
|
||||
}, {
|
||||
pluralValue: moreTasksCount,
|
||||
})}
|
||||
</div>
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
} from '../../../config';
|
||||
import {
|
||||
getMainUsername,
|
||||
getMessageInvoice, getMessageText, isChatChannel,
|
||||
getMessageInvoice, getMessageTextWithFallback, isChatChannel,
|
||||
} from '../../../global/helpers';
|
||||
import { getMessageContent } from '../../../global/helpers';
|
||||
import { getPeerTitle } from '../../../global/helpers/peers';
|
||||
@ -116,7 +116,7 @@ const ActionMessageText = ({
|
||||
switch (action.type) {
|
||||
case 'pinMessage': {
|
||||
if (replyMessage) {
|
||||
const formattedText = getMessageText(replyMessage);
|
||||
const formattedText = getMessageTextWithFallback(lang, replyMessage);
|
||||
if (formattedText) {
|
||||
const textLink = renderMessageLink(
|
||||
replyMessage,
|
||||
|
||||
@ -1763,7 +1763,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
color="translucent-white"
|
||||
round
|
||||
size="tiny"
|
||||
ariaLabel="Focus message"
|
||||
ariaLabel={lang('FocusMessage')}
|
||||
onClick={isPinnedList ? handleFocus : handleFocusForwarded}
|
||||
>
|
||||
<Icon name="arrow-right" />
|
||||
|
||||
@ -113,7 +113,6 @@ const SuggestedPostApproval = ({
|
||||
{translateWithYou(lang, 'SuggestedPostReceiveAmount', !isAdmin, {
|
||||
peer: renderChatLink(),
|
||||
duration,
|
||||
currency: currency === TON_CURRENCY_CODE ? lang('CurrencyTon') : lang('CurrencyStars'),
|
||||
}, { withMarkdown: true })}
|
||||
</div>
|
||||
|
||||
@ -121,7 +120,6 @@ const SuggestedPostApproval = ({
|
||||
{translateWithYou(lang, 'SuggestedPostRefund', !isAdmin, {
|
||||
peer: renderChatLink(),
|
||||
duration,
|
||||
currency: currency === TON_CURRENCY_CODE ? lang('CurrencyTon') : lang('CurrencyStars'),
|
||||
}, { withMarkdown: true })}
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -21,6 +21,7 @@ import {
|
||||
copyTextToClipboard,
|
||||
} from '../../../../util/clipboard';
|
||||
import getMessageIdsForSelectedText from '../../../../util/getMessageIdsForSelectedText';
|
||||
import { getTranslationFn } from '../../../../util/localization';
|
||||
import * as mediaLoader from '../../../../util/mediaLoader';
|
||||
import { renderMessageText } from '../../../common/helpers/renderMessageText';
|
||||
|
||||
@ -99,7 +100,7 @@ export function getMessageCopyOptions(
|
||||
if (clipboardText) {
|
||||
copyHtmlToClipboard(
|
||||
clipboardText.join(''),
|
||||
getMessageTextWithSpoilers(message, statefulContent)!,
|
||||
getMessageTextWithSpoilers(getTranslationFn(), message, statefulContent)!,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,9 +86,10 @@ function GiftItemStar({
|
||||
|
||||
if (isUserLimitReached) {
|
||||
showNotification({
|
||||
message: lang('NotificationGiftsLimit', {
|
||||
message: lang('NotificationGiftsLimit2', {
|
||||
count: perUserTotal,
|
||||
}, {
|
||||
pluralValue: perUserTotal!,
|
||||
withMarkdown: true,
|
||||
withNodes: true,
|
||||
}),
|
||||
|
||||
@ -142,7 +142,7 @@ const GiftWithdrawModal = ({ modal, hasPassword, passwordHint }: OwnProps & Stat
|
||||
placeholder={lang('CheckPasswordPlaceholder')}
|
||||
error={renderingModal?.errorKey && lang.withRegular(renderingModal?.errorKey)}
|
||||
description={lang('CheckPasswordDescription')}
|
||||
clearError={clearGiftWithdrawError}
|
||||
onClearError={clearGiftWithdrawError}
|
||||
isLoading={renderingModal?.isLoading}
|
||||
hint={passwordHint}
|
||||
isPasswordVisible={shouldShowPassword}
|
||||
|
||||
@ -1056,7 +1056,7 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
|
||||
)}
|
||||
style={frameStyle}
|
||||
src={url}
|
||||
title={`${bot?.firstName} Web App`}
|
||||
title={lang('AriaMiniApp', { bot: bot?.firstName })}
|
||||
sandbox={SANDBOX_ATTRIBUTES}
|
||||
allow="camera; microphone; geolocation; clipboard-write;"
|
||||
allowFullScreen
|
||||
|
||||
@ -56,7 +56,7 @@ const PasswordConfirm: FC<OwnProps & StateProps> = ({
|
||||
hint={passwordHint}
|
||||
description={oldLang('PaymentConfirmationMessage', cardName)}
|
||||
placeholder={oldLang('Password')}
|
||||
clearError={clearPaymentError}
|
||||
onClearError={clearPaymentError}
|
||||
shouldShowSubmit={false}
|
||||
shouldResetValue={isActive}
|
||||
isPasswordVisible={shouldShowPassword}
|
||||
|
||||
@ -256,7 +256,7 @@ const PaymentModal: FC<OwnProps & StateProps> = ({
|
||||
isText
|
||||
onClick={handleClearPaymentError}
|
||||
>
|
||||
{oldLang('OK')}
|
||||
{lang('OK')}
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
@ -540,10 +540,7 @@ const PaymentModal: FC<OwnProps & StateProps> = ({
|
||||
onCloseAnimationEnd={handleModalClose}
|
||||
>
|
||||
<p>
|
||||
Sorry, Telegram Web A doesn't support payments with this provider yet.
|
||||
{' '}
|
||||
<br />
|
||||
Please use one of our mobile apps to do this.
|
||||
{lang('PaymentsProvidesNotSupported', undefined, { withNodes: true, renderTextFilters: ['br'] })}
|
||||
</p>
|
||||
<div className="dialog-buttons mt-2">
|
||||
<Button
|
||||
@ -573,7 +570,7 @@ const PaymentModal: FC<OwnProps & StateProps> = ({
|
||||
round
|
||||
size="smaller"
|
||||
onClick={step === PaymentStep.Checkout ? closeModal : handleBackClick}
|
||||
ariaLabel="Close"
|
||||
ariaLabel={lang('Close')}
|
||||
>
|
||||
<Icon name={step === PaymentStep.Checkout ? 'close' : 'arrow-left'} />
|
||||
</Button>
|
||||
|
||||
@ -601,7 +601,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
||||
className="content empty-list"
|
||||
>
|
||||
{!noSpinner && !forceRenderHiddenMembers && <Spinner />}
|
||||
{forceRenderHiddenMembers && <NothingFound text="You have no access to group members list." />}
|
||||
{forceRenderHiddenMembers && <NothingFound text={lang('ChatMemberListNoAccess')} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -617,7 +617,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
||||
|
||||
switch (resultType) {
|
||||
case 'members':
|
||||
text = areMembersHidden ? 'You have no access to group members list.' : 'No members found';
|
||||
text = areMembersHidden ? lang('ChatMemberListNoAccess') : lang('NoMembersFound');
|
||||
break;
|
||||
case 'commonChats':
|
||||
text = oldLang('NoGroupsInCommon');
|
||||
|
||||
@ -3,7 +3,6 @@ import { memo, useCallback } from '../../../lib/teact/teact';
|
||||
import { getActions } from '../../../global';
|
||||
|
||||
import type { ApiMessage, StatisticsMessageInteractionCounter } from '../../../api/types';
|
||||
import type { OldLangFn } from '../../../hooks/useOldLang';
|
||||
|
||||
import {
|
||||
getMessageRoundVideo,
|
||||
@ -11,12 +10,13 @@ import {
|
||||
} from '../../../global/helpers';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { formatDateTimeToString } from '../../../util/dates/dateFormat';
|
||||
import { type LangFn } from '../../../util/localization';
|
||||
import { renderMessageSummary } from '../../common/helpers/renderMessageText';
|
||||
|
||||
import useMessageMediaHash from '../../../hooks/media/useMessageMediaHash';
|
||||
import useThumbnail from '../../../hooks/media/useThumbnail';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useMedia from '../../../hooks/useMedia';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
|
||||
import Icon from '../../common/icons/Icon';
|
||||
import StatisticsRecentPostMeta from './StatisticsRecentPostMeta';
|
||||
@ -29,7 +29,7 @@ export type OwnProps = {
|
||||
};
|
||||
|
||||
const StatisticsRecentMessage: FC<OwnProps> = ({ postStatistic, message }) => {
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
const { toggleMessageStatistics } = getActions();
|
||||
|
||||
const thumbDataUri = useThumbnail(message);
|
||||
@ -54,7 +54,11 @@ const StatisticsRecentMessage: FC<OwnProps> = ({ postStatistic, message }) => {
|
||||
{renderSummary(lang, message, mediaBlobUrl || thumbDataUri, isRoundVideo)}
|
||||
</div>
|
||||
<div className={styles.meta}>
|
||||
{lang('ChannelStats.ViewsCount', postStatistic.viewsCount, 'i')}
|
||||
{lang(
|
||||
'ChannelStatsViewsCount',
|
||||
{ count: postStatistic.viewsCount },
|
||||
{ pluralValue: postStatistic.viewsCount },
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -68,7 +72,7 @@ const StatisticsRecentMessage: FC<OwnProps> = ({ postStatistic, message }) => {
|
||||
);
|
||||
};
|
||||
|
||||
function renderSummary(lang: OldLangFn, message: ApiMessage, blobUrl?: string, isRoundVideo?: boolean) {
|
||||
function renderSummary(lang: LangFn, message: ApiMessage, blobUrl?: string, isRoundVideo?: boolean) {
|
||||
if (!blobUrl) {
|
||||
return renderMessageSummary(lang, message);
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@ import {
|
||||
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
|
||||
import useLang from '../../hooks/useLang';
|
||||
|
||||
import Icon from '../common/icons/Icon';
|
||||
import CropModal from './CropModal';
|
||||
|
||||
@ -20,7 +22,7 @@ interface OwnProps {
|
||||
}
|
||||
|
||||
const AvatarEditable: FC<OwnProps> = ({
|
||||
title = 'Change your profile picture',
|
||||
title,
|
||||
disabled,
|
||||
isForForum,
|
||||
currentAvatarBlobUrl,
|
||||
@ -29,6 +31,8 @@ const AvatarEditable: FC<OwnProps> = ({
|
||||
const [selectedFile, setSelectedFile] = useState<File | undefined>();
|
||||
const [croppedBlobUrl, setCroppedBlobUrl] = useState<string | undefined>(currentAvatarBlobUrl);
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
useEffect(() => {
|
||||
setCroppedBlobUrl(currentAvatarBlobUrl);
|
||||
}, [currentAvatarBlobUrl]);
|
||||
@ -70,7 +74,7 @@ const AvatarEditable: FC<OwnProps> = ({
|
||||
className={labelClassName}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
title={title}
|
||||
title={title || lang('ChangeYourProfilePicture')}
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
@ -78,7 +82,7 @@ const AvatarEditable: FC<OwnProps> = ({
|
||||
accept="image/png, image/jpeg"
|
||||
/>
|
||||
<Icon name="camera-add" />
|
||||
{croppedBlobUrl && <img src={croppedBlobUrl} draggable={false} alt="Avatar" />}
|
||||
{croppedBlobUrl && <img src={croppedBlobUrl} draggable={false} alt="" />}
|
||||
</label>
|
||||
<CropModal file={selectedFile} onClose={handleModalClose} onChange={handleAvatarCrop} />
|
||||
</div>
|
||||
|
||||
@ -7,7 +7,7 @@ import type { TextPart } from '../../types';
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
|
||||
import useKeyboardListNavigation from '../../hooks/useKeyboardListNavigation';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
import useLang from '../../hooks/useLang';
|
||||
|
||||
import Button from './Button';
|
||||
import Modal from './Modal';
|
||||
@ -38,7 +38,7 @@ const ConfirmDialog: FC<OwnProps> = ({
|
||||
header,
|
||||
text,
|
||||
textParts,
|
||||
confirmLabel = 'Confirm',
|
||||
confirmLabel,
|
||||
confirmIsDestructive,
|
||||
isConfirmDisabled,
|
||||
isOnlyConfirm,
|
||||
@ -49,7 +49,7 @@ const ConfirmDialog: FC<OwnProps> = ({
|
||||
onClose,
|
||||
onCloseAnimationEnd,
|
||||
}) => {
|
||||
const lang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
const containerRef = useRef<HTMLDivElement>();
|
||||
|
||||
@ -84,7 +84,7 @@ const ConfirmDialog: FC<OwnProps> = ({
|
||||
color={confirmIsDestructive ? 'danger' : 'primary'}
|
||||
disabled={isConfirmDisabled}
|
||||
>
|
||||
{confirmLabel}
|
||||
{confirmLabel || lang('GeneralConfirm')}
|
||||
</Button>
|
||||
{!isOnlyConfirm && <Button className="confirm-dialog-button" isText onClick={onClose}>{lang('Cancel')}</Button>}
|
||||
</div>
|
||||
|
||||
@ -284,8 +284,6 @@ export const CONTENT_TYPES_WITH_PREVIEW = new Set([
|
||||
...SUPPORTED_VIDEO_CONTENT_TYPES,
|
||||
]);
|
||||
|
||||
export const CONTENT_NOT_SUPPORTED = 'The message is not supported on this version of Telegram.';
|
||||
|
||||
// Taken from https://github.com/telegramdesktop/tdesktop/blob/41d9a9fcbd0c809c60ddbd9350791b1436aff7d9/Telegram/SourceFiles/ui/boxes/choose_language_box.cpp#L28
|
||||
export const SUPPORTED_TRANSLATION_LANGUAGES = [
|
||||
// Official
|
||||
|
||||
@ -17,8 +17,7 @@ import { IS_TOUCH_ENV } from '../../../util/browser/windowEnvironment';
|
||||
import { copyHtmlToClipboard } from '../../../util/clipboard';
|
||||
import { getCurrentTabId } from '../../../util/establishMultitabRole';
|
||||
import { compact, findLast } from '../../../util/iteratees';
|
||||
import * as langProvider from '../../../util/oldLangProvider';
|
||||
import { oldTranslate } from '../../../util/oldLangProvider';
|
||||
import { getTranslationFn } from '../../../util/localization';
|
||||
import parseHtmlAsFormattedText from '../../../util/parseHtmlAsFormattedText';
|
||||
import { getServerTime } from '../../../util/serverTime';
|
||||
import versionNotification from '../../../versionNotification.txt';
|
||||
@ -414,7 +413,7 @@ addActionHandler('focusMessage', (global, actions, payload): ActionReturnType =>
|
||||
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat) {
|
||||
actions.showNotification({ message: oldTranslate('Conversation.ErrorInaccessibleMessage'), tabId });
|
||||
actions.showNotification({ message: { key: 'ErrorFocusInaccessibleMessage' }, tabId });
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -719,8 +718,9 @@ addActionHandler('toggleMessageSelection', (global, actions, payload): ActionRet
|
||||
if (global.shouldShowContextMenuHint) {
|
||||
actions.disableContextMenuHint();
|
||||
actions.showNotification({
|
||||
// eslint-disable-next-line @stylistic/max-len
|
||||
message: `To **edit** or **reply**, close this menu. Then ${IS_TOUCH_ENV ? 'long tap' : 'right click'} on a message.`,
|
||||
message: {
|
||||
key: IS_TOUCH_ENV ? 'ContextMenuHintTouch' : 'ContextMenuHintMouse',
|
||||
},
|
||||
tabId,
|
||||
});
|
||||
}
|
||||
@ -1050,7 +1050,7 @@ addActionHandler('closeSuggestedPostApprovalModal', (global, actions, payload):
|
||||
|
||||
function copyTextForMessages(global: GlobalState, chatId: string, messageIds: number[]) {
|
||||
const { type: messageListType, threadId } = selectCurrentMessageList(global) || {};
|
||||
const lang = langProvider.oldTranslate;
|
||||
const lang = getTranslationFn();
|
||||
|
||||
const chat = selectChat(global, chatId);
|
||||
|
||||
|
||||
@ -304,7 +304,7 @@ export function getCanDeleteChat(chat: ApiChat) {
|
||||
return isChatBasicGroup(chat) || ((isChatSuperGroup(chat) || isChatChannel(chat)) && chat.isCreator);
|
||||
}
|
||||
|
||||
export function getFolderDescriptionText(lang: OldLangFn, folder: ApiChatFolder, chatsCount?: number) {
|
||||
export function getFolderDescriptionText(lang: LangFn, folder: ApiChatFolder, chatsCount?: number) {
|
||||
const {
|
||||
excludedChatIds, includedChatIds,
|
||||
bots, groups, contacts, nonContacts, channels,
|
||||
@ -320,7 +320,7 @@ export function getFolderDescriptionText(lang: OldLangFn, folder: ApiChatFolder,
|
||||
|| (excludedChatIds?.length)
|
||||
|| (includedChatIds?.length)
|
||||
)) {
|
||||
return lang('Chats', chatsCount);
|
||||
return lang('ChatsPlural', { count: chatsCount }, { pluralValue: chatsCount });
|
||||
}
|
||||
|
||||
// Otherwise, we return a short description of a single filter
|
||||
|
||||
@ -3,21 +3,20 @@ import type { TeactNode } from '../../lib/teact/teact';
|
||||
import type {
|
||||
ApiMediaExtendedPreview, ApiMessage, MediaContent, StatefulMediaContent,
|
||||
} from '../../api/types';
|
||||
import type { OldLangFn } from '../../hooks/useOldLang';
|
||||
import { ApiMessageEntityTypes } from '../../api/types';
|
||||
|
||||
import { CONTENT_NOT_SUPPORTED } from '../../config';
|
||||
import { type LangFn } from '../../util/localization';
|
||||
import trimText from '../../util/trimText';
|
||||
import { renderTextWithEntities } from '../../components/common/helpers/renderTextWithEntities';
|
||||
import {
|
||||
getMessageText, getMessageTranscription,
|
||||
getMessageTextWithFallback, getMessageTranscription,
|
||||
} from './messages';
|
||||
|
||||
const SPOILER_CHARS = ['⠺', '⠵', '⠞', '⠟'];
|
||||
export const TRUNCATED_SUMMARY_LENGTH = 80;
|
||||
|
||||
export function getMessageSummaryText(
|
||||
lang: OldLangFn,
|
||||
lang: LangFn,
|
||||
message: ApiMessage,
|
||||
statefulContent: StatefulMediaContent | undefined,
|
||||
noEmoji = false,
|
||||
@ -26,16 +25,20 @@ export function getMessageSummaryText(
|
||||
) {
|
||||
const emoji = !noEmoji && getMessageSummaryEmoji(message);
|
||||
const emojiWithSpace = emoji ? `${emoji} ` : '';
|
||||
const text = trimText(getMessageTextWithSpoilers(message, statefulContent), truncateLength);
|
||||
const text = trimText(getMessageTextWithSpoilers(lang, message, statefulContent), truncateLength);
|
||||
const description = getMessageSummaryDescription(lang, message, statefulContent, text, isExtended) as string;
|
||||
|
||||
return `${emojiWithSpace}${description}`;
|
||||
}
|
||||
|
||||
export function getMessageTextWithSpoilers(message: ApiMessage, statefulContent: StatefulMediaContent | undefined) {
|
||||
export function getMessageTextWithSpoilers(
|
||||
lang: LangFn,
|
||||
message: ApiMessage,
|
||||
statefulContent: StatefulMediaContent | undefined,
|
||||
) {
|
||||
const transcription = getMessageTranscription(message);
|
||||
|
||||
const textWithoutTranscription = getMessageText(statefulContent?.story || message)?.text;
|
||||
const textWithoutTranscription = getMessageTextWithFallback(lang, statefulContent?.story || message)?.text;
|
||||
if (!textWithoutTranscription) {
|
||||
return transcription;
|
||||
}
|
||||
@ -56,7 +59,7 @@ export function getMessageTextWithSpoilers(message: ApiMessage, statefulContent:
|
||||
|
||||
const spoiler = generateBrailleSpoiler(length);
|
||||
|
||||
return `${accText.substr(0, offset)}${spoiler}${accText.substr(offset + length, accText.length)}`;
|
||||
return `${accText.slice(0, offset)}${spoiler}${accText.slice(offset + length)}`;
|
||||
}, textWithoutTranscription);
|
||||
|
||||
return transcription ? `${transcription}\n${text}` : text;
|
||||
@ -111,12 +114,12 @@ export function getMessageSummaryEmoji(message: ApiMessage) {
|
||||
}
|
||||
|
||||
export function getMediaContentTypeDescription(
|
||||
lang: OldLangFn, content: MediaContent, statefulContent: StatefulMediaContent | undefined,
|
||||
lang: LangFn, content: MediaContent, statefulContent: StatefulMediaContent | undefined,
|
||||
) {
|
||||
return getSummaryDescription(lang, content, statefulContent);
|
||||
}
|
||||
export function getMessageSummaryDescription(
|
||||
lang: OldLangFn,
|
||||
lang: LangFn,
|
||||
message: ApiMessage,
|
||||
statefulContent: StatefulMediaContent | undefined,
|
||||
truncatedText?: string | TeactNode,
|
||||
@ -125,7 +128,7 @@ export function getMessageSummaryDescription(
|
||||
return getSummaryDescription(lang, message.content, statefulContent, message, truncatedText, isExtended);
|
||||
}
|
||||
function getSummaryDescription(
|
||||
lang: OldLangFn,
|
||||
lang: LangFn,
|
||||
mediaContent: MediaContent,
|
||||
statefulContent: StatefulMediaContent | undefined,
|
||||
message?: ApiMessage,
|
||||
@ -166,7 +169,7 @@ function getSummaryDescription(
|
||||
|
||||
if (message?.groupedId || isPaidMediaAlbum) {
|
||||
hasUsedTruncatedText = true;
|
||||
summary = truncatedText || lang('lng_in_dlg_album');
|
||||
summary = truncatedText || lang('Album');
|
||||
}
|
||||
|
||||
if (photo || isPaidMediaSinglePhoto) {
|
||||
@ -210,7 +213,7 @@ function getSummaryDescription(
|
||||
}
|
||||
|
||||
if (invoice) {
|
||||
summary = invoice.extendedMedia ? invoice.title : `${lang('PaymentInvoice')}: ${invoice.description}`;
|
||||
summary = invoice.extendedMedia ? invoice.title : lang('AttachInvoice', { description: invoice.description });
|
||||
}
|
||||
|
||||
if (text) {
|
||||
@ -222,11 +225,11 @@ function getSummaryDescription(
|
||||
}
|
||||
|
||||
if (location?.mediaType === 'geo' || location?.mediaType === 'venue') {
|
||||
summary = lang('Message.Location');
|
||||
summary = lang('AttachLocation');
|
||||
}
|
||||
|
||||
if (location?.mediaType === 'geoLive') {
|
||||
summary = lang('Message.LiveLocation');
|
||||
summary = lang('AttachLiveLocation');
|
||||
}
|
||||
|
||||
if (game) {
|
||||
@ -234,22 +237,22 @@ function getSummaryDescription(
|
||||
}
|
||||
|
||||
if (giveaway) {
|
||||
summary = lang('BoostingGiveawayChannelStarted');
|
||||
summary = lang('AttachGiveaway');
|
||||
}
|
||||
|
||||
if (giveawayResults) {
|
||||
summary = lang('Message.GiveawayEndedWinners', giveawayResults.winnersCount);
|
||||
summary = lang('AttachGiveawayResults');
|
||||
}
|
||||
|
||||
if (storyData) {
|
||||
summary = truncatedText || (message ? lang('ForwardedStory') : lang('Chat.ReplyStory'));
|
||||
summary = truncatedText || lang('AttachStory');
|
||||
}
|
||||
|
||||
if (todo) {
|
||||
summary = lang('Chat.Todo.Message.Title');
|
||||
summary = lang('AttachTodo');
|
||||
}
|
||||
|
||||
return summary || CONTENT_NOT_SUPPORTED;
|
||||
return summary || lang('MessageUnsupported');
|
||||
}
|
||||
|
||||
export function generateBrailleSpoiler(length: number) {
|
||||
|
||||
@ -17,7 +17,6 @@ import type { GlobalState } from '../types';
|
||||
import { ApiMessageEntityTypes, MAIN_THREAD_ID } from '../../api/types';
|
||||
|
||||
import {
|
||||
CONTENT_NOT_SUPPORTED,
|
||||
LOTTIE_STICKER_MIME_TYPE,
|
||||
RE_LINK_TEMPLATE,
|
||||
SERVICE_NOTIFICATIONS_USER_ID,
|
||||
@ -95,7 +94,11 @@ export function groupStatefulContent({
|
||||
}
|
||||
|
||||
export function getMessageText(message: MediaContainer) {
|
||||
return hasMessageText(message) ? message.content.text || { text: CONTENT_NOT_SUPPORTED } : undefined;
|
||||
return hasMessageText(message) ? message.content.text : undefined;
|
||||
}
|
||||
|
||||
export function getMessageTextWithFallback(lang: LangFn, message: MediaContainer) {
|
||||
return hasMessageText(message) ? message.content.text || { text: lang('MessageUnsupported') } : undefined;
|
||||
}
|
||||
|
||||
export function getMessageCustomShape(message: ApiMessage): boolean {
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import type { ApiMessage } from '../../api/types';
|
||||
import type { OldLangFn } from '../../hooks/useOldLang';
|
||||
|
||||
import { type LangFn } from '../../util/localization';
|
||||
import { renderMessageText } from '../../components/common/helpers/renderMessageText';
|
||||
import { getGlobal } from '..';
|
||||
import { getMessageStatefulContent } from './messages';
|
||||
import { getMessageSummaryDescription, getMessageSummaryEmoji } from './messageSummary';
|
||||
|
||||
export function renderMessageSummaryHtml(
|
||||
lang: OldLangFn,
|
||||
lang: LangFn,
|
||||
message: ApiMessage,
|
||||
) {
|
||||
const global = getGlobal();
|
||||
|
||||
85
src/types/language.d.ts
vendored
85
src/types/language.d.ts
vendored
@ -58,6 +58,7 @@ export interface LangPair {
|
||||
'PremiumLimitAccountsNoPremium': undefined;
|
||||
'PremiumLimitAccounts': undefined;
|
||||
'SendMessage': undefined;
|
||||
'MessageUnsupported': undefined;
|
||||
'ConversationDefaultRestrictedMedia': undefined;
|
||||
'AccDescrVoiceMessage': undefined;
|
||||
'BotSettings': undefined;
|
||||
@ -111,6 +112,7 @@ export interface LangPair {
|
||||
'UserRestrictionsNoChangeInfo': undefined;
|
||||
'UserRestrictionsInviteUsers': undefined;
|
||||
'UserRestrictionsPinMessages': undefined;
|
||||
'ChatPermissionNotAvailable': undefined;
|
||||
'StatsMessageInteractionsTitle': undefined;
|
||||
'StatsGroupGrowthTitle': undefined;
|
||||
'StatsGroupMembersTitle': undefined;
|
||||
@ -424,6 +426,7 @@ export interface LangPair {
|
||||
'AlwaysShareWith': undefined;
|
||||
'NeverShareWith': undefined;
|
||||
'SessionsTitle': undefined;
|
||||
'SessionTerminate': undefined;
|
||||
'OtherWebSessions': undefined;
|
||||
'BlockedUsers': undefined;
|
||||
'TwoStepVerification': undefined;
|
||||
@ -608,6 +611,7 @@ export interface LangPair {
|
||||
'SettingsPerformanceStickerEffects': undefined;
|
||||
'SettingsPerformanceAutoplayGif': undefined;
|
||||
'SettingsPerformanceAutoplayVideo': undefined;
|
||||
'SettingsPerformanceGranularTitle': undefined;
|
||||
'FavoriteStickers': undefined;
|
||||
'PremiumStickers': undefined;
|
||||
'GroupStickers': undefined;
|
||||
@ -627,7 +631,6 @@ export interface LangPair {
|
||||
'ErrorUnspecified': undefined;
|
||||
'NoStickers': undefined;
|
||||
'ClearRecentEmoji': undefined;
|
||||
'TextFormatAddLinkTitle': undefined;
|
||||
'Save': undefined;
|
||||
'ConversationEmptyPlaceholder': undefined;
|
||||
'ConversationGreetingText': undefined;
|
||||
@ -832,8 +835,16 @@ export interface LangPair {
|
||||
'ChannelPermissionsHeader': undefined;
|
||||
'UserRestrictionsSend': undefined;
|
||||
'UserRestrictionsSendMedia': undefined;
|
||||
'UserRestrictionsSendStickers': undefined;
|
||||
'UserRestrictionsSendPolls': undefined;
|
||||
'UserRestrictionsCreateTopics': undefined;
|
||||
'SendMediaPermissionFiles': undefined;
|
||||
'SendMediaPermissionPhotos': undefined;
|
||||
'SendMediaPermissionVideos': undefined;
|
||||
'SendMediaPermissionStickersGifs': undefined;
|
||||
'SendMediaPermissionAudios': undefined;
|
||||
'SendMediaPermissionVoices': undefined;
|
||||
'SendMediaPermissionRoundVideos': undefined;
|
||||
'SendMediaPermissionWebPages': undefined;
|
||||
'SendMediaPermissionPolls': undefined;
|
||||
'UserRestrictionsEmbedLinks': undefined;
|
||||
'UserRestrictionsChangeInfo': undefined;
|
||||
'ChannelAddException': undefined;
|
||||
@ -944,7 +955,7 @@ export interface LangPair {
|
||||
'FilterContacts': undefined;
|
||||
'FilterNonContacts': undefined;
|
||||
'FromYou': undefined;
|
||||
'InDlgAlbum': undefined;
|
||||
'Album': undefined;
|
||||
'AttachPhoto': undefined;
|
||||
'AttachGif': undefined;
|
||||
'AttachVideo': undefined;
|
||||
@ -952,8 +963,10 @@ export interface LangPair {
|
||||
'AttachMusic': undefined;
|
||||
'AttachContact': undefined;
|
||||
'AttachStory': undefined;
|
||||
'MessageLocation': undefined;
|
||||
'MessageLiveLocation': undefined;
|
||||
'AttachLocation': undefined;
|
||||
'AttachGiveaway': undefined;
|
||||
'AttachGiveawayResults': undefined;
|
||||
'AttachTodo': undefined;
|
||||
'ServiceNotifications': undefined;
|
||||
'Bot': undefined;
|
||||
'ALongTimeAgo': undefined;
|
||||
@ -1086,6 +1099,7 @@ export interface LangPair {
|
||||
'SettingsPasscodeStart1': undefined;
|
||||
'SettingsPasscodeStart2': undefined;
|
||||
'CurrentPasswordPlaceholder': undefined;
|
||||
'ChangeYourProfilePicture': undefined;
|
||||
'TooManyTabsTitle': undefined;
|
||||
'TooManyTabsDescription': undefined;
|
||||
'TooManyTabsReload': undefined;
|
||||
@ -1141,6 +1155,7 @@ export interface LangPair {
|
||||
'FormattingMonospaceAria': undefined;
|
||||
'FormattingUnderlineAria': undefined;
|
||||
'FormattingStrikethroughAria': undefined;
|
||||
'FormattingAddLinkAria': undefined;
|
||||
'FormattingEnterUrl': undefined;
|
||||
'PreviewWebPageClose': undefined;
|
||||
'MediaLocaltionImageAlt': undefined;
|
||||
@ -1190,6 +1205,8 @@ export interface LangPair {
|
||||
'ReplyInPrivateMessage': undefined;
|
||||
'ProfileOpenAppTerms': undefined;
|
||||
'ProfileBotOpenAppInfoLink': undefined;
|
||||
'ProfileBirthday': undefined;
|
||||
'ProfileBirthdayToday': undefined;
|
||||
'MonetizationInfoTONTitle': undefined;
|
||||
'AriaSearchOlderResult': undefined;
|
||||
'AriaSearchNewerResult': undefined;
|
||||
@ -1339,6 +1356,9 @@ export interface LangPair {
|
||||
'SearchTabVoice': undefined;
|
||||
'SearchTabMessages': undefined;
|
||||
'SearchTabPublicPosts': undefined;
|
||||
'SearchResultTopics': undefined;
|
||||
'SearchResultMyChannels': undefined;
|
||||
'SearchResultRecommendedChannels': undefined;
|
||||
'StarsTransactionsAll': undefined;
|
||||
'StarsTransactionsIncoming': undefined;
|
||||
'StarsTransactionsOutgoing': undefined;
|
||||
@ -1392,6 +1412,8 @@ export interface LangPair {
|
||||
'CheckPasswordTitle': undefined;
|
||||
'CheckPasswordPlaceholder': undefined;
|
||||
'CheckPasswordDescription': undefined;
|
||||
'PasswordFormPlaceholder': undefined;
|
||||
'PasswordFormSubmit': undefined;
|
||||
'ActionFallbackUser': undefined;
|
||||
'ActionFallbackChat': undefined;
|
||||
'ActionFallbackChannel': undefined;
|
||||
@ -1655,6 +1677,9 @@ export interface LangPair {
|
||||
'RatingNegativeLevel': undefined;
|
||||
'LinkDescriptionRatingBack': undefined;
|
||||
'LinkDescriptionRatingPreview': undefined;
|
||||
'ErrorFocusInaccessibleMessage': undefined;
|
||||
'ContextMenuHintMouse': undefined;
|
||||
'ContextMenuHintTouch': undefined;
|
||||
}
|
||||
|
||||
export interface LangPairWithVariables<V = LangVariable> {
|
||||
@ -1901,6 +1926,9 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
'NewDiscussionChatTitle': {
|
||||
'name': V;
|
||||
};
|
||||
'AttachInvoice': {
|
||||
'description': V;
|
||||
};
|
||||
'LastSeenTodayAt': {
|
||||
'time': V;
|
||||
};
|
||||
@ -1973,6 +2001,20 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
'ProfileOpenAppAbout': {
|
||||
'terms': V;
|
||||
};
|
||||
'ProfileBirthdayValue': {
|
||||
'date': V;
|
||||
};
|
||||
'ProfileBirthdayValueYear': {
|
||||
'date': V;
|
||||
'age': V;
|
||||
};
|
||||
'ProfileBirthdayTodayValue': {
|
||||
'date': V;
|
||||
};
|
||||
'ProfileBirthdayTodayValueYear': {
|
||||
'date': V;
|
||||
'age': V;
|
||||
};
|
||||
'ChannelEarnLearnCoinAbout': {
|
||||
'link': V;
|
||||
};
|
||||
@ -2135,6 +2177,9 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
'StarsReactionTerms': {
|
||||
'link': V;
|
||||
};
|
||||
'AriaMiniApp': {
|
||||
'bot': V;
|
||||
};
|
||||
'StarsSubscribeInfo': {
|
||||
'link': V;
|
||||
};
|
||||
@ -2545,8 +2590,8 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
'amount': V;
|
||||
};
|
||||
'ActionPaidOneMessageIncoming': {
|
||||
'amount': V;
|
||||
'user': V;
|
||||
'amount': V;
|
||||
};
|
||||
'PaneMessagePaidMessageCharge': {
|
||||
'peer': V;
|
||||
@ -2688,12 +2733,10 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
};
|
||||
'SuggestedPostReceiveAmount': {
|
||||
'peer': V;
|
||||
'currency': V;
|
||||
'duration': V;
|
||||
};
|
||||
'SuggestedPostReceiveAmountYou': {
|
||||
'peer': V;
|
||||
'currency': V;
|
||||
'duration': V;
|
||||
};
|
||||
'SuggestedPostRefund': {
|
||||
@ -2703,7 +2746,6 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
'SuggestedPostRefundYou': {
|
||||
'peer': V;
|
||||
'duration': V;
|
||||
'currency': V;
|
||||
};
|
||||
'SuggestedPostBalanceTooLow': {
|
||||
'peer': V;
|
||||
@ -2748,7 +2790,6 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
};
|
||||
'SuggestedPostConfirmDetailsUser': {
|
||||
'amount': V;
|
||||
'commission': V;
|
||||
'duration': V;
|
||||
};
|
||||
'SuggestedPostConfirmDetailsWithTimeAdmin': {
|
||||
@ -2759,7 +2800,6 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
};
|
||||
'SuggestedPostConfirmDetailsWithTimeUser': {
|
||||
'amount': V;
|
||||
'commission': V;
|
||||
'time': V;
|
||||
'duration': V;
|
||||
};
|
||||
@ -2819,9 +2859,6 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
'tasks': V;
|
||||
'list': V;
|
||||
};
|
||||
'HintTodoListTasksCount': {
|
||||
'count': V;
|
||||
};
|
||||
'GiftInfoCollectibleBy': {
|
||||
'number': V;
|
||||
'owner': V;
|
||||
@ -2832,12 +2869,6 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
'ButtonSensitiveAlways': {
|
||||
'years': V;
|
||||
};
|
||||
'NotificationGiftsLimit': {
|
||||
'count': V;
|
||||
};
|
||||
'DescriptionGiftPremiumRequired': {
|
||||
'count': V;
|
||||
};
|
||||
'DescriptionComposerGiftMinimumCurrencyPrice': {
|
||||
'amount': V;
|
||||
};
|
||||
@ -2984,6 +3015,9 @@ export interface LangPairPluralWithVariables<V = LangVariable> {
|
||||
'ChannelStatsSharesCount': {
|
||||
'count': V;
|
||||
};
|
||||
'ChatsPlural': {
|
||||
'count': V;
|
||||
};
|
||||
'LastSeenMinutesAgo': {
|
||||
'count': V;
|
||||
};
|
||||
@ -3187,9 +3221,18 @@ export interface LangPairPluralWithVariables<V = LangVariable> {
|
||||
'MessageActionTodoTaskCount': {
|
||||
'count': V;
|
||||
};
|
||||
'HintTodoListTasksCount2': {
|
||||
'count': V;
|
||||
};
|
||||
'TextAgeVerificationModal': {
|
||||
'count': V;
|
||||
};
|
||||
'NotificationGiftsLimit2': {
|
||||
'count': V;
|
||||
};
|
||||
'DescriptionGiftPremiumRequired2': {
|
||||
'count': V;
|
||||
};
|
||||
'RemainingPublicPostsSearch': {
|
||||
'count': V;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user