diff --git a/bbb-client-check/src/org/bigbluebutton/clientcheck/service/RTMPTunnelingService.as b/bbb-client-check/src/org/bigbluebutton/clientcheck/service/RTMPTunnelingService.as index a3e6803fc663bb4b09feae4ec2d5079b555f117e..30d5921ad8f502c60f50bbc5a55cd2004beb9d12 100644 --- a/bbb-client-check/src/org/bigbluebutton/clientcheck/service/RTMPTunnelingService.as +++ b/bbb-client-check/src/org/bigbluebutton/clientcheck/service/RTMPTunnelingService.as @@ -43,6 +43,7 @@ package org.bigbluebutton.clientcheck.service private static var RECORD_MOCK:Boolean=false; private static var EXTERNAL_USER_ID_MOCK:String="123456"; private static var INTERNAL_USER_ID_MOCK:String="654321"; + private static var CLIENT_CONN_ID:String="client-conn-id"; private static var LOCK_ON_MOCK:Boolean=true; public function init():void @@ -60,7 +61,7 @@ package org.bigbluebutton.clientcheck.service // sip has a different way of connecting to the red5 server, need to fake connection data. if (systemConfiguration.rtmpApps[i].applicationUri.indexOf("sip") > 0) { - _netConnection.connect(systemConfiguration.rtmpApps[i].applicationUri, ROOM_MOCK, EXTERNAL_USER_ID_MOCK, USER_NAME_MOCK, INTERNAL_USER_ID_MOCK); + _netConnection.connect(systemConfiguration.rtmpApps[i].applicationUri, ROOM_MOCK, EXTERNAL_USER_ID_MOCK, USER_NAME_MOCK, INTERNAL_USER_ID_MOCK, CLIENT_CONN_ID); continue; } else diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/Application.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/Application.java index 7521484f37852933891144bfdaa285266bb35561..42d7240014aeec2f69daf79c1898c616997e57c5 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/Application.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/Application.java @@ -86,7 +86,7 @@ public class Application extends MultiThreadedApplicationAdapter { public boolean appConnect(IConnection conn, Object[] params) { if(params.length != 5) { - log.error("Invalid number of parameters. param length=" + params.length); + log.error("Invalid number of parameters. Provided parameters={} .Required parameters=5", params.length); return false; } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/sounds/ScreenshareOff.mp3 b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/sounds/ScreenshareOff.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..9a64f01329ee0d8c92b7b16f331f7a3aecd46b68 Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/sounds/ScreenshareOff.mp3 differ diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ViewerWindowManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ViewerWindowManager.as index 16cfb0681833834c731d9fff50d1c70acc212ef8..939ec9f5a24e3e31f67c76f048b297e617d4a879 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ViewerWindowManager.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ViewerWindowManager.as @@ -56,6 +56,7 @@ package org.bigbluebutton.modules.screenshare.managers { LOGGER.debug("ViewerWindowManager Received stop viewing command"); if (viewWindow) { closeWindow(viewWindow); + viewWindow = null; isViewing = false; } } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/WebRTCPublishWindowManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/WebRTCPublishWindowManager.as index 9580c607bfaa4700e4ec4293719f7fcd9b7a7f9d..11cbfc36aafce8be21d022da8dd302e5a60ddbbf 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/WebRTCPublishWindowManager.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/WebRTCPublishWindowManager.as @@ -51,12 +51,11 @@ package org.bigbluebutton.modules.screenshare.managers if (shareWindow != null) shareWindow.stopSharing(); } - private function autopublishTimerHandler(event:TimerEvent):void { - shareWindow.shareScreen(true); - } - public function handleShareWindowCloseEvent():void { - closeWindow(shareWindow); + if (shareWindow) { + closeWindow(shareWindow); + shareWindow = null; + } } private function openWindow(window:IBbbModuleWindow = null):void { @@ -77,7 +76,6 @@ package org.bigbluebutton.modules.screenshare.managers var event:CloseWindowEvent = new CloseWindowEvent(CloseWindowEvent.CLOSE_WINDOW_EVENT); event.window = window; globalDispatcher.dispatchEvent(event); - shareWindow = null; } public function startSharing():void { diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/WebRTCViewerWindowManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/WebRTCViewerWindowManager.as index 37e73b854fdef8d7bb38309a0d376b77c58d28c3..b6c4a42041c6121cd1f71b05dc17d76c6ce51399 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/WebRTCViewerWindowManager.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/WebRTCViewerWindowManager.as @@ -50,8 +50,10 @@ package org.bigbluebutton.modules.screenshare.managers public function handleViewWindowCloseEvent():void { LOGGER.debug("Received close view window event"); - closeWindow(viewWindow); - isViewing = false; + if (viewWindow) { + closeWindow(viewWindow); + isViewing = false; + } } private function closeWindow(window:IBbbModuleWindow):void { diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml index 219264b853929c3c388cb7afd26f90bc7efc46f9..eaa4be18ad91c98c1f61b3910ba5ebecf8b6887b 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml @@ -107,6 +107,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. [Bindable] private var shareTypeProvider:Array; + + [Embed(source="../../assets/sounds/ScreenshareOff.mp3")] + private var noticeSoundClass:Class; + private var noticeSound:Sound = new noticeSoundClass() as Sound; + private var soundPlayed:Boolean = false; private function init():void { dsOptions = Options.getOptions(ScreenshareOptions) as ScreenshareOptions; @@ -431,6 +436,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. private function closeWindow():void { dispatchEvent(new ShareWindowEvent(ShareWindowEvent.CLOSE)); + + if (!soundPlayed) { + trace("playing from java publish window"); + var tSC:SoundChannel = noticeSound.play(0, 0, new SoundTransform(0.25)); + soundPlayed = true; + } } private function restartJava():void { diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/WebRTCDesktopPublishWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/WebRTCDesktopPublishWindow.mxml index fc87c8b734eb64be1e0edd992da1e719e5f87c20..c6805e0c7075d5fb9e341cf67032901e54f76372 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/WebRTCDesktopPublishWindow.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/WebRTCDesktopPublishWindow.mxml @@ -97,6 +97,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. private var globalDispatcher:Dispatcher = new Dispatcher(); [Bindable] private var dsOptions:ScreenshareOptions; + + [Embed(source="../../assets/sounds/ScreenshareOff.mp3")] + private var noticeSoundClass:Class; + private var noticeSound:Sound = new noticeSoundClass() as Sound; + private var soundPlayed:Boolean = false; private function displayInstall():void { setCurrentState("displayInstall"); @@ -115,9 +120,14 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. if (ExternalInterface.available) { var isIncognito:Function = function(args:Object):void { incognitoLbl.visible = true; + ExternalInterface.addCallback("isIncognito", null); + ExternalInterface.addCallback("isNotIncognito", null); }; - var isNotIncognito:Function = function(args:Object):void {}; + var isNotIncognito:Function = function(args:Object):void { + ExternalInterface.addCallback("isIncognito", null); + ExternalInterface.addCallback("isNotIncognito", null); + }; ExternalInterface.addCallback("isIncognito", isIncognito); ExternalInterface.addCallback("isNotIncognito", isNotIncognito); @@ -145,6 +155,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. ExternalInterface.addCallback("onSuccess", onSuccess); ExternalInterface.call("checkChromeExtInstalled", "onSuccess", dsOptions.chromeExtensionKey); } + + private function init():void { dsOptions = Options.getOptions(ScreenshareOptions) as ScreenshareOptions; @@ -248,24 +260,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. */ public function resetWidthAndHeight():void{/* do nothing */} - public function initWindow(connection:NetConnection, uri:String, useTLS:Boolean , room:String):void { - this.connection = connection; - this.uri = uri; - this.useTLS = useTLS; - this.room = room; - } - - public function shareScreen(fullScreen:Boolean):void { - LOGGER.debug("Calling shareScreen"); - startSharing(connection, uri, useTLS , room, fullScreen); - } - - private function startSharing(connection:NetConnection, uri:String , useTLS:Boolean , room:String, fullScreen:Boolean):void { - var captureX:Number = 0; - var captureY:Number = 0; - - } - public function stopSharing():void{ if (streaming) { stopStream(); @@ -273,7 +267,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. dispatchEvent(streamEvent); } streaming = false; - closeWindow(); + //closeWindow(); } public function stopSharingEvent(evt:StopSharingButtonEvent):void{ @@ -427,12 +421,15 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. video.y = videoHolder.y = (this.height - VID_HEIGHT_PAD - vidH) / 2; } - private function stopStream():void{ + private function stopStream():void { streaming = false; if (ns != null) { ns.close(); } + if (connection != null) { + connection.close(); + } } private function onAsyncError(e:AsyncErrorEvent):void{ @@ -479,9 +476,18 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. } private function closeWindow():void { + // Have to remove the callback so we can garbage collect + ExternalInterface.addCallback("onFail", null); + // LOGGER.debug("Calling stopApplet in closeWindow()"); dispatchEvent(new WebRTCShareWindowEvent(WebRTCShareWindowEvent.CLOSE)); - globalDispatcher.dispatchEvent(new DeskshareToolbarEvent(DeskshareToolbarEvent.STOP)); + globalDispatcher.dispatchEvent(new DeskshareToolbarEvent(DeskshareToolbarEvent.STOP)); + + if (!soundPlayed) { + trace("playing from webrtc publish window"); + var tSC:SoundChannel = noticeSound.play(0, 0, new SoundTransform(0.25)); + soundPlayed = true; + } } /* diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageReceiver.as b/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageReceiver.as index cc95493b8b7e5d36ec7ad533364ee96d7f2c9cfc..3d39fcc3f852d687f3561bdd3c318ef9d6c63c9e 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageReceiver.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageReceiver.as @@ -970,6 +970,9 @@ package org.bigbluebutton.modules.users.services if (UsersUtil.isMe(userId)) { LiveMeeting.inst().me.role = role; dispatcher.dispatchEvent(new ChangeMyRole(role)); + + // need to fake a new lock settings so that the lock state gets revalidated + UsersUtil.applyLockSettings(); } dispatcher.dispatchEvent(new UserStatusChangedEvent(userId)); diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/MediaItemRenderer.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/MediaItemRenderer.mxml index b072a08437a072cc184ffeb885e9ab836841d4a7..cca024a7915c3640497d2df3bac4713e3d30d107 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/MediaItemRenderer.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/views/MediaItemRenderer.mxml @@ -193,12 +193,13 @@ muteImg.filters = null; var ls:LockSettingsVO = UsersUtil.getLockSettings(); + var amIMod:Boolean = UsersUtil.amIModerator(); if (data != null) { var allowModeratorToSeeOwnSettings: Boolean = !data.me || (data.me && UsersUtil.amIModerator()); settingsBtn.visible = rolledOver && allowModeratorToSeeOwnSettings && !UsersUtil.isBreakout(); - if (!data.inVoiceConf) { + if ( !data.inVoiceConf || ( options.moderatorUnmute == false && amIMod && !UsersUtil.isMe(data.userId) ) ) { muteImg.visible = false; muteImg.includeInLayout = false; muteBtn.visible = false; @@ -210,7 +211,7 @@ muteImg.includeInLayout = true; muteBtn.visible = false; muteBtn.includeInLayout = false; - } else if (data.locked && ls.getDisableMic()) { + } else if (!amIMod && data.locked && ls.getDisableMic()) { muteImg.visible = true; muteImg.includeInLayout = true; muteBtn.visible = false; diff --git a/bigbluebutton-config/bin/bbb-conf b/bigbluebutton-config/bin/bbb-conf index ed13fd42c75b6dba05b124613d6dae62b4720047..394f69004cfed62a763f4ea7ea2e424b8f5fa69c 100755 --- a/bigbluebutton-config/bin/bbb-conf +++ b/bigbluebutton-config/bin/bbb-conf @@ -1792,11 +1792,12 @@ if [ -n "$HOST" ]; then # echo "Assigning $HOST for http[s]:// in /var/www/bigbluebutton/client/conf/config.xml" - chromeExtensionLinkURL=$(cat /var/www/bigbluebutton/client/conf/config.xml | sed -n '/chromeExtensionLink/{s/.*https*:\/\///;s/\/.*//;p}') - sudo sed -i "s/http[s]*:\/\/\([^\"\/]*\)\([\"\/]\)/$PROTOCOL_HTTP:\/\/$HOST\2/g" \ - /var/www/bigbluebutton/client/conf/config.xml - sudo sed -i "s/chromeExtensionLink=\"https:\/\/[^\/]*/chromeExtensionLink=\"https:\/\/$chromeExtensionLinkURL/g" \ - /var/www/bigbluebutton/client/conf/config.xml + sudo sed -i "s/http[s]*:\/\/\([^\"\/]*\)\([\"\/]\)/$PROTOCOL_HTTP:\/\/$HOST\2/g" /var/www/bigbluebutton/client/conf/config.xml + if ! echo "$chromeExtensionLinkURL" | grep -q '""'; then + sudo sed -i "s/chromeExtensionLink=\"https:\/\/[^\/]*/chromeExtensionLink=\"https:\/\/$chromeExtensionLinkURL/g" \ + /var/www/bigbluebutton/client/conf/config.xml + fi + echo "Assigning $HOST for publishURI in /var/www/bigbluebutton/client/conf/config.xml" sudo sed -i "s/publishURI=\"[^\"]*\"/publishURI=\"$HOST\"/" /var/www/bigbluebutton/client/conf/config.xml diff --git a/bigbluebutton-html5/client/main.html b/bigbluebutton-html5/client/main.html old mode 100644 new mode 100755 index f0dc4c57bcf700ca2cf6b17d49cea0595c59eb5f..732f35244c3b09cc1d724c4d45fabc4e5f371d08 --- a/bigbluebutton-html5/client/main.html +++ b/bigbluebutton-html5/client/main.html @@ -1,5 +1,5 @@ <head> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <style> html { box-sizing: border-box; diff --git a/bigbluebutton-html5/imports/api/audio/client/bridge/base.js b/bigbluebutton-html5/imports/api/audio/client/bridge/base.js old mode 100644 new mode 100755 index 69e256274f1c44a6468168fb41d85cba8b4c352f..a9c63969a29328327d4ad2cd06a1ec4e2b1ffbf6 --- a/bigbluebutton-html5/imports/api/audio/client/bridge/base.js +++ b/bigbluebutton-html5/imports/api/audio/client/bridge/base.js @@ -8,6 +8,8 @@ export default class BaseAudioBridge { REQUEST_TIMEOUT: 'REQUEST_TIMEOUT', GENERIC_ERROR: 'GENERIC_ERROR', MEDIA_ERROR: 'MEDIA_ERROR', + WEBRTC_NOT_SUPPORTED: 'WEBRTC_NOT_SUPPORTED', + ICE_NEGOTIATION_FAILED: 'ICE_NEGOTIATION_FAILED', }; this.baseCallStates = { diff --git a/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js b/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js old mode 100644 new mode 100755 index b3678cf46e202799604746a74bb15058ee2a2b9c..e16be8fdc569844e32fd73ca918d947206076aa4 --- a/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js +++ b/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js @@ -9,6 +9,7 @@ const MEDIA_TAG = MEDIA.mediaTag; const CALL_TRANSFER_TIMEOUT = MEDIA.callTransferTimeout; const CALL_HANGUP_TIMEOUT = MEDIA.callHangupTimeout; const CALL_HANGUP_MAX_RETRIES = MEDIA.callHangupMaximumRetries; +const CONNECTION_TERMINATED_EVENTS = ['iceConnectionFailed', 'iceConnectionClosed']; const fetchStunTurnServers = (sessionToken) => { const handleStunTurnResponse = ({ stunServers, turnServers }) => { @@ -76,6 +77,20 @@ export default class SIPBridge extends BaseAudioBridge { [causes.REQUEST_TIMEOUT]: this.baseErrorCodes.REQUEST_TIMEOUT, [causes.INVALID_TARGET]: this.baseErrorCodes.INVALID_TARGET, [causes.CONNECTION_ERROR]: this.baseErrorCodes.CONNECTION_ERROR, + [causes.WEBRTC_NOT_SUPPORTED]: this.baseErrorCodes.WEBRTC_NOT_SUPPORTED, + }; + this.webRtcError = { + 1001: '1001', + 1002: '1002', + 1003: '1003', + 1004: '1004', + 1005: '1005', + 1006: '1006', + 1007: '1007', + 1008: '1008', + 1009: '1009', + 1010: '1010', + 1011: '1011', }; } @@ -168,6 +183,10 @@ export default class SIPBridge extends BaseAudioBridge { return new Promise((resolve, reject) => { let hangupRetries = 0; let hangup = false; + const { mediaHandler } = this.currentSession; + + // Removing termination events to avoid triggering an error + CONNECTION_TERMINATED_EVENTS.forEach(e => mediaHandler.off(e)); const tryHangup = () => { this.currentSession.bye(); hangupRetries += 1; @@ -229,19 +248,22 @@ export default class SIPBridge extends BaseAudioBridge { resolve(userAgent); }; - const handleUserAgentDisconnection = () => { + const handleUserAgentDisconnection = (event) => { userAgent.stop(); userAgent = null; + const { lastTransportError } = event.transport; + const errorCode = lastTransportError.code; + const error = this.webRtcError[errorCode] || this.baseErrorCodes.CONNECTION_ERROR; this.callback({ status: this.baseCallStates.failed, - error: this.baseErrorCodes.CONNECTION_ERROR, + error, bridgeError: 'User Agent Disconnected', }); reject(this.baseErrorCodes.CONNECTION_ERROR); }; userAgent.on('connected', handleUserAgentConnection); - userAgent.on('disconnected', handleUserAgentDisconnection); + userAgent.on('disconnected', handleUserAgentDisconnection); userAgent.start(); }); @@ -311,16 +333,15 @@ export default class SIPBridge extends BaseAudioBridge { }; currentSession.on('terminated', handleSessionTerminated); - const connectionTerminatedEvents = ['iceConnectionFailed', 'iceConnectionDisconnected']; const handleConnectionTerminated = (peer) => { - connectionTerminatedEvents.forEach(e => mediaHandler.off(e, handleConnectionTerminated)); + CONNECTION_TERMINATED_EVENTS.forEach(e => mediaHandler.off(e, handleConnectionTerminated)); this.callback({ status: this.baseCallStates.failed, - error: this.baseErrorCodes.CONNECTION_ERROR, + error: this.baseErrorCodes.ICE_NEGOTIATION_FAILED, bridgeError: peer, }); }; - connectionTerminatedEvents.forEach(e => mediaHandler.on(e, handleConnectionTerminated)); + CONNECTION_TERMINATED_EVENTS.forEach(e => mediaHandler.on(e, handleConnectionTerminated)); this.currentSession = currentSession; }); diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/validateAuthToken.js b/bigbluebutton-html5/imports/api/users/server/handlers/validateAuthToken.js index 0cc164f2ae12ff158db1591fba3af6d248abcc0f..9fdd768003d311d9dab6274183419d9da07c56d7 100644 --- a/bigbluebutton-html5/imports/api/users/server/handlers/validateAuthToken.js +++ b/bigbluebutton-html5/imports/api/users/server/handlers/validateAuthToken.js @@ -1,31 +1,9 @@ import { check } from 'meteor/check'; import Logger from '/imports/startup/server/logger'; -import Meetings from '/imports/api/meetings'; import Users from '/imports/api/users'; -import addChat from '/imports/api/chat/server/modifiers/addChat'; -import clearUserSystemMessages from '/imports/api/chat/server/modifiers/clearUserSystemMessages'; - import userJoin from '../methods/userJoin'; -const addWelcomeChatMessage = (meetingId, userId) => { - const CHAT_CONFIG = Meteor.settings.public.chat; - - const Meeting = Meetings.findOne({ meetingId }); - - const message = { - message: Meeting.welcomeProp.welcomeMsg, - fromColor: '0x3399FF', - toUserId: userId, - toUsername: CHAT_CONFIG.type_system, - fromUserId: CHAT_CONFIG.type_system, - fromUsername: '', - fromTime: (new Date()).getTime(), - }; - - addChat(meetingId, message); -}; - const clearOtherSessions = (sessionUserId, current = false) => { const serverSessions = Meteor.server.sessions; Object.keys(serverSessions) @@ -72,9 +50,6 @@ export default function handleValidateAuthToken({ body }, meetingId) { if (numChanged) { if (valid) { - clearUserSystemMessages(meetingId, userId); - addWelcomeChatMessage(meetingId, userId); - const sessionUserId = `${meetingId}-${userId}`; const currentConnectionId = User.connectionId ? User.connectionId : false; clearOtherSessions(sessionUserId, currentConnectionId); diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js b/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js index 972380ec39528234bfbbccc400455eaf125f821b..c0c165feffe47e44ea0a69122cb27fbf9f42abd5 100755 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js @@ -8,12 +8,33 @@ import flat from 'flat'; import addVoiceUser from '/imports/api/voice-users/server/modifiers/addVoiceUser'; import changeRole from '/imports/api/users/server/modifiers/changeRole'; +import Meetings from '/imports/api/meetings'; +import addChat from '/imports/api/chat/server/modifiers/addChat'; +import clearUserSystemMessages from '/imports/api/chat/server/modifiers/clearUserSystemMessages'; + const COLOR_LIST = [ '#7b1fa2', '#6a1b9a', '#4a148c', '#5e35b1', '#512da8', '#4527a0', '#311b92', '#3949ab', '#303f9f', '#283593', '#1a237e', '#1976d2', '#1565c0', '#0d47a1', '#0277bd', '#01579b', ]; +// add some default welcoming message to the chat (welcome / mod only) +const addWelcomingChatMessage = (messageText, meetingId, userId) => { + const CHAT_CONFIG = Meteor.settings.public.chat; + + const message = { + message: messageText, + fromColor: '0x3399FF', + toUserId: userId, + toUsername: CHAT_CONFIG.type_system, + fromUserId: CHAT_CONFIG.type_system, + fromUsername: '', + fromTime: (new Date()).getTime(), + }; + + addChat(meetingId, message); +}; + export default function addUser(meetingId, user) { check(meetingId, String); @@ -95,12 +116,26 @@ export default function addUser(meetingId, user) { return Logger.error(`Adding user to collection: ${err}`); } + clearUserSystemMessages(meetingId, userId); + + const Meeting = Meetings.findOne({ meetingId }); + addWelcomingChatMessage( + Meeting.welcomeProp.welcomeMsg, + meetingId, userId, + ); + if (user.presenter) { changeRole(ROLE_PRESENTER, true, userId, meetingId); } if (userRole === ROLE_MODERATOR) { changeRole(ROLE_MODERATOR, true, userId, meetingId); + if (Meeting.welcomeProp.modOnlyMessage) { + addWelcomingChatMessage( + Meeting.welcomeProp.modOnlyMessage, + meetingId, userId, + ); + } } const { insertedId } = numChanged; diff --git a/bigbluebutton-html5/imports/startup/client/base.jsx b/bigbluebutton-html5/imports/startup/client/base.jsx index ef39c274e209cf81ec42e5b257a3ec7e5ffd0ec9..46d5e1b9e21aae213dbed903baefc894f35dc65e 100755 --- a/bigbluebutton-html5/imports/startup/client/base.jsx +++ b/bigbluebutton-html5/imports/startup/client/base.jsx @@ -127,11 +127,12 @@ const BaseContainer = withRouter(withTracker(({ params, router }) => { const annotationsHandler = Meteor.subscribe('annotations', credentials, { onReady: () => { - Annotations.find({}, { reactive: false }).forEach(a => { + AnnotationsLocal.remove({}); + Annotations.find({}, { reactive: false }).forEach((a) => { try { - AnnotationsLocal.insert(a) + AnnotationsLocal.insert(a); } catch (e) { - // who cares. + // who cares. } }); annotationsHandler.stop(); diff --git a/bigbluebutton-html5/imports/ui/components/audio/container.jsx b/bigbluebutton-html5/imports/ui/components/audio/container.jsx old mode 100644 new mode 100755 index 874667d8274e7c464be17a80439f12a7c0fc4e9e..f00e27e077e496c9b87441b20a8c5d9adbcf0886 --- a/bigbluebutton-html5/imports/ui/components/audio/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/container.jsx @@ -2,6 +2,7 @@ import React from 'react'; import { withTracker } from 'meteor/react-meteor-data'; import { withModalMounter } from '/imports/ui/components/modal/service'; import { injectIntl, defineMessages } from 'react-intl'; +import _ from 'lodash'; import Breakouts from '/imports/api/breakouts'; import Service from './service'; import AudioModalContainer from './audio-modal/container'; @@ -39,6 +40,14 @@ const intlMessages = defineMessages({ id: 'app.audioManager.mediaError', description: 'Media error message', }, + BrowserNotSupported: { + id: 'app.audioNotification.audioFailedError1003', + description: 'browser not supported error messsage', + }, + iceNegotiationError: { + id: 'app.audioNotification.audioFailedError1007', + description: 'ice negociation error messsage', + }, }); @@ -81,6 +90,12 @@ export default withModalMounter(injectIntl(withTracker(({ mountModal, intl }) => }, }); + const webRtcError = _.range(1001, 1012) + .reduce((acc, value) => ({ + ...acc, + [value]: intl.formatMessage({ id: `app.audioNotification.audioFailedError${value}` }), + }), {}); + const messages = { info: { JOINED_AUDIO: intl.formatMessage(intlMessages.joinedAudio), @@ -93,6 +108,9 @@ export default withModalMounter(injectIntl(withTracker(({ mountModal, intl }) => REQUEST_TIMEOUT: intl.formatMessage(intlMessages.requestTimeout), INVALID_TARGET: intl.formatMessage(intlMessages.invalidTarget), MEDIA_ERROR: intl.formatMessage(intlMessages.mediaError), + WEBRTC_NOT_SUPPORTED: intl.formatMessage(intlMessages.BrowserNotSupported), + ICE_NEGOTIATION_FAILED: intl.formatMessage(intlMessages.iceNegotiationError), + ...webRtcError, }, }; diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx old mode 100644 new mode 100755 index 98716c98ee166b7555f5246028247c8dc593cafe..a4c569b573fc742cd3a5e8243a10075317e30fb8 --- a/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx @@ -80,13 +80,17 @@ class MessageForm extends Component { const { minMessageLength, maxMessageLength } = this.props; if (message.length < minMessageLength) { - error = intl.formatMessage(messages.errorMinMessageLength, - { 0: minMessageLength - message.length }); + error = intl.formatMessage( + messages.errorMinMessageLength, + { 0: minMessageLength - message.length }, + ); } if (message.length > maxMessageLength) { - error = intl.formatMessage(messages.errorMaxMessageLength, - { 0: message.length - maxMessageLength }); + error = intl.formatMessage( + messages.errorMaxMessageLength, + { 0: message.length - maxMessageLength }, + ); } this.setState({ @@ -123,8 +127,10 @@ class MessageForm extends Component { } render() { - const { intl, chatTitle, chatName, disabled, - minMessageLength, maxMessageLength } = this.props; + const { + intl, chatTitle, chatName, disabled, + minMessageLength, maxMessageLength, + } = this.props; const { hasErrors, error } = this.state; diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss old mode 100644 new mode 100755 index caebbfd4d10ae68f6a78755598643c56084422c8..f02d35fb1d66c68a63d59babaf9b49823119f3a4 --- a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.scss @@ -56,7 +56,7 @@ resize: none; transition: none; border-radius: $border-radius; - font-size: $font-size-base * .90; + font-size: $font-size-base; min-height: 2.5rem; max-height: 10rem; border: 1px solid $color-gray-lighter; diff --git a/bigbluebutton-html5/imports/ui/components/cursor/presentation-overlay/component.jsx b/bigbluebutton-html5/imports/ui/components/cursor/presentation-overlay/component.jsx index ecaf2efb4e6b522267d5055ecf969406d4ce2b0e..e3a5a505ce742f519ad237df5834d063fbd9ebd7 100755 --- a/bigbluebutton-html5/imports/ui/components/cursor/presentation-overlay/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/cursor/presentation-overlay/component.jsx @@ -92,6 +92,7 @@ export default class PresentationOverlay extends Component { } handleTouchMove(event) { + event.preventDefault(); const { clientX, clientY } = event.changedTouches[0]; this.currentClientX = clientX; diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-overlay/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-overlay/component.jsx index 66f7867ca4685469c1da896a27f39666b97d3483..74422d6de4af58b550616ad8b4186b8b5c402bf2 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-overlay/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-overlay/component.jsx @@ -97,6 +97,8 @@ export default class PresentationOverlay extends Component { } handleTouchMove(event) { + event.preventDefault(); + const { clientX, clientY } = event.changedTouches[0]; this.currentClientX = clientX; @@ -187,6 +189,8 @@ export default class PresentationOverlay extends Component { y="0" width={this.props.slideWidth} height={this.props.slideHeight} + // maximun value of z-index to prevent other things from overlapping + style={{ zIndex: 2 ** 31 - 1 }} > <div onTouchStart={this.handleTouchStart} diff --git a/bigbluebutton-html5/imports/ui/components/settings/component.jsx b/bigbluebutton-html5/imports/ui/components/settings/component.jsx index d2a77b2ced7f3e4f1ee3d257842ffcef910b850c..bd499f6835bd8ecc81f384205120221619d8d55b 100644 --- a/bigbluebutton-html5/imports/ui/components/settings/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/settings/component.jsx @@ -210,6 +210,7 @@ class Settings extends Component { intl, router, location, + mountModal, } = this.props; return ( @@ -218,17 +219,20 @@ class Settings extends Component { confirm={{ callback: () => { this.updateSettings(this.state.current); - this.props.router.push(location.pathname); + router.push(location.pathname); /* We need to use mountModal(null) here to prevent submenu state updates, * from re-opening the modal. */ - this.props.mountModal(null); + mountModal(null); }, label: intl.formatMessage(intlMessages.SaveLabel), description: intl.formatMessage(intlMessages.SaveLabelDesc), }} dismiss={{ - callback: () => Settings.setHtmlFontSize(this.state.saved.application.fontSize), + callback: () => { + Settings.setHtmlFontSize(this.state.saved.application.fontSize); + mountModal(null); + }, label: intl.formatMessage(intlMessages.CancelLabel), description: intl.formatMessage(intlMessages.CancelLabelDesc), }} diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/service.js b/bigbluebutton-html5/imports/ui/components/whiteboard/service.js index 9bf6879cf087083de113c58e5cec3b378a34a8bf..c9795aa06e6c363c41a663262cedfadcc85a7c2e 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/service.js +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/service.js @@ -1,14 +1,15 @@ import Users from '/imports/api/users'; import Auth from '/imports/ui/services/auth'; +import WhiteboardMultiUser from '/imports/api/whiteboard-multi-user/'; import { AnnotationsStreamer } from '/imports/api/annotations'; import addAnnotationQuery from '/imports/api/annotations/addAnnotation'; -import { isEqual, isArray } from 'lodash'; +import { isEqual } from 'lodash'; const Annotations = new Mongo.Collection(null); -const Logger = { - info: console.log, - error: console.error, -}; + +function clearFakeAnnotations() { + Annotations.remove({ id: /-fake/g }); +} function handleAddedAnnotation({ meetingId, whiteboardId, userId, annotation, @@ -71,7 +72,7 @@ function handleRemovedAnnotation({ } if (shapeId) { - query.id = shapeId; + query.id = { $in: [shapeId, `${shapeId}-fake`] }; } Annotations.remove(query); @@ -83,23 +84,25 @@ AnnotationsStreamer.on('added', ({ annotations }) => { annotations.forEach(annotation => handleAddedAnnotation(annotation)); }); -function increase_brightness(hex, percent) { - hex = parseInt(hex, 10).toString(16).padStart(6, 0); +function increaseBrightness(realHex, percent) { + let hex = parseInt(realHex, 10).toString(16).padStart(6, 0); // strip the leading # if it's there hex = hex.replace(/^\s*#|\s*$/g, ''); // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF` - if (hex.length == 3) { + if (hex.length === 3) { hex = hex.replace(/(.)/g, '$1$1'); } - let r = parseInt(hex.substr(0, 2), 16), - g = parseInt(hex.substr(2, 2), 16), - b = parseInt(hex.substr(4, 2), 16); + const r = parseInt(hex.substr(0, 2), 16); + const g = parseInt(hex.substr(2, 2), 16); + const b = parseInt(hex.substr(4, 2), 16); - return parseInt(((0 | (1 << 8) + r + (256 - r) * percent / 100).toString(16)).substr(1) + - ((0 | (1 << 8) + g + (256 - g) * percent / 100).toString(16)).substr(1) + - ((0 | (1 << 8) + b + (256 - b) * percent / 100).toString(16)).substr(1), 16); + /* eslint-disable no-bitwise, no-mixed-operators */ + return parseInt(((0 | (1 << 8) + r + ((256 - r) * percent) / 100).toString(16)).substr(1) + + ((0 | (1 << 8) + g + ((256 - g) * percent) / 100).toString(16)).substr(1) + + ((0 | (1 << 8) + b + ((256 - b) * percent) / 100).toString(16)).substr(1), 16); + /* eslint-enable no-bitwise, no-mixed-operators */ } let annotationsQueue = []; @@ -124,13 +127,17 @@ const proccessAnnotationsQueue = () => { AnnotationsStreamer.emit('publish', { credentials: Auth.credentials, payload: annotationsQueue }); annotationsQueue = []; // ask tiago - const delayPerc = Math.min(annotationsMaxDelayQueueSize, queueSize) / annotationsMaxDelayQueueSize; + const delayPerc = + Math.min(annotationsMaxDelayQueueSize, queueSize) / annotationsMaxDelayQueueSize; const delayDelta = annotationsBufferTimeMax - annotationsBufferTimeMin; const delayTime = annotationsBufferTimeMin + (delayDelta * delayPerc); setTimeout(proccessAnnotationsQueue, delayTime); }; export function sendAnnotation(annotation) { + // Prevent sending annotations while disconnected + if (!Meteor.status().connected) return; + annotationsQueue.push(annotation); if (!annotationsSenderIsRunning) setTimeout(proccessAnnotationsQueue, annotationsBufferTimeMin); @@ -146,11 +153,23 @@ export function sendAnnotation(annotation) { position: Number.MAX_SAFE_INTEGER, annotationInfo: { ...annotation.annotationInfo, - color: increase_brightness(annotation.annotationInfo.color, 40), + color: increaseBrightness(annotation.annotationInfo.color, 40), }, }, ); - return Annotations.upsert(queryFake.selector, queryFake.modifier); + + Annotations.upsert(queryFake.selector, queryFake.modifier); } +WhiteboardMultiUser.find({ meetingId: Auth.meetingID }).observeChanges({ + changed: clearFakeAnnotations, +}); + +Users.find({ userId: Auth.userID }).observeChanges({ + changed(id, { presenter }) { + console.log(presenter); + if (presenter === false) clearFakeAnnotations(); + }, +}); + export default Annotations; diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx index 01c66d37a366f72f89e717d6270a6a5760aba5a7..2297f6b8f7c600e98d5de2e47433a75bffbe13bd 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/pencil-draw-listener/component.jsx @@ -102,6 +102,7 @@ export default class PencilDrawListener extends Component { } handleTouchMove(event) { + event.preventDefault(); const { clientX, clientY } = event.changedTouches[0]; this.commonDrawMoveHandler(clientX, clientY); } @@ -213,6 +214,7 @@ export default class PencilDrawListener extends Component { width: '100%', height: '100%', touchAction: 'none', + zIndex: 2 ** 31 - 1, // maximun value of z-index to prevent other things from overlapping cursor: `url('${baseName}/resources/images/whiteboard-cursor/pencil.png') 2 22, default`, }; return ( diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx index 5c9f7c130fcbcbb9ef75c70d821bffbd8c11de0e..2992fe43e489c67cc5e0f8558d330e23b0835c79 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/shape-draw-listener/component.jsx @@ -133,6 +133,7 @@ export default class ShapeDrawListener extends Component { } handleTouchMove(event) { + event.preventDefault(); const { clientX, clientY } = event.changedTouches[0]; this.commonDrawMoveHandler(clientX, clientY); } @@ -284,6 +285,7 @@ export default class ShapeDrawListener extends Component { width: '100%', height: '100%', touchAction: 'none', + zIndex: 2 ** 31 - 1, // maximun value of z-index to prevent other things from overlapping cursor: `url('${baseName}/resources/images/whiteboard-cursor/${tool !== 'rectangle' ? tool : 'square'}.png'), default`, }; return ( diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx old mode 100644 new mode 100755 index d68288a6cd4712626ba1edcc54b674da8a401701..f615c81b198d975e3678bd1fed72f7feb8e5e753 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-overlay/text-draw-listener/component.jsx @@ -151,6 +151,7 @@ export default class TextDrawListener extends Component { } handleTouchMove(event) { + event.preventDefault(); const { clientX, clientY } = event.changedTouches[0]; this.commonDrawMoveHandler(clientX, clientY); } @@ -373,6 +374,7 @@ export default class TextDrawListener extends Component { width: '100%', height: '100%', touchAction: 'none', + zIndex: 2 ** 31 - 1, // maximun value of z-index to prevent other things from overlapping cursor: `url('${baseName}/resources/images/whiteboard-cursor/text.png'), default`, }; return ( diff --git a/bigbluebutton-html5/imports/ui/services/audio-manager/index.js b/bigbluebutton-html5/imports/ui/services/audio-manager/index.js index d432835a0e68325edd684ad3829fd5dbef4615ad..5d79563e5260aabc0bbb5425a4de4efd0f33e165 100755 --- a/bigbluebutton-html5/imports/ui/services/audio-manager/index.js +++ b/bigbluebutton-html5/imports/ui/services/audio-manager/index.js @@ -171,7 +171,7 @@ class AudioManager { exitAudio() { if (!this.isConnected) return Promise.resolve(); - const bridge = USE_KURENTO? this.listenOnlyBridge : this.bridge; + const bridge = (USE_KURENTO && this.isListenOnly) ? this.listenOnlyBridge : this.bridge; this.isHangingUp = true; this.isEchoTest = false; @@ -260,9 +260,10 @@ class AudioManager { this.onAudioExit(); } else if (status === FAILED) { this.error = error; - this.notify(this.messages.error[error], true); + this.notify(this.messages.error[error] || this.messages.error.GENERIC_ERROR, true); makeCall('failed callStateCallback audio', response); console.error('Audio Error:', error, bridgeError); + this.exitAudio(); this.onAudioExit(); } }); diff --git a/bigbluebutton-html5/private/locales/fr.json b/bigbluebutton-html5/private/locales/fr.json index 8684b99ff757159acf42456173404e85cc107f8a..a88eeb123f417e3ed14c12b9eda7ff8cadef63eb 100644 --- a/bigbluebutton-html5/private/locales/fr.json +++ b/bigbluebutton-html5/private/locales/fr.json @@ -40,7 +40,7 @@ "app.userList.menu.promoteUser.label": "Promouvoir {0} modérateur", "app.userList.menu.demoteUser.label": "Redéfinir {0} comme participant", "app.media.label": "Média", - "app.media.screenshare.start": "Le Partage d'écran à débuté", + "app.media.screenshare.start": "Le Partage d'écran à commencé", "app.media.screenshare.end": "Le Partage d'écran s'est terminé", "app.media.screenshare.safariNotSupported": "Le Partage d'écran n'est pour le moment pas supporté par Safari. Veuillez utiliser Firefox ou Google Chrome.", "app.meeting.ended": "Cette session s'est terminée", @@ -136,7 +136,7 @@ "app.submenu.application.languageOptionLabel": "Choisir la langue", "app.submenu.application.noLocaleOptionLabel": "Pas de lieu actif", "app.submenu.audio.micSourceLabel": "Source du Micro", - "app.submenu.audio.speakerSourceLabel": "Source des diffuseurs", + "app.submenu.audio.speakerSourceLabel": "Source du haut-parleur", "app.submenu.audio.streamVolumeLabel": "Volume de votre flux audio", "app.submenu.video.title": "Vidéo", "app.submenu.video.videoSourceLabel": "Voir la source", @@ -162,17 +162,17 @@ "app.submenu.participants.lockCamDesc": "Désactiver la webcam de tous les participants verrouillés", "app.submenu.participants.lockPublicChatDesc": "Désactiver la discussion publique pour tous les participants verrouillés", "app.submenu.participants.lockPrivateChatDesc": "Désactiver la discussion privée pour tous les participants verrouillés", - "app.submenu.participants.lockLayoutDesc": "Verrouiller les mise en page pour tous les participants verrouillés", + "app.submenu.participants.lockLayoutDesc": "Verrouiller la disposition pour tous les participants verrouillés", "app.submenu.participants.lockMicAriaLabel": "Verrouillage du micro", "app.submenu.participants.lockCamAriaLabel": "Verrouillage de la webcam", "app.submenu.participants.lockPublicChatAriaLabel": "Discussion publique verrouillée", "app.submenu.participants.lockPrivateChatAriaLabel": "Discussion privée verrouillée", - "app.submenu.participants.lockLayoutAriaLabel": "Mise en page verrouillée", + "app.submenu.participants.lockLayoutAriaLabel": "Disposition verrouillée", "app.submenu.participants.lockMicLabel": "Microphone", "app.submenu.participants.lockCamLabel": "Webcam", "app.submenu.participants.lockPublicChatLabel": "Discussion Publique", "app.submenu.participants.lockPrivateChatLabel": "Discussion Privée", - "app.submenu.participants.lockLayoutLabel": "Mise en page", + "app.submenu.participants.lockLayoutLabel": "Disposition", "app.settings.applicationTab.label": "Application", "app.settings.audioTab.label": "Audio", "app.settings.videoTab.label": "Vidéo", @@ -316,6 +316,9 @@ "app.video.iceCandidateError": "Erreur lors de l'ajout d'un candidat ICE", "app.video.permissionError": "Erreur lors du partage de la webcam. Veuillez vérifier les permissions.", "app.video.sharingError": "Erreur lors du partage de la Webcam", + "app.video.notFoundError": "Webcam introuvable. Assurez-vous qu'elle soit bien connectée", + "app.video.notAllowed": "Permission manquante pour partager la Webcam. Veuillez vérifier les permissions dans votre navigateur", + "app.video.mediaServerOffline": "Le serveur de médias est hors ligne. Veuillez ré-essayer plus tard.", "app.video.swapCam": "Échanger", "app.video.swapCamDesc": "Permuter les Webcams", "app.video.videoMenu": "Menu Vidéo", @@ -327,11 +330,13 @@ "app.video.stats.packetsReceived": "Paquets reçus", "app.video.stats.packetsSent": "Paquets envoyés", "app.video.stats.packetsLost": "Paquets perdus", + "app.video.stats.bitrate": "Bitrate", "app.video.stats.lostPercentage": "Pourcentage perdu total", "app.video.stats.lostRecentPercentage": "Pourcentage perdu récent", "app.video.stats.dimensions": "Dimensions", "app.video.stats.codec": "Codec", "app.video.stats.decodeDelay": "Délai de décodage", + "app.video.stats.rtt": "RTT", "app.video.stats.encodeUsagePercent": "Usage de l'encodage", "app.video.stats.currentDelay": "Délai actuel", "app.meeting.endNotification.ok.label": "OK", @@ -366,7 +371,9 @@ "app.whiteboard.toolbar.fontSize": "Liste des Tailles de Police", "app.feedback.title": "Vous avez quitté la conférence", "app.feedback.subtitle": "Nous aimerions connaitre votre expérience avec BigBlueButton (optionnel)", - "app.feedback.textarea": "Comment pouvons nous améliorer BigBlueButton ?" + "app.feedback.textarea": "Comment pouvons nous améliorer BigBlueButton ?", + "app.videoDock.webcamFocusLabel": "Focus", + "app.videoDock.webcamFocusDesc": "Focus sur la webcam sélectionnée" } diff --git a/bigbluebutton-html5/private/locales/ja.json b/bigbluebutton-html5/private/locales/ja.json index 4162b7d681359126b9528381f7c8451413c88133..b1aad8ba7fc1bddda6ef5c6349f008d73db6a11f 100644 --- a/bigbluebutton-html5/private/locales/ja.json +++ b/bigbluebutton-html5/private/locales/ja.json @@ -346,7 +346,7 @@ "app.whiteboard.toolbar.tools.pencil": "ペン", "app.whiteboard.toolbar.tools.rectangle": "長方形", "app.whiteboard.toolbar.tools.triangle": "三角形", - "app.whiteboard.toolbar.tools.ellipse": "長方形", + "app.whiteboard.toolbar.tools.ellipse": "楕円", "app.whiteboard.toolbar.tools.line": "ç·š", "app.whiteboard.toolbar.tools.text": "テã‚スト", "app.whiteboard.toolbar.thickness": "ç·šã®å¤ªã•", @@ -371,7 +371,7 @@ "app.whiteboard.toolbar.multiUserOff": "マルãƒãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã‚’外ã™", "app.whiteboard.toolbar.fontSize": "フォントサイズ", "app.feedback.title": "セッションã‹ã‚‰ãƒã‚°ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸ", - "app.feedback.subtitle": "BigBlueButtonã®æ„Ÿæƒ³ã¯ï¼Ÿ (ä»»æ„)\"", + "app.feedback.subtitle": "BigBlueButtonã®æ„Ÿæƒ³ã¯ï¼Ÿ (ä»»æ„)", "app.feedback.textarea": "BigBlueButtonã«ä½•ãŒæ¬²ã—ã„ã§ã™ã‹?", "app.feedback.sendFeedback": "フィードãƒãƒƒã‚¯ã‚’é€ã‚‹", "app.feedback.sendFeedbackDesc": "フィードãƒãƒƒã‚¯ã‚’é€ã£ã¦ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‹ã‚‰é€€å¸ã™ã‚‹", diff --git a/bigbluebutton-html5/private/locales/ja_JP.json b/bigbluebutton-html5/private/locales/ja_JP.json index 4162b7d681359126b9528381f7c8451413c88133..b1aad8ba7fc1bddda6ef5c6349f008d73db6a11f 100644 --- a/bigbluebutton-html5/private/locales/ja_JP.json +++ b/bigbluebutton-html5/private/locales/ja_JP.json @@ -346,7 +346,7 @@ "app.whiteboard.toolbar.tools.pencil": "ペン", "app.whiteboard.toolbar.tools.rectangle": "長方形", "app.whiteboard.toolbar.tools.triangle": "三角形", - "app.whiteboard.toolbar.tools.ellipse": "長方形", + "app.whiteboard.toolbar.tools.ellipse": "楕円", "app.whiteboard.toolbar.tools.line": "ç·š", "app.whiteboard.toolbar.tools.text": "テã‚スト", "app.whiteboard.toolbar.thickness": "ç·šã®å¤ªã•", @@ -371,7 +371,7 @@ "app.whiteboard.toolbar.multiUserOff": "マルãƒãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã‚’外ã™", "app.whiteboard.toolbar.fontSize": "フォントサイズ", "app.feedback.title": "セッションã‹ã‚‰ãƒã‚°ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸ", - "app.feedback.subtitle": "BigBlueButtonã®æ„Ÿæƒ³ã¯ï¼Ÿ (ä»»æ„)\"", + "app.feedback.subtitle": "BigBlueButtonã®æ„Ÿæƒ³ã¯ï¼Ÿ (ä»»æ„)", "app.feedback.textarea": "BigBlueButtonã«ä½•ãŒæ¬²ã—ã„ã§ã™ã‹?", "app.feedback.sendFeedback": "フィードãƒãƒƒã‚¯ã‚’é€ã‚‹", "app.feedback.sendFeedbackDesc": "フィードãƒãƒƒã‚¯ã‚’é€ã£ã¦ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‹ã‚‰é€€å¸ã™ã‚‹", diff --git a/bigbluebutton-html5/private/locales/pt_BR.json b/bigbluebutton-html5/private/locales/pt_BR.json index 78b0b6cc29ad266e7f6722e806ac4af59e3f7bf0..2248f585e1461f92a66680e71ddae7a68212eb4e 100644 --- a/bigbluebutton-html5/private/locales/pt_BR.json +++ b/bigbluebutton-html5/private/locales/pt_BR.json @@ -69,7 +69,9 @@ "app.presentationUploder.fileToUpload": "Carregar arquivo...", "app.presentationUploder.currentBadge": "Atual", "app.presentationUploder.genericError": "Ops, algo deu errado", + "app.presentationUploder.upload.progress": "Carregando ({0}%)", "app.presentationUploder.upload.413": "O arquivo é muito grande", + "app.presentationUploder.conversion.conversionProcessingSlides": "Página de processamento {0} de {1}", "app.presentationUploder.conversion.genericConversionStatus": "Convertendo arquivo...", "app.presentationUploder.conversion.generatingThumbnail": "Gerando miniaturas...", "app.presentationUploder.conversion.generatedSlides": "Slides gerados...", @@ -294,6 +296,9 @@ "app.error.leaveLabel": "Faça o login novamente", "app.guest.waiting": "Esperando aprovação para participar", "app.toast.breakoutRoomEnded": "A sala de apoio terminou. Clique no Ãcone do microfone para reingressar a conferência de áudio na sala principal", + "app.toast.chat.public": "Nova mensagem de Bate-papo público", + "app.toast.chat.private": "Nova mensagem de Bate-papo privado", + "app.toast.chat.system": "Sistema", "app.notification.recordingStart": "Esta reunião está sendo gravada", "app.notification.recordingStop": "Esta reunião não está mais sendo gravada", "app.shortcut-help.title": "Atalhos de teclado", @@ -327,6 +332,19 @@ "app.video.videoMenuDesc": "Abra o menu de vÃdeo", "app.video.chromeExtensionError": "Você deve instalar o seguinte:", "app.video.chromeExtensionErrorLink": "esta extensão do Chrome", + "app.video.stats.title": "EstatÃsticas de conexão", + "app.video.stats.packetsReceived": "Pacotes recebidos", + "app.video.stats.packetsSent": "Pacotes enviados", + "app.video.stats.packetsLost": "Pacotes perdidos", + "app.video.stats.bitrate": "Taxa de bits", + "app.video.stats.lostPercentage": "Percentuais de perda total", + "app.video.stats.lostRecentPercentage": "Percentuais de perda recentemente", + "app.video.stats.dimensions": "Dimensões", + "app.video.stats.codec": "Codec", + "app.video.stats.decodeDelay": "Atraso de decodificação", + "app.video.stats.rtt": "RTT", + "app.video.stats.encodeUsagePercent": "Uso de codificação", + "app.video.stats.currentDelay": "Atraso atual", "app.meeting.endNotification.ok.label": "OK", "app.whiteboard.toolbar.tools": "Ferramentas", "app.whiteboard.toolbar.tools.pointer": "Cursor", @@ -344,6 +362,7 @@ "app.whiteboard.toolbar.color.white": "Branco", "app.whiteboard.toolbar.color.red": "Vermelho", "app.whiteboard.toolbar.color.orange": "Laranja", + "app.whiteboard.toolbar.color.eletricLime": "Verde limão", "app.whiteboard.toolbar.color.lime": "Verde", "app.whiteboard.toolbar.color.cyan": "Ciano", "app.whiteboard.toolbar.color.dodgerBlue": "Azul Dodger", diff --git a/bigbluebutton-html5/private/locales/ru_RU.json b/bigbluebutton-html5/private/locales/ru_RU.json index c767de27ba850d720d802ca3748c28ae702407c5..f277f07ebc4ecccb1b443ca56f71a2448bba7305 100644 --- a/bigbluebutton-html5/private/locales/ru_RU.json +++ b/bigbluebutton-html5/private/locales/ru_RU.json @@ -1,9 +1,9 @@ { "app.home.greeting": "Добро пожаловать {0}! Ваша Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ð°Ñ‡Ð½Ñ‘Ñ‚ÑÑ Ð² ближайшее времÑ... ", "app.chat.submitLabel": "Отправить Ñообщение", - "app.chat.errorMinMessageLength": "Сообщение Ñлишком короткое ({0} Ñимволов)", - "app.chat.errorMaxMessageLength": "Сообщение Ñлишком длинное ({0} Ñимволов)", - "app.chat.inputLabel": "Поле ввода ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð»Ñ {0}", + "app.chat.errorMinMessageLength": "Сообщение из {0} Ñимвола(-ов) Ñлишком короткое", + "app.chat.errorMaxMessageLength": "Сообщение из {0} Ñимвола(-ов) Ñлишком длинное", + "app.chat.inputLabel": "Ввод Ñообщений Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ð° {0}", "app.chat.inputPlaceholder": "Сообщение {0}", "app.chat.titlePublic": "Общий чат", "app.chat.titlePrivate": "Приватный чат Ñ {0}", @@ -33,12 +33,16 @@ "app.userList.menu.chat.label": "Чат", "app.userList.menu.clearStatus.label": "ОчиÑтить ÑтатуÑ", "app.userList.menu.makePresenter.label": "Сделать ведущим", - "app.userList.menu.removeUser.label": "Удалить пользователÑ", + "app.userList.menu.removeUser.label": "ИÑключить пользователÑ", "app.userList.menu.muteUserAudio.label": "Выключить микрофон пользователÑ", "app.userList.menu.unmuteUserAudio.label": "Включить микрофон пользователÑ", + "app.userList.userAriaLabel": "{0} {1} {2} Ð¡Ñ‚Ð°Ñ‚ÑƒÑ {3}", "app.userList.menu.promoteUser.label": "ПовыÑить {0} до модератора", "app.userList.menu.demoteUser.label": "Понизить {0} до зрителÑ", "app.media.label": "Медиа", + "app.media.screenshare.start": "ДемонÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ñкрана началаÑÑŒ", + "app.media.screenshare.end": "ДемонÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ñкрана закончилаÑÑŒ", + "app.media.screenshare.safariNotSupported": "ДемонÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ñкрана на данный момент не поддерживаетÑÑ Safari. ПожалуйÑта, иÑпользуйте Firefox или Google Chrome.", "app.meeting.ended": "Ð¡ÐµÐ°Ð½Ñ Ð¾ÐºÐ¾Ð½Ñ‡ÐµÐ½", "app.meeting.endedMessage": "Ð’Ñ‹ будете перенаправлены назад на главный Ñкран", "app.presentation.presentationToolbar.prevSlideLabel": "Предыдущий Ñлайд", @@ -47,9 +51,9 @@ "app.presentation.presentationToolbar.nextSlideDesc": "Переключить презентацию на Ñледующий Ñлайд", "app.presentation.presentationToolbar.skipSlideLabel": "ПропуÑтить Ñлайд", "app.presentation.presentationToolbar.skipSlideDesc": "Переключить презентацию на указанный Ñлайд", - "app.presentation.presentationToolbar.fitWidthLabel": "По ширине", + "app.presentation.presentationToolbar.fitWidthLabel": "Подогнать по ширине", "app.presentation.presentationToolbar.fitWidthDesc": "УмеÑтить по ширине Ñлайда", - "app.presentation.presentationToolbar.fitScreenLabel": "По размеру Ñкрана", + "app.presentation.presentationToolbar.fitScreenLabel": "Подогнать к Ñкрану", "app.presentation.presentationToolbar.fitScreenDesc": "УмеÑтить Ñлайд целиком", "app.presentation.presentationToolbar.zoomLabel": "МаÑштаб", "app.presentation.presentationToolbar.zoomDesc": "Изменить маÑштаб презетации", @@ -59,21 +63,25 @@ "app.presentationUploder.confirmLabel": "Ðачать", "app.presentationUploder.confirmDesc": "Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ начать презентацию", "app.presentationUploder.dismissLabel": "Отменить", - "app.presentationUploder.dismissDesc": "Закрыть вÑплывающее окно и отменить изменениÑ", + "app.presentationUploder.dismissDesc": "Закрыть окно Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¸ отменить изменениÑ", "app.presentationUploder.dropzoneLabel": "Перетащите Ñюда файлы, чтобы загрузить их", "app.presentationUploder.browseFilesLabel": "или выберите файл", "app.presentationUploder.fileToUpload": "Чтобы загрузить...", "app.presentationUploder.currentBadge": "Текущий", "app.presentationUploder.genericError": "Ой, что-то пошло не так", + "app.presentationUploder.upload.progress": "Загрузка ({0}%)", "app.presentationUploder.upload.413": "Файл Ñлишком большой", + "app.presentationUploder.conversion.conversionProcessingSlides": "Обработка Ñтраницы {0} из {1}", "app.presentationUploder.conversion.genericConversionStatus": "Файл конвертируетÑÑ...", "app.presentationUploder.conversion.generatingThumbnail": "ГенерируютÑÑ Ð¼Ð¸Ð½Ð¸Ð°Ñ‚ÑŽÑ€Ñ‹...", - "app.presentationUploder.conversion.generatedSlides": "Слайды Ñгенерированы...", + "app.presentationUploder.conversion.generatedSlides": "Слайды генерируютÑÑ...", "app.presentationUploder.conversion.generatingSvg": "Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ð¹ SVG...", "app.presentationUploder.conversion.pageCountExceeded": "Ой, доÑтигнут предел количеÑтва Ñтраниц", "app.presentationUploder.conversion.timeout": "Ой, ÐºÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ð¸Ñ Ð·Ð°Ð½Ð¸Ð¼Ð°ÐµÑ‚ Ñлишком много времени", "app.polling.pollingTitle": "Варианты голоÑованиÑ", - "app.failedMessage": "Apologies, trouble connecting to the server.", + "app.polling.pollAnswerLabel": "Результат опроÑа {0}", + "app.polling.pollAnswerDesc": "Выберите Ñтот вариант, чтобы проголоÑовать за {0}", + "app.failedMessage": "Извините, проблемы Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸ÐµÐ¼ к Ñерверу.", "app.connectingMessage": "Подключение...", "app.waitingMessage": "Соединение потерÑно. Попытка Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· {0} Ñекунд...", "app.navBar.settingsDropdown.optionsLabel": "Опции", @@ -87,9 +95,12 @@ "app.navBar.settingsDropdown.aboutDesc": "Показать информацию о клиенте", "app.navBar.settingsDropdown.leaveSessionDesc": "Покинуть конференцию", "app.navBar.settingsDropdown.exitFullscreenDesc": "Выйти из полноÑкранного режима", + "app.navBar.settingsDropdown.hotkeysLabel": "БыÑтрые клавиши", + "app.navBar.settingsDropdown.hotkeysDesc": "СпиÑок доÑтупных быÑтрых клавиш", "app.navBar.userListToggleBtnLabel": "Включить/выключить ÑпиÑок пользователей", + "app.navBar.toggleUserList.ariaLabel": "Включить/выключить Пользователей и СообщениÑ", "app.navBar.toggleUserList.newMessages": "Ñ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸ÐµÐ¼ о новых ÑообщениÑÑ…", - "app.navBar.recording": "Ðтот ÑÐµÐ°Ð½Ñ Ð±ÑƒÐ´ÐµÑ‚ запиÑан", + "app.navBar.recording": "Ðтот ÑÐµÐ°Ð½Ñ Ð·Ð°Ð¿Ð¸ÑываетÑÑ", "app.navBar.recording.on": "ЗапиÑываетÑÑ", "app.navBar.recording.off": "Ðе запиÑываетÑÑ", "app.leaveConfirmation.title": "Покинуть ÑеанÑ", @@ -97,8 +108,9 @@ "app.leaveConfirmation.confirmLabel": "Выйти", "app.leaveConfirmation.confirmDesc": "Выйти из конференции", "app.leaveConfirmation.dismissLabel": "Отмена", - "app.leaveConfirmation.dismissDesc": "Ðе выходить из конференции", + "app.leaveConfirmation.dismissDesc": "Закрывает и отклонÑет подтверждение о выходе", "app.leaveConfirmation.endMeetingLabel": "Да, завершить ÑеанÑ", + "app.leaveConfirmation.endMeetingAriaLabel": "Покинуть и завершить ÑеанÑ", "app.leaveConfirmation.endMeetingDesc": "Подтвердить завершение конференции", "app.about.title": "О программе", "app.about.version": "Сборка клиента:", @@ -115,7 +127,7 @@ "app.actionsBar.label": "Панель дейÑтвий", "app.submenu.application.applicationSectionTitle": "Приложение", "app.submenu.application.audioNotifyLabel": "Звуковые ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ‡Ð°Ñ‚Ð°", - "app.submenu.application.pushNotifyLabel": "Пуш ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ‡Ð°Ñ‚Ð°", + "app.submenu.application.pushNotifyLabel": "Push-ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ð°", "app.submenu.application.fontSizeControlLabel": "Размер шрифта", "app.submenu.application.increaseFontBtnLabel": "Увеличить шрифт приложениÑ", "app.submenu.application.decreaseFontBtnLabel": "Уменьшить шрифт приложениÑ", @@ -123,8 +135,8 @@ "app.submenu.application.ariaLanguageLabel": "Изменить Ñзык приложениÑ", "app.submenu.application.languageOptionLabel": "Выберите Ñзык", "app.submenu.application.noLocaleOptionLabel": "Ðет доÑтупных переводов", - "app.submenu.audio.micSourceLabel": "Микрофон", - "app.submenu.audio.speakerSourceLabel": "Динамики", + "app.submenu.audio.micSourceLabel": "ИÑточник микрофона", + "app.submenu.audio.speakerSourceLabel": "ИÑточник динамиков", "app.submenu.audio.streamVolumeLabel": "ГромкоÑть аудио-потока", "app.submenu.video.title": "Видео", "app.submenu.video.videoSourceLabel": "Видео-иÑточник", @@ -171,7 +183,9 @@ "app.settings.main.cancel.label.description": "СбраÑывает Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ закрывает меню наÑтроек", "app.settings.main.save.label": "Сохранить", "app.settings.main.save.label.description": "СохранÑет Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ закрывает меню наÑтроек", - "app.settings.dataSavingTab.label": "ÐÐºÐ¾Ð½Ð¾Ð¼Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…", + "app.settings.dataSavingTab.label": "Сохранение данных", + "app.settings.dataSavingTab.webcam": "Включить веб камеры", + "app.settings.dataSavingTab.screenShare": "Включить демонÑтрацию рабочего Ñтола", "app.settings.dataSavingTab.description": "Чтобы Ñохранить уÑтойчивую ÑкороÑть ÑоединениÑ, выберите, что будет отображатьÑÑ", "app.switch.onLabel": "ВКЛ", "app.switch.offLabel": "ВЫКЛ", @@ -179,63 +193,71 @@ "app.actionsBar.actionsDropdown.presentationLabel": "Загрузить презентацию", "app.actionsBar.actionsDropdown.initPollLabel": "Ðачать опроÑ", "app.actionsBar.actionsDropdown.desktopShareLabel": "ДемонÑтировать ваш Ñкран", - "app.actionsBar.actionsDropdown.stopDesktopShareLabel": "ОÑтавить демонÑтрацию Ñкрана", + "app.actionsBar.actionsDropdown.stopDesktopShareLabel": "ОÑтановить демонÑтрацию Ñкрана", "app.actionsBar.actionsDropdown.presentationDesc": "Загрузите вашу презентацию", "app.actionsBar.actionsDropdown.initPollDesc": "Ðачать опроÑ", "app.actionsBar.actionsDropdown.desktopShareDesc": "ДемонÑтрировать ваш Ñкран другим учаÑтникам", - "app.actionsBar.actionsDropdown.stopDesktopShareDesc": "Ðе демонÑтрировать ваш Ñкран ", + "app.actionsBar.actionsDropdown.stopDesktopShareDesc": "ОÑтановить демонÑтрацию Ñкрана ", "app.actionsBar.actionsDropdown.startRecording": "Ðачать запиÑÑŒ", "app.actionsBar.actionsDropdown.stopRecording": "ОÑтановить запиÑÑŒ", + "app.actionsBar.emojiMenu.statusTriggerLabel": "УÑтановить ÑтатуÑ", "app.actionsBar.emojiMenu.awayLabel": "Отошел", - "app.actionsBar.emojiMenu.awayDesc": "Изменить ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Отошел\"", + "app.actionsBar.emojiMenu.awayDesc": "ИзменÑет ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Отошел\"", "app.actionsBar.emojiMenu.raiseHandLabel": "ПоднÑть руку", "app.actionsBar.emojiMenu.raiseHandDesc": "ПоднÑть руку, чтобы задать вопроÑ", "app.actionsBar.emojiMenu.neutralLabel": "Ðерешительный", - "app.actionsBar.emojiMenu.neutralDesc": "Изменить ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Ðерешительный\"", + "app.actionsBar.emojiMenu.neutralDesc": "ИзменÑет ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Ðерешительный\"", "app.actionsBar.emojiMenu.confusedLabel": "Смущен", - "app.actionsBar.emojiMenu.confusedDesc": "Изменить ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Смущен\"", + "app.actionsBar.emojiMenu.confusedDesc": "ИзменÑет ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Смущен\"", "app.actionsBar.emojiMenu.sadLabel": "ГруÑтный", - "app.actionsBar.emojiMenu.sadDesc": "Изменить ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"ГруÑтный\"", + "app.actionsBar.emojiMenu.sadDesc": "ИзменÑет ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"ГруÑтный\"", "app.actionsBar.emojiMenu.happyLabel": "СчаÑтливый", - "app.actionsBar.emojiMenu.happyDesc": "Изменить ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"СчаÑтливый\"", - "app.actionsBar.emojiMenu.noneDesc": "ОчиÑтить ваш ÑтатуÑ", + "app.actionsBar.emojiMenu.happyDesc": "ИзменÑет ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"СчаÑтливый\"", + "app.actionsBar.emojiMenu.noneLabel": "ОчиÑтить ÑтатуÑ", + "app.actionsBar.emojiMenu.noneDesc": "Очищает ваш ÑтатуÑ", "app.actionsBar.emojiMenu.applauseLabel": "ÐпплодиÑменты", - "app.actionsBar.emojiMenu.applauseDesc": "Изменить ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"ÐплодиÑменты\"", + "app.actionsBar.emojiMenu.applauseDesc": "ИзменÑет ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"ÐплодиÑменты\"", "app.actionsBar.emojiMenu.thumbsUpLabel": "ÐравитÑÑ", - "app.actionsBar.emojiMenu.thumbsUpDesc": "Изменить ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"ÐравитÑÑ\"", + "app.actionsBar.emojiMenu.thumbsUpDesc": "ИзменÑет ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"ÐравитÑÑ\"", "app.actionsBar.emojiMenu.thumbsDownLabel": "Ðе нравитÑÑ", - "app.actionsBar.emojiMenu.thumbsDownDesc": "Изменить ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Ðе нравитÑÑ\"", + "app.actionsBar.emojiMenu.thumbsDownDesc": "ИзменÑет ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Ðе нравитÑÑ\"", "app.actionsBar.currentStatusDesc": "текущий ÑÑ‚Ð°Ñ‚ÑƒÑ {0}", - "app.audioNotification.audioFailedError1001": "Ошибка 1001: Соединение закрыто", - "app.audioNotification.audioFailedError1002": "Ошибка 1002: невозможно уÑтановить Ñоединение", - "app.audioNotification.audioFailedError1003": "Ошибка 1003: верÑÐ¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð° не поддерживаетÑÑ", - "app.audioNotification.audioFailedError1004": "Ошибка 1004: Failure on call", - "app.audioNotification.audioFailedError1005": "Ошибка 1005: Call ended unexpectedly", - "app.audioNotification.audioFailedError1006": "Ошибка 1006: Call timed out", - "app.audioNotification.audioFailedError1007": "Ошибка 1007: ICE negotiation failed", - "app.audioNotification.audioFailedError1008": "Ошибка 1008: Ñбой передачи", + "app.audioNotification.audioFailedError1001": "Ошибка 1001: WebSocket отключен", + "app.audioNotification.audioFailedError1002": "Ошибка 1002: Ðе удалоÑÑŒ уÑтановить Ñоединение WebSocket", + "app.audioNotification.audioFailedError1003": "Ошибка 1003: ВерÑÐ¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð° не поддерживаетÑÑ", + "app.audioNotification.audioFailedError1004": "Ошибка 1004: Сбой вызова", + "app.audioNotification.audioFailedError1005": "Ошибка 1005: Вызов внезапно прервалÑÑ", + "app.audioNotification.audioFailedError1006": "Ошибка 1006: Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð·Ð¾Ð²Ð° иÑтекло", + "app.audioNotification.audioFailedError1007": "Ошибка 1007: СоглаÑование ICE не ÑоÑтоÑлоÑÑŒ", + "app.audioNotification.audioFailedError1008": "Ошибка 1008: Сбой передачи", "app.audioNotification.audioFailedError1009": "Ошибка 1009: не удалоÑÑŒ получить информацию STUN/TURN Ñервера", - "app.audioNotification.audioFailedError1010": "Ошибка 1010: ICE negotiation timeout", - "app.audioNotification.audioFailedError1011": "Ошибка 1011: ICE gathering timeout", + "app.audioNotification.audioFailedError1010": "Ошибка 1010: Ð’Ñ€ÐµÐ¼Ñ ÑоглаÑÐ¾Ð²Ð°Ð½Ð¸Ñ ICE иÑтекло ", + "app.audioNotification.audioFailedError1011": "Ошибка 1011: Превышено Ð²Ñ€ÐµÐ¼Ñ Ñбора ICE", "app.audioNotification.audioFailedMessage": "Ðе удалоÑÑŒ уÑтановить аудио-Ñоединение", "app.audioNotification.mediaFailedMessage": "Ошибка getUserMicMedia, разрешены только безопаÑные иÑточники", "app.audioNotification.closeLabel": "Закрыть", "app.breakoutJoinConfirmation.title": "ПриÑоединитьÑÑ Ðº комнате групповой работы", "app.breakoutJoinConfirmation.message": "Ð’Ñ‹ хотите приÑоединитьÑÑ Ðº ", "app.breakoutJoinConfirmation.confirmLabel": "ПриÑоединитьÑÑ", - "app.breakoutJoinConfirmation.confirmDesc": "Join you to the Breakout Room", + "app.breakoutJoinConfirmation.confirmDesc": "ПриÑоединÑет Ð²Ð°Ñ Ðº конференции", "app.breakoutJoinConfirmation.dismissLabel": "Отмена", - "app.breakoutJoinConfirmation.dismissDesc": "Закрыть и отменить приÑоединение", + "app.breakoutJoinConfirmation.dismissDesc": "Закрывает и отклонÑет приÑоединение к конференции", + "app.breakoutTimeRemainingMessage": "ОÑтавшееÑÑ Ð²Ñ€ÐµÐ¼Ñ ÐºÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ð¸: {0}", "app.breakoutWillCloseMessage": "Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÑˆÐ»Ð¾. Комната групповой работы Ñкоро закроетÑÑ.", "app.calculatingBreakoutTimeRemaining": "ПодÑчёт оÑтавшегоÑÑ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸...", "app.audioModal.microphoneLabel": "Микрофон", "app.audioModal.listenOnlyLabel": "Только Ñлушать", - "app.audioModal.audioChoiceLabel": "Как вы хотите иÑпользовать звуковое Ñоединение?", + "app.audioModal.audioChoiceLabel": "Как вы хотите войти в аудио-конференцию?", + "app.audioModal.iOSBrowser": "Ðудио/Видео не поддерживаетÑÑ", + "app.audioModal.iOSErrorDescription": "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð°ÑƒÐ´Ð¸Ð¾ и видео не поддерживаютÑÑ Ð² Chrome Ð´Ð»Ñ iOS.", + "app.audioModal.iOSErrorRecommendation": "Мы рекомендуем иÑпользовать Safari Ð´Ð»Ñ iOS.", "app.audioModal.audioChoiceDesc": "Выберите, как учаÑтвовать в аудио-конференции", "app.audioModal.closeLabel": "Закрыть", "app.audioModal.yes": "Да", "app.audioModal.no": "Ðет", - "app.audioModal.echoTestTitle": "Ðто теÑтирование звука, его Ñлышите только вы. Скажите неÑколько Ñлов в микрофон: Ñлышите ли вы ÑÐµÐ±Ñ Ð² динамиках?", + "app.audioModal.yes.arialabel" : "Звучит Ñхо", + "app.audioModal.no.arialabel" : "Ðхо не звучит", + "app.audioModal.echoTestTitle": "Ðто теÑтирование звука, его Ñлышите только вы. Скажите неÑколько Ñлов в микрофон. Слышите ли вы ÑÐµÐ±Ñ Ð² динамиках?", "app.audioModal.settingsTitle": "Изменить наÑтройки звука", "app.audioModal.helpTitle": "Возникли проблемы Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ аудио-уÑтройÑтвами", "app.audioModal.helpText": "Дали ли вы BigBlueButton разрешение на иÑпользование вашего микрофона? Когда вы подключаете аудио, вы должны увидеть диалог запроÑа доÑтупа к аудио-уÑтройÑтвам - вы должны предоÑтавить доÑтуп, чтобы учавÑтвовать в аудио-конференции. ЕÑли Ñтого не произошло, попробуйте изменить наÑтройки доÑтупа к микрофону в наÑтройках вашего браузера.", @@ -247,9 +269,10 @@ "app.audioManager.genericError": "Ошибка: что-то пошло не так, пожалуйÑта, попробуйте еще раз", "app.audioManager.connectionError": "Ошибка: подключение не удалоÑÑŒ", "app.audioManager.requestTimeout": "Ошибка: Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¸Ñтекло", + "app.audioManager.invalidTarget": "Ошибка: Попытка запроÑить что-то от неверной цели", "app.audioManager.mediaError": "Ошибка: возникла проблема Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ аудио-уÑтройÑтвами", - "app.audio.joinAudio": "ПодключитьÑÑ Ðº аудио", - "app.audio.leaveAudio": "Покинуть аудио", + "app.audio.joinAudio": "ПриÑоединитьÑÑ Ðº аудио-конференции", + "app.audio.leaveAudio": "Покинуть аудио-конференцию", "app.audio.enterSessionLabel": "ПодключитьÑÑ Ðº ÑеанÑу", "app.audio.playSoundLabel": "Проиграть звук", "app.audio.backLabel": "Ðазад", @@ -272,16 +295,45 @@ "app.error.403": "ДоÑтуп запрещен", "app.error.leaveLabel": "Зайдите Ñнова", "app.guest.waiting": "Ожидание Ð¾Ð´Ð¾Ð±Ñ€ÐµÐ½Ð¸Ñ Ð²Ñ…Ð¾Ð´Ð°", + "app.toast.breakoutRoomEnded": "ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ð¸Ñ Ð·Ð°ÐºÐ¾Ð½Ñ‡Ð¸Ð»Ð°ÑÑŒ. ПожалуйÑта, приÑоединитеÑÑŒ Ñнова к аудио конференции.", + "app.toast.chat.public": "Ðовое Ñообщение в публичном чате", + "app.toast.chat.private": "Ðовое Ñообщение в приватном чате", + "app.toast.chat.system": "СиÑтема", "app.notification.recordingStart": "Ðтот ÑÐµÐ°Ð½Ñ Ð·Ð°Ð¿Ð¸ÑываетÑÑ", "app.notification.recordingStop": "Ðтот ÑÐµÐ°Ð½Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ не будет запиÑан", - "app.video.joinVideo": "Включить веб-камеру", - "app.video.leaveVideo": "Отключить веб-камеру", + "app.shortcut-help.title": "Клавиши быÑтрого доÑтупа", + "app.shortcut-help.accessKeyNotAvailable": "ДоÑтуп к ключам недоÑтупен.", + "app.shortcut-help.comboLabel": "Комбо", + "app.shortcut-help.functionLabel": "ФункциÑ", + "app.shortcut-help.closeLabel": "Закрыть", + "app.shortcut-help.closeDesc": "Закрывает модальные клавиши быÑтрого доÑтупа", + "app.shortcut-help.openOptions": "Открывает параметры", + "app.shortcut-help.toggleUserList": "Включает ÑпиÑок пользователей", + "app.shortcut-help.toggleMute": "Включает / Выключает микрофон", + "app.shortcut-help.togglePublicChat": "Включает публичный чат (СпиÑок пользователей должен быть открыт)", + "app.shortcut-help.hidePrivateChat": "ПрÑчет приватный чат", + "app.shortcut-help.closePrivateChat": "Закрывает приватный чат", + "app.shortcut-help.openActions": "Открывает меню дейÑтвий", + "app.shortcut-help.openStatus": "Открывает меню ÑтатуÑа", + "app.video.joinVideo": "ТранÑлировать веб-камеру", + "app.video.leaveVideo": "Ðе транÑлировать веб-камеру", + "app.video.iceCandidateError": "Щшибка Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ice кандидата", "app.video.permissionError": "Ошибка. Проверьте разрешение на доÑтуп к веб-камере.", "app.video.sharingError": "Ошибка транÑлÑции веб-камеры", + "app.video.notFoundError": "Ðевозможно найти веб-камеру. ПожалуйÑта, проверте приÑоединена ли она", + "app.video.notAllowed": "ОтÑутÑтвует разрешение на транÑлÑцию веб-камеры, пожалуйÑта, убедитеÑÑŒ, что ваш браузер имеет необходиміе разрешениÑ", + "app.video.notSupportedError": "Можна транÑлировать видео Ñ Ð²ÐµÐ±-камеры только Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñных иÑточников, убедитеÑÑŒ, что ваш Ñертификат SSL дейÑтвителен", + "app.video.notReadableError": "Ðе удалоÑÑŒ получить видео Ñ Ð²ÐµÐ±-камеры. УбедитеÑÑŒ, что Ð´Ñ€ÑƒÐ³Ð°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð° не иÑпользует веб-камеру", + "app.video.mediaServerOffline": "Медиа-Ñервер отключен. ПожалуйÑта, повторите попытку позже.", + "app.video.swapCam": "Заменить", + "app.video.swapCamDesc": "поменÑть направление веб-камер", "app.video.videoMenu": "Меню видео", + "app.video.videoMenuDisabled": "Меню видео веб-камеры отключено в наÑтройках", "app.video.videoMenuDesc": "Открыть выпадающее меню видео", "app.video.chromeExtensionError": "Ð’Ñ‹ должны уÑтановить", "app.video.chromeExtensionErrorLink": "Ñто раÑширение Chrome", + "app.video.stats.title": "СтатиÑтика подключений", + "app.video.stats.packetsReceived": "Полученные пакеты", "app.meeting.endNotification.ok.label": "ОК", "app.whiteboard.toolbar.tools": "ИнÑтрументы", "app.whiteboard.toolbar.tools.pencil": "Карандаш", diff --git a/bigbluebutton-html5/private/locales/uk_UA.json b/bigbluebutton-html5/private/locales/uk_UA.json index b662006f61f57751dbefaa8b99fcf9b37adf7c61..0c4ff779cc9a57cf7e6ec694685a971ba55d9a99 100644 --- a/bigbluebutton-html5/private/locales/uk_UA.json +++ b/bigbluebutton-html5/private/locales/uk_UA.json @@ -3,7 +3,7 @@ "app.chat.submitLabel": "ÐадіÑлати повідомленнÑ", "app.chat.errorMinMessageLength": "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ–Ð· {0} Ñимвола(-ів) занадто коротке", "app.chat.errorMaxMessageLength": "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ–Ð· {0} Ñимвола(-ів) занадто довге", - "app.chat.inputLabel": "Message input for chat {0}", + "app.chat.inputLabel": "Ð’Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ {0}", "app.chat.inputPlaceholder": "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ {0}", "app.chat.titlePublic": "Загальний чат", "app.chat.titlePrivate": "Приватний чат з {0}", @@ -25,28 +25,315 @@ "app.userList.you": "Ви", "app.userList.locked": "Заблокований", "app.userList.label": "СпиÑок кориÑтувачів", + "app.userList.toggleCompactView.label": "Увімкнути/вимкнути компактний вид", + "app.userList.guest": "ГіÑть", + "app.userList.menuTitleContext": "ДоÑтупні опції", + "app.userList.chatListItem.unreadSingular": "{0} нове повідомленнÑ", + "app.userList.chatListItem.unreadPlural": "{0} нових повідомлень", + "app.userList.menu.chat.label": "Чат", + "app.userList.menu.clearStatus.label": "ОчиÑтити ÑтатуÑ", + "app.userList.menu.makePresenter.label": "Зробити ведучим", + "app.userList.menu.removeUser.label": "Виключити кориÑтувача", + "app.userList.menu.muteUserAudio.label": "Вимкнути мікрофон кориÑтувача", + "app.userList.menu.unmuteUserAudio.label": "Увімкнути мікрофон кориÑтувача", + "app.userList.userAriaLabel": "{0} {1} {2} Ð¡Ñ‚Ð°Ñ‚ÑƒÑ {3}", + "app.userList.menu.promoteUser.label": "Підвищити {0} до модератора", + "app.userList.menu.demoteUser.label": "Понизити {0} до глÑдача", + "app.media.label": "МедіÑ", + "app.media.screenshare.start": "ДемонÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ ÐµÐºÑ€Ð°Ð½Ñƒ розпочалаÑÑ", + "app.media.screenshare.end": "ДемонÑтрацію екрану закінчено", + "app.media.screenshare.safariNotSupported": "ДемонÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ ÐµÐºÑ€Ð°Ð½Ñƒ наразі не підтримуєтьÑÑ Safari. Будь лаÑка, викориÑтовуйте Firefox або Google Chrome.", + "app.meeting.ended": "Ð¦Ñ ÑеÑÑ–Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ð»Ð°ÑÑ", + "app.meeting.endedMessage": "Ви будете перенаправлені на головний екран", "app.presentation.presentationToolbar.prevSlideLabel": "Попередній Ñлайд", + "app.presentation.presentationToolbar.prevSlideDesc": "Перемкнути презентацію на попередній Ñлайд", "app.presentation.presentationToolbar.nextSlideLabel": "ÐаÑтупний Ñлайд", - "app.presentation.presentationToolbar.zoomLabel": "МаÑштаб презентації", + "app.presentation.presentationToolbar.nextSlideDesc": "Перемкнути презентацію на наÑтупний Ñлайд", + "app.presentation.presentationToolbar.skipSlideLabel": "ПропуÑтити Ñлайд", + "app.presentation.presentationToolbar.skipSlideDesc": "Перемкнути презентацію на вказаний Ñлайд", + "app.presentation.presentationToolbar.fitWidthLabel": "Підігнати по ширині", + "app.presentation.presentationToolbar.fitWidthDesc": "Показати вÑÑŽ ширину Ñлайда", + "app.presentation.presentationToolbar.fitScreenLabel": "Підігнати до екрана", + "app.presentation.presentationToolbar.fitScreenDesc": "Показати веÑÑŒ Ñлайд", + "app.presentation.presentationToolbar.zoomLabel": "МаÑштаб", + "app.presentation.presentationToolbar.zoomDesc": "Змінити маÑштаб презентації", + "app.presentation.presentationToolbar.goToSlide": "Слайд {0}", + "app.presentationUploder.title": "ПрезентаціÑ", + "app.presentationUploder.message": "Як ведучий у BigBlueButton, ви маєте можливіÑть завантажувати будь-Ñкий офіÑний документ або файл PDF. Ми рекомендуємо завантажувати файл PDF Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð½Ð°Ð¹ÐºÑ€Ð°Ñ‰Ð¸Ñ… результатів.", + "app.presentationUploder.confirmLabel": "Почати", + "app.presentationUploder.confirmDesc": "Зберегти зміни та розпочати презентацію", + "app.presentationUploder.dismissLabel": "Відмінити", + "app.presentationUploder.dismissDesc": "Закрити вікно Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° ÑкаÑувати зміни", + "app.presentationUploder.dropzoneLabel": "ПеретÑгніть файли Ñюди, щоб завантажити", + "app.presentationUploder.browseFilesLabel": "або виберіть файл", + "app.presentationUploder.fileToUpload": "Щоб завантажити", + "app.presentationUploder.currentBadge": "Поточний", + "app.presentationUploder.genericError": "Ой, щоÑÑŒ пішло не так", + "app.presentationUploder.upload.progress": "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ({0}%)", + "app.presentationUploder.upload.413": "Файл занадто великий", + "app.presentationUploder.conversion.conversionProcessingSlides": "Обробка Ñторінки {0} з {1}", + "app.presentationUploder.conversion.genericConversionStatus": "Файл конвертуєтьÑÑ...", + "app.presentationUploder.conversion.generatingThumbnail": "Ð“ÐµÐ½ÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ñ–Ð½Ñ–Ð°Ñ‚ÑŽÑ€...", + "app.presentationUploder.conversion.generatedSlides": "Слайди генеруютьÑÑ...", + "app.presentationUploder.conversion.generatingSvg": "Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ñ–Ñ Ñлайдів SVG...", + "app.presentationUploder.conversion.pageCountExceeded": "Ой, кількіÑть Ñторінок перевищила ліміт", + "app.presentationUploder.conversion.timeout": "Ой, Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¹Ð¼Ð°Ñ” надто багато чаÑу", + "app.polling.pollingTitle": "Варіанти опитуваннÑ", + "app.polling.pollAnswerLabel": "Результат Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ {0}", + "app.polling.pollAnswerDesc": "Виберіть цей варіант щоб проголоÑувати за {0}", + "app.failedMessage": "Вибачте, проблеми з підключеннÑм до Ñервера.", "app.connectingMessage": "З'єднаннÑ...", + "app.waitingMessage": "Втрачено з'еднаннÑ. Спроба повторного Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· {0} Ñекунд...", "app.navBar.settingsDropdown.optionsLabel": "Опції", - "app.navBar.settingsDropdown.settingsLabel": "Відкрити наÑтройки", + "app.navBar.settingsDropdown.fullscreenLabel": "Розгорнути на веÑÑŒ екран", + "app.navBar.settingsDropdown.settingsLabel": "Відкрити параметри", "app.navBar.settingsDropdown.aboutLabel": "Про програму", "app.navBar.settingsDropdown.leaveSessionLabel": "Вихід", - "app.navBar.settingsDropdown.settingsDesc": "Змінити загальні наÑтройки", - "app.navBar.settingsDropdown.aboutDesc": "Show information about the client", + "app.navBar.settingsDropdown.exitFullscreenLabel": "Вийти з повноекранного режиму", + "app.navBar.settingsDropdown.fullscreenDesc": "Розгорнути меню параметрів на веÑÑŒ екран", + "app.navBar.settingsDropdown.settingsDesc": "Змінити загальні параметри", + "app.navBar.settingsDropdown.aboutDesc": "Показати інформацію про клієнта", "app.navBar.settingsDropdown.leaveSessionDesc": "Залишити конференцію", + "app.navBar.settingsDropdown.exitFullscreenDesc": "Вийти з повноекранного режиму", + "app.navBar.settingsDropdown.hotkeysLabel": "Швидкі клавіши", + "app.navBar.settingsDropdown.hotkeysDesc": "Перелік наÑвних швидких клавіш", + "app.navBar.userListToggleBtnLabel": "Увімкнути/вимкнути ÑпиÑок кориÑтувачів", + "app.navBar.toggleUserList.ariaLabel": "Увімкнути/вимкнути КориÑтувачів та ПовідомленнÑ", + "app.navBar.toggleUserList.newMessages": "зі ÑповіщеннÑм про нове повідомленнÑ", + "app.navBar.recording": "Ð¦Ñ ÑеÑÑ–Ñ Ð·Ð°Ð¿Ð¸ÑуєтьÑÑ", + "app.navBar.recording.on": "ЗапиÑуєтьÑÑ", + "app.navBar.recording.off": "Ðе запиÑуєтьÑÑ", "app.leaveConfirmation.title": "Залишити ÑеÑÑ–ÑŽ", "app.leaveConfirmation.message": "Ви впевнені, що хочете залишити цю конференцію?", - "app.leaveConfirmation.confirmLabel": "Вихід", + "app.leaveConfirmation.confirmLabel": "Вийти", + "app.leaveConfirmation.confirmDesc": "Вийти з конференції", "app.leaveConfirmation.dismissLabel": "Відміна", + "app.leaveConfirmation.dismissDesc": "Закриває та відхилÑÑ” Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ вихід", + "app.leaveConfirmation.endMeetingLabel": "Так, залишити ÑеÑÑ–ÑŽ", + "app.leaveConfirmation.endMeetingAriaLabel": "Покинути та завершити ÑеÑÑ–ÑŽ", + "app.leaveConfirmation.endMeetingDesc": "Підтвердити Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ñ–Ñ—", "app.about.title": "Про програму", + "app.about.version": "Збірка клієнта:", "app.about.copyright": "ÐвторÑьке право:", + "app.about.confirmLabel": "OK", + "app.about.confirmDesc": "OK", "app.about.dismissLabel": "Відміна", + "app.about.dismissDesc": "Закрити інформацію про клієнта", "app.actionsBar.changeStatusLabel": "Змінити ÑтатуÑ", "app.actionsBar.muteLabel": "Вимкнути мікрофон", "app.actionsBar.unmuteLabel": "Увімкнути мікрофон", - "app.actionsBar.camOffLabel": "Вимкнути камеру" + "app.actionsBar.camOffLabel": "Вимкнути камеру", + "app.actionsBar.raiseLabel": "ПіднÑти", + "app.actionsBar.label": "Панель дій", + "app.submenu.application.applicationSectionTitle": "ЗаÑтоÑунок", + "app.submenu.application.audioNotifyLabel": "Ðудіо ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‡Ð°Ñ‚Ñƒ", + "app.submenu.application.pushNotifyLabel": "Push-ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ", + "app.submenu.application.fontSizeControlLabel": "Розмір шрифту", + "app.submenu.application.increaseFontBtnLabel": "Збільшити шрифт заÑтоÑунку", + "app.submenu.application.decreaseFontBtnLabel": "Зменшити шрифт заÑтоÑунку", + "app.submenu.application.languageLabel": "Мова заÑтоÑунку", + "app.submenu.application.ariaLanguageLabel": "Змінити мову заÑтоÑунку", + "app.submenu.application.languageOptionLabel": "Вибрати мову", + "app.submenu.application.noLocaleOptionLabel": "ВідÑутні доÑтупні переклади", + "app.submenu.audio.micSourceLabel": "Джерело мікрофона", + "app.submenu.audio.speakerSourceLabel": "Джерело динаміків", + "app.submenu.audio.streamVolumeLabel": "ГучніÑть аудіо потоку", + "app.submenu.video.title": "Відео", + "app.submenu.video.videoSourceLabel": "Джерело відео", + "app.submenu.video.videoOptionLabel": "Виберіть джерело відео", + "app.submenu.video.videoQualityLabel": "ЯкіÑть відео", + "app.submenu.video.qualityOptionLabel": "Виберіть ÑкіÑть відео", + "app.submenu.video.participantsCamLabel": "ПереглÑд веб-камер учаÑників", + "app.submenu.closedCaptions.closedCaptionsLabel": "Субтитри", + "app.submenu.closedCaptions.takeOwnershipLabel": "Перехопити", + "app.submenu.closedCaptions.languageLabel": "Мова", + "app.submenu.closedCaptions.localeOptionLabel": "Виберіть мову", + "app.submenu.closedCaptions.noLocaleOptionLabel": "ВідÑутні доÑтупні переклади", + "app.submenu.closedCaptions.fontFamilyLabel": "Шрифт", + "app.submenu.closedCaptions.fontFamilyOptionLabel": "Виберіть шрифт", + "app.submenu.closedCaptions.fontSizeLabel": "Розмір шрифту", + "app.submenu.closedCaptions.fontSizeOptionLabel": "Виберіть розмір шрифту", + "app.submenu.closedCaptions.backgroundColorLabel": "Колір фону", + "app.submenu.closedCaptions.fontColorLabel": "Колір шрифта", + "app.submenu.participants.muteAllLabel": "Вимкнути мікрофони у вÑÑ–Ñ… окрім ведучого", + "app.submenu.participants.lockAllLabel": "Заблокувати вÑÑ–Ñ… учаÑників", + "app.submenu.participants.lockItemLabel": "УчаÑники {0}", + "app.submenu.participants.lockMicDesc": "Вимикає мікрофони уÑÑ–Ñ… заблокованих учаÑників", + "app.submenu.participants.lockCamDesc": "Вимикає веб-камери уÑÑ–Ñ… заблокованих учаÑників", + "app.submenu.participants.lockPublicChatDesc": "Вимикає загальний чат Ð´Ð»Ñ ÑƒÑÑ–Ñ… заблокованих учаÑників", + "app.submenu.participants.lockPrivateChatDesc": "Вимикає приватний чат Ð´Ð»Ñ ÑƒÑÑ–Ñ… заблокованих учаÑників", + "app.submenu.participants.lockLayoutDesc": "Блокує Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–ÐºÐ¾Ð½ Ð´Ð»Ñ ÑƒÑÑ–Ñ… заблокованих учаÑників", + "app.submenu.participants.lockMicAriaLabel": "Блокувати мікрофон", + "app.submenu.participants.lockCamAriaLabel": "Блокувати веб-камеру", + "app.submenu.participants.lockPublicChatAriaLabel": "Блокувати публічний чат", + "app.submenu.participants.lockPrivateChatAriaLabel": "Блокувати приватний чат", + "app.submenu.participants.lockLayoutAriaLabel": "Блокувати Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–ÐºÐ¾Ð½", + "app.submenu.participants.lockMicLabel": "Мікрофон", + "app.submenu.participants.lockCamLabel": "Веб-камера", + "app.submenu.participants.lockPublicChatLabel": "Публічний чат", + "app.submenu.participants.lockPrivateChatLabel": "Приватний чат", + "app.submenu.participants.lockLayoutLabel": "Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–ÐºÐ¾Ð½", + "app.settings.applicationTab.label": "ЗаÑтоÑунок", + "app.settings.audioTab.label": "Ðудіо", + "app.settings.videoTab.label": "Відео", + "app.settings.closedcaptionTab.label": "Субтитри", + "app.settings.usersTab.label": "УчаÑники", + "app.settings.main.label": "ÐалаштуваннÑ", + "app.settings.main.cancel.label": "Відмінити", + "app.settings.main.cancel.label.description": "ВідмінÑÑ” зміни та закриває меню налаштувань", + "app.settings.main.save.label": "Зберегти", + "app.settings.main.save.label.description": "Зберігає зміни та закриває меню налаштувань", + "app.settings.dataSavingTab.label": "Ð—Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ…", + "app.settings.dataSavingTab.webcam": "Увімкнути веб-камери", + "app.settings.dataSavingTab.screenShare": "Увімкнути демонÑтрацію робочого Ñтолу", + "app.settings.dataSavingTab.description": "Щоб зберегти пропуÑкну здатніÑть, виберіть що зараз буде відображатиÑÑŒ.", + "app.switch.onLabel": "УВІМК.", + "app.switch.offLabel": "ВИМК.", + "app.actionsBar.actionsDropdown.actionsLabel": "Дії", + "app.actionsBar.actionsDropdown.presentationLabel": "Завантажити презентацію", + "app.actionsBar.actionsDropdown.initPollLabel": "Розпочати опитуваннÑ", + "app.actionsBar.actionsDropdown.desktopShareLabel": "ДемонÑтрувати ваш екран", + "app.actionsBar.actionsDropdown.stopDesktopShareLabel": "Зупинити демонÑтрацію екрану", + "app.actionsBar.actionsDropdown.presentationDesc": "Завантажити вашу презентацію", + "app.actionsBar.actionsDropdown.initPollDesc": "Розпочати опитуваннÑ", + "app.actionsBar.actionsDropdown.desktopShareDesc": "ДемонÑтрувати ваш екран іншим учаÑникам", + "app.actionsBar.actionsDropdown.stopDesktopShareDesc": "Зупинити демонÑтрацію екрану", + "app.actionsBar.actionsDropdown.startRecording": "Почати запиÑ", + "app.actionsBar.actionsDropdown.stopRecording": "Зупинити запиÑ", + "app.actionsBar.emojiMenu.statusTriggerLabel": "Ð’Ñтановити ÑтатуÑ", + "app.actionsBar.emojiMenu.awayLabel": "Відійшов", + "app.actionsBar.emojiMenu.awayDesc": "Змінює ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Відійшов\"", + "app.actionsBar.emojiMenu.raiseHandLabel": "ПіднÑти руку", + "app.actionsBar.emojiMenu.raiseHandDesc": "ПіднÑти руку щоб поÑтавити питаннÑ", + "app.actionsBar.emojiMenu.neutralLabel": "Ðе визначивÑÑ", + "app.actionsBar.emojiMenu.neutralDesc": "Змінює ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Ðе визначивÑÑ\"", + "app.actionsBar.emojiMenu.confusedLabel": "Збентежений", + "app.actionsBar.emojiMenu.confusedDesc": "Змінює ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Збентежений\"", + "app.actionsBar.emojiMenu.sadLabel": "Сумний", + "app.actionsBar.emojiMenu.sadDesc": "Змінює ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Сумний\"", + "app.actionsBar.emojiMenu.happyLabel": "ЩаÑливий", + "app.actionsBar.emojiMenu.happyDesc": "Змінює ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"ЩаÑливий\"", + "app.actionsBar.emojiMenu.noneLabel": "ОчиÑтити ÑтатуÑ", + "app.actionsBar.emojiMenu.noneDesc": "Очищує ваш ÑтатуÑ", + "app.actionsBar.emojiMenu.applauseLabel": "ОплеÑки", + "app.actionsBar.emojiMenu.applauseDesc": "Змінює ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"ОплеÑки\"", + "app.actionsBar.emojiMenu.thumbsUpLabel": "ПодобаєтьÑÑ", + "app.actionsBar.emojiMenu.thumbsUpDesc": "Змінює ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"ПодобаєтьÑÑ\"", + "app.actionsBar.emojiMenu.thumbsDownLabel": "Ðе подобаєтьÑÑ", + "app.actionsBar.emojiMenu.thumbsDownDesc": "Змінює ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° \"Ðе подобаєтьÑÑ\"", + "app.actionsBar.currentStatusDesc": "нинішній ÑÑ‚Ð°Ñ‚ÑƒÑ {0}", + "app.audioNotification.audioFailedError1001": "Помилка 1001: WebSocket відключено", + "app.audioNotification.audioFailedError1002": "Помилка 1002: Ðе вдалоÑÑŒ вÑтановити з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ WebSocket", + "app.audioNotification.audioFailedError1003": "Помилка 1003: ВерÑÑ–Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð° не підтримуєтьÑÑ", + "app.audioNotification.audioFailedError1004": "Помилка 1004: Збій виклика", + "app.audioNotification.audioFailedError1005": "Помилка 1005: Виклик раптово перервавÑÑ", + "app.audioNotification.audioFailedError1006": "Помилка 1006: Ð§Ð°Ñ Ð´Ð·Ð²Ñ–Ð½ÐºÐ° минув", + "app.audioNotification.audioFailedError1007": "Помилка 1007: Ð£Ð·Ð³Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ ICE не відбулоÑÑŒ", + "app.audioNotification.audioFailedError1008": "Помилка 1008: Передача не вдалаÑÑŒ", + "app.audioNotification.audioFailedError1009": "Помилка 1009: Ðе вдалоÑÑŒ отримати STUN/TURN інформацію з Ñерверу", + "app.audioNotification.audioFailedError1010": "Помилка 1010: Ð§Ð°Ñ ÑƒÐ·Ð³Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ ICE вичерпано", + "app.audioNotification.audioFailedError1011": "Помилка 1011: Перевищено Ñ‡Ð°Ñ Ð·Ð±Ð¾Ñ€Ñƒ ICE", + "app.audioNotification.audioFailedMessage": "Ðе вдалоÑÑ Ð²Ñтановити аудіо з'єднаннÑ", + "app.audioNotification.mediaFailedMessage": "Помилка getUserMicMedia, дозволені тільки безпечні джерела", + "app.audioNotification.closeLabel": "Закрити", + "app.breakoutJoinConfirmation.title": "ПриєднатиÑÑŒ до зуÑтрічі", + "app.breakoutJoinConfirmation.message": "Чи хочете ви приєднатиÑÑ Ð´Ð¾", + "app.breakoutJoinConfirmation.confirmLabel": "ПриєднатиÑÑ", + "app.breakoutJoinConfirmation.confirmDesc": "Приєднує Ð²Ð°Ñ Ð´Ð¾ зуÑтрічі", + "app.breakoutJoinConfirmation.dismissLabel": "СкаÑувати", + "app.breakoutJoinConfirmation.dismissDesc": "Закриває та відмовлÑÑ” в приєднанні до зуÑтрічі", + "app.breakoutTimeRemainingMessage": "Ð§Ð°Ñ Ð´Ð¾ Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ñ–Ñ—: {0}", + "app.breakoutWillCloseMessage": "Ð§Ð°Ñ Ð²Ð¸Ñ‡ÐµÑ€Ð¿Ð°Ð½Ð¾. Конференцію невдовзі буде закрито", + "app.calculatingBreakoutTimeRemaining": "Підрахунок чаÑу що залишивÑÑ...", + "app.audioModal.microphoneLabel": "Мікрофон", + "app.audioModal.listenOnlyLabel": "Тільки Ñлухати", + "app.audioModal.audioChoiceLabel": "Як ви хочете увійти в аудіо-конференцію?", + "app.audioModal.iOSBrowser": "Ðудіо/Відео не підтримуєтьÑÑ", + "app.audioModal.iOSErrorDescription": "Ðаразі аудіо та відео в Chrome Ð´Ð»Ñ iOS не підтримуютьÑÑ.", + "app.audioModal.iOSErrorRecommendation": "Ми рекомендуємо викориÑтовувати Safari Ð´Ð»Ñ iOS.", + "app.audioModal.audioChoiceDesc": "Виберіть Ñк брати учаÑть в аудіоконференції", + "app.audioModal.closeLabel": "Закрити", + "app.audioModal.yes": "Так", + "app.audioModal.no": "ÐÑ–", + "app.audioModal.yes.arialabel" : "Звучить ехо", + "app.audioModal.no.arialabel" : "Ехо не звучить", + "app.audioModal.echoTestTitle": "Це приватний ехо-теÑÑ‚. Промовте кілька Ñлів. Чи чуєте ви Ñебе в динаміках?", + "app.audioModal.settingsTitle": "Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð°ÑƒÐ´Ñ–Ð¾", + "app.audioModal.helpTitle": "З'ÑвилиÑÑ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ з вашими аудіоприладами", + "app.audioModal.helpText": "Чи надали ви BigBlueButton дозвіл на доÑтуп до мікрофона? Зверніть увагу що коли ви намагаєтеÑÑ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑ Ð´Ð¾ аудіоконференції має з'ÑвитиÑÑ Ð´Ñ–Ð°Ð»Ð¾Ð³Ð¾Ð²Ðµ вікно запитуючи дозволи на Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¼ÐµÐ´Ñ–Ð°-приÑтрою, будь лаÑка, прийміть це, щоб приєднатиÑÑ Ð´Ð¾ аудіоконференції. Якщо цього не відбулоÑÑ Ñпробуйте змінити дозволи мікрофона у налаштуваннÑÑ… вашого веб-переглÑдача.", + "app.audioModal.connecting": "ПідключеннÑ", + "app.audioModal.connectingEchoTest": "ÐŸÑ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ ехо теÑту", + "app.audioManager.joinedAudio": "Ви приєдналиÑÑ Ð´Ð¾ аудіоконференції", + "app.audioManager.joinedEcho": "Ви приєдналиÑÑ Ð´Ð¾ ехо теÑту", + "app.audioManager.leftAudio": "Ви покинули аудіо конференцію", + "app.audioManager.genericError": "Помилка: ЩоÑÑŒ пішло не так, будь лаÑка, Ñпробуйте ще раз", + "app.audioManager.connectionError": "Помилка: ÐŸÑ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð½Ðµ вдалоÑÑ", + "app.audioManager.requestTimeout": "Помилка: Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð²Ð¸Ñ‡ÐµÑ€Ð¿Ð°Ð½Ð¾", + "app.audioManager.invalidTarget": "Помилка: Спроба запроÑити що-небудь від невірної цілі", + "app.audioManager.mediaError": "Помилка: Виникли проблеми з вашими аудіоприÑтроÑми", + "app.audio.joinAudio": "ПриєднатиÑÑ Ð´Ð¾ аудіоконференції", + "app.audio.leaveAudio": "Залишити аудіоконференцію", + "app.audio.enterSessionLabel": "ПідключитиÑÑ Ð´Ð¾ ÑеанÑу", + "app.audio.playSoundLabel": "Програти звук", + "app.audio.backLabel": "Ðазад", + "app.audio.audioSettings.titleLabel": "Виберіть Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð²ÑƒÐºÑƒ", + "app.audio.audioSettings.descriptionLabel": "Зверніть увагу, що в вашому браузері з'ÑвитьÑÑ Ð´Ñ–Ð°Ð»Ð¾Ð³Ð¾Ð²Ðµ вікно, що вимагає дозволу вашого мікрофона.", + "app.audio.audioSettings.microphoneSourceLabel": "Джерело мікрофона", + "app.audio.audioSettings.speakerSourceLabel": "Джерело динаміків", + "app.audio.audioSettings.microphoneStreamLabel": "ГучніÑть вашого аудіопотоку", + "app.audio.audioSettings.retryLabel": "Повторити", + "app.audio.listenOnly.backLabel": "Ðезад", + "app.audio.listenOnly.closeLabel": "Закрити", + "app.audio.permissionsOverlay.title": "Дозволити BigBlueButton викориÑтовувати ваші медіа-приÑтрої", + "app.audio.permissionsOverlay.hint": "Ðам потрібно, щоб ви дозволили нам викориÑтовувати Ñвої медіа-приÑтрої, щоб приєднатиÑÑŒ до голоÑової конференції :)", + "app.error.removed": "Ви були вилучені з конференції", + "app.error.meeting.ended": "Ви вийшли з конференції", + "app.dropdown.close": "Закрити", + "app.error.500": "Ой, щоÑÑŒ пішло не так", + "app.error.404": "Ðе знайдено", + "app.error.401": "Ðеавторизований", + "app.error.403": "Заборонено", + "app.error.leaveLabel": "Увійдіть знову", + "app.guest.waiting": "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ", + "app.toast.breakoutRoomEnded": "ÐšÐ¾Ð½Ñ„ÐµÑ€ÐµÐ½Ñ†Ñ–Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ð»Ð°ÑÑ. Будь лаÑка, приєднайтеÑÑŒ знову до аудіо конференції.", + "app.toast.chat.public": "Ðове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð² публічному чаті", + "app.toast.chat.private": "Ðове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð² приватному чаті", + "app.toast.chat.system": "СиÑтема", + "app.notification.recordingStart": "Цей ÑÐµÐ°Ð½Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– запиÑуєтьÑÑ", + "app.notification.recordingStop": "Цей ÑÐµÐ°Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆÐµ не запиÑуєтьÑÑ", + "app.shortcut-help.title": "Клавіші швидкого доÑтупу", + "app.shortcut-help.accessKeyNotAvailable": "Ключі доÑтупу недоÑтупні.", + "app.shortcut-help.comboLabel": "Комбо", + "app.shortcut-help.functionLabel": "ФункціÑ", + "app.shortcut-help.closeLabel": "Закрити", + "app.shortcut-help.closeDesc": "Закриває модальні клавіші швидкого доÑтупу", + "app.shortcut-help.openOptions": "Відкриває параметри", + "app.shortcut-help.toggleUserList": "Вмикає ÑпиÑок кориÑтувачів", + "app.shortcut-help.toggleMute": "Вмикає / Вимикає мікрофон", + "app.shortcut-help.togglePublicChat": "Вмикає публічеий чат (СпиÑок кориÑтувачів має бути відкитим)", + "app.shortcut-help.hidePrivateChat": "Приховує приватний чат", + "app.shortcut-help.closePrivateChat": "Закриває приватний чат", + "app.shortcut-help.openActions": "Відкриває меню дій", + "app.shortcut-help.openStatus": "Відкриває меню ÑтатуÑу", + "app.video.joinVideo": "ТранÑлювати веб-камеру", + "app.video.leaveVideo": "Припинити транÑлювати веб-камеру", + "app.video.iceCandidateError": "Помилка при додаванні ice кандидата", + "app.video.permissionError": "Помилка при транÑлÑції веб-камерию Будь лаÑка перевірте дозволи", + "app.video.sharingError": "Помилка при транÑлÑції веб-камери", + "app.video.notFoundError": "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ веб-камеру. ПереконайтеÑÑ, що вона під'єднана", + "app.video.notAllowed": "ВідÑутній дозвіл на транÑлÑцію веб-камери, будь лаÑка, переконайтеÑÑ, що ваш браузер має необхідні дозволи", + "app.video.notSupportedError": "Можна транÑлювати веб-камеру лише з безпечних джерел, переконайтеÑÑ, що Ñертифікат SSL дійÑний", + "app.video.notReadableError": "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ відео з веб-камери. Будь лаÑка, переконайтеÑÑ, що інша програма не викориÑтовує веб-камеру", + "app.video.mediaServerOffline": "МедіаÑервер відключено. Будь-лаÑка Ñпробуйте ще раз пізніше.", + "app.video.swapCam": "Змінити", + "app.video.swapCamDesc": "помінÑти напрÑмок веб-камер", + "app.video.videoMenu": "Меню відео", + "app.video.videoMenuDisabled": "Меню відео веб-камера відключено в налаштуваннÑÑ…", + "app.video.videoMenuDesc": "Відкрити контекÑтне меню відео", + "app.video.chromeExtensionError": "Ви маєте вÑтановити", + "app.video.chromeExtensionErrorLink": "Це Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Chrome", + "app.video.stats.title": "СтатиÑтика з'єднань", + "app.video.stats.packetsReceived": "Пакети отримані" }