Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: [1]
  Reply  |  Print  
Author Topic: Localizing forms  (Read 16267 times)
Andrew C.
Posts: 48


« on: January 24, 2008, 07:55:39 am »

Has anyone considered automating the localization of forms using either XSLT (those of us in customer land) or directly in the form compiler?

I've just made a little XSLT

Code
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3.  
  4. <xsl:template match="node() | @*">
  5.  <xsl:copy>
  6.    <xsl:if test="@text">
  7.      <LStr>
  8.        <xsl:attribute name="text">
  9.          <xsl:value-of select="@text"/>
  10.        </xsl:attribute>
  11.      </LStr>
  12.    </xsl:if>
  13.  
  14.    <xsl:if test="@comment">
  15.      <LStr>
  16.        <xsl:attribute name="comment">
  17.          <xsl:value-of select="@comment"/>
  18.        </xsl:attribute>
  19.      </LStr>
  20.    </xsl:if>
  21.  
  22.    <xsl:apply-templates select="@* | node()"/>
  23.  </xsl:copy>
  24. </xsl:template>
  25. </xsl:stylesheet>

which takes a .42f and inserts the <LStr> nodes into it.

Given that this seems so effective and simple compared to the ritual suggested in the manual, I wonder why the form compiler can't just do the same thing directly, maybe under the influence of a command line option?
Sebastien F.
Four Js
Posts: 509


« Reply #1 on: January 26, 2008, 03:40:58 pm »

Andrew,

If I understand correctly, this XSLT adds LStr nodes to all form items where "text" or "comment" are used, as if a %"xxx" localized string was used... right?

I would rather add % before each string of TEXT, COMMENT, TITLE attributes in the real source file of form (The .per file)

A simple sed like this one would do the job:

  sed -e 's/[eE][xX][ ]*=[ ]*"/TEXT=%"/'

Localizating application strings is a long process that takes some efforts...

Here we speak about form files, but in the 4gl sources, you will you have to add a % before all string to be localized. This has to be done by hand...

I would also strongly suggest to replace the original strings by a real string resource identifier:

  COMMENT = %"customer_name.comment"

As other compiled files, the string resource files are compiled for a specific locale... If you have non-ASCII characters in the original text, it will not be easy to define several .str string resource files in different locales (LANG/LC_ALL): The non-ASCII characters in the string identifier (on the left side) would not display properly in a different locale as the original locale used to write the .per file.

In a future version of Genero, we will compile string resource files (and other 42m or 42f) by using a Unicode (utf-8) encoding, so that you can deploy your application in any locale without re-compiling in a specific locale.

Cheers,
Seb
Andrew C.
Posts: 48


« Reply #2 on: January 29, 2008, 12:22:41 am »

Quote
If I understand correctly, this XSLT adds LStr nodes to all form items where "text" or "comment" are used, as if a %"xxx" localized string was used... right?

Yes.

Quote
I would rather add % before each string of TEXT, COMMENT, TITLE attributes in the real source file of form (The .per file)

Not if you have over 4000 form files to process; besides, your suggestion does not deal with literal strings in the grid image sections: the XSLT neatly injects mappings for literals too. The localisation section of the FGL manual suggests:
Quote
Warning: It is not possible to specify a static localized string directly in the area of containers like GRID, TABLE or SCROLLGRID. You must use label fields to use localized strings in layout labels:

