xpinyin: 只显示拼音

xpinyin: 只显示拼音

我正在翻译包含大量中文名称的古文。我希望有一种方法可以让我简单地输入中文字符,以便它们自动翻译成拼音(这样就不会显示中文字符,中文字符在我的文档中以并行文本显示)。这样做的原因是它不仅可以省去很多工作(查找正确的拼音并输入),还可以避免很多意外错误。

因此,我希望使用类似 \pyc{诸葛 亮} 的命令,在输出中用“Zhūgě Liàng”替换此单词。(最好选择保留空格并将单词大写。)

xpinyin 包具有使用拼音注释汉字的所有机制,但是输出不灵活。

或者有没有其他可以做类似事情的软件包?

答案1

我想到了一个临时解决方案。主要缺点是标点符号时空格的处理。如您所见,到目前为止,示例中尚未添加任何标点符号。

在此处输入图片描述

\documentclass{article}
\usepackage{xpinyin}
\usepackage{fontspec}
\usepackage{expl3}


\ExplSyntaxOn

\tl_new:N \l_doc_tmpa_tl
\tl_new:N \l_doc_tmpb_tl
\tl_new:N \l_doc_tmpc_tl
\tl_new:N \l_doc_tmpd_tl
\tl_new:N \l_doc_tmpe_tl

