Common Lisp에서 다국어 대응을 위해 gettext 사용

12579 단어 ECLcommon-lispGettext

Common Lisp에서 다국어 대응을 위해 gettext 사용



소개



평소 Wordpress에서, po라든지 mo라든지를 볼 수 있지만, 제대로 마주본 적이 없었기 때문에 Common Lisp의 연습이 되면, gettext를 사용해 보기로 했습니다.

환경



  • 데비안 GNU/리눅스 10.2

  • ECL 16.1.3

  • gettext 0.19.8
  • cl-gettext

  • poedit 2.2.1

  • 이번 내용의 소스 코드



    설치



    먼저 apt에서 필요한 도구를 설치해 둡니다.
    $ sudo apt install gettext poedit
    

    Poedit는 번역 파일을 만드는 소프트웨어입니다.

    프로젝트 만들기



    htps : // 기트 b. 코 m/후. Moon s tone / Dee ps Pase 을 사용하여 프로젝트의 병아리를 생성합니다.
    $ deepspace -t project -o create -n locale-sample
    $ cd locale-sample
    $ tree
    .
    ├── build
    ├── doc
    ├── lib
    ├── locale-sample-test.asd
    ├── locale-sample.asd
    ├── resources
    │   ├── data
    │   ├── images
    │   └── sounds
    ├── src
    │   ├── c
    │   └── lisp
    │       ├── locale-sample.lisp
    │       └── package.lisp
    └── test
        ├── c
        └── lisp
            ├── locale-sample-test.lisp
            └── package.lisp
    
    14 directories, 8 files
    

    로케일에 대한 파일을 저장하기 위해,
    $ mkdir -p resources/locale
    

    에서 디렉토리를 먼저 만듭니다.

    Quicklisp 등에서 cl-gettext를 도입하고 ASD 파일을 다음과 같이 작성합니다.

    locale-sample.asd
    (asdf:defsystem :locale-sample
      :serial t
      :pathname "src/lisp"
      :components ((:file "package")
                   (:file "locale-sample"))
      :depends-on (:asdf :alexandria :gettext))
    

    그 후, src/lisp/package.lisp 에 이하의 내용을 기술합니다.

    src/lisp/package.lisp
    (in-package :cl-user)
    (defpackage :locale-sample
      (:use :cl :gettext)
      (:export :main))
    

    이번에 gettext를 시도하기 위해 작성한 코드는 다음과 같습니다.

    src/lisp/locale-sample.lisp
    (in-package :locale-sample)
    
    (setup-gettext :locale-sample "locale-sample")
    (preload-catalogs #.(asdf:system-relative-pathname :locale-sample "resources/locale/"))
    
    (defun replace-all (string part replacement &key (test #'char=))
        (with-output-to-string (out)
          (loop with part-length = (length part)
                for old-pos = 0 then (+ pos part-length)
                for pos = (search part string
                                  :start2 old-pos
                                  :test test)
                do (write-string string out
                                 :start old-pos
                                 :end (or pos (length string)))
                when pos do (write-string replacement out)
             while pos)))
    
    (defparameter *labels* (make-hash-table))
    (dolist (label `(,(_ "Dog")
                      ,(_ "Cat")
                      ,(_ "Penguin")))
    
      (let ((key (alexandria:make-keyword (string-upcase (replace-all label " " "-")))))
        (setf (gethash key *labels*) label)))
    
    (defun main ()
      (setf *current-locale* "ja")
      (format t "-------------------------------~%")
      (format t "~A~%" (_ (gethash :dog *labels*)))
      (format t "~A~%" (_ (gethash :cat *labels*)))
      (format t "~A~%" (_ (gethash :penguin *labels*))))
    

    초기화 및 리소스 위치 지정


    setup-gettext 에 의해 gettext의 초기화를 실시합니다. 그 후, 나중에 작성하는 번역 파일의 위치를 ​​resources/locale/ 이하에 있는 형태로 지정합니다.
    (setup-gettext :locale-sample "locale-sample")
    (preload-catalogs #.(asdf:system-relative-pathname :locale-sample "resources/locale/"))
    

    텍스트 목록 준비



    Poedit는 소스 코드에서 특정 텍스트를 추출할 수 있으므로 먼저 번역할 텍스트 목록을 만듭니다. 여기에서는, *labels* 을 해시 테이블에 등록합니다.
    (defparameter *labels* (make-hash-table))
    (dolist (label `(,(_ "Dog")
                      ,(_ "Cat")
                      ,(_ "Penguin")))
    
      (let ((key (alexandria:make-keyword (string-upcase (replace-all label " " "-")))))
        (setf (gethash key *labels*) label)))
    

    키의 이름은 자동으로 만들려고합니다. 캐릭터 라인 정보를 모두 대문자로 변경해, 스페이스가 있는 경우는 하이픈으로 연결하도록(듯이) 했습니다. 이제 Dog:dog 로 액세스할 수 있으며 Iron Man:iron-man 로 액세스할 수 있습니다.

    이런 식으로 Poedit 소스에서 추출하는 기능을 사용하면 세 단어가 목록에 표시되므로 해당 일본어 텍스트를 입력하고 저장합니다. mo, po 파일은 /resources/locale/ja/LC_MESSAGES 아래에 locale-sample.mo , locale-sample.po 라는 이름으로 저장합니다.



    로케일 설정



    다음 부분에서 로케일을 일본어로 변경하고 있습니다.
    (setf *current-locale* "ja")
    

    실행


    ;;; End of Pass 1.-------------------------------
    犬
    猫
    ペンギン
    

    좋은 웹페이지 즐겨찾기