Merge pull request #5900 from riadvice/v2.0.x-rtl-popups

Improve RTL layout behaviour and fix its display
This commit is contained in:
Richard Alam 2018-07-24 15:04:50 -04:00 committed by GitHub
commit 1a26ff5777
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 348 additions and 47 deletions

View File

@ -15,7 +15,7 @@
<locale code="nl_NL" name="Dutch" native="Nederlands"/> <locale code="nl_NL" name="Dutch" native="Nederlands"/>
<locale code="en_US" name="English" native="English"/> <locale code="en_US" name="English" native="English"/>
<locale code="et_EE" name="Estonian" native="Eesti"/> <locale code="et_EE" name="Estonian" native="Eesti"/>
<locale code="fa_IR" name="Farsi" native="فارسى"/> <locale code="fa_IR" name="Farsi" native="فارسى" direction="rtl"/>
<locale code="fi_FI" name="Finnish" native="Suomi"/> <locale code="fi_FI" name="Finnish" native="Suomi"/>
<locale code="fr_FR" name="French" native="Français"/> <locale code="fr_FR" name="French" native="Français"/>
<locale code="fr_CA" name="French (Canadian)" native="Français (Canadien)"/> <locale code="fr_CA" name="French (Canadian)" native="Français (Canadien)"/>

View File

@ -19,9 +19,10 @@ You should have received a copy of the GNU Lesser General Public License along
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
--> -->
<mx:Application xmlns:mx="library://ns.adobe.com/flex/mx" <BigBlueButtonApplication xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:views="*" xmlns:views="*"
xmlns="org.bigbluebutton.core.*"
xmlns:logging="org.bigbluebutton.common.logging.*" xmlns:logging="org.bigbluebutton.common.logging.*"
pageTitle="BigBlueButton" pageTitle="BigBlueButton"
layout="absolute" layout="absolute"
@ -54,4 +55,4 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<views:BigBlueButtonMainContainer id="bbbShell"/> <views:BigBlueButtonMainContainer id="bbbShell"/>
</mx:Application> </BigBlueButtonApplication>

View File

@ -0,0 +1,25 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core {
import mx.core.Application;
[Frame(factoryClass = "org.bigbluebutton.core.managers.SystemManager")]
public class BigBlueButtonApplication extends Application {
}
}

View File

