로케일(Locale)에 관하여...

  1. 로케일(Locale)의 의미
  2.  세계 여러 나라들은 각자 다른 문화(언어, 날짜, 시간 등)을 갖고 있다. 프로그램의
    국제화(Internationalization, 줄여서 i18n)는 사용자로 하여금 프로그램 수행시
    로케일이란 것에 의해 입맛에 맞는 환경을 선택할 수 있도록 만든 것을 말한다.
    예를 들어 어떤 프로그램의 메시지가 여러가지 언어로 주어져 있는 경우 이중에
    어떤 언어의 것을 출력할 것인가를 사용자가 결정할 수 있는 것이다. 그것을 
    가능하게 해 주는 수단이 바로 로케일이다. 이것은 단순히 메시지 뿐만이 아니고
    숫자표현법, 날짜 또는 시간표현법 등 여러가지에 사용될 수 있다. 그것 각각을
    우리는 카테고리(category)라고 부른다. 카테고리에는 LC_COLLATE, LC_CTYPE,
    LC_MESSAGES, LC_MONETARY, LC_NUMERIC, LC_TIME 가 있다.
    

  3. 로케일 설정방법
  4.  로케일을 지원하는 프로그램의 실행 방식을 선택하기 위해서는 환경 변수 설정을
    이용한다. (카테고리 각각에 해당하는 환경변수는 카테고리 이름과 동일하다.)
    로케일 환경 변수에 관한 정보는 locale이란 명령으로 간단히 얻을 수 있다.
    % locale
    LANG=ko_KR.eucKR
    LC_CTYPE="ko_KR.eucKR"
    LC_NUMERIC="ko_KR.eucKR"
    LC_TIME="ko_KR.eucKR"
    LC_COLLATE="ko_KR.eucKR"
    LC_MONETARY="ko_KR.eucKR"
    LC_MESSAGES="ko_KR.eucKR"
    LC_ALL=
     위에서 ko_KR.eucKR은 로케일 값(locale name)이다. 일반적인 로케일 값의 형식은
    ll[_CC[.EEEE]][@dddd] 이다. ll은 언어(language)를 지정하는 소문자 두 글자 ISO
    639 language code, CC는 지역(territory)를 지정하는 대문자 두 글자 ISO 3166
    country code, EEEE는 코드셋(codeset)을 지정하는 문자셋(character set) 또는
    인코딩(encoding), dddd는 방언 등의 변종을 구별하기 위한 것(modifier)이다. []로
    표시된 내용은 안 쓸수도 있음을 의미한다. 예를 들면 en_US는 미국 영어권, en_CA는
    영어권 카나다, de_DE는 독일의 독일어, fr_FR는 프랑스의 프랑스어를 의미한다.
     아무 로케일도 설정하지 않았을 때 glibc에서의 기본 로케일은 C 또는 POSIX
    (glibc에서는 C 로케일의 alias) 로케일이다. 
    % locale -a
    라는 명령을 이용하면 이외에 사용 가능한 로케일의 이름들을 알 수 있다.
     다음은 여러가지 환경변수의 역할(카테고리의 경우에는 동시에 카테고리의 역할)에
    관한 설명이다.
    
      LANG : 모든 카테고리에 대한 로케일 설정을 위한 환경변수이다. 하지만 LC_*
    환경변수보다 우선 순위가 낮다. LC_ALL이 설정이 안 되어 있고 LC_* 값들이 설정이
    따로 설정이 않된 경우 LANG을 변화시키면 LC_ALL을 제외한 로케일 카테고리들의
    값이 변경되지만 LC_ALL이 설정 되어 있는 경우 LANG의 변화는 로케일 카테고리들의
    값에 영향을 주지 않는다.
      LC_CTYPE : 문자 분류(알파벳, 숫자, 한글 또는 소문자, 대문자 등등), 변환,
    대소문자 비교을 위한 로케일 설정을 의미한다. 이것은 예를 들어 fgetwc(), is*(),
    isw*(), mblen(), mbtowc(), wcstombs() 등의 함수에 영향을 줄 수 있다.
      LC_COLLATE : 스트링(string)의 정렬 순서(sort order 또는 collation)를 위한
    로케일 설정을 위해 사용된다. 이것은 예를 들어 strcoll(), wcscoll(), strxfrm()
    등의 함수에 영향을 줄 수 있다.
      LC_MESSAGES : 메시지 표현을 위한 로케일 설정. 메시지의 국제화를 위한
    catopen(), gettext() 등의 함수에 영향을 줄 수 있다.
      LC_NUMERIC : 금액이 아닌 숫자 표현(천단위, 소수점, 숫자 그룹핑 등)을 위한
    로케일 설정. 예를 들어 strtod(), atof().
      LC_MONETARY : 금액 표현(천단위 구분 문자, 소수점 문자, 금액 표시 문자, 그 
    위치 등)을 위한 로케일 설정. 예를 들어 strfmon().
      LC_TIME : 시간과 날짜의 표현(년, 월, 일에 대한 명칭 등)을 위한 로케일 설정
    예를 들어 strftime(), strptime().
      LC_ALL : 모든 카테고리에 대한 로케일 설정을 위한 환경변수이다. 위의 LC_* 및
    LANG의 어떤 것보다 우선 순위가 높다. 그리고 LC_ALL을 설정하면 다른 로케일
    카테고리의 값들이 LC_ALL의 값의 변경되고 LC_ALL설정을 없애면 다른 로케일
    카테고리의 값들은 이전값을 유지한다.
      LANGUAGE : 로케일의 다중 설정을 위해 gettext에서 사용되는 GNU extension 
    환경변수로 LC_ALL보다도 우선순위가 높다. 로케일들은 구분문자 : 을 이용하여
    우선순위가 높은 순대로 나열된다. 예를 들어 LANGUAGE=en_US:ko_KR
      LINGUAS : gettext를 사용하는 프로그램 설치시 지정한 언어들의 메시지만을
    설치하기 위한 환경변수. 구분 문자는 스페이스이다. 예를 들어 LINGUAS="ko ja"
    

  5. 로케일을 지원하기 위한 방법 및 작동 원리
  6.  로케일을 제대로 지원하는 프로그램을 작성하기 위해서는 setlocale()함수를
    이용하여 로케일을 설정하고 확인하여야 한다. setlocale()함수는 헤더 파일
    locale.h 에 정의되어 있으며 그 프로토타입은 다음과 같다.
     char *setlocale (int category, const char *locale);
    이 함수의 역할은 카테고리 category에 대해 로케일 locale을 설정하고 (물론, 사용
    가능한 로케일인 경우), 설정된 로케일값을 리턴하는 것이다.
     locale 부분에 ""을 넣은 다음과 같은 예는
     setlocale (LC_ALL, "");
    적당한 환경변수를 참조하여 로케일을 설정하고 그 값을 리턴한다. 환경변수를
    참조하는 우선순위는 위에서 설명한대로 LC_ALL, 그외 카테고리, LANG변수 순이고,
    변수값을 알아내면 locale.alias(예를 들어, /usr/share/locale/)를 참조한 후
    뒤에서부터 @ . _ 을 단위로 순서대로 잘라가며 사용가능한 로케일을 찾아낸다.
     인수 locale 부분에 NULL을 넣은 다음예는 
     locale = setlocale (LC_ALL, NULL);
    로케일 값을 변경시키지 않고 단지 카테고리에 관한 현재 로케일값을 알아내고자 
    하기 위해 그 리턴값을 사용하는 예이다.
     다음은 함수 setlocale()을 사용하여 임시로 로케일로 변경하는 예이다. (glibc
    manual에 있는 예)
    
         #include <stddef.h>
         #include <locale.h>
         #include <stdlib.h>
         #include <string.h>
         
         void
         with_other_locale (char *new_locale,
                            void (*subroutine) (int),
                            int argument)
         {
           char *old_locale, *saved_locale;
         
           /* 현재 로케일명을 알아낸다. */
           old_locale = setlocale (LC_ALL, NULL);
         
           /* setlocale()의 재호출 의해 변경될 것을 대비해 로케일 이름을 미리 복사해 둔다. */
           saved_locale = strdup (old_locale);
           if (saved_locale == NULL)
             fatal ("Out of memory");
         
           /* 로케일을 변경하고 subroutine을 수행한다. */
           setlocale (LC_ALL, new_locale);
           (*subroutine) (argument);
         
           /* 원래의 로케일로 복귀한다. */
           setlocale (LC_ALL, saved_locale);
           free (saved_locale);
         }
    
     다음은 로케일을 이용하여 날짜/시간을 출력하는 프로그램의 예이다.
    	#include <stdio.h>
    	#include <locale.h>
    	#include <time.h>
    
    	int main(void)
    	{
    		time_t now;
    		struct tm *l_time;
    		char string[256];
    
    		/* 환경변수로부터 시간 관련 로케일을 결정한다. */
    		setlocale(LC_TIME, "");
    
    		/* calendar 시간을 now라는 변수에 저장. 
    		 * 그 값은 1970년 1월 1일 이후부터 지금까지의 초단위 시간 */
    		now = time((time_t *)NULL);
    
    		/* calendar 시간의 다른 유용한 형태를 l_time변수에 저장 */
    		l_time = localtime(&now);
    
    		/* 우리가 원하는 포맷의 시간 포맷을 string이라는 변수에 저장 */
    		strftime(string, sizeof string, "%c", l_time);
    
    		/* 출력 */
    	 	printf("%s\n", string);
    
    		return 0;
    	}
     다음은 위의 파일을 time_test.c라고 저장하고 컴파일하여 c쉘에서 시험하는 
    예이다.
    % gcc -o time_test time_test.c
    % setenv LANG ko_KR.eucKR
    % ./time_test
    2000년 01월 12일 수요일 오후 10시 26분 56초
    % setenv LANG C
    % ./time_test
    Wed Jan 12 22:27:22 2000
    


<주 페이지로> <한단계 위로>
Copyright 2000.8 by HyunChul Kim

최근 수정일: 12/08/00