Skip to main content

Getting Started on a Translation

In the "Rules" directory, there are subfolders that correspond to various languages that already have translations. The "en" (English) subdirectory has the most complete translation and is probably the best candidate to use as a starting point. However, other directories can be used and might be better starting points if the language is similar to your language.

Here is an outline of what you should do to begin a translation:

  1. Copy the "en" directory (or other directory you choose) and create a directory with the appropriate ISO 639-1 language code for the language for which you are doing a translation. The remaining instructions apply to the new/copied files. Do not modify the files in the "en" directory.

  2. If you do not know what is the language code is, here is a list of codes. Use the 639-1 column. If there are multiple dialects of a language (e.g., US English and British English), first create the files for what you believe should be the default and then add a subdirectory for the other dialect(s) with the appropriate ISO code (e.g, en-GB). Contact WIRIS for further instructions

  3. If Nemeth Code is not used as a Braille code for the target language, remove the files MathSpeak.tdl, MathSpeak_unicode.tld, and MathSpeak-en.tdl. If Nemeth Code is used for the target language, it might be useful to translate these files also, but you can wait to do that at a later date.

  4. ClearSpeak builds in some common ways of speaking math in English. It might not be appropriate for other languages. Starting with SimpleSpeak is probably best. Remove all the files that start with "ClearSpeak". For example, remove ClearSpeak.tdl.

  5. Rename simple-speech-en.tdl:  change the "en" to the appropriate country code (eg, simple-speech-es.tdl)

  6. Open the renamed file in a text editor that is able to handle utf-8 encoded files. Notepad, Notepad++, and WordPad are all able to handle utf-8 encoded files.

    • Near the top of the file are some lines like:

speechStyle = "Simple Speech PI"; description = "Simple Speech PI input translator v1.00 by Design Science, Inc."; isoLanguage = "en"; language = "English";

Change at least the last two lines to refer to the new language. "language" can be in your native language -- it is displayed in a drop-down list.

  * Remove some apparently English only rules for saying "negative" and "positive". The first line to remove is

// rule for speaking "negative" instead of "minus" (apparently English-only) and all of the lines between it and // subject area rules should be first (but not including this last line) should be removed.

  1. Open simple-speech.tdl in a text editor that handles utf-8 encoded files.

    • Do the same change with "speechStyle" etc., in that file as you did above.

    • Change the line

     phaseIFile = "simple-speech-en.tdl"; to point to the renamed file

  1. Do the same thing for the files Simple-speech-nav-en.tdl and Simple-speech-nav.tdl.

  2. Open the MathPlayer control panel (close and reopen if you had it open from before). Under "Language for Speech", you should now see the new language listed. "Simple Speech" (or whatever name you choose) should be listed under "Speech Style" next to it. If you don't see that, make sure you followed the above steps; make sure the quotes remain balanced; and make sure a ";" is at the end of lines.

  3. Open simple-speech-words.tdl in a text editor that handles utf-8 encoded files. Find the first occurrence of "UIWord". You should start by modifying all of the English words inside of quotes that follow 'text="xxx"'. For example, the Spanish translation changes the word used in a fraction from

     text="over" to      & text="sobre" See the Verbosity and  Target Group sections below for a discussion about those and the meaning/syntax of "?" and ":".

  1. Open unicode.tdl and change the string values of 'text="xxx"' as before. This is a very large file and most characters will never be used. See to see what the characters look like. We recommended you translate at least the following Unicode values:

    • 0x0032 - 0x00FF, although translating modified characters such as

     text="cap e with grave" can be skipped on the first pass. At this point, you can test simple expressions such as fractions and powers and see if they speak correctly.  If nothing is spoken or there are problems, see the Debugging section below.

  * 0x0391 - 0x0x03F6 (Greek letters)
  * 0x2010 - 0x2063
  * 0x20AC  (Euro)
  * 0x2190 - 0x2199,  0x21BC - 0x21BF, 0x21D0 - 0x21D5, and 0x21FD - 0x21FF (Arrows)
  * 0x2200 - 0x224D, 0x2260 - 0x228B,  0x22C0 - 0x22C3, 0x22EE- 0x22F1 (Mathematical Operators)
  * 0x27E6 - 0x27EF (Brackets)
  * 0x27F5 - 0x27FA (Long arrows)
  * 0x2308 - 0x230B (Floor, Ceiling), 0x2329 - 0x232A (deprecated angle brackets), 0x23DE - 0x23E1 (horizontal brackets)
  * 0xF000 - 0xF251 including the plane 1 chars 0x1D504, etc (Fraktur, Script, etc, letters)
  * The more characters you translate, the better, but this is by far the most tedious task. Finishing off the 2200 block (Mathematical Operators) and the Arrow block are probably next on the most important character list.
