Linux 2006/09/08 23:28
블로그 > 도시의 매연 위 푸른하늘... http://blog.naver.com/savemyface/120006480613 | |
1. 로케일(Locale)의 의미 세계 여러 나라들은 각자 다른 문화(언어, 날짜, 시간 등)을 갖고 있다. 프로그램의국제화(Internationalization, 줄여서 i18n)는 사용자로 하여금 프로그램 수행시 로케일이란 것에 의해 입맛에 맞는 환경을 선택할 수 있도록 만든 것을 말한다. 예를 들어 어떤 프로그램의 메시지가 여러가지 언어로 주어져 있는 경우 이중에 어떤 언어의 것을 출력할 것인가를 사용자가 결정할 수 있는 것이다. 그것을 가능하게 해 주는 수단이 바로 로케일이다. 이것은 단순히 메시지 뿐만이 아니고 숫자표현법, 날짜 또는 시간표현법 등 여러가지에 사용될 수 있다. 그것 각각을우리는 카테고리(category)라고 부른다. 카테고리에는 LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC, LC_TIME 가 있다. 2. 로케일 설정방법 로케일을 지원하는 프로그램의 실행 방식을 선택하기 위해서는 환경 변수 설정을 이용한다. (카테고리 각각에 해당하는 환경변수는 카테고리 이름과 동일하다.) 로케일 환경 변수에 관한 정보는 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" 로케일을 지원하기 위한 방법 및 3. 작동 원리 로케일을 제대로 지원하는 프로그램을 작성하기 위해서는 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 |
이 글에는 트랙백을 보낼 수 없습니다
0