@ -56,9 +56,8 @@ package org.bigbluebutton.core.managers {
var date:Date = new Date(); var date:Date = new Date();
var localeReqURL:String = buildRequestURL(); var localeReqURL:String = buildRequestURL();
trace("::loadConfig [{0}]", [localeReqURL]);
trace(localeReqURL + " session=[" + sessionToken + "]"); LOGGER.debug("loadConfig request={0} session=[{1}]", [localeReqURL, sessionToken]);
var request:URLRequest = new URLRequest(localeReqURL); var request:URLRequest = new URLRequest(localeReqURL);
request.method = URLRequestMethod.GET; request.method = URLRequestMethod.GET;
@ -75,21 +74,19 @@ package org.bigbluebutton.core.managers {
} }
private function handleComplete(e:Event):void { private function handleComplete(e:Event):void {
trace("handleComplete [{0}]", [new XML(e.target.data)]); LOGGER.debug("handleComplete [{0}]", [new XML(e.target.data)]);
var xml:XML = new XML(e.target.data) var xml:XML = new XML(e.target.data)
var dispatcher:Dispatcher = new Dispatcher(); var dispatcher:Dispatcher = new Dispatcher();
if (xml.returncode == "FAILED") { if (xml.returncode == "FAILED") {
LOGGER.error("Getting configXML failed [{0}]", [xml]);
// trace("Getting configXML failed [{0}]", [xml]);
dispatcher.dispatchEvent(new MeetingNotFoundEvent(xml.response.logoutURL)); dispatcher.dispatchEvent(new MeetingNotFoundEvent(xml.response.logoutURL));
} else { } else {
// trace("Getting configXML passed [{0}]", [xml]); LOGGER.info("Getting configXML passed [{0}]", [xml]);
_config = new Config(new XML(e.target.data)); _config = new Config(new XML(e.target.data));
trace("Initializing logging."); LOGGER.debug("Initializing logging.");
LogUtil.initLogging(); LogUtil.initLogging();
dispatcher.dispatchEvent(new ConfigLoadedEvent()); dispatcher.dispatchEvent(new ConfigLoadedEvent());

View File

@ -0,0 +1,187 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.managers {
import flash.display.DisplayObject;
import flash.geom.Point;
import flash.geom.Rectangle;
import mx.core.FlexVersion;
import mx.core.IFlexDisplayObject;
import mx.core.IInvalidating;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.Request;
import mx.managers.IPopUpManager;
import mx.managers.ISystemManager;
import mx.managers.PopUpData;
import mx.managers.PopUpManagerImpl;
use namespace mx_internal;
public class PopUpManagerImpl extends mx.managers.PopUpManagerImpl {
/**
* @private
*/
private static var instance:IPopUpManager;
/**
* @private
*/
public static function getInstance():IPopUpManager {
if (!instance)
instance = new org.bigbluebutton.core.managers.PopUpManagerImpl();
return instance;
}
/**
* Centers a popup window over whatever window was used in the call
* to the <code>createPopUp()</code> or <code>addPopUp()</code> method.
*
* <p>Note that the position of the popup window may not
* change immediately after this call since Flex may wait to measure and layout the
* popup window before centering it.</p>
*
* @param The IFlexDisplayObject representing the popup.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
override public function centerPopUp(popUp:IFlexDisplayObject):void {
if (popUp is IInvalidating)
IInvalidating(popUp).validateNow();
const o:PopUpData = findPopupInfoByOwner(popUp);
// If we don't find the pop owner or if the owner's parent is not specified or is not on the
// stage, then center based on the popUp's current parent.
var popUpParent:DisplayObject = (o && o.parent && o.parent.stage) ? o.parent : popUp.parent;
if (popUpParent) {
//FLEX-28967 : https://issues.apache.org/jira/browse/FLEX-28967. Fix by miroslav.havrlent
var systemManager:ISystemManager;
if (o != null) {
systemManager = o.systemManager;
} else if (popUpParent.hasOwnProperty("systemManager")) {
systemManager = popUpParent["systemManager"];
} else if (popUpParent is ISystemManager) {
systemManager = popUpParent as ISystemManager;
}
if (!systemManager)
return; // or throw exception maybe ?
var x:Number;
var y:Number;
var appWidth:Number;
var appHeight:Number;
var parentWidth:Number;
var parentHeight:Number;
var rect:Rectangle;
var clippingOffset:Point = new Point();
var pt:Point;
var isTopLevelRoot:Boolean;
var sbRoot:DisplayObject = systemManager.getSandboxRoot();
var request:Request;
if (hasEventListener("isTopLevelRoot")) {
request = new Request("isTopLevelRoot", false, true);
}
if (request && !dispatchEvent(request))
isTopLevelRoot = Boolean(request.value);
else
isTopLevelRoot = systemManager.isTopLevelRoot();
if (isTopLevelRoot && (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_6)) {
// The sandbox root is the top level root.
// The application width is just the screen width.
var screen:Rectangle = systemManager.screen;
appWidth = screen.width;
appHeight = screen.height;
} else {
rect = systemManager.getVisibleApplicationRect();
rect.topLeft = DisplayObject(systemManager).globalToLocal(rect.topLeft);
rect.bottomRight = DisplayObject(systemManager).globalToLocal(rect.bottomRight);
// Offset the top, left of the window to bring it into view.
clippingOffset = rect.topLeft.clone();
appWidth = rect.width;
appHeight = rect.height;
}
// If parent is a UIComponent, check for clipping between
// the object and its SystemManager
if (popUpParent is UIComponent) {
rect = UIComponent(popUpParent).getVisibleRect();
if (UIComponent(popUpParent).systemManager != sbRoot)
rect = UIComponent(popUpParent).systemManager.getVisibleApplicationRect(rect);
var offset:Point = popUpParent.globalToLocal(rect.topLeft);
clippingOffset.x += offset.x;
clippingOffset.y += offset.y;
parentWidth = rect.width;
parentHeight = rect.height;
} else {
parentWidth = popUpParent.width;
parentHeight = popUpParent.height;
}
// The appWidth may smaller than parentWidth if the application is
// clipped by the parent application.
x = Math.max(0, (Math.min(appWidth, parentWidth) - popUp.width) / 2);
y = Math.max(0, (Math.min(appHeight, parentHeight) - popUp.height) / 2);
// If the layout has been mirrored, then 0,0 is the uppper
// right corner; compensate here.
// Code removed below, centring a popup does not need RTL layou check
pt = new Point(clippingOffset.x, clippingOffset.y);
pt = popUpParent.localToGlobal(pt);
pt = popUp.parent.globalToLocal(pt);
popUp.move(Math.round(x) + pt.x, Math.round(y) + pt.y);
}
}
/**
* @private
* Returns the index position of the PopUpData in the popupInfo array (or -1)
* for a given popupInfo.owner
*/
private function findPopupInfoIndexByOwner(owner:Object):int {
const n:int = popupInfo.length;
for (var i:int = 0; i < n; i++) {
var o:PopUpData = popupInfo[i];
if (o.owner == owner)
return i;
}
return -1;
}
/**
* @private
* Returns the PopUpData (or null) for a given popupInfo.owner
*/
private function findPopupInfoByOwner(owner:Object):PopUpData {
var index:int = findPopupInfoIndexByOwner(owner);
return index > -1 ? popupInfo[index] : null;
}
}
}

View File

@ -0,0 +1,34 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.managers {
import mx.core.Singleton;
import mx.core.mx_internal;
import mx.managers.SystemManager;
use namespace mx_internal;
public class SystemManager extends mx.managers.SystemManager {
override mx_internal function kickOff():void {
if (document)
return;
Singleton.registerClass("mx.managers::IPopUpManager", PopUpManagerImpl);
super.kickOff();
}
}
}

View File

@ -42,7 +42,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
} }
private function changeLanguage():void { private function changeLanguage():void {
ResourceUtil.getInstance().setPreferredLocale(selectedItem); ResourceUtil.getInstance().setPreferredLocale(selectedItem.code);
} }
]]> ]]>
</fx:Script> </fx:Script>

