· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Linuxdoc Sgml/Locales

Locales mini-HOWTO

Locales mini-HOWTO

Peeter Joot, joot@ecf.toronto.edu

v1.3, 1996년 6월 6일 이 만 용 geoman@nownuri.net
이 문서는 리눅스에서 locale 를 쓰기 위해 설정하는 방법을 설명한다.

1. 소개

여기서 나는 localdef 를 인스톨하기 위하여 무엇을 했으며 어떻게 locale을 컴파 일했는지 그리고 그 경험에 대해서 이야기식으로 진행하려고 한다. 나는 단지 재미로 이 일에 뛰어들었고 다른 사람들도 이 일에 흥미를 가질 것이 라고 생각했다. 일단 설정만 되면 여러분의 선택한 로케일을 가지고 NLS 지원의 어플리케이션을 사용할 수 있다. 조금 있으면 로케일 지원은 표준 배포판의 일부 가 될 것이고 이 미니 하우투 문서에도 많은 내용이 추가되리라 본다.

2. 도대체 로케일(locale)이란 무엇인가?

로케일은 여러분이 여러분의 프로그램 속으로 하드코딩을 해서는 안되는 언어/문 화 관련의 사항을 다룬다. 만약 다양한 로케일을 설치해두었다면 다음 환경 변수 설정을 통하여 로케일을 지원하는 프로그램의 실행 방식을 선택할 수 있다.

기본 로케일은 C 또는 POSIX 이며 libc 에 하드코딩되어 있다.

LANG

이 세팅을 통해 로케일을 설정한다. 하지만 LC_xxxx 환경 변수에 의해 변화될 수 있다.

LC_COLLATE

정렬 순서

LC_CTYPE

문자 정의, 대문자, 소문자,... 이들은 toupper, tolower, islower, isdigit 등의 함수에 사용된다.

LC_MONETARY

금액을 표현하는 형식 정보를 포함하고 있다. 천단위를 구분하는 문자, 소수점 문자, 그리고 금액 표시 문자, 그 위치 등의 정보를 제시한다.

LC_NUMERIC

숫자를 표현함에 있어, 천단위, 소수점, 숫자 그룹핑을 다룬다.

LC_TIME

시간과 날짜의 표현형식을 지정한다. 주와 달에 대한 명칭과 약어를 다룬 다.

LC_MESSAGES

예/아니오 표현

LC_ALL

로케일을 지정한다. 하지만 다른 LC_xxxx 으로 변화될 수 있다. 여기 몇 가지 로케일에 대한 예가 있다.

en_CA

영어권 카나다

en_US

미국 영어권

de_DE

독일의 독일어

fr_FR

프랑스의 프랑스어

여러분이 프로그램을 짜는데 있어 그것이 국제적으로 사용되기 위해서는 로케일 을 이용해야 한다. 가장 중요한 이유 중 하나는 모든 사람이 여러분과 같은 문자 를 사용하지는 않는다는 사실이다. 여러분의 프로그램에서 다음과 같은 식으로 사용하지 말라.

/* check for alphabetic characters */ if ( (( c >= 'a') && ( c <= 'z' )) || (( c >= 'A') && ( c <= 'Z' )) ) { ... }

여러분이 이렇게 모든 화일을 ASCII 화일이라고만 가정하고 만든다면 사용자의 로케일에 따른 코드 페이지 정의를 존중하지 않게 되는 것이다.

예를 들어 독일어 환경에서 쓰이는 움라우프 문자 등이 제외된다고 말할 수 있다. 여러분은 대신 isalpha() 과 같은 로케일 인식 함수를 사용해야 한다. 여러분이 US-ASCII 알파벳 문자만을 요구한다 할 지라도 여전히 isalpha() 함수를 사용하기 바란다. 하지만 우선 setlocalte(LC_TYPE,"C")라고 하든지 아니면 LANG, LC_TYPE, LC_ALL 등의 환경 변수를 "C"로 설정하면 된다. 로케일은 상당한 유연성을 제공하며 프로그래머들이 ASCII 기반의 C 프로그램을 잘못 만들어왔다고 생각한다.