- Open **functions.tdl** and translate the string values of 'text="xxx"' as before.
- Open **units.tdl** and translate the string values of 'text="xxx"' as before.
  * **{{units.xht|units.xht}}** is useful for testing these translations.
  * Some languages have special ways of reading certain numbers. Eg, Spanish uses "un" instead of "uno" in some cases. See the Spanish version of units.tdl and simple-speech-es.tdl to see how this is handled if it is relevant to your language. Contact WIRIS if you need help getting special cases right.
- Open **money.tdl** and translate the string values of 'text="xxx"' as before.
  * Some languages may not use a connector such as "and" between dollars and cents. Use an empty string ("") if this is true for the target language.
  * **{{money.xht|money.xht}}** is useful for testing these translations.
  * As with units, some languages have special ways for speaking monetary amounts that differ from the normal pattern. Check the Spanish files for examples if that is the case with your language. Contact WIRIS if you need help getting special cases right.
- Open the subject area files **geometry.tdl**, **statistics.tdl**, and **calculus.tdl** and translate the string values of 'text="xxx"' as before.
  * We have tried to include notations not used in the US, but there are likely to be ones that need to be added to simple-speech-en.tdl. Contact WIRIS if you need help getting special cases right.
  * There are test files included for testing these translations.
- Open and translate **chemistry.tdl**. For Romance languages, it might be better to start with French or some other Romance langauge as there are word order issues that do not come up in English.
- Open **elementary-math.tdl** and translate the string values of 'text="xxx"' as before.
  * This file and the related elementary-math-base.tdl file are still undergoing development and may change. In particular, we are looking for a better way to speak borrows and carries. If you have a suggestion, please contact WIRIS.
  * Examples of elementary are not currently part of the example files. To try out some examples, go to the [[|elementary math examples]] at the W3C math testsuite. There are many styles of long division. All should work, but find the style used in your country and verify that the speech is correct for that.
- If you feel that any of the pauses are too long or too short, [[|let us know]]. If could be that they are not well tuned in general, or it could be that they don't work well with your language. If you think it is language-specific, copy the specific rule from simple-speech-base.tdl to simple-speech-xx.tdl and modify the values given in "pause{ms=nnn;}". You can also add "pause" statements if they are not present.


Note: MathPlayer 4 fully supports MathML 3, including support for elementary math notation. elementary-math-base.tdl is a start on speaking the new notations, however, much more work remains to be done before translators should attempt to translate that file.

Some info about the files

The speech rules are invoked by a pattern matcher. The pattern matcher has four phases, but only two phases are language specific. One of these phases matches MathML (the language used on web pages for math) and produces phrase templates. The next phase matches these phrase templates and fills in the actual text to speak -- that is where you will do most of your work. Matching the MathML is mostly shared by all languages and (of course), matching the phrase templates is language-specific.

If there are language specific patterns/math notations that need to be matched for your language that are not already handled, they can be added to simple-speech-xx.tdl in the new directory you created. For example, in the Spanish file (simple-speech-es.tdl), there are rules for matching "sen" (sin) and for saying "un" and "y un" in certain cases.

The general rules are in the parent directory of the language rules. The general rules are broken apart into related rule sets such as those for money, units, and geometry. There are corresponding files to these in the language-specific directors where the words get filled in for the match. For example, in your new directory, there should be files money.tdl, units.tdl, and geometry.tdl.

The main files are simple-speech-en.tdl and simple-speech.tdl. These files have statements in them that include other files such as money.tdl. "Simple speech" is one speech that we have developed, but MathPlayer allows for others such as the MathSpeak style (based on Nemeth code) and a new style being co-developed with ETS called "ClearSpeak". Both of these other styles will reuse some other existing parts (such as money.tdl) so that new speech styles do not have to duplicate all of the work done for Simple Speech.

File Syntax

Here is some information about the syntax of rules. You do not need to know this -- it is only for informational purposes for the curious who have some programming background. The pattern matcher works on a tree and finds the first match it can in a file. The pattern matcher tries to match a node in the input tree and if it finds a rule that matches, produces an output node. Nodes have a name, can have attributes (name/value pairs), and can have children. In general, a rule looks like

nodeName ? boolean tests
   => newNodeName(children) {attribute values}

An example from

UIWord ? (ruleRef=="RR_simpleSuperScript" )
=> UIInput(string{text=(::verbosity < ::v_full) ? "to the" : "raised to the";})
          { ruleRef="RR_simpleSuperScript"; };

In this example, the nodeName is "UIWord" and we are testing its "ruleRef" attribute is the string "RR_simpleSuperScript". If it is, then we generate a new tree node named "UIInput" with the child named "string". String has a text attribute whose value depends upon the value of the global variable "verbosity". "UIInput" has the attribute named "ruleRef".

A lot of the syntax is based on C/C++ and is similar to Java and Javascript. One piece of syntax that is used a lot in the rules is the conditional operator

condition ? value-if-true : value-if-false

The example above uses it to return different strings to speak depending on the values of the global variable "verbosity".

Note that all global variables are accessed using the "::" syntax as in "::verbosity".

Target Group

