diff --git a/bigbluebutton-html5/client/langprovider.jsx b/bigbluebutton-html5/client/langprovider.jsx new file mode 100755 index 0000000000000000000000000000000000000000..71328523c3cf5ac98bef542a86bfce07553a0861 --- /dev/null +++ b/bigbluebutton-html5/client/langprovider.jsx @@ -0,0 +1,58 @@ +import React, { Component, PropTypes } from 'react'; +import { IntlProvider } from 'react-intl'; +import { loadMessages } from './services'; +import { renderRoutes } from '../imports/startup/client/routes.js'; +import Locales from '../imports/locales'; + +//Set the defaultLocale below for all <FormattedMessage /> default messages. +//The corresponding locale must be exported in /imports/locales/index.js +let defaultLocale = "en"; + +let defaultMsgs, newMsgs; +let msgsUpdated = false, flag = true; + +let browserLang = navigator.language.split('-'); +let langRegion = browserLang[0] + "-" + browserLang[1].toUpperCase(); +let lang = browserLang[0], region = browserLang[1].toUpperCase(); + +defaultMsgs = Locales[defaultLocale]; + +if(langRegion == defaultLocale || lang == defaultLocale){ + flag = false; +} + +class LangProvider extends Component { + constructor(props) { + super(props); + this.state = {}; + } + + updateMessages(msgs){ + let updatedMsgs = loadMessages(msgs, defaultLocale, lang, langRegion); + return updatedMsgs; + } + + render() { + while(flag){ + newMsgs = this.updateMessages(defaultMsgs); + flag = false; + msgsUpdated = true; + } + + let passLocale, passMsgs; + + if(msgsUpdated){ + passLocale=newMsgs[0]; passMsgs=newMsgs[1]; + }else{ + passLocale=defaultLocale; passMsgs=defaultMsgs; + } + + return ( + <IntlProvider locale={passLocale} messages={passMsgs}> + {renderRoutes()} + </IntlProvider> + ); + } +} + +export default LangProvider; diff --git a/bigbluebutton-html5/client/main.jsx b/bigbluebutton-html5/client/main.jsx index 95002c1a2b43020a592d46d8e5560458de8b1f7b..6faf1f18281f6fb1c3788040ff763c55d75fa1bf 100755 --- a/bigbluebutton-html5/client/main.jsx +++ b/bigbluebutton-html5/client/main.jsx @@ -2,26 +2,10 @@ import React from 'react'; import { Meteor } from 'meteor/meteor'; import { render } from 'react-dom'; import { renderRoutes } from '../imports/startup/client/routes.js'; -import { IntlProvider, addLocaleData } from 'react-intl'; +import { IntlProvider } from 'react-intl'; -import Locales from '../imports/locales'; +import LangProvider from './langprovider'; -import en from 'react-intl/locale-data/en'; -import es from 'react-intl/locale-data/es'; -import pt from 'react-intl/locale-data/pt'; - -/* TODO: Add this dynamically */ -addLocaleData([...en, ...es, ...pt]); - -// Safari sends us en-us instead of en-US -let locale = navigator.language.split('-'); -locale = locale[1] ? `${locale[0]}-${locale[1].toUpperCase()}` : navigator.language; - -// locale = 'pt-BR'; // Set a locale for testing - -/* TODO: We should load the en first then merge with the en-US - (eg: load country translation then region) */ -let messages = Locales[locale] || Locales.en || {}; // Helper to load javascript libraries from the BBB server function loadLib(libname, success, fail) { @@ -55,8 +39,6 @@ Meteor.startup(() => { loadLib('jquery.jsonrpcclient.js'); render(( - <IntlProvider locale={locale} messages={messages}> - {renderRoutes()} - </IntlProvider> + <LangProvider /> ), document.getElementById('app')); }); diff --git a/bigbluebutton-html5/client/services.js b/bigbluebutton-html5/client/services.js new file mode 100755 index 0000000000000000000000000000000000000000..93a973436eb6b0fbf3cb65754eca903874dcd889 --- /dev/null +++ b/bigbluebutton-html5/client/services.js @@ -0,0 +1,85 @@ +import { Meteor } from 'meteor/meteor'; +import Locales from '../imports/locales'; + +var extend = require('util')._extend; + +function loadMessages(defaultMsgs, defaultLocale, lang, langRegion) { + let newMessages; + let langOnly = false, langRegionOnly = false; + //let localeFound = false, attempted = false; + + + //pt_BR is used for testing. + let pt_BR = { + "app.home.greeting": "Bem-vindo {name}! Sua aprensentação começará em breve...", + "app.userlist.participantsTitle": "Participantes", + "app.userlist.messagesTitle": "Mensagens", + "app.userlist.presenter": "Apresentador", + "app.userlist.you": "Você", + "app.chat.submitLabel": "Enviar Mensagem", + "app.chat.inputLabel": "Campo de mensagem para conversa {name}", + "app.chat.titlePublic": "Conversa PublÃca", + "app.chat.titlePrivate": "Conversa Privada com {name}", + "app.chat.partnerDisconnected": "{name} saiu da sala", + "app.chat.moreMessages": "Mais mensagens abaixo", + "app.kickMessage": "Você foi expulso da apresentação", + "app.failedMessage": "Desculpas, estamos com problemas para se conectar ao servidor.", + "app.connectingMessage": "Conectando...", + "app.waitingMessage": "Desconectado. Tentando reconectar em {seconds} segundos..." + } + + + + //TODO: get ajax calls to work, issue is with the url. doesnt have access to locale .json files + /* + while(!localeFound && !attempted){ + $.ajax({ + type: 'GET', + url: `http://192.168.32.128/bigbluebutton/${langRegion}.json`, + dataType: 'json', + success: function (data) { + //alert("SUCCESS::> " + data); + newMessages = data; + attempted = true; + localeFound = true; + langRegionOnly = true; + }, + error: function (result) { + alert("Error: Not found, Checking backup"); + $.ajax({ + type: 'GET', + url: `http://192.168.32.128/bigbluebutton/${lang}.json`, + dataType: 'json', + success: function (data) { + //alert("SUCCESS::> " + data); + newMessages = data; + attempted = true; + localeFound = true; + langOnly = true; + }, + error: function (result) { + alert("Error: Locale not found, Using Default"); + }, + }); + }, + }); + attempted = true; + } + */ + + var combined = extend(defaultMsgs, newMessages); + //var combined = extend(defaultMsgs, pt_BR); + + let results = []; + if(langOnly){ + results = [lang, combined]; + }else if (langRegionOnly) { + results = [langRegion, combined]; + }else{ + results = [defaultLocale, combined]; + } + + return results; +} + +export {loadMessages}; diff --git a/bigbluebutton-html5/imports/locales/en.json b/bigbluebutton-html5/imports/locales/en.json index be78a5d8bc2a35c25ff8acce48836e1555bc978d..4183f0b30e5dd0ca56c0bcbf8ac12e1e997dda7a 100755 --- a/bigbluebutton-html5/imports/locales/en.json +++ b/bigbluebutton-html5/imports/locales/en.json @@ -1,3 +1,6 @@ + + + { "app.home.greeting": "Welcome {name}! Your presentation will begin shortly...", "app.userlist.participantsTitle": "Participants", @@ -39,6 +42,9 @@ "app.leaveConfirmation.confirmDesc": "Logs you out of the meeting", "app.leaveConfirmation.dismissLabel": "Cancel", "app.leaveConfirmation.dismissDesc": "Closes and rejects the leave confirmation", + "app.actionsBar.muteLabel": "Mute", + "app.actionsBar.camOffLabel": "Cam Off", + "app.actionsBar.raiseLabel": "Raise", "app.actionsBar.actionsDropdown.actionsLabel": "Actions", "app.actionsBar.actionsDropdown.presentationLabel": "Upload a presentation", "app.actionsBar.actionsDropdown.initPollLabel": "Initiate a poll", diff --git a/bigbluebutton-html5/imports/locales/index.js b/bigbluebutton-html5/imports/locales/index.js old mode 100644 new mode 100755 index f7abe1b3cb27ec54abc776c4736e65825eb5685e..f1b81d29f1fe342534c3664e01e0030834b4a53d --- a/bigbluebutton-html5/imports/locales/index.js +++ b/bigbluebutton-html5/imports/locales/index.js @@ -1,7 +1,7 @@ import en from './en.json'; -import ptBR from './pt-BR.json'; +//import ptBR from './pt-BR.json'; export default { en: en, - 'pt-BR': ptBR, + //'pt-BR': ptBR, }; diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx index b9312a25d567f5ab5aa589c101381077308b1eb8..fa2d1efa6df9df8c1339eebc0bb91fe62800ef0d 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx @@ -1,97 +1,97 @@ -import React, { Component, PropTypes } from 'react'; -import { defineMessages, injectIntl } from 'react-intl'; - -import Button from '/imports/ui/components/button/component'; -import Dropdown from '/imports/ui/components/dropdown/component'; -import DropdownTrigger from '/imports/ui/components/dropdown/trigger/component'; -import DropdownContent from '/imports/ui/components/dropdown/content/component'; -import DropdownList from '/imports/ui/components/dropdown/list/component'; -import DropdownListItem from '/imports/ui/components/dropdown/list/item/component'; - -const intlMessages = defineMessages({ - actionsLabel: { - id: 'app.actionsBar.actionsDropdown.actionsLabel', - defaultMessage: 'Actions', - }, - presentationLabel: { - id: 'app.actionsBar.actionsDropdown.presentationLabel', - defaultMessage: 'Upload a presentation', - }, - initPollLabel: { - id: 'app.actionsBar.actionsDropdown.initPollLabel', - defaultMessage: 'Initiate a poll', - }, - desktopShareLabel: { - id: 'app.actionsBar.actionsDropdown.desktopShareLabel', - defaultMessage: 'Share your screen', - }, - presentationDesc: { - id: 'app.actionsBar.actionsDropdown.presentationDesc', - defaultMessage: 'Upload your presentation', - }, - initPollDesc: { - id: 'app.actionsBar.actionsDropdown.initPollDesc', - defaultMessage: 'Initiate a poll', - }, - desktopShareDesc: { - id: 'app.actionsBar.actionsDropdown.desktopShareDesc', - defaultMessage: 'Share your screen with others', - }, -}); - -const presentation = () => {console.log('Should show the uploader component');}; - -const polling = () => {console.log('Should initiate a polling');}; - -const shareScreen = () => {console.log('Should start screen sharing');}; - -class ActionsDropdown extends Component { - constructor(props) { - super(props); - } - - render() { - const { intl } = this.props; - return ( - <Dropdown ref="dropdown"> - <DropdownTrigger> - <Button - label={intl.formatMessage(intlMessages.actionsLabel)} - icon="circle-add" - color="primary" - size="lg" - circle={true} - onClick={() => null} - /> - </DropdownTrigger> - <DropdownContent placement="top left"> - <DropdownList> - <DropdownListItem - icon="presentation" - label={intl.formatMessage(intlMessages.presentationLabel)} - description={intl.formatMessage(intlMessages.presentationDesc)} - onClick={presentation.bind(this)} - /> - - {/* These icons are unaligned because of the font issue - Check it later */} - <DropdownListItem - icon="polling" - label={intl.formatMessage(intlMessages.initPollLabel)} - description={intl.formatMessage(intlMessages.initPollDesc)} - onClick={polling.bind(this)} - /> - <DropdownListItem - icon="desktop" - label={intl.formatMessage(intlMessages.desktopShareLabel)} - description={intl.formatMessage(intlMessages.desktopShareDesc)} - onClick={shareScreen.bind(this)} - /> - </DropdownList> - </DropdownContent> - </Dropdown> - ); - } -} - -export default injectIntl(ActionsDropdown); +import React, { Component, PropTypes } from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; + +import Button from '/imports/ui/components/button/component'; +import Dropdown from '/imports/ui/components/dropdown/component'; +import DropdownTrigger from '/imports/ui/components/dropdown/trigger/component'; +import DropdownContent from '/imports/ui/components/dropdown/content/component'; +import DropdownList from '/imports/ui/components/dropdown/list/component'; +import DropdownListItem from '/imports/ui/components/dropdown/list/item/component'; + +const intlMessages = defineMessages({ + actionsLabel: { + id: 'app.actionsBar.actionsDropdown.actionsLabel', + //defaultMessage: 'Actions', + }, + presentationLabel: { + id: 'app.actionsBar.actionsDropdown.presentationLabel', + defaultMessage: 'Upload a presentation', + }, + initPollLabel: { + id: 'app.actionsBar.actionsDropdown.initPollLabel', + defaultMessage: 'Initiate a poll', + }, + desktopShareLabel: { + id: 'app.actionsBar.actionsDropdown.desktopShareLabel', + defaultMessage: 'Share your screen', + }, + presentationDesc: { + id: 'app.actionsBar.actionsDropdown.presentationDesc', + defaultMessage: 'Upload your presentation', + }, + initPollDesc: { + id: 'app.actionsBar.actionsDropdown.initPollDesc', + defaultMessage: 'Initiate a poll', + }, + desktopShareDesc: { + id: 'app.actionsBar.actionsDropdown.desktopShareDesc', + defaultMessage: 'Share your screen with others', + }, +}); + +const presentation = () => {console.log('Should show the uploader component');}; + +const polling = () => {console.log('Should initiate a polling');}; + +const shareScreen = () => {console.log('Should start screen sharing');}; + +class ActionsDropdown extends Component { + constructor(props) { + super(props); + } + + render() { + const { intl } = this.props; + return ( + <Dropdown ref="dropdown"> + <DropdownTrigger> + <Button + label={intl.formatMessage(intlMessages.actionsLabel)} + icon="circle-add" + color="primary" + size="lg" + circle={true} + onClick={() => null} + /> + </DropdownTrigger> + <DropdownContent placement="top left"> + <DropdownList> + <DropdownListItem + icon="presentation" + label={intl.formatMessage(intlMessages.presentationLabel)} + description={intl.formatMessage(intlMessages.presentationDesc)} + onClick={presentation.bind(this)} + /> + + {/* These icons are unaligned because of the font issue + Check it later */} + <DropdownListItem + icon="polling" + label={intl.formatMessage(intlMessages.initPollLabel)} + description={intl.formatMessage(intlMessages.initPollDesc)} + onClick={polling.bind(this)} + /> + <DropdownListItem + icon="desktop" + label={intl.formatMessage(intlMessages.desktopShareLabel)} + description={intl.formatMessage(intlMessages.desktopShareDesc)} + onClick={shareScreen.bind(this)} + /> + </DropdownList> + </DropdownContent> + </Dropdown> + ); + } +} + +export default injectIntl(ActionsDropdown);