예를 들어 여러분은 문자의 코드 위치를 가정할 수 없다. 여러분은 A 라는 문자의 코드 위치를 0x41 이 아닌 0xC1 으로 정의하는 문자표 화일을 만들 수도 있다. 이것은 메인프레임에서 사용된는 IBM 코드 페이지 37에서의 A 가 갖는 위치이다. 그리고 전자는 바로 US-ASCII, iso8859-x 등에서 사용되고 있는 방식이다. 기본적인 아이디어는 서로 다른 사람들이 다른 언어를 사용하며 정렬 순서도 다르 고 다른 코드 페이지를 사용하며 다른 나라에 살고 있다는 사실로부터 나온다. 바로 로케일과 로케인 인식 프로그램이 그러한 문제에 대한 해결책을 제시하고 있 다. 많은 작업이 필요한 것은 아니고 단지 프로그램 작성시 약간 다른 사고방식을 요구한다.

3. 주의 사항

[] 내 머신에서 로케일을 설정하기 위하여 약간의 업그레이드가 필요했다. ftp.tu-clausthal.de:/pub/linux/SLT/nls 에는 a.out 버전의 로케일과 local- def( nlsutils-0.5.tar.gz 화일 안에 )이 들어있다. ELF 시스템이 아니거나 ELF 를 사용하지 않으려는 사람에게 유용하다. 다른 곳에 아마도 nls 유틸 패키지가 있을 것이다. 하지만 찾지 못했다. 독립적인 로케일, localdef가 있는지 모르겠으며 그러한 libc 를 가지고 있는지도 모르겠다. 이 하우투 문서는 본인이 libc 등을 업그레이드한 개인적인 경험일 분이다. 여러분이 이 작업을 하려면 본인처럼 ELF 시스템을 운영하거나 ELF 시스템으 로 업그레이드해야 할 것이다.

  • 본인이 한 시스템 업그레이드는 a.out 에서 ELF 업그레이드하기 위해 필요한 것들이었다. ELF 시스템이 아니라면 여러분은 일단 최근 ELF HOWTO 문서를 구 해야 할 것이다. 상당히 좋은 문서이며 libc, ld.so, 그리고 다른 ELF 시스템 인스톨, 업그레이드에 대한 많은 지식을 전해줄 것이다.
  • 여러분이 인스톨하는 모든 것에 대해서 릴리즈 노트나 README 를 읽어보라. 여기서 본인이 말한 바를 제대로 이해하지 못하거나 그로 인해 시스템을 망쳤 다고 본인을 원망하지는 말기 바란다.
  • 새로운 libc, ld.so 를 잘못 설치하는 경우 부팅 자체가 안될 수 있다. 일단은 부트 디스크를 하나 가지고 중요한 자료는 백업을 해두는 것이 좋다.

4. 여러분에게 필요한 사항

몇 개의 자료를 다운로드받을 필요가 있다. locale 소스 화일을 제외한 대부분은 sunsite.unc.edu, tsx-11.mit.edu, 또는 로컬 미러 사이트에서 구할 수 있다.

[] 로케일, 문자표 소스 - localdef 를 가지고 컴파일하게 될 것이다.
[] libc-5.2.18.bin.tar.gz --- ELF C 공유 라이브러리와 수학 라이브러리
[] libc-5.2.18.tar.gz --- ELF 라이브러리에 대한 소스 코드. localdef 를 컴파
     일하기 위해서는 바로 이 화일이 필요하다.
[] make-3.74.tar.gz -- dirent 버그를 고친 버전이 필요하다.
[] release.libc-5.2.18 --- make 에 대한 패치를 포함한 릴리즈 노트
[] ld.so-1.7.12+ -- 동적 링커
[] ELF gcc-2.7.2+ --- 컴파일에 사용
[] ELF 커널 1.1.92+ 또는 ELF 커널 1.3.40+ -- 컴파일에 사용
[] binutils 2.6.0.2+ --- 컴파일에 사용

로케일 소스를 얻을 수 있는 곳은 많다. 공개 로케일과 문자표를 다음과 같은 사이트에서 얻을 수 있었다. dkuug.dk:/i18n/WG15-collection/locales < ftp.dkuug.dk/i18n/WG15-collection/locales> dkuug.dk:/i18n/WG15-collection/charmaps < ftp.dkuug.dk/i18n/WG15-collection/charmaps>

