模組:Furigana

萌娘百科,萬物皆可萌的百科全書!轉載請標註來源頁面的網頁連結,並聲明引自萌娘百科。內容不可商用。
貢獻者:
Template-info.svg 模塊文檔  [查看] [] [歷史] [刷新]
Icon-info.png

本模板可以被替換引用(使用{{subst:振假名|…}}

為保持代碼整潔,請勿輕易替換引用。

用於標註一堆振假名。

用法

{{Photrans/button}}
{{LyricsKai
|original=
{{振假名|template=Photrans
|きらり空(そら)に響(ひび)く星(ほし)の聲(こえ)
ああ海(うみ)を照(て)らす 光(ひかり)を辿(たど)れたら
流(なが)れた星(ほし)はどこへ行(ゆ)く?
きっと何(なに)かがそこで待(ま)ってる
旗(はた)を掲(かか)げ進(すす)もう
いつでも月(つき)は歌(うた)い 旅人(たびびと)を導(みちび)いて
「もう迷(まよ)わなくていいから」
}}
|translated= <!-- 略 -->
}}

與下面這段代碼效果相同。

{{Photrans/button}}
{{LyricsKai
|original=
きらり{{Photrans|空|そら}}に{{Photrans|響|ひび}}く{{Photrans|星|ほし}}の{{Photrans|聲|こえ}}
ああ{{Photrans|海|うみ}}を{{Photrans|照|て}}らす {{Photrans|光|ひかり}}を{{Photrans|辿|たど}}れたら
{{Photrans|流|なが}}れた{{Photrans|星|ほし}}はどこへ{{Photrans|行|ゆ}}く?
きっと{{Photrans|何|なに}}かがそこで{{Photrans|待|ま}}ってる
{{Photrans|旗|はた}}を{{Photrans|掲|かか}}げ{{Photrans|進|すす}}もう
いつでも{{Photrans|月|つき}}は{{Photrans|歌|うた}}い {{Photrans|旅人|たびびと}}を{{Photrans|導|みちび}}いて
「もう{{Photrans|迷|まよ}}わなくていいから」
|translated= <!-- 略 -->
}}

效果:

[關閉注音]
本段落中所使用的歌詞,其著作權屬於原著作權人,僅以介紹為目的引用。
きらりそらひびほしこえ
亮晶晶 天空中迴響著 星星的聲音
ああうみらす ひかり辿たどれたら
啊 追著照亮海面的光束
ながれたほしはどこへく?
流星將去向何處
きっとなにかがそこでってる
在那兒一定有什麼在等著
はたかかすすもう
揚起旗幟前進吧
いつでもつきうたい 旅人たびびとみちびいて
無論何時 月兒在歌唱 為旅人指著路
「もうまよわなくていいから」
所以不會再迷路了

參數

  • 匿名參數:需要轉換振假名的內容,可以傳入多個參數。形如漢字[1](かんじ)的將被轉換為{{template|漢字|かんじ}},注意是全角括號。
  • template:振假名所用模板名,默認值為Ruby
  • compatible:為非空值時啟用兼容模式。僅當不啟用兼容模式會出問題時才應啟用兼容模式。

模板不自帶語言屬性,請確保本模板外部標註了語言,例如,{{LyricsKai}}左欄默認標註了lang="ja"

連續漢字只標註一部分

用管道符隔開即可:

{{lj|{{振假名|……由崎|星空(ナサ)……}}}}

結果:……由崎星空ナサ……

對比不隔開的效果:

{{lj|{{振假名|……由崎星空(ナサ)……}}}}

結果:……由崎星空ナサ……

漢字後的括號不是注音

要使漢字後的括號出現在正文中,使用管道符將漢字與括號隔開即可:

{{lj|{{振假名|世紀の覚醒|(2度寢ー3度寢ー)}}}}

結果:世紀の覚醒(2度寢ー3度寢ー)

想要注音的文字不是漢字

本模板內可以正常用其他注音模板:

{{lj|{{振假名|{{ruby|1人|ひとり}}でも大丈夫(だいじょうぶ)だからただ前(まえ)を見(み)て}}}}

結果:1人ひとりでも大丈夫だいじょうぶだからただまえ

從其他注音模板轉換為本模板

一個工具模塊Furigana/utilstransform函數可用於轉換原始碼,使用時請替換引用(即subst:)。它將自動識別所使用的注音模板(限{{Ruby}}、{{Photrans}}、{{Photrans2}}和{{Photransa}}),並選擇出現次數最多的作為template參數[2],未被選中的會保留原樣

{{LyricsKai
|original=
{{subst:#invoke:Furigana/utils|transform|
きらり{{Photrans|空|そら}}に{{Photrans|響|ひび}}く{{Photrans|星|ほし}}の{{Photrans|聲|こえ}}
ああ{{Photrans|海|うみ}}を{{Photrans|照|て}}らす {{Photrans|光|ひかり}}を{{Photrans|辿|たど}}れたら
{{Photrans|流|なが}}れた{{Photrans|星|ほし}}はどこへ{{ruby|行|ゆ}}く?
きっと{{Photrans|何|なに}}かがそこで{{Photrans|待|ま}}ってる
{{Photrans|旗|はた}}を{{Photrans|掲|かか}}げ{{Photrans|進|すす}}もう
いつでも{{Photrans|月|つき}}は{{Photrans|歌|うた}}い {{Photrans|旅人|たびびと}}を{{Photrans|導|みちび}}いて
「もう{{Photrans|迷|まよ}}わなくていいから」
}}
|translated= <!-- 略 -->
}}

保存後代碼將變為:

{{LyricsKai
|original=
{{振假名|template=Photrans
|きらり空(そら)に響(ひび)く星(ほし)の聲(こえ)
ああ海(うみ)を照(て)らす 光(ひかり)を辿(たど)れたら
流(なが)れた星(ほし)はどこへ{{ruby|行|ゆ}}く?
きっと何(なに)かがそこで待(ま)ってる
旗(はた)を掲(かか)げ進(すす)もう
いつでも月(つき)は歌(うた)い 旅人(たびびと)を導(みちび)いて
「もう迷(まよ)わなくていいから」
}}
|translated= <!-- 略 -->
}}

該轉換模塊同樣支持通過template手動指定注音模板,不限於上面幾個自動識別的模板。

注意,如果原始代碼中,某個注音模板符合以下情況之一:

  • 包含超過2個參數;
  • 包含換行;
  • 包含等號;
  • 參數1不全是漢字[1]
  • 嵌套了模板。

則該注音模板將保留原樣。例如:

{{subst:#invoke:Furigana/utils|transform|
きらり{{ruby|空|そら}}{{ruby|響|ひび|ja}}{{ruby|星|ほ
し}}{{ruby|聲|{{黑幕|こえ}}}}

{{ruby|1人|ひとり}}
}}

保存後代碼將變為:

{{振假名
|きらり空(そら){{ruby|響|ひび|ja}}{{ruby|星|ほ
し}}{{ruby|聲|{{黑幕|こえ}}}}

{{ruby|1人|ひとり}}
}}

模塊測試結果(開發者用)

展開結果
  • 通過】測試1:將「漢字(注音)」(漢字可能是多個字符)解析為{ type = 'rb-rt', rb = '漢字', rt = '注音' },其餘部分解析為{ type = '...', content = '...' }

  • 通過】測試2:能夠解析連續「漢字(注音)」

  • 通過】測試3:某處「漢字(注音)」的括號不成對時,不影響同一行後續的解析

  • 通過】測試4:每行單獨統計成對的括號。括號內容跨行時,不視為rt,上一行的左括號不會作為下一行括號閉合的依據

  • 通過】測試5:「非漢字(括號內的內容)」視為普通文本

  • 通過】測試6:嵌套括號

  • 通過】測試7:HTML標籤屬性中的括號不會被視為rt

  • 通過】測試8:存在<ruby>元素時,該元素的內容不會被解析為rb-rt,即使它包含括號

  • 通過】測試9:換行不會影響對<ruby>元素的判斷

  • 通過】測試10:傳入多個字符串時,前一個字符串尾部與後一個字符串頭部的漢字不會被當成一個整體

注釋

  1. 移至: 1.0 1.1 以及「」「」。
  2. 移至 由於Ruby是默認值,所以將會省略。
  1. local p = {}
  2. -- 轉化為upvalue,提升速度
  3. local type = type
  4. local ipairs = ipairs
  5. local concat = table.concat
  6. local u_gsub = mw.ustring.gsub
  7. local u_sub = mw.ustring.sub
  8. local KANJI_LIKE_UNICODE_RANGES = {
  9. { 0x2E80, 0x2EFF }, -- CJK部首補充
  10. { 0x3005, 0x3007 }, -- "々、〆、〇"
  11. { 0x31C0, 0x31EF }, -- CJK筆畫
  12. { 0x3400, 0x4DBF }, -- CJK統一表意文字擴展A
  13. { 0x4E00, 0x9FFF }, -- CJK統一表意文字
  14. { 0xF900, 0xFAFF }, -- CJK兼容表意文字
  15. { 0x20000, 0x2A6DF }, -- CJK統一表意文字擴展B
  16. { 0x2A700, 0x2EE5F }, -- CJK統一表意文字擴展C-I
  17. { 0x2F800, 0x2FA1F }, -- CJK兼容表意文字補充
  18. { 0x30000, 0x323AF }, -- CJK統一表意文字擴展G-H
  19. }
  20. local KANJI_LIKE_PATTERN = (function ()
  21. local char = mw.ustring.char
  22. local parts = {}
  23. for i, range in ipairs(KANJI_LIKE_UNICODE_RANGES) do
  24. parts[i] = type(range) == 'table' and char(range[1])..'-'..char(range[2]) or char(range)
  25. end
  26. return '['..concat(parts)..']'
  27. end)()
  28. --[[
  29. 把<tag>、</tag>與其他文本分開。
  30. ```lua
  31. divide_tags_and_non_tags('A<span title="(title)">B</span>C')
  32. -->
  33. {
  34. { type = 'unknown', content = 'A' },
  35. { type = 'tag', content = '<span title="(title)">' },
  36. { type = 'unknown', content = 'B' },
  37. { type = 'tag', content = '</span>' },
  38. { type = 'unknown', content = 'C' },
  39. ```
  40. ]]
  41. ---@param text string
  42. ---@return {type: 'tag' | 'unkown', content: string}[]
  43. local function extract_tags(text)
  44. local result = {}
  45. local rest = text
  46. :gsub(
  47. '(.-)(</?[:%a_][:%w_-.]*[^<>]*>)',
  48. function (non_tag, tag)
  49. if non_tag ~= '' then
  50. result[#result+1] = { type = 'unknown', content = non_tag }
  51. end
  52. result[#result+1] = { type = 'tag', content = tag }
  53. return ''
  54. end
  55. )
  56. if rest ~= '' then
  57. result[#result+1] = { type = 'unknown', content = rest }
  58. end
  59. return result
  60. end
  61. local EXTRACT_RB_RT_PATTERN = '(.-)('..KANJI_LIKE_PATTERN..'+)(%b())'
  62. ---@param text string
  63. ---@param into_tokens ({type: 'ruby-part' | 'tag' | 'text', content: string} | {type: 'rb-rt', rb: string, rt: string})[]
  64. local function extract_rb_rt(text, into_tokens)
  65. for line_with_lf in text:gmatch('[^\n]*\n*') do
  66. local rest = u_gsub(
  67. line_with_lf,
  68. EXTRACT_RB_RT_PATTERN,
  69. function (before, rb, rt)
  70. if before ~= '' then
  71. into_tokens[#into_tokens+1] = { type = 'text', content = before }
  72. end
  73. into_tokens[#into_tokens+1] = {
  74. type = 'rb-rt',
  75. rb = rb,
  76. rt = u_sub(rt, 2, -2), -- 去除括號
  77. }
  78. return ''
  79. end
  80. )
  81. if rest ~= '' then
  82. into_tokens[#into_tokens+1] = { type = 'text', content = rest }
  83. end
  84. end
  85. end
  86. ---細節見測試 [[Module:Furigana/tests]]。
  87. ---@param tokens {type: 'tag' | 'unkown', content: string}[]
  88. ---@param into_tokens ({type: 'ruby-part' | 'tag' | 'text', content: string} | {type: 'rb-rt', rb: string, rt: string})[]
  89. local function extract_others(tokens, into_tokens)
  90. local ruby_start_index = nil
  91. for i, token in ipairs(tokens) do
  92. if ruby_start_index then -- 如果處於<ruby>標籤內,則所有token都是ruby-part
  93. into_tokens[#into_tokens+1] = { type = 'ruby-part', content = token.content }
  94. if token.type == 'tag' and token.content:match('^</[Rr][Uu][Bb][Yy]') then
  95. ruby_start_index = nil
  96. end
  97. elseif token.type == 'tag' then
  98. if token.content:match('^<[Rr][Uu][Bb][Yy]') then
  99. into_tokens[#into_tokens+1] = { type = 'ruby-part', content = token.content }
  100. ruby_start_index = i
  101. else
  102. ---@diagnostic disable-next-line: assign-type-mismatch
  103. into_tokens[#into_tokens+1] = token
  104. end
  105. else
  106. -- assert(token.type == 'unknown')
  107. extract_rb_rt(token.content, into_tokens)
  108. end
  109. end
  110. end
  111. ---將`texts`解析為tokens,細節見測試[[Module:Furigana/tests]]。
  112. ---@param texts string[]
  113. ---@return ({type: 'ruby-part' | 'tag' | 'text', content: string} | {type: 'rb-rt', rb: string, rt: string})[]
  114. local function parse(texts)
  115. local tokens = {}
  116. for _, text in ipairs(texts) do
  117. extract_others(extract_tags(text), tokens)
  118. end
  119. return tokens
  120. end
  121. p.parse = parse
  122. ---用`render_ruby`渲染`tokens`中的`rb-rt` token,其餘token不變,最終連接為一個字符串。
  123. ---@param tokens ({type: 'ruby-part' | 'tag' | 'text', content: string} | {type: 'rb-rt', rb: string, rt: string})[]
  124. ---@param render_ruby fun(rb: string, rt: string): string
  125. ---@return string
  126. local function render(tokens, render_ruby)
  127. local result = {}
  128. for i, token in ipairs(tokens) do
  129. result[i] = token.type == 'rb-rt' and render_ruby(token.rb, token.rt) or token.content
  130. end
  131. return concat(result)
  132. end
  133. p.render = render
  134. ---將`texts`中用“漢字(注音)”表示的振假名替換為`render_ruby`的返回值。
  135. ---@param texts string | string[]
  136. ---@param render_ruby fun(rb: string, rt: string): string
  137. ---@return string
  138. function p.process(texts, render_ruby)
  139. if type(texts) == 'string' then
  140. texts = { texts }
  141. end
  142. local tokens = parse(texts)
  143. return render(tokens, render_ruby)
  144. end
  145. function p.main(frame, args)
  146. if not args then
  147. local parent = frame:getParent()
  148. local templates = { ['Template:振假名'] = true, ['Template:Sandbox'] = true }
  149. if parent and templates[parent:getTitle()] then
  150. frame = parent
  151. end
  152. args = frame.args
  153. end
  154. local template = args.template or 'Ruby'
  155. if mw.isSubsting() then
  156. local prefix = '{{'..template..'|'
  157. return p.process(args, function (rb, rt)
  158. return prefix..rb..'|'..rt..'}}'
  159. end)
  160. end
  161. local is_compatible_mode = args.compatible and args.compatible ~= ''
  162. if not is_compatible_mode then
  163. -- 快速模式,通過字符串替換,避免多次調用frame:expandTemplate
  164. local placeholder_pattern = '!@$r[bt]$@!'
  165. local rb_placeholder = '!@$rb$@!'
  166. local rt_placeholder = '!@$rt$@!'
  167. local template_string = frame:expandTemplate {
  168. title = template,
  169. args = { rb_placeholder, rt_placeholder },
  170. }
  171. if template_string:find(placeholder_pattern) then
  172. return p.process(args, function (rb, rt)
  173. return template_string:gsub(placeholder_pattern, { [rb_placeholder] = rb, [rt_placeholder] = rt })
  174. end)
  175. end
  176. end
  177. return p.process(args, function (rb, rt)
  178. return frame:expandTemplate {
  179. title = template,
  180. args = { rb, rt },
  181. }
  182. end)
  183. end
  184. return p
此頁面最後編輯於 2024年10月12日 (週六) 01:54。
搜尋萌娘百科 (按"/"快速搜尋)
有新的未讀公告

阅读更多:模塊:Furigana(http://mzh.moegirl.tw/%E6%A8%A1%E5%A1%8A%3AFurigana )
本文引自萌娘百科(http://mzh.moegirl.tw ),文字内容默认使用《知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆》协议。