

![]() | Start a set with this search |
![]() | Include this search in one of my sets |
![]() | Exclude this search from one of my sets |
![]() | Permalink to these results Paste this link in email or IM: |
| Atom feed for tracking future search results Paste this URL into your reader: |
28 messages in net.sourceforge.lists.courier-sqwebmailRe: [sqwebmail] Spelling and other te...| From | Sent On | Attachments |
|---|---|---|
| oth...@freeshell.org | Dec 21, 2004 1:57 pm | |
| Brian Candler | Dec 28, 2004 3:11 am | |
| Sam Varshavchik | Dec 28, 2004 4:16 am | |
| Paul L. Allen | Dec 28, 2004 11:32 am | |
| oth...@freeshell.org | Dec 28, 2004 7:45 pm | |
| oth...@freeshell.org | Dec 28, 2004 8:45 pm | |
| oth...@freeshell.org | Dec 28, 2004 9:02 pm | |
| Paul L. Allen | Dec 29, 2004 3:28 am | |
| oth...@freeshell.org | Dec 29, 2004 11:39 am | |
| Paul L. Allen | Dec 29, 2004 1:18 pm | |
| oth...@freeshell.org | Dec 29, 2004 2:34 pm | |
| Paul L. Allen | Dec 29, 2004 4:50 pm | |
| oth...@freeshell.org | Dec 29, 2004 9:08 pm | |
| Brian Candler | Dec 30, 2004 1:10 am | |
| Brian Candler | Dec 30, 2004 2:29 am | |
| Paul L. Allen | Dec 30, 2004 9:56 am | |
| Paul L. Allen | Dec 30, 2004 12:15 pm | |
| oth...@freeshell.org | Dec 30, 2004 2:39 pm | |
| oth...@freeshell.org | Dec 30, 2004 3:14 pm | |
| Paul L. Allen | Dec 30, 2004 4:07 pm | |
| Brian Candler | Dec 31, 2004 2:40 am | |
| Laurent Wacrenier | Dec 31, 2004 3:00 am | |
| Paul L. Allen | Dec 31, 2004 3:41 am | |
| Brian Candler | Dec 31, 2004 4:11 am | |
| Pawel Tecza | Dec 31, 2004 4:47 am | |
| Laurent Wacrenier | Dec 31, 2004 5:22 am | |
| Brian Candler | Jan 1, 2005 4:45 am | |
| Brian Candler | Jan 1, 2005 5:17 am |

