![多语言支持 - 需要 xkeyval 方面的帮助](https://linux22.com/image/468696/%E5%A4%9A%E8%AF%AD%E8%A8%80%E6%94%AF%E6%8C%81%20-%20%E9%9C%80%E8%A6%81%20xkeyval%20%E6%96%B9%E9%9D%A2%E7%9A%84%E5%B8%AE%E5%8A%A9.png)
我正在尝试对多受众包进行一些改进。具体来说,我希望有一个包含多种语言的 Latex 文档。
为简化起见,多种语言的文本应按段落排列。事实上,大多数这些事情已经可以用多受众包来完成。
现在我面临的问题是,对于文档发布来说,创建两种 pdf 文档可能要简单得多,而不是每种语言创建两种,而是创建一种通用的。特别是 \section 命令在这里存在问题 - 因为第一种语言和第二种语言的标题不应该创建两个“真正的”部分。
我给出一个容易理解的代码片段:
\showto{E}{\section{english section}
\showto{D}{\section{german section}
\showto{E}{english text}
\showto{D}{german text}
如果我选择\DefCurrentAudience{D}
或\DefCurrentAudience{E}
,这将正常工作,但使用 时会造成混乱\DefCurrentAudience{D,E}
。文本将出现在错误的部分。
我希望获得这样的输出:
1. english section / german section
[E] english text
[D] german text
我的想法是编写一个新的(多语言)部分命令,将两个标题合二为一,以防激活多种语言
\mlsection{E=english section title, G=german section title}
请给我一些提示,告诉我如何分离键和值对。当然,也欢迎任何其他想法
谢谢乔治
这是一个最小的例子
\documentclass{scrartcl}
\usepackage{multilanguage}
\SetNewLanguage{D}
\SetNewLanguage{E}
\DefCurrentLanguage{D,E}
\begin{document}
\section{Erstens}
\showto{D}{THIS IS GERMAN}
\showto{E}{THIS IS ENGLISH}
\showto{D}{\section{GERMAN SECTION}}
\showto{E}{\section{ENGLISH SECTION}}
new try
\mlsection{G=German Section, E=English Section}
\end{document}
以及新推出的“多语言”套餐——多受众的简化版本
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{multilanguage}
[2023/09/08 v1.0 Some tests]
\providecommand*\CurrentLanguage{default}
\def\DefCurrentLanguage#1{\def\CurrentLanguage{#1}}
\newif\if@MULTLANG@shown
\@MULTLANG@showntrue
\RequirePackage{xkeyval}
\def\SetNewLanguage#1{
\define@key{MULTLANG}{#1}[]{
\def\@MULTLANG@currkey{#1}
\@for\@tempa:=\CurrentLanguage \do{%
\ifx\@MULTLANG@currkey\@tempa
\@MULTLANG@showntrue
\fi
}%
}%
}
\long\def\showto#1#2{%
\@MULTLANG@shownfalse
\setkeys{MULTLANG}{#1}
\if@MULTLANG@shown#2\fi
}
\long\def\mlsection#1{%
\@for\@tempa:=#1\do {%
% SOME CODE IS MISSING HERE
}%
}
@Skillmon 我非常喜欢下面显示的小宏。我仔细阅读了代码 - 我想我明白你在做什么。我还发现了一种很好的方法来使用代码先用德语编写一个内容文件,然后用英语编写相同的内容文件。此外,-尤其是对于更正-我使用的是堆叠版本,其中德语和英语是逐段发布的。我正在寻找一种很好的方法来突出显示独立的语言。例如,英语为绿色,德语为红色,或者在实际文本块之前使用文本标识符。有简单的解决方案吗?谢谢 georg
答案1
不确定您的界面有多灵活,但我建议使用以下代码。它不是在每次使用时检查哪些语言处于活动状态,而是仅激活 上使用的语言\DefCurrentLanguage
,然后使用内部宏来跟踪此状态(因此它不会拾取 的外部更改\CurrentLanguage
)。优点是,这样我们可以快速且可扩展地检查语言是否处于活动状态。
\mlsection
对于以下用途的键/值部分,expkv
因为它是完全可扩展的。这样,我们可以添加键,例如label
设置一个\label
,或者default
如果之前没有使用其他语言,则会使用它。
我还改变了定义新语言的方式,以接受逗号分隔的语言列表,而不是使用多个调用。对于 csv 处理,以下使用\ekvcsvloop
而不是 LaTeX 的内置\@for
,因为我认为它具有更清晰的界面(它还可以正确处理空格剥离)。
如果您不想使用expkv
,原则上也可以使用来进行以下编码(但由于我是以下内容expl3
的作者,因此使用它)。expkv
\begin{filecontents}{multilanguage.sty}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{multilanguage}
[2023/09/08 v1.0 Some tests]
\RequirePackage{expkv}
\providecommand*\CurrentLanguage{}
\protected\def\DefCurrentLanguage
{%
\@MULTLANG@deactivate
\ekvcsvloop\@MULTLANG@activate
}
\protected\def\@MULTLANG@activate#1%
{%
\expandafter\let
\csname @MULTLANG@@iflang@\detokenize{#1}\endcsname
\@firstoftwo
}
\newcommand\@MULTLANG@deactivate{}
\protected\def\SetNewLanguages{\ekvcsvloop\@MULTLANG@new@language}
\protected\def\@MULTLANG@new@language#1%
{%
\@ifundefined{@MULTLANG@@iflang@\detokenize{#1}}%
{%
% add it to the list of languages which need to be deactivated on
% language change
\edef\@MULTLANG@deactivate
{%
\unexpanded\expandafter{\@MULTLANG@deactivate}%
\unexpanded\expandafter
{%
\expandafter\let
\csname @MULTLANG@@iflang@\detokenize{#1}\endcsname
\@secondoftwo
}%
}%
% init the language
\expandafter\let
\csname @MULTLANG@@iflang@\detokenize{#1}\endcsname
\@secondoftwo
}%
{%
\PackageError{multilanguage}%
{Language `\detokenize{#1}' already defined.}{}%
}%
}
\def\showto#1%
{%
\@ifundefined{@MULTLANG@@iflang@\detokenize{#1}}%
{%
% expandable error message
\ekverr{multilanguage}{Unknown language `#1'}%
\@gobble
}%
{%
\csname @MULTLANG@@iflang@\detokenize{#1}\endcsname
\@firstofone
\@gobble
}%
}
\ekvsetdef\@MULTLANG@section@keys{MULTLANG/section}
% keep in mind that the key will be used in an expanded-context, so we use
% \unexpanded
\ekvdef{MULTLANG/section}{label}{\unexpanded{\label{#1}}}
% default will only be used if no other language was used before it
\ekvdef{MULTLANG/section}{default}
{%
\ifcsname @MULTLANG@@flag@notfirst\endcsname
\expandafter\@gobble
\else
\expandafter\@gobble\csname @MULTLANG@@flag@notfirst\endcsname
\expandafter\@firstofone
\fi
{\unexpanded{#1}}%
}
% every unknown key will be interpreted as a language key
\ekvdefunknown{MULTLANG/section}
{%
\showto{#2}
{%
\ifcsname @MULTLANG@@flag@notfirst\endcsname
\space/\space
\else
\expandafter\@gobble\csname @MULTLANG@@flag@notfirst\endcsname
\fi
\unexpanded{#1}%
}%
}
\def\mlsection#1%
{%
% group to keep the notfirst-flag local
\begingroup
\expandafter\section\expanded
{{\@MULTLANG@section@keys{#1}}}%
\endgroup
}
\def\@MULTLANG@missing@value#1%
{%
\ekvifdefinedNoVal{#1}{\@MULTLANG@section@keys{#1}}%
{\ekverr{multilanguage}{Missing value for `#1'}}%
}
\def\@MULTLANG@mlsection#1#2%
{%
\ekvifdefined{MULTLANG/section}{#1}{\@MULTLANG@section@keys{{#1}={#2}}}%
\showto{#1}
{%
\ifcsname @MULTLANG@@flag@notfirst\endcsname
\space/\space
\else
\expandafter\@gobble\csname @MULTLANG@@flag@notfirst\endcsname
\fi
\unexpanded{#2}%
}%
}
\end{filecontents}
\documentclass{scrartcl}
\usepackage{multilanguage}
\SetNewLanguages{D,E}
\DefCurrentLanguage{D,E}
\begin{document}
\section{Erstens}
\showto{D}{THIS IS GERMAN}
\showto{E}{THIS IS ENGLISH}
\showto{D}{\section{GERMAN SECTION}}
\showto{E}{\section{ENGLISH SECTION}}
new try
\mlsection{D=German Section, E=English Section, default=FALLBACK TITLE, label=sec:multilang}
See section~\ref{sec:multilang}.
\end{document}