[Dev] Localization: Reassign lang function for memo (#2341)

This commit is contained in:
Alexander Zinchuk 2023-01-28 02:15:16 +01:00
parent 6c40a8e487
commit 68f28b9405
14 changed files with 79 additions and 67 deletions

View File

@ -25,7 +25,6 @@ import buildClassName from '../../util/buildClassName';
import { formatMediaDateTime, formatMediaDuration, formatPastTimeShort } from '../../util/dateFormat'; import { formatMediaDateTime, formatMediaDuration, formatPastTimeShort } from '../../util/dateFormat';
import { decodeWaveform, interpolateArray } from '../../util/waveform'; import { decodeWaveform, interpolateArray } from '../../util/waveform';
import { makeTrackId } from '../../util/audioPlayer'; import { makeTrackId } from '../../util/audioPlayer';
import { getTranslation } from '../../util/langProvider';
import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress'; import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress';
import useShowTransition from '../../hooks/useShowTransition'; import useShowTransition from '../../hooks/useShowTransition';
import type { BufferedRange } from '../../hooks/useBuffering'; import type { BufferedRange } from '../../hooks/useBuffering';
@ -443,7 +442,7 @@ function renderAudio(
title, performer, fileName, title, performer, fileName,
} = audio; } = audio;
const showSeekline = isPlaying || (playProgress > 0 && playProgress < 1); const showSeekline = isPlaying || (playProgress > 0 && playProgress < 1);
const { isRtl } = getTranslation; const { isRtl } = lang;
return ( return (
<div className="content"> <div className="content">

View File

@ -10,7 +10,7 @@ import type { TextFilter } from './renderText';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import renderText from './renderText'; import renderText from './renderText';
import { copyTextToClipboard } from '../../../util/clipboard'; import { copyTextToClipboard } from '../../../util/clipboard';
import { getTranslation } from '../../../util/langProvider'; import { translate } from '../../../util/langProvider';
import { buildCustomEmojiHtmlFromEntity } from '../../middle/composer/helpers/customEmoji'; import { buildCustomEmojiHtmlFromEntity } from '../../middle/composer/helpers/customEmoji';
import MentionLink from '../../middle/message/MentionLink'; import MentionLink from '../../middle/message/MentionLink';
@ -550,6 +550,6 @@ function handleHashtagClick(e: React.MouseEvent<HTMLAnchorElement>) {
function handleCodeClick(e: React.MouseEvent<HTMLElement>) { function handleCodeClick(e: React.MouseEvent<HTMLElement>) {
copyTextToClipboard(e.currentTarget.innerText); copyTextToClipboard(e.currentTarget.innerText);
getActions().showNotification({ getActions().showNotification({
message: getTranslation('TextCopied'), message: translate('TextCopied'),
}); });
} }

View File

@ -1,7 +1,7 @@
import { addActionHandler, getGlobal, setGlobal } from '../../index'; import { addActionHandler, getGlobal, setGlobal } from '../../index';
import { selectChat } from '../../selectors'; import { selectChat } from '../../selectors';
import { callApi } from '../../../api/gramjs'; import { callApi } from '../../../api/gramjs';
import { getTranslation } from '../../../util/langProvider'; import { translate } from '../../../util/langProvider';
import { addUsers } from '../../reducers'; import { addUsers } from '../../reducers';
import { buildCollectionByKey } from '../../../util/iteratees'; import { buildCollectionByKey } from '../../../util/iteratees';
@ -28,7 +28,7 @@ addActionHandler('reportPeer', async (global, actions, payload) => {
actions.showNotification({ actions.showNotification({
message: result message: result
? getTranslation('ReportPeer.AlertSuccess') ? translate('ReportPeer.AlertSuccess')
: 'An error occurred while submitting your report. Please, try again later.', : 'An error occurred while submitting your report. Please, try again later.',
}); });
}); });
@ -58,7 +58,7 @@ addActionHandler('reportProfilePhoto', async (global, actions, payload) => {
actions.showNotification({ actions.showNotification({
message: result message: result
? getTranslation('ReportPeer.AlertSuccess') ? translate('ReportPeer.AlertSuccess')
: 'An error occurred while submitting your report. Please, try again later.', : 'An error occurred while submitting your report. Please, try again later.',
}); });
}); });

View File

