<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;C0MGQ348eCp7ImA9WhRRFEk.&quot;"><id>tag:blogger.com,1999:blog-8796582083368239187</id><updated>2011-11-28T02:50:22.070+02:00</updated><category term="RTL Layout" /><category term="DNN" /><category term="ASP.Net" /><category term="DotNetNuke" /><category term="Localization" /><title>Michael Fayez Blog</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://michaelfayez.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://michaelfayez.blogspot.com/" /><author><name>Michael Fayez</name><uri>http://www.blogger.com/profile/16252645336692523661</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>4</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/MichaelFayezBlog" /><feedburner:info uri="michaelfayezblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DUUHSXwzfyp7ImA9WxBXGUU.&quot;"><id>tag:blogger.com,1999:blog-8796582083368239187.post-8068648855225541482</id><published>2010-01-31T02:13:00.001+02:00</published><updated>2010-02-01T03:20:38.287+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-01T03:20:38.287+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="RTL Layout" /><category scheme="http://www.blogger.com/atom/ns#" term="Localization" /><category scheme="http://www.blogger.com/atom/ns#" term="DotNetNuke" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.Net" /><category scheme="http://www.blogger.com/atom/ns#" term="DNN" /><title>Modified DNN with RTL support release</title><content type="html">&lt;p&gt;As promised here the release of DNN version 5.02.01 modified to support RTL languages as a proof of concept of my suggestions. Here is a summary of modifications that are explained more in &lt;a href="http://michaelfayez.blogspot.com/2010/01/proposal-for-dnn-support-of-rtl-layout.html" target="_blank"&gt;Part 1&lt;/a&gt; &amp;amp; &lt;a href="http://michaelfayez.blogspot.com/2010/01/proposal-for-dnn-support-of-rtl-layout_22.html" target="_blank"&gt;Part 2&lt;/a&gt; for proposal to support RTL in DNN (without messing up the LTR layout). You can download this release from &lt;a href="http://cid-9269c74f7e8e207c.skydrive.live.com/self.aspx/.Public/ModifiedDotNetNuke^_Community^_05.02.01^_Source.zip" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;h4&gt;Release Notes&lt;/h4&gt;  &lt;h5&gt;1. API Changes&lt;/h5&gt;  &lt;ol&gt;   &lt;li&gt;Added read only property IsRightToLeft in Localization class to determine if the current culture is right to left. &lt;/li&gt;    &lt;li&gt;Added an extension method GetLabelModeString to LabelMode enumeration. When LabelMode is left and text direction is rtl the method returns right instead of left and when right the method returns left. If the text direction is left it has no effect when direction. This method should be used instead of ToString for supporting both LTR and RTL directions. This method returns string in lower case. &lt;/li&gt;    &lt;li&gt;Changed the PropertyGrid class to use the method described in point 2 above instead of using ToString method. &lt;/li&gt;    &lt;li&gt;Changed the behavior of AddStyleSheet in CDefault class to check the existance of RTL files and inculde them along side the normal CSS file in case of RTL culture. For example if AddStyleSheet is called to add file x.css, it will check for existance of x.rtl.css and include it if exists and RTL culture. &lt;/li&gt;    &lt;li&gt;Added dnn.direction() method in dnn.js. It returns rtl in case direction is RTL. &lt;/li&gt; &lt;/ol&gt;  &lt;h5&gt;2. Changes in WebSite&lt;/h5&gt;  &lt;ol&gt;   &lt;li&gt;Added RTL CSS files according to point 4 above. &lt;/li&gt;    &lt;li&gt;Fixed calculations for Menu absolute positioning in dnn.controls.dnnmenu.js &lt;/li&gt;    &lt;li&gt;Fixed layout of Search controls in Search.js file. (background-image is always aligned left in CSS. In case of RTL direction, it needs to aligned right using background-position. &lt;/li&gt;    &lt;li&gt;Numerous fixes in the website to support both RTL and LTR layout. You can find them by searching through the solution for Modified By Michael Fayez in the code. &lt;/li&gt;    &lt;li&gt;Added the changes suggested &lt;a href="http://www.dotnetnuke.com/Community/Forums/tabid/795/forumid/77/threadid/300971/scope/posts/Default.aspx" target="_blank"&gt;here&lt;/a&gt; for adding rtl/ltr plugin to FCK editor (with slight modifications).&lt;/li&gt;    &lt;li&gt;I didn’t use CSS flipping as it didn’t work on Opera. I used flipped images from the original ones when needed. &lt;/li&gt; &lt;/ol&gt;  &lt;h5&gt;3. Notes&lt;/h5&gt;  &lt;ol&gt;   &lt;li&gt;The attached file is only a proof of concept and is not supported by any means. &lt;/li&gt;    &lt;li&gt;I don’t claim any copyright for these modifications. (Thanking me would be nice).&amp;#160; &lt;/li&gt;    &lt;li&gt;The RTL modification of default skin could be better by flipping images of borders to have the shadows mirrored. Though the current solution passes. &lt;/li&gt;    &lt;li&gt;Only default skin and default menu are fixed. &lt;/li&gt;    &lt;li&gt;In some places like breadcrumb, the layout looks not mirrored in RTL mode this is because of flow direction of English in an RTL language the layout would be mirrored automatically. So this is not an issue at all. &lt;/li&gt;    &lt;li&gt;I didn't make any modifications to the core modules of DNN. They need to be checked one by one to fix them. I know that there are problems in forum module in RTL. The repository module layout engine uses a single template from html file per module which may not be adequate in case of supporting both direction LTR and RTL and so on. &lt;/li&gt;    &lt;li&gt;I don’t guarantee nor know if the DNN team would embrace these changes or supporting RTL layout. (Currently they fix RTL issues one by one without resolving to the root cause of the problem). &lt;/li&gt;    &lt;li&gt;This release is not thoroughly tested. My changes may cause bugs in some scenarios unknown to me. &lt;/li&gt;    &lt;li&gt;I only changed the pages and controls that made the layout wrong in the pages i visited while testing. I didn’t fix ALL DNN user controls with hardcoded alignments. &lt;/li&gt;    &lt;li&gt;This code is not upgradable. When I started working on modifying DNN for RTL, latest DNN version was 5.02.01. Version 5.02.02 was released during my work. Copying the changes to the new version was too much to do. &lt;/li&gt;    &lt;li&gt;The RTL style is having some problems in IE 7 (and I assume IE 6 too), while working fine on other browsers. I don’t think this is a major issue for a proof of concept. &lt;/li&gt;    &lt;li&gt;The default theme for FCK editor has curved dotted end in its toolbars. They look ugly in RTL mode. They should be flipped but I didn’t try to find a solution for this. As a workaround you can use the sliver theme which has a straight dotted vertical line at the end of toolbars.&lt;/li&gt; &lt;/ol&gt;  &lt;h5&gt;4. Installation&lt;/h5&gt;  &lt;ol&gt;   &lt;li&gt;Set up DNN using the normal method. &lt;/li&gt;    &lt;li&gt;Copy the file portal.rtl.css from _default portal file to the folder of your created portals. (I didn’t find a way for the automatic copy of this file every time a new portal is created and didn’t want to spend more time in this point). &lt;strong&gt;&lt;u&gt;This is VERY important as without it the page won’t have direction:rtl style and all JavaScript calculations that depends on dnn.direction() will not work.&lt;/u&gt;&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;Add an RTL culture in languages page and compare the layouts of both RTL and LTR layouts by switching cultures using the flags in the top. &lt;/li&gt; &lt;/ol&gt;  &lt;h5&gt;&lt;/h5&gt;  &lt;h5&gt;5. Things to consider&lt;/h5&gt;  &lt;p&gt;I suggested that RTL CSS is loaded along the normal css. But this duplicates the number of CSS files loaded and download by browser in RTL layout as almost no CSS file is suitable for both LTR and RTL directions so it duplicates the overhead of downloading. The other solution would be that RTL CSS file is loaded instead of the normal CSS file and duplicate the normal CSS file styles while modifying it for RTL layout. Maybe this is a better solution and easily doable by modifying the attached code.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8796582083368239187-8068648855225541482?l=michaelfayez.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/emXohTSAug7f9VXFkTi1lii522o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/emXohTSAug7f9VXFkTi1lii522o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/emXohTSAug7f9VXFkTi1lii522o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/emXohTSAug7f9VXFkTi1lii522o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MichaelFayezBlog/~4/3sEob2tFlLQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://michaelfayez.blogspot.com/feeds/8068648855225541482/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://michaelfayez.blogspot.com/2010/01/modified-dnn-with-rtl-support-release.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8796582083368239187/posts/default/8068648855225541482?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8796582083368239187/posts/default/8068648855225541482?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MichaelFayezBlog/~3/3sEob2tFlLQ/modified-dnn-with-rtl-support-release.html" title="Modified DNN with RTL support release" /><author><name>Michael Fayez</name><uri>http://www.blogger.com/profile/16252645336692523661</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://michaelfayez.blogspot.com/2010/01/modified-dnn-with-rtl-support-release.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYGRHgycSp7ImA9WxBXEU8.&quot;"><id>tag:blogger.com,1999:blog-8796582083368239187.post-1873788659245303352</id><published>2010-01-22T04:40:00.001+02:00</published><updated>2010-01-22T04:42:05.699+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-22T04:42:05.699+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="RTL Layout" /><category scheme="http://www.blogger.com/atom/ns#" term="Localization" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.Net" /><category scheme="http://www.blogger.com/atom/ns#" term="DNN" /><title>Proposal for DNN support of RTL layout Part 2</title><content type="html">Please read the &lt;a href="http://michaelfayez.blogspot.com/2010/01/proposal-for-dnn-support-of-rtl-layout.html" target="_blank"&gt;first part&lt;/a&gt; of this post first to better understand this post.&lt;br /&gt;
In my first post, I didn’t speak about the number of RTL script language users. They are about 600 millions (300 million in Arabic states (including economically important Persian gulf states), 170 millions in Pakistan, 75 millions in Iran, 30 millions in Afghanistan, etc.). This makes about 10% of the human population use RTL scripts mostly using the Arabic script which is used for many languages not just Arabic. Hebrew script users are 5 millions. Thaana script users in Maldives are 350,000 users.I have no info about Syriac user community but I think they won't be more than 3 millions but not sure.&lt;br /&gt;
&lt;br /&gt;
I want also to clarify part of my previous post that maybe was not clear enough. The RTL CSS should override any property that affects horizontal direction not only float, text-align but also padding, margin, border any other property that affects the horizontal layout as in RTL layout it should be mirrored. &lt;br /&gt;
Now, I will continue explaining how to handle images and JavaScript in RTL layout.   &lt;br /&gt;
&lt;h4&gt;



