% babelbidi-lang.sty % % Babelbidi: Bidi extensions for Babel. % % Copyright (C) 2026 Amer Amikhteh % % This file is part of the Babelbidi package. % % This work is free software: you may redistribute it and/or modify % it under the terms of the LaTeX Project Public License as published % by the LaTeX Project, either version 1.3c of the License, or % (at your option) any later version. % % This work is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. % % This work is "maintained" by Amer Amikhteh. \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{babelbidi-lang} [2026/10/14 v0.3.0 Babel language metadata, selection, and bidi utilities] \makeatletter % -------------------------------------------------------------------------- % Manual language options % -------------------------------------------------------------------------- \def\bbd@option@code{} \def\bbd@option@latin{} \def\bbd@option@ltr{} \def\bbd@option@rtl{} \DeclareKeys[babelbidi-lang]{% code .store = \bbd@option@code, latin .store = \bbd@option@latin, ltr .store = \bbd@option@ltr, rtl .store = \bbd@option@rtl } \ProcessKeyOptions[babelbidi-lang] % -------------------------------------------------------------------------- % Constants % -------------------------------------------------------------------------- \def\bbd@name@english{english} \def\bbd@name@null{null} \def\bbd@name@nil{nil} \def\bbd@script@latin{Latin} \def\bbd@direction@ltr{LTR} \def\bbd@direction@rtl{RTL} % -------------------------------------------------------------------------- % Babel language metadata % -------------------------------------------------------------------------- \def\bbd@script#1{% \ifcsname bbl@sname@#1\endcsname \csname bbl@sname@#1\endcsname \else null% \fi } \def\bbd@dir#1{% \def\bbd@dirresult{null}% \edef\bbd@dir@language{#1}% \ifx\bbd@dir@language\bbd@name@nil % nil is a placeholder, not a candidate auxiliary language. \else \ifcsname bbl@sname@#1\endcsname \ifcsname bbl@provide@dirs\endcsname % Babel also writes Lua locale properties for localeid. % Assign the inspected language's id in a local context. \begingroup \edef\languagename{#1}% \bbl@id@assign \bbl@provide@dirs{#1}% \endgroup \fi \ifcsname bbl@wdir@#1\endcsname \edef\bbd@wdir{% \csname bbl@wdir@#1\endcsname }% \ifx\bbd@wdir\@empty \def\bbd@dirresult{null}% \else \ifnum\bbd@wdir=0 \def\bbd@dirresult{LTR}% \else \def\bbd@dirresult{RTL}% \fi \fi \fi \fi \fi } \def\bbd@english{% \def\bbd@result{null}% \def\bbd@found{0}% \bbl@foreach{\bbl@ini@loaded}{% \ifnum\bbd@found=0 \edef\bbd@tmp{##1}% \ifx\bbd@tmp\bbd@name@english \def\bbd@result{english}% \def\bbd@found{1}% \fi \fi }% } % -------------------------------------------------------------------------- % Metadata tests % -------------------------------------------------------------------------- \newif\ifbbd@latin \newif\ifbbd@direction \def\bbd@if@latin#1{% \bbd@latinfalse \edef\bbd@tmp{#1}% \ifx\bbd@tmp\bbd@name@nil \let\bbd@tmp\bbd@name@null \else \edef\bbd@tmp{\bbd@script{#1}}% \fi \ifx\bbd@tmp\bbd@script@latin \bbd@latintrue \fi } \def\bbd@if@direction#1#2{% \bbd@directionfalse \bbd@dir{#1}% \edef\bbd@wanted{#2}% \ifx\bbd@dirresult\bbd@wanted \bbd@directiontrue \fi } % -------------------------------------------------------------------------- % Search functions % -------------------------------------------------------------------------- \def\bbd@first@latin{% \def\bbd@result{null}% \def\bbd@found{0}% \bbl@foreach{\bbl@ini@loaded}{% \ifnum\bbd@found=0 \bbd@if@latin{##1}% \ifbbd@latin \edef\bbd@result{##1}% \def\bbd@found{1}% \fi \fi }% } \def\bbd@first@direction#1{% \def\bbd@result{null}% \def\bbd@found{0}% \bbl@foreach{\bbl@ini@loaded}{% \ifnum\bbd@found=0 \bbd@if@direction{##1}{#1}% \ifbbd@direction \edef\bbd@result{##1}% \def\bbd@found{1}% \fi \fi }% } % -------------------------------------------------------------------------- % Language selectors % -------------------------------------------------------------------------- \def\bbd@select@code{% \edef\bbd@main{\bbl@main@language}% \bbd@if@latin{\bbd@main}% \ifbbd@latin \edef\bbd@result{\bbd@main}% \else \bbd@english \ifx\bbd@result\bbd@name@null \bbd@first@latin \ifx\bbd@result\bbd@name@null \bbd@if@direction{\bbd@main}{\bbd@direction@ltr}% \ifbbd@direction \edef\bbd@result{\bbd@main}% \else \bbd@first@direction{\bbd@direction@ltr}% \ifx\bbd@result\bbd@name@null \ifx\bbd@main\bbd@name@nil \def\bbd@result{english}% \else \edef\bbd@result{\bbd@main}% \fi \fi \fi \fi \fi \fi } \def\bbd@select@latin{% \edef\bbd@main{\bbl@main@language}% \bbd@if@latin{\bbd@main}% \ifbbd@latin \edef\bbd@result{\bbd@main}% \else \bbd@first@latin \ifx\bbd@result\bbd@name@null \def\bbd@result{english}% \fi \fi } \def\bbd@select@ltr{% \edef\bbd@main{\bbl@main@language}% \bbd@if@direction{\bbd@main}{\bbd@direction@ltr}% \ifbbd@direction \edef\bbd@result{\bbd@main}% \else \bbd@first@direction{\bbd@direction@ltr}% \ifx\bbd@result\bbd@name@null \def\bbd@result{english}% \fi \fi } \def\bbd@select@rtl{% \edef\bbd@main{\bbl@main@language}% \bbd@if@direction{\bbd@main}{\bbd@direction@rtl}% \ifbbd@direction \edef\bbd@result{\bbd@main}% \else \bbd@first@direction{\bbd@direction@rtl}% \ifx\bbd@result\bbd@name@null \def\bbd@result{arabic}% \fi \fi } % -------------------------------------------------------------------------- % Select the four aliases at package load and after each babelprovide % -------------------------------------------------------------------------- \def\bbd@update@langs{% \begingroup \ifx\bbd@option@code\@empty \bbd@select@code \xdef\bbd@main@code{\bbd@result}% \else \xdef\bbd@main@code{\bbd@option@code}% \fi \ifx\bbd@option@latin\@empty \bbd@select@latin \xdef\bbd@main@latin{\bbd@result}% \else \xdef\bbd@main@latin{\bbd@option@latin}% \fi \ifx\bbd@option@ltr\@empty \bbd@select@ltr \xdef\bbd@main@ltr{\bbd@result}% \else \xdef\bbd@main@ltr{\bbd@option@ltr}% \fi \ifx\bbd@option@rtl\@empty \bbd@select@rtl \xdef\bbd@main@rtl{\bbd@result}% \else \xdef\bbd@main@rtl{\bbd@option@rtl}% \fi \endgroup } \bbd@update@langs % Preserve Babel's optional-argument parser and update immediately in the % preamble as well as in the document, after Babel has finished its work. \NewCommandCopy\bbd@babelprovide\babelprovide \RenewDocumentCommand\babelprovide{O{} m}{% \bbd@babelprovide[#1]{#2}% \bbd@update@langs } % -------------------------------------------------------------------------- % Inline language commands % -------------------------------------------------------------------------- \NewDocumentCommand\lr{m}{\foreignlanguage[captions]{\bbd@main@ltr}{#1}} \NewDocumentCommand\rl{m}{\foreignlanguage[captions]{\bbd@main@rtl}{#1}} % -------------------------------------------------------------------------- % Latin environment % -------------------------------------------------------------------------- \NewDocumentEnvironment{latin}{}% {% \par \begin{otherlanguage}{\bbd@main@latin}% }% {% \end{otherlanguage}% \par }% % ------------------------------------------ % Date helpers % ------------------------------------------ \DeclareRobustCommand{\latintoday}{% \foreignlanguage[date]{\bbd@main@latin}{\today}% } \makeatother \endinput