用於標註一堆振假名。
用法
{{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人|ひとり}}でも大丈夫(だいじょうぶ)だからただ前(まえ)を見(み)て}}}}
結果:
從其他注音模板轉換為本模板
一個工具模塊Furigana/utils的transform
函數可用於轉換原始碼,使用時請替換引用(即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人|ひとり}} }}
模塊測試結果(開發者用)
展開結果 |
---|
|
注釋
- local p = {}
- -- 轉化為upvalue,提升速度
- local type = type
- local ipairs = ipairs
- local concat = table.concat
- local u_gsub = mw.ustring.gsub
- local u_sub = mw.ustring.sub
- local KANJI_LIKE_UNICODE_RANGES = {
- { 0x2E80, 0x2EFF }, -- CJK部首補充
- { 0x3005, 0x3007 }, -- "々、〆、〇"
- { 0x31C0, 0x31EF }, -- CJK筆畫
- { 0x3400, 0x4DBF }, -- CJK統一表意文字擴展A
- { 0x4E00, 0x9FFF }, -- CJK統一表意文字
- { 0xF900, 0xFAFF }, -- CJK兼容表意文字
- { 0x20000, 0x2A6DF }, -- CJK統一表意文字擴展B
- { 0x2A700, 0x2EE5F }, -- CJK統一表意文字擴展C-I
- { 0x2F800, 0x2FA1F }, -- CJK兼容表意文字補充
- { 0x30000, 0x323AF }, -- CJK統一表意文字擴展G-H
- }
- local KANJI_LIKE_PATTERN = (function ()
- local char = mw.ustring.char
- local parts = {}
- for i, range in ipairs(KANJI_LIKE_UNICODE_RANGES) do
- parts[i] = type(range) == 'table' and char(range[1])..'-'..char(range[2]) or char(range)
- end
- return '['..concat(parts)..']'
- end)()
- --[[
- 把<tag>、</tag>與其他文本分開。
- ```lua
- divide_tags_and_non_tags('A<span title="(title)">B</span>C')
- -->
- {
- { type = 'unknown', content = 'A' },
- { type = 'tag', content = '<span title="(title)">' },
- { type = 'unknown', content = 'B' },
- { type = 'tag', content = '</span>' },
- { type = 'unknown', content = 'C' },
- ```
- ]]
- ---@param text string
- ---@return {type: 'tag' | 'unkown', content: string}[]
- local function extract_tags(text)
- local result = {}
- local rest = text
- :gsub(
- '(.-)(</?[:%a_][:%w_-.]*[^<>]*>)',
- function (non_tag, tag)
- if non_tag ~= '' then
- result[#result+1] = { type = 'unknown', content = non_tag }
- end
- result[#result+1] = { type = 'tag', content = tag }
- return ''
- end
- )
- if rest ~= '' then
- result[#result+1] = { type = 'unknown', content = rest }
- end
- return result
- end
- local EXTRACT_RB_RT_PATTERN = '(.-)('..KANJI_LIKE_PATTERN..'+)(%b())'
- ---@param text string
- ---@param into_tokens ({type: 'ruby-part' | 'tag' | 'text', content: string} | {type: 'rb-rt', rb: string, rt: string})[]
- local function extract_rb_rt(text, into_tokens)
- for line_with_lf in text:gmatch('[^\n]*\n*') do
- local rest = u_gsub(
- line_with_lf,
- EXTRACT_RB_RT_PATTERN,
- function (before, rb, rt)
- if before ~= '' then
- into_tokens[#into_tokens+1] = { type = 'text', content = before }
- end
- into_tokens[#into_tokens+1] = {
- type = 'rb-rt',
- rb = rb,
- rt = u_sub(rt, 2, -2), -- 去除括號
- }
- return ''
- end
- )
- if rest ~= '' then
- into_tokens[#into_tokens+1] = { type = 'text', content = rest }
- end
- end
- end
- ---細節見測試 [[Module:Furigana/tests]]。
- ---@param tokens {type: 'tag' | 'unkown', content: string}[]
- ---@param into_tokens ({type: 'ruby-part' | 'tag' | 'text', content: string} | {type: 'rb-rt', rb: string, rt: string})[]
- local function extract_others(tokens, into_tokens)
- local ruby_start_index = nil
- for i, token in ipairs(tokens) do
- if ruby_start_index then -- 如果處於<ruby>標籤內,則所有token都是ruby-part
- into_tokens[#into_tokens+1] = { type = 'ruby-part', content = token.content }
- if token.type == 'tag' and token.content:match('^</[Rr][Uu][Bb][Yy]') then
- ruby_start_index = nil
- end
- elseif token.type == 'tag' then
- if token.content:match('^<[Rr][Uu][Bb][Yy]') then
- into_tokens[#into_tokens+1] = { type = 'ruby-part', content = token.content }
- ruby_start_index = i
- else
- ---@diagnostic disable-next-line: assign-type-mismatch
- into_tokens[#into_tokens+1] = token
- end
- else
- -- assert(token.type == 'unknown')
- extract_rb_rt(token.content, into_tokens)
- end
- end
- end
- ---將`texts`解析為tokens,細節見測試[[Module:Furigana/tests]]。
- ---@param texts string[]
- ---@return ({type: 'ruby-part' | 'tag' | 'text', content: string} | {type: 'rb-rt', rb: string, rt: string})[]
- local function parse(texts)
- local tokens = {}
- for _, text in ipairs(texts) do
- extract_others(extract_tags(text), tokens)
- end
- return tokens
- end
- p.parse = parse
- ---用`render_ruby`渲染`tokens`中的`rb-rt` token,其餘token不變,最終連接為一個字符串。
- ---@param tokens ({type: 'ruby-part' | 'tag' | 'text', content: string} | {type: 'rb-rt', rb: string, rt: string})[]
- ---@param render_ruby fun(rb: string, rt: string): string
- ---@return string
- local function render(tokens, render_ruby)
- local result = {}
- for i, token in ipairs(tokens) do
- result[i] = token.type == 'rb-rt' and render_ruby(token.rb, token.rt) or token.content
- end
- return concat(result)
- end
- p.render = render
- ---將`texts`中用“漢字(注音)”表示的振假名替換為`render_ruby`的返回值。
- ---@param texts string | string[]
- ---@param render_ruby fun(rb: string, rt: string): string
- ---@return string
- function p.process(texts, render_ruby)
- if type(texts) == 'string' then
- texts = { texts }
- end
- local tokens = parse(texts)
- return render(tokens, render_ruby)
- end
- function p.main(frame, args)
- if not args then
- local parent = frame:getParent()
- local templates = { ['Template:振假名'] = true, ['Template:Sandbox'] = true }
- if parent and templates[parent:getTitle()] then
- frame = parent
- end
- args = frame.args
- end
- local template = args.template or 'Ruby'
- if mw.isSubsting() then
- local prefix = '{{'..template..'|'
- return p.process(args, function (rb, rt)
- return prefix..rb..'|'..rt..'}}'
- end)
- end
- local is_compatible_mode = args.compatible and args.compatible ~= ''
- if not is_compatible_mode then
- -- 快速模式,通過字符串替換,避免多次調用frame:expandTemplate
- local placeholder_pattern = '!@$r[bt]$@!'
- local rb_placeholder = '!@$rb$@!'
- local rt_placeholder = '!@$rt$@!'
- local template_string = frame:expandTemplate {
- title = template,
- args = { rb_placeholder, rt_placeholder },
- }
- if template_string:find(placeholder_pattern) then
- return p.process(args, function (rb, rt)
- return template_string:gsub(placeholder_pattern, { [rb_placeholder] = rb, [rt_placeholder] = rt })
- end)
- end
- end
- return p.process(args, function (rb, rt)
- return frame:expandTemplate {
- title = template,
- args = { rb, rt },
- }
- end)
- end
- return p