模組:引聖經
外表
| 呢個模組已經被評為alpha版,可以接受第三方輸入,並可以用喺少量版以檢查有冇問題,但需要受到見識。歡迎提供新功能或者修改佢輸入輸出機制嘅建議。 |
概要
[編輯]{{#invoke:引聖經| cite | [ 書卷章節 ]] | 其他參數... }}
{{#invoke:引聖經| cite | [ 書卷 [ | 章節 [ | 譯本代號 ]]] | 其他參數... }}
{{#invoke:引聖經| cite2 }}
{{#invoke:引聖經| dump_codes }}
{{#invoke:引聖經| list_books | 譯本代號 }}
{{#invoke:引聖經| list_versions [ | conjunction=連接詞 ] }}
用途
[編輯]正常引用
[編輯]呢個模組通常係透過引聖經模間接叫用 cite2 函數,所有參數用文章版面(parent frame)畀嘅模參數。參數詳情請睇原碼或者睇引聖經模嘅模解。
喺版面用 #invoke 直接叫用 cite 函數都得;兩個函數嘅功能完全一樣,分別只係 cite 函數用嘅係 #invoke 巨集畀嘅參數(current frame)。
分開寫書卷同章節本來係模擬英維同中維嘅 Bibleverse 模,模擬功能應該已經正常運作。
模解版用
[編輯]模組提供一個 dump_codes 函數,用嚟畀模解版直接叫用,將模組內部用嘅書卷代碼同對應嘅書卷名列哂出嚟。咁做係因為如果要要喺模解版寫哂啲代碼出嚟,萬一代碼有變,模解好易會過時出錯。
dump_versions 函數亦都係用嚟畀模解版直接叫用,將模組內部用嘅譯本代碼同(如果有)對應嘅譯本名列哂出嚟,但係輸出係句子形式,可以指定連接詞,唔指定嘅話連接詞係 「同」。
其他
[編輯]模組另外提供一個 list_books 函數係用嚟畀個別譯本嘅文直接叫用,表嘅格式係參考聖經和合本呢篇文。
本地化
[編輯]呢個模組係粵維原創;除咗程式註解同少量錯誤訊息之外,應該已經係粵語。
睇埋
[編輯]| 上面嘅解係穿透包含咗自模組:引聖經/doc。 (改 | 史) 編者可以響呢個模組嘅沙盤 (開 | 鏡)同埋試例 (開)版度試驗佢。 呢個模組嘅細版。 |
-- vi:set sw=4 ts=4 ai sm:
---- Bible citation module designed for Cantonese Wikipedia
---- This module implements the backend logic for Template:引聖經
---- (A new module is necessary because in Chinese languages
---- we almost always need to link to two bible texts, not one)
---- 引聖經模嘅對應模組,2022年粵維原創,處理同時連去和合本同思高本
require ('strict');
local p = {};
local Syu1meng2 = require('Module:書名');
local NumberToChinese = require('模組:中文數字');
-- TAG: how_to_mark_books
-- 聖經章節嘅書卷名點處理,三揀一:
-- 1. Syu1meng2.auto_build_citable = 甲式書名號,傳統做法,例如思高本係咁做
-- 2. Syu1meng2.build_type_2_citable = 乙式書名號,實際上冇人會咁做
-- 3. false = 唔用書名號,通常做法
local how_to_mark_books = false;
-- / 教派傳統(protestant、catholic、orthodox、judaism)
-- \ 其他值唔應該擺呢度,係初頭設計錯誤,但係拎走嘅話要大執
local traditions = {
['protestant'] = '基督教';
['catholic'] = '天主教';
['orthodox'] = '東正教';
['english'] = '英文'; -- FIXME
['judaism'] = '猶太教';
['greek'] = ''; -- for TR, etc. - no label
['hebrew'] = ''; -- for MT, etc. - no label
['latin'] = ''; -- for Vulgate - no label
}
-- / 教派傳統對應嘅語言(細楷)
-- \ 語言(大楷),可能係初頭設計錯誤,但係拎走嘅話要大執
local languages = {
-- traditions
['protestant'] = '中文';
['catholic'] = '中文';
['orthodox'] = '中文';
['english'] = '英文'; -- FIXME
['judaism'] = '希伯來文'; -- for testing
-- special cases
['greek'] = '古希臘文';
['latin'] = '拉丁文';
-- languages
['ENGLISH'] = 'english';
['HEBREW'] = 'hebrew';
}
-- 天干,天主教傳統部分章數用
local stems = {
['A'] = '甲';
['B'] = '乙';
['C'] = '丙';
['D'] = '丁';
['E'] = '戊';
['F'] = '己';
['G'] = '庚';
['H'] = '辛';
['I'] = '壬';
['J'] = '癸';
}
-- 教派傳統嘅書卷章節編號特徵
-- default = 譯本代號(典型譯本)
-- kanji_chapters_p = 用中文章數(true)定阿拉伯數字章數(false,預設)
local numbering = {
['protestant'] = {
['default'] = 'CUV';
};
['catholic'] = {
['default'] = 'SBV';
['kanji_chapters_p'] = true;
};
['orthodox'] = {
};
['greek'] = {
};
['hebrew'] = {
};
['latin'] = {
};
['english'] = {
['default'] = 'NIV';
};
['judaism'] = { -- for testing
['default'] = 'JPS';
};
}
-- 書卷定義表
-- 第一層:書卷代號(唔用空格)
-- (主要出自 CSB,CSB 冇就用 NAB,再冇先老作,老作嘅代號加 x- 前綴)
-- 第二層:書卷屬性
-- order = 排列次序
-- protestant = 基督教中文名
-- catholic = 天主教中文名
-- orthodox = 東正教中文名(抄自[[舊約聖經]]、[[新約聖經]])
-- english = 英文名
-- hebrew = 希伯來文名
-- latin = 拉丁文名(出自《基督教聖經與神學詞典》,下稱 Lo et al. (2003))
-- div = 最大分段叫乜(三㨂一:章、篇、節)
-- parts = 理論上嘅書卷實際上對應乜嘢書卷,猶太教專用
-- embeds = 有乜用天干嘅章數同次序係乜,天主教專用
-- 注意,CSB 同 NAB 都係用短代號(例如用 Gn 唔用 Gen),但係呢兩個譯本嘅代號有時會有出入
local books = {
['Gn'] = {
['order'] = 100,
['protestant'] = { '創世記', '創' },
['catholic'] = { '創世紀', '創' },
['orthodox'] = { '起源之書' },
['english'] = { 'Genesis', 'Gen.' },
['hebrew'] = { 'בראשית' },
['latin'] = { 'Genesis' },
['div'] = '章',
},
['Ex'] = {
['order'] = 110,
['protestant'] = { '出埃及記', '出' },
['catholic'] = { '出谷紀', '出' },
['orthodox'] = { '出離之書' },
['english'] = { 'Exodus' },
['hebrew'] = { 'שמות' },
['latin'] = { 'Exodus' },
['div'] = '章',
},
['Lv'] = {
['order'] = 120,
['protestant'] = { '利未記', '利' },
['catholic'] = { '肋未紀', '肋' },
['orthodox'] = { '勒維人之書' },
['english'] = { 'Leviticus' },
['hebrew'] = { 'ויקרא' },
['latin'] = { 'Leviticus' },
['div'] = '章',
},
['Nm'] = {
['order'] = 130,
['protestant'] = { '民數記', '民' },
['catholic'] = { '戶籍紀', '戶' },
['orthodox'] = { '民數之書' },
['english'] = { 'Numbers' },
['hebrew'] = { 'במדבר' },
['latin'] = { 'Numeri' },
['div'] = '章',
},
['Dt'] = {
['order'] = 140,
['protestant'] = { '申命記', '申' },
['catholic'] = { '申命紀', '申' },
['orthodox'] = { '第二法典之書' },
['english'] = { 'Deuteronomy', 'Deut.' },
['hebrew'] = { 'דברים' },
['latin'] = { 'Deuteronomium' },
['div'] = '章',
},
['Jos'] = {
['order'] = 150,
['protestant'] = { '約書亞記', '書' },
['catholic'] = { '若蘇厄書', '蘇' },
['orthodox'] = { '納維之子伊穌斯傳' },
['english'] = { 'Joshua' },
['hebrew'] = { 'יהושע' },
['latin'] = { 'Iosue' },
['div'] = '章',
},
['Jdg'] = {
['order'] = 160,
['protestant'] = { '士師記', '士' },
['catholic'] = { '民長紀', '民' },
['orthodox'] = { '眾審判者傳' },
['english'] = { 'Judges', 'Jgs.' },
['hebrew'] = { 'שופטים' },
['latin'] = { 'Iudicum' },
['div'] = '章',
},
['Ru'] = {
['order'] = 170,
['protestant'] = { '路得記', '得' },
['catholic'] = { '盧德傳', '盧' },
['orthodox'] = { '如特傳' },
['english'] = { 'Ruth' },
['hebrew'] = { 'רות' },
['latin'] = { 'Ruth' },
['div'] = '章',
},
['x-Sm'] = { -- XXX for testing
['order'] = 175,
['english'] = { 'Samuel' },
['hebrew'] = { 'שמואל' },
['parts'] = { '1Sm', '2Sm' },
},
['1Sm'] = {
['order'] = 180,
['protestant'] = { '撒母耳記上', '撒上' },
['catholic'] = { '撒慕爾紀上', '撒上' },
['orthodox'] = { '眾王傳一', '1 Kings' },
['english'] = { '1 Samuel' },
['hebrew'] = { 'שמואל א' }, -- 理論上係 שמואל,但係實際上(例如 Jerusalem Bible)係分 א 同 ב
['latin'] = { 'Samuelis I' },
['div'] = '章',
},
['2Sm'] = {
['order'] = 190,
['protestant'] = { '撒母耳記下', '撒下' },
['catholic'] = { '撒慕爾紀下', '撒下' },
['orthodox'] = { '眾王傳二', '2 Kings' },
['english'] = { '2 Samuel' },
['hebrew'] = { 'שמואל ב' },
['latin'] = { 'Samuelis II' },
['div'] = '章',
},
['x-Kg'] = { -- XXX for testing
['order'] = 195,
['english'] = { 'Kings' },
['hebrew'] = { 'מלכים' },
['parts'] = { '1Kg', '2Kg' },
},
['1Kg'] = {
['order'] = 200,
['protestant'] = { '列王紀上', '王上' },
['catholic'] = { '列王紀上', '列上' },
['orthodox'] = { '眾王傳三', '3 Kings' },
['english'] = { '1 Kings', '1 Kgs.' },
['hebrew'] = { 'מלכים א' }, -- 見 1Sm
['latin'] = { 'Regum I' },
['div'] = '章',
},
['2Kg'] = {
['order'] = 210,
['protestant'] = { '列王紀下', '王下' },
['catholic'] = { '列王紀下', '列下' },
['orthodox'] = { '眾王傳四', '4 Kings' },
['english'] = { '2 Kings', '2 Kgs.' },
['hebrew'] = { 'מלכים ב' },
['latin'] = { 'Regum II' },
['div'] = '章',
},
['x-Ch'] = { -- XXX for testing
['order'] = 215,
['english'] = { 'Chronicles' },
['hebrew'] = { 'דברי הימים' },
['parts'] = { '1Ch', '2Ch' },
},
['1Ch'] = {
['order'] = 220,
['protestant'] = { '歷代志上', '代上' },
['catholic'] = { '編年紀上', '編上' },
['orthodox'] = { '史書補遺一', '紀年書一' },
['english'] = { '1 Chronicles', '1 Chr.' },
['hebrew'] = { 'דברי הימים א' }, -- 見 1Sm
['latin'] = { 'Paralipomenon I' },
['div'] = '章',
},
['2Ch'] = {
['order'] = 230,
['protestant'] = { '歷代志下', '代下' },
['catholic'] = { '編年紀下', '編下' },
['orthodox'] = { '史書補遺二', '紀年書二' },
['english'] = { '2 Chronicles', '2 Chr.' },
['hebrew'] = { 'דברי הימים ב' },
['latin'] = { 'Paralipomenon II' },
['div'] = '章',
},
['PrMan'] = {
['order'] = 231, -- 擺呢度係跟英維
--XXX['protestant'] = { '瑪拿西禱文' },
['english'] = { 'Prayer of Manasseh' },
['latin'] = { 'Oratio Manassae' },
['div'] = '節',
},
['x-Ezr-Neh'] = { -- XXX for testing
['order'] = 235,
['english'] = { 'Ezra-Nehemiah' },
['hebrew'] = { 'עזרא־נחמיה' },
['parts'] = { 'Ezr', 'Neh' },
},
['3Esd'] = { -- per Lo et al. (2003)
['order'] = 240,
--XXX['protestant'] = { '以斯得拉一書' },
['orthodox'] = { '艾斯德拉紀一' },
['english'] = { '1 Esdras' },
['hebrew'] = { 'עזרא החיצוני' },
['latin'] = { 'Esdrae III' },
['div'] = '章',
},
['4Esd'] = { -- per Lo et al. (2003)
['order'] = 241,
--XXX['protestant'] = { '以斯得拉二書' },
['english'] = { '2 Esdras' },
['latin'] = { 'Esdrae IV' },
['div'] = '章',
},
['Ezr'] = {
['order'] = 250,
['protestant'] = { '以斯拉記', '拉' },
['catholic'] = { '厄斯德拉上', '厄上', '厄斯德拉卷上' },
['orthodox'] = { '艾斯德拉紀二' },
['english'] = { 'Ezra' },
['hebrew'] = { 'עזרא' },
['latin'] = { 'Esdrae' },
['div'] = '章',
},
['Neh'] = {
['order'] = 260,
['protestant'] = { '尼希米記', '尼' },
['catholic'] = { '厄斯德拉下', '厄下', '厄斯德拉卷下', '乃赫米雅', '乃赫米雅書' },
['orthodox'] = { '奈俄彌亞紀' },
['english'] = { 'Nehemiah' },
['hebrew'] = { 'נחמיה' },
['latin'] = { 'Nehemiae' },
['div'] = '章',
},
['Tb'] = {
['order'] = 270,
['catholic'] = { '多俾亞傳', '多' },
['orthodox'] = { '托維特傳' },
['english'] = { 'Tobit' },
['hebrew'] = { 'טובי' },
['latin'] = { 'Tobiae' },
['div'] = '章',
},
['Jdt'] = {
['order'] = 280,
['catholic'] = { '友弟德傳', '友' },
['orthodox'] = { '虞狄特傳' },
['english'] = { 'Judith' },
['hebrew'] = { 'יהודית' },
['latin'] = { 'Iudith' },
['div'] = '章',
},
['Est'] = {
['order'] = 290,
['protestant'] = { '以斯帖記', '斯' },
['catholic'] = { '艾斯德爾傳', '艾' },
['orthodox'] = { '艾斯提爾傳' },
['english'] = { 'Esther' },
['hebrew'] = { 'אסתר' },
['latin'] = { 'Esther' },
['div'] = '章',
['embeds'] = {
['A'] = 1,
['B'] = 3,
['C'] = 4,
['D'] = 4,
['E'] = 8, -- 警告:8:1-12 冇問題,但係思高本嘅 8:13-17 冇標題,NAB 同思高本嘅 E(戊)章分嘅節完全唔同
['F'] = 10,
},
},
['1Mc'] = {
['order'] = 300,
['catholic'] = { '瑪加伯上', '加上', '{{full}}瑪加伯書上' }, -- 見 2Mc
['orthodox'] = { '瑪喀維傳一' },
['english'] = { '1 Maccabees' },
['hebrew'] = { 'מקבים א' },
['latin'] = { 'Machabaeorum I' },
['div'] = '章',
},
['2Mc'] = {
['order'] = 310,
['catholic'] = { '瑪加伯下', '加下',
'{{full}}瑪加伯書下' }, -- 見 https://fatimacc.catholic.org.hk/daily.reading.2021/2021.11/20211116.pdf
['orthodox'] = { '瑪喀維傳二' },
['english'] = { '2 Maccabees' },
['hebrew'] = { 'מקבים ב' },
['latin'] = { 'Machabaeorum II' },
['div'] = '章',
},
['3Mc'] = {
['order'] = 320,
['orthodox'] = { '瑪喀維傳三' },
['english'] = { '3 Maccabees' },
['hebrew'] = { 'מקבים ג' },
['div'] = '章',
},
['4Mc'] = {
['order'] = 330,
['orthodox'] = { '瑪喀維傳四(附錄)', '瑪喀維傳四' },
['english'] = { '4 Maccabees' },
['hebrew'] = { 'מקבים ד' },
['div'] = '章',
},
['Jb'] = {
['order'] = 340,
['protestant'] = { '約伯記', '伯' },
['catholic'] = { '約伯傳', '約' },
['orthodox'] = { '約弗傳' },
['english'] = { 'Job' },
['hebrew'] = { 'איוב' },
['latin'] = { 'Iob' },
['div'] = '章',
},
['Ps'] = {
['order'] = 350,
['protestant'] = { '詩篇', '詩' },
['catholic'] = { '{{plural}}聖詠集', '詠', '{{singular}}聖詠' },
['orthodox'] = { '聖詠集' },
['english'] = { 'Psalms', 'Pss.' },
['hebrew'] = { 'תהלים' },
['latin'] = { 'Psalmi' },
['div'] = '篇',
},
['Pr'] = {
['order'] = 360,
['protestant'] = { '箴言', '箴' },
['catholic'] = { '箴言', '箴' },
['orthodox'] = { '索洛蒙箴言' },
['english'] = { 'Proverbs', 'Prv.', 'Prov.' },
['hebrew'] = { 'משלי' },
['latin'] = { 'Proverbia' },
['div'] = '章',
},
['Ec'] = {
['order'] = 370,
['protestant'] = { '傳道書', '傳' },
['catholic'] = { '訓道篇', '訓' },
['orthodox'] = { '訓道篇' },
['english'] = { 'Ecclesiastes', 'Eccl.' },
['hebrew'] = { 'קהלת' },
['latin'] = { 'Ecclesiastes' },
['div'] = '章',
},
['Sg'] = {
['order'] = 380,
['protestant'] = { '雅歌', '歌' },
['catholic'] = { '雅歌', '歌' },
['orthodox'] = { '歌中之歌' },
['english'] = { 'Song of Songs' },
['hebrew'] = { 'שיר השירים' },
['latin'] = { 'Canticum Canticorum' },
['div'] = '章',
},
['Wis'] = {
['order'] = 390,
--XXX['protestant'] = { '所羅門智訓' },
['catholic'] = { '智慧篇', '智' },
['orthodox'] = { '索洛蒙的智慧書' },
['english'] = { 'Wisdom' },
['hebrew'] = { 'חכמת שלמה' },
['latin'] = { 'Sapientia' },
['div'] = '章',
},
['Sir'] = {
['order'] = 400,
--XXX['protestant'] = { '傳道經' },
['catholic'] = { '德訓篇', '德' },
['orthodox'] = { '希拉赫的智慧書' },
['english'] = { 'Sirach', 'Ecclesiasticus' },
['hebrew'] = { 'בן סירא' },
['latin'] = { 'Ecclesiasticus' },
['div'] = '章',
},
['Is'] = {
['order'] = 410,
['protestant'] = { '以賽亞書', '賽' },
['catholic'] = { '依撒意亞', '依', '{{full}}依撒意亞先知書' },
['orthodox'] = { '伊撒依亞書' },
['english'] = { 'Isaiah' },
['hebrew'] = { 'ישעיהו' },
['latin'] = { 'Isaias' },
['div'] = '章',
},
['Jr'] = {
['order'] = 420,
['protestant'] = { '耶利米書', '耶' },
['catholic'] = { '耶肋米亞', '耶', '{{full}}耶肋米亞先知書' },
['orthodox'] = { '耶熱彌亞書' },
['english'] = { 'Jeremiah', 'Jer.' },
['hebrew'] = { 'ירמיהו' },
['latin'] = { 'Ieremias' },
['div'] = '章',
},
['Lm'] = {
['order'] = 430,
['protestant'] = { '耶利米哀歌', '哀' },
['catholic'] = { '哀歌', '哀', '{{full}}耶肋米亞哀歌' },
['orthodox'] = { '耶熱彌亞之哀歌' },
['english'] = { 'Lamentations', 'Lam.' },
['hebrew'] = { 'יחזקאל' },
['latin'] = { 'Lamentationes' },
['div'] = '章',
},
['Bar'] = {
['order'] = 440,
---XXX['protestant'] = { '巴錄書' },
['catholic'] = { '巴路克', '巴', '{{full}}巴路克先知書' },
['orthodox'] = { '瓦如赫書' },
['english'] = { 'Baruch' },
['hebrew'] = { 'ברוך' },
['latin'] = { 'Baruch' },
['div'] = '章',
},
['x-LtJr'] = {--XXX made-up code
['order'] = 450,
['orthodox'] = { '耶熱彌亞之書信' },
['english'] = { 'Letter of Jeremiah' },
['hebrew'] = { 'איגרת ירמיהו' },
['div'] = '章',
},
['Ezk'] = {
['order'] = 460,
['protestant'] = { '以西結書', '結' },
['catholic'] = { '厄則克耳', '則', '{{full}}厄則克耳先知書'},
['orthodox'] = { '耶則基伊爾書' },
['english'] = { 'Ezekiel', 'Ez.' },
['hebrew'] = { 'יחזקאל' },
['latin'] = { 'Ezechiel' },
['div'] = '章',
},
['Dn'] = {
['order'] = 470,
['protestant'] = { '但以理書', '但' },
['catholic'] = { '達尼爾', '達', '{{full}}達尼爾先知書' },
['orthodox'] = { '達尼伊爾書' },
['english'] = { 'Daniel' },
['hebrew'] = { 'דניאל' },
['latin'] = { 'Daniel' },
['div'] = '章',
},
['Hs'] = {
['order'] = 480,
['protestant'] = { '何西阿書', '何' },
['catholic'] = { '歐瑟亞', '歐', '{{full}}歐瑟亞先知書' },
['orthodox'] = { '奧西埃書' },
['english'] = { 'Hosea', 'Hos.' },
['hebrew'] = { 'הושע' },
['latin'] = { 'Osee' },
['div'] = '章',
},
['Jl'] = {
['order'] = 490,
['protestant'] = { '約珥書', '珥' },
['catholic'] = { '岳厄爾', '岳', '{{full}}岳厄爾先知書' },
['orthodox'] = { '約伊爾書' },
['english'] = { 'Joel', 'Hos.' },
['hebrew'] = { 'יואל' },
['latin'] = { 'Ioel' },
['div'] = '章',
},
['Am'] = {
['order'] = 500,
['protestant'] = { '阿摩司書', '摩' },
['catholic'] = { '亞毛斯', '亞', '{{full}}亞毛斯先知書' },
['orthodox'] = { '阿摩斯書' },
['english'] = { 'Amos' },
['hebrew'] = { 'עמוס' },
['latin'] = { 'Amos' },
['div'] = '章',
},
['Ob'] = {
['order'] = 510,
['protestant'] = { '俄巴底亞書', '俄' },
['catholic'] = { '亞北底亞', '北', '{{full}}亞北底亞先知書' },
['orthodox'] = { '奧弗狄亞書' },
['english'] = { 'Obadiah' },
['hebrew'] = { 'עבדיה' },
['latin'] = { 'Abdias' },
['div'] = '節',
},
['Jnh'] = {
['order'] = 520,
['protestant'] = { '約拿書', '拿' },
['catholic'] = { '約納', '納', '{{full}}約納先知書' },
['orthodox'] = { '約納書' },
['english'] = { 'Jonah', 'Jon.' },
['hebrew'] = { 'יונה' },
['latin'] = { 'Ionas' },
['div'] = '章',
},
['Mc'] = {
['order'] = 530,
['protestant'] = { '彌迦書', '彌' },
['catholic'] = { '米該亞', '米', '{{full}}米該亞先知書' },
['orthodox'] = { '彌亥亞書' },
['english'] = { 'Micah', 'Mi.' },
['hebrew'] = { 'מיכה' },
['latin'] = { 'Michaeas' },
['div'] = '章',
},
['Nah'] = {
['order'] = 540,
['protestant'] = { '那鴻書', '鴻' },
['catholic'] = { '納鴻', '鴻', '{{full}}納鴻先知書' },
['orthodox'] = { '納翁書' },
['english'] = { 'Nahum', 'Na.' },
['hebrew'] = { 'נחום' },
['latin'] = { 'Nahum' },
['div'] = '章',
},
['Hab'] = {
['order'] = 550,
['protestant'] = { '哈巴谷書', '哈' },
['catholic'] = { '哈巴谷', '哈', '{{full}}哈巴谷先知書' },
['orthodox'] = { '盎瓦庫穆書' },
['english'] = { 'Habakkuk', 'Hb.' },
['hebrew'] = { 'חבקוק' },
['latin'] = { 'Habacuc' },
['div'] = '章',
},
['Zph'] = {
['order'] = 560,
['protestant'] = { '西番雅書', '番' },
['catholic'] = { '索福尼亞', '索', '{{full}}索福尼亞先知書' },
['orthodox'] = { '索佛尼亞書' },
['english'] = { 'Zephaniah', 'Zep.' },
['hebrew'] = { 'צפניה' },
['latin'] = { 'Sophonias' },
['div'] = '章',
},
['Hg'] = {
['order'] = 570,
['protestant'] = { '哈該書', '該' },
['catholic'] = { '哈蓋', '蓋', '{{full}}哈蓋先知書' },
['orthodox'] = { '盎蓋書' },
['english'] = { 'Haggai' },
['hebrew'] = { 'חגי' },
['latin'] = { 'Aggaeus' },
['div'] = '章',
},
['Zch'] = {
['order'] = 580,
['protestant'] = { '撒迦利亞書', '亞' },
['catholic'] = { '匝加利亞', '匝', '{{full}}匝加利亞先知書' },
['orthodox'] = { '匝哈里亞書' },
['english'] = { 'Zechariah', 'Zec.' },
['hebrew'] = { 'זכריה' },
['latin'] = { 'Zacharias' },
['div'] = '章',
},
['Mal'] = {
['order'] = 590,
['protestant'] = { '瑪拉基書', '瑪' },
['catholic'] = { '瑪拉基亞', '拉', '{{full}}瑪拉基亞先知書' },
['orthodox'] = { '瑪拉希亞書' },
['english'] = { 'Malachi' },
['hebrew'] = { 'מלאכי' },
['latin'] = { 'Malachias' },
['div'] = '章',
},
['Mt'] = {
['order'] = 600,
['protestant'] = { '馬太福音', '太' },
['catholic'] = { '瑪竇福音', '瑪', '{{full}}聖瑪竇福音' },
['orthodox'] = { '聖福音依瑪特泰所傳者' },
['english'] = { 'Matthew', 'Matt.' },
['greek'] = { 'Κατά Ματθαίον' },
['latin'] = { 'Matthaeus' },
['div'] = '章',
},
['Mk'] = {
['order'] = 610,
['protestant'] = { '馬可福音', '可' },
['catholic'] = { '馬爾谷福音', '谷', '{{full}}聖馬爾谷福音' },
['orthodox'] = { '聖福音依瑪爾克所傳者' },
['english'] = { 'Mark' },
['greek'] = { 'Κατά Μάρκον' },
['latin'] = { 'Marcus' },
['div'] = '章',
},
['Lk'] = {
['order'] = 620,
['protestant'] = { '路加福音', '路' },
['catholic'] = { '路加福音', '路', '{{full}}聖路加福音' },
['orthodox'] = { '聖福音依路喀所傳者' },
['english'] = { 'Luke' },
['greek'] = { 'Κατά Λουκάν' },
['latin'] = { 'Lucas' },
['div'] = '章',
},
['Jn'] = {
['order'] = 630,
['protestant'] = { '約翰福音', '約' },
['catholic'] = { '若望福音', '若', '{{full}}聖若望福音' },
['orthodox'] = { '聖福音依約安所傳者' },
['english'] = { 'John' },
['greek'] = { 'Κατά Ιωάννην' },
['latin'] = { 'Ioannes' },
['div'] = '章',
},
['Ac'] = {
['order'] = 640,
['protestant'] = { '使徒行傳', '徒' },
['catholic'] = { '宗徒大事錄', '宗' },
['orthodox'] = { '使徒行實' },
['english'] = { 'Acts' },
['greek'] = { 'Πράξεις' },
['latin'] = { 'Actus Apostolorum' },
['div'] = '章',
},
['Rm'] = {
['order'] = 650,
['protestant'] = { '羅馬書', '羅' },
['catholic'] = { '羅馬書', '羅', '{{full}}聖保祿宗徒致羅馬人書' },
['orthodox'] = { '致羅馬人書' },
['english'] = { 'Romans', 'Rom.' },
['greek'] = { 'Προς Ρωμαίους' },
['latin'] = { 'Ad Romanos' },
['div'] = '章',
},
['1Co'] = {
['order'] = 660,
['protestant'] = { '哥林多前書', '林前' },
['catholic'] = { '格林多前書', '格前', '{{full}}聖保祿宗徒致格林多人前書' },
['orthodox'] = { '致科林托人書一' },
['english'] = { '1 Corinthians', '1 Cor.' },
['greek'] = { 'Προς Κορινθίους Αʹ' }, -- U+0374 Greek numeral sign
['latin'] = { 'Ad Corinthios I' },
['div'] = '章',
},
['2Co'] = {
['order'] = 670,
['protestant'] = { '哥林多後書', '林後' },
['catholic'] = { '格林多後書', '格後', '{{full}}聖保祿宗徒致格林多人後書' },
['orthodox'] = { '致科林托人書二' },
['english'] = { '2 Corinthians', '2 Cor.' },
['greek'] = { 'Προς Κορινθίους Βʹ' }, -- U+0374 Greek numeral sign
['latin'] = { 'Ad Corinthios II' },
['div'] = '章',
},
['Gl'] = {
['order'] = 680,
['protestant'] = { '加拉太書', '加' },
['catholic'] = { '迦拉達書', '迦', '{{full}}聖保祿宗徒致迦拉達人書' },
['orthodox'] = { '致噶拉塔人書' },
['english'] = { 'Galatians', 'Gal.' },
['greek'] = { 'Προς Γαλάτας' },
['latin'] = { 'Ad Galatas' },
['div'] = '章',
},
['Eph'] = {
['order'] = 690,
['protestant'] = { '以弗所書', '弗' },
['catholic'] = { '厄弗所書', '弗', '{{full}}聖保祿宗徒致厄弗所人書' },
['orthodox'] = { '致艾弗所人書' },
['english'] = { 'Ephesians', 'Eph.' },
['greek'] = { 'Προς Εφεσίους' },
['latin'] = { 'Ad Ephesios' },
['div'] = '章',
},
['Php'] = {
['order'] = 700,
['protestant'] = { '腓立比書', '腓' },
['catholic'] = { '斐理伯書', '斐', '{{full}}聖保祿宗徒致斐理伯人書' },
['orthodox'] = { '致斐利彼人書' },
['english'] = { 'Philippians', 'Phil.' },
['greek'] = { 'Προς Φιλιππησίους' },
['latin'] = { 'Ad Philippenses' },
['div'] = '章',
},
['Col'] = {
['order'] = 710,
['protestant'] = { '歌羅西書', '西' },
['catholic'] = { '哥羅森書', '哥', '{{full}}聖保祿宗徒致哥羅森人書' },
['orthodox'] = { '致科羅西人書' },
['english'] = { 'Colossians' },
['greek'] = { 'Προς Κολοσσαείς' },
['latin'] = { 'Ad Colossenses' },
['div'] = '章',
},
['1Th'] = {
['order'] = 720,
['protestant'] = { '帖撒羅尼迦前書', '帖前' },
['catholic'] = { '得撒洛尼前書', '得前', '{{full}}聖保祿宗徒致得撒洛尼人前書' },
['orthodox'] = { '致德撒洛尼基人書一' },
['english'] = { '1 Thessalonians', '1 Thes.' },
['greek'] = { 'Προς Θεσσαλονικείς Αʹ' }, -- U+374
['latin'] = { 'Ad Thessalonicenses I' },
['div'] = '章',
},
['2Th'] = {
['order'] = 730,
['protestant'] = { '帖撒羅尼迦後書', '帖後' },
['catholic'] = { '得撒洛尼後書', '得後', '{{full}}聖保祿宗徒致得撒洛尼人後書' },
['orthodox'] = { '致德撒洛尼基人書二' },
['english'] = { '2 Thessalonians', '2 Thes.' },
['greek'] = { 'Προς Θεσσαλονικείς Βʹ' }, -- U+374
['latin'] = { 'Ad Thessalonicenses II' },
['div'] = '章',
},
['1Tm'] = {
['order'] = 740,
['protestant'] = { '提摩太前書', '提前' },
['catholic'] = { '弟茂德前書', '弟前', '{{full}}聖保祿宗徒致弟茂德前書' },
['orthodox'] = { '致提摩泰書一' },
['english'] = { '1 Timothy' },
['greek'] = { 'Προς Τιμόθεον Αʹ' }, -- U+374
['latin'] = { 'Ad Timotheum I' },
['div'] = '章',
},
['2Tm'] = {
['order'] = 750,
['protestant'] = { '提摩太後書', '提後' },
['catholic'] = { '弟茂德後書', '弟後', '{{full}}聖保祿宗徒致弟茂德後書' },
['orthodox'] = { '致提摩泰書二' },
['english'] = { '2 Timothy' },
['greek'] = { 'Προς Τιμόθεον Βʹ' }, -- U+374
['latin'] = { 'Ad Timotheum II' },
['div'] = '章',
},
['Ti'] = {
['order'] = 760,
['protestant'] = { '提多書', '多' },
['catholic'] = { '弟鐸書', '鐸', '{{full}}聖保祿宗徒致弟鐸書' },
['orthodox'] = { '致提托書' },
['english'] = { 'Titus' },
['greek'] = { 'Προς Τίτον' },
['latin'] = { 'Ad Titum' },
['div'] = '章',
},
['Phm'] = {
['order'] = 770,
['protestant'] = { '腓利門書', '門' },
['catholic'] = { '費肋孟書', '費', '{{full}}聖保祿宗徒致費肋孟書' },
['orthodox'] = { '致斐利蒙書' },
['english'] = { 'Philemon', 'Phlm.' },
['greek'] = { 'Προς Φιλήμονα' },
['latin'] = { 'Ad Philemonem' },
['div'] = '節',
},
['Heb'] = {
['order'] = 780,
['protestant'] = { '希伯來書', '來' },
['catholic'] = { '希伯來書', '希', '{{full}}致希伯來人書' },
['orthodox'] = { '致希伯來人書' },
['english'] = { 'Hebrews', 'Phlm.' },
['greek'] = { 'Προς Εβραίους' },
['latin'] = { 'Ad Hebraeos' },
['div'] = '章',
},
['Jms'] = {
['order'] = 790,
['protestant'] = { '雅各書', '雅' },
['catholic'] = { '雅各伯書', '雅' }, -- not sure what the long names of these ones are
['orthodox'] = { '雅科弗書信' },
['english'] = { 'James', 'Jas.' },
['greek'] = { 'Ιακώβου' },
['latin'] = { 'Iacobi' },
['div'] = '章',
},
['1Pt'] = {
['order'] = 800,
['protestant'] = { '彼得前書', '彼前' },
['catholic'] = { '伯多祿前書', '伯前' },
['orthodox'] = { '裴特若書信一' },
['english'] = { '1 Peter' },
['greek'] = { 'Πέτρου Αʹ' }, -- U+374
['latin'] = { 'Petri I' },
['div'] = '章',
},
['2Pt'] = {
['order'] = 810,
['protestant'] = { '彼得後書', '彼後' },
['catholic'] = { '伯多祿後書', '伯後' },
['orthodox'] = { '裴特若書信二' },
['english'] = { '1 Peter' },
['greek'] = { 'Πέτρου Βʹ' }, -- U+374
['latin'] = { 'Petri II' },
['div'] = '章',
},
['1Jn'] = {
['order'] = 820,
['protestant'] = { '約翰一書', '約壹' },
['catholic'] = { '若望一書', '若一', '若壹', '壹若' },
['orthodox'] = { '約安書信一' },
['english'] = { '1 John' },
['greek'] = { 'Ιωάννου Αʹ' }, -- U+374
['latin'] = { 'Ioannis I' },
['div'] = '章',
},
['2Jn'] = {
['order'] = 830,
['protestant'] = { '約翰二書', '約貳' },
['catholic'] = { '若望二書', '若二', '若貳', '貳若' },
['orthodox'] = { '約安書信二' },
['english'] = { '2 John' },
['greek'] = { 'Ιωάννου Βʹ' }, -- U+374
['latin'] = { 'Ioannis II' },
['div'] = '節',
},
['3Jn'] = {
['order'] = 840,
['protestant'] = { '約翰三書', '約叁' },
['catholic'] = { '若望三書', '若三', '若叁', '叁若' },
['orthodox'] = { '約安書信三' },
['english'] = { '3 John' },
['greek'] = { 'Ιωάννου Γʹ' }, -- U+374
['latin'] = { 'Ioannis III' },
['div'] = '節',
},
['Jd'] = {
['order'] = 850,
['protestant'] = { '猶大書', '猶' },
['catholic'] = { '猶達書', '猶' },
['orthodox'] = { '儒達書信' },
['english'] = { 'Jude' },
['greek'] = { 'Ιούδα' },
['latin'] = { 'Iudae' },
['div'] = '節',
},
['Rv'] = {
['order'] = 860,
['protestant'] = { '啟示錄', '啟' },
['catholic'] = { '{{full}}若望默示錄', '默', '{{preferred}}默示錄' },
['orthodox'] = { '約安之啟示錄' },
['english'] = { 'Revelation' },
['greek'] = { 'Αποκάλυψις Ιωάννου' },
['latin'] = { 'Apocalypsis' },
['div'] = '章',
},
}
local number_of_chapters = {
['CUV'] = {
['Gn'] = 50,
['Ex'] = 40,
['Lv'] = 27,
['Nm'] = 36,
['Dt'] = 34,
['Jos'] = 24,
['Jdg'] = 21,
['Ru'] = 4,
['1Sm'] = 31,
['2Sm'] = 24,
['1Kg'] = 22,
['2Kg'] = 25,
['1Ch'] = 29,
['2Ch'] = 36,
['Ezr'] = 10,
['Neh'] = 13,
['Est'] = 10,
['Jb'] = 42,
['Ps'] = 150,
['Pr'] = 31,
['Ec'] = 12,
['Sg'] = 8,
['Is'] = 66,
['Jr'] = 52,
['Lm'] = 5,
['Ezk'] = 48,
['Dn'] = 12,
['Hs'] = 14,
['Jl'] = 3, -- 基督教第3章 = 天主教第4章
['Am'] = 9,
['Ob'] = 1,
['Jnh'] = 4,
['Mc'] = 7,
['Nah'] = 3,
['Hab'] = 3,
['Zph'] = 3,
['Hg'] = 2,
['Zch'] = 14,
['Mal'] = 4, -- 基督教 4:1 = 天主教 3:19;內容一樣,但係天主教開咗新章
['Mt'] = 28,
['Mk'] = 16,
['Lk'] = 24,
['Jn'] = 21,
['Ac'] = 28,
['Rm'] = 16,
['1Co'] = 16,
['2Co'] = 13,
['Gl'] = 6,
['Eph'] = 6,
['Php'] = 4,
['Col'] = 4,
['1Th'] = 5,
['2Th'] = 3,
['1Tm'] = 6,
['2Tm'] = 4,
['Ti'] = 3,
['Phm'] = 1,
['Heb'] = 13,
['Jms'] = 5,
['1Pt'] = 5,
['2Pt'] = 3,
['1Jn'] = 5,
['2Jn'] = 1,
['3Jn'] = 1,
['Jd'] = 1,
['Rv'] = 22,
};
['SBV'] = {
['Gn'] = 50,
['Ex'] = 40,
['Lv'] = 27,
['Nm'] = 36,
['Dt'] = 34,
['Jos'] = 24,
['Jdg'] = 21,
['Ru'] = 4,
['1Sm'] = 31,
['2Sm'] = 24,
['1Kg'] = 22,
['2Kg'] = 25,
['1Ch'] = 29,
['2Ch'] = 36,
['Ezr'] = 10,
['Neh'] = 13,
['Tb'] = 14,
['Jdt'] = 16,
['Est'] = 10 + 6, -- 多咗6章 「補錄」,章數用天干,插喺正常章之間(次序 A 1 2 3 B 4 C D 5 6 7 8 E 8 9 10 F)
['1Mc'] = 16,
['2Mc'] = 15,
['Jb'] = 42,
['Ps'] = 150,
['Pr'] = 31,
['Ec'] = 12,
['Sg'] = 8,
['Wis'] = 19,
['Sir'] = 51,
['Is'] = 66,
['Jr'] = 52,
['Lm'] = 5,
['Bar'] = 6,
['Ezk'] = 48,
['Dn'] = 14, -- 第 13-14 章叫 「附錄」
['Hs'] = 14,
['Jl'] = 4, -- 天主教第 4 章 = 基督教第 3 章,天主教第 3 章係基督教冇嘅內容
['Am'] = 9,
['Ob'] = 1,
['Jnh'] = 4,
['Mc'] = 7,
['Nah'] = 3,
['Hab'] = 3,
['Zph'] = 3,
['Hg'] = 2,
['Zch'] = 14,
['Mal'] = 3, -- 天主教 3:19 = 基督教 4:1;內容一樣,但係天主教開咗新章
['Mt'] = 28,
['Mk'] = 16,
['Lk'] = 24,
['Jn'] = 21, -- 21 叫 「附錄」
['Ac'] = 28,
['Rm'] = 16,
['1Co'] = 16,
['2Co'] = 13,
['Gl'] = 6,
['Eph'] = 6,
['Php'] = 4,
['Col'] = 4,
['1Th'] = 5,
['2Th'] = 3,
['1Tm'] = 6,
['2Tm'] = 4,
['Ti'] = 3,
['Phm'] = 1,
['Heb'] = 13,
['Jms'] = 5,
['1Pt'] = 5,
['2Pt'] = 3,
['1Jn'] = 5,
['2Jn'] = 1,
['3Jn'] = 1,
['Jd'] = 1,
['Rv'] = 22,
};
}
-- 唔同教派嘅聖經,將聖經分成嘅部分,入面對應乜嘢書卷
-- 第一層:聖經分部嘅代號
-- 第二層:構成書卷代號(books 序列第一層,順次序排)
local seq = {
TORAH = {
'Gn', 'Ex', 'Lv', 'Nm', 'Dt',
};
PROPHETS = {
'Jos', 'Jdg', 'x-Sm', 'x-Kg',
'Is', 'Jr', 'Ezk',
'Hs', 'Jl', 'Am', 'Ob', 'Jnh', 'Mc', 'Nah', 'Hab', 'Zph', 'Hg', 'Zch', 'Mal',
};
WRITINGS = {
'x-Ch', 'Ps', 'Jb', 'Pr', 'Ru', 'Sg', 'Ec', 'Lm', 'Est', 'Dn', 'x-Ezr-Neh',
};
CATHOLIC_OLD_TESTAMENT = {
'Gn', 'Ex', 'Lv', 'Nm', 'Dt',
'Jos', 'Jdg', 'Ru', '1Sm', '2Sm', '1Kg', '2Kg', '1Ch', '2Ch', 'Ezr', 'Neh',
'Tb', 'Jdt', 'Est', '1Mc', '2Mc',
'Jb', 'Ps', 'Pr', 'Ec', 'Sg', 'Wis', 'Sir',
'Is', 'Jr', 'Lm', 'Bar', 'Ezk', 'Dn',
'Hs', 'Jl', 'Am', 'Ob', 'Jnh', 'Mc', 'Nah', 'Hab', 'Zph', 'Hg', 'Zch', 'Mal',
};
PROTESTANT_OLD_TESTAMENT = {
'Gn', 'Ex', 'Lv', 'Nm', 'Dt',
'Jos', 'Jdg', 'Ru', '1Sm', '2Sm', '1Kg', '2Kg', '1Ch', '2Ch', 'Ezr', 'Neh',
'Est',
'Jb', 'Ps', 'Pr', 'Ec', 'Sg',
'Is', 'Jr', 'Lm', 'Ezk', 'Dn',
'Hs', 'Jl', 'Am', 'Ob', 'Jnh', 'Mc', 'Nah', 'Hab', 'Zph', 'Hg', 'Zch', 'Mal',
};
NEW_TESTAMENT = {
'Mt', 'Mk', 'Lk', 'Jn',
'Ac',
'Rm', '1Co', '2Co', 'Gl', 'Eph', 'Php', 'Col', '1Th', '2Th', '1Tm', '2Tm', 'Ti', 'Phm',
'Heb', 'Jms', '1Pt', '2Pt', '1Jn', '2Jn', '3Jn', 'Jd',
'Rv',
}
}
-- 唔同教派嘅聖經,組成嘅部分係乜,同有乜屬性
-- 第一層:聖經抽象實現體代號(通常係指教派)
-- 第二層:構成部分(順次序排)
-- 第三層:構成部分嘅屬性
-- names = 中文名
-- books = 構成分部代號(seq 序列第一層)
local parts = {
CHRISTIAN_NEW_TESTAMENT = {
{
['names'] = { '新約' };
['books'] = seq.NEW_TESTAMENT;
},
};
CATHOLIC = {
{
['names'] = { '舊約' };
['books'] = seq.CATHOLIC_OLD_TESTAMENT;
}, {
['names'] = { '新約' };
['books'] = seq.NEW_TESTAMENT;
},
};
PROTESTANT = {
{
['names'] = { '舊約' };
['books'] = seq.PROTESTANT_OLD_TESTAMENT;
}, {
['names'] = { '新約' };
['books'] = seq.NEW_TESTAMENT;
},
};
JUDAISM = {
{
['names'] = { '五經' };
['books'] = seq.TORAH;
}, {
['names'] = { '先知' };
['books'] = seq.PROPHETS;
}, {
['names'] = { '聖錄' };
['books'] = seq.WRITINGS;
},
};
}
-- 聖經譯本
-- 第一層:譯本代號
-- 第二層:代號屬性
-- names = 中文名(非必填)
-- link = 譯本喺粵維嘅文章名(非必填)
-- tradition = 教派(traditions 序列第一層)
-- language = 語言(唔係中文先用,languages 序列第二層大楷代號)
-- number_of_chapters = 章數定義(number_of_chapters 序列第一層)
-- parts = 分部定義(parts 序列第一層)
-- has_embeds_p = 有冇任何書卷有用天干嘅章(true = 有,false = 冇,天主教專用)
-- url = 網站定義(非必填,參數 &book;、&numbers;、&version;)
-- url_book_transform = 書卷名滿射函數,參數1係Bible Gateway書卷代號,參數2係呢個模組嘅書卷代號
-- url_chapter_transform = 章數滿射函數,參數1係章數
local versions = {
['CSB'] = { -- for testing
['names'] = {
'基督教標準聖經', -- v. https://tc.tgcchinese.org/essay/the-bible-in-translation
};
['tradition'] = 'protestant';
['language'] = languages.ENGLISH;
['number_of_chapters'] = number_of_chapters.CUV;
['parts'] = parts.PROTESTANT;
};
['CNV'] = {
['names'] = {
'新譯本',
'聖經新譯本',
'CNVT', -- Bible Gateway 兼容
};
['link'] = '聖經新譯本',
['tradition'] = 'protestant';
['number_of_chapters'] = number_of_chapters.CUV;
['parts'] = parts.PROTESTANT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=CNVT';
};
['CUV'] = {
['names'] = {
'和合本',
'聖經和合本',
};
['link'] = '聖經和合本';
['tradition'] = 'protestant';
['number_of_chapters'] = number_of_chapters.CUV;
['parts'] = parts.PROTESTANT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=CUVMPT';
};
['JPS'] = {
['link'] = '塔納赫#英文版《塔納赫》';
['tradition'] = 'judaism';
['language'] = languages.ENGLISH;
['number_of_chapters'] = nil;
['parts'] = parts.JUDAISM;
['url'] = 'https://mechon-mamre.org/p/pt/pt&book;&chapter;.htm';
['url_book_transform'] = function (s, id)
local codes = {
['Gn'] = '01',
['Ex'] = '02',
['Lv'] = '03',
['Nm'] = '04',
['Dt'] = '05',
['Jos'] = '06',
['Jdg'] = '07',
['Ru'] = '29',
['1Sm'] = '08a',
['2Sm'] = '08b',
['1Kg'] = '09a',
['2Kg'] = '09b',
['1Ch'] = '25a',
['2Ch'] = '25b',
['Ezr'] = '35a',
['Neh'] = '35b',
['Est'] = '33',
['Jb'] = '27',
['Ps'] = '26',
['Pr'] = '28',
['Ec'] = '31',
['Sg'] = '30',
['Is'] = '10',
['Jr'] = '11',
['Lm'] = '32',
['Ezk'] = '12',
['Dn'] = '34',
['Hs'] = '13',
['Jl'] = '14',
['Am'] = '15',
['Ob'] = '16',
['Jnh'] = '17',
['Mc'] = '18',
['Nah'] = '19',
['Hab'] = '20',
['Zph'] = '21',
['Hg'] = '22',
['Zch'] = '23',
['Mal'] = '24',
}
if not codes[id] then
error('Internal error: book code "' .. id .. '" (name ' .. s .. ') not found in JPS codes table');
end
return codes[id];
end;
['url_chapter_transform'] = function (s)
return string.format('%x', math.floor(s/10)) .. string.format('%d', s%10);
end;
};
['KJV'] = {
['names'] = {
'欽定本',
'英王欽定本',
};
['link'] = '英王欽定本',
['tradition'] = 'protestant';
['number_of_chapters'] = number_of_chapters.CUV;
['parts'] = parts.PROTESTANT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=KJV';
};
['MT'] = {
['names'] = {
'馬所拉經文',
'塔納赫',
'he', -- bibleverse 兼容
};
['link'] = '馬所拉經文';
['tradition'] = 'hebrew';
['language'] = languages.HEBREW;
['number_of_chapters'] = nil;
['parts'] = parts.JUDAISM;
['url'] = 'https://mechon-mamre.org/p/pt/pt&book;&chapter;.htm';
-- url_book_transform、url_chapter_transform 喺後面抄
};
['NAB'] = {
['names'] = {
'新美國聖經',
};
['link'] = '新美國聖經';
['tradition'] = 'catholic';
['language'] = languages.ENGLISH;
['number_of_chapters'] = nil;
['parts'] = parts.CATHOLIC;
['has_embeds_p'] = true;
['url'] = 'https://bible.usccb.org/bible/&book;/&chapter;';
['url_book_transform'] = function (s)
return s:lower():gsub('%+', '');
end;
};
['NIV'] = {
['tradition'] = 'protestant';
['language'] = languages.ENGLISH;
['number_of_chapters'] = nil;
['parts'] = parts.PROTESTANT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=NIV';
};
['NRSVA'] = {
['names'] = {
'NRSV 英國英文版',
};
['tradition'] = 'protestant';
['language'] = languages.ENGLISH;
['number_of_chapters'] = nil;
['parts'] = parts.PROTESTANT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=NRSVA';
};
['RCU17TS'] = {
['names'] = {
'和合本修訂版',
};
['link'] = '和合本修訂版';
['tradition'] = 'protestant';
['number_of_chapters'] = number_of_chapters.CUV;
['parts'] = parts.PROTESTANT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=RCU17TS';
};
['SBV'] = {
['names'] = {
'思高本',
'思高聖經',
'思高中文聖經',
'聖經思高本',
};
['link'] = '聖經思高本';
['tradition'] = 'catholic';
['number_of_chapters'] = number_of_chapters.SBV;
['parts'] = parts.CATHOLIC;
['has_embeds_p'] = true;
['url'] = 'https://www.ccreadbible.org/chinesebible/sigao/&book;_bible_Ch_&chapter;_.html';
['url_book_transform'] = function (s)
return s:gsub('%+', '_');
end;
};
['Vulgate'] = {
['names'] = {
'拉丁通用本',
'拉丁通俗本',
'拉丁普及本',
'聖經拉丁通用本',
'聖經拉丁通俗本',
'聖經拉丁普及本',
'武加大譯本',
};
['link'] = '聖經拉丁通用本';
['tradition'] = 'latin';
['number_of_chapters'] = number_of_chapters.SBV;
['parts'] = parts.CATHOLIC;
['has_embeds_p'] = true;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=Vulgate';
};
['SBLGNT'] = { -- https://sblgnt.com/ (CC 4.0)
['names'] = {
'SBL 希臘文新約',
};
['tradition'] = 'greek';
['number_of_chapters'] = nil;
['parts'] = parts.CHRISTIAN_NEW_TESTAMENT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=SBLGNT';
};
['THGNT'] = { -- https://academic.tyndalehouse.com/research/the-greek-new-testament/
['names'] = {
'Tyndale House 希臘文新約',
};
['tradition'] = 'greek';
['number_of_chapters'] = nil;
['parts'] = parts.CHRISTIAN_NEW_TESTAMENT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=THGNT';
};
['TR1550'] = {
['names'] = {
'公認經文', -- Protestant name
'TR',
};
['tradition'] = 'greek';
['number_of_chapters'] = nil;
['parts'] = parts.CHRISTIAN_NEW_TESTAMENT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=TR1550';
};
['TR1894'] = {
['names'] = {
'公認經文', -- Protestant name
'TR',
};
['tradition'] = 'greek';
['number_of_chapters'] = nil;
['parts'] = parts.CHRISTIAN_NEW_TESTAMENT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=TR1894';
};
['WH'] = {
['names'] = {
'魏斯科-霍特新約希臘文聖經', -- Lo et al. (2003) p. 580, de-Mandarinized
'WHNU',
};
['tradition'] = 'greek';
['number_of_chapters'] = nil;
['parts'] = parts.CHRISTIAN_NEW_TESTAMENT;
['url'] = 'https://www.biblegateway.com/passage/?search=&book;+&numbers;&version=WHNU';
};
}
versions.MT.url_book_transform = versions.JPS.url_book_transform;
versions.MT.url_chapter_transform = versions.JPS.url_chapter_transform;
-- 章節數格式定義
-- 加格式唔可以就咁加,要改埋源碼
local pats = {
['key val'] = '^([1-4]? *[^0-9]+) *(.*)$',
['key add vv'] = '^([1-4]? *[^0-9]+) *([A-Z]:.*)$',
['n'] = '^(([1-9][0-9]*))$',
['A'] = '^(([A-J]))$',
['n:n'] = '^(([1-9][0-9]*):([1-9][0-9]*))$',
['A:n'] = '^(([A-J]):([1-9][0-9]*))$',
['n:n-n'] = '^(([1-9][0-9]*):([1-9][0-9]*-[1-9][0-9]*))$',
['A:n-n'] = '^(([A-J]):([1-9][0-9]*-[1-9][0-9]*))$',
}
-- 錯誤訊息
local cat_all_unknown_versions = '引聖經用咗不明譯本嘅文';
local cat_specific_unknown_version_prefix = '引聖經指定用不明譯本';
local cat_specific_unknown_version_suffix = '嘅文';
--- Auxiliaries ---------------------------------------------------------------
local function fix_argument (s)
return s:gsub('^ +', ''):gsub(' +$', '');
end
local function fix_en_dash (s)
if s then
s = mw.ustring.gsub(s, '–', '-');
end
return s;
end
local function croak (s)
local frame = mw.getCurrentFrame();
if frame:getParent() then
frame = frame:getParent();
end
local note = '(引模參數係:' .. Syu1meng2.cvs(frame.args) .. ')';
error('引聖經失敗,' .. s .. note, 0);
end
local function parse_tagged_name (s)
local it = { tags = {} };
while true do
local tag, remainder = mw.ustring.match(s, '^\{\{([^\{\}]*)\}\}(.*)$');
if remainder == nil then break end;
s = remainder;
if not tag then break end;
it.tags[tag] = true;
end
it.value = s;
return it;
end
local function get_book_definition (id, tradition)
local it;
if tradition == 'judaism' and books[id] and not books[id][tradition] then
tradition = 'hebrew'; -- XXX stupid hack for testing
end
if books[id] and books[id][tradition] then
it = books[id][tradition];
end
return it;
end
local function book_exists_in_tradition (id, tradition)
return get_book_definition(id, tradition);
end
local function find_book_name (id, tradition, forms)
local it;
if forms == nil then -- we need to wrap a nil, but Lua arrays can't contain nil; I hate Lua so much
forms = { false };
elseif type(forms) ~= 'table' then
forms = { forms };
end
if tradition and get_book_definition(id, tradition) then
-- start from position 1 and look for a name with the correct tag
local candidates = get_book_definition(id, tradition);
local fallback;
for j, form in ipairs(forms) do
for i = 1, #candidates do
local candidate = parse_tagged_name(candidates[i]);
if candidate.tags[form] then
it = candidate.value;
elseif not fallback then
fallback = candidate.value;
end
if it then break end;
end
if it then break end;
end
if not it then
it = fallback;
end
elseif tradition then
error('Internal error, book ' .. id .. ' does not exist in tradition ' .. tradition
.. ' (correct language label is missing in books array)', 2);
else
error('Internal error, invalid book id ' .. id, 2);
end
return it;
end
local function describe_tradition_genitive (tradition)
local it;
if not traditions[tradition] then
it = tradition .. ' ';
elseif tradition == 'english' then -- XXX stupid hack
it = '其他教派講';
else
it = traditions[tradition];
end
if #it > 0 then
it = it .. '嘅';
end
return it;
end
local function describe_book (id, tradition, describe_tradition_p)
local it;
if describe_tradition_p == nil then
describe_tradition_p = true;
end
if tradition and get_book_definition(id, tradition) then
it = '';
if describe_tradition_p then
it = it .. describe_tradition_genitive(tradition);
end
it = it .. '《' .. find_book_name(id, tradition, nil) .. '》';
else
for _, candidate_tradition in pairs({'protestant', 'catholic', 'orthodox', 'judaism'}) do
if get_book_definition(id, candidate_tradition) then
it = '';
if describe_tradition_p then
it = it .. describe_tradition_genitive(candidate_tradition);
end
it = it .. '《' .. find_book_name(id, candidate_tradition, nil) .. '》';
end
if it then break end;
end
if not it then
error('Internal error, got invalid book id ' .. id, 2);
end
end
return it;
end
local function canonicalize_version (id_or_name)
local it = id_or_name;
if not versions[id_or_name] then
local candidates = {};
for id, version in pairs(versions) do
if version.names then
local something_done_p = false;
for _, candidate in pairs(version.names) do
if id_or_name == candidate then
table.insert(candidates, id);
something_done_p = true;
end
if something_done_p then break end;
end
end
if id_or_name:lower() == id:lower() then
table.insert(candidates, id);
end
end
if #candidates > 1 then
croak('「' .. id_or_name .. '」 可以指:' .. mw.text.listToText(candidates, '、', ' 或者 '));
elseif #candidates == 1 then
it = candidates[1];
end
end
return it;
end
local function describe_version (id, suppress_spacing_tweaks_p)
local it;
if versions[id] and versions[id].names then
it = versions[id].names[1];
else
it = id;
if id:match('[a-zA-Z]$') then
if not suppress_spacing_tweaks_p then
it = it .. ' ';
end
it = it .. '譯本';
end
end
return it;
end
local function describe_ambiguity (ids, conjunction, describe_tradition_p)
local it = '';
if not conjunction then
conjunction = '或者';
end
if describe_tradition_p == nil then
describe_tradition_p = true;
end
if false then -- if debugging
it = Syu1meng2.cvs(ids)
else
for i = 1, #ids do
if i == 1 then
-- I hate Lua
elseif i == #ids then
it = it .. ' ' .. conjunction;
elseif i > 1 then
it = it .. '、';
end
it = it .. describe_book(ids[i].id, ids[i].naming, describe_tradition_p);
it = it .. '(' .. ids[i].id .. ')';
end
end
return it;
end
local function build_citable (work, chapter)
local it;
if how_to_mark_books then
it = how_to_mark_books(work, chapter);
elseif work and chapter then
error('Internal error: build_citable received both work and chapter'); -- valid but should not happen in this module
elseif work then
it = work;
else
it = chapter;
end
return it;
end
local function find_book (s)
local it = {};
if books[s] then
table.insert(it, {['id'] = s; });
else
local s1 = mw.ustring.upper(mw.ustring.gsub(s, '[ %.]', ''));
for key, book in pairs(books) do
for _, naming in pairs({'protestant', 'catholic', 'orthodox', 'english'}) do
if book[naming] then
for j, candidate_with_tags in pairs(book[naming]) do
local candidate = (parse_tagged_name(candidate_with_tags))['value'];
if candidate == s then
table.insert(it, {['id'] = key; ['naming'] = naming..''; });
elseif naming == 'english' and mw.ustring.upper(mw.ustring.gsub(candidate, '[ %.]', '')) == s1 then
table.insert(it, {['id'] = key; });
end
end
end
end
end
end
return it;
end
local function assert_canonical_book_code (generic)
local candidates = find_book(generic);
local it;
if #candidates == 0 then
croak('搵唔到叫 「' .. generic .. '」 嘅書卷');
elseif #candidates > 1 then
croak('「' .. generic .. '」 可以指' .. describe_ambiguity(candidates, '或者'));
else
it = candidates[1].id;
end
return it;
end
local function parse_reference (s)
local it;
local key, specific, chapter, verses;
if type(s) == 'table' then
key = assert_canonical_book_code(s.book);
specific = fix_en_dash(s.numbers);
chapter = s.chapter;
verses = fix_en_dash(s.verses);
it = s;
else
-- Split book and numbers; try the weird ones first (only in catholic)
local generic;
s = fix_en_dash(s);
generic, specific = mw.ustring.match(s, pats['key add vv']);
if not specific then
generic, specific = mw.ustring.match(s, pats['key val']);
end
if generic then
generic = mw.ustring.gsub(generic, ' +$', '');
key = assert_canonical_book_code(generic);
it = {};
end
end
if specific and not (chapter or verses) then
local numbers;
for _, pat in pairs({'n', 'A'}) do
numbers, chapter = mw.ustring.match(specific, pats[pat]);
if numbers then break end;
end
if not numbers then
for _, pat in pairs({'n:n', 'A:n', 'n:n-n', 'A:n-n'}) do
numbers, chapter, verses = mw.ustring.match(specific, pats[pat]);
if numbers then break end;
end
end
if not numbers then
croak('唔明 「' .. specific .. '」 係乜嘢章節');
end
end
if key then
if books[key].div == '節' then
verses = chapter;
chapter = nil;
end
it.book = key;
it.chapter = chapter;
it.verses = verses;
end
return it;
end
local function build_external_link (url, label)
-- style 係夾硬修正維基百科設計錯誤,導致書卷名係希伯來文嘅話會顯示錯誤
return '[' .. url .. ' <span style="display:inline-block">' .. label .. '</span>]';
end
local function find_abbreviation (id, tradition, version, allow_informal_digits_p, allow_fallback_p)
local it;
local specified_language;
if tradition == 'english' then
specified_language = tradition;
elseif version and versions[version] and versions[version].language then
specified_language = versions[version].language;
end
if specified_language then
if specified_language == languages.ENGLISH then
-- FIXME. not ideal for tradition = 'judaism', outright wrong for tradition = 'orthodox'
it = id;
else
tradition = specified_language; -- FIXME temporary hack
end
end
if not it then
local candidates = get_book_definition(id, tradition);
if candidates and #candidates > 1 then
-- Start from position 2 and look for what looks like a short form
if allow_informal_digits_p == nil then
allow_informal_digits_p = not numbering[tradition].kanji_chapters_p;
end
for i = 2, #candidates do
local candidate = candidates[i];
if mw.ustring.match(candidate, '^..?$') and (
allow_informal_digits_p
or mw.ustring.match(candidate, '[^一二三四]$')) then
it = candidate;
end
if it then break end;
end
end
if not it and allow_fallback_p then -- no abbreviated forms found
it = candidates[1];
end
end
return it;
end
local function format_numbering (ref, tradition, version)
local it;
local book = books[ref.book];
local embeds = book.embeds;
local error_p = false;
if tradition == nil then
it = '';
if book.div == '節' then
it = it .. ref.verses .. book.div;
elseif ref.chapter then
if stems[ref.chapter] then
it = it .. '補錄' .. stems[ref.chapter]; -- FIXME
else
it = it .. ref.chapter .. book.div;
end
if ref.verses then
it = it .. ref.verses .. '節';
end
end
else
local t = find_abbreviation(ref.book, tradition, version, nil, nil);
if not t then
t = find_book_name(ref.book, tradition, nil);
end
if not t then
error('format_numbering: Internal error, tradition “' .. tradition .. '” not defined in book definition '..Syu1meng2.cvs(book), 2);
end
local book = mw.ustring.gsub(book.english[1], '%s+', '+');
if Syu1meng2.cjk_p(t) then
t = build_citable(nil, t);
else
t = t .. ' ';
end
local numbers = '';
-- Figure out version first, because it's needed to figure out how to render chapter numbers
local unknown_version_p = false;
if not version then
version = numbering[tradition].default;
end
if version and not versions[version] then
--croak('唔知 「' .. version .. '」 係乜嘢譯本');
unknown_version_p = true;
elseif version and tradition and versions[version] and versions[version].tradition ~= tradition then
croak('「' .. version .. '」 唔係' .. traditions[tradition] .. '譯本');
end
-- Note that ref.chapter may not exist; some books don't have chapters
if ref.chapter and ref.verses then
numbers = ref.chapter .. ':' .. ref.verses;
elseif ref.chapter then
numbers = ref.chapter;
else
numbers = ref.verses;
end
if numbering[tradition].kanji_chapters_p and not versions[version].language then
if ref.chapter then
if stems[ref.chapter] then
t = t .. '補錄' .. stems[ref.chapter] -- FIXME
else
t = t .. NumberToChinese.sbv_chapter_number(ref.chapter, {kanji_p=true})
end
end
if ref.verses then
t = t .. ref.verses;
end
elseif numbers then
t = t .. numbers;
end
if version and versions[version] and versions[version].url then
-- Construct an external link (CUV works; others, maybe)
local book_code = book; -- note that this is not the id, and spaces are already replaced by +
local chapter_code = ref.chapter;
local f = versions[version].url_book_transform;
local g = versions[version].url_chapter_transform;
if f then
book_code = f(book_code, ref.book);
end
if g then
chapter_code = g(chapter_code);
end
if embeds and embeds[chapter_code] then
chapter_code = embeds[chapter_code];
end
t = build_external_link(versions[version].url
:gsub('&book;', book_code)
:gsub('&numbers;', numbers or '')
:gsub('&chapter;', chapter_code or '1'), t);
elseif unknown_version_p then
-- Assume specified version is a Bible Gateway code
t = build_external_link('https://www.biblegateway.com/passage/?search=' .. book
.. (numbers or '') .. '&version=' .. version, t);
end
if not version then
t = '<small>' .. traditions[tradition] .. ':</small>' .. t;
elseif unknown_version_p then
t = '<small>不明譯本' .. version .. ':</small>' .. t;
else
local label = version;
if versions[version].names then
label = versions[version].names[1];
end
if versions[version].link then
label = '[[' .. versions[version].link .. '|' .. label .. ']]';
end
t = '<small>' .. traditions[tradition] .. label .. ':</small>' .. t;
end
it = t;
end
--it = Syu1meng2.cvs(ref); -- DEBUG
return it;
end
local function version_has_book_p (version, id)
local it = false;
if versions[version] and versions[version].parts then
local parts = versions[version].parts;
for i, part_id in pairs(parts) do
for j, book_id in pairs(parts[i].books) do
if book_id == id then
it = book_id;
-- Check if the listed book is a theoretical aggregate (e.g., "Kings" or "Chronicles")
elseif books[book_id].parts then
for k, scroll_id in pairs(books[book_id].parts) do
if scroll_id == id then
it = scroll_id;
end
if it then break end;
end
end
if it then break end;
end
if it then break end;
end
end
return it;
end
local function version_not_compatible_p (ref, version)
local it;
assert(version);
assert(versions[version]);
assert(ref.book);
-- Does the book exist?
if not version_has_book_p(version, ref.book) then
it = describe_version(version) .. '冇書卷' .. describe_book(ref.book, nil, false);
-- Do we require weird alphabetic chapters but the version doesn't have them?
elseif stems[ref.chapter] and not versions[version].has_embeds_p then
it = describe_version(version) .. '嘅' .. describe_book(ref.book , nil, false).. '唔會有 「補錄' .. stems[ref.chapter] .. '」';
end
return it;
end
local function assert_compatibility (ref, version)
local det = version_not_compatible_p(ref, version);
if det then
croak(det);
end
end
local function tracking_cat_for_version (version)
local it;
if version then
it = '';
-- Create tracking category, genericizing (de-Protestantizing) the term for "Greek NT"
local version_label = describe_version(version, true);
version_label = mw.ustring.gsub(version_label, '新約希臘文聖經', '新約原文版本'); -- rm Lo et al. (2003) transl.
version_label = mw.ustring.gsub(version_label, '希臘文新約', '新約原文版本'); -- rm my own transl.
it = it .. '引聖經指定用';
it = it .. describe_tradition_genitive(versions[version].tradition);
if version_label:match(' ') then
it = it .. ' ';
end
it = it .. version_label .. '嘅文';
end
return it;
end
local function tracking_cat_for_unknown_version (version)
local it;
if version then
it = cat_specific_unknown_version_prefix;
local version_label = describe_version(version, true);
if version_label:match(' ') then
it = it .. ' ';
end
it = it .. version_label .. cat_specific_unknown_version_suffix;
end
return it;
end
local function construct_formatted_reference (s, flags)
local it;
local ref;
ref = parse_reference(s);
if ref then
local book = books[ref.book];
local preferred_name, full_name, tradition;
local require_embedding_p = stems[ref.chapter];
local candidate_traditions;
local prioritize_catholicism_p = false;
if ref.version and versions[ref.version] and versions[ref.version].tradition then
prioritize_catholicism_p = versions[ref.version].tradition == 'catholic';
end
if require_embedding_p then
candidate_traditions = {'catholic', 'orthodox'};
elseif prioritize_catholicism_p then
candidate_traditions = {'catholic', 'protestant', 'orthodox', 'judaism'};
else
candidate_traditions = {'protestant', 'catholic', 'orthodox', 'judaism'};
end
it = '';
for _, candidate_tradition in pairs(candidate_traditions) do
if book_exists_in_tradition(ref.book, candidate_tradition) then
tradition = candidate_tradition;
preferred_name = find_book_name(ref.book, tradition, {'singular', 'preferred'});
full_name = find_book_name(ref.book, tradition, 'full');
end
if full_name then break end;
end
-- quick check to see if the citation is clearly impossible
if book.parts then
local tmp = {};
for i = 1, #(book.parts) do
table.insert(tmp, { ['id'] = book.parts[i], ['naming'] = tradition });
end
croak('「' .. preferred_name .. '」 喺' .. traditions[tradition] .. '概念上係一卷書,但係實際引用嗰陣,要指明係' .. describe_ambiguity(tmp, '定係', false));
elseif require_embedding_p and (not book.embeds or not book.embeds[ref.chapter]) then
croak('' .. preferred_name .. '似乎冇 「補錄' .. stems[ref.chapter] .. '」');
end
-- emit the reference, without any external links
it = '[[' .. full_name .. '|' .. build_citable(nil, preferred_name) .. ']]';
it = it .. format_numbering(ref, nil, nil);
-- figure out usable versions then emit them with corresponding links
local specifics = {};
local seealso = {};
if ref.version then
local v;
if versions[ref.version] then -- known translation
assert_compatibility(ref, ref.version);
v = format_numbering(ref, versions[ref.version].tradition, ref.version);
it = it .. '[[Category:' .. tracking_cat_for_version(ref.version) .. ']]';
else -- unknown translation
it = it .. '[[Category:' .. cat_all_unknown_versions .. ']]';
it = it .. '[[Category:' .. tracking_cat_for_unknown_version(ref.version) .. ']]';
v = format_numbering(ref, 'protestant', ref.version);
end
table.insert(specifics, v);
end
for _, candidate_tradition in pairs({'protestant', 'catholic'}) do
if numbering[candidate_tradition] then
local candidate_version = numbering[candidate_tradition].default;
if candidate_version ~= ref.version
and book[candidate_tradition]
and (not require_embedding_p or versions[candidate_version].has_embeds_p) then
local v = format_numbering(ref, candidate_tradition, nil);
assert_compatibility(ref, numbering[candidate_tradition].default);
table.insert(seealso, v);
end
end
end
if #specifics > 0 then
it = it .. '(' .. table.concat(specifics, '、');
if not flags or not flags.no_seealso_p then
it = it .. ';可以睇埋:' .. table.concat(seealso, '、');
end
it = it .. ')';
else
it = it .. '(' .. table.concat(seealso, '、') .. ')';
end
else
croak('唔明 「' .. s .. '」 係指乜');
end
return it;
end
--- Exported, invocable functions ---------------------------------------------
-- Entry point for template
p.cite2 = function( frame )
return p.cite(frame:getParent());
end
-- Entry point for direct #invoke
p.cite = function( frame )
local it;
local styles = '模組:Citation/CS1/styles.css';
local postscript = '.';
local ref = {};
local flags = {};
-- Make an attempt to emulate :en:Bibleverse
-- The # operator doesn't work on frame.args so we need a second pass
-- We also need to ignore empty positionals so one pass won't work
local ignore_positional_parameters_p;
if true then
local n = 0;
local non_empty_positionals = {};
for k, v in pairs(frame.args) do
if type(k) == 'number' then
local v = fix_argument(frame.args[k]);
if #v > 0 then
table.insert(non_empty_positionals, v);
n = n + 1;
end
end
end
if n > 3 then
croak('太多唔畀名嘅參數');
elseif n > 1 then
local i = 1;
ref.book = fix_argument(non_empty_positionals[1]);
ref.numbers = fix_argument(non_empty_positionals[2]);
ignore_positional_parameters_p = true;
if n == 3 then
ref.version = fix_argument(non_empty_positionals[3]);
end
end
end
local parts = {};
it = ''
for k, v in pairs(frame.args) do
v = fix_argument(v);
if type(k) == 'number' then
if not ignore_positional_parameters_p then
for k, v in pairs(parse_reference(v)) do
ref[k] = v;
end
end
elseif k == 'book' or k == 'book-title' or k == 'title' then
ref.book = v;
elseif k == 'at' then
if ref.chapter then
croak('遇到 「' .. k .. '」 參到,但係已經用咗唔兼容嘅 「chapter」 參數');
elseif ref.verses then
croak('遇到 「' .. k .. '」 參到,但係已經用咗唔兼容嘅 「verse」 或者 「verses」 參數');
elseif ref.numbers then
croak('之前已經寫咗喺 「' .. ref.numbers .. '」');
end
ref.numbers = v;
elseif k == 'chapter' then
if ref.numbers then
croak('遇到 「' .. k .. '」 參到,但係已經用咗唔兼容嘅 「at」 參數');
elseif ref.chapter then
croak('之前已經寫咗係第 「' .. ref.chapter .. '」 章');
end
ref.chapter = v;
elseif k == 'postscript' then
if v == 'none' then
postscript = '';
else
postscript = v;
end
elseif k == 'seealso' then
if v == 'yes' then
flags.no_seealso_p = false;
elseif v == 'no' then
flags.no_seealso_p = true;
else
croak('「' .. v .. '」 並唔係 「' .. k .. '」 參數嘅有效值');
end
elseif k == 'verse' or k == 'verses' then
if ref.numbers then
croak('遇到 「' .. k .. '」 參到,但係已經用咗唔兼容嘅 「at」 參數');
elseif ref.verses then
croak('之前已經寫咗係第 「' .. ref.verses .. '」 節');
end
ref.verses = v;
elseif k == 'version' then
if ref.version then
croak('之前已經寫咗版本係 「' .. ref.version .. '」');
end
ref.version = v;
else
croak('引聖經模遇到不明參數 「' .. k .. '」');
end
end
if ref.version then
ref.version = canonicalize_version(ref.version);
end
if #parts == 0 then
if ref.book then
table.insert(parts, construct_formatted_reference(ref, flags));
else
croak('冇畀書卷名');
end
end
if #parts == 0 then
croak('搵唔到引乜嘢');
end
-- build it
it = table.concat(parts, ';');
it = it .. postscript;
-- request our style sheet
it = table.concat ({
frame:extensionTag ('templatestyles', '', {src=styles}),
it
});
return it;
end
-- Code dump for documentation page
p.dump_codes = function( frame )
-- pairs() gives random order, so stash the results in an array first
local result = {};
for id, book in pairs(books) do
local id_sort = id:gsub('^x%-', ''):gsub('^(%d+)(.*)', '%2%1');
local it = '';
it = it .. "|-\n";
it = it .. "|&TK;\n";
if id:match('^x%-') then
it = it .. '|data-sort-value="' .. id_sort .. '"|\n';
else
it = it .. '|data-sort-value="' .. id_sort .. '"| ' .. id .. "\n";
end
for _, k in pairs({'protestant', 'catholic', 'orthodox', 'english'}) do
if book[k] then
local book_name = find_book_name(id, k, 'preferred');
local sort_key = mw.ustring.gsub(book_name, '^(%d+)(.*)', '%2%1');
it = it .. '|data-sort-value="' .. sort_key .. '"|' .. book_name .. "\n";
else
it = it .. "|\n";
end
end
table.insert(result, {book.order, it});
end
-- sort the results before we dump it out
table.sort(result, function( a, b ) return a[1] < b[1] end);
local it = '{| class="wikitable sortable"\n';
it = it .. '!data-sort-type="number"|順序 !!代碼 !! 基督教名 !! 天主教名 !! 東正教名 !! 英文名\n';
for i = 1, #result do
it = it .. mw.ustring.gsub(result[i][2], '&TK;', i);
end
it = it .. "|}";
return it;
end
-- Version dump for documentation page
p.dump_versions = function( frame )
local it;
local order = {};
local conjunction = frame.args['conjunction'] or '同';
-- pass 1
for id, spec in pairs(versions) do
table.insert(order, id);
end
if #order > 0 then
table.sort(order);
-- pass 2
it = '';
for i = 1, #order do
local id = order[i];
local label = id;
local stag = '';
local etag = '';
if versions[id].link then
stag = '[[' .. versions[id].link .. '|';
etag = ']]';
end
if versions[id].names then
label = label .. '(' .. stag .. versions[id].names[1] .. etag .. ')';
else
label = stag .. label .. etag;
end
if i == #order then
it = it .. ' ' .. conjunction .. ' ';
elseif i > 1 then
it = it .. '、';
end
it = it .. label;
end
end
return it;
end
-- Tracking category dump for documentation page
-- WARNING: This is "expensive" (according to reference manual) so it can cause crashes
p.dump_tracking_cats = function( frame )
local it = '';
-- pass 1, stash into temporary hash because some versions generate duplicate tracking cats
local tmp_cats = {};
for id, spec in pairs(versions) do
local cat = tracking_cat_for_version(id);
if not cat then -- id defined but no cat returned, should not happen
error('Internal error: No tracking cat for id="' .. id .. '"');
else
tmp_cats[frame:expandTemplate{ title = 'clc', args = { cat } }] = true;
end
end
tmp_cats[frame:expandTemplate{ title = 'clc', args = { cat_all_unknown_versions } }] = true;
-- pass 2, convert the hash into a normal array
local cats = {};
for k, v in pairs(tmp_cats) do
table.insert(cats, k);
end
-- pass 3, sort the array and print it out
table.sort(cats, function (a, b)
local it;
local det_a = a:match('.-%((%d+)%)');
local det_b = b:match('.-%((%d+)%)');
if det_a and det_b then
det_a = tonumber(det_a);
det_b = tonumber(det_b);
if det_a ~= det_b then
it = det_a > det_b; -- reverse numeric
end
end
if it == nil then
it = a < b;
end
return it;
end);
for i = 1, #cats do
if #it > 0 then
it = it .. "\n";
end
it = it .. '*' .. cats[i];
end
return it;
end
-- Book listing function for actual articles
p.list_books = function( frame )
local it;
local id = frame.args[1] or frame.args.version;
if not id then
croak('冇畀參數,唔知要列乜出來');
elseif not versions[id] then
croak('唔知 「' .. id .. '」 係乜嘢譯本嘅代碼');
else
local version = versions[id];
local parts = version.parts;
local abbreviations_exist_p = false;
for pass = 1, 2 do
if pass == 2 then
it = '{| class="wikitable sortable"\n';
it = it .. '!data-sort-type="number"|順序\n';
it = it .. "!" .. languages[version.tradition] .. "卷名\n";
if abbreviations_exist_p then
it = it .. "!縮寫\n";
end
if version.number_of_chapters then
it = it .. '!data-sort-type="number"|章數\n';
end
if languages[version.tradition] ~= '英文' then
it = it .. "!英文卷名對照\n";
end
end
local n = 1;
for i = 1, #parts do
for j = 1, #(parts[i].books) do
local id = parts[i].books[j];
local abbreviation = find_abbreviation(id, version.tradition, nil, true, false);
if pass == 1 then
if abbreviation then
abbreviations_exist_p = true;
end
else
it = it .. "|-\n";
it = it .. '| ' .. n .. "\n";
local book_name = find_book_name(id, version.tradition, nil);
local link_target = find_book_name(id, version.tradition, 'full');
if books[id].protestant then
link_target = find_book_name(id, 'protestant');
end
it = it .. '| [[' .. link_target .. '|' .. book_name .. "]]\n";
if abbreviations_exist_p then
it = it .. '| ' .. (abbreviation or '') .. "\n";
end
if version.number_of_chapters then
local m = version.number_of_chapters[id];
if m then
it = it .. '| ' .. m .. "\n";
else
it = it .. "|\n";
end
end
if languages[version.tradition] ~= '英文' then
local english_name = find_book_name(id, 'english');
local english_sort_key = mw.ustring.gsub(english_name, '^(%d+)(.*)', '%2%1');
it = it .. '|data-sort-value="' .. english_sort_key .. '"|' .. english_name .. "\n";
end
n = n + 1;
end
end
end
if pass == 2 then
it = it .. "|}";
end
end
end
return it;
end
--- Test cases ----------------------------------------------------------------
--
-- Unfortunately this module was not written the correct way (SE-wise);
-- viz. tests were not written first, so a lot of test cases are missing
p.test = function ()
-- test case for crash observed 2023-02-24
local Gn_6_4 = {
['book'] = 'Gn';
['chapter'] = '6';
['verses'] = '4';
};
local det = format_numbering(Gn_6_4, 'judaism', 'JPS');
assert(mw.ustring.match(det, 'JPS')); -- Make sure it does not crash
assert(mw.ustring.match(det, 'G')); -- JPS is an English translation
assert(not mw.ustring.match(det, '〈'));
assert(mw.ustring.match(det, ' '));
assert(mw.ustring.match(det, 'pt0106%.htm'));
-- test case for unrecognized book observed 2023-04-09
assert(version_has_book_p('JPS', '1Kg'));
assert(version_has_book_p('JPS', '2Kg'));
assert(version_has_book_p('JPS', '1Ch'));
assert(version_has_book_p('JPS', '2Ch'));
assert(version_has_book_p('JPS', 'Ezr'));
assert(version_has_book_p('JPS', 'Neh'));
assert_canonical_book_code('1Kg');
local I_Kg_17 = {
['book'] = '1Kg';
['chapter'] = '17';
['version'] = 'JPS';
};
assert(construct_formatted_reference(I_Kg_17));
-- test case for en dash in bibleverse emulation mode, observed 2025-03-02
local a, b = pcall(p.cite2, {
-- template call
['getParent'] = function ()
return {
extensionTag = function () return '' end;
args= { 'Mt', '3:13–17' }; -- en dash
};
end;
-- direct #invoke
extensionTag = function () return '' end;
args = {
};
});
assert(a and b:match('13%-17'));
-- test case for empty argument in bibleverse emulation mode (ignored in real bibleverse), observed 2025-04-01
local a, b = pcall(p.cite2, {
-- template call
['getParent'] = function ()
return {
extensionTag = function () return '' end;
args= { '', 'Mt', '3:13-17' }; -- empty first argument
};
end;
-- direct #invoke
extensionTag = function () return '' end;
args = {
};
});
assert(a and b:match('13%-17'));
-- test case for lowercase version ID in bibleverse emulation mode, observed 2025-04-01
local a, b = pcall(p.cite2, {
-- template call
['getParent'] = function ()
return {
extensionTag = function () return '' end;
args= {'Mt', '3:13-17', 'nab'}; -- lowercase third argument
};
end;
-- direct #invoke
extensionTag = function () return '' end;
args = {
};
});
assert(a and not b:match('不明譯本'));
-- test case for MT version crashing with an undefined variable error, observed 2025-04-02
local a, b = pcall(p.cite2, {
-- template call
['getParent'] = function ()
return {
extensionTag = function () return '' end;
args= {'Gen', '1:1', 'MT'}; -- lowercase third argument
};
end;
-- direct #invoke
extensionTag = function () return '' end;
args = {
};
});
assert(a and not b:match('不明譯本'));
end
--- Non-invocable internal functions exported for other modules to use --------
return p;