You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
tex-compiler/texmf-dist/tex/latex/polyglossia/polyglossia.sty

2215 lines
69 KiB

\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