1if not modules then modules = { } end modules [ ' core-con ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to core-con.mkiv " ,
4 author = " Hans Hagen, PRAGMA-ADE, Hasselt NL " ,
5 copyright = " PRAGMA ADE / ConTeXt Development Team " ,
6 license = " see context related readme files "
7}
8
9
10
11
18
19local floor = math . floor
20local osdate , ostime = os . date , os . time
21local concat , insert , reverse = table . concat , table . insert , table . reverse
22local lower , upper , rep , match , gsub = string . lower , string . upper , string . rep , string . match , string . gsub
23local utfchar , utfbyte = utf . char , utf . byte
24local tonumber , tostring , type , rawset = tonumber , tostring , type , rawset
25local P , S , R , Cc , Cf , Cg , Ct , Cs , C , V , Carg = lpeg . P , lpeg . S , lpeg . R , lpeg . Cc , lpeg . Cf , lpeg . Cg , lpeg . Ct , lpeg . Cs , lpeg . C , lpeg . V , lpeg . Carg
26local lpegmatch , lpegpatterns = lpeg . match , lpeg . patterns
27local div , mod = math . div , math . mod
28
29local context = context
30local commands = commands
31local implement = interfaces . implement
32
33local settings_to_array = utilities . parsers . settings_to_array
34local allocate = utilities . storage . allocate
35local setmetatableindex = table . setmetatableindex
36local formatters = string . formatters
37local variables = interfaces . variables
38local constants = interfaces . constants
39local addformatter = utilities . strings . formatters . add
40
41local texset = tex . set
42
43converters = converters or { }
44local converters = converters
45
46languages = languages or { }
47local languages = languages
48
49local helpers = converters . helpers or { }
50converters . helpers = helpers
51
52local ctx_labeltext = context . labeltext
53local ctx_LABELTEXT = context . LABELTEXT
54local ctx_space = context . space
55local ctx_convertnumber = context . convertnumber
56local ctx_highordinalstr = context . highordinalstr
57
58converters . number = tonumber
59converters . numbers = tonumber
60
61implement { name = " number " , actions = context }
62implement { name = " numbers " , actions = context }
63
64
65
66local counters = allocate {
67 [ ' default ' ] = {
68 0x0061 , 0x0062 , 0x0063 , 0x0064 , 0x0065 ,
69 0x0066 , 0x0067 , 0x0068 , 0x0069 , 0x006A ,
70 0x006B , 0x006C , 0x006D , 0x006E , 0x006F ,
71 0x0070 , 0x0071 , 0x0072 , 0x0073 , 0x0074 ,
72 0x0075 , 0x0076 , 0x0077 , 0x0078 , 0x0079 ,
73 0x007A
74 } ,
75 [ ' slovenian ' ] = {
76 0x0061 , 0x0062 , 0x0063 , 0x010D , 0x0064 ,
77 0x0065 , 0x0066 , 0x0067 , 0x0068 , 0x0069 ,
78 0x006A , 0x006B , 0x006C , 0x006D , 0x006E ,
79 0x006F , 0x0070 , 0x0072 , 0x0073 , 0x0161 ,
80 0x0074 , 0x0075 , 0x0076 , 0x007A , 0x017E
81 } ,
82 [ ' spanish ' ] = {
83 0x0061 , 0x0062 , 0x0063 , 0x0064 , 0x0065 ,
84 0x0066 , 0x0067 , 0x0068 , 0x0069 , 0x006A ,
85 0x006B , 0x006C , 0x006D , 0x006E , 0x00F1 ,
86 0x006F , 0x0070 , 0x0071 , 0x0072 , 0x0073 ,
87 0x0074 , 0x0075 , 0x0076 , 0x0077 , 0x0078 ,
88 0x0079 , 0x007A
89 } ,
90 [ ' russian ' ] = {
91 0x0430 , 0x0431 , 0x0432 , 0x0433 , 0x0434 ,
92 0x0435 , 0x0436 , 0x0437 , 0x0438 , 0x043a ,
93 0x043b , 0x043c , 0x043d , 0x043e , 0x043f ,
94 0x0440 , 0x0441 , 0x0442 , 0x0443 , 0x0444 ,
95 0x0445 , 0x0446 , 0x0447 , 0x0448 , 0x0449 ,
96 0x044d , 0x044e , 0x044f
97 } ,
98 [ ' greek ' ] = {
99
100
101
102
103
104 0x03B1 , 0x03B2 , 0x03B3 , 0x03B4 , 0x03B5 ,
105 0x03B6 , 0x03B7 , 0x03B8 , 0x03B9 , 0x03BA ,
106 0x03BB , 0x03BC , 0x03BD , 0x03BE , 0x03BF ,
107 0x03C0 , 0x03C1 , 0x03C3 , 0x03C4 , 0x03C5 ,
108 0x03C6 , 0x03C7 , 0x03C8 , 0x03C9 ,
109 } ,
110 [ ' arabic ' ] = {
111 0x0627 , 0x0628 , 0x062C , 0x062F , 0x0647 ,
112 0x0648 , 0x0632 , 0x062D , 0x0637 , 0x0649 ,
113 0x0643 , 0x0644 , 0x0645 , 0x0646 , 0x0633 ,
114 0x0639 , 0x0641 , 0x0635 , 0x0642 , 0x0631 ,
115 0x0634 , 0x062A , 0x062B , 0x062E , 0x0630 ,
116 0x0636 , 0x0638 , 0x063A ,
117 } ,
118 [ ' persian ' ] = {
119 0x0627 , 0x0628 , 0x062C , 0x062F , 0x0647 ,
120 0x0648 , 0x0632 , 0x062D , 0x0637 , 0x0649 ,
121 0x06A9 , 0x0644 , 0x0645 , 0x0646 , 0x0633 ,
122 0x0639 , 0x0641 , 0x0635 , 0x0642 , 0x0631 ,
123 0x0634 , 0x062A , 0x062B , 0x062E , 0x0630 ,
124 0x0636 , 0x0638 , 0x063A ,
125 } ,
126 [ ' thai ' ] = {
127 0xE050 , 0xE051 , 0xE052 , 0xE053 , 0xE054 ,
128 0xE055 , 0xE056 , 0xE057 , 0xE058 , 0xE059
129 } ,
130 [ ' devangari ' ] = {
131 0x0966 , 0x0967 , 0x0968 , 0x0969 , 0x096A ,
132 0x096B , 0x096C , 0x096D , 0x096E , 0x096F
133 } ,
134 [ ' gurmurkhi ' ] = {
135 0x0A66 , 0x0A67 , 0x0A68 , 0x0A69 , 0x0A6A ,
136 0x0A6B , 0x0A6C , 0x0A6D , 0x0A6E , 0x0A6F
137 } ,
138 [ ' gujarati ' ] = {
139 0x0AE6 , 0x0AE7 , 0x0AE8 , 0x0AE9 , 0x0AEA ,
140 0x0AEB , 0x0AEC , 0x0AED , 0x0AEE , 0x0AEF
141 } ,
142 [ ' tibetan ' ] = {
143 0x0F20 , 0x0F21 , 0x0F22 , 0x0F23 , 0x0F24 ,
144 0x0F25 , 0x0F26 , 0x0F27 , 0x0F28 , 0x0F29
145 } ,
146 [ ' korean ' ] = {
147 0x3131 , 0x3134 , 0x3137 , 0x3139 , 0x3141 ,
148 0x3142 , 0x3145 , 0x3147 , 0x3148 , 0x314A ,
149 0x314B , 0x314C , 0x314D , 0x314E
150 } ,
151 [ ' korean-parenthesis ' ] = {
152 0x3200 , 0x3201 , 0x3202 , 0x3203 , 0x3204 ,
153 0x3205 , 0x3206 , 0x3207 , 0x3208 , 0x3209 ,
154 0x320A , 0x320B , 0x320C , 0x320D
155 } ,
156 [ ' korean-circle ' ] = {
157 0x3260 , 0x3261 , 0x3262 , 0x3263 , 0x3264 ,
158 0x3265 , 0x3266 , 0x3267 , 0x3268 , 0x3269 ,
159 0x326A , 0x326B , 0x326C , 0x326D
160 } ,
161}
162
163languages . counters = counters
164
165counters [ ' ar ' ] = counters [ ' arabic ' ]
166counters [ ' gr ' ] = counters [ ' greek ' ]
167counters [ ' g ' ] = counters [ ' greek ' ]
168counters [ ' sl ' ] = counters [ ' slovenian ' ]
169counters [ ' es ' ] = counters [ ' spanish ' ]
170counters [ ' ru ' ] = counters [ ' russian ' ]
171counters [ ' kr ' ] = counters [ ' korean ' ]
172counters [ ' kr-p ' ] = counters [ ' korean-parenthesis ' ]
173counters [ ' kr-c ' ] = counters [ ' korean-circle ' ]
174
175counters [ ' thainumerals ' ] = counters [ ' thai ' ]
176counters [ ' devanagarinumerals ' ] = counters [ ' devanagari ' ]
177counters [ ' gurmurkhinumerals ' ] = counters [ ' gurmurkhi ' ]
178counters [ ' gujaratinumerals ' ] = counters [ ' gujarati ' ]
179counters [ ' tibetannumerals ' ] = counters [ ' tibetan ' ]
180counters [ ' greeknumerals ' ] = counters [ ' greek ' ]
181counters [ ' arabicnumerals ' ] = counters [ ' arabic ' ]
182counters [ ' persiannumerals ' ] = counters [ ' persian ' ]
183counters [ ' arabicexnumerals ' ] = counters [ ' persian ' ]
184counters [ ' koreannumerals ' ] = counters [ ' korean ' ]
185counters [ ' koreanparenthesisnumerals ' ] = counters [ ' korean-parenthesis ' ]
186counters [ ' koreancirclenumerals ' ] = counters [ ' korean-circle ' ]
187
188counters [ ' sloveniannumerals ' ] = counters [ ' slovenian ' ]
189counters [ ' spanishnumerals ' ] = counters [ ' spanish ' ]
190counters [ ' russiannumerals ' ] = counters [ ' russian ' ]
191
192local decimals = allocate {
193 [ ' arabic ' ] = {
194 [ " 0 " ] = " ٠ " , [ " 1 " ] = " ١ " , [ " 2 " ] = " ٢ " , [ " 3 " ] = " ٣ " , [ " 4 " ] = " ٤ " ,
195 [ " 5 " ] = " ٥ " , [ " 6 " ] = " ٦ " , [ " 7 " ] = " ٧ " , [ " 8 " ] = " ٨ " , [ " 9 " ] = " ٩ " ,
196 } ,
197 [ ' persian ' ] = {
198 [ " 0 " ] = " ۰ " , [ " 1 " ] = " ۱ " , [ " 2 " ] = " ۲ " , [ " 3 " ] = " ۳ " , [ " 4 " ] = " ۴ " ,
199 [ " 5 " ] = " ۵ " , [ " 6 " ] = " ۶ " , [ " 7 " ] = " ۷ " , [ " 8 " ] = " ۸ " , [ " 9 " ] = " ۹ " ,
200 }
201}
202
203languages . decimals = decimals
204
205local fallback = utfbyte ( ' 0 ' )
206
207local function chr ( n , m )
208 return ( n > 0 and n < 27 and utfchar ( n + m ) ) or " "
209end
210
211local function chrs ( n , m , t )
212 if not t then
213 t = { }
214 end
215 if n > 26 then
216 chrs ( floor ( ( n -1 ) / 26 ) , m , t )
217 n = ( n -1 ) % 26 + 1
218 end
219 if n ~ = 0 then
220 t [ # t + 1 ] = utfchar ( n + m )
221 end
222 if n < = 26 then
223 return concat ( t )
224 end
225end
226
227local function maxchrs ( n , m , cmd , t )
228 if not t then
229 t = { }
230 end
231 if n > m then
232 maxchrs ( floor ( ( n -1 ) / m ) , m , cmd )
233 n = ( n -1 ) % m + 1
234 end
235 t [ # t + 1 ] = formatters [ " %s{%s} " ] ( cmd , n )
236 if n < = m then
237 return concat ( t )
238 end
239end
240
241converters . chr = chr
242converters . chrs = chrs
243converters . maxchrs = maxchrs
244
245local lowercharacter = characters . lcchars
246local uppercharacter = characters . ucchars
247
248local defaultcounter = counters . default
249
250local function do_alphabetic ( n , mapping , mapper , t )
251 if not t then
252 t = { }
253 end
254 local max = # mapping
255 if n > max then
256 do_alphabetic ( floor ( ( n -1 ) / max ) , mapping , mapper , t )
257 n = ( n -1 ) % max + 1
258 end
259 local chr = mapping [ n ] or fallback
260 t [ # t + 1 ] = mapper and mapper [ chr ] or chr
261 if n < = max then
262 return concat ( t )
263 end
264end
265
266local function alphabetic ( n , code )
267 return do_alphabetic ( n , code and code ~ = " " and counters [ code ] or defaultcounter , lowercharacter )
268end
269
270local function Alphabetic ( n , code )
271 return do_alphabetic ( n , code and code ~ = " " and counters [ code ] or defaultcounter , uppercharacter )
272end
273
274converters . alphabetic = alphabetic
275converters . Alphabetic = Alphabetic
276
277
278
279local function todecimals ( n , name )
280 local stream = tostring ( n )
281 local mapping = decimals [ name ]
282 return mapping and gsub ( stream , " . " , mapping ) or stream
283end
284
285converters . decimals = todecimals
286
287local lower_offset = 96
288local upper_offset = 64
289
290function converters . character ( n ) return chr ( n , lower_offset ) end
291function converters . Character ( n ) return chr ( n , upper_offset ) end
292function converters . characters ( n ) return chrs ( n , lower_offset ) end
293function converters . Characters ( n ) return chrs ( n , upper_offset ) end
294
295implement { name = " alphabetic " , actions = { alphabetic , context } , arguments = { " integer " , " string " } }
296implement { name = " Alphabetic " , actions = { Alphabetic , context } , arguments = { " integer " , " string " } }
297
298implement { name = " character " , actions = { chr , context } , arguments = { " integer " , lower_offset } }
299implement { name = " Character " , actions = { chr , context } , arguments = { " integer " , upper_offset } }
300implement { name = " characters " , actions = { chrs , context } , arguments = { " integer " , lower_offset } }
301implement { name = " Characters " , actions = { chrs , context } , arguments = { " integer " , upper_offset } }
302
303implement { name = " decimals " , actions = { todecimals , context } , arguments = { " integer " , " string " } }
304
305local weekday = os . weekday
306local isleapyear = os . isleapyear
307local nofdays = os . nofdays
308
309local function leapyear ( year )
310 return isleapyear ( year ) and 1 or 0
311end
312
313local function textime ( )
314 return tonumber ( osdate ( " %H " ) ) * 60 + tonumber ( osdate ( " %M " ) )
315end
316
317
318
319
320
321
322
323
324
325
326
327converters . weekday = weekday
328converters . isleapyear = isleapyear
329converters . leapyear = leapyear
330converters . nofdays = nofdays
331converters . textime = textime
332
333implement { name = " weekday " , actions = { weekday , context } , arguments = { " integer " , " integer " , " integer " } }
334implement { name = " leapyear " , actions = { leapyear , context } , arguments = " integer " }
335implement { name = " nofdays " , actions = { nofdays , context } , arguments = { " integer " , " integer " } }
336
337implement { name = " year " , actions = { osdate , context } , arguments = " '%Y' " }
338implement { name = " month " , actions = { osdate , context } , arguments = " '%m' " }
339implement { name = " day " , actions = { osdate , context } , arguments = " '%d' " }
340implement { name = " hour " , actions = { osdate , context } , arguments = " '%H' " }
341implement { name = " minute " , actions = { osdate , context } , arguments = " '%M' " }
342implement { name = " second " , actions = { osdate , context } , arguments = " '%S' " }
343implement { name = " textime " , actions = { textime , context } }
344
345implement {
346 name = " doifelseleapyear " ,
347 actions = { isleapyear , commands . doifelse } ,
348 arguments = " integer "
349}
350
351local roman = {
352 { [ 0 ] = ' ' , ' I ' , ' II ' , ' III ' , ' IV ' , ' V ' , ' VI ' , ' VII ' , ' VIII ' , ' IX ' } ,
353 { [ 0 ] = ' ' , ' X ' , ' XX ' , ' XXX ' , ' XL ' , ' L ' , ' LX ' , ' LXX ' , ' LXXX ' , ' XC ' } ,
354 { [ 0 ] = ' ' , ' C ' , ' CC ' , ' CCC ' , ' CD ' , ' D ' , ' DC ' , ' DCC ' , ' DCCC ' , ' CM ' } ,
355}
356
357local function toroman ( n )
358 if n > = 4000 then
359 return toroman ( floor ( n / 1000 ) ) . . " " . . toroman ( n % 1000 )
360 else
361 return rep ( " M " , floor ( n / 1000 ) ) . . roman [ 3 ] [ floor ( ( n % 1000 ) / 100 ) ] . . roman [ 2 ] [ floor ( ( n % 100 ) / 10 ) ] . . roman [ 1 ] [ floor ( ( n % 10 ) / 1 ) ]
362 end
363end
364
365converters . toroman = toroman
366converters . Romannumerals = toroman
367converters . romannumerals = function ( n ) return lower ( toroman ( n ) ) end
368
369converters [ ' i ' ] = converters . romannumerals
370converters [ ' I ' ] = converters . Romannumerals
371converters [ ' r ' ] = converters . romannumerals
372converters [ ' R ' ] = converters . Romannumerals
373converters [ ' KR ' ] = converters . Romannumerals
374converters [ ' RK ' ] = converters . Romannumerals
375
376implement {
377 name = " romannumerals " ,
378 actions = { toroman , lower , context } ,
379 arguments = " integer " ,
380}
381
382implement {
383 name = " Romannumerals " ,
384 actions = { toroman , context } ,
385 arguments = " integer " ,
386}
387
388
389
390
391
392
393
394
395
396
397
398
399local small = {
400 " ا " , " ٮ " , " ح " , " د " , " ه " , " و " , " ر " ,
401}
402
403local medium = {
404 " ا " , " ب " , " ج " , " د " , " ه " , " و " , " ز " , " ح " , " ط " ,
405 " ي " , " ك " , " ل " , " م " , " ن " , " س " , " ع " , " ف " , " ص " ,
406 " ق " , " ر " , " ش " , " ت " , " ث " , " خ " , " ذ " , " ض " , " ظ " ,
407 " غ " ,
408}
409
410local large = {
411 { " ا " , " ب " , " ج " , " د " , " ه " , " و " , " ز " , " ح " , " ط " } ,
412 { " ي " , " ك " , " ل " , " م " , " ن " , " س " , " ع " , " ف " , " ص " } ,
413 { " ق " , " ر " , " ش " , " ت " , " ث " , " خ " , " ذ " , " ض " , " ظ " } ,
414 { " غ " } ,
415}
416
417local function toabjad ( n , what )
418 if n < = 0 or n > = 2000 then
419 return tostring ( n )
420 elseif what = = 2 and n < = 7 then
421 return small [ n ]
422 elseif what = = 3 and n < = 28 then
423 return medium [ n ]
424 else
425 local a , b , c , d
426 a , n = floor ( n / 1000 ) , n % 1000
427 b , n = floor ( n / 100 ) , n % 100
428 c , n = floor ( n / 10 ) , n % 10
429 d , n = floor ( n / 1 ) , n % 1
430 return ( large [ 4 ] [ a ] or " " ) . . ( large [ 3 ] [ b ] or " " ) . . ( large [ 2 ] [ c ] or " " ) . . ( large [ 1 ] [ d ] or " " )
431 end
432end
433
434converters . toabjad = toabjad
435
436function converters . abjadnumerals ( n ) return toabjad ( n , false ) end
437function converters . abjadnodotnumerals ( n ) return toabjad ( n , true ) end
438
439implement {
440 name = " abjadnumerals " ,
441 actions = { toabjad , context } ,
442 arguments = { " integer " , false }
443}
444
445implement {
446 name = " abjadnodotnumerals " ,
447 actions = { toabjad , context } ,
448 arguments = { " integer " , true }
449}
450
451
452
453local trace_hebrew trackers . register ( " converters.hebrew " , function ( v )
454 trace_hebrew = v
455end )
456
457local list = {
458 { 400 , " ת " } , { 300 , " ש " } , { 200 , " ר " } , { 100 , " ק " } ,
459 { 90 , " צ " } , { 80 , " פ " } , { 70 , " ע " } , { 60 , " ס " } , { 50 , " נ " } , { 40 , " מ " } , { 30 , " ל " } , { 20 , " כ " } , { 10 , " י " } ,
460 { 9 , " ט " } , { 8 , " ח " } , { 7 , " ז " , } , { 6 , " ו " , } , { 5 , " ה " } , { 4 , " ד " } , { 3 , " ג " } , { 2 , " ב " } , { 1 , " א " } ,
461}
462
463local special = {
464 [ 15 ] = " ט״ו " ,
465 [ 16 ] = " ט״ז " ,
466}
467
468local function tohebrew ( n , gershayim , geresh )
469 local split = { }
470 local size = 0
471 while n > 1000 do
472 size = size + 1
473 split [ size ] = n % 1000
474 n = floor ( n / 1000 )
475 end
476 size = size + 1
477 split [ size ] = n
478 for i = 1 , size do
479 local t = { }
480 local n = 0
481 local s = split [ i ]
482 while s > 0 do
483 for i = 1 , # list do
484 :: again ::
485 local li = list [ i ]
486 local l1 = li [ 1 ]
487 local s1 = special [ l1 ]
488 if s1 then
489 s = s - l1
490 n = n + 1
491 t [ n ] = s1
492 goto again
493 elseif s > = l1 then
494 s = s - l1
495 n = n + 1
496 t [ n ] = li [ 2 ]
497 goto again
498 end
499 end
500 end
501 :: done ::
502 split [ i ] = t
503 end
504 if gershayim then
505 for i = 1 , size do
506 local si = split [ i ]
507 local ni = # si
508 if ni > = 2 then
509 local s = " ״ "
510 insert ( split [ i ] , ni , trace_hebrew and ( " {\\red " . . s . . " } " ) or s )
511 end
512 end
513 end
514 if geresh then
515 for i = 2 , # split do
516 local s = rep ( " ׳ " , i -1 )
517 insert ( split [ i ] , trace_hebrew and ( " {\\blue " . . s . . " } " ) or s )
518 end
519 end
520 for i = 1 , size do
521 split [ i ] = concat ( split [ i ] )
522 end
523 return concat ( reverse ( split ) )
524end
525
526converters . tohebrew = tohebrew
527converters . hebrewnumerals = converters . tohebrew
528
529
530
531interfaces . implement {
532 name = " hebrewnumerals " ,
533 actions = { tohebrew , context } ,
534 arguments = { " integer " , true , true }
535}
536
537
538
539local vector = {
540 normal = {
541 [ 0 ] = " 〇 " ,
542 [ 1 ] = " 一 " ,
543 [ 2 ] = " 二 " ,
544 [ 3 ] = " 三 " ,
545 [ 4 ] = " 四 " ,
546 [ 5 ] = " 五 " ,
547 [ 6 ] = " 六 " ,
548 [ 7 ] = " 七 " ,
549 [ 8 ] = " 八 " ,
550 [ 9 ] = " 九 " ,
551 [ 10 ] = " 十 " ,
552 [ 100 ] = " 百 " ,
553 [ 1000 ] = " 千 " ,
554 [ 10000 ] = " 万 " ,
555 [ 100000000 ] = " 亿 " ,
556 } ,
557 cap = {
558 [ 0 ] = " 零 " ,
559 [ 1 ] = " 壹 " ,
560 [ 2 ] = " 贰 " ,
561 [ 3 ] = " 叁 " ,
562 [ 4 ] = " 肆 " ,
563 [ 5 ] = " 伍 " ,
564 [ 6 ] = " 陆 " ,
565 [ 7 ] = " 柒 " ,
566 [ 8 ] = " 捌 " ,
567 [ 9 ] = " 玖 " ,
568 [ 10 ] = " 拾 " ,
569 [ 100 ] = " 佰 " ,
570 [ 1000 ] = " 仟 " ,
571 [ 10000 ] = " 萬 " ,
572 [ 100000000 ] = " 亿 " ,
573 } ,
574 all = {
575 [ 0 ] = " 〇 " ,
576 [ 1 ] = " 一 " ,
577 [ 2 ] = " 二 " ,
578 [ 3 ] = " 三 " ,
579 [ 4 ] = " 四 " ,
580 [ 5 ] = " 五 " ,
581 [ 6 ] = " 六 " ,
582 [ 7 ] = " 七 " ,
583 [ 8 ] = " 八 " ,
584 [ 9 ] = " 九 " ,
585 [ 10 ] = " 十 " ,
586 [ 20 ] = " 廿 " ,
587 [ 30 ] = " 卅 " ,
588 [ 100 ] = " 百 " ,
589 [ 1000 ] = " 千 " ,
590 [ 10000 ] = " 万 " ,
591 [ 100000000 ] = " 亿 " ,
592 }
593}
594
595local function tochinese ( n , name )
596
597 local result , r = { } , 0
598 local vector = vector [ name ] or vector . normal
599 while true do
600 if n = = 0 then
601 break
602 elseif n > = 100000000 then
603 local m = floor ( n / 100000000 )
604 r = r + 1 ; result [ r ] = tochinese ( m , name )
605 r = r + 1 ; result [ r ] = vector [ 100000000 ]
606 local z = n - m * 100000000
607 if z > 0 and z < 10000000 then r = r + 1 ; result [ r ] = vector [ 0 ] end
608 n = n % 100000000
609 elseif n > = 10000000 then
610 local m = floor ( n / 10000 )
611 r = r + 1 ; result [ r ] = tochinese ( m , name )
612 r = r + 1 ; result [ r ] = vector [ 10000 ]
613 local z = n - m * 10000
614 if z > 0 and z < 1000 then r = r + 1 ; result [ r ] = vector [ 0 ] end
615 n = n % 10000
616 elseif n > = 1000000 then
617 local m = floor ( n / 10000 )
618 r = r + 1 ; result [ r ] = tochinese ( m , name )
619 r = r + 1 ; result [ r ] = vector [ 10000 ]
620 local z = n - m * 10000
621 if z > 0 and z < 1000 then r = r + 1 ; result [ r ] = vector [ 0 ] end
622 n = n % 10000
623 elseif n > = 100000 then
624 local m = floor ( n / 10000 )
625 r = r + 1 ; result [ r ] = tochinese ( m , name )
626 r = r + 1 ; result [ r ] = vector [ 10000 ]
627 local z = n - m * 10000
628 if z > 0 and z < 1000 then r = r + 1 ; result [ r ] = vector [ 0 ] end
629 n = n % 10000
630 elseif n > = 10000 then
631 local m = floor ( n / 10000 )
632 r = r + 1 ; result [ r ] = vector [ m ]
633 r = r + 1 ; result [ r ] = vector [ 10000 ]
634 local z = n - m * 10000
635 if z > 0 and z < 1000 then r = r + 1 ; result [ r ] = vector [ 0 ] end
636 n = n % 10000
637 elseif n > = 1000 then
638 local m = floor ( n / 1000 )
639 r = r + 1 ; result [ r ] = vector [ m ]
640 r = r + 1 ; result [ r ] = vector [ 1000 ]
641 local z = n - m * 1000
642 if z > 0 and z < 100 then r = r + 1 ; result [ r ] = vector [ 0 ] end
643 n = n % 1000
644 elseif n > = 100 then
645 local m = floor ( n / 100 )
646 r = r + 1 ; result [ r ] = vector [ m ]
647 r = r + 1 ; result [ r ] = vector [ 100 ]
648 local z = n - m * 100
649 if z > 0 and z < 10 then r = r + 1 ; result [ r ] = vector [ 0 ] end
650 n = n % 100
651 elseif n > = 10 then
652 local m = floor ( n / 10 )
653 if m > 1 and vector [ m * 10 ] then
654 r = r + 1 ; result [ r ] = vector [ m * 10 ]
655 else
656 r = r + 1 ; result [ r ] = vector [ m ]
657 r = r + 1 ; result [ r ] = vector [ 10 ]
658 end
659 n = n % 10
660 else
661 r = r + 1 ; result [ r ] = vector [ n ]
662 break
663 end
664 end
665 if ( result [ 1 ] = = vector [ 1 ] and result [ 2 ] = = vector [ 10 ] ) then
666 result [ 1 ] = " "
667 end
668 return concat ( result )
669end
670
671
672
673
674
675
676
677converters . tochinese = tochinese
678
679function converters . chinesenumerals ( n , how ) return tochinese ( n , how or " normal " ) end
680function converters . chinesecapnumerals ( n ) return tochinese ( n , " cap " ) end
681function converters . chineseallnumerals ( n ) return tochinese ( n , " all " ) end
682
683converters [ ' cn ' ] = converters . chinesenumerals
684converters [ ' cn-c ' ] = converters . chinesecapnumerals
685converters [ ' cn-a ' ] = converters . chineseallnumerals
686
687implement {
688 name = " chinesenumerals " ,
689 actions = { tochinese , context } ,
690 arguments = { " integer " , " string " }
691}
692
693
694
695
696converters [ ' a ' ] = converters . characters
697converters [ ' A ' ] = converters . Characters
698converters [ ' AK ' ] = converters . Characters
699converters [ ' KA ' ] = converters . Characters
700
701function converters . spanishnumerals ( n ) return alphabetic ( n , " es " ) end
702function converters . Spanishnumerals ( n ) return Alphabetic ( n , " es " ) end
703function converters . sloveniannumerals ( n ) return alphabetic ( n , " sl " ) end
704function converters . Sloveniannumerals ( n ) return Alphabetic ( n , " sl " ) end
705function converters . russiannumerals ( n ) return alphabetic ( n , " ru " ) end
706function converters . Russiannumerals ( n ) return Alphabetic ( n , " ru " ) end
707
708converters [ ' alphabetic:es ' ] = converters . spanishnumerals
709converters [ ' alphabetic:sl ' ] = converters . sloveniannumerals
710converters [ ' alphabetic:ru ' ] = converters . russiannumerals
711
712converters [ ' Alphabetic:es ' ] = converters . Spanishnumerals
713converters [ ' Alphabetic:sl ' ] = converters . Sloveniannumerals
714converters [ ' Alphabetic:ru ' ] = converters . Russiannumerals
715
716
717
718converters [ ' a:es ' ] = converters . spanishnumerals
719converters [ ' a:sl ' ] = converters . sloveniannumerals
720converters [ ' a:ru ' ] = converters . russiannumerals
721converters [ ' A:es ' ] = converters . Spanishnumerals
722converters [ ' A:sl ' ] = converters . Sloveniannumerals
723converters [ ' A:ru ' ] = converters . Russiannumerals
724
725
726
727converters . sequences = converters . sequences or { }
728local sequences = converters . sequences
729
730storage . register ( " converters/sequences " , sequences , " converters.sequences " )
731
732function converters . define ( name , set )
733
734
735
736 sequences [ name ] = settings_to_array ( set )
737end
738
739function converters . max ( name )
740 local s = sequences [ name ]
741 return s and # s or 0
742end
743
744implement {
745 name = " defineconversion " ,
746 actions = converters . define ,
747 arguments = " 2 strings " ,
748}
749
750implement {
751 name = " nofconversions " ,
752 actions = { converters . max , context } ,
753 arguments = " string " ,
754}
755
756local function convert ( method , n , language )
757 local converter = language and converters [ method . . " : " . . language ] or converters [ method ]
758 if converter then
759 return converter ( n )
760 else
761 local lowermethod = lower ( method )
762 local linguistic = counters [ lowermethod ]
763 if linguistic then
764 return do_alphabetic ( n , linguistic , lowermethod = = method and lowercharacter or uppercharacter )
765 end
766 local sequence = sequences [ method ]
767 if sequence then
768 local max = # sequence
769 if n > max then
770 return sequence [ ( n -1 ) % max + 1 ]
771 else
772 return sequence [ n ]
773 end
774 end
775 return n
776 end
777end
778
779converters . convert = convert
780
781local function valid ( method , language )
782 return converters [ method . . " : " . . language ] or converters [ method ] or sequences [ method ]
783end
784
785implement {
786 name = " doifelseconverter " ,
787 actions = { valid , commands . doifelse } ,
788 arguments = " 2 strings " ,
789}
790
791implement {
792 name = " checkedconversion " ,
793 actions = { convert , context } ,
794 arguments = { " string " , " integer " }
795}
796
797
798
799local gregorian_to_hebrew do
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817 local NISAN = 1
818 local IYYAR = 2
819 local SIVAN = 3
820 local TAMUZ = 4
821 local AV = 5
822 local ELUL = 6
823 local TISHREI = 7
824 local CHESHVAN = 8
825 local KISLEV = 9
826 local TEVET = 10
827 local SHVAT = 11
828 local ADAR_I = 12
829 local ADAR_II = 13
830
831 local mmap = {
832 KISLEV ,
833 TEVET ,
834 SHVAT ,
835 ADAR_I ,
836 NISAN ,
837 IYYAR ,
838 SIVAN ,
839 TAMUZ ,
840 TISHREI ,
841 TISHREI ,
842 TISHREI ,
843 CHESHVAN
844 }
845
846 local function greg2abs ( year , month , day )
847 local y = year - 1
848 return y * 365 + div ( y , 4 ) - div ( y , 100 ) + div ( y , 400 ) + os . nofdays ( year , month , day )
849 end
850
851 local function abs2greg ( abs )
852
853 local d0 = abs - 1
854
855 local n400 = div ( d0 , 146097 )
856 local d1 = mod ( d0 , 146097 )
857 local n100 = div ( d1 , 36524 )
858 local d2 = mod ( d1 , 36524 )
859 local n4 = div ( d2 , 1461 )
860 local d3 = mod ( d2 , 1461 )
861 local n1 = div ( d3 , 365 )
862
863 local day = mod ( d3 , 365 ) + 1
864 local year = 400 * n400 + 100 * n100 + 4 * n4 + n1
865
866 if n100 = = 4 or n1 = = 4 then
867 return year , 12 , 31
868 else
869 year = year + 1
870 month = 1
871 while true do
872 local mlen = os . nofdays ( year , month )
873 if mlen < day then
874 day = day - mlen
875 month = month + 1
876 else
877 break
878 end
879 end
880 return year , month , day
881 end
882 end
883
884 local function hebrew_leapyear ( year )
885 return mod ( 1 + year * 7 , 19 ) < 7
886 end
887
888 local function hebrew_months_in_year ( year )
889 return hebrew_leapyear ( year ) and 13 or 12
890 end
891
892 local function hebrew_elapsed_days ( year )
893 local y = year - 1
894 local m_elapsed = 235 * div ( y , 19 ) + 12 * mod ( y , 19 ) + div ( ( ( mod ( y , 19 ) * 7 ) + 1 ) , 19 )
895 local p_elapsed = 204 + 793 * mod ( m_elapsed , 1080 )
896 local h_elapsed = 5 + 12 * m_elapsed + 793 * div ( m_elapsed , 1080 ) + div ( p_elapsed , 1080 )
897 local parts = mod ( p_elapsed , 1080 ) + 1080 * mod ( h_elapsed , 24 )
898 local day = 1 + 29 * m_elapsed + div ( h_elapsed , 24 )
899 local d = mod ( day , 7 )
900 local alt_day = day
901 if parts > = 19440
902 or ( parts > = 9924 and d = = 2 and not ( hebrew_leapyear ( year ) ) )
903 or ( parts > = 16789 and d = = 1 and hebrew_leapyear ( y ) ) then
904 alt_day = alt_day + 1
905 end
906 d = mod ( alt_day , 7 )
907 if d = = 0 or d = = 3 or d = = 5 then
908 alt_day = alt_day + 1
909 end
910 return alt_day
911 end
912
913 local function days_in_hebrew_year ( year )
914 return hebrew_elapsed_days ( year + 1 ) - hebrew_elapsed_days ( year )
915 end
916
917 local function long_cheshvan ( year )
918 return mod ( days_in_hebrew_year ( year ) , 10 ) = = 5
919 end
920
921 local function short_kislev ( year )
922 return mod ( days_in_hebrew_year ( year ) , 10 ) = = 3
923 end
924
925 local function max_days_in_heb_month ( month , year )
926 if month = = IYYAR or month = = TAMUZ or month = = ELUL or month = = TEVET or month = = ADAR_II or
927 ( month = = ADAR_I and not hebrew_leapyear ( year ) ) or
928 ( month = = CHESHVAN and not long_cheshvan ( year ) ) or
929 ( month = = KISLEV and short_kislev ( year ) ) then
930 return 29
931 else
932 return 30
933 end
934 end
935
936 local function hebrew2abs ( year , month , day )
937 if month < TISHREI then
938 for m = TISHREI , hebrew_months_in_year ( year ) , 1 do
939 day = day + max_days_in_heb_month ( m , year )
940 end
941 for m = NISAN , month - 1 , 1 do
942 day = day + max_days_in_heb_month ( m , year )
943 end
944 else
945 for m = TISHREI , month - 1 , 1 do
946 day = day + max_days_in_heb_month ( m , year )
947 end
948 end
949 return hebrew_elapsed_days ( year ) - 1373429 + day
950 end
951
952 local function abs2hebrew ( abs )
953 local yy , mm , dd = abs2greg ( abs )
954 local day = 1
955 local month = TISHREI
956 local year = 3760 + yy
957 while abs > = hebrew2abs ( year + 1 , month , day ) do
958 year = year + 1
959 end
960 if year > = 4635 and year < 10666 then
961 month = mmap [ mm ]
962 end
963 while abs > hebrew2abs ( year , month , max_days_in_heb_month ( month , year ) ) do
964 month = mod ( month , hebrew_months_in_year ( year ) ) + 1
965 end
966 day = abs - hebrew2abs ( year , month , 1 ) + 1
967 return year , month , day
968 end
969
970
971
972 gregorian_to_hebrew = function ( y , m , d )
973 return abs2hebrew ( greg2abs ( y , m , d ) )
974 end
975
976 converters . gregorian_to_hebrew = gregorian_to_hebrew
977
978end
979
980local gregorian_to_jalali , jalali_to_gregorian do
981
982
983
984
985
986
987
988
989
990
991
992
993
994 local g_days_in_month = { [ 0 ] = 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 }
995 local j_days_in_month = { [ 0 ] = 31 , 31 , 31 , 31 , 31 , 31 , 30 , 30 , 30 , 30 , 30 , 29 }
996
997
998 gregorian_to_jalali = function ( gy , gm , gd )
999 local jy , jm , jd , g_day_no , j_day_no , j_np , i
1000 gy , gm , gd = gy - 1600 , gm - 1 , gd - 1
1001 g_day_no = 365 * gy + div ( ( gy + 3 ) , 4 ) - div ( ( gy + 99 ) , 100 ) + div ( ( gy + 399 ) , 400 )
1002 i = 0
1003 while i < gm do
1004 g_day_no = g_day_no + g_days_in_month [ i ]
1005 i = i + 1
1006 end
1007 if ( gm > 1 and ( ( gy % 4 = = 0 and gy % 100 ~ = 0 ) or ( gy % 400 = = 0 ) ) ) then
1008 g_day_no = g_day_no + 1
1009 end
1010 g_day_no = g_day_no + gd
1011 j_day_no = g_day_no - 79
1012 j_np = div ( j_day_no , 12053 )
1013 j_day_no = mod ( j_day_no , 12053 )
1014 jy = 979 + 33 * j_np + 4 * div ( j_day_no , 1461 )
1015 j_day_no = mod ( j_day_no , 1461 )
1016 if j_day_no > = 366 then
1017 jy = jy + div ( ( j_day_no -1 ) , 365 )
1018 j_day_no = mod ( ( j_day_no -1 ) , 365 )
1019 end
1020 i = 0
1021 while i < 11 and j_day_no > = j_days_in_month [ i ] do
1022 j_day_no = j_day_no - j_days_in_month [ i ]
1023 i = i + 1
1024 end
1025 jm = i + 1
1026 jd = j_day_no + 1
1027 return jy , jm , jd
1028 end
1029
1030 jalali_to_gregorian = function ( jy , jm , jd )
1031 local gy , gm , gd , g_day_no , j_day_no , leap , i
1032 jy , jm , jd = jy - 979 , jm - 1 , jd - 1
1033 j_day_no = 365 * jy + div ( jy , 33 ) * 8 + div ( ( mod ( jy , 33 ) + 3 ) , 4 )
1034 for i = 0 , jm -1 , 1 do
1035 j_day_no = j_day_no + j_days_in_month [ i ]
1036 end
1037 j_day_no = j_day_no + jd
1038 g_day_no = j_day_no + 79
1039 gy = 1600 + 400 * div ( g_day_no , 146097 )
1040 g_day_no = mod ( g_day_no , 146097 )
1041 leap = 1
1042 if g_day_no > = 36525 then
1043 g_day_no = g_day_no - 1
1044 gy = gy + 100 * div ( g_day_no , 36524 )
1045 g_day_no = mod ( g_day_no , 36524 )
1046 if g_day_no > = 365 then
1047 g_day_no = g_day_no + 1
1048 else
1049 leap = 0
1050 end
1051 end
1052 gy = gy + 4 * div ( g_day_no , 1461 )
1053 g_day_no = mod ( g_day_no , 1461 )
1054 if g_day_no > = 366 then
1055 leap = 0
1056 g_day_no = g_day_no - 1
1057 gy = gy + div ( g_day_no , 365 )
1058 g_day_no = mod ( g_day_no , 365 )
1059 end
1060 i = 0
1061 while true do
1062 local d = g_days_in_month [ i ] + ( ( i = = 1 and leap ) or 0 )
1063 if g_day_no > = d then
1064 g_day_no = g_day_no - d
1065 i = i + 1
1066 else
1067 break
1068 end
1069 end
1070 gm = i + 1
1071 gd = g_day_no + 1
1072 return gy , gm , gd
1073 end
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090 converters . gregorian_to_jalali = gregorian_to_jalali
1091 converters . jalali_to_gregorian = jalali_to_gregorian
1092
1093end
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131local ordinals = {
1132 english = function ( n )
1133 local two = n % 100
1134 if two = = 11 or two = = 12 or two = = 13 then
1135 return " th "
1136 else
1137 local one = n % 10
1138 if one = = 1 then
1139 return " st "
1140 elseif one = = 2 then
1141 return " nd "
1142 elseif one = = 3 then
1143 return " rd "
1144 else
1145 return " th "
1146 end
1147 end
1148 end ,
1149 dutch = function ( n )
1150 return " e "
1151 end ,
1152 french = function ( n )
1153 if n = = 1 then
1154 return " er "
1155 end
1156 end ,
1157}
1158
1159ordinals . en = ordinals . english
1160ordinals . nl = ordinals . dutch
1161ordinals . fr = ordinals . french
1162
1163function converters . ordinal ( n , language )
1164 local t = language and ordinals [ language ]
1165 return t and t ( n )
1166end
1167
1168local function ctxordinal ( n , language )
1169 local t = language and ordinals [ language ]
1170 local o = t and t ( n )
1171 context ( n )
1172 if o then
1173 ctx_highordinalstr ( o )
1174 end
1175end
1176
1177implement {
1178 name = " ordinal " ,
1179 actions = ctxordinal ,
1180 arguments = { " integer " , " string " }
1181}
1182
1183
1184
1185local data = allocate ( )
1186local verbose = { data = data }
1187converters . verbose = verbose
1188
1189
1190
1191local words = {
1192 [ 0 ] = " zero " ,
1193 [ 1 ] = " one " ,
1194 [ 2 ] = " two " ,
1195 [ 3 ] = " three " ,
1196 [ 4 ] = " four " ,
1197 [ 5 ] = " five " ,
1198 [ 6 ] = " six " ,
1199 [ 7 ] = " seven " ,
1200 [ 8 ] = " eight " ,
1201 [ 9 ] = " nine " ,
1202 [ 10 ] = " ten " ,
1203 [ 11 ] = " eleven " ,
1204 [ 12 ] = " twelve " ,
1205 [ 13 ] = " thirteen " ,
1206 [ 14 ] = " fourteen " ,
1207 [ 15 ] = " fifteen " ,
1208 [ 16 ] = " sixteen " ,
1209 [ 17 ] = " seventeen " ,
1210 [ 18 ] = " eighteen " ,
1211 [ 19 ] = " nineteen " ,
1212 [ 20 ] = " twenty " ,
1213 [ 30 ] = " thirty " ,
1214 [ 40 ] = " forty " ,
1215 [ 50 ] = " fifty " ,
1216 [ 60 ] = " sixty " ,
1217 [ 70 ] = " seventy " ,
1218 [ 80 ] = " eighty " ,
1219 [ 90 ] = " ninety " ,
1220 [ 100 ] = " hundred " ,
1221 [ 1000 ] = " thousand " ,
1222 [ 1000000 ] = " million " ,
1223 [ 1000000000 ] = " billion " ,
1224 [ 1000000000000 ] = " trillion " ,
1225}
1226
1227local function translate ( n )
1228 local w = words [ n ]
1229 if w then
1230 return w
1231 end
1232 local t = { }
1233 local function compose_one ( n )
1234 local w = words [ n ]
1235 if w then
1236 t [ # t + 1 ] = w
1237 return
1238 end
1239 local a , b = floor ( n / 100 ) , n % 100
1240 if a = = 10 then
1241 t [ # t + 1 ] = words [ 1 ]
1242 t [ # t + 1 ] = words [ 1000 ]
1243 elseif a > 0 then
1244 t [ # t + 1 ] = words [ a ]
1245 t [ # t + 1 ] = words [ 100 ]
1246
1247 if b = = 0 then
1248 return
1249 end
1250 end
1251 if words [ b ] then
1252 t [ # t + 1 ] = words [ b ]
1253 else
1254 a , b = floor ( b / 10 ) , n % 10
1255 t [ # t + 1 ] = words [ a * 10 ]
1256 t [ # t + 1 ] = words [ b ]
1257 end
1258 end
1259 local function compose_two ( n , m )
1260 if n > ( m -1 ) then
1261 local a , b = floor ( n / m ) , n % m
1262 if a > 0 then
1263 compose_one ( a )
1264 end
1265 t [ # t + 1 ] = words [ m ]
1266 n = b
1267 end
1268 return n
1269 end
1270 n = compose_two ( n , 1000000000000 )
1271 n = compose_two ( n , 1000000000 )
1272 n = compose_two ( n , 1000000 )
1273 n = compose_two ( n , 1000 )
1274 if n > 0 then
1275 compose_one ( n )
1276 end
1277 return # t > 0 and concat ( t , " " ) or tostring ( n )
1278end
1279
1280data . english = {
1281 words = words ,
1282 translate = translate ,
1283}
1284
1285data . en = data . english
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297local words = {
1298 [ 1 ] = " uno " ,
1299 [ 2 ] = " dos " ,
1300 [ 3 ] = " tres " ,
1301 [ 4 ] = " cuatro " ,
1302 [ 5 ] = " cinco " ,
1303 [ 6 ] = " seis " ,
1304 [ 7 ] = " siete " ,
1305 [ 8 ] = " ocho " ,
1306 [ 9 ] = " nueve " ,
1307 [ 10 ] = " diez " ,
1308 [ 11 ] = " once " ,
1309 [ 12 ] = " doce " ,
1310 [ 13 ] = " trece " ,
1311 [ 14 ] = " catorce " ,
1312 [ 15 ] = " quince " ,
1313 [ 16 ] = " dieciséis " ,
1314 [ 17 ] = " diecisiete " ,
1315 [ 18 ] = " dieciocho " ,
1316 [ 19 ] = " diecinueve " ,
1317 [ 20 ] = " veinte " ,
1318 [ 21 ] = " veintiuno " ,
1319 [ 22 ] = " veintidós " ,
1320 [ 23 ] = " veintitrés " ,
1321 [ 24 ] = " veinticuatro " ,
1322 [ 25 ] = " veinticinco " ,
1323 [ 26 ] = " veintiséis " ,
1324 [ 27 ] = " veintisiete " ,
1325 [ 28 ] = " veintiocho " ,
1326 [ 29 ] = " veintinueve " ,
1327 [ 30 ] = " treinta " ,
1328 [ 40 ] = " cuarenta " ,
1329 [ 50 ] = " cincuenta " ,
1330 [ 60 ] = " sesenta " ,
1331 [ 70 ] = " setenta " ,
1332 [ 80 ] = " ochenta " ,
1333 [ 90 ] = " noventa " ,
1334 [ 100 ] = " ciento " ,
1335 [ 200 ] = " doscientos " ,
1336 [ 300 ] = " trescientos " ,
1337 [ 400 ] = " cuatrocientos " ,
1338 [ 500 ] = " quinientos " ,
1339 [ 600 ] = " seiscientos " ,
1340 [ 700 ] = " setecientos " ,
1341 [ 800 ] = " ochocientos " ,
1342 [ 900 ] = " novecientos " ,
1343 [ 1000 ] = " mil " ,
1344 [ 1000000 ] = " millón " ,
1345 [ 1000000000 ] = " mil millones " ,
1346 [ 1000000000000 ] = " billón " ,
1347}
1348
1349local function translate ( n )
1350 local w = words [ n ]
1351 if w then
1352 return w
1353 end
1354 local t = { }
1355 local function compose_one ( n )
1356 local w = words [ n ]
1357 if w then
1358 t [ # t + 1 ] = w
1359 return
1360 end
1361
1362 local a , b = floor ( n / 100 ) , n % 100
1363
1364 if a = = 10 then
1365 t [ # t + 1 ] = words [ 1 ]
1366 t [ # t + 1 ] = words [ 1000 ]
1367
1368
1369
1370 elseif a > 0 then
1371 t [ # t + 1 ] = words [ a * 100 ]
1372 end
1373
1374 if words [ b ] then
1375 t [ # t + 1 ] = words [ b ]
1376 else
1377
1378 a , b = floor ( b / 10 ) , n % 10
1379 t [ # t + 1 ] = words [ a * 10 ]
1380 t [ # t + 1 ] = " y "
1381 t [ # t + 1 ] = words [ b ]
1382 end
1383 end
1384
1385
1386 local function compose_two ( n , m )
1387 if n > ( m -1 ) then
1388 local a , b = floor ( n / m ) , n % m
1389 if a > 0 then
1390 compose_one ( a )
1391 end
1392 t [ # t + 1 ] = words [ m ]
1393 n = b
1394 end
1395 return n
1396 end
1397 n = compose_two ( n , 1000000000000 )
1398 n = compose_two ( n , 1000000000 )
1399 n = compose_two ( n , 1000000 )
1400 n = compose_two ( n , 1000 )
1401 if n > 0 then
1402 compose_one ( n )
1403 end
1404 return # t > 0 and concat ( t , " " ) or tostring ( n )
1405end
1406
1407data . spanish = {
1408 words = words ,
1409 translate = translate ,
1410}
1411
1412data . es = data . spanish
1413
1414
1415
1416
1417
1418
1419
1420function converters . verbose . translate ( n , language )
1421 local t = language and data [ language ]
1422 return t and t . translate ( n ) or n
1423end
1424
1425local function verbose ( n , language )
1426 local t = language and data [ language ]
1427 context ( t and t . translate ( n ) or n )
1428end
1429
1430implement {
1431 name = " verbose " ,
1432 actions = verbose ,
1433 arguments = { " integer " , " string " }
1434}
1435
1436
1437
1438
1439local whitespace = lpegpatterns . whitespace
1440local word = lpegpatterns . utf8uppercharacter ^ -1 * ( 1 - whitespace ) ^ 1
1441local pattern_one = Cs ( whitespace ^ 0 * word ^ -1 * P ( 1 ) ^ 0 )
1442local pattern_all = Cs ( ( whitespace ^ 1 + word ) ^ 1 )
1443
1444function converters . word ( s ) return s end
1445function converters . words ( s ) return s end
1446
1447local function Word ( s ) return lpegmatch ( pattern_one , s ) or s end
1448local function Words ( s ) return lpegmatch ( pattern_all , s ) or s end
1449
1450converters . Word = Word
1451converters . Words = Words
1452
1453converters . upper = characters . upper
1454converters . lower = characters . lower
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468local v_day = variables . day
1469local v_year = variables . year
1470local v_month = variables . month
1471local v_weekday = variables . weekday
1472local v_referral = variables . referral
1473local v_space = variables . space
1474
1475local v_MONTH = upper ( v_month )
1476local v_WEEKDAY = upper ( v_weekday )
1477
1478local convert = converters . convert
1479
1480local days = {
1481 " sunday " ,
1482 " monday " ,
1483 " tuesday " ,
1484 " wednesday " ,
1485 " thursday " ,
1486 " friday " ,
1487 " saturday " ,
1488}
1489
1490local months = {
1491 " january " ,
1492 " february " ,
1493 " march " ,
1494 " april " ,
1495 " may " ,
1496 " june " ,
1497 " july " ,
1498 " august " ,
1499 " september " ,
1500 " october " ,
1501 " november " ,
1502 " december " ,
1503}
1504
1505local monthmnems = {
1506
1507}
1508
1509local daymnems = {
1510
1511}
1512
1513setmetatableindex ( days , function ( t , k ) return " unknown " end )
1514setmetatableindex ( daymnems , function ( t , k ) return days [ k ] . . " :mnem " end )
1515setmetatableindex ( months , function ( t , k ) return " unknown " end )
1516setmetatableindex ( monthmnems , function ( t , k ) return months [ k ] . . " :mnem " end )
1517
1518do
1519
1520 local function dayname ( n )
1521 ctx_labeltext ( days [ n ] )
1522 end
1523
1524 local function daymnem ( n )
1525 ctx_labeltext ( daymnems [ n ] )
1526 end
1527
1528 local function weekdayname ( day , month , year )
1529 ctx_labeltext ( days [ weekday ( day , month , year ) ] )
1530 end
1531
1532 local function monthname ( n )
1533 ctx_labeltext ( months [ n ] )
1534 end
1535
1536 local function monthmnem ( n )
1537 ctx_labeltext ( monthmnems [ n ] )
1538 end
1539
1540 implement {
1541 name = " dayname " ,
1542 actions = dayname ,
1543 arguments = " integer " ,
1544 }
1545
1546 implement {
1547 name = " daymnem " ,
1548 actions = daymnem ,
1549 arguments = " integer " ,
1550 }
1551
1552 implement {
1553 name = " weekdayname " ,
1554 actions = weekdayname ,
1555 arguments = { " integer " , " integer " , " integer " }
1556 }
1557
1558 implement {
1559 name = " monthname " ,
1560 actions = monthname ,
1561 arguments = " integer " ,
1562 }
1563
1564 implement {
1565 name = " monthmnem " ,
1566 actions = monthmnem ,
1567 arguments = " integer " ,
1568 }
1569
1570
1571
1572 local f_monthlong = formatters [ " \\monthlong{%s} " ]
1573 local f_monthshort = formatters [ " \\monthshort{%s} " ]
1574 local f_daylong = formatters [ " \\daylong{%s} " ]
1575 local f_dayshort = formatters [ " \\dayshort{%s} " ]
1576 local f_weekday = formatters [ " \\weekday{%s} " ]
1577 local f_dayoftheweek = formatters [ " \\dayoftheweek{%s}{%s}{%s} " ]
1578
1579 local function tomonthlong ( m ) return f_monthlong ( tonumber ( m ) or 1 ) end
1580 local function tomonthshort ( m ) return f_monthshort ( tonumber ( m ) or 1 ) end
1581 local function todaylong ( d ) return f_daylong ( tonumber ( d ) or 1 ) end
1582 local function todayshort ( d ) return f_dayshort ( tonumber ( d ) or 1 ) end
1583 local function toweekday ( d ) return f_weekday ( tonumber ( d ) or 1 ) end
1584
1585 local function todayoftheweek ( d , m , y )
1586 return f_dayoftheweek ( tonumber ( d ) or 1 , tonumber ( m ) or 1 , tonumber ( y ) or 2000 )
1587 end
1588
1589 addformatter ( formatters , " monthlong " , [[ tomonthlong(%s) ]] , { tomonthlong = tomonthlong } )
1590 addformatter ( formatters , " monthshort " , [[ tomonthshort(%s) ]] , { tomonthshort = tomonthshort } )
1591 addformatter ( formatters , " daylong " , [[ todaylong(%s) ]] , { todaylong = todaylong } )
1592 addformatter ( formatters , " dayshort " , [[ todayshort(%s) ]] , { todayshort = todayshort } )
1593 addformatter ( formatters , " weekday " , [[ toweekday(%s) ]] , { toweekday = toweekday } )
1594 addformatter ( formatters , " dayoftheweek " , [[ todayoftheweek(%s,%s,%s) ]] , { todayoftheweek = todayoftheweek } )
1595
1596
1597
1598 local function toeyear ( e ) return osdate ( " %Y " , tonumber ( e ) ) end
1599 local function toemonth ( e ) return osdate ( " %m " , tonumber ( e ) ) end
1600 local function toeday ( e ) return osdate ( " %d " , tonumber ( e ) ) end
1601 local function toeminute ( e ) return osdate ( " %M " , tonumber ( e ) ) end
1602 local function toesecond ( e ) return osdate ( " %S " , tonumber ( e ) ) end
1603
1604 local function toemonthlong ( e )
1605 return f_monthlong ( tonumber ( osdate ( " %m " , tonumber ( e ) ) ) )
1606 end
1607
1608 local function toemonthshort ( e )
1609 return f_monthshort ( tonumber ( osdate ( " %m " , tonumber ( e ) ) ) )
1610 end
1611
1612 local function toedaylong ( e )
1613 return f_datlong ( tonumber ( osdate ( " %w " , tonumber ( e ) ) ) )
1614 end
1615
1616 local function toedayshort ( e )
1617 return f_dayshort ( tonumber ( osdate ( " %w " , tonumber ( e ) ) ) )
1618 end
1619
1620 local function toeweek ( e )
1621 return tostring ( tonumber ( osdate ( " %w " , tonumber ( e ) ) ) + 1 )
1622 end
1623
1624 local function toeweekday ( e )
1625 return f_weekday ( tonumber ( osdate ( " %w " , tonumber ( e ) ) ) + 1 )
1626 end
1627
1628 local function toedate ( format , e )
1629 return osdate ( format , tonumber ( e ) )
1630 end
1631
1632 addformatter ( formatters , " eyear " , [[ toeyear(%s) ]] , { toeyear = toeyear } )
1633 addformatter ( formatters , " emonth " , [[ toemonth(%s) ]] , { toemonth = toemonth } )
1634 addformatter ( formatters , " eday " , [[ toeday(%s) ]] , { toeday = toeday } )
1635 addformatter ( formatters , " eweek " , [[ toeweek(%s) ]] , { toeweek = toeweek } )
1636 addformatter ( formatters , " eminute " , [[ toeminute(%s) ]] , { toeminute = toeminute } )
1637 addformatter ( formatters , " esecond " , [[ toesecond(%s) ]] , { toesecond = toesecond } )
1638
1639 addformatter ( formatters , " emonthlong " , [[ toemonthlong(%s) ]] , { toemonthlong = toemonthlong } )
1640 addformatter ( formatters , " emonthshort " , [[ toemonthshort(%s) ]] , { toemonthshort = toemonthshort } )
1641 addformatter ( formatters , " edaylong " , [[ toedaylong(%s) ]] , { toedaylong = toedaylong } )
1642 addformatter ( formatters , " edayshort " , [[ toedayshort(%s) ]] , { toedayshort = toedayshort } )
1643 addformatter ( formatters , " eweekday " , [[ toeweekday(%s) ]] , { toeweekday = toeweekday } )
1644
1645 addformatter ( formatters , " edate " , [[ toedate(%s,%s) ]] , { toedate = toedate } )
1646
1647end
1648
1649
1650
1651
1652
1653
1654local spaced = {
1655 [ v_year ] = true ,
1656 [ v_month ] = true ,
1657 [ v_MONTH ] = true ,
1658 [ v_day ] = true ,
1659 [ v_weekday ] = true ,
1660 [ v_WEEKDAY ] = true ,
1661}
1662
1663local dateconverters = {
1664 [ " hebrew:to " ] = gregorian_to_hebrew ,
1665 [ " jalali:to " ] = gregorian_to_jalali ,
1666 [ " jalali:from " ] = jalali_to_gregorian ,
1667}
1668
1669local variants = {
1670 mnem = {
1671 month = monthmnems ,
1672 day = daymnems ,
1673 } ,
1674 hebrew = {
1675 month = setmetatableindex ( function ( t , k ) return months [ k ] . . " :hebrew " end ) ,
1676 day = setmetatableindex ( function ( t , k ) return days [ k ] . . " :hebrew " end ) ,
1677 } ,
1678 jalali = {
1679 month = setmetatableindex ( function ( t , k ) return months [ k ] . . " :jalali " end ) ,
1680 day = setmetatableindex ( function ( t , k ) return days [ k ] . . " :jalali " end ) ,
1681 } ,
1682}
1683
1684do
1685
1686 local function currentdate ( str , currentlanguage , year , month , day )
1687 local list = utilities . parsers . settings_to_array ( str )
1688 local splitlabel = languages . labels . split or string . itself
1689
1690
1691
1692 local auto = true
1693 if currentlanguage = = " " then
1694 currentlanguage = false
1695 end
1696 for i = 1 , # list do
1697 local entry = list [ i ]
1698 local convert = dateconverters [ entry ]
1699 if convert then
1700 year , month , day = convert ( year , month , day )
1701 else
1702 local tag , plus = splitlabel ( entry )
1703 local ordinal , mnemonic , whatordinal , highordinal = false , false , nil , false
1704 if not tag then
1705 tag = entry
1706 elseif plus = = " + " or plus = = " ord " then
1707 ordinal = true
1708 elseif plus = = " ++ " or plus = = " highord " then
1709 ordinal = true
1710 highordinal = true
1711 elseif plus then
1712 mnemonic = variants [ plus ]
1713 end
1714 if not auto and spaced [ tag ] then
1715 ctx_space ( )
1716 end
1717 auto = false
1718 if tag = = v_year or tag = = " y " or tag = = " Y " then
1719 if plus then
1720 plus = converters [ plus ]
1721 end
1722 if plus then
1723 context ( plus ( year ) )
1724 elseif currentlanguage = = false then
1725 context ( year )
1726 else
1727 ctx_convertnumber ( v_year , year )
1728 end
1729 elseif tag = = " yy " or tag = = " YY " then
1730 context ( " %02i " , year % 100 )
1731 elseif tag = = v_month or tag = = " m " then
1732 if currentlanguage = = false then
1733 context ( Word ( months [ month ] ) )
1734 else
1735 if type ( mnemonic ) = = " table " then
1736 mnemonic = mnemonic . month
1737 end
1738 if mnemonic then
1739 ctx_labeltext ( variables [ mnemonic [ month ] ] )
1740 else
1741 ctx_labeltext ( variables [ months [ month ] ] )
1742 end
1743 end
1744 elseif tag = = v_MONTH then
1745 if currentlanguage = = false then
1746 context ( Word ( variables [ months [ month ] ] ) )
1747 else
1748 if type ( mnemonic ) = = " table " then
1749 mnemonic = mnemonic . month
1750 end
1751 if mnemonic then
1752 ctx_LABELTEXT ( variables [ mnemonic [ month ] ] )
1753 else
1754 ctx_LABELTEXT ( variables [ months [ month ] ] )
1755 end
1756 end
1757 elseif tag = = " mm " then
1758 context ( " %02i " , month )
1759 elseif tag = = " M " then
1760 context ( month )
1761 elseif tag = = v_day or tag = = " d " then
1762 if plus then
1763 plus = converters [ plus ]
1764 end
1765 if plus then
1766 context ( plus ( day ) )
1767 elseif currentlanguage = = false then
1768 context ( day )
1769 else
1770 ctx_convertnumber ( v_day , day )
1771 end
1772 whatordinal = day
1773 elseif tag = = " dd " then
1774 context ( " %02i " , day )
1775 whatordinal = day
1776 elseif tag = = " D " then
1777 context ( day )
1778 whatordinal = day
1779 elseif tag = = v_weekday or tag = = " w " then
1780 local wd = weekday ( day , month , year )
1781 if currentlanguage = = false then
1782 context ( Word ( days [ wd ] ) )
1783 else
1784 if type ( mnemonic ) = = " table " then
1785 mnemonic = mnemonic . day
1786 end
1787 if mnemonic then
1788 ctx_labeltext ( variables [ mnemonic [ wd ] ] )
1789 else
1790 ctx_labeltext ( variables [ days [ wd ] ] )
1791 end
1792 end
1793 elseif tag = = v_WEEKDAY then
1794 local wd = weekday ( day , month , year )
1795 if currentlanguage = = false then
1796 context ( Word ( days [ wd ] ) )
1797 else
1798 if type ( mnemonic ) = = " table " then
1799 mnemonic = mnemonic . day
1800 end
1801 if mnemonic then
1802 ctx_LABELTEXT ( variables [ mnemonic [ wd ] ] )
1803 else
1804 ctx_LABELTEXT ( variables [ days [ wd ] ] )
1805 end
1806 end
1807 elseif tag = = " W " then
1808 context ( weekday ( day , month , year ) )
1809 elseif tag = = v_referral then
1810 context ( " %04i%02i%02i " , year , month , day )
1811 elseif tag = = v_space or tag = = " \\ " then
1812 ctx_space ( )
1813 auto = true
1814 elseif tag ~ = " " then
1815 context ( tag )
1816 auto = true
1817 end
1818 if ordinal and whatordinal then
1819 if currentlanguage = = false then
1820
1821 else
1822 context [ highordinal and " highordinalstr " or " ordinalstr " ] ( converters . ordinal ( whatordinal , currentlanguage ) )
1823 end
1824 end
1825 end
1826 end
1827 end
1828
1829 implement {
1830 name = " currentdate " ,
1831 arguments = { " string " , " string " , " string " , " integer " , " integer " , " integer " } ,
1832 actions = function ( pattern , default , language , year , month , day )
1833 currentdate (
1834 pattern = = " " and default or pattern ,
1835 language = = " " and false or language ,
1836 year , month , day
1837 )
1838 end ,
1839 }
1840
1841 local function todate ( s , y , m , d )
1842 if y or m or d then
1843 return formatters [ " \\date[y=%s,m=%s,d=%s][%s]\\relax " ] ( y or " " , m or " " , d or " " , s or " " )
1844 else
1845 return formatters [ " \\currentdate[%s]\\relax " ] ( s )
1846 end
1847 end
1848
1849 addformatter ( formatters , " date " , [[ todate(...) ]] , { todate = todate } )
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859end
1860
1861implement {
1862 name = " unihex " ,
1863 arguments = " integer " ,
1864 actions = { formatters [ " U+%05X " ] , context } ,
1865}
1866
1867local n = R ( " 09 " ) ^ 1 / tonumber
1868
1869local p = Cf ( Ct ( " " )
1870 * Cg ( Cc ( " year " ) * ( n ) ) * P ( " - " ) ^ -1
1871 * Cg ( Cc ( " month " ) * ( n + Cc ( 1 ) ) ) * P ( " - " ) ^ -1
1872 * Cg ( Cc ( " day " ) * ( n + Cc ( 1 ) ) ) * whitespace ^ -1
1873 * Cg ( Cc ( " hour " ) * ( n + Cc ( 0 ) ) ) * P ( " : " ) ^ -1
1874 * Cg ( Cc ( " min " ) * ( n + Cc ( 0 ) ) )
1875 , rawset )
1876
1877function converters . totime ( s )
1878 if not s then
1879 return
1880 elseif type ( s ) = = " table " then
1881 return s
1882 elseif type ( s ) = = " string " then
1883 return lpegmatch ( p , s )
1884 end
1885 local n = tonumber ( s )
1886 if n and n > = 0 then
1887 return date ( " *t " , n )
1888 end
1889end
1890
1891function converters . settime ( t )
1892 if type ( t ) ~ = " table " then
1893 t = converters . totime ( t )
1894 end
1895 if t then
1896 texset ( " year " , t . year or 1000 )
1897 texset ( " month " , t . month or 1 )
1898 texset ( " day " , t . day or 1 )
1899 texset ( " time " , ( t . hour or 0 ) * 60 + ( t . min or 0 ) )
1900 end
1901end
1902
1903
1904
1905local d_one = lpegpatterns . digit
1906local d_two = d_one * d_one
1907local d_three = d_two * d_one
1908local d_four = d_three * d_one
1909local d_split = P ( -1 ) + Carg ( 2 ) * ( lpegpatterns . period / " " )
1910
1911local d_spaced = ( Carg ( 1 ) * d_three ) ^ 1
1912
1913local digitized_1 = Cs ( (
1914 d_three * d_spaced * d_split +
1915 d_two * d_spaced * d_split +
1916 d_one * d_spaced * d_split +
1917 P ( 1 )
1918 ) ^ 1 )
1919
1920local p_fourbefore = d_four * d_split
1921local p_fourafter = d_four * P ( -1 )
1922
1923local p_beforesplit = d_three * d_spaced ^ 0 * d_split
1924 + d_two * d_spaced ^ 0 * d_split
1925 + d_one * d_spaced ^ 0 * d_split
1926 + d_one * d_split
1927
1928local p_aftersplit = p_fourafter
1929 + d_three * d_spaced
1930 + d_two * d_spaced
1931 + d_one * d_spaced
1932
1933local digitized_2 = Cs (
1934 p_fourbefore * ( p_aftersplit ^ 0 ) +
1935 p_beforesplit * ( ( p_aftersplit + d_one ^ 1 ) ^ 0 )
1936 )
1937
1938local p_fourbefore = d_four * d_split
1939local p_fourafter = d_four
1940local d_spaced = ( Carg ( 1 ) * ( d_three + d_two + d_one ) ) ^ 1
1941local p_aftersplit = p_fourafter * P ( -1 )
1942 + d_three * d_spaced * P ( 1 ) ^ 0
1943 + d_one ^ 1
1944
1945local digitized_3 = Cs ( ( p_fourbefore + p_beforesplit ) * p_aftersplit ^ 0 )
1946
1947local digits_space = utfchar ( 0x2008 )
1948
1949local splitmethods = {
1950 digitized_1 ,
1951 digitized_2 ,
1952 digitized_3 ,
1953}
1954
1955local replacers = table . setmetatableindex ( function ( t , k )
1956 local v = lpeg . replacer ( " . " , k )
1957 t [ k ] = v
1958 return v
1959end )
1960
1961function converters . spaceddigits ( settings , data )
1962 local data = tostring ( data or settings . data or " " )
1963 if data ~ = " " then
1964 local method = settings . method
1965 local split = splitmethods [ tonumber ( method ) or 1 ]
1966 if split then
1967 local symbol = settings . symbol
1968 local separator = settings . separator
1969 if not symbol or symbol = = " " then
1970 symbol = " . "
1971 end
1972 if type ( separator ) ~ = " string " or separator = = " " then
1973 separator = digits_space
1974 end
1975 local result = lpegmatch ( split , data , 1 , separator , symbol )
1976 if not result and symbol ~ = " . " then
1977 result = lpegmatch ( replacers [ symbol ] , data )
1978 end
1979 if result then
1980
1981 return result
1982 end
1983 end
1984 end
1985 return str
1986end
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028implement {
2029 name = " spaceddigits " ,
2030 actions = { converters . spaceddigits , context } ,
2031 arguments = {
2032 {
2033 { " symbol " } ,
2034 { " separator " } ,
2035 { " data " } ,
2036 { " method " } ,
2037 }
2038 }
2039}
2040
2041local function field ( n ) return context ( osdate ( " *t " ) [ n ] ) end
2042
2043implement { name = " actualday " , public = true , actions = function ( ) field ( " day " ) end }
2044implement { name = " actualmonth " , public = true , actions = function ( ) field ( " month " ) end }
2045implement { name = " actualyear " , public = true , actions = function ( ) field ( " year " ) end }
2046 |