aboutsummaryrefslogtreecommitdiff
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu build locale)
  #:use-module (guix build utils)
  #:use-module (srfi srfi-1)
  #:use-module (ice-9 rdelim)
  #:use-module (ice-9 match)
  #:use-module (ice-9 regex)
  #:export (build-locale
            normalize-codeset
            locale->name+codeset
            read-supported-locales))

(define locale-rx
  ;; Regexp matching a locale line in 'localedata/SUPPORTED'.
  (make-regexp
   "^[[:space:]]*([[:graph:]]+)/([[:graph:]]+)[[:space:]]*\\\\$"))

(define (read-supported-locales port)
  "Read the 'localedata/SUPPORTED' file from PORT.  That file is actually a
makefile snippet, with one locale per line, and a header that can be
discarded."
  (let loop ((locales '()))
    (define line
      (read-line port))

    (cond ((eof-object? line)
           (reverse locales))
          ((string-prefix? "#" (string-trim line)) ;comment
           (loop locales))
          ((string-contains line "=")            ;makefile variable assignment
           (loop locales))
          (else
           (match (regexp-exec locale-rx line)
             (#f
              (loop locales))
             (m
              (loop (alist-cons (match:substring m 1)
                                (match:substring m 2)
                                locales))))))))

(define (normalize-codeset codeset)
  "Compute the \"normalized\" variant of CODESET."
  ;; info "(libc) Using gettextized software", for the algorithm used to
  ;; compute the normalized codeset.
  (letrec-syntax ((-> (syntax-rules ()
                        ((_ proc value)
                         (proc value))
                        ((_ proc rest ...)
                         (proc (-> rest ...))))))
    (-> (lambda (str)
          (if (string-every char-set:digit str)
              (string-append "iso" str)
              str))
        string-downcase
        (lambda (str)
          (string-filter char-set:letter+digit str))
        codeset)))

(define* (build-locale locale
                       #:key
                       (localedef "localedef")
                       (directory ".")
                       (codeset "UTF-8")
                       (name (string-append locale "." codeset)))
  "Compute locale data for LOCALE and CODESET--e.g., \"en_US\" and
\"UTF-8\"--with LOCALEDEF, and store it in DIRECTORY under NAME."
  (format #t "building locale '~a'...~%" name)
  (invoke localedef "--no-archive" "--prefix" directory
          "-i" locale "-f" codeset
          (string-append directory "/" name)))

(define (locale->name+codeset locale)
  "Split a locale name such as \"aa_ER@saaho.UTF-8\" into two values: the
language/territory/modifier part, and the codeset."
  (match (string-rindex locale #\.)
    (#f  (values locale #f))
    (dot (values (string-take locale dot)
                 (string-drop locale (+ dot 1))))))
/td>Merge branch 'master' into core-updates....Maxim Cournoyer 2023-03-30system: Remove obsolete GUIX_LOCPATH workaround....Bruno Victal 2023-03-20Merge remote-tracking branch 'origin/master' into core-updatesAndreas Enge 2023-03-16services: etc-service: Deprecate etc-service procedure....Bruno Victal 2023-03-13system: Remove redundant gexp-ungexp usage....Bruno Victal 2023-03-13system: Simplify nsswitch binding....Bruno Victal 2023-03-02Merge remote-tracking branch 'savannah/master' into core-updates...Christopher Baines 2023-03-03services: base: Deprecate 'host-name-service' procedure....Bruno Victal 2023-02-23system: Do not export local-host-entries....Bruno Victal 2023-02-09system: Deprecate hosts-file....Bruno Victal 2023-01-30Merge remote-tracking branch 'origin/master' into core-updates...Efraim Flashner 2023-01-05system: Define default 'PS1' in /etc/bashrc rather than ~/.bashrc....Ludovic Courtès 2022-12-05system: Add e2fsprogs to %base-packages-utils....Maxim Cournoyer 2022-12-05system: Rename and move %base-packages-disk-utilities....Maxim Cournoyer 2022-11-27gnu: shadow: Merge in shadow-with-man-pages....Efraim Flashner 2022-10-23gnu: Fix typos....Vagrant Cascadian 2022-10-23system: hurd: Boot with the statically-linked 'exec' server....Ludovic Courtès 2022-10-11system: operating-system: Make the timezone field default to Etc/UTC....Maxim Cournoyer 2022-09-28services: Add file system utilities to profile....Brice Waegeneire 2022-07-14gnu: system: Add fusermount3 to setuid-programs....Maxim Cournoyer 2022-06-15system: <operating-system> compiler truly honors the 'system' argument....Ludovic Courtès 2022-06-06system: Fix typo, add doc....Maxim Cournoyer 2022-05-21system: Improve warning when using LUKS mapped devices without UUIDs....Maxim Cournoyer 2022-04-07services: shepherd: Default to version 0.9....Ludovic Courtès 2022-03-21system: Use 'shadow-with-man-pages' in %BASE-PACKAGES-UTILS....Ludovic Courtès 2022-03-16system: Improve 'read-boot-parameters' incompatibility diagnostic....Ludovic Courtès 2022-03-07system: Set kernel name for riscv64-linux....Efraim Flashner 2022-03-01initrd: Use non-hyphenated kernel command-line parameter names....Maxim Cournoyer 2022-03-01system: Streamline operating-system-boot-parameters-file a bit....Maxim Cournoyer 2022-03-01system: Add a version field to the <boot-parameters> record....Maxim Cournoyer