ConTeXt 中如何当语言切换时切换字体?

ConTeXt 中如何当语言切换时切换字体?

我有一份主要由英文组成的文档,其字体定义如下:

\usemodule[simplefonts]
\setmainfont[MinionPro-Regular]
\setsansfont[MyriadPro-Bold]

有时候需要出现一些中文,使用\language[cn]{},由于上述字体没有中文,所以当主字体中间出现中文时,需要它暂时切换到 Adob​​e Song Std,当在使用 sans 字体的地方出现中文时,需要它暂时切换到 Adob​​e Heiti Std。

  • 如何设置 ConTeXt 在切换到其他语言时自动切换字体?

答案1

如何设置 ConTeXt 在切换到其他语言时自动切换字体? 这里可能存在误解,不知道它\language[foo]到底起什么作用。它改变了当前的连字规则,但绝不是切换到另一种脚本和/或字体。

因此,您的问题至少可以用两种方式来解释:

  1. 一旦完成了,您希望能够使用另一个脚本\language[...]
  2. 您需要一个通用的语言环境切换。

第一种方案最好使用字体回退即使没有命令也可以工作\language。这可以被认为是一种廉价而简单的解决方案。第二种方法乍一看可能更复杂,但它与整体界面完美集成,并且可以根据需要扩展其他语言相关功能(文本方向、音译、强调等)。

下面的例子将使用俄语进行演示但应该适用于任何定义的语言。


后备方法:首先,我们需要一个用于替换的代码点范围列表,在本例中是四个已定义的西里尔字母范围。列表中的第一个已经涵盖了当代俄语,但没有理由不彻底一点。

  • 0x0400:0x04ff 西里尔文
  • 0x0500:0x052f 西里尔文补充
  • 0x2de0:0x2dff 西里尔扩展 A
  • 0xa640:0xa69f 西里尔扩展 B

他们是在上下文中预定义这样我们就可以直呼其名。无论如何,明确地称呼他们也无妨。

在示例中,我们将从计算机现代 Unicode这与 Latin Modern 非常接近。(CMU 字体是 TEX Live 的一部分。)对于四种变体中的每一种常规的斜体大胆的加粗斜体衬线字体需要不同的后备字体,因为我们希望 Context 替换相应 CMU 字体的字形。之后,后备字体就可以在我们的 TypeScript 中使用了,这里的名称为主字体

\definefontfallback [cyrillic_regular]    [name:CMUSerifRoman]
                    [0x0400:0x04ff,0x0500:0x052f,0x2de0:0x2dff,0xa640:0xa69f] [force=yes]
\definefontfallback [cyrillic_bold]       [name:CMUSerifBold]
                    [0x0400:0x04ff,0x0500:0x052f,0x2de0:0x2dff,0xa640:0xa69f] [force=yes]
\definefontfallback [cyrillic_italic]     [name:CMUSerifItalic]
                    [0x0400:0x04ff,0x0500:0x052f,0x2de0:0x2dff,0xa640:0xa69f] [force=yes]
\definefontfallback [cyrillic_bolditalic] [name:CMUSerifBoldItalic]
                    [0x0400:0x04ff,0x0500:0x052f,0x2de0:0x2dff,0xa640:0xa69f] [force=yes]

%% Now we hook the fallbacks into their respective type faces.
\starttypescript [serif] [mainfont]
  \setups[font:fallback:serif]
  \definefontsynonym [Serif]           [name:Latin Modern Roman]             [fallbacks=cyrillic_regular]
  \definefontsynonym [SerifBold]       [name:Latin Modern Roman Bold]        [fallbacks=cyrillic_bold]
  \definefontsynonym [SerifItalic]     [name:Latin Modern Roman Italic]      [fallbacks=cyrillic_italic]
  \definefontsynonym [SerifBoldItalic] [name:Latin Modern Roman Bold Italic] [fallbacks=cyrillic_bolditalic]
\stoptypescript

