123
A REINTRODUCTION TO RUBY M17N NARUSE, Yui

A Reintroduction To Ruby M17 N

Embed Size (px)

DESCRIPTION

東京RubyKaigi03 成瀬の発表 「A reintroduction to Ruby M17N」 http://nalsh.jp/pub/A%20reintroduction%20to%20Ruby%20M17N.pptx

Citation preview

Page 1: A Reintroduction To Ruby M17 N

A REINTRODUCTION TO RUBY M17N

NARUSE, Yui

Page 2: A Reintroduction To Ruby M17 N

序 今日はみなさんに日本を生ま

れた事を後悔してもらいに来ました

の、つもりだったのだが…… 「地球に生まれた事に」に

なってしまった……

Page 3: A Reintroduction To Ruby M17 N

話す事・話さない事

話す事 文字コード Ruby M17N

話さない事 メッセージの切り替え 時刻・時間とか通貨とか

Page 4: A Reintroduction To Ruby M17 N

コンピュータで文字を扱う 表示・印刷 字形 ( グリフイメージ ) 字体 ( グリフ ) 書記素クラスタ (grapheme

cluster) コードポイント 符号化文字集合 ( コードユニット ) (UTF-16/32) バイト 文字符号化方式 処理・格納

Page 5: A Reintroduction To Ruby M17 N

「文字コード」とは 「文字」をコンピュータで扱う仕組み

のうち、比較的低層の部分 つまり、グリフやフォントよりちょっ

と下まで 扱う文字を決め、番号を振る 文字列を番号列、バイト列、ビット列

にする

Page 6: A Reintroduction To Ruby M17 N

文字集合 Abstract Character Repertoire どのような文字を扱うか ある文字とある文字が同じか違うか

の決定 何文字扱うか、扱えるか 必要な文字 vs. メモリサイズ・性能

Page 7: A Reintroduction To Ruby M17 N

何を扱うか アラビア数字 アルファベット大文字 ― 6bit アルファベット小文字 ― 7bit カタカナ ― 8bit ひらがな 漢字 絵文字 など ― 16bit などなどなど ― 21bit

Page 8: A Reintroduction To Ruby M17 N

文字の同定 ある文字とある文字が等しいかどうかの決

定 包摂規準 ( その文字の射程範囲の決定 ) 何が一文字か e.g. リガチャ「 ffi 」 典拠の確保―いい加減だと幽霊文字が混

じったり、重複したり

e.g. 妛 𡚴 「あけんばら」で検索

Page 9: A Reintroduction To Ruby M17 N

字形の違い 色々な「フォント差」「書体差」

a a a a a a a a a 「 g 」「 g」メガネ

g 「 l 」「 l 」ループ L

言 言 言

Page 10: A Reintroduction To Ruby M17 N

字体の違い

JIS では同じだが Unicode では別「高」と「髙」 「吉」と「 」𠮷

JIS でも Unicode でも同じコードポイント

Page 11: A Reintroduction To Ruby M17 N

符号化文字集合 CCS / Coded Character Set 文字集合を構成する「文字」、一つ一つに

番号を振ったもの 一般にはこの番号を「コードポイント」 Unicode の場合

「 Unicode Scalar Value 」「あ」→ U+3042 (Unicode)

JIS X 0208「ビット組合せ」や「区点コード」「あ」→ 04 区 02 点 (JIS X 0208)

Page 12: A Reintroduction To Ruby M17 N

符号化文字集合の例 ASCII 英数記号 ISO/IEC 8859-1 アクセント付き文字 JIS X 0201 いわゆる半角カナ JIS X 0208 第一・第二水準漢字など JIS X 0212 補助漢字など JIS X 0213 第三・第四水準漢字など Unicode いろいろ

Page 13: A Reintroduction To Ruby M17 N

JIS X

02

08

http

://ww

w.ka

nji.zin

bun.ky

oto

-u.a

c.jp/~

yasu

oka

/kan

jibuku

ro/ja

pan.h

tml

Page 14: A Reintroduction To Ruby M17 N

文字符号化方式 CES, Character Encoding Scheme 符号化文字集合の番号をバイト列に変

換する方式 Shift_JIS

「あ」 → 04 区 02 点 → "\x82¥xA0"「い」 → 04 区 04 点 → "\x82\xA2"

UTF-8「あ」 → U+3042 → "\xE3\x81\x82"「い」 → U+3044 → "\xE3\x81\x84"

Page 15: A Reintroduction To Ruby M17 N

エンコーディング encoding (W3C) charset (IETF) あるバイトデータを解釈するには、

「文字符号化方式」と「符号化文字集合」を共に特定する必要

Shift_JIS"\x82¥xA0" → 04 区 02 点 → 「あ」

UTF-8"\xE3\x81\x82" → U+3042 → 「あ」

Page 16: A Reintroduction To Ruby M17 N

IANA Charset 各々のエンコーディングに名前を付けて登録管

理 インターネット上に流すデータは登録されてる

必要 一部のエンコーディングは実態と乖離もhttp://www.iana.org/assignments/character-sets

ISO-2022-JP EUC-JP Shift_JIS Windows-31J

