[gen] Added support for right-to-left (RTL) languages.

This commit is contained in:
Gaetan Delannay 2012-06-27 13:27:24 +02:00
parent b680a5ddcb
commit 1b375d387c
18 changed files with 83 additions and 41 deletions

View file

@ -110,7 +110,7 @@ class ToolMixin(BaseMixin):
if not cfg.languageSelector: return if not cfg.languageSelector: return
if len(cfg.languages) < 2: return if len(cfg.languages) < 2: return
page = self.REQUEST.get('ACTUAL_URL').split('/')[-1] page = self.REQUEST.get('ACTUAL_URL').split('/')[-1]
return page not in ('edit', 'query', 'search') return page not in ('edit', 'query', 'search', 'do')
def getLanguages(self): def getLanguages(self):
'''Returns the supported languages. First one is the default.''' '''Returns the supported languages. First one is the default.'''
@ -128,11 +128,21 @@ class ToolMixin(BaseMixin):
rq.RESPONSE.setCookie('_ZopeLg', rq['language'], path='/') rq.RESPONSE.setCookie('_ZopeLg', rq['language'], path='/')
return self.goto(rq['HTTP_REFERER']) return self.goto(rq['HTTP_REFERER'])
def flipLanguageDirection(self, align, dir):
'''According to language direction p_dir ('ltr' or 'rtl'), this method
turns p_align from 'left' to 'right' (or the inverse) when
required.'''
if dir == 'ltr': return align
if align == 'left': return 'right'
if align == 'right': return 'left'
return align
def getGlobalCssJs(self): def getGlobalCssJs(self):
'''Returns the list of CSS and JS files to include in the main template. '''Returns the list of CSS and JS files to include in the main template.
The method ensures that appy.css and appy.js come first.''' The method ensures that appy.css and appy.js come first.'''
names = self.getPhysicalRoot().ui.objectIds('File') names = self.getPhysicalRoot().ui.objectIds('File')
names.remove('appy.js'); names.insert(0, 'appy.js') names.remove('appy.js'); names.insert(0, 'appy.js')
names.remove('appyrtl.css'); names.insert(0, 'appyrtl.css')
names.remove('appy.css'); names.insert(0, 'appy.css') names.remove('appy.css'); names.insert(0, 'appy.css')
return names return names

View file

@ -10,6 +10,7 @@ from appy.gen.utils import *
from appy.gen.layout import Table, defaultPageLayouts from appy.gen.layout import Table, defaultPageLayouts
from appy.gen.descriptors import WorkflowDescriptor, ClassDescriptor from appy.gen.descriptors import WorkflowDescriptor, ClassDescriptor
from appy.shared.utils import sequenceTypes from appy.shared.utils import sequenceTypes
from appy.shared.data import rtlLanguages
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class BaseMixin: class BaseMixin:
@ -1404,6 +1405,11 @@ class BaseMixin:
if '-' in res: res = res[:res.find('-')] if '-' in res: res = res[:res.find('-')]
return res return res
def getLanguageDirection(self, lang):
'''Determines if p_lang is a LTR or RTL language.'''
if lang in rtlLanguages: return 'rtl'
return 'ltr'
def formatText(self, text, format='html'): def formatText(self, text, format='html'):
'''Produces a representation of p_text into the desired p_format, which '''Produces a representation of p_text into the desired p_format, which
is "html" by default.''' is "html" by default.'''

View file

