로캘에 문자 집합이 포함되는 이유는 무엇입니까?

로캘에 문자 집합이 포함되는 이유는 무엇입니까?

내가 이해한 바로는 POSIX에서는 로케일 정의에 UTF-8과 같은 문자 인코딩 유형이 포함되어야 한다고 말합니다. 로케일은 일반적으로 쉘 환경 변수로 구현됩니다.

이 두 개념이 분리되지 않는 이유는 무엇입니까? 예를 들어, 이제 지원되는 인코딩 수에 따라 여러 개의 en_US 로케일이 있습니다. 디자인 관점에서 볼 때 이것은 지저분하고 확장하기 어려운 것처럼 보입니다. 그렇다면 그 근거는 무엇입니까?

답변1

중국어와 같은 일부 언어는 둘 이상의 문자 세트로 작성될 수 있으며 두 문자 세트 모두 정확합니다. 여기에는 더 새롭고 단순화된 문자 세트와 더 복잡하고 전통적인 문자 세트가 있습니다. 또는 몽골어나 세르비아어를 키릴 문자나 라틴 문자로 쓸 수도 있습니다.

또한 ä, ö 등과 같은 많은 언어의 악센트 문자는 화면에서는 동일하더라도 인코딩에 따라 코드가 다릅니다. 따라서 ä를 파일에 쓴다는 것은 파일이 다른 표준에 의해 인코딩된 것처럼(내 예에서는 이름이 iso8859-1 인코딩임) 파일에 다른 바이트 시퀀스를 쓰는 것을 의미합니다(utf8로 인코딩된 경우).

또한 단일 또는 특정 언어를 지원하는 인코딩이 있습니다. 예를 들어 iso8859-1은 대부분의 서유럽 언어를 지원하고 iso8859-2는 라틴 문자로 작성될 때까지 중부 유럽 및 동유럽 언어를 지원합니다. Ascii는 영어만 지원하지만 utf8은 전 세계 거의 모든 언어를 지원합니다.

따라서 언어와 가능한 인코딩 사이에는 다대다 관계가 있습니다. 언어는 여러 인코딩으로 인코딩될 수 있으며 대부분의 인코딩은 여러 언어로 사용될 수 있습니다.

인코딩 호환성에는 다대다 관계도 있습니다. 예를 들어 iso8859-2는 ascii와 상위 호환되지만 ebcdic은 상위 호환되지 않습니다.

인코딩 호환성 간에도 다대다 관계가 있습니다. 예를 들어 ebcdic은 ascii로 변환할 수 있지만 iso8859-2는 변환할 수 없습니다.

결과적으로 부분적으로 호환되는 표준으로 구성된 복잡한 네트워크가 존재합니다. 사용되는 실제 인코딩은 언어와 마찬가지로 로캘에도 완전히 속합니다. 그러므로 언어처럼 처리되어야 한다. 그렇기 때문에 처리에 동일한 환경 변수를 사용합니다.

가능하지만 제 생각에는 다른 환경 변수에 의해 처리되는 경우 더 나은 접근 방식입니다. 따라서 언어로서의 인코딩은 다른 환경 변수를 갖게 되며 언어 문자열의 확장이 아닙니다. 그 이유는 주로 역사적인 이유와 호환성 이유입니다.

그러나 적어도 glibc에서는 다른 환경 변수도 지원됩니다. 내 영어 Linux에서 로케일 출력은 다음과 같습니다.

$ locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

보시다시피 다양한 LANG 및 LANGUAGE 환경 변수가 있습니다. 불행하게도 이는 대부분 일부 표준 호환성을 위한 것이며 시스템이 실제로 이를 따르지 않는 것 같습니다.

확장하다:

역사에 관하여: 고대에는 거의 모든 시스템이 ASCII 또는 EBCDIC 인코딩을 사용하는 미국 영어였습니다. 다중 언어 또는 다중 인코딩 지원은 들어본 적이 없으며, 개발된 경우 해결 방법을 사용합니다(예: 시스템 펌웨어의 문자 집합 비트맵을 덮어쓰는 등). 또한 저는 1988년경에 c64에 대한 latin2 문자 지원을 개발하고 있었습니다(나는 latin2에 일부 문자만 제공했지만 코드 페이지는 제공하지 않았습니다. 당시에는 코드 페이지가 무엇인지조차 몰랐습니다). 코드 페이지는 원래 ASCII와 유사한 확장을 표준화하기 위해 고안된 것입니다. 본질적으로 ascii와 호환되지 않는 ebcdic을 사용하여 메인프레임 세계에서 유사한 변환이 발생했습니다(ebcdic은 원래 사람이 쉽게 읽을 수 있는 펀치 카드를 만들기 위해 개발되었지만 ascii는 쉬운 데이터 처리를 목표로 했습니다).

이러한 인코딩은 모두 1바이트를 나타내기 위해 1문자를 사용합니다. Linux에서는 libc4 시대(90년대 초반)부터 다중 언어 지원이 시작되었습니다. 유니코드는 아직 존재하지 않았고, 구현되지 않은 새로운 표준이었으며, 모든 소프트웨어는 1문자 = 1바이트라는 의심을 가지고 개발되었습니다. UTF를 실현 가능하게 만들려면 이 모든 것이 대폭 수정되어야 하며 이는 향후 10년 동안 주요 문제의 원인이었습니다.

모든 언어 확장은 바이트의 상위 절반을 사용합니다(ascii는 7비트만 지정하므로 ä, ö 또는 키릴 문자/그리스어 스크립트 위치는 128-255 사이입니다). 따라서 서로 호환되지 않습니다. 따라서 그 당시에는 언어와 코드 페이지 간의 관계가 지금의 다대다처럼 일대일에 가깝습니다.

따라서 지원되는 언어도 사용할 코드 페이지를 명시적으로 지정합니다. 따라서 다른 코드페이지는 지원되지 않으며, 코드페이지라는 용어조차 널리 사용되지 않습니다. win95가 win31의 ibm850에서 cp1251로 전환했을 때 얼마나 많은 문제가 발생했는지 상상할 수 있으며 대부분의 도구는 코드 페이지의 존재조차 알지 못했습니다.

Linux에서 언어는 LANG 환경 변수의 2문자로 결정되며 그 이상은 아닙니다. 언어 방언 지원(예: 브라질 포르투갈어의 경우 단순히 "pt" 대신 "pt_BR")은 이미 이에 대한 별도의 확장입니다.

여러 래퍼를 사용하여 동일한 언어를 지원하려면 utf8이 절실히 필요합니다. 이 문제는 당시 이미 존재했지만(세르비아어, 키릴 문자와 라틴어로 쓸 수 있는 내용 참조) 일부 작은 언어에서만 문제를 일으켰습니다(내가 아는 한 세르비아어는 라틴어만 사용하여 모든 것을 씁니다). 따라서 다중 인코딩 지원은 지속적인 개발의 다음 단계입니다. 따라서 이는 언어 문자열의 추가 확장이라는 공통 패턴을 따릅니다.

관련 정보