when_exe 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +333 -212
- data/bin/make_ttl.rb +37 -0
- data/bin/make_ttl.rb.config +9 -0
- data/lib/when_exe.rb +923 -925
- data/lib/when_exe/calendarnote.rb +9 -5
- data/lib/when_exe/coordinates.rb +2437 -2446
- data/lib/when_exe/inspect.rb +1480 -1408
- data/lib/when_exe/linkeddata.rb +574 -0
- data/lib/when_exe/locales/akt.rb +177 -176
- data/lib/when_exe/locales/locale.rb +751 -751
- data/lib/when_exe/mini_application.rb +307 -307
- data/lib/when_exe/parts/resource.rb +1115 -1103
- data/lib/when_exe/region/chinese/epochs.rb +6 -5
- data/lib/when_exe/region/christian.rb +831 -829
- data/lib/when_exe/region/japanese.rb +93 -93
- data/lib/when_exe/region/japanese/notes.rb +1510 -1495
- data/lib/when_exe/region/japanese/residues.rb +13 -13
- data/lib/when_exe/tmposition.rb +2307 -2273
- data/lib/when_exe/tmreference.rb +1744 -1734
- data/lib/when_exe/version.rb +2 -2
- data/link_to_online_documents +1 -1
- data/test/scripts/3.ext.rb +6 -6
- data/test/scripts/3.rb +6 -6
- data/test/test.rb +76 -75
- data/test/test/icalendar.rb +883 -879
- data/test/test/linkeddata.rb +224 -0
- data/test/test/region/m17n.rb +193 -193
- data/when_exe.gemspec +3 -2
- metadata +13 -6
data/lib/when_exe/locales/akt.rb
CHANGED
@@ -1,176 +1,177 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
=begin
|
3
|
-
Copyright (C) 2014 Takashi SUGA
|
4
|
-
|
5
|
-
You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
|
6
|
-
=end
|
7
|
-
|
8
|
-
require 'when_exe/locales/transliteration_table'
|
9
|
-
|
10
|
-
module When
|
11
|
-
module Locale
|
12
|
-
|
13
|
-
#
|
14
|
-
# AKT: Alphabet of Katakana Transliteration
|
15
|
-
#
|
16
|
-
# see { http://www.asahi-net.or.jp/~dy5h-kdm/end2.htm MadKod}
|
17
|
-
#
|
18
|
-
AKT = {
|
19
|
-
'ja' => {
|
20
|
-
"a" =>"ア", "i" =>"イ", "u" =>"ウ", "e" =>"エ", "o" =>"オ",
|
21
|
-
"ka" =>"カ", "ki" =>"キ", "ku" =>"ク", "ke" =>"ケ", "ko" =>"コ", "k" =>"ク",
|
22
|
-
"qa" =>"カ", "qi" =>"キ", "qu" =>"ク", "qe" =>"ケ", "qo" =>"コ", "q" =>"ク",
|
23
|
-
"ga" =>"ガ", "gi" =>"ギ", "gu" =>"グ", "ge" =>"ゲ", "go" =>"ゴ", "g" =>"グ",
|
24
|
-
"sa" =>"サ", "si" =>"シ", "su" =>"ス", "se" =>"セ", "so" =>"ソ", "s" =>"ス",
|
25
|
-
"za" =>"ザ", "zi" =>"ヂ", "zu" =>"ズ", "ze" =>"ゼ", "zo" =>"ゾ", "z" =>"ズ",
|
26
|
-
"ja" =>"ジャ", "ji" =>"ジ", "ju" =>"ジュ", "je" =>"ジェ", "jo" =>"ジョ", "j" =>"ジュ",
|
27
|
-
"ca" =>"カ", "ci" =>"チ", "cu" =>"ク", "ce" =>"セ", "co" =>"コ", "c" =>"ク",
|
28
|
-
"ta" =>"タ", "ti" =>"ティ", "tu" =>"トゥ", "te" =>"テ", "to" =>"ト", "t" =>"ト",
|
29
|
-
"tsa"=>"ツァ", "tsi"=>"ツィ", "tsu"=>"ツ", "tse"=>"ツェ", "tso"=>"ツォ", "ts"=>"ツ",
|
30
|
-
"da" =>"ダ", "di" =>"ディ", "du" =>"ドゥ", "de" =>"デ", "do" =>"ド", "d" =>"ド",
|
31
|
-
"na" =>"ナ", "ni" =>"ニ", "nu" =>"ヌ", "ne" =>"ネ", "no" =>"ノ", "n" =>"ン",
|
32
|
-
"ha" =>"ハ", "hi" =>"ヒ", "hu" =>"フ", "he" =>"ヘ", "ho" =>"ホ", "h" =>"フ",
|
33
|
-
"ba" =>"バ", "bi" =>"ビ", "bu" =>"ブ", "be" =>"ベ", "bo" =>"ボ", "b" =>"ブ",
|
34
|
-
"pa" =>"パ", "pi" =>"ピ", "pu" =>"プ", "pe" =>"ペ", "po" =>"ポ", "p" =>"プ",
|
35
|
-
"fa" =>"ファ", "fi" =>"フィ", "fu" =>"フ", "fe" =>"フェ", "fo" =>"フォ", "f" =>"フ",
|
36
|
-
"va" =>"ヴァ", "vi" =>"ヴィ", "vu" =>"ヴ", "ve" =>"ヴェ", "vo" =>"ヴォ", "v" =>"ヴ",
|
37
|
-
"ma" =>"マ", "mi" =>"ミ", "mu" =>"ム", "me" =>"メ", "mo" =>"モ", "m" =>"ム",
|
38
|
-
"mma"=>"ンマ", "mmi"=>"ンミ", "mmu"=>"ンム", "mme"=>"ンメ", "mmo"=>"ンモ",
|
39
|
-
"ra" =>"ラ", "ri" =>"リ", "ru" =>"ル", "re" =>"レ", "ro" =>"ロ", "r" =>"ル",
|
40
|
-
"la" =>"ラ", "li" =>"リ", "lu" =>"ル", "le" =>"レ", "lo" =>"ロ", "l" =>"ル",
|
41
|
-
"wa" =>"ワ", "wi" =>"ウィ", "wu" =>"ゥ", "we" =>"ウェ", "wo" =>"ヲ", "w" =>"ゥ",
|
42
|
-
"wwa"=>"ウヮ", "wwi"=>"ウィ", "wwu"=>"ウゥ", "wwe"=>"ウェ", "wwo"=>"ウォ",
|
43
|
-
"xa" =>"ァ", "xi" =>"ィ", "xu" =>"ゥ", "xe" =>"ェ", "xo" =>"ォ", "x" =>"クス",
|
44
|
-
"ya" =>"ヤ", "yu" =>"ユ", "yo" =>"ヨ", "y" =>"イ",
|
45
|
-
"kya"=>"キャ", "kyu"=>"キュ", "kyo"=>"キョ",
|
46
|
-
"kja"=>"キャ", "kvu"=>"キュ", "kjo"=>"キョ",
|
47
|
-
"qja"=>"キャ", "qju"=>"キュ", "qjo"=>"キョ",
|
48
|
-
"gya"=>"ギャ", "gyu"=>"ギュ", "gyo"=>"ギョ",
|
49
|
-
"gja"=>"ギャ", "gju"=>"ギュ", "gjo"=>"ギョ",
|
50
|
-
"sya"=>"シャ", "syu"=>"シュ", "syo"=>"ショ",
|
51
|
-
"sja"=>"シャ", "sju"=>"シュ", "sjo"=>"ショ",
|
52
|
-
"zya"=>"ジャ", "zyu"=>"ジュ", "zyo"=>"ジョ",
|
53
|
-
"zja"=>"ヂャ", "zju"=>"ヂュ", "zjo"=>"ヂョ",
|
54
|
-
"jya"=>"ジャ", "jyu"=>"ジュ", "jye"=>"ジェ", "jyo"=>"ジョ",
|
55
|
-
"cyi"=>"チィ", "cyu"=>"チュ", "tyi"=>"ティ",
|
56
|
-
"tyu"=>"テュ", "tye"=>"テェ", "tja"=>"チャ",
|
57
|
-
"tju"=>"チュ", "tjo"=>"チョ", "-" =>"ー", "tsx"=>"ッ",
|
58
|
-
"dyi"=>"ディ", "dyu"=>"デュ", "dye"=>"デェ",
|
59
|
-
"dja"=>"ヂャ", "dju"=>"ヂュ", "djo"=>"ヂョ",
|
60
|
-
"nya"=>"ニャ", "nyu"=>"ニュ", "nyo"=>"ニョ",
|
61
|
-
"nva"=>"ニャ", "nvu"=>"ニュ", "nvo"=>"ニョ",
|
62
|
-
"hya"=>"ヒャ", "hyu"=>"ヒュ", "hyo"=>"ヒョ",
|
63
|
-
"bya"=>"ビャ", "byu"=>"ビュ", "byo"=>"ビョ",
|
64
|
-
"pya"=>"ピャ", "pyu"=>"ピュ", "pyo"=>"ピョ",
|
65
|
-
"fyu"=>"フュ", "vyu"=>"ヴュ",
|
66
|
-
"mya"=>"ミャ", "myu"=>"ミュ", "myo"=>"ミョ",
|
67
|
-
"mva"=>"ミャ", "mvu"=>"ミュ", "mvo"=>"ミョ",
|
68
|
-
"rya"=>"リャ", "ryu"=>"リュ", "ryo"=>"リョ",
|
69
|
-
"lya"=>"リャ", "lyu"=>"リュ", "lyo"=>"リョ",
|
70
|
-
"wyi"=>"ウイ", "wyu"=>"ウユ", "wye"=>"ウエ",
|
71
|
-
"xya"=>"ャ", "xyu"=>"ュ", "xyo"=>"ョ",
|
72
|
-
"yya"=>"イャ", "yyi"=>"イィ", "yyu"=>"イュ", "yye"=>"イェ", "yyo"=>"イョ",
|
73
|
-
"kwa"=>"クヮ", "kwi"=>"クィ", "kwu"=>"クゥ", "kwe"=>"クェ", "kwo"=>"クォ",
|
74
|
-
"kha"=>"クァ", "khi"=>"クィ", "khu"=>"クゥ", "khe"=>"クェ", "kho"=>"クォ",
|
75
|
-
"qha"=>"クァ", "qhi"=>"クィ", "qhu"=>"クゥ", "qhe"=>"クェ", "qho"=>"クォ",
|
76
|
-
"gwa"=>"グヮ", "gwi"=>"グィ", "gwu"=>"グゥ", "gwe"=>"グェ", "gwo"=>"グォ",
|
77
|
-
"gha"=>"グァ", "ghi"=>"グィ", "ghu"=>"グゥ", "ghe"=>"グェ", "gho"=>"グォ",
|
78
|
-
"sha"=>"シャ", "shi"=>"シ", "shu"=>"シュ", "she"=>"シェ", "sho"=>"ショ", "sh"=>"シュ",
|
79
|
-
"swa"=>"スワ", "swi"=>"スィ", "swu"=>"スゥ", "swe"=>"スェ", "swo"=>"スヲ",
|
80
|
-
"zha"=>"ツァ", "zhi"=>"ツィ", "zhu"=>"ズゥ", "zhe"=>"ツェ", "zho"=>"ツォ",
|
81
|
-
"zxa"=>"ツァ", "zxi"=>"ツィ", "zxu"=>"ズゥ", "zxe"=>"ツェ", "zxo"=>"ツォ",
|
82
|
-
"jxa"=>"ジァ", "jxi"=>"ジィ", "jxu"=>"ジゥ", "jxe"=>"ジェ", "jxo"=>"ジォ",
|
83
|
-
"cha"=>"チャ", "chi"=>"チ", "chu"=>"チュ", "che"=>"チェ", "cho"=>"チョ",
|
84
|
-
"twa"=>"トワ", "twi"=>"ツイ", "twu"=>"トゥ", "twe"=>"ツエ", "two"=>"ツー",
|
85
|
-
"tha"=>"スァ", "thi"=>"スィ", "thu"=>"スゥ", "the"=>"スェ", "tho"=>"スォ",
|
86
|
-
"tza"=>"ツァ", "tzi"=>"ツィ", "tzu"=>"ズー", "tze"=>"ツェ", "tzo"=>"ツォ",
|
87
|
-
"dwa"=>"ドワ", "dwi"=>"ドィ", "dwu"=>"ドゥ", "dwe"=>"ドェ", "dwo"=>"ドヲ",
|
88
|
-
"dha"=>"ダー", "dhi"=>"ジー", "dhu"=>"ドフ", "dhe"=>"ドヘ", "dho"=>"ドホ",
|
89
|
-
"dsa"=>"ドサ", "dsi"=>"ドシ", "dsu"=>"ズ", "dse"=>"ドセ", "dso"=>"ドソ",
|
90
|
-
"nxa"=>"ニァ", "nxi"=>"ニィ", "nxu"=>"ニゥ", "nxe"=>"ニェ", "nxo"=>"ニォ",
|
91
|
-
"hwa"=>"ホヮ", "hwi"=>"ホィ", "hwu"=>"ホゥ", "hwe"=>"ホェ", "hwo"=>"ホォ",
|
92
|
-
"bha"=>"バー", "bhi"=>"ビー", "bhu"=>"ブー", "bhe"=>"ベー", "bho"=>"ボー",
|
93
|
-
"pwa"=>"プヮ", "pwi"=>"プィ", "pwu"=>"プゥ", "pwe"=>"プェ", "pwo"=>"プォ",
|
94
|
-
"pha"=>"ファ", "phi"=>"フィ", "phu"=>"フュ", "phe"=>"フェ", "pho"=>"フォ",
|
95
|
-
"vha"=>"ヒャ", "vhi"=>"ヒィ", "vhu"=>"ヒュ", "vhe"=>"ヒェ", "vho"=>"ヒョ",
|
96
|
-
"mha"=>"ムァ", "mhi"=>"ムィ", "mhu"=>"ムゥ", "mhe"=>"ムェ", "mho"=>"ムォ",
|
97
|
-
"mwa"=>"ムヮ", "mwi"=>"ムィ", "mwu"=>"ムゥ", "mwe"=>"ムェ", "mwo"=>"ムォ",
|
98
|
-
"rja"=>"リャ", "rji"=>"リィ", "rju"=>"リュ", "rje"=>"リェ", "rjo"=>"リョ",
|
99
|
-
"lja"=>"リャ", "lji"=>"リィ", "lju"=>"リュ", "lje"=>"リェ", "ljo"=>"リョ",
|
100
|
-
"wha"=>"ホワ", "whi"=>"ホイ", "whu"=>"ホウ", "whe"=>"ホエ", "who"=>"ホオ",
|
101
|
-
"wxa"=>"ヮ", "wxi"=>"ヰ", "wxu"=>"ゥ", "wxe"=>"ヱ", "wxo"=>"ウォ",
|
102
|
-
"xwa"=>"ヮ", "xwi"=>"ヰ", "xwu"=>"ゥ", "xwe"=>"ヱ", "xwo"=>"ウォ"
|
103
|
-
}
|
104
|
-
}
|
105
|
-
|
106
|
-
# @private
|
107
|
-
IAST_K = {
|
108
|
-
"Ā" => "A-", "ā" => "a-",
|
109
|
-
"Ī" => "I-", "ī" => "i-",
|
110
|
-
"Ū" => "U-", "ū" => "u-",
|
111
|
-
"E" => "e-", "e" => "e-",
|
112
|
-
"Ē" => "e-", "ē" => "e-",
|
113
|
-
"O" => "O-", "o" => "o-",
|
114
|
-
"Ō" => "O-", "ō" => "o-",
|
115
|
-
"Ṛ" => "R:", "ṛ" => "r:",
|
116
|
-
"Ṝ" => "R:-", "ṝ" => "r:-",
|
117
|
-
"R̥" => "R:", "r̥" => "r:",
|
118
|
-
"R̥̄" => "R:-", "r̥̄" => "r:-",
|
119
|
-
"Ḷ" => "L:", "ḷ" => "l:",
|
120
|
-
"Ḹ" => "L:", "ḹ" => "l:",
|
121
|
-
"Ṃ" => "M:", "ṃ" => "m:",
|
122
|
-
"Ṁ" => "M:", "ṁ" => "m:",
|
123
|
-
"Ḥ" => "H:", "ḥ" => "h:",
|
124
|
-
"C" => "Ch", "c" => "ch",
|
125
|
-
"Ṭ" => "T", "ṭ" => "t",
|
126
|
-
"Kh" => "K", "kh" => "k",
|
127
|
-
"Ch" => "Ch", "ch" => "ch",
|
128
|
-
"Ṭh" => "T", "ṭh" => "t",
|
129
|
-
"Th" => "T", "th" => "t",
|
130
|
-
"Ph" => "P", "ph" => "p",
|
131
|
-
"Ḍ" => "D", "ḍ" => "d",
|
132
|
-
"Gh" => "G", "gh" => "g",
|
133
|
-
"Jh" => "J", "jh" => "j",
|
134
|
-
"Ḍh" => "D", "ḍh" => "d",
|
135
|
-
"Dh" => "D", "dh" => "d",
|
136
|
-
"Bh" => "B", "bh" => "b",
|
137
|
-
"Ṅ" => "N", "ṅ" => "n",
|
138
|
-
"Ñ" => "Ny", "ñ" => "ny",
|
139
|
-
"Ṇ" => "N", "ṇ" => "n",
|
140
|
-
"Ś" => "Sh", "ś" => "sh",
|
141
|
-
"Ṣ" => "Sh", "ṣ" => "sh"
|
142
|
-
}
|
143
|
-
|
144
|
-
# @private
|
145
|
-
AKT_keys = transliteration_keys_hash(AKT)
|
146
|
-
|
147
|
-
# @private
|
148
|
-
IAST_K_keys = transliteration_keys(IAST_K)
|
149
|
-
|
150
|
-
#
|
151
|
-
# Convert AKT string to katakana scripts
|
152
|
-
#
|
153
|
-
def self.akt(string, locale='ja')
|
154
|
-
string.
|
155
|
-
|
156
|
-
gsub(
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
#
|
163
|
-
#
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
end
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
=begin
|
3
|
+
Copyright (C) 2014-2015 Takashi SUGA
|
4
|
+
|
5
|
+
You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
|
6
|
+
=end
|
7
|
+
|
8
|
+
require 'when_exe/locales/transliteration_table'
|
9
|
+
|
10
|
+
module When
|
11
|
+
module Locale
|
12
|
+
|
13
|
+
#
|
14
|
+
# AKT: Alphabet of Katakana Transliteration
|
15
|
+
#
|
16
|
+
# see { http://www.asahi-net.or.jp/~dy5h-kdm/end2.htm MadKod}
|
17
|
+
#
|
18
|
+
AKT = {
|
19
|
+
'ja' => {
|
20
|
+
"a" =>"ア", "i" =>"イ", "u" =>"ウ", "e" =>"エ", "o" =>"オ",
|
21
|
+
"ka" =>"カ", "ki" =>"キ", "ku" =>"ク", "ke" =>"ケ", "ko" =>"コ", "k" =>"ク",
|
22
|
+
"qa" =>"カ", "qi" =>"キ", "qu" =>"ク", "qe" =>"ケ", "qo" =>"コ", "q" =>"ク",
|
23
|
+
"ga" =>"ガ", "gi" =>"ギ", "gu" =>"グ", "ge" =>"ゲ", "go" =>"ゴ", "g" =>"グ",
|
24
|
+
"sa" =>"サ", "si" =>"シ", "su" =>"ス", "se" =>"セ", "so" =>"ソ", "s" =>"ス",
|
25
|
+
"za" =>"ザ", "zi" =>"ヂ", "zu" =>"ズ", "ze" =>"ゼ", "zo" =>"ゾ", "z" =>"ズ",
|
26
|
+
"ja" =>"ジャ", "ji" =>"ジ", "ju" =>"ジュ", "je" =>"ジェ", "jo" =>"ジョ", "j" =>"ジュ",
|
27
|
+
"ca" =>"カ", "ci" =>"チ", "cu" =>"ク", "ce" =>"セ", "co" =>"コ", "c" =>"ク",
|
28
|
+
"ta" =>"タ", "ti" =>"ティ", "tu" =>"トゥ", "te" =>"テ", "to" =>"ト", "t" =>"ト",
|
29
|
+
"tsa"=>"ツァ", "tsi"=>"ツィ", "tsu"=>"ツ", "tse"=>"ツェ", "tso"=>"ツォ", "ts"=>"ツ",
|
30
|
+
"da" =>"ダ", "di" =>"ディ", "du" =>"ドゥ", "de" =>"デ", "do" =>"ド", "d" =>"ド",
|
31
|
+
"na" =>"ナ", "ni" =>"ニ", "nu" =>"ヌ", "ne" =>"ネ", "no" =>"ノ", "n" =>"ン",
|
32
|
+
"ha" =>"ハ", "hi" =>"ヒ", "hu" =>"フ", "he" =>"ヘ", "ho" =>"ホ", "h" =>"フ",
|
33
|
+
"ba" =>"バ", "bi" =>"ビ", "bu" =>"ブ", "be" =>"ベ", "bo" =>"ボ", "b" =>"ブ",
|
34
|
+
"pa" =>"パ", "pi" =>"ピ", "pu" =>"プ", "pe" =>"ペ", "po" =>"ポ", "p" =>"プ",
|
35
|
+
"fa" =>"ファ", "fi" =>"フィ", "fu" =>"フ", "fe" =>"フェ", "fo" =>"フォ", "f" =>"フ",
|
36
|
+
"va" =>"ヴァ", "vi" =>"ヴィ", "vu" =>"ヴ", "ve" =>"ヴェ", "vo" =>"ヴォ", "v" =>"ヴ",
|
37
|
+
"ma" =>"マ", "mi" =>"ミ", "mu" =>"ム", "me" =>"メ", "mo" =>"モ", "m" =>"ム",
|
38
|
+
"mma"=>"ンマ", "mmi"=>"ンミ", "mmu"=>"ンム", "mme"=>"ンメ", "mmo"=>"ンモ",
|
39
|
+
"ra" =>"ラ", "ri" =>"リ", "ru" =>"ル", "re" =>"レ", "ro" =>"ロ", "r" =>"ル",
|
40
|
+
"la" =>"ラ", "li" =>"リ", "lu" =>"ル", "le" =>"レ", "lo" =>"ロ", "l" =>"ル",
|
41
|
+
"wa" =>"ワ", "wi" =>"ウィ", "wu" =>"ゥ", "we" =>"ウェ", "wo" =>"ヲ", "w" =>"ゥ",
|
42
|
+
"wwa"=>"ウヮ", "wwi"=>"ウィ", "wwu"=>"ウゥ", "wwe"=>"ウェ", "wwo"=>"ウォ",
|
43
|
+
"xa" =>"ァ", "xi" =>"ィ", "xu" =>"ゥ", "xe" =>"ェ", "xo" =>"ォ", "x" =>"クス",
|
44
|
+
"ya" =>"ヤ", "yu" =>"ユ", "yo" =>"ヨ", "y" =>"イ",
|
45
|
+
"kya"=>"キャ", "kyu"=>"キュ", "kyo"=>"キョ",
|
46
|
+
"kja"=>"キャ", "kvu"=>"キュ", "kjo"=>"キョ",
|
47
|
+
"qja"=>"キャ", "qju"=>"キュ", "qjo"=>"キョ",
|
48
|
+
"gya"=>"ギャ", "gyu"=>"ギュ", "gyo"=>"ギョ",
|
49
|
+
"gja"=>"ギャ", "gju"=>"ギュ", "gjo"=>"ギョ",
|
50
|
+
"sya"=>"シャ", "syu"=>"シュ", "syo"=>"ショ",
|
51
|
+
"sja"=>"シャ", "sju"=>"シュ", "sjo"=>"ショ",
|
52
|
+
"zya"=>"ジャ", "zyu"=>"ジュ", "zyo"=>"ジョ",
|
53
|
+
"zja"=>"ヂャ", "zju"=>"ヂュ", "zjo"=>"ヂョ",
|
54
|
+
"jya"=>"ジャ", "jyu"=>"ジュ", "jye"=>"ジェ", "jyo"=>"ジョ",
|
55
|
+
"cyi"=>"チィ", "cyu"=>"チュ", "tyi"=>"ティ",
|
56
|
+
"tyu"=>"テュ", "tye"=>"テェ", "tja"=>"チャ",
|
57
|
+
"tju"=>"チュ", "tjo"=>"チョ", "-" =>"ー", "tsx"=>"ッ",
|
58
|
+
"dyi"=>"ディ", "dyu"=>"デュ", "dye"=>"デェ",
|
59
|
+
"dja"=>"ヂャ", "dju"=>"ヂュ", "djo"=>"ヂョ",
|
60
|
+
"nya"=>"ニャ", "nyu"=>"ニュ", "nyo"=>"ニョ",
|
61
|
+
"nva"=>"ニャ", "nvu"=>"ニュ", "nvo"=>"ニョ",
|
62
|
+
"hya"=>"ヒャ", "hyu"=>"ヒュ", "hyo"=>"ヒョ",
|
63
|
+
"bya"=>"ビャ", "byu"=>"ビュ", "byo"=>"ビョ",
|
64
|
+
"pya"=>"ピャ", "pyu"=>"ピュ", "pyo"=>"ピョ",
|
65
|
+
"fyu"=>"フュ", "vyu"=>"ヴュ",
|
66
|
+
"mya"=>"ミャ", "myu"=>"ミュ", "myo"=>"ミョ",
|
67
|
+
"mva"=>"ミャ", "mvu"=>"ミュ", "mvo"=>"ミョ",
|
68
|
+
"rya"=>"リャ", "ryu"=>"リュ", "ryo"=>"リョ",
|
69
|
+
"lya"=>"リャ", "lyu"=>"リュ", "lyo"=>"リョ",
|
70
|
+
"wyi"=>"ウイ", "wyu"=>"ウユ", "wye"=>"ウエ",
|
71
|
+
"xya"=>"ャ", "xyu"=>"ュ", "xyo"=>"ョ",
|
72
|
+
"yya"=>"イャ", "yyi"=>"イィ", "yyu"=>"イュ", "yye"=>"イェ", "yyo"=>"イョ",
|
73
|
+
"kwa"=>"クヮ", "kwi"=>"クィ", "kwu"=>"クゥ", "kwe"=>"クェ", "kwo"=>"クォ",
|
74
|
+
"kha"=>"クァ", "khi"=>"クィ", "khu"=>"クゥ", "khe"=>"クェ", "kho"=>"クォ",
|
75
|
+
"qha"=>"クァ", "qhi"=>"クィ", "qhu"=>"クゥ", "qhe"=>"クェ", "qho"=>"クォ",
|
76
|
+
"gwa"=>"グヮ", "gwi"=>"グィ", "gwu"=>"グゥ", "gwe"=>"グェ", "gwo"=>"グォ",
|
77
|
+
"gha"=>"グァ", "ghi"=>"グィ", "ghu"=>"グゥ", "ghe"=>"グェ", "gho"=>"グォ",
|
78
|
+
"sha"=>"シャ", "shi"=>"シ", "shu"=>"シュ", "she"=>"シェ", "sho"=>"ショ", "sh"=>"シュ",
|
79
|
+
"swa"=>"スワ", "swi"=>"スィ", "swu"=>"スゥ", "swe"=>"スェ", "swo"=>"スヲ",
|
80
|
+
"zha"=>"ツァ", "zhi"=>"ツィ", "zhu"=>"ズゥ", "zhe"=>"ツェ", "zho"=>"ツォ",
|
81
|
+
"zxa"=>"ツァ", "zxi"=>"ツィ", "zxu"=>"ズゥ", "zxe"=>"ツェ", "zxo"=>"ツォ",
|
82
|
+
"jxa"=>"ジァ", "jxi"=>"ジィ", "jxu"=>"ジゥ", "jxe"=>"ジェ", "jxo"=>"ジォ",
|
83
|
+
"cha"=>"チャ", "chi"=>"チ", "chu"=>"チュ", "che"=>"チェ", "cho"=>"チョ",
|
84
|
+
"twa"=>"トワ", "twi"=>"ツイ", "twu"=>"トゥ", "twe"=>"ツエ", "two"=>"ツー",
|
85
|
+
"tha"=>"スァ", "thi"=>"スィ", "thu"=>"スゥ", "the"=>"スェ", "tho"=>"スォ",
|
86
|
+
"tza"=>"ツァ", "tzi"=>"ツィ", "tzu"=>"ズー", "tze"=>"ツェ", "tzo"=>"ツォ",
|
87
|
+
"dwa"=>"ドワ", "dwi"=>"ドィ", "dwu"=>"ドゥ", "dwe"=>"ドェ", "dwo"=>"ドヲ",
|
88
|
+
"dha"=>"ダー", "dhi"=>"ジー", "dhu"=>"ドフ", "dhe"=>"ドヘ", "dho"=>"ドホ",
|
89
|
+
"dsa"=>"ドサ", "dsi"=>"ドシ", "dsu"=>"ズ", "dse"=>"ドセ", "dso"=>"ドソ",
|
90
|
+
"nxa"=>"ニァ", "nxi"=>"ニィ", "nxu"=>"ニゥ", "nxe"=>"ニェ", "nxo"=>"ニォ",
|
91
|
+
"hwa"=>"ホヮ", "hwi"=>"ホィ", "hwu"=>"ホゥ", "hwe"=>"ホェ", "hwo"=>"ホォ",
|
92
|
+
"bha"=>"バー", "bhi"=>"ビー", "bhu"=>"ブー", "bhe"=>"ベー", "bho"=>"ボー",
|
93
|
+
"pwa"=>"プヮ", "pwi"=>"プィ", "pwu"=>"プゥ", "pwe"=>"プェ", "pwo"=>"プォ",
|
94
|
+
"pha"=>"ファ", "phi"=>"フィ", "phu"=>"フュ", "phe"=>"フェ", "pho"=>"フォ",
|
95
|
+
"vha"=>"ヒャ", "vhi"=>"ヒィ", "vhu"=>"ヒュ", "vhe"=>"ヒェ", "vho"=>"ヒョ",
|
96
|
+
"mha"=>"ムァ", "mhi"=>"ムィ", "mhu"=>"ムゥ", "mhe"=>"ムェ", "mho"=>"ムォ",
|
97
|
+
"mwa"=>"ムヮ", "mwi"=>"ムィ", "mwu"=>"ムゥ", "mwe"=>"ムェ", "mwo"=>"ムォ",
|
98
|
+
"rja"=>"リャ", "rji"=>"リィ", "rju"=>"リュ", "rje"=>"リェ", "rjo"=>"リョ",
|
99
|
+
"lja"=>"リャ", "lji"=>"リィ", "lju"=>"リュ", "lje"=>"リェ", "ljo"=>"リョ",
|
100
|
+
"wha"=>"ホワ", "whi"=>"ホイ", "whu"=>"ホウ", "whe"=>"ホエ", "who"=>"ホオ",
|
101
|
+
"wxa"=>"ヮ", "wxi"=>"ヰ", "wxu"=>"ゥ", "wxe"=>"ヱ", "wxo"=>"ウォ",
|
102
|
+
"xwa"=>"ヮ", "xwi"=>"ヰ", "xwu"=>"ゥ", "xwe"=>"ヱ", "xwo"=>"ウォ"
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
# @private
|
107
|
+
IAST_K = {
|
108
|
+
"Ā" => "A-", "ā" => "a-",
|
109
|
+
"Ī" => "I-", "ī" => "i-",
|
110
|
+
"Ū" => "U-", "ū" => "u-",
|
111
|
+
"E" => "e-", "e" => "e-",
|
112
|
+
"Ē" => "e-", "ē" => "e-",
|
113
|
+
"O" => "O-", "o" => "o-",
|
114
|
+
"Ō" => "O-", "ō" => "o-",
|
115
|
+
"Ṛ" => "R:", "ṛ" => "r:",
|
116
|
+
"Ṝ" => "R:-", "ṝ" => "r:-",
|
117
|
+
"R̥" => "R:", "r̥" => "r:",
|
118
|
+
"R̥̄" => "R:-", "r̥̄" => "r:-",
|
119
|
+
"Ḷ" => "L:", "ḷ" => "l:",
|
120
|
+
"Ḹ" => "L:", "ḹ" => "l:",
|
121
|
+
"Ṃ" => "M:", "ṃ" => "m:",
|
122
|
+
"Ṁ" => "M:", "ṁ" => "m:",
|
123
|
+
"Ḥ" => "H:", "ḥ" => "h:",
|
124
|
+
"C" => "Ch", "c" => "ch",
|
125
|
+
"Ṭ" => "T", "ṭ" => "t",
|
126
|
+
"Kh" => "K", "kh" => "k",
|
127
|
+
"Ch" => "Ch", "ch" => "ch",
|
128
|
+
"Ṭh" => "T", "ṭh" => "t",
|
129
|
+
"Th" => "T", "th" => "t",
|
130
|
+
"Ph" => "P", "ph" => "p",
|
131
|
+
"Ḍ" => "D", "ḍ" => "d",
|
132
|
+
"Gh" => "G", "gh" => "g",
|
133
|
+
"Jh" => "J", "jh" => "j",
|
134
|
+
"Ḍh" => "D", "ḍh" => "d",
|
135
|
+
"Dh" => "D", "dh" => "d",
|
136
|
+
"Bh" => "B", "bh" => "b",
|
137
|
+
"Ṅ" => "N", "ṅ" => "n",
|
138
|
+
"Ñ" => "Ny", "ñ" => "ny",
|
139
|
+
"Ṇ" => "N", "ṇ" => "n",
|
140
|
+
"Ś" => "Sh", "ś" => "sh",
|
141
|
+
"Ṣ" => "Sh", "ṣ" => "sh"
|
142
|
+
}
|
143
|
+
|
144
|
+
# @private
|
145
|
+
AKT_keys = transliteration_keys_hash(AKT)
|
146
|
+
|
147
|
+
# @private
|
148
|
+
IAST_K_keys = transliteration_keys(IAST_K)
|
149
|
+
|
150
|
+
#
|
151
|
+
# Convert AKT string to katakana scripts
|
152
|
+
#
|
153
|
+
def self.akt(string, locale='ja')
|
154
|
+
string.downcase.
|
155
|
+
gsub(/([^aeiou])\1/, 'ッ\1').
|
156
|
+
gsub(/m([fpb])/, 'n\1').
|
157
|
+
gsub(AKT_keys[locale]) {|code|
|
158
|
+
AKT[locale][code] || code
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# Convert IAST string to katakana scripts
|
164
|
+
#
|
165
|
+
def self.iast_akt(string, locale='ja')
|
166
|
+
akt(
|
167
|
+
string.gsub(IAST_K_keys) {|code| IAST_K[code] || code}.
|
168
|
+
downcase.gsub(/(.):-?(.)|(.):-?\z/) {|code|
|
169
|
+
"aeiou".index($2||':') ? $1 + $2 :
|
170
|
+
$1=='m' ? "ン#{$2}" :
|
171
|
+
code.sub(':','i')
|
172
|
+
}.
|
173
|
+
gsub(/([rm])y/, '\1uy'),
|
174
|
+
locale)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -1,751 +1,751 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
=begin
|
3
|
-
Copyright (C) 2011-
|
4
|
-
|
5
|
-
You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
|
6
|
-
=end
|
7
|
-
|
8
|
-
require 'when_exe/locales/encoding_conversion'
|
9
|
-
|
10
|
-
module When
|
11
|
-
|
12
|
-
#
|
13
|
-
# Multilingualization(M17n) 対応モジュール
|
14
|
-
#
|
15
|
-
# When::BasicTypes::M17n の実装のうち When::BasicTypes 内部で
|
16
|
-
# 定義すべきでない部分を切り出してモジュールとしている
|
17
|
-
#
|
18
|
-
module Locale
|
19
|
-
|
20
|
-
# Locale 読み替えの初期設定
|
21
|
-
DefaultAlias = {'alias'=>'ja', '日本語'=>'ja', '英語'=>'en'}
|
22
|
-
|
23
|
-
# 省略時 Namespace
|
24
|
-
DefaultNamespaces = Hash.new {|hash, key|
|
25
|
-
hash[key] = "http://#{key}.wikipedia.org/wiki/"
|
26
|
-
}.update({
|
27
|
-
'mailto' => false,
|
28
|
-
'https' => false,
|
29
|
-
'http' => false,
|
30
|
-
'ftp' => false
|
31
|
-
})
|
32
|
-
|
33
|
-
# 漢字の包摂
|
34
|
-
DefaultUnification = {
|
35
|
-
'煕'=>'熙', '廣'=>'広', '寶'=>'宝', '國'=>'国',
|
36
|
-
'應'=>'応', '觀'=>'観', '龜'=>'亀', '齊'=>'斉',
|
37
|
-
'靈'=>'霊', '攝'=>'摂', '壽'=>'寿', '萬'=>'万',
|
38
|
-
'廢'=>'廃', '顯'=>'顕', '會'=>'会', '聰'=>'聡',
|
39
|
-
'總'=>'総', '證'=>'証', '禮'=>'礼', '與'=>'与',
|
40
|
-
'竜'=>'龍'
|
41
|
-
}
|
42
|
-
|
43
|
-
# Escape
|
44
|
-
# @private
|
45
|
-
Escape = {
|
46
|
-
"\\\\" => "\\",
|
47
|
-
"\\n" => "\n",
|
48
|
-
"\\r" => "\r",
|
49
|
-
"\\," => ","
|
50
|
-
}
|
51
|
-
|
52
|
-
# Wikipedia の URL の正規表現
|
53
|
-
# @private
|
54
|
-
Ref = /\Ahttp:\/\/(.+?)\.wikipedia\.org\/wiki\/([^#]+?)\z/
|
55
|
-
|
56
|
-
# Wikipedia の多言語リンクの正規表現
|
57
|
-
# @private
|
58
|
-
Link = /<li class="interlanguage-link interwiki-(.+?)"><a href="\/\/(.+?)\.wikipedia\.org\/wiki\/(.+?)" title="(.+?) – /
|
59
|
-
|
60
|
-
class << self
|
61
|
-
|
62
|
-
# Wikipedia の連続的な参照を抑制するための遅延時間/秒
|
63
|
-
#
|
64
|
-
# @return [Numeric]
|
65
|
-
#
|
66
|
-
attr_accessor :wikipedia_interval
|
67
|
-
|
68
|
-
# When::Locale Module のグローバルな設定を行う
|
69
|
-
#
|
70
|
-
# @param [Hash] options 下記の通り
|
71
|
-
# @option options [Hash] :alias Locale の読み替えパターンを Hash で指定する。
|
72
|
-
# @option options [String] :namespace_foramt 名前空間定義の省略時に名前空間生成に用いる書式
|
73
|
-
# @option options [Hash] :unification 漢字の包摂パターンを Hash で指定する。
|
74
|
-
# @option options [Numeric] :wikipedia_interval Wikipedia の連続的な参照を抑制するための遅延時間/秒
|
75
|
-
#
|
76
|
-
# @note
|
77
|
-
# :alias の指定がない場合、aliases は DefaultAlias(モジュール定数)と解釈する。
|
78
|
-
# :unification の指定がない場合、unifications は DefaultUnification(モジュール定数)と解釈する。
|
79
|
-
#
|
80
|
-
def _setup_(options={})
|
81
|
-
@aliases = options[:alias] || DefaultAlias
|
82
|
-
@namespaces = options[:namespace_foramt] || DefaultNamespaces
|
83
|
-
@unifications = options[:unification] || DefaultUnification
|
84
|
-
@wikipedia_interval = options[:wikipedia_interval]
|
85
|
-
end
|
86
|
-
|
87
|
-
# 設定情報を取得する
|
88
|
-
#
|
89
|
-
# @return [Hash] 設定情報
|
90
|
-
#
|
91
|
-
def _setup_info
|
92
|
-
{:alias => _alias,
|
93
|
-
:namespace_foramt => _namespaces,
|
94
|
-
:unification => _unification,
|
95
|
-
:wikipedia_interval => @wikipedia_interval}
|
96
|
-
end
|
97
|
-
|
98
|
-
# 特定 locale に対応した文字列の取得
|
99
|
-
#
|
100
|
-
# @param [String] source もとにする String または M17n
|
101
|
-
#
|
102
|
-
# @param[String] loc locale の指定 ( lang[-|_]country.encode )
|
103
|
-
# [ lang - 言語 ]
|
104
|
-
# [ country - 国(省略可) ]
|
105
|
-
# [ encode - 文字コード(省略可) ]
|
106
|
-
#
|
107
|
-
# @return [String] loc に対応した文字列
|
108
|
-
#
|
109
|
-
# @note source が Hash や Array の場合、その構成要素を変換して返す
|
110
|
-
# @note encode は通常大文字だが、大文字/小文字の変換は行わず指定されたまま使用している
|
111
|
-
#
|
112
|
-
def translate(source, loc='')
|
113
|
-
return source unless loc
|
114
|
-
case source
|
115
|
-
when Hash
|
116
|
-
result = {}
|
117
|
-
source.each_pair do |key, value|
|
118
|
-
result[translate(key, loc)] = translate(value, loc)
|
119
|
-
end
|
120
|
-
return result
|
121
|
-
when Array
|
122
|
-
return source.map {|value| translate(value, loc)}
|
123
|
-
when Locale
|
124
|
-
return source.translate(loc)
|
125
|
-
when String
|
126
|
-
return source.encode($1) if loc =~ /\.(.+)\z/
|
127
|
-
end
|
128
|
-
source
|
129
|
-
end
|
130
|
-
|
131
|
-
# 包摂リストに登録されている文字を包摂する
|
132
|
-
#
|
133
|
-
# @param [When::Locale] source 文字を包摂しようとする国際化文字列
|
134
|
-
# @param [String] source 文字を包摂しようとする文字列
|
135
|
-
# @param [Regexp] source 文字を包摂しようとする正規表現
|
136
|
-
# @param [Hash] pattern 包摂ルール
|
137
|
-
#
|
138
|
-
# @return [When::Locale] 文字を包摂した国際化文字列
|
139
|
-
# @return [String] 文字を包摂した文字列
|
140
|
-
# @return [Regexp] 文字を包摂した正規表現
|
141
|
-
#
|
142
|
-
def ideographic_unification(source, pattern=_unification)
|
143
|
-
case source
|
144
|
-
when When::Locale
|
145
|
-
source.ideographic_unification(pattern)
|
146
|
-
when Regexp
|
147
|
-
Regexp.compile(ideographic_unification(source.source.encode('UTF-8'), pattern), source.options)
|
148
|
-
when String
|
149
|
-
source.gsub(/./) do |c|
|
150
|
-
pattern[c] ? pattern[c] : c
|
151
|
-
end
|
152
|
-
else
|
153
|
-
source
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
# 文字列で表現された namespace 指定を Hash に変換する
|
158
|
-
# @private
|
159
|
-
def _namespace(source=nil)
|
160
|
-
case source
|
161
|
-
when Hash ; source
|
162
|
-
when nil ; {}
|
163
|
-
when String
|
164
|
-
namespace = {}
|
165
|
-
source = $1 if (source=~/\A\s*\[?(.+?)\]?\s*\z/m)
|
166
|
-
source.split(/[\n\r,]+/).each do |v|
|
167
|
-
v.strip!
|
168
|
-
next if (v=~/\A#/)
|
169
|
-
pair = [''] + v.split(/\s*=\s*/, 2)
|
170
|
-
namespace[pair[-2]] = pair[-1]
|
171
|
-
end
|
172
|
-
namespace
|
173
|
-
when When::Parts::Resource::ContentLine
|
174
|
-
source.object.names
|
175
|
-
else ; raise TypeError, "Irregal Namespace Type: #{source.class}"
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
# locale 指定を Array に変換する
|
180
|
-
# @private
|
181
|
-
def _locale(source=nil)
|
182
|
-
# default の Locale
|
183
|
-
return [[nil, '', nil]] unless source
|
184
|
-
|
185
|
-
# source の配列化
|
186
|
-
if source.kind_of?(String)
|
187
|
-
source = $1 if (source=~/\A\s*\[?(.+?)\]?\s*\z/m)
|
188
|
-
source = source.scan(/((?:[^\\\n\r,]|\\.)+)(?:[\n\r,]+(?!\z))?|[\n\r,]+/m).flatten.map {|token|
|
189
|
-
(token||'').gsub(/\\./) {|escape| Escape[escape] || escape}
|
190
|
-
}
|
191
|
-
end
|
192
|
-
|
193
|
-
# 各Localeの展開
|
194
|
-
source.map {|v|
|
195
|
-
if v.kind_of?(String)
|
196
|
-
v = v.strip
|
197
|
-
next if (v=~/\A#/)
|
198
|
-
(v =~ /\A(\*)?(.*?)(?:\s*=\s*(.*))?\z/) ? $~[1..3] : [[nil, '', nil]]
|
199
|
-
else
|
200
|
-
v
|
201
|
-
end
|
202
|
-
}.compact
|
203
|
-
end
|
204
|
-
|
205
|
-
# 文字列 [.., .., ..] を分割する
|
206
|
-
# @private
|
207
|
-
def _split(source)
|
208
|
-
line = source.dup
|
209
|
-
return [line] unless line =~ /,/
|
210
|
-
list = []
|
211
|
-
b = d = s = 0
|
212
|
-
(source.length-1).downto(0) do |i|
|
213
|
-
bs = 0
|
214
|
-
(i-1).downto(0) do |k|
|
215
|
-
break unless (line[k,1] == '\\')
|
216
|
-
bs += 1
|
217
|
-
end
|
218
|
-
next if (bs[0] == 1)
|
219
|
-
case line[i,1]
|
220
|
-
when "'" ; s = 1-s if (d == 0)
|
221
|
-
when '"' ; d = 1-d if (s == 0)
|
222
|
-
when ']','}',')' ; b += 1 if (d+s == 0)
|
223
|
-
when '[','{','(' ; b -= 1 if (d+s == 0 && b > 0)
|
224
|
-
when ','
|
225
|
-
if (b+d+s == 0)
|
226
|
-
list.unshift(line[i+1..-1])
|
227
|
-
line = i > 0 ? line[0..i-1] : ''
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
231
|
-
list.unshift(line)
|
232
|
-
end
|
233
|
-
|
234
|
-
# locale 指定を解析して Hash の値を取り出す
|
235
|
-
# @private
|
236
|
-
def _hash_value(hash, locale, defaults=['', 'en'])
|
237
|
-
locale = locale.sub(/\..*/, '')
|
238
|
-
return hash[locale] if hash[locale]
|
239
|
-
return _hash_value(hash, _alias[locale], defaults) if _alias[locale]
|
240
|
-
language = locale.sub(/-.*/, '')
|
241
|
-
return hash[language] if hash[language]
|
242
|
-
defaults.each do |default|
|
243
|
-
return hash[default] if hash[default]
|
244
|
-
end
|
245
|
-
return nil
|
246
|
-
end
|
247
|
-
|
248
|
-
# 漢字の包摂パターン
|
249
|
-
# @private
|
250
|
-
def _unification
|
251
|
-
@unifications ||= DefaultUnification
|
252
|
-
end
|
253
|
-
|
254
|
-
# @private
|
255
|
-
def _get_locale(locale, access_key)
|
256
|
-
return nil unless access_key
|
257
|
-
access_key = access_key.split(/\//).map {|key| key =~ /\A[0-9]+\z/ ? key.to_i : key}
|
258
|
-
locale = locale.sub(/\..*/, '')
|
259
|
-
[locale, locale.sub(/-.*/, '')].each do |loc|
|
260
|
-
symbol = ('Locale_' + loc.sub(/-/,'_')).to_sym
|
261
|
-
return {locale=>access_key.inject(const_get(symbol)) {|hash, key| hash = hash[key]}} if const_defined?(symbol)
|
262
|
-
end
|
263
|
-
return nil
|
264
|
-
end
|
265
|
-
|
266
|
-
private
|
267
|
-
|
268
|
-
# Locale の読み替えパターン
|
269
|
-
def _alias
|
270
|
-
@aliases ||= DefaultAlias
|
271
|
-
end
|
272
|
-
|
273
|
-
# 名前空間定義の省略時に名前空間生成に用いる書式
|
274
|
-
def _namespaces
|
275
|
-
@namespaces ||= DefaultNamespaces
|
276
|
-
end
|
277
|
-
|
278
|
-
# wikipedia オブジェクトの生成・参照
|
279
|
-
def wikipedia_object(path, options={})
|
280
|
-
query = options.delete(:query)
|
281
|
-
interval = options.key?(:interval) ? options.delete(:interval) : @wikipedia_interval
|
282
|
-
return nil unless Object.const_defined?(:JSON) && path =~ Ref
|
283
|
-
_wikipedia_relation(_wikipedia_object(path, $1, $2, query, interval, options), path, query)
|
284
|
-
end
|
285
|
-
|
286
|
-
# wikipedia の読み込み
|
287
|
-
def _wikipedia_object(path, locale, file, query, interval, options)
|
288
|
-
# 採取済みデータ
|
289
|
-
title = URI.decode(file.gsub('_', ' '))
|
290
|
-
mode = "".respond_to?(:force_encoding) ? ':utf-8' : ''
|
291
|
-
dir = When::Parts::Resource.root_dir + '/data/wikipedia/' + locale
|
292
|
-
FileUtils.mkdir_p(dir) unless FileTest.exist?(dir)
|
293
|
-
|
294
|
-
open("#{dir}/#{file}.json", 'r'+mode) do |source|
|
295
|
-
json = JSON.parse(source.read)
|
296
|
-
json.update(Hash[*query.split('&').map {|pair| pair.split('=')}.flatten]) if query
|
297
|
-
json.key?('names') ?
|
298
|
-
When::BasicTypes::M17n.new(json) :
|
299
|
-
When::Coordinates::Spatial.new(json)
|
300
|
-
end
|
301
|
-
|
302
|
-
rescue => no_file_error
|
303
|
-
# 新しいデータ
|
304
|
-
case interval
|
305
|
-
when 0
|
306
|
-
raise no_file_error
|
307
|
-
when Numeric
|
308
|
-
if @wikipedia_last_access
|
309
|
-
delay = (@wikipedia_last_access + interval.abs - Time.now.to_f).ceil
|
310
|
-
sleep(delay) if delay > 0
|
311
|
-
end
|
312
|
-
end
|
313
|
-
contents = nil
|
314
|
-
begin
|
315
|
-
OpenURI
|
316
|
-
source = open(path, 'r'+mode)
|
317
|
-
contents = source.read
|
318
|
-
ensure
|
319
|
-
@wikipedia_last_access = Time.now.to_f
|
320
|
-
source.close if source
|
321
|
-
end
|
322
|
-
|
323
|
-
# wikipedia contents
|
324
|
-
raise KeyError, 'Article not found: ' + title if contents =~ /<div class="noarticletext">/
|
325
|
-
|
326
|
-
# word
|
327
|
-
word = {
|
328
|
-
:label => title,
|
329
|
-
:names => {''=>title, locale=>title},
|
330
|
-
:link => {''=>path, locale=>path }
|
331
|
-
}
|
332
|
-
contents.scan(Link) do |link|
|
333
|
-
word[:names][$
|
334
|
-
word[:link ][$
|
335
|
-
end
|
336
|
-
object = When::BasicTypes::M17n.new(word)
|
337
|
-
|
338
|
-
# location
|
339
|
-
if contents =~ /tools\.wmflabs\.org\/geohack\/geohack\.php\?.+?params=(.+?[NS])_(.+?[EW])/
|
340
|
-
location = {
|
341
|
-
:label => object
|
342
|
-
}
|
343
|
-
location[:lat], location[:long] = $~[1..2].map {|pos|
|
344
|
-
pos.gsub(/_(\d)[._]/, '_0\1_').sub('.', '_').sub('_', '.').gsub('_', '')
|
345
|
-
}
|
346
|
-
object = When::Coordinates::Spatial.new(location)
|
347
|
-
end
|
348
|
-
|
349
|
-
# save data
|
350
|
-
open("#{dir}/#{file}.json", 'w'+mode) do |source|
|
351
|
-
source.write(JSON.dump(object.to_h({:method=>:to_h}).update(options)))
|
352
|
-
end
|
353
|
-
query ? _wikipedia_object(path, locale, file, query) : object
|
354
|
-
end
|
355
|
-
|
356
|
-
# wikipedia オブジェクトの関連付け
|
357
|
-
def _wikipedia_relation(object, path, query)
|
358
|
-
code_space = path.sub(/[^\/]+\z/, '')
|
359
|
-
if object.kind_of?(When::Coordinates::Spatial)
|
360
|
-
object.label._pool['..'] = object
|
361
|
-
object._pool[object.label.to_s] = object.label
|
362
|
-
object.send(:child=, [object.label])
|
363
|
-
object.label.send(:code_space=, code_space)
|
364
|
-
else
|
365
|
-
object.send(:code_space=, code_space)
|
366
|
-
end
|
367
|
-
object._pool['..'] = path
|
368
|
-
object._pool['..'] += '?' + query if query
|
369
|
-
object
|
370
|
-
end
|
371
|
-
end
|
372
|
-
|
373
|
-
# ローケール指定時の文字列
|
374
|
-
#
|
375
|
-
# @return [Hash]
|
376
|
-
attr_reader :names
|
377
|
-
|
378
|
-
# 有効なローケール指定
|
379
|
-
#
|
380
|
-
# @return [Array<String>]
|
381
|
-
attr_reader :keys
|
382
|
-
|
383
|
-
# 有効な文字列 - additional attribute
|
384
|
-
#
|
385
|
-
# @return [Array<String>]
|
386
|
-
attr_reader :values
|
387
|
-
|
388
|
-
# 文字列の説明 - additional attribute
|
389
|
-
#
|
390
|
-
# @return [Hash] { anyURI }
|
391
|
-
attr_reader :link
|
392
|
-
|
393
|
-
# Rails 用 I18n 定義へのアクセス・キー
|
394
|
-
#
|
395
|
-
# @return [String]
|
396
|
-
attr_reader :access_key
|
397
|
-
protected :access_key
|
398
|
-
|
399
|
-
# 特定 locale に対応した文字列の取得
|
400
|
-
#
|
401
|
-
# @param [String] loc locale の指定 ( lang[-|_]country.encode )
|
402
|
-
# [ lang - 言語 ]
|
403
|
-
# [ country - 国(省略可) ]
|
404
|
-
# [ encode - 文字コード(省略可) ]
|
405
|
-
#
|
406
|
-
# @return [String] loc に対応した文字列
|
407
|
-
#
|
408
|
-
def translate(loc='')
|
409
|
-
return to_s unless loc
|
410
|
-
loc = loc.sub('_', '-')
|
411
|
-
lang, code = loc.split(/\./)
|
412
|
-
result = _label_value(loc)
|
413
|
-
return result if !code || @names.member?(loc)
|
414
|
-
return result.encode(code)
|
415
|
-
end
|
416
|
-
alias :/ :translate
|
417
|
-
|
418
|
-
# 特定 locale に対応した reference URI の取得
|
419
|
-
#
|
420
|
-
# @param [String] loc locale の指定
|
421
|
-
#
|
422
|
-
# @return [String] loc に対応した reference URI
|
423
|
-
#
|
424
|
-
def reference(loc='')
|
425
|
-
loc ||= ''
|
426
|
-
return Locale._hash_value(@link, loc.sub('_', '-'))
|
427
|
-
end
|
428
|
-
|
429
|
-
# 部分文字列
|
430
|
-
#
|
431
|
-
# @param [Range] range String#[] と同様の指定方法で範囲を指定する
|
432
|
-
#
|
433
|
-
# @return [When::Locale] 指定範囲に対応した部分文字列
|
434
|
-
#
|
435
|
-
def [](range)
|
436
|
-
dup._copy({
|
437
|
-
:label => to_s[range],
|
438
|
-
:names => @names.keys.inject({}) {|l,k|
|
439
|
-
l[k] = @names[k][range]
|
440
|
-
l
|
441
|
-
}
|
442
|
-
})
|
443
|
-
end
|
444
|
-
|
445
|
-
# 文字列の一致
|
446
|
-
#
|
447
|
-
# @param [String, Regexp] regexp マッチする正規表現
|
448
|
-
#
|
449
|
-
# @return [Integer] マッチした位置のindex(いずれかの locale でマッチが成功した場合)
|
450
|
-
# @return [nil] すべての locale でマッチに失敗した場合
|
451
|
-
#
|
452
|
-
def =~(regexp)
|
453
|
-
@keys.each do |key|
|
454
|
-
index = (@names[key] =~ regexp)
|
455
|
-
return index if index
|
456
|
-
end
|
457
|
-
return nil
|
458
|
-
end
|
459
|
-
|
460
|
-
# 部分文字列の位置
|
461
|
-
#
|
462
|
-
# @param [String] other 部分文字列
|
463
|
-
#
|
464
|
-
# @return [Integer] 部分文字列の先頭のindex(いずれかの locale で部分文字列を含んだ場合)
|
465
|
-
# @return [nil] すべての locale で部分文字列を含まない場合
|
466
|
-
#
|
467
|
-
def index(other)
|
468
|
-
@keys.each do |key|
|
469
|
-
index = @names[key].index(Locale.translate(other, key))
|
470
|
-
return index if index
|
471
|
-
end
|
472
|
-
return nil
|
473
|
-
end
|
474
|
-
|
475
|
-
# 文字列の連結
|
476
|
-
#
|
477
|
-
# @param [String, When::Toos::Locale] other 連結する文字列
|
478
|
-
#
|
479
|
-
# @return [When::Toos::Locale] 連結された文字列
|
480
|
-
#
|
481
|
-
def +(other)
|
482
|
-
names = {}
|
483
|
-
case other
|
484
|
-
when Locale
|
485
|
-
(@names.keys + other.names.keys).uniq.each do |key|
|
486
|
-
names[key] = _label_value(key) + other._label_value(key)
|
487
|
-
end
|
488
|
-
links = other.link
|
489
|
-
else
|
490
|
-
@names.keys.each do |key|
|
491
|
-
names[key] = _label_value(key) + other.to_s
|
492
|
-
end
|
493
|
-
links = {}
|
494
|
-
end
|
495
|
-
return dup._copy({:names=>names, :link=>links.merge(link), :label=>to_s + other.to_s})
|
496
|
-
end
|
497
|
-
|
498
|
-
# 書式指定による文字列化
|
499
|
-
#
|
500
|
-
# @param [Array<Object>] other 文字列化する Object の Array
|
501
|
-
# @param [Array<String>] locale 文字列化を行う locale の指定(デフォルト : すべて)
|
502
|
-
#
|
503
|
-
# @return [When::Toos::Locale] 文字列化された Object
|
504
|
-
#
|
505
|
-
def _printf(other, locale=nil)
|
506
|
-
# 処理する配列
|
507
|
-
terms = other.kind_of?(Array) ? [self] + other : [self, other]
|
508
|
-
|
509
|
-
# locale key の配列
|
510
|
-
if locale == []
|
511
|
-
keys = []
|
512
|
-
else
|
513
|
-
keys = terms.inject([]) {|k,t|
|
514
|
-
k += t.keys if t.kind_of?(Locale)
|
515
|
-
k
|
516
|
-
}.uniq
|
517
|
-
if locale
|
518
|
-
locale = [locale] unless locale.kind_of?(Array)
|
519
|
-
keys = locale | (locale & keys)
|
520
|
-
end
|
521
|
-
end
|
522
|
-
keys << nil if keys.include?('')
|
523
|
-
|
524
|
-
# names ハッシュ
|
525
|
-
names = keys.inject({}) {|l,k|
|
526
|
-
l[k] = When::Coordinates::Pair._format(
|
527
|
-
(block_given? ? yield(k, *terms) : terms).map {|t|
|
528
|
-
t.kind_of?(Locale) ? t.translate(k) : t
|
529
|
-
}
|
530
|
-
)
|
531
|
-
l
|
532
|
-
}
|
533
|
-
|
534
|
-
# link ハッシュ
|
535
|
-
links = terms.reverse.inject({}) {|h,t|
|
536
|
-
h.update(t.link) if t.kind_of?(Locale)
|
537
|
-
h
|
538
|
-
}
|
539
|
-
|
540
|
-
# 生成
|
541
|
-
dup._copy({
|
542
|
-
:label => keys.include?('') ? names.delete(nil) : (names[''] = names[keys[0]]),
|
543
|
-
:names => names,
|
544
|
-
:link => links
|
545
|
-
})
|
546
|
-
end
|
547
|
-
alias :% :_printf
|
548
|
-
|
549
|
-
# ローケールの更新
|
550
|
-
#
|
551
|
-
# @param [Hash] options 下記の通り
|
552
|
-
# @option options [String] カントリーコード 表現文字列
|
553
|
-
# @option options [Hash] :link { カントリーコード => 参照URL文字列 }
|
554
|
-
# @option options [String] :code_space 規格や辞書を特定するコードスペースのURL文字列
|
555
|
-
# @option options [String] :label 代表文字列
|
556
|
-
# @note Hashキーはすべて Optional で、存在するもののみ更新します
|
557
|
-
#
|
558
|
-
# @return [self] 更新された Object
|
559
|
-
#
|
560
|
-
def update(options={})
|
561
|
-
options = options.dup
|
562
|
-
@link.update(options.delete(:link)) if (options.key?(:link))
|
563
|
-
@code_space = options.delete(:code_space) if (options.key?(:code_space))
|
564
|
-
self[0..-1] = options.delete(:label) if (options.key?(:label))
|
565
|
-
unless (options.empty?)
|
566
|
-
@names.update(options)
|
567
|
-
@keys = @names.keys.sort
|
568
|
-
@values = @names.values.sort.reverse
|
569
|
-
end
|
570
|
-
return self
|
571
|
-
end
|
572
|
-
|
573
|
-
# 包摂リストに登録されている文字を包摂する(自己破壊)
|
574
|
-
#
|
575
|
-
# @param [Hash] pattern 包摂ルール
|
576
|
-
#
|
577
|
-
# @return [When::Locale] self
|
578
|
-
# @private
|
579
|
-
def ideographic_unification!(pattern=_unification)
|
580
|
-
names = {}
|
581
|
-
@names.each_pair do |key, value|
|
582
|
-
names[key] = Locale.ideographic_unification(value, pattern)
|
583
|
-
end
|
584
|
-
@names = names
|
585
|
-
@values = @names.values.sort.reverse
|
586
|
-
self[0..-1] = Locale.ideographic_unification(self.to_s[0..-1], pattern)
|
587
|
-
return self
|
588
|
-
end
|
589
|
-
protected :ideographic_unification!
|
590
|
-
|
591
|
-
# 包摂リストに登録されている文字を包摂する(自己保存)
|
592
|
-
#
|
593
|
-
# @param [Hash] pattern 包摂ルール
|
594
|
-
#
|
595
|
-
# @return [When::Locale] 包摂結果
|
596
|
-
#
|
597
|
-
def ideographic_unification(pattern=_unification)
|
598
|
-
dup.ideographic_unification!(pattern)
|
599
|
-
end
|
600
|
-
|
601
|
-
# 閏の表記を扱うための書式付整形
|
602
|
-
# @private
|
603
|
-
def prefix(other, locale=nil)
|
604
|
-
return self.dup unless other
|
605
|
-
other = m17n(other) unless other.kind_of?(Locale)
|
606
|
-
other._printf(self, locale) do |k, *t|
|
607
|
-
t[0] = t[0].translate(k)
|
608
|
-
t[0] += "%s" unless t[0] =~ /%[-+]?[.\d]*s/
|
609
|
-
t
|
610
|
-
end
|
611
|
-
end
|
612
|
-
|
613
|
-
protected
|
614
|
-
|
615
|
-
# @private
|
616
|
-
def _copy(options={})
|
617
|
-
if options.key?('label') # for JSON
|
618
|
-
opt = {}
|
619
|
-
options.each_pair do |key, value|
|
620
|
-
opt[key.to_sym] = value
|
621
|
-
end
|
622
|
-
else
|
623
|
-
opt = options
|
624
|
-
end
|
625
|
-
|
626
|
-
self[0..-1] = opt[:label] if opt[:label]
|
627
|
-
if opt[:names]
|
628
|
-
@names = opt[:names]
|
629
|
-
@keys = @names.keys.sort
|
630
|
-
@values = @names.values.compact.sort.reverse
|
631
|
-
end
|
632
|
-
@label = opt[:label] if opt[:label]
|
633
|
-
@link = opt[:link] if opt[:link]
|
634
|
-
@access_key = opt[:access_key] if opt[:access_key]
|
635
|
-
@code_space = opt[:code_space] if opt[:code_space]
|
636
|
-
return self
|
637
|
-
end
|
638
|
-
|
639
|
-
# @private
|
640
|
-
def _copy_all(other)
|
641
|
-
_copy({:label => other.to_s,
|
642
|
-
:names => other.names,
|
643
|
-
:link => other.link,
|
644
|
-
:access_key => other.access_key,
|
645
|
-
:code_space => other.code_space
|
646
|
-
})
|
647
|
-
end
|
648
|
-
|
649
|
-
# locale 指定を解析して @names の値を取り出す
|
650
|
-
# @private
|
651
|
-
def _label_value(locale)
|
652
|
-
label = Locale._hash_value(@names, locale, [])
|
653
|
-
return label if label
|
654
|
-
foreign = Locale._get_locale(locale, @access_key)
|
655
|
-
return @names[''] unless foreign
|
656
|
-
english = @names['en'] || @names['']
|
657
|
-
addition = english.dup.sub!(/\A#{Locale._get_locale('en', @access_key)['en']}/, '')
|
658
|
-
foreign[locale] += addition if addition
|
659
|
-
update(foreign)
|
660
|
-
return Locale._hash_value(@names, locale)
|
661
|
-
end
|
662
|
-
|
663
|
-
private
|
664
|
-
|
665
|
-
def _names(names, namespace, default_locale)
|
666
|
-
|
667
|
-
# names, link の組み立て
|
668
|
-
@names = {}
|
669
|
-
@link = {}
|
670
|
-
|
671
|
-
if names.kind_of?(String)
|
672
|
-
unless (names=~/\A\s*\[(.+?)\]\s*\z/m)
|
673
|
-
names = names.strip
|
674
|
-
@names[''] = names
|
675
|
-
@keys = ['']
|
676
|
-
@values = [names]
|
677
|
-
return names
|
678
|
-
end
|
679
|
-
names = $1.split(/[\n\r,]+/)
|
680
|
-
end
|
681
|
-
|
682
|
-
mark = []
|
683
|
-
asterisk = []
|
684
|
-
default_locale = default_locale.dup
|
685
|
-
names.each do |v|
|
686
|
-
v.strip!
|
687
|
-
case v
|
688
|
-
when '', /\A#/ ;
|
689
|
-
when /\A\/(.+)/; @access_key = $1
|
690
|
-
when /\A(\*)?(?:([^=%]*?)\s*:)?\s*(.+?)\s*(=\s*([^=]+?(\?.+)?)?)?\z/
|
691
|
-
asterisk[0], locale, name, assignment, ref = $~[1..5]
|
692
|
-
asterisk[1], locale, default_ref = default_locale.shift unless locale
|
693
|
-
locale ||= ''
|
694
|
-
ref ||= default_ref unless (assignment)
|
695
|
-
ref ||= ''
|
696
|
-
mark[0] = locale if asterisk[0]
|
697
|
-
mark[1] = locale if asterisk[1]
|
698
|
-
mark[2] = locale unless mark[2]
|
699
|
-
name = _replacement($1, locale, ($3 || @names['en'] || @names[''])) if name =~ /\A_([A-Z_]+)_(\((.+)\))?\z/
|
700
|
-
name.gsub!(/<[0-9A-F]{2}>/i) {|code| code[1..2].to_i(16).chr}
|
701
|
-
@names[locale] = name
|
702
|
-
if ref =~ /\A(.+):/
|
703
|
-
prefix = namespace[$1] || Locale.send(:_namespaces)[$1]
|
704
|
-
ref.sub!(/\A.+:/, prefix) if prefix
|
705
|
-
end
|
706
|
-
ref += name =~ /\A<.+>\z/ ? '%%' + name : '%%<' + name + '>' if ref =~ /[\/#:]\z/
|
707
|
-
unless ref == ''
|
708
|
-
@link[locale] = _encode(ref)
|
709
|
-
# When.logger.info("%s[%s]->%s" % [@names[locale], locale, @link[locale]]) if When.logger
|
710
|
-
end
|
711
|
-
else ; raise ArgumentError, "Irregal locale format: " + v
|
712
|
-
end
|
713
|
-
end
|
714
|
-
if Locale.wikipedia_interval && Locale.wikipedia_interval <= 0
|
715
|
-
['en', ''].each do |lc|
|
716
|
-
if Locale::Ref =~ @link[lc] && $1 == 'en'
|
717
|
-
object = Locale.send(:wikipedia_object, @link[lc])
|
718
|
-
if object
|
719
|
-
@names = object.names.merge(@names)
|
720
|
-
@link = object.link.merge(@link)
|
721
|
-
end
|
722
|
-
break
|
723
|
-
end
|
724
|
-
end
|
725
|
-
end
|
726
|
-
|
727
|
-
# keys, values の準備
|
728
|
-
@keys = @names.keys.sort
|
729
|
-
@values = @names.values.sort.reverse
|
730
|
-
|
731
|
-
# 代表名
|
732
|
-
@names[mark[0] || mark[1] || mark[2]]
|
733
|
-
end
|
734
|
-
|
735
|
-
#
|
736
|
-
# 英語表記を現地表記に置き換える
|
737
|
-
#
|
738
|
-
def _replacement(table, locale, name)
|
739
|
-
Locale.const_get(table.split('_')[-1])[locale] ?
|
740
|
-
Locale.send(table.downcase, name, locale) :
|
741
|
-
name
|
742
|
-
end
|
743
|
-
|
744
|
-
# encode URI from patterns %%(...) or %.(...)
|
745
|
-
def _encode(source)
|
746
|
-
source.gsub(/%.<.+?>/) do |match|
|
747
|
-
URI.encode(match[3..-2]).gsub('%', match[1..1])
|
748
|
-
end
|
749
|
-
end
|
750
|
-
end
|
751
|
-
end
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
=begin
|
3
|
+
Copyright (C) 2011-2015 Takashi SUGA
|
4
|
+
|
5
|
+
You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
|
6
|
+
=end
|
7
|
+
|
8
|
+
require 'when_exe/locales/encoding_conversion'
|
9
|
+
|
10
|
+
module When
|
11
|
+
|
12
|
+
#
|
13
|
+
# Multilingualization(M17n) 対応モジュール
|
14
|
+
#
|
15
|
+
# When::BasicTypes::M17n の実装のうち When::BasicTypes 内部で
|
16
|
+
# 定義すべきでない部分を切り出してモジュールとしている
|
17
|
+
#
|
18
|
+
module Locale
|
19
|
+
|
20
|
+
# Locale 読み替えの初期設定
|
21
|
+
DefaultAlias = {'alias'=>'ja', '日本語'=>'ja', '英語'=>'en'}
|
22
|
+
|
23
|
+
# 省略時 Namespace
|
24
|
+
DefaultNamespaces = Hash.new {|hash, key|
|
25
|
+
hash[key] = "http://#{key}.wikipedia.org/wiki/"
|
26
|
+
}.update({
|
27
|
+
'mailto' => false,
|
28
|
+
'https' => false,
|
29
|
+
'http' => false,
|
30
|
+
'ftp' => false
|
31
|
+
})
|
32
|
+
|
33
|
+
# 漢字の包摂
|
34
|
+
DefaultUnification = {
|
35
|
+
'煕'=>'熙', '廣'=>'広', '寶'=>'宝', '國'=>'国',
|
36
|
+
'應'=>'応', '觀'=>'観', '龜'=>'亀', '齊'=>'斉',
|
37
|
+
'靈'=>'霊', '攝'=>'摂', '壽'=>'寿', '萬'=>'万',
|
38
|
+
'廢'=>'廃', '顯'=>'顕', '會'=>'会', '聰'=>'聡',
|
39
|
+
'總'=>'総', '證'=>'証', '禮'=>'礼', '與'=>'与',
|
40
|
+
'竜'=>'龍'
|
41
|
+
}
|
42
|
+
|
43
|
+
# Escape
|
44
|
+
# @private
|
45
|
+
Escape = {
|
46
|
+
"\\\\" => "\\",
|
47
|
+
"\\n" => "\n",
|
48
|
+
"\\r" => "\r",
|
49
|
+
"\\," => ","
|
50
|
+
}
|
51
|
+
|
52
|
+
# Wikipedia の URL の正規表現
|
53
|
+
# @private
|
54
|
+
Ref = /\Ahttp:\/\/(.+?)\.wikipedia\.org\/wiki\/([^#]+?)\z/
|
55
|
+
|
56
|
+
# Wikipedia の多言語リンクの正規表現
|
57
|
+
# @private
|
58
|
+
Link = /<li class="interlanguage-link interwiki-(.+?)"><a href="\/\/(.+?)\.wikipedia\.org\/wiki\/(.+?)" title="(.+?) – /
|
59
|
+
|
60
|
+
class << self
|
61
|
+
|
62
|
+
# Wikipedia の連続的な参照を抑制するための遅延時間/秒
|
63
|
+
#
|
64
|
+
# @return [Numeric]
|
65
|
+
#
|
66
|
+
attr_accessor :wikipedia_interval
|
67
|
+
|
68
|
+
# When::Locale Module のグローバルな設定を行う
|
69
|
+
#
|
70
|
+
# @param [Hash] options 下記の通り
|
71
|
+
# @option options [Hash] :alias Locale の読み替えパターンを Hash で指定する。
|
72
|
+
# @option options [String] :namespace_foramt 名前空間定義の省略時に名前空間生成に用いる書式
|
73
|
+
# @option options [Hash] :unification 漢字の包摂パターンを Hash で指定する。
|
74
|
+
# @option options [Numeric] :wikipedia_interval Wikipedia の連続的な参照を抑制するための遅延時間/秒
|
75
|
+
#
|
76
|
+
# @note
|
77
|
+
# :alias の指定がない場合、aliases は DefaultAlias(モジュール定数)と解釈する。
|
78
|
+
# :unification の指定がない場合、unifications は DefaultUnification(モジュール定数)と解釈する。
|
79
|
+
#
|
80
|
+
def _setup_(options={})
|
81
|
+
@aliases = options[:alias] || DefaultAlias
|
82
|
+
@namespaces = options[:namespace_foramt] || DefaultNamespaces
|
83
|
+
@unifications = options[:unification] || DefaultUnification
|
84
|
+
@wikipedia_interval = options[:wikipedia_interval]
|
85
|
+
end
|
86
|
+
|
87
|
+
# 設定情報を取得する
|
88
|
+
#
|
89
|
+
# @return [Hash] 設定情報
|
90
|
+
#
|
91
|
+
def _setup_info
|
92
|
+
{:alias => _alias,
|
93
|
+
:namespace_foramt => _namespaces,
|
94
|
+
:unification => _unification,
|
95
|
+
:wikipedia_interval => @wikipedia_interval}
|
96
|
+
end
|
97
|
+
|
98
|
+
# 特定 locale に対応した文字列の取得
|
99
|
+
#
|
100
|
+
# @param [String] source もとにする String または M17n
|
101
|
+
#
|
102
|
+
# @param[String] loc locale の指定 ( lang[-|_]country.encode )
|
103
|
+
# [ lang - 言語 ]
|
104
|
+
# [ country - 国(省略可) ]
|
105
|
+
# [ encode - 文字コード(省略可) ]
|
106
|
+
#
|
107
|
+
# @return [String] loc に対応した文字列
|
108
|
+
#
|
109
|
+
# @note source が Hash や Array の場合、その構成要素を変換して返す
|
110
|
+
# @note encode は通常大文字だが、大文字/小文字の変換は行わず指定されたまま使用している
|
111
|
+
#
|
112
|
+
def translate(source, loc='')
|
113
|
+
return source unless loc
|
114
|
+
case source
|
115
|
+
when Hash
|
116
|
+
result = {}
|
117
|
+
source.each_pair do |key, value|
|
118
|
+
result[translate(key, loc)] = translate(value, loc)
|
119
|
+
end
|
120
|
+
return result
|
121
|
+
when Array
|
122
|
+
return source.map {|value| translate(value, loc)}
|
123
|
+
when Locale
|
124
|
+
return source.translate(loc)
|
125
|
+
when String
|
126
|
+
return source.encode($1) if loc =~ /\.(.+)\z/
|
127
|
+
end
|
128
|
+
source
|
129
|
+
end
|
130
|
+
|
131
|
+
# 包摂リストに登録されている文字を包摂する
|
132
|
+
#
|
133
|
+
# @param [When::Locale] source 文字を包摂しようとする国際化文字列
|
134
|
+
# @param [String] source 文字を包摂しようとする文字列
|
135
|
+
# @param [Regexp] source 文字を包摂しようとする正規表現
|
136
|
+
# @param [Hash] pattern 包摂ルール
|
137
|
+
#
|
138
|
+
# @return [When::Locale] 文字を包摂した国際化文字列
|
139
|
+
# @return [String] 文字を包摂した文字列
|
140
|
+
# @return [Regexp] 文字を包摂した正規表現
|
141
|
+
#
|
142
|
+
def ideographic_unification(source, pattern=_unification)
|
143
|
+
case source
|
144
|
+
when When::Locale
|
145
|
+
source.ideographic_unification(pattern)
|
146
|
+
when Regexp
|
147
|
+
Regexp.compile(ideographic_unification(source.source.encode('UTF-8'), pattern), source.options)
|
148
|
+
when String
|
149
|
+
source.gsub(/./) do |c|
|
150
|
+
pattern[c] ? pattern[c] : c
|
151
|
+
end
|
152
|
+
else
|
153
|
+
source
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# 文字列で表現された namespace 指定を Hash に変換する
|
158
|
+
# @private
|
159
|
+
def _namespace(source=nil)
|
160
|
+
case source
|
161
|
+
when Hash ; source
|
162
|
+
when nil ; {}
|
163
|
+
when String
|
164
|
+
namespace = {}
|
165
|
+
source = $1 if (source=~/\A\s*\[?(.+?)\]?\s*\z/m)
|
166
|
+
source.split(/[\n\r,]+/).each do |v|
|
167
|
+
v.strip!
|
168
|
+
next if (v=~/\A#/)
|
169
|
+
pair = [''] + v.split(/\s*=\s*/, 2)
|
170
|
+
namespace[pair[-2]] = pair[-1]
|
171
|
+
end
|
172
|
+
namespace
|
173
|
+
when When::Parts::Resource::ContentLine
|
174
|
+
source.object.names
|
175
|
+
else ; raise TypeError, "Irregal Namespace Type: #{source.class}"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# locale 指定を Array に変換する
|
180
|
+
# @private
|
181
|
+
def _locale(source=nil)
|
182
|
+
# default の Locale
|
183
|
+
return [[nil, '', nil]] unless source
|
184
|
+
|
185
|
+
# source の配列化
|
186
|
+
if source.kind_of?(String)
|
187
|
+
source = $1 if (source=~/\A\s*\[?(.+?)\]?\s*\z/m)
|
188
|
+
source = source.scan(/((?:[^\\\n\r,]|\\.)+)(?:[\n\r,]+(?!\z))?|[\n\r,]+/m).flatten.map {|token|
|
189
|
+
(token||'').gsub(/\\./) {|escape| Escape[escape] || escape}
|
190
|
+
}
|
191
|
+
end
|
192
|
+
|
193
|
+
# 各Localeの展開
|
194
|
+
source.map {|v|
|
195
|
+
if v.kind_of?(String)
|
196
|
+
v = v.strip
|
197
|
+
next if (v=~/\A#/)
|
198
|
+
(v =~ /\A(\*)?(.*?)(?:\s*=\s*(.*))?\z/) ? $~[1..3] : [[nil, '', nil]]
|
199
|
+
else
|
200
|
+
v
|
201
|
+
end
|
202
|
+
}.compact
|
203
|
+
end
|
204
|
+
|
205
|
+
# 文字列 [.., .., ..] を分割する
|
206
|
+
# @private
|
207
|
+
def _split(source)
|
208
|
+
line = source.dup
|
209
|
+
return [line] unless line =~ /,/
|
210
|
+
list = []
|
211
|
+
b = d = s = 0
|
212
|
+
(source.length-1).downto(0) do |i|
|
213
|
+
bs = 0
|
214
|
+
(i-1).downto(0) do |k|
|
215
|
+
break unless (line[k,1] == '\\')
|
216
|
+
bs += 1
|
217
|
+
end
|
218
|
+
next if (bs[0] == 1)
|
219
|
+
case line[i,1]
|
220
|
+
when "'" ; s = 1-s if (d == 0)
|
221
|
+
when '"' ; d = 1-d if (s == 0)
|
222
|
+
when ']','}',')' ; b += 1 if (d+s == 0)
|
223
|
+
when '[','{','(' ; b -= 1 if (d+s == 0 && b > 0)
|
224
|
+
when ','
|
225
|
+
if (b+d+s == 0)
|
226
|
+
list.unshift(line[i+1..-1])
|
227
|
+
line = i > 0 ? line[0..i-1] : ''
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
list.unshift(line)
|
232
|
+
end
|
233
|
+
|
234
|
+
# locale 指定を解析して Hash の値を取り出す
|
235
|
+
# @private
|
236
|
+
def _hash_value(hash, locale, defaults=['', 'en'])
|
237
|
+
locale = locale.sub(/\..*/, '')
|
238
|
+
return hash[locale] if hash[locale]
|
239
|
+
return _hash_value(hash, _alias[locale], defaults) if _alias[locale]
|
240
|
+
language = locale.sub(/-.*/, '')
|
241
|
+
return hash[language] if hash[language]
|
242
|
+
defaults.each do |default|
|
243
|
+
return hash[default] if hash[default]
|
244
|
+
end
|
245
|
+
return nil
|
246
|
+
end
|
247
|
+
|
248
|
+
# 漢字の包摂パターン
|
249
|
+
# @private
|
250
|
+
def _unification
|
251
|
+
@unifications ||= DefaultUnification
|
252
|
+
end
|
253
|
+
|
254
|
+
# @private
|
255
|
+
def _get_locale(locale, access_key)
|
256
|
+
return nil unless access_key
|
257
|
+
access_key = access_key.split(/\//).map {|key| key =~ /\A[0-9]+\z/ ? key.to_i : key}
|
258
|
+
locale = locale.sub(/\..*/, '')
|
259
|
+
[locale, locale.sub(/-.*/, '')].each do |loc|
|
260
|
+
symbol = ('Locale_' + loc.sub(/-/,'_')).to_sym
|
261
|
+
return {locale=>access_key.inject(const_get(symbol)) {|hash, key| hash = hash[key]}} if const_defined?(symbol)
|
262
|
+
end
|
263
|
+
return nil
|
264
|
+
end
|
265
|
+
|
266
|
+
private
|
267
|
+
|
268
|
+
# Locale の読み替えパターン
|
269
|
+
def _alias
|
270
|
+
@aliases ||= DefaultAlias
|
271
|
+
end
|
272
|
+
|
273
|
+
# 名前空間定義の省略時に名前空間生成に用いる書式
|
274
|
+
def _namespaces
|
275
|
+
@namespaces ||= DefaultNamespaces
|
276
|
+
end
|
277
|
+
|
278
|
+
# wikipedia オブジェクトの生成・参照
|
279
|
+
def wikipedia_object(path, options={})
|
280
|
+
query = options.delete(:query)
|
281
|
+
interval = options.key?(:interval) ? options.delete(:interval) : @wikipedia_interval
|
282
|
+
return nil unless Object.const_defined?(:JSON) && path =~ Ref
|
283
|
+
_wikipedia_relation(_wikipedia_object(path, $1, $2, query, interval, options), path, query)
|
284
|
+
end
|
285
|
+
|
286
|
+
# wikipedia の読み込み
|
287
|
+
def _wikipedia_object(path, locale, file, query, interval, options)
|
288
|
+
# 採取済みデータ
|
289
|
+
title = URI.decode(file.gsub('_', ' '))
|
290
|
+
mode = "".respond_to?(:force_encoding) ? ':utf-8' : ''
|
291
|
+
dir = When::Parts::Resource.root_dir + '/data/wikipedia/' + locale
|
292
|
+
FileUtils.mkdir_p(dir) unless FileTest.exist?(dir)
|
293
|
+
|
294
|
+
open("#{dir}/#{file}.json", 'r'+mode) do |source|
|
295
|
+
json = JSON.parse(source.read)
|
296
|
+
json.update(Hash[*query.split('&').map {|pair| pair.split('=')}.flatten]) if query
|
297
|
+
json.key?('names') ?
|
298
|
+
When::BasicTypes::M17n.new(json) :
|
299
|
+
When::Coordinates::Spatial.new(json)
|
300
|
+
end
|
301
|
+
|
302
|
+
rescue => no_file_error
|
303
|
+
# 新しいデータ
|
304
|
+
case interval
|
305
|
+
when 0
|
306
|
+
raise no_file_error
|
307
|
+
when Numeric
|
308
|
+
if @wikipedia_last_access
|
309
|
+
delay = (@wikipedia_last_access + interval.abs - Time.now.to_f).ceil
|
310
|
+
sleep(delay) if delay > 0
|
311
|
+
end
|
312
|
+
end
|
313
|
+
contents = nil
|
314
|
+
begin
|
315
|
+
OpenURI
|
316
|
+
source = open(path, 'r'+mode)
|
317
|
+
contents = source.read
|
318
|
+
ensure
|
319
|
+
@wikipedia_last_access = Time.now.to_f
|
320
|
+
source.close if source
|
321
|
+
end
|
322
|
+
|
323
|
+
# wikipedia contents
|
324
|
+
raise KeyError, 'Article not found: ' + title if contents =~ /<div class="noarticletext">/
|
325
|
+
|
326
|
+
# word
|
327
|
+
word = {
|
328
|
+
:label => title,
|
329
|
+
:names => {''=>title, locale=>title},
|
330
|
+
:link => {''=>path, locale=>path }
|
331
|
+
}
|
332
|
+
contents.scan(Link) do |link|
|
333
|
+
word[:names][$2] = $4
|
334
|
+
word[:link ][$2] = "http://#{$2}.wikipedia.org/wiki/#{$3}"
|
335
|
+
end
|
336
|
+
object = When::BasicTypes::M17n.new(word)
|
337
|
+
|
338
|
+
# location
|
339
|
+
if contents =~ /tools\.wmflabs\.org\/geohack\/geohack\.php\?.+?params=(.+?[NS])_(.+?[EW])/
|
340
|
+
location = {
|
341
|
+
:label => object
|
342
|
+
}
|
343
|
+
location[:lat], location[:long] = $~[1..2].map {|pos|
|
344
|
+
pos.gsub(/_(\d)[._]/, '_0\1_').sub('.', '_').sub('_', '.').gsub('_', '')
|
345
|
+
}
|
346
|
+
object = When::Coordinates::Spatial.new(location)
|
347
|
+
end
|
348
|
+
|
349
|
+
# save data
|
350
|
+
open("#{dir}/#{file}.json", 'w'+mode) do |source|
|
351
|
+
source.write(JSON.dump(object.to_h({:method=>:to_h}).update(options)))
|
352
|
+
end
|
353
|
+
query ? _wikipedia_object(path, locale, file, query) : object
|
354
|
+
end
|
355
|
+
|
356
|
+
# wikipedia オブジェクトの関連付け
|
357
|
+
def _wikipedia_relation(object, path, query)
|
358
|
+
code_space = path.sub(/[^\/]+\z/, '')
|
359
|
+
if object.kind_of?(When::Coordinates::Spatial)
|
360
|
+
object.label._pool['..'] = object
|
361
|
+
object._pool[object.label.to_s] = object.label
|
362
|
+
object.send(:child=, [object.label])
|
363
|
+
object.label.send(:code_space=, code_space)
|
364
|
+
else
|
365
|
+
object.send(:code_space=, code_space)
|
366
|
+
end
|
367
|
+
object._pool['..'] = path
|
368
|
+
object._pool['..'] += '?' + query if query
|
369
|
+
object
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
# ローケール指定時の文字列
|
374
|
+
#
|
375
|
+
# @return [Hash]
|
376
|
+
attr_reader :names
|
377
|
+
|
378
|
+
# 有効なローケール指定
|
379
|
+
#
|
380
|
+
# @return [Array<String>]
|
381
|
+
attr_reader :keys
|
382
|
+
|
383
|
+
# 有効な文字列 - additional attribute
|
384
|
+
#
|
385
|
+
# @return [Array<String>]
|
386
|
+
attr_reader :values
|
387
|
+
|
388
|
+
# 文字列の説明 - additional attribute
|
389
|
+
#
|
390
|
+
# @return [Hash] { anyURI }
|
391
|
+
attr_reader :link
|
392
|
+
|
393
|
+
# Rails 用 I18n 定義へのアクセス・キー
|
394
|
+
#
|
395
|
+
# @return [String]
|
396
|
+
attr_reader :access_key
|
397
|
+
protected :access_key
|
398
|
+
|
399
|
+
# 特定 locale に対応した文字列の取得
|
400
|
+
#
|
401
|
+
# @param [String] loc locale の指定 ( lang[-|_]country.encode )
|
402
|
+
# [ lang - 言語 ]
|
403
|
+
# [ country - 国(省略可) ]
|
404
|
+
# [ encode - 文字コード(省略可) ]
|
405
|
+
#
|
406
|
+
# @return [String] loc に対応した文字列
|
407
|
+
#
|
408
|
+
def translate(loc='')
|
409
|
+
return to_s unless loc
|
410
|
+
loc = loc.sub('_', '-')
|
411
|
+
lang, code = loc.split(/\./)
|
412
|
+
result = _label_value(loc)
|
413
|
+
return result if !code || @names.member?(loc)
|
414
|
+
return result.encode(code)
|
415
|
+
end
|
416
|
+
alias :/ :translate
|
417
|
+
|
418
|
+
# 特定 locale に対応した reference URI の取得
|
419
|
+
#
|
420
|
+
# @param [String] loc locale の指定
|
421
|
+
#
|
422
|
+
# @return [String] loc に対応した reference URI
|
423
|
+
#
|
424
|
+
def reference(loc='')
|
425
|
+
loc ||= ''
|
426
|
+
return Locale._hash_value(@link, loc.sub('_', '-'))
|
427
|
+
end
|
428
|
+
|
429
|
+
# 部分文字列
|
430
|
+
#
|
431
|
+
# @param [Range] range String#[] と同様の指定方法で範囲を指定する
|
432
|
+
#
|
433
|
+
# @return [When::Locale] 指定範囲に対応した部分文字列
|
434
|
+
#
|
435
|
+
def [](range)
|
436
|
+
dup._copy({
|
437
|
+
:label => to_s[range],
|
438
|
+
:names => @names.keys.inject({}) {|l,k|
|
439
|
+
l[k] = @names[k][range]
|
440
|
+
l
|
441
|
+
}
|
442
|
+
})
|
443
|
+
end
|
444
|
+
|
445
|
+
# 文字列の一致
|
446
|
+
#
|
447
|
+
# @param [String, Regexp] regexp マッチする正規表現
|
448
|
+
#
|
449
|
+
# @return [Integer] マッチした位置のindex(いずれかの locale でマッチが成功した場合)
|
450
|
+
# @return [nil] すべての locale でマッチに失敗した場合
|
451
|
+
#
|
452
|
+
def =~(regexp)
|
453
|
+
@keys.each do |key|
|
454
|
+
index = (@names[key] =~ regexp)
|
455
|
+
return index if index
|
456
|
+
end
|
457
|
+
return nil
|
458
|
+
end
|
459
|
+
|
460
|
+
# 部分文字列の位置
|
461
|
+
#
|
462
|
+
# @param [String] other 部分文字列
|
463
|
+
#
|
464
|
+
# @return [Integer] 部分文字列の先頭のindex(いずれかの locale で部分文字列を含んだ場合)
|
465
|
+
# @return [nil] すべての locale で部分文字列を含まない場合
|
466
|
+
#
|
467
|
+
def index(other)
|
468
|
+
@keys.each do |key|
|
469
|
+
index = @names[key].index(Locale.translate(other, key))
|
470
|
+
return index if index
|
471
|
+
end
|
472
|
+
return nil
|
473
|
+
end
|
474
|
+
|
475
|
+
# 文字列の連結
|
476
|
+
#
|
477
|
+
# @param [String, When::Toos::Locale] other 連結する文字列
|
478
|
+
#
|
479
|
+
# @return [When::Toos::Locale] 連結された文字列
|
480
|
+
#
|
481
|
+
def +(other)
|
482
|
+
names = {}
|
483
|
+
case other
|
484
|
+
when Locale
|
485
|
+
(@names.keys + other.names.keys).uniq.each do |key|
|
486
|
+
names[key] = _label_value(key) + other._label_value(key)
|
487
|
+
end
|
488
|
+
links = other.link
|
489
|
+
else
|
490
|
+
@names.keys.each do |key|
|
491
|
+
names[key] = _label_value(key) + other.to_s
|
492
|
+
end
|
493
|
+
links = {}
|
494
|
+
end
|
495
|
+
return dup._copy({:names=>names, :link=>links.merge(link), :label=>to_s + other.to_s})
|
496
|
+
end
|
497
|
+
|
498
|
+
# 書式指定による文字列化
|
499
|
+
#
|
500
|
+
# @param [Array<Object>] other 文字列化する Object の Array
|
501
|
+
# @param [Array<String>] locale 文字列化を行う locale の指定(デフォルト : すべて)
|
502
|
+
#
|
503
|
+
# @return [When::Toos::Locale] 文字列化された Object
|
504
|
+
#
|
505
|
+
def _printf(other, locale=nil)
|
506
|
+
# 処理する配列
|
507
|
+
terms = other.kind_of?(Array) ? [self] + other : [self, other]
|
508
|
+
|
509
|
+
# locale key の配列
|
510
|
+
if locale == []
|
511
|
+
keys = []
|
512
|
+
else
|
513
|
+
keys = terms.inject([]) {|k,t|
|
514
|
+
k += t.keys if t.kind_of?(Locale)
|
515
|
+
k
|
516
|
+
}.uniq
|
517
|
+
if locale
|
518
|
+
locale = [locale] unless locale.kind_of?(Array)
|
519
|
+
keys = locale | (locale & keys)
|
520
|
+
end
|
521
|
+
end
|
522
|
+
keys << nil if keys.include?('')
|
523
|
+
|
524
|
+
# names ハッシュ
|
525
|
+
names = keys.inject({}) {|l,k|
|
526
|
+
l[k] = When::Coordinates::Pair._format(
|
527
|
+
(block_given? ? yield(k, *terms) : terms).map {|t|
|
528
|
+
t.kind_of?(Locale) ? t.translate(k) : t
|
529
|
+
}
|
530
|
+
)
|
531
|
+
l
|
532
|
+
}
|
533
|
+
|
534
|
+
# link ハッシュ
|
535
|
+
links = terms.reverse.inject({}) {|h,t|
|
536
|
+
h.update(t.link) if t.kind_of?(Locale)
|
537
|
+
h
|
538
|
+
}
|
539
|
+
|
540
|
+
# 生成
|
541
|
+
dup._copy({
|
542
|
+
:label => keys.include?('') ? names.delete(nil) : (names[''] = names[keys[0]]),
|
543
|
+
:names => names,
|
544
|
+
:link => links
|
545
|
+
})
|
546
|
+
end
|
547
|
+
alias :% :_printf
|
548
|
+
|
549
|
+
# ローケールの更新
|
550
|
+
#
|
551
|
+
# @param [Hash] options 下記の通り
|
552
|
+
# @option options [String] カントリーコード 表現文字列
|
553
|
+
# @option options [Hash] :link { カントリーコード => 参照URL文字列 }
|
554
|
+
# @option options [String] :code_space 規格や辞書を特定するコードスペースのURL文字列
|
555
|
+
# @option options [String] :label 代表文字列
|
556
|
+
# @note Hashキーはすべて Optional で、存在するもののみ更新します
|
557
|
+
#
|
558
|
+
# @return [self] 更新された Object
|
559
|
+
#
|
560
|
+
def update(options={})
|
561
|
+
options = options.dup
|
562
|
+
@link.update(options.delete(:link)) if (options.key?(:link))
|
563
|
+
@code_space = options.delete(:code_space) if (options.key?(:code_space))
|
564
|
+
self[0..-1] = options.delete(:label) if (options.key?(:label))
|
565
|
+
unless (options.empty?)
|
566
|
+
@names.update(options)
|
567
|
+
@keys = @names.keys.sort
|
568
|
+
@values = @names.values.sort.reverse
|
569
|
+
end
|
570
|
+
return self
|
571
|
+
end
|
572
|
+
|
573
|
+
# 包摂リストに登録されている文字を包摂する(自己破壊)
|
574
|
+
#
|
575
|
+
# @param [Hash] pattern 包摂ルール
|
576
|
+
#
|
577
|
+
# @return [When::Locale] self
|
578
|
+
# @private
|
579
|
+
def ideographic_unification!(pattern=_unification)
|
580
|
+
names = {}
|
581
|
+
@names.each_pair do |key, value|
|
582
|
+
names[key] = Locale.ideographic_unification(value, pattern)
|
583
|
+
end
|
584
|
+
@names = names
|
585
|
+
@values = @names.values.sort.reverse
|
586
|
+
self[0..-1] = Locale.ideographic_unification(self.to_s[0..-1], pattern)
|
587
|
+
return self
|
588
|
+
end
|
589
|
+
protected :ideographic_unification!
|
590
|
+
|
591
|
+
# 包摂リストに登録されている文字を包摂する(自己保存)
|
592
|
+
#
|
593
|
+
# @param [Hash] pattern 包摂ルール
|
594
|
+
#
|
595
|
+
# @return [When::Locale] 包摂結果
|
596
|
+
#
|
597
|
+
def ideographic_unification(pattern=_unification)
|
598
|
+
dup.ideographic_unification!(pattern)
|
599
|
+
end
|
600
|
+
|
601
|
+
# 閏の表記を扱うための書式付整形
|
602
|
+
# @private
|
603
|
+
def prefix(other, locale=nil)
|
604
|
+
return self.dup unless other
|
605
|
+
other = m17n(other) unless other.kind_of?(Locale)
|
606
|
+
other._printf(self, locale) do |k, *t|
|
607
|
+
t[0] = t[0].translate(k)
|
608
|
+
t[0] += "%s" unless t[0] =~ /%[-+]?[.\d]*s/
|
609
|
+
t
|
610
|
+
end
|
611
|
+
end
|
612
|
+
|
613
|
+
protected
|
614
|
+
|
615
|
+
# @private
|
616
|
+
def _copy(options={})
|
617
|
+
if options.key?('label') # for JSON
|
618
|
+
opt = {}
|
619
|
+
options.each_pair do |key, value|
|
620
|
+
opt[key.to_sym] = value
|
621
|
+
end
|
622
|
+
else
|
623
|
+
opt = options
|
624
|
+
end
|
625
|
+
|
626
|
+
self[0..-1] = opt[:label] if opt[:label]
|
627
|
+
if opt[:names]
|
628
|
+
@names = opt[:names]
|
629
|
+
@keys = @names.keys.sort
|
630
|
+
@values = @names.values.compact.sort.reverse
|
631
|
+
end
|
632
|
+
@label = opt[:label] if opt[:label]
|
633
|
+
@link = opt[:link] if opt[:link]
|
634
|
+
@access_key = opt[:access_key] if opt[:access_key]
|
635
|
+
@code_space = opt[:code_space] if opt[:code_space]
|
636
|
+
return self
|
637
|
+
end
|
638
|
+
|
639
|
+
# @private
|
640
|
+
def _copy_all(other)
|
641
|
+
_copy({:label => other.to_s,
|
642
|
+
:names => other.names,
|
643
|
+
:link => other.link,
|
644
|
+
:access_key => other.access_key,
|
645
|
+
:code_space => other.code_space
|
646
|
+
})
|
647
|
+
end
|
648
|
+
|
649
|
+
# locale 指定を解析して @names の値を取り出す
|
650
|
+
# @private
|
651
|
+
def _label_value(locale)
|
652
|
+
label = Locale._hash_value(@names, locale, [])
|
653
|
+
return label if label
|
654
|
+
foreign = Locale._get_locale(locale, @access_key)
|
655
|
+
return @names[''] unless foreign
|
656
|
+
english = @names['en'] || @names['']
|
657
|
+
addition = english.dup.sub!(/\A#{Locale._get_locale('en', @access_key)['en']}/, '')
|
658
|
+
foreign[locale] += addition if addition
|
659
|
+
update(foreign)
|
660
|
+
return Locale._hash_value(@names, locale)
|
661
|
+
end
|
662
|
+
|
663
|
+
private
|
664
|
+
|
665
|
+
def _names(names, namespace, default_locale)
|
666
|
+
|
667
|
+
# names, link の組み立て
|
668
|
+
@names = {}
|
669
|
+
@link = {}
|
670
|
+
|
671
|
+
if names.kind_of?(String)
|
672
|
+
unless (names=~/\A\s*\[(.+?)\]\s*\z/m)
|
673
|
+
names = names.strip
|
674
|
+
@names[''] = names
|
675
|
+
@keys = ['']
|
676
|
+
@values = [names]
|
677
|
+
return names
|
678
|
+
end
|
679
|
+
names = $1.split(/[\n\r,]+/)
|
680
|
+
end
|
681
|
+
|
682
|
+
mark = []
|
683
|
+
asterisk = []
|
684
|
+
default_locale = default_locale.dup
|
685
|
+
names.each do |v|
|
686
|
+
v.strip!
|
687
|
+
case v
|
688
|
+
when '', /\A#/ ;
|
689
|
+
when /\A\/(.+)/; @access_key = $1
|
690
|
+
when /\A(\*)?(?:([^=%]*?)\s*:)?\s*(.+?)\s*(=\s*([^=]+?(\?.+)?)?)?\z/
|
691
|
+
asterisk[0], locale, name, assignment, ref = $~[1..5]
|
692
|
+
asterisk[1], locale, default_ref = default_locale.shift unless locale
|
693
|
+
locale ||= ''
|
694
|
+
ref ||= default_ref unless (assignment)
|
695
|
+
ref ||= ''
|
696
|
+
mark[0] = locale if asterisk[0]
|
697
|
+
mark[1] = locale if asterisk[1]
|
698
|
+
mark[2] = locale unless mark[2]
|
699
|
+
name = _replacement($1, locale, ($3 || @names['en'] || @names[''])) if name =~ /\A_([A-Z_]+)_(\((.+)\))?\z/
|
700
|
+
name.gsub!(/<[0-9A-F]{2}>/i) {|code| code[1..2].to_i(16).chr}
|
701
|
+
@names[locale] = name
|
702
|
+
if ref =~ /\A(.+):/
|
703
|
+
prefix = namespace[$1] || Locale.send(:_namespaces)[$1]
|
704
|
+
ref.sub!(/\A.+:/, prefix) if prefix
|
705
|
+
end
|
706
|
+
ref += name =~ /\A<.+>\z/ ? '%%' + name : '%%<' + name + '>' if ref =~ /[\/#:]\z/
|
707
|
+
unless ref == ''
|
708
|
+
@link[locale] = _encode(ref)
|
709
|
+
# When.logger.info("%s[%s]->%s" % [@names[locale], locale, @link[locale]]) if When.logger
|
710
|
+
end
|
711
|
+
else ; raise ArgumentError, "Irregal locale format: " + v
|
712
|
+
end
|
713
|
+
end
|
714
|
+
if Locale.wikipedia_interval && Locale.wikipedia_interval <= 0
|
715
|
+
['en', ''].each do |lc|
|
716
|
+
if Locale::Ref =~ @link[lc] && $1 == 'en'
|
717
|
+
object = Locale.send(:wikipedia_object, @link[lc])
|
718
|
+
if object
|
719
|
+
@names = object.names.merge(@names)
|
720
|
+
@link = object.link.merge(@link)
|
721
|
+
end
|
722
|
+
break
|
723
|
+
end
|
724
|
+
end
|
725
|
+
end
|
726
|
+
|
727
|
+
# keys, values の準備
|
728
|
+
@keys = @names.keys.sort
|
729
|
+
@values = @names.values.sort.reverse
|
730
|
+
|
731
|
+
# 代表名
|
732
|
+
@names[mark[0] || mark[1] || mark[2]]
|
733
|
+
end
|
734
|
+
|
735
|
+
#
|
736
|
+
# 英語表記を現地表記に置き換える
|
737
|
+
#
|
738
|
+
def _replacement(table, locale, name)
|
739
|
+
Locale.const_get(table.split('_')[-1])[locale] ?
|
740
|
+
Locale.send(table.downcase, name, locale) :
|
741
|
+
name
|
742
|
+
end
|
743
|
+
|
744
|
+
# encode URI from patterns %%(...) or %.(...)
|
745
|
+
def _encode(source)
|
746
|
+
source.gsub(/%.<.+?>/) do |match|
|
747
|
+
URI.encode(match[3..-2]).gsub('%', match[1..1])
|
748
|
+
end
|
749
|
+
end
|
750
|
+
end
|
751
|
+
end
|