用一种语言或另一种语言生成文档的模式

用一种语言或另一种语言生成文档的模式

他是我的问题:我需要更新许多文件(简历、研究陈述、研究项目、摘要列表等),并随时准备提交申请,有时非常匆忙。但是,根据我发送文件的地方,语言会发生变化,我会以这样或那样的方式一遍又一遍地翻译。我想避免这种情况,并停止在大量基本相同内容的副本之间来回切换。

有没有办法定义一种“模式”(比如“英语”或“德语”或“法语”),在一个文件中用两种语言写入内容,例如

\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}

在此处输入图片描述

相关内容