babelshorthand“= 不适用于 BibLaTeX?

babelshorthand“= 不适用于 BibLaTeX?

我使用带有软件包的 LaTeXbabelbiblatex经常处理我主要以德语为基础的文档。

最近,我为所有 BibTeX 条目添加了类似的注释,只要条目引用了 TeXLive 发行版提供的 PDF 文档即可。翻译成英文后,注释内容如下:

note={Part of the online documentation of TeXLive distribution, file
      \url{<filename>.pdf}},

这是我使用的德语文本:

note={Bestandteil der Online"=Dokumentation von \TeXLive, 
      Datei \url{<filename>.pdf}},

我添加了在或语言"=中启用的babel 简写 。但即使我用 来包装注释文本,我也无法像我预期的那样将简写替换为普通连字符。germanngerman\foreignlanguage{ngerman}{...}

如果我用普通连字符替换它,第二个单词“Dokumentation”就不会再被 LaTeX 破坏,因此通常会导致错误overfull hbox

这是一个 MWE(当然是德语)。

\documentclass[english,ngerman]{scrartcl}

\usepackage[style=numeric]{biblatex}
\usepackage{babel}
\usepackage{csquotes}
\usepackage{dtk-logos}

\addbibresource{\jobname.bib}

\begin{filecontents}{\jobname.bib}
@Manual{class:scrguide,
  title      = {KOMA-Script},
  author     = {Kohm, Markus},
  month      = May,
  year       = 2016,
  url        = {http://www.komascript.de/~mkohm/scrguide.pdf},
  langid     = {ngerman},
  note       = {Bestandteil der Online"=Dokumentation von
                  \TeXLive, Datei \url{scrguide.pdf}},
  keywords   = {manual},
}
\end{filecontents}


\begin{document}
Der Eintrag~\cite{class:scrguide} aus meiner
Literatur"=Datenbank erscheint im Quellen"=Verzeichnis leider mit
einem \verb|"=| in der Ausgabe.

\printbibliography%

\end{document}

"=(亲爱的德国读者:请忽略上面例子中速记的愚蠢例子。它们被插入是为了证明它们被正常的连字符所取代。)

这是输出:

在此处输入图片描述

如何解决这一困境?

答案1

多年来,法语、德语、荷兰语等语言中广泛使用活动字符,并且不时会产生一些令人讨厌的副作用。使用 TeX 或 pdfTeX 引擎时,您必须忍受它们。

幸运的是,LuaTeX 提供了一些工具来摆脱它们,我为 babel-french 做了同样的事,并查看了你的报告,该报告遵循了 (丹尼斯·比图泽), 我决定检查德语 dblquote 是否也可以在 LuaTeX 中保持非活动状态。

我编写了以下“dblquote.sty”文件作为“概念证明”;它似乎可以工作,但由于我不是德语母语人士,我无法判断这个 Lua 代码(改进后)是否可以替换 (n)german.ldf 文件中的当前代码。

要尝试一下,只需在序言中添加 \usepackage{dblquote},并在 \begin{document} 之后添加一行 \shorthandoff{"}。

\ProvidesPackage{dblquote}
                [2021/07/04 v.0.01 Daniel Flipo]
\NeedsTeXFormat{LaTeX2e}[2021/06/01]
\ifdefined\directlua
  \RequirePackage{luatexbase,luacode}
\else
  \PackageError{This package is meant for LuaTeX only! Aborting}
               {No more information available, sorry!}
\fi
\newattribute\DQ     \DQ=1 \relax
\newattribute\toss   \toss=0 \relax
\ifluatex
  \def\mdqon{\DQ=1\relax}
  \def\mdqoff{\DQ=0\relax}
%\else
%  \def\mdqon{\shorthandon{"}}
%  \def\mdqoff{\shorthandoff{"}}
\fi

\begin{luacode}
  dblquote = { }
  local DQ            = luatexbase.attributes['DQ']
  local toss          = luatexbase.attributes['toss']
  local has_attribute = node.has_attribute
  local traverse_id   = node.traverse_id
  local remove        = node.remove
  local insert_before = node.insert_before
  local insert_after  = node.insert_after
  local current_attr  = node.current_attr
  local new_node      = node.new
  local copy_node     = node.copy
  local copy_list     = node.copy_list
  local node_id       = node.id
  local DISC          = node_id("disc")
  local HLIST         = node_id("hlist")
  local GLUE          = node_id("glue")
  local GLYPH         = node_id("glyph")
  local KERN          = node_id("kern")
  local PENALTY       = node_id("penalty")
  local nobreak       = new_node(PENALTY,0)
  nobreak.penalty     = 10000
  local hskip0        = new_node(GLUE,0)

-- Replace "a with ä etc.
dblquote.replace = function (head)
  local t = { }
    t[string.byte("'")] = 0x201C
    t[0x2019]           = 0x201C    -- quoteright (Ligatures=TeX)
    t[string.byte("`")] = 0x201E
    t[0x2018]           = 0x201E    -- quoteleft  (Ligatures=TeX)
    t[string.byte("<")] = 0x00AB
    t[string.byte(">")] = 0x00BB
    t[string.byte("A")] = 0x00C4
    t[string.byte("a")] = 0x00E4
    t[string.byte("E")] = 0x00CB
    t[string.byte("e")] = 0x00EB
    t[string.byte("I")] = 0x00CF
    t[string.byte("i")] = 0x00EF
    t[string.byte("O")] = 0x00D6
    t[string.byte("o")] = 0x00F6
    t[string.byte("U")] = 0x00DC
    t[string.byte("u")] = 0x00FC
    t[string.byte("S")] = 0x0053
    t[string.byte("Z")] = 0x005A
  for item in traverse_id(GLYPH, head) do
    local lang = item.lang
    local char = item.char
    local DQon = has_attribute(item, DQ)
    DQon = DQon and DQon > 0
    local tossON = has_attribute(item, toss)
    tossON = tossON and tossON > 0
    if (lang == DE or lang == DEn) and DQon and
       (char == 0x201D or char == 0x22) then
       local next  = item.next
       local nchar = next.char
       if tossON then
          t[string.byte("s")] = string.byte("s")
          t[string.byte("z")] = string.byte("z")
       else
          t[string.byte("s")] = 0x00DF
          t[string.byte("z")] = 0x00DF
       end
       if t[nchar] then
          next.char = t[nchar]
          if t[nchar] == string.byte("s") or t[nchar] == string.byte("z") then
             item.char = string.byte("s")
          elseif t[nchar] == string.byte("S") or t[nchar] == string.byte("Z") then
             item.char = string.byte("S")
          else
             head = remove(head,item)
          end
       end
    end
  end
  return head
end
-- Hyphenation and ligatures
dblquote.disc = function (head)
  local to = { }
    to[string.byte("f")] = true
    to[string.byte("F")] = true
    to[string.byte("l")] = true
    to[string.byte("L")] = true
    to[string.byte("m")] = true
    to[string.byte("M")] = true
    to[string.byte("n")] = true
    to[string.byte("N")] = true
    to[string.byte("p")] = true
    to[string.byte("P")] = true
    to[string.byte("r")] = true
    to[string.byte("R")] = true
    to[string.byte("t")] = true
    to[string.byte("T")] = true
 for item in node.traverse_id(GLYPH, head) do
    local lang = item.lang
    local char = item.char
    local DQon = has_attribute(item, DQ)
    DQon = DQon and DQon > 0
    if DQon and (char == 0x201D or char == 0x22) then
       -- traditionnal German only
       if lang == DE then
          local n  = item.next
          local nn  = n.next
          local nchar = n.char
          local prev  = item.prev
          -- "ck and "CK
          if nchar == string.byte("c") or nchar == string.byte("C") then
             head = remove(head,n)
             head = remove(head,item)
             -- building d.pre looks clumsy, to be improved!
             local pre = new_node(HLIST,0)
             local hyph = copy_node(nn)
             hyph.char = string.byte("-")
             local first = copy_node(nn)
             local second = copy_node(hyph)
             pre.head = first
             first.next = second
             second.next = nil
             ----------------------------------------------
             local d = new_node(DISC,0)
             d.attr = current_attr()
             d.penalty = tex.hyphenpenalty
             d.pre = copy_list(first)
             d.replace = copy_node(n)
             insert_after(head,prev,copy_node(d))
             insert_after(head,prev,copy_node(nobreak))
             insert_before(head,nn,copy_node(nobreak))
             insert_before(head,nn,copy_node(hskip0))
          -- all others "ff, "FF, etc.
          elseif to[nchar] and nn.char and nn.char == n.char then
             head = remove(head,n)
             head = remove(head,item)
             local d = new_node(DISC,0)
             d.attr = current_attr()
             d.penalty = tex.hyphenpenalty
             -- building d.pre looks clumsy, to be improved!
             local pre = new_node(HLIST,0)
             local hyph = copy_node(nn)
             hyph.char = string.byte("-")
             local first, second, third
             -- "f is special
             if nchar == string.byte("f") then
                local ff = copy_node(n)
                ff.char = 0xFB00            -- ligature "ff"
                first = copy_node(ff)
                second = copy_node(hyph)
                second.next = nil
                d.post = copy_node(n)
                d.replace = copy_node(ff)
                head = remove(head,nn)
             else
                first = copy_node(n)
                second = copy_node(n)
                third = copy_node(hyph)
                third.next = nil
                d.replace = copy_node(n)
             end
             pre.head = first
             first.next = second
             second.next = third
             --
             d.attr = current_attr()
             d.pre = copy_list(first)
             d.penalty = tex.hyphenpenalty
             insert_after(head,prev,copy_node(hskip0))
             insert_after(head,prev,copy_node(nobreak))
             insert_after(head,prev,copy_node(d))
             insert_after(head,prev,copy_node(nobreak))
          end
       end
       -- modern and traditionnal German
       if lang == DE or lang == DEn then
          local n  = item.next
          local nchar
          if n.id == GLYPH then
             nchar = n.char
          elseif n.id == PENALTY then   -- n = node ~
             nchar = 1
          end
          local prev  = item.prev
          if nchar == string.byte("-") then
             local d = new_node(DISC,0)
             d.attr = current_attr()
             d.penalty = tex.hyphenpenalty
             local hyph = copy_node(n)
             hyph.char = string.byte("-")
             d.pre = copy_node(hyph)
             head = remove(head,n)
             head = remove(head,item)
             insert_after(head,prev,copy_node(hskip0))
             insert_after(head,prev,copy_node(nobreak))
             insert_after(head,prev,copy_node(d))
             insert_after(head,prev,copy_node(nobreak))
          elseif nchar == string.byte("|") then
             local d = new_node(DISC,0)
             d.attr = current_attr()
             d.penalty = tex.hyphenpenalty
             local hyph = copy_node(n)
             hyph.char = string.byte("-")
             d.pre = copy_node(hyph)
             local k = new_node(KERN,1)
             k.attr = current_attr()
             k.kern = 20000
             d.replace = copy_node(k)
             head = remove(head,n)
             head = remove(head,item)
             insert_after(head,prev,copy_node(hskip0))
             insert_after(head,prev,copy_node(nobreak))
             insert_after(head,prev,copy_node(d))
             insert_after(head,prev,copy_node(nobreak))
          elseif nchar == string.byte('"') then
             head = remove(head,n)
             head = remove(head,item)
             insert_after(head,prev,copy_node(hskip0))
          elseif nchar == 1 then    -- ("~)
             local hyph = copy_node(item)
             hyph.char = string.byte("-")
             head = remove(head,n.next)
             head = remove(head,n)
             head = remove(head,item)
             insert_after(head,prev,copy_node(nobreak))
             insert_after(head,prev,copy_node(hyph))
          elseif nchar == string.byte("=") then
             local hyph = copy_node(n)
             hyph.char = string.byte("-")
             head = remove(head,n)
             head = remove(head,item)
             insert_after(head,prev,copy_node(hskip0))
             insert_after(head,prev,copy_node(hyph))
             insert_after(head,prev,copy_node(nobreak))
          elseif nchar == string.byte("/") then
             local d = new_node(DISC,0)
             d.attr = current_attr()
             d.penalty = tex.hyphenpenalty
             local slash = copy_node(n)
             slash.char = string.byte("/")
             d.pre = copy_node(slash)
             d.replace = copy_node(slash)
             head = remove(head,n)
             head = remove(head,item)
             insert_after(head,prev,copy_node(hskip0))
             insert_after(head,prev,copy_node(nobreak))
             insert_after(head,prev,copy_node(d))
             insert_after(head,prev,copy_node(hskip0))
             insert_after(head,prev,copy_node(nobreak))
          end
       end
    end
  end
  return head
end
return dblquote.replace, dblquote.disc
\end{luacode}

\directlua{%
   DE = \the\l@german ;
   DEn = \the\l@ngerman ;
   luatexbase.add_to_callback
           ("pre_linebreak_filter",dblquote.disc,"discretionary",1)
   luatexbase.add_to_callback
           ("pre_linebreak_filter",dblquote.replace,"replace",1)
   luatexbase.add_to_callback
           ("hpack_filter",dblquote.replace,"replace")
  }

\endinput`

相关内容