5. 모든 것을 인스톨하기

이것 모두가 본인이 인스톨한 것이다. 본인은 이미 ELF 시스템( 컴파일러, 커널 ) 을 가지고 있었다.

  1. 우선은 tar xvzf binutils-2.6.0.2.bin.tar.gz -C / 하여 바이너리 유틸리티를 설치하였다.
  2. 다음으로는 동적 링커를 설치하였다. tar zxf ld.so-1.7.12.tar.gz -C /usr/src cd /usr/src/ld.so-1.7.12 sh instldso.sh
  3. . 그 다음 나는 lib 를 설치하였다. 자세한 설명은 release.libc-5.2.18 을 보기 바란다. rm -f /usr/lib/libc.so /usr/lib/libm.so rm -f /usr/include/iolibio.h /usr/include/iostdio.h rm -f /usr/include/ld_so_config.h /usr/include/localeinfo.h rm -rf /usr/include/netinet /usr/include/net /usr/include/pthread tar -xzf libc-5.2.18.bin.tar.gz -C /
  4. 새로운 공유 라이브러리의 위치를 알리기 위하여 ldconfig -v 를 실행
  5. make 과 다른 프로그램에 대한 버그 패치가 libc 에 들어있었다. 여기서 나는 make 를 다시 컴파일하여 인스톨하였다. tar zxf make-3.74.tar.gz -C /usr/src cd /usr/src/make-3.74 patch < /whereever_you_put_it/release.libc-5.2.18 configure --prefix=/usr sh build.sh ../make install cd .. rm -rf make-2.74
  6. 여기서 localdef 를 컴파일하여 설치하였다. mkdir /usr/src/libc tar zxf libc-5.2.18.tar.gz -C /usr/src/libc cd /usr/src/libc cd include ln -s /usr/src/linux/include/asm . ln -s /usr/src/linux/include/linux . cd ../libc ./configure # 이 두 가지 make 과정이 필요한지는 모르겠으나 안전하게 해두도록 하자. make clean ; make depend cd locale make programs mv localedef /usr/local/bin mv locale /usr/local/bin
  7. localdef 가 찾을 수 있는 곳에 문자표를 설치한다. dkuug.dk FTP 사이트로 부터 charmaps.tar, locales.tar 라는 화일로 구한 것을 사용하였다.