Handling images in RTL mode&lt;/h4&gt;
&lt;h5&gt;



Usually images shouldn’t be horizontally flipped in RTL mode except:&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;Images that specifies horizontal direction. For example in the image below the required image should be flipped to point to the text box not to point to the empty space beside the empty textbox. &lt;/li&gt;
&lt;/ol&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/_Ah2PMbLLv4Y/S1jhjiSpGPI/AAAAAAAAAA4/f2Jizw6bEFo/s1600-h/direction.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_Ah2PMbLLv4Y/S1jhjiSpGPI/AAAAAAAAAA4/f2Jizw6bEFo/s320/direction.jpg" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li value="2"&gt;Images that are displayed in sequence horizontally as in RTL these images should be flipped to give the same effect. A real life example here is &lt;a href="http://www.dnnskins.com/free-skins.aspx?List=0&amp;amp;SortField=ProductName%2cProductName&amp;amp;ProductID=156" target="_blank"&gt;XDNewBlue&lt;/a&gt; skin. The skin is having messy layout in RTL mode because of its asymmetric layout. Here I will only show the container in RTL and LTR modes. The container header has 3 consecutive images which when rendered in reverse order were not correct. You will need to reverse second image to have the same layout of LTR flipped horizontally. In this case the image file is specified in a CSS file so the flipped image should be referenced in the RTL CSS file.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/_Ah2PMbLLv4Y/S1jmQCbgiPI/AAAAAAAAABI/wivBXYdQhyk/s1600-h/container.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_Ah2PMbLLv4Y/S1jmQCbgiPI/AAAAAAAAABI/wivBXYdQhyk/s320/container.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;
&lt;h5&gt;



