Hi, "pelzflorian (Florian Pelz)" <pelzflor...@pelzflorian.de> skribis:
>> > +(define (sgettext x) >> > + "After choosing an identifier for marking s-expressions for >> > +translation, make it usable by defining a macro with it calling >> > +sgettext. If for example the chosen identifier is G_, >> > +use (define-syntax G_ sgettext)." >> > + (syntax-case x () >> > + ((id exp) >> > + (let* ((msgid (sexp->msgid (syntax->datum #'exp))) >> > + (new-exp (deconstruct (syntax->datum #'exp) >> > + (gettext msgid)))) >> > + (datum->syntax #'id new-exp))))) >> >> For this and other similar macros you must use ‘define-syntax’, not >> ‘define’, so that they are defined at expansion time, not at run time. > > As per the above docstring, I already have a definition > > (define-syntax G_ sgettext) > > in (apps i18n). Possibly I should just move it here. Hmmm right. It works, but it’s surprising and “borderline”. If all you want is an alias, I’d recommend writing, say: (define-syntax sgettext …) (define-syntax G_ (identifier-syntax sgettext)) >> (It doesn’t make any difference when you’re evaluating code since both >> phases run in the same module, but it does make a difference when these >> phases happen at different times, in different processes.) >> >> Consequently, you must arrange for ‘sexp->msgid’ and ‘deconstruct’ to be >> available at expansion time too. This can be done by wrapping their >> definition in ‘eval-when’: >> >> (eval-when (load expand eval) >> (define (sexp->msgid …) …) >> (define (deconstruct …) …)) >> >> But actually it’s not clear to me why these are macros. I think they >> could be regular procedures and it’d work just fine, no? >> > > I do not understand. sexp->msgid and deconstruct are procedures, not > syntax transformers. I can add eval-when, but the current code runs > as expected for me. I tried to explain above but you can check the Guile manual on ‘eval-when’ (info "(guile) Eval When"). The example there hopefully clarifies what the problem is. >> > +(define %plural-numbers >> > + ;; Hard-coded list of input numbers such that for each language’s >> > + ;; plural formula, for each possible output grammatical number, >> > + ;; there is an n among %plural-numbers that yields this output >> > + ;; (cf. section Plural forms in the gettext manual), except 1 is >> > + ;; omitted from this list because it is a special case for >> > + ;; sngettext. That is, calling ngettext with each number from >> > + ;; %plural-numbers and with 1 in any locale is guaranteed to return >> > + ;; each plural form at least once. It would be more resilient >> > + ;; towards new languages if instead of hard-coding we computed this >> > + ;; from the Plural-Forms in the MO file header entry, but that is >> > + ;; not worth the incurred code complexity. >> > + '(0 2 3 11 100)) >> >> I don’t understand this: are these the only plural numbers in all >> languages, or…? >> > > Yes, in all languages for which a plural= formula is documented in the > gettext manual. > > For example, Arabic has > > Plural-Forms: nplurals=6; \ > plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? > 3 \ > : n%100>=11 ? 4 : 5; > > with input plural numbers 0, 1, 2, 3, 11, 100 mapping to all outputs > 0, 1, 2, 3, 4, 5. > > Maybe I should add this example to the code comment. Oh I see. Maybe just link to the relevant section of the manual ("info (gettext) Plural forms"). I think you can go ahead and push this series to a branch, say ‘wip-i18n’ (the ‘wip-’ prefix meaning that you reserve the right to rebase the branch as you will.) We can then maybe set up a ‘static-web-site’ service on berlin, with appropriate nginx rules, to build and publish the manual at a separate URL so we can all test it. See hydra/berlin.scm in maintenance.git. Thoughts? Thank you! Ludo’.