* Static, pure Scheme internationalization
@ 2024-12-21 9:30 Vivien Kraus
2024-12-21 11:18 ` Nala Ginrut
0 siblings, 1 reply; 9+ messages in thread
From: Vivien Kraus @ 2024-12-21 9:30 UTC (permalink / raw)
To: Guile User
Dear Guile users,
I am very excited about Hoot, but there is one aspect I was not
satisfied with: internationalization. Since it is usually done with
gettext, it requires a C library at run-time. Hoot programs can’t
unfortunately use that.
With your help, I managed to understand how I could rewrite code with
macros.
Thanks to this knowledge, I was able to create a small library for
static and pure Scheme internationalization.
It works like this
(https://labo.planete-kraus.eu/guile-static-i18n.git/tree/example.scm):
(define-module (example)
#:use-module (static-i18n)
#:declarative? #t
#:export (main))
;; We have to tell where the pot file lives at expansion time.
(eval-when (expand)
(project-pot-file
(string-append (dirname (current-filename)) "/example.pot"))
(project-po-directory
(string-append (dirname (current-filename)) "/example-po")))
;; collect-strings updates a PO template file, regenerates PO files,
;; and use them to provide translations for any calls to G_.
(collect-strings
;; This is defined at the top-level.
(define (main args)
;; current-locale-order is parameterized by a list of locale names
;; to try in order.
(parameterize ((current-locale-order '("de" "fr" "en")))
;; Note how you can use (G_ context message) to register a new
;; record, without having to call xgettext.
(format #t (G_ "GREETING" "Hello, world!~%")))))
(main (command-line))
Once expanded, every call to G_ will have all possible translations
compiled in, and the correct one will be chosen according to a list of
preference for the user (a run-time Guile parameter).
The big downside is, it doesn’t support plurals. However, I believe it
can be useful!
https://labo.planete-kraus.eu/guile-static-i18n.git
Best regards,
Vivien
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Static, pure Scheme internationalization
2024-12-21 9:30 Static, pure Scheme internationalization Vivien Kraus
@ 2024-12-21 11:18 ` Nala Ginrut
2024-12-21 11:46 ` Vivien Kraus
0 siblings, 1 reply; 9+ messages in thread
From: Nala Ginrut @ 2024-12-21 11:18 UTC (permalink / raw)
To: Vivien Kraus; +Cc: Guile User
Hi Vivien!
I'm also interested in Hoot for potential web frontend in Scheme.
Back to your case, as I understand, Hoot reused part of Guile code, include
i18n.
Maybe not complete yet, but it contains gettext, and G_ is its short hand.
I saw you implemented a simple G_ macro, is there any reason that it can't
meet your requirements? Or you just happend to not know it exited in Hoot?
Best regards.
Best regards.
On Sat, Dec 21, 2024, 18:31 Vivien Kraus <vivien@planete-kraus.eu> wrote:
> Dear Guile users,
>
> I am very excited about Hoot, but there is one aspect I was not
> satisfied with: internationalization. Since it is usually done with
> gettext, it requires a C library at run-time. Hoot programs can’t
> unfortunately use that.
>
> With your help, I managed to understand how I could rewrite code with
> macros.
>
> Thanks to this knowledge, I was able to create a small library for
> static and pure Scheme internationalization.
>
> It works like this
> (https://labo.planete-kraus.eu/guile-static-i18n.git/tree/example.scm):
>
> (define-module (example)
> #:use-module (static-i18n)
> #:declarative? #t
> #:export (main))
>
> ;; We have to tell where the pot file lives at expansion time.
> (eval-when (expand)
> (project-pot-file
> (string-append (dirname (current-filename)) "/example.pot"))
> (project-po-directory
> (string-append (dirname (current-filename)) "/example-po")))
>
> ;; collect-strings updates a PO template file, regenerates PO files,
> ;; and use them to provide translations for any calls to G_.
> (collect-strings
> ;; This is defined at the top-level.
> (define (main args)
> ;; current-locale-order is parameterized by a list of locale names
> ;; to try in order.
> (parameterize ((current-locale-order '("de" "fr" "en")))
> ;; Note how you can use (G_ context message) to register a new
> ;; record, without having to call xgettext.
> (format #t (G_ "GREETING" "Hello, world!~%")))))
>
> (main (command-line))
>
> Once expanded, every call to G_ will have all possible translations
> compiled in, and the correct one will be chosen according to a list of
> preference for the user (a run-time Guile parameter).
>
> The big downside is, it doesn’t support plurals. However, I believe it
> can be useful!
>
> https://labo.planete-kraus.eu/guile-static-i18n.git
>
> Best regards,
>
> Vivien
>
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Static, pure Scheme internationalization
2024-12-21 11:18 ` Nala Ginrut
@ 2024-12-21 11:46 ` Vivien Kraus
2024-12-21 12:14 ` Nala Ginrut
0 siblings, 1 reply; 9+ messages in thread
From: Vivien Kraus @ 2024-12-21 11:46 UTC (permalink / raw)
To: Nala Ginrut; +Cc: Guile User
Hello!
Le samedi 21 décembre 2024 à 20:18 +0900, Nala Ginrut a écrit :
> Maybe not complete yet, but it contains gettext, and G_ is its short
> hand.
> I saw you implemented a simple G_ macro, is there any reason that it
> can't meet your requirements? Or you just happend to not know it
> exited in Hoot?
Maybe I did not look in the correct place? As far as I understand, the
implementation in Hoot for (ice-9 i18n) is this:
https://gitlab.com/spritely/guile-hoot/-/blob/main/lib/ice-9/i18n.scm?ref_type=heads
It does not contain any meaningful implementation of gettext, and this
file claims that i18n is not supported yet.
Vivien
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Static, pure Scheme internationalization
2024-12-21 11:46 ` Vivien Kraus
@ 2024-12-21 12:14 ` Nala Ginrut
2024-12-21 12:36 ` Nala Ginrut
0 siblings, 1 reply; 9+ messages in thread
From: Nala Ginrut @ 2024-12-21 12:14 UTC (permalink / raw)
To: Vivien Kraus; +Cc: Guile User
I see, it's in *unimplemented-bindings of guile.scm, that's why I grep
'gettext' and it exists!
Best regards.
On Sat, Dec 21, 2024 at 8:46 PM Vivien Kraus <vivien@planete-kraus.eu>
wrote:
> Hello!
>
> Le samedi 21 décembre 2024 à 20:18 +0900, Nala Ginrut a écrit :
> > Maybe not complete yet, but it contains gettext, and G_ is its short
> > hand.
> > I saw you implemented a simple G_ macro, is there any reason that it
> > can't meet your requirements? Or you just happend to not know it
> > exited in Hoot?
>
> Maybe I did not look in the correct place? As far as I understand, the
> implementation in Hoot for (ice-9 i18n) is this:
>
> https://gitlab.com/spritely/guile-hoot/-/blob/main/lib/ice-9/i18n.scm?ref_type=heads
>
> It does not contain any meaningful implementation of gettext, and this
> file claims that i18n is not supported yet.
>
> Vivien
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Static, pure Scheme internationalization
2024-12-21 12:14 ` Nala Ginrut
@ 2024-12-21 12:36 ` Nala Ginrut
2024-12-21 14:15 ` Vivien Kraus
0 siblings, 1 reply; 9+ messages in thread
From: Nala Ginrut @ 2024-12-21 12:36 UTC (permalink / raw)
To: Vivien Kraus; +Cc: Guile User
For this part, maybe there's more efficient way:
----------------------------------------------------------------
(define (get-bytevector-u32 port) "Read a 4-byte big-endian number."
(car (bytevector->uint-list (get-bytevector-n port 4)
(current-endianness) 4)))
------------------------------------
(bytevector-u32-ref (get-bytevector-n port 4) 0 (native-endianess))
If you want to base on Hoot, maybe it's OK to implement your own
(current-endianess) as you showed. And I think it's Hoot's work to compile
it to WASM
Not sure if it's possible to just reuse (native-endianess) of Guile.
On Sat, Dec 21, 2024 at 9:14 PM Nala Ginrut <nalaginrut@gmail.com> wrote:
> I see, it's in *unimplemented-bindings of guile.scm, that's why I grep
> 'gettext' and it exists!
>
> Best regards.
>
> On Sat, Dec 21, 2024 at 8:46 PM Vivien Kraus <vivien@planete-kraus.eu>
> wrote:
>
>> Hello!
>>
>> Le samedi 21 décembre 2024 à 20:18 +0900, Nala Ginrut a écrit :
>> > Maybe not complete yet, but it contains gettext, and G_ is its short
>> > hand.
>> > I saw you implemented a simple G_ macro, is there any reason that it
>> > can't meet your requirements? Or you just happend to not know it
>> > exited in Hoot?
>>
>> Maybe I did not look in the correct place? As far as I understand, the
>> implementation in Hoot for (ice-9 i18n) is this:
>>
>> https://gitlab.com/spritely/guile-hoot/-/blob/main/lib/ice-9/i18n.scm?ref_type=heads
>>
>> It does not contain any meaningful implementation of gettext, and this
>> file claims that i18n is not supported yet.
>>
>> Vivien
>>
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Static, pure Scheme internationalization
2024-12-21 12:36 ` Nala Ginrut
@ 2024-12-21 14:15 ` Vivien Kraus
2024-12-21 14:18 ` Nala Ginrut
0 siblings, 1 reply; 9+ messages in thread
From: Vivien Kraus @ 2024-12-21 14:15 UTC (permalink / raw)
To: Nala Ginrut; +Cc: Guile User
Le samedi 21 décembre 2024 à 21:36 +0900, Nala Ginrut a écrit :
> If you want to base on Hoot, maybe it's OK to implement your own
> (current-endianess) as you showed.
This will not run on Hoot, it only runs at expansion time. However,
from what I understand from the GNU MO file format specification, it
can be written either as big-endian or little-endian, I assume
depending on the machine used to produce the MO file. You can detect
which one it is by looking at the magic header in the file.
Thank you for the bytevector-u32-ref suggestion!
Vivien
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Static, pure Scheme internationalization
2024-12-21 14:15 ` Vivien Kraus
@ 2024-12-21 14:18 ` Nala Ginrut
2024-12-21 14:31 ` Vivien Kraus
0 siblings, 1 reply; 9+ messages in thread
From: Nala Ginrut @ 2024-12-21 14:18 UTC (permalink / raw)
To: Vivien Kraus; +Cc: Guile User
If you're going to run it like any normal Guile program, it's better to use
the "native-endianess" function of Guile to detect the endianness of the
current platform, IIRC it's in (rnrs).
On Sat, Dec 21, 2024 at 11:15 PM Vivien Kraus <vivien@planete-kraus.eu>
wrote:
> Le samedi 21 décembre 2024 à 21:36 +0900, Nala Ginrut a écrit :
> > If you want to base on Hoot, maybe it's OK to implement your own
> > (current-endianess) as you showed.
>
> This will not run on Hoot, it only runs at expansion time. However,
> from what I understand from the GNU MO file format specification, it
> can be written either as big-endian or little-endian, I assume
> depending on the machine used to produce the MO file. You can detect
> which one it is by looking at the magic header in the file.
>
> Thank you for the bytevector-u32-ref suggestion!
>
> Vivien
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Static, pure Scheme internationalization
2024-12-21 14:18 ` Nala Ginrut
@ 2024-12-21 14:31 ` Vivien Kraus
2024-12-21 18:27 ` Nala Ginrut
0 siblings, 1 reply; 9+ messages in thread
From: Vivien Kraus @ 2024-12-21 14:31 UTC (permalink / raw)
To: Nala Ginrut; +Cc: Guile User
Le samedi 21 décembre 2024 à 23:18 +0900, Nala Ginrut a écrit :
> If you're going to run it like any normal Guile program, it's better
> to use the "native-endianess" function of Guile to detect the
> endianness of the current platform, IIRC it's in (rnrs).
The MO file specification is not very clear:
https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html
The only place it talks about endianness is this:
“The magic number will always signal GNU MO files. The number is stored
in the byte order used when the MO file was generated, so the magic
number really is two numbers: 0x950412de and 0xde120495.”
I could be wrong, but my interpretation is that I should trust the
magic number to indicate which byte order to use for every 4-byte
number in the file. This is a bit of a stretch, admittedly, but I think
it’s more robust that way.
Vivien
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Static, pure Scheme internationalization
2024-12-21 14:31 ` Vivien Kraus
@ 2024-12-21 18:27 ` Nala Ginrut
0 siblings, 0 replies; 9+ messages in thread
From: Nala Ginrut @ 2024-12-21 18:27 UTC (permalink / raw)
To: Vivien Kraus; +Cc: Guile User
Oh, I'm not familiar with MO file, it seems the endianess is unrelated to
the platform, you need go test it to confirm each time.
Best regards.
On Sat, Dec 21, 2024, 23:31 Vivien Kraus <vivien@planete-kraus.eu> wrote:
> Le samedi 21 décembre 2024 à 23:18 +0900, Nala Ginrut a écrit :
> > If you're going to run it like any normal Guile program, it's better
> > to use the "native-endianess" function of Guile to detect the
> > endianness of the current platform, IIRC it's in (rnrs).
>
> The MO file specification is not very clear:
> https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html
>
> The only place it talks about endianness is this:
>
> “The magic number will always signal GNU MO files. The number is stored
> in the byte order used when the MO file was generated, so the magic
> number really is two numbers: 0x950412de and 0xde120495.”
>
> I could be wrong, but my interpretation is that I should trust the
> magic number to indicate which byte order to use for every 4-byte
> number in the file. This is a bit of a stretch, admittedly, but I think
> it’s more robust that way.
>
> Vivien
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2024-12-21 18:27 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-21 9:30 Static, pure Scheme internationalization Vivien Kraus
2024-12-21 11:18 ` Nala Ginrut
2024-12-21 11:46 ` Vivien Kraus
2024-12-21 12:14 ` Nala Ginrut
2024-12-21 12:36 ` Nala Ginrut
2024-12-21 14:15 ` Vivien Kraus
2024-12-21 14:18 ` Nala Ginrut
2024-12-21 14:31 ` Vivien Kraus
2024-12-21 18:27 ` Nala Ginrut
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).