Language preprocessor
This is a cheap preprocessor for a one-level conditional compilation of Inform files. This could be used for a single source file containing the data for different languages.
Usage:
perl inf-tags.pl
[inf-compiler] {inf-options}-L
[language-tag] [src] {game}
or possibly:
./inf-tags.pl
[inf-compiler] {inf-options}-L
[language-tag] [src] {game}
[Square brackets] denote mandatory, {curly braces} optional items.
[inf-compiler] is the Inform compiler to use, perhaps with a full path name prepended. [src] is the source file and {game} the game file to be written which defaults the the source’s base name with a z-Code suffix.
{inf-options} are the usual options of the Inform compiler. The language tag must be specified. This can be any continous string of non-whitespace characters like EN
, EN-UK
or ENGLISH
. The tag is case-sensitive. There is no default value.
Inside the source code, the text must be structured like this:
...
description
:EN "It is about two feet long.",
:ES "Mide aproximadamente sesenta centímetros.",
:DE "Es ist ungefähr einen halben Meter lang.",
:
That is, the text looks a bit like a switch statement. There is a line for every tag, the whole block is terminated with a single colon. With the -W
option activated, a warning is issued when the block does not contain a definition for the requested language as for example would be the case if the above example hat be compiles with the tag IT. If the -W
switch is set the compilation will not be started if there are empty blocks for that language tag.
It is important to close all tag blocks!
The tagging follows Inform Include
statements, but it skips system files. This means that in any library file, the System_file;
directive must be the first non-comment.
The script creates temporary source and output files. By default, these files are deleted after the script completes. With the -K
option which must be on its own, the file is only converted and written to stdout
so that it can be redirected with >
.
The option -V
(verbose) reports inclusion of files.
inf-tags.pl
Inform 6 preprocessor
Download zip archive with example
This is a Perl script and requires Perl 5. No special packages are required.
Known issues
The script assumes that the standard error style is -E0
(Acorn style messages). Since the script scans the output and replaces the temporary line numbers with line numbers in the tagged source, the correct error style must be known. You can wor around this by always specifying the error style with -E
or by setting the defult error style in the script to something diffenent: just change the following line
my $errorstyle = 0;
Discussion
The method described here uses the “everything in one file” approach. This might be useful if one person writes all the text in several languages. The example below illustrates that it is easy to lose track of the game itself by adding too many languages. I would favour an approach that uses a game skeleton that can be filled with translations.
The method used in inf-tags.pl
might be useful for small teams, though. (In fact, I am told it is currently being used for a bilingual project involving several authors.)
An example
Roberto Grassi from Italy, Urbatain from Spain and Eric Forgeot from France have reworked my original Jade example so that it includes an English, a German, an Italian, a Spanish and a French version in a single file:
Here it is, highlighted by language:
!========================================================== ! Multilingual Inform Game ! Version Nov. 2006 !========================================================== Constant Story :DE "DIE JADESTATUE"; :EN "THE JADE STATUETTE"; :IT "LA STATUETTA DI GIADA"; :SP "LA ESTATUILLA DE JADE"; :FR "LA STATUETTE DE JADE"; : Constant Headline :DE "^^Ein interaktives Beispiel^ Viersprachige Version 2006 von Eric Forgeot, Roberto Grassi, Urbatain und Martin Oehm^^"; :EN "^^An interactive example^ Multilingual version 2006 by Martin Oehm, Eric Forgeot, Roberto Grassi and El Clérigo Urbatain.^^"; :IT "^^Un esempio interattivo^ Versione quattrilingue 2006 di Martin Oehm, El Clérigo Urbatain, Eric Forgeot e Roberto Grassi.^^"; :SP "^^Un ejemplo interactivo^ Version cuatrilingue 2006 por Martin Oehm, Eric Forgeot, Roberto Grassi and El Clérigo Urbatain.^^"; :FR "^^Un exemple interactif^ Version 2006 multilingue par Martin Oehm, Roberto Grassi, El Clérigo Urbatain et Eric Forgeot.^^"; : Constant NO_PUNCTUATION; Release 1; Serial "030215"; !JJMMTT Include "Parser"; Include "VerbLib"; [ Initialise; location = Lichtung; print :DE "Endlich! Nach tagelangem Suchen im Dschungel stößt du auf eine Lichtung. Und auf etwas mehr. Vielleicht ist dies der Ort, an dem sich die Jadestatue befindet?^^"; :EN "At last! After days of restless searching through the nearby jungle, you have come across a clearing. And something more. Maybe this is where you can find the fabled jade statuette?^^"; :IT "Finalmente! Dopo giorni di ricerca senza sosta nella vicina giungla sei giunto in una radura. E c'e' anche dell'altro. Forse sei vicino a trovare la famosa statuetta di giada?^^"; :SP "¡Al fin! Después de días de búsqueda sin descanso a través de la jungla cercana, has llegado a un claro. Y algo más. ¿Quizás es aqui donde podrás encontrar la legendaria estatuilla de jade?^^"; :FR "Enfin ! Après des jours d'exploration sans repos à travers la jungle, vous êtes arrivé à une clairière. Et bien plus. Peut-être est-ce ici que vous pourrez trouver la fabuleuse statuette de jade ?^^"; : ]; Object Lichtung :DE "Lichtung im Dschungel" :EN "Jungle Clearing" :IT "Radura nella giungla" :SP "Claro en la Jungla" :FR "Clairière dans la jungle" : with cant_go :DE "Dort ist der Dschungel zu dicht, es gibt keinen Pfad in diese Richtung.", :EN "In this direction, the jungle is too dense; There's no path in that direction.", :IT "La giungla e' troppo densa in quella direzione; non ci sono sentieri percorribili.", :SP "En esa dirección, la jungla es demasiado densa; No hay camino en esa dirección.", :FR "Dans cette direction la jungle est trop fournie, il n'y a aucun chemin dans cette direction.", : n_to Im_Schrein, in_to Lichtung, s_to [; if (Jadestatue notin player) :DE "Nicht ohne die Statue!"; :EN "Not without the statuette!"; :IT "Non senza la statuetta!"; :SP "¡No sin la estátua!"; :FR "Pas sans la statuette !"; : deadflag = 2; :DE "Du schaffst es, mit der Statue wieder zurück in die Zivilisation zu gelangen."; :EN "You make it back to civilisation, and you got that statuette, too."; :IT "Torni alla civilta'... con la statuetta."; :SP "Vuelves a la civilización, y llevas la estatuilla además."; :FR "Vous retournez à la civilisation, et vous avez avec vous la statuette."; : ], description :DE "Du stehst auf einer Lichtung im dichten Dschungel. Im Norden steht ein alter, von Ranken überzogener Schrein. Im Süden führt ein schmaler Pfad zurück in die Zivilisation.", :EN "You are standing on a clearing in a dense jungle. To the north there is an old shrine, overgrown with vines. A narrow track leads to the south and back to civilisation.", :IT "Sei in una radura di una densa giungla. A nord vedi un vecchio tempio, coperto quasi interamente dalle radici. Un sentiero conduce a sud, verso la civilta'.", :SP "Estás en un claro en la densa jungla. Al norte hay un santuario antiguo, envuelto en enredaderas. Un sendero estrecho conduce hacia el sur de vuelta a la civilización.", :FR "Vous vous trouvez dans une clairière d'une jungle dense. Au nord se trouve un ancien tombeau, recouvert de lierre. Un petit sentier conduit au sud, vers la civilisation.", : has light; Object -> Stein :DE "Stein" :EN "stone the size of your fist" :IT "una pietra grande quanto il tuo pugno" :SP "una piedra del tamaño de tu puño" :FR "une pierre grosse comme le poing" : with name :DE 'faustgross' 'gross' 'rund' 'glatt' 'stein', dekl 3, adj "faustgroß", :EN 'stone' 'big' 'fist' 'size' 'sized' 'fist-sized', :IT 'pietra' 'grande' 'pugno', :SP 'piedra' 'grande' 'puño' 'tamaño', :FR 'pierre' 'grande' 'grosse' 'comme' 'taille' 'poing', : description :DE "Der Stein ist so groß wie eine Faust und außergewöhnlich glatt und rund.", :EN "The stone is about as big as your fist and it is incredibly smooth and perfectly round.", :IT "La pietra è grande quanto il tuo pugno. E' incredibilmente levigata e perfettamente sferica.", :SP "La piedra es tan grande como tu puño y es increiblemente suave y perfectamente redonda.", :FR "La pierre est environ grande comme votre poing, incroyablement lisse et parfaitement ronde.", : initial :DE "^In der Nähe des Schreins liegt ein glatter, runder Stein im Gras.", :EN "^A smooth, round stone is lying in the grass by the shrine.", :IT "^Una pietra levigata e circolare giace tra l'erba intorno al tempio.", :SP "^Una piedra redonda y suave está tirada en la hierba al lado del santuario.", :FR "^Une pierre ronde et lisse se trouve sur l'herbe dans les environs du tombeau.", : has :DE male :IT female :SP female :FR female : ; Object -> Schrein :DE "Schrein" :EN "shrine" :IT "tempio" :SP "santuario" :FR "tombeau" : with name :DE 'alt' 'toltekisch' 'schrein' 'efeu' 'ranken', dekl 1, adj "alt", :EN 'old' 'toltec' 'shrine' 'temple' 'vines' 'weeds', :IT 'vecchio' 'tolteco' 'tempio' 'costruzione' 'radici', :SP 'antiguo' 'toltec' 'santuario' 'templo' 'enrredaderas', :FR 'vieux' 'tolteque' 'tombeau' 'sanctuaire' 'lierre', : description :DE "Der alte Toltekenschrein ist fast komplett mit Efeu überwuchert.", :EN "The old Toltec shrine is completely overgrown with vines.", :IT "Il vecchio tempio tolteco e' quasi completamente avvolto dalle radici.", :SP "El antiguo santuario de Toltec está completamente lleno de enrredaderas.", :FR "L'ancien tombeau toltèque est complètement recouvert de lierre.", : before [; Enter: <>; ], has :DE male :IT male :SP male :FR male : scenery; Object Im_Schrein :DE "Im Schrein" :EN "In the Shrine" :IT "Nel tempio" :SP "En el Santuario" :FR "Dans le sanctuaire" : with description :DE "In dem kleinen Schrein ist es dunkel, nur wenig Licht fällt durch das halb verfallene Dach. Ein großer Lichtstrahl fällt auf eine Steinsäule in der Mitte des Schreins. ^^Die Lichtung liegt im Süden.", :EN "It is dark inside the small shrine, only little light pours in through the broken roof. A wide beam of light illuminates a stone pedestal in the centre of the room, however.^^ The clearing is to the south.", :IT "Nel piccolo tempio regna l'oscurita', tuttavia una luce fioca filtra dal tetto danneggiato. Un raggio di luce illumina un piedistallo al centro della stanza.^^ L'uscita e' a sud.", :SP "Está oscuro dentro del pequeño santuario, sólo un poco de luz cae a través del tejado roto. Sin embargo, un ancho haz de luz ilumina un pedestal de piedra en el centro de la habitación.^^ El claro está hacia el sur.", :FR "Il fait sombre dans le petit tombeau, juste un peu de lumière passe à travers la toiture cassée. Un large rayon de lumière illumine un piédestal de pierre dans le centre de la pièce.^^ La clairière est vers le sud.", : s_to Lichtung, out_to Lichtung, has light; Object -> Saeule :DE "Steinsäule" :EN "stone pedestal" :IT "piedistallo di pietra" :SP "pedestal de piedra" :FR "piédestal en pierre" : with :DE dekl 9, : name :DE 'steinsaeule' 'saeule' 'steinpodest' 'podest', :EN 'stone' 'pedestal' 'pillar', :IT 'pietra' 'piedistallo', :SP 'piedra' 'pedestal' 'pilar', :FR 'pied' 'piedestal' 'pilier' 'roche', : description :DE "Die Säule ist aus glattem Stein gehauen, etwas mehr als einen Meter hoch und oben flach, wie ein Podest.", :EN "The pedestal is carved from smooth stone. It is about one metre high and has a flat top.", :IT "Il piedistallo e' scolpito nella roccia. E' alto un metro ed ha una base piatta.", :SP "El pedestal está formado por suaves labrados. Es como un metro de alto y la parte alta está plana.", :FR "Le piédestal est taillé dans une roche lisse. Il fait environ un mètre de haut et a sa partie supérieure plane.", : has :DE female :IT male :SP male :FR male : supporter static concealed; Object -> -> Jadestatue :DE "Jadestatue" :EN "jade statuette" :IT "statuetta di giada" :SP "estatuilla de jade" :FR "statuette de jade" : with name :DE 'gruen' 'klein' 'statue' 'figur' 'jadestatue' 'jadefigur', dekl 9, :EN 'green' 'small' 'jade' 'figurine' 'statue' 'statuette' 'idol', :IT 'verde' 'piccola' 'giada' 'figurina' 'statua' 'statuetta' 'idolo', :SP 'verde' 'pequena' 'jade' 'figura' 'estatua' 'estatuilla' 'idolo', :FR 'verte' 'petite' 'jade' 'figurine' 'statue' 'statuette' 'idole', : description :DE "Es ist die Statue einer toltekischen Gottheit, komplett aus grüner Jade geschnitzt. Sie glänzt und sieht sehr wertvoll aus.", :EN "It is the statue of a Toltec deity, crafted from green jade. It reflects the light beautifully and looks quite valuable.", :IT "E' la statua di una divinita' tolteca, intagliata da una giada verde. Riflette la luce meravigiosamente e sembra di grande valore.", :SP "Es una estatua de la deidad Toltec, tallada en jade verde. Refleja la luz de una manera hermosa y parece muy valiosa.", :FR "C'est la statuette d'une divinité toltèque, taillée dans du jade vert. Elle reflète merveilleusement la lumière et semble avoir beaucoup de valeur.", : before [; Take: if (self in Saeule && ~~(Stein in Saeule)) { deadflag = true; :DE "Als du das Gewicht der Statue von der Säule nimmst, hörst Du ein klickendes Geräusch. Kurz darauf wirst du von Giftpfeilen durchbohrt."; :EN "As you lift the stauette's weight off the pedestal, you hear a klicking sound. A second later, you are pierced by poison darts."; :IT "Appena sollevi la statuetta dal piedistallo, senti uno scatto. Un momento dopo, sei colpito da dardi avvelenati."; :SP "En cuanto levantas la estatuilla del pedestal, escuchas un click. Un segundo después, tienes clavado un dardo envenenado."; :FR "Tandis que vous soulevez le poids de la statuette hors du piédestal, vous entendez un cliquetis. Une seconde plus tard, vous êtes transpercé par une fléchette empoisonnée."; : } ], has female; :DE Include "GermanG"; :EN Include "Grammar"; :IT Include "ItalianG"; :SP Include "SpanishG"; :FR Include "FrenchG"; : end;