@ -15,9 +15,13 @@
app tool/getApp; app tool/getApp;
appUrl app/absolute_url; appUrl app/absolute_url;
template python: contextObj.getPageTemplate(app.ui, page); template python: contextObj.getPageTemplate(app.ui, page);
lang tool/getUserLanguage;
dir python: tool.getLanguageDirection(lang);
dleft python: (dir == 'ltr') and 'left' or 'right';
dright python: (dir == 'ltr') and 'right' or 'left';
x python: resp.setHeader('Content-Type','text/html;;charset=utf-8'); x python: resp.setHeader('Content-Type','text/html;;charset=utf-8');
x python: resp.setHeader('Expires', 'Mon, 11 Dec 1975 12:05:05 GMT'); x python: resp.setHeader('Expires', 'Mon, 11 Dec 1975 12:05:05 GMT');
x python: resp.setHeader('Content-Language', req.get('language', 'en')); x python: resp.setHeader('Content-Language', lang);
x python: resp.setHeader('CacheControl', 'no-cache')"> x python: resp.setHeader('CacheControl', 'no-cache')">
<tal:comment replace="nothing">Keys "Expires" and "CacheControl" are used for preventing IE to cache <tal:comment replace="nothing">Keys "Expires" and "CacheControl" are used for preventing IE to cache
this page. Indeed, this page is retrieved through an asynchronous XMLHttpRequest by the browser, and this page. Indeed, this page is retrieved through an asynchronous XMLHttpRequest by the browser, and

View file

