Hi Frank! > Le 18 avr. 2020 à 17:08, Frank Heckenbach <[email protected]> a écrit : > > Akim Demaille wrote: > >> So **please** take the time to play with this beta, > > So far it works well with my parsers.
Great news! While I have taken care of not breaking backward compatibility (and in fact the test suite is still using the old names), s*t happens, so it is reassuring to know that it works well for you. >> in particular to >> see how these features allow you to get rid of dirty hacks you needed >> to customize your error messages (I listed several such examples in >> https://lists.gnu.org/r/bison-patches/2020-01/msg00000.html). > > I haven't used any such hacks, but I might start i14ing my parsers (there were also hacks for people who want to play with quotes around the token names). > now that it's properly supported. On that subject: > >> Therefore, by default, error messages now refer to "end of file" >> (internationalized) rather than the cryptic "$end", or to "invaid token" > > Typo: "invaid" (only in NEWS apparently). Thanks, I've fixed that. >> **** Token aliases internationalization >> >> When the %define variable parse.error is set to `custom` or `detailed`, >> one may specify which token aliases are to be translated using _(). For >> instance >> >> %token >> PLUS "+" >> MINUS "-" >> <double> >> NUM _("double precision number") >> <symrec*> >> FUN _("function") >> VAR _("variable") >> >> In that case the user must define _() and N_(), and yysymbol_name returns >> the translated symbol (i.e., it returns '_("variable")' rather that >> '"variable"'). In Java, the user must provide an i18n() function. > > I've used GNU gettext, but not those (strange IMHO) macros with it, > so I had to find out what to define them to. You might want to > elaborate a bit on that. So I guess I should point people to the documentation of gettext. I can elaborate a bit more, but I should not aim at a full description of how to add i18n, that's way out of scope. > In examples/c/bistromathic/parse.y I see just: > > #define N_ > #define _ > > If I do that, I get the compiler warning: > > error: this condition has identical branches [-Werror=duplicated-branches] > > about: > > return (yysymbol < YYNTOKENS && yytranslatable[yysymbol] > ? _(yy_sname[yysymbol]) > : yy_sname[yysymbol]); > > Not sure if you consider this a problem, since this seems to be just > "nop" i14ing. Yes, that's not the typical set up :) > Looking further in several tests, I found that apparently "N_" > (unlike "_") should indeed always be defined as a nop Yes. '_' serves two purposes: one is that at runtime it is actually consulting the translation dictionary to return the translation, the other is that it is recognized as a markup for strings to internationalize by the i18n tools that scan the source code. However in C you can't call a function when you define a table, so you need to split in two: 'N_' serves as markup, and does nothing, while '_' actually translates. > -- but if so, > can't the skeleton do this by itself? Hum. Good point. I guess it would be ok to just define it if N_ is not yet #defined. > Also, since I don't use autoblah, :) :) :) > it seems I have to define both > YYENABLE_NLS and ENABLE_NLS. The former is mentioned in the manual > (but only in conjunction with autoblah), the latter not at all. > > So if I got it correctly now, this seems to be the minimum required > for i18n, apart from the bindtextdomain call. Is that correct? > > %define parse.error detailed > %{ > #define YYENABLE_NLS 1 > #define ENABLE_NLS 1 > #define N_ > static auto _ (const char *s) { return dgettext ("mydomain", s); } > %} I don't think this is the right approach. I think you are trying to exploit the fact that the skeleton is actually already having support to translate its own messages ("syntax error, expected..."). Rather I had something like the attachement in mind. I am very afraid about really installing this in the source tree, because I expect tons of portability issues here: the examples are meant to be self-contained, independent of bison's build, so I cannot use the same tricks to be portable. But I agree it would be better to actually demonstrate the whole process in bistromathic. I'll see what I can do. Cheers! commit c993d94c918cdeb60c9d0eb7f8e183697316169c Author: Akim Demaille <[email protected]> Date: Sun Apr 19 09:13:47 2020 +0200 examples: bistromathic: demontrate internationalization Currently it was only using stubs. Let's actually translate the strings using gettext. * examples/c/bistromathic/local.mk: Define LOCALEDIR and link with libintl. * examples/c/bistromathic/parse.y: Use them. diff --git a/examples/c/bistromathic/local.mk b/examples/c/bistromathic/local.mk index cab026e2..f3b9045d 100644 --- a/examples/c/bistromathic/local.mk +++ b/examples/c/bistromathic/local.mk @@ -26,8 +26,10 @@ nodist_%C%_bistromathic_SOURCES = %D%/parse.y %D%/parse.h %D%/parse.c: $(dependencies) # Don't use gnulib's system headers. -%C%_bistromathic_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D% -%C%_bistromathic_LDADD = -lm -lreadline +%C%_bistromathic_CPPFLAGS = \ + -DLOCALEDIR='"$(localdir)"' \ + -I$(top_srcdir)/%D% -I$(top_builddir)/%D% +%C%_bistromathic_LDADD = -lm -lreadline -lintl dist_bistromathic_DATA = %D%/parse.y %D%/Makefile %D%/README.md CLEANFILES += %D%/parse.[ch] %D%/parse.output diff --git a/examples/c/bistromathic/parse.y b/examples/c/bistromathic/parse.y index a3b34c38..a868def9 100644 --- a/examples/c/bistromathic/parse.y +++ b/examples/c/bistromathic/parse.y @@ -10,6 +10,10 @@ #include <readline/readline.h> #include <readline/history.h> + + #ifdef LOCALEDIR + # include <libintl.h> + #endif } %code requires { @@ -40,8 +44,12 @@ } %code { -#define N_ -#define _ + #ifdef LOCALEDIR + # define _(Msgid) gettext (Msgid) + #else + # define _(Msgid) (Msgid) + #endif + #define N_(Msgid) (Msgid) // Whether to quit. int done = 0; @@ -467,6 +475,13 @@ void init_readline (void) int main (int argc, char const* argv[]) { +#ifdef LOCALEDIR + // Set up internationalization. + setlocale (LC_ALL, ""); + bindtextdomain ("bistromathic", LOCALEDIR); + textdomain ("bistromathic"); +#endif + // Enable parse traces on option -p. if (argc == 2 && strcmp (argv[1], "-p") == 0) yydebug = 1;
