system: Selected locale is automatically built.

Fixes <http://bugs.gnu.org/22572>.
Reported by Mark H Weaver <mhw@netris.org>.

* gnu/system/locale.scm (%not-dot): New variable.
(denormalize-codeset, locale-name->definition): New procedures.
* gnu/system.scm (locale-name->definition*): New procedure.
(operating-system-locale-directory): Instead of raising an error, add
the missing locale.
* doc/guix.texi (Locales): Adjust accordingly.
This commit is contained in:
Ludovic Courtès 2016-02-10 11:01:54 +01:00
parent 32e1611206
commit f5582b2c1d
3 changed files with 61 additions and 18 deletions

View file

@ -6452,17 +6452,17 @@ Usually, you will want to specify the default locale for the machine
using the @code{locale} field of the @code{operating-system} declaration using the @code{locale} field of the @code{operating-system} declaration
(@pxref{operating-system Reference, @code{locale}}). (@pxref{operating-system Reference, @code{locale}}).
That locale must be among the @dfn{locale definitions} that are known to The selected locale is automatically added to the @dfn{locale
the system---and these are specified in the @code{locale-definitions} definitions} known to the system if needed, with its codeset inferred
slot of @code{operating-system}. The default value includes locale from its name---e.g., @code{bo_CN.utf8} will be assumed to use the
definitions for some widely used locales, but not for all the available @code{UTF-8} codeset. Additional locale definitions can be specified in
locales, in order to save space. the @code{locale-definitions} slot of @code{operating-system}---this is
useful, for instance, if the codeset could not be inferred from the
locale name. The default set of locale definitions includes some widely
used locales, but not all the available locales, in order to save space.
If the locale specified in the @code{locale} field is not among the For instance, to add the North Frisian locale for Germany, the value of
definitions listed in @code{locale-definitions}, @command{guix system} that field may be:
raises an error. In that case, you should add the locale definition to
the @code{locale-definitions} field. For instance, to add the North
Frisian locale for Germany, the value of that field may be:
@example @example
(cons (locale-definition (cons (locale-definition

View file

@ -669,18 +669,31 @@ (define make-initrd
#:mapped-devices mapped-devices))) #:mapped-devices mapped-devices)))
(return #~(string-append #$initrd "/initrd")))) (return #~(string-append #$initrd "/initrd"))))
(define (locale-name->definition* name)
"Variant of 'locale-name->definition' that raises an error upon failure."
(match (locale-name->definition name)
(#f
(raise (condition
(&message
(message (format #f (_ "~a: invalid locale name") name))))))
(def def)))
(define (operating-system-locale-directory os) (define (operating-system-locale-directory os)
"Return the directory containing the locales compiled for the definitions "Return the directory containing the locales compiled for the definitions
listed in OS. The C library expects to find it under listed in OS. The C library expects to find it under
/run/current-system/locale." /run/current-system/locale."
;; While we're at it, check whether the locale of OS is defined. (define name
(unless (member (operating-system-locale os) (operating-system-locale os))
(map locale-definition-name
(operating-system-locale-definitions os)))
(raise (condition
(&message (message "system locale lacks a definition")))))
(locale-directory (operating-system-locale-definitions os) (define definitions
;; While we're at it, check whether NAME is defined and add it if needed.
(if (member name (map locale-definition-name
(operating-system-locale-definitions os)))
(operating-system-locale-definitions os)
(cons (locale-name->definition* name)
(operating-system-locale-definitions os))))
(locale-directory definitions
#:libcs (operating-system-locale-libcs os))) #:libcs (operating-system-locale-libcs os)))
(define (kernel->grub-label kernel) (define (kernel->grub-label kernel)

View file

@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
;;; ;;;
@ -33,6 +33,7 @@ (define-module (gnu system locale)
locale-definition-source locale-definition-source
locale-definition-charset locale-definition-charset
locale-name->definition
locale-directory locale-directory
%default-locale-libcs %default-locale-libcs
@ -52,6 +53,35 @@ (define-record-type* <locale-definition> locale-definition
(charset locale-definition-charset ;string--e.g., "UTF-8" (charset locale-definition-charset ;string--e.g., "UTF-8"
(default "UTF-8"))) (default "UTF-8")))
(define %not-dot
(char-set-complement (char-set #\.)))
(define (denormalize-codeset codeset)
"Attempt to guess the \"real\" name of CODESET, a normalized codeset as
defined in (info \"(libc) Using gettextized software\")."
(cond ((string=? codeset "utf8")
"UTF-8")
((string-prefix? "iso8859" codeset)
(string-append "ISO-8859-" (string-drop codeset 7)))
((string=? codeset "eucjp")
"EUC-JP")
(else ;cross fingers, hope for the best
codeset)))
(define (locale-name->definition name)
"Return a <locale-definition> corresponding to NAME, guessing the charset,
or #f on failure."
(match (string-tokenize name %not-dot)
((source charset)
;; XXX: NAME is supposed to use the "normalized codeset", such as "utf8",
;; whereas the actual name used is different. Add a special case to make
;; the right guess for UTF-8.
(locale-definition (name name)
(source source)
(charset (denormalize-codeset charset))))
(_
#f)))
(define* (localedef-command locale (define* (localedef-command locale
#:key (libc (canonical-package glibc))) #:key (libc (canonical-package glibc)))
"Return a gexp that runs 'localedef' from LIBC to build LOCALE." "Return a gexp that runs 'localedef' from LIBC to build LOCALE."