ſ (long s) and hyphenation
For LuaTeX here is an implementation of David Carlisles idea to create a hypenate
callback. It works by replacing every ſ
with a marked s
before hyphenation and then recovering the original characters after hyphenation:
\documentclass{article}
\usepackage[ngerman]{babel}
\usepackage{luacode}
\begin{luacode*}
local sattr = luatexbase.new_attribute("longsattr")
local disc = node.id'disc'
print('DISC', disc)
local function long_to_s(head, tail)
for n in node.traverse(head) do
if n == tail then break end
if n.id == disc then
print(n)
long_to_s(n.pre)
long_to_s(n.post)
long_to_s(n.replace)
end
if n.char == 383 then
n.char = 115
node.set_attribute(n, sattr, 383)
end
end
end
local function s_to_long(head, tail)
for n in node.traverse(head) do
if n == tail then break end
if n.id == disc then
s_to_long(n.pre)
s_to_long(n.post)
s_to_long(n.replace)
end
local a = node.get_attribute(n, sattr)
if a then
n.char = a
node.unset_attribute(n, sattr)
end
end
end
local function myhyph(head, tail)
long_to_s(head, tail)
lang.hyphenate(head, tail)
s_to_long(head, tail)
end
luatexbase.add_to_callback("hyphenate",myhyph,"hyphenate with modified s")
\end{luacode*}
\begin{document}
XXX Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft
XXX Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft
\end{document}
LuaTeX also allows you to manipulate the hyphenation pattern during a run, so you can also use (this is an automated version of David Carlisles choice (b)):
\documentclass{article}
\usepackage[ngerman]{babel}
\usepackage{luacode}
\begin{luacode*}
local l = lang.new(tex.language)
l:patterns(l:patterns():gsub('s', 'ſ'))
\end{luacode*}
\begin{document}
XXX Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft
XXX Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft Geſellſchaft
\end{document}
A simple way to do this is to choose a font that supports ſ as an open type character variant, e.g., EB Garamond. Then you can just select that variant when you need it.
(Re-reading the comments above, I see this corresponds to option (c) from David Carlisle, which you said wasn't suitable, but this MWE shows you can have both kinds of s with this method.)
Update showing iſt and ſelbes.
\documentclass{article}
\usepackage[ngerman]{babel}
\babelfont{rm}{EB Garamond}
\begin{document}
XXX Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft
\addfontfeature{CharacterVariant=1}
XXX Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft Gesellschaft
ist selbes
\end{document}