How to reencode old OT2 files into T2A in LaTeX?

I have some old files prepared with the OT2 encoding and Washington cyrillic, i.e. the TeX files are typeset as Latin letters using the American keyboard, whereas the output is in Cyrillic letters. Now, I want to use parts of these old files in a new one but in another font which is T2A encoded in LaTeX (not XeTeX) environment. In other words, I will obtain a file in which one part is typeset in OT2 and another one in T2A encoding, and both should print the output in the same T2A font.

Changing input encoding via inputenc.sty does not work, since it is based on activating characters >127, and activating ASCII characters A-Z, a-z will severely harm all TeX commands. I fixed this problem by generating new TFM files via the afm2tfm utility, but I consider this solution very inappropriate. Does anybody know how to force LaTeX to output a Cyrillic Г, when it finds G? Maybe the same question can be raised for dealing with other scripts.

There is an answer at Serbian Cyrillic using LuaTeX and XeTeX if one uses XeTeX, but I am interested in a LaTeX solution.

• I'm afraid that only creating a bunch of virtual fonts can help. You should map the Latin characters to their Cyrillic counterpart using the OT2 correspondence with the same ligatures. It's probably easier processing the text with Perl or something like it. – egreg Jul 20 '13 at 21:20

This would be quite a work. You need to build virtual fonts mapping each Latin Character to their T2A counterpart using the OT2 correspondence with the ligatures pointing to the right character.

It's possible to automate this creation, which should be made for every font you plan to use, because the scheme is fixed. I can easily predict many hours of tedious labour.

A TeX solution could consist in examining characters in pairs. If they form a ligature, print the corresponding character and go on with the next two; otherwise, print the first and restart with the next two.

Here's a proof of concept; there are problems with spaces, so this simple macros won't work in the argument of other commands. A slower routine should be used, for that case, or a different approach with LaTeX3 functions.

\documentclass{article}
\usepackage[T2A,T1]{fontenc}

\makeatletter
\newcommand{\cyrtext}{%
\begingroup\fontencoding{T2A}\selectfont
\catcode\ =12 \@cyrtext}

\def\@cyrtext#1{%
\@@cyrtext#1\@empty\@empty
\endgroup
}

\def\@@cyrtext#1#2{%
\ifx#2\@empty
\csname @cyr@#1\endcsname
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{\@@cyr#1#2}%
}
\def\@@cyr#1#2{%
\ifcsname @cyr@#1#2\endcsname
\csname @cyr@#1#2\endcsname
\expandafter\@firstoftwo
\else
\csname @cyr@#1\endcsname
\expandafter\@secondoftwo
\fi
{\@@cyrtext}%
{\@@cyrtext#2}%
}
\def\@cyr@R{\CYRR}
\def\@cyr@u{\cyru}
\def\@cyr@s{\cyrs}
\def\@cyr@k{\cyrk}
\def\@cyr@i{\cyri}
\@namedef{@cyr@i0}{\cyrishrt}
\@namedef{@cyr@ }{ }
\def\@cyr@ya{\cyrya}
\def\@cyr@z{\cyrz}
\def\@cyr@y{\cyrery}
%%% supplement all other needed macros
\makeatother

\begin{document}
\cyrtext{Russkii0 yazyk}
\end{document}


Here's a possible implementation with LaTeX3, which allows for including \cyrtext as argument to another command. The character | shouldn't appear in the argument. Nor, with the current definitions, any macro.

\documentclass{article}
\usepackage[T2A,T1]{fontenc}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\cyrtext}{m}
{
\group_begin:
\fontencoding{T2A}\selectfont
\djk_cyrtext:n { #1 }
\group_end:
}

\tl_new:N \l_djk_cyrtext_tl
\prop_new:N \g_djk_cyrletters_prop
\cs_generate_variant:Nn \prop_get:Nn { Nx }

\cs_new_protected:Npn \djk_cyrtext:n #1
{
\tl_set:Nn \l_djk_cyrtext_tl { #1 \prg_do_nothing: \prg_do_nothing: }
\tl_replace_all:Nnn \l_djk_cyrtext_tl { ~ } { | }
\exp_after:wN \__djk_cyrtext:NN \l_djk_cyrtext_tl
}

\cs_new_protected:Npn \__djk_cyrtext:NN #1 #2
{
\token_if_eq_meaning:NNTF \prg_do_nothing: #2
{ \prop_get:Nx \g_djk_cyrletters_prop { #1 } }
{ \__djk_cyrtext_aux:NN #1 #2 }
}

\cs_new_protected:Npn \__djk_cyrtext_aux:NN #1 #2
{
\prop_if_in:NnTF \g_djk_cyrletters_prop { #1 #2 }
{ \prop_get:Nn \g_djk_cyrletters_prop { #1 #2 } \__djk_cyrtext:NN }
{ \prop_get:Nn \g_djk_cyrletters_prop { #1 } \__djk_cyrtext:NN #2 }
}

\prop_gput:Nnn \g_djk_cyrletters_prop { } { } % empty property
\prop_gput:Nnn \g_djk_cyrletters_prop { | } { ~ } % | is a space
\prop_gput:Nnn \g_djk_cyrletters_prop { R } { \CYRR }
\prop_gput:Nnn \g_djk_cyrletters_prop { u } { \cyru }
\prop_gput:Nnn \g_djk_cyrletters_prop { s } { \cyrs }
\prop_gput:Nnn \g_djk_cyrletters_prop { k } { \cyrk }
\prop_gput:Nnn \g_djk_cyrletters_prop { i } { \cyri }
\prop_gput:Nnn \g_djk_cyrletters_prop { i0 }{ \cyrishrt }
\prop_gput:Nnn \g_djk_cyrletters_prop { ya }{ \cyrya }
\prop_gput:Nnn \g_djk_cyrletters_prop { z } { \cyrz }
\prop_gput:Nnn \g_djk_cyrletters_prop { y } { \cyrery }
%%% add all the other combinations
\ExplSyntaxOff

\begin{document}
\cyrtext{Russkii0 yazyk}

\textbf{\cyrtext{Russkii0}}
\end{document}


• Thanks Egreg for this interstring solutuion. Perheaps, it is possible to hide commands, using \everypar for instance. Nevertheless, we have to skip math formulae, such as $a\in\mathbb R$ and similar that appears inside paragraphs. Furthuremore we have to skip aqll commands and control sequences. For instance "\hskip 2cm" or "\hbox to 2in" etc. After all some manual adjustment will be necessary. Namely, we can find user defined macros, for instance "\mycommand{abc}" and we can't be sure whether "abc" is user defined control sequence or part of the text. So, I vote for vurtual fonts. – DjK Oct 29 '13 at 20:46
• Note that as of September 2014, \prop_get:Nn has been renamed to \prop_item:Nn` – egreg Sep 17 '14 at 17:55