@ -636,7 +636,7 @@ addActionHandler('openChatByPhoneNumber', async (global, actions, payload) => {
if (!chat) { if (!chat) {
actions.openPreviousChat(); actions.openPreviousChat();
actions.showNotification({ actions.showNotification({
message: langProvider.getTranslation('lng_username_by_phone_not_found').replace('{phone}', phoneNumber), message: langProvider.translate('lng_username_by_phone_not_found').replace('{phone}', phoneNumber),
}); });
return; return;
} }
@ -1525,7 +1525,7 @@ addActionHandler('toggleTopicPinned', (global, actions, payload) => {
if (isPinned && Object.values(chat.topics).filter((topic) => topic.isPinned).length >= topicsPinnedLimit) { if (isPinned && Object.values(chat.topics).filter((topic) => topic.isPinned).length >= topicsPinnedLimit) {
actions.showNotification({ actions.showNotification({
message: langProvider.getTranslation('LimitReachedPinnedTopics', topicsPinnedLimit, 'i'), message: langProvider.translate('LimitReachedPinnedTopics', topicsPinnedLimit, 'i'),
}); });
return; return;
} }
@ -1953,7 +1953,7 @@ async function getAttachBotOrNotify(global: GlobalState, username: string) {
global = getGlobal(); global = getGlobal();
if (!result) { if (!result) {
getActions().showNotification({ message: langProvider.getTranslation('WebApp.AddToAttachmentUnavailableError') }); getActions().showNotification({ message: langProvider.translate('WebApp.AddToAttachmentUnavailableError') });
return undefined; return undefined;
} }

View File

@ -84,7 +84,7 @@ import {
import { import {
getMessageOriginalId, getUserFullName, isDeletedUser, isServiceNotificationMessage, isUserBot, getMessageOriginalId, getUserFullName, isDeletedUser, isServiceNotificationMessage, isUserBot,
} from '../../helpers'; } from '../../helpers';
import { getTranslation } from '../../../util/langProvider'; import { translate } from '../../../util/langProvider';
import { ensureProtocol } from '../../../util/ensureProtocol'; import { ensureProtocol } from '../../../util/ensureProtocol';
const AUTOLOGIN_TOKEN_KEY = 'autologin_token'; const AUTOLOGIN_TOKEN_KEY = 'autologin_token';
@ -494,7 +494,7 @@ addActionHandler('reportMessages', async (global, actions, payload) => {
actions.showNotification({ actions.showNotification({
message: result message: result
? getTranslation('ReportPeer.AlertSuccess') ? translate('ReportPeer.AlertSuccess')
: 'An error occurred while submitting your report. Please, try again later.', : 'An error occurred while submitting your report. Please, try again later.',
}); });
}); });
@ -1336,7 +1336,7 @@ addActionHandler('setForwardChatOrTopic', async (global, actions, payload) => {
if (user?.fullInfo!.noVoiceMessages) { if (user?.fullInfo!.noVoiceMessages) {
actions.showDialog({ actions.showDialog({
data: { data: {
message: getTranslation('VoiceMessagesRestrictedByPrivacy', getUserFullName(user)), message: translate('VoiceMessagesRestrictedByPrivacy', getUserFullName(user)),
}, },
}); });
return; return;

View File

@ -18,7 +18,7 @@ import {
} from '../../reducers'; } from '../../reducers';
import searchWords from '../../../util/searchWords'; import searchWords from '../../../util/searchWords';
import { selectIsCurrentUserPremium, selectStickerSet } from '../../selectors'; import { selectIsCurrentUserPremium, selectStickerSet } from '../../selectors';
import { getTranslation } from '../../../util/langProvider'; import { translate } from '../../../util/langProvider';
import { selectCurrentLimit, selectPremiumLimit } from '../../selectors/limits'; import { selectCurrentLimit, selectPremiumLimit } from '../../selectors/limits';
import * as langProvider from '../../../util/langProvider'; import * as langProvider from '../../../util/langProvider';
import { buildCollectionByKey } from '../../../util/iteratees'; import { buildCollectionByKey } from '../../../util/iteratees';
@ -273,9 +273,9 @@ addActionHandler('saveGif', async (global, actions, payload) => {
if (!shouldUnsave && length && length >= limit) { if (!shouldUnsave && length && length >= limit) {
actions.showNotification({ actions.showNotification({
title: langProvider.getTranslation('LimitReachedFavoriteGifs', limit.toString()), title: langProvider.translate('LimitReachedFavoriteGifs', limit.toString()),
message: isPremium ? langProvider.getTranslation('LimitReachedFavoriteGifsSubtitlePremium') message: isPremium ? langProvider.translate('LimitReachedFavoriteGifsSubtitlePremium')
: langProvider.getTranslation('LimitReachedFavoriteGifsSubtitle', : langProvider.translate('LimitReachedFavoriteGifsSubtitle',
premiumLimit.toString()), premiumLimit.toString()),
...(!isPremium && { action: actions.openPremiumModal }), ...(!isPremium && { action: actions.openPremiumModal }),
className: 'bold-link', className: 'bold-link',
@ -312,9 +312,9 @@ addActionHandler('faveSticker', (global, actions, payload) => {
if (current >= limit) { if (current >= limit) {
actions.showNotification({ actions.showNotification({
title: langProvider.getTranslation('LimitReachedFavoriteStickers', limit.toString()), title: langProvider.translate('LimitReachedFavoriteStickers', limit.toString()),
message: isPremium ? langProvider.getTranslation('LimitReachedFavoriteStickersSubtitlePremium') message: isPremium ? langProvider.translate('LimitReachedFavoriteStickersSubtitlePremium')
: langProvider.getTranslation('LimitReachedFavoriteStickersSubtitle', : langProvider.translate('LimitReachedFavoriteStickersSubtitle',
premiumLimit.toString()), premiumLimit.toString()),
...(!isPremium && { action: actions.openPremiumModal }), ...(!isPremium && { action: actions.openPremiumModal }),
className: 'bold-link', className: 'bold-link',
@ -476,7 +476,7 @@ async function loadStickers(stickerSetInfo: ApiStickerSetInfo) {
if (!stickerSet) { if (!stickerSet) {
onTickEnd(() => { onTickEnd(() => {
getActions().showNotification({ getActions().showNotification({
message: getTranslation('StickerPack.ErrorNotFound'), message: translate('StickerPack.ErrorNotFound'),
}); });
}); });
if ('shortName' in stickerSetInfo && global.openedStickerSetShortName === stickerSetInfo.shortName) { if ('shortName' in stickerSetInfo && global.openedStickerSetShortName === stickerSetInfo.shortName) {
@ -621,7 +621,7 @@ addActionHandler('openStickerSet', async (global, actions, payload) => {
const set = selectStickerSet(global, stickerSetInfo); const set = selectStickerSet(global, stickerSetInfo);
if (!set?.shortName) { if (!set?.shortName) {
actions.showNotification({ actions.showNotification({
message: getTranslation('StickerPack.ErrorNotFound'), message: translate('StickerPack.ErrorNotFound'),
}); });
return; return;
} }

View File

@ -302,7 +302,7 @@ addActionHandler('importContact', async (global, actions, payload) => {
const result = await callApi('importContact', { phone, firstName, lastName }); const result = await callApi('importContact', { phone, firstName, lastName });
if (!result) { if (!result) {
actions.showNotification({ actions.showNotification({
message: langProvider.getTranslation('Contacts.PhoneNumber.NotRegistred'), message: langProvider.translate('Contacts.PhoneNumber.NotRegistred'),
}); });
return; return;

View File

@ -105,7 +105,7 @@ addActionHandler('apiUpdate', (global, actions, update) => {
if (!verifyPhoneCallProtocol(call.protocol)) { if (!verifyPhoneCallProtocol(call.protocol)) {
const user = selectPhoneCallUser(global); const user = selectPhoneCallUser(global);
actions.hangUp(); actions.hangUp();
actions.showNotification({ message: langProvider.getTranslation('VoipPeerIncompatible', user?.firstName) }); actions.showNotification({ message: langProvider.translate('VoipPeerIncompatible', user?.firstName) });
return undefined; return undefined;
} }
} }

View File

@ -18,8 +18,8 @@ addActionHandler('apiUpdate', (global, actions, update) => {
const { amount, currency, title } = message.content.invoice; const { amount, currency, title } = message.content.invoice;
actions.showNotification({ actions.showNotification({
message: langProvider.getTranslation('PaymentInfoHint', [ message: langProvider.translate('PaymentInfoHint', [
formatCurrency(amount, currency, langProvider.getTranslation.code), formatCurrency(amount, currency, langProvider.getTranslationFn().code),
title, title,
]), ]),
}); });

View File

@ -196,7 +196,7 @@ addActionHandler('joinVoiceChatByLink', async (global, actions, payload) => {
const chat = await fetchChatByUsername(username); const chat = await fetchChatByUsername(username);
if (!chat) { if (!chat) {
actions.showNotification({ message: langProvider.getTranslation('NoUsernameFound') }); actions.showNotification({ message: langProvider.translate('NoUsernameFound') });
return; return;
} }
@ -383,7 +383,7 @@ export function checkNavigatorUserMediaPermissions(isVideo?: boolean) {
.then((stream) => { .then((stream) => {
if (stream.getVideoTracks().length === 0) { if (stream.getVideoTracks().length === 0) {
getActions().showNotification({ getActions().showNotification({
message: langProvider.getTranslation('Call.Camera.Error'), message: langProvider.translate('Call.Camera.Error'),
}); });
} else { } else {
checkMicrophonePermission(); checkMicrophonePermission();
@ -391,7 +391,7 @@ export function checkNavigatorUserMediaPermissions(isVideo?: boolean) {
}) })
.catch(() => { .catch(() => {
getActions().showNotification({ getActions().showNotification({
message: langProvider.getTranslation('Call.Camera.Error'), message: langProvider.translate('Call.Camera.Error'),
}); });
}); });
} else { } else {
@ -404,13 +404,13 @@ function checkMicrophonePermission() {
.then((stream) => { .then((stream) => {
if (stream.getAudioTracks().length === 0) { if (stream.getAudioTracks().length === 0) {
getActions().showNotification({ getActions().showNotification({
message: langProvider.getTranslation('RequestAcces.Error.HaveNotAccess.Call'), message: langProvider.translate('RequestAcces.Error.HaveNotAccess.Call'),
}); });
} }
}) })
.catch(() => { .catch(() => {
getActions().showNotification({ getActions().showNotification({
message: langProvider.getTranslation('RequestAcces.Error.HaveNotAccess.Call'), message: langProvider.translate('RequestAcces.Error.HaveNotAccess.Call'),
}); });
}); });
} }

View File

@ -751,7 +751,7 @@ addActionHandler('copyMessagesByIds', (global, actions, payload: { messageIds?:
function copyTextForMessages(global: GlobalState, chatId: string, messageIds: number[]) { function copyTextForMessages(global: GlobalState, chatId: string, messageIds: number[]) {
const { type: messageListType, threadId } = selectCurrentMessageList(global) || {}; const { type: messageListType, threadId } = selectCurrentMessageList(global) || {};
const lang = langProvider.getTranslation; const lang = langProvider.translate;
const chatMessages = messageListType === 'scheduled' const chatMessages = messageListType === 'scheduled'
? selectChatScheduledMessages(global, chatId) ? selectChatScheduledMessages(global, chatId)

View File

@ -2,7 +2,7 @@ import * as langProvider from '../util/langProvider';
import useForceUpdate from './useForceUpdate'; import useForceUpdate from './useForceUpdate';
import useOnChange from './useOnChange'; import useOnChange from './useOnChange';
export type LangFn = typeof langProvider.getTranslation; export type LangFn = langProvider.LangFn;
const useLang = (): LangFn => { const useLang = (): LangFn => {
const forceUpdate = useForceUpdate(); const forceUpdate = useForceUpdate();
@ -11,7 +11,7 @@ const useLang = (): LangFn => {
return langProvider.addCallback(forceUpdate); return langProvider.addCallback(forceUpdate);
}, [forceUpdate]); }, [forceUpdate]);
return langProvider.getTranslation; return langProvider.getTranslationFn();
}; };
export default useLang; export default useLang;

View File

@ -11,7 +11,7 @@ import { callApi } from '../api/gramjs';
import { createCallbackManager } from './callbacks'; import { createCallbackManager } from './callbacks';
import { formatInteger } from './textFormat'; import { formatInteger } from './textFormat';
interface LangFn { export interface LangFn {
(key: string, value?: any, format?: 'i', pluralValue?: number): string; (key: string, value?: any, format?: 'i', pluralValue?: number): string;
isRtl?: boolean; isRtl?: boolean;
@ -94,30 +94,42 @@ export { addCallback, removeCallback };
let currentLangCode: string | undefined; let currentLangCode: string | undefined;
let currentTimeFormat: TimeFormat | undefined; let currentTimeFormat: TimeFormat | undefined;
export const getTranslation: LangFn = (key: string, value?: any, format?: 'i', pluralValue?: number) => { function createLangFn() {
if (value !== undefined) { return (key: string, value?: any, format?: 'i', pluralValue?: number) => {
const cacheValue = Array.isArray(value) ? JSON.stringify(value) : value; if (value !== undefined) {
const cached = cache.get(`${key}_${cacheValue}_${format}${pluralValue ? `_${pluralValue}` : ''}`); const cacheValue = Array.isArray(value) ? JSON.stringify(value) : value;
if (cached) { const cached = cache.get(`${key}_${cacheValue}_${format}${pluralValue ? `_${pluralValue}` : ''}`);
return cached; if (cached) {
} return cached;
} }
if (!langPack && !fallbackLangPack) {
return key;
}
const langString = (langPack?.[key]) || (fallbackLangPack?.[key]);
if (!langString) {
if (!fallbackLangPack) {
void importFallbackLangPack();
} }
return key; if (!langPack && !fallbackLangPack) {
} return key;
}
return processTranslation(langString, key, value, format, pluralValue); const langString = (langPack?.[key]) || (fallbackLangPack?.[key]);
}; if (!langString) {
if (!fallbackLangPack) {
void importFallbackLangPack();
}
return key;
}
return processTranslation(langString, key, value, format, pluralValue);
};
}
let translationFn: LangFn = createLangFn();
export function translate(...args: Parameters<LangFn>) {
return translationFn(...args);
}
export function getTranslationFn(): LangFn {
return translationFn;
}
export async function getTranslationForLangString(langCode: string, key: string) { export async function getTranslationForLangString(langCode: string, key: string) {
let translateString: ApiLangString | undefined = await cacheApi.fetch( let translateString: ApiLangString | undefined = await cacheApi.fetch(
@ -162,10 +174,11 @@ export async function setLanguage(langCode: LangCode, callback?: NoneToVoidFunct
const { languages, timeFormat } = getGlobal().settings.byKey; const { languages, timeFormat } = getGlobal().settings.byKey;
const langInfo = languages?.find((lang) => lang.langCode === langCode); const langInfo = languages?.find((lang) => lang.langCode === langCode);
getTranslation.isRtl = Boolean(langInfo?.rtl); translationFn = createLangFn();
getTranslation.code = langCode.replace('-raw', '') as LangCode; translationFn.isRtl = Boolean(langInfo?.rtl);
getTranslation.langName = langInfo?.nativeName; translationFn.code = langCode.replace('-raw', '') as LangCode;
getTranslation.timeFormat = timeFormat; translationFn.langName = langInfo?.nativeName;
translationFn.timeFormat = timeFormat;
if (callback) { if (callback) {
callback(); callback();
@ -180,7 +193,7 @@ export function setTimeFormat(timeFormat: TimeFormat) {
} }
currentTimeFormat = timeFormat; currentTimeFormat = timeFormat;
getTranslation.timeFormat = timeFormat; translationFn.timeFormat = timeFormat;
runCallbacks(); runCallbacks();
} }

View File

@ -29,7 +29,7 @@ import {
selectUser, selectUser,
} from '../global/selectors'; } from '../global/selectors';
import { IS_SERVICE_WORKER_SUPPORTED, IS_TOUCH_ENV } from './environment'; import { IS_SERVICE_WORKER_SUPPORTED, IS_TOUCH_ENV } from './environment';
import { getTranslation } from './langProvider'; import { translate } from './langProvider';
import * as mediaLoader from './mediaLoader'; import * as mediaLoader from './mediaLoader';
import { debounce } from './schedulers'; import { debounce } from './schedulers';
@ -300,7 +300,7 @@ function getNotificationContent(chat: ApiChat, message: ApiMessage, reaction?: A
const isChat = chat && (isChatChannel(chat) || message.senderId === message.chatId); const isChat = chat && (isChatChannel(chat) || message.senderId === message.chatId);
body = renderActionMessageText( body = renderActionMessageText(
getTranslation, translate,
message, message,
!isChat ? messageSender : undefined, !isChat ? messageSender : undefined,
isChat ? chat : undefined, isChat ? chat : undefined,
@ -312,8 +312,8 @@ function getNotificationContent(chat: ApiChat, message: ApiMessage, reaction?: A
) as string; ) as string;
} else { } else {
// TODO[forums] Support ApiChat // TODO[forums] Support ApiChat
const senderName = getMessageSenderName(getTranslation, chat.id, messageSender); const senderName = getMessageSenderName(translate, chat.id, messageSender);
const summary = getMessageSummaryText(getTranslation, message, false, 60, false); const summary = getMessageSummaryText(translate, message, false, 60, false);
body = senderName ? `${senderName}: ${summary}` : summary; body = senderName ? `${senderName}: ${summary}` : summary;
} }
@ -321,7 +321,7 @@ function getNotificationContent(chat: ApiChat, message: ApiMessage, reaction?: A
body = 'New message'; body = 'New message';
} }
let title = isScreenLocked ? APP_NAME : getChatTitle(getTranslation, chat, privateChatUser); let title = isScreenLocked ? APP_NAME : getChatTitle(translate, chat, privateChatUser);
if (message.isSilent) { if (message.isSilent) {
title += ' 🔕'; title += ' 🔕';
@ -364,7 +364,7 @@ export async function notifyAboutCall({
options.vibrate = [200, 100, 200]; options.vibrate = [200, 100, 200];
} }
const notification = new Notification(getTranslation('VoipIncoming'), options); const notification = new Notification(translate('VoipIncoming'), options);
notification.onclick = () => { notification.onclick = () => {
notification.close(); notification.close();