Images should be flipped either using:&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;Client side horizontal flipping: this way is done using flipping images using CSS and remove the need to having a separate mirrored image file. After doing some search, I found a solution &lt;a href="http://stackoverflow.com/questions/1309055/cross-browser-way-to-flip-image-via-javascript-css" target="_blank"&gt;here&lt;/a&gt;. This solution is very good and would work by adding the CSS class below to the element to be flipped. This class should be empty in normal CSS and only having the text below in the RTL CSS file. Unfortunately this solution while it worked on Internet Explorer, Firefox, Safari and Chrome, it didn’t work on Opera browser. If you find any solution for Opera, please send it to me in comments. Please also note that if you apply this style to an element with text, the text will be mirrored which would not make it readable.&lt;/li&gt;
&lt;/ol&gt;
&lt;div style="background-color: #f4f4f4; border-bottom: silver 1px solid; border-left: silver 1px solid; border-right: silver 1px solid; border-top: silver 1px solid; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; height: 95px; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding-bottom: 4px; padding-left: 4px; padding-right: 4px; padding-top: 4px; text-align: left; width: 80.66%;"&gt;
.flip-horizontal {    &lt;br /&gt;
-moz-transform: scaleX(-1);     &lt;br /&gt;
-webkit-transform: scaleX(-1);     &lt;br /&gt;
transform: scaleX(-1);     &lt;br /&gt;
filter: fliph; /*IE*/ }     &lt;br /&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li value="2"&gt;Server side flipping: A more trivial and cross browser way but will require a separate copy of every flipped image file. I suggest if the original image called x.jpg, the flipped one should be called x.rtl.jpg. This is just a naming convention and will not imply automatic loading. You will have to handle programmatically substituting images with flipped ones in case you detect the culture is RTL culture. &lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;



JavaScript files in RTL mode&lt;/h4&gt;
Usually JavaScript code don’t have problems with RTL layout. The catch here is that you should not specify any inline style properties in JavaScript files that affect horizontal layout as possible as you can. Use instead classes specified in CSS files, so they would be correct for both LTR and RTL layout or you will have to programmatically check for RTL and then reverse the style.   &lt;br /&gt;
&lt;h5&gt;



To determine the direction client side:&lt;/h5&gt;
According to &lt;a href="http://michaelfayez.blogspot.com/2010/01/proposal-for-dnn-support-of-rtl-layout.html" target="_blank"&gt;Part 1&lt;/a&gt; of this post direction propery is put in the portal.rtl.css file. So the only way to get this value in either use GetComputedStyle in Firefox or currentStyle for Internet Explorer. The function below is inspired from &lt;a href="http://www.howtocreate.co.uk/tutorials/javascript/domcss" target="_blank"&gt;here&lt;/a&gt;. The code&amp;nbsp;should be put in js/dnn.js file.   &lt;br /&gt;
&lt;div style="background-color: #f4f4f4; border-bottom: silver 1px solid; border-left: silver 1px solid; border-right: silver 1px solid; border-top: silver 1px solid; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; height: 130px; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding-bottom: 4px; padding-left: 4px; padding-right: 4px; padding-top: 4px; text-align: left; width: 80.66%;"&gt;
dnn.direction = function() {    &lt;br /&gt;
if (typeof (dnn.__direction) == "undefined") {     &lt;br /&gt;
var hElement = document.getElementsByTagName('html')[0];     &lt;br /&gt;
if (window.getComputedStyle)     &lt;br /&gt;
dnn.__direction = window.getComputedStyle(hElement, null).direction;     &lt;br /&gt;
else if (oElement.currentStyle)     &lt;br /&gt;
dnn.__direction = hElement.currentStyle.direction;     &lt;br /&gt;
}     &lt;br /&gt;
return dnn.__direction;     &lt;br /&gt;
}     &lt;br /&gt;
&lt;/div&gt;
&lt;h5&gt;



