# Why does media9 need babel?

I wonder why the media9 package, a new replacement for movie15, needs babel? And what will happen if I would want to load polyglossia instead of babel as it is required for XeLaTeX to compile Russian text (note that standard babel conflicts with XeLaTeX if Russian language is requested)?

NB: Fortunately, there is a custom russification for babel (http://ctan.org/pkg/russian) which does not conflict with XeLaTeX--I am just curious.

-
The package uses \defineshorthand; I believe it can easily dispense with it. –  egreg Apr 4 '12 at 14:06
@egreg: Indeed, media9 uses \defineshorthand. Could we replace it with something home-made? –  AlexG Apr 4 '12 at 14:28

In media9, the command \defineshorthand, defined in babel, is used in order to correctly treat possibly active characters that may occur in URLs and path specifications passed to \includemedia.

Some characters frequently encountered in URLs, such as : and ~ have a special meaning in a standard LaTeX environment or get the same, if a certain language package is loaded with babel. However, URLs and paths containing such characters must be inserted verbatim into certain PDF objects related to media inclusion.

As an example, one of the characters \usepackage[french]{babel} makes active is :. In file frenchb.ldf, : is redefined as

\initiate@active@char{:}%
\declare@shorthand{french}{:}{%
\ifhmode
\ifdim\lastskip>\z@
\unskip\penalty\@M\Fcolonspace
\else
\FDP@colonspace
\fi
\fi
\string:}


In order to prevent \includemedia from inserting rubbish into the PDF, it temporarily redefines it as a simple letter:

\defineshorthand{:}{\detokenize{:}}


which is undone, as soon as command \includemedia has completed.

I am not happy with media9 depending on babel. I prefer a stand-alone solution. Maybe someone capable can help?

-
Formal answer to my question as it was formulated is given by Alexander Grahn, so I am going to accept his answer. But I also want the package media9 to be improved so I am postponing formal approval for not to disturb fruitful discussion. –  Igor Kotelnikov Apr 5 '12 at 6:55
Next release (to appear after Easter) won't depend on babel any longer, thanks to @egreg! –  AlexG Apr 5 '12 at 15:33

It seems that media9 requires babel just to have available \defineshorthand, which is used in the macro \mix@uribegin, which has several lines such as

\defineshorthand{"}{\detokenize{"}}%


which is meant to say: if " is active, redefine it to \detokenize{"}. The same effect may be obtained by using a helper macro:

\def\neutralize#1{%
\begingroup\lccode~=#1\lowercase{\endgroup\def~}{\detokenize{#1}}}


and changing the line above into

\neutralize{"}


If an active " is found, it will be changed into a detokenized ".

In LaTeX3 parlance this might be

\group_begin:
\char_set_catcode_active:N \~
\cs_new:Npn \mix_neutralize_active_char:n #1
{
\group_begin:
\char_set_lccode:nn { ~ }{ #1 }
\tl_to_lowercase:n { \group_end: \cs_set:Npn ~ }{\token_to_str:N #1}
}
\cs_new:Npn \mix_uribegin:
{
\group_begin:
\mix_neutralize_active_char:n {"}
\mix_neutralize_active_char:n {:}
\mix_neutralize_active_char:n {/}
\mix_neutralize_active_char:n {?}
\mix_neutralize_active_char:n {[}
\mix_neutralize_active_char:n {]}
\mix_neutralize_active_char:n {@}
\mix_neutralize_active_char:n {!}
\mix_neutralize_active_char:n {$} \mix_neutralize_active_char:n {&} \mix_neutralize_active_char:n {'} \mix_neutralize_active_char:n {(} \mix_neutralize_active_char:n {)} \mix_neutralize_active_char:n {*} \mix_neutralize_active_char:n {+} \mix_neutralize_active_char:n {,} \mix_neutralize_active_char:n {;} \mix_neutralize_active_char:n {=} \mix_neutralize_active_char:n {-} \mix_neutralize_active_char:n {.} \mix_neutralize_active_char:n {_} \mix_neutralize_active_char:n {~} \cs_set:Npn \% {\token_to_str:N \%} \cs_set:Npn \# {\token_to_str:N \#} } \group_end: \cs_set_eq:NN \mix_uriend: \group_end:  This should replace the definitions of \mix@uribegin and \mix@uriend; where these appear, they must be replaced by \mix_uribegin: and \mix_uriend: ## EDIT Following Joseph Wright's suggestion, here's a shorter definition: \group_begin: \char_set_catcode_active:N \~ \cs_new:Npn \mix_uribegin: { \group_begin: \tl_map_inline:nn {":/?[]@!$&'()*+,=-._~}
{
\group_begin:
\char_set_lccode:nn { \~ }{ ##1 }
\tl_to_lowercase:n { \group_end: \cs_set:Npn ~ }{\token_to_str:N ##1}
}
\cs_set:Npn \% {\token_to_str:N \%}
\cs_set:Npn \# {\token_to_str:N \#}
}
\group_end:
\cs_set_eq:NN \mix_uriend: \group_end:


The principle is exactly the same, but the code is at least more elegant.

-
Unfortunately it doesn't seem to work. In case of [french]{babel}, : is translated into penalty @M : in the pdf string. I inserted your LaTeX3 code snippet into media9.sty. –  AlexG Apr 4 '12 at 15:25
@AlexanderGrahn I was expecting that not everything would work immediately. I'll try doing some tests. –  egreg Apr 4 '12 at 15:27
Thanks for your effort! –  AlexG Apr 4 '12 at 15:29
@AlexanderGrahn If I define \NewDocumentCommand{\try}{m}{\mix_uribegin:#1\mix_uriend:} and then in a French setup I do \try{?:"} I get the expected result. I'll complete the code: the ... stood for "similar lines". –  egreg Apr 4 '12 at 15:42
Thanks a lot! Your code works almost perfectly. Only ~ still doesn't work. Is it due to its special meaning if ExplSyntaxOn? The error is: ! Missing \endcsname inserted. <to be read again> \unhbox l.30 ]{}{":/?[]@!\$&'()*+,;=-._~} –  AlexG Apr 4 '12 at 19:51