Porting the luatex/ConTeXt module "translate" to lualatex

This is more a proof-of-concept than a real bulletproof style file, but it does what you request:

The style file (filterltx.sty)

\ProvidesPackage{filterltx}
\RequirePackage{luatexbase,luacode}

\begin{luacode*}
do
  local replace = {}

  local filter = function ( buf )
    local start,stop,init,pos
    local positions = {}
    for k,v in pairs(replace) do
      local init = 1
      repeat
        start,stop = string.find(string.lower(buf),k,init,true)
        if start then
          init = stop
          pos = string.find(v,"|*|",1,plain)
          positions[#positions + 1] = pos + start - 2
        end
      until start == nil
    end
      table.sort(positions)
      for i = #positions,1,-1 do
        buf = string.sub(buf,1,positions[i] ) .. [[\penalty10000\discretionary{-}{}{\kern.03em}\nobreak \hskip 0pt plus0pt minus0pt]] .. string.sub(buf, positions[i] + 1)
      end
    return buf
  end

  function enablefilter()
    luatexbase.add_to_callback('process_input_buffer', filter, 'filter')
  end

  function disablefilter()
    luatexbase.remove_from_callback('process_input_buffer', 'filter')
  end

  function translateinput( arg1,arg2 )
    replace[arg1] = arg2
  end

end
\end{luacode*}

\newcommand\enableinputtranslation{
  \directlua{enablefilter()}
}
\newcommand\disableinputtranslation{
  \directlua{disablefilter()}
}
\newcommand\translateinput[2]{
  \directlua{translateinput("\luatexluaescapestring{#1}","\luatexluaescapestring{#2}")}
}

and the test document (test.tex):

\documentclass{article}
\usepackage{filterltx}

\translateinput{shelfful}{shelf|*|ful} 
\translateinput{selfish}{self|*|ish}
\translateinput{halflife}{half|*|life} 
\translateinput{cufflink}{cuff|*|link}

\begin{document}

Ligatures not disabled:\\
shelfful selfish halflife cufflink 

\medskip
\enableinputtranslation 
Ligatures disabled:\\
shelfful selfish halflife cufflink\\
Shelfful Selfish Halflife Cufflink

\medskip
\disableinputtranslation
Ligatures not disabled:\\
shelfful selfish halflife cufflink 

% to make sure the words still hyphenate:
% \showhyphens{shelfful selfish halflife cufflink}
% yields: shelf- ful self- ish half- life cuff- link
\end{document}

Run with lualatex test.

The output: filteroutput


The basic functionality is part of luatex. For example, the following code (in luatex plain format) changes "hello" to "hi".

\directlua{
  local gsub = string.gsub
  local function translate(line)
      return gsub(line, "hello", "hi")
  end

  callback.register("process_input_buffer", translate)
}

hello world

why say hello
\bye

The ConTeXt code just provides syntax sugar so that you can easily define multiple translations. I tried to translate this code to lualatex but in lualatex I get an error

uatexbase-mcb error: function callback.register has been trapped,
(luatexbase-mcb)             please use luatexbase.add_to_callback instead.

stack traceback:
    [C]: in function 'error'
    .../share/texmf-dist/tex/luatex/luatexbase/modutils.lua:26: in function 'modul
e_error_int'
    .../share/texmf-dist/tex/luatex/luatexbase/modutils.lua:45: in function 'err'
    /usr/share/texmf-dist/tex/luatex/luatexbase/mcb.lua:85: in function 'register'

    <\directlua >:7: in main chunk.
\luacode@execute ...oup \luatexbase@directlua {#1}

l.11 \end{luacode}

but I could not get the code to work with luatexbase.add_to_callback either.

The above plain TeX code shows that basic functionality is part of luatex and should be easily accessible in lualatex as well (once you figure out the appropriate renaming done by luacode package).