comp.lang.ada
 help / color / mirror / Atom feed
* Programming for the World in Ada95
@ 2000-02-14  0:00 John J Cupak Jr
  2000-02-14  0:00 ` Ehud Lamm
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: John J Cupak Jr @ 2000-02-14  0:00 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 356 bytes --]

Ah, Ada Gurus"

Does anyone have any experiences, thoughts, or comments on how to write
Ada 95 so that user messages, etc., are EASILY modified for different
spoken/read languages, as noted in O'Donnel's excellent book,
"Programming for the World"?

Is there an easy way to specify message strings at load time, or must
this be done at compile time?

John

[-- Attachment #2: Card for John J Cupak Jr --]
[-- Type: text/x-vcard, Size: 364 bytes --]

begin:vcard 
n:Cupak Jr;John J
tel;fax:978.858.4336
tel;work:978.858.1222
x-mozilla-html:TRUE
org:Raytheon Company;Northeast Software Training
version:2.1
email;internet:John_J_Cupak@res.raytheon.com
title:Software Engineering Instructor
adr;quoted-printable:;;50 Apple Hill Road=0D=0AT3MN35;Tewksbury;MA;01876;USA
x-mozilla-cpt:;9904
fn:John J Cupak Jr
end:vcard

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-14  0:00 Programming for the World in Ada95 John J Cupak Jr
  2000-02-14  0:00 ` Ehud Lamm
@ 2000-02-14  0:00 ` Larry Kilgallen
  2000-02-16  0:00   ` Robert A Duff
  2000-02-14  0:00 ` Gautier
  2000-02-15  0:00 ` Jean-Pierre Rosen
  3 siblings, 1 reply; 13+ messages in thread
From: Larry Kilgallen @ 2000-02-14  0:00 UTC (permalink / raw)


In article <38A83838.44A43A7D@res.raytheon.com>, John J Cupak Jr <John_J_Cupak@res.raytheon.com> writes:

> This is a multi-part message in MIME format.

Please don't send MIME to comp.lang.ada.

> Does anyone have any experiences, thoughts, or comments on how to write
> Ada 95 so that user messages, etc., are EASILY modified for different
> spoken/read languages, as noted in O'Donnel's excellent book,
> "Programming for the World"?

If you expect people to read that book before responding, you may have
a long wait.

> Is there an easy way to specify message strings at load time, or must
> this be done at compile time?

In general, standards for such things are controlled by the operating
system vendors.  Although you may have a recent book on the subject,
VMS has had a way of doing it since the beginning 22 years ago.
Macintosh from the beginning 16 years ago.  I know less about the
Microsoft way of doing it, or what version of Windows/DOS may have
introduced it.  In Unix, it tends to be tied into the notion of
"locale" in the C programming language.

If you want useful software, you will build it so the system manager
can configure the language settings in a fashion typical for the OS
in use.  That means you will not be able to avoid platform-specific
issues.

Larry Kilgallen




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-14  0:00 Programming for the World in Ada95 John J Cupak Jr
  2000-02-14  0:00 ` Ehud Lamm
  2000-02-14  0:00 ` Larry Kilgallen
@ 2000-02-14  0:00 ` Gautier
  2000-02-15  0:00 ` Jean-Pierre Rosen
  3 siblings, 0 replies; 13+ messages in thread
From: Gautier @ 2000-02-14  0:00 UTC (permalink / raw)


> Is there an easy way to specify message strings at load time, or must
> this be done at compile time?

You can do both with an enumerated type : type language is ( english,... )
For load time, you can have several files with a message per line,
whose names are "msg_file: array( language ) of string( 1..8 ):= ( "engl.msg",...
or use "language'image" for that.
Each message would be indexed by another, (orthogonal:-) enumerated type:
"type message is ( alert_such, warning_bla,... );".
Loading via
"Open(f, msg_file( chosen_language )); for m in message loop Get_Line(f,..."
For compile you could use constant arrays or use case statements for displaying.
Just ideas. A primitive implementation in AD's source
direct: http://members.xoom.com/gdemont/logiciel/ad.zip
page: http://members.xoom.com/gdemont/ad.htm 
HTH
-- 
Gautier




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-14  0:00 Programming for the World in Ada95 John J Cupak Jr
@ 2000-02-14  0:00 ` Ehud Lamm
  2000-02-14  0:00 ` Larry Kilgallen
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Ehud Lamm @ 2000-02-14  0:00 UTC (permalink / raw)


