guile-devel
[Top][All Lists]
Advanced

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

Re: Website translations with Haunt


From: pelzflorian (Florian Pelz)
Subject: Re: Website translations with Haunt
Date: Wed, 13 Dec 2017 15:53:33 +0100
User-agent: NeoMutt/20171208

On Sat, Dec 09, 2017 at 10:29:49PM +0000, ng0 wrote:
> pelzflorian (Florian Pelz) transcribed 2.4K bytes:
> > On Sat, Dec 09, 2017 at 06:15:29PM +0000, ng0 wrote:
> > > My idea was a reimplementation of prep (a text format and html document
> > > generator that is capable to include multiple languages in its source
> > > files, written by lynX back in the early 90s (or earlier) iirc (and
> > > still used today).
> > >
> > 
> > Hmm I can find neither prep nor lynX in a quick Web search.
> 
> lynX is the author of many things, among them the psyc and psyc2 protol,
> psyced, the /me command in IRC etc. this page is generated from prep: 
> http://my.pages.de
> (http://my.pages.de/me should show more).
> 

I see.  lynX deserves a better Duckduckgo search ranking than he has. ;)

There is a lot to look at; thank you for the link.  I now also
understand better what kind of organization youbroketheinternet is.

Either way,

> > Po files are separate from the source code files.  I don’t know if
> > prep has such a separation or if such a separation really is better.
> > 
> > Then again, another issue with HTML/SHTML is that e.g. a hyperlink within
> > the text is difficult to handle with traditional format strings
> > without breaking the separation:
> > 
> >  * The link text should be translated in the context of the text
> >    surrounding the link
> > 
> >  * but the link formatting and maybe the link destination URL maybe
> >    should not be changeable by the translator.
> > 
> > Does prep handle this?
> 
> To some extent. prep is not SGML. It's been a while since I've looked
> into it but basically you have a unique syntax. The following snippet
> (from pages/my/convivenza.mlm) doesn't show it's full usage,
> but it show how links are handled:
> 
> 
> I)#section Approfondimenti
> D)#section Vertiefung
> E)#section Further Reading
> 
> […]
> To my best knowledge nothing has been developed that allows to conveniently
> define multiple languages in one source file outside from plain S/XML, and
> this is what I find interesting about prep. Wether I end up writing a 
> reimplementation
> in Guile or not, there are some interesting ideas that could possibly be 
> applied
> to your approach.
> I'll need some time to find time to compare the two approaches and find 
> similarities.
> 
> Maybe my reply already helps, with reading the provided (really small) 
> codebase
> of prep.
>

Thank you, I looked at it.  This is certainly interesting but
combining SHTML and translation in one file is not what I want.  I
agree that it has advantages, but I have settled on this for now:


(define (paragraph-about-a-manatee-for-lingua lingua)
  (let* ((current-lingua lingua))
    `(p
      ,@(__ "img1|This|| is an image of a 
||link1|https://en.wikipedia.org/wiki/Manatee|manatee||."
            `(("img1" .
               ,(lambda (text)
                  `(img (@ (src 
"https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Bair%27s_Cove_-_Haulover_Canal%2C_Merritt_Island_FL_-_Flickr_-_Rusty_Clark_%2833%29.jpg/320px-Bair%27s_Cove_-_Haulover_Canal%2C_Merritt_Island_FL_-_Flickr_-_Rusty_Clark_%2833%29.jpg";)
                           (alt ,text)))))
              ("link1" .
               ,(lambda (url text)
                  `(a (@ (href ,url))
                     ,text))))))))





I implemented it like this:

(define translated-msg
  ;; gettext is not used directly because it would require repeated
  ;; setlocale calls, which should not be necessary.
  ;; See: https://stackoverflow.com/questions/3398113/php-gettext-problems
  (let […]
    (lambda (msgid lingua)
      "Returns the msgstr for MSGID from the po file for LINGUA."
      […])))

(define (translated-multipart-msg msg lingua assoc)
  "Looks up MSG for LINGUA via Gettext and returns a list of its parts.

Parts are separated by two vertical bars ||.  If a part is prefixed by
a text followed by a vertical bar the text is looked up a lambda in
the association list ASSOC.  If found, the lambda is called on the
remainder of the part and the result added to the list.  If it is not
found or there is no vertical bar, the entire part is added to the
list."
  (define (split-along-unescaped-matches str pattern)
    "Splits along pattern unless pattern is escaped by a backslash."
    (let loop ((remainder str) ; what to match with
               (start 0)) ; where to start matching, used to ignore escaped 
matches
      (let ((match (string-match pattern remainder start)))
        (if match ; if there is a match:
            (if (and
                 ;; if match not at the beginning
                 (not (= (match:start match) 0))
                 (eq? ; and escaped by a backslash
                  (string-ref
                   remainder
                   (- (match:start match) 1))
                  #\\))
                ;; then continue matching after the escaped match:
                (loop
                 (string-append ; the same as remainder but
                  (string-drop-right (match:prefix match) 1) ; drop backslash
                  (match:substring match)
                  (match:suffix match))
                 (- (match:end match) 1))
                ;; otherwise:
                (cons
                 ;; everything before the match
                 (match:prefix match)
                 (loop ; recursive call
                  (match:suffix match) ; on everything after the match
                  0))) ; start matching at start
            ;; if pattern did not match:
            (list remainder)))))
  (let ((msgstr-parts
         (split-along-unescaped-matches
          (translated-msg msg lingua)
          "\\\|\\\|")))
    (map
     (lambda (msgstr-part)
       (let* ((subparts
               (split-along-unescaped-matches
                msgstr-part
                "\\\|"))
              (part-lambda (assoc-ref assoc (car subparts)))
              (args (cdr subparts)))
         (if part-lambda
             (apply part-lambda args)
             msgstr-part)))
     msgstr-parts)))

(define-syntax __
  (lambda (x)
    "Gettext shorthand for multipart messages separated by || in the string."
    (syntax-case x ()
      ((__ msg assoc)
       (with-syntax ((current-lingua (datum->syntax x 'current-lingua)))
                    #'(translated-multipart-msg msg current-lingua assoc))))))



Regards,
Florian

Attachment: signature.asc
Description: PGP signature


reply via email to

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