他是我的问题:我需要更新许多文件(简历、研究陈述、研究项目、摘要列表等),并随时准备提交申请,有时非常匆忙。但是,根据我发送文件的地方,语言会发生变化,我会以这样或那样的方式一遍又一遍地翻译。我想避免这种情况,并停止在大量基本相同内容的副本之间来回切换。
有没有办法定义一种“模式”(比如“英语”或“德语”或“法语”),在一个文件中用两种语言写入内容,例如
\english{2020-2023: PhD student}
\german{2020-2023: Doktorand}
\french{2020-2023: Étudiant doctoral}
并在文档顶部定义模式,例如
\mode{english}
这样打印的 PDF 只会考虑所需的语言条目(此处为英语)?
基本上,我当然需要继续进行翻译和编写,但对于每一点需要更新的内容进行翻译会更方便,而不是每次都重新检查整个文档以查看它是否确实是最后一个版本。
我希望它足够强大,能够继续与 beamers、moderncv 或任何已经存在的类或环境一起工作。
答案1
该iflang
包可以做到这一点。
\documentclass[french,ngerman,english]{article}
\usepackage{libertinus}
\usepackage[main=french]{babel}
\usepackage{iflang}
\newcommand\IfEnglish[1]{%
\IfLanguageName{english}%
{#1}%
{}%
\ignorespaces}
\newcommand\IfFrench[1]{%
\IfLanguageName{french}%
{#1}%
{}%
\ignorespaces}
\newcommand\IfGerman[1]{%
\IfLanguageName{german}%
{#1}%
{\IfLanguageName{ngerman}%
{#1}%
{}}%
\ignorespaces}
\begin{document}
\section*{Curriculum Vitae}
\noindent\IfEnglish{2020--2023: PhD student}
\IfFrench{2020--2023: Étudiant doctoral}
\IfGerman{2020--2023: Doktorand}
\end{document}
您现在可以通过更改选项main=
或babel
通过将选项更改为文档类来进行切换。
另一种方法是随包提供每种语言的翻译translator
。这样做的好处是,它始终只显示一次翻译的字符串,无论是当前语言还是英语,即使您错误地漏掉了翻译或两次提供同一种语言的翻译。
\documentclass[french,ngerman,english]{article}
\usepackage{libertinus}
\usepackage[main=ngerman]{babel}
\usepackage{translator}
\providetranslation[to=English]{PHD student}{Ph.D. student}
\providetranslation[to=French]{PHD student}{Étudiant doctoral}
\providetranslation[to=German]{PHD student}{Doktorand}
\begin{document}
\section*{Curriculum Vit\ae}
\noindent2020--2023: \translate{PHD student}
\end{document}
答案2
因为这个问题与 LaTeX 没有明确关系,所以我展示了如何使用另一种 TeX 格式:OpTeX。
第一种选择:您可以将与语言相关的短语映射到标识符(下面示例中的 phdstudent),然后运行 _mtext{identifier}。它会根据当前语言扩展为语言短语:
\sdef{_mt:phdstudent:en}{2020-2023: PhD student}
\sdef{_mt:phdstudent:de}{2020-2023: Doktorand}
\sdef{_mt:phdstudent:fr}{2020-2023: Étudiant doctoral}
\enlang % default
\_mtext{phdstudent} % expands to 2020-2023: PhD student
\frlang % another language
\_mtext{phdstudent} % expands to 2020-2023: Étudiant doctoral
第二种选择。您可以通过以下方式在语言之间切换\ifnum
:
\long\def\threelangs#1#2#3{%
\ifnum\language=\_enPatt #1\fi
\ifnum\language=\_dePatt #2\fi
\ifnum\language=\_frPatt #3\fi
}
\threelangs
{2020-2023: PhD student}
{2020-2023: Doktorand}
{2020-2023: Étudiant doctoral}
% expands to the first or second or third parameter depending on
% the current language.
答案3
如果您愿意使用 expl3 的功能来迭代键值列表,我可以提供带有键值语法的宏:
\SelectLanguageString{⟨comma-separated ⟨language⟩=⟨string⟩-list⟩}
所有那些⟨字符串⟩将交付其⟨语言⟩当前已被选中。
如果一个⟨细绳⟩本身就是包含逗号,它可以嵌套在花括号中。
您还可以指定密钥other language=...
。
如果不存在任何密钥,则将提供属于该密钥的字符串⟨语言⟩其中指定了当前选定的字符串。
\DefineLanguageSpecificMacro{⟨macro⟩}[⟨amount of parameters⟩][⟨1st optional argument's default-value⟩]{⟨comma-separated ⟨language⟩=⟨string⟩-list containing language-specific definition-texts⟩}
或者
\DefineLanguageSpecificMacro{⟨macro⟩}[][⟨parameter-text in plain-TeX-syntax⟩]{⟨comma-separated ⟨language⟩=⟨string⟩-list containing language-specific definition-texts⟩}
或者
\DefineLanguageSpecificMacro{⟨macro⟩}{⟨comma-separated ⟨language⟩=⟨string⟩-list containing language-specific definition-texts⟩}
⟨宏⟩(和⟨参数⟩如果提供)将从⟨定义文本⟩谁的⟨语言⟩当前已被选中。
与上面类似,您也可以指定密钥other language=...
。
如果您提供多个⟨定义文本⟩对于当前选定的⟨语言⟩您将收到一条错误消息。
\documentclass[french,ngerman,english,spanish]{article}
\usepackage{xparse}
\usepackage{libertinus}
\usepackage[main=french]{babel} % <- You get "french=..."-strings with \SelectLanguageString and \DefineLanguageSpecificMacro.
%\usepackage[main=english]{babel} % <- You get "english=..."-strings with \SelectLanguageString and \DefineLanguageSpecificMacro.
%\usepackage[main=german]{babel} % <- You get "german=..."-strings with \SelectLanguageString and \DefineLanguageSpecificMacro.
%\usepackage[main=spanish]{babel} % <- As no "spanish=..."-strings are specified you get "other language=..."-strings with \SelectLanguageString and \DefineLanguageSpecificMacro.
\usepackage{iflang}
\ExplSyntaxOn
%-------------------------------------------------------------------------------------------------------------------
\bool_new:N \__SelectLanguageString_LanguageFound_bool
\msg_new:nnnn {SelectLanguageString}{unknown-language}
{No\ language\ specified\ for\ string\ `#1'}
{You\ need\ to\ specify\ both\ a\ language\ and\ a\ string\ in\ that\ language}
\msg_new:nnnn {DefineLanguageSpecificMacro}{unknown-language}
{No\ language\ specified\ for\ string\ `#1'}
{You\ need\ to\ specify\ both\ a\ language\ and\ a\ string\ in\ that\ language}
\msg_new:nnnn {DefineLanguageSpecificMacro}{IncorrectParameterText}
{Parameter-text-specification\ is\ incorrect}
{Parameter-text\ can\ be\ specified\ as\ follows:\\
LaTeX-Syntax:\\
-\ first\ optional\ argument:\ amount\ of\ arguments\\
-\ second\ optional\ argument:\ default\ in\ case\ 1st\ arg\ is\ optional\\
plain-TeX-Syntax:\\
-\ first\ optional\ argument:\ empty\\
-\ second\ optional\ argument:\ plain-TeX\ parameter-text}
\msg_new:nnnn {DefineLanguageSpecificMacro}{command-already-defined}
{ Command\ '#1'\ already\ defined! }
{
You\ have\ used\ #2\
with\ a\ command\ that\ already\ has\ a\ definition.\\
The\ existing\ definition\ of\ '#1'\ will\ not\ be\ altered.
}
\msg_new:nnnn {DefineLanguageSpecificMacro}{string-already-specified}
{ String\ for\ language\ '#1'\ already\ specified! }
{
You\ have\ used\ #2\ with\ more\ than\ one\ definition\ text\ for\ language\ '#1'.\\
Specify\ only\ one\ definition\ text\ per\ language.\\
'#3'\ will\ be\ defined\ from\ the\ first\ definition\ text\ specified.
}
\cs_new:Nn \__SelectLanguageString_LanguageDetect:n {
\group_begin:
\cs_set:Nn \msg_error_text:n {Macro~\exp_args:Nc \token_to_str:N {##1}~Error}
\msg_error:nnx {SelectLanguageString}{unknown-language}{ \exp_not:n {#1} }
\group_end:
}
\cs_new:Nn \__SelectLanguageString_Define_LanguageDetect:n {
\group_begin:
\cs_set:Nn \msg_error_text:n {Macro~\exp_args:Nc \token_to_str:N {##1}~Error}
\msg_error:nnx {DefineLanguageSpecificMacro}{unknown-language}{ \exp_not:n {#1} }
\group_end:
}
\cs_new:Nn \__SelectLanguageString_LanguageDetect:nn { \IfLanguageName{#1}{\bool_set_true:N \__SelectLanguageString_LanguageFound_bool}{} }
\cs_new:Nn \__SelectLanguageString_SelectLanguage:n {}
\cs_new:Nn \__SelectLanguageString_SelectLanguage:nn { \IfLanguageName{#1}{\__SelectLanguageString_MacroDefiner:nn{#1}{#2}}{} }
\cs_new:Nn \__SelectLanguageString_SelectOtherLanguage:n {}
\cs_new:Nn \__SelectLanguageString_SelectOtherLanguage:nn { \str_if_eq:nnTF{#1}{other~language}{\__SelectLanguageString_MacroDefiner:nn{#1}{#2}}{} }
\cs_new:Nn\__SelectLanguageString_MacroDefiner:nn { #2 }
\cs_new:Nn\__SelectLanguageString_DefineMacroDefiner:Nnn {
\cs_set:Nx\__SelectLanguageString_MacroDefiner:nn {
\exp_not:n{\tl_put_right:Nn \l_tmpa_tl}{\exp_not:n{\__SelectLanguageString_CheckDefined:nnnnn}{##1}\exp_not:n{{#3}{#1}{#2}}{##2}}
}
}
\cs_new:Nn \__SelectLanguageString_CheckDefined:nnnnn{
\cs_if_exist:NTF{#3}{
\group_begin:
\cs_set:Nn \msg_error_text:n {Macro~\exp_args:Nc \token_to_str:N {##1}~Error}
\msg_error:nnxxx {DefineLanguageSpecificMacro}{string-already-specified}%
{\tl_to_str:n{#1}}{\token_to_str:N \DefineLanguageSpecificMacro}{\token_to_str:N #3}
\group_end:
}{
#2 #3 #4 {#5}
}
}
\cs_new:Nn \__SelectLanguageString_SwapArgs:nn {#2#1}
%-------------------------------------------------------------------------------------------------------------------
% \SelectLanguageString{%
% key-val-list with texts for each language
% }%
\NewDocumentCommand \SelectLanguageString {m} {
\group_begin:
\bool_set_false:N \__SelectLanguageString_LanguageFound_bool
\keyval_parse:NNn \__SelectLanguageString_LanguageDetect:n \__SelectLanguageString_LanguageDetect:nn {#1}
\bool_if:NTF \__SelectLanguageString_LanguageFound_bool {
\group_end:
\keyval_parse:NNn \__SelectLanguageString_SelectLanguage:n \__SelectLanguageString_SelectLanguage:nn {#1}
}{
\group_end:
\keyval_parse:NNn \__SelectLanguageString_SelectOtherLanguage:n \__SelectLanguageString_SelectOtherLanguage:nn {#1}
}
}
%-------------------------------------------------------------------------------------------------------------------
% \DefineLanguageDependentMacro{<macro>}{<parameters>}{%
% key-val-list with definition-text for each language
% }%
\NewDocumentCommand \DefineLanguageSpecificMacro {mO{}om}{
\cs_if_exist:NTF{#1}{%
\group_begin:
\cs_set:Nn \msg_error_text:n {Macro~\exp_args:Nc \token_to_str:N {##1}~Error}
\msg_error:nnxx {DefineLanguageSpecificMacro}{command-already-defined}{\token_to_str:N #1 }{ \token_to_str:N \DefineLanguageSpecificMacro }
\group_end:
}{
\group_begin:
\bool_set_false:N \__SelectLanguageString_LanguageFound_bool
\keyval_parse:NNn \__SelectLanguageString_Define_LanguageDetect:n \__SelectLanguageString_LanguageDetect:nn {#4}
\bool_if:NTF \__SelectLanguageString_LanguageFound_bool {
\group_end:
\group_begin:
\tl_set:Nn \l_tmpa_tl {\group_end:}
\__SelectLanguageString_SwapArgs:nn{
\keyval_parse:NNn \__SelectLanguageString_SelectLanguage:n \__SelectLanguageString_SelectLanguage:nn {#4}
}
}{
\group_end:
\group_begin:
\tl_set:Nn \l_tmpa_tl {\group_end:}
\__SelectLanguageString_SwapArgs:nn{
\keyval_parse:NNn \__SelectLanguageString_SelectOtherLanguage:n \__SelectLanguageString_SelectOtherLanguage:nn {#4}
}
}
{
\IfNoValueTF{#3}{
\str_case:nnTF{#2}{
{0} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {} { \cs_set_protected:Npn }}
{1} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {##1} { \cs_set_protected:Npn }}
{2} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {##1##2} { \cs_set_protected:Npn }}
{3} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {##1##2##3} { \cs_set_protected:Npn }}
{4} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {##1##2##3##4} { \cs_set_protected:Npn }}
{5} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {##1##2##3##4##5} { \cs_set_protected:Npn }}
{6} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {##1##2##3##4##5##6} { \cs_set_protected:Npn }}
{7} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {##1##2##3##4##5##6##7} { \cs_set_protected:Npn }}
{8} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {##1##2##3##4##5##6##7##8} { \cs_set_protected:Npn }}
{9} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {##1##2##3##4##5##6##7##8##9} { \cs_set_protected:Npn }}
{} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {} { \cs_set_protected:Npn }}
{~} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {} { \cs_set_protected:Npn }}
}
}{
\str_case:nnTF{#2}{
{0} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {{+O{#3}}} {\NewDocumentCommand}}
{1} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {{+O{#3}}} {\NewDocumentCommand}}
{2} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {{+O{#3}+m}} {\NewDocumentCommand}}
{3} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {{+O{#3}+m+m}} {\NewDocumentCommand}}
{4} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {{+O{#3}+m+m+m}} {\NewDocumentCommand}}
{5} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {{+O{#3}+m+m+m+m}} {\NewDocumentCommand}}
{6} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {{+O{#3}+m+m+m+m+m}} {\NewDocumentCommand}}
{7} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {{+O{#3}+m+m+m+m+m+m}} {\NewDocumentCommand}}
{8} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {{+O{#3}+m+m+m+m+m+m+m}} {\NewDocumentCommand}}
{9} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {{+O{#3}+m+m+m+m+m+m+m+m}} {\NewDocumentCommand}}
{} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {#3} { \cs_set_protected:Npn }}
{~} {\__SelectLanguageString_DefineMacroDefiner:Nnn #1 {#3} { \cs_set_protected:Npn }}
}
}
{}{
\cs_set:Nn \msg_error_text:n {Macro~\exp_args:Nc \token_to_str:N {##1}~Error}
\msg_error:nn {DefineLanguageSpecificMacro}{IncorrectParameterText}
}
}
\tl_use:N \l_tmpa_tl
}
}
\ExplSyntaxOff
\DefineLanguageSpecificMacro{\SomeLanguageSpecificMacro}[1]{%
english={This is in English and this is the argument: \textbf{#1}},
french={Ceci est en français et voici l'argument: \textbf{#1}},
german={Dies ist auf deutsch und das ist das Argument: \textbf{#1}},
other language={Ĉi tio estas en Esperanto kaj jen la argumento: \textbf{#1}},
}%
\begin{document}
\section*{Curriculum Vitae}
\noindent
\texttt{\string\SomeLanguageSpecificMacro: \meaning\SomeLanguageSpecificMacro}
\bigskip\noindent
\SomeLanguageSpecificMacro{Argument}
\bigskip\noindent
2020--2023: \SelectLanguageString{%
english=PhD student,
french=Étudiant doctoral,
german=Doktorand,
other language=Doktoriĝanto,
}%
\end{document}