web-dev-qa-db-ja.com

ロケールに文字セットが含まれているのはなぜですか?

私が理解しているように、POSIXは、ロケール定義にUTF-8のような文字エンコードのタイプを含める必要があると言っています。ロケールは通常、シェル環境変数として実装されます。

これらの2つの概念が分離されていないのはなぜですか?たとえば、サポートされているエンコーディングの数に応じて、複数のen_USロケールがあります。設計の観点からは面倒でスケーリングが難しいように思われるので、その理由は何ですか?

4
jiggunjer

中国語などの一部の言語は、複数の文字セットで記述でき、どちらも正しいです。それらには、より新しく単純化された文字セットと、より複雑で従来の文字セットがあります。または、モンゴル文字またはセルビア語は、キリル文字またはラテン文字の両方で記述できます。

さらに、多くの言語のä、öなどのアクセント付き文字は、画面上では同じですが、異なるエンコーディングで異なるコードを持っています。したがって、äをファイルに書き込むとは、utf8でエンコードされている場合、別の標準でエンコードされているかのように、このファイルに別のバイトシーケンスを書き込むことを意味します(私の例では、その名前はiso8859-1エンコーディングです)。

さらに、単一または一部の言語をサポートできるエンコーディングがあります。たとえば、iso8859-1はほとんどの西ヨーロッパ言語をサポートし、iso8859-2はラテン文字で記述されるまで、中央ヨーロッパと東ヨーロッパの言語をサポートします。 Asciiは英語のみをサポートしますが、utf8は世界のほぼすべての言語をサポートします。

したがって、言語と可能なエンコーディングの間には多対多の関係があります。言語は複数のエンコーディングでエンコードでき、ほとんどのエンコーディングは複数の言語で使用できます。

エンコーディングの互換性には多対多の関係もあります。たとえば、iso8859-2はasciiと上位互換性がありますが、ebcdicはそうではありません。

エンコーディングの互換性の間にも多対多の関係があります。たとえば、ebcdicはasciiに変換できますが、iso8859-2は変換できません。

したがって、部分的に互換性のある標準の複雑なネットワークがあります。実際に使用されるエンコーディングは、言語として、ロケールに正確に属します。したがって、言語と同様に処理する必要があります。これが、同じ環境変数で処理される理由です。

別の環境変数で処理することは可能ですが、私の意見では、より良い方法です。したがって、言語としてのエンコーディングには異なる環境変数があり、それは言語文字列の拡張ではありません。その理由は、互換性の理由から、主に歴史的なものです。

ただし、少なくともglibcでは、さまざまな環境変数もサポートされています。これは私の英語のLinuxの1つでの「ロケール」出力がどのように見えるかです:

$ 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年代初頭)に開始されました。 Unicodeはまだ存在していませんでした。これは新しく実装されていない標準であり、すべてのソフトウェアは1文字= 1バイトの疑いで開発されました。 utfを実行可能にするには、それらすべてを大幅に変更する必要があります。これは、次の10年の大きな問題の原因でした。

すべての言語拡張機能はバイトの上半分を使用していました(asciiは7ビットのみを指定しているため、ä、ö、またはキリル文字/ギリシャ文字の場所は128〜255でした)。したがって、これらは互いに互換性がありませんでした。したがって、当時、言語とコードページの関係は、現在の多対多のように、1対1のようなものでした。

したがって、使用するコードページも明確に指定された言語をサポートします。したがって、さまざまなコードページのサポートはありませんでした。用語としてのコードページでさえ、あまり受け入れられていませんでした。ほとんどのツールはコードページが存在することすら知らなかったのに、win95がwin31のibm850からcp1251に切り替わったときに、いくつの問題が発生したかを想像できます。

Linuxでは、言語はLANG環境変数の2文字で決定され、それ以上は決定されませんでした。言語方言のサポート(ブラジルポルトガル語の「pt_BR」のように、単に「pt」の代わりに)は、すでにそのための独立した拡張機能でした。

Utf8では、複数の包含で同じ言語をサポートする必要性が非常に緊急でした。問題はその時点ですでに存在していましたが(セルビア語、キリル文字とラテン文字で記述できるものを参照)、一部の小さな言語でのみ問題が発生しました(私が知る限り、セルビア語はすべてにラテン文字を使用していました)。したがって、マルチエンコーディングのサポートは、継続的で継続的な開発の次のステップでした。したがって、それは一般的なパターンに従いました:言語文字列のさらなる拡張。