This document in English is to help developpers to internationalise the scrountch tool: that is to let people program in their own language.

scrountch is built on top of Groovy which is itself built on top of Java. Developpers who want to configure scrountch, so it could accept code in a specific language, should be familiar with internationalisation ressource handling in Java through .properties files and should know how to update a jar file.

How are translations operated in scrountch

(A rather technical topic for those familiar with Groovy)

The internationalisation of code happens through 3 steps:

  • The text of the code is scanned for anything that looks like a keyword (or a very common function like println). Then these words are searched in a dictionary and if a translation from the current language to english is found then the english word replaces the initial word in the text. This should not be used to rename classes or methods.

  • At load-time original class names are aliased with their translation in the current language.

  • At runtime if a method is not found to be associated with a given class (which at runtime has its original name) a translation of this method is searched and then the method name is added to the metaclass.

    Most free functions (that are not invoked as members of a class) are supposed to be static methods of the scrountch.Fab class (unless these are declared in the current code).

Note
Reminder

Properties files have an ISO8859-1 encoding so to write characters that are out of this range you should use the native2ascii utility to create the correct character description with a correct unicode sequence.

Here is an example for a chinese word:

# translation of the int keyword
\u6574\u6570=int

Sometimes you may need several unicodes for a single character. Here is an example with an emoji:

# translation of the int keyword (a single image)
\uD83D\uDD22=int

The properties files

Each of those files is supposed to be part of the scrountch package and should be named according to the internationalisation convention used in Java.

For instance if the language is arabic then the internationalisation of keywords should reside in a file scrountch/keywords_ar.properties (or with the name_language_country.properties convention)

Keywords

Keywords and current types and function (such as int, String or println) should reside in the keywords ressource.

Here is a model:

# modify the needed keywords
#as
#assert
#break
#case
#catch
#class
#const
#continue
#def
#default
#do
#else
#enum
#extends
#false
#finally
#for
#goto
#if
#implements
#import
#in
#instanceof
#interface
#new
#null
#package
#return
#super
#switch
#this
#throw
#throws
#trait
#true
#try
#while

#int
#short
#byte
#char
#double
#float
#boolean

# other non keywords
# String
# println

Since there may be some confusion with identifier you may use a convention for internationalisation of keywords (underline is used in french except for types or litterals: so int is translated entier, true is translated VRAI but while is translated _tantQue )

BEWARE : original keywords are still in use! So if you translated int or while the code can still use the english keywords! (which is useful when delegates slowly switch from completely translated to code to "real" code).

Class names

Class names are translated in the classes properties files.

You can translate any class name be it java or groovy standard or specific to scrountch

You shoud check the scrountch code to know which classes you want to translate.

Here is an example of a classes_fr.properties for french:

scrountch.geom.SFrame = Cadre
scrountch.geom.Cell = Canevas

scrountch.geom.GraphicObject = ObjetGraphique
scrountch.geom.GraphicImage = ImageGraphique
scrountch.geom.GraphicString = ChaineGraphique
scrountch.geom.GraphicShape = FormeGraphique
scrountch.geom.SButton = Bouton
scrountch.geom.Turtle = Tortue
scrountch.geom.IconImage = Icone
scrountch.geom.Radial2D= RadialInfo

#
scrountch.utils.SelectionListener = VeilleurSelection

# import from std libs
java.awt.Shape = Forme
java.awt.Label = Label
java.awt.BasicStroke = TraitSimple
java.awt.Polygon = Polygone
java.awt.Rectangle = Rectangle
java.awt.event.MouseListener = VeilleurSouris
java.awt.event.ActionListener = VeilleurAction

# import from java.awt.geom
# this one is necessary if translation of Shape needed
java.awt.geom.RectangularShape=FormeRectangulaire
# BEWARE OF INNER CLASSES!!!
java.awt.geom.Ellipse2D$Double = EllipseD
java.awt.geom.Ellipse2D = Ellipse2d
java.awt.geom.Line2D$Double = LigneD
java.awt.geom.Point2D$Double = PointD
java.awt.geom.Path2D$Double = Cheminement
java.awt.geom.Rectangle2D$Double = RectangleD
java.awt.geom.RoundRectangle2D$Double = RectangleArrondiD
java.awt.geom.Area = java.awt.geom.Area

#import from Groovy
groovy.lang.Closure = Fermeture

Many more classes should be added to the list!

Method names

The translation are described in the methods properties file.

Remember how methods are searched: the execution starts from the "real" name of the class, so the description is strange since we need to describe a translated method name to an original class name!

Here is an example from the methods_fr.properties : note that the properties entry is of the form originalClassName#translatedMethodName=originalMethodName