tar xf charmaps.tar -C /tmp mkdir /usr/share/nls mkdir /usr/share/nls/charmap mkdir /usr/share/locale mv /tmp/charmaps/* /usr/share/nls/charmap rm -rf /tmp/charmaps tar xf locales.tar -C /usr/share # put these where you want.


# 어떤 로케일 소스는 `copy'를 사용하며 따라서 다른 로케일에 대한
  # 의존성을 가진다. 본인은 grep, cut, sed 를 사용하여 makefile 을 
  # 이렇게 해주면 /usr/share/locale 디렉토리에 모든 로케일 객체를
  # 만들어 줄 것이다.
  #
  localedef -ci locales/en_DK -f ISO_8859-1:1987 en_DK
  localedef -ci locales/sv_SE -f ISO_8859-1:1987 sv_SE
  localedef -ci locales/fi_FI -f ISO_8859-1:1987 fi_FI
  localedef -ci locales/sv_FI -f ISO_8859-1:1987 sv_FI
  localedef -ci locales/ro_RO -f ISO_8859-1:1987 ro_RO
  localedef -ci locales/pt_PT -f ISO_8859-1:1987 pt_PT
  localedef -ci locales/no_NO -f ISO_8859-1:1987 no_NO
  localedef -ci locales/nl_NL -f ISO_8859-1:1987 nl_NL
  localedef -ci locales/fr_BE -f ISO_8859-1:1987 fr_BE
  localedef -ci locales/nl_BE -f ISO_8859-1:1987 nl_BE
  localedef -ci locales/da_DK -f ISO_8859-1:1987 da_DK
  localedef -ci locales/kl_GL -f ISO_8859-1:1987 kl_GL
  localedef -ci locales/it_IT -f ISO_8859-1:1987 it_IT
  localedef -ci locales/is_IS -f ISO_8859-1:1987 is_IS
  localedef -ci locales/fr_LU -f ISO_8859-1:1987 fr_LU
  localedef -ci locales/fr_FR -f ISO_8859-1:1987 fr_FR
  localedef -ci locales/de_DE -f ISO_8859-1:1987 de_DE
  localedef -ci locales/de_CH -f ISO_8859-1:1987 de_CH
  localedef -ci locales/fr_CH -f ISO_8859-1:1987 fr_CH
  localedef -ci locales/en_CA -f ISO_8859-1:1987 en_CA
  localedef -ci locales/fr_CA -f ISO_8859-1:1987 fr_CA
  localedef -ci locales/fo_FO -f ISO_8859-1:1987 fo_FO
  localedef -ci locales/et_EE -f ISO_8859-1:1987 et_EE
  localedef -ci locales/es_ES -f ISO_8859-1:1987 es_ES
  localedef -ci locales/en_US -f ISO_8859-1:1987 en_US
  localedef -ci locales/en_GB -f ISO_8859-1:1987 en_GB
  localedef -ci locales/en_IE -f ISO_8859-1:1987 en_IE
  localedef -ci locales/de_LU -f ISO_8859-1:1987 de_LU
  localedef -ci locales/de_BE -f ISO_8859-1:1987 de_BE
  localedef -ci locales/de_AT -f ISO_8859-1:1987 de_AT
  localedef -ci locales/sl_SI -f ISO_8859-2:1987 sl_SI
  localedef -ci locales/ru_RU -f ISO_8859-5:1988 ru_RU
  localedef -ci locales/pl_PL -f ISO_8859-2:1987 pl_PL
  localedef -ci locales/lv_LV -f BALTIC lv_LV
  localedef -ci locales/lt_LT -f BALTIC lt_LT
  localedef -ci locales/iw_IL -f ISO_8859-8:1988 iw_IL
  localedef -ci locales/hu_HU -f ISO_8859-2:1987 hu_HU
  localedef -ci locales/hr_HR -f ISO_8859-4:1988 hr_HR
  localedef -ci locales/gr_GR -f ISO_8859-7:1987 gr_GR

6. 이제 무엇을 할 것인가?

이렇게 설치하고 난 후 여러분은 로케일을 사용할 수 있게 된다. 여기 아주 간단한 예가 있다.


     /* test.c : 로케일이 로딩되고 사용되는지 테스트 */
       #include <locale.h>
       #include <stdio.h>
       #include <time.h>
     main(){
               time_t t;
               struct tm * _t;
               char buf[256];
             time(&t);
               _t = gmtime(&t);
             setlocale(LC_TIME,"");
               strftime(buf,256,"%c",_t);
             printf("%s\n",buf);
       }

로케일 프로그램을 사용하여 하여 현재 로케일 환경변수가 어떤지 알아볼 수 있다.
     $ # 서로 다른 몇 가지 로케일 설정을 하여 위 프로그램을 수행시킨다.
       $ gcc -s -o Test test.c
       $ # 로케일이 무엇인지 알아본다.
       $ locale
       LANG=POSIX
       LC_COLLATE="POSIX"
       LC_CTYPE="POSIX"
       LC_MONETARY="POSIX"
       LC_NUMERIC="POSIX"
       LC_TIME="POSIX"
       LC_MESSAGES="POSIX"
       LC_ALL=
       $ # 지루하기 짝이 없는 C 로케일을 사용하고 있다. -_-
       $ # 영어권 카나다로 바꾸어보자.
       $ export LC_TIME=en_CA
       $ Test
       Sat 23 Mar 1996 07:51:49 PM
       $ # 이번에는 프랑스어권 카다나로 바꾸어보자.
       $ export LC_TIME=fr_CA
       $ Test
       sam 23 mar 1996 19:55:27

7. catopen 버그 고치기

로케일을 인스톨하게 되면 리눅스 libc 에 있는 catopen 명령에 있는 버그(기능?) 을 고치게 된다. 메세지 목록을 사용하는 프로그램을 만든 후 독일어 목록을

/home/peeter/catalogs/de_DE 에 만들어 넣으라.

de_DE 로케일을 인스톨하기 전에 다음을 수행한다.

