--- #default rules shared among several speech rules - name: default tag: math match: "." replace: - with: variables: - ClearSpeak_Fractions: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Fractions='Auto', 'EndFrac', $ClearSpeak_Fractions)" - ClearSpeak_AbsoluteValue: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_AbsoluteValue='Auto', 'AbsEnd', $ClearSpeak_AbsoluteValue)" - ClearSpeak_Roots: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Roots='Auto', 'RootEnd', $ClearSpeak_Roots)" - ClearSpeak_Matrix: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Matrix='Auto', 'EndMatrix', $ClearSpeak_Matrix)" replace: - test: if: "$MathRate = 100" then: [x: "*"] else: - rate: value: "$MathRate" replace: [x: "*"] - name: empty-mrow tag: mrow match: "not(*)" replace: - t: " " # say nothing -- placeholder - name: default tag: mrow match: "." replace: - insert: nodes: "*" replace: [pause: auto] - name: default tag: mn match: "." replace: - bookmark: "@id" - x: "translate(., $BlockSeparators, '')" # remove digit block separators - name: default tag: [mo, mtext] match: "." replace: - bookmark: "@id" - x: "text()" - name: default tag: mi match: "." replace: - bookmark: "@id" - test: if: "string-length(.) = 1 and text() != '_'" # need unicode.tdl to kick in for single letter tokens then: [x: "text()"] else: [x: "translate(., '-_\u00A0', ' ')" ] # from intent literals - name: default tag: ms match: "." replace: - T: "la cadena" - pause: short - x: "text()" - name: default tag: mstyle match: "." replace: [x: "*"] - name: literal-simple # don't include nested fractions. E.g, fraction a plus b over c + 1 end fraction" is ambiguous # by simplistic SimpleSpeak's rules "b over c" is a fraction, but if we say nested fractions # are never simple, then any 'over' applies only to enclosing "fraction...end fraction" pair. tag: mfrac match: - "(IsNode(*[1],'leaf') and IsNode(*[2],'leaf')) and" - "not(ancestor::*[name() != 'mrow'][1]/self::m:fraction)" # FIX: can't test for mrow -- what should be used??? replace: - x: "*[1]" - T: "partido por" - x: "*[2]" - pause: short - name: literal-default tag: mfrac match: "." replace: - T: "comenzar" - pause: short - x: "*[1]" - test: if: "not(IsNode(*[1],'leaf'))" then: [{pause: short}] - T: "partido por" - test: if: "not(IsNode(*[2],'leaf'))" then: [{pause: short}] - x: "*[2]" - pause: short - T: "fracción final" - pause: medium - name: simple-sub tag: particular-value-of # invisible comma -- want "x sub 1 1" without "end sub" match: "count(*)=2 and (IsNode(*[2], 'leaf') or *[2][self::m:mrow][*[2][text()='⁣']])" replace: - x: "*[1]" - test: if: "$Verbosity!='Terse' or not(*[2][self::m:mn])" # just say "x 1" for terse vs "x sub 1" then: [T: "subíndice"] - x: "*[2]" - name: default tag: particular-value-of match: "count(*)=2" replace: - x: "*[1]" - T: "subíndice" - x: "*[2]" - T: "fin del subíndice" - pause: short - name: literal tag: msub match: "." replace: - x: "*[1]" - T: "subíndice" - x: "*[2]" - name: literal tag: [msup, msubsup] match: "." replace: - x: "*[1]" - test: if: "name(.)='msubsup'" then: - T: "subíndice" - x: "*[2]" - test: if: "*[last()][translate(., '′″‴⁗†‡°*', '')='']" then: [x: "*[last()]"] else_test: if: "ancestor-or-self::*[contains(@data-intent-property, ':literal:')]" # FIX: is this test necessary? then: - T: "superíndice" - x: "*[last()]" - test: if: "not(IsNode(*[last()], 'simple'))" then: [T: "final del superíndice"] else: - T: "elevado a la" - x: "*[last()]" - T: "potencia" - name: default tag: munder match: "." replace: - test: if: "not(IsNode(*[1], 'leaf'))" then: [T: "modificado"] - x: "*[1]" - T: "con" - x: "*[2]" - T: abajo - name: diacriticals tag: mover match: "*[1][self::m:mi] and *[2][translate(., '\u0306\u030c.\u00A8\u02D9\u20DB\u20DC`^~→¯_', '')='']" replace: - x: "*[1]" - x: "*[2]" - name: default tag: mover match: "." replace: - test: if: "not(IsNode(*[1], 'leaf'))" then: [T: "modificado"] - x: "*[1]" - T: "con" - x: "*[2]" - T: "por encima de" - name: default tag: munderover match: "." replace: - test: if: "not(IsNode(*[1], 'leaf'))" then: [T: "modificado"] - x: "*[1]" - T: "con" - x: "*[2]" - T: "y abajo" - x: "*[3]" - T: "por encima de" - name: default # Here we support up to 2 prescripts and up to 4 postscripts -- that should cover all reasonable cases # If there are more, we just dump them out without regard to sup/super :-( # FIX: this could use more special cases # There is (currently) no way in MathCAT to deal with n-ary arguments other than "all" ('*') or an individual entry ('*[1]'). tag: mmultiscripts match: "." variables: # computing the number of postscripts is messy because of being optionally present -- we use "mod" to get the count right - Prescripts: "m:mprescripts/following-sibling::*" - NumChildren: "count(*)" # need to stash this since the count is wrong inside '*[...]' below - Postscripts: "*[position()>1 and position() < (last() + ($NumChildren mod 2) -count($Prescripts))]" replace: - x: "*[1]" - test: if: "$Prescripts" # more common case then: - with: variables: - PreSubscript: "IfThenElse($Verbosity='Verbose', 'pre subscript', 'pre sub')" - PreSuperscript: "IfThenElse($Verbosity='Verbose', 'pre superscript', 'pre super')" replace: - test: # only bother announcing if there is more than one prescript if: "count($Prescripts) > 2" then: - T: "con" - x: "count($Prescripts) div 2" - T: "secuencia" - pause: short - test: if: "not($Prescripts[1][self::m:none])" then: - x: "$PreSubscript" - x: "$Prescripts[1]" - test: if: "not($Prescripts[1][self::m:none] or $Prescripts[2][self::m:none])" then: [T: "y"] - test: if: "not($Prescripts[2][self::m:none])" then: - x: "$PreSuperscript" - x: "$Prescripts[2]" - pause: short - test: if: "count($Prescripts) > 2" # more common case then: - test: if: "not($Prescripts[3][self::m:none])" then: - x: "$PreSubscript" - x: "$Prescripts[3]" - test: if: "not($Prescripts[3][self::m:none] or $Prescripts[4][self::m:none])" then: [T: "y"] - test: if: "not($Prescripts[4][self::m:none])" then: - x: "$PreSuperscript" - x: "$Prescripts[4]" - test: if: "count($Prescripts) > 4" # give up and just dump them out so at least the content is there then: - T: "una secuencia alternativa" - x: "$Prescripts[position() > 4]" - T: "fin de la secuencia" - test: if: "$Postscripts" then: - with: variables: - PostSubscript: "IfThenElse($Verbosity='Verbose', 'subscript', 'sub')" - PostSuperscript: "IfThenElse($Verbosity='Verbose', 'superscript', 'super')" replace: - test: # only bother announcing if there is more than one postscript if: "count($Postscripts) > 2" then: - test: if: "$Prescripts" then: [T: "y"] - T: "con" - x: "count($Postscripts) div 2" - T: "adición" - pause: short - test: if: "not($Postscripts[1][self::m:none])" then: - x: "$PostSubscript" - x: "$Postscripts[1]" - test: if: "not($Postscripts[1][self::m:none] or $Postscripts[2][self::m:none])" then: [T: "y"] - test: if: "not($Postscripts[2][self::m:none])" then: - x: "$PostSuperscript" - x: "$Postscripts[2]" - test: if: "count($Postscripts) > 2" then: - test: if: "not($Postscripts[3][self::m:none])" then: - x: "$PostSubscript" - x: "$Postscripts[3]" - test: if: "not($Postscripts[3][self::m:none] or $Postscripts[4][self::m:none])" then: [T: "y"] - test: if: "not($Postscripts[4][self::m:none])" then: - x: "$PostSuperscript" - x: "$Postscripts[4]" - test: if: "count($Postscripts) > 4" then: - test: if: "not($Postscripts[5][self::m:none])" then: - x: "$PostSubscript" - x: "$Postscripts[5]" - test: if: "not($Postscripts[5][self::m:none] or $Postscripts[6][self::m:none])" then: [T: "y"] - test: if: "not($Postscripts[6][self::m:none])" then: - x: "$PostSuperscript" - x: "$Postscripts[6]" - test: if: "count($Postscripts) > 6" then: - test: if: "not($Postscripts[7][self::m:none])" then: - x: "$PostSubscript" - x: "$Postscripts[7]" - test: if: "not($Postscripts[7][self::m:none] or $Postscripts[8][self::m:none])" then: [T: "y"] - test: if: "not($Postscripts[8][self::m:none])" then: - x: "$PostSuperscript" - x: "$Postscripts[8]" - test: if: "count($Postscripts) > 8" # give up and just dump them out so at least the content is there then: - T: "and alternating scripts" - x: "$Postscripts[position() > 8]" - T: "end scripts" - name: default tag: mtable variables: [IsColumnSilent: false()] match: "." replace: - T: "tabla con" - x: count(*) - test: if: count(*)=1 then: [T: "fila"] else: [T: "filas"] - T: y - x: "count(*[1]/*)" - test: if: "count(*[1]/*)=1" then: [T: "columna"] else: [t: "columnas"] - pause: long - x: "*" - name: default # callers/context should do that. # this may get called from navigation -- in that case, there is no context to speak the row #, so don't do it tag: mtr match: "." replace: - x: "*" - name: default tag: mtd match: "." replace: - T: "columna" - x: "count(preceding-sibling::*)+1" - pause: medium - x: "*" # speak the entry - pause: long - name: empty-box # The ordering below is the order in which words come out when there is more than one value # Note: @notation can contain more than one value tag: menclose match: "@notation='box' and *[self::m:mtext and text()=' ']" replace: - T: "celda vacía" - name: default # The ordering below is the order in which words come out when there is more than one value # Note: @notation can contain more than one value tag: menclose match: "." replace: - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' box ')]" then: [T: "celda", pause: short] - test: if: ".[contains(@notation,'roundedbox')]" then: [T: "celda redonda", pause: short] - test: if: ".[contains(@notation,'circle')]" then: [T: "círculo", pause: short] - test: if: ".[ contains(concat(' ', normalize-space(@notation), ' '), ' left ') or contains(concat(' ', normalize-space(@notation), ' '), ' right ') or contains(@notation,'top') or contains(@notation,'bottom') ]" then: - T: línea sobre - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' left ')]" then: [T: "izquierda", pause: short] - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' right ')]" then: [T: "derecha", pause: short] - test: if: ".[contains(@notation,'top')]" then: [T: "superior", pause: short] - test: if: ".[contains(@notation,'bottom')]" then: [T: "inferior", pause: short] - test: if: ".[ contains(@notation,'updiagonalstrike') or contains(@notation,'downdiagonalstrike') or contains(@notation,'verticalstrike') or contains(@notation,'horizontalstrike') ]" then: - test: if: ".[contains(@notation,'updiagonalstrike') and contains(@notation,'downdiagonalstrike')]" then: [spell: "'x'", pause: short] # seems better to say 'x cross out' than 'up diagonal, down diagonal cross out' else: - test: if: ".[contains(@notation,'updiagonalstrike')]" then: [T: "diagonal superior", pause: short] - test: if: ".[contains(@notation,'downdiagonalstrike')]" then: [T: "diagonal inferior", pause: short] - test: if: ".[contains(@notation,'verticalstrike')]" then: [T: "vertical", pause: short] - test: if: ".[contains(@notation,'horizontalstrike')]" then: [T: "horizontal", pause: short] - T: tachar - pause: short - test: if: ".[contains(@notation,'uparrow')]" then: [T: "flecha arriba", pause: short] - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' downarrow ')]" then: [T: "flecha abajo", pause: short] - test: if: ".[contains(@notation,'leftarrow')]" then: [T: "flecha izquierda", pause: short] - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' rightarrow ')]" then: [T: "flecha derecha", pause: short] - test: if: ".[contains(@notation,'northeastarrow')]" then: [T: " flecha hacia el nordeste", pause: short] - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' southeastarrow ')]" then: [T: "flecha hacia el sudeste", pause: short] - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' southwestarrow ')]" then: [T: "flecha hacia el sudoeste", pause: short] - test: if: ".[contains(@notation,'northwestarrow')]" then: [T: "flecha hacia el noroeste", pause: short] - test: if: ".[contains(@notation,'updownarrow')]" then: [T: "flecha vertical con doble extremo", pause: short] - test: if: ".[contains(@notation,'leftrightarrow')]" then: [T: "flecha horizontal de doble extremo", pause: short] - test: if: ".[contains(@notation,'northeastsouthwestarrow')]" then: [T: "flecha diagonal superior de doble extremo", pause: short] - test: if: ".[contains(@notation,'northwestsoutheastarrow')]" then: [T: "flecha diagonal inferior de doble extremo", pause: short] - test: if: ".[contains(@notation,'actuarial')]" then: [T: "símbolo actuarial", pause: short] - test: if: ".[contains(@notation,'madrub')]" then: [t: "símbolo factorial arábigo", pause: short] - test: if: ".[contains(@notation,'phasorangle')]" then: [T: "ángulo fasorial", pause: short] - test: if: ".[contains(@notation,'longdiv') or not(@notation) or normalize-space(@notation) ='']" # default then: [T: "símbolo de larga partición", pause: short] - test: if: ".[contains(@notation,'radical')]" then: [T: "raíz cuadrada", pause: short] - T: agregando - test: if: "*[self::m:mtext and text()=' ']" then: [T: "espacio"] # otherwise there is complete silence else: [x: "*"] - test: if: "$Impairment = 'Blindness' and ( $SpeechStyle != 'SimpleSpeak' or not(IsNode(*[1], 'leaf')) )" then: [T: agregación final ] - pause: short - name: semantics tag: "semantics" match: "*[@encoding='MathML-Presentation']" replace: - x: "*[@encoding='MathML-Presentation']/*[1]" - name: semantics-default tag: "semantics" match: . replace: - x: "*[1]" - name: apply-function tag: "apply-function" match: . replace: - x: "*[1]" - T: "aplicado a" - x: "*[2]" # Here are the intent hints that need to be handled: 'prefix' | 'infix' | 'postfix' | 'function' | 'silent' - name: silent-intent # uncaught intent -- speak as arg1 arg2 .... tag: "*" match: "contains(@data-intent-property, ':silent:') and count(*)>0" replace: - x: "*" - name: prefix-intent # uncaught intent -- speak as arg1 arg2 .... tag: "*" match: "contains(@data-intent-property, ':prefix:') and count(*)>0" replace: - x: "translate(name(.), '-_', ' ')" - x: "*" - pause: short - name: postfix-intent # uncaught intent -- speak as arg1 arg2 .... tag: "*" match: "contains(@data-intent-property, ':postfix:') and count(*)>0" replace: - pause: short - x: "*" - x: "translate(name(.), '-_', ' ')" - name: infix-intent # uncaught intent -- speak as foo of arg1 comma arg2 .... tag: "*" match: "contains(@data-intent-property, ':infix:') and count(*)>0" replace: - pause: short - insert: nodes: "*" replace: [x: "translate(name(.), '-_', ' ')", pause: auto] - pause: short - name: function-intent # uncaught intent -- speak as foo of arg1 comma arg2 .... tag: "*" match: count(*)>0 replace: - x: "translate(name(.), '-_', ' ')" - T: "de" - pause: short - insert: nodes: "*" replace: [T: "coma", pause: auto] - name: default-text # unknown leaf -- just speak the text -- could be a literal intent tag: "*" match: "." replace: - x: "translate(name(), '-_', ' ')"