It would seem strange to me to see this as a language problem... :-) Human
langugae yes, but programming language?

You can create constant message strings that can be replaced during
compile time, load messages from a file, so you can control it without
recomiplation and so on.

Naturally you would want to abstract these details awy using packages etc.
- so that the code using the messages will not be dependent on the
language.

It is of course important to realize that the messages themselves are one
of the easy parts. Input (in langyages that are right to left for example,
like Hebrew) is an issue, character set (unicode, anyone?), collating
sequence and so on.


Ehud Lamm mslamm@mscc.huji.ac.il
http://purl.oclc.org/NET/ehudlamm <== My home on the web 
Check it out and subscribe to the E-List- for interesting essays and more!






^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-15  0:00   ` Marin D. Condic
@ 2000-02-15  0:00     ` Ray Blaak
  2000-02-16  0:00       ` Nick Roberts
                         ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Ray Blaak @ 2000-02-15  0:00 UTC (permalink / raw)


"Marin D. Condic" <mcondic-nospam@quadruscorp.com> writes:
> While this will work, it does happen at compile time. A better method would
> be to do it at run time so that an "International" software product would
> differ only by a simple text file. [...] I'd build an error message package
> that loaded the text at startup [...]:
> 
> package Error_Messages is
> 
>     type Error_Type is (
>         Some_Error,
>         Another_Error,
>         Etc_Errors) ;
> 
>     procedure Display_Message (
>         Err    : in     Error_Type) ;
> 
>     -- The rest is an exercise for the student.
> 
> end Error_Messages ;

A much better idea. It still needs to allow parameterized messages, however, so
that you can say thing like: "there are 5 bad things here" or "yadda ko 5 cacca
dinca etho"

A common mistake in many systems is to follow C's printf conventions, so that
the string in the data file looks like: "there are %d bad things here".  The
problem comes when you have multiple parameters:

"there are %d bad things here, %d of which matter"

A sensible translation might need to reorder the parameters, i.e. maybe the
translated sentence needs to be in this order:

"%d critical things are in the %d bad things here"

But now the software won't match, since it is using positional notation.

The fix is, of course, named placement holders:

"there are ${total_count} bad things here, ${critical_count} of which matter"

Now a reordering will still work:

"${critical_count} critical things are in the ${total_count} bad things here"

The upshot is that the messages package now needs to allow the specification of
values for the placeholders, using name/value pairs:

  type Replacement is private:
  type Replacements is array (<>) of Replacement;
  
  function Subst(Name, Value : in String) return Replacement;

  function Translate
      (message : in Translatable_Message; parameters : in Replacements)
        return String;
  -- I prefer Translate or Lookup instead of Display_Message, since you might
  -- need the translated string for many purposes, e.g. logging, error
  -- messages, on a button, in a menu, etc.  I also suggest
  -- Translatable_Message or something similar, since the text is not
  -- necessarily for errors.

  ...

  Display(Translate (Message => Some_Error,
                     Parameters => 
                       (Subst("total_count", Integer'Image(total)),
                        Subst("critical_count", Integer'Image(critical)))));
          


-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
blaak@infomatch.com                            The Rhythm has my soul.




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-14  0:00 Programming for the World in Ada95 John J Cupak Jr
                   ` (2 preceding siblings ...)
  2000-02-14  0:00 ` Gautier
@ 2000-02-15  0:00 ` Jean-Pierre Rosen
  2000-02-15  0:00   ` Marin D. Condic
  3 siblings, 1 reply; 13+ messages in thread
From: Jean-Pierre Rosen @ 2000-02-15  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1640 bytes --]


John J Cupak Jr <John_J_Cupak@res.raytheon.com> a �crit dans le message :
38A83838.44A43A7D@res.raytheon.com...
> Ah, Ada Gurus"
>
> Does anyone have any experiences, thoughts, or comments on how to write
> Ada 95 so that user messages, etc., are EASILY modified for different
> spoken/read languages, as noted in O'Donnel's excellent book,
> "Programming for the World"?
>
> Is there an easy way to specify message strings at load time, or must
> this be done at compile time?
>
Of course, the solution depends on your requirements.
If you just want *messages* in several languages, and accept to have
selection of the language at compile time, here is a useful trick:

declare all your messages as constants in packages, one package per
language, i.e.
package Messages_English is
  -- english constants here
end Messages_English;

package Messages_French is
  -- french constants here
end Messages_French;

Every module then declares:
with Messages;

And you simply declare a library level renaming:
with Messages_English;
package Messages renames Messages_English;

By simply changing "_English" to "_French" in the above two lines, all your
application will switch to French.

For an example of using this technique, see package Debug, available from
Adalog's components page (http://pro.wanadoo.fr/adalog/compo2.htm). Note
that this technique can be extended (to a certain extent) to manage inputs:
You declare the character that means "yes" ('y' or 'o'), etc.

--
---------------------------------------------------------
           J-P. Rosen (Rosen.Adalog@wanadoo.fr)
Visit Adalog's web site at http://pro.wanadoo.fr/adalog






^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-15  0:00 ` Jean-Pierre Rosen
@ 2000-02-15  0:00   ` Marin D. Condic
  2000-02-15  0:00     ` Ray Blaak
  0 siblings, 1 reply; 13+ messages in thread
