discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnustep] Localization


From: Pascal J. Bourguignon
Subject: Re: [Discuss-gnustep] Localization
Date: Fri, 22 Sep 2000 06:38:28 +0200 (CEST)

> Date: Fri, 22 Sep 2000 02:49:55 +0200 (CEST)
> From: Nicola Pero <n.pero@mi.flashnet.it>
> Sender: nico@leonardo
> Reply-To: Nicola Pero <n.pero@mi.flashnet.it>
> cc: discuss-gnustep@gnu.org
> Content-Type: TEXT/PLAIN; charset=US-ASCII
> X-UIDL: 5451b1805b7aacf9d5c0efd099af4149
> 
> 
> 
> > > > I had the idea a while back of creating a command-line tool that would
> > > > scan your sources for occurances of this macro, and then create a 
> > > > template
> > > > Localizable.strings file to hand off to your translators.  Of course,
> > > > Apple beat me too it, as I noticed in their release notes that they have
> > > > added just such a tool to MacOS X.
> > > 
> > > Ahm - yes - forgot that - this is the other thing which gettext has 
> > > (and I guess MacOS X has taken the idea from gettext) and which OPENSTEP 
> > > lacks.
> > 
> > Wrong. genstrings  existed at least  since NeXTSTEP 3.3. 
> > 
> > I doubt that it would be missing in OPENSTEP.
> 
> Great - it is missing in GNUstep then :)

Have a look at my script "get-local-strings" at:

     ftp://hermes.afaa.asso.fr/users/pascal/develop/gnustep/gls.tar.gz

It's not perfect, but it could  be a starting point for a full fleshed
genstring.
 
> Pretty simply, most of you have convinced me that what we already have if
> well documented and completed [by writing something like genstrings etc], 
> and with a little short-cut inline function, could be quite good  :)
> 
> One thing I still miss in the picture.  
> 
> Look at the following example, in which I declare 
> 
> static NSString *result[2] = { @"yes", @"no" }; 
> 
> and then use it at runtime as: 
> 
> if (i > 5)
>   {
>     [button setStringValue: NSLocalizedString (result[0], @"")];
>   }
> else /* i <= 5 */ 
>   {
>     [button setStringValue: NSLocalizedString (result[1], @"")];
>   }
> 
> [This example is stupid, but more complicated examples, very meaningful,
> can be built.  It's quite common to put messages into static arrays /
> structures while writing apps, so you have all the strings and options in
> a single place separated from the code and it is easy to add/remove/change
> strings, options, messages, blocks, bundles etc.  Sometimes these kind
> of tables could be better saved in property list files, but not always.].
> 
> How would a genstrings-like tool know that the strings in the result array
> need to be localized ? 

