\enzh
我正在使用如下定义的宏用两种语言编写文档:
\documentclass{article}
\newif\ifen
\entrue % comment out to switch to Chinese
\newcommand{\enzh}[2]{\ifen#1\else#2\fi}
\begin{document}
\enzh{English text}{Chinese text}
\end{document}
目前显示“英文文本”,如果\entrue
注释掉则显示“中文文本”。此部分工作正常。
但是,两种语言可能存在一些共同的元素。我不想为两种语言重复相同的代码,而是希望用这些共同的元素替换两种语言字符串中的占位符,使用类似于 Python 字符串的语法format
。例如:
\documentclass{article}
\usepackage{hyperref}
\newif\ifen
\entrue % comment out to switch to Chinese
\newcommand{\enzh}[2]{\ifen#1\else#2\fi} % how should this command be implemented?
\begin{document}
\enzh{English #1 text #2}{Chinese #2 text #1}{\href{https://www.google.com}{Google}}{b}
\end{document}
应显示“英语谷歌文本b”和“中文b文本”谷歌“对于两种语言模式。理想情况下,可以进行任意多次替换,但就我的目的而言,3 次就足够了。
\enzh
为了实现这一点,应该如何执行命令?
答案1
使用 expl3 你可以定义一个\MyReplace
带有三个参数的命令,
- ⟨英文原文⟩
- ⟨中文文本⟩
- ⟨英文/中文文本中常用替换 {1}、{2}、{3}、… 的文本短语列表⟩
,它实际上包含括号嵌套的未分隔参数列表。
取决于迭代是否\englishtrue
发生\englishfalse
在⟨英文文本⟩或⟨中文文本⟩的未限定参数上,其中每个元素处理如下:
- 如果它的第一个标记是,
:
则假定它表示一个非常见的文本短语,并且它会被:
删除。 - 如果它的第一个标记不是,
:
则假定它表示数字 k,并且如果该列表有第 k个元素,则传递⟨常用文本短语列表⟩的第 k个元素。
起初我考虑过反过来做,即:⟨number⟩
用 而不是:⟨non-common text phrase⟩
,但随后出现了一个问题,即如何处理非常见文本短语以 为前导的情况:
,而不会错误地将其作为 :⟨number⟩ 传递给处理,这可能会导致低级 TeX 错误消息。
\documentclass{article}
\ExplSyntaxOn
\bool_new:N \l_english_bool
\cs_new_protected:Npn \englishtrue {\bool_set_true:N \l_english_bool}
\cs_new_protected:Npn \englishfalse {\bool_set_false:N \l_english_bool}
\cs_new_protected:Npn \enzh #1#2 {\bool_if:nTF \l_english_bool {#1}{#2}}
\cs_new_protected:Npn \MyReplace #1#2#3
{
\bool_if:nTF \l_english_bool
{\tl_map_tokens:nn {#1} }
{\tl_map_tokens:nn {#2} }
{\mymodule_get_kth_arg:nn{#3}}
}
\cs_new:Nx \mymodule_get_kth_arg:nn
{
\exp_not:N\tl_if_blank:nF {#2} {
\exp_not:N\tl_if_head_eq_meaning:nNTF
{#2}\token_to_str:N :
{\exp_not:N\tl_tail:n {#2}}
{\exp_not:N\tl_item:nn{#1}{#2}}
}
}
\ExplSyntaxOff
\begin{document}
\englishtrue
\enzh{English text}{Chinese text}
\MyReplace{ {1}{: }{2}{: English text A }{2}{: English text B }{5}{: English text C }{4}{: English text D }{3} }%
{ {2}{: }{1}{: Chinese Text text A }{1}{: Chinese text B }{3}{: Chinese Text text C }{4}{: Chinese text D }{5} }%
{
{Common Phrase 1}
{Common Phrase 2}
{Common Phrase 3}
{Common Phrase 4}
{Common Phrase 5}
}
\bigskip
\englishfalse
\enzh{English text}{Chinese text}
\MyReplace{ {1}{: }{2}{: English text A }{2}{: English text B }{5}{: English text C }{4}{: English text D }{3} }%
{ {2}{: }{1}{: Chinese Text text A }{1}{: Chinese text B }{3}{: Chinese Text text C }{4}{: Chinese text D }{5} }%
{
{Common Phrase 1}
{Common Phrase 2}
{Common Phrase 3}
{Common Phrase 4}
{Common Phrase 5}
}
\end{document}
在上述示例的 ⟨英文文本⟩ 和 ⟨中文文本⟩ 中,{: }
空格都用作非常用文本短语。您也可以将空格用作另一个常用文本短语,然后执行
\MyReplace{ {1}{6}{2}{: English text A }{2}{: English text B }{5}{: English text C }{4}{: English text D }{3} }%
{ {2}{6}{1}{: Chinese Text text A }{1}{: Chinese text B }{3}{: Chinese Text text C }{4}{: Chinese text D }{5} }%
{
{Common Phrase 1}
{Common Phrase 2}
{Common Phrase 3}
{Common Phrase 4}
{Common Phrase 5}
{ }
}
#1
如果您更喜欢通过, #2
, ... , #11
... 而不是{1}
, {2}
, ... , ...来表示常见的文本短语/替换,{11}
并且如果可扩展性不是问题,那么您可以使用 l3regex 的正则表达式。
在以下示例中,正则表达式将搜索#
以一系列数字0
, 1
, 2
, 3
, 4
, 5
, 6
, 7
, 8
,9
结尾,并以一个可选斜杠结尾,/
这样您就可以将属于常用文本短语/替换列表元素编号的数字与属于要传递的文本的数字分开 - 因此,如果您希望在文本中紧跟在常用文本短语后面/紧跟在 表示的替换后面出现斜杠#⟨sequence of digits denoting the number of the common text phrase/replacement⟩
,则需要输入两个斜杠:
#⟨sequence of digits denoting the number of the common text phrase/replacement⟩//The second one of these slashes goes into the text. The first one is removed as "digit"-separator"
:
\documentclass{article}
\ExplSyntaxOn
\bool_new:N \l_english_bool
\tl_new:N \l_mymodule_replacementlist_tl
\tl_new:N \l_mymodule_textphrase_tl
\cs_new_protected:Npn \englishtrue {\bool_set_true:N \l_english_bool}
\cs_new_protected:Npn \englishfalse {\bool_set_false:N \l_english_bool}
\cs_new_protected:Npn \enzh #1#2 {\bool_if:nTF \l_english_bool {#1}{#2}}
\cs_new_protected:Npn \MyReplace #1#2#3
{
\bool_if:nTF \l_english_bool
{\tl_set:Nn\l_mymodule_textphrase_tl {#1} }
{\tl_set:Nn\l_mymodule_textphrase_tl {#2} }
\tl_set:Nn \l_mymodule_replacementlist_tl {#3}
% \cA. denotes any active character; \cC. denotes any control sequence token,
% so the following prepends \noexpand to tokens that might be expandable:
\regex_replace_all:nnN {(?:\cA.|\cC.)}{\c{exp\_not\:N}\0}\l_mymodule_textphrase_tl
% \tl_show:N \l_mymodule_textphrase_tl
% Replace any #<digit sequence><optional slash> of category 6 that is preceeded by an even amount of hashes
% by \tl_\item:Nn \l_mymodule_replacementlist_tl {<digit sequence>}:
\regex_replace_all:nnN { ((?:\G|[^\cP.])(?:[\cP.][\cP.])*) [\cP.] (\cO[\d]+)\cO\/? }
{\1 \c{tl\_item\:Nn} \c{l\_mymodule\_replacementlist\_tl} \cB\{ \2 \cE\}}
\l_mymodule_textphrase_tl
% \tl_show:N \l_mymodule_textphrase_tl
% Expand the token list to get the token-list-items and halve doubled hashes:
\exp_args:NNx \tl_set:Nn \l_mymodule_textphrase_tl {\tl_use:N \l_mymodule_textphrase_tl }
% \tl_show:N \l_mymodule_textphrase_tl
\tl_use:N \l_mymodule_textphrase_tl
}
\ExplSyntaxOff
\begin{document}
\tableofcontents
\englishtrue
\MyReplace{\section{#1 English text #2}}
{\section{#2 Chinese text #1}}
{
{Common 1} % <- this is #1
{Common 2} % <- this is #2
}
\enzh{English text}{Chinese text}
\bigskip
\MyReplace{#1 #2 English text A #2//English text B #5 English text C #4 English text D #3/7 is a nice digit.}%
{#2 #1 Chinese Text text A #1//Chinese text B #3 Chinese Text text C #4 Chinese text D #5/7 is a nice digit.}%
{
{Common Phrase 1} % <- this is #1
{Common Phrase 2} % <- this is #2
{Common Phrase 3} % <- this is #3
{Common Phrase 4} % <- this is #4
{Common Phrase 5} % <- this is #5
}
\bigskip
\MyReplace{\def\MACRO##1##2{#1 English text #2}}%
{\def\MACRO##1##2{#2 Chinese text #1}}%
{
{Common Phrase 1, Argument 1: #1, Argument 2: #2} % <- in the two arguments above this is #1
{Common Phrase 2, Argument 1: #1, Argument 2: #2} % <- in the two arguments above this is #2
}%
{\tt\frenchspacing\string\MACRO: \meaning\MACRO}
\englishfalse
\MyReplace{\section{#1 English text #2}}
{\section{#2 Chinese text #1}}
{
{Common 1} % <- this is #1
{Common 2} % <- this is #2
}
\enzh{English text}{Chinese text}
\bigskip
\MyReplace{#1 #2 English text A #2//English text B #5 English text C #4 English text D #3/7 is a nice digit.}%
{#2 #1 Chinese Text text A #1//Chinese text B #3 Chinese Text text C #4 Chinese text D #5/7 is a nice digit.}%
{
{Common Phrase 1} % <- this is #1
{Common Phrase 2} % <- this is #2
{Common Phrase 3} % <- this is #3
{Common Phrase 4} % <- this is #4
{Common Phrase 5} % <- this is #5
}
\bigskip
\MyReplace{\def\MACRO##1##2{#1 English text #2}}%
{\def\MACRO##1##2{#2 Chinese text #1}}%
{
{Common Phrase 1, Argument 1: #1, Argument 2: #2} % <- in the two arguments above this is #1
{Common Phrase 2, Argument 1: #1, Argument 2: #2} % <- in the two arguments above this is #2
}%
{\tt\frenchspacing\string\MACRO: \meaning\MACRO}
\end{document}
如果您按照这种方式执行操作并将其用作\MyReplace
宏的 ⟨定义⟩ 的替换文本/⟨平衡文本⟩的组成部分,则#
表示常用文本短语/替换的数量的哈希值需要加倍,就像在 ⟨定义⟩ 内嵌套 ⟨定义⟩ 时表示参数的哈希值需要加倍一样。
答案2
您可以简单地定义\enzhi
单个参数、\enzhii
两个参数等等。
\newif\ifen
\entrue
\def\enzh#1#2{\ifen#1\else#2\fi}
\def\enzhi#1#2{\def\tmp##1{\ifen#1\else#2\fi}\tmp}
\def\enzhii#1#2{\def\tmp##1##2{\ifen#1\else#2\fi}\tmp}
\enzhii{English #1 text #2}{Chinese #2 text #1}{\href{https://www.google.com}{Google}}{b}
答案3
主要问题是要有一致的语法,所以我建议\enzh
有两个尾随可选参数。如果存在,则两个强制参数将被解释为模板(您可以在其中使用#1
和#2
)。
\documentclass{article}
\usepackage{hyperref}
\ExplSyntaxOn
\NewDocumentCommand{\enzh}{mmoO{#3}}
{
\IfNoValueTF{#3}
{% no optional arguments
\legacy_if:nTF { en } { #1 } { #2 }
}
{% with optional arguments
\tian_enzh:nnnn { #1 } { #2 } { #3 } { #4 }
}
}
\cs_new_protected:Nn \tian_enzh:nnnn
{
\group_begin:
\legacy_if:nTF { en }
{% en is true, use the first argument as template
\cs_set:Nn \__tian_enzh_do:nn { #1 }
}
{% en is false, use the second argument as template
\cs_set:Nn \__tian_enzh_do:nn { #2 }
}
% do the job
\__tian_enzh_do:nn { #3 } { #4 }
\group_end:
}
\cs_new:Nn \__tian_enzh_do:nn {} % initialize the auxiliary function
\ExplSyntaxOff
\newif\ifen
\begin{document}
\section{Chinese}
\enzh{English text}{Chinese text}
\enzh{English #1 text #2}{Chinese #2 text #1}[\href{https://www.google.com}{Google}][b]
\section{English}
\entrue
\enzh{English text}{Chinese text}
\enzh{English #1 text #2}{Chinese #2 text #1}[\href{https://www.google.com}{Google}][b]
\end{document}
如果只有一个可选参数,则第二个参数将被视为与出现的参数相同。