View File

@ -109,6 +109,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import mx.core.UIComponent; import mx.core.UIComponent;
import mx.events.FlexEvent; import mx.events.FlexEvent;
import flashx.textLayout.formats.Direction;
import flexlib.mdi.effects.effectsLib.MDIVistaEffects; import flexlib.mdi.effects.effectsLib.MDIVistaEffects;
import org.as3commons.lang.StringUtils; import org.as3commons.lang.StringUtils;
@ -164,6 +166,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.util.browser.BrowserCheck; import org.bigbluebutton.util.browser.BrowserCheck;
import org.bigbluebutton.util.i18n.ResourceUtil; import org.bigbluebutton.util.i18n.ResourceUtil;
private static const LOGGER:ILogger = getClassLogger(MainApplicationShell); private static const LOGGER:ILogger = getClassLogger(MainApplicationShell);
private var globalDispatcher:Dispatcher; private var globalDispatcher:Dispatcher;
@ -225,6 +231,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
} }
public function initOptions(e:Event):void { public function initOptions(e:Event):void {
// Set the layout direction at the application start
ResourceUtil.getInstance().updateLayoutDirection();
brandingOptions = Options.getOptions(BrandingOptions) as BrandingOptions; brandingOptions = Options.getOptions(BrandingOptions) as BrandingOptions;
layoutOptions = Options.getOptions(LayoutOptions) as LayoutOptions; layoutOptions = Options.getOptions(LayoutOptions) as LayoutOptions;
usersOptions = Options.getOptions(UsersOptions) as UsersOptions; usersOptions = Options.getOptions(UsersOptions) as UsersOptions;
@ -414,7 +423,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
guestWindow = PopUpUtil.createModalPopUp( FlexGlobals.topLevelApplication as DisplayObject, GuestWindow, false) as GuestWindow; guestWindow = PopUpUtil.createModalPopUp( FlexGlobals.topLevelApplication as DisplayObject, GuestWindow, false) as GuestWindow;
PopUpUtil.lockPosition(guestWindow, function():Point { PopUpUtil.lockPosition(guestWindow, function():Point {
if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) {
return new Point(20, 20);
} else {
return new Point(systemManager.screen.width - guestWindow.width - 20, 20); return new Point(systemManager.screen.width - guestWindow.width - 20, 20);
}
}); });
guestWindow.addEventListener(Event.CLOSE, closeGuestWindow); guestWindow.addEventListener(Event.CLOSE, closeGuestWindow);
@ -856,7 +869,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
var popUp:RecordWindow = PopUpUtil.createModalPopUp(FlexGlobals.topLevelApplication as DisplayObject, RecordWindow, false) as RecordWindow; var popUp:RecordWindow = PopUpUtil.createModalPopUp(FlexGlobals.topLevelApplication as DisplayObject, RecordWindow, false) as RecordWindow;
popUp.setRecordingFlag(e.payload.recording); popUp.setRecordingFlag(e.payload.recording);
PopUpUtil.lockPosition(popUp, function():Point { PopUpUtil.lockPosition(popUp, function():Point {
return new Point(parentApplication.width - 150 - popUp.width, y + toolbar.height); if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) {
return new Point(150, y + toolbar.height);
} else {
return new Point(parentApplication.width - popUp.width - 150, y + toolbar.height);
}
}); });
} }
@ -877,9 +894,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
} }
private function onLocaleChanged(e:LocaleChangeEvent) : void { private function onLocaleChanged(e:LocaleChangeEvent) : void {
if (ResourceUtil.getInstance().isRTLEnabled()) {
FlexGlobals.topLevelApplication.setStyle("layoutDirection", ResourceUtil.getInstance().getCurrentLanguageDirection());
}
PopUpUtil.initAlert(); PopUpUtil.initAlert();
} }