%% Complete the typescript for all four type faces. Note that we default
%% to the predefined Latin Modern setups for the three other faces.
\starttypescript [mainfont]
 \definetypeface [mainfont] [rm] [serif] [mainfont]     [default]
 \definetypeface [mainfont] [ss] [sans]  [latin-modern] [default]
 \definetypeface [mainfont] [tt] [mono]  [latin-modern] [default]
 \definetypeface [mainfont] [mm] [math]  [latin-modern] [default]
\stoptypescript

%% Finally, we are ready to activate the typescript.
\setupbodyfont [mainfont,20pt]

\starttext

English {\italic English} {\bold English} {\bolditalic English}

\language[ru] %% does only switch the hyphenation pattern
             Маленький мальчик нашел пулемет. Больше в деревне никто не живет. \par
{\italic     Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
{\bold       Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
{\bolditalic Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par

\stoptext

示例输出


宏方法:对于偶尔出现的外来词,只需切换字体和连字符模式即可,但多语言排版通常会有进一步的要求,例如法语的不同间距约定。因此,可以根据需求扩展的宏具有很大的价值。下面的清单给出了\definelazylanguage随附的上下文样式宏生成器的骨架代码\setuplazylanguage。它允许定义以这种基本形式处理模式和字体切换的命令。所有定义都将创建(1)一个普通宏\foo{...}和(2)补充\startfoo/\stopfoo环境。它们接受可选的第一个参数(当然在括号中)用于本地设置。

编辑:仅供\installnamespace参考\installcorenamespace使这一切成为可能的目前居住在多重辅助.mkiv,请参阅那里以获取更多文档。

另一项编辑:以下代码片段已根据 Wolfgang 刚刚发给我的一组修复进行了修改。(非常感谢!)它不仅纠正了分组错误,而且比以前的版本更有效地利用了命名空间功能。

% macros=mkvi
\unprotect
\installnamespace                        {lazylanguage}
\installcommandhandler \????lazylanguage {lazylanguage} \????lazylanguage

\appendtoks
  \setuevalue        {\currentlazylanguage}{\lazylanguage_direct[\currentlazylanguage]}%
  \setuevalue{\e!start\currentlazylanguage}{\lazylanguage_start [\currentlazylanguage]}%
  \setuevalue{\e!stop \currentlazylanguage}{\lazylanguage_stop                        }%
\to \everydefinelazylanguage

\unexpanded\def\lazylanguage_direct[#id]%
  {\edef\currentlazylanguage{#id}%
   \dosingleempty\lazylanguage_direct_indeed}

\def\lazylanguage_direct_indeed[#options]%
  {\groupedcommand
     {\lazylanguage_start_indeed[#options]}%
     \donothing}

\unexpanded\def\lazylanguage_start[#id]%
  {\bgroup
   \edef\currentlazylanguage{#id}%
   \dosingleempty\lazylanguage_start_indeed}

% %% This is the macro that implements the core switching functionality.
\def\lazylanguage_start_indeed[#options]%
  {\iffirstargument
     \setupcurrentlazylanguage[#options]%
   \fi
   %% Here would be the place where you can hook further language
   %% settings into your command, imitating the pattern of below
   %% expressions.
   \language[\lazylanguageparameter{patterns}]
   \doifsomething{\lazylanguageparameter{bodyfont}}
    {\switchtobodyfont[\lazylanguageparameter{bodyfont}]}}

\let\lazylanguage_stop\egroup
\protect

\definelazylanguage [lru]
\setuplazylanguage  [lru] [
  bodyfont=antykwa,
  patterns=ru,
]

\startlru
             Маленький мальчик нашел пулемет. Больше в деревне никто не живет. \par
{\italic     Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
{\bold       Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
{\bolditalic Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
\stoplru

English {\italic English} {\bold English} {\bolditalic English}

\stoptext

示例输出 2 请注意,代码乍一看可能令人困惑,但这是因为多层包装,所以它实际上是一个功能 =)。您需要了解的是,真正的操作发生在宏内部\lazylanguage_start_indeed,您可以根据以下方案随时挂钩进一步的参数:

\doifsomething{\lazylanguageparameter{<parametername>}}
  {\lazylanguageparameter{<parametername>}}%

只需<parametername>用您选择的钥匙替换假人,您就可以在设置中使用它。

相关内容