Explicit handling of RTL layout in JavaScript&lt;/h5&gt;
The only case I can think of now is handling absolute positioning set programmatically. Usually this is done in menus. Below the image of DNN menu in RTL layout   &lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/_Ah2PMbLLv4Y/S1j27dVKamI/AAAAAAAAABY/6retZaIDTKw/s1600-h/WrongMenuRTL.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_Ah2PMbLLv4Y/S1j27dVKamI/AAAAAAAAABY/6retZaIDTKw/s320/WrongMenuRTL.jpg" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
As the co-ordinates are not mirrored for RTL layout, the code adjusts the absolute position of menu to the left offset of the button. The solution here for RTL layout is if in RTL layout then it should position the menu = offsetLeft of button - menu width + offsetWidth of button and then the menu will look like the image below  &lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/_Ah2PMbLLv4Y/S1j3-Yda_kI/AAAAAAAAABg/P8rquzQG0ic/s1600-h/Correct+MenuRTL.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_Ah2PMbLLv4Y/S1j3-Yda_kI/AAAAAAAAABg/P8rquzQG0ic/s320/Correct+MenuRTL.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;



Catches:&lt;/h4&gt;
Real testing RTL layout should ALWAYS be done using an RTL script. In the screenshots above though text is aligned right but text itself is written from left to right which is not the case with RTL scripts (I took screenshots in English for simplicity). The RTL script is written from right to left. This text direction could affect in some cases the layout. For Example the image below is for Save/Cancel buttons are messed up because Latin script is written left to right regardless of alignment.  &lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/_Ah2PMbLLv4Y/S1j61SfJ77I/AAAAAAAAABo/0tBob6oVl3E/s1600-h/WrongOrderRegisterCancel.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_Ah2PMbLLv4Y/S1j61SfJ77I/AAAAAAAAABo/0tBob6oVl3E/s320/WrongOrderRegisterCancel.jpg" /&gt;&lt;/a&gt;    &lt;br /&gt;&lt;/div&gt;
As you see the save icon is beside cancel and the cancel icon is beside register. But when the text is really in RTL Arabic script, we see in the image below that everything is OK without doing any change.  &lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/_Ah2PMbLLv4Y/S1j8ZNxXq8I/AAAAAAAAABw/dx9R-1qlwx4/s1600-h/CorrectRegisterCancel.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_Ah2PMbLLv4Y/S1j8ZNxXq8I/AAAAAAAAABw/dx9R-1qlwx4/s320/CorrectRegisterCancel.jpg" /&gt;&lt;/a&gt;    &lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;