Page 17: A Reintroduction To Ruby M17 N

用語の整理 charset

Character set が由来と思われるため、「文字集合」の意味に感じられるが、用法としては encoding と同じ

文字コード文字集合encodingある文字のコードポイント

Page 18: A Reintroduction To Ruby M17 N

Unicode 用語集 UCS-2 は文字集合ではなく encoding

ISO/IEC 10646 の定義13.1 Two-octet BMP form (UCS-2)

This coded representation form permits the use of characters from the Basic Multilingual Plane with each character represented by two octets.

Unicode の定義“UCS-2. ISO/IEC 10646 encoding form: Universal Character Set coded in 2 octets, limited to the Basic Multilingual Plane.”http://www.unicode.org/glossary/#UCS_2

Page 19: A Reintroduction To Ruby M17 N

History of I18N

Internationalization, 国際化 I .{18} N I18N S12N (Scherpenhuizen さんが元祖 ) http://blog.miraclelinux.com/yume/2007/01/i18n_8bc0.html

Page 20: A Reintroduction To Ruby M17 N

略語解説 L10N (Localization) ( 地域化 )

それぞれの地域・言語に適したようにすることある言語に対応することcf. nls (national language support)

I18N (Internationalization) ( 国際化 ) 地域化しやすいように、あらかじめソフトウェア側を抽象化し

ておくこと 言語を切り替えて使用できるようにすること

M17N (Multilingualization) (多言語化 )複数の言語などで利用するためにローカライズ同時に複数の言語を扱えるように (Ruby)

Page 21: A Reintroduction To Ruby M17 N

国際化というからには

元は国際対応じゃない

最初はどうだったのか ?

Page 22: A Reintroduction To Ruby M17 N

始まりは ASCII 1970年頃 ASCII以前から文字コードはあっ

た ASCII は電信の遺産を継承してい

る まぁ情報通信的には ASCII から始まるていうか ISO/IEC 646 でしょEBCDIC のことを忘れないでくだ

さい

Page 23: A Reintroduction To Ruby M17 N

ECMA-6 IRV(≒ ASCII)

http

://ww

w.e

cma-in

tern

atio

nal.o

rg/p

ublica

tions/sta

ndard

s/Ecm

a-0

06

.htm

Page 24: A Reintroduction To Ruby M17 N

ASCII に含まれる文字種

アラビア数字 アルファベット大文字 アルファベット小文字 記号全 94 文字

Page 25: A Reintroduction To Ruby M17 N

文字が足りない アクセント付きアルファベット

(ISO 8859シリーズ ) 577 文字 いわゆる半角カタカナ

(JIS X 0201) 56+7 文字 漢字など

(JIS X 0208) 6355+524 文字

Page 26: A Reintroduction To Ruby M17 N

ASCII を拡張しよう JIS X 0201 (ASCII 亜種・ 8bit 化 ) ISO-8859-1 (8bit 化 ) ISO-2022-JP ( エスケープシーケン

ス ) SJIS / EUC / UTF-8 (マルチバイト ) UTF-16 (16bit 化 ) UTF-32 (32bit 化 )

Page 27: A Reintroduction To Ruby M17 N

拡張したよ!ASCII-8BIT, UTF-8, US-ASCII, Big5, Big5-HKSCS, Big5-UAO, CP949, Emacs-Mule, EUC-JP, EUC-KR, EUC-TW, GB18030, GBK, ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-11, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16, KOI8-R, KOI8-U, Shift_JIS, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE, Windows-1251, IBM437, IBM737, IBM775, CP850, IBM852, CP852, IBM855, CP855, IBM857, IBM860, IBM861, IBM862, IBM863, IBM864, IBM865, IBM866, IBM869, Windows-1258, GB1988, macCentEuro, macCroatian, macCyrillic, macGreek, macIceland, macRoman, macRomania, macThai, macTurkish, macUkraine, stateless-ISO-2022-JP, eucJP-ms, CP51932, GB2312, GB12345, ISO-2022-JP, ISO-2022-JP-2, CP50221, Windows-1252, Windows-1250, Windows-1256, Windows-1253, Windows-1255, Windows-1254, TIS-620, Windows-874, Windows-1257, Windows-31J, MacJapanese, UTF-7, UTF8-MAC

Ruby 1.9.2 サポート予定分

Page 28: A Reintroduction To Ruby M17 N

どうしてこうなった ?制約の中でベストを尽くそうとするため メモリ容量 処理速度 プログラミングの複雑さ 必要な文字の違い ベンダ間の調整不足 結局、ほっとけば文字コードは増える →統一への努力

Page 29: A Reintroduction To Ruby M17 N

どうしよう…… ? 敵を知るしかない 知った上で個別撃破 たいていの罠は「歴史的経緯」

歴史を知る事が重要

Page 30: A Reintroduction To Ruby M17 N

ISO 646― 分裂の始まり ISO/IEC 646 ASCII の ISO バージョン 一部の文字の置き換えを認めている

択一 #/£ $/¤任意 [ \ ] ^ { | } ~

Page 31: A Reintroduction To Ruby M17 N