\cs_set:Npn \__doc_group_helper:n #1 {
    {\exp_not:n {#1}}
}

\newcommand{\pyonly}[1]{
    \tl_set:Nn \l_doc_tmpa_tl {#1}
    \tl_clear:N \l_doc_tmpd_tl
    
    \bool_do_until:nn {\tl_if_empty_p:N \l_doc_tmpa_tl} {
        \exp_args:NV \tl_if_head_is_group:nTF \l_doc_tmpa_tl {
             \tl_set:Nx \l_doc_tmpb_tl {\tl_head:N \l_doc_tmpa_tl}
             \tl_set:Nx \l_doc_tmpa_tl {\tl_tail:N \l_doc_tmpa_tl}
             \tl_put_right:Nx \l_doc_tmpd_tl {
                \exp_args:NV \__doc_group_helper:n \l_doc_tmpb_tl
             }
        } {
             \tl_set:Nx \l_doc_tmpb_tl {\tl_head:N \l_doc_tmpa_tl}
             \tl_set:Nx \l_doc_tmpa_tl {\tl_tail:N \l_doc_tmpa_tl}
             \bool_if:nTF {
                 \bool_lazy_any_p:n {
                     {\exp_args:NV \token_if_letter_p:N \l_doc_tmpb_tl}
                     {\exp_args:NV \token_if_other_p:N \l_doc_tmpb_tl}
                 }
             } {
                 \tl_set:Nx \l_doc_tmpc_tl { \exp_args:NV \__xpinyin_to_unicode:n \l_doc_tmpb_tl }
                 \cs_if_exist:cTF { c__xpinyin_ \l_doc_tmpc_tl _tl }{
                     \tl_put_right:Nx \l_doc_tmpd_tl {\tl_use:c {c__xpinyin_ \l_doc_tmpc_tl _tl}~}
                 } {
                     \tl_put_right:NV \l_doc_tmpd_tl \l_doc_tmpb_tl
                 }
             } {
                 \tl_put_right:NV \l_doc_tmpd_tl \l_doc_tmpb_tl
             }   
        }
    }
    
    \tl_show:N \l_doc_tmpd_tl
    \tl_use:N \l_doc_tmpd_tl
}

\newcommand{\pyor}[2]{
    \pinyin{#2}~
}

\ExplSyntaxOff

\begin{document}

\par \pyonly{你好我的名字是小明}
\par \pyonly{我的读音不\pyor{一}{er4}样}

\end{document}

这个问题在 LuaTeX 中有更好的解决方案。用纯 LaTeX 实现实在是太困难了。请参阅下面的代码。要运行它,您需要下载中文转拼音并将其保存在您的工作目录中。

在此处输入图片描述

\documentclass{article}
\usepackage[fontset=fandol]{ctex}
\usepackage{luacode}
\usepackage{xcolor}
\usepackage{xparse}


\begin{luacode*}
require"chn-to-pinyin"

pinyin_vowel_v_mapping = {
    "ü", "Ü"
}

pinyin_vowel_tone_mapping = {
    ["a"] = {
        "ā", "á", "ǎ", "à"
    },
    ["e"] = {
        "ē", "é", "ě", "è"
    },
    ["i"] = {
        "ī", "í", "ǐ", "ì"
    },
    ["o"] = {
        "ō", "ó", "ǒ", "ò"
    },
    ["u"] = {
        "ū", "ú", "ǔ", "ù"
    },
    ["v"] = {
        "ǖ", "ǘ", "ǚ", "ǜ"
    },
    ["A"] = {
        "Ā", "Á", "Ǎ", "À"
    },
    ["E"] = {
        "Ē", "É", "Ě", "È"
    },
    ["I"] = {
        "Ī", "Í", "Ǐ", "Ì"
    },
    ["O"] = {
        "Ō", "Ó", "Ǒ", "Ò"
    },
    ["U"] = {
        "Ū", "Ú", "Ǔ", "Ù"
    },
    ["V"] = {
        "Ǖ", "Ǘ", "Ǚ", "Ǜ"
    }
}

pinyin_vowel_letters_lower = {"a", "e", "i", "o", "u", "v"}

pinyin_vowel_to_lower = {}
pinyin_vowel_to_upper = {}

for ind, lower in ipairs(pinyin_vowel_letters_lower) do
    local upper = lower:upper()
    local tbl1 = pinyin_vowel_tone_mapping[lower]
    local tbl2 = pinyin_vowel_tone_mapping[upper]
    assert(#tbl1 == #tbl2, "inconsistent pinyin configuration")
    for i=1,#tbl1 do
        pinyin_vowel_to_lower[tbl2[i]] = tbl1[i]
        pinyin_vowel_to_upper[tbl1[i]] = tbl2[i]
    end
end
pinyin_vowel_to_upper[pinyin_vowel_v_mapping[1]] = pinyin_vowel_v_mapping[2]
pinyin_vowel_to_lower[pinyin_vowel_v_mapping[2]] = pinyin_vowel_v_mapping[1]

pinyin_consonants = {
    "zh", "ch", "sh", "b", "p", "m", "f", "d", 
    "t", "n", "l", "g", "k", "h", "j", "q", "x", 
    "r", "z", "c", "s", "w", "y"
}

pinyin_vowels = {
    "iang", "uang", "ueng", "iong", "uai", "uei", "iao", "ian", 
    "uan", "van", "ang", "eng", "ing", "ong", "ia", "ua", "uo", 
    "ie", "ve", "ai", "ei", "ao", "ou", "iu", "an", "en", "in", 
    "un", "vn", "er", "i", "u", "v", "a", "o", "e"
}

pinyin_vowel_tone_locs = {
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
}

assert(#pinyin_vowels == #pinyin_vowel_tone_locs, "inconsistent pinyin configuration")

function find_next_consonant(s, s_lower, loc)
    local b
    for _, consonant in ipairs(pinyin_consonants) do
        b, _ = s_lower:find(consonant, loc)
        if b == loc then
            return s:sub(loc, loc + #consonant - 1)
        end
    end
    return nil
end

function find_next_vowel(s, s_lower, loc)
    local b
    for vowel_ind, vowel in ipairs(pinyin_vowels) do
        b, _ = s_lower:find(vowel, loc)
        if b == loc then
            return s:sub(loc, loc + #vowel - 1), vowel_ind
        end
    end
    return nil
end

function find_next_tone(s, s_lower, loc)
    local char = s_lower:sub(loc, loc)
    if char ~= nil and char:len() > 0 then
        local byte = char:byte()
        if byte >= 48 and byte <= 57 then
            return char
        end
    end
    return nil
end

function render_pinyin(consonant, vowel, vowel_ind, tone)
    local res = ""
    if consonant ~= nil then
        res = res .. consonant
    end
    local tone_loc = -1
    if tone ~= nil then
         tone_loc = pinyin_vowel_tone_locs[vowel_ind]
    end
    local char, tone_char
    for i=1,vowel:len() do
        char = vowel:sub(i, i)
        if i == tone_loc then
            tone_char = pinyin_vowel_tone_mapping[char][tonumber(tone)]
            assert(tone_char ~= nil, string.format("invalid tone combination: '%s', %s", vowel, tone))
            res = res .. tone_char
        else
            -- deal with "v"
            if char == "v" then
                res = res .. pinyin_vowel_v_mapping[1]
            elseif char == "V" then
                res = res .. pinyin_vowel_v_mapping[2]
            else
                res = res .. char
            end
        end
    end
    return res
end

function latin_to_pinyin(s)
    -- discard spaces
    s = s:gsub("%s", "")
    local s_lower = s:lower()
    local loc = 1
    local old_loc = loc
    local consonant, vowel, tone, vowel_ind, render
    local result = {}
    while loc <= s:len() do
        -- start by finding consonant
        consonant = find_next_consonant(s, s_lower, loc)
        if consonant ~= nil then
            loc = loc + consonant:len()
        end
        -- proceed to find vowel
        vowel, vowel_ind = find_next_vowel(s, s_lower, loc)
        assert(vowel ~= nil, string.format("cannot find vowel for '%s...'", s:sub(loc, loc + 10)))
        loc = loc + vowel:len()
        -- peek next char to see if we can find a tone
        tone = find_next_tone(s, s_lower, loc)
        if tone ~= nil then
            loc = loc + tone:len()
        end
        if loc == old_loc then
            error("latin to pinyin algorithm is stuck, please check the integrity of latin input")
        end
        texio.write_nl(string.format("pinyin-debug: %s, %s, %s", consonant, vowel, tone))
        render = render_pinyin(consonant, vowel, vowel_ind, tone)
        table.insert(result, render)
        old_loc = loc
    end
    return result
end

function chinese_to_pinyin(s)
    local code = utf8.codepoint(s)
    local char = utf8.char(code)
    local pinyin = chn_to_pinyin[char]
    return char, pinyin
end


function pinyin_upper(s)
    cap_first = cap_first or false
    local res = ""
    local query, char
    for p, code in utf8.codes(s) do
        char = utf8.char(code)
        query = pinyin_vowel_to_upper[char]
        if query ~= nil then
            res = res .. query
        else
            res = res .. char:upper()
        end
    end
    return res
end

function chinese_to_pinyin_latex(s, cap_first)
    cap_first = cap_first or false
    local char, pinyin = chinese_to_pinyin(s)
    local out_val  = ""
    if pinyin==nil then
        -- special treatment for "*"
        if char == "*" then
            out_val = char
        else
            out_val = [[\textcolor{red}{]] .. char .. "}"
        end
    else
        if cap_first then
            local first_code = utf8.codepoint(pinyin)
            local first_code_offset = utf8.offset(pinyin, 2)
            pinyin = pinyin_upper(utf8.char(first_code)) .. pinyin:sub(first_code_offset)
        end
        out_val = pinyin
    end
    token.set_macro("l_doc_tmpc_tl", out_val)
end



\end{luacode*}

\newcommand{\latintopinyin}[1]{%
    \directlua{
        local pinyin_table = latin_to_pinyin("\luaescapestring{#1}")
        tex.print(table.concat(pinyin_table, " "))
    }%
}

\ExplSyntaxOn

\tl_new:N \l_doc_tmpa_tl
\tl_new:N \l_doc_tmpb_tl
\tl_new:N \l_doc_tmpc_tl

\NewDocumentCommand{\chntopinyin}{sm}{
    \group_begin:
    \tl_set:Nn \l_doc_tmpa_tl {#2}
    \tl_clear:N \l_doc_tmpb_tl
    \bool_do_until:nn {\tl_if_empty_p:N \l_doc_tmpa_tl} {
        \exp_args:NV \tl_if_head_is_group:nTF \l_doc_tmpa_tl {
            \tl_put_right:Nx \l_doc_tmpb_tl {{\tl_head:N \l_doc_tmpa_tl}}
        } {
            \exp_args:Nx \token_if_cs:NTF {\tl_head:N \l_doc_tmpa_tl} {
                \tl_put_right:Nx \l_doc_tmpb_tl {\tl_head:N \l_doc_tmpa_tl}
            } {
                \IfBooleanTF{#1}{
                    \directlua{
                        chinese_to_pinyin_latex("\luaescapestring{\tl_head:N\l_doc_tmpa_tl}", true)
                    }
                    \tl_put_right:NV \l_doc_tmpb_tl \l_doc_tmpc_tl
                }{
                    \directlua{
                        chinese_to_pinyin_latex("\luaescapestring{\tl_head:N\l_doc_tmpa_tl}")
                    }
                    \tl_put_right:NV \l_doc_tmpb_tl \l_doc_tmpc_tl
                }
                \tl_put_right:NV \l_doc_tmpb_tl \space
            }
        }
        \tl_set:Nx \l_doc_tmpa_tl {\tl_tail:N \l_doc_tmpa_tl}
    }
    \tl_use:N \l_doc_tmpb_tl
    \group_end:
}


\newcommand{\pinyin}[2]{
    \latintopinyin{#2}\space
}

\ExplSyntaxOff

\begin{document}
\par\latintopinyin{zhuang1jia1huan2chuang4}
\par\latintopinyin{yi1Er2SAn1SI4}
\par Supported characters are highlighted in red
\par\chntopinyin{测试\chntopinyin*{中文}到\pinyin{拼}{pin3}音\pinyin{转}{Zhuan3}换ひらがな}
\par\chntopinyin{\chntopinyin*{诸葛亮}六出祁山}
\par\chntopinyin*{二}
\end{document}

答案2

问题涉及多个方面:(1)打印拼音;(2)格式化名称;(3)处理空格。

这里讨论第一个方面,直接演示如何读取拼音数据库,并定义一个命令来使用 expl3 函数replace将每个字符替换为其拼音,打印单读拼音和多个读音中的第一个(标有 *)或多个读音的全集(括在括号中)

因此:

拼音

如果事先知道名称,并且用空格格式化,则可以对其进行拼音(先读)和标题大小写:

名称

暗示在有多种可能的读数的情况下需要标记。

平均能量损失

代码可以在 lualatex 下运行。仅使用 expl3。不依赖 xpinyin 包(它通过 xeCJK 依赖项与 xelatex 绑定)。

\documentclass{article}
\usepackage{fontspec}
\setmainfont{Noto Serif}
\setsansfont{Noto Sans}
\setmonofont{Noto Sans Mono}
\usepackage{xparse}
\newfontfamily\cjk{NotoSerifCJKtc-Regular}
%-------------------------------------------------------------
\ExplSyntaxOn

% Adapted from xpinyin.sty:
% #1 (character), rather than #2 (Unicode codepoint),
% becomes part of the control sequence name.
% #3 is the pinyin. All three are in the database.
\cs_new_protected:Npn \xpinyin_customary:nnn #1#2
  { \cs_gset_nopar:cpn { c__xpinyin_#1_tl } }
\cs_new_protected:Npn \xpinyin_multiple:nnn #1#2
  { \cs_gset_nopar:cpn { c__xpinyin_multiple_#1_clist } }
\group_begin:
  \cs_set_eq:NN \XPYU  \xpinyin_customary:nnn
  \cs_set_eq:NN \XPYUM \xpinyin_multiple:nnn
  \file_input:n { xpinyin-database.def }
\group_end:



        \cs_generate_variant:Nn 
            \tl_replace_all:Nnn 
            { Nxx }

        \cs_generate_variant:Nn 
            \str_replace_all:Nnn 
            { Nxx }

%-----------------------------
    \cs_set:Npn \gl_funcxpp:n #1 { 
     \tl_set:Nn \l_tmpb_tl { #1 }
%    \tl_show:N \l_tmpb_tl

   \tl_replace_all:Nxx
    \l_tmpa_tl
    { \l_tmpb_tl }
    {
        \clist_if_exist:cTF
                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                { % there is a comma list for the character
        \bool_if:NTF
        \g__gloss_printfirstvar_bool
        { % bool true = print first reading
                        \clist_item:cn 
                                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                                { 1 }
                                * %=multi
            }
            {   % bool false = print all readings               
                                (
                                \clist_use:cn                               
                                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                                { , }
                                )                               
     }
                                \tex_space:D
                 }
                { % not a comma list = only one reading
                    \cs_if_exist:cT
                    { c__xpinyin_ \l_tmpb_tl _tl }
                    {
                     \use:c { c__xpinyin_ \l_tmpb_tl _tl }
                     \tex_space:D
                    }
                }
                }

%   \cs_show:c { c__xpinyin_ \l_tmpb_tl _tl }
}

\tl_new:N \l_gl_item_tl
%-----------------------------
    \cs_set:Npn \gl_functitlecase:n #1
      {~
            \tl_set:Nn \l_gl_item_tl { #1 }
        \text_titlecase:nn {en} { \tl_use:N \l_gl_item_tl }
%        \tex_space:D
      }
      
%-----------------------------
    \cs_set:Npn \gl_funcxppname:n #1 { 
     \tl_set:Nn \l_tmpb_tl { #1 }

   \tl_replace_all:Nxx
    \l_tmpa_tl
    { \l_tmpb_tl }
    {
        \clist_if_exist:cTF
                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                { % there is a comma list for the character
                        \clist_item:cn 
                                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                                { 1 }
                 }
                { % not a comma list = only one reading
                    \cs_if_exist:cTF
                    { c__xpinyin_ \l_tmpb_tl _tl }
                    {
                     \use:c { c__xpinyin_ \l_tmpb_tl _tl }
                    }
                    { % anything else
                        #1
                    }
                }
                }
}







\bool_new:N \g__gloss_printfirstvar_bool
\NewDocumentCommand \xpppinyin { s m }
  {
  \IfBooleanTF {#1 }
        { \bool_gset_false:N \g__gloss_printfirstvar_bool }
        { \bool_gset_true:N \g__gloss_printfirstvar_bool }
  
        \tl_set:Nn \l_tmpa_tl { #2 }

        \tl_map_function:NN
        \l_tmpa_tl 
        \gl_funcxpp:n 

        \tl_use:N \l_tmpa_tl

  }

\NewDocumentCommand \xppname { m }
  {
  
        \tl_set:Nn \l_tmpa_tl { #1 }

        \tl_map_function:NN
        \l_tmpa_tl
        \gl_funcxppname:n 

        \seq_set_split:NnV \l_tmpa_seq { ~ } \l_tmpa_tl

    \seq_map_function:NN 
                \l_tmpa_seq 
                \gl_functitlecase:n
  }




\ExplSyntaxOff
    
\begin{document}

{\cjk 我诸葛 亮} $\mapsto$ \xpppinyin{我诸葛 亮}

{\cjk 我诸葛 亮} $\mapsto$ \xpppinyin*{我诸葛 亮}

\xppname{诸葛 亮}


\end{document}


附录

增加了一个基本的键值机制来选择拼音第 3 个字符,最多 3 个字符一、二、三

关键附加值

平均能量损失

\documentclass{article}
\usepackage{fontspec}
\setmainfont{Noto Serif}
\setsansfont{Noto Sans}
\setmonofont{Noto Sans Mono}
\usepackage{xparse}
\newfontfamily\cjk{NotoSerifCJKtc-Regular}
\newfontface\sym{DejaVu Sans}
\newcommand\tick{{\sym ✓}}
%-------------------------------------------------------------
\ExplSyntaxOn

% Adapted from xpinyin.sty:
% #1 (character), rather than #2 (Unicode codepoint),
% becomes part of the control sequence name.
% #3 is the pinyin. All three are in the database.
\cs_new_protected:Npn \xpinyin_customary:nnn #1#2
  { \cs_gset_nopar:cpn { c__xpinyin_#1_tl } }
\cs_new_protected:Npn \xpinyin_multiple:nnn #1#2
  { \cs_gset_nopar:cpn { c__xpinyin_multiple_#1_clist } }
\group_begin:
  \cs_set_eq:NN \XPYU  \xpinyin_customary:nnn
  \cs_set_eq:NN \XPYUM \xpinyin_multiple:nnn
  \file_input:n { xpinyin-database.def }
\group_end:

%-----------------------------
%-----------------------------




        \cs_generate_variant:Nn 
            \tl_replace_all:Nnn 
            { Nxx }

        \cs_generate_variant:Nn 
            \str_replace_all:Nnn 
            { Nxx }

        \cs_generate_variant:Nn 
                    \seq_set_split:Nnn 
                { cnx }

%-----------------------------
\keys_define:nn { mpy }
{
mpya .tl_set:c = { l_mpy_char1_tl },
mpyb .tl_set:c = { l_mpy_char2_tl },
mpyc .tl_set:c = { l_mpy_char3_tl },
}
\seq_new:c { l_mpy_char1_seq }
\seq_new:c { l_mpy_char2_seq }
\seq_new:c { l_mpy_char3_seq }

\int_new:c { l_mpy_char1item_int }
\int_new:c { l_mpy_char2item_int }
\int_new:c { l_mpy_char3item_int }

\int_new:c { l_mpy_char1py_int }
\int_new:c { l_mpy_char2py_int }
\int_new:c { l_mpy_char3py_int }


%-----------------------------
    \cs_set:Npn \gl_funcxpp:n #1 { 
     \tl_set:Nn \l_tmpb_tl { #1 }
%    \tl_show:N \l_tmpb_tl

   \tl_replace_all:Nxx
    \l_tmpa_tl
    { \l_tmpb_tl }
    {
        \clist_if_exist:cTF
                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                { % there is a comma list for the character
        \bool_if:NTF
        \g__mpy_printfirstvar_bool
        { % bool true = print first reading
                        \clist_item:cn 
                                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                                { 1 }
                                * %=multi
            }
            {   % bool false = print all readings               
                                (
                                \clist_use:cn                               
                                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                                { , }
                                )                               
     }
                                \tex_space:D
                 }
                { % not a comma list = only one reading
                    \cs_if_exist:cT
                    { c__xpinyin_ \l_tmpb_tl _tl }
                    {
                     \use:c { c__xpinyin_ \l_tmpb_tl _tl }
                     \tex_space:D
                    }
                }
                }

%   \cs_show:c { c__xpinyin_ \l_tmpb_tl _tl }
}

\tl_new:N \l_gl_item_tl
%-----------------------------
    \cs_set:Npn \gl_functitlecase:n #1
      {~
            \tl_set:Nn \l_gl_item_tl { #1 }
        \text_titlecase:nn {en} { \tl_use:N \l_gl_item_tl }
%        \tex_space:D
      }
      
%-----------------------------
    \cs_set:Npn \gl_funcxppname:n #1 { 

        \int_gincr:c { l_mpy_char1count_int }
    
     \tl_set:Nn \l_tmpb_tl { #1 }

   \tl_replace_all:Nxx
    \l_tmpa_tl
    { \l_tmpb_tl }
    {
        \clist_if_exist:cTF
                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                { % there is a comma list for the character
                   % nth character's mth pinyin
                        \int_compare:nNnTF
                                  { \int_use:c { l_mpy_char1count_int } }
                                   = 
                                   { \int_use:c { l_mpy_char2item_int } }
                                  {
                        \clist_item:cn 
                                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                                { \int_use:c { l_mpy_char2py_int } }
                                        }%%
                            { %not 2            
                   % nth character's mth pinyin
                        \int_compare:nNnTF
                                  { \int_use:c { l_mpy_char1count_int } }
                                   = 
                                   { \int_use:c { l_mpy_char3item_int } }
                                  {
                        \clist_item:cn 
                                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                                { \int_use:c { l_mpy_char3py_int } }
                                        }%%
                    { % not 3
                   % nth character's mth pinyin
                        \int_compare:nNnTF
                                  { \int_use:c { l_mpy_char1count_int } }
                                   = 
                                   { \int_use:c { l_mpy_char1item_int } }
                                  {
                        \clist_item:cn 
                                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                                { \int_use:c { l_mpy_char1py_int } }
                                        }%%
                                        { % not 1, therefore 1st pinyin
                        \clist_item:cn 
                                { c__xpinyin_multiple_ \l_tmpb_tl _clist }
                                { 1 }
                                }%false1
                                }%false2
                                }%false3
                 }
                { % not a comma list = only one reading
                    \cs_if_exist:cTF
                    { c__xpinyin_ \l_tmpb_tl _tl }
                    {
                     \use:c { c__xpinyin_ \l_tmpb_tl _tl }
                    }
                    { % anything else
                        #1
                    }
                }
                }
}







\bool_new:N \g__mpy_printfirstvar_bool
\NewDocumentCommand \xpppinyin { s m }
  {
  \IfBooleanTF {#1 }
        { \bool_gset_false:N \g__mpy_printfirstvar_bool }
        { \bool_gset_true:N \g__mpy_printfirstvar_bool }
  
        \tl_set:Nn \l_tmpa_tl { #2 }

        \tl_map_function:NN
        \l_tmpa_tl 
        \gl_funcxpp:n 

        \tl_use:N \l_tmpa_tl

  }


\int_new:c { l_mpy_char1count_int }
\NewDocumentCommand \xppname { O{mpya={},
mpyb={},
mpyc={},} m }
  {
  
     \int_gset:cn { l_mpy_char1count_int } { 0 }
     \int_gset:cn { l_mpy_char1item_int  } { 0 } 
     \int_gset:cn { l_mpy_char2item_int  } { 0 } 
     \int_gset:cn { l_mpy_char3item_int  } { 0 } 
          
      \IfNoValueF{#1}
    {
        \keys_set:nn { mpy } { #1 } 
        }
  
  
  %----- if the option has been set
        \tl_if_empty:cF { l_mpy_char1_tl }
        {  
                %----- store the record
                    \seq_set_split:cnx
                             { l_mpy_char1_seq }
                            { ; } % separator
                            { \tl_use:c { l_mpy_char1_tl } }
                %----- store the fields
                \int_set:cn
                        { l_mpy_char1item_int }
                        {
                                \seq_item:cn
                                    { l_mpy_char1_seq }
                                    { 1 } %the i-th character
                        }
                \int_set:cn
                        { l_mpy_char1py_int }
                        {
                                \seq_item:cn
                                    { l_mpy_char1_seq }
                                    { 2 } %the k-th pinyin reading
                        }

        }%end1
  %----- if the option has been set
        \tl_if_empty:cF { l_mpy_char2_tl }
        {  
                %----- store the record
                    \seq_set_split:cnx
                             { l_mpy_char2_seq }
                            { ; } % separator
                            { \tl_use:c { l_mpy_char2_tl } }
                %----- store the fields
                \int_set:cn
                        { l_mpy_char2item_int }
                        {
                                \seq_item:cn
                                    { l_mpy_char2_seq }
                                    { 1 } %the i-th character
                        }
                \int_set:cn
                        { l_mpy_char2py_int }
                        {
                                \seq_item:cn
                                    { l_mpy_char2_seq }
                                    { 2 } %the k-th pinyin reading
                        }

        }%end2
  %----- if the option has been set
        \tl_if_empty:cF { l_mpy_char3_tl }
        {  
                %----- store the record
                    \seq_set_split:cnx
                             { l_mpy_char3_seq }
                            { ; } % separator
                            { \tl_use:c { l_mpy_char3_tl } }
                %----- store the fields
                \int_set:cn
                        { l_mpy_char3item_int }
                        {
                                \seq_item:cn
                                    { l_mpy_char3_seq }
                                    { 1 } %the i-th character
                        }
                \int_set:cn
                        { l_mpy_char3py_int }
                        {
                                \seq_item:cn
                                    { l_mpy_char3_seq }
                                    { 2 } %the k-th pinyin reading
                        }

        }%end3
  
  





  
  %-----
        \tl_set:Nn \l_tmpa_tl { #2 }

        \tl_map_function:NN
        \l_tmpa_tl
        \gl_funcxppname:n 

        \seq_set_split:NnV \l_tmpa_seq { ~ } \l_tmpa_tl

    \seq_map_function:NN 
                \l_tmpa_seq 
                \gl_functitlecase:n
  }




\ExplSyntaxOff
    
\begin{document}

{\cjk 诸葛 亮} $\mapsto$ \xpppinyin{诸葛 亮}

{\cjk 诸葛 亮} $\mapsto$ \xpppinyin*{诸葛 亮}

\xppname{诸葛 亮}, ...

%  mpya - for a character setting ``a''
%  = - set it to
%  2 - character position in the argument
%  ; - delimiter
%  2 - pinyin position in the comma list
\xppname[mpya=2;2]{诸葛 亮}, ...

\bigskip
\xpppinyin*{

相关内容