| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 |
|
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 |
|
| 27 | (define-module (gnu system locale)
|
| 28 | #:use-module (guix gexp)
|
| 29 | #:use-module (guix store)
|
| 30 | #:use-module (guix modules)
|
| 31 | #:use-module (guix records)
|
| 32 | #:use-module (guix packages)
|
| 33 | #:use-module (guix utils)
|
| 34 | #:use-module (gnu packages base)
|
| 35 | #:use-module (gnu packages compression)
|
| 36 | #:use-module (srfi srfi-26)
|
| 37 | #:use-module (ice-9 match)
|
| 38 | #:export (locale-definition
|
| 39 | locale-definition?
|
| 40 | locale-definition-name
|
| 41 | locale-definition-source
|
| 42 | locale-definition-charset
|
| 43 |
|
| 44 | locale-name->definition
|
| 45 | locale-directory
|
| 46 |
|
| 47 | %default-locale-libcs
|
| 48 | %default-locale-definitions
|
| 49 |
|
| 50 | glibc-supported-locales))
|
| 51 |
|
| 52 | (define-record-type* <locale-definition> locale-definition
|
| 53 | make-locale-definition
|
| 54 | locale-definition?
|
| 55 | (name locale-definition-name) |
| 56 | (source locale-definition-source) |
| 57 | (charset locale-definition-charset |
| 58 | (default "UTF-8")))
|
| 59 |
|
| 60 | (define %not-dot
|
| 61 | (char-set-complement (char-set #\.)))
|
| 62 |
|
| 63 | (define (denormalize-codeset codeset)
|
| 64 | "Attempt to guess the \"real\" name of CODESET, a normalized codeset as
|
| 65 | defined in (info \"(libc) Using gettextized software\")."
|
| 66 | (cond ((string=? codeset "utf8")
|
| 67 | "UTF-8")
|
| 68 | ((string-prefix? "iso8859" codeset)
|
| 69 | (string-append "ISO-8859-" (string-drop codeset 7)))
|
| 70 | ((string=? codeset "eucjp")
|
| 71 | "EUC-JP")
|
| 72 | (else |
| 73 | codeset)))
|
| 74 |
|
| 75 | (define (locale-name->definition name)
|
| 76 | "Return a <locale-definition> corresponding to NAME, guessing the charset,
|
| 77 | or #f on failure."
|
| 78 | (match (string-tokenize name %not-dot)
|
| 79 | ((source charset)
|
| 80 | |
| 81 | |
| 82 | |
| 83 | (locale-definition (name name)
|
| 84 | (source source)
|
| 85 | (charset (denormalize-codeset charset))))
|
| 86 | (_
|
| 87 | #f)))
|
| 88 |
|
| 89 | (define* (single-locale-directory locales
|
| 90 | #:key (libc glibc))
|
| 91 | "Return a directory containing all of LOCALES for LIBC compiled.
|
| 92 |
|
| 93 | Because locale data formats are incompatible when switching from one libc to
|
| 94 | another, locale data is put in a sub-directory named after the 'version' field
|
| 95 | of LIBC."
|
| 96 | (define version
|
| 97 | (version-major+minor (package-version libc)))
|
| 98 |
|
| 99 | (define build
|
| 100 | (with-imported-modules (source-module-closure
|
| 101 | '((gnu build locale)))
|
| 102 | #~(begin
|
| 103 | (use-modules (gnu build locale))
|
| 104 |
|
| 105 | (mkdir #$output)
|
| 106 | (mkdir (string-append #$output "/" #$version))
|
| 107 |
|
| 108 | |
| 109 | (setenv "PATH"
|
| 110 | (string-append #+gzip "/bin:" #+libc "/bin"))
|
| 111 |
|
| 112 | (setvbuf (current-output-port) 'line)
|
| 113 | (setvbuf (current-error-port) 'line)
|
| 114 | (for-each (lambda (locale codeset name)
|
| 115 | (build-locale locale
|
| 116 | #:codeset codeset
|
| 117 | #:name name
|
| 118 | #:directory
|
| 119 | (string-append #$output "/" #$version)))
|
| 120 | '#$(map locale-definition-source locales)
|
| 121 | '#$(map locale-definition-charset locales)
|
| 122 | '#$(map locale-definition-name locales)))))
|
| 123 |
|
| 124 | (computed-file (string-append "locale-" version) build))
|
| 125 |
|
| 126 | (define* (locale-directory locales
|
| 127 | #:key (libcs %default-locale-libcs))
|
| 128 | "Return a locale directory containing all of LOCALES for each libc package
|
| 129 | listed in LIBCS.
|
| 130 |
|
| 131 | It is useful to list more than one libc when willing to support
|
| 132 | already-installed packages built against a different libc since the locale
|
| 133 | data format changes between libc versions."
|
| 134 | (match libcs
|
| 135 | ((libc)
|
| 136 | (single-locale-directory locales #:libc libc))
|
| 137 | ((libcs ..1)
|
| 138 | (let ((dirs (map (lambda (libc)
|
| 139 | (single-locale-directory locales #:libc libc))
|
| 140 | libcs)))
|
| 141 | (computed-file "locale-multiple-versions"
|
| 142 | (with-imported-modules '((guix build union))
|
| 143 | #~(begin
|
| 144 | (use-modules (guix build union))
|
| 145 | (union-build #$output (list #$@dirs))))
|
| 146 | #:options '(#:local-build? #t
|
| 147 | #:substitutable? #f))))))
|
| 148 |
|
| 149 | (define %default-locale-libcs
|
| 150 | |
| 151 | (list glibc glibc-2.39))
|
| 152 |
|
| 153 | (define %default-locale-definitions
|
| 154 | |
| 155 | |
| 156 | |
| 157 | |
| 158 | (letrec-syntax ((utf8-locale (syntax-rules ()
|
| 159 | ((_ name*)
|
| 160 | (locale-definition
|
| 161 | |
| 162 | |
| 163 | (name (string-append name* ".utf8"))
|
| 164 | (source name*)
|
| 165 | (charset "UTF-8")))))
|
| 166 | (utf8-locales (syntax-rules ()
|
| 167 | ((_ name ...)
|
| 168 | (list (utf8-locale name) ...)))))
|
| 169 | |
| 170 | |
| 171 | (utf8-locales "ar_DZ"
|
| 172 | "en_GB"
|
| 173 | "en_US"
|
| 174 | "es_AR"
|
| 175 | "es_ES"
|
| 176 | "fr_FR"
|
| 177 | "pt_BR"
|
| 178 | "pt_PT"
|
| 179 | "ru_RU"
|
| 180 | "zh_CN")))
|
| 181 |
|
| 182 |
|
| 183 | |
| 184 | |
| 185 | |
| 186 |
|
| 187 | (define* (glibc-supported-locales #:optional (glibc glibc))
|
| 188 | "Return a file-like object that contains a list of locale name/encoding
|
| 189 | pairs such as (\"oc_FR.UTF-8\" . \"UTF-8\"). Each pair corresponds to a
|
| 190 | locale supported by GLIBC."
|
| 191 | (define build
|
| 192 | (with-imported-modules (source-module-closure
|
| 193 | '((guix build gnu-build-system)
|
| 194 | (gnu build locale)))
|
| 195 | #~(begin
|
| 196 | (use-modules (guix build gnu-build-system)
|
| 197 | (gnu build locale)
|
| 198 | (ice-9 pretty-print))
|
| 199 |
|
| 200 | (define unpack
|
| 201 | (assq-ref %standard-phases 'unpack))
|
| 202 |
|
| 203 |
|
| 204 | (setenv "PATH"
|
| 205 | (string-append #+(file-append tar "/bin") ":"
|
| 206 | #+(file-append zstd "/bin") ":"
|
| 207 | #+(file-append gzip "/bin")))
|
| 208 | (unpack #:source #+(package-source glibc))
|
| 209 |
|
| 210 | (let ((locales (call-with-input-file "localedata/SUPPORTED"
|
| 211 | read-supported-locales)))
|
| 212 | (call-with-output-file #$output
|
| 213 | (lambda (port)
|
| 214 | (pretty-print locales port)))))))
|
| 215 |
|
| 216 | (computed-file "glibc-supported-locales.scm" build))
|
| 217 |
|
| 218 | |