Recommendations:&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Changes to core DNN library and core modules should be done to handle both LTR and RTL layouts automatically.&lt;/li&gt;
&lt;li&gt;In &lt;a href="http://www.snowcovered.com/" target="_blank"&gt;snowcovered&lt;/a&gt; sold modules, there should be some info about if the displayed module is tested in RTL layout with the default to No.&lt;/li&gt;
&lt;li&gt;Every release of DNN or DNN core modules should be developed with RTL layout in mind and should be tested by a developer that knows a language that is written in RTL script ( There would be a lot of them especially Egyptians, Pakistanis and Israelis)&lt;/li&gt;
&lt;/ol&gt;
I didnt discuss the RTL localization of FCK editor. There is a post about it &lt;a href="http://www.dotnetnuke.com/Community/Forums/tabid/795/forumid/77/threadid/300971/scope/posts/Default.aspx"&gt;here&lt;/a&gt;.&lt;br /&gt;
Next week, I will publish the DNN code described here as a proof of concept.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8796582083368239187-1873788659245303352?l=michaelfayez.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/W0WFFG6WPw0SnWvd0P-ubaiVxUo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/W0WFFG6WPw0SnWvd0P-ubaiVxUo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/W0WFFG6WPw0SnWvd0P-ubaiVxUo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/W0WFFG6WPw0SnWvd0P-ubaiVxUo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MichaelFayezBlog/~4/yqd62RRfnCY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://michaelfayez.blogspot.com/feeds/1873788659245303352/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://michaelfayez.blogspot.com/2010/01/proposal-for-dnn-support-of-rtl-layout_22.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8796582083368239187/posts/default/1873788659245303352?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8796582083368239187/posts/default/1873788659245303352?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MichaelFayezBlog/~3/yqd62RRfnCY/proposal-for-dnn-support-of-rtl-layout_22.html" title="Proposal for DNN support of RTL layout Part 2" /><author><name>Michael Fayez</name><uri>http://www.blogger.com/profile/16252645336692523661</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_Ah2PMbLLv4Y/S1jhjiSpGPI/AAAAAAAAAA4/f2Jizw6bEFo/s72-c/direction.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://michaelfayez.blogspot.com/2010/01/proposal-for-dnn-support-of-rtl-layout_22.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEMR3g-cSp7ImA9WxBXEU8.&quot;"><id>tag:blogger.com,1999:blog-8796582083368239187.post-1089165759855812069</id><published>2010-01-15T03:25:00.000+02:00</published><updated>2010-01-22T03:28:06.659+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-22T03:28:06.659+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="RTL Layout" /><category scheme="http://www.blogger.com/atom/ns#" term="Localization" /><category scheme="http://www.blogger.com/atom/ns#" term="DotNetNuke" /><category scheme="http://www.blogger.com/atom/ns#" term="ASP.Net" /><category scheme="http://www.blogger.com/atom/ns#" term="DNN" /><title>Proposal for DNN support of RTL layout Part 1</title><content type="html">&lt;a href="http://www.dotnetnuke.com/" target="_blank"&gt;DotNetNuke&lt;/a&gt; or (DNN in short) is an open source CMS that is built over ASP.Net. It is also extensible using modules providing a powerful programming platform. Unfortunately it has some issues with right to left (RTL) layout. In this blog post I am proposing the steps to be done in DNN to fully support RTL and LTR in the same portal out of the box.   &lt;h4&gt;For any CMS to fully support localization it needs:&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;Static content localization: currently supported by DNN using Resx files and allows admins to modify them using the languages page in admin menu. admins can translate the resx files manually or just use a language pack if they can find a good and complete one. &lt;/li&gt;    &lt;li&gt;Dynamic content localization: DNN Corp is currently working on it. They put an infrastructure for dynamic content localization in version 5.2 but still not usable for the end-user. If you cannot wait for it to be complete you can use for example &lt;a href="http://magiccontent.codeplex.com/" target="_blank"&gt;Magic content&lt;/a&gt; instead of HTML module, &lt;a href="http://ealo.codeplex.com/" target="_blank"&gt;Ealo package&lt;/a&gt; for menu, breadcrumb localization and &lt;a href="http://nbstore.codeplex.com/" target="_blank"&gt;NBStore&lt;/a&gt; instead of DNN Store module. All these modules support dynamic content localization &lt;/li&gt;    &lt;li&gt;Right to left layout: for scripts that is written in right to left direction. Currently there is no official support for RTL in DNN. You will have to manually add in portal.css html {direction:rtl;} to make layout flipped. Most of the forms of DNN works good but some forms like login and manage profile don’t have a correct layout along with the default DNN menu in the default skin. Though the layout issue is not a blocking bug, it makes the layout looks wrong and amateurish for the end user. &lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;The scripts that uses right to left layout are:&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;Arabic script: which is used for writing Arabic, Persian, Urdu, Punjabi, Sindhi, etc. &lt;/li&gt;    &lt;li&gt;Hebrew script: which is used for writing Hebrew and Jewish languages like Yiddish, Ladino, etc. &lt;/li&gt;    &lt;li&gt;Scripts that are used by minority languages that nobody knows or cares about: like &lt;a href="http://en.wikipedia.org/wiki/Thaana" target="_blank"&gt;Thaana&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Syriac" target="_blank"&gt;Syriac&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/N%27Ko" target="_blank"&gt;N'Ko&lt;/a&gt;, etc. &lt;/li&gt; &lt;/ol&gt; Only Arabic and Hebrew scripts have economic value especially in the Persian Gulf area and in Israel.   &lt;br /&gt;  &lt;h4&gt;Root causes of messing up the RTL layout in web applications:&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;In table cell alignment when a cell content is aligned left it remains aligned left event in RTL direction and when aligned right it remains aligned right in RTL direction. It should be mirrored. So when in a perfect world when i say when in RTL mode an html element is having      &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: rgb(244,244,244); margin: 20px 0px 10px; padding-left: 4px; width: 56.16%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;,courier,monospace; direction: ltr; height: 76px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px"&gt;       &lt;p&gt;&amp;lt;table align=&amp;quot;left&amp;quot;&amp;gt;&lt;/p&gt;        &lt;br /&gt;&lt;/div&gt; it should align right and vice versa. unfortunately this is not the case.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;When using float left and float right css styles, they behave like point 1      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;When assuming that images are displayed in specific order horizontally, this order is reversed in RTL mode. So some images will need to be flipped to look as good as in LTR mode (will give an example for this when discussing image RTL localization).      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;The absolute positioning always starts from top left of the page regardless of the direction of the page (RTL or LTR). Usually this affects absolute positioning when an html element is placed using calculated co-ordinates to align left with another element. In RTL mode you should update the calculation to align right(will give an example for this when discussing JavaScript RTL localization). &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;These four reasons made some great Javascript frameworks like &lt;a href="http://www.extjs.com" target="_blank"&gt;ExtJs&lt;/a&gt; unusable in RTL layout without much customization.     &lt;br /&gt;&lt;/p&gt; Though this is out of topic, Microsoft did a really good job on supporting RTL layout out of the box in&amp;#160; Windows forms. When a control is positioned using a left anchor in RTL layout it is positioned right though the anchor is still left. All of the standard windows forms controls behaves well in RTL mode. (though not all third party windows forms controls support RTL mode like &lt;a href="http://www.devexpress.com/" target="_blank"&gt;Devexpress&lt;/a&gt; for example but this is not the time to discuss this here)   &lt;br /&gt;  &lt;br /&gt;  &lt;h4&gt;Straightforward steps to make DNN portal have an RTL layout:&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;modify portal.css and add &lt;/li&gt; &lt;/ol&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: rgb(244,244,244); margin: 20px 0px 10px; padding-left: 4px; width: 58.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;,courier,monospace; direction: ltr; height: 68px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px"&gt;   &lt;p&gt;html {direction:rtl;}&lt;/p&gt;    &lt;br /&gt;&lt;/div&gt;  &lt;ol&gt;   &lt;li&gt;Open ~/DesktopModules/AuthenticationServices/DNN/login.ascx and modify all table align=&amp;quot;left&amp;quot; to align=&amp;quot;right&amp;quot; and vice versa.      &lt;br /&gt;&lt;/li&gt; &lt;/ol&gt; Unfortunately the straight forward approach fails due to:   &lt;br /&gt;  &lt;ol&gt;   &lt;li&gt;Usually my customers want a multi lingual portal (English/Arabic) using dynamic content localization as described above. Adding the direction:rtl in portal.css will lead to displaying English language in RTL mode which is not correct.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;The default menu is still in LTR mode.&amp;#160; &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;The manage profile tab is messed up because of hardcoded style of text-align: left in Profile.ascx. (though the RTL issue is supposed to be &lt;a href="http://support.dotnetnuke.com/issue/ViewIssue.aspx?ID=7001&amp;amp;PROJID=2" target="_blank"&gt;resolved&lt;/a&gt; but apparently the developer that fixed it doesn’t know how RTL languages would look like because he left behind text-align: left which messed up the RTL layout) &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;So now we have a dead end for a trivial quick solution.&lt;/p&gt;  &lt;h4&gt;The good solution for the RTL problem:&lt;/h4&gt;  &lt;h5&gt;Requirements:&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;The solution should fix the problem of RTL without messing the layout of the LTR languages on the same multi-lingual portal. &lt;/li&gt; &lt;/ul&gt;  &lt;h5&gt;&lt;/h5&gt;  &lt;h5&gt;Detecting RTL culture server side:&lt;/h5&gt;  &lt;p&gt;We need to detect the RTL language culture server side to do some actions for handling RTL layout as I will discuss later. The best way to do this is using Thread.CurrentThread.CurrentUICulture.TextInfo.IsRightToLeft property which is deeply buried in the properties of the properties of the properties of the current thread object.&lt;/p&gt;  &lt;p&gt;I suggest adding a shared/static readonly property to DotNetNuke.Services.Localization.Localization class to return the IsRightToLeft property&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: rgb(244,244,244); margin: 20px 0px 10px; padding-left: 4px; width: 87%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;,courier,monospace; direction: ltr; height: 137px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px"&gt;   &lt;p&gt;Public Shared ReadOnly Property IsRightToLeft() As Boolean      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return Thread.CurrentThread.CurrentUICulture.TextInfo.IsRightToLeft       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End Get       &lt;br /&gt;End Property&lt;/p&gt;    &lt;br /&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Handling the embedded styles in tags:&lt;/p&gt;  &lt;p&gt;After digging into the DNN code, I found an enumeration called DotNetNuke.UI.WebControls.LabelMode. this enumeration is used by the FieldEditorControl to display the register and the user profile control. Labels have the LabelMode left and controls have the LabelMode right. And then the FieldEditorControl calls the ToSring().ToLower() for the enumeration to get the text to embed in style left or right (these are the two properties we care about now for RTL layout). So the good news is that if we override the ToString() of the enumeration to render left property if not RTL then &amp;quot;left&amp;quot; else &amp;quot;right&amp;quot; and vice versa, all the forms that uses this control will be adjusted automatically without handling them case by case. The bad news is that there is no support for overriding ToString() method for enumerations :). So we will need an extension method to get label mode text and get the correct string according to text layout and this extension method should be used instead of ToString()&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: rgb(244,244,244); margin: 20px 0px 10px; padding-left: 4px; width: 94.92%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;,courier,monospace; direction: ltr; height: 146px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px"&gt;   &lt;p&gt;Public Module LabelModeHelper      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Runtime.CompilerServices.Extension()&amp;gt; _       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Public Function GetLabelModeString(ByVal mode As LabelMode) As String       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If mode &amp;lt;&amp;gt; LabelMode.Left AndAlso mode &amp;lt;&amp;gt; LabelMode.Right Then Return mode.ToString().ToLower()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If mode = LabelMode.Left Then       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return If(Localization.IsRightToLeft, &amp;quot;right&amp;quot;, &amp;quot;left&amp;quot;)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If mode = LabelMode.Right Then       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return If(Localization.IsRightToLeft, &amp;quot;left&amp;quot;, &amp;quot;right&amp;quot;)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return String.Empty       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End Function       &lt;br /&gt;&amp;#160;&amp;#160; End Module&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;There remains another issue; handling LabelMode in RTL is &lt;a href="http://support.dotnetnuke.com/issue/ViewIssue.aspx?ID=7001&amp;amp;PROJID=2" target="_blank"&gt;fixed&lt;/a&gt; in three places Membership, Profile and User user controls. the same code is copy pasted 3 times in the user control. I write it here for convenience&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: rgb(244,244,244); margin: 20px 0px 10px; padding-left: 4px; width: 96.03%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;,courier,monospace; direction: ltr; height: 147px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px"&gt;   &lt;p&gt;Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'Get the base Page       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dim basePage As PageBase = TryCast(Me.Page, PageBase)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If basePage IsNot Nothing Then       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'Check if culture is RTL       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If basePage.PageCulture.TextInfo.IsRightToLeft Then       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; UserEditor.LabelMode = LabelMode.Right       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Else       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; UserEditor.LabelMode = LabelMode.Left       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End Sub&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;The code above is not based on a good design as it was written 3 times over and over again!!!! I commented it to make my code work as it would conflict with it. In my code I am trying to imitate the perfect case of Windows forms as I mentioned above. Thus developers would LabelMode.Left without bothering to think how it should be rendered in RTL mode.&lt;/p&gt;  &lt;p&gt;For styles embedded in ascx align=&amp;quot;left&amp;quot; or text-align:left, and also for right all these makes RTL layout looks odd. So all these should be deleted except if really needed and use the following code &amp;lt;%= LabelMode.Left.GetLabelModeString %&amp;gt; for hard coded part of &amp;quot;left&amp;quot; or move the embded alignments like float, text-align to CSS files which I will discuss now how to localize them.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h5&gt;Handling CSS in RTL mode:&lt;/h5&gt;  &lt;p&gt;The CSS files would contain values of float:left , float:right, text-align:left, etc. These values should be reversed in RTL mode. The solution I propose here is to immitate ScriptManager control in ASP.Net for loading javascript files. For example when ScriptManager loads x.js file, if ASP.Net is in debug mode and there exists a file called x.debug.js, this file will be loaded instead of x.js which would be loaded in release mode.&lt;/p&gt;  &lt;p&gt;I suggest that all css would be optimized for LTR mode for example a file called x.css and if there is style in it that would make RTL looks odd, it would be overridden in another CSS file with the same name for example x.rtl.css&amp;#160; with the same classes but with only the parts that&amp;#160; make a conflict overridden and loaded only when the language is detected to have an RTL layout. So in this case of RTL language both files would be loaded unlike what the ScriptManager does.&lt;/p&gt;  &lt;p&gt;To achieve this we need to modify the code in the AddStyleSheet method in CDefault class in the core DNN library to check if:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;An RTL language is used for current culture &lt;/li&gt;    &lt;li&gt;and there exists a file with the same name of the CSS file being added to the page ending with .rtl.css &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;if both conditions are fulfilled then the .rtl.css class is loaded immediately after the file being added.&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: rgb(244,244,244); margin: 20px 0px 10px; padding-left: 4px; width: 94.33%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;,courier,monospace; direction: ltr; height: 147px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px"&gt;   &lt;p&gt;Public Sub AddStyleSheet(ByVal id As String, ByVal href As String, ByVal isFirst As Boolean)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 'Find the placeholder control       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Dim objCSS As Control = Me.FindControl(&amp;quot;CSS&amp;quot;) &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; If Not objCSS Is Nothing Then      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'First see if we have already added the &amp;lt;LINK&amp;gt; control       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dim objCtrl As Control = Page.Header.FindControl(id) &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If objCtrl Is Nothing Then      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dim objLink As New HtmlLink()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objLink.ID = id       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objLink.Attributes(&amp;quot;rel&amp;quot;) = &amp;quot;stylesheet&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objLink.Attributes(&amp;quot;type&amp;quot;) = &amp;quot;text/css&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objLink.Href = href &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If isFirst Then      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'Find the first HtmlLink       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dim iLink As Integer       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; For iLink = 0 To objCSS.Controls.Count - 1       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If TypeOf objCSS.Controls(iLink) Is HtmlLink Then       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Exit For       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Next       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objCSS.Controls.AddAt(iLink, objLink)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If Localization.IsRightToLeft Then       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AddRTLStyleSheet(id, href, objCSS, iLink + 1)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Else       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objCSS.Controls.Add(objLink)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If Localization.IsRightToLeft Then       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AddRTLStyleSheet(id, href, objCSS)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;End Sub       &lt;br /&gt;      &lt;br /&gt;Private Sub AddRTLStyleSheet(ByVal id As String, ByVal href As String, ByVal objCSS As Control, Optional ByVal index As Integer = -1)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Dim rtlhref As String = GetRTLStyleSheetName(href)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; If String.IsNullOrEmpty(rtlhref) Then Return       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Dim objLink As New HtmlLink()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; objLink.ID = id + &amp;quot;rtl_&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; objLink.Attributes(&amp;quot;rel&amp;quot;) = &amp;quot;stylesheet&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; objLink.Attributes(&amp;quot;type&amp;quot;) = &amp;quot;text/css&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; objLink.Href = rtlhref       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; If index &amp;lt;&amp;gt; -1 Then       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objCSS.Controls.AddAt(index, objLink)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Else       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objCSS.Controls.Add(objLink)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End If &lt;/p&gt;    &lt;p&gt;End Sub      &lt;br /&gt;      &lt;br /&gt;Private Function GetRTLStyleSheetName(ByVal href As String) As String       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Dim physicalFilePath As String = Server.MapPath(href)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; If Path.GetExtension(physicalFilePath).ToLower &amp;lt;&amp;gt; &amp;quot;.css&amp;quot; Then       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return Nothing       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; physicalFilePath = physicalFilePath.Substring(0, physicalFilePath.Length - 4) + &amp;quot;.rtl.css&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; If File.Exists(physicalFilePath) Then       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Return href.Substring(0, href.Length - 4) + &amp;quot;.rtl.css&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; End If       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Return Nothing       &lt;br /&gt;End Function&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;I have tested the code above and it loaded portal.rtl.css, skin.rtl.css and index.rtl.css which are files that I made. It may not be fully optimized but it is a start at least.&lt;/p&gt;  &lt;p&gt;portal.rtl.css is the file that should contain html {direction:rtl;} not in portal.css.&lt;/p&gt;  &lt;p&gt;The rtl css files should be only overriding properties in&amp;#160; css classes in the normal css files that are only related to rtl only. No need to copy/paste the stylesheet and make changes. This way you will double size of css and will have to maintain 2 css files. Below is an example for this.&lt;/p&gt;  &lt;p&gt;In portal.css file there is class&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: rgb(244,244,244); margin: 20px 0px 10px; padding-left: 4px; width: 64.54%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;,courier,monospace; direction: ltr; height: 77px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px"&gt;.branding-bottom li { list-style: none; margin: 0 10px 0 0; padding: 0; display: block; width: 170px; float: left; }&lt;/div&gt;  &lt;p&gt;In portal.rtl.css there should be&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: rgb(244,244,244); margin: 20px 0px 10px; padding-left: 4px; width: 64.76%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;,courier,monospace; direction: ltr; height: 35px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px"&gt;.branding-bottom li { float: right; margin: 0 0 0 10px; }&lt;/div&gt;  &lt;p&gt;In my next post, I will discuss the 2 remaining aspects of RTL localization; localizing images and JavaScript files. I will publish my modified code as a proof of concept but won’t be suitable for production.&lt;/p&gt;  &lt;p&gt;I hope that DNN corp incorporate these changes to make DNN more powerful than it already is.&lt;/p&gt;  &lt;p&gt;Acknowledgements: I copied the style of the grey code boxes form &lt;a href="http://weblogs.asp.net/pawanmishra/" target="_blank"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8796582083368239187-1089165759855812069?l=michaelfayez.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/DWN52JlWqRY-bksbZELIztfIk-E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/DWN52JlWqRY-bksbZELIztfIk-E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/DWN52JlWqRY-bksbZELIztfIk-E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/DWN52JlWqRY-bksbZELIztfIk-E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MichaelFayezBlog/~4/dXWCrS2BK20" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://michaelfayez.blogspot.com/feeds/1089165759855812069/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://michaelfayez.blogspot.com/2010/01/proposal-for-dnn-support-of-rtl-layout.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8796582083368239187/posts/default/1089165759855812069?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8796582083368239187/posts/default/1089165759855812069?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MichaelFayezBlog/~3/dXWCrS2BK20/proposal-for-dnn-support-of-rtl-layout.html" title="Proposal for DNN support of RTL layout Part 1" /><author><name>Michael Fayez</name><uri>http://www.blogger.com/profile/16252645336692523661</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://michaelfayez.blogspot.com/2010/01/proposal-for-dnn-support-of-rtl-layout.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQBRXc5fyp7ImA9WxBQFE8.&quot;"><id>tag:blogger.com,1999:blog-8796582083368239187.post-6949982573731376800</id><published>2010-01-14T02:01:00.001+02:00</published><updated>2010-01-14T02:02:34.927+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-14T02:02:34.927+02:00</app:edited><title>My first post</title><content type="html">&lt;p&gt;This my first time to start blogging. I found myself tempted to start a blog to share my ideas with the developer community. For what I see now, I will always blog about programming and software development. Talking about politics could be dangerous :) so I hope I won’t speak about them&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8796582083368239187-6949982573731376800?l=michaelfayez.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/tPFzclikk4pkLqndcxOh_RrbtRc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tPFzclikk4pkLqndcxOh_RrbtRc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/tPFzclikk4pkLqndcxOh_RrbtRc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tPFzclikk4pkLqndcxOh_RrbtRc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MichaelFayezBlog/~4/dDbsU9UOvq4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://michaelfayez.blogspot.com/feeds/6949982573731376800/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://michaelfayez.blogspot.com/2010/01/my-first-post.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8796582083368239187/posts/default/6949982573731376800?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8796582083368239187/posts/default/6949982573731376800?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MichaelFayezBlog/~3/dDbsU9UOvq4/my-first-post.html" title="My first post" /><author><name>Michael Fayez</name><uri>http://www.blogger.com/profile/16252645336692523661</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://michaelfayez.blogspot.com/2010/01/my-first-post.html</feedburner:origLink></entry></feed>