![]() | Permalink for this message Paste this link in email or IM: |
![]() | Permalink for this thread Paste this link in email or IM: |
| Atom feed for this thread Paste this URL into your reader: |
| Subject: | Re: [sqwebmail] Spelling and other templates (Was: stale processes and m17n) | Actions... |
|---|---|---|
| From: | Brian Candler (B.Ca...@pobox.com) | |
| Date: | Dec 30, 2004 2:29:00 am | |
| List: | net.sourceforge.lists.courier-sqwebmail | |
On Wed, Dec 29, 2004 at 09:18:47PM +0000, Paul L. Allen wrote:
That uses gettext. I've seen the difficulties gettext causes on another list, and that is in code where it is actually appropriate to use it. Those who are willing to translate to another language have difficulties figuring out how to drive the tools needed to create and merge in the translations.
ISTM that gettext is unnecessary overhead, because sqwebmail already has three-quarters of such a subsitution mechanism built in. It's just that the substitution strings are currently kept in the templates, so it's not possible to override text without changing the templates themselves.
If I understand it correctly, to use it in sqwebmail would STILL require template substitution. Instead of having <td>Login</td> the template would have <td>[#S509#]</td>, the code would spot the [#S509#] and translate that using an internal table that maps S590 to Login and then it would call gettext to translate Login.
I'm sure you could map S590 to "Login" directly in gettext. The difference would be that should the particular language translation be missing that string, the user would actually see "S590" on the web page, instead of the English string.
Another way would be to abandon templates and have all the html generated on the fly by the code. That would eliminate the template substitution step. But then you lose the ability to easily change the look and feel of the page - you have to hack code instead of html and most people who are good coders are not good at page design/layout (and vice versa).
I believe we should move towards the other extreme - all HTML in the templates and none in the code.
What I'm thinking of is a recursive substitution mechanism. As a starting point:
[#HTML_LOGINPAGE= <html> <title>[#LOGINTITLE#]</title> <span class="errormsg">[!ERROR!]</span> <table> <tr><td>[#USERNAME#]</td><td><input name="username"</td></tr> <tr><td>[#PASSWORD#]</td><td><input name="password"</td></tr> </table></html> #]
[#LOGINTITLE=Sqwebmail Login - [#COPYRIGHT#]#] [#COPYRIGHT=Copyright 1999-2004 Double Precision, Inc.#] [#USERNAME=E-mail address:#] [#ERROR_INVALID=Login failed, incorrect username or password#] [#ERROR_EXPIRED=Login expired, please login again#]
Now, the rendering of the login page would simply call [#HTML_LOGINPAGE#], and as it was expanded, other strings would be dynamically sub-expanded.
Note that [!ERROR!] is a special case. It triggers some C code which expands either to an empty string or to [#ERROR_INVALID#] or [#ERROR_EXPIRED#], depending on the context.
Translations would simply override some of the strings (those containing text). Alternate templates would override other ones (those containing HTML or HTML fragments). Perhaps logically the 'html fragments' (indexed by template name) and 'language strings' (indexed by language name) should be separated for clarity, but I don't think it's actually necessary.
HTML designers could use the snippets as macros, for example using them for things like the rounded corners [#CORNERTL#] could eliminate a lot of duplication within the templates, and also make it easier to tweak them (e.g. a local override to replace four strings with blank text if you want to get rid of all the corners)
Since sqwebmail is a daemon now, it can read in all the strings into RAM at startup time and apply local overrides etc. The sources can be plain text files; no need to convert them into any indexed representation (e.g. dbm).
I believe there's another disadvantage to the gettext method. Sometimes our users are so dim it is desirable to change the actual text to give them a clue what they're supposed to do or what something is for. With the qmailadmin method I change some words in a plain text file (or more than one if we use translations). I know how to drive a text editor, how to search for a particular word or phrase and how to replace it.
I think there should be local overrides for strings, stored separately from the sqwebmail templates so they are not lost when you upgrade version.
Now, I think the simple mechanism I've outlined would do pretty well, but it could be made more sophisticated.
One option is to make it use XML syntax. Instead of [#FOO#] you can have <span id='FOO'/> which expands to the text alone. If there are additional attributes, or the tag is not 'span', then you keep the tag as well. For example:
<span id='FOO' class='error'> expands to <span class='error'>the text</span>
or <div id='FOO'/> expands to <div>the text</div>
Now, the other thing to recognise is there will be a lot of special cases in code where fragments conditionally embed other fragments which embed other fragments. Let's take something like the folder list:
[!FOLDERLIST!] <!-- currently [#F#] I believe -->
Now, in the new scheme this would trigger some C code which in turn triggers more HTML fragments: it may trigger [#NODELPERM#] or [#NOINSERTPERM#]
otherwise it goes onto to some more steps. First it generates [#FOLDER_TABLESTART#] which contains <table width="100%" border="0" cellspacing="0" cellpadding="4"> <tr class="folder-index-header"> <th align="center">[#NUM#]</th><th> </th><th>[#DATE#]</th> <th>[#FROM#]</th><th>[#SUBJECT#]</th><th>[#SIZE#]</th> </tr>
then it goes into a loop generating repeatedly
[#FOLDER_TABLEROW#]
which contains
<tr class="folder-index-bg-[!ODDEVEN!]">
<td align="right"
class="message-number">[!ENTRY_START!][!POS!][!ENTRY_END!]</td>
<td class="message-status"><input type="checkbox" name="MOVE-[!POS!]"
id="MOVE-[!POS!]" [!DISABLED!]/>
... etc
</tr>
and there are there are various special case tags which make sense in this context: [!ODDEVEN!] inserts 1 or 2 for alternate messages [!ENTRY_START!] inserts either [#ENTRY_START_READ#] or [#ENTRY_START_UNREAD#] depending on whether the message is read or not [#ENTRY_START_READ=<span class="read-message">#] [#ENTRY_START_UNREAD=<strong class="unread-message">#] [!POS!] inserts the current message number, and so forth.
I think that would work just fine and has the huge advantage of removing all the HTML code fragments from the C source. However it involves a lot of cross-referencing to see which bits of HTML are inserted where, and you still need to look at the C source to find out the logic for the magic bits, such the names of the HTML fragments which [!ENTRY_START!] might generate, or the fact that [#FOLDER_TABLEROW#] is generated multiple times within a loop.
An alternative would be if the HTML fragments were nested, rather than cross-referenced. What I am thinking of is this. Instead of [!FOLDERLIST!] you put the following HTML in the template:
<table id="folderlist" width="100%" ... >
<span id="nodelperm"/>
<span id="noinsertperm"/>
<table id="foldertable" width="100%" ... >
<tr><th>...headings...</th></tr>
<span id="folderrows">
<tr id="folderrow-odd" class="folder-index-bg-1">
<td align="right" class="message-number">
<span id="msg-read" class="read-message"><span id="pos"/></span>
<strong id="msg-unread" class="unread-message"><span
id="pos"/></span>
</td>
...
</tr>
<tr id="folderrow-even" class="folder-index-bg-2">
<td align="right" class="message-number">
<span id="index-read" class="read-message"><span id="pos"/></span>
<strong id="index-unread" class="unread-message"><span
id="pos"/></span>
</td>
...
</tr>
</span>
</table>
</table>
Now, the magic goes with the "id=..." binding.
Firstly, it performs conditional insertion: if in the current context the id string is not bound, the tag (and any content) is excluded. So if there are no values for 'nodelperm' or 'noinsertperm' defined at the current point, those tags do not appear in the output.
Secondly, it performs looping. The id 'folderrows' starts the folder loop and binds alternately folderrow-odd and folderrow-even, also the parameters of the current row like 'pos' and either 'msg-read' or 'msg-unread', and then inserts the enclosed HTML as many times as there are rows. (These ideas all stolen shamelessly from Ruby's Amrita module, BTW)
I don't think this necessarily gives you any more power than the previous tag-substitution example, but it means all the HTML is in one place and has the same nested structure that the output will have. Perhaps the explicit nested tag-substitution is simpler to code and understand for sqwebmail developers though.
What I'd really like to get to is a situation where a template designer can offer a substantially different user interface, such as an Outlook-style combined folder list / folder index / message view, without touching the code. And that probably needs rather more thought.
Cheers,
Brian.







