| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 |
|
| 19 | (define-module (gnu build locale)
|
| 20 | #:use-module (guix build utils)
|
| 21 | #:use-module (srfi srfi-1)
|
| 22 | #:use-module (ice-9 rdelim)
|
| 23 | #:use-module (ice-9 match)
|
| 24 | #:use-module (ice-9 regex)
|
| 25 | #:export (build-locale
|
| 26 | normalize-codeset
|
| 27 | locale->name+codeset
|
| 28 | read-supported-locales))
|
| 29 |
|
| 30 | (define locale-rx
|
| 31 | |
| 32 | (make-regexp
|
| 33 | "^[[:space:]]*([[:graph:]]+)/([[:graph:]]+)[[:space:]]*\\\\$"))
|
| 34 |
|
| 35 | (define (read-supported-locales port)
|
| 36 | "Read the 'localedata/SUPPORTED' file from PORT. That file is actually a
|
| 37 | makefile snippet, with one locale per line, and a header that can be
|
| 38 | discarded."
|
| 39 | (let loop ((locales '()))
|
| 40 | (define line
|
| 41 | (read-line port))
|
| 42 |
|
| 43 | (cond ((eof-object? line)
|
| 44 | (reverse locales))
|
| 45 | ((string-prefix? "#" (string-trim line)) |
| 46 | (loop locales))
|
| 47 | ((string-contains line "=") |
| 48 | (loop locales))
|
| 49 | (else
|
| 50 | (match (regexp-exec locale-rx line)
|
| 51 | (#f
|
| 52 | (loop locales))
|
| 53 | (m
|
| 54 | (loop (alist-cons (match:substring m 1)
|
| 55 | (match:substring m 2)
|
| 56 | locales))))))))
|
| 57 |
|
| 58 | (define (normalize-codeset codeset)
|
| 59 | "Compute the \"normalized\" variant of CODESET."
|
| 60 | |
| 61 | |
| 62 | (letrec-syntax ((-> (syntax-rules ()
|
| 63 | ((_ proc value)
|
| 64 | (proc value))
|
| 65 | ((_ proc rest ...)
|
| 66 | (proc (-> rest ...))))))
|
| 67 | (-> (lambda (str)
|
| 68 | (if (string-every char-set:digit str)
|
| 69 | (string-append "iso" str)
|
| 70 | str))
|
| 71 | string-downcase
|
| 72 | (lambda (str)
|
| 73 | (string-filter char-set:letter+digit str))
|
| 74 | codeset)))
|
| 75 |
|
| 76 | (define* (build-locale locale
|
| 77 | #:key
|
| 78 | (localedef "localedef")
|
| 79 | (directory ".")
|
| 80 | (codeset "UTF-8")
|
| 81 | (name (string-append locale "." codeset)))
|
| 82 | "Compute locale data for LOCALE and CODESET--e.g., \"en_US\" and
|
| 83 | \"UTF-8\"--with LOCALEDEF, and store it in DIRECTORY under NAME."
|
| 84 | (format #t "building locale '~a'...~%" name)
|
| 85 | (invoke localedef "--no-archive" "--prefix" directory
|
| 86 | "-i" locale "-f" codeset
|
| 87 | (string-append directory "/" name)))
|
| 88 |
|
| 89 | (define (locale->name+codeset locale)
|
| 90 | "Split a locale name such as \"[email protected]\" into two values: the
|
| 91 | language/territory/modifier part, and the codeset."
|
| 92 | (match (string-rindex locale #\.)
|
| 93 | (#f (values locale #f))
|
| 94 | (dot (values (string-take locale dot)
|
| 95 | (string-drop locale (+ dot 1))))))
|