Subject: Re: [bug#44075] [PATCH] gnu: Add make-glibc-locales-collection.

From: Miguel Ángel Arruga Vivas <[email-masked]>
Date: Thu, 22 Oct 2020 01:18:16 +0200

Hello,

Efraim Flashner <[email-masked]> writes:
> Your patch was what got me to actually send mine to guix-patches :)

Thanks. :-)

> That is a good point. I'll change it to something actually useful,
> mentioning that there's a convention but that people often get it wrong.

Great, the more knowledge, the easier to overcome that common
misunderstanding. :-)

> I agree it should be renamed to en-us. I have some bikeshedding to think
> about for en-us-glibc-locales vs glibc-locales-en-us. And I'll also test
> out one for glibc-locales-guile-tests.

I meant the ISO-8859-1, the locale creation should be en_EN.iso88591,
the locale name can be en_EN.88591 too...

Although in that case shouldn't be glibc-en-us-locales?  I'd like green
lights for the bike shed, please. ;-)

> I hadn't seen gnu/build/locales.scm. I'll have to see what we can do
> about using it. We normally don't allow cross-over from the build side
> to the packages side.

It is already being used in the build of glibc-locales and I guess it
would be harmless to move it to guix build if that is a problem, but I
think it can be used as it is right now, even I didn't check yet.  In
this for-each(gnu/packages/base.scm:1084), for example:
------------------------->8-------------begin----------------------
(for-each (lambda (directory)
            (let*-values (((base)
                           (basename directory))
                          ((name codeset)
                           (locale->name+codeset base))
                          ((normalized)
                           (normalize-codeset codeset)))
              (unless (string=? codeset normalized)
                (symlink base
                         (string-append (dirname directory)
                                        "/" name "."
                                        normalized)))))
          locales)
-------------------------8<--------------end-----------------------

I would write something like this in the builder code:
------------------------->8-------------begin----------------------
(define (locale-builder directory)
  (lambda (locale)
    (let-values (((name codeset)
                  (locale->name+codeset)))
      (if codeset
          (build-locale name
                        #:directory directory
                        #:codeset (normalize-codeset codeset))
          (build-locale name
                        #:directory directory
                        #:codeset "utf8")))))
(let ...
  (for-each (locale-builder localedir) '(,@locales))
  ...)
-------------------------8<--------------end-----------------------

I leave you here the function I was hacking apart (please, do not
confuse with working code ;-)) if you want to take any idea other from
it:
------------------------->8-------------begin----------------------
(define*-public (make-glibc-selected-locales
                 glibc
                 #:key
                 (suffix "-utf8-locales")
                 (locales %default-locales)
                 (alias %default-alias))
  (package
    (name (string-append (package-name glibc) suffix))
    (version (package-version glibc))
    (source #f)
    (build-system trivial-build-system)
    (arguments
     `(#:modules ((guix build utils) (gnu build locale))
       #:builder
       (begin
         (use-modules (guix build utils) (gnu build locale))
         ;; Print the common alias for locale
         (define (print-locale-alias locale)
           (let-values (((name codeset)
                         (locale->name+codeset)))
             (if codeset
                 (or (string-equal codeset (normalize-codeset codeset))
                     (format #t "~a.~a ~a.~a~%" name codeset
                             name (normalize-codeset codeset)))
                 (format #t "~a.UTF-8 ~a.utf8" name name))))

         ;; Generate a function that builds the locale into directory.
         (define (locale-builder directory)
           (lambda (locale)
             (let-values (((name codeset)
                           (locale->name+codeset)))
               (if codeset
                   (build-locale name
                                 #:directory directory
                                 #:codeset (normalize-codeset codeset))
                   (build-locale name
                                 #:directory directory
                                 #:codeset "utf8")))))

         ;; Do the job.
         (let* ((libc      (assoc-ref %build-inputs "glibc"))
                (gzip      (assoc-ref %build-inputs "gzip"))
                (out       (assoc-ref %outputs "out"))
                (localedir (string-append out "/lib/locale/"
                                          ,(version-major+minor version)))
                (alias     (string-append localedir "/locale.alias"))
                (locales   '(,@locales)))

           ;; 'localedef' needs 'gzip'.
           (setenv "PATH" (string-append libc "/bin:" gzip "/bin"))

           (mkdir-p localedir)
           ;; Generate each locale provided.
           (for-each (locale-builder localedir) locales)
           ;; Generate alias file.
           (with-output-to-file alias
             (lambda ()
               (format #t "~a~%" "# Aliases for common codeset names.")
               (for-each print-locale-alias locales)
               (format #t "~a~%" "# Other aliases.")
               (for-each (lambda (line)
                           (format #t "~a~%" line))
                         '(,@alias)))))))
    (native-inputs `(("glibc" ,glibc)
                     ("gzip" ,gzip)))
    (synopsis "Configured sample of locales")
    (description
     "TODO.")
    (home-page (package-home-page glibc))
    (license (package-license glibc))))
-------------------------8<--------------end-----------------------

Happy hacking,
Miguel