MathPlayer currently supports the notion of speech for three different vision related disabilities: blindness, low vision, and vision-related learning disability such as dyslexia. The words that should be spoken for these groups differ. In particular, if someone can see the math, they do not want to hear begin/end delimiters such as "begin fraction". However, if someone is blind, it is often very important to use them so that the person knows where notation begins and ends.

The target group is set in the MathPlayer control panel under "Generate speech for". Based on those settings, the global variable ::target_group is set to one of the values "Blind", "Low Vision", or "LD". Some speech rules test for this. For example, one of the rules for fractions is:

UIWord ? (ruleRef=="RR_fraction" && wordRef=="before")
  => UIInput( string{text= ::target_group=="Blind" ? "fraction" : "";} )
            { ruleRef="RR_fraction"; wordRef="before";};

The line

text= ::target_group=="Blind" ? "fraction" : "";

is a similar to C++ and Java syntax. If the global variable "target_group" is the string "Blind", then the variable "text" is assigned the value "fraction". Otherwise, it gets an empty string. In other words, if the target group is "Blind", then we say "fraction" at the start of the fraction, otherwise we say nothing.

Currently, the speech rules only differentiate between someone who is blind and everyone else.


MathPlayer currently supports the notion of verbosity. This is an option a user can set in the MathPlayer control panel. There five levels verbosity, with three of them named: ::v_full, v_medium, and v_terse. These are integer valued variables and are usually compared to the global variable "::verbosity" when generating speech.

When someone is just learning a subject, one often uses longer phrases to make it more understandable. However, over time, we often shorten the phrases and even elide words so that we can more quickly communicate ideas/problems. For example, when we are first learning about variables, "y = 2x" might be spoken as "y is equal to 2 times x". Soon however, this will get shortened to "y equals 2 times x" and eventually will be spoken as "y equals 2 x".

Verbosity is a relatively new feature in MathPlayer and we are still experimenting with it. Feel free to remove verbosity tests if they don't make sense for your language. Simiarly, you can add them if you feel that they would be useful in cases they are not currently part of the rule.


Some files that can be used for testing are included in this distribution in the directory. You can easily create more files by using Word+MathType. Write your Word document with whatever math expressions you wish to try out. Save the document and then use the Export (or Publish) to MathPage menu item, ribbon button, or toolbar button. Make sure you select MathML as the output type.

The rule interpreter will notice when any rule file is changed and reload the new file(s) so you don't need to restart MathPlayer/NVDA/Word.

Debugging (what to do if it isn't working)

It is almost guaranteed that you will encounter problems when you try test cases. If the expression spoken in the wrong language, you probably need to change the current speech style. To do this, right click on an expression and pick “Choose Speech”. Make sure you are using the appropriate language and rule set in that language (if there is more than one).

If the problem involves a mispronunciation, check the spelling or spacing. You may need to change the spelling to emphasize the way a word is spoken. Caution should be taken though, as different speech engines may pronounce the same word differently. If you have access to more than one voice, it is a good idea to try out multiple voices.

Other problems may be more complex, and therefore involve more steps in debugging. If MathPlayer is speaking only part of the expression or not speaking it at all, first check your coding to make sure you didn't create a syntax error in the file you changed by accidentally adding or deleting characters. Common syntax errors include:

  • missing or unbalanced quotation marks;

  • missing semicolons, typically after setting an attribute and before “}” or after a rule;

  • missing commas at the end of child nodes (i.e., after a “)” or “}”);

  • using the wrong parenthesis instead of braces or vice-versa (i.e., “( )” instead of “{ }”);

  • unbalanced parenthesis in a condition on a rule

If nothing is noticeably wrong, you should look in the debugging file speech-debug.txt. It is located in your temp folder (%temp%).

This file contains a lot of information about your rules. To check if there was a syntax error or runtime error, search for “Error:” in the file. Make sure you include the colon. The error message will tell you what is wrong and where in the file the error is located. The line that the error message references is where rule interrupter first sees a problem. The real problem might be on a previous line that is missing a ‘;’ or a ‘"’.

Another file used for debugging is called speech-trees.txt. This will be in the same directory as speech-debug.txt and will be generated if you uncomment (remove the "//") in the line:

  // log_show_speech_trees=true;

You may want to remove this line in both simple-speech.tdl and simple-speech-xx.tdl. This file contains the speech trees of the specific example MathPlayer spoke. The math expression goes through various steps before it eventually gets spoken. You can look over the speech trees, which will show how the TTS engine interprets the expression, and see if anything looks inaccurate.

If none of the above processes work, there are a few other things to check. All of these "stupid" errors are things that I have done more than once:

  • Check to make sure you did a "save" on the file with your changes.

  • Make sure any new files that you create are encoded as UTF8 (with "BOM") or as UTF16.

  • If you have multiple versions of the same file, make sure you were editing the right version of the file.

If you are still stuck, send us an email and include the files you have changed along with speech-debug.txt.