Korrekturen nach Analyse der Trennstellenkategorisierung.
[wortliste.git] / skripte / python / s2long-s.py
blobd263bdc68d63e8982165f8aa9116c7ad1c513b6d
1 #!/usr/bin/env python
2 # -*- coding: utf8 -*-
3 # :Copyright: © 2012, 2014 Günter Milde.
4 # :Licence: This work may be distributed and/or modified under
5 # the conditions of the `LaTeX Project Public License`,
6 # either version 1.3 of this license or (at your option)
7 # any later version.
8 # :Version: 0.3 (2014-06-14)
10 # ===================================================================
11 # Langes oder rundes S: Automatische Konversion nach Silbentrennung
12 # ===================================================================
14 # ::
16 """
17 Automatische Bestimmung der S-Schreibung auf Basis der Silbentrennung
18 in der `Wortliste der deutschsprachigen Trennmustermannschaft`."""
20 # .. contents::
22 # Vorspann
23 # ========
25 # Lade Funktionen und Klassen für reguläre Ausdrücke::
27 import re, sys, os, optparse
29 # path for local Python modules
30 sys.path.append(os.path.dirname(__file__))
31 from werkzeug import WordFile, WordEntry, join_word
34 # Trennzeichen
35 # ------------
37 # Die Trennzeichen der Wortliste sind
39 # == ================================================================
40 # \· ungewichtete Trennstellen (solche, wo noch niemand sich um die
41 # Gewichtung gekümmert hat)
42 # . unerwünschte Trennstellen (sinnverwirrend), z.B. Ur-in.stinkt
43 # = Haupttrennstellen
44 # \- Nebentrennstellen
45 # < Trennstellen nach Vorsilben
46 # > Trennstellen vor Suffixen
47 # == ================================================================
50 # Funktionen
51 # ==========
53 # ſ-Regeln
54 # --------
56 # Siehe [wikipedia]_ und ("DDR"-) [Duden]_ (Regeln K 44,45)::
58 def s_ersetzen(word):
60 # Ausnahmeregeln
61 # ~~~~~~~~~~~~~~
63 # Für sz und sk gelten Regeln, welche die Herkunft der Wörter beachten.
64 # Diese und weitere spezielle Fälle, welche Lang-S vor Trennstellen verlangen
65 # sind in `Ausnahmen Lang-S`_ gelistet::
67 for fall in ausnahmen_lang_s:
68 word = word.replace(fall.replace(u'ſ', u's'), fall)
70 # Allgemeine Regeln
71 # ~~~~~~~~~~~~~~~~~
73 # ſ steht im Silbenanlaut::
75 word = re.sub(ur'(^|[-<>=·.])s', ur'\1ſ', word)
77 # ſ steht im Inlaut als stimmhaftes s zwischen Vokalen
78 # (gilt auch für ungetrenntes ss zwischen Selbstlauten, z.B. Hausse, Baisse)::
80 word = re.sub(ur'([AEIOUYÄÖÜaeiouäöüé])s([aeiouyäöüé])', ur'\1ſ\2', word)
81 word = re.sub(ur'([AEIOUYÄÖÜaeiouäöüé])ss([aeiouyäöüé])', ur'\1ſſ\2', word)
84 # Doppel-S statt ß
85 # ----------------
87 # Wenn kein ß vorhanden ist (GROSSSCHREIBUNG) und in der Schweiz wird ss
88 # statt ß geschrieben. Seit 1996 wird auch am Wort-/Silbenende und vor t nach
89 # kurzem Vokal ss geschrieben. Der "Reformduden" empfielt im Fraktursatz die
90 # Schreibung "ſs" (die auch vor 1901 in Gebrauch war).
92 # Wir übernehmen diese Schreibung am Wort-/Silbenende::
94 word = re.sub(u'ss($|[-=<>.])', ur'ſs\1', word)
96 # Vor t schreiben wir nach kurzem Vokal Doppel-ſ::
98 word = word.replace(u'sst', u'ſſt')
100 # Nach langem Vokal steht auch in de-1996 ein ß, in de-x-GROSS ist keine
101 # ſ-Wandlung nötig/möglich.
102 # TODO: in der Schweizer Orthographie müßte nach langem Vokal oder Zwielaut
103 # auch vor t ein ſs stehen (beißt -> beiſst).
105 # Verbindungen und Digraphen
106 # --------------------------
108 # ſ steht in den Verbindungen sp, st, sch und in Digraphen::
110 word = word.replace(u'st', u'ſt')
111 word = word.replace(u'sp', u'ſp')
112 word = word.replace(u'sch', u'ſch')
114 # word = word.replace(u'ps', u'pſ')
115 word = word.replace(u'Ps', u'Pſ') # Ψ
116 word = re.sub(ur'^ps', ur'pſ', word) # ψ (ps am Wortanfang)
117 word = re.sub(ur'([-<>=·.])ps', ur'\1pſ', word) # ψ (ps am Silbenanfang)
120 # ſ vor Trennstellen
121 # ------------------
123 # Die Verbindungen ss, sp¹, st werden zu ſſ, ſp und ſt, auch wenn sie
124 # durch eine Nebentrennstelle (Trennung innerhalb eines Wortbestandteiles)
125 # getrennt sind. Das s bleibt rund im Auslaut, d.h. am Wortende und vor
126 # einer Haupttrennstelle (Trennung an der Grenze zweier Wortbestandteile
127 # (Vorsilb<Stamm, Bestimmungswort=Grundwort).
129 # ¹ s bleibt rund vor Nebentrennstelle wenn ph folgt (Phos-phor).
131 # ::
133 word = re.sub(ur's([-.]+)ſ([aeiouyäöüé])', ur'ſ\1ſ\2', word)
134 word = re.sub(ur's([-.]+)p([^h])', ur'ſ\1p\2', word)
135 word = re.sub(ur'(^|[^s])s([-.]+)t', ur'\1ſ\2t', word) # Reformschreibung
137 # ſ wird auch geschrieben, wenn der S-Laut nur scheinbar im Auslaut steht,
138 # weil ein folgendes unbetontes e ausfällt:
140 # "ss-l", aber nicht bei "...eiss-l" und "Ess-lingen" mit ss statt ß::
142 word = re.sub(ur'([^iE])ss-l', ur'\1ſſ-l', word) # Droſſ-lung, ...
144 # "s-l" (Baſ-ler, pinſ-le, Kapſ-lung, Wechſ-ler, wechſ-le, Ries-ling),
145 # aber nicht bei
146 # M.s-l: Mus-lim, Mos-lem, ...
147 # [iys]s-l: Gris-ly, is-lam, Crys-ler, ... (ss-l siehe obige Regel)
148 # s-la: Bra-tis-la-va, Gos-lar, Bres-lau,
150 word = re.sub(ur'([^mM][^siy])s-l([^a])', ur'\1ſ-l\2', word)
152 # (für weitere Fälle siehe auch `Ausnahmen Lang-S`_):
155 # Fremdwörter und Eigennamen mit Schluss-ß
156 # """"""""""""""""""""""""""""""""""""""""
158 # Der 1971er [Duden]_ führt zu englischen Fremdwörtern mit Schluß-ß die
159 # österreichische Schreibung mit "ss" auf (Miß, engl. und österr. Schreibung
160 # Miss) wobei das Schluß-s nicht unterstrichen ist (also lang sein müßte?). So
161 # auch Boss, Business, Stewardess.
163 # Dagegen sagt [en.wiktionary.org]_: "the digraph «ss» was often written «ſs»
164 # rather than «ſſ»". Die Lang-S Seite der [wikipedia]_ zeigt Beispiele der
165 # englischen Schreibung "Congreſs".
167 # ::
169 # TODO ſſ oder ſs (wie in de-1996)? :
170 # if lang == 'de-1901':
171 # word = re.sub(ur'ss$', ur'ſſ', word)
172 # word = word.replace(u'ss=', u'ſſ=')
173 # word = word.replace(u'ss-ſch', u'ſſ-ſch')
175 return word
178 # Ausnahmen Lang-S
179 # ~~~~~~~~~~~~~~~~~~~
181 # Teilstrings mit Lang-S vor Trennstelle.
183 # ſ wird geschrieben, wenn der S-Laut nur scheinbar im Auslaut steht,
184 # weil ein folgendes unbetontes e ausfällt::
186 ausnahmen_lang_s = [
188 u'Pilſ-ner', # < Pilsen, aber Mes-ner, Meiss-ner (de-ch)
189 u'Klauſ-ner', # < Klause, aber Gleiss-ner (de-ch)
190 u'riſſ-ne', # ge<riss-ne, ... (de-ch)
191 u'oſſ-ne', # ge<schoss-ne, ge<schloss-ne, ... (de-ch)
192 u'er<leſ-ne', # auserlesne
193 u'unſ-r', # unsre, unsrige, ...
194 u'ſſl', # Röſſl
195 u'ſl', # Beiſl, Häuſl
196 u'kreiſ-le',
197 u'Wieſn',
198 u'Schiſſ-la-weng',
199 u'Pſſſt', # im Duden pst!
202 # ſ steht in Abkürzungen, wenn es im abgekürzten Wort steht
203 # (Abſ. - Abſatz/Abſender, (de)creſc. - (de)creſcendo, daſ. - daſelbst ...)
204 # ::
206 ausnahmen_lang_s.extend([
208 u'creſc', # creſcendo
209 u'Diſſ', # Diſſertation
210 u'Maſſ', # Maſſachuſetts
214 # Alternativtrennung, wo beide Fälle ſ verlangen::
216 ausnahmen_lang_s.extend([
218 u'er<.]ſa' # Kind=er<.satz/Kin-der=satz
219 u'ſ[-ter=/t' # Tes[-ter=/t=er<.]ken-nung
223 # Fremdwörter und Eigennamen
224 # --------------------------
226 # Schreibung nach Regeln der Herkunftssprache. Dabei ist zu bedenken, daß zu
227 # der Zeit, als das lange s im Antiquasatz noch üblich war (bis ca. 1800), die
228 # Rechtschreibung freier gehandhabt wurde und mehrfach Wandlungen unterworfen
229 # war [West06]_.
231 # Im Deutschen werden im Fraktursatz nicht eingedeutschte Fremdwörter
232 # lateinischen und romanischen Ursprungs in Antiqua mit rund-s geschrieben.
234 # English:
235 # The long, medial, or descending ess, as distinct from the short or
236 # terminal ess. In Roman script, the long ess was used everywhere except at
237 # the end of words, where the short ess was used, and frequently in what is
238 # now the digraph «ss», which was often written «ſs» rather than «ſſ»
239 # [en.wiktionary.org]_. See also [Typefounder08]_ and [West06]_.
241 # ::
243 ausnahmen_lang_s.extend([
245 u'ſh', # (englisch)
246 # u'Diſc', # (englisch) TODO: so, oder Disc (wie eingedeutscht Disk)
247 u'Cſar', # Cs -> Tsch (Csardas, ... ungarisch)
248 u'ſz', # polnisch, ungarisch (Liszt, Puszta)
250 # ts am Silbenanfang (chinesisch, japanisch, griechisch)::
252 u'Tſa', u'Tſe', u'tſe', u'tſi', u'Tſu', u'tſu',
254 # In vielen (aber nicht allen) Fremdwörtern steht ſz trotz Trennzeichen::
256 u'ſ-zen', # Adoleszenz, Aszendent, ...
257 u'ſ-ze-n', # Damaszener, ...
258 u'ſ-ze-r', # vis-ze-ral...
259 u'aſ-zi', # [Ll]asziv, laszive, ...
260 u'viſ-zi-do', # Mukoviszidose
261 u'ſ-zil-l' , # Oszillation, Oszilloskop, ...
262 u'asſ-zi', # faszinieren, fasziniert, ...
263 u'gnoſ-zie', # rekognoszieren,
264 u'o-reſ-z', # fluoreszieren, phosporeszieren, ...
265 u'-reſ-c', # Fluo-res-ce-in
266 u'le-biſ-zi', # Plebiszit, ...
268 # ſ steht in der Endung sk in Wörtern und Namen slawischen Ursprungs
270 # ::
272 u'Gdanſk',
273 u'Minſk',
274 u'Mur-manſk',
275 u'ſi-birſk',
276 u'Smo-lenſk',
278 # ſſ steht wenn auf die Vorsilbe "dis-" oder "as-" ein "s" folgt::
280 u'aſ<ſ', # Assoziation, ...
281 u'diſ<ſ', # Dissoziation, ...
282 u'Diſ<ſ', # dissonant, ...
286 # s-Regeln
287 # --------
289 # Test auf verbliebene Unklarheiten
291 # Wenn ein Wort "s" nur an Stellen enthält wo die Regeln rundes S vorsehen,
292 # ist die automatische Konversion abgeschlossen.
294 # Ausnahmen und spezielle Regeln
296 # Liste von Teilstrings, welche stets rund-s behalten ::
298 ausnahmen_rund_s = [
300 # Abkürzungen::
302 u'Ausg', # Ausgan, Ausgabe
303 u'ausſchl',
304 u'desgl', # des<gleichen
305 u'hrsg', # herausgegeben
306 u'Hrsg', # Herausgeber
307 u'insb',
309 # ausgelassenes flüchtiges e::
311 u'Dresd-ne', # Dresd-ner/Dresd-ne-rin
313 # s steht auch in einigen Fremdwörtern vor z und c::
315 u'on<fis-zie', # konfiszieren, ...
316 # u'le-bis-z', # plebiszit (nach [duden]_ mit Lang-S)
317 u'is-zi-pl', # Disziplin (nach [duden]_, aber Duden (1934) Diſziplin)
318 u'mas-ze-ner', # Damaszener
319 u'Disc', # TODO: rund oder Diſc (aber eingedeutscht Disk)
321 # ss im Auslaut (vgl. `Fremdwörter und Eigennamen`_)::
323 # u'Gauss', # vgl. "Briefwechsel zwischen C.F. Gauss und H.C. Schumacher, herausg. von C.A.F. Peters"
324 # aber Boſſ, Busineſſ, Dreſſ
329 def is_complete(word):
331 # Ersetze s an Stellen, wo es rund zu schreiben ist, durch ~ und teste auf
332 # verbliebene Vorkommen.
334 # Einzelfälle mit rundem S (substrings)::
336 for fall in ausnahmen_rund_s:
337 word = word.replace(fall, fall.replace('s', '~'))
339 # s steht am Wortende, auch in Zusammensetzungen (vor Haupttrennstellen)::
341 word = re.sub(ur's($|[=<>])', ur'~\1', word)
343 # Einige ältere Quellen schreiben ss am Schluss von Fremdwörtern oder Namen
344 # (Gauss). Andere schreiben ſs oder ſſ. (Vgl. `Fremdwörter und Eigennamen
345 # mit Schluss-ß`_) Wir verwenden ſs (TODO oder?)::
347 #word = re.sub(ur'ss(=|$)', ur'~~\1', word)
349 # s steht am Silbenende (vor Nebentrennstellen), wenn kein p, t, z oder ſ
350 # folgt (in der traditionellen Schreibung wird st nicht getrennt)::
352 word = re.sub(ur'ss?([·.\-][^ptzſ])', ur'~\1', word) # konservativ
354 # s steht auch vor Nebentrennstellen, wenn ph oder sch folgt::
356 word = word.replace(u's-ph', u'~-ph')
357 word = word.replace(u's-ſch', u'~-ſch')
359 # s steht nach Vorsilben (wie aus<) auch wenn s, p, t, oder z folgt::
361 word = word.replace(u's<', u'~<')
363 # s steht vor Trennstellen am Suffixanfang (wie >sen, >son),
364 # auch wenn s, p, t, oder z folgt::
366 word = word.replace(u's>', u'~>')
368 # s steht im Inlaut vor k, n, w::
370 word = re.sub(ur's([knw])', ur'~\1', word)
372 # s steht in der Verbindung sst, die in der Schweiz und
373 # bei fehlendem ß (GROSS) für ßt steht::
375 # TODO: nur nach Zielaut und langem Vokal.
376 # word = word.replace(u'ſst', u'ſ~t')
377 # word = word.replace(u'ſs-t', u'ſ~-t')
379 # s steht als zweiter Buchstabe im ersetzten ß::
381 word = word.replace(u'-ſs', u'-ſ~') # traditionelle Orthographie
383 # und suche nach übrigen Vorkommen::
385 return 's' not in word
388 # Aufruf von der Kommandozeile
389 # ============================
391 # ::
393 if __name__ == '__main__':
395 # Optionen::
397 usage = u'%prog [Optionen]\n' + __doc__
398 parser = optparse.OptionParser(usage=usage)
399 parser.add_option('-i', '--infile', dest='infile',
400 help=u'Eingangsdatei ("-" oder "stdin" für '
401 u'Standardeingabe), Vorgabe "../../wortliste"',
402 default='../../wortliste')
403 parser.add_option('-o', '--outfile', dest='outfile',
404 help=u'Ausgangsdatei, ("-" oder "stdout" für '
405 u'Standardausgabe) Vorgabe: "words-<language>-Latf.txt"',
406 default='') # wird später ausgefüllt
407 parser.add_option('-l', '--language', dest='language',
408 help=u'Sprachvariante(n) (kommagetrennte Liste von '
409 u'ISO Sprachtags), Vorgabe "de-1901"',
410 default='de-1901')
411 parser.add_option('-d', '--drop-homonyms', action="store_true",
412 default=False,
413 help=u'Bei mehrdeutigen Wörtern, die sich nur in '
414 'Lang-S-Schreibung unterscheiden, nimm nur das erste.')
416 (options, args) = parser.parse_args()
418 # Angabe der Sprachvariante nach [BCP47]_ (Reformschreibung 'de' oder
419 # 'de-1996', Schweiz 'de-CH', ...)::
421 lang = options.language
423 # Iterator::
425 if options.infile in ('-', 'stdin'):
426 wordfile = (WordEntry(line.rstrip().decode('utf-8'))
427 for line in sys.stdin)
428 else:
429 wordfile = WordFile(options.infile)
431 # Ausgabedatei::
432 if options.outfile in ('-', 'stdout'):
433 outstream = sys.stdout
434 else:
435 outfile = options.outfile or 'words-' + lang.replace(',','-')
436 + '-Latf.txt'
437 outstream = file(outfile, 'w')
440 # Hauptschleife
441 # =============
443 # Konvertiere die Wörter der Trennliste und sortiere die Ergebnisse in
444 # Listen::
446 no_of_words = 0 # Gesamtwortzahl der gewählten Sprache(n)
447 completed = [] # Automatisch konvertiert
448 irreversible = [] # Rückkonversion ungleich Original (Fehler)
449 unkategorisiert = [] # Unterscheidung in Haupt- und Nebentrennstellen fehlt
450 offen = [] # Der Algorithmus kann die Schreibweise (noch) nicht ermitteln
452 # Iteration über alle Zeilen der Wortliste::
454 for entry in wordfile:
456 word = entry.get(lang) # Wort mit Trennstellen
457 if word is None: # Wort existiert nicht in der Sprachvariante
458 continue
459 no_of_words += 1
461 # Vorsortieren
462 # ------------
464 # Wörter ohne Binnen-s müssen nicht konvertiert werden. Damit wird die
465 # Wortliste ungefähr um die Hälfte kürzer::
467 if 's' not in entry[0][:-1]:
468 completed.append(entry[0])
469 continue
471 # Regelbasierte s/ſ-Schreibung::
473 lang_s_word = s_ersetzen(word)
475 # Einsortieren nach Vollständigkeit der Ersetzungen::
477 entry.set(lang_s_word, lang) # Rückschreiben von teilweisen Ersetzungen
479 if lang_s_word.replace(u'ſ', u's') != word:
480 entry.comment = lang_s_word.replace(u'ſ', u's') + u" != " + word
481 irreversible.append(entry)
482 continue
484 if not is_complete(lang_s_word):
485 if lang_s_word.find(u's·') != -1:
486 unkategorisiert.append(entry)
487 else:
488 offen.append(entry)
489 continue
491 # Mehrdeutigkeiten [ſ/s] oder [s/ſ] auflösen::
493 lang_s_word = join_word(lang_s_word)
494 if u'/' in lang_s_word:
495 # 1. Alternative:
496 completed.append(re.sub(ur'\[(.+)/.+\]', ur'\1', lang_s_word))
497 if not options.drop_homonyms:
498 completed.append(re.sub(ur'\[.+/(.+)\]', ur'\1', lang_s_word))
499 else:
500 completed.append(lang_s_word)
501 # completed.append(lang_s_word)
504 # Ausgabe
505 # =======
507 # Wortliste mit automatisch bestimmter S-Schreibung, ohne Trennstellen::
509 outstream.write(u'\n'.join(completed).encode('utf8') + '\n')
511 # Auswertung
512 # ==========
514 # ::
516 sys.stderr.write("# Gesamtwortzahl %s %s\n" % (lang, no_of_words))
517 sys.stderr.write("# Automatisch konvertiert: %d\n" % len(completed))
518 sys.stderr.write("# erkannte Konvertierungsfehler: %d\n"
519 % len(irreversible))
520 for entry in irreversible:
521 sys.stderr.write(unicode(entry).encode('utf8')+'\n')
522 sys.stderr.write("# Kategorisierung der Trennstellen fehlt: %d\n"
523 % len(unkategorisiert))
524 for entry in unkategorisiert:
525 sys.stderr.write(unicode(entry).encode('utf8')+'\n')
526 sys.stderr.write("# noch offen/unklar: %d\n" % len(offen))
527 for entry in offen:
528 sys.stderr.write(unicode(entry).encode('utf8')+'\n')
531 # Diskussion
532 # ==========
534 # Für gebrochene Schriften gibt es den `ISO Sprachtag`_
536 # :Latf: Latin (Fraktur variant)
538 # also "Lateinisches Alphabet, gebrochen". Dieser Tag wird and die
539 # Ausgabedateien angehängt (e.g. "de-1901-Latf", "de-1996-Latf").
541 # .. _ISO Sprachtag: http://www.unicode.org/iso15924/iso15924-codes.html
543 # Statistik
544 # ---------
546 # Gesamtwortzahl (traditionelle Rechtschreibung): 427746
547 # Automatisch konvertiert: 427740
548 # Kategorisierung der Trennstellen fehlt: 0
549 # noch offen: 6
551 # Die Mehrzahl der Wörter der Trennliste wurde nach den Regeln des Dudens in
552 # die Schreibung mit langem `S` (ſ) konvertiert (wobei ungefähr die Hälfte der
553 # Wörter kein kleines `s` enthält womit die Konversion trivial wird).
555 # Für eine beschränke Anzahl offener Fälle wurden Ausnahmeregeln und Ausnahmen
556 # implementiert.
558 # Das Resultat muß noch auf nicht erfaßte Ausnahmen und Sonderfälle geprüft
559 # werden. Fehlentscheidungen sind nicht auszuschließen.
562 # Offene Fälle
563 # ------------
565 # Wörter mit identischer Schreibung ohne Lang-S
566 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
568 # Einige mehrdeutige Zusammensetzungen unterscheiden sich in der
569 # Lang-S-Schreibung, z.B.
571 # * Wach[s/ſ]tube: Wach-Stube / Wachs-Tube
572 # * Ga[s/ſ]traſſe: Gas-Trasse / Gast-Rasse
573 # * Schiff[ſ/s]tau: Schiffs-Tau / Schiff-Stau
575 # Im Normalfall schreibt s2long-s.py beide Varianten in die Ausgabedatei. Die
576 # Option --drop_homonyms kann verwendet werden, wenn dies nicht erwünscht ist.
578 # Unklare Schreibung
579 # ~~~~~~~~~~~~~~~~~~
581 # * Ersetztes SZ in reformierter Rechtschreibung, wenn ein Selbstlaut folgt
582 # (z.B. "Straſ-ſe" oder "Straſ-se).
584 # - Während in 1901-er Rechtschreibung die Trennung vor dem "ss" erfolgt
585 # (was Ersetzung mit "ſs" impliziert) wäre bei Trennung "wie normales
586 # Doppel-S" dann ein rundes S am Silbenanfang.
588 # Korrekte Fallunterscheidung geht nur bei Betrachtung der Nachbarfelder.
590 # * Tonarten (As-Dur oder Aſ-Dur)
592 # - Im Fraktur-Duden steht As *in Antiqua* mit rundem s, also
593 # keine Aussage zur Schreibung in Fraktur.
594 # - Im 1976-er [Duden]_ steht As ohne Unterstreichung des `s`,
595 # das wäre Lang-S, obgleich am Wortende!
597 # Quellen
598 # =======
600 # .. [Duden] `Der Große Duden` 16. Auflage, VEB Bibliographisches Institut
601 # Leipzig, 1971
603 # Kennzeichnet im Stichwortteil rundes s durch Unterstreichen.
605 # .. [wikipedia] Langes s
606 # http://de.wikipedia.org/wiki/Langes_s
608 # .. [en.wiktionary.org]
609 # http://en.wiktionary.org/wiki/%C5%BF
611 # .. [Typefounder08]
612 # http://typefoundry.blogspot.com/2008/01/long-s.html
614 # .. [West06] Andrew West, `The rules for long s`, 2006
615 # http://babelstone.blogspot.com/2006/06/rules-for-long-s.html
617 # .. [BCP47] A. Phillips und M. Davis, (Editoren.),
618 # `Tags for Identifying Languages`, http://www.rfc-editor.org/rfc/bcp/bcp47.txt
620 # .. Links:
622 # .. _Wortliste der deutschsprachigen Trennmustermannschaft:
623 # http://mirrors.ctan.org/language/hyphenation/dehyph-exptl/projektbeschreibung.pdf