From 29c168ece00ecfa1e8fdfbcfcb6299152f32b276 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Sat, 24 Apr 2021 13:59:49 +0200 Subject: [PATCH] Removed the whole `{:br:}` syntax and removed jQuery from the `tra` method --- shared/js/ConnectionHandler.ts | 7 +- shared/js/connection/rtc/SdpUtils.ts | 2 +- .../connectionlog/DispatcherNotifications.ts | 4 +- shared/js/connectionlog/History.ts | 2 +- .../ChannelConversationManager.ts | 4 +- shared/js/file/OwnAvatarStorage.ts | 1 + shared/js/i18n/localize.ts | 34 ++-- shared/js/media/Video.ts | 2 +- shared/js/music/PlaylistManager.ts | 1 + shared/js/text/bbcode/InviteController.ts | 1 + shared/js/text/bbcode/YoutubeRenderer.tsx | 1 + shared/js/ui/frames/chat.ts | 2 +- .../js/ui/frames/side/ClientInfoController.ts | 1 + .../js/ui/frames/side/ClientInfoRenderer.tsx | 5 +- shared/js/ui/frames/side/HeaderController.ts | 1 + shared/js/ui/frames/side/HeaderRenderer.tsx | 1 + .../ui/frames/side/MusicPlaylistController.ts | 1 + shared/js/ui/frames/video/Controller.ts | 2 +- shared/js/ui/modal/ModalGroupCreate.tsx | 2 +- shared/js/ui/modal/ModalIconSelect.ts | 8 +- shared/js/ui/modal/ModalMusicManage.ts | 4 +- .../js/ui/modal/ModalServerInfoBandwidth.ts | 192 ------------------ .../js/ui/modal/avatar-upload/Controller.ts | 12 +- shared/js/ui/modal/avatar-upload/Renderer.tsx | 3 +- .../js/ui/modal/input-processor/Renderer.tsx | 4 +- .../js/ui/modal/permission/ModalController.ts | 2 +- shared/js/ui/modal/server-info/Controller.ts | 1 - shared/js/ui/modal/settings/Keymap.tsx | 2 +- .../ui/modal/settings/MicrophoneRenderer.tsx | 1 + .../transfer/FileBrowserControllerRemote.ts | 8 +- .../ui/modal/transfer/FileBrowserRenderer.tsx | 14 +- shared/js/ui/modal/yes-no/Controller.ts | 24 +++ shared/js/ui/react-elements/Tab.tsx | 1 + .../modal/external/renderer/EntryPoint.ts | 2 +- shared/js/ui/tree/DragHelper.ts | 1 + shared/js/ui/utils/Variable.ts | 5 +- 36 files changed, 102 insertions(+), 256 deletions(-) delete mode 100644 shared/js/ui/modal/ModalServerInfoBandwidth.ts create mode 100644 shared/js/ui/modal/yes-no/Controller.ts diff --git a/shared/js/ConnectionHandler.ts b/shared/js/ConnectionHandler.ts index d111a559..cb1df76b 100644 --- a/shared/js/ConnectionHandler.ts +++ b/shared/js/ConnectionHandler.ts @@ -3,7 +3,6 @@ import {PermissionManager} from "./permission/PermissionManager"; import {GroupManager} from "./permission/GroupManager"; import {Settings, settings} from "./settings"; import {Sound, SoundManager} from "./audio/Sounds"; -import {ConnectionProfile} from "./profiles/ConnectionProfile"; import {LogCategory, logError, logInfo, logTrace, logWarn} from "./log"; import {createErrorModal, createInputModal, Modal} from "./ui/elements/Modal"; import {hashPassword} from "./utils/helpers"; @@ -13,7 +12,7 @@ import {defaultRecorder, RecorderProfile} from "./voice/RecorderProfile"; import {formatMessage} from "./ui/frames/chat"; import {EventHandler, Registry} from "./events"; import {FileManager} from "./file/FileManager"; -import {tr} from "./i18n/localize"; +import {tr, tra} from "./i18n/localize"; import {guid} from "./crypto/uid"; import {PluginCmdRegistry} from "./connection/PluginCmdHandler"; import {VoiceConnectionStatus, WhisperSessionInitializeData} from "./connection/VoiceConnection"; @@ -632,7 +631,7 @@ export class ConnectionHandler { case DisconnectReason.IDENTITY_TOO_LOW: createErrorModal( tr("Identity level is too low"), - formatMessage(tr("You've been disconnected, because your Identity level is too low.{:br:}You need at least a level of {0}"), data["extra_message"]) + formatMessage(tr("You've been disconnected, because your Identity level is too low.\nYou need at least a level of {0}"), data["extra_message"]) ).open(); this.sound.play(Sound.CONNECTION_DISCONNECTED); @@ -691,7 +690,7 @@ export class ConnectionHandler { const modal = createErrorModal( tr("You've been kicked"), formatMessage( - have_invoker ? tr("You've been kicked from the server by {0}:{:br:}{1}") : tr("You've been kicked from the server:{:br:}{1}"), + have_invoker ? tr("You've been kicked from the server by {0}:\n{1}") : tr("You've been kicked from the server:\n{1}"), have_invoker ? htmltags.generate_client_object({ client_id: parseInt(data["invokerid"]), client_unique_id: data["invokeruid"], client_name: data["invokername"]}) : "", diff --git a/shared/js/connection/rtc/SdpUtils.ts b/shared/js/connection/rtc/SdpUtils.ts index 25fb7811..81cfadb5 100644 --- a/shared/js/connection/rtc/SdpUtils.ts +++ b/shared/js/connection/rtc/SdpUtils.ts @@ -1,5 +1,5 @@ import * as sdpTransform from "sdp-transform"; -import { tr } from "tc-shared/i18n/localize"; +import {tr, tra} from "tc-shared/i18n/localize"; interface SdpCodec { payload: number; diff --git a/shared/js/connectionlog/DispatcherNotifications.ts b/shared/js/connectionlog/DispatcherNotifications.ts index a75fa527..9484dcc6 100644 --- a/shared/js/connectionlog/DispatcherNotifications.ts +++ b/shared/js/connectionlog/DispatcherNotifications.ts @@ -359,11 +359,11 @@ registerDispatcher(EventType.CLIENT_VIEW_LEAVE, (data, handlerId) => { break; case ViewReasonId.VREASON_SERVER_KICK: - message = tra("{0} was kicked from the server by {1}.{2}", data.client, data.invoker.client_name, data.message ? " (" + data.message + ")" : ""); + message = tra("{0} was kicked from the server by {1}.{2}", data.client.client_name, data.invoker.client_name, data.message ? " (" + data.message + ")" : ""); break; case ViewReasonId.VREASON_CHANNEL_KICK: - message = tra("{0} was kicked from channel {1} by {2}.{3}", data.client, data.channel_from.channel_name, data.invoker.client_name, data.message ? " (" + data.message + ")" : ""); + message = tra("{0} was kicked from channel {1} by {2}.{3}", data.client.client_name, data.channel_from.channel_name, data.invoker.client_name, data.message ? " (" + data.message + ")" : ""); break; case ViewReasonId.VREASON_BAN: diff --git a/shared/js/connectionlog/History.ts b/shared/js/connectionlog/History.ts index 54d64ea2..1aa4ec1a 100644 --- a/shared/js/connectionlog/History.ts +++ b/shared/js/connectionlog/History.ts @@ -1,5 +1,5 @@ import {LogCategory, logError, logWarn} from "tc-shared/log"; -import {tr} from "tc-shared/i18n/localize"; +import {tr, tra} from "tc-shared/i18n/localize"; import * as loader from "tc-loader"; import {Stage} from "tc-loader"; import {ConnectionHandler} from "tc-shared/ConnectionHandler"; diff --git a/shared/js/conversations/ChannelConversationManager.ts b/shared/js/conversations/ChannelConversationManager.ts index 23b8f99c..f38beea6 100644 --- a/shared/js/conversations/ChannelConversationManager.ts +++ b/shared/js/conversations/ChannelConversationManager.ts @@ -11,7 +11,7 @@ import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration"; import {ErrorCode} from "tc-shared/connection/ErrorCode"; import {LogCategory, logError, logWarn} from "tc-shared/log"; import {createErrorModal} from "tc-shared/ui/elements/Modal"; -import {traj} from "tc-shared/i18n/localize"; +import {trJQuery} from "tc-shared/i18n/localize"; import {ConnectionHandler, ConnectionState} from "tc-shared/ConnectionHandler"; import {LocalClientEntry} from "tc-shared/tree/Client"; import {ServerCommand} from "tc-shared/connection/ConnectionBase"; @@ -281,7 +281,7 @@ export class ChannelConversation extends AbstractChat error = error.extra_message || error.message; } - createErrorModal(tr("Failed to delete message"), traj("Failed to delete conversation message{:br:}Error: {}", error)).open(); + createErrorModal(tr("Failed to delete message"), trJQuery("Failed to delete conversation message{:br:}Error: {}", error)).open(); }); } diff --git a/shared/js/file/OwnAvatarStorage.ts b/shared/js/file/OwnAvatarStorage.ts index 2565a671..ca9cda6e 100644 --- a/shared/js/file/OwnAvatarStorage.ts +++ b/shared/js/file/OwnAvatarStorage.ts @@ -3,6 +3,7 @@ import {LogCategory, logError, logWarn} from "tc-shared/log"; import * as loader from "tc-loader"; import {Stage} from "tc-loader"; import * as crypto from "crypto-js"; +import {tra} from "tc-shared/i18n/localize"; export type LocalAvatarInfo = { fileName: string, diff --git a/shared/js/i18n/localize.ts b/shared/js/i18n/localize.ts index 114dc595..e53b31e2 100644 --- a/shared/js/i18n/localize.ts +++ b/shared/js/i18n/localize.ts @@ -75,9 +75,13 @@ export function tr(message: string, key?: string) : string { return translated; } -export function tra(message: string, ...args: (string | number | boolean)[]) : string; -export function tra(message: string, ...args: any[]) : JQuery[]; -export function tra(message: string, ...args: any[]) : any { +export function trJQuery(message: string, ...args: any[]) : JQuery[] { + message = /* @tr-ignore */ tr(message); + return formatMessage(message, ...args); +} + +/* We can remove our checks if we're sure that no call calls this with an object any more*/ +export function tra(message: string, ...args: (string | number | boolean)[]) : string { message = /* @tr-ignore */ tr(message); for(const element of args) { if(element === null) { @@ -92,16 +96,18 @@ export function tra(message: string, ...args: any[]) : any { continue; default: - return formatMessage(message, ...args); + debugger; + logWarn(LogCategory.GENERAL, tr("Received tra argument which isn't a string")); } } - if(message.indexOf("{:") !== -1) - return formatMessage(message, ...args); - return formatMessageString(message, ...args); -} -export function traj(message: string, ...args: any[]) : JQuery[] { - return tra(message, ...args, {}); + if(message.indexOf("{:") !== -1) { + debugger; + logWarn(LogCategory.GENERAL, tr("Received tra message which contains HTML elements")); + message = message.replace(/{:br:}/g, "\n"); + } + + return formatMessageString(message, ...args); } async function load_translation_file(url: string, path: string) : Promise { @@ -331,7 +337,7 @@ export async function initializeI18N() { logError(LogCategory.I18N, tr("Failed to initialize selected translation: %o"), error); const show_error = () => { import("../ui/elements/Modal").then(Modal => { - Modal.createErrorModal(tr("Translation System"), tra("Failed to load current selected translation file.{:br:}File: {0}{:br:}Error: {1}{:br:}{:br:}Using default fallback translations.", cfg.current_translation_url, error)).open() + Modal.createErrorModal(tr("Translation System"), tra("Failed to load current selected translation file.\nFile: {0}\nError: {1}\n\nUsing default fallback translations.", cfg.current_translation_url, error)).open() }); }; if(loader.running()) @@ -351,16 +357,12 @@ export async function initializeI18N() { declare global { interface Window { tr(message: string) : string; - tra(message: string, ...args: (string | number | boolean | null | undefined)[]) : string; - tra(message: string, ...args: any[]) : JQuery[]; log: any; StaticSettings: any; } const tr: typeof window.tr; - const tra: typeof window.tra; } -window.tr = tr; -window.tra = tra; \ No newline at end of file +window.tr = tr; \ No newline at end of file diff --git a/shared/js/media/Video.ts b/shared/js/media/Video.ts index b041c5aa..b41cc062 100644 --- a/shared/js/media/Video.ts +++ b/shared/js/media/Video.ts @@ -10,7 +10,7 @@ import {Registry} from "tc-shared/events"; import {InputStartError} from "tc-shared/voice/RecorderBase"; import {LogCategory, logDebug, logError, logWarn} from "tc-shared/log"; import {queryMediaPermissions, requestMediaStream, stopMediaStream} from "tc-shared/media/Stream"; -import {tr} from "tc-shared/i18n/localize"; +import {tr, tra} from "tc-shared/i18n/localize"; declare global { interface MediaDevices { diff --git a/shared/js/music/PlaylistManager.ts b/shared/js/music/PlaylistManager.ts index f3551c30..1f56c7cf 100644 --- a/shared/js/music/PlaylistManager.ts +++ b/shared/js/music/PlaylistManager.ts @@ -4,6 +4,7 @@ import {Registry} from "tc-shared/events"; import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration"; import {ErrorCode} from "tc-shared/connection/ErrorCode"; import _ = require("lodash"); +import {tra} from "tc-shared/i18n/localize"; export type PlaylistEntry = { type: "song", diff --git a/shared/js/text/bbcode/InviteController.ts b/shared/js/text/bbcode/InviteController.ts index 7b7a9862..93d2043c 100644 --- a/shared/js/text/bbcode/InviteController.ts +++ b/shared/js/text/bbcode/InviteController.ts @@ -6,6 +6,7 @@ import {LogCategory, logError} from "tc-shared/log"; import {clientServiceInvite, clientServices} from "tc-shared/clientservice"; import {handleConnectRequest} from "tc-shared/main"; import {assertMainApplication} from "tc-shared/ui/utils"; +import {tra} from "tc-shared/i18n/localize"; assertMainApplication(); diff --git a/shared/js/text/bbcode/YoutubeRenderer.tsx b/shared/js/text/bbcode/YoutubeRenderer.tsx index 6d0c1904..fcf674f0 100644 --- a/shared/js/text/bbcode/YoutubeRenderer.tsx +++ b/shared/js/text/bbcode/YoutubeRenderer.tsx @@ -11,6 +11,7 @@ import {useContext} from "react"; import * as contextmenu from "tc-shared/ui/elements/ContextMenu"; import IconPlay from "./YoutubePlayButton.svg"; +import {tra} from "tc-shared/i18n/localize"; const cssStyle = require("./YoutubeRenderer.scss"); const patternYtVideoId = /^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^?&"'>]{10,11})$/; diff --git a/shared/js/ui/frames/chat.ts b/shared/js/ui/frames/chat.ts index 442bf7b8..6e5122af 100644 --- a/shared/js/ui/frames/chat.ts +++ b/shared/js/ui/frames/chat.ts @@ -94,7 +94,7 @@ export function formatMessage(pattern: string, ...objects: any[]) : JQuery[] { return result; } -export function formatMessageString(pattern: string, ...args: string[]) : string { +export function formatMessageString(pattern: string, ...args: (string | number | boolean)[]) : string { return parseMessageWithArguments(pattern, args.length).map(e => typeof e === "string" ? e : args[e]).join(""); } diff --git a/shared/js/ui/frames/side/ClientInfoController.ts b/shared/js/ui/frames/side/ClientInfoController.ts index f4dfd5bd..6f533343 100644 --- a/shared/js/ui/frames/side/ClientInfoController.ts +++ b/shared/js/ui/frames/side/ClientInfoController.ts @@ -4,6 +4,7 @@ import {ClientGroupInfo, ClientInfoEvents, InheritedChannelInfo,} from "tc-share import {Registry} from "tc-shared/events"; import {openClientInfo} from "tc-shared/ui/modal/ModalClientInfo"; import {spawnAvatarUpload} from "tc-shared/ui/modal/avatar-upload/Controller"; +import {tra} from "tc-shared/i18n/localize"; export class ClientInfoController { private readonly uiEvents: Registry; diff --git a/shared/js/ui/frames/side/ClientInfoRenderer.tsx b/shared/js/ui/frames/side/ClientInfoRenderer.tsx index fbfa4153..de584b33 100644 --- a/shared/js/ui/frames/side/ClientInfoRenderer.tsx +++ b/shared/js/ui/frames/side/ClientInfoRenderer.tsx @@ -16,7 +16,7 @@ import {ClientAvatar, getGlobalAvatarManagerFactory} from "tc-shared/file/Avatar import {AvatarRenderer} from "tc-shared/ui/react-elements/Avatar"; import {Translatable} from "tc-shared/ui/react-elements/i18n"; import {LoadingDots} from "tc-shared/ui/react-elements/LoadingDots"; -import {ChannelTag, ClientTag} from "tc-shared/ui/tree/EntryTags"; +import {ClientTag} from "tc-shared/ui/tree/EntryTags"; import {guid} from "tc-shared/crypto/uid"; import {useDependentState} from "tc-shared/ui/react-elements/Helper"; import {format_online_time} from "tc-shared/utils/TimeUtils"; @@ -25,7 +25,8 @@ import {ClientIconRenderer} from "tc-shared/ui/react-elements/Icons"; import {getIconManager} from "tc-shared/file/Icons"; import {RemoteIconRenderer} from "tc-shared/ui/react-elements/Icon"; import {CountryCode} from "tc-shared/ui/react-elements/CountryCode"; -import {getKeyBoard, SpecialKey} from "tc-shared/PPTListener"; +import {getKeyBoard} from "tc-shared/PPTListener"; +import {tra} from "tc-shared/i18n/localize"; const cssStyle = require("./ClientInfoRenderer.scss"); diff --git a/shared/js/ui/frames/side/HeaderController.ts b/shared/js/ui/frames/side/HeaderController.ts index 4cd817f6..5cba918b 100644 --- a/shared/js/ui/frames/side/HeaderController.ts +++ b/shared/js/ui/frames/side/HeaderController.ts @@ -7,6 +7,7 @@ import {openMusicManage} from "tc-shared/ui/modal/ModalMusicManage"; import {createErrorModal, createInputModal} from "tc-shared/ui/elements/Modal"; import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration"; import {LogCategory, logError} from "tc-shared/log"; +import {tra} from "tc-shared/i18n/localize"; const ChannelInfoUpdateProperties: (keyof ChannelProperties)[] = [ "channel_name", diff --git a/shared/js/ui/frames/side/HeaderRenderer.tsx b/shared/js/ui/frames/side/HeaderRenderer.tsx index 2253646a..51fac7a5 100644 --- a/shared/js/ui/frames/side/HeaderRenderer.tsx +++ b/shared/js/ui/frames/side/HeaderRenderer.tsx @@ -12,6 +12,7 @@ import { import {Translatable, VariadicTranslatable} from "tc-shared/ui/react-elements/i18n"; import {RemoteIconRenderer} from "tc-shared/ui/react-elements/Icon"; import {getIconManager} from "tc-shared/file/Icons"; +import {tra} from "tc-shared/i18n/localize"; const StateContext = React.createContext(undefined); const EventsContext = React.createContext>(undefined); diff --git a/shared/js/ui/frames/side/MusicPlaylistController.ts b/shared/js/ui/frames/side/MusicPlaylistController.ts index 92434da4..d6092b0b 100644 --- a/shared/js/ui/frames/side/MusicPlaylistController.ts +++ b/shared/js/ui/frames/side/MusicPlaylistController.ts @@ -4,6 +4,7 @@ import {MusicPlaylistStatus, MusicPlaylistUiEvents} from "tc-shared/ui/frames/si import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration"; import {LogCategory, logError} from "tc-shared/log"; import {createErrorModal} from "tc-shared/ui/elements/Modal"; +import {tra} from "tc-shared/i18n/localize"; export class MusicPlaylistController { readonly uiEvents: Registry; diff --git a/shared/js/ui/frames/video/Controller.ts b/shared/js/ui/frames/video/Controller.ts index 04f1d9e6..a65c81f8 100644 --- a/shared/js/ui/frames/video/Controller.ts +++ b/shared/js/ui/frames/video/Controller.ts @@ -18,7 +18,7 @@ import { } from "tc-shared/connection/VideoConnection"; import {ClientEntry, ClientType, LocalClientEntry, MusicClientEntry} from "tc-shared/tree/Client"; import {LogCategory, logError, logWarn} from "tc-shared/log"; -import {tr} from "tc-shared/i18n/localize"; +import {tr, tra} from "tc-shared/i18n/localize"; import {Settings, settings} from "tc-shared/settings"; import * as _ from "lodash"; import PermissionType from "tc-shared/permission/PermissionType"; diff --git a/shared/js/ui/modal/ModalGroupCreate.tsx b/shared/js/ui/modal/ModalGroupCreate.tsx index ed08021f..a1449d60 100644 --- a/shared/js/ui/modal/ModalGroupCreate.tsx +++ b/shared/js/ui/modal/ModalGroupCreate.tsx @@ -345,7 +345,7 @@ function initializeGroupCreateController(connection: ConnectionHandler, events: }).catch(error => { if(error instanceof CommandResult && error.id === ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) { createErrorModal(tr("Failed to create group"), - tra("Failed to create group.\nMissing permission {}", connection.permissions.resolveInfo(parseInt(error.json["failed_permid"]))?.name || tr("unknwon"))).open(); + tra("Failed to create group.\nMissing permission {}", connection.permissions.getFailedPermission(error))).open(); return; } diff --git a/shared/js/ui/modal/ModalIconSelect.ts b/shared/js/ui/modal/ModalIconSelect.ts index 1b7cb728..a2e05715 100644 --- a/shared/js/ui/modal/ModalIconSelect.ts +++ b/shared/js/ui/modal/ModalIconSelect.ts @@ -3,7 +3,7 @@ import PermissionType from "../../permission/PermissionType"; import {createErrorModal, createModal} from "../../ui/elements/Modal"; import {LogCategory, logError, logInfo, logWarn} from "../../log"; import {CommandResult} from "../../connection/ServerConnectionDeclaration"; -import {tra, traj} from "../../i18n/localize"; +import {tra, trJQuery} from "../../i18n/localize"; import {arrayBufferBase64} from "../../utils/buffers"; import * as crc32 from "../../crypto/crc32"; import {FileInfo} from "../../file/FileManager"; @@ -285,13 +285,13 @@ function handle_icon_upload(file: File, client: ConnectionHandler): UploadingIco } catch (error) { logInfo(LogCategory.GENERAL, "Image failed to load (%o)", error); logError(LogCategory.GENERAL, tr("Failed to load file %s: Image failed to load"), file.name); - createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.{:br:}Failed to load image", file.name)).open(); + createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.\nFailed to load image", file.name)).open(); icon.state = "error"; } const width_error = message => { logError(LogCategory.GENERAL, tr("Failed to load file %s: Invalid bounds: %s"), file.name, message); - createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.{:br:}Image is too large ({})", file.name, message)).open(); + createErrorModal(tr("Icon upload failed"), tra("Failed to upload icon {}.\nImage is too large ({})", file.name, message)).open(); icon.state = "error"; }; @@ -469,7 +469,7 @@ export function spawnIconUpload(client: ConnectionHandler) { const update_upload_button = () => { const icon_count = icons.filter(e => e.state === "valid").length; button_upload.empty(); - traj("Upload icons ({})", icon_count).forEach(e => e.appendTo(button_upload)); + trJQuery("Upload icons ({})", icon_count).forEach(e => e.appendTo(button_upload)); button_upload.prop("disabled", icon_count == 0); }; update_upload_button(); diff --git a/shared/js/ui/modal/ModalMusicManage.ts b/shared/js/ui/modal/ModalMusicManage.ts index 35d5d88a..ab25f82f 100644 --- a/shared/js/ui/modal/ModalMusicManage.ts +++ b/shared/js/ui/modal/ModalMusicManage.ts @@ -1619,7 +1619,7 @@ function build_permission_container(event_registry: Registry, tag: last_sync_value = event.value; } else if (event.status === "error") { if (typeof last_sync_value === "number") input.val(last_sync_value); - createErrorModal(tr("Failed to change permission"), tra("Failed to change permission:{:br:}{}", event.error_msg)).open(); + createErrorModal(tr("Failed to change permission"), tra("Failed to change permission:\n{}", event.error_msg)).open(); } }); @@ -1977,7 +1977,7 @@ function build_permission_container(event_registry: Registry, tag: last_sync_value = event.value; } else if (event.status === "error") { if (typeof last_sync_value === "number") input.val(last_sync_value); - createErrorModal(tr("Failed to change permission"), tra("Failed to change permission:{:br:}{}", event.error_msg)).open(); + createErrorModal(tr("Failed to change permission"), tra("Failed to change permission:\n{}", event.error_msg)).open(); } hide_indicator = false; update_indicator(); diff --git a/shared/js/ui/modal/ModalServerInfoBandwidth.ts b/shared/js/ui/modal/ModalServerInfoBandwidth.ts deleted file mode 100644 index 03e7e414..00000000 --- a/shared/js/ui/modal/ModalServerInfoBandwidth.ts +++ /dev/null @@ -1,192 +0,0 @@ -import {ServerConnectionInfo, ServerEntry} from "../../tree/Server"; -import {createModal, Modal} from "../../ui/elements/Modal"; -import {CommandResult} from "../../connection/ServerConnectionDeclaration"; -import {Graph} from "../../ui/elements/NetGraph"; -import * as tooltip from "../../ui/elements/Tooltip"; -import {network} from "../../ui/frames/chat"; -import {ErrorCode} from "../../connection/ErrorCode"; -import {tr} from "tc-shared/i18n/localize"; - -export enum RequestInfoStatus { - SUCCESS, - UNKNOWN, - NO_PERMISSION -} -export type ServerBandwidthInfoUpdateCallback = (status: RequestInfoStatus, info?: ServerConnectionInfo) => any; -export function openServerInfoBandwidth(server: ServerEntry, update_callbacks?: ServerBandwidthInfoUpdateCallback[]) : Modal { - let modal: Modal; - let own_callbacks = !update_callbacks; - update_callbacks = update_callbacks || []; - - modal = createModal({ - header: tr("Server bandwidth data"), - body: () => { - const template = $("#tmpl_server_info_bandwidth").renderTag(); - - const children = template.children(); - initialize_current_bandwidth(modal, children.find(".statistic-bandwidth"), update_callbacks); - initialize_ft_bandwidth(modal, children.find(".statistic-ft-bandwidth"), update_callbacks); - initialize_general(template.find(".top"), update_callbacks); - - tooltip.initialize(template); - return template.children(); - }, - footer: null, - min_width: "25em" - }); - - if(own_callbacks) { - const updater = setInterval(() => { - server.request_connection_info().then(info => update_callbacks.forEach(e => e(RequestInfoStatus.SUCCESS, info))).catch(error => { - if(error instanceof CommandResult && error.id == ErrorCode.SERVER_INSUFFICIENT_PERMISSIONS) { - update_callbacks.forEach(e => e(RequestInfoStatus.NO_PERMISSION)); - return; - } - update_callbacks.forEach(e => e(RequestInfoStatus.UNKNOWN)); - }); - }, 1000); - modal.close_listener.push(() => clearInterval(updater)); - } - - - modal.htmlTag.find(".button-close").on('click', event => modal.close()); - modal.htmlTag.find(".modal-body").addClass("modal-server-info-bandwidth"); - modal.open(); - return modal; -} - -function initialize_graph(modal: Modal, tag: JQuery, callbacks: ServerBandwidthInfoUpdateCallback[], fields: {uplaod: string, download: string}) { - const canvas = tag.find("canvas")[0] as HTMLCanvasElement; - const label_upload = tag.find(".upload"); - const label_download = tag.find(".download"); - let last_info: { status: RequestInfoStatus, info: ServerConnectionInfo }; - let custom_info = false; - - const show_info = (upload: number | undefined, download: number | undefined) => { - let fallback_text = last_info && last_info.status === RequestInfoStatus.NO_PERMISSION ? tr("No permission") : tr("receiving..."); - - if(typeof upload !== "number") - upload = last_info ? last_info[fields.uplaod] : undefined; - - if(typeof download !== "number") - download = last_info ? last_info[fields.download] : undefined; - - if(typeof upload !== "number") - label_upload.text(fallback_text); - else - label_upload.text(network.format_bytes(upload, {unit: "Bytes", time: "s", exact: false})); - - if(typeof download !== "number") - label_download.text(fallback_text); - else - label_download.text(network.format_bytes(download, {unit: "Bytes", time: "s", exact: false})); - }; - show_info(undefined, undefined); - - const graph = new Graph(); - graph.initializeCanvas(canvas); - graph.pushEntry({ timestamp: Date.now(), upload: undefined, download: undefined}); - callbacks.push((status, values) => { - last_info = {status: status, info: values}; - - if(!values) { - graph.pushEntry({ timestamp: Date.now(), upload: undefined, download: undefined}); - } else { - graph.pushEntry({ - timestamp: Date.now(), - download: values[fields.download], //values.connection_bandwidth_received_last_second_total, - upload: values[fields.uplaod], //values.connection_bandwidth_sent_last_second_total - }); - } - - /* set that we want to show the entry within one second */ - graph.timeSpan.origin = Object.assign(graph.calculateTimespan(), { time: Date.now() }); - graph.timeSpan.target = { - begin: Date.now() - 120 * 1000, - end: Date.now(), - time: Date.now() + 200 - }; - - graph.cleanup(); - if(!custom_info) { - show_info(undefined, undefined); - graph.resize(); /* just to ensure (we have to rethink this maybe; cause it causes a recalculates the style */ - } - }); - - graph.maxGapSize(0); - graph.initialize(); - - graph.callbackDetailedHide = () => { - custom_info = false; - show_info(undefined, undefined); - }; - - graph.callbackDetailedInfo = (upload, download, timestamp, event) => { - custom_info = true; - show_info(upload, download); - }; - - modal.close_listener.push(() => graph.finalize()); - modal.open_listener.push(() => graph.resize()); - - tag.addClass("window-resize-listener").on('resize', event => graph.resize()); -} - -function initialize_current_bandwidth(modal: Modal, tag: JQuery, callbacks: ServerBandwidthInfoUpdateCallback[]) { - initialize_graph(modal, tag, callbacks, { - uplaod: "connection_bandwidth_sent_last_second_total", - download: "connection_bandwidth_received_last_second_total" - }); -} - -function initialize_ft_bandwidth(modal: Modal, tag: JQuery, callbacks: ServerBandwidthInfoUpdateCallback[]) { - initialize_graph(modal, tag, callbacks, { - uplaod: "connection_filetransfer_bandwidth_sent", - download: "connection_filetransfer_bandwidth_received" - }); -} - -function initialize_general(tag: JQuery, callbacks: ServerBandwidthInfoUpdateCallback[]) { - const tag_packets_upload = tag.find(".statistic-packets .upload"); - const tag_packets_download = tag.find(".statistic-packets .download"); - - const tag_bytes_upload = tag.find(".statistic-bytes .upload"); - const tag_bytes_download = tag.find(".statistic-bytes .download"); - - const tag_ft_bytes_upload = tag.find(".statistic-ft-bytes .upload"); - const tag_ft_bytes_download = tag.find(".statistic-ft-bytes .download"); - - const update = (tag, value: undefined | null | number) => { - if(typeof value === "undefined") - tag.text(tr("receiving...")); - else if(value === null) - tag.text(tr("no permissions")); - else - tag.text(network.format_bytes(value, {unit: "Bytes", exact: false})); - }; - - const props = [ - {tag: tag_packets_download, property: "connection_packets_received_total"}, - {tag: tag_packets_upload, property: "connection_packets_sent_total"}, - - {tag: tag_bytes_download, property: "connection_bytes_received_total"}, - {tag: tag_bytes_upload, property: "connection_bytes_sent_total"}, - - {tag: tag_ft_bytes_upload, property: "connection_filetransfer_bytes_received_total"}, - {tag: tag_ft_bytes_download, property: "connection_filetransfer_bytes_sent_total"}, - ]; - - callbacks.push((status, info) => { - if(status === RequestInfoStatus.SUCCESS) { - for(const entry of props) - update(entry.tag, info[entry.property]); - } else if(status === RequestInfoStatus.NO_PERMISSION) { - for(const entry of props) - update(entry.tag, null); - } else { - for(const entry of props) - update(entry.tag, undefined); - } - }); -} \ No newline at end of file diff --git a/shared/js/ui/modal/avatar-upload/Controller.ts b/shared/js/ui/modal/avatar-upload/Controller.ts index be9379ee..d8753be7 100644 --- a/shared/js/ui/modal/avatar-upload/Controller.ts +++ b/shared/js/ui/modal/avatar-upload/Controller.ts @@ -8,7 +8,7 @@ import PermissionType from "tc-shared/permission/PermissionType"; import {getOwnAvatarStorage, LocalAvatarInfo} from "tc-shared/file/OwnAvatarStorage"; import {LogCategory, logError, logInfo, logWarn} from "tc-shared/log"; import {Mutex} from "tc-shared/Mutex"; -import {tr, traj} from "tc-shared/i18n/localize"; +import {tr, trJQuery} from "tc-shared/i18n/localize"; import {createErrorModal, createInfoModal} from "tc-shared/ui/elements/Modal"; import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration"; import {formatMessage} from "tc-shared/ui/frames/chat"; @@ -211,11 +211,11 @@ class Controller { let message; if(error instanceof CommandResult) { - message = formatMessage(tr("Failed to delete avatar.{:br:}Error: {0}"), error.formattedMessage()); + message = formatMessage(tr("Failed to delete avatar.\nError: {0}"), error.formattedMessage()); } if(!message) { - message = formatMessage(tr("Failed to delete avatar.{:br:}Lookup the console for more details")); + message = formatMessage(tr("Failed to delete avatar.\nLookup the console for more details")); } createErrorModal(tr("Failed to delete avatar"), message).open(); @@ -262,7 +262,7 @@ class Controller { if (transfer.transferState() !== FileTransferState.FINISHED) { if (transfer.transferState() === FileTransferState.ERRORED) { logWarn(LogCategory.FILE_TRANSFER, tr("Failed to upload clients avatar: %o"), transfer.currentError()); - createErrorModal(tr("Failed to upload avatar"), traj("Failed to upload avatar:{:br:}{0}", transfer.currentErrorMessage())).open(); + createErrorModal(tr("Failed to upload avatar"), tr("Failed to upload avatar:\n{0}", transfer.currentErrorMessage())).open(); return; } else if (transfer.transferState() === FileTransferState.CANCELED) { createErrorModal(tr("Failed to upload avatar"), tr("Your avatar upload has been canceled.")).open(); @@ -287,11 +287,11 @@ class Controller { let message; if(error instanceof CommandResult) { - message = formatMessage(tr("Failed to update avatar flag.{:br:}Error: {0}"), error.formattedMessage()); + message = formatMessage(tr("Failed to update avatar flag.\nError: {0}"), error.formattedMessage()); } if(!message) { - message = formatMessage(tr("Failed to update avatar flag.{:br:}Lookup the console for more details")); + message = formatMessage(tr("Failed to update avatar flag.\nLookup the console for more details")); } createErrorModal(tr("Failed to set avatar"), message).open(); diff --git a/shared/js/ui/modal/avatar-upload/Renderer.tsx b/shared/js/ui/modal/avatar-upload/Renderer.tsx index 9b134b27..5cd38d33 100644 --- a/shared/js/ui/modal/avatar-upload/Renderer.tsx +++ b/shared/js/ui/modal/avatar-upload/Renderer.tsx @@ -19,6 +19,7 @@ import {joinClassList, useDependentState} from "tc-shared/ui/react-elements/Help import kDefaultAvatarUrl from "../../../../img/style/avatar.png"; import byteSizeToString = network.binarySizeToString; +import {tra} from "tc-shared/i18n/localize"; const ServerUniqueIdContext = React.createContext(undefined); const EventContext = React.createContext>(undefined); @@ -294,7 +295,7 @@ class ModalAvatarUpload extends AbstractModal { createErrorModal(tr("Failed to load avatar"), tra("Failed to load avatar: {}", result.reason)).open(); succeeded = false; } else if(result.status === "cache-unavailable") { - createErrorModal(tr("Failed to load avatar"), tra("Failed to load avatar:{:br:}Own avatar cach unavailable.")).open(); + createErrorModal(tr("Failed to load avatar"), tra("Failed to load avatar:{:br:}Own avatar cache unavailable.")).open(); succeeded = false; } else { succeeded = false; diff --git a/shared/js/ui/modal/input-processor/Renderer.tsx b/shared/js/ui/modal/input-processor/Renderer.tsx index c8d8bb8b..3dc06369 100644 --- a/shared/js/ui/modal/input-processor/Renderer.tsx +++ b/shared/js/ui/modal/input-processor/Renderer.tsx @@ -10,7 +10,7 @@ import {joinClassList, useTr} from "tc-shared/ui/react-elements/Helper"; import {Checkbox} from "tc-shared/ui/react-elements/Checkbox"; import {ControlledBoxedInputField, ControlledSelect} from "tc-shared/ui/react-elements/InputField"; import {createErrorModal} from "tc-shared/ui/elements/Modal"; -import {traj} from "tc-shared/i18n/localize"; +import {tr, tra} from "tc-shared/i18n/localize"; const cssStyle = require("./Renderer.scss"); const EventContext = React.createContext>(undefined); @@ -382,7 +382,7 @@ class Modal extends AbstractModal { this.variables = createIpcUiVariableConsumer(variables); this.events.on("notify_apply_error", event => { - createErrorModal(tr("Failed to apply changes"), traj("Failed to apply changes:{:br:}{}", event.message)).open(); + createErrorModal(tr("Failed to apply changes"), tra("Failed to apply changes:\n{}", event.message)).open(); }) } diff --git a/shared/js/ui/modal/permission/ModalController.ts b/shared/js/ui/modal/permission/ModalController.ts index 7408355d..f4d70387 100644 --- a/shared/js/ui/modal/permission/ModalController.ts +++ b/shared/js/ui/modal/permission/ModalController.ts @@ -86,7 +86,7 @@ export function spawnPermissionEditorModal(connection: ConnectionHandler, defaul function initializePermissionModalResultHandlers(events: Registry) { events.on("action_rename_group_result", event => { if (event.status === "error") { - createErrorModal(tr("Failed to rename group"), formatMessage(tr("Failed to rename group:{:br:}"), event.error)).open(); + createErrorModal(tr("Failed to rename group"), formatMessage(tra("Failed to rename group:\n{}", event.error))).open(); } else { createInfoModal(tr("Group renamed"), tr("The group has been renamed.")).open(); } diff --git a/shared/js/ui/modal/server-info/Controller.ts b/shared/js/ui/modal/server-info/Controller.ts index 0646d648..155834ea 100644 --- a/shared/js/ui/modal/server-info/Controller.ts +++ b/shared/js/ui/modal/server-info/Controller.ts @@ -6,7 +6,6 @@ import {CallOnce, ignorePromise} from "tc-shared/proto"; import {spawnModal} from "tc-shared/ui/react-elements/modal"; import {ServerConnectionInfoResult, ServerProperties} from "tc-shared/tree/Server"; import {LogCategory, logWarn} from "tc-shared/log"; -import {openServerInfoBandwidth} from "tc-shared/ui/modal/ModalServerInfoBandwidth"; import {spawnServerBandwidth} from "tc-shared/ui/modal/server-bandwidth/Controller"; const kPropertyUpdateMatrix: {[T in keyof ServerProperties]?: [keyof ModalServerInfoVariables]} = { diff --git a/shared/js/ui/modal/settings/Keymap.tsx b/shared/js/ui/modal/settings/Keymap.tsx index 8f696d35..66b3bf36 100644 --- a/shared/js/ui/modal/settings/Keymap.tsx +++ b/shared/js/ui/modal/settings/Keymap.tsx @@ -189,7 +189,7 @@ class KeyActionEntry extends ReactComponentBase>(undefined); diff --git a/shared/js/ui/modal/transfer/FileBrowserControllerRemote.ts b/shared/js/ui/modal/transfer/FileBrowserControllerRemote.ts index 78da1b78..dff92f5e 100644 --- a/shared/js/ui/modal/transfer/FileBrowserControllerRemote.ts +++ b/shared/js/ui/modal/transfer/FileBrowserControllerRemote.ts @@ -7,7 +7,7 @@ import {LogCategory, logError, logTrace} from "../../../log"; import {Entry, MenuEntry, MenuEntryType, spawn_context_menu} from "../../../ui/elements/ContextMenu"; import {getKeyBoard, SpecialKey} from "../../../PPTListener"; import {spawnYesNo} from "../../../ui/modal/ModalYesNo"; -import {tr, tra, traj} from "../../../i18n/localize"; +import {tr, tra} from "../../../i18n/localize"; import { FileTransfer, FileTransferState, @@ -708,7 +708,7 @@ export function initializeRemoteFileBrowserController(connection: ConnectionHand }); transfer.awaitFinished().then(() => { if (transfer.transferState() === FileTransferState.ERRORED) { - createErrorModal(tr("Failed to download file"), traj("Failed to download {0}:{:br:}{1}", fileName, transfer.currentErrorMessage())).open(); + createErrorModal(tr("Failed to download file"), tra("Failed to download {0}:\n{1}", fileName, transfer.currentErrorMessage())).open(); } }); } catch (error) { @@ -739,7 +739,7 @@ export function initializeRemoteFileBrowserController(connection: ConnectionHand } else if (event.mode === "files") { const pathInfo = parsePath(event.path, connection); if (pathInfo.type !== "channel") { - createErrorModal(tr("Failed to upload file(s)"), tra("Failed to upload files:{:br:}File uplaod is only supported in channel directories")).open(); + createErrorModal(tr("Failed to upload file(s)"), tra("Failed to upload files:\nFile uplaod is only supported in channel directories")).open(); return; } for (const file of event.files) { @@ -753,7 +753,7 @@ export function initializeRemoteFileBrowserController(connection: ConnectionHand }); transfer.awaitFinished().then(() => { if (transfer.transferState() === FileTransferState.ERRORED) { - createErrorModal(tr("Failed to upload file"), tra("Failed to upload {0}:{:br:}{1}", fileName, transfer.currentErrorMessage())).open(); + createErrorModal(tr("Failed to upload file"), tra("Failed to upload {0}:\n{1}", fileName, transfer.currentErrorMessage())).open(); } }); } diff --git a/shared/js/ui/modal/transfer/FileBrowserRenderer.tsx b/shared/js/ui/modal/transfer/FileBrowserRenderer.tsx index 91afb170..70b86779 100644 --- a/shared/js/ui/modal/transfer/FileBrowserRenderer.tsx +++ b/shared/js/ui/modal/transfer/FileBrowserRenderer.tsx @@ -321,9 +321,9 @@ export class NavigationBar extends ReactComponentBase { } else { setFileName(props.file.name); if (event.status === "timeout") { - createErrorModal(tr("Failed to rename file"), tra("Failed to rename file.{:br:}Action resulted in a timeout.")).open(); + createErrorModal(tr("Failed to rename file"), tra("Failed to rename file.\nAction resulted in a timeout.")).open(); } else { - createErrorModal(tr("Failed to rename file"), tra("Failed to rename file:{:br:}{0}", event.error)).open(); + createErrorModal(tr("Failed to rename file"), tra("Failed to rename file:\n{0}", event.error)).open(); } } }); @@ -1306,7 +1306,7 @@ export class FileBrowserRenderer extends ReactComponentBase { + /* Having these checks because tra(..) still might return jQuery */ + if(typeof properties.title !== "string") { + debugger; + throw "yes-no title isn't a string"; + } + + if(typeof properties.question !== "string") { + debugger; + throw "yes-no question isn't a string"; + } + + return false; +} \ No newline at end of file diff --git a/shared/js/ui/react-elements/Tab.tsx b/shared/js/ui/react-elements/Tab.tsx index 37075377..9a02e2d9 100644 --- a/shared/js/ui/react-elements/Tab.tsx +++ b/shared/js/ui/react-elements/Tab.tsx @@ -1,4 +1,5 @@ import * as React from "react"; +import {tra} from "tc-shared/i18n/localize"; const cssStyle = require("./Tab.scss"); diff --git a/shared/js/ui/react-elements/modal/external/renderer/EntryPoint.ts b/shared/js/ui/react-elements/modal/external/renderer/EntryPoint.ts index 7b9ec12d..617f9857 100644 --- a/shared/js/ui/react-elements/modal/external/renderer/EntryPoint.ts +++ b/shared/js/ui/react-elements/modal/external/renderer/EntryPoint.ts @@ -1,6 +1,6 @@ import * as loader from "tc-loader"; import {setupIpcHandler} from "tc-shared/ipc/BrowserIPC"; -import {initializeI18N} from "tc-shared/i18n/localize"; +import {initializeI18N, tra} from "tc-shared/i18n/localize"; import {Stage} from "tc-loader"; import {AbstractModal, constructAbstractModalClass} from "tc-shared/ui/react-elements/modal/Definitions"; import {AppParameters, Settings, settings} from "tc-shared/settings"; diff --git a/shared/js/ui/tree/DragHelper.ts b/shared/js/ui/tree/DragHelper.ts index d606d09f..6ef82353 100644 --- a/shared/js/ui/tree/DragHelper.ts +++ b/shared/js/ui/tree/DragHelper.ts @@ -9,6 +9,7 @@ import { } from "svg-sprites/client-icons"; import {LogCategory, logDebug} from "tc-shared/log"; import {ChannelTreeDragData, ChannelTreeDragEntry} from "tc-shared/ui/tree/Definitions"; +import {tra} from "tc-shared/i18n/localize"; let spriteImage: HTMLImageElement; diff --git a/shared/js/ui/utils/Variable.ts b/shared/js/ui/utils/Variable.ts index 38674b41..7e0edacf 100644 --- a/shared/js/ui/utils/Variable.ts +++ b/shared/js/ui/utils/Variable.ts @@ -2,6 +2,7 @@ import {useEffect, useState} from "react"; import * as _ from "lodash"; import {ReadonlyKeys, WritableKeys} from "tc-shared/proto"; import {useDependentState} from "tc-shared/ui/react-elements/Helper"; +import {tra} from "tc-shared/i18n/localize"; /* * To deliver optimized performance, we only promisify the values we need. @@ -71,7 +72,7 @@ export abstract class UiVariableProvider { sendVariable(variable: T, customData?: any, forceSend?: boolean) : void | Promise { const providers = this.variableProvider[variable as any]; if(!providers) { - throw tra("missing provider for {}", variable); + throw tra("missing provider for {}", variable as string); } const result = providers(customData); @@ -98,7 +99,7 @@ export abstract class UiVariableProvider { async getVariable(variable: T, customData?: any, ignoreCache?: boolean) : Promise { const providers = this.variableProvider[variable as any]; if(!providers) { - throw tra("missing provider for {}", variable); + throw tra("missing provider for {}", variable as string); } const result = providers(customData);