01 LAYOUT
02   GRID
03   {
04     [lab01  |f001              ]
05   {
06   END
07 END
08 ATTRIBUTES
09 LABEL lab01 : TEXT=%"myform.label01";
10 EDIT f001 = FORMONLY.field01;
11 END

I expect I would get lynched if I tried to make the programmers work with that. The entire form would become very cryptic and inpenetrable. Not only is the label's TEXT attributes a few pages down in the editor, the contents aren't even immediately obvious! Now, the contents of the TEXT could progressively be converted to something reasonably descriptive and rational over time, but how much time for 4000+ forms? I don't think it's an option.

I believe that converting all text and comment attributes would capture all and only all the descriptive strings, without damaging any CODE type attributes. Of course I will need to confirm that, and perhaps add a few exceptions or special rules for special attributes, but overall the XSLT will make trivial the rather complex and time-consuming process of localizing forms.

Quote
Here we speak about form files, but in the 4gl sources, you will you have to add a % before all string to be localized. This has to be done by hand...

This problem has not been missed. The 4GL's will contain a mixture of codes, SQL string fragments, and descriptive text. There is little an automatic tool can do. However we should be able to use scripts to progressively identify patterns, exceptions and rules which can be combined with human intervention to tumble home the conversion of 4GLs. At this stage I don't see much better than this.

Quote
I would also strongly suggest to replace the original strings by a real string resource identifier:

  COMMENT = %"customer_name.comment"

This sounds like a fairly attractive proposition for field comments. Some simple scripts could gather all comments from all forms, beg for human intervention when the same field has the different strings, attach them to the fields in a data dictionary and then re-comment all the fields with your symbolic suggestion when a dictionary entry is available. Yes, I like that.

Quote
If you have non-ASCII characters in the original text,

Fortunately not a problem for us; Australia is an English speaking country (if you believe the hype, many would disagree :-) and we're ASCII all the way.

Our first "localization" is to another English speaking country, so the conversions will be relatively trivial changes for local custom and legislation. The next possible conversion is to a real non-english language, which fortunately still uses ASCII or a simple 8-bit character set at the worst case. So the English conversion will be a nice stepping stone to get some useful infrastructure in place. I think without a very quick and convenient structured editor for looking up strings, we would be risking a rebellion if we tried to go non-english.

But regardless of whether it's a minor english-to-english conversion, or a much larger english-to-X conversion, we're not going to quickly get away from mapping strings like "please enter the cost of widgets" vs. logical "top.middle.base" strings. Therefore the option of automagic localization of forms would be very welcome, especially since it would deal with the literal strings of GRID TABLE and SCROLLGRID containers.

While we're discussing localization, what thought has been given to allowing parameterisation of the LSTR function? I consider reordering important because I hear that the proper translation of this example:

    Found 10 documents out of 15

is properly translated to

    Out of 15 documents, there are 10 found

in some language (italian? mandarin? must re-read my sources)

And of course many many more parameterised strings will no doubt have ordering issues.

The C# convention of using {0} {1} {2} etc is probably smarter than the old C style of %d %x since it allows reordering of the parameters. However the syntax used to interpolate parameters is of course open to any suggestion.
.
Posts: 14


« Reply #3 on: January 29, 2008, 02:06:08 am »

Andrew,

At Quanta we ended up with something like

Code
  1. LAYOUT
  2. GRID
  3. {
  4. [lblProductCode|f01     |d01                     ]
  5. ...
  6. }
  7. END
  8. END
  9. ATTRIBUTES
  10. LABEL lblProductCode: lblProductCode, TEXT=%"ProductCode", STYLE="prompt";
  11. EDIT f01 = formonly.productcode;
  12. LABEL d01 = formonly.productdesc, STYLE="desc";

The benefits included...
  • ability to apply STYLE attribute to the label
  • ability to apply JUSTIFY attribute to the label
  • ability to hide the label as it has a name attribute
  • by giving the label the name lblProductCode as opposed to something like lab01, the developers can 'read' the form, and we also have the added benefit that we have allowed a little space in the forms in case the translated text is longer than the original text. (if I was to do it again, I'd probably go with some name like xxProductCodexx instead of lblProductCode). 

We were fortunate that our forms already had some of this logic built in from our pre Genero localization which made the conversion easier.  The downside is note how many times I have had to type ProductCode in the example above.

I don't think your .xlst solution would cater for the case where the text is right-justified i.e.. typical column headings where you aren't using a TABLE e.g.

Code
  1.            Current      Future
  2. Price    [p01      ][p02       ]
  3. Discount [d01      ][d02       ]


With regards to your comment on LSTR, you have seen SFMT? e.g.

MESSAGE SFMT(%"FoundMessage", found, total)

FoundMessage = "Found %1 documents out of %2"
FoundMessage = "Out of %2 documents, there are %1"
Andrew C.
Posts: 48


« Reply #4 on: January 29, 2008, 02:41:42 am »

Quote
With regards to your comment on LSTR, you have seen SFMT? e.g.

MESSAGE SFMT(%"FoundMessage", found, total)

FoundMessage = "Found %1 documents out of %2"
FoundMessage = "Out of %2 documents, there are %1"
No, it has escaped my attention. Thanks for the tip.

Quote
The benefits included...
  • ability to apply STYLE attribute to the label
  • ability to apply JUSTIFY attribute to the label
  • ability to hide the label as it has a name attribute
Hmmm, since the literal strings in the grid are just Label nodes, I think the style and justify could be injected too. That sounds very interesting. Point taken though for doing it manually too; at least there would be some choice, especially in the case of right justifying labels.

For hiding I've provided a function where the string text can be searched for. First time a literal image string is found, it's text is copied to a name attribute so it can be found again under the original string. Otherwise it could be changed only once and then you'd be stuck...

Quote
and we also have the added benefit that we have allowed a little space in the forms in case the translated text is longer than the original text.
That is a very interesting point; what DOES happen if you don't leave enough space to it to fit? Does the extra get truncated? Does it push everything near it around? If it pushes, is it neat or does the alignment go to hell?

Whatever the final solution, manually performing this on 4000+ forms, let alone the countless 4GL's sounds daunting. Any method to ease the process would be highly desirable. Even if we went on un-encoded strings initially, finishing with logical codes at the end, it would be easier to automate the encoding and use of label fields after a large collection has been established and vetted.

Thanks all round for the ideas, chaps.
Sebastien F.
Four Js
Posts: 509


« Reply #5 on: January 29, 2008, 09:30:30 am »

Quote
and we also have the added benefit that we have allowed a little space in the forms in case the translated text is longer than the original text.
That is a very interesting point; what DOES happen if you don't leave enough space to it to fit? Does the extra get truncated? Does it push everything near it around? If it pushes, is it neat or does the alignment go to hell?
[/quote]

You should have a look at the SIZEPOLICY attribute:

https://4js.com/techdocs/genero/fgl/devel/DocRoot/User/FSFAttributes.html#FA_SIZEPOLICY

and also:

https://4js.com/techdocs/genero/fgl/devel/DocRoot/User/FormSpecFiles.html#FF_HBOX_TAG
https://4js.com/techdocs/genero/fgl/devel/DocRoot/User/Layout.html

About translation tools, you can also take a look at the String Manager utility available as demo in 2.10.

   FGLDIR/demo/Tools/fglstrmg

Cheers,
Seb
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines