Updating translations for Inform 10.1.0

Hi! So here’s the promised thread about translating the new version of Inform!

I’ll start with a guide to get a translation started. Keep in mind there are still a few things to iron out.

And thanks @CrocMiam who helped for some of the points!


Creating the language kit

First, we’ll assume you’re using this on the command line to compile a project.

inform7 -internal Internal -external External -project project.inform -format=Inform6/32d -no-census-update -transient Transient

With the source of the project being:

"Hello World" by Natrium729 (in French)

[With your language inside the parentheses above.]

Kitchen is a room.

The next step is to create a kit for your translation. Copy the English kit located at Internal/Inter/EnglishLanguageKit/ into External/Inter/ (no need to copy the .interb files). Rename it into FrenchLanguageKit or ItalianLanguageKit and so on, and rename the file FrenchLanguageKit/Sections/Language.i6t into Language.w.

In your kit, remove the priority field from kit_metadata.json (so that it’s read after the Standard Rules, since it’s likely the translation uses things defined in them) and update the title and version fields; and the need field to point to the Inform extension of your translation.

Then, update the Title, Author, Purpose and Licence fields in the file Contents.w in your kit.

And if I haven’t forgotten anything, we’re done now for the kit! Onto the next step, the extension.

For more info about kits, see the relevant page in the extension.

Creating the extension

Now, create an empty extension in External/Extensions/Author name/French Language.i7x (with the correct author and language name, of course).

Then paste the content from the extension for the previous version of Inform piece by piece, and compile each time to make sure nothing is broken. There are some things to watch for, though.

For Inform 6 inclusions, if they are replacing a part of Language.i6t, then you likely have to move them into the Sections/Language.w of your kit, into the appropriate part, instead of writing it in the extension.

If they are replacing another part of the template, for example:

Include (-
[ PrintTimeOfDay;
    ! Content of the routine.
];
-) instead of "Digital Printing" in "Time.i6t".

You have to use the new syntax to replace an existing Inform 6 routine instead:

Include (-
[ PrintTimeOfDay;
    ! Content of the routine.
];
-) replacing "PrintTimeOfDay".

For Preform, some no longer work, for example <indefinite-article>. You have to find the new equivalent Preform, but I haven’t found everything out yet, so I just kept it commented out for the moment. For the X translates into French as Y to work, you have to add the following, (replace fr in the name with your language code), even though I don’t understand everything in it:

<grammatical-case-names> ::=
	nominative | accusative

<noun-declension> ::=
	*    <fr-noun-declension-group> <fr-noun-declension-tables>

<fr-noun-declension-group> ::=
	*	1

<fr-noun-declension-tables> ::=
	<fr-noun-declension-uninflected>

<fr-noun-declension-uninflected> ::=
	0 | 0 |
	0 | 0

Defining adjectives with In French X is an adjective makes Inter error out, but I haven’t found why.

For the rest of the Preform, you have to double-check that the names and content of the non-terminals are still the same as in the English Syntax.preform built in Inform.

A bug with adaptive verbs: in text subtitution, you write them in the viewpoint specified in the adaptive text viewpoint property of the language. In French, that would be "[as]" for “avoir” However, when using the verb as a value (like in a phrase To lookup (V - a verb)), you now have to use the first person plural, like in English: "[lookup the verb avons]".

Some new responses to add since 6L38:

  • describe what’s on mentioned supporters in room descriptions rule response (A)
  • action processing internal rule response (K)
  • immediately undo rule response (F)
  • announce items from multiple object lists rule response (A)
  • can’t insert what’s already inserted rule response (A)

And now you should have a more or less working translation, albeit with some workarounds. You also should double-check the Inform 6 to make sure they weren’t updated since last time (Some constants in #Ifdefs aren’t the same, for instance, like in Banner.).


So I hope that was helpful and that I haven’t forgotten anything! I’ll add things as I encounter them, and I’ll hope you’ll do too!

Let’s get the translations going!

13 Likes

Thank you very much! It’s a quite difficult procedure (more than I expected), but I’ll try to follow it soon to get a nearly working Italian Language extension. I hope that someone is going to fix the bug you cited, now that the sources are open. Thank you again!

2 Likes

It’s not that difficult. Really, it mostly a matter of copying files around. The most difficult part was finding ways to get aroung bugs. Now what will be difficult will be finding with what should be replaced what doesn’t work anymore.

About the bugs, I’ll report them. A workaround for the character escapes: using print (char) $ABC instead, where $ABC is the ZSCII/Unicode code point.

Graham Nelson has fixed some of the biggest hurdles!

Writing (in French) now correctly includes the kit, so you don’t need to to duplicate the English kit and empty it, nor mess with an inform7-settings.txt file. No need to change the priority of the kit in the kit metadata either (which is now a JSON by the way, so you have to update it if you still have the .txt file.)

Edit: Actually there seem to be a new bug which causes kits not to be built, so you still need the inform7-settings.txt and the empty English kit. It forces the kits to be built.

It should now also be possible to translate Inform’s syntax into another language by inlcuding a Preform file into the language bundle, but I haven’t tried that yet.

There’s more info in a new guide in the documentation.

The bug which made impossible to type the I6 char ''' is also fixed.

I’ll update the first post soon to reflect those changes.

5 Likes

“Le Port des brumes” by Georges Simenon (in French)
If it begins “in”, then the rest must be the English form of the name of a language
If the note does not begin “in”, then it must be text recognised by a language bundle:
“Le Port des brumes” by Georges Simenon (en français)

This could be a problem in italian, in fact we use “in” as in English:
“Il porto delle nebbie” (in Italian) LOP in italian and LOS in english
“Il porto delle nebbie” (in italiano) LOP in italian and LOS in italian

I’m waiting for the LOS in italian since the project Champollion. I hope to try this possibility soon.

The docs give this exact example and suggests to use “scritto in italiano” not “in italiano”.

1 Like

Thank you! I missed the suggestion. I don’t like very much that “in” is reserved in that way (in 6L38 it was possible to use “in italiano”), but the workaround is acceptable. Thank you again.

1 Like

The -kit command line option has been retired, but now everything works anyway. Just writing (in French/Italian/etc.) will correctly include the kit. No need to mess with the English kit.

The Inform 6 character escapes now work properly too.

I now have 2 blocking problems.

  • I haven’t been able to make it possible to use French articles in the source. So writing Le machin is a thing will create a neuter proper-named thing with printed name Le machin instead of a masculine thing with name machin. So for now we should write The machin (m) is a thing.
  • Adaptive adjective make Inter error out and I haven’t found the root cause.

(I also encountered other minor issues that are easy to workaround.)

I’ve updated the initial post.


For what I’ve tried, it doesn’t really work yet. It would seem that changing the syntax language makes Inform not understand the Standard Rules anymore, since the English syntax is not loaded.

1 Like

Finally I had time to work on the Italian extension. I’ve followed your precious instructions (thank you very much!) and now I have a working extension (more or less similar to the 6M62 version).
A few problems left that I don’t know how to solve (adjectives and preform stuff apart):

Replacing functions

The code:

Include (-
[ PrintTimeOfDayEnglish t h m dir aop say_minutes quad;
	! adapted the spanish version by Sebastian Arg
    ! some code here...
];
-) replacing "PrintTimeOfDayEnglish".

Gives:

>--> My low-level reader of source code reported a mistake - "inform 6 syntax
    error in function 'PrintTimeOfDayEnglish': unexpected use of reserved word
    'else'". Low-level material written in Inform 6 syntax occurs either in
    kits or in matter written inside 'Include (- ... -)' in source text, either
    in the main source or in an extension used by it.

If necessary I can post the code, but the same code worked perfectly in 6M62.

Replacing portions of code

Replacing whole functions works usually fine following the new syntax, but how can I replace portions of code, like this?

[Taken from the Spanish extension by Sebastian Arg - replaces "by" by "di".]
Include (-
[ Banner;
!print (string) Story;!deprecated
! other code here...
];
-) instead of "Banner" in "Printing.i6t".
Replacing i7 code

I tried to replace this section of the Standard Rules to set localized default values for title, author etc. In 6M62 the trick was successful (in that case the section had another name).

Section 3.4.1 - The bibliographical data (in place of Section 7 - Unindexed Standard Rules variables - Unindexed in Standard Rules by Graham Nelson)

The story title, the story author, the story headline, the story genre and the story description are text variables. [*****]
The release number and the story creation year are number variables. [**]

The release number is usually 1.
The story title is usually "Senza titolo".
The story author is usually "Anonimo".
The story headline is usually "Un[']opera di narrativa interattiva".
The story genre is usually "Narrativa".

The story title variable translates into Inter as "Story".

The compiler answers this message:

>--> In the sentence 'Section 3.4.1 - The bibliographical data (in place of
    Section 7 - Unindexed Standard Rules variables - Unindexed in Standard
    Rules by Graham Nelson)' (External\Extensions\Leonardo Boselli\Italian
    Language.i7x, line 4182), it looks as if you intend to replace a section of
    source text from the extension 'Standard Rules by Graham Nelson', but that
    extension does not seem to have any heading called 'Section 7 - Unindexed
    Standard Rules variables - Unindexed'. (The version I loaded was 6.)

However the name of the section is that one.

I6 function impossible to replace
Include (-
[ LanguageNumber n f;
	if (n==0)    { print "zero"; rfalse; }
        ! other code here...
];
-) replacing "LanguageNumber".

The error is:

 >--> Something went wrong late in compilation, when working through the
    'pipeline' of code-generation steps. (This should not normally happen
    unless your source text is making use of '(-' and '-)' and getting that
    wrong, or unless you are experimenting with non-standard pipelines.) The
    pipeline looks like so:
    1. read
    2. parse-insertions
    3. resolve-conditional-compilation
    4. compile-splats
    5. load-binary-kits
    6. make-synoptic-module
    7. shorten-wiring
    Problem: unable to find definitions for the following name(s): to
    8. detect-indirect-calls
    9. make-identifiers-unique
    10. reconcile-verbs
    11. eliminate-redundant-labels
    12. eliminate-redundant-operations
    13. optionally-generate text ->
    14. generate
    15. index

Thank you in advance for any suggestion!

1 Like

For Inform 6/Inter errors, Inform 6 is a bit more strict so things that were accepted in 6M62 aren’t anymore. You will have to find what yourself, or post the code.

I’m not sure I understand the problem with the banner. You can just write replacing "Banner".

About replacing a heading from the Standard Rules, you’re right, I forgot I had the same error. Inform thinks it does not exist. I haven’t found a workaround for this one. :slightly_frowning_face:

1 Like

Thank you for the suggestions! I’ve solved almost all the issues I had, in fact I dropped the old code of the modified “italian” functions and I have reimplemented the same capabilities modifying directly the original “english” functions.
However some of them are quite complex and I observe some strange behaviour of the compiler. If you have time, can you tell me what’s going wrong with this code? Thank you in advance!

In the extension
Include (-
[ LanguageNumber n f;
	if (n == 0)    { print "zero"; rfalse; }
	if (n < 0)     { print "meno "; n = -n; }
#Iftrue (WORDSIZE == 4);
	if (n >= 1000000000) {
		if (f == 1) print ", ";
		if (n < 2000000000) print "un miliardo";
		if (n >= 2000000000) print (LanguageNumber) n/1000000000, " miliardi";
		n = n%1000000000; f = 1;
	}
	if (n >= 1000000) {
		if (f == 1) print ", ";
		if (n < 2000000) print "un milione";
		if (n >= 2000000) print (LanguageNumber) n/1000000, " milioni";
		n = n%1000000; f = 1;
	}
#Endif;
	if (n >= 1000) {
		if (f == 1) print ", ";
		if (n < 2000) print "mille";
		if (n >= 2000) print (LanguageNumber) n/1000, "mila";
		n = n%1000; f = 0;
	}
	if (n >= 100)  {
		if (f == 1) print ", ";
		if (n < 200) print "cento";
		if (n >= 200) print (LanguageNumber) n/100, "cento";
		n = n%100; f = 1;
	}
	if (n == 0) rfalse;
	switch(n) {
		1:  print "uno";
		2:  print "due";
		3:  print "tre";
		4:  print "quattro";
		5:  print "cinque";
		6:  print "sei";
		7:  print "sette";
		8:  print "otto";
		9:  print "nove";
		10: print "dieci";
		11: print "undici";
		12: print "dodici";
		13: print "tredici";
		14: print "quattordici";
		15: print "quindici";
		16: print "sedici";
		17: print "diciassette";
		18: print "diciotto";
		19: print "diciannove";
		default:
			switch(n/10) {
				2:  print "vent";
					if (n%10 == 0) {print "i"; return; }
					if (n%10 == 1) {print "uno"; return; }
					if (n%10 == 3) {print "itré"; return; }
					if (n%10 > 1) {print "i"; LanguageNumber(n%10); return; }
				3:  print "trent";
					if (n%10 == 1) {print "uno"; return; }
					if (n%10 == 3) {print "atré"; return; }
				4:  print "quarant";
					if (n%10 == 1) {print "uno"; return; }
					if (n%10 == 3) {print "atré"; return; }
				5:  print "cinquant";
					if (n%10 == 1) {print "uno"; return; }
					if (n%10 == 3) {print "atré"; return; }
				6:  print "sessant";
					if (n%10 == 1) {print "uno"; return; }
					if (n%10 == 3) {print "atré"; return; }
				7:  print "settant";
					if (n%10 == 1) {print "uno"; return; }
					if (n%10 == 3) {print "atré"; return; }
				8:  print "ottant";
					if (n%10 == 1) {print "uno"; return; }
					if (n%10 == 3) {print "atré"; return; }
				9:  print "novant";
					if (n%10 == 1) {print "uno"; return; }
					if (n%10 == 3) {print "atré"; return; }
			}
			if (n%10 ~= 0)
			{
				print "a"; LanguageNumber(n%10);
			}
	}
];
-) replacing "LanguageNumber".

Instead of “default” in the second “switch” there was “20 to 99:”, but now it doesn’t recompile.
The “auto.inf” generated shows strange code at the bottom:

auto.inf
[ LanguageNumber n f;
    if ((n == 0)) {
        print "zero";
        rfalse;
    }
    if ((n < 0)) {
        print "meno ";
        (n = (-(n)));
    }
    if ((n >= 1000000000)) {
        if ((f == 1)) {
            print ", ";
        }
        if ((n < 2000000000)) {
            print "un miliardo";
        }
        if ((n >= 2000000000)) {
            LanguageNumber((n/1000000000));
            print " miliardi";
        }
        (n = (n%1000000000));
        (f = 1);
    }
    if ((n >= 1000000)) {
        if ((f == 1)) {
            print ", ";
        }
        if ((n < 2000000)) {
            print "un milione";
        }
        if ((n >= 2000000)) {
            LanguageNumber((n/1000000));
            print " milioni";
        }
        (n = (n%1000000));
        (f = 1);
    }
    if ((n >= 1000)) {
        if ((f == 1)) {
            print ", ";
        }
        if ((n < 2000)) {
            print "mille";
        }
        if ((n >= 2000)) {
            LanguageNumber((n/1000));
            print "mila";
        }
        (n = (n%1000));
        (f = 0);
    }
    if ((n >= 100)) {
        if ((f == 1)) {
            print ", ";
        }
        if ((n < 200)) {
            print "cento";
        }
        if ((n >= 200)) {
            LanguageNumber((n/100));
            print "cento";
        }
        (n = (n%100));
        (f = 1);
    }
    if ((n == 0)) {
        rfalse;
    }
    switch (n) {
        1:
            print "uno";
            ;
        2:
            print "due";
            ;
        3:
            print "tre";
            ;
        4:
            print "quattro";
            ;
        5:
            print "cinque";
            ;
        6:
            print "sei";
            ;
        7:
            print "sette";
            ;
        8:
            print "otto";
            ;
        9:
            print "nove";
            ;
        10:
            print "dieci";
            ;
        11:
            print "undici";
            ;
        12:
            print "dodici";
            ;
        13:
            print "tredici";
            ;
        14:
            print "quattordici";
            ;
        15:
            print "quindici";
            ;
        16:
            print "sedici";
            ;
        17:
            print "diciassette";
            ;
        18:
            print "diciotto";
            ;
        19:
            print "diciannove";
            ;
        default:
            switch ((n/10)) {
                2:
                    print "vent";
                    if (((n%10) == 0)) {
                        if (((n%10) == 1)) {
                            if (((n%10) == 3)) {
                                if (((n%10) > 1)) {
                                    3:
                                        print "trent";
                                        ;
                                }
                            }
                        }
                    }
                    if (((n%10) == 1)) {
                        if (((n%10) == 3)) {
                            4:
                                print "quarant";
                                ;
                        }
                    }
                    if (((n%10) == 1)) {
                        if (((n%10) == 3)) {
                            5:
                                print "cinquant";
                                ;
                        }
                    }
                    if (((n%10) == 1)) {
                        if (((n%10) == 3)) {
                            6:
                                print "sessant";
                                ;
                        }
                    }
                    if (((n%10) == 1)) {
                        if (((n%10) == 3)) {
                            7:
                                print "settant";
                                ;
                        }
                    }
                    if (((n%10) == 1)) {
                        if (((n%10) == 3)) {
                            8:
                                print "ottant";
                                ;
                        }
                    }
                    if (((n%10) == 1)) {
                        if (((n%10) == 3)) {
                            9:
                                print "novant";
                                ;
                        }
                    }
                    if (((n%10) == 1)) {
                        if (((n%10) == 3)) {
                        }
                        if (((n%10) ~= 0)) {
                            print "a";
                        }
                    }
                    LanguageNumber((n%10));
                    ;
            }
            ;
    }
];

I really don’t know what I’m doing wrong.

P.S. I don’t understand why the “Include (- -)” construct changes my correct I6 code in the extension to wrong code in “auto.inf”. Is the converter seriously bugged, or did I miss anything fundamental?

Finally I’ve found a workaround. Rephrasing the code this way, the “converter” (?) transforms my code without adding wrong changes:

Summary
		default:
			switch(n/10) {
				2:  print "vent";
					if (n%10 == 0) {
						print "i";
					} else {
						if (n%10 == 1) {
							print "uno";
						} else {
							if (n%10 == 3) {
								print "itré";
							} else {
								if (n%10 > 1) {
									print "i";
									LanguageNumber(n%10);
								}
							}
						}
					}
				3:  print "trent";
					if (n%10 == 1) {
						print "uno";
					} else {
						if (n%10 == 3) {
							print "atré";
						}
					}
				4:  print "quarant";
					if (n%10 == 1) {
						print "uno";
					} else {
						if (n%10 == 3) {
							print "atré";
						}
					}
				5:  print "cinquant";
					if (n%10 == 1) {
						print "uno";
					} else {
						if (n%10 == 3) {
							print "atré";
						}
					}
				6:  print "sessant";
					if (n%10 == 1) {
						print "uno";
					} else {
						if (n%10 == 3) {
							print "atré";
						}
					}
				7:  print "settant";
					if (n%10 == 1) {
						print "uno";
					} else {
						if (n%10 == 3) {
							print "atré";
						}
					}
				8:  print "ottant";
					if (n%10 == 1) {
						print "uno";
					} else {
						if (n%10 == 3) {
							print "atré";
						}
					}
				9:  print "novant";
					if (n%10 == 1) {
						print "uno";
					} else {
						if (n%10 == 3) {
							print "atré";
						}
					}
			}
			if (n%10 ~= 0)
			{
				print "a"; LanguageNumber(n%10);
			}