export LC_MESSAGES=de_DE export NLSPATH=/home/peeter/catalogs/%L/%N.cat:$NLSPATH 독일어 메세지는 열리지 않고 catget 의 기본 메세지가 사용된다.

이 이유는 catopen 이 올바른 메세지 범주를 얻어내기 위해 setlocale 를 호출하 하는데 setlocale 은 환경변수가 제대로 세팅되어 있음에도 불구하고 실패하 기 때문이다.

catopen 은 NLSPATH의 모든 "%L"에 대하여 C 로 교체하려고 한다. 로케일을 설치하지 않아도 여러분의 메세지 목록을 사용할 수는 있다. 하지만 NLSPATH를 정확히 다음과 같이 명시해주어야 할 것이다.

export NLSPATH=/home/peeter/catalogs/de_DE/%N.cat:$NLSPATH 하지만 이렇게 되면 로케일 범주에 대한 환경변수를 사용할 필요성 자체가 사라 지는 것이다.

8. 질문과 답

이 섹션은 지금으로서는 FAQ 라고 할 수 없겠지만 앞으로 FAQ 로 자라날 것이다.

8.1 msgcat 질문

나는 리눅스 사용자이며 다음과 같은 시험 프로그램을 만들었다.


       #include <stdio.h>
       #include <locale.h>
       #include <features.h>
       #include <nl_types.h>
     main(int argc, char ** argv)
       {
               nl_catd catd;
             setlocale(LC_MESSAGES, "");
               catd = catopen("msg", MCLoadBySet);
               fprintf(stderr,catgets(catd, 1, 1, "locale message fail\n"));
               catclose(catd);
       }

$ msg.m $set 1 1 locale message pass\n

If I use absolute path in catopen like

내가 만약 catopen("/etc/locale/msg.cat",MCLoadBySet); 와 같이 절대 경로를 사용하면 옳은 결과를 얻어내지만 위처럼 사용하면 결과값 -1 즉 실패하게 된다.

8.2 msgcat 답변

이 질문은 지난 섹션에서 답변이 된 문제이긴 하지만 몇 가지 부가적인 정보를 말할 기회라고 생각한다.

여러분의 메세지 목록을 넣을 수 있는 곳은 아주 많다. 환경변수에서 NLSPATH를 명시적으로 설정하지 않았다 하더라도 다음과 같이 libc 에 정의되어 있다.


     $ strings /lib/libc.so.5.2.18 | grep locale | grep %L
       /etc/locale/%L/%N.cat:/usr/lib/locale/%L/%N.cat:/usr
       /lib/locale/%N/%L:/usr/share/locale/%L/%N.cat:/usr/
       local/share/locale/%L/%N.cat

따라서 다음 중 하나를 세팅해주면 :
     $ export LC_MESSAGES=en_CA
       $ export LC_ALL=en_CA
       $ export LANG=en_CA

위에서 보여진 NLSPATH와 환경변수에 의거하여 catopen("msg", MCLoadBySet); 는
  다음 디렉토리 중 하나에 메세지 목록이 있는 경우 작동하게 된다.
     /etc/locale/en_CA/msg.cat
       /usr/lib/locale/en_CA/msg.cat
       /usr/lib/locale/msg/en_CA
       /usr/share/locale/en_CA/msg.cat
       /usr/local/share/locale/en_CA/msg.cat

This, however, will not work if you don't have the en_CA locale

하지만 여러분이 en_CA 로케일을 설치하지 않았다면 제대로 동작하지 않는다. 왜냐하면 setlocale 가 실패하여 catopen 루틴의 %L을 en_CA 가 아닌 C 로 교체 하기 때문이다.

9. 끝내는 말

자, 이것이 전부다. 이 문서가 여러분에게 약간이라고 도움이 되었기를 바란다. 로케일 인식 프로그램을 짜는데 대한 다른 정보를 찾을 수 있는 곳이 많이 있을 것이다. libc에 대한 info 페이지에도 약간의 정보가 있고 맨페이지에도 있다. 약간 웹을 돌아다니다 보면 많은 정보를 얻을 수 있으리라 본다. 국제화된 프로그램에 대한 좋은 정보 원천을 찾게 되고 본인도 알기 바란다면, 여기다 적어놓기로 하겠다.




sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2003-08-10 11:52:30
Processing time 0.0028 sec