ISO 646 の各国ごとの違い16進 ASCII CN DE DK/

NO GB HU JP KR MT SE YU

23 # # # # £ # # # # # #

24 $ \ $ $ $ ¤ $ $ $ ¤ $

40 @ @ § @ @ Á @ @ @ @ Ž

5B [ [ Ä Æ [ É [ [ ġ Ä Š

5C \ \ Ö Ø \ Ö ¥ ₩ Ż Ö Đ

5D ] ] Ü Å ] Ü ] ] ħ Å Ć

5E ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Č

60 ` ` ` ` ` á ` ` ċ ` ž

7B { { ä æ { é { { Ġ ä š

7C | | ö ø | ö | | Ż ö đ

7D } } ü å } ü } } Ħ å ć

7E ~ ‾ ß ~ ~ ˝ ‾ ‾ Ċ ~ č

http

://ja.w

ikipedia

.org

/wiki/IS

O_6

46

http

://en.w

ikipedia

.org

/wiki/IS

O/IE

C_6

46

Page 32: A Reintroduction To Ruby M17 N

ISO 646 文字の意味論の違いCode Characters for each ISO 646 compatible charset

hex INV T.61 US JA JA-O KR CN TW IRV GB DK NO NO-2 SE SE-C DE HU FR FR-0 CA-1 CA-2 IE IS ita por PT esp ES CU MT YU

22 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "

23   # # # # # # # # £ # # § # # # # £ £ # # £ # £ # £ # # # # #

24   ¤ $ $ $ $ ¥ $ $ $ $ $ $ ¤ ¤ $ ¤ $ $ $ $ $ $ $ $ $ $ $ ¤ $ $

27 ' ' ' ' ' ' ' ' ’ ’ ’ ’ ’ ’ ’ ’ ’ ’ ’ ’ ’ ’ ' ’ ’ ’ ’ ’ ’ ’ ’

2C , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,

2D - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

2F / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /

40   @ @ @ @ @ @ @ @ @ @ @ @ @ É § Á à à à à Ó Ð § § ´ § · @ @ Ž

5B   [ [ [ [ [ [ [ [ [ Æ Æ Æ Ä Ä Ä É ° ° â â É Þ ° Ã Ã ¡ ¡ ¡ ġ Š

5C     \ ¥ ¥ ₩ \ \ \ \ Ø Ø Ø Ö Ö Ö Ö ç ç ç ç Í \ ç Ç Ç Ñ Ñ Ñ ż Đ

5D   ] ] ] ] ] ] ] ] ] Å Å Å Å Å Ü Ü § § ê ê Ú Æ é Õ Õ ¿ Ç ] ħ Ć

5E     ^ ^ ^ ^ ^ ^ ˆ ˆ ˆ ˆ ˆ ˆ Ü ˆ ˆ ^ ˆ î É Á Ö ˆ ˆ ˆ ˆ ¿ ¿ ˆ Č

5F _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