From: Marin D. Condic @ 2000-02-15  0:00 UTC (permalink / raw)


Jean-Pierre Rosen wrote:
> declare all your messages as constants in packages, one package per
> language, i.e.
<snip>

While this will work, it does happen at compile time. A better method
would be to do it at run time so that an "International" software
product would differ only by a simple text file.

Short of an OS specific solution, I'd build an error message package
that loaded the text at startup from a language specific file and then
index all the error messages by an enumerated type. Something like:

package Error_Messages is

    type Error_Type is (
        Some_Error,
        Another_Error,
        Etc_Errors) ;

    procedure Display_Message (
        Err    : in     Error_Type) ;

    -- The rest is an exercise for the student.

end Error_Messages ;

Clearly, the source code will be language specific, but whatever text
you want to associate with "Some_Error" or "Another_Error" could be very
dynamic. How elaborate you want to get with selecting the specific error
message file would depend on your tastes and how much work you want to
do.

Of course, this is an overall strategy which is not really Ada specific.
A good software design for doing this would be an advantage to any
application in any language.

MDC
-- 
=============================================================
Marin David Condic   - Quadrus Corporation -   1.800.555.3393
1015-116 Atlantic Boulevard, Atlantic Beach, FL 32233
http://www.quadruscorp.com/
m c o n d i c @ q u a d r u s c o r p . c o m

Visit my web site at:  http://www.mcondic.com/

"Capitalism without failure is like religion without sin." 
        --  Allan Meltzer, Economist 