View File

@ -345,7 +345,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
// Needs to be improved in case of RTL layout // Needs to be improved in case of RTL layout
PopUpUtil.lockPosition(logoutWindow, function():Point { PopUpUtil.lockPosition(logoutWindow, function():Point {
if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) {
return new Point(5, btnLogout.y + btnLogout.height + 5)
} else {
return new Point(width - logoutWindow.width - 5, btnLogout.y + btnLogout.height + 5) return new Point(width - logoutWindow.width - 5, btnLogout.y + btnLogout.height + 5)
}
}); });
} else { } else {
doLogout(); doLogout();
@ -439,6 +443,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
if (!StringUtils.isEmpty(brandingOptions.toolbarColor)) { if (!StringUtils.isEmpty(brandingOptions.toolbarColor)) {
mainBox.setStyle("backgroundColor", uint("0x" + brandingOptions.toolbarColor.substr(1))); mainBox.setStyle("backgroundColor", uint("0x" + brandingOptions.toolbarColor.substr(1)));
} }
updateStyle();
} }
private function onDisconnectTest():void{ private function onDisconnectTest():void{
@ -456,15 +462,18 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
} }
private function localeChanged(event:LocaleChangeEvent) : void { private function localeChanged(event:LocaleChangeEvent) : void {
updateStyle();
initBreakoutRibbon();
updateMeetingNameLabel();
}
private function updateStyle():void {
var styleNameExt : String = ""; var styleNameExt : String = "";
if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) { if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) {
styleNameExt = "RTL"; styleNameExt = "RTL";
} }
btnLogout.styleName = "logoutButtonStyle" + styleNameExt; btnLogout.styleName = "logoutButtonStyle" + styleNameExt;
initBreakoutRibbon();
updateMeetingNameLabel();
} }
private function openSettings(e:Event = null):void{ private function openSettings(e:Event = null):void{

View File

@ -52,11 +52,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import flash.events.TextEvent; import flash.events.TextEvent;
import flashx.textLayout.formats.Direction;
import mx.binding.utils.BindingUtils; import mx.binding.utils.BindingUtils;
import mx.events.ScrollEvent; import mx.events.ScrollEvent;
import flashx.textLayout.formats.Direction;
import org.as3commons.lang.StringUtils; import org.as3commons.lang.StringUtils;
import org.as3commons.logging.api.ILogger; import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger; import org.as3commons.logging.api.getClassLogger;
@ -80,7 +80,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.modules.chat.events.SendPrivateChatMessageEvent; import org.bigbluebutton.modules.chat.events.SendPrivateChatMessageEvent;
import org.bigbluebutton.modules.chat.events.SendPublicChatMessageEvent; import org.bigbluebutton.modules.chat.events.SendPublicChatMessageEvent;
import org.bigbluebutton.modules.chat.model.ChatConversation; import org.bigbluebutton.modules.chat.model.ChatConversation;
import org.bigbluebutton.modules.chat.model.ChatMessage;
import org.bigbluebutton.modules.chat.model.ChatOptions; import org.bigbluebutton.modules.chat.model.ChatOptions;
import org.bigbluebutton.modules.chat.vo.ChatMessageVO; import org.bigbluebutton.modules.chat.vo.ChatMessageVO;
import org.bigbluebutton.modules.polling.events.StartCustomPollEvent; import org.bigbluebutton.modules.polling.events.StartCustomPollEvent;
@ -167,6 +166,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
// chatToolbar.registerListeners(chatMessagesList); // chatToolbar.registerListeners(chatMessagesList);
chatMessagesList.addEventListener(ChatEvent.RESIZE_CHAT_TOOLBAR, adjustToolbarWidthAccordingToScrollBar); chatMessagesList.addEventListener(ChatEvent.RESIZE_CHAT_TOOLBAR, adjustToolbarWidthAccordingToScrollBar);
updateStyles();
} }