60     ` `   ` ` ` ` ` ` ` ` ` é ` á µ µ ô ô ó ð ù ` ` ` ` ` ċ ž

7B     { { { { { { { { æ æ æ ä ä ä é é é é é é þ à ã ã ° ´ ´ Ġ š

7C   | | | | | | | | | ø ø ø ö ö ö ö ù ù ù ù í | ò ç ç ñ ñ ñ Ż đ

7D     } } } } } } } } å å å å å ü ü è è è è ú æ è õ õ ç ç [ Ħ ć

7E     ~ ‾   ‾ ‾ ‾ ˜ ˜ ˜ ¯ | ˜ ü ß ˝ ¨ ¨ û û á ö ì ° ˜ ˜ ¨ ¨ Ċ č

赤字は文字合成を許すもの。例 : <A BS “>→ Ä

Page 33: A Reintroduction To Ruby M17 N

まだまだ足りない アクセント付きアルファベッ

ト(ISO 8859シリーズ ) 577 字

いわゆる半角カタカナ(JIS X 0201) 56+7 字

漢字など(JIS X 0208) 6355+524 字

Page 34: A Reintroduction To Ruby M17 N

ISO/IEC 2022 Character Code Structure and Extension

Techniques ISO 646 を拡張した文字コードの作り方を定

める 具体例

ISO 8859シリーズ (8bit 化 )ISO-2022-JP ( エスケープシーケンス )EUC系 (多バイト )

シフト JIS や UTF-8 などは違う

Page 35: A Reintroduction To Ruby M17 N

EC

MA

-35

(≒ IS

O/IE

C 2

02

2)

http

://ww

w.e

cma-in

tern

atio

nal.o

rg/p

ublica

tions/sta

ndard

s/Ecm

a-0

35

.htm

Page 36: A Reintroduction To Ruby M17 N

ISO/IEC 2022 の構造

\x20|

\x7F

\xA0|

\xFF

JIS X 0201ローマ字

JIS X 0208

JIS X 0201片仮名

JIS X 0212

AESC ( B A

US-ASCII

JIS X 0213

EUC-JP G1 EUC-JP G2

EUC-JP G3

\x8E (SS2)漢ESC $ B 4A

Page 37: A Reintroduction To Ruby M17 N

ISO 2022 のバイト列 どの文字集合を使うか指定

バッファへの指示 (stateful)バッファからの呼び出し○ シングルシフト○ ロッキングシフト (stateful)

その文字集合のどの文字を使うか指定

Page 38: A Reintroduction To Ruby M17 N

ISO/IEC 2022系の欠点 状態を持つ事 (持たないものもあるが ) 文字コードがどんどん増える 文字コードごとに別のコードが必要になる 規格が複雑になってしまった

Page 39: A Reintroduction To Ruby M17 N

Unicode

1986年頃から Xerox と Apple が始める 1988年 ISO に Unicode 88 を持ち込む 1991年 1.0 ( 漢字なし ), 1992年 1.0.1 1993年 1.1 で ISO と同期 1996年 2.0, UTF-8 と UTF-16 登場 2002年 3.2 で JIS X 0213 対応 2010年末 6.0 で絵文字対応 ?

Page 40: A Reintroduction To Ruby M17 N

Design Of Unicode 文字コードから地域・言語を分離

1 つの Unicode 文字列には複数の言語を混ぜられない

フラットな空間に全ての文字を入れる16bit → 32bitUTF-16 の制限から 1,114,112 文字種

用字系が同じならば文字統合

Page 41: A Reintroduction To Ruby M17 N

漢字統合plaintext+encoding からフォントを決定できない

Page 42: A Reintroduction To Ruby M17 N

一見大きな問題に見えるが

トルコ語では” i”.upcase →“İ”

ドイツ語では” ss”.upcase →“ß”

実は ASCII の範囲も言語の指定が必要

Page 43: A Reintroduction To Ruby M17 N

There Ain't No Such ThingAs Plain Text.

Joel Spolskyhttp://www.joelonsoftware.com/articles/Unicode.html

TEXT needsEncoding and Language

Page 44: A Reintroduction To Ruby M17 N

Legacy Encoding Unicode以前の文字コードたち Unicode 時代のプログラムで動かす

には変換して取り込む必要

変換表をどうするか ? 人によって変換表が異なると問題

Page 45: A Reintroduction To Ruby M17 N

ご存じですか ? CP932

他の話がさっぱりでも「 CP932 の存在」だけは知って帰って頂きたい

Windows Codepage 932IBM Codepage 932 とは微妙に違う

Windows版シフト JIS 正式名称 : Windows-31J JIS 規格由来の Shift_JIS と変換表が異

なる CP932 を用いるといくつかの問題を回避可能

Page 46: A Reintroduction To Ruby M17 N

円記号問題「 \ 」

問題の始まり ISO 646系の 0x5C JIS X 0201 円記号 ¥ ASCII バックスラッシュ \

Page 47: A Reintroduction To Ruby M17 N

ISO 646 の各国ごとの違い16進 ASCII CN DE DK/

NO GB HU JP KR MT SE YU

23 # # # # £ # # # # # #

24 $ \ $ $ $ ¤ $ $ $ ¤ $

40 @ @ § @ @ Á @ @ @ @ Ž

5B [ [ Ä Æ [ É [ [ ġ Ä Š

5C \ \ Ö Ø \ Ö ¥ ₩ Ż Ö Đ

5D ] ] Ü Å ] Ü ] ] ħ Å Ć

5E ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Č

60 ` ` ` ` ` á ` ` ċ ` ž

7B { { ä æ { é { { Ġ ä š

7C | | ö ø | ö | | Ż ö đ

7D } } ü å } ü } } Ħ å ć

7E ~ ‾ ß ~ ~ ˝ ‾ ‾ Ċ ~ č

http

://ja.w

ikipedia

.org

/wiki/IS

O_6

46

http

://en.w

ikipedia

.org

/wiki/IS

O/IE

C_6

46

Page 48: A Reintroduction To Ruby M17 N

どこで問題になるか ?

まずは表示上の問題 「円記号」のつもりが「バックスラッシュ」で表示JIS X 0201 データを ASCII端末で表示

「バックスラッシュ」 のつもりが「円記号」で表示ASCII のデータを JIS X 0201端末で表示

取り違えると「文字化け」する

Page 49: A Reintroduction To Ruby M17 N

制御コードとの衝突 バックスラッシュは制御記号扱い

C 言語のエスケープ記号MS-DOS のパス区切り文字

同じ 0x5C の円記号も同じ扱いに\n\e 「えんいー」

Page 50: A Reintroduction To Ruby M17 N

シフト JIS と円記号問題 「表」はシフト JIS では \x95 \x5C シフト JIS を理解しないプログラムで問題

% cat yen.rbputs " 表 "% ruby1.8 ./yen.rb./yen.rb:1: unterminated string meets end of file

Page 51: A Reintroduction To Ruby M17 N

理由

puts " 表 " puts "\x95\x5C" p u t s " \x95 \ " puts "\x95\" 引用符を閉じていない扱い

に ! unterminated string meets end of file

Page 52: A Reintroduction To Ruby M17 N

回避方法 Ruby 1.8 の場合 -Ks Ruby 1.9 の場合 magic

comment% cat yen.rb#coding:Windows-31Jputs " 表 "% ruby1.8 -Ks ./yen.rb表

Page 53: A Reintroduction To Ruby M17 N

Unicode と円記号

シフト JIS の 0x5C を Unicodeに変換

Shift_JIS の 0x5C は本来 JIS X 0201 JIS X 0201 扱いなら、 U+00A5 ASCII 扱いなら、 U+005C EUC-JP の 0x5C は ASCII のはず

Page 54: A Reintroduction To Ruby M17 N

それぞれの変換の問題

ASCII: 0x5C が U+005C になると、 表示がバックスラッシュになる ?

JIS X 0201: 0x5C が U+00A5 になると、 パス区切りではなくなる ソースコードのエスケープじゃなくな

Page 55: A Reintroduction To Ruby M17 N

Windows での解決 0x5C は U+005C に変換する (ASCII風 )

日本語用フォントでは、U+005C のグリフを「円記号」にする

5C = U+005C : REVERSE SOLIDUS (YEN SIGN) http://msdn.microsoft.com/en-us/goglobal/cc305152.aspx

韓国のウォンでも同様の問題 5C = U+005C : REVERSE SOLIDUS (WON SIGN) http://msdn.microsoft.com/en-us/goglobal/cc305154.aspx

Page 56: A Reintroduction To Ruby M17 N

波ダッシュ問題「~」 JIS X 0208: U+301C(WAVE DASH) CP932: U+FF5E(FULLWIDTH TILDE) 問題

Windows は U+301C をシフト JIS に戻せない

CP932 の変換テーブルにないからXP添付のフォントで U+301C を表示しよ

うとすると、誤ったグリフになる「〜」(Vista以降では修正済み )

Page 57: A Reintroduction To Ruby M17 N

Shift_JIS と CP932 の違いシフト JIS UCS (JIS) Unicode (CP932)

0x5C \ U+00A5 (YEN SIGN) U+005C (REVERSE SOLIDUS)

0x7E ~ U+203E (OVERLINE) U+007E (TILDE)

0x815C ― U+2014 (EM DASH) U+2015 (HORIZONTAL BAR)

0x815F \ U+005C (REVERSE SOLIDUS)

U+FF3C (FULLWIDTH REVERSE SOLIDUS)

0x8160 ~ U+301C (WAVE DASH) U+FF5E (FULLWIDTH TILDE)

0x8161 ∥ U+2016 (DOUBLE VERTICAL LINE) U+2225 (PARALLEL TO)

0x817C - U+2212 (MINUS SIGN) U+FF0D (FULLWIDTH HYPHEN-MINUS)

0x8192 £ U+00A3 (POND SIGN) U+FFE1 (FULLWIDTH POUND SIGN)

0x819C ¢ U+00A2 (CENT SIGN) U+FFE0 (FULLWIDTH CENT SIGN)

0x81CA ¬ U+00AC (NOT SIGN) U+FFE2 (FULLWIDTH NOT SIGN)

Page 58: A Reintroduction To Ruby M17 N

機種依存文字 マイクロソフト標準キャラクタセット NEC 特殊文字

①Ⅰ など㌶ IBM拡張文字

ⅰ¦ 髙など﨑 NEC選定 IBM拡張文字

Page 59: A Reintroduction To Ruby M17 N

CP932風別エンコーディング

CP51932Windows版日本語 EUCCP932 にある機種依存文字があるJIS X 0212 がないWeb 上の「 EUC-JP 」はこれかも

CP50221Windows版 ISO-2022-JPいわゆる半角カナがあるCP932 にある機種依存文字がある

Page 60: A Reintroduction To Ruby M17 N

シフト JIS関連の名前 「シフト JIS 」 マイクロソフトウェア・アソシエイツが名

付けた。総称として用いられる 「 Shift-JIS 」「 Shift JIS 」 「シフト JIS 」の英語表記 「 MS 漢字コード」 開発者の山下による命名 「 SJIS 」 Unix 方面での名前 「 Shift_JIS 」 IANA Charset での名前 「シフト符号化表現」 JIS X 0208:1997 附属書 1 「 Shift_JISX0213 符号化表現」 JIS X 0213:2000  付属書

1 「 Shift_JIS-2004 符号化表現」 JIS X 0213:2004 付属書

1 「 CP932 (Windows Codepage 932) 」 Microsoft 実装 「 Windows-31J 」 CP932 の IANA Charset での名前 「 IBM CP932 」 MS CP932 とは別物 「 IBM943 」 MS CP932 とおおむね同じ、 JIS X 0201 「 IBM943C 」 MS CP932 と同じ、 ASCII

Page 61: A Reintroduction To Ruby M17 N

日本語 EUC関連の名前 「日本語 EUC (圧縮形式 ) 」 情報交換用の EUC 、普通は

これ 「日本語 EUC (固定長形式 ) 」 System V での内部表現 「 eucJP 」 UI-OSF 日本語環境実装規約で定義 「 EUC-JP 」 IANA Charset での名前 「 UJIS 」 ΣOS での名前 「 CP51932 」 Internet  Explorer での日本語 EUC 実装

「 eucJP-ms 」 TOG/JVC CDE/Motif 技術検討 WG が定義

「 EUC-JISX0213 」 JIS X 0213:2000 付属書 3 「 EUC-JP-2004 」 JIS X 0213:2004 付属書 3

Page 62: A Reintroduction To Ruby M17 N

処理系の課題

内部エンコーディングを何にするか

様々な encoding の入力の扱い

地域・言語ごとに異なる規則

Page 63: A Reintroduction To Ruby M17 N

内部コードはどうするか

UCS正規化 内部では特定の 1 つに変換するCSI (Code Set Independent) それぞれの文字コードに対応す

Page 64: A Reintroduction To Ruby M17 N

UCS正規化

Universal Character Set Java, Perl などほとんどが採用 内部コードを統一 入出力で変換が必要

入力はそのコードに変換内部コードで処理出力時に再び変換

Page 65: A Reintroduction To Ruby M17 N

CSI 方式

それぞれの encoding に対応

入出力を変換しない入力そのまま取り込むそのまま処理そのまま出力

Page 66: A Reintroduction To Ruby M17 N

Java 開発時期 : 1990~ 1995 内部コード : UTF-16 ( サロゲートペアは

1.5 から ) 文字型 : char ( コードポイントは int) 文字列型 : java.lang.String グリフ列 : CharSequence, BreakIterator

等 「 Java における Unicode 補助文字のサ

ポート」 Windows NT も同時期

Page 67: A Reintroduction To Ruby M17 N

.NET Framework 2000年リリース 内部コード : UTF-16 文字型 : Char 構造体

( コードポイントは Int32) 文字列型 : System.String グリフ列 : System.Globalization.StringInfo http://msdn.microsoft.com/ja-jp/library/system.globalization.stringinfo.aspx http://msdn.microsoft.com/ja-jp/library/system.globalization.cultureinfo.aspx

Page 68: A Reintroduction To Ruby M17 N

Perl 5.6 2000年リリース 内部コード : UTF-8 文字型 : なし 文字列型 : バイト列 / 文字列 (utf8

フラグ ) Perl は「型」の概念が薄い http://github.com/github/perl/blob/blead/utf8.c

Page 69: A Reintroduction To Ruby M17 N

Python 1.6 2000年リリース 内部 UTF-16 文字型 : char (UTF-16 code unit; 16bit)

文字列型 : String (UTF-16) http://www.egenix.com/www2002/python/

unicode-proposal.txt

Page 70: A Reintroduction To Ruby M17 N

Ruby 1.8 内部コード : ASCII/SJIS/EUC/UTF-8 文字型 : Fixnum (8bit) 文字列型 : String $KCODE でプロセスの文字コードを指定

「文字」のサポートはほとんどない

Page 71: A Reintroduction To Ruby M17 N

Ruby 1.9 2007年 1.9.0 リリース 2009年 1.9.1 リリース 内部コード : N/A (CSI) 文字 : 1 文字 String 文字列型 : String グリフ列 : なし

Page 72: A Reintroduction To Ruby M17 N

Ruby 1.9 の特徴 String が文字単位になった

バイト操作と文字操作を区別する必要 CSI 方式

特定の内部エンコーディングがないString それぞれが encoding を持つ

正規表現エンジンの刷新鬼車ベースに変更

Page 73: A Reintroduction To Ruby M17 N

文字志向な String " あいう ".length

→ 3 " あいうえお "[0]

→ " あ " " あい ".gsub(/ あ /," か ")

→ " かい " "abc".tr("abc"," あいう ")

→ " あいう "

Page 74: A Reintroduction To Ruby M17 N

String#each_*

String#each_byte String#each_codepoint String#each_char String#each_line

String#each は削除された

Page 75: A Reintroduction To Ruby M17 N

1 文字 String 専用の文字型は無い 文字は 1 文字 String で表す ?a → "a" "abc"[0] → "a" "abc"[0] == ?a は 1.9 でも成り立つ

Page 76: A Reintroduction To Ruby M17 N

「文字」型に必要なもの

コードポイント , Encoding, ( 言語 )

String は両方持っている Ruby は大クラス主義 String を使えばよい

Page 77: A Reintroduction To Ruby M17 N

Ruby 1.9 の Regexp /(.)/ =~ " あ " → 0

$1 → " あ " /\w/ =~ " あ " → nil

1.9.1-p376 以降、 1.9.2

以下は Unicode系 /(\p{Alphabetic})/ =~ " あ "

$1 → " あ " /(\p{Ideographic})/ =~ " 漢 "

$1 → " 漢 "

Page 78: A Reintroduction To Ruby M17 N

1.9 の String に必要なこと

適切に encoding が設定されていること 理由

String の encoding を見て処理するから 設定方法

Magic comment ( リテラル )IO のオプション (入出力 )String#force_encoding (強制指定 )

Page 79: A Reintroduction To Ruby M17 N

encoding が誤っている時 invalid multibyte char (US-ASCII)

Magic comment忘れ Encoding::CompatibilityError

異なった encoding の String を混ぜた時文字列をバイナリ扱いのままにしている時

ArgumentError: invalid byte sequence単純な指定ミス壊れた入力

Page 80: A Reintroduction To Ruby M17 N

Magic Comment

リテラルのエンコーディングを指定String, Regexp

デフォルトは US-ASCIIMagic Comment がないとソースに ASCII以外を書くことはできない

#coding:utf-8 #!/usr/local/bin/ruby

#coding:utf-8 # -*- coding: UTF-8 -*-

Page 81: A Reintroduction To Ruby M17 N

ERB 用 Magic Comment

ERB でも Magic Comment が必要 <%# coding: UTF-8 %>

Page 82: A Reintroduction To Ruby M17 N

IO と Encoding

入出力の encoding を指定する 外部リソースの encoding を指定 open("foo.txt","r:UTF-8") 未指定なら

Encoding.default_external

Page 83: A Reintroduction To Ruby M17 N

ネットワークからの入力 Socket, Net::HTTP など 現在はバイナリ API 扱い → 文字列の場合は自分で Encoding を設定する必要

Page 84: A Reintroduction To Ruby M17 N

Encoding の強制指定 String#force_encoding(enc) 任意の encoding の文字列をバイナリ

から作りたい時str = "\xE3\x81\x82"

str.force_encoding("UTF-8")str #=> " あ "

外部から来たデータに設定する時IO なら外部エンコーディングを設定するべ

きsocket や net系のライブラリで必要

Page 85: A Reintroduction To Ruby M17 N

$KCODE is obsolete

$KCODE は内部コード指定のため使われた

Ruby1.9 ではシステム全体の内部コードは、

決定不可能なため、廃止。 $KCODE を参照しているスクリプトは注意

Page 86: A Reintroduction To Ruby M17 N

結局 encoding とは

String にとっての「型」 型が違えばエラー 型同士で互換性があれば、自動変換されることも→ ASCII互換でのasciionly

Page 87: A Reintroduction To Ruby M17 N

Encoding の 3 分類 ASCII互換 ASCII非互換ダミー

Page 88: A Reintroduction To Ruby M17 N

ASCII互換 フルサポート Ruby スクリプトのソース

エンコーディングとして使用可能

UTF-8, Shift_JIS, EUC-JP, ...

Page 89: A Reintroduction To Ruby M17 N

Major Encodings

US-ASCIIASCII-8BITUTF-8

Page 90: A Reintroduction To Ruby M17 N

日本語用Shift_JISEUC-JP

Page 91: A Reintroduction To Ruby M17 N

Other Encodings Big5, Big5-UAO, EUC-KR,

EUC-TW, GBK, ISO-8859-X, KOI8-R, KOI8-

U, etc

Page 92: A Reintroduction To Ruby M17 N

Windows機種依存 Windows-31J CP51932 eucJP-ms Windows-125X

Page 93: A Reintroduction To Ruby M17 N

ASCII-8BIT ASCII互換バイト列 バイナリだけど ASCII互換 ASCII互換の恩恵を得るた

Page 94: A Reintroduction To Ruby M17 N

ASCII Only 特別扱い

ASCII互換エンコーディング内容が 7bit

"abcde".ascii_only?→true "abcde" + " あいうえお "

ASCII互換エンコーディングなら、両者のエンコーディングによらず成功

Page 95: A Reintroduction To Ruby M17 N

ASCII非互換 限定サポートソースコードには使えな

い UTF-{16,32}{BE,LE}

Page 96: A Reintroduction To Ruby M17 N

UTF-16 & UTF-32 UTF-16BE, UTF-16LE UTF-32BE, UTF-32LE しかし、 UTF-16 や UTF-32 には非対応BOM 対応が困難なため

Page 97: A Reintroduction To Ruby M17 N

Dummy encoding Ruby は名前を知っているだ

け 「文字」のサポートはしない for stateful encodings Encoding#dummy?

→ true ISO-2022-JP, UTF-7

Page 98: A Reintroduction To Ruby M17 N

Encoding 「エンコーディング」を司るク

ラス CSI ではエンコーディングが内

部処理でも使われるから活躍 でも、たいていエンコーディン

グ名を表す文字列でよい

Page 99: A Reintroduction To Ruby M17 N

Encoding の取得 enc = Encoding.find(“UTF-8”)

=> #<Encoding:UTF-8> Encoding.find(“external”)

デフォルト外部エンコーディング Encoding.find(“internal”)

デフォルト内部エンコーディング Encoding.find(“filesystem”)

ファイルシステムエンコーディング Encoding::UTF_8

定数も定義されている

Page 100: A Reintroduction To Ruby M17 N

Encoding の一覧 Encoding.listオブジェクトの配列

Encoding.aliases別名 => 本名 の Hash

Encoding.namesEncoding.find の引数になるString の配列

Page 101: A Reintroduction To Ruby M17 N

Encoding の情報 enc.name

=> “UTF-8” enc.names

=> ["UTF-8", "CP65001", "locale", "external", "filesystem"]

enc.dummy?ダミーエンコーディングかどうか

enc.ascii_compatible?ASCII互換かどうか

Page 102: A Reintroduction To Ruby M17 N

エンコーディング変換 nkf kconv iconv uconv String#encode Encoding::Converter

Page 103: A Reintroduction To Ruby M17 N

nkf Network Kanji Filter 歴史ある変換コマンド 使うなら --ic, --oc オプションを使う

Page 104: A Reintroduction To Ruby M17 N

kconv nkf のラッパー String#tosjis などと簡単 歴史的経緯による意図しない挙動勝手に MIME デコードいわゆる半角カナが全角に

もはやオススメしない

Page 105: A Reintroduction To Ruby M17 N

iconv POSIX 由来の iconv(3) のラッパー

挙動が環境依存glibc/GNU libiconv/Citrus/…

1.9 ではあえて使う必要はないはず

Page 106: A Reintroduction To Ruby M17 N

uconv Unicode 変換用拡張モジュール 0.5.3 から 1.9.1 に対応しているが、互

換性確保用に止めるべきであろう http

://www.yoshidam.net/Ruby_ja.html

Page 107: A Reintroduction To Ruby M17 N

String#encode Ruby 1.9独自の transcode String#encode(to, from, opt) たいていの用途はこれでいける

はず

Page 108: A Reintroduction To Ruby M17 N

Encoding::Converter transcode のエンジン 変換を一時停止・再開したい

時 常人は使わないはずだが、何

かの間違いで必要になるかもしれない

Page 109: A Reintroduction To Ruby M17 N

Don't forget… 不必要な変換は避ける open() 等の引数に指定

Page 110: A Reintroduction To Ruby M17 N

RUBY M17N の難しさ テストがしづらい

US-ASCIIASCI-8BITUTF-8 (ASCII Compatible)UTF-16 (ASCII Incompatible)ISO-2022-JP (dummy encoding)

Page 111: A Reintroduction To Ruby M17 N

SJIS と Windows-31J

Windows環境 Magic comment などで SJIS を指定 Encoding::CompatibilityError 入力は Windows-31J だから →Windows-31J指定が正しい あなたが SJIS だと思っているのは、実

は Windows-31J です

Page 112: A Reintroduction To Ruby M17 N

ASCII-8BIT

Ruby M17N未対応のライブラリを使った時

ネットワーク系や DB系など 明示的にエンコーディングを指定 String#force_encoding(enc)

Page 113: A Reintroduction To Ruby M17 N

ASCII非互換の正規表現 ASCII非互換エンコーディングな正規

表現はリテラルで書けない UTF-16LE の正規表現リテラルは書け

ない Regexp.new を使う Regexp.new(

" あ ".encode("UTF-16LE"))

Page 114: A Reintroduction To Ruby M17 N

Open problems

ケータイ絵文字 Windows の Unicodeパス 結合文字 異体字セレクタ /IVS String と言語 Stateful encoding Unicode 用ユーティリティ

Page 115: A Reintroduction To Ruby M17 N

ケータイ絵文字 mrkn さんや設楽さんたちが作業中 1.9.2 に入るかも

Page 116: A Reintroduction To Ruby M17 N

Windows の Unicodeパス 一部対応その他非対応 方針としては、現在Windows の A系

API を叩いているものを、 W系 API を使うように変える

そこら中で踏むのでリソース不足 いじれる方が居たらパッチください Win32-unicode-testブランチ

Page 117: A Reintroduction To Ruby M17 N

結合文字 「が」を「か」 + 「゛」で表す 複数のコードポイントを 1 文字扱いす

る必要 String の「文字」をこれにする変更が入った事はあるが巻き戻された [ruby-dev:36375]

「文字」の単位が Unicode のバージョンに依存

エスケープなどに影響 Java の BreakIterator っぽいものが必

要 ? 検討中

Page 118: A Reintroduction To Ruby M17 N

異体字セレクタ /IVS

Ideographic Variation Sequence 結合文字同様、複数のコードポイント

を 1 文字扱いする必要

Page 119: A Reintroduction To Ruby M17 N

String と言語 日本語と中国語を同時に扱いたい 日本語と中国語を 1 つの String に入れ

たい 可能かは文字コードによります UTF-8 ではできません Unicode は言語を別に与えないといけ

ない String に encoding と lang を持たせ

る必要 現状ユースケース不足

Page 120: A Reintroduction To Ruby M17 N

Stateful encoding

現状ダミーエンコーディング 改善予定無し

Page 121: A Reintroduction To Ruby M17 N

Unicode ユーティリティ 文字幅 Unicode正規化 Unicode 大文字小文字化 API をどうするか そもそもどこにいれるのか

Page 122: A Reintroduction To Ruby M17 N

String#sort

デフォルトでは文字コード順 シフト JIS や日本語 EUC の系統

と、 Unicode系のエンコーディングで並び順が変わる

現状では sort に block引数を指定するRuby には Collation とかは添付されてい

ない自分で比較ルーチンを用意して渡す

Page 123: A Reintroduction To Ruby M17 N

Feedback を よい API を設計するには、ユースケー

スの収集が大事なので feedback が重要 失敗談等は ruby-listへ バグ・提案は ruby-devへ オレはようやくのぼりはじめたばかり

だからなこの果てしなく遠い M17N をよ…

未実装