If I remember  well, genstrings would not work very  well with such an
example. (get-local-strings won't work well at all).

The localization MACROS (are not functions) do not work this way:
     NSLocalizedString (result[0], @"")

They  have   a  double  semantic,  being  processed   twice,  once  by
genstrings, and once by the cpp. By genstrings, they are mere tags for
their arguments,  to let genstrings extract  them and put  them in the
strings file.   By cpp, they send a  message to some bundle  to do the
localization of the key string.  (Which is done using the strings file
generated by genstrings).


Therefore,  you must  localize  when initializing  such run-time  data
structures, not when using them.

    static NSString* result[2];

  void init_result(void)
  {
   result[0]=NSLocalizedString(@"Yes",@"Positive answer to a generic question");
   result[1]=NSLocalizedString(@"No",@"Negative answer to a generic question");
  }/*init_result*/


    int label_index;
    init_result();
    if (i > 5){
       label_index=0;
    }else{ /* i <= 5 */
       label_index=1;        
    }
    [button setStringValue:result[label_index]];

> [In gettext there is a special macro for this, expanding to nothing but
> being recognized as a marker for translatable strings by the tool.]

Well, that's SEEMS a good idea anyway.  Something like:

#define GSWillBeALocalizedString(s,c) s
#define GSWillBeALocalizedStringFromTable(s,t,c) s
#define GSWillBeALocalizedStringFromTableInBundle(s,t,b,c) s

Oops!!! How will you remember the table and the bundle the string must
be localized later from? 


> And - if one wants a comment with each string from the array, can this be
> accomplished ?  The only solution I see is a macro variant of
> NSLocalizedString which expands to nothing discarding the comment; it
> would have as variant the one without the comment.  But since I don't see
> anything of this kind in the gnustep base library I wonder how this would
> be managed in OPENSTEP.


Anyway, I think that genstrings works on the given source file without
pre-processing  it, because I  used to  apply cpp  to my  files before
passing them to  genstrings. 

The   comment  IS  used   by  genstrings,   never  generated   by  the
NSLocalizedString* macros.


> And still, we really need to introduce just some very short form of
> NSLocalizedString, without the comment.  Something like
> 
> static inline NSString *NS_(NSString *s)
> {
>   return NSLocalizedString (s, @"");
> }
> 
> I can use this definition in my code of course, but everyone will have
> this problem (since every single line of code has to be localized), so why
> don't we choose a system-wide convention ?
> 
> We can't spend time typing 
> 
> NSLocalizedString (@"Save", @"No comment")
> 
> (35 characters overhead to localize a string)  when what we want to do
> is simply to enter the string "Save", while any gnome boy is typing
> 
> _("Save")
> 
> (3 characters overhead).  It's important considering that *any* string
> meant to talk to the user *must* be localized.
> 
> Perhaps NS_(@"Save") is not that bad.

Do you mean "Save" as in Save Our Souls       -> Sauvez nos âmes ?
                or as in Save this file       -> Enregistrer ce fichier ?
                or as in These save this one  -> Ceux-ci sauf celui-ci ?
                or as in Save they're dead,   -> A moins qu'ils soient morts ?
                or as in Save your money      -> Éconnomisez votre argent ?
                or as in to save him falling  -> pour l'empêcher de tomber ?
                or as in to save appearances  -> pour préserver les apparences ?
                or as in a goalie made a save -> le gardien arrêta la balle ?
(I'm a little weak on football (soccer), you may find a better translation here)
                or as in I save it for later  -> Je le garde pour plus tard ?
                or as in he'll save his job   -> il conservera son travail ?
                or as in SAVE                 -> SAVE ?
 
(From The Free On-line Dictionary of Computing (15Feb98) [foldoc]:
       SAVE
          An {assembler} for the {Burroughs 220} by Melvin Conway (see
          {Conway's Law}).  The name "SAVE" didn't stand for anything,
          it was just that you lost fewer card decks and listings
          because they all had SAVE written on them.
)

And it's  not because  we're starting from  an English word,  the same
would be true  (granted, to a smaller extend),  from any other natural
language.


Even such a simple word as  "Yes" can be translated to either "Oui" or
"Si" in French, depending on the context.

        Mustn't we stop?           Ne faut-il pas arrêter ?   
        [ Yes ]   [ No ]           [ Si ]           [ Non ]      
(                                 
  Granted, that kind of question  is to be avoided, but that's because
  there's no "Si" in English. They don't pose any problem in French.

        Mustn't we stop?           Ne faut-il pas arrêter ?   
        [ Yes ]   [ No ]           [ Si ]           [ Non ]    
        (We don't know!)           (We stop)        (We don't stop)
)

Since localization is  needed mainly for natural language,  we need to
add a  comments to all localizable  string to let the  translator do a
good job.  Well, you, as a programmer  may not feel the  need, but the
translator would miss them terribly.

Something like NS_(@"Save","Order to save a file.") is mandatory. Pity
for the poor translators, and foreign users!




For example, for  a small-to-medium sized module of  an application, I
used 62 localized  strings, for which I wrote  comments of length from
36 characters to 259 characters. There was :

   35 comments of less than 100 characters,
   21 comments between 100 and 150 characters, and
    6 comments over 150 characters.

(The longest comments  are those of format strings:  they explain what
is expected  to be put in the  place of each of  the format directives
(%d, %s, %@, ...)).


Therefore,  copy-and-pasting "NSLocalizedStringFromTable" is  not much
work, if you have to type two  to four lines more for these strings (I
did not felt  the need to define a smaller macro  then). I had defines
like:

#define sE_PoliceNonDisponible NSLocalizedStringFromTable(@"Mention",\
        @"sE_PoliceNonDisponible",\
        @"La police Postscript '%s' n'est pas disponible. L'affichage "\
        @"du texte de la mention se fera dans la police par défaut.",\
        @"Message indiquant l'absence d'une police Postscript impliquant "\
        @"l'affichage du texte de la mention dans la police par défaut. "\
        @"Le champ %s sera remplacé par le nom de la police Postcript "\
        @"manquante.") 

and later:         [text setStringValue:sE_PoliceNonDisponible];


-- 
__Pascal Bourguignon__    PGP Key ID:      0xEF5E9966
mailto:pjb@imaginet.fr    PGP fingerprint: 00 F5 7B DB CA 51 8A AD 04 5B 
http://www.imaginet.fr/~pjb/               6C DE 32 60 16 8E EF 5E 99 66

() Join the ASCII ribbon campaign against html email and Microsoft attachments.
/\ Software patents are endangering the computer industry all around the world.
   Join the LPF:     http://lpf.ai.mit.edu/      http://petition.eurolinux.org/


reply via email to

[Prev in Thread] Current Thread [Next in Thread]