View File

@ -46,6 +46,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private function init():void { private function init():void {
refreshRole(UsersUtil.amIModerator()); refreshRole(UsersUtil.amIModerator());
updateStyles();
} }
private function onClick(e:Event):void { private function onClick(e:Event):void {
@ -57,6 +58,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
} }
private function localeChanged(event:LocaleChangeEvent) : void { private function localeChanged(event:LocaleChangeEvent) : void {
updateStyles();
}
private function updateStyles():void {
var styleNameExt : String = ""; var styleNameExt : String = "";
if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) { if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) {
styleNameExt = "RTL"; styleNameExt = "RTL";

View File

@ -147,6 +147,8 @@
typistsTimer.addEventListener(TimerEvent.TIMER, updateTypists); typistsTimer.addEventListener(TimerEvent.TIMER, updateTypists);
typistsTimer.start(); typistsTimer.start();
updateStyles();
} }
private function updateTypists(e:Event):void { private function updateTypists(e:Event):void {
@ -578,6 +580,10 @@
} }
private function onLocaleChanged(event:LocaleChangeEvent):void { private function onLocaleChanged(event:LocaleChangeEvent):void {
updateStyles();
}
private function updateStyles():void {
var styleNameExt : String = ""; var styleNameExt : String = "";
if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) { if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) {
styleNameExt = "RTL"; styleNameExt = "RTL";

View File

@ -102,11 +102,11 @@ package org.bigbluebutton.util.i18n
preferredLocale = getDefaultLocale(); preferredLocale = getDefaultLocale();
if (preferredLocale != MASTER_LOCALE) { if (preferredLocale != MASTER_LOCALE) {
trace("Preferred locale=" + preferredLocale + " is not the same as master locale=" + MASTER_LOCALE); LOGGER.debug("Preferred locale={0} is not the same as master locale={1}", [preferredLocale, MASTER_LOCALE]);
loadMasterLocale(MASTER_LOCALE); loadMasterLocale(MASTER_LOCALE);
} }
// To improve
setPreferredLocale({code:preferredLocale, direction:"ltr"}); setPreferredLocale(preferredLocale);
} }
private function parse(xml:XML):void{ private function parse(xml:XML):void{
@ -134,12 +134,25 @@ package org.bigbluebutton.util.i18n
return ExternalInterface.call("getLanguage"); return ExternalInterface.call("getLanguage");
} }
private function isPreferredLocaleAvailable(prefLocale:String):Boolean { private function findPreferredLocale(prefLocale:String) : * {
for each(var item:* in locales) { var item:* = null;
// Lookginf for locale in format 'en_US'
for each(item in locales) {
if (prefLocale == item.code) if (prefLocale == item.code)
return true; return item;
} }
return false; // If not found we look for form 'en'
var mainLocale : String = prefLocale.substr(0,2);
for each(item in locales) {
if (mainLocale == item.code)
return item;
}
// If not found we look for the first item that contains 'en'
for each(item in locales) {
if (StringUtils.startsWith(item.code, mainLocale))
return item;
}
return null;
} }
private function getIndexForLocale(prefLocale:String):int { private function getIndexForLocale(prefLocale:String):int {
@ -150,19 +163,21 @@ package org.bigbluebutton.util.i18n
return -1; return -1;
} }
public function setPreferredLocale(locale:Object):void { public function setPreferredLocale(locale:String):void {
var localeCode : String = locale.code; var localeCode : String = locale;
if (localeCode == DEFAULT_LOCALE_IDENTIFIER) { if (localeCode == DEFAULT_LOCALE_IDENTIFIER) {
localeCode = getDefaultLocale(); localeCode = getDefaultLocale();
} }
if (isPreferredLocaleAvailable(localeCode)) { var foundLocale : Object = findPreferredLocale(localeCode);
preferredLocale = localeCode; if (foundLocale) {
}else{ preferredLocale = foundLocale.code;
preferredDirection = foundLocale.direction;
} else {
preferredLocale = MASTER_LOCALE; preferredLocale = MASTER_LOCALE;
preferredDirection = "ltr";
} }
preferredDirection = locale.direction;
changeLocale(preferredLocale); changeLocale(preferredLocale);
} }
@ -184,7 +199,7 @@ package org.bigbluebutton.util.i18n
} }
private function loadMasterLocale(locale:String):void { private function loadMasterLocale(locale:String):void {
trace("Loading master locale=" + locale); LOGGER.debug("Loading master locale={0}", [locale]);
/** /**
* http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/resources/IResourceManager.html#localeChain * http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/resources/IResourceManager.html#localeChain
* Always load the default language, so if the chosen language * Always load the default language, so if the chosen language
@ -195,10 +210,10 @@ package org.bigbluebutton.util.i18n
} }
private function onMasterLocaleLoaded(event:ResourceEvent):void { private function onMasterLocaleLoaded(event:ResourceEvent):void {
trace("Master locale is loaded"); LOGGER.debug("Master locale is loaded");
masterLocaleLoaded = true; masterLocaleLoaded = true;
if (masterLocaleLoadedCallback != null) { if (masterLocaleLoadedCallback != null) {
trace("Calling callback to load a second language"); LOGGER.debug("Calling callback to load a second language");
masterLocaleLoadedCallback(); masterLocaleLoadedCallback();
} }
} }
@ -208,7 +223,7 @@ package org.bigbluebutton.util.i18n
var date:Date = new Date(); var date:Date = new Date();
var localeURI:String = buildRequestURL() + 'client/locale/' + language + '_resources.swf?a=' + date.time; var localeURI:String = buildRequestURL() + 'client/locale/' + language + '_resources.swf?a=' + date.time;
trace("Loading locale " + localeURI); LOGGER.debug("Loading locale {0}", [localeURI]);
return resourceManager.loadResourceModule( localeURI, false); return resourceManager.loadResourceModule( localeURI, false);
} }
@ -227,10 +242,10 @@ package org.bigbluebutton.util.i18n
public function changeLocale(locale:String):void { public function changeLocale(locale:String):void {
if (masterLocaleLoaded || locale == MASTER_LOCALE) { if (masterLocaleLoaded || locale == MASTER_LOCALE) {
trace("Loading immediately " + locale); LOGGER.debug("Loading immediately {0}", [locale]);
changeLocaleHelper(locale); changeLocaleHelper(locale);
} else { } else {
trace("Registering callback to load " + locale + " later"); LOGGER.debug("Registering callback to load {0} later", [locale]);
masterLocaleLoadedCallback = function():void { masterLocaleLoadedCallback = function():void {
changeLocaleHelper(locale); changeLocaleHelper(locale);
} }
@ -246,7 +261,7 @@ package org.bigbluebutton.util.i18n
var logData:Object = UsersUtil.initLogData(); var logData:Object = UsersUtil.initLogData();
logData.tags = ["locale"]; logData.tags = ["locale"];
logData.message = "Failed to load locale = " + preferredLocale; logData.message = "Failed to load locale = " + preferredLocale;
trace(JSON.stringify(logData)); LOGGER.debug(JSON.stringify(logData));
} }
masterLocaleLoaded = true; masterLocaleLoaded = true;
resourceManager.localeChain = [MASTER_LOCALE]; resourceManager.localeChain = [MASTER_LOCALE];
@ -257,7 +272,7 @@ package org.bigbluebutton.util.i18n
} }
private function sendAppAndLocaleVersions():void { private function sendAppAndLocaleVersions():void {
trace("Sending locale version"); LOGGER.debug("Sending locale version");
var dispatcher:Dispatcher = new Dispatcher(); var dispatcher:Dispatcher = new Dispatcher();
var versionEvent:AppVersionEvent = new AppVersionEvent(); var versionEvent:AppVersionEvent = new AppVersionEvent();
versionEvent.configLocaleVersion = false; versionEvent.configLocaleVersion = false;
@ -269,7 +284,7 @@ package org.bigbluebutton.util.i18n
* @param event * @param event
*/ */
private function handleResourceNotLoaded(event:ResourceEvent):void { private function handleResourceNotLoaded(event:ResourceEvent):void {
trace("Resource locale [" + preferredLocale + "] could not be loaded."); LOGGER.debug("Resource locale {0} could not be loaded.", [preferredLocale]);
resourceManager.localeChain = [MASTER_LOCALE]; resourceManager.localeChain = [MASTER_LOCALE];
preferredLocale = MASTER_LOCALE; preferredLocale = MASTER_LOCALE;
update(); update();
@ -278,11 +293,18 @@ package org.bigbluebutton.util.i18n
public function update():void{ public function update():void{
reloadLocaleNames(); reloadLocaleNames();
sendAppAndLocaleVersions(); sendAppAndLocaleVersions();
updateLayoutDirection();
var dispatcher:Dispatcher = new Dispatcher; var dispatcher:Dispatcher = new Dispatcher;
dispatcher.dispatchEvent(new LocaleChangeEvent(LocaleChangeEvent.LOCALE_CHANGED)); dispatcher.dispatchEvent(new LocaleChangeEvent(LocaleChangeEvent.LOCALE_CHANGED));
dispatchEvent(new Event(Event.CHANGE)); dispatchEvent(new Event(Event.CHANGE));
} }
public function updateLayoutDirection():void {
if (isRTLEnabled()) {
FlexGlobals.topLevelApplication.setStyle("layoutDirection", preferredDirection);
}
}
[Bindable("change")] [Bindable("change")]
public function getString(resourceName:String, parameters:Array = null, locale:String = null):String{ public function getString(resourceName:String, parameters:Array = null, locale:String = null):String{
/** /**