|
|
\NeedsTeXFormat{LaTeX2e}
|
|
|
\ProvidesPackage{polyglossia}[2020/04/08 v1.49
|
|
|
Modern multilingual typesetting with XeLaTeX and LuaLaTeX]
|
|
|
\RequirePackage{etoolbox}
|
|
|
\RequirePackage{makecmds}
|
|
|
\RequirePackage{xkeyval}[2008/08/13]
|
|
|
% Will raise error if used with anything else than XeTeX or LuaTeX
|
|
|
\RequirePackage{fontspec}[2010/06/08]% v2.0
|
|
|
% Ironically, ifluatex.sty is included by some other package if we run
|
|
|
% LuaTeX, but it's not if we run XeTeX, and we need it to know which of
|
|
|
% the two engines it is! Hence we include it here.
|
|
|
\RequirePackage{ifluatex}
|
|
|
% For symmetry with ifluatex
|
|
|
\RequirePackage{ifxetex}
|
|
|
\RequirePackage{expl3}
|
|
|
\RequirePackage{l3keys2e}
|
|
|
\RequirePackage{xparse}
|
|
|
\RequirePackage{filehook}
|
|
|
|
|
|
% correct a bug in tracklang
|
|
|
\AtBeginOfPackageFile*{tracklang}{
|
|
|
\@ifpackagelater{tracklang}{2019/08/30}{}{\global\def\AddTrackedLangage{\AddTrackedLanguage}}
|
|
|
}
|
|
|
|
|
|
|
|
|
% fontspec now uses LaTeX3 packages such as expl3, so we need this:
|
|
|
\ExplSyntaxOn
|
|
|
|
|
|
%% This is for compatibility with Babel-aware package:
|
|
|
\cslet{ver@babel.sty}{\@empty} % this "fakes" babel
|
|
|
\def\languageshorthands#1{\relax} %this is for scrlttr2 class
|
|
|
\def\bbl@cs#1{\csname bbl@#1\endcsname}%
|
|
|
\AtEndPreamble{\let\bbl@set@language\xpg@set@language@aux} %for biblatex
|
|
|
\AtEndPreamble{\let\bbl@main@language\xpg@main@language} %for biblatex
|
|
|
|
|
|
\ifluatex
|
|
|
\RequirePackage{luatexbase} % already included by fontspec, but needed here
|
|
|
\RequireLuaModule{polyglossia}
|
|
|
\fi
|
|
|
|
|
|
% Which version of XeTeX do we use? What is the boudary class? 4095 or 255
|
|
|
\@ifundefined{e@alloc@intercharclass@top}
|
|
|
{\chardef\xpg@boundaryclass=\@cclv}
|
|
|
{\let\xpg@boundaryclass=\e@alloc@intercharclass@top}
|
|
|
|
|
|
% Useful for getting list of loaded languages and variants. Like babel's bbl@loaded
|
|
|
\let\xpg@loaded\@empty% list of loaded languages (polyglossia name)
|
|
|
\let\xpg@vloaded\@empty% list of loaded variants
|
|
|
\let\xpg@bloaded\@empty% list of loaded languages (babel name)
|
|
|
\let\xpg@bcp@loaded\@empty% list of loaded languages (bcp-47 id)
|
|
|
|
|
|
% counter in latin
|
|
|
\def\latinalph#1{\expandafter\latin@alph\csname c@#1\endcsname}
|
|
|
\def\latinAlph#1{\expandafter\latin@Alph\csname c@#1\endcsname}
|
|
|
|
|
|
% select language hook
|
|
|
\cs_new_nopar:Nn \polyglossia@AtBeginDocument@selectlanguage: {}
|
|
|
% \disablehyphenation hook
|
|
|
\cs_new_nopar:Nn \polyglossia@AtBeginDocument@hyphenation: {}
|
|
|
|
|
|
% hook to be executed at begin of document
|
|
|
\cs_new_nopar:Nn \polyglossia@AtBeginDocument: {
|
|
|
% save various command
|
|
|
\let\latin@alph\@alph % TODO rename when we have the C locale
|
|
|
\let\latin@Alph\@Alph % TODO rename when we have the C locale
|
|
|
% push to C language gloss
|
|
|
\let\polyglossia@Clang@@arabic\@arabic
|
|
|
\let\polyglossia@Clang@arabic\arabic
|
|
|
|
|
|
\xpg@initial@setup
|
|
|
% apply \familydefault changes
|
|
|
\xpg@set@familydefault
|
|
|
}
|
|
|
|
|
|
\AtBeginDocument{
|
|
|
\polyglossia@AtBeginDocument:
|
|
|
}
|
|
|
|
|
|
% The following needs to go after any \AtBeginDocument (also of packages
|
|
|
% loaded after \set[main|other]language
|
|
|
\AfterEndPreamble{
|
|
|
% now we have the C locale definition: select the language
|
|
|
\polyglossia@AtBeginDocument@selectlanguage:
|
|
|
% If hyphenation disabling has been requested in preamble, do it now
|
|
|
\polyglossia@AtBeginDocument@hyphenation:
|
|
|
}
|
|
|
|
|
|
%% custom message macros
|
|
|
\providecommand*{\xpg@error}[1]{%
|
|
|
\PackageError{polyglossia}{#1}{}%
|
|
|
}
|
|
|
|
|
|
\providecommand*{\xpg@warning}[1]{%
|
|
|
\PackageWarning{polyglossia}{#1}%
|
|
|
}
|
|
|
|
|
|
\providecommand*{\xpg@info}[1]{%
|
|
|
\PackageInfo{polyglossia}%
|
|
|
{#1\@gobble}%
|
|
|
} %% the \@gobble is to prevent displaying the line nr
|
|
|
|
|
|
%TODO change all instances of \xpg@nopatterns in gloss-*.ldf files
|
|
|
\providecommand*{\xpg@nopatterns@fallback}[2][nohyphenation]{%
|
|
|
\xpg@warning{No~ hyphenation~ patterns~ were~ loaded~ for~ `#2'\MessageBreak
|
|
|
I~ will~ use~ \string\language=\string\l@ #1\space instead}%
|
|
|
\expandafter\adddialect\csname l@#2\expandafter\endcsname\csname l@#1\endcsname\relax}
|
|
|
|
|
|
\providecommand*{\xpg@nopatterns}[1]{%
|
|
|
\xpg@warning{No~ hyphenation~ patterns~ were~ loaded~ for~ `#1'\MessageBreak
|
|
|
I~ will~ use~ \string\language=\string\l@nohyphenation\space instead}%
|
|
|
%%TODO? \expandafter\adddialect\csname l@#1\endcsname\l@nohyphenation\relax
|
|
|
}
|
|
|
|
|
|
\def\xpg@ill@value#1#2{%
|
|
|
\xpg@warning{Illegal~ value~ (#1)~ for~ #2}}
|
|
|
|
|
|
% error out if lang is not loaded
|
|
|
\cs_new_nopar:Nn \polyglossia@error@iflangnotloaded:n
|
|
|
{
|
|
|
\cs_if_exist:cF{#1@loaded}
|
|
|
{
|
|
|
\xpg@error{language~ #1~ is~ not~ loaded.~ Please~ load~ it~ before~ using~ it.}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
% error do not use directly the gloss file
|
|
|
\msg_new:nnn { polyglossia } { directloadgloss }
|
|
|
{
|
|
|
You~ should~ not~ load~ directly~ the~ gloss~ file~ using~ `\string\usepackage'.
|
|
|
You~ must~ use~ `\string\setotherlanguage\{#1\}' or `\string\setmainlanguage\{#1\}'.
|
|
|
}
|
|
|
\msg_redirect_name:nnn { polyglossia } { directloadgloss } { critical }
|
|
|
|
|
|
%% use macro if defined, else warn that it is not
|
|
|
\def\csuse@warn#1{%
|
|
|
\ifcsundef{#1}{\xpg@warning{ \expandafter\string\csname #1\endcsname\space is~ not~ defined}}%
|
|
|
{\csname #1\endcsname}}
|
|
|
|
|
|
%% ensure directionality if bidi is loaded, else ignore
|
|
|
\def\@@ensure@dir#1{\ifcsundef{@ensure@dir}{#1}{\@ensure@dir{#1}}}
|
|
|
\def\@@ensure@maindir#1{\ifcsundef{@ensure@maindir}{#1}{\@ensure@maindir{#1}}}
|
|
|
|
|
|
%% Used by the language definitions files for right-to-left languages
|
|
|
\def\RequireBidi{%
|
|
|
\str_case_e:nnF{\c_sys_engine_str}{
|
|
|
{luatex}{\ifx\@onlypreamble\@notprerr\else\RequirePackage{luabidi}\fi}
|
|
|
{xetex}{\ifx\@onlypreamble\@notprerr\else\RequirePackage{bidi}\fi}
|
|
|
}
|
|
|
{
|
|
|
\xpg@warning{You’re running a TeX engine that is not LuaTeX or XeTeX.\MessageBreak
|
|
|
That is almost guaranteed to cause problems.}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% (lua)bidi commands to change directionality for paragraphs
|
|
|
% and inline text.
|
|
|
% overwritten with correct package
|
|
|
\cs_new_nopar:Nn{\polyglossia@setpardirection:n}{%
|
|
|
\str_case_e:nnTF{#1}{%
|
|
|
{LR}{\relax}%
|
|
|
{RL}{\xpg@error{right-to-left,~ but~ (lua)bidi~ package~ was~ not~ loaded!}}%
|
|
|
}%
|
|
|
{}%
|
|
|
{\xpg@error{Unknown~ language~ direction~ #1 ~(base~ wrapper)}}%
|
|
|
}
|
|
|
\cs_new_nopar:Nn{\polyglossia@settextdirection:n}{%
|
|
|
\str_case_e:nnTF{#1}{%
|
|
|
{LR}{\relax}%
|
|
|
{RL}{\xpg@error{right-to-left,~ but~ (lua)bidi~ package~ was~ not~ loaded!}}%
|
|
|
}%
|
|
|
{}%
|
|
|
{\xpg@error{Unknown~ language~ direction~ #1 ~(base~ wrapper)}}%
|
|
|
}
|
|
|
\AtEndOfPackageFile*{bidi}{%
|
|
|
\ExplSyntaxOn%
|
|
|
\cs_gset_nopar:Nn{\polyglossia@setpardirection:n}{%
|
|
|
\str_case_e:nnTF{#1}{%
|
|
|
{LR}{\setLR}%
|
|
|
{RL}{\setRL}%
|
|
|
}%
|
|
|
{}%
|
|
|
{\xpg@error{Unknown~ language~ direction~ #1 ~(bidi~ wrapper)}}%
|
|
|
}%
|
|
|
\cs_gset_nopar:Nn{\polyglossia@settextdirection:n}{%
|
|
|
\str_case_e:nnTF{#1}{%
|
|
|
{LR}{\LRE}%
|
|
|
{RL}{\RLE}%
|
|
|
}%
|
|
|
{}%
|
|
|
{\xpg@error{Unknown~ language~ direction~ #1 ~(bidi~ wrapper)}}%
|
|
|
}%
|
|
|
\ExplSyntaxOff%
|
|
|
}
|
|
|
\AtEndOfPackageFile*{luabidi}{%
|
|
|
\ExplSyntaxOn%
|
|
|
\cs_gset_nopar:Nn{\polyglossia@setpardirection:n}{%
|
|
|
\str_case_e:nnTF{#1}{%
|
|
|
{LR}{\setLR}%
|
|
|
{RL}{\setRL}%
|
|
|
}
|
|
|
{}%
|
|
|
{\xpg@error{Unknown~ language~ direction~ #1 ~(luabidi~ wrapper)}}%
|
|
|
}%
|
|
|
\cs_gset_nopar:Nn{\polyglossia@settextdirection:n}{%
|
|
|
\str_case_e:nnTF{#1}{%
|
|
|
{LR}{\LRE}%
|
|
|
{RL}{\RLE}%
|
|
|
}
|
|
|
{}%
|
|
|
{\xpg@error{Unknown~ language~ direction~ #1 ~(luabidi~ wrapper)}}%
|
|
|
}%
|
|
|
\ExplSyntaxOff%
|
|
|
}
|
|
|
|
|
|
%% compatibility with babel
|
|
|
\let\addto\gappto% gappto is defined in etoolbox
|
|
|
|
|
|
%% NEW EXPERIMENTAL SETUP INTERFACE FOR GLOSS FILES
|
|
|
%% options currently available:
|
|
|
%% language : the name of the language (as understood by fontspec)
|
|
|
%% hyphennames : the different hyphenation patterns to try (comma separated list)
|
|
|
%%% TODO: if pattern is prefixed by !, then it should be loaded as a fallback, with \xpg@nopatterns@fallback - i.e. with a warning: e.g. sanskrit for hindi, or catalan for asturian. – Also for languages with variants! (English and German, etc.)
|
|
|
%% script : the name of the script (as understood by fontspec) – default is Latin
|
|
|
%% scripttag : the OpenType tag for the script
|
|
|
%% langtag : the OpenType tag for the language
|
|
|
%% hyphenmins : the hyphenmins for this language (comma-sep list of two integers)
|
|
|
%% frenchspacing : boolean
|
|
|
%% indentfirst : boolean
|
|
|
%% fontsetup : boolean
|
|
|
%% TODO: nouppercase : boolean (for scripts like Arabic, Devanagari, etc which have no concept of uppercase/lowercase)
|
|
|
%% TODO: localalph = {<alph_csname>,<Alph_csname>}
|
|
|
%% TODO: localnumeral = <csname>
|
|
|
%% or even better localdigits = {0123456789} for fully automatic setup
|
|
|
\newif\if@xpg@language@really@defined@
|
|
|
\newcommand*\PolyglossiaSetup[2]{%
|
|
|
\polyglossia@keys_define_lang:n{#1}%
|
|
|
\keys_set:nn { polyglossia / #1 } { #2 }%
|
|
|
\prop_log:N{\polyglossia@langsetup}
|
|
|
\polyglossia_setup_hyphen:n {#1}
|
|
|
%define booleans etoolbox style and set defaults
|
|
|
%% TODO ? \providetoggle{#1@setup@done}%
|
|
|
% we initialize these so that we can use \gappto below
|
|
|
\csgdef{init@extras@#1}{}%
|
|
|
\csgdef{init@noextras@#1}{}% we don't use this yet: remove?
|
|
|
% here we do the fontsetup:
|
|
|
\polyglossia@lang@autosetupfont:n{#1}
|
|
|
%% TODO? \toggletrue{#1@setup@done}%
|
|
|
% reinit \do
|
|
|
\def\do##1{\setotherlanguage{##1}}%
|
|
|
}
|
|
|
|
|
|
% Adjust language key setting after initial setup
|
|
|
% This is needed, e.g., for languages with varying script
|
|
|
\DeclareDocumentCommand \SetLanguageKeys { m m }
|
|
|
{
|
|
|
\clist_map_inline:nn { #1 } { \keys_set:nn { polyglossia / ##1 } { #2 } }
|
|
|
}
|
|
|
|
|
|
|
|
|
% setup hyphennames from a str list of hyphen
|
|
|
\cs_new:Nn \polyglossia_setup_hyphen:n {
|
|
|
\exp_args:Nne \clist_set:Nn{\l_tmpa_clist}{\prop_item:Nn \polyglossia@langsetup {#1 / hyphennames}}
|
|
|
\providebool{havehyphen}
|
|
|
\boolfalse{havehyphen}
|
|
|
% for each hyphen in the set until we find one that works
|
|
|
\clist_map_inline:Nn \l_tmpa_clist {
|
|
|
\ifbool{havehyphen}{}{%
|
|
|
% check if language hyphenname is defined
|
|
|
\polyglossia@check@ifdefined:NF{#1}{%
|
|
|
% if not, first consider nohyphenation
|
|
|
\str_if_eq:nnTF{##1}{nohyphenation}
|
|
|
{%
|
|
|
\cs_gset_eq:cc{l@#1}{l@##1}
|
|
|
\global\booltrue{havehyphen}
|
|
|
}{%
|
|
|
% then test if hyphenation is defined
|
|
|
\xpg@ifdefined{##1}{
|
|
|
% test if language hyphenation is nohyphenation
|
|
|
\cs_if_eq:cNF{l@#1}{\l@nohyphenation}{\global\booltrue{havehyphen}}{%
|
|
|
% if false define language to hyphenation if it is not equal...
|
|
|
\str_if_eq:nnF{#1}{##1}{\cs_gset_eq:cc{l@#1}{l@##1}}
|
|
|
% ...and load
|
|
|
\xpg@set@hyphenation@patterns{##1}
|
|
|
\global\booltrue{havehyphen}
|
|
|
}%
|
|
|
}{}%
|
|
|
}%
|
|
|
}%
|
|
|
}%
|
|
|
}%
|
|
|
% if l@#1 does not yet exist,
|
|
|
% we assign it to nohyphenation
|
|
|
% we do this here in case and if the hyphennames key was omitted
|
|
|
\ifbool{havehyphen}{}{%
|
|
|
\xpg@ifdefined{#1}{}%
|
|
|
{
|
|
|
\xpg@nopatterns{#1}
|
|
|
\expandafter\adddialect\csname l@#1\endcsname\l@nohyphenation\relax
|
|
|
}%
|
|
|
}%
|
|
|
\csdef{#1@language}{%
|
|
|
\polyglossia@setup@language@patterns{#1}%
|
|
|
}%
|
|
|
% setup hyphenmins
|
|
|
\exp_args:NNe \clist_set:Nn \l_tmpa_clist
|
|
|
{ \prop_item:Nn \polyglossia@langsetup {#1 / hyphenmins} }
|
|
|
\cs_if_eq:cNF {l@#1} \l@nohyphenation
|
|
|
{
|
|
|
\use:x
|
|
|
{
|
|
|
\exp_not:N \setlocalhyphenmins {#1}
|
|
|
{ \clist_item:Nn \l_tmpa_clist {1} }
|
|
|
{ \clist_item:Nn \l_tmpa_clist {2} }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
\newcommand*\polyglossia@setup@language@patterns[1]{%
|
|
|
\ifbool{xpg@hyphenation@disabled}{%
|
|
|
\xdef\xpg@lastlanguage{\the\csname l@#1\endcsname}%
|
|
|
}{%
|
|
|
% first, test if \l@#1 exists
|
|
|
% without that, \csname l@#1\endcsname will be defined as \relax
|
|
|
\cs_if_exist:cTF {l@#1}
|
|
|
{
|
|
|
\cs_if_eq:cNTF {l@#1} \l@nohyphenation
|
|
|
{
|
|
|
\language=\l@nohyphenation
|
|
|
}
|
|
|
{
|
|
|
\xpg@set@hyphenation@patterns{#1}
|
|
|
}
|
|
|
}
|
|
|
{%
|
|
|
% Since this function is sometimes called from the gloss files
|
|
|
% directly, we need to check whether the requested hyphenname exists.
|
|
|
\xpg@ifdefined{#1}{}%
|
|
|
{%
|
|
|
\xpg@nopatterns{#1}
|
|
|
\expandafter\adddialect\csname l@#1\endcsname\l@nohyphenation\relax%
|
|
|
}%
|
|
|
\xpg@set@hyphenation@patterns{#1}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
\prop_new:N \polyglossia@langsetup
|
|
|
|
|
|
\cs_new_protected:Npn \polyglossia@keys_define_lang:n #1 {
|
|
|
\keys_define:nn {polyglossia}{
|
|
|
% the script font
|
|
|
#1 / script
|
|
|
.code:n = {
|
|
|
\prop_gput:Nnn{\polyglossia@langsetup}{#1/script}{##1}
|
|
|
\prop_gput:Nnx{\polyglossia@langsetup}{#1/lcscript}
|
|
|
{\tl_if_empty:nF{##1}{\str_lowercase:n##1}}
|
|
|
},
|
|
|
#1 / script
|
|
|
.value_required:n = true,
|
|
|
#1 / script
|
|
|
.initial:n = latin,
|
|
|
% the opentype script tag
|
|
|
#1 / scripttag
|
|
|
.code:n = {\prop_gput:Nnn{\polyglossia@langsetup}{#1/scripttag}{##1}},
|
|
|
#1 / scripttag
|
|
|
.default:n = {},
|
|
|
#1 / scripttag
|
|
|
.initial:n = {},
|
|
|
% the language full name
|
|
|
#1 / language
|
|
|
.code:n = {\prop_gput:Nnn{\polyglossia@langsetup}{#1/language}{##1}},
|
|
|
#1 / language
|
|
|
.value_required:n = true,
|
|
|
#1 / language
|
|
|
.initial:x = {\str_upper_case:n#1},
|
|
|
% the language tag
|
|
|
#1 / langtag
|
|
|
.code:n = {\prop_gput:Nnn{\polyglossia@langsetup}{#1/langtag}{##1}},
|
|
|
#1 / langtag
|
|
|
.value_required:n = true,
|
|
|
#1 / langtag
|
|
|
.initial:n = {},
|
|
|
% the BCP-47 tag
|
|
|
#1 / bcp47
|
|
|
.code:n = {\prop_gput:Nnn{\polyglossia@langsetup}{#1/bcp47}{##1}},
|
|
|
#1 / bcp47
|
|
|
.value_required:n = true,
|
|
|
#1 / bcp47
|
|
|
.initial:n = {},
|
|
|
% hyphennames
|
|
|
#1 / hyphennames
|
|
|
.code:n = {
|
|
|
\clist_set:Nn{\l_tmpa_clist}{##1}
|
|
|
\prop_gput:Nnx{\polyglossia@langsetup}{#1/hyphennames}{\clist_use:Nn \l_tmpa_clist {,}}
|
|
|
},
|
|
|
#1 / hyphennames
|
|
|
.value_required:n = true,
|
|
|
#1 / hyphennames
|
|
|
.initial:x = {\c_empty_clist},
|
|
|
% direction
|
|
|
#1 / direction
|
|
|
. code:n = {
|
|
|
\str_case_e:nnTF{##1}{
|
|
|
{LR}{}
|
|
|
{RL}{\RequireBidi}
|
|
|
}
|
|
|
{\prop_gput:Nnn{\polyglossia@langsetup}{#1/direction}{##1}}
|
|
|
{\xpg@error{Unknown~ direction~ "##1"~ for~ language~ "#1"}}
|
|
|
},
|
|
|
#1 / direction
|
|
|
.value_required:n = true,
|
|
|
#1 / direction
|
|
|
.initial:n = {LR},
|
|
|
% minimal left and right hyphenation minima using
|
|
|
#1 / hyphenmins
|
|
|
.code:n = {
|
|
|
% check syntax
|
|
|
\int_compare:nNnF { \clist_count:n {##1} } = {2}
|
|
|
{\xpg@error{hypenmins~should~be~a~list~of~two~entries,~got~"##1"}}
|
|
|
% set prop
|
|
|
\prop_gput:Nnn \polyglossia@langsetup {#1/hyphenmins} {##1}
|
|
|
},
|
|
|
#1 / hyphenmins
|
|
|
.value_required:n = true,
|
|
|
#1 / hyphenmins
|
|
|
.initial:n = {2,3},
|
|
|
% minimal length for hyphenation (LuaTeX only)
|
|
|
#1 / totalhyphenmin
|
|
|
.code:n = {
|
|
|
% check syntax
|
|
|
\int_compare:nNnF { \clist_count:n {##1} } = {1}
|
|
|
{\xpg@error{totalhyphenhypenmin~should~be~a~single~entry,~got~"##1"}}
|
|
|
% set prop
|
|
|
\prop_gput:Nnn \polyglossia@langsetup {#1/totalhyphenmin} {##1}
|
|
|
},
|
|
|
#1 / totalhyphenmin
|
|
|
.value_required:n = false,
|
|
|
% frenchspacing
|
|
|
#1 / frenchspacing
|
|
|
.code:n = {
|
|
|
\str_case_e:nnTF{##1}{
|
|
|
{true}{}
|
|
|
{false}{}
|
|
|
}
|
|
|
{}
|
|
|
{\xpg@error{frenchspacing~should~be~true~or~false. Is~ "##1"~ for~ language~ "#1"}}
|
|
|
\prop_gput:Nnn{\polyglossia@langsetup}{#1/frenchspacing}{##1}
|
|
|
},
|
|
|
#1 / frenchspacing
|
|
|
.default:n = true,
|
|
|
#1 / frenchspacing
|
|
|
.initial:n = false,
|
|
|
% indent first line
|
|
|
#1 / indentfirst
|
|
|
.code:n = {
|
|
|
\str_case_e:nnTF{##1}{
|
|
|
{true}{}
|
|
|
{false}{}
|
|
|
}
|
|
|
{}
|
|
|
{\xpg@error{indentfirst~should~be~true~or~false. Is~ "##1"~ for~ language "#1"}}
|
|
|
\prop_gput:Nnn{\polyglossia@langsetup}{#1/indentfirst}{##1}
|
|
|
},
|
|
|
#1 / indentfirst
|
|
|
.default:n = true,
|
|
|
#1 / indentfirst
|
|
|
.initial:n = false,
|
|
|
% fontsetup
|
|
|
#1 / fontsetup
|
|
|
.code:n = {
|
|
|
\str_case_e:nnTF{##1}{
|
|
|
{true}{}
|
|
|
{false}{}
|
|
|
}
|
|
|
{}
|
|
|
{\xpg@error{fontsetup~should~be~true~or~false. Is "##1"~ for~ language~ "#1"}}
|
|
|
\prop_gput:Nnn{\polyglossia@langsetup}{#1/fontsetup}{##1}
|
|
|
},
|
|
|
#1 / fontsetup
|
|
|
.default:n = true,
|
|
|
#1 / fontsetup
|
|
|
.initial:n = false,
|
|
|
% environment name
|
|
|
#1 / envname
|
|
|
.code:n = {
|
|
|
\prop_gput:Nnn{\polyglossia@langsetup}{#1/envname}{##1}
|
|
|
},
|
|
|
#1/ envname.value_required:n = true,
|
|
|
#1/ envname.initial:n = {#1},
|
|
|
% babel name
|
|
|
#1 / babelname
|
|
|
.code:n = {
|
|
|
\prop_gput:Nnn{\polyglossia@langsetup}{#1/babelname}{##1}
|
|
|
},
|
|
|
#1/ babelname.value_required:n = true,
|
|
|
#1/ babelname.initial:n = {#1},
|
|
|
% default numerals
|
|
|
#1 / localnumeral
|
|
|
. code:n = {
|
|
|
\prop_gput:Nnn{\polyglossia@langsetup}{#1/localnumeral}{##1}
|
|
|
\prop_gput:Nnn{\polyglossia@langsetup}{#1/Localnumeral}{##1}
|
|
|
},
|
|
|
#1 / localnumeral.value_required:n = true,
|
|
|
#1 / localnumeral.initial:n = {polyglossia@C@localnumeral},
|
|
|
% uppercased
|
|
|
#1 / Localnumeral
|
|
|
. code:n = {
|
|
|
\prop_gput:Nnn{\polyglossia@langsetup}{#1/Localnumeral}{##1}
|
|
|
},
|
|
|
#1 / Localnumeral.value_required:n = true,
|
|
|
#1 / Localnumeral.initial:n = {polyglossia@C@localnumeral}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% TODO move to C module
|
|
|
\newcommand*{\polyglossia@C@localnumeral}[2]{
|
|
|
\polyglossia@Clang@@arabic{#2}
|
|
|
}
|
|
|
|
|
|
% print using main language
|
|
|
% #2 is the numeral to print
|
|
|
% #3 is the mainlanguage (should be expanded)
|
|
|
% #4 is the current language (should be expanded)
|
|
|
% #1 is the option list (should be expanded)
|
|
|
% #5 is the name of the field to use
|
|
|
\cs_new:Nn \polyglossia_localnumeral_mainlang:nnnnn {
|
|
|
\foreignlanguage{#3}{\use:c {\prop_item:Nn \polyglossia@langsetup {#3/#5}} {#1} {#2}}
|
|
|
}
|
|
|
|
|
|
|
|
|
% print using local language
|
|
|
% #2 is the numeral to print
|
|
|
% #3 is the mainlanguage (should be expanded)
|
|
|
% #4 is the current language (should be expanded)
|
|
|
% #1 is the option list (should be expanded)
|
|
|
% #5 is the name of the field to use
|
|
|
\cs_new:Nn \polyglossia_localnumeral_locallang:nnnnn {
|
|
|
\use:c {\prop_item:Nn \polyglossia@langsetup {#4/#5}} {#1} {#2}
|
|
|
}
|
|
|
|
|
|
% this function try to resolve some simple parameter about lang
|
|
|
% call #2 then branching if found
|
|
|
% call parameter #3 if not found
|
|
|
% (use curing)
|
|
|
\cs_new:Npn \polyglossia_localnumeral_callshortcutorlong:nF #1#2 {
|
|
|
\str_case:nnF{#1}{
|
|
|
{lang=local}{\polyglossia_localnumeral_locallang:nnnnn}
|
|
|
}
|
|
|
{#2}
|
|
|
}
|
|
|
|
|
|
\cs_new:Npn \polyglossia_iii_map_csv_field_split_kv_iii_localnumeral:w #1 = #2 \q_stop {
|
|
|
\str_case:nnF{#2}{
|
|
|
{local} {\clist_map_break:n{\use_i:nn \polyglossia_localnumeral_locallang:nnnnn }}
|
|
|
{default}{\clist_map_break:n{\use_i:nn \polyglossia_localnumeral_locallang:nnnnn }}
|
|
|
{*} {\clist_map_break:n{\use_i:nn\polyglossia_localnumeral_mainlang:nnnnn }}
|
|
|
{main} {\clist_map_break:n{\use_i:nn\polyglossia_localnumeral_mainlang:nnnnn }}
|
|
|
}{
|
|
|
\clist_map_break:n{ \use_i_ii:nnn \polyglossia_localnumeral_langlang:nnnnnn {{#2}} }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
% call the language
|
|
|
% #3 is the numeral to print
|
|
|
% #4 is the mainlanguage (should be expanded)
|
|
|
% #5 is the current language (should be expanded)
|
|
|
% #2 is the option list (should be expanded)
|
|
|
% #6 is the name of the field to use
|
|
|
% #1 is the language used
|
|
|
\cs_new:Nn \polyglossia_localnumeral_langlang:nnnnnn {
|
|
|
\foreignlanguage{#1}{\use:c {\prop_item:Nn \polyglossia@langsetup {#1/#6}} {#2} {#3}}
|
|
|
}
|
|
|
|
|
|
|
|
|
% check if empty value
|
|
|
\cs_new:Npn \polyglossia_iii_map_csv_field_split_kv_ii_localnumeral:w #1 #2 = #3 \q_stop {
|
|
|
\quark_if_no_value:NTF {#3}
|
|
|
{
|
|
|
\clist_map_break:n{\use_i:nn \polyglossia_localnumeral_locallang:nnnnn}
|
|
|
}
|
|
|
{
|
|
|
\polyglossia_iii_map_csv_field_split_kv_iii_localnumeral:w #1 \q_stop
|
|
|
}
|
|
|
}
|
|
|
|
|
|
\cs_new:Npn \polyglossia_iii_map_csv_field_split_kv_i_localnumeral:nw #1 #2 = #3 \q_stop {
|
|
|
% parse only lang tag
|
|
|
\tl_trim_spaces_apply:nN {#2} \str_if_eq:nnT {lang}
|
|
|
{
|
|
|
% if empty value
|
|
|
\quark_if_nil:nTF{#3}
|
|
|
{
|
|
|
\clist_map_break:n{\use_i:nn \polyglossia_localnumeral_locallang:nnnn}
|
|
|
}
|
|
|
{
|
|
|
% here we know what we have an equal sign
|
|
|
\polyglossia_iii_map_csv_field_split_kv_ii_localnumeral:w {#1} #1 \q_no_value \q_stop
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% map function
|
|
|
\cs_new:Nn \polyglossia_iii_map_csv_localnumeral:n {
|
|
|
% fast case is do nothing is empty
|
|
|
\tl_if_empty:nF{#1}
|
|
|
{
|
|
|
\polyglossia_iii_map_csv_field_split_kv_i_localnumeral:nw {#1} #1 = \q_nil \q_stop
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
% treat option is empty and option is lang=local
|
|
|
% #2 number
|
|
|
% #3 mainlanguage
|
|
|
% #4 locallanguage
|
|
|
% #5 field to call
|
|
|
% #1 option
|
|
|
% strip space to option
|
|
|
\cs_new:Nn \polyglossia_iii_localnumeral:nnnnn {
|
|
|
\tl_if_blank:nTF{#1}
|
|
|
{
|
|
|
\polyglossia_localnumeral_mainlang:nnnnn
|
|
|
}
|
|
|
{
|
|
|
\str_if_eq:nnTF{#1}{lang=local}
|
|
|
{
|
|
|
\polyglossia_localnumeral_locallang:nnnnn
|
|
|
}
|
|
|
{
|
|
|
% use postscript like trick push to stack {#1} {#2} {#3} {#4}
|
|
|
\polyglossia_localnumeral_callshortcutorlong:nF {#1}
|
|
|
{
|
|
|
% same trick here if found we emit \use_i:nn
|
|
|
% thus discarding the default choice that is not lang specified thus local
|
|
|
\clist_map_function:nN {#1} {\polyglossia_iii_map_csv_localnumeral:n}
|
|
|
\polyglossia_localnumeral_locallang:nnnnn
|
|
|
}
|
|
|
}
|
|
|
{#1} {#2} {#3} {#4} {#5}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
% internal helper useful for oeee and onnn
|
|
|
% #1 number
|
|
|
% #2 mainlanguage
|
|
|
% #3 locallanguage
|
|
|
% #4 option
|
|
|
% #5 field to call
|
|
|
% strip space to option
|
|
|
\cs_new:Nn \polyglossia_ii_localnumeral:nnnnn {
|
|
|
\tl_trim_spaces_apply:nN {#4} \polyglossia_iii_localnumeral:nnnnn {#1}{#2}{#3}{#5}
|
|
|
}
|
|
|
\cs_generate_variant:Nn \polyglossia_ii_localnumeral:nnnnn {
|
|
|
eeenn, eeeon, eeeen
|
|
|
}
|
|
|
|
|
|
% convert the counter to value
|
|
|
% #1 counter
|
|
|
% #2 mainlanguage
|
|
|
% #3 locallanguage
|
|
|
% #4 option
|
|
|
\cs_new:Nn \polyglossia_i_localnumeral:nnnnn
|
|
|
{
|
|
|
\polyglossia_ii_localnumeral:eeeen {\int_value:w #1} {#2} {#3} {#4} {#5}
|
|
|
}
|
|
|
|
|
|
% print number usage \localnumeral[option]{numeral}
|
|
|
% or \localnumeral*[option]{counter}
|
|
|
% \Localnumeral[]{numeral} use main language
|
|
|
% \localnumeral{numeral} use local language
|
|
|
\NewExpandableDocumentCommand{\localnumeral}{som}
|
|
|
{
|
|
|
\IfBooleanTF{#1}%
|
|
|
{% starred: take counter
|
|
|
\exp_args:Nc \polyglossia_i_localnumeral:nnnnn {c@#3}
|
|
|
{\mainlanguagename} {\languagename} {\IfNoValueTF {#2}{lang=local}{#2}} {localnumeral}
|
|
|
}{% unstarred: take number
|
|
|
\polyglossia_ii_localnumeral:eeeen {\int_eval:n{#3}}
|
|
|
{\mainlanguagename} {\languagename} {\IfNoValueTF {#2}{lang=local}{#2}} {localnumeral}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% print number usage \Localnumeral[option]{numeral}
|
|
|
% or \Localnumeral*[option]{counter}
|
|
|
% \Localnumeral[]{numeral} use main language
|
|
|
% \localnumeral{numeral} use local language
|
|
|
\NewExpandableDocumentCommand{\Localnumeral}{som}
|
|
|
{
|
|
|
\IfBooleanTF{#1}%
|
|
|
{% starred: take counter
|
|
|
\exp_args:Nc \polyglossia_i_localnumeral:nnnnn {c@#3}
|
|
|
{\mainlanguagename} {\languagename} {\IfNoValueTF {#2}{lang=local}{#2}} {Localnumeral}
|
|
|
}{% unstarred: take number
|
|
|
\polyglossia_ii_localnumeral:eeeon {\int_eval:n{#3}}
|
|
|
{\mainlanguagename} {\languagename} {\IfNoValueTF {#2}{lang=local}{#2}} {Localnumeral}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
\cs_new_nopar:Nn{\polyglossia@lang@frenchspacing:n}{
|
|
|
\prop_get:NxNTF \polyglossia@langsetup {#1/frenchspacing} \l_tmpa_tl
|
|
|
{
|
|
|
\str_case_e:nnF{\l_tmpa_tl}{
|
|
|
{true}{\frenchspacing}
|
|
|
{false}{\nonfrenchspacing}
|
|
|
}
|
|
|
{\xpg@error{frenchspacing~should~be~true~or~false. Is~"\l_tmpa_ttl"~ for~ language~ "#1"}}
|
|
|
}
|
|
|
{
|
|
|
\xpg@error{Could~ not~ retrieve~ key~ frenchspacing~ for~ language~ "#1"}
|
|
|
\prop_show:N{\polyglossia@langsetup}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
\cs_new_nopar:Nn{\polyglossia@lang@indentfirst:n}{
|
|
|
\prop_get:NxNTF \polyglossia@langsetup {#1/indentfirst} \l_tmpa_tl
|
|
|
{
|
|
|
\str_case_e:nnF{\l_tmpa_tl}{
|
|
|
{true}{\french@indent}
|
|
|
{false}{\nofrench@indent}
|
|
|
}
|
|
|
{\xpg@error{indentfirst~should~be~true~or~false. Is~"\l_tmpa_ttl"~ for~ language~ "#1"}}
|
|
|
}
|
|
|
{
|
|
|
\xpg@error{Could~ not~ retrieve~ key~ indentfirst~ for~ language~ "#1"}
|
|
|
\prop_show:N{\polyglossia@langsetup}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
\cs_new:Nn{\polyglossia@lang@setpardirection:n}{
|
|
|
\prop_get:NxNTF \polyglossia@langsetup {#1/direction} \l_tmpa_tl
|
|
|
{
|
|
|
\polyglossia@setpardirection:n{\l_tmpa_tl}
|
|
|
}
|
|
|
{
|
|
|
\xpg@error{Could~ not~ retrieve~ key~ direction~ for~ language~ "#1"}
|
|
|
\prop_show:N{\polyglossia@langsetup}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
\cs_new:Nn{\polyglossia@lang@settextdirection:nn}{
|
|
|
\prop_get:NxNTF \polyglossia@langsetup {#1/direction} \l_tmpa_tl
|
|
|
{
|
|
|
\polyglossia@settextdirection:n{\l_tmpa_tl}{#2}
|
|
|
}
|
|
|
{
|
|
|
\xpg@error{Could~ not~ retrieve~ key~ direction~ for~ language~ "#1"}
|
|
|
\prop_show:N{\polyglossia@langsetup}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
\AtEndDocument{\prop_log:N{\polyglossia@langsetup}}
|
|
|
\def\xpg@lastlanguage{0}%
|
|
|
|
|
|
\providebool{xpg@hyphenation@disabled}%
|
|
|
\boolfalse{xpg@hyphenation@disabled}
|
|
|
|
|
|
\def\xpg@disablehyphenation{%
|
|
|
\ifx\@onlypreamble\@notprerr%
|
|
|
\xpg@@disablehyphenation%
|
|
|
\else%
|
|
|
% if this is used in the preamble, we have to postpone
|
|
|
% the execution until the main language has been set (#125).
|
|
|
\cs_gset_nopar:Nn \polyglossia@AtBeginDocument@hyphenation: {
|
|
|
\xpg@@disablehyphenation%
|
|
|
}%
|
|
|
\fi%
|
|
|
}
|
|
|
|
|
|
\def\xpg@@disablehyphenation{%
|
|
|
\ifbool{xpg@hyphenation@disabled}{}{%
|
|
|
\booltrue{xpg@hyphenation@disabled}%
|
|
|
\xdef\xpg@lastlanguage{\the\language}%
|
|
|
% We do not call \xpg@set@hyphenation@patterns here to avoid a warning message.
|
|
|
% "nohyphenation" is not listed in language.dat.lua.
|
|
|
\language=\l@nohyphenation%
|
|
|
}%
|
|
|
}
|
|
|
|
|
|
\def\xpg@enablehyphenation{%
|
|
|
\ifbool{xpg@hyphenation@disabled}{%
|
|
|
\boolfalse{xpg@hyphenation@disabled}%
|
|
|
\language=\csname xpg@lastlanguage\endcsname%
|
|
|
}{}%
|
|
|
}
|
|
|
|
|
|
\let\disablehyphenation\xpg@disablehyphenation
|
|
|
\let\enablehyphenation\xpg@enablehyphenation
|
|
|
|
|
|
%\def\xpg@fontsetup#1{\xpg@csifdef@warn{xpg@fontsetup@#1}}
|
|
|
%\def\xpg@fontsetup@none#1{\csgdef{#1@font}{\ifcsdef{#1font}{\csname #1font\endcsname}{}}} %<-- simplistic
|
|
|
%\def\xpg@fontsetup@custom#1{\csuse{#1@font}}
|
|
|
|
|
|
\cs_new:Nn \polyglossia@lang@autosetupfont:n {
|
|
|
\str_if_eq:eeTF{\prop_item:Nn{\polyglossia@langsetup}{#1/fontsetup}}{true}
|
|
|
{
|
|
|
\str_if_eq:eeTF{\prop_item:Nn{\polyglossia@langsetup}{#1/lcscript}}{latin}%
|
|
|
{\xpg@fontsetup@latin{#1}}
|
|
|
{\xpg@fontsetup@nonlatin{#1}}
|
|
|
}
|
|
|
{
|
|
|
\xpg@info{Skipping~ automatic~ font~ setup~ for~ language~ #1}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
% add fontfeature Language=#2 to langtag #1
|
|
|
% do nothing if #1 or #2 is empty
|
|
|
\cs_new:Nn \polyglossia@addfontfeature@language:nn {
|
|
|
\bool_if:nTF{\tl_if_empty_p:n{#1} || \tl_if_empty_p:n{#2}}
|
|
|
{
|
|
|
% maybe an error ?
|
|
|
\xpg@warning{Asking~ to~ add~ empty~ feature~to~ latin~ font~
|
|
|
(Language="#2"~ to~ langtag~ "#1")}
|
|
|
}
|
|
|
{
|
|
|
\str_if_eq:nnTF{#2}{Turkish}{
|
|
|
\fontspec_if_language:nTF {TRK}%
|
|
|
{
|
|
|
\addfontfeature{Language=Turkish}
|
|
|
}
|
|
|
{
|
|
|
\fontspec_if_language:nTF {TUR}%
|
|
|
{
|
|
|
\addfontfeature{Language=Turkish}
|
|
|
}{}
|
|
|
}
|
|
|
}{
|
|
|
\fontspec_if_language:nTF{#1}
|
|
|
{
|
|
|
\addfontfeature{Language=#2}
|
|
|
}
|
|
|
{}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
\cs_generate_variant:Nn \polyglossia@addfontfeature@language:nn { on , no, oo , Vn, nV, VV , xn, nx, xx}
|
|
|
|
|
|
% add fontfeature Script=#2 to scripttag #1
|
|
|
% do nothing if #1 or #2 is empty
|
|
|
\cs_new:Nn \polyglossia@addfontfeature@script:nn {
|
|
|
\bool_if:nTF{\tl_if_empty_p:n{#1} || \tl_if_empty_p:n{#2}}
|
|
|
{
|
|
|
% maybe an error ?
|
|
|
\xpg@warning{Asking~ to~ add~ empty~ feature~to~ latin~ font
|
|
|
(Script="#2"~ to~ scripttag~ "#1")}
|
|
|
}
|
|
|
{
|
|
|
\fontspec_if_script:nTF{#1}
|
|
|
{\addfontfeature{Script=#2}}
|
|
|
{\xpg@error{
|
|
|
The~ current~ latin ~ font~ \l_fontspec_family_tl\space does~ not~ contain~ the~"#2"~ script!\MessageBreak
|
|
|
Please~ define~\csname\tl_if_empty:nF{#2}{\str_lowercase:n#2}font\endcsname~
|
|
|
with~ \string\newfontfamily\space command
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
\cs_generate_variant:Nn \polyglossia@addfontfeature@script:nn { on , no, oo , Vn, nV, VV , xn, nx, xx}
|
|
|
|
|
|
\def\xpg@fontsetup@latin#1{%
|
|
|
\begingroup
|
|
|
\csgdef{#1@font@rm}{%
|
|
|
\cs_if_exist_use:cF{#1font}{
|
|
|
\rmfamilylatin
|
|
|
\polyglossia@addfontfeature@language:xx{\prop_item:Nn{\polyglossia@langsetup}{#1/langtag}}
|
|
|
{\prop_item:Nn{\polyglossia@langsetup}{#1/language}}
|
|
|
}
|
|
|
}
|
|
|
\csgdef{#1@font@sf}{%
|
|
|
\cs_if_exist_use:cF{#1fontsf}{
|
|
|
\sffamilylatin
|
|
|
\polyglossia@addfontfeature@language:xx{\prop_item:Nn{\polyglossia@langsetup}{#1/langtag}}
|
|
|
{\prop_item:Nn{\polyglossia@langsetup}{#1/language}}
|
|
|
}%
|
|
|
}%
|
|
|
\csgdef{#1@font@tt}{%
|
|
|
\cs_if_exist_use:cF{#1fonttt}{
|
|
|
\ttfamilylatin
|
|
|
\polyglossia@addfontfeature@language:xx{\prop_item:Nn{\polyglossia@langsetup}{#1/langtag}}
|
|
|
{\prop_item:Nn{\polyglossia@langsetup}{#1/language}}
|
|
|
}%
|
|
|
}%
|
|
|
\endgroup
|
|
|
}
|
|
|
|
|
|
\def\xpg@fontsetup@nonlatin#1{%
|
|
|
\begingroup
|
|
|
\csgdef{#1@font@rm}{%
|
|
|
\cs_if_exist_use:cF{#1font}
|
|
|
{
|
|
|
\providetoggle{#1@use@script@font}%
|
|
|
\str_if_eq:nnTF{\prop_item:Nn{\polyglossia@langsetup}{#1/script}}{\prop_item:Nn{\polyglossia@langsetup}{#1/language}}
|
|
|
{\rmfamilylatin}%
|
|
|
{\cs_if_exist_use:cTF{\prop_item:Nn{\polyglossia@langsetup}{#1/lcscript} font}
|
|
|
{
|
|
|
\toggletrue{#1@use@script@font}%
|
|
|
}
|
|
|
{
|
|
|
\rmfamilylatin
|
|
|
}
|
|
|
}
|
|
|
\iftoggle{#1@use@script@font}{}{%
|
|
|
\polyglossia@addfontfeature@script:xx{\prop_item:Nn{\polyglossia@langsetup}{#1/scripttag}}
|
|
|
{\prop_item:Nn{\polyglossia@langsetup}{#1/script}}
|
|
|
}%
|
|
|
\polyglossia@addfontfeature@language:xx{\prop_item:Nn{\polyglossia@langsetup}{#1/langtag}}
|
|
|
{\prop_item:Nn{\polyglossia@langsetup}{#1/language}}
|
|
|
}}%
|
|
|
\csgdef{#1@font@sf}{%
|
|
|
\cs_if_exist_use:cF{#1fontsf}%
|
|
|
{
|
|
|
\providetoggle{#1@use@script@fontsf}%
|
|
|
\str_if_eq:nnTF{\prop_item:Nn{\polyglossia@langsetup}{#1/script}}{\prop_item:Nn{\polyglossia@langsetup}{#1/language}}
|
|
|
{\sffamilylatin}%
|
|
|
{\cs_if_exist_use:cTF{\prop_item:Nn{\polyglossia@langsetup}{#1/lcscript} fontsf}
|
|
|
{
|
|
|
\toggletrue{#1@use@script@fontsf}%
|
|
|
}
|
|
|
{
|
|
|
\sffamilylatin
|
|
|
}
|
|
|
}
|
|
|
\iftoggle{#1@use@script@fontsf}{}{%
|
|
|
\polyglossia@addfontfeature@script:xx{\prop_item:Nn{\polyglossia@langsetup}{#1/scripttag}}
|
|
|
{\prop_item:Nn{\polyglossia@langsetup}{#1/script}}
|
|
|
}%
|
|
|
\polyglossia@addfontfeature@language:xx{\prop_item:Nn{\polyglossia@langsetup}{#1/langtag}}
|
|
|
{\prop_item:Nn{\polyglossia@langsetup}{#1/language}}
|
|
|
}}%
|
|
|
\csgdef{#1@font@tt}{%
|
|
|
\cs_if_exist_use:cF{#1fonttt}%
|
|
|
{
|
|
|
\providetoggle{#1@use@script@fonttt}%
|
|
|
\str_if_eq:nnTF{\prop_item:Nn{\polyglossia@langsetup}{#1/script}}{\prop_item:Nn{\polyglossia@langsetup}{#1/language}}
|
|
|
{\ttfamilylatin}%
|
|
|
{\cs_if_exist_use:cTF{\prop_item:Nn{\polyglossia@langsetup}{#1/lcscript} fonttt}
|
|
|
{
|
|
|
\toggletrue{#1@use@script@fonttt}%
|
|
|
}
|
|
|
{
|
|
|
\ttfamilylatin
|
|
|
}
|
|
|
}
|
|
|
\iftoggle{#1@use@script@fonttt}{}{%
|
|
|
\polyglossia@addfontfeature@script:xx{\prop_item:Nn{\polyglossia@langsetup}{#1/scripttag}}
|
|
|
{\prop_item:Nn{\polyglossia@langsetup}{#1/script}}
|
|
|
}%
|
|
|
\polyglossia@addfontfeature@language:xx{\prop_item:Nn{\polyglossia@langsetup}{#1/langtag}}
|
|
|
{\prop_item:Nn{\polyglossia@langsetup}{#1/language}}
|
|
|
}}%
|
|
|
\endgroup
|
|
|
}
|
|
|
|
|
|
%%% END OF PolyglossiaSetup
|
|
|
|
|
|
%% ensure localization of \markright and \markboth commands
|
|
|
%%% THIS IS NOW DISABLED BY DEFAULT
|
|
|
\cs_new_nopar:Nn {\polyglossia@local@marks:n} {}
|
|
|
\cs_new_nopar:Nn {\polyglossia@enable@local@marks:}
|
|
|
{
|
|
|
\xpg@info{Option:~ localmarks}%
|
|
|
\cs_gset_nopar:Nn \polyglossia@local@marks:n
|
|
|
{%
|
|
|
\def\xpg@tmp@lang{##1}%
|
|
|
\DeclareRobustCommand\markboth[2]{%
|
|
|
\begingroup
|
|
|
\let\label\relax \let\index\relax \let\glossary\relax
|
|
|
\unrestored@protected@xdef\@themark
|
|
|
{%
|
|
|
{\lowercase{\foreignlanguage{\xpg@tmp@lang}}{\protect\@@ensure@maindir{####1}}}%
|
|
|
{\lowercase{\foreignlanguage{\xpg@tmp@lang}}{\protect\@@ensure@maindir{####2}}}%
|
|
|
}%
|
|
|
\@temptokena \expandafter{\@themark}%
|
|
|
\mark{\the\@temptokena}%
|
|
|
\endgroup
|
|
|
\if@nobreak\ifvmode\nobreak\fi\fi%
|
|
|
}%
|
|
|
\DeclareRobustCommand\markright[1]{%
|
|
|
\begingroup
|
|
|
\let\label\relax \let\index\relax \let\glossary\relax
|
|
|
\expandafter\@markright\@themark
|
|
|
{\lowercase{\foreignlanguage{\xpg@tmp@lang}}{\protect\@@ensure@maindir{####1}}}%
|
|
|
\@temptokena \expandafter{\@themark}%
|
|
|
\mark{\the\@temptokena}%
|
|
|
\endgroup
|
|
|
\if@nobreak\ifvmode\nobreak\fi\fi%
|
|
|
}%
|
|
|
% This part seems wrong (see #396 for explanation). Remove after a while.
|
|
|
% \def\@markright####1####2####3{%
|
|
|
% \@temptokena{\protect\@@ensure@maindir{####1}}%
|
|
|
% \unrestored@protected@xdef\@themark{%
|
|
|
% {\the\@temptokena}%
|
|
|
% {\protect\@@ensure@maindir{####3}}%
|
|
|
% }%
|
|
|
% }%
|
|
|
}%
|
|
|
}
|
|
|
|
|
|
|
|
|
% Easy way out – Arthur, 2012-08-01
|
|
|
\ifcsdef{newXeTeXintercharclass}{%
|
|
|
% to reset the intercharclass of a character to "normal"
|
|
|
\newXeTeXintercharclass\xpg@normalclass %TODO
|
|
|
}{}
|
|
|
|
|
|
\ifxetex
|
|
|
%% when no patterns are available, we use \l@nohyphenation, assigned to 255
|
|
|
%% (suggestion by Enrico Gregorio)
|
|
|
\@ifundefined{l@nohyphenation}{\chardef\l@nohyphenation=255 }{}
|
|
|
\else\ifluatex
|
|
|
\@ifundefined{l@nohyphenation}{\chardef\l@nohyphenation=\directlua{
|
|
|
tex.sprint(polyglossia.newloader_loaded_languages.nohyphenation)}\relax
|
|
|
}{}
|
|
|
\fi\fi
|
|
|
|
|
|
%we call this macro when a gloss file is not found for a given language
|
|
|
\def\xpg@nogloss#1{%
|
|
|
\xpg@warning{File~ gloss-#1.ldf~ does~ not~ exist!\MessageBreak
|
|
|
I~ will~ nevertheless~ try~ to~ use~ hyphenation~ patterns~ for~ #1.}%
|
|
|
\PolyglossiaSetup{#1}{hyphenmins,hyphennames={#1},fontsetup=true}%
|
|
|
% the above amounts to:
|
|
|
%\ifcsundef{l@#1}%
|
|
|
% {\expandafter\adddialect\csname l@#1\endcsname\l@nohyphenation\relax}%
|
|
|
% {\setlocalhyphenmins{#1}{2}{3}}%
|
|
|
%\csdef{#1@language}{\language=\csname l@#1\endcsname}%
|
|
|
}
|
|
|
|
|
|
\newcommand{\xpg@input}[1]{%
|
|
|
\chardef\xpg@atcatcode\catcode`\@
|
|
|
\makeatletter
|
|
|
\input{#1}\catcode`\@=\xpg@atcatcode}
|
|
|
|
|
|
% try to load a language file
|
|
|
\cs_new:Nn \polyglossia_load_lang_definition:nn {
|
|
|
\file_if_exist:nTF{gloss-#2.ldf}
|
|
|
{
|
|
|
\xpg@input{gloss-#2.ldf}
|
|
|
\setkeys{#2}{#1}
|
|
|
}
|
|
|
{
|
|
|
\xpg@nogloss{#2}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% load a master language from an alias file
|
|
|
\newcommand*\xpg@load@master@language[1] {
|
|
|
\xpg@input{gloss-#1.ldf}
|
|
|
\ifcsundef{#1@loaded}%
|
|
|
{
|
|
|
\exp_args:Nx\polyglossia@define@language@cmd:n{#1}%
|
|
|
}{}
|
|
|
\csgdef{#1@loaded}{}
|
|
|
\global\edef\xpg@loaded{#1\ifx\xpg@loaded\@empty\else,\xpg@loaded\fi}%
|
|
|
}
|
|
|
|
|
|
|
|
|
% define environment and command
|
|
|
\cs_new:Nn \polyglossia@define@language@cmd:n {
|
|
|
\ifcsundef{#1@alias@lang}{%
|
|
|
\exp_args:Ne
|
|
|
\newenvironment {\prop_item:Nn{\polyglossia@langsetup}{#1/envname}} [1] []
|
|
|
{
|
|
|
\begin{otherlanguage}[##1]{#1}
|
|
|
}%
|
|
|
{
|
|
|
\end{otherlanguage}
|
|
|
}%
|
|
|
\exp_args:Nc \newcommand {text#1} [2][]
|
|
|
{%
|
|
|
\xpg@textlanguage[##1]{#1}{##2}%
|
|
|
}%
|
|
|
}{}
|
|
|
}
|
|
|
|
|
|
% provide way to define alias environment and command
|
|
|
% \setlanguagealias[<options>]{<language>}{<alias>}
|
|
|
\DeclareDocumentCommand \setlanguagealias {s O{} m m}
|
|
|
{
|
|
|
% The starred version does not define commands and environments
|
|
|
\IfBooleanF {#1}
|
|
|
{
|
|
|
\ifcsundef{#4@alias@lang}{%
|
|
|
\exp_args:Ne
|
|
|
\newenvironment {#4}
|
|
|
{
|
|
|
\begin{otherlanguage}[#2]{#3}
|
|
|
}%
|
|
|
{
|
|
|
\end{otherlanguage}
|
|
|
}%
|
|
|
\exp_args:Nc \newcommand {text#4} [2][]
|
|
|
{%
|
|
|
\xpg@textlanguage[#2,##1]{#3}{##2}%
|
|
|
}%
|
|
|
}{%
|
|
|
\exp_args:Ne
|
|
|
\renewenvironment {#4}
|
|
|
{
|
|
|
\begin{otherlanguage}[#2]{#3}
|
|
|
}%
|
|
|
{
|
|
|
\end{otherlanguage}
|
|
|
}%
|
|
|
\exp_args:Nc \renewcommand {text#4} [2][]
|
|
|
{%
|
|
|
\xpg@textlanguage[#2,##1]{#3}{##2}%
|
|
|
}%
|
|
|
}%
|
|
|
}%
|
|
|
\csgdef{#4@alias@lang}{#3}%
|
|
|
\tl_if_blank:nF {#2} {\csgdef{#4@alias@opts}{#2}}%
|
|
|
}
|
|
|
|
|
|
\newcommand{\setdefaultlanguage}[2][]{%
|
|
|
\ifcsundef{#2@loaded}%
|
|
|
{
|
|
|
% latex is an internal language, so do not record
|
|
|
\ifstrequal{#2}{latex}{}{%
|
|
|
\global\edef\xpg@loaded{#2\ifx\xpg@loaded\@empty\else,\xpg@loaded\fi}%
|
|
|
\global\edef\xpg@bloaded{\prop_item:Nn{\polyglossia@langsetup}{#2/babelname}%
|
|
|
\ifx\xpg@bloaded\@empty\else,\xpg@bloaded\fi}%
|
|
|
\global\edef\xpg@bcp@loaded{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}%
|
|
|
\ifx\xpg@bcp@loaded\@empty\else,\xpg@bcp@loaded\fi}%
|
|
|
}%
|
|
|
\polyglossia_load_lang_definition:nn{#1}{#2}
|
|
|
% define environment and command (except for internal latex language)
|
|
|
\ifstrequal{#2}{latex}{}{%
|
|
|
\exp_args:Nx\polyglossia@define@language@cmd:n{#2}
|
|
|
}%
|
|
|
\csgdef{#2@loaded}{}%
|
|
|
}
|
|
|
{
|
|
|
\relax
|
|
|
}
|
|
|
\ifcsdef{#2@alias@lang}{%
|
|
|
\ifcsdef{#2@alias@opts}{%
|
|
|
\exp_args:Nxx \polyglossia_load_lang_definition:nn {\csuse{#2@alias@opts},#1} {\csuse{#2@alias@lang}}%
|
|
|
\exp_args:Nxx \polyglossia@set@default@language:nn {\csuse{#2@alias@opts},#1} {\csuse{#2@alias@lang}}%
|
|
|
}{%
|
|
|
\polyglossia@set@default@language:nn {#1} {\csuse{#2@alias@lang}}%
|
|
|
}%
|
|
|
}{%
|
|
|
\polyglossia@set@default@language:nn {#1} {#2}%
|
|
|
}%
|
|
|
}
|
|
|
|
|
|
\cs_new:Nn \polyglossia@set@default@language:nn
|
|
|
{
|
|
|
\ifcsundef{#2@loaded}%
|
|
|
{
|
|
|
% latex is an internal language, so do not record
|
|
|
\ifstrequal{#2}{latex}{}{%
|
|
|
\global\edef\xpg@loaded{#2\ifx\xpg@loaded\@empty\else,\xpg@loaded\fi}%
|
|
|
\global\edef\xpg@bloaded{\prop_item:Nn{\polyglossia@langsetup}{#2/babelname}%
|
|
|
\ifx\xpg@bloaded\@empty\else,\xpg@bloaded\fi}%
|
|
|
\global\edef\xpg@bcp@loaded{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}%
|
|
|
\ifx\xpg@bcp@loaded\@empty\else,\xpg@bcp@loaded\fi}%
|
|
|
}%
|
|
|
\csgdef{#2@loaded}{}%
|
|
|
}{}
|
|
|
\gdef\xpg@main@language{#2}%
|
|
|
\tl_if_blank:nTF {#1}{\gdef\mainlanguagevariant{}}{%
|
|
|
% Register the language options
|
|
|
\polyglossia@set@lang@options:nn {#2} {#1}%
|
|
|
}%
|
|
|
\csgdef{#2@gvar}{\mainlanguagevariant}%
|
|
|
%% The following settings are for the default language and script
|
|
|
% this tells bidi.sty or luabidi.sty that the document is RTL
|
|
|
\str_if_eq:eeTF{\prop_item:Nn{\polyglossia@langsetup}{#2/direction}}{RL}{%
|
|
|
\str_case_e:nnF{\c_sys_engine_str}{%
|
|
|
{luatex}{\setRTLmain}
|
|
|
{xetex}{\@RTLmaintrue\setnonlatin}
|
|
|
}{}%
|
|
|
}{}%
|
|
|
\cs_gset_nopar:Nn \polyglossia@AtBeginDocument@selectlanguage: {
|
|
|
\selectbackgroundlanguage{#2}
|
|
|
\selectlanguage[#1]{#2}%
|
|
|
}
|
|
|
\xpg@info{Default~ language~ is~ #2}%
|
|
|
\polyglossia@set@language@name[#1]{#2}%
|
|
|
\def\mainlanguagename{#2}
|
|
|
% Store babelname of main language (for external packages such as biblatex)
|
|
|
\prop_get:NxNT \polyglossia@langsetup {#2/babelname} \l_tmpa_tl
|
|
|
{ \edef\mainbabelname{\l_tmpa_tl} }
|
|
|
% Store babelname of current language (for external packages such as biblatex)
|
|
|
\prop_get:NxNT \polyglossia@langsetup {#2/babelname} \l_tmpa_tl
|
|
|
{ \edef\babelname{\l_tmpa_tl}%
|
|
|
\cs_gset_eq:cc{#2@gbabelname}{babelname}%
|
|
|
}
|
|
|
% Store BCP-47 id of main language
|
|
|
\prop_get:NxNT \polyglossia@langsetup {#2/bcp47} \l_tmpa_tl
|
|
|
{ \csedef{mainbcp47id}{\l_tmpa_tl} }
|
|
|
% Store BCP-47 id of current language
|
|
|
\prop_get:NxNT \polyglossia@langsetup {#2/bcp47} \l_tmpa_tl
|
|
|
{ \csedef{bcp47id}{\l_tmpa_tl}%
|
|
|
\cs_gset_eq:cc{#2@gbcp47id}{bcp47id}%
|
|
|
}
|
|
|
\ifluatex %
|
|
|
\directlua{polyglossia.set_default_language('\luatexluaescapestring{\string#2}')}%
|
|
|
\fi %
|
|
|
}
|
|
|
|
|
|
\let\setmainlanguage=\setdefaultlanguage
|
|
|
|
|
|
% Returns the language ID of the current language
|
|
|
% Currently supported: bcp-47
|
|
|
\DeclareDocumentCommand \languageid {m}
|
|
|
{
|
|
|
\str_case:nnTF {#1}
|
|
|
{
|
|
|
{bcp-47} { \csuse{bcp47id} }
|
|
|
{bcp47} { \csuse{bcp47id} }
|
|
|
}
|
|
|
{}
|
|
|
{
|
|
|
\xpg@error{Invalid~ \string\languageid\space argument:~ #1}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% Returns the language ID of the main language
|
|
|
% Currently supported: bcp-47
|
|
|
\DeclareDocumentCommand \mainlanguageid {m}
|
|
|
{
|
|
|
\str_case:nnTF {#1}
|
|
|
{
|
|
|
{bcp-47} { \csuse{mainbcp47id} }
|
|
|
{bcp47} { \csuse{mainbcp47id} }
|
|
|
}
|
|
|
{}
|
|
|
{
|
|
|
\xpg@error{Invalid~ \string\mainlanguageid\space argument:~ #1}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
\def\mainbabelname{}%
|
|
|
\def\mainlanguagevariant{}%
|
|
|
% Store main language variant for external packages
|
|
|
\define@key{xpg@main@langvariant}{variant}{%
|
|
|
\gdef\mainlanguagevariant{#1}%
|
|
|
}
|
|
|
|
|
|
\def\babelname{}%
|
|
|
\def\languagevariant{}%
|
|
|
% Store current language variant for external packages
|
|
|
\define@key{xpg@set@langvariant}{variant}{%
|
|
|
\def\languagevariant{#1}%
|
|
|
}
|
|
|
|
|
|
\newcommand*\polyglossia@set@language@name[2][]{
|
|
|
\def\languagename{#2}%
|
|
|
\tl_if_blank:nTF {#1}{%
|
|
|
\ifcsundef{#2@gvar}{\def\languagevariant{}}{\def\languagevariant{\csuse{#2@gvar}}}
|
|
|
}{%
|
|
|
% Register the language options
|
|
|
\polyglossia@set@lang@options:nn {#2} {#1}%
|
|
|
}%
|
|
|
}
|
|
|
|
|
|
|
|
|
\newcommand*{\resetdefaultlanguage}[2][]{%
|
|
|
\ifcsdef{#2@alias@lang}{%
|
|
|
\ifcsdef{#2@alias@opts}{%
|
|
|
\exp_args:Nxx \polyglossia@reset@default@language:nn {\csuse{#2@alias@opts},#1} {\csuse{#2@alias@lang}}%
|
|
|
}{%
|
|
|
polyglossia@reset@default@language:nn {#1} {\csuse{#2@alias@lang}}%
|
|
|
}%
|
|
|
}{%
|
|
|
polyglossia@reset@default@language:nn {#1} {#2}%
|
|
|
}%
|
|
|
}
|
|
|
|
|
|
\cs_new:Nn \polyglossia@reset@default@language:nn
|
|
|
{
|
|
|
\polyglossia@error@iflangnotloaded:n{#2}
|
|
|
% disable globalnumbers of previously defined default language
|
|
|
\csuse{no\xpg@main@language @globalnumbers}
|
|
|
\csuse{noextras@\xpg@main@language}%
|
|
|
% This is a hook for external packages which want to access variants
|
|
|
% via babelname (such as biblatex)
|
|
|
\cs_if_exist_use:c{noextras@bbl@\mainbabelname}%
|
|
|
\csuse{init@noextras@\xpg@main@language}%
|
|
|
\polyglossia@set@language@name[#1]{#2}%
|
|
|
\str_if_eq:eeTF{\prop_item:Nn{\polyglossia@langsetup}{#2/direction}}{RL}{\@rlmaintrue\@rl@footnotetrue}{}%
|
|
|
\selectlanguage[#1]{#2}%
|
|
|
\selectbackgroundlanguage{#2}%
|
|
|
% Store babelname of current language (for external packages such as biblatex)
|
|
|
\tl_if_blank:nTF {#1}{%
|
|
|
\ifcsundef{#2@gbabelname}{%
|
|
|
\edef\babelname{\prop_item:Nn{\polyglossia@langsetup}{#2/babelname}}%
|
|
|
}{%
|
|
|
\edef\babelname{\csuse{#2@gbabelname}}%
|
|
|
}%
|
|
|
}{%
|
|
|
\edef\babelname{\prop_item:Nn{\polyglossia@langsetup}{#2/babelname}}%
|
|
|
}%
|
|
|
% Store BCP-47 id of current language
|
|
|
\tl_if_blank:nTF {#1}{%
|
|
|
\ifcsundef{#2@gbcp47id}{%
|
|
|
\csedef{bcp47id}{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}}%
|
|
|
}{%
|
|
|
\csedef{bcp47id}{\csuse{#2@gbcp47id}}%
|
|
|
}%
|
|
|
}{%
|
|
|
\csedef{bcp47id}{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}}%
|
|
|
}%
|
|
|
}
|
|
|
|
|
|
% This saves the normalfont for the latin script since we may change normalfont in other scripts
|
|
|
\let\normalfontlatin=\normalfont%
|
|
|
|
|
|
% Provide default fonts (as set with \setmainfont, \setsansfont and \setmonofont)
|
|
|
% for Latin scripts and as a fallback for non-Latin scripts.
|
|
|
\DeclareRobustCommand\xpg@defaultfont@rm{%
|
|
|
\tl_if_empty:NF{\g__fontspec_nfss_enc_tl}{\fontencoding{\g__fontspec_nfss_enc_tl}}%
|
|
|
\fontfamily\rmdefault%
|
|
|
\selectfont%
|
|
|
}
|
|
|
\DeclareRobustCommand\xpg@defaultfont@sf{%
|
|
|
\tl_if_empty:NF{\g__fontspec_nfss_enc_tl}{\fontencoding{\g__fontspec_nfss_enc_tl}}%
|
|
|
\fontfamily\sfdefault%
|
|
|
\selectfont%
|
|
|
}
|
|
|
\DeclareRobustCommand\xpg@defaultfont@tt{%
|
|
|
\tl_if_empty:NF{\g__fontspec_nfss_enc_tl}{\fontencoding{\g__fontspec_nfss_enc_tl}}%
|
|
|
\fontfamily\ttdefault%
|
|
|
\selectfont%
|
|
|
}
|
|
|
|
|
|
\def\xpg@patch@fontfamilies{%
|
|
|
% This robustifies the redefinitions of \<xx>family (suggestion by Enrico Gregorio)
|
|
|
% e.g. to prevent expansion of the \familytype redefinition in auxiliary files
|
|
|
\csgappto{rmfamily~}{\def\familytype{rm}}
|
|
|
\csgappto{sffamily~}{\def\familytype{sf}}
|
|
|
\csgappto{ttfamily~}{\def\familytype{tt}}
|
|
|
}
|
|
|
|
|
|
% These switches activate the default fonts
|
|
|
% Note that a simple \let\rmfamilylatin=\rmfamily
|
|
|
% does not work reliably (see #24)
|
|
|
\cs_gset_eq:cc{rmfamilylatin}{xpg@defaultfont@rm}%
|
|
|
\cs_gset_eq:cc{sffamilylatin}{xpg@defaultfont@sf}%
|
|
|
\cs_gset_eq:cc{ttfamilylatin}{xpg@defaultfont@tt}%
|
|
|
|
|
|
\def\xpg@set@familydefault{%
|
|
|
% We need the \edef route here in order
|
|
|
% to detect both \renewcommand and \let
|
|
|
% changes.
|
|
|
\edef\tempa{\familydefault}%
|
|
|
\edef\tempb{\sfdefault}%
|
|
|
\ifcsequal{tempa}{tempb}%
|
|
|
{\def\familytype{sf}}
|
|
|
{\edef\tempb{\ttdefault}%
|
|
|
\ifcsequal{tempa}{tempb}%
|
|
|
{\def\familytype{tt}}
|
|
|
{\def\familytype{rm}}}
|
|
|
\xpg@patch@fontfamilies%
|
|
|
% This (re-)saves the normalfont for the latin script since we may
|
|
|
% change normalfont in other scripts
|
|
|
\let\normalfontlatin=\normalfont%
|
|
|
% And for all cases, we also reset \<xx>familylatin
|
|
|
\cs_gset_eq:cc{rmfamilylatin}{xpg@defaultfont@rm}%
|
|
|
\cs_gset_eq:cc{sffamilylatin}{xpg@defaultfont@sf}%
|
|
|
\cs_gset_eq:cc{ttfamilylatin}{xpg@defaultfont@tt}%
|
|
|
}
|
|
|
|
|
|
\def\resetfontlatin{%
|
|
|
\DeclareRobustCommand\rmfamily{\xpg@defaultfont@rm}%
|
|
|
\DeclareRobustCommand\sffamily{\xpg@defaultfont@sf}%
|
|
|
\DeclareRobustCommand\ttfamily{\xpg@defaultfont@tt}%
|
|
|
\xpg@patch@fontfamilies%
|
|
|
\global\let\normalfont=\normalfontlatin%
|
|
|
}
|
|
|
|
|
|
\def\selectfontfamilylatin{%
|
|
|
\def\tmp@tt{tt}\def\tmp@sf{sf}%
|
|
|
\ifx\familytype\tmp@tt%
|
|
|
\ttfamilylatin%
|
|
|
\else\ifx\familytype\tmp@sf%
|
|
|
\sffamilylatin%
|
|
|
\else\rmfamilylatin\fi\fi}
|
|
|
|
|
|
\def\xpg@select@fontfamily#1{%
|
|
|
\def\tmp@tt{tt}\def\tmp@sf{sf}%
|
|
|
\ifx\familytype\tmp@tt
|
|
|
\csuse@warn{#1@font@tt}%
|
|
|
\else\ifx\familytype\tmp@sf
|
|
|
\csuse@warn{#1@font@sf}%
|
|
|
\else\csuse@warn{#1@font@rm}\fi\fi}
|
|
|
|
|
|
\def\xpg@set@normalfont#1{%
|
|
|
\letcs{\rmfamily}{#1@font@rm}%
|
|
|
\letcs{\sffamily}{#1@font@sf}%
|
|
|
\letcs{\ttfamily}{#1@font@tt}%
|
|
|
\gdef\normalfont{\protect\xpg@select@fontfamily{#1}%
|
|
|
\fontseries{\seriesdefault}\selectfont%
|
|
|
\fontshape{\shapedefault}\selectfont}%
|
|
|
\gdef\reset@font{\protect\normalfont}%
|
|
|
}
|
|
|
|
|
|
\let\@@fterindentfalse\@afterindentfalse
|
|
|
\def\french@indent{%
|
|
|
\let\@afterindentfalse\@afterindenttrue
|
|
|
\@afterindenttrue%
|
|
|
}
|
|
|
\def\nofrench@indent{%
|
|
|
\let\@afterindentfalse\@@fterindentfalse
|
|
|
\@afterindentfalse%
|
|
|
}
|
|
|
|
|
|
\newcommand*{\selectbackgroundlanguage}[1]{%
|
|
|
\ifcsdef{#1@alias@lang}{%
|
|
|
\polyglossia@select@background@language:n {\csuse{#1@alias@lang}}%
|
|
|
}{%
|
|
|
\polyglossia@select@background@language:n {#1}%
|
|
|
}%
|
|
|
}
|
|
|
|
|
|
\cs_new:Nn \polyglossia@select@background@language:n
|
|
|
{
|
|
|
\str_if_eq:eeTF{\prop_item:Nn{\polyglossia@langsetup}{#1/lcscript}}{latin}
|
|
|
{}
|
|
|
{\xpg@set@normalfont{#1}}%
|
|
|
\csuse{#1@globalnumbers}%
|
|
|
}
|
|
|
|
|
|
\newcommand{\setotherlanguage}[2][]{%
|
|
|
\ifcsundef{#2@loaded}
|
|
|
{
|
|
|
\global\edef\xpg@loaded{#2\ifx\xpg@loaded\@empty\else,\xpg@loaded\fi}%
|
|
|
\polyglossia_load_lang_definition:nn{#1}{#2}
|
|
|
% define environment and command
|
|
|
\exp_args:Nx\polyglossia@define@language@cmd:n{#2}
|
|
|
\csgdef{#2@loaded}{}%
|
|
|
\ifcsdef{#2@alias@lang}{%
|
|
|
\ifcsdef{#2@alias@opts}{%
|
|
|
\exp_args:Nxx \polyglossia_load_lang_definition:nn {\csuse{#2@alias@opts},#1} {\csuse{#2@alias@lang}}%
|
|
|
\exp_args:Nxx \polyglossia@set@other@language:nn {\csuse{#2@alias@opts},#1} {\csuse{#2@alias@lang}}%
|
|
|
}{%
|
|
|
\polyglossia@set@other@language:nn {#1} {\csuse{#2@alias@lang}}%
|
|
|
}%
|
|
|
}{%
|
|
|
\polyglossia@set@other@language:nn {#1} {#2}%
|
|
|
}%
|
|
|
}
|
|
|
{}
|
|
|
}
|
|
|
|
|
|
\cs_new:Nn \polyglossia@set@other@language:nn
|
|
|
{
|
|
|
\ifcsundef{#2@loaded}
|
|
|
{
|
|
|
\global\edef\xpg@loaded{#2\ifx\xpg@loaded\@empty\else,\xpg@loaded\fi}%
|
|
|
\csgdef{#2@loaded}{}%
|
|
|
}{}
|
|
|
% If a variant is set, store it.
|
|
|
\gdef\otherlanguagevariant{}
|
|
|
\tl_if_blank:nTF {#1}{}{%
|
|
|
% Register the language options
|
|
|
\polyglossia@set@lang@options:nn {#2} {#1}%
|
|
|
}%
|
|
|
\csgdef{#2@gvar}{\otherlanguagevariant}%
|
|
|
\prop_get:NxNT \polyglossia@langsetup {#2/babelname} \l_tmpa_tl
|
|
|
{ \xdef\otherlanguagebabelname{\l_tmpa_tl} }
|
|
|
\cs_gset_eq:cc{#2@gbabelname}{otherlanguagebabelname}%
|
|
|
}
|
|
|
|
|
|
% Store main language variant for external packages
|
|
|
\define@key{xpg@other@langvariant}{variant}{%
|
|
|
\gdef\otherlanguagevariant{#1}%
|
|
|
}
|
|
|
|
|
|
\newcommand\setotherlanguages[1]{%
|
|
|
\def\do##1{\setotherlanguage{##1}}%
|
|
|
\exp_args:Nx\docsvlist{#1}}%
|
|
|
|
|
|
\def\common@language{% FIXME is this really needed???
|
|
|
\ifbool{xpg@hyphenation@disabled}{%
|
|
|
\xdef\xpg@lastlanguage{\z@}%
|
|
|
}{%
|
|
|
\language=\z@
|
|
|
}%
|
|
|
\lefthyphenmin=\tw@
|
|
|
\righthyphenmin=\thr@@}
|
|
|
|
|
|
\def\xpg@initial@setup{%
|
|
|
\common@language%
|
|
|
}
|
|
|
|
|
|
|
|
|
% Alias to \text<lang>, but more suitable
|
|
|
% for specific (esp. tag-based) aliases
|
|
|
% where \text<alias> would cause clashes
|
|
|
% (e.g., \textit)
|
|
|
\newcommand\textlang[3][]{%
|
|
|
\ifcsdef{#2@alias@lang}{%
|
|
|
\ifcsdef{#2@alias@opts}{%
|
|
|
\exp_args:Nxx \xpg@textlanguage[\csuse{#2@alias@opts},#1]{\csuse{#2@alias@lang}}{#3}%
|
|
|
}{%
|
|
|
\xpg@textlanguage[#1]{\csuse{#2@alias@lang}}{#3}%
|
|
|
}%
|
|
|
}{%
|
|
|
\xpg@textlanguage[#1]{#2}{#3}%
|
|
|
}%
|
|
|
}%
|
|
|
|
|
|
% Alias to {<lang>}, but more suitable
|
|
|
% for specific (esp. tag-based) aliases
|
|
|
% where {<alias>} would cause clashes
|
|
|
% (e.g., \fi)
|
|
|
\newenvironment{lang}[2][]{%
|
|
|
\begin{otherlanguage}[#1]{#2}%
|
|
|
}{%
|
|
|
\end{otherlanguage}
|
|
|
}%
|
|
|
|
|
|
\providecommand{\foreignlanguage}{}
|
|
|
|
|
|
% wrapper for foreignlanguage and otherlanguage*
|
|
|
\newcommand*\polyglossia@setforeignlanguage[2][]{
|
|
|
\select@@language[#1]{#2}
|
|
|
% Store babelname of current language (for external packages such as biblatex)
|
|
|
\tl_if_blank:nTF {#1}{%
|
|
|
\ifcsundef{#2@gbabelname}{%
|
|
|
\edef\babelname{\prop_item:Nn{\polyglossia@langsetup}{#2/babelname}}%
|
|
|
}{%
|
|
|
\edef\babelname{\csuse{#2@gbabelname}}%
|
|
|
}%
|
|
|
}{%
|
|
|
\edef\babelname{\prop_item:Nn{\polyglossia@langsetup}{#2/babelname}}%
|
|
|
}%
|
|
|
% Store BCP-47 id of current language
|
|
|
\tl_if_blank:nTF {#1}{%
|
|
|
\ifcsundef{#2@gbcp47id}{%
|
|
|
\csedef{bcp47id}{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}}%
|
|
|
}{%
|
|
|
\csedef{bcp47id}{\csuse{#2@gbcp47id}}%
|
|
|
}%
|
|
|
}{%
|
|
|
\csedef{bcp47id}{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}}%
|
|
|
}%
|
|
|
}
|
|
|
|
|
|
% joint code of \foreignlanguage, otherlanguage*
|
|
|
% and \text<lang>
|
|
|
\newcommand{\xpg@otherlanguage}[2][]
|
|
|
{%
|
|
|
\polyglossia@error@iflangnotloaded:n{#2}
|
|
|
\exp_args:Nne \setkeys{#2}{#1}%
|
|
|
\polyglossia@setforeignlanguage[#1]{#2}
|
|
|
% Hook for external packages such as biblatex
|
|
|
\polyglossia@language@switched%
|
|
|
% buggy restoration heure
|
|
|
\csuse{inlineextras@#2}%
|
|
|
% This is a hook for external packages which want to access variants
|
|
|
% via babelname (such as biblatex)
|
|
|
\cs_if_exist_use:c{inlineextras@bbl@\babelname}%
|
|
|
}
|
|
|
|
|
|
\renewcommand{\foreignlanguage}[3][]
|
|
|
{%
|
|
|
\ifcsdef{#2@alias@lang}{%
|
|
|
\ifcsdef{#2@alias@opts}{%
|
|
|
\exp_args:Nxx \polyglossia@foreignlanguage:nnn {\csuse{#2@alias@opts},#1} {\csuse{#2@alias@lang}} {#3}%
|
|
|
}{%
|
|
|
\polyglossia@foreignlanguage:nnn {#1} {\csuse{#2@alias@lang}} {#3}%
|
|
|
}%
|
|
|
}{%
|
|
|
\polyglossia@foreignlanguage:nnn {#1} {#2} {#3}%
|
|
|
}%
|
|
|
}
|
|
|
|
|
|
\cs_new:Nn \polyglossia@foreignlanguage:nnn
|
|
|
{
|
|
|
\polyglossia@error@iflangnotloaded:n{#2}
|
|
|
\bgroup
|
|
|
\xpg@otherlanguage[#1]{#2}%
|
|
|
\polyglossia@lang@settextdirection:nn{#2}{#3}%
|
|
|
\egroup
|
|
|
}
|
|
|
|
|
|
% otherlanguage* is the environment equivalent of \foreignlanguage
|
|
|
\expandafter\providecommand\csname otherlanguage*\endcsname{}
|
|
|
|
|
|
\renewenvironment{otherlanguage*}[2][]
|
|
|
{%
|
|
|
\ifcsdef{#2@alias@lang}{%
|
|
|
\ifcsdef{#2@alias@opts}{%
|
|
|
\exp_args:Nxx \polyglossia@otherlanguage:nn {\csuse{#2@alias@opts},#1} {\csuse{#2@alias@lang}}%
|
|
|
}{%
|
|
|
\polyglossia@otherlanguage:nn {#1} {\csuse{#2@alias@lang}}%
|
|
|
}%
|
|
|
}{%
|
|
|
\polyglossia@otherlanguage:nn {#1} {#2}%
|
|
|
}%
|
|
|
}
|
|
|
{\egroup}
|
|
|
|
|
|
\cs_new:Nn \polyglossia@otherlanguage:nn
|
|
|
{
|
|
|
\xpg@otherlanguage[#1]{#2}%
|
|
|
\polyglossia@lang@settextdirection:nn{#2}\bgroup%
|
|
|
}
|
|
|
|
|
|
% use by \text<lang> and \textlang. Equivalent to \foreignlanguage,
|
|
|
% except that dates are localized.
|
|
|
\newcommand\xpg@textlanguage[3][]{%
|
|
|
\polyglossia@error@iflangnotloaded:n{#2}
|
|
|
\bgroup
|
|
|
\xpg@otherlanguage[#1]{#2}%
|
|
|
\csuse{date#2}%
|
|
|
% This is a hook for external packages which want to access variants
|
|
|
% via babelname (such as biblatex)
|
|
|
\cs_if_exist_use:c{date@bbl@\babelname}%
|
|
|
\polyglossia@lang@settextdirection:nn{#2}{#3}%
|
|
|
\egroup
|
|
|
% Reset the language's/script's font families
|
|
|
\str_if_eq:eeTF{\prop_item:Nn{\polyglossia@langsetup}{#2/lcscript}}{latin}{}{\resetfontlatin}%
|
|
|
}
|
|
|
|
|
|
|
|
|
% Define language-specific hyphenation exceptions
|
|
|
\newcommand\pghyphenation[3][]{
|
|
|
\bgroup
|
|
|
\polyglossia@error@iflangnotloaded:n{#2}
|
|
|
\setkeys{#2}{#1}%
|
|
|
\select@@language[#1]{#2}%
|
|
|
\hyphenation{#3}%
|
|
|
\egroup
|
|
|
}
|
|
|
|
|
|
|
|
|
% Hook that other package authors can use
|
|
|
% (for instance biblatex):
|
|
|
\newcommand*{\xpg@hook@setlanguage}{}
|
|
|
|
|
|
\def\xpg@pop@language@i#1#2{%
|
|
|
\xpg@set@language@aux[#1]{#2}%
|
|
|
\xpg@hook@setlanguage
|
|
|
\let\emp@langname\@undefined}
|
|
|
|
|
|
\DeclareDocumentCommand \selectlanguage {s O{} m}
|
|
|
{%
|
|
|
\ifcsdef{#3@alias@lang}{%
|
|
|
\ifcsdef{#3@alias@opts}{%
|
|
|
\exp_args:Nxx \polyglossia@select@language:nnn {#1} {\csuse{#3@alias@opts},#2} {\csuse{#3@alias@lang}}%
|
|
|
}{%
|
|
|
\polyglossia@select@language:nnn {#1} {#2} {\csuse{#3@alias@lang}}%
|
|
|
}%
|
|
|
}{%
|
|
|
\polyglossia@error@iflangnotloaded:n{#3}%
|
|
|
\polyglossia@select@language:nnn {#1} {#2} {#3}%
|
|
|
}
|
|
|
}
|
|
|
|
|
|
\cs_new:Nn \polyglossia@select@language:nnn
|
|
|
{
|
|
|
\IfBooleanF {#1}
|
|
|
{
|
|
|
\cs_set_nopar:Npx \xpg@pop@language { \exp_not:N \xpg@pop@language@i {#2} {#3} }
|
|
|
\group_insert_after:N \xpg@pop@language
|
|
|
}
|
|
|
\tl_if_blank:nTF {#2}{}{%
|
|
|
% Register the language options
|
|
|
\polyglossia@set@lang@options:nn {#3} {#2}%
|
|
|
}%
|
|
|
% The starred variant does not write to the aux
|
|
|
\IfBooleanTF#1{%
|
|
|
\xpg@set@language@nonaux[#2]{#3}%
|
|
|
}{%
|
|
|
\xpg@set@language@aux[#2]{#3}%
|
|
|
}%
|
|
|
\ifluatex%
|
|
|
\directlua{polyglossia.select_language('\luatexluaescapestring{\string#3}',
|
|
|
\the\csname l@#3\endcsname)}%
|
|
|
\fi%
|
|
|
\def\xpg@tmp@babelname{\prop_item:Nn{\polyglossia@langsetup}{#3/babelname}}
|
|
|
% Store babelname in \xpg@bloaded csv list
|
|
|
\ifcsundef{\csname xpg@tmp@babelname\endcsname @bbl@loaded}
|
|
|
{
|
|
|
\global\edef\xpg@bloaded{\xpg@tmp@babelname%
|
|
|
\ifx\xpg@bloaded\@empty\else,\xpg@bloaded\fi}%
|
|
|
\csgdef{\csname xpg@tmp@babelname\endcsname @bbl@loaded}{}%
|
|
|
}{}
|
|
|
}
|
|
|
|
|
|
|
|
|
\cs_new:Nn \polyglossia@set@lang@options:nn
|
|
|
{
|
|
|
% If the optional argument sets a value for the key “variant”, copy it to xpg@langvariant
|
|
|
\clist_map_inline:nn { #2 } {%
|
|
|
\xpg@parsevariantkeyvalue##1=@xpg@langvariant:#1\relax
|
|
|
}%
|
|
|
\exp_args:Nne \setkeys{#1}{#2}%
|
|
|
}
|
|
|
|
|
|
% Initialize default language options, so that
|
|
|
% \iflanguageoption has the info it needs also
|
|
|
% for default settings
|
|
|
\newcommand*\xpg@initialize@gloss@options[2]{%
|
|
|
\polyglossia@set@lang@options:nn {#1} {#2}%
|
|
|
}
|
|
|
|
|
|
% Record synonymous keyvals such as variant=us and variant=american
|
|
|
% Syntax: \xpg@set@alias@values{<lang>}{<key>}{<val>}{<alias vals, comma-separated>}
|
|
|
\newcommand*\xpg@set@alias@values[4]{%
|
|
|
\prop_if_exist:cF { xpg@alias@keyvals@#1@#3 }
|
|
|
{ \prop_new:c {xpg@alias@keyvals@#1@#3} }
|
|
|
\prop_put:cnn { xpg@alias@keyvals@#1@#3 }
|
|
|
{#2}{#4}
|
|
|
\prop_put:cnn { xpg@alias@keyvals@#1@#4 }
|
|
|
{#2}{#3}
|
|
|
}
|
|
|
|
|
|
% Patch xkeyval to record default values of keys
|
|
|
\pretocmd{\XKV@define@default}{%
|
|
|
\csgdef{xpg@default@opt@\XKV@header #1}{#2}%
|
|
|
}{}{\xpg@warning{Patching xkeyval failed!}}
|
|
|
|
|
|
% Helper to get and register option keyvals
|
|
|
\def\xpg@parsevariantkeyvalue#1=#2@#3:#4\relax{%
|
|
|
\def\@tmpa{#1}
|
|
|
\def\@tmpb{variant}
|
|
|
% variant values are stored in specific macros
|
|
|
% (\xpg@main@langvariant, \xpg@other@langvariant
|
|
|
% and \xpg@set@langvariant)
|
|
|
\ifx\@tmpa\@tmpb\setkeys{#3}{#1=#2}\fi
|
|
|
\tl_if_empty:nTF{#2}
|
|
|
{
|
|
|
\ifcsdef{xpg@default@opt@KV@#4@#1}%
|
|
|
{\xpg@store@opt@keyval#1:\csuse{xpg@default@opt@KV@#4@#1}=:#4\relax}%
|
|
|
{}%
|
|
|
}
|
|
|
{ \xpg@store@opt@keyval#1:#2:#4\relax }
|
|
|
}%
|
|
|
|
|
|
% Store option keys and values
|
|
|
% This strips trailing '=' from values.
|
|
|
\def\xpg@store@opt@keyval#1:#2=:#3\relax{%
|
|
|
\prop_if_exist:cF { xpg@current@options@#3 }
|
|
|
{ \prop_new:c {xpg@current@options@#3} }
|
|
|
\prop_put:cnn { xpg@current@options@#3 }
|
|
|
{#1}{#2}
|
|
|
}
|
|
|
|
|
|
|
|
|
\prg_set_conditional:Npnn \polyglossia@check@option@value:NNN #1#2#3 { p , T , F , TF }
|
|
|
{
|
|
|
\prop_get:cnNTF {xpg@current@options@#1} {#2} \l_tmpa_tl
|
|
|
{
|
|
|
\exp_args:Nee \str_if_eq:NNTF{\l_tmpa_tl}{#3}
|
|
|
{\prg_return_true:}
|
|
|
{
|
|
|
\prop_get:cnNTF {xpg@alias@keyvals@#1@#3} {#2} \l_tmpb_tl
|
|
|
{
|
|
|
\exp_args:Nne \clist_set:Nn{\l_tmpa_clist}{\l_tmpb_tl}
|
|
|
\providetoggle{xpgvalfound}
|
|
|
\togglefalse{xpgvalfound}
|
|
|
\clist_map_inline:Nn \l_tmpa_clist {
|
|
|
\exp_args:Nee \str_if_eq:NNT{##1}{\l_tmpa_tl}
|
|
|
{ \toggletrue{xpgvalfound} }
|
|
|
}
|
|
|
\iftoggle{xpgvalfound}{\prg_return_true:}{\prg_return_false:}
|
|
|
}
|
|
|
{
|
|
|
\prg_return_false:
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
{
|
|
|
\prg_return_false:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% Test if option value is set
|
|
|
\newcommand*\iflanguageoption[5]{%
|
|
|
\polyglossia@check@option@value:NNNTF{#1}{#2}{#3}{#4}{#5}%
|
|
|
}
|
|
|
|
|
|
|
|
|
% Append any variant to csv list of variants
|
|
|
\define@key{xpg@langvariant}{variant}{%
|
|
|
\edef\xpg@vloaded{#1\ifx\xpg@vloaded\@empty\else,\xpg@vloaded\fi}%
|
|
|
}
|
|
|
|
|
|
\prg_set_conditional:Npnn \polyglossia@check@if@lang@loaded:N #1 { p , T , F , TF }{
|
|
|
\cs_if_exist:cTF{#1}{
|
|
|
\prg_return_true:
|
|
|
}{
|
|
|
\prg_return_false:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% Test if language is loaded
|
|
|
\newcommand*\iflanguageloaded[3]{%
|
|
|
\polyglossia@check@if@lang@loaded:NTF{#1@loaded}{#2}{#3}%
|
|
|
}
|
|
|
|
|
|
% Same for babellanguage is loaded
|
|
|
\newcommand*\ifbabellanguageloaded[3]{%
|
|
|
\polyglossia@check@if@lang@loaded:NTF{#1@bbl@loaded}{#2}{#3}%
|
|
|
}
|
|
|
|
|
|
% Same for languageid
|
|
|
\DeclareDocumentCommand \iflanguageidloaded {mmmm}
|
|
|
{
|
|
|
\str_case:nnTF {#1}
|
|
|
{
|
|
|
{bcp-47} { \polyglossia@check@if@lang@loaded:NTF{#2@bcp@loaded}{#3}{#4} }
|
|
|
{bcp47} { \polyglossia@check@if@lang@loaded:NTF{#2@bcp@loaded}{#3}{#4} }
|
|
|
}
|
|
|
{}
|
|
|
{
|
|
|
\xpg@error{Invalid~ \string\iflanguageidloaded\space argument:~ #1}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% Check if the current font has a given glyph
|
|
|
\prg_set_conditional:Npnn \polyglossia@check@if@char@available:N #1 { p , T , F , TF }
|
|
|
{
|
|
|
\str_case_e:nnF{\c_sys_engine_str}{
|
|
|
{luatex}{
|
|
|
\int_compare:nNnTF { \directlua{polyglossia.check_char(0x#1)} } > { 0 }
|
|
|
{\prg_return_true:}
|
|
|
{\prg_return_false:}
|
|
|
}
|
|
|
{xetex}{
|
|
|
\int_compare:nNnTF { \the\XeTeXcharglyph"#1 } > { 0 }
|
|
|
{\prg_return_true:}
|
|
|
{\prg_return_false:}
|
|
|
}
|
|
|
}
|
|
|
{
|
|
|
\xpg@warning{You’re running a TeX engine that is not LuaTeX or XeTeX.\MessageBreak
|
|
|
That is almost guaranteed to cause problems.}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% Test if a char (by char code) is available in the current font
|
|
|
\newcommand*\xpg@if@char@available[3]{%
|
|
|
\polyglossia@check@if@char@available:NTF{#1}{#2}{#3}%
|
|
|
}
|
|
|
|
|
|
\newcommand*\charifavailable[2]{%
|
|
|
\xpg@if@char@available{#1}{\char"#1}{#2}%
|
|
|
}
|
|
|
|
|
|
|
|
|
\newcommand*{\xpg@set@language@nonaux}[2][]{%
|
|
|
\@select@language[#1]{#2}%
|
|
|
}
|
|
|
|
|
|
|
|
|
\newcommand*{\xpg@set@language@aux}[2][]{%
|
|
|
% Store babelname of current language (for external packages such as biblatex)
|
|
|
\tl_if_blank:nTF {#1}{%
|
|
|
\ifcsundef{#2@gbabelname}{%
|
|
|
\edef\babelname{\prop_item:Nn{\polyglossia@langsetup}{#2/babelname}}%
|
|
|
}{%
|
|
|
\edef\babelname{\csuse{#2@gbabelname}}%
|
|
|
}%
|
|
|
}{%
|
|
|
\edef\babelname{\prop_item:Nn{\polyglossia@langsetup}{#2/babelname}}%
|
|
|
}%
|
|
|
% Store BCP-47 id of current language
|
|
|
\tl_if_blank:nTF {#1}{%
|
|
|
\ifcsundef{#2@gbcp47id}{%
|
|
|
\csedef{bcp47id}{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}}%
|
|
|
}{%
|
|
|
\csedef{bcp47id}{\csuse{#2@gbcp47id}}%
|
|
|
}%
|
|
|
}{%
|
|
|
\csedef{bcp47id}{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}}%
|
|
|
}%
|
|
|
% Store bcp47 in \xpg@bcp@loaded csv list
|
|
|
\def\xpg@tmp@bcpname{\csuse{bcp47id}}%
|
|
|
\ifcsundef{\csname xpg@tmp@bcpname\endcsname @bcp@loaded}
|
|
|
{
|
|
|
\global\edef\xpg@bcp@loaded{\xpg@tmp@bcpname%
|
|
|
\ifx\xpg@bcp@loaded\@empty\else,\xpg@bcp@loaded\fi}%
|
|
|
\csgdef{\csname xpg@tmp@bcpname\endcsname @bcp@loaded}{}%
|
|
|
}{}
|
|
|
\@select@language[#1]{#2}%
|
|
|
% Write to the aux
|
|
|
\if@filesw%
|
|
|
\ifx#1\\\\%
|
|
|
\protected@write\@auxout{}{\protect\selectlanguage*{#2}}%
|
|
|
\addtocontents{toc}{\protect\selectlanguage*{#2}}%
|
|
|
\addtocontents{lof}{\protect\selectlanguage*{#2}}%
|
|
|
\addtocontents{lot}{\protect\selectlanguage*{#2}}%
|
|
|
\else
|
|
|
\protected@write\@auxout{}{\protect\selectlanguage*[#1]{#2}}%
|
|
|
\addtocontents{toc}{\protect\selectlanguage*[#1]{#2}}%
|
|
|
\addtocontents{lof}{\protect\selectlanguage*[#1]{#2}}%
|
|
|
\addtocontents{lot}{\protect\selectlanguage*[#1]{#2}}%
|
|
|
\fi
|
|
|
\fi
|
|
|
}
|
|
|
|
|
|
% The bidi package swaps the output stream within RTL tables
|
|
|
% (to get the column order right). This also swaps group
|
|
|
% delimiters inserted to the aux files via otherlanguage (see #354).
|
|
|
% We therefore patch bidi and insert a bool that tells us
|
|
|
% whether we are in such a table.
|
|
|
\newbool{xpg@inbiditable}
|
|
|
\AtBeginDocument{%
|
|
|
\@ifpackageloaded{bidi}{%
|
|
|
\patchcmd{\@tabular}%
|
|
|
{\if@RTLtab}%
|
|
|
{\if@RTLtab\booltrue{xpg@inbiditable}}%
|
|
|
{}% success
|
|
|
{\xpg@warning{Patching bidi table failed!}}%
|
|
|
}{}%
|
|
|
}
|
|
|
|
|
|
% Open a group in the aux file. This is to keep
|
|
|
% nested language options local (see #320).
|
|
|
% In bidi tables, the opening/closing needs to be swapped (see #354)
|
|
|
\newcommand*{\xpg@set@group@aux}{%
|
|
|
\if@filesw%
|
|
|
\ifbool{xpg@inbiditable}{%
|
|
|
\protected@write\@auxout{}{\egroup}%
|
|
|
\addtocontents{toc}{\egroup}%
|
|
|
\addtocontents{lof}{\egroup}%
|
|
|
\addtocontents{lot}{\egroup}%
|
|
|
}{%
|
|
|
\protected@write\@auxout{}{\bgroup}%
|
|
|
\addtocontents{toc}{\bgroup}%
|
|
|
\addtocontents{lof}{\bgroup}%
|
|
|
\addtocontents{lot}{\bgroup}%
|
|
|
}%
|
|
|
\fi
|
|
|
}
|
|
|
|
|
|
% Close the group in the aux file.
|
|
|
% In bidi RTL tables, the opening/closing needs
|
|
|
% to be swapped (see #354).
|
|
|
\newcommand*{\xpg@unset@group@aux}{%
|
|
|
\if@filesw%
|
|
|
\ifbool{xpg@inbiditable}{%
|
|
|
\protected@write\@auxout{}{\bgroup}%
|
|
|
\addtocontents{toc}{\bgroup}%
|
|
|
\addtocontents{lof}{\bgroup}%
|
|
|
\addtocontents{lot}{\bgroup}%
|
|
|
}{%
|
|
|
\protected@write\@auxout{}{\egroup}%
|
|
|
\addtocontents{toc}{\egroup}%
|
|
|
\addtocontents{lof}{\egroup}%
|
|
|
\addtocontents{lot}{\egroup}%
|
|
|
}%
|
|
|
\fi
|
|
|
}
|
|
|
|
|
|
\prg_set_conditional:Npnn \polyglossia@check@ifdefined:N #1 { p , T , F , TF }{
|
|
|
\cs_if_exist:cTF {l@#1}
|
|
|
{
|
|
|
\cs_if_eq:cNTF {l@#1} \l@nohyphenation
|
|
|
{
|
|
|
\prg_return_false:
|
|
|
}
|
|
|
{
|
|
|
% it's possible that sometimes \csname l@#1\endcsname becomes \relax
|
|
|
\cs_if_eq:cNTF {l@#1} \relax
|
|
|
{ \prg_return_false: }
|
|
|
{ \prg_return_true: }
|
|
|
}
|
|
|
}
|
|
|
{
|
|
|
\prg_return_false:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
\def\polyglossia@luatex@load@lang#1{%
|
|
|
% if \l@#1 is not properly defined, call lua function newloader(#1),
|
|
|
% and assign the returned number to \l@#1
|
|
|
\polyglossia@check@ifdefined:NF {#1}
|
|
|
{
|
|
|
\expandafter\chardef\csname l@#1\endcsname=
|
|
|
\directlua{ tex.sprint(polyglossia.newloader'#1') }\relax
|
|
|
}
|
|
|
}
|
|
|
|
|
|
% This check is also used by biblatex, so don't
|
|
|
% rename silently.
|
|
|
\newcommand\xpg@ifdefined[3]{%
|
|
|
% With luatex, we first need to define \l@#1.
|
|
|
\ifluatex
|
|
|
\polyglossia@luatex@load@lang{#1}%
|
|
|
\fi
|
|
|
\polyglossia@check@ifdefined:NTF{#1}{#2}{#3}%
|
|
|
}%
|
|
|
|
|
|
% Set \bbl@hyphendata@\the\language, which is (lua)babel's
|
|
|
% hyphenation pattern hook
|
|
|
% FIXME Clarifiy why/when this is needed.
|
|
|
\newcommand*\xpg@set@bbl@hyphendata[1]{%
|
|
|
\ifluatex%
|
|
|
\ifcsdef{bbl@hyphendata@#1}{}{%
|
|
|
\global\@namedef{bbl@hyphendata@\the\language}{}%
|
|
|
}%
|
|
|
\fi%
|
|
|
}
|
|
|
|
|
|
% Set hyphenation patterns for a given language. This does the right
|
|
|
% thing both for XeTeX and LuaTeX
|
|
|
\newcommand*\xpg@set@hyphenation@patterns[1]{%
|
|
|
\ifluatex
|
|
|
\polyglossia@luatex@load@lang{#1}%
|
|
|
\language=\csname l@#1\endcsname
|
|
|
\else
|
|
|
\ifxetex
|
|
|
\language=\csname l@#1\endcsname
|
|
|
\else
|
|
|
\xpg@warning{You’re~running~a~TeX~engine~that~is~not~LuaTeX~or~XeTeX.\MessageBreak
|
|
|
That~is~almost~guaranteed~to~cause~problems.}%
|
|
|
\fi
|
|
|
\fi
|
|
|
}
|
|
|
|
|
|
|
|
|
\newcommand*\@select@language[2][]{
|
|
|
% hook for compatibility with biblatex
|
|
|
\select@language{#2}
|
|
|
\xpg@set@bbl@hyphendata{\the\language}
|
|
|
\xpg@initial@setup%
|
|
|
\select@@language[#1]{#2}%
|
|
|
% Hook for external packages such as biblatex
|
|
|
\polyglossia@language@switched%
|
|
|
\polyglossia@lang@setpardirection:n{#2}%
|
|
|
\csuse{captions#2}%
|
|
|
\csuse{date#2}%
|
|
|
% These are hooks for external packages which want to access variants
|
|
|
% via babelname (such as biblatex)
|
|
|
\cs_if_exist_use:c{captions@bbl@\babelname}%
|
|
|
\cs_if_exist_use:c{date@bbl@\babelname}%
|
|
|
\polyglossia@local@marks:n{#2}%
|
|
|
\csuse{init@extras@#2}%
|
|
|
\polyglossia@lang@indentfirst:n{#2}
|
|
|
\csuse{blockextras@#2}%
|
|
|
% This is a hook for external packages which want to access variants
|
|
|
% via babelname (such as biblatex)
|
|
|
\cs_if_exist_use:c{blockextras@bbl@\babelname}%
|
|
|
}
|
|
|
|
|
|
% hook for compatibility with biblatex
|
|
|
% (probably no longer used due to the
|
|
|
% more general hook that follows, but
|
|
|
% we keep it for backwards comp.)
|
|
|
\def\select@language#1{}
|
|
|
|
|
|
% Hook for external packages such as biblatex
|
|
|
\def\polyglossia@language@switched{}
|
|
|
|
|
|
\def\noextrascurrent#1{%
|
|
|
\csuse{noextras@#1}%
|
|
|
% This is a hook for external packages which want to access variants
|
|
|
% via babelname (such as biblatex)
|
|
|
\cs_if_exist_use:c{noextras@bbl@\babelname}
|
|
|
}
|
|
|
|
|
|
% Common code for `\select@language' and `\foreignlanguage'.
|
|
|
\newcommand{\select@@language}[2][]{%
|
|
|
% disable the extras and number settings of the previous language
|
|
|
\ifcsundef{languagename}{}{%
|
|
|
\noextrascurrent{\languagename}%
|
|
|
\csuse{no\languagename @numbers}%
|
|
|
\ifxetex
|
|
|
\str_if_eq:eeTF{\exp_args:Nne\prop_item:Nn{\polyglossia@langsetup}{\languagename/direction}}{RL}%
|
|
|
{%
|
|
|
\str_if_eq:eeTF{\prop_item:Nn{\polyglossia@langsetup}{#2/direction}}{RL}%
|
|
|
{}% RTL -> RTL
|
|
|
{\setlatin}% RTL -> LTR
|
|
|
}{%
|
|
|
\str_if_eq:eeTF{\prop_item:Nn{\polyglossia@langsetup}{#2/direction}}{RL}%
|
|
|
{\setnonlatin}% LTR -> RTL
|
|
|
{}% LTR -> LTR
|
|
|
}%
|
|
|
\fi
|
|
|
}%
|
|
|
\polyglossia@set@language@name[#1]{#2}%
|
|
|
% Set the language's/script's font families
|
|
|
\str_if_eq:eeTF{\prop_item:Nn{\polyglossia@langsetup}{#2/lcscript}}{latin}{\resetfontlatin}{\xpg@set@normalfont{#2}}%
|
|
|
\xpg@select@fontfamily{#2}%
|
|
|
\csuse@warn{#2@language}%
|
|
|
\csuse{#2@numbers}%
|
|
|
\use@localhyphenmins{#2}%
|
|
|
\polyglossia@lang@frenchspacing:n{#2}
|
|
|
}
|
|
|
|
|
|
|
|
|
\let\xpg@pop@language\relax
|
|
|
|
|
|
\provideenvironment{otherlanguage}{}{}
|
|
|
|
|
|
\newbool{xpg@noset@groups}
|
|
|
\renewenvironment{otherlanguage}[2][]
|
|
|
{%
|
|
|
% We usually embrace the switch in groups to keep the changes local.
|
|
|
% We cannot do this if an LTR environmet starts in an RTL paragraph,
|
|
|
% as bidi interferes here badly with its directionality smartness.
|
|
|
\ifxetex
|
|
|
\str_if_eq:eeT{\exp_args:Nne\prop_item:Nn{\polyglossia@langsetup}{\languagename/direction}}{RL}%
|
|
|
{%
|
|
|
\str_if_eq:eeTF{\prop_item:Nn{\polyglossia@langsetup}{#1/direction}}{RL}%
|
|
|
{}% RTL -> RTL
|
|
|
{\ifvmode\else\booltrue{xpg@noset@groups}\fi}% RTL -> LTR
|
|
|
}%
|
|
|
\fi%
|
|
|
\ifbool{xpg@noset@groups}{}{\xpg@set@group@aux}%
|
|
|
\selectlanguage[#1]{#2}%
|
|
|
}
|
|
|
{\ifbool{xpg@noset@groups}{}{\xpg@unset@group@aux}}
|
|
|
|
|
|
\newcommand{\setlocalhyphenmins}[3]{%
|
|
|
\xpg@ifdefined{#1}{%
|
|
|
\expandafter\ifx\csname l@#1\endcsname\l@nohyphenation%
|
|
|
\xpg@warning{\string\setlocalhyphenmin\space~ useless~ for~ unhyphenated~ language~ #1}%
|
|
|
\else
|
|
|
\providehyphenmins{#1}{#2#3}%
|
|
|
\fi
|
|
|
}{%
|
|
|
\xpg@warning{\string\setlocalhyphenmin\space~ useless~ for~ unknown~ language~ #1}%
|
|
|
}}%
|
|
|
|
|
|
\def\use@localhyphenmins#1{%
|
|
|
\ifcsundef{#1hyphenmins}{}%
|
|
|
{\expandafter\expandafter\expandafter\set@hyphenmins\csname #1hyphenmins\endcsname\relax}
|
|
|
\ifluatex
|
|
|
% Set \totalhyphenmin if specified
|
|
|
\prop_get:NxNTF \polyglossia@langsetup {#1/totalhyphenmin} \l_tmpa_tl
|
|
|
{
|
|
|
\xpg@warning{totalhyphenmin: '\l_tmpa_tl'}
|
|
|
\expandafter\hyphenationmin \l_tmpa_tl%
|
|
|
}%
|
|
|
{}%
|
|
|
\fi
|
|
|
}
|
|
|
|
|
|
\AtEndPreamble{%
|
|
|
\@ifpackageloaded{bidi}{%
|
|
|
\providecommand*{\aemph}[1]{$\overline{\hboxR{#1}}$}%
|
|
|
}{}%
|
|
|
\@ifpackageloaded{luabidi}{%
|
|
|
\providecommand*{\aemph}[1]{$\overline{\hbox{\RL{#1}}}$}%
|
|
|
}{}%
|
|
|
}
|
|
|
|
|
|
|
|
|
% keys for main package
|
|
|
\keys_define:nn { polyglossia } {
|
|
|
verbose
|
|
|
.bool_set:N = \l_polyglossia_verbose_bool,
|
|
|
verbose
|
|
|
.default:n = true,
|
|
|
% compatibility
|
|
|
quiet
|
|
|
.meta:n = { verbose = false },
|
|
|
|
|
|
localmarks
|
|
|
.bool_set:N = \l_polyglossia_localmarks_bool,
|
|
|
localmarks
|
|
|
.default:n = true,
|
|
|
% compatibility
|
|
|
nolocalmarks
|
|
|
.meta:n = { localmarks = false },
|
|
|
|
|
|
babelshorthands
|
|
|
.bool_set:N = \l_polyglossia_babelshorthands_bool,
|
|
|
babelshorthands
|
|
|
.default:n = true,
|
|
|
}
|
|
|
|
|
|
\keys_set:nn { polyglossia } {
|
|
|
localmarks = false,
|
|
|
verbose = true,
|
|
|
babelshorthands = false,
|
|
|
}
|
|
|
|
|
|
% load by default latex
|
|
|
\setmainlanguage{latex}
|
|
|
% then process key in order to overwrite
|
|
|
\ProcessKeysOptions{polyglossia}
|
|
|
|
|
|
\bool_if:nTF \l_polyglossia_verbose_bool {} {
|
|
|
\gdef\@latex@info#1{\relax}% no latex info
|
|
|
\gdef\@font@info#1{\relax}% no latex font info
|
|
|
\gdef\@font@warning#1{\relax}% no latex font warnings
|
|
|
\gdef\zf@PackageInfo#1{\relax}% no fontspec info
|
|
|
\gdef\xpg@info#1{\relax}% no polyglossia info
|
|
|
}
|
|
|
|
|
|
\bool_if:nTF \l_polyglossia_localmarks_bool {
|
|
|
\polyglossia@enable@local@marks:
|
|
|
}{}
|
|
|
|
|
|
% compatibility
|
|
|
\newif\ifsystem@babelshorthands
|
|
|
\bool_if:nTF \l_polyglossia_babelshorthands_bool {
|
|
|
\system@babelshorthandstrue
|
|
|
}{
|
|
|
\system@babelshorthandsfalse
|
|
|
}
|
|
|
|
|
|
%
|
|
|
% FIXME these should also be loaded \AtEndOfPackage !!!
|
|
|
\def\xpg@option#1#2{%
|
|
|
\ifcsundef{xpg@main@language}{\setdefaultlanguage}{\setotherlanguage}%
|
|
|
[#1]{#2}}
|
|
|
\ExplSyntaxOff
|
|
|
|
|
|
\endinput
|
|
|
|