@ -92,6 +92,7 @@ img { border: 0; vertical-align: middle}
.grid th { font-style: italic; font-weight: normal; .grid th { font-style: italic; font-weight: normal;
border-bottom: 2px solid grey; padding: 2px 2px;} border-bottom: 2px solid grey; padding: 2px 2px;}
.grid td { padding-right: 5px; } .grid td { padding-right: 5px; }
.cellGap { padding-right: 0.4em; }
.noStyle { border: 0 !important; padding: 0 !important; margin: 0 !important; } .noStyle { border: 0 !important; padding: 0 !important; margin: 0 !important; }
.noStyle td { border:0 !important; padding:0 !important; margin:0 !important; } .noStyle td { border:0 !important; padding:0 !important; margin:0 !important; }
.translationLabel { background-color: #EAEAEA; border-bottom: 1px dashed grey; .translationLabel { background-color: #EAEAEA; border-bottom: 1px dashed grey;

7
gen/ui/appyrtl.css Normal file
View file

@ -0,0 +1,7 @@
ul { margin: 0 0.6em 0.2em 0 }
ul li { background-image: url("ui/lirtl.gif");
background-position: right center;
padding-right: 15px; padding-left: 0px}
.portlet { border-right: none; border-left: 1px solid #5F7983 }
.lang { margin-right: 0px; margin-left: 6px; }
.cellGap { padding-left: 0.4em; }

BIN
gen/ui/bannerrtl.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

@ -1,4 +1,4 @@
<table metal:define-macro="footer" <table metal:define-macro="footer"
cellpadding="0" cellspacing="0" width="100%" class="footer"> cellpadding="0" cellspacing="0" width="100%" class="footer">
<tr><td align="right">Made with <a href="http://appyframework.org" target="_blank">Appy</a></td></tr> <tr><td tal:attributes="align dright">Made with <a href="http://appyframework.org" target="_blank">Appy</a></td></tr>
</table> </table>

BIN
gen/ui/lirtl.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 B

View file

@ -1,4 +1,4 @@
<div metal:define-macro="appyNavigate" tal:condition="python: totalNumber &gt; batchSize" align="right"> <div metal:define-macro="appyNavigate" tal:condition="python: totalNumber &gt; batchSize" tal:attributes="align dright">
<tal:comment replace="nothing"> <tal:comment replace="nothing">
Buttons for navigating among a list of elements (next, back, first, last, etc). Buttons for navigating among a list of elements (next, back, first, last, etc).
</tal:comment> </tal:comment>

View file

@ -72,10 +72,10 @@
<metal:nav use-macro="context/ui/navigate/macros/appyNavigate"/> <metal:nav use-macro="context/ui/navigate/macros/appyNavigate"/>
<table width="100%" class="history"> <table width="100%" class="history">
<tr> <tr>
<th align="left">Action</th> <th tal:attributes="align dleft">Action</th>
<th align="left">By</th> <th tal:attributes="align dleft">By</th>
<th align="left">Date</th> <th tal:attributes="align dleft">Date</th>
<th align="left">Comment</th> <th tal:attributes="align dleft">Comment</th>
</tr> </tr>
<tal:event repeat="event objs"> <tal:event repeat="event objs">
<tr tal:define="odd repeat/event/odd; <tr tal:define="odd repeat/event/odd;
@ -98,8 +98,8 @@
Display the previous values of the fields whose value were modified in this change.</tal:comment> Display the previous values of the fields whose value were modified in this change.</tal:comment>
<table class="appyChanges" width="100%"> <table class="appyChanges" width="100%">
<tr> <tr>
<th align="left" width="30%" tal:content="python: _('modified_field')"></th> <th tal:attributes="align dleft" width="30%" tal:content="python: _('modified_field')"></th>
<th align="left" width="70%" tal:content="python: _('previous_value')"></th> <th tal:attributes="align dleft" width="70%" tal:content="python: _('previous_value')"></th>
</tr> </tr>
<tr tal:repeat="change event/changes/items" valign="top"> <tr tal:repeat="change event/changes/items" valign="top">
<tal:change define="appyType python:contextObj.getAppyType(change[0], asDict=True);"> <tal:change define="appyType python:contextObj.getAppyType(change[0], asDict=True);">
@ -157,7 +157,7 @@
<tal:comment replace="nothing">Input field for storing comment</tal:comment> <tal:comment replace="nothing">Input field for storing comment</tal:comment>
<textarea id="comment" name="comment" cols="30" rows="3" style="display:none"></textarea> <textarea id="comment" name="comment" cols="30" rows="3" style="display:none"></textarea>
<tal:comment replace="nothing">Buttons for triggering transitions</tal:comment> <tal:comment replace="nothing">Buttons for triggering transitions</tal:comment>
<td align="right" tal:repeat="transition transitions"> <td tal:attributes="align dright" tal:repeat="transition transitions">
<tal:comment replace="nothing">Real button</tal:comment> <tal:comment replace="nothing">Real button</tal:comment>
<input type="button" tal:condition="transition/may_trigger" <input type="button" tal:condition="transition/may_trigger"
tal:attributes="value transition/title; tal:attributes="value transition/title;
@ -198,8 +198,9 @@
<tal:comment replace="nothing">Creator and last modification date</tal:comment> <tal:comment replace="nothing">Creator and last modification date</tal:comment>
<tal:comment replace="nothing">Plus/minus icon for accessing history</tal:comment> <tal:comment replace="nothing">Plus/minus icon for accessing history</tal:comment>
<tal:accessHistory condition="hasHistory"> <tal:accessHistory condition="hasHistory">
<img align="left" style="cursor:pointer" onClick="toggleCookie('appyHistory')" <img style="cursor:pointer" onClick="toggleCookie('appyHistory')"
tal:attributes="src python:test(historyExpanded, 'ui/collapse.gif', 'ui/expand.gif');" tal:attributes="src python:test(historyExpanded, 'ui/collapse.gif', 'ui/expand.gif');
align dleft"
id="appyHistory_img"/>&nbsp; id="appyHistory_img"/>&nbsp;
<span>History</span> ||&nbsp; <span>History</span> ||&nbsp;
</tal:accessHistory> </tal:accessHistory>
@ -233,7 +234,7 @@
<table width="100%"> <table width="100%">
<tr> <tr>
<td><metal:states use-macro="here/ui/page/macros/states"/></td> <td><metal:states use-macro="here/ui/page/macros/states"/></td>
<td align="right"><metal:states use-macro="here/ui/page/macros/transitions"/></td> <td tal:attributes="align dright"><metal:states use-macro="here/ui/page/macros/transitions"/></td>
</tr> </tr>
</table> </table>
</td> </td>

View file

@ -62,10 +62,11 @@
expanded python: request.get(group['labelId'], 'collapsed') == 'expanded'"> expanded python: request.get(group['labelId'], 'collapsed') == 'expanded'">
<tal:comment replace="nothing">Group name</tal:comment> <tal:comment replace="nothing">Group name</tal:comment>
<div class="portletGroup"> <div class="portletGroup">
<img align="left" style="cursor:pointer; margin-right: 3px" <img style="cursor:pointer; margin-right: 3px"
tal:attributes="id python: '%s_img' % group['labelId']; tal:attributes="id python: '%s_img' % group['labelId'];
src python:test(expanded, 'ui/collapse.gif', 'ui/expand.gif'); src python:test(expanded, 'ui/collapse.gif', 'ui/expand.gif');
onClick python:'toggleCookie(\'%s\')' % group['labelId']"/> onClick python:'toggleCookie(\'%s\')' % group['labelId'];
align dleft"/>
<span tal:replace="group/label"/> <span tal:replace="group/label"/>
</div> </div>
<tal:comment replace="nothing">Group searches</tal:comment> <tal:comment replace="nothing">Group searches</tal:comment>

View file

@ -27,10 +27,10 @@
<tal:result condition="objs"> <tal:result condition="objs">
<tal:comment replace="nothing">Display here POD templates if required.</tal:comment> <tal:comment replace="nothing">Display here POD templates if required.</tal:comment>
<table align="right" <table tal:define="widgets python: tool.getResultPodFields(className);
tal:define="widgets python: tool.getResultPodFields(className);
layoutType python:'view'" layoutType python:'view'"
tal:condition="python: objs and widgets"> tal:condition="python: objs and widgets"
tal:attributes="align dright">
<tr> <tr>
<td tal:define="contextObj python: objs[0]" tal:repeat="widget widgets"> <td tal:define="contextObj python: objs[0]" tal:repeat="widget widgets">
<metal:pod use-macro="context/ui/widgets/show/macros/field"/>&nbsp;&nbsp;&nbsp; <metal:pod use-macro="context/ui/widgets/show/macros/field"/>&nbsp;&nbsp;&nbsp;
@ -55,7 +55,7 @@
<span class="discreet" tal:content="descr"></span><br/> <span class="discreet" tal:content="descr"></span><br/>
</td> </td>
</tal:descr> </tal:descr>
<td align="right" width="25%"> <td tal:attributes="align dright" width="25%">
<tal:comment replace="nothing">Appy (top) navigation</tal:comment> <tal:comment replace="nothing">Appy (top) navigation</tal:comment>
<metal:nav use-macro="context/ui/navigate/macros/appyNavigate"/> <metal:nav use-macro="context/ui/navigate/macros/appyNavigate"/>
</td> </td>
@ -118,7 +118,7 @@
tal:content="python: _(obj.portal_type)"></td> tal:content="python: _(obj.portal_type)"></td>
<tal:comment replace="nothing">Column "Actions"</tal:comment> <tal:comment replace="nothing">Column "Actions"</tal:comment>
<td align="right"> <td tal:attributes="align dright">
<table class="noStyle" tal:condition="obj/mayAct"> <table class="noStyle" tal:condition="obj/mayAct">
<tr> <tr>
<tal:comment replace="nothing">Edit the element</tal:comment> <tal:comment replace="nothing">Edit the element</tal:comment>

View file

@ -39,7 +39,7 @@
</table> </table>
<tal:comment replace="nothing">Submit button</tal:comment> <tal:comment replace="nothing">Submit button</tal:comment>
<p align="right"><br/> <p tal:attributes="align dright"><br/>
<input type="submit" tal:attributes="value python: _('search_button')"/> <input type="submit" tal:attributes="value python: _('search_button')"/>
</p> </p>
</form> </form>

View file

@ -9,14 +9,19 @@
_ python: tool.translate; _ python: tool.translate;
req python: request; req python: request;
resp req/RESPONSE; resp req/RESPONSE;
lang tool/getUserLanguage;
dir python: tool.getLanguageDirection(lang);
dleft python: (dir == 'ltr') and 'left' or 'right';
dright python: (dir == 'ltr') and 'right' or 'left';
x python: resp.setHeader('Content-type', 'text/html;;charset=UTF-8'); x python: resp.setHeader('Content-type', 'text/html;;charset=UTF-8');
x python: resp.setHeader('Expires', 'Thu, 11 Dec 1975 12:05:00 GMT+2'); x python: resp.setHeader('Expires', 'Thu, 11 Dec 1975 12:05:00 GMT+2');
x python: resp.setHeader('Content-Language', req.get('language', 'en'))"> x python: resp.setHeader('Content-Language', lang)"
tal:attributes="dir python: tool.getLanguageDirection(lang)">
<head> <head>
<title tal:content="tool/getAppName"></title> <title tal:content="tool/getAppName"></title>
<tal:link repeat="name tool/getGlobalCssJs"> <tal:link repeat="name tool/getGlobalCssJs">
<link tal:condition="python: name.endswith('.css')" <link tal:condition="python: name.endswith('.css') and not ((dir == 'ltr') and (name == 'appyrtl.css'))"
rel="stylesheet" type="text/css" tal:attributes="href string:$appUrl/ui/$name"/> rel="stylesheet" type="text/css" tal:attributes="href string:$appUrl/ui/$name"/>
<script tal:condition="python: name.endswith('.js')" <script tal:condition="python: name.endswith('.js')"
type="text/javascript" tal:attributes="src string:$appUrl/ui/$name"></script> type="text/javascript" tal:attributes="src string:$appUrl/ui/$name"></script>
@ -27,16 +32,16 @@
<table class="main" align="center" cellpadding="0"> <table class="main" align="center" cellpadding="0">
<tal:comment replace="nothing">Top banner</tal:comment> <tal:comment replace="nothing">Top banner</tal:comment>
<tr class="top" metal:define-slot="top"> <tr class="top" metal:define-slot="top">
<td tal:attributes="style python: 'background-image: url(%s/ui/banner.jpg)' % appUrl"> <td tal:define="bannerName python: (dir == 'ltr') and 'banner' or 'bannerrtl'"
tal:attributes="style python: 'background-image: url(%s/ui/%s.jpg)' % (appUrl, bannerName)">
<table width="100%"> <table width="100%">
<tr valign="top"> <tr valign="top" tal:define="pages tool/getMainPages">
<tal:comment replace="nothing">Links to main pages</tal:comment> <tal:comment replace="nothing">Links to main pages</tal:comment>
<td> <td tal:condition="pages"><a tal:repeat="page pages" class="pageLink"
<a tal:repeat="page tool/getMainPages" class="pageLink"
tal:content="page/title" tal:attributes="href page/absolute_url"></a> tal:content="page/title" tal:attributes="href page/absolute_url"></a>
</td> </td>
<tal:comment replace="nothing">Language selector (links or listbox)</tal:comment> <tal:comment replace="nothing">Language selector (links or listbox)</tal:comment>
<td align="right" tal:condition="tool/showLanguageSelector"> <td tal:condition="tool/showLanguageSelector" tal:attributes="align dright">
<tal:lgs define="languages tool/getLanguages; <tal:lgs define="languages tool/getLanguages;
defaultLanguage python: languages[0]; defaultLanguage python: languages[0];
asLinks python: len(languages) &lt;= 8"> asLinks python: len(languages) &lt;= 8">
@ -51,7 +56,7 @@
</tr> </tr>
</table> </table>
<select tal:condition="not: asLinks" <select tal:condition="not: asLinks"
tal:attributes="onchange string:window.location='${context/absolute_url}/switchLanguage?set_language=' + this.options[this.selectedIndex].value"> tal:attributes="onchange string:window.location='$appUrl/config/changeLanguage?language=' + this.options[this.selectedIndex].value">
<option tal:repeat="lang languages" <option tal:repeat="lang languages"
tal:content="python: tool.getLanguageName(lang)" tal:content="python: tool.getLanguageName(lang)"
tal:attributes="selected python:defaultLanguage == lang; value lang"> tal:attributes="selected python:defaultLanguage == lang; value lang">
@ -79,7 +84,7 @@
<p id="appyConfirmText"></p> <p id="appyConfirmText"></p>
<input type="hidden" name="actionType"/> <input type="hidden" name="actionType"/>
<input type="hidden" name="action"/> <input type="hidden" name="action"/>
<div id="commentArea" align="left"><br/> <div id="commentArea" tal:attributes="align dleft"><br/>
<span tal:content="python: _('workflow_comment')" class="discreet"></span> <span tal:content="python: _('workflow_comment')" class="discreet"></span>
<textarea name="comment" cols="30" rows="3"></textarea> <textarea name="comment" cols="30" rows="3"></textarea>
<br/> <br/>
@ -143,7 +148,7 @@
<img tal:attributes="src string: $appUrl/ui/logout.gif"/> <img tal:attributes="src string: $appUrl/ui/logout.gif"/>
</a> </a>
</td> </td>
<td align="right" class="userStripText" tal:define="userInfo tool/getUserLine"> <td class="userStripText" tal:define="userInfo tool/getUserLine" tal:attributes="align dright">
<span tal:content="python: userInfo[0]"></span> <span tal:content="python: userInfo[0]"></span>
<a tal:condition="python: userInfo[1]" <a tal:condition="python: userInfo[1]"
tal:attributes="href python: userInfo[1]"> tal:attributes="href python: userInfo[1]">

View file

@ -9,7 +9,8 @@
</tal:show> </tal:show>
</td> </td>
<tal:comment replace="nothing">Icon for removing the row</tal:comment> <tal:comment replace="nothing">Icon for removing the row</tal:comment>
<td align="right" tal:condition="python: layoutType=='edit'"> <td tal:condition="python: layoutType=='edit'"
tal:attributes="align dright">
<img style="cursor:pointer" <img style="cursor:pointer"
tal:attributes="src string:$appUrl/ui/delete.png; tal:attributes="src string:$appUrl/ui/delete.png;
title python: 'Delete'; title python: 'Delete';

View file

@ -208,7 +208,7 @@
</tal:other> </tal:other>
</td> </td>
<tal:comment replace="nothing">Actions</tal:comment> <tal:comment replace="nothing">Actions</tal:comment>
<td align="right"> <td tal:attributes="align dright">
<tal:show condition="obj/mayAct"> <tal:show condition="obj/mayAct">
<metal:showObjectActions use-macro="app/ui/widgets/ref/macros/objectActions" /> <metal:showObjectActions use-macro="app/ui/widgets/ref/macros/objectActions" />
</tal:show> </tal:show>

View file

@ -22,7 +22,7 @@
<table tal:attributes="cellpadding layout/cellpadding; <table tal:attributes="cellpadding layout/cellpadding;
cellspacing layout/cellspacing; cellspacing layout/cellspacing;
width layout/width; width layout/width;
align layout/align; align python: tool.flipLanguageDirection(layout['align'], dir);
class python: tagCss and ('%s %s' % (tagCss, layoutCss)).strip() or layoutCss; class python: tagCss and ('%s %s' % (tagCss, layoutCss)).strip() or layoutCss;
style layout/style; style layout/style;
id tagId; id tagId;
@ -30,14 +30,16 @@
<tal:comment replace="nothing">The table header row</tal:comment> <tal:comment replace="nothing">The table header row</tal:comment>
<tr tal:condition="layout/headerRow" tal:attributes="valign layout/headerRow/valign"> <tr tal:condition="layout/headerRow" tal:attributes="valign layout/headerRow/valign">
<th tal:repeat="cell layout/headerRow/cells" <th tal:repeat="cell layout/headerRow/cells"
tal:attributes="align cell/align; width cell/width;"> tal:attributes="align python: tool.flipLanguageDirection(cell['align'], dir);
width cell/width;">
</th> </th>
</tr> </tr>
<tal:comment replace="nothing">The table content</tal:comment> <tal:comment replace="nothing">The table content</tal:comment>
<tr tal:repeat="row layout/rows" tal:attributes="valign row/valign"> <tr tal:repeat="row layout/rows" tal:attributes="valign row/valign">
<td tal:repeat="cell row/cells" <td tal:repeat="cell row/cells"
tal:attributes="align cell/align; colspan cell/colspan; tal:attributes="align python: tool.flipLanguageDirection(cell['align'], dir);
style python: test(repeat['cell'].end, '', 'padding-right: 0.4em')"><tal:content repeat="elem cell/content"><tal:field condition="python: elem == '?'"><metal:call use-macro="python: getattr(contextMacro, widget['type'].lower()).macros[layoutType]"/></tal:field><tal:other condition="python: elem != '?'"><metal:call use-macro="python: getattr(contextMacro, elem[0]).macros[elem[1]]"/></tal:other><img tal:condition="not: repeat/elem/end" tal:attributes="src string: $appUrl/ui/space.gif"/></tal:content> colspan cell/colspan;
class python: test(repeat['cell'].end, '', 'cellGap')"><tal:content repeat="elem cell/content"><tal:field condition="python: elem == '?'"><metal:call use-macro="python: getattr(contextMacro, widget['type'].lower()).macros[layoutType]"/></tal:field><tal:other condition="python: elem != '?'"><metal:call use-macro="python: getattr(contextMacro, elem[0]).macros[elem[1]]"/></tal:other><img tal:condition="not: repeat/elem/end" tal:attributes="src string: $appUrl/ui/space.gif"/></tal:content>
</td> </td>
</tr> </tr>
</table> </table>
@ -153,7 +155,7 @@
<table metal:define-macro="groupContent" <table metal:define-macro="groupContent"
tal:define="cellgap widget/cellgap" tal:define="cellgap widget/cellgap"
tal:attributes="width widget/wide; tal:attributes="width widget/wide;
align widget/align; align python: tool.flipLanguageDirection(widget['align'], dir);
class groupCss; class groupCss;
cellspacing widget/cellspacing; cellspacing widget/cellspacing;
cellpadding widget/cellpadding; cellpadding widget/cellpadding;
@ -161,7 +163,8 @@
<tal:comment replace="nothing">Display the title of the group if it is not rendered a fieldset.</tal:comment> <tal:comment replace="nothing">Display the title of the group if it is not rendered a fieldset.</tal:comment>
<tr tal:condition="python: (widget['style'] != 'fieldset') and widget['hasLabel']"> <tr tal:condition="python: (widget['style'] != 'fieldset') and widget['hasLabel']">
<td tal:attributes="colspan python: len(widget['columnsWidths']); <td tal:attributes="colspan python: len(widget['columnsWidths']);
class widget/style" align="left"> class widget/style;
align dleft">
<span tal:replace="structure python: contextObj.translate(widget['labelId'])"/> <span tal:replace="structure python: contextObj.translate(widget['labelId'])"/>
<tal:help condition="widget/hasHelp"> <tal:help condition="widget/hasHelp">
<metal:call use-macro="app/ui/widgets/show/macros/help"/> <metal:call use-macro="app/ui/widgets/show/macros/help"/>
@ -176,7 +179,7 @@
<tr> <tal:comment replace="nothing">The column headers</tal:comment> <tr> <tal:comment replace="nothing">The column headers</tal:comment>
<th tal:repeat="colNb python:range(len(widget['columnsWidths']))" <th tal:repeat="colNb python:range(len(widget['columnsWidths']))"
tal:attributes="width python:widget['columnsWidths'][colNb]; tal:attributes="width python:widget['columnsWidths'][colNb];
align python:widget['columnsAligns'][colNb]" align python: tool.flipLanguageDirection(widget['columnsAligns'][colNb], dir)"
tal:content="structure python: widget['hasHeaders'] and contextObj.translate('%s_col%d' % (widget['labelId'], colNb+1)) or ''"> tal:content="structure python: widget['hasHeaders'] and contextObj.translate('%s_col%d' % (widget['labelId'], colNb+1)) or ''">
</th> </th>
</tr> </tr>

View file

@ -160,6 +160,9 @@ nativeNames = {
'zh' : '中文', 'zh' : '中文',
'zu' : 'isiZulu' 'zu' : 'isiZulu'
} }
# List of languages having direction right-to-left (RTL) -----------------------
rtlLanguages = ('ar', 'he', 'fa')
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class Languages: class Languages:
'''This class gives access to the language codes and names as standardized '''This class gives access to the language codes and names as standardized