=============================================================




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-15  0:00     ` Ray Blaak
  2000-02-16  0:00       ` Nick Roberts
  2000-02-16  0:00       ` Pascal Obry
@ 2000-02-16  0:00       ` Larry Kilgallen
  2000-02-16  0:00       ` Pascal Obry
  3 siblings, 0 replies; 13+ messages in thread
From: Larry Kilgallen @ 2000-02-16  0:00 UTC (permalink / raw)


In article <m3n1p13cmy.fsf@ns59.infomatch.bc.ca>, Ray Blaak <blaak@infomatch.com> writes:

> A common mistake in many systems is to follow C's printf conventions, so that
> the string in the data file looks like: "there are %d bad things here".  The
> problem comes when you have multiple parameters:
> 
> "there are %d bad things here, %d of which matter"
> 
> A sensible translation might need to reorder the parameters, i.e. maybe the
> translated sentence needs to be in this order:
> 
> "%d critical things are in the %d bad things here"
> 
> But now the software won't match, since it is using positional notation.
> 
> The fix is, of course, named placement holders:
> 
> "there are ${total_count} bad things here, ${critical_count} of which matter"

That is one solution, but not "of course" the only solution.
VMS provides (and has for 20 years) provided control sequences within
the string for the translator to adjust the order in which the passed
parameters are consumed.  !+ and !- come to mind, although I could be
remembering them wrong (knowing only one natural language, I find that
nobody calls on me for translation services :-).

Certainly other operating systems have taken other approaches, and
I would be quite surprised if OS400, for instance, did not have some
other way to accomplish the same goal.

If you are planning on selling into a production environment, it is
the system manager who must deal with choosing which users get which
languages, and doing it in the standard OS way is important to gain
acceptance.  It is not good if Ada programs get a reputation for being
hard (i.e., different) to install and configure.  Even in the PC world
large corporations have central system managers who don't care at all
about the algorithms in your FlumBot 2000 program, only whether it installs
and configures in the standard Microsoft fashion.

Larry Kilgallen




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-14  0:00 ` Larry Kilgallen
@ 2000-02-16  0:00   ` Robert A Duff
  0 siblings, 0 replies; 13+ messages in thread
From: Robert A Duff @ 2000-02-16  0:00 UTC (permalink / raw)


kilgallen@eisner.decus.org (Larry Kilgallen) writes:

> If you expect people to read that book before responding, you may have
> a long wait.

Not *so* long, since I read it months ago.  ;-)

The advice in the book is pretty much language independent.
I don't think there's anything specific about Ada that
affects the issues (other than just general good support
for abstraction).

> If you want useful software, you will build it so the system manager
> can configure the language settings in a fashion typical for the OS
> in use.  That means you will not be able to avoid platform-specific
> issues.

Sad, but true.

- Bob




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-15  0:00     ` Ray Blaak
@ 2000-02-16  0:00       ` Nick Roberts
  2000-02-16  0:00       ` Pascal Obry
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Nick Roberts @ 2000-02-16  0:00 UTC (permalink / raw)


I was going to write an extensive reply to this one, but (I hear you sigh
with relief ;-)  I've cut it down to the following brief recommendations.

1. Introduce one package which declares an abstract root tagged type to
represent a piece of text, and a function to turn the object into actual
(Unicode) text. E.g.:

    package International.Text is

        type Root_Text_Piece is abstract tagged private;

        function Image (Piece: in Root_Text_Piece) return Wide_String is
abstract;

    end;

2. Derive types (in child or other packages, as appropriate) which
correspond to actual text messages. You must implement the 'Image' function
for each. Use an enumerated type as the basic message selector, and have a
derived type (its extension part) contain a component of this enumerated
type. The type can be further parametised in the same way, as necessary.

You can often avoid having to parameterise things too much by recasting your
output in a form which moves the parametised bits (e.g. numbers) out from
being embedded in the text. For example, instead of saying "there were 16
errors, of which 9 matter", you could say "Total number of errors:      16"
on one line, and "Number of critical errors:       9" on the next line,
perhaps. This style often tends to be neater, easier to read, easier to
program, easier to maintain and change, and generally avoids the necessity
for messing around with singular and plural forms.

3. Introduce a package (maybe generic) which implements message retrieval
from a configuration file or (much better) a database table. If your project
is divided into separate modules, being developed independently to some
extent (or simply if the program is very large), make sure you have
facilities for each module's person/team to add and delete messages to/from
the file/table independently of one another. Add a package that allows you
to list the enumeration literals that are message selectors against their
corresponding file/table messages (and keys). Maybe add 'fallback' code that
uses an internal message table in the event the configuration file/table
cannot be opened.

--
Nick Roberts
http://www.adapower.com/lab/adaos








^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-16  0:00       ` Pascal Obry
@ 2000-02-16  0:00         ` Ray Blaak
  0 siblings, 0 replies; 13+ messages in thread
From: Ray Blaak @ 2000-02-16  0:00 UTC (permalink / raw)


"Pascal Obry" <p.obry@wanadoo.fr> writes:
> And what about:
> 
> function Critical_Error (Total_Count, Critical_Count : in Positive) return
> String is
> begin
>    return "there are" & Positive'Image (Total_Count) & " bad things here,"
>       & Positive'Image (Critical_Count) & " of which matter";
> end Critical_Error;

Well sure, but the point was to be able to have translated strings come from a
data file rather than being hard coded into the program.

