\NeedsTeXFormat{LaTeX2e} \ProvidesPackage{polyglossia}[2020/10/09 v1.50 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 \RequirePackage{iftex} \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 \providecommand\texorpdfstring[2]{#1}% dummy command if hyperref is not loaded \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 = {,} %% TODO: localnumeral = %% 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]{% % Store catcode of @ before making at letter \chardef\xpg@saved@at@catcode\catcode`\@ \makeatletter \input{#1}% % restore former @ catcode \catcode`\@=\xpg@saved@at@catcode% } % try to load a language file \cs_new:Nn \polyglossia_load_lang_definition:nn { \file_if_exist:nTF{gloss-#2.ldf} { % Temporarily force catcode of ~ to 13 since babelsh.def % requires it. This is needed particularly with LaTeX3 % packages which force \ExplSyntaxOn (#425) \protected\edef\xpg@restore@tilde@catcode{\catcode 126 = \the\catcode 126\relax} \catcode 126 = 13 \xpg@input{gloss-#2.ldf} \setkeys{#2}{#1} % restore former ~ catcode \xpg@restore@tilde@catcode } { \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}% }{} \polyglossia@register@language:nn{}{#1}% \csgdef{#1@loaded}{}% } % 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[]{}{} \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}}% } \cs_new:Nn \polyglossia@register@language:nn { % register polyglossia language name \ifcsundef{#2@registered}{% \global\edef\xpg@loaded{% \ifx\xpg@loaded\@empty\else\xpg@loaded,\fi #2% }% }{} \csgdef{#2@registered}{}% \tl_if_blank:nF {#1}{% % Register the language options \polyglossia@set@lang@options:nn {#2} {#1}% }% % register babelname \def\xpg@tmp@babelname{\prop_item:Nn{\polyglossia@langsetup}{#2/babelname}}% \ifcsundef{\csname xpg@tmp@babelname\endcsname @bbl@registered}{% \global\edef\xpg@bloaded{% \ifx\xpg@bloaded\@empty\else\xpg@bloaded,\fi\xpg@tmp@babelname}% }{}% \csgdef{\csname xpg@tmp@babelname\endcsname @bbl@registered}{}% % register BCP-47 ID \def\xpg@tmp@bcpname{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}}% \ifcsundef{\csname xpg@tmp@bcpname\endcsname @bcp@registered}{% \global\edef\xpg@bcp@loaded{% \ifx\xpg@bcp@loaded\@empty\else\xpg@bcp@loaded,\fi\xpg@tmp@bcpname}% }{}% \csgdef{\csname xpg@tmp@bcpname\endcsname @bcp@registered}{}% } \newcommand{\setdefaultlanguage}[2][]{% \ifcsundef{#2@loaded}% { \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 { \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 \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 \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{% \DeclareRobustCommand\rmfamily{\csuse{#1@font@rm}}% \DeclareRobustCommand\sffamily{\csuse{#1@font@sf}}% \DeclareRobustCommand\ttfamily{\csuse{#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} { \polyglossia_load_lang_definition:nn{#1}{#2} % define environment and command \exp_args:Nx\polyglossia@define@language@cmd:n{#2} \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}% }% \csgdef{#2@loaded}{}% } {} } \cs_new:Nn \polyglossia@set@other@language:nn { \polyglossia@register@language:nn{#1}{#2}% % 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, but more suitable % for specific (esp. tag-based) aliases % where \text 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 {}, but more suitable % for specific (esp. tag-based) aliases % where {} 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} \polyglossia@register@language:nn{#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 \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 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% \polyglossia@register@language:nn{#2}{#3}% } \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{}{}{}{} \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}}% }% \@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[#1]{#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}% }% }% % \setlanghyphenmins[options]{lang}{l}{r} \newcommand*\setlanghyphenmins[4][]{% % Check for real language name and options \edef\xpg@tmp@lang{#2}% \edef\xpg@tmp@opts{#1}% \ifcsdef{#2@alias@lang}{% \edef\xpg@tmp@lang{\csuse{#2@alias@lang}}% \ifcsdef{#2@alias@opts}{% \edef\xpg@tmp@opts{\csuse{#2@alias@opts},#1}% }{}% }{}% \bgroup \polyglossia@error@iflangnotloaded:n{\xpg@tmp@lang} \exp_args:Nne \setkeys{\xpg@tmp@lang}{\xpg@tmp@opts}% % Store BCP-47 id of language \tl_if_blank:nTF {\xpg@tmp@opts}{% \ifcsundef{\csname xpg@tmp@lang\endcsname @gbcp47id}{% \csedef{tmp@bcp47id}{\exp_args:Nne\prop_item:Nn{\polyglossia@langsetup}{\xpg@tmp@lang /bcp47}}% }{% \csedef{tmp@bcp47id}{\csuse{#2@gbcp47id}}% }% }{% \csedef{tmp@bcp47id}{\exp_args:Nne \prop_item:Nn{\polyglossia@langsetup}{\xpg@tmp@lang /bcp47}}% }% \xpg@warning{id: \csuse{tmp@bcp47id}}% \csgdef{\csname tmp@bcp47id\endcsname @hyphenmins}{{#3}{#4}}% \egroup } % \use@localhypenmins[options]{lang} \newcommand*\use@localhyphenmins[2][]{% \bgroup \polyglossia@error@iflangnotloaded:n{#2} \setkeys{#2}{#1}% % Store BCP-47 id of language \tl_if_blank:nTF {#1}{% \ifcsundef{#2@gbcp47id}{% \csxdef{tmp@bcp47id}{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}}% }{% \csxdef{tmp@bcp47id}{\csuse{#2@gbcp47id}}% }% }{% \csxdef{tmp@bcp47id}{\prop_item:Nn{\polyglossia@langsetup}{#2/bcp47}}% }% \egroup \ifcsundef{\csname tmp@bcp47id\endcsname @hyphenmins}{% \ifcsundef{#2hyphenmins}{}% {% \expandafter\expandafter\expandafter\set@hyphenmins\csname #2hyphenmins\endcsname\relax% } }{% \edef\tmpa{\csuse{\csname tmp@bcp47id\endcsname @hyphenmins}}% \expandafter\expandafter\expandafter\set@hyphenmins\tmpa\relax% } \ifluatex % Set \totalhyphenmin if specified \prop_get:NxNTF \polyglossia@langsetup {#2/totalhyphenmin} \l_tmpa_tl { \xpg@warning{totalhyphenmin: '\l_tmpa_tl'} \expandafter\hyphenationmin \l_tmpa_tl% }% {}% \fi } % Babel previously compiled in hyphenrules into the kernel (via hyphen.cfg) % but this is no longer the case. In any case, we roll our own one now % and possibly overwrite babel's. \provideenvironment{hyphenrules}{}{} % As opposed to the one inherited from switch.def/babel, our environment % supports language options and aliases. \renewenvironment{hyphenrules}[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}% % Check for real language name and options \edef\xpg@tmp@lang{#2}% \edef\xpg@tmp@opts{#1}% \ifcsdef{#2@alias@lang}{% \edef\xpg@tmp@lang{\csuse{#2@alias@lang}}% \ifcsdef{#2@alias@opts}{% \edef\xpg@tmp@opts{\csuse{#2@alias@opts},#1}% }{}% }{}% \tl_if_blank:nF {\xpg@tmp@opts}{% % Register the language options \polyglossia@set@lang@options:nn {\xpg@tmp@lang} {\xpg@tmp@opts}% }% % Now switch patterns \csuse@warn{\csuse{xpg@tmp@lang}@language}% % And activate hyphenmins \use@localhyphenmins[\xpg@tmp@opts]{\xpg@tmp@lang}% } {\ifbool{xpg@noset@groups}{}{\xpg@unset@group@aux}} \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, luatexrenderer .cs_set:Np = \l_polyglossia_luatex_renderer, luatexrenderer .value_required:n = true, } \keys_set:nn { polyglossia } { localmarks = false, verbose = true, babelshorthands = false, luatexrenderer = Harfbuzz } % load by default latex \setmainlanguage{latex} % then process key in order to overwrite \ProcessKeysOptions{polyglossia} % Set the LuaTeX renderer. As opposed to fontspec, we use Harfbuzz by default. % This can be changed via the luatexrenderer package option. \ifluatex \exp_args:Nee \str_if_eq:nnF{\l_polyglossia_luatex_renderer}{none} { \xpg@info{Setting~ LuaTeX~ font~ renderer~ to~ \l_polyglossia_luatex_renderer} \exp_args:Nee \defaultfontfeatures{Renderer=\l_polyglossia_luatex_renderer} } \fi \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