# Factories
# basic static functions from the default Fab code
Fab#créerPolygone=createPolygon
Fab#créerRectangle=createRectangle
Fab#créerEllipse=createEllipse
Fab#créerLigne=createLine
Fab#créerTrait =createStroke
Fab#créerTortue =createTurtle
Fab#iconeDepuisFichier=createIconImageFromFile
Fab#iconeDepuisURL=createIconImageFromURL
# Graphic objects
Fab#créerFormeGraphique=createGraphicShape
Fab#formeGraphiqueCentrée=centeredGraphicShape
Fab#créerImageGraphique=createGraphicImage
Fab#créerChaineGraphique=createGraphicString
Fab#imageDepuisFichier=createGraphicImageFromFile
Fab#imageDepuisURL=createGraphicImageFromURL
Fab#créerPolygoneGraphique= createGraphicPolygon
Fab#créerRectangleGraphique= createGraphicRectangle
Fab#créerEllipseGraphique= createGraphicEllipse
Fab#créerLigneGraphique= createGraphicLine

Fab#courbe= createLineCurve
Fab#courbeParPoints= createDotCurve
Fab#histogramme= createSimpleHistogram
Fab#axes= axles
Fab#axesGradués= axlesTicks

Fab#compiler=compileFiles
Fab#garder=keep
Fab#recentrer=forceCenter
Fab#activerTraces=enableTraces
Fab#nombreAuHasard=randomInt
#  awt
Fab#créerCadre=createFrame
Fab#créerBouton=createButton
Fab#créerLabel=createLabel

# SFrame methods
SFrame#canevas=getCell
SFrame#tousLesCanevas=cells
SFrame#ajouterAuNord=addNorth
SFrame#retirerDuNord=removeNorth
SFrame#ajouterAuSud=addSouth
SFrame#retirerDuSud=removeSouth
SFrame#siClicSurTous=allOnClick

# Cell methods
Cell#listeGraphiques=getList
Cell#ajoutGraphique=addToGraphics
Cell#ajoutListeGraphiques=addAll
Cell#effacerGraphique=removeFromGraphics
Cell#effacerTout=clearGraphics
Cell#ajout=addNoRepaint
Cell#enlever=remove
Cell#enleverTout=clear
Cell#siClic=onClick
Cell#retirerVeilleurSouris=removeMouseListener
Cell#siSelection=onSelection
Cell#retirerVeilleurSelection=removeSelectionListener
Cell#repeindre=forceRepaint
Cell#ligne= getLinePos
Cell#colonne= getColPos
Cell#arrièrePlan=setBackground
Cell#couleurTracé=setForeground

#SButton methods
SButton#référence=getRef
SButton#siClic=onClick
SButton#retirerVeilleurSouris=removeMouseListener

# GraphicObject methods
GraphicObject#déplacerDe=moveAlong
GraphicObject#changerDirection=changeDirection
GraphicObject#rotationCentrée= centerRotation
#GraphicImage
#GraphicImage#rallonger=lenghtenPath
GraphicImage#hauteurInitiale = getOriginalHeight
GraphicImage#largeurInitiale = getOriginalWidth
GraphicImage#changerEchelle = setScale
GraphicImage#retour = home
GraphicImage#rotationCentrée= centerRotation
GraphicImage#rotationCoin= cornerRotation
GraphicImage#annulerRotations= clearRotation

#GraphicString methods
GraphicString#retour = home
GraphicString#rotationCentrée= centerRotation
GraphicString#rotationCoin= cornerRotation
GraphicString#couleurTracé= setDrawPaint
GraphicString#changerPolice= setFont

#GraphicShape methods
GraphicShape#hauteurInitiale = getOriginalHeight
GraphicShape#largeurInitiale = getOriginalWidth
GraphicShape#changerTrait=setStroke
GraphicShape#couleurTracé=setDrawPaint
GraphicShape#remplissage=setFillPaint
GraphicShape#retour = home
GraphicShape#rotationCentrée= centerRotation
GraphicShape#rotationCoin= cornerRotation

# Turtle methods
Turtle#avance=forward
Turtle#sauteEn=jumpTo
Turtle#tourneDroite=turnRight
Turtle#tourneGauche=turnLeft
Turtle#pointCourant=getCurrentPoint

#IconImage methods
IconImage#hauteur=getIconHeight
IconImage#largeur=getIconWidth

# graphics
Shape#enveloppe=getBounds
Shape#hauteur=getHeight
Shape#largeur=getWidth
Shape#plusGrandeDim=maxDim
Rectangle#hauteur=getHeight
Rectangle#largeur=getWidth
# BEWARE OF INNER CLASSES NAMES
Rectangle2D$Double#hauteur=getHeight
Rectangle2D$Double#largeur=getWidth
#Ellipse2D$Double#enveloppe=getBounds
Ellipse2D$Double#hauteur=getHeight
Ellipse2D$Double#largeur=getWidth
java.awt.geom.Area#contient=contains
Radial2D#rayon=getRadius

Note: you can use the simple name of the class or, if ambiguous, the canonical name.

Messages

Though not yet widely used (yet) there is room for message translations in the messages properties file:

A limited list of messages to be translated:

save_changes_to=Save changes to
Interrupt_question=Script executing. Press 'OK' to attempt to interrupt it before exiting.

Updates

Once your properties files is created you can update the scrountchConsole.jar file (with -u option).

You can test also by invoking java with a specific option such as java -Duser.language=xx -jar scrountchConsole.jar (xx being the code for your language)