That way, one can do translations after the fact, and farm out translation
tasks to consultants who know the languages, but are not necessarily
programmers.

Most importantly, that way you can have the same software that runs anywhere
and have it dynamically decide which translation data to use, based on the
locale information as provided by the operating system.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
blaak@infomatch.com                            The Rhythm has my soul.




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-15  0:00     ` Ray Blaak
  2000-02-16  0:00       ` Nick Roberts
@ 2000-02-16  0:00       ` Pascal Obry
  2000-02-16  0:00         ` Ray Blaak
  2000-02-16  0:00       ` Larry Kilgallen
  2000-02-16  0:00       ` Pascal Obry
  3 siblings, 1 reply; 13+ messages in thread
From: Pascal Obry @ 2000-02-16  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1504 bytes --]

Ray Blaak a �crit dans le message ...
>The fix is, of course, named placement holders:
>
>"there are ${total_count} bad things here, ${critical_count} of which
matter"
>


And what about:

function Critical_Error (Total_Count, Critical_Count : in Positive) return
String is
begin
   return "there are" & Positive'Image (Total_Count) & " bad things here,"
      & Positive'Image (Critical_Count) & " of which matter";
end Critical_Error;

Now there is no problem with reordering :)

For a multi-lingual error system a OO design will do as in:

type Error_Message is abstract tagged private;

function Critical_Error (E : Error_Message;
      Total_Count, Critical_Count : in Positive) return string is abstract;

type English_EM is new Error_Message with private;

function Critical_Error (E : English_EM;
      Total_Count, Critical_Count : in Positive) return string is abstract;

type French_EM is new Error_Message with private;

function Critical_Error (E : French_EM;
      Total_Count, Critical_Count : in Positive) return string is abstract;

Pascal.

PS : this code has not been check by any compiler except myself so it could
just not compile :)

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|         http://perso.wanadoo.fr/pascal.obry
--|
--| "The best way to travel is by means of imagination"







^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Programming for the World in Ada95
  2000-02-15  0:00     ` Ray Blaak
                         ` (2 preceding siblings ...)
  2000-02-16  0:00       ` Larry Kilgallen
@ 2000-02-16  0:00       ` Pascal Obry
  3 siblings, 0 replies; 13+ messages in thread
From: Pascal Obry @ 2000-02-16  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1439 bytes --]


Ray Blaak a �crit dans le message ...
>"${critical_count} critical things are in the ${total_count} bad things
here"
>
>The upshot is that the messages package now needs to allow the
specification of
>values for the placeholders, using name/value pairs:
>
>  type Replacement is private:
>  type Replacements is array (<>) of Replacement;
>
>  function Subst(Name, Value : in String) return Replacement;
>
>  function Translate
>      (message : in Translatable_Message; parameters : in Replacements)
>        return String;
>  -- I prefer Translate or Lookup instead of Display_Message, since you
might
>  -- need the translated string for many purposes, e.g. logging, error
>  -- messages, on a button, in a menu, etc.  I also suggest
>  -- Translatable_Message or something similar, since the text is not
>  -- necessarily for errors.


A function very close to this one could be found in my Template_Parser
package. Nice plug isn't it :)

I use it all the time to parse Web page template containing tags to be
replaced
by some values before sending it back to the Web server.

Pascal.

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|         http://perso.wanadoo.fr/pascal.obry
--|
--| "The best way to travel is by means of imagination"







^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2000-02-16  0:00 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-02-14  0:00 Programming for the World in Ada95 John J Cupak Jr
2000-02-14  0:00 ` Ehud Lamm
2000-02-14  0:00 ` Larry Kilgallen
2000-02-16  0:00   ` Robert A Duff
2000-02-14  0:00 ` Gautier
2000-02-15  0:00 ` Jean-Pierre Rosen
2000-02-15  0:00   ` Marin D. Condic
2000-02-15  0:00     ` Ray Blaak
2000-02-16  0:00       ` Nick Roberts
2000-02-16  0:00       ` Pascal Obry
2000-02-16  0:00         ` Ray Blaak
2000-02-16  0:00       ` Larry Kilgallen
2000-02-16  0:00       ` Pascal Obry

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox