From 1b59103f2900755a72ee5f5b92a883341f511387 Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 21 Apr 2026 08:11:26 +0200 Subject: [PATCH 01/43] Update Norwegian ClearSpeak rules Changed logic of log function. Will now always speak "ln" if the expression is simple. Updated `spell` to `SPELL`. Added `# audit-ignore` to checked rules. Minor formatting improvements to comments. --- Rules/Languages/nb/ClearSpeak_Rules.yaml | 66 ++++++++++++++++-------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/Rules/Languages/nb/ClearSpeak_Rules.yaml b/Rules/Languages/nb/ClearSpeak_Rules.yaml index 6a9dd8c80..61ce93d34 100644 --- a/Rules/Languages/nb/ClearSpeak_Rules.yaml +++ b/Rules/Languages/nb/ClearSpeak_Rules.yaml @@ -1,4 +1,5 @@ --- +# audit-ignore - name: pause tag: "!*" match: "not(self::m:math) and not($MatchingPause) and @data-intent-property[contains(., ':pause')]" @@ -14,12 +15,14 @@ else: [pause: medium] - x: "." +# audit-ignore - name: intent-literal-silent tag: [mi, mo, mn] match: "contains(@data-intent-property, ':silent:')" # say nothing replace: [] +# audit-ignore # handling of negative numbers that come from 'intent' is hard -- we do something that is close to right here - name: intent-literal-negative-number tag: mn @@ -28,6 +31,7 @@ - T: "minus" # phrase(10 'minus' 4 equals 6) - x: "translate(text(), '-_', '')" +# audit-ignore - name: default tag: square-root match: "." @@ -55,6 +59,7 @@ then: [pause: short] else: [pause: long] +# audit-ignore - name: default tag: root match: "." @@ -70,7 +75,7 @@ then: [T: "den negative"] # phrase(minus 6 is a 'negative' number) else: [T: "den positive"] # phrase(10 is a 'positive' number) - test: - if: "*[2][self::m:mn and not(contains(., $DecimalSeparators))]" #NORWEGIAN: Changed decimal point to $DecimalSeparators + if: "*[2][self::m:mn and not(contains(., $DecimalSeparators))]" # NORWEGIAN: Changed decimal point to $DecimalSeparators then_test: - if: "*[2][.='2']" then: [T: "kvadratroten"] # phrase(5 is the 'square root' of 25) @@ -95,6 +100,7 @@ then: [pause: short] else: [pause: long] +# audit-ignore # The 'negative' rule interacts with the msqrt/mroot rules as those might pick off this case ("the negative square root of x") - name: negative_and_positive tag: [plus, minus] @@ -115,7 +121,8 @@ # Fraction rules # Mixed numbers mostly "just work" because the invisible char reads as "and" and other parts read properly on their own - + +# audit-ignore # Units (e.g., meters per second) # NORWEGIAN: Added rule for t="time" - name: per-fraction @@ -135,13 +142,14 @@ else: - x: "*[2]" +# audit-ignore # Note: if the bounds change for what is a common fraction, change them in general.yaml for units - name: common-fraction tag: fraction match: - "($ClearSpeak_Fractions='Auto' or $ClearSpeak_Fractions='Ordinal' or $ClearSpeak_Fractions='EndFrac') and" - - "*[1][self::m:mn][not(contains(., $DecimalSeparators)) and ($ClearSpeak_Fractions='Ordinal' or text()<20)] and" #NORWEGIAN: Changed decimal point to $DecimalSeparators - - "*[2][self::m:mn][not(contains(., $DecimalSeparators)) and (2<= text() and text()<=10)]" #NORWEGIAN: Removed $ClearSpeak_Fractions='Ordinal', cause the pattern for ordinal fractions is not right. + - "*[1][self::m:mn][not(contains(., $DecimalSeparators)) and ($ClearSpeak_Fractions='Ordinal' or text()<20)] and" # NORWEGIAN: Changed decimal point to $DecimalSeparators + - "*[2][self::m:mn][not(contains(., $DecimalSeparators)) and (2<= text() and text()<=10)]" # NORWEGIAN: Removed $ClearSpeak_Fractions='Ordinal', cause the pattern for ordinal fractions is not right. variables: - IsPlural: "not(*[1]=1 or preceding-sibling::*[1][self::m:mo and .='\u2064'])" # '\u2064' is invisible plus and is used in mixed fractions # set right level for the location of the common fraction/mixed fraction @@ -186,8 +194,8 @@ then: [x: "DefinitionValue(*[2], 'Speech', 'OrdinalFractionalDenominatorsForUnits')"] else: [x: "*[2]", CT: "dels"] # this is wrong but shouldn't occur normally -- need to write a function to compute cardinal numbers as words - -#NORWEGIAN: Changed to English version, but changed decimal point to $DecimalSeparators +# audit-ignore +# NORWEGIAN: Changed to English version, but changed decimal point to $DecimalSeparators - name: fraction-over-simple tag: fraction match: @@ -213,6 +221,7 @@ - T: "slutt brøk" # phrase(7 over 8 'end fraction') - pause: short +# audit-ignore - # fraction with text or numbers followed by text in both numerator and denominator name: fraction-over-text tag: fraction @@ -242,7 +251,8 @@ - T: "slutt brøk" # phrase(7 over 8 'end fraction') - pause: short -#NORWEGIAN: Changed to English version +# audit-ignore +# NORWEGIAN: Changed to English version - name: default tag: fraction match: "." @@ -263,6 +273,7 @@ - T: "slutt brøk" # phrase(the fraction with 3 over 4 'end fraction') - pause: short +# audit-ignore # rules for functions raised to a power # these could have been written on 'mrow' but putting them on msup seems more specific # to see if it is a function, we look right to see if the following sibling is apply-function @@ -278,7 +289,7 @@ then: [bookmark: "*[2]/@id", T: "arcus", x: "*[1]"] # phrase(the 'buelenge' of a circle) else: [bookmark: "*[2]/@id", T: "invers", x: "*[1]"] # default/Auto # phrase(8 over 5 is the 'inverse' of 5 over 8) - +# audit-ignore - name: function-squared-or-cubed tag: power match: @@ -343,7 +354,7 @@ - name: simple-integer tag: power - match: "*[2][self::m:mn][not(contains(., $DecimalSeparators))]" #NORWEGIAN: Changed decimal point to $DecimalSeparators + match: "*[2][self::m:mn][not(contains(., $DecimalSeparators))]" # NORWEGIAN: Changed decimal point to $DecimalSeparators replace: - x: "*[1]" - T: "opphøyd i" @@ -355,7 +366,7 @@ tag: power match: - "*[2][self::m:minus and count(*)=1 and" - - " *[1][self::m:mn][not(contains(., $DecimalSeparators))]" #NORWEGIAN: Changed decimal point to $DecimalSeparators + - " *[1][self::m:mn][not(contains(., $DecimalSeparators))]" # NORWEGIAN: Changed decimal point to $DecimalSeparators - " ]" replace: - x: "*[1]" @@ -391,7 +402,7 @@ - " *[2][self::m:mn][.='2' or .='3'] and " # exp is 2 or 3 # base is mn, mi, common fraction ([xxx] case) - " *[1][self::m:mn or self::m:mi or " - - " self::m:fraction[*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" #NORWEGIAN: Changed decimal point to $DecimalSeparators + - " self::m:fraction[*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" # NORWEGIAN: Changed decimal point to $DecimalSeparators - " *[2][self::m:mn][not(contains(., $DecimalSeparators)) and 2<= text() and text()<=10]]" - " ]" - " ]" @@ -410,7 +421,7 @@ - " *[2][self::m:mn][.='2' or .='3'] and " # exp is 2 or 3" # base is mn, mi, common fraction ([xxx] case) - " *[1][self::m:mn or self::m:mi or " - - " self::m:fraction[*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" #NORWEGIAN: Changed decimal point to $DecimalSeparators + - " self::m:fraction[*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" # NORWEGIAN: Changed decimal point to $DecimalSeparators - " *[2][self::m:mn][not(contains(., $DecimalSeparators)) and 2<= text() and text()<=10]]" - " ]" - " ]" @@ -433,7 +444,7 @@ - " *[2][self::m:mo][.='⁢'] and " # invisible times # base is mn, or common fraction ([xxx] case) - " *[1][self::m:mn or " - - " self::m:fraction[*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" #NORWEGIAN: Changed decimal point to $DecimalSeparators + - " self::m:fraction[*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" # NORWEGIAN: Changed decimal point to $DecimalSeparators - " *[2][self::m:mn][not(contains(., $DecimalSeparators)) and 2<= text() and text()<=10]]" - " ]" - " ]" @@ -456,7 +467,7 @@ - " *[1][self::m:minus and count(*)=1 and " # base is mn, or common fraction ([xxx] case) - " *[1][self::m:mn or " - - " self::m:fraction[*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" #NORWEGIAN: Changed decimal point to $DecimalSeparators + - " self::m:fraction[*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" # NORWEGIAN: Changed decimal point to $DecimalSeparators - " *[2][self::m:mn][not(contains(., $DecimalSeparators)) and 2<= text() and text()<=10]]" - " ]" - " ]" @@ -489,6 +500,7 @@ # # Some rules on mrows # +# audit-ignore - # the inference rules lump absolute value and cardinality together, so those rules are implemented here name: ClearSpeak-absolute-value tag: absolute-value @@ -509,6 +521,7 @@ - x: "$EndToSay" - pause: short +# audit-ignore - name: set tag: set match: "." @@ -546,6 +559,7 @@ # SWEDISH/NORWEGIAN: rewrote the intervals function to better deal with Swedish/Norwegian convention of speaking intervals # NORWEGIAN: Removed test for verbosity, cause you should always say "det åpne" etc. + # audit-ignore - name: ClearSpeak-intervals # avoid overriding with default "intervals" name variables: - is_intervals_start_infinity: "*[1][self::m:minus and count(*)=1 and *[1][.='∞']]" @@ -571,6 +585,7 @@ then: [T: "og med"] - x: "*[2]" + # audit-ignore - name: binomial-frac-vector tag: matrix match: @@ -581,6 +596,7 @@ - T: "over" # phrase(the binomial coefficient n 'choose' m) - x: "*[2]/*[1]/*" + # audit-ignore - name: ClearSpeak-default tag: [mtr, mlabeledtr] match: "parent::m:matrix or parent::m:determinant" @@ -609,16 +625,16 @@ replace: - bookmark: "@id" - test: - if: "IsNode(following-sibling::*[2],'simple')" + if: "$log_is_simple" then: - test: - if: ".='log'" then: [T: "log"] # phrase(the 'log' of x) - else_if: ".='lg'" - then: [spell: "'lg'"] # phrase(the 'lg' of x) - - else_if: $ClearSpeak_Log = 'LnAsNaturalLog' or $Verbosity='Verbose' + then: [SPELL: "'lg'"] # phrase(the 'lg' of x) + - else_if: $ClearSpeak_Log = 'LnAsNaturalLog' then: [T: "den naturlige logaritmen"] # phrase(the 'natural log' of the product of 2 numbers) - else: [spell: "'ln'"] + else: [SPELL: "'ln'"] else: - test: - if: ".='log'" @@ -632,12 +648,13 @@ - test: - if: "$Verbosity='Verbose'" then: [T: "tier-logaritmen"] - else: [spell: "'lg'"] # phrase(the 'lg' of x) + else: [SPELL: "'lg'"] # phrase(the 'lg' of x) - else_if: $ClearSpeak_Log = 'LnAsNaturalLog' or $Verbosity='Verbose' then: [T: "den naturlige logaritmen"] # phrase(the 'natural log' of x) - else: [spell: "'ln'"] + else: [SPELL: "'ln'"] -#NORWEGIAN: Changed to English version +# audit-ignore +# NORWEGIAN: Changed to English version - name: ClearSpeak-multi-line tag: [piecewise, system-of-equations, lines] # these are ignored in favor of the ClearSpeak prefs match: "." @@ -691,7 +708,8 @@ - pause: short - x: "*" -#NORWEGIAN: Changed from Swedish to English version +# audit-ignore +# NORWEGIAN: Changed from Swedish to English version - name: ClearSpeak-default-multiline tag: [mtr, mlabeledtr] match: "parent::m:piecewise or parent::m:system-of-equations or parent::m:lines" @@ -731,6 +749,7 @@ then: [x: "*[position()>1]"] else: [x: "*"] +# audit-ignore - name: ClearSpeak_Functions_None tag: mo match: @@ -742,6 +761,7 @@ then: [T: ""] else: [T: "ganger"] # phrase(5 'times' 3 equals 15) +# audit-ignore - name: no-times tag: mo match: @@ -750,6 +770,7 @@ replace: - T: "" +# audit-ignore # NORWEGIAN: Changed to English version - name: ClearSpeak-times tag: mo @@ -782,6 +803,7 @@ replace: - T: "ganger" # phrase(5 'times' 3 equals 15) +# audit-ignore - name: no-say-parens tag: mrow match: From 0cc49ba43391458eea2189f02866975879d7a88b Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 21 Apr 2026 08:23:29 +0200 Subject: [PATCH 02/43] Added "hektar" as neuter unit --- Rules/Languages/nb/definitions.yaml | 1 + tests/Languages/nb/units.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Rules/Languages/nb/definitions.yaml b/Rules/Languages/nb/definitions.yaml index eb446a1bc..0b09ed316 100644 --- a/Rules/Languages/nb/definitions.yaml +++ b/Rules/Languages/nb/definitions.yaml @@ -321,6 +321,7 @@ "arcmin", "amin", "am", "MOA":, "arcsec", "asec", "ltyr", "ly", "l.y.", + "ha", #EnglishUnits "bbl", "BBL", "lb", diff --git a/tests/Languages/nb/units.rs b/tests/Languages/nb/units.rs index 0bc7d7a9f..273abffff 100644 --- a/tests/Languages/nb/units.rs +++ b/tests/Languages/nb/units.rs @@ -418,7 +418,7 @@ fn without_prefix_other() -> Result<()> { 1erg,2erg "#; test("nb", "SimpleSpeak", expr, - "1 hektar, komma, 2 hektar, komma, \ + "ett hektar, komma, 2 hektar, komma, \ 1 desibel, komma, 2 desibel, komma, \ 1 atmosfære, komma, 2 atmosfærer, komma; \ 1 atommasseenhet, komma; 2 atommasseenheter, komma, \ From 984540876b641a216b7a644b75a9a6502f713e0e Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 21 Apr 2026 09:32:25 +0200 Subject: [PATCH 03/43] Update Norwegian SimpleSpeak rules for verbosity and audit status - Implement verbosity checks for square roots, using "roten av" for Terse settings. - Add "# audit-ignore" to checked rules. - Minor formatting improvements to comments. --- Rules/Languages/nb/SimpleSpeak_Rules.yaml | 46 +++++++++++++++++------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/Rules/Languages/nb/SimpleSpeak_Rules.yaml b/Rules/Languages/nb/SimpleSpeak_Rules.yaml index 412fa1c7b..7784d9377 100644 --- a/Rules/Languages/nb/SimpleSpeak_Rules.yaml +++ b/Rules/Languages/nb/SimpleSpeak_Rules.yaml @@ -1,4 +1,5 @@ --- +# audit-ignore - name: pause tag: "!*" match: "not(self::m:math) and not($MatchingPause) and @data-intent-property[contains(., ':pause')]" @@ -13,13 +14,15 @@ then: [pause: short] else: [pause: medium] - x: "." - + +# audit-ignore - name: intent-literal-silent tag: [mi, mo, mn] match: "contains(@data-intent-property, ':silent:')" # say nothing replace: [] +# audit-ignore # handling of negative numbers that come from 'intent' is hard -- we do something that is close to right here - name: intent-literal-negative-number tag: mn @@ -28,24 +31,28 @@ - T: "minus" # phrase(x 'minus' y) - x: "translate(text(), '-_', '')" +# audit-ignore - name: default tag: square-root match: "." replace: - - T: "kvadratroten av" # phrase(the 'square root' of x) - # NORWEGIAN: Removed test for Verbosity + - test: + if: "$Verbosity!='Terse'" + then: [T: "kvadratroten av"] # phrase(the 'square root' of x) + else: [T: "roten av"] - x: "*[1]" - test: if: IsNode(*[1], 'leaf') then: [pause: short] else: [pause: short, T: "slutt rot", pause: short] # phrase(start the square root of x 'end of root') +# audit-ignore - name: default tag: root match: "." replace: - test: - if: "*[2][self::m:mn and not(contains(., $DecimalSeparators))]" #NORWEGIAN: Changed decimal point to $DecimalSeparators + if: "*[2][self::m:mn and not(contains(., $DecimalSeparators))]" # NORWEGIAN: Changed decimal point to $DecimalSeparators then_test: - if: "*[2][.='2']" then: [T: "kvadratroten"] # phrase(the 'square root' of x) @@ -64,13 +71,14 @@ then: [pause: short] else: [pause: short, T: "slutt rot", pause: short] # phrase(start the fifth root of x 'end of root') +# audit-ignore # Fraction rules # Mixed numbers mostly "just work" because the invisible char reads as "and" and other parts read properly on their own # Note: if the bounds change for what is a common fraction, change them in general.yaml for units - name: common-fraction tag: fraction match: - - "*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" #NORWEGIAN: Changed decimal point to $DecimalSeparators + - "*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" # NORWEGIAN: Changed decimal point to $DecimalSeparators - "*[2][self::m:mn][not(contains(., $DecimalSeparators)) and 2<= text() and text()<=10]" variables: - IsPlural: "not(*[1]=1 or preceding-sibling::*[1][self::m:mo and .='\u2064'])" # '\u2064' is invisible plus and is used in mixed fractions @@ -114,9 +122,9 @@ then: [x: "DefinitionValue(*[2], 'Speech', 'OrdinalFractionalDenominatorsForUnits')"] else: [x: "*[2]", CT: "dels"] # this is wrong but shouldn't occur normally -- need to write a function to compute cardinal numbers as words - +# audit-ignore # Units (e.g., meters per second, m^2/s^2, (3m^2)/s) -#NORWEGIAN: Added rule for t="time" +# NORWEGIAN: Added rule for t="time" - name: per-fraction tag: fraction match: @@ -132,7 +140,8 @@ then: [T: "time"] else: - x: "*[2]" - + +# audit-ignore - name: 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 @@ -147,6 +156,7 @@ - x: "*[2]" - pause: short +# audit-ignore - name: default tag: fraction match: "." @@ -166,6 +176,7 @@ - T: "slutt brøk" # phrase(start 7 over 8 'end of fraction') - pause: medium +# audit-ignore # rules for functions raised to a power # these could have been written on 'mrow' but putting them on msup seems more specific # to see if it is a function, we look right to see if the following sibling is apply-function @@ -176,6 +187,7 @@ - T: "invers" # phrase(the 'inverse' of f) - x: "*[1]" +# audit-ignore - name: function-squared-or-cubed tag: power match: @@ -189,6 +201,7 @@ then: [T: "i andre"] # phrase(5 'squared' equals 25) else: [T: "i tredje"] # phrase(5 'cubed' equals 125) +# audit-ignore - name: function-power tag: power match: @@ -200,6 +213,7 @@ - x: "*[2]" - pause: short +# audit-ignore # non-function rules for power - name: squared-or-cubed tag: power @@ -212,26 +226,29 @@ then: [T: "i andre"] # phrase(5 'squared' equals 25) else: [T: "i tredje"] # phrase(5 'cubed' equals 125) +# audit-ignore - name: simple-integer tag: power - match: "*[2][self::m:mn][not(contains(., $DecimalSeparators))]" #NORWEGIAN: Changed decimal point to $DecimalSeparators + match: "*[2][self::m:mn][not(contains(., $DecimalSeparators))]" # NORWEGIAN: Changed decimal point to $DecimalSeparators replace: - x: "*[1]" - T: "opphøyd i" - x: "*[2]" - pause: short +# audit-ignore - name: simple-negative-integer tag: power match: - "*[2][self::m:minus and count(*)=1 and" - - " *[1][self::m:mn][not(contains(., $DecimalSeparators))]]" #NORWEGIAN: Changed decimal point to $DecimalSeparators + - " *[1][self::m:mn][not(contains(., $DecimalSeparators))]]" # NORWEGIAN: Changed decimal point to $DecimalSeparators replace: - x: "*[1]" - T: "opphøyd i" - x: "*[2]" - pause: short +# audit-ignore - name: simple-var tag: power match: "*[2][self::m:mi][string-length(.)=1]" @@ -241,6 +258,7 @@ - x: "*[2]" - pause: short +# audit-ignore - name: simple tag: power match: "IsNode(*[2], 'leaf')" @@ -250,6 +268,7 @@ - x: "*[2]" - pause: short +# audit-ignore - name: nested # it won't end in "power" if the exponent is simple enough # FIX: not that important, but this misses the case where the nested exp is a negative integer (change test if this is fixed) @@ -267,6 +286,7 @@ - pause: short - T: "slutt eksponent" # phrase(start 2 raised to the exponent 4 'end of exponent') +# Norwegian: Need to find something similar to the word "power" or add a long pause. - name: default tag: power match: "." @@ -277,7 +297,7 @@ # # Some rules on mrows -# +# audit-ignore - name: set tag: set match: "." @@ -295,7 +315,8 @@ else: - T: "mengden" # phrase(here is a 'set' of numbers) - x: "*[1]" - + +# audit-ignore # NORWEGIAN: Added sqrt, so it, for example, says "sqrt a times sqrt b" - name: times tag: mo @@ -325,6 +346,7 @@ replace: - T: "ganger" # phrase(7 'times' 5 equals 35) +# audit-ignore - name: no-say-parens tag: mrow match: From 2160ace7e92b965fadb198a5ba69fb4596989ea6 Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 21 Apr 2026 10:48:20 +0200 Subject: [PATCH 04/43] Update Norwegian Unicode rules for literal intent and SPELL consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add support for `:literal:` intent for several symbols (/, |, ·, ×) to provide more literal readings like "skråstrek" and "vertikal strek". - Update `spell` to `SPELL` throughout the file for consistency. - Changed logic in the rule for the multiplication sign (×). --- Rules/Languages/nb/unicode.yaml | 49 ++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/Rules/Languages/nb/unicode.yaml b/Rules/Languages/nb/unicode.yaml index 25600faa0..4271fafee 100644 --- a/Rules/Languages/nb/unicode.yaml +++ b/Rules/Languages/nb/unicode.yaml @@ -3,7 +3,7 @@ - test: if: "$TTS='none'" then: [T: "."] # (en: '.', google translation) - else: [spell: "'.'"] + else: [SPELL: "'.'"] # Capital letters are a little tricky: users can pick their favorite word (something that was requested) and # screen readers have options to use pitch changes or beeps instead of or in addition to say "cap" @@ -27,7 +27,7 @@ - pitch: value: "$CapitalLetters_Pitch" # note: processing of ranges converts '.' into the character, so it needs to be in quotes below - replace: [spell: "translate('.', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"] + replace: [SPELL: "translate('.', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"] - "0-9": [T: "."] # (en: '.', google: 'A') @@ -97,7 +97,11 @@ if: "parent::*[1][self::m:mn]" then: [T: "punktum"] # (en: 'point', google translation) else: [T: "prikk"] # (en: 'dot') - - "/": [T: "delt på"] # 0x2f (en: 'divided by') + - "/": # 0x2f (en: 'divided by') + - test: + if: "ancestor-or-self::*[contains(@data-intent-property, ':literal:')]" + then: [t: "skråstrek"] # 0x2f + else: [t: "delt på"] # 0x2f - ":": [T: "kolon"] # 0x3a (en: 'colon') - ";": [T: "semikolon"] # 0x3b (en: 'semicolon') - "<": # 0x3c @@ -141,16 +145,18 @@ then: [T: "start krøllparentes"] # (en: 'open brace', google translation) else: [T: "venstre krøllparentes"] # (en: 'left brace') - pause: short - - "|": # 0x7c NORWEGIAN: Changed to English version + - "|": # 0x7c # note: for ClearSpeak and SimpleSpeak, "|" inside of sets is handled at the mrow level, same for 'sets' - with: variables: [DefaultToGiven: "count(preceding-sibling::*)=1 and count(following-sibling::*)=1 and ../../../*[1][.='P']"] # P(A|B) replace: - test: - - if: "$SpeechStyle != 'ClearSpeak'" + - if: "ancestor-or-self::*[contains(@data-intent-property, ':literal:')]" + then: [T: "vertikal strek"] + - else_if: "$SpeechStyle != 'ClearSpeak'" then_test: - if: "$DefaultToGiven" - then: [pause: short, T: "gitt"] + then: [T: "gitt"] - else_if: "preceding-sibling::*[1][self::m:mn and not(contains(., $DecimalSeparators))] and following-sibling::*[1][self::m:mn and not(contains(., $DecimalSeparators))]" then: [T: "deler"] @@ -160,7 +166,7 @@ - else_if: "$ClearSpeak_VerticalLine = 'SuchThat'" then: [T: "slik at"] - else_if: "$ClearSpeak_VerticalLine = 'Given' or $DefaultToGiven" - then: [pause: short, T: "gitt"] + then: [T: "gitt"] - else: [T: "deler"] - "}": # 0x7d @@ -183,17 +189,22 @@ - "´": [T: "akutt aksent"] # 0xb4 (en: 'acute') - "·": # 0xB7 - test: - if: "$SpeechStyle = 'LiteralSpeak' or not($SpeechStyle = 'ClearSpeak' and $ClearSpeak_MultSymbolDot = 'Auto')" + if: "ancestor-or-self::*[contains(@data-intent-property, ':literal:')] or not($SpeechStyle = 'ClearSpeak' and $ClearSpeak_MultSymbolDot = 'Auto')" then: [T: "midtstilt prikk"] # (en: 'times', google translation) else: [T: "ganger"] # (en: 'dot', MathPlayer: 'mellanpunkt', google: 'punkt') - - "×": # 0xd7 + - "×": # 0xd7 - test: - if: "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_MultSymbolX = 'Auto'" - then: [T: "ganger"] # (en: 'times', google translation) + if: "$SpeechStyle = 'ClearSpeak'" + then_test: + - if: "$ClearSpeak_MultSymbolX = 'Auto'" + then: [T: "ganger"] + - else_if: "$ClearSpeak_MultSymbolX = 'By'" + then: [T: "ganger"] + else: [T: "kryss"] else_test: - if: $ClearSpeak_MultSymbolX = 'By' - then: [T: "ganger"] # (en: 'by', google translation) - else: [T: "kryss"] # (en: 'cross') + if: "ancestor-or-self::*[contains(@data-intent-property, ':literal:')]" + then: [T: "kryss"] + else: [T: "ganger"] - "÷": [T: "delt på"] # 0xf7 (en: 'divided by') - "̀": [T: "grav aksent"] # 0x300 (en: 'grave accent embellishment', google: 'allvarlig accentutsmyckning') - "́": [T: "akutt aksent"] # 0x301 (en: 'acute accent embellishment', google: 'akut accentutsmyckning') @@ -223,7 +234,7 @@ - pitch: value: "$CapitalLetters_Pitch" # note: processing of ranges converts '.' into the character, so it needs to be in quotes below - replace: [spell: "translate('.', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ', 'αβγδεζηθικλμνξοπρςστυφχψω')"] + replace: [SPELL: "translate('.', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ', 'αβγδεζηθικλμνξοπρςστυφχψω')"] - "α": [T: "alfa"] # 0x3b1 (en: 'alpha') - "β": [T: "beta"] # 0x3b2 @@ -295,24 +306,24 @@ - "ℂℕℚℝℤ": # here we rely on this running through the table again to speak "cap xxx" - T: "dobbeltstreket" # (en: 'double-struck') - - spell: "translate('.', 'ℂℕℚℝℤ', 'CNQRZ')" + - SPELL: "translate('.', 'ℂℕℚℝℤ', 'CNQRZ')" - "℃": [T: "grader celsius"] # 0x2103 (en: 'degrees celsius') - "℉": [T: "grader fahrenheit"] # 0x2109 (en: 'degrees fahrenheit') - "ℋℛℓ": # 0x210b - T: "script font" # (en: 'script', google: 'manus') - - spell: "translate('.', 'ℋℛℓ', 'HRl')" + - SPELL: "translate('.', 'ℋℛℓ', 'HRl')" - "ℎ": [T: "plancks konstant"] # 0x210e - "ℜ": # 0x211c - T: "fraktur" # (en: 'fraktur', google: 'fraktur') - - spell: "'R'" + - SPELL: "'R'" - "Ω": [T: "ohm"] # 0x2126 (en: 'ohms') - "K": [T: "kelvin"] # 0x212a (en: 'kelvin') - "Å": [T: "ångstrøm"] # 0x212b - "ⅆⅇⅈⅉ": # 0x2146-9 - T: "dobbeltstreket kursiv" # (en: 'double-struck italic') - - spell: "translate('.', 'ⅆⅇⅈⅉ', 'deij')" + - SPELL: "translate('.', 'ⅆⅇⅈⅉ', 'deij')" - "←": [T: "venstrepil"] # 0x2190 (en: 'leftwards arrow') - "↑": [T: "oppoverpil"] # 0x2191 (en: 'upwards arrow') From d35b438252a7ab85d2da6a0dda8dca3fed5fc7bb Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 22 Apr 2026 06:58:50 +0200 Subject: [PATCH 05/43] Update Norwegian Unicode rules for expanded character support and consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added unicode characters. - Updated `spell` to `SPELL`. - Implement `:literal:` intent logic for double exclamation (‼) and fraction slash (⁄). - Add verbosity-based logic for the cross product symbol (⨯). - Add support for MathJax PUA values used for chemical bonds and arrows. --- Rules/Languages/nb/unicode-full.yaml | 330 ++++++++++++++++++--------- 1 file changed, 222 insertions(+), 108 deletions(-) diff --git a/Rules/Languages/nb/unicode-full.yaml b/Rules/Languages/nb/unicode-full.yaml index a2bad5061..d65c0ad4c 100644 --- a/Rules/Languages/nb/unicode-full.yaml +++ b/Rules/Languages/nb/unicode-full.yaml @@ -37,6 +37,9 @@ then: [T: "ganger"] # (en: 'by', google translation) else: [T: "kryss"] # (en: 'cross') - "÷": [T: "delt på"] # 0xf7 (en: 'divided by') + - "¡": [T: "omvendt utropstegn"] # 0xa1 + - "¶": [T: "paragraftegn"] # 0xb6 + - "¿": [T: "omvendt spørsmålstegn"] # 0xbf #------------------------------------------------------------------------------------------------------- # SWEDISH: The Swedish character translations are based on the placement and appearance of the characters rather than their function, as function might be context-dependent. Placement above is used as the baseline, and low characters are translated as "låg(t)" (eng "low"). In most cases, no difference has been made in the translation between non-combining, modifier (Spacing Modifier Letters), and combining/embellishment characters. However, in the case of alphabetical letters and punctuation marks as modifier characters (such as modifier small h or comma embellishment), the construction "med ...( efter)" (eng "with ...( placed after it)") is used to prevent any possible ambiguity. # Norwegian: Same as Swedish @@ -50,7 +53,7 @@ - "ʵ": [T: "med liten rotert r med krok etter"] # 0x2b5 (en: 'modifier small turned r with hook', google translation) - "ʶ": # 0x2b6 - T: "med liten rotert" # (en: 'modifier small inverted', google translation) - - spell: "translate('R', 'R', 'R')" + - SPELL: "translate('R', 'R', 'R')" - "ʷ": [T: "med liten w etter"] # 0x2b7 (en: 'modifier small w', google translation) - "ʸ": [T: "med liten y etter"] # 0x2b8 (en: 'modifier small y', google translation) #-------------------------- @@ -213,6 +216,7 @@ - "̿": [T: "dobbel strek"] # 0x33f (en: 'double overline embellishment', google translation) - "̀": [T: "grav tone"] # 0x340 (en: 'grave tone mark embellishment', google translation) - "́": [T: "akutt tone"] # 0x341 (en: 'acute tone mark embellishment', google translation) + - "͆": [T: "bro"] # 0x346 #---------------------------------------------------------------------------------------------------------------- # Greek and Coptic OK - "ΪΫϏ": # 0x3aa, 0x3ab, 0x3cf @@ -232,7 +236,7 @@ else: [x: "$SpeechOverrides_CapitalLetters"] - pitch: value: "$CapitalLetters_Pitch" - replace: [spell: "translate('.', 'ΪΫϏ', 'ιυϗ')"] + replace: [SPELL: "translate('.', 'ΪΫϏ', 'ιυϗ')"] - T: "med dialytika" # (en: 'with dialytika', google translation) - "ϊ": [T: "iota med dialytika"] # 0x3ca (en: 'iota with dialytika', google translation) - "ϋ": [T: "ypsilon med dialytika"] # 0x3cb (en: 'upsilon with dialytika', google translation) @@ -247,6 +251,8 @@ - "ϕ": [T: "fi"] # 0x3d5 (en: 'phi', google: 'phi') - "ϖ": [T: "pi"] # 0x3d6 (en: 'pi', google: 'pi') - "ϗ": [T: "kai"] # 0x3d7 (en: 'kai') + - "Ϙ": [T: "stor arkaisk koppa"] # 0x3d8 + - "ϙ": [T: "arkaisk koppa"] # 0x3d9 - "ϵ": [T: "epsilon"] # 0x3f5 - "϶": [T: "omvendt epsilon"] # 0x3f6 (en: 'reversed epsilon') #----------------------------------------------------------------------------------------------------------------- @@ -268,7 +274,7 @@ else: [x: "$SpeechOverrides_CapitalLetters"] - pitch: value: "$CapitalLetters_Pitch" - replace: [spell: "translate('.', 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ', 'абвгдежзийклмнопрстуфхцчшщъыьэюя')", pause: short] + replace: [SPELL: "translate('.', 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ', 'абвгдежзийклмнопрстуфхцчшщъыьэюя')", pause: short] - "а": [T: "a"] # 0x430 (google: 'а') - "б": [T: "be"] # 0x431 (google: 'vara') - "в": [T: "ve"] # 0x432 @@ -301,6 +307,9 @@ - "э": [T: "e"] # 0x44d (google: 'э') - "ю": [T: "ju"] # 0x44e - "я": [T: "ja"] # 0x44f + - "؆": [T: "arabisk-indisk kubikkrot"] # 0x606 + - "؇": [T: "arabisk-indisk fjerderot"] # 0x607 + - "؈": [T: "arabisk stråle"] # 0x608 #----------------------------------------------------------------------------------------------------------- #General punctuation OK - "‐": [T: "bindestrek"] # 0x2010 (en: 'hyphen') @@ -312,6 +321,8 @@ - "‖": [T: "dobbel loddrett strek"] # 0x2016 (en: 'double vertical line') - "†": [T: "kors"] # 0x2020 (en: 'dagger') - "‡": [T: "dobbelt kors"] # 0x2021 (en: 'double dagger') + + - " - ": [T: " "] # 0x2000 - 0x2007 - "•": # 0x2022 - test: @@ -343,10 +354,26 @@ - "‸": [T: "innsettingstegn"] # 0x2038 (en: 'to the', google: 'till') - "‹": [T: "venstrepekende vinkel-sitattegn"] # 0x2039 (en: 'single left pointing angle quote mark') - "›": [T: "høyrepekende vinkel-sitattegn"] # 0x203a (en: 'single right pointing angle quote mark') - - "‼": [T: "dobbelt utropstegn"] # 0x203c (en: 'double factorial', google: 'dubbel faktorie') - - "⁄": [T: "delt på"] # 0x2044 (en: 'divided by') + - "‼": # 0x203c + - test: + if: "ancestor-or-self::*[contains(@data-intent-property, ':literal:')]" + then: [T: "dobbelt utropstegn"] # 0x203c + else: [T: "dobbel fakultet"] # 0x203c + - "⁄": # 0x2044 + - test: + if: "ancestor-or-self::*[contains(@data-intent-property, ':literal:')]" + then: [T: "stor skråstrek"] # 0x203c + else: [T: "delt på"] # 0x203c - "⁅": [T: "venstre piggparentes"] # 0x2045 (en: 'left square bracket with quill', google: 'vänster fyrkantig konsol med quill') - "⁆": [T: "høyre piggparentes"] # 0x2046 (en: 'right square bracket with quill', google: 'höger fyrkantig konsol med quill') + - "※": [T: "referansetegn"] # 0x203b + - "‿": [T: "underbinding"] # 0x203F + - "⁀": [T: "bindetegn"] # 0x2040 + - "⁎": [T: "lav asterisk"] # 0x204e + - "⁏": [T: "omvendt semikolon"] # 0x204f + - "⁐": [T: "sammentrekksmerke"] # 0x2050 + - "⁑": [T: "to vertikale asterisk"] # 0x2051 + - "⁒": [T: "kommersielt minustegn"] # 0x2052 - "⁗": [T: "firedobbelt primtegn"] # 0x2057 (en: 'quadruple prime', MathPlayer: 'quadruple prime', google: 'fyrdubbla prime') - "⁠": [T: ""] # 0x2060 #------------------------------------------------------------------------------------------------------------------------- @@ -467,11 +494,11 @@ - "ℊ": [T: "script font g"] # 0x210a (en: 'script g') - "ℌℑℨℭ": # 0x210c, 0x2111, 0x2128, 0x212d - T: "fraktur" # (en: 'fraktur', google: 'fraktur') - - spell: "translate('.', 'ℌℑℨℭ', 'HIZC')" + - SPELL: "translate('.', 'ℌℑℨℭ', 'HIZC')" - "ℍℙℾℿ": # 0x210d, 0x2119, 0x213e, 0x213f - T: "dobbeltstreket" # (en: 'double struck', google translation) - - spell: "translate('.', 'ℍℙℾℿ', 'HPΓΠ')" + - SPELL: "translate('.', 'ℍℙℾℿ', 'HPΓΠ')" - "ℎ": [T: "plancks konstant"] # 0x210e - "ℏ": [T: "h strek"] # 0x210f @@ -479,7 +506,7 @@ - "ℐℒ℘ℬℰℱℳ": # 0x2110, 0x2112, 0x2118, 0x2130, 0x2131, 0x2133 - T: "script font" # (en: 'script') - - spell: "translate('.', 'ℐℒ℘ℬℰℱℳ', 'ILPBEFM')" + - SPELL: "translate('.', 'ℐℒ℘ℬℰℱℳ', 'ILPBEFM')" - "ℓ": [T: "script font l"] # 0x2113 (en: 'script l') - "℔": [T: "pund"] # 0x2114 (en: 'pounds', google: 'pund') @@ -502,7 +529,7 @@ - else_if: "'.' = '⅃'" then: [T: "omvendt sans-serif"] # (en: 'reversed sans-serif', google translation) else: [T: "rotert sans-serif"] # (en: 'turned sans-serif', google: 'vände sans-serif') - - spell: "translate('.', 'Ⅎ℺⅁⅂⅃⅄', 'FQGLLY')" + - SPELL: "translate('.', 'Ⅎ℺⅁⅂⅃⅄', 'FQGLLY')" - "ℴ": [T: "script font o"] # 0x2134 (en: 'script o') - "ℵ": [T: "alef"] # 0x2135 (en: 'first transfinite cardinal') @@ -517,6 +544,9 @@ - "ⅎ": [T: "rotert f"] # 0x214e (en: 'turned F', google: 'vände f') #-------------------------------------------------------------------------------------------------------------- #Number formats OK + - "¼": [T: "én fjerdedel"] # 0x00bc + - "½": [T: "én halv"] # 0x00bd + - "¾": [T: "tre fjerdedeler"] # 0x00be - "⅐": [T: "én sjudel"] # 0x2150 (en: 'one seventh', google: 'en sjunde') - "⅑": [T: "én nidel"] # 0x2151 (en: 'one ninth', google: 'en nionde') - "⅒": [T: "én tidel"] # 0x2152 (en: 'one tenth') @@ -1385,15 +1415,31 @@ - "⌳": [T: "helning"] # 0x2333 (en: 'slope', google translation) - "⌴": [T: "plansenkning"] # 0x2334 (en: 'counterbore', google translation) - "⌵": [T: "forsenkning"] # 0x2335 (en: 'countersink', google translation) + - "⌶": [T: "apl i beam"] # 0x2336 + - "⌽": [T: "apl circle stile"] # 0x233d + - "⌿": [T: "apl slash bar"] # 0x233f + - "⍼": [T: "rett vinkel med nedover sikksakk-pil"] # 0x237c + - "⎔": [T: "heksagon"] # 0x2394 + - "⎶": [T: "nedre hakeparentes over øvre hakeparentes"] # 0x23b6 + - "⏜": [T: "øvre parentes"] # 0x23dc + - "⏝": [T: "nedre parentes"] # 0x23dd - "⍰": [T: "ukjent boks"] # 0x2370 (en: 'unknown box', google: 'okänd ruta') - "⎕": [T: "boks"] # 0x2395 (en: 'box', google translation) - "⏞": [T: "øvre krøllparentes"] # 0x23DE (en: 'top brace') - "⏟": [T: "nedre krøllparentes"] # 0x23DF (en: 'bottom brace') + - "⏠": [T: "øvre skilpaddeskall-parentes"] # 0x23e0 + - "⏡": [T: "nedre skilpaddeskall-parentes"] # 0x23e1 + - "⏢": [T: "hvit trapes"] # 0x23e2 + - "⏣": [T: "benzenring med sirkel"] # 0x23e3 + - "⏤": [T: "retthet"] # 0x23e4 + - "⏥": [T: "flathet"] # 0x23e5 + - "⏦": [T: "vekselstrøm"] # 0x23e6 + - "⏧": [T: "elektrisk skjæring"] # 0x23e7 #---------------------------------------------------------------------------------------------------- #Enclosed Alphanumerics OK - "①-⑨": # 0x2460 - 0x2469 # SWEDISH: switched order - - spell: "translate('.', '①②③④⑤⑥⑦⑧⑨', '123456789')" + - SPELL: "translate('.', '①②③④⑤⑥⑦⑧⑨', '123456789')" - T: "i sirkel" # (en: 'circled') - "⑩": [T: "ti i sirkel"] # 0x2469 (en: 'circled ten', google translation) - "⑪": [T: "elleve i sirkel"] # 0x246a (en: 'circled eleven', google translation) @@ -1407,7 +1453,7 @@ - "⑳": [T: "tjue i sirkel"] # 0x2473 (en: 'circled twenty', google translation) - "⑴-⑼": # 0x2474 - 0x247d # SWEDISH: switched order - - spell: "translate('.', '⑴⑵⑶⑷⑸⑹⑺⑻⑼', '123456789')" + - SPELL: "translate('.', '⑴⑵⑶⑷⑸⑹⑺⑻⑼', '123456789')" - T: "i parentes" # (en: 'parenthesized', google translation) - "⑽": [T: "ti i parentes"] # 0x247d (en: 'parenthesized ten', google translation) - "⑾": [T: "elleve i parentes"] # 0x247e (en: 'parenthesized eleven', google translation) @@ -1421,7 +1467,7 @@ - "⒆": [T: "nitten i parentes"] # 0x2486 (en: 'parenthesized nineteen', google translation) - "⒇": [T: "tjue i parentes"] # 0x2487 (en: 'parenthesized twenty', google translation) - "⒈-⒐": # 0x2488 - 0x2491 - - spell: "translate('.', '⒈⒉⒊⒋⒌⒍⒎⒏⒐', '123456789')" + - SPELL: "translate('.', '⒈⒉⒊⒋⒌⒍⒎⒏⒐', '123456789')" - T: "med punktum" # (en: 'with period', google translation) - "⒑": [T: "ti med punktum"] # 0x2491 (en: 'ten with period', google translation) - "⒒": [T: "elleve med punktum"] # 0x2492 (en: 'eleven with period', google translation) @@ -1436,22 +1482,22 @@ - "⒛": [T: "tjue med punktum"] # 0x249b (en: 'twenty with period', google translation) - "⒜-⒵": # 0x249c - 0x24b5 # SWEDISH: switched order - - spell: "translate('.', '⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵', 'abcdefghijklmnopqrstuvwxyz')" - T: "i parentes" # (en: 'parenthesized', google translation) - - "Ⓐ-Ⓩ": + - "Ⓐ-Ⓩ": # 0x24b6 - 0x24cf # SWEDISH: switched order - - spell: "translate('.', 'ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏ', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', 'ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏ', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - T: "i sirkel" # (en: 'circled', google translation) - "🅐-🅩": # 0x1f150 - 0x1f169 # switched order - - spell: "translate('.', '🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - T: "i fylt sirkel" # (en: 'black circled', google translation) - "ⓐ-ⓩ": # 0x24d0 - 0x24e9 # SWEDISH: switched order - - spell: "translate('.', 'ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', 'ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ', 'abcdefghijklmnopqrstuvwxyz')" - T: "i sirkel" # (en: 'circled', google translation) - "⓪": [T: "null i sirkel"] # 0x24ea (google translation) - "⓫": [T: "elleve i fylt sirkel"] # 0x24eb (en: 'black circled eleven', google translation) @@ -1466,7 +1512,7 @@ - "⓴": [T: "tjue i fylt sirkel"] # 0x24f4 (en: 'black circled twenty', google translation) - "⓵-⓽": # 0x24f5 - 0x24fe # SWEDISH: switched order - - spell: "translate('.', '⓵⓶⓷⓸⓹⓺⓻⓼⓽', '123456789')" + - SPELL: "translate('.', '⓵⓶⓷⓸⓹⓺⓻⓼⓽', '123456789')" - T: "i dobbel sirkel" # (en: 'double circled', google translation) - "⓾": [T: "ti i dobbel sirkel"] # 0x24fe (en: 'double circled ten', google translation) - "⓿": [T: "null i fylt sirkel"] # 0x24ff (en: 'black circled zero', google translation) @@ -1570,7 +1616,28 @@ - "◿": [T: "trekant ned til høyre"] # 0x25ff (en: 'lower right triangle') #------------------------------------------------------------------------------------------------ #Miscellaneous symbols OK - + - "★": [T: "svart stjerne"] # 0x2605 + - "☆": [T: "hvit stjerne"] # 0x2606 + - "☉": [T: "sol"] # 0x2609 + - "☌": [T: "konjunksjon"] # 0x260c + - "☒": [T: "avkrysningsboks med kryss"] # 0x2612 + - "☽": [T: "tiltagende måne"] # 0x263d + - "☾": [T: "avtagende måne"] # 0x263e + - "☿": [T: "merkur"] # 0x263f + - "♀": [T: "kvinne"] # 0x2640 + - "♁": [T: "jorda"] # 0x2641 + - "♂": [T: "mann"] # 0x2642 + - "♃": [T: "jupiter"] # 0x2643 + - "♄": [T: "saturn"] # 0x2644 + - "♅": [T: "uranus"] # 0x2645 + - "♆": [T: "neptun"] # 0x2646 + - "♇": [T: "pluto"] # 0x2647 + - "♈": [T: "væren"] # 0x2648 + - "♉": [T: "tyren"] # 0x2649 + - "♩": [T: "fjerdedelsnote"] # 0x2669 + - "♭": [T: "musikalsk b"] # 0x266d + - "♮": [T: "musikalsk oppløsningstegn"] # 0x266e + - "♯": [T: "musikalsk kryss"] # 0x266f - "♠": [T: "svart spar"] # 0x2660 (en: 'black spade suit', google: 'svart spade kostym') - "♡": [T: "hvit hjerter"] # 0x2661 (en: 'white heart suit', google: 'vit hjärtdräkt') - "♢": [T: "hvit ruter"] # 0x2662 (en: 'white diamond suit', google: 'vit diamantdräkt') @@ -1579,8 +1646,27 @@ - "♥": [T: "svart hjerter"] # 0x2665 (en: 'black heart suit', google: 'black heart suit') - "♦": [T: "svart ruter"] # 0x2666 (en: 'black diamond suit', google: 'svart diamantdräkt') - "♧": [T: "hvit kløver"] # 0x2667 (en: 'white club suit', google: 'vit klubbdräkt') + - "⚀": [T: "terningkast 1"] # 0x2680 + - "⚁": [T: "terningkast 2"] # 0x2681 + - "⚂": [T: "terningkast 3"] # 0x2682 + - "⚃": [T: "terningkast 4"] # 0x2683 + - "⚄": [T: "terningkast 5"] # 0x2684 + - "⚅": [T: "terningkast 6"] # 0x2685 + - "⚆": [T: "hvit sirkel med prikk til høyre"] # 0x2686 + - "⚇": [T: "hvit sirkel med to prikker"] # 0x2687 + - "⚈": [T: "svart sirkel med prikk til høyre"] # 0x2688 + - "⚉": [T: "svart sirkel med to prikker"] # 0x2689 + - "⚪": [T: "mellomstor hvit sirkel"] # 0x26aa + - "⚫": [T: "mellomstor svart sirkel"] # 0x26ab + - "⚬": [T: "middels liten hvit sirkel"] # 0x26ac + - "⚲": [T: "nøytral"] # 0x26b2 + #------------------------------------------------------------------------------------------------ #Dingbats OK + - "✓": [T: "avkrysningshake"] # 0x2713 + - "✠": [T: "malteserkors"] # 0x2720 + - "✪": [T: "sirkel med hvit stjerne"] # 0x272a + - "✶": [T: "svart heksagram"] # 0x2736 - "❨": [T: "venstreparentes"] # 0x2768 (en: 'medium left parentheses ornament', google: 'medium vänster-parentesesprydnad') - "❩": [T: "høyreparentes"] # 0x2769 (en: 'medium right parentheses ornament', google: 'medium höger parentesetheses ornament') - "❪": [T: "avflatet venstreparentes"] # 0x276a (en: 'medium flattened left parentheses ornament', google: 'medium plattad vänster parentese -prydnad') @@ -2057,7 +2143,11 @@ - "⨬": [T: "minus med stigende prikker"] # 0x2a2c (en: 'minus sign with rising dots', google: 'minus tecken med stigande prickar') - "⨭": [T: "pluss i venstre halvsirkel"] # 0x2a2d (en: 'plus sign in left half circle', MathPlayer: 'plustecken i vänster halvcirkel', google: 'plus logga in vänster halva cirkeln') - "⨮": [T: "pluss i høyre halvsirkel"] # 0x2a2e (en: 'plus sign in right half circle', MathPlayer: 'plustecken i höger halvcirkel', google: 'plus logga in höger halv cirkel') - - "⨯": [T: "kryssprodukt"] # 0x2a2f (en: 'cross product') + - "⨯": # 0x2a2f + - test: + if: "$Verbosity='Terse'" + then: [T: "kryss"] + else: [T: "kryssprodukt"] - "⨰": [T: "multiplikasjon med prikk over"] # 0x2a30 (en: 'multiplication sign with dot above') - "⨱": [T: "multiplikasjon med strek under"] # 0x2a31 (en: 'multiplication sign with underbar') - "⨲": [T: "semi-direkte produkt med lukket bunn"] # 0x2a32 (en: 'semidirect product with bottom closed', google: 'semidirect -produkt med botten stängd') @@ -2072,6 +2162,7 @@ - "⨻": [T: "multiplikasjon i trekant"] # 0x2a3b (en: 'multiplication sign in triangle') - "⨼": [T: "interior product"] # 0x2a3c (en: 'interior product', MathPlayer: 'interior product', google: 'interiörprodukt') - "⨽": [T: "invers interior product"] # 0x2a3d (en: 'righthand interior product', google: 'högra interiörprodukt') + - "⨾": [T: "relasjonssammensetning z-notasjon"] # 0x2a3e - "⨿": [T: "koprodukt"] # 0x2a3f (en: 'amalgamation or coproduct', MathPlayer: 'amalgamation or coproduct', google: 'amalgamation eller coprodukt') - "⩀": [T: "snitt med prikk"] # 0x2a40 (en: 'intersection with dot') - "⩁": [T: "union med minus"] # 0x2a41 (en: 'union with minus sign', google: 'union med minus tecken') @@ -3027,7 +3118,7 @@ - "ⅈ": [T: "i"] # 0x2148 - "": [T: ""] # 0xed13 (en: 'j', google translation) - "ⅅ": - - spell: "translate('.', 'ⅅ', 'DD')" # 0xed16, 0x2145 + - SPELL: "translate('.', 'ⅅ', 'DD')" # 0xed16, 0x2145 # The private use chars are from MathType - "": [T: "kurveintegral-loop mot klokka"] # 0xee00 (en: 'anticlockwise contour integral loop', google translation) @@ -3096,57 +3187,57 @@ # Some of these are reserved because they were used in Plane 0 -- that shouldn't be an issue other than causing the other chars to not display - "𝔄-𝔜": # 0x1d504 - 0x1d51d ('z' version is reserved) - T: "fraktur" # (google translation) - - spell: "translate('.', '𝔄𝔅𝔆𝔇𝔈𝔉𝔊𝔋𝔌𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔𝔕𝔖𝔗𝔘𝔙𝔚𝔛𝔜', 'ABCDEFGHIJKLMNOPQRSTUVWXY')" + - SPELL: "translate('.', '𝔄𝔅𝔆𝔇𝔈𝔉𝔊𝔋𝔌𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔𝔕𝔖𝔗𝔘𝔙𝔚𝔛𝔜', 'ABCDEFGHIJKLMNOPQRSTUVWXY')" - "-": # 0xf000 - 0xf018 - T: "fraktur" # (google translation) - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXY')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXY')" - "𝔞-𝔷": # 0x1d51e - 0x1d537 - T: "fraktur" # (google translation) - - spell: "translate('.', '𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf01a - 0xf033 - T: "fraktur" # (google translation) - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝕬-𝖅": # 0x1D56C - 0x1D585 - T: "fraktur fet" # (google translation) - - spell: "translate('.', '𝕬𝕭𝕮𝕯𝕰𝕱𝕲𝕳𝕴𝕵𝕶𝕷𝕸𝕹𝕺𝕻𝕼𝕽𝕾𝕿𝖀𝖁𝖂𝖃𝖄𝖅', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝕬𝕭𝕮𝕯𝕰𝕱𝕲𝕳𝕴𝕵𝕶𝕷𝕸𝕹𝕺𝕻𝕼𝕽𝕾𝕿𝖀𝖁𝖂𝖃𝖄𝖅', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf040 - 0xf059 - T: "fraktur fet" # (google translation) - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝖆-𝖟": # 0x1d586 - 0x1d59f - T: "fraktur fet" # (google translation) - - spell: "translate('.', '𝖆𝖇𝖈𝖉𝖊𝖋𝖌𝖍𝖎𝖏𝖐𝖑𝖒𝖓𝖔𝖕𝖖𝖗𝖘𝖙𝖚𝖛𝖜𝖝𝖞𝖟', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝖆𝖇𝖈𝖉𝖊𝖋𝖌𝖍𝖎𝖏𝖐𝖑𝖒𝖓𝖔𝖕𝖖𝖗𝖘𝖙𝖚𝖛𝖜𝖝𝖞𝖟', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf05a - 0xf073 - T: "fraktur fet" # (google translation) - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" # double struck (blackboard bold) chars in math alphabetic block and also MathType private use area # Some of these are reserved because they were used in Plane 0 -- that shouldn't be an issue other than causing the other chars to not display - "𝔸-𝕐": # 0x1d504 - 0x1d51d ('z' version is reserved) - T: "dobbeltstreket" # (en: 'double struck', google translation) - - spell: "translate('.', '𝔸𝔹𝔺𝔻𝔼𝔽𝔾𝔿𝕀𝕁𝕂𝕃𝕄𝕅𝕆𝕇𝕈𝕉𝕊𝕋𝕌𝕍𝕎𝕏𝕐', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝔸𝔹𝔺𝔻𝔼𝔽𝔾𝔿𝕀𝕁𝕂𝕃𝕄𝕅𝕆𝕇𝕈𝕉𝕊𝕋𝕌𝕍𝕎𝕏𝕐', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf080 - 0xf098 - T: "dobbeltstreket" # (en: 'double struck', google translation) - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝕒-𝕫": # 0x1d552 - 0x1d56b - T: "dobbeltstreket" # (en: 'double struck', google translation) - - spell: "translate('.', '𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf09a - 0xf0b3 - T: "dobbeltstreket" # (en: 'double struck', google translation) - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝟘-𝟡": # 0x1d7d8 - 0x1d7e1 - T: "dobbeltstreket" # (en: 'double struck', google translation) - - spell: "translate('.', '𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡', '0123456789')" + - SPELL: "translate('.', '𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡', '0123456789')" - "-": # 0xf0c0 - 0xf0c9 - T: "dobbeltstreket" # (en: 'double struck', google translation) - - spell: "translate('.', '', '0123456789')" + - SPELL: "translate('.', '', '0123456789')" - "": [T: "dobbeltstreket nabla"] # 0xf0ca (en: 'double struck nabla', google translation) - "": [T: "dobbeltstreket eulerkonstant"] # 0xf0cb (en: 'double struck euler constant', google translation) @@ -3156,39 +3247,39 @@ # NORWEGIAN: Used "script font" - "𝒜-𝒵": # 0x1d49c - 0x1d4b5 - T: "script font" # (en: 'script', google translation) - - spell: "translate('.', '𝒜𝒝𝒞𝒟𝒠𝒡𝒢𝒣𝒤𝒥𝒦𝒧𝒨𝒩𝒪𝒫𝒬𝒭𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝒜𝒝𝒞𝒟𝒠𝒡𝒢𝒣𝒤𝒥𝒦𝒧𝒨𝒩𝒪𝒫𝒬𝒭𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf100 - 0xf119 - T: "script font" # (en: 'script', google translation) - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝒶-𝓏": # 0x1d4b6 - 0x1d4cf - T: "script font" # (en: 'script', google translation) - - spell: "translate('.', '𝒶𝒷𝒸𝒹𝒺𝒻𝒼𝒽𝒾𝒿𝓀𝓁𝓂𝓃𝓄𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝒶𝒷𝒸𝒹𝒺𝒻𝒼𝒽𝒾𝒿𝓀𝓁𝓂𝓃𝓄𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf11a - 0xf133 - T: "script font" # (en: 'script', google translation) - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" # bold script chars in math alphabetic block and also MathType private use area - "𝓐-𝓩": # 0x1d4d0 - 0x1d4e9 - T: "script font fet" # (en: 'script bold', google translation) - - spell: "translate('.', '𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf140 - 0xf159 - T: "script font fet" # (en: 'script bold', google translation) - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝓪-𝔃": # 0x1d4ea - 0x1d503 - T: "script font fet" # (en: 'script bold', google translation) - - spell: "translate('.', '𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf15a - 0xf173 - T: "script font fet" # (en: 'script bold', google translation) - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf180 - 0xf199 - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "": # 0xf19a - test: @@ -3248,124 +3339,124 @@ # MathType only has a few of the cap Greek letters in PUA - "": # 0xf201 - 0xf209 - T: "dobbeltstreket" # (en: 'double struck', google translation) - - spell: "translate('.', '', 'ΔΨΛΠΣΘΓΩΥ')" + - SPELL: "translate('.', '', 'ΔΨΛΠΣΘΓΩΥ')" - "-": # 0xf220 - 0xf236 - T: "dobbeltstreket" # (en: 'double struck', google translation) - - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "": [T: "dobbeltstreket sluttsigma"] # 0xf237 (en: 'double struck final sigma', google translation) - "": [T: "dobbeltstreket rho"] # 0xf250 (en: 'double struck rho', google translation) - "": [T: "dobbeltstreket fi"] # 0xf251 (en: 'double struck phi', google translation) - "𝐀-𝐙": # 0x1d400 - 0x1d419 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf260 - 0xf279 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝐚-𝐳": # 0x1d41a - 0x1d433 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf27a - 0xf293 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝐴-𝑍": # 0x1d434 - 0x1d44d - - spell: "translate('.', '𝐴𝐵𝐶𝐷𝐸𝐹𝐺𝐻𝐼𝐽𝐾𝐿𝑀𝑁𝑂𝑃𝑄𝑅𝑆𝑇𝑈𝑉𝑊𝑋𝑌𝑍', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝐴𝐵𝐶𝐷𝐸𝐹𝐺𝐻𝐼𝐽𝐾𝐿𝑀𝑁𝑂𝑃𝑄𝑅𝑆𝑇𝑈𝑉𝑊𝑋𝑌𝑍', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf294 - 0xf2ad - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝑎-𝑧": # 0x1d44e - 0x1d467 - - spell: "translate('.', '𝑎𝑏𝑐𝑑𝑒𝑓𝑔𝑕𝑖𝑗𝑘𝑙𝑚𝑛𝑜𝑝𝑞𝑟𝑠𝑡𝑢𝑣𝑤𝑥𝑦𝑧', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝑎𝑏𝑐𝑑𝑒𝑓𝑔𝑕𝑖𝑗𝑘𝑙𝑚𝑛𝑜𝑝𝑞𝑟𝑠𝑡𝑢𝑣𝑤𝑥𝑦𝑧', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf2ae - 0xf2c7 - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝑨-𝒁": # 0x1d468 - 0x1d481 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf2c8 - 0xf2e1 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝒂-𝒛": # 0x1d482 - 0x1d49b - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf2e2 - 0xf2fb - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝖠-𝖹": # 0x1d5a0 - 0x1d5b9 - - spell: "translate('.', '𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf300 - 0xf319 - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝖺-𝗓": # 0x1d5ba - 0x1d5d3 - - spell: "translate('.', '𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf31a - 0xf333 - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝗔-𝗭": # 0x1d5d4 - 0x1d5ed - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf334 - 0xf34d - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝗮-𝘇": # 0x1d5ee - 0x1d607 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf34e - 0xf367 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝘈-𝘡": # 0x1d608 - 0x1d621 - - spell: "translate('.', '𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf368 - 0xf381 - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝘢-𝘻": # 0x1d622 - 0x1d63b - - spell: "translate('.', '𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf382 - 0xf39b - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝘼-𝙕": # 0x1d63c - 0x1d655 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf39c - 0xf3b5 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝙖-𝙯": # 0x1d656 - 0x1d66f - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf3b6 - 0xf3cf - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝙰-𝚉": # 0x1d670 - 0x1d689 - - spell: "translate('.', '𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf3d0 - 0xf3e9 - - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" + - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝚊-𝚣": # 0x1d68a - 0x1d6a3 - - spell: "translate('.', '𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf3ea - 0xf403 - - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" + - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "": [T: "i uten prikk"] # 0xf404 (google translation) - "𝚤": [T: "kursiv i uten prikk"] # 0x1d6a4 (en: 'dotless i', google: 'dotless i') @@ -3373,128 +3464,128 @@ - "𝚨-𝛀": # 0x1d6a8 - 0x1d6c0 - T: "fet" # (en: 'bold', google: 'djärv') - - spell: "translate('.', '𝚨𝚩𝚪𝚫𝚬𝚭𝚮𝚯𝚰𝚱𝚲𝚳𝚴𝚵𝚶𝚷𝚸𝚹𝚺𝚻𝚼𝚽𝚾𝚿𝛀', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '𝚨𝚩𝚪𝚫𝚬𝚭𝚮𝚯𝚰𝚱𝚲𝚳𝚴𝚵𝚶𝚷𝚸𝚹𝚺𝚻𝚼𝚽𝚾𝚿𝛀', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "-": # 0xf408 - 0xf420 - T: "fet" # (en: 'bold', google: 'djärv') - - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "𝛂-𝛚": # 0x1d6c2 - 0x1d6da - T: "fet" # (en: 'bold', google: 'djärv') - - spell: "translate('.', '𝛂𝛃𝛄𝛅𝛆𝛇𝛈𝛉𝛊𝛋𝛌𝛍𝛎𝛏𝛐𝛑𝛒𝛓𝛔𝛕𝛖𝛗𝛘𝛙𝛚', 'αβγδεζηθικλμνξοπρςστυφχψω')" + - SPELL: "translate('.', '𝛂𝛃𝛄𝛅𝛆𝛇𝛈𝛉𝛊𝛋𝛌𝛍𝛎𝛏𝛐𝛑𝛒𝛓𝛔𝛕𝛖𝛗𝛘𝛙𝛚', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "-": # 0xf422 - 0xf43a - T: "fet" # (en: 'bold', google: 'djärv') - - spell: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" + - SPELL: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "": [T: "fet nabla"] # 0xf421 (en: 'bold nabla', google translation) - "𝛁": [T: "fet nabla"] # 0x1d6c1 (en: 'bold nabla', google translation) - "𝛛𝛜𝛝𝛞𝛟𝛠𝛡": # 0x1D6DB - 0x1D6E1 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝛛𝛜𝛝𝛞𝛟𝛠𝛡', '∂εθκφρπ')" + - SPELL: "translate('.', '𝛛𝛜𝛝𝛞𝛟𝛠𝛡', '∂εθκφρπ')" - "": # 0xF43C - 0xF441 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', '∂εθκφρπ')" + - SPELL: "translate('.', '', '∂εθκφρπ')" - "𝛢-𝛺": # 0x1d6e2 - 0x1d6fa - - spell: "translate('.', '𝛢𝛣𝛤𝛥𝛦𝛧𝛨𝛩𝛪𝛫𝛬𝛭𝛮𝛯𝛰𝛱𝛲𝛳𝛴𝛵𝛶𝛷𝛸𝛹𝛺', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '𝛢𝛣𝛤𝛥𝛦𝛧𝛨𝛩𝛪𝛫𝛬𝛭𝛮𝛯𝛰𝛱𝛲𝛳𝛴𝛵𝛶𝛷𝛸𝛹𝛺', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "-": # 0xf442 - 0xf45a - - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "𝛼-𝜔": # 0x1d6fc - 0x1d714 - - spell: "translate('.', '𝛼𝛽𝛾𝛿𝜀𝜁𝜂𝜃𝜄𝜅𝜆𝜇𝜈𝜉𝜊𝜋𝜌𝜍𝜎𝜏𝜐𝜑𝜒𝜓𝜔', 'αβγδεζηθικλμνξοπρςστυφχψω')" + - SPELL: "translate('.', '𝛼𝛽𝛾𝛿𝜀𝜁𝜂𝜃𝜄𝜅𝜆𝜇𝜈𝜉𝜊𝜋𝜌𝜍𝜎𝜏𝜐𝜑𝜒𝜓𝜔', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "-": # 0xf45c - 0xf474 - - spell: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" + - SPELL: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "": [T: "kursiv nabla"] # 0xf45b (en: 'italic nabla', google translation) - "𝛻": [T: "kursiv nabla"] # 0x1d6fb (en: 'italic nabla', google translation) - "𝜕𝜖𝜗𝜘𝜙𝜚𝜛": # 0x1d715 - 0x1d71b - - spell: "translate('.', '𝜕𝜖𝜗𝜘𝜙𝜚𝜛', '∂εθκφρπ')" + - SPELL: "translate('.', '𝜕𝜖𝜗𝜘𝜙𝜚𝜛', '∂εθκφρπ')" - "": # 0xf475 - 0xf47b - - spell: "translate('.', '', '∂εθκφρπ')" + - SPELL: "translate('.', '', '∂εθκφρπ')" - "𝜜-𝜴": # 0x1d71c - 0x1d734 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝜜𝜝𝜞𝜟𝜠𝜡𝜢𝜣𝜤𝜥𝜦𝜧𝜨𝜩𝜪𝜫𝜬𝜭𝜮𝜯𝜰𝜱𝜲𝜳𝜴', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '𝜜𝜝𝜞𝜟𝜠𝜡𝜢𝜣𝜤𝜥𝜦𝜧𝜨𝜩𝜪𝜫𝜬𝜭𝜮𝜯𝜰𝜱𝜲𝜳𝜴', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "-": # 0xf47c - 0xf494 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "𝜶-𝝎": # 0x1d736 - 0x1d74e - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝜶𝜷𝜸𝜹𝜺𝜻𝜼𝜽𝜾𝜿𝝀𝝁𝝂𝝃𝝄𝝅𝝆𝝇𝝈𝝉𝝊𝝋𝝌𝝍𝝎', 'αβγδεζηθικλμνξοπρςστυφχψω')" + - SPELL: "translate('.', '𝜶𝜷𝜸𝜹𝜺𝜻𝜼𝜽𝜾𝜿𝝀𝝁𝝂𝝃𝝄𝝅𝝆𝝇𝝈𝝉𝝊𝝋𝝌𝝍𝝎', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "-": # 0xf496 - 0xf4ae - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" + - SPELL: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "𝝏𝝐𝝑𝝒𝝓𝝔𝝕": # 0x1d74f - 0x1d755 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝝏𝝐𝝑𝝒𝝓𝝔𝝕', '∂εθκφρπ')" + - SPELL: "translate('.', '𝝏𝝐𝝑𝝒𝝓𝝔𝝕', '∂εθκφρπ')" - "": # 0xf422 - 0xf43a - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', '∂εθκφρπ')" + - SPELL: "translate('.', '', '∂εθκφρπ')" - "𝜵": [T: "fet kursiv nabla"] # 0x1d735 (en: 'bold italic nabla', google translation) - "": [T: "fet kursiv nabla"] # 0xf495 (en: 'bold italic nabla', google translation) - "𝝖-𝝮": # 0x1d756 - 0x1d76e - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝝖𝝗𝝘𝝙𝝚𝝛𝝜𝝝𝝞𝝟𝝠𝝡𝝢𝝣𝝤𝝥𝝦𝝧𝝨𝝩𝝪𝝫𝝬𝝭𝝮', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '𝝖𝝗𝝘𝝙𝝚𝝛𝝜𝝝𝝞𝝟𝝠𝝡𝝢𝝣𝝤𝝥𝝦𝝧𝝨𝝩𝝪𝝫𝝬𝝭𝝮', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "-": # 0xf4b6 - 0xf4ce - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "𝝰-𝞈": # 0x1d770 - 0x1d788 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝝰𝝱𝝲𝝳𝝴𝝵𝝶𝝷𝝸𝝹𝝺𝝻𝝼𝝽𝝾𝝿𝞀𝞁𝞂𝞃𝞄𝞅𝞆𝞇𝞈', 'αβγδεζηθικλμνξοπρςστυφχψω')" + - SPELL: "translate('.', '𝝰𝝱𝝲𝝳𝝴𝝵𝝶𝝷𝝸𝝹𝝺𝝻𝝼𝝽𝝾𝝿𝞀𝞁𝞂𝞃𝞄𝞅𝞆𝞇𝞈', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "-": # 0xf4d0 - 0xf4e8 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" + - SPELL: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "𝞉𝞊𝞋𝞌𝞍𝞎𝞏": # 0x1d789 - 0x1d78f - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝞉𝞊𝞋𝞌𝞍𝞎𝞏', '∂εθκφρπ')" + - SPELL: "translate('.', '𝞉𝞊𝞋𝞌𝞍𝞎𝞏', '∂εθκφρπ')" - "": # 0xf4e9 - 0xf4ef - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', '∂εθκφρπ')" + - SPELL: "translate('.', '', '∂εθκφρπ')" - "": [T: "fet nabla"] # 0xf4cf (en: 'bold nabla', google translation) - "𝝯": [T: "fet nabla"] # 0x1d76f (en: 'bold nabla', google translation) - "𝞐-𝞨": # 0x1d790 - 0x1d7a8 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝞐𝞑𝞒𝞓𝞔𝞕𝞖𝞗𝞘𝞙𝞚𝞛𝞜𝞝𝞞𝞟𝞠𝞡𝞢𝞣𝞤𝞥𝞦𝞧𝞨', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '𝞐𝞑𝞒𝞓𝞔𝞕𝞖𝞗𝞘𝞙𝞚𝞛𝞜𝞝𝞞𝞟𝞠𝞡𝞢𝞣𝞤𝞥𝞦𝞧𝞨', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "-": # 0xf4f0 - 0xf508 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" + - SPELL: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "𝞪-𝟂": # 0x1d7aa - 0x1d7c2 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝞪𝞫𝞬𝞭𝞮𝞯𝞰𝞱𝞲𝞳𝞴𝞵𝞶𝞷𝞸𝞹𝞺𝞻𝞼𝞽𝞾𝞿𝟀𝟁𝟂', 'αβγδεζηθικλμνξοπρςστυφχψω')" + - SPELL: "translate('.', '𝞪𝞫𝞬𝞭𝞮𝞯𝞰𝞱𝞲𝞳𝞴𝞵𝞶𝞷𝞸𝞹𝞺𝞻𝞼𝞽𝞾𝞿𝟀𝟁𝟂', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "-": # 0xf50a - 0xf522 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" + - SPELL: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "𝟃𝟄𝟅𝟆𝟇𝟈𝟉": # 0x1d7c3 - 0x1d7c9 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '𝟃𝟄𝟅𝟆𝟇𝟈𝟉', '∂εθκφρπ')" + - SPELL: "translate('.', '𝟃𝟄𝟅𝟆𝟇𝟈𝟉', '∂εθκφρπ')" - "": # 0xf523 - 0xf529 - T: "fet" # (en: 'bold', google translation) - - spell: "translate('.', '', '∂εθκφρπ')" + - SPELL: "translate('.', '', '∂εθκφρπ')" - "": [T: "fet nabla"] # 0xf509 (en: 'bold nabla', google translation) - "𝞩": [T: "fet nabla"] # 0x1d7a9 (en: 'bold nabla', google translation) @@ -3619,6 +3710,7 @@ - "ffl": [T: "f f l"] # 0xfb04 (en: 'ffl', google: 'ffl') - "ſt": [T: "f t"] # 0xfb05 (en: 'ft', google translation) - "st": [T: "s t"] # 0xfb06 (google translation) + - "﬩": [T: "hebraisk bokstav alternativ pluss"] # 0xfb29 #------------------------------------------------------------------------------------------------------------------ # Combining half marks - "︠": [T: "ligatur venstre halvdel"] # 0xfe20 (en: 'ligature left half embellishment', google translation) @@ -3681,3 +3773,25 @@ #Specials - "": [T: "ukjent eller savnet objekt"] # 0xfffc (en: 'unknown or missing object', google translation) - "�": [T: "ukjent eller savnet tegn"] # 0xfffd (google: 'okänd eller saknad karaktär') + + - "🣑": [T: "er i likevekt med"] # 0x1F8D1 + - "🣒": [T: "er i likevekt, forskjøvet mot høyre, med"] # 0x1F8D2 + - "🣓": [T: "er i likevekt, forskjøvet mot venstre, med"] # 0x1F8D3 + +# MathJax v4 has adopted these PUA values for some partial chem bonds that aren't in Unicode + - "\uE410": [T: "delvis enkeltbinding"] # 0xe410 + - "\uE411": [T: "delvis dobbeltbinding"] # 0xe411 + - "\uE412": [T: "delvis trippelbinding"] # 0xe412 + +# MathJax v4 also adopted these PUA values for some arrows thar are in Unicode +# Hopefully these will be exported properly in future versions of MathJax + - "\uE428": [SPELL: "'⟵'"] # 0xe428 defer to def of arrow + - "\uE429": [SPELL: "'⟶'"] # 0xe429 defer to def of arrow + - "\uE42A": [SPELL: "'⟷'"] # 0xe42a defer to def of arrow + - "\uE408": [SPELL: "'🣑'"] # 0xe408 defer to def of arrow + - "\uE409": [SPELL: "'🣒'"] # 0xe409 defer to def of arrow + - "\uE40A": [SPELL: "'🣓'"] # 0xe40a defer to def of arrow + - "\uE42B": [SPELL: "'⇄'"] # 0xe42b defer to def of arrow + - "\uE42C": [SPELL: "'←'"] # 0xe42c defer to def of arrow + - "\uE42D": [SPELL: "'→'"] # 0xe42d defer to def of arrow + - "\uE42E": [SPELL: "'⇄'"] # 0xe42e defer to def of arrow \ No newline at end of file From 3cf2e19d7ded7f6b79241b48d8560a8eff11236c Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 22 Apr 2026 06:59:53 +0200 Subject: [PATCH 06/43] Fix two typos --- Rules/Languages/en/unicode-full.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rules/Languages/en/unicode-full.yaml b/Rules/Languages/en/unicode-full.yaml index eb4a6cbe4..c7d7893a1 100644 --- a/Rules/Languages/en/unicode-full.yaml +++ b/Rules/Languages/en/unicode-full.yaml @@ -1403,7 +1403,7 @@ - "⏠": [t: "top tortoise shell bracket"] # 0x23e0 - "⏡": [t: "bottom tortoise shell bracket"] # 0x23e1 - "⏢": [t: "white trapezium"] # 0x23e2 - - "⏣": [t: "benzene right with circle"] # 0x23e3 + - "⏣": [t: "benzene ring with circle"] # 0x23e3 - "⏤": [t: "straightness"] # 0x23e4 - "⏥": [t: "flatness"] # 0x23e5 - "⏦": # 0x23e6 @@ -1617,7 +1617,7 @@ - "⚆": [t: "white circle with dot right"] # 0x2686 - "⚇": [t: "white circle wiht two dots"] # 0x2687 - "⚈": [t: "black circle with dot right"] # 0x2688 - - "⚉": [t: "black circle wiht two dots"] # 0x2689 + - "⚉": [t: "black circle with two dots"] # 0x2689 - "⚪": [t: "medium white circle"] # 0x26aa - "⚫": [t: "medium black circle"] # 0x26ab - "⚬": [t: "medium small white circle"] # 0x26ac From d3f19a77e7100b47c6c901faf7c162054f682521 Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 22 Apr 2026 10:31:20 +0200 Subject: [PATCH 07/43] Update Norwegian Unicode rules for conditional bold and character consistency - Implement logic to make the "fet" (bold) descriptor conditional based on the `$IgnoreBold` variable across multiple alphanumeric blocks. - Consolidate individual digit entries into ranges. - Added test for ignore-bold. --- Rules/Languages/nb/unicode-full.yaml | 321 ++++++++++++++++----------- tests/Languages/nb/shared.rs | 26 ++- 2 files changed, 214 insertions(+), 133 deletions(-) diff --git a/Rules/Languages/nb/unicode-full.yaml b/Rules/Languages/nb/unicode-full.yaml index d65c0ad4c..6737e72a1 100644 --- a/Rules/Languages/nb/unicode-full.yaml +++ b/Rules/Languages/nb/unicode-full.yaml @@ -3164,7 +3164,6 @@ - " ": [T: ""] # 0x205f - "": [T: ""] # 0xef04 - "": [T: ""] # 0xef05 - - " ": [T: ""] # 0x2003 - "": [T: ""] # 0xef06 - "": [T: ""] # 0xef07 - "": [T: ""] # 0xef08 @@ -3200,18 +3199,30 @@ - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝕬-𝖅": # 0x1D56C - 0x1D585 - - T: "fraktur fet" # (google translation) + - T: "fraktur" # (google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝕬𝕭𝕮𝕯𝕰𝕱𝕲𝕳𝕴𝕵𝕶𝕷𝕸𝕹𝕺𝕻𝕼𝕽𝕾𝕿𝖀𝖁𝖂𝖃𝖄𝖅', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf040 - 0xf059 - - T: "fraktur fet" # (google translation) + - T: "fraktur" # (google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝖆-𝖟": # 0x1d586 - 0x1d59f - - T: "fraktur fet" # (google translation) + - T: "fraktur" # (google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝖆𝖇𝖈𝖉𝖊𝖋𝖌𝖍𝖎𝖏𝖐𝖑𝖒𝖓𝖔𝖕𝖖𝖗𝖘𝖙𝖚𝖛𝖜𝖝𝖞𝖟', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf05a - 0xf073 - - T: "fraktur fet" # (google translation) + - T: "fraktur" # (google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" # double struck (blackboard bold) chars in math alphabetic block and also MathType private use area @@ -3263,19 +3274,31 @@ # bold script chars in math alphabetic block and also MathType private use area - "𝓐-𝓩": # 0x1d4d0 - 0x1d4e9 - - T: "script font fet" # (en: 'script bold', google translation) + - T: "script font" # (en: 'script bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf140 - 0xf159 - - T: "script font fet" # (en: 'script bold', google translation) + - T: "script font" # (en: 'script bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝓪-𝔃": # 0x1d4ea - 0x1d503 - - T: "script font fet" # (en: 'script bold', google translation) + - T: "script font" # (en: 'script bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf15a - 0xf173 - - T: "script font fet" # (en: 'script bold', google translation) + - T: "script font" # (en: 'script bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf180 - 0xf199 @@ -3349,19 +3372,27 @@ - "": [T: "dobbeltstreket rho"] # 0xf250 (en: 'double struck rho', google translation) - "": [T: "dobbeltstreket fi"] # 0xf251 (en: 'double struck phi', google translation) - "𝐀-𝐙": # 0x1d400 - 0x1d419 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf260 - 0xf279 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝐚-𝐳": # 0x1d41a - 0x1d433 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf27a - 0xf293 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝐴-𝑍": # 0x1d434 - 0x1d44d @@ -3377,19 +3408,27 @@ - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝑨-𝒁": # 0x1d468 - 0x1d481 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf2c8 - 0xf2e1 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝒂-𝒛": # 0x1d482 - 0x1d49b - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf2e2 - 0xf2fb - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝖠-𝖹": # 0x1d5a0 - 0x1d5b9 @@ -3405,19 +3444,27 @@ - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝗔-𝗭": # 0x1d5d4 - 0x1d5ed - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf334 - 0xf34d - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝗮-𝘇": # 0x1d5ee - 0x1d607 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf34e - 0xf367 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝘈-𝘡": # 0x1d608 - 0x1d621 - SPELL: "translate('.', '𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" @@ -3431,19 +3478,27 @@ - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝘼-𝙕": # 0x1d63c - 0x1d655 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "-": # 0xf39c - 0xf3b5 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" - "𝙖-𝙯": # 0x1d656 - 0x1d66f - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯', 'abcdefghijklmnopqrstuvwxyz')" - "-": # 0xf3b6 - 0xf3cf - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')" - "𝙰-𝚉": # 0x1d670 - 0x1d689 @@ -3463,30 +3518,42 @@ - "𝚥": [T: "kursiv j uten prikk"] # 0x1d6a5 (en: 'dotless j', google: 'dotless j') - "𝚨-𝛀": # 0x1d6a8 - 0x1d6c0 - - T: "fet" # (en: 'bold', google: 'djärv') + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝚨𝚩𝚪𝚫𝚬𝚭𝚮𝚯𝚰𝚱𝚲𝚳𝚴𝚵𝚶𝚷𝚸𝚹𝚺𝚻𝚼𝚽𝚾𝚿𝛀', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "-": # 0xf408 - 0xf420 - - T: "fet" # (en: 'bold', google: 'djärv') + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "𝛂-𝛚": # 0x1d6c2 - 0x1d6da - - T: "fet" # (en: 'bold', google: 'djärv') + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝛂𝛃𝛄𝛅𝛆𝛇𝛈𝛉𝛊𝛋𝛌𝛍𝛎𝛏𝛐𝛑𝛒𝛓𝛔𝛕𝛖𝛗𝛘𝛙𝛚', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "-": # 0xf422 - 0xf43a - - T: "fet" # (en: 'bold', google: 'djärv') + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "": [T: "fet nabla"] # 0xf421 (en: 'bold nabla', google translation) - "𝛁": [T: "fet nabla"] # 0x1d6c1 (en: 'bold nabla', google translation) - "𝛛𝛜𝛝𝛞𝛟𝛠𝛡": # 0x1D6DB - 0x1D6E1 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝛛𝛜𝛝𝛞𝛟𝛠𝛡', '∂εθκφρπ')" - "": # 0xF43C - 0xF441 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', '∂εθκφρπ')" - "𝛢-𝛺": # 0x1d6e2 - 0x1d6fa @@ -3511,165 +3578,157 @@ - SPELL: "translate('.', '', '∂εθκφρπ')" - "𝜜-𝜴": # 0x1d71c - 0x1d734 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝜜𝜝𝜞𝜟𝜠𝜡𝜢𝜣𝜤𝜥𝜦𝜧𝜨𝜩𝜪𝜫𝜬𝜭𝜮𝜯𝜰𝜱𝜲𝜳𝜴', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "-": # 0xf47c - 0xf494 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "𝜶-𝝎": # 0x1d736 - 0x1d74e - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝜶𝜷𝜸𝜹𝜺𝜻𝜼𝜽𝜾𝜿𝝀𝝁𝝂𝝃𝝄𝝅𝝆𝝇𝝈𝝉𝝊𝝋𝝌𝝍𝝎', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "-": # 0xf496 - 0xf4ae - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "𝝏𝝐𝝑𝝒𝝓𝝔𝝕": # 0x1d74f - 0x1d755 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝝏𝝐𝝑𝝒𝝓𝝔𝝕', '∂εθκφρπ')" - "": # 0xf422 - 0xf43a - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', '∂εθκφρπ')" - "𝜵": [T: "fet kursiv nabla"] # 0x1d735 (en: 'bold italic nabla', google translation) - "": [T: "fet kursiv nabla"] # 0xf495 (en: 'bold italic nabla', google translation) - "𝝖-𝝮": # 0x1d756 - 0x1d76e - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝝖𝝗𝝘𝝙𝝚𝝛𝝜𝝝𝝞𝝟𝝠𝝡𝝢𝝣𝝤𝝥𝝦𝝧𝝨𝝩𝝪𝝫𝝬𝝭𝝮', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "-": # 0xf4b6 - 0xf4ce - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "𝝰-𝞈": # 0x1d770 - 0x1d788 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝝰𝝱𝝲𝝳𝝴𝝵𝝶𝝷𝝸𝝹𝝺𝝻𝝼𝝽𝝾𝝿𝞀𝞁𝞂𝞃𝞄𝞅𝞆𝞇𝞈', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "-": # 0xf4d0 - 0xf4e8 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "𝞉𝞊𝞋𝞌𝞍𝞎𝞏": # 0x1d789 - 0x1d78f - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝞉𝞊𝞋𝞌𝞍𝞎𝞏', '∂εθκφρπ')" - "": # 0xf4e9 - 0xf4ef - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', '∂εθκφρπ')" - "": [T: "fet nabla"] # 0xf4cf (en: 'bold nabla', google translation) - "𝝯": [T: "fet nabla"] # 0x1d76f (en: 'bold nabla', google translation) - "𝞐-𝞨": # 0x1d790 - 0x1d7a8 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝞐𝞑𝞒𝞓𝞔𝞕𝞖𝞗𝞘𝞙𝞚𝞛𝞜𝞝𝞞𝞟𝞠𝞡𝞢𝞣𝞤𝞥𝞦𝞧𝞨', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "-": # 0xf4f0 - 0xf508 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩ')" - "𝞪-𝟂": # 0x1d7aa - 0x1d7c2 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝞪𝞫𝞬𝞭𝞮𝞯𝞰𝞱𝞲𝞳𝞴𝞵𝞶𝞷𝞸𝞹𝞺𝞻𝞼𝞽𝞾𝞿𝟀𝟁𝟂', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "-": # 0xf50a - 0xf522 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')" - "𝟃𝟄𝟅𝟆𝟇𝟈𝟉": # 0x1d7c3 - 0x1d7c9 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '𝟃𝟄𝟅𝟆𝟇𝟈𝟉', '∂εθκφρπ')" - "": # 0xf523 - 0xf529 - - T: "fet" # (en: 'bold', google translation) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] - SPELL: "translate('.', '', '∂εθκφρπ')" - "": [T: "fet nabla"] # 0xf509 (en: 'bold nabla', google translation) - - "𝞩": [T: "fet nabla"] # 0x1d7a9 (en: 'bold nabla', google translation) - - - "": [T: "fet null"] # 0xf52e (en: 'bold zero', google translation) - - "𝟎": [T: "fet null"] # 0x1d7ce (en: 'bold zero', google translation) - - "": [T: "fet én"] # 0xf52f (en: 'bold one', google translation) - - "𝟏": [T: "fet én"] # 0x1d7cf (en: 'bold one', google translation) - - "": [T: "fet to"] # 0xf530 (en: 'bold two', google translation) - - "𝟐": [T: "fet to"] # 0x1d7d0 (en: 'bold two', google translation) - - "": [T: "fet tre"] # 0xf531 (en: 'bold three', google translation) - - "𝟑": [T: "fet tre"] # 0x1d7d1 (en: 'bold three', google translation) - - "": [T: "fet fire"] # 0xf532 (en: 'bold four', google translation) - - "𝟒": [T: "fet fire"] # 0x1d7d2 (en: 'bold four', google translation) - - "": [T: "fet fem"] # 0xf533 (en: 'bold five', google translation) - - "𝟓": [T: "fet fem"] # 0x1d7d3 (en: 'bold five', google translation) - - "": [T: "fet seks"] # 0xf534 (en: 'bold six', google translation) - - "𝟔": [T: "fet seks"] # 0x1d7d4 (en: 'bold six', google translation) - - "": [T: "fet sju"] # 0xf535 (en: 'bold seven', google translation) - - "𝟕": [T: "fet sju"] # 0x1d7d5 (en: 'bold seven', google translation) - - "": [T: "fet åtte"] # 0xf536 (en: 'bold eight', google translation) - - "𝟖": [T: "fet åtte"] # 0x1d7d6 (en: 'bold eight', google translation) - - "": [T: "fet ni"] # 0xf537 (en: 'bold nine', google translation) - - "𝟗": [T: "fet ni"] # 0x1d7d7 (en: 'bold nine', google translation) - - "": [T: "null"] # 0xf542 (en: 'zero', google translation) - - "𝟢": [T: "null"] # 0x1d7e2 (en: 'zero', google translation) - - "": [T: "én"] # 0xf543 (en: 'one', google translation) - - "𝟣": [T: "én"] # 0x1d7e3 (en: 'one', google translation) - - "": [T: "to"] # 0xf544 (en: 'two', google translation) - - "𝟤": [T: "to"] # 0x1d7e4 (en: 'two', google translation) - - "": [T: "tre"] # 0xf545 (en: 'three', google translation) - - "𝟥": [T: "tre"] # 0x1d7e5 (en: 'three', google translation) - - "": [T: "fire"] # 0xf546 (en: 'four', google translation) - - "𝟦": [T: "fire"] # 0x1d7e6 (en: 'four', google translation) - - "": [T: "fem"] # 0xf547 (en: 'five', google translation) - - "𝟧": [T: "fem"] # 0x1d7e7 (en: 'five', google translation) - - "": [T: "seks"] # 0xf548 (en: 'six', google translation) - - "𝟨": [T: "seks"] # 0x1d7e8 (en: 'six', google translation) - - "": [T: "sju"] # 0xf549 (en: 'seven', google translation) - - "𝟩": [T: "sju"] # 0x1d7e9 (en: 'seven', google translation) - - "": [T: "åtte"] # 0xf54a (en: 'eight', google translation) - - "𝟪": [T: "åtte"] # 0x1d7ea (en: 'eight', google translation) - - "": [T: "ni"] # 0xf54b (en: 'nine', google translation) - - "𝟫": [T: "ni"] # 0x1d7eb (en: 'nine', google translation) - - "": [T: "fet null"] # 0xf54c (en: 'bold zero', google translation) - - "𝟬": [T: "fet null"] # 0x1d7ec (en: 'bold zero', google translation) - - "": [T: "fet én"] # 0xf54d (en: 'bold one', google translation) - - "𝟭": [T: "fet én"] # 0x1d7ed (en: 'bold one', google translation) - - "": [T: "fet to"] # 0xf54e (en: 'bold two', google translation) - - "𝟮": [T: "fet to"] # 0x1d7ee (en: 'bold two', google translation) - - "": [T: "fet tre"] # 0xf54f (en: 'bold three', google translation) - - "𝟯": [T: "fet tre"] # 0x1d7ef (en: 'bold three', google translation) - - "": [T: "fet fire"] # 0xf550 (en: 'bold four', google translation) - - "𝟰": [T: "fet fire"] # 0x1d7f0 (en: 'bold four', google translation) - - "": [T: "fet fem"] # 0xf551 (en: 'bold five', google translation) - - "𝟱": [T: "fet fem"] # 0x1d7f1 (en: 'bold five', google translation) - - "": [T: "fet seks"] # 0xf552 (en: 'bold six', google translation) - - "𝟲": [T: "fet seks"] # 0x1d7f2 (en: 'bold six', google translation) - - "": [T: "fet sju"] # 0xf553 (en: 'bold seven', google translation) - - "𝟳": [T: "fet sju"] # 0x1d7f3 (en: 'bold seven', google translation) - - "": [T: "fet åtte"] # 0xf554 (en: 'bold eight', google translation) - - "𝟴": [T: "fet åtte"] # 0x1d7f4 (en: 'bold eight', google translation) - - "": [T: "fet ni"] # 0xf555 (en: 'bold nine', google translation) - - "𝟵": [T: "fet ni"] # 0x1d7f5 (en: 'bold nine', google translation) - - "": [T: "null"] # 0xf556 (en: 'zero', google translation) - - "𝟶": [T: "null"] # 0x1d7f6 (en: 'zero', google translation) - - "": [T: "én"] # 0xf557 (en: 'one', google translation) - - "𝟷": [T: "én"] # 0x1d7f7 (en: 'one', google translation) - - "": [T: "to"] # 0xf558 (en: 'two', google translation) - - "𝟸": [T: "to"] # 0x1d7f8 (en: 'two', google translation) - - "": [T: "tre"] # 0xf559 (en: 'three', google translation) - - "𝟹": [T: "tre"] # 0x1d7f9 (en: 'three', google translation) - - "": [T: "fire"] # 0xf55a (en: 'four', google translation) - - "𝟺": [T: "fire"] # 0x1d7fa (en: 'four', google translation) - - "": [T: "fem"] # 0xf55b (en: 'five', google translation) - - "𝟻": [T: "fem"] # 0x1d7fb (en: 'five', google translation) - - "": [T: "seks"] # 0xf55c (en: 'six', google translation) - - "𝟼": [T: "seks"] # 0x1d7fc (en: 'six', google translation) - - "": [T: "sju"] # 0xf55d (en: 'seven', google translation) - - "𝟽": [T: "sju"] # 0x1d7fd (en: 'seven', google translation) - - "": [T: "åtte"] # 0xf55e (en: 'eight', google translation) - - "𝟾": [T: "åtte"] # 0x1d7fe (en: 'eight', google translation) - - "": [T: "ni"] # 0xf55f (en: 'nine', google translation) - - "𝟿": [T: "ni"] # 0x1d7ff (en: 'nine', google translation) + - "𝞩": [T: "fet nabla"] # 0x1d7a9 (en: 'bold nabla', google translation + + - "-": # 0xf52e - 0xf537 (old MathType) + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] + - SPELL: "translate('.', '', '0123456789')" + + - "𝟎-𝟗": # 0x1d7ce - 0x1d7d7 + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] + - SPELL: "translate('.', '𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗', '0123456789')" + + - "-": # 0xf542 - 0xf54b (old MathType) + - SPELL: "translate('.', '', '0123456789')" + + - "𝟢-𝟫": # 0x1d7e2 - 0x1d7eb (old MathType) + - SPELL: "translate('.', '𝟢𝟣𝟤𝟥𝟦𝟧𝟨𝟩𝟪𝟫', '0123456789')" + + - "-": # 0xf54c - 0xf555 + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] + - SPELL: "translate('.', '', '0123456789')" + + - "𝟬-𝟵": # 0x1d7ec - 0x1d7f5 + - test: + if: "not($IgnoreBold)" + then: [T: "fet"] + - SPELL: "translate('.', '𝟬𝟭𝟮𝟯𝟰𝟱𝟲𝟳𝟴𝟵', '0123456789')" + + - "-": # 0xf556 - 0xf55f (old MathType) + - SPELL: "translate('.', '', '0123456789')" + + - "𝟶-𝟿": # 0x1d7f6 - 0x1d7ff + - SPELL: "translate('.', '𝟶𝟷𝟸𝟹𝟺𝟻𝟼𝟽𝟾𝟿', '0123456789')" + - "": [T: "ukjent tegn"] # 0xf700 (en: 'unknown character', google translation) - "": [T: "nedre høyre og nedre venstre trekanter"] # 0xf726 (en: 'lower right and lower left triangles', google translation) - "": [T: "horisontal ellipse forlenger"] # 0xf72d (en: 'horizontal ellipsis extender', google translation) diff --git a/tests/Languages/nb/shared.rs b/tests/Languages/nb/shared.rs index 35b0e3855..45c9358e2 100644 --- a/tests/Languages/nb/shared.rs +++ b/tests/Languages/nb/shared.rs @@ -149,8 +149,8 @@ fn prime() -> Result<()> { #[test] fn given() -> Result<()> { let expr = "P(A|B)"; - test("nb", "SimpleSpeak", expr, "stor p; startparentes; stor a, gitt stor b; sluttparentes")?; - test("nb", "ClearSpeak", expr, "stor p; startparentes; stor a, gitt stor b; sluttparentes")?; // not good, but follows the spec + test("nb", "SimpleSpeak", expr, "stor p; startparentes; stor a gitt stor b; sluttparentes")?; + test("nb", "ClearSpeak", expr, "stor p; startparentes; stor a gitt stor b; sluttparentes")?; // not good, but follows the spec return Ok(()); } @@ -382,6 +382,28 @@ fn mn_with_space() -> Result<()> { } +#[test] +fn ignore_bold() -> Result<()> { + let expr = r#" + x + = + 2 + + 𝒔𝒊𝒏 + + t + + - + 1 + "#; + test_prefs("nb", "SimpleSpeak", vec![("IgnoreBold", "false")], + expr, "fet x er lik, 2 sinus av fet t, minus 1")?; + test_prefs("nb", "SimpleSpeak", vec![("IgnoreBold", "true")], + expr, "x er lik, 2 sinus av t, minus 1")?; + return Ok(()); + +} + #[test] fn mn_with_block_and_decimal_separators() -> Result<()> { let expr = "1.234,56"; // may want to change this for another language From 42338eed95300b691d6465f82a6fe7659a8997cb Mon Sep 17 00:00:00 2001 From: Marthe Date: Mon, 27 Apr 2026 07:35:42 +0200 Subject: [PATCH 08/43] Update spell to SPELL - Update `spell` to `SPELL` in `general.yaml` - Update test output because of small changes to the rule for vertical line --- Rules/Languages/nb/SharedRules/general.yaml | 2 +- tests/Languages/nb/ClearSpeak/symbols_and_adornments.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Rules/Languages/nb/SharedRules/general.yaml b/Rules/Languages/nb/SharedRules/general.yaml index f5babe078..1eb4ffc71 100644 --- a/Rules/Languages/nb/SharedRules/general.yaml +++ b/Rules/Languages/nb/SharedRules/general.yaml @@ -540,7 +540,7 @@ - if: ".='log'" then: [T: "log"] # phrase(the 'log' function is used in mathematics) - else_if: ".='lg'" - then: [spell: "'lg'"] # phrase(the 'lg' of x) + then: [SPELL: "'lg'"] # phrase(the 'lg' of x) # SWEDISH/NORWEGIAN: We have added the term "lg" for the logarithm with base 10. Also added a verbosity test for long and short form. - else_if: "$Verbosity!='Verbose'" then: [spell: "'ln'"] diff --git a/tests/Languages/nb/ClearSpeak/symbols_and_adornments.rs b/tests/Languages/nb/ClearSpeak/symbols_and_adornments.rs index 5e1dd7964..5c7d9dbcb 100644 --- a/tests/Languages/nb/ClearSpeak/symbols_and_adornments.rs +++ b/tests/Languages/nb/ClearSpeak/symbols_and_adornments.rs @@ -181,7 +181,7 @@ fn vertical_line_divides() -> Result<()> { 3|6 "; test_ClearSpeak("nb", "ClearSpeak_VerticalLine", "Given", expr, - "3, gitt 6")?; + "3 gitt 6")?; return Ok(()); } @@ -201,7 +201,7 @@ fn vertical_line_divides() -> Result<()> { "; test_ClearSpeak_prefs("nb", vec![("ClearSpeak_VerticalLine", "Given"), ("ClearSpeak_ImpliedTimes", "None")] - , expr, "stor p; startparentes; stor a, gitt stor b; sluttparentes")?; + , expr, "stor p; startparentes; stor a gitt stor b; sluttparentes")?; return Ok(()); } From 9f3b8c87e6614131b03b628a6c0d787f13f8bb7e Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 28 Apr 2026 07:29:54 +0200 Subject: [PATCH 09/43] Added the comment audit-ignore --- Rules/Languages/nb/SharedRules/geometry.yaml | 9 ++++++--- Rules/Languages/nb/SharedRules/linear-algebra.yaml | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Rules/Languages/nb/SharedRules/geometry.yaml b/Rules/Languages/nb/SharedRules/geometry.yaml index 85bacf8d2..9792c790a 100644 --- a/Rules/Languages/nb/SharedRules/geometry.yaml +++ b/Rules/Languages/nb/SharedRules/geometry.yaml @@ -1,5 +1,5 @@ --- - +# audit-ignore - name: line-segment tag: line-segment match: "count(*)=2" @@ -15,7 +15,8 @@ - T: "linjestykke" # phrase(the 'line segment' A B) - x: "*[1]" - x: "*[2]" - + +# audit-ignore - name: geometry-ray tag: ray match: "count(*)=2" @@ -32,6 +33,7 @@ - x: "*[1]" - x: "*[2]" +# audit-ignore - name: geometry-arc tag: arc match: "count(*)=2" @@ -40,6 +42,7 @@ - x: "*[1]" - x: "*[2]" +# audit-ignore - name: measure-of-angle tag: measure-of-angle match: "count(*)=3" @@ -54,7 +57,7 @@ - x: "*[2]" - x: "*[3]" -#NORWEGIAN: Added from English, but not testet yet. +# audit-ignore - name: coordinate tag: coordinate match: "." diff --git a/Rules/Languages/nb/SharedRules/linear-algebra.yaml b/Rules/Languages/nb/SharedRules/linear-algebra.yaml index d09d75e2c..405316d91 100644 --- a/Rules/Languages/nb/SharedRules/linear-algebra.yaml +++ b/Rules/Languages/nb/SharedRules/linear-algebra.yaml @@ -1,4 +1,5 @@ --- +# audit-ignore - name: scalar-determinant tag: determinant match: "count(*)=1 and not(*[1][self::m:mtr])" @@ -11,6 +12,7 @@ if: "not(IsNode(*[1], 'simple'))" then: [T: "slutt determinant"] # phrase('end determinant' of a matrix) +# audit-ignore - name: subscripted-norm tag: subscripted-norm match: "count(*)=2" @@ -21,6 +23,7 @@ - T: "til" # phrase(systems 'of' linear equations) - x: "*[1]" +# audit-ignore - name: homomorphism # can't use IntentMappings because this doesn't fit the function pattern tag: homomorphism @@ -39,6 +42,7 @@ then: [pause: short] else: [pause: auto] +# audit-ignore # NORWEGIAN: Removed test for Verbosity - name: kernel # can't use IntentMappings because this doesn't fit the function pattern @@ -56,6 +60,7 @@ then: [pause: short] else: [pause: auto] +# audit-ignore # NORWEGIAN: Kept these rules here, cause we say "dimensjonen til" and "normen til" instead of "dimensjonen av" and "normen av". - name: dimension tag: dimension @@ -65,6 +70,7 @@ - T: "til" # phrase(systems 'of' linear equations) - x: "*[1]" +# audit-ignore - name: norm tag: norm match: "count(*)=1" From 2c045ae8e0f01d79b7284592ace935820527c48f Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 28 Apr 2026 08:18:30 +0200 Subject: [PATCH 10/43] Added the comment audit-ignore --- Rules/Languages/nb/SharedRules/calculus.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Rules/Languages/nb/SharedRules/calculus.yaml b/Rules/Languages/nb/SharedRules/calculus.yaml index d8fab660e..1fc32cecf 100644 --- a/Rules/Languages/nb/SharedRules/calculus.yaml +++ b/Rules/Languages/nb/SharedRules/calculus.yaml @@ -1,5 +1,5 @@ --- - +# audit-ignore - name: divergence tag: divergence match: "count(*) = 1" @@ -13,6 +13,7 @@ then: [pause: short] - x: "*[1]" +# audit-ignore - name: curl tag: curl match: "count(*) = 1" @@ -26,6 +27,7 @@ then: [pause: short] - x: "*[1]" +# audit-ignore - name: gradient tag: gradient match: "count(*) = 1" @@ -35,3 +37,4 @@ if: "not(IsNode(*[1], 'leaf'))" then: [pause: short] - x: "*[1]" + From ae03c412cf30d68872b6b0d2d518e611aed8bb91 Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 28 Apr 2026 10:35:20 +0200 Subject: [PATCH 11/43] Enhance Norwegian speech for currencies, units, and hyperbolic functions - Added the rule "unit-terse" - Added the rule "currency". Added test for neuter currencies. - Added sets for currency symbols. - Re-introduce verbosity-dependent speech for hyperbolic functions with updated terse forms. - Update `spell` to `SPELL`. - Add `audit-ignore` tags to various rules. --- Rules/Languages/nb/SharedRules/general.yaml | 118 ++++++++++++++------ Rules/Languages/nb/definitions.yaml | 16 +++ tests/Languages/nb/units.rs | 35 ++++++ 3 files changed, 132 insertions(+), 37 deletions(-) diff --git a/Rules/Languages/nb/SharedRules/general.yaml b/Rules/Languages/nb/SharedRules/general.yaml index 1eb4ffc71..1f22440be 100644 --- a/Rules/Languages/nb/SharedRules/general.yaml +++ b/Rules/Languages/nb/SharedRules/general.yaml @@ -8,6 +8,7 @@ - T: "punktum" - x: "substring-after(., '.')" +# audit-ignore # number-sets are a little messy in that the base was converted to a number-set, so we have to match that (simple) case last - name: pos-neg-number-sets tag: number-sets @@ -89,6 +90,7 @@ - bookmark: "@id" - T: "den imaginære delen" # phrase('the imaginary part' is part of a complex number) +# audit-ignore # rules on scripted vertical bars ('evaluated at') - name: evaluated-at-2 tag: evaluate @@ -104,6 +106,7 @@ - pause: auto - x: "*[2]" +# audit-ignore - name: evaluated-at-3 tag: evaluate match: "count(*)=3" @@ -123,6 +126,7 @@ - pause: short - x: "*[2]" +# audit-ignore - name: permutation tag: pochhammer match: "count(*)=2" @@ -132,6 +136,7 @@ - T: "elementer av" # phrase(the solution involves several 'permutations of' values) - x: "*[1]" +# audit-ignore # NORWEGIAN: Removed test for verbosity - name: intervals tag: [open-interval, open-closed-interval, closed-interval, closed-open-interval] @@ -162,6 +167,7 @@ # - T: "komma" # phrase(use a 'comma' to divide large numbers or as a decimal point) # - x: "*[2]" +# audit-ignore - name: default-point tag: point match: "count(*)=2" @@ -171,6 +177,7 @@ - T: "komma" # phrase(use a 'comma' to divide large numbers or as a decimal point) - x: "*[2]" +# audit-ignore - name: bigop-both tag: large-op match: "count(*) = 3" @@ -186,7 +193,7 @@ if: "following-sibling::*" then: [T: "av"] # phrase(the square root 'of' 25 equals 5) - +# audit-ignore - name: bigop-under tag: large-op match: "count(*)=2" @@ -199,6 +206,7 @@ if: "following-sibling::*" then: [T: "av"] # phrase(the square root 'of' 25 equals 5) +# audit-ignore - name: largeop tag: mrow match: "count(*)=2 and IsInDefinition(*[1], 'Speech', 'LargeOperators')" @@ -215,8 +223,9 @@ replace: - x: "*[1]" - T: "med repeterende siffer" # phrase('with repeating digits') - - spell: "*[2]" + - SPELL: "*[2]" +# audit-ignore - name: msubsup-skip-super # handles single, double, etc., prime tag: [skip-super, say-super] @@ -247,6 +256,13 @@ else: [T: "hevet"] # phrase(this is a 'super' set of numbers) - x: "*[3]" - pause: short + +- name: unit-terse + tag: unit + match: "$Verbosity = 'Terse' and string-length(.)=1" + replace: + - bookmark: "@id" + - SPELL: "text()" # need to say "ett" for '1' in front of a neuter unit # this is extra complicated because we need to allow do it for a 1 in front of a mixed fraction @@ -379,7 +395,31 @@ then: [x: "concat('\uF8FE', DefinitionValue($Word, 'Speech', 'PluralForms'))"] else: [x: "concat('\uF8FE', $Word)"] +# audit-ignore +# need to reverse the order of speech: $ 3 -> 3 dollars +# Added test for neuter currencies, which use "ett" instead of "en" for the singular form of "one". +- name: currency + tag: mrow + match: "count(*)=3 and DefinitionValue(*[1], 'Speech', 'CurrencySymbols') != ''" + variables: + # If the amount is singular, we don't add the plural ending. + - IsSingular: "*[3][self::m:mn and .=1] and *[2]='\u2062'" + - IsNeuterCurrency: "DefinitionValue(*[1], 'Speech', 'CurrencySymbolsNeuter') != ''" + - CurrencyWord: "DefinitionValue(*[1], 'Speech', 'CurrencySymbols')" + replace: + - bookmark: "*[3]/@id" + - test: + - if: "$IsSingular and $IsNeuterCurrency" + then: [T: "ett"] + else: [x: "*[3]"] + - test: + - if: "$IsSingular" + then: [x: "$CurrencyWord"] + - else_if: "DefinitionValue($CurrencyWord, 'Speech', 'PluralForms') != ''" + then: [x: "DefinitionValue($CurrencyWord, 'Speech', 'PluralForms')"] + else: [x: "$CurrencyWord"] +# audit-ignore - name: sin tag: mi match: ".='sin'" @@ -391,6 +431,7 @@ else: [T: "sinus"] # phrase(the 'sine' of the angle) # SWEDISH/NORWEGIAN: Added short form. +# audit-ignore - name: cos tag: mi match: ".='cos'" @@ -401,6 +442,7 @@ then: [T: "cos"] # phrase('cos' is the abbreviation for cosine) else: [T: "cosinus"] # phrase(find the 'cosine' in a right-angle triangle) +# audit-ignore - name: tan tag: mi match: ".='tan' or .='tg'" @@ -411,6 +453,7 @@ then: [T: "tan"] # phrase(the 'tan' is the ratio of the opposite to the adjacent side of a right-angled triangle) else: [T: "tangens"] # phrase(a 'tangent' is a straight line that touches a curve) +# audit-ignore - name: sec tag: mi match: ".='sec'" @@ -421,6 +464,7 @@ then: [T: "sec"] # phrase(to 'seek' a solution) else: [T: "sekans"] # phrase(a 'secant' intersects a curve at two or more points) +# audit-ignore - name: csc tag: mi match: ".='csc'" @@ -431,6 +475,7 @@ then: [T: "cosec"] # phrase(we will 'cosecant' a solution) else: [T: "cosekans"] # phrase(the 'cosecant' is the reciprocal of the secant) +# audit-ignore - name: cot tag: mi match: ".='cot'" @@ -441,72 +486,65 @@ then: [T: "cotan"] # phrase(find the 'cotangent' in a right-angle triangle) else: [T: "cotangens"] # phrase(the 'cotangent' is the reciprocal of the tangent) -# NORWEGIAN: Removed tests for verbosity. We don't say "sin hype" etc., and "sinh" sounds like "sin" - name: sinh tag: mi match: ".='sinh'" replace: - bookmark: "@id" - - T: "sinus hyperbolicus" - #- test: - #if: "$Verbosity='Terse'" - #then: [T: "sin hype"] # phrase(the word 'sinch' is an abbreviation for hyperbolic sine) - #else: [T: "sinus hyperbolicus"] # phrase(the 'hyperbolic sine' is used in mathematics) + - test: + if: "$Verbosity='Terse'" + then: [T: "sin hyperbolicus"] # phrase(the word 'sinch' is an abbreviation for hyperbolic sine) + else: [T: "sinus hyperbolicus"] # phrase(the 'hyperbolic sine' is used in mathematics) - name: cosh tag: mi match: ".='cosh'" replace: - bookmark: "@id" - - T: "cosinus hyperbolicus" - #- test: - #if: "$Verbosity='Terse'" - #then: [T: "cos hype"] # phrase('cosh' is an abbreviation of hyperbolic cosine) - #else: [T: "cosinus hyperbolicus"] # phrase(the 'hyperbolic cosine' is a mathematical function) + - test: + if: "$Verbosity='Terse'" + then: [T: "cos hyperbolicus"] # phrase('cosh' is an abbreviation of hyperbolic cosine) + else: [T: "cosinus hyperbolicus"] # phrase(the 'hyperbolic cosine' is a mathematical function) - name: tanh tag: mi match: ".='tanh'" replace: - bookmark: "@id" - - T: "tangens hyperbolicus" - #- test: - #if: "$Verbosity='Terse'" - #then: [T: "tan hype"] # phrase('tanch' is shorthand for hyperbolic tangent) - #else: [T: "tangens hyperbolicus"] # phrase('hyperbolic tangent' is a mathematical function) + - test: + if: "$Verbosity='Terse'" + then: [T: "tan hyperbolicus"] # phrase('tanch' is shorthand for hyperbolic tangent) + else: [T: "tangens hyperbolicus"] # phrase('hyperbolic tangent' is a mathematical function) - name: sech tag: mi match: ".='sech'" replace: - bookmark: "@id" - - T: "sekans hyperbolicus" - #- test: - #if: "$Verbosity='Terse'" - #then: [T: "sec hype"] # phrase('sheck' is shorthand for hyperbolic secant) - #else: [T: "sekans hyperbolicus"] # phrase('hyperbolic secant' is a mathematical function) + - test: + if: "$Verbosity='Terse'" + then: [T: "sec hyperbolicus"] # phrase('sheck' is shorthand for hyperbolic secant) + else: [T: "sekans hyperbolicus"] # phrase('hyperbolic secant' is a mathematical function) - name: csch tag: mi match: ".='csch'" replace: - bookmark: "@id" - - T: "cosekans hyperbolicus" - #- test: - #if: "$Verbosity='Terse'" - #then: [T: "cosec hype"] # phrase('cosheck' is shorthand for hyperbolic cosecant) - #else: [T: "cosekans hyperbolicus"] # phrase('hyperbolic cosecant' is a mathematical function) + - test: + if: "$Verbosity='Terse'" + then: [T: "cosec hyperbolicus"] # phrase('cosheck' is shorthand for hyperbolic cosecant) + else: [T: "cosekans hyperbolicus"] # phrase('hyperbolic cosecant' is a mathematical function) - name: coth tag: mi match: ".='coth'" replace: - bookmark: "@id" - - T: "cotangens hyperbolicus" - #- test: - #if: "$Verbosity='Terse'" - #then: [T: "cotan hype"] # phrase('cotanch' is shorthand for hyperbolic cotangent) - #else: [T: "cotangens hyperbolicus"] # phrase(the 'hyperbolic cotangent' is a mathematical function) + - test: + if: "$Verbosity='Terse'" + then: [T: "cotan hyperbolicus"] # phrase('cotanch' is shorthand for hyperbolic cotangent) + else: [T: "cotangens hyperbolicus"] # phrase(the 'hyperbolic cotangent' is a mathematical function) # NORWEGIAN: Added this rule from English version - name: exponential @@ -519,6 +557,7 @@ then: [T: "exp"] # phrase('exp' means exponential function) else: [T: "eksponensialfunksjonen"] # phrase('exponential' function) #Norwegian: Spelled wrong for correct pronunciation +# audit-ignore # NORWEGIAN: Added this rule from English version, but removed test for verbosity. - name: covariance tag: mi @@ -527,6 +566,7 @@ - bookmark: "@id" - T: "kovarians" +# consider to change this to be equal to the ClearSpeak rule. - # handle both log and ln name: log tag: mi @@ -543,7 +583,7 @@ then: [SPELL: "'lg'"] # phrase(the 'lg' of x) # SWEDISH/NORWEGIAN: We have added the term "lg" for the logarithm with base 10. Also added a verbosity test for long and short form. - else_if: "$Verbosity!='Verbose'" - then: [spell: "'ln'"] + then: [SPELL: "'ln'"] else: [T: "den naturlige logaritmen"] # phrase(the 'natural log' function is used in mathematics) else: - test: @@ -555,13 +595,14 @@ - else_if: ".='lg'" then_test: - if: "$Verbosity!='Verbose'" - then: [spell: "'lg'"] # phrase(the 'lg' of x) + then: [SPELL: "'lg'"] # phrase(the 'lg' of x) else: [T: "tier-logaritmen"] - else_if: "$Verbosity='Terse'" - then: [spell: "'ln'"] + then: [SPELL: "'ln'"] else: [T: "den naturlige logaritmen"] # phrase(the 'natural log' function is used in mathematics) +# audit-ignore # NORWEGIAN: Changed from Swedish to English version. - name: multi-line # that eliminates the need for the if: else_if: ... @@ -626,6 +667,7 @@ then: [x: "*[position()>1]"] else: [x: "*"] +# audit-ignore # NORWEGIAN: Changed from Swedish to English version. - name: default-multiline tag: mtd @@ -748,6 +790,7 @@ then: [T: "vektor"] # phrase(the 2 column 'vector') else: [T: "matrise"] # phrase(the 2 by 2 'matrix') +# audit-ignore - name: default-column-matrix tag: matrix variables: [IsColumnSilent: true()] @@ -868,6 +911,7 @@ then: [T: "determinant"] # phrase(the 2 by 2 'determinant') else: [T: "matrise"] # phrase(the 2 by 2 'matrix's) +# audit-ignore - name: chemistry-msub tag: [chemical-formula] match: "*[1][.='msub']" @@ -1090,7 +1134,7 @@ match: "." replace: - bookmark: "@id" - - spell: text() + - SPELL: text() - pause: short - name: chemical-state diff --git a/Rules/Languages/nb/definitions.yaml b/Rules/Languages/nb/definitions.yaml index 0b09ed316..6d686df36 100644 --- a/Rules/Languages/nb/definitions.yaml +++ b/Rules/Languages/nb/definitions.yaml @@ -240,6 +240,17 @@ "mph": "mile per hour", "mpg": "mile per gallon", } + +- CurrencySymbols: { + "$": "dollar", "¢": "cent", "€": "euro", "£": "pund", "₡": "colón", "₤": "lira", "₨": "rupi", + "₩": "won", "₪": "ny shekel", "₱": "peso", "₹": "indisk rupi", "₺": "tyrkisk lira", "₿": "bitcoin", "kr": "krone", "NOK": "norsk krone", + # could add more currencies... + } + +# Norwegian: Added this set because we differentiate between masculine and neuter currencies. +- CurrencySymbolsNeuter: { + "£": "pund", + } - PluralForms: { # SWEDISH: this should be complete. Units not listed here are not modified when pluralised. /Tim @@ -305,6 +316,11 @@ "omdreining per minutt": "omdreininger per minutt", "curie": "curier", "annuum": "annua", + "indisk rupi": "indiske rupi", + "tyrkisk lira": "tyrkiske lira", + "bitcoin": "bitcoins", + "krone": "kroner", + "norsk krone": "norske kroner", } diff --git a/tests/Languages/nb/units.rs b/tests/Languages/nb/units.rs index 273abffff..21bde49ac 100644 --- a/tests/Languages/nb/units.rs +++ b/tests/Languages/nb/units.rs @@ -1029,4 +1029,39 @@ fn density_two_fifths() -> Result<()> { test("nb", "SimpleSpeak", expr, "2 femtedels, kilo-gram per meter i tredje")?; return Ok(()); +} + +#[test] +fn currency_singular() -> Result<()> { + let expr = r#" + + kr1 +"#; + test("nb", "ClearSpeak", expr, "1 krone")?; + test("nb", "SimpleSpeak", expr, "1 krone")?; + return Ok(()); + +} + +#[test] +fn currency_neuter_singular() -> Result<()> { + let expr = r#" + + £1 +"#; + test("nb", "ClearSpeak", expr, "ett pund")?; + test("nb", "SimpleSpeak", expr, "ett pund")?; + return Ok(()); + +} +#[test] +fn currency_plural() -> Result<()> { + let expr = r#" + + kr10 +"#; + test("nb", "ClearSpeak", expr, "10 kroner")?; + test("nb", "SimpleSpeak", expr, "10 kroner")?; + return Ok(()); + } \ No newline at end of file From c1f604cbd7ee8b65cefaa443c9ce411f53ff2019 Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 28 Apr 2026 11:22:05 +0200 Subject: [PATCH 12/43] Moved placement of the comment "# audit-ignore" --- Rules/Languages/nb/SharedRules/calculus.yaml | 9 +-- Rules/Languages/nb/SharedRules/general.yaml | 68 +++++++------------ Rules/Languages/nb/SharedRules/geometry.yaml | 15 ++-- .../nb/SharedRules/linear-algebra.yaml | 18 ++--- 4 files changed, 37 insertions(+), 73 deletions(-) diff --git a/Rules/Languages/nb/SharedRules/calculus.yaml b/Rules/Languages/nb/SharedRules/calculus.yaml index 1fc32cecf..704d86c06 100644 --- a/Rules/Languages/nb/SharedRules/calculus.yaml +++ b/Rules/Languages/nb/SharedRules/calculus.yaml @@ -1,6 +1,5 @@ --- -# audit-ignore -- name: divergence +- name: divergence # audit-ignore tag: divergence match: "count(*) = 1" replace: @@ -13,8 +12,7 @@ then: [pause: short] - x: "*[1]" -# audit-ignore -- name: curl +- name: curl # audit-ignore tag: curl match: "count(*) = 1" replace: @@ -27,8 +25,7 @@ then: [pause: short] - x: "*[1]" -# audit-ignore -- name: gradient +- name: gradient # audit-ignore tag: gradient match: "count(*) = 1" replace: diff --git a/Rules/Languages/nb/SharedRules/general.yaml b/Rules/Languages/nb/SharedRules/general.yaml index 1f22440be..377a38c17 100644 --- a/Rules/Languages/nb/SharedRules/general.yaml +++ b/Rules/Languages/nb/SharedRules/general.yaml @@ -8,9 +8,8 @@ - T: "punktum" - x: "substring-after(., '.')" -# audit-ignore # number-sets are a little messy in that the base was converted to a number-set, so we have to match that (simple) case last -- name: pos-neg-number-sets +- name: pos-neg-number-sets # audit-ignore tag: number-sets match: "count(*)=2 and *[2][.='+' or .='-']" replace: @@ -90,9 +89,8 @@ - bookmark: "@id" - T: "den imaginære delen" # phrase('the imaginary part' is part of a complex number) -# audit-ignore # rules on scripted vertical bars ('evaluated at') -- name: evaluated-at-2 +- name: evaluated-at-2 # audit-ignore tag: evaluate match: "count(*)=2" replace: @@ -106,8 +104,7 @@ - pause: auto - x: "*[2]" -# audit-ignore -- name: evaluated-at-3 +- name: evaluated-at-3 # audit-ignore tag: evaluate match: "count(*)=3" replace: @@ -126,8 +123,7 @@ - pause: short - x: "*[2]" -# audit-ignore -- name: permutation +- name: permutation # audit-ignore tag: pochhammer match: "count(*)=2" replace: @@ -136,9 +132,8 @@ - T: "elementer av" # phrase(the solution involves several 'permutations of' values) - x: "*[1]" -# audit-ignore # NORWEGIAN: Removed test for verbosity -- name: intervals +- name: intervals # audit-ignore tag: [open-interval, open-closed-interval, closed-interval, closed-open-interval] match: "count(*)=2" replace: @@ -167,8 +162,7 @@ # - T: "komma" # phrase(use a 'comma' to divide large numbers or as a decimal point) # - x: "*[2]" -# audit-ignore -- name: default-point +- name: default-point # audit-ignore tag: point match: "count(*)=2" replace: @@ -177,8 +171,7 @@ - T: "komma" # phrase(use a 'comma' to divide large numbers or as a decimal point) - x: "*[2]" -# audit-ignore -- name: bigop-both +- name: bigop-both # audit-ignore tag: large-op match: "count(*) = 3" replace: @@ -192,9 +185,8 @@ - test: if: "following-sibling::*" then: [T: "av"] # phrase(the square root 'of' 25 equals 5) - -# audit-ignore -- name: bigop-under + +- name: bigop-under # audit-ignore tag: large-op match: "count(*)=2" replace: @@ -206,8 +198,7 @@ if: "following-sibling::*" then: [T: "av"] # phrase(the square root 'of' 25 equals 5) -# audit-ignore -- name: largeop +- name: largeop # audit-ignore tag: mrow match: "count(*)=2 and IsInDefinition(*[1], 'Speech', 'LargeOperators')" replace: @@ -225,8 +216,7 @@ - T: "med repeterende siffer" # phrase('with repeating digits') - SPELL: "*[2]" -# audit-ignore -- name: msubsup-skip-super +- name: msubsup-skip-super # audit-ignore # handles single, double, etc., prime tag: [skip-super, say-super] match: "count(*)=3" @@ -395,10 +385,9 @@ then: [x: "concat('\uF8FE', DefinitionValue($Word, 'Speech', 'PluralForms'))"] else: [x: "concat('\uF8FE', $Word)"] -# audit-ignore # need to reverse the order of speech: $ 3 -> 3 dollars # Added test for neuter currencies, which use "ett" instead of "en" for the singular form of "one". -- name: currency +- name: currency # audit-ignore tag: mrow match: "count(*)=3 and DefinitionValue(*[1], 'Speech', 'CurrencySymbols') != ''" variables: @@ -419,8 +408,7 @@ then: [x: "DefinitionValue($CurrencyWord, 'Speech', 'PluralForms')"] else: [x: "$CurrencyWord"] -# audit-ignore -- name: sin +- name: sin # audit-ignore tag: mi match: ".='sin'" replace: @@ -431,8 +419,7 @@ else: [T: "sinus"] # phrase(the 'sine' of the angle) # SWEDISH/NORWEGIAN: Added short form. -# audit-ignore -- name: cos +- name: cos # audit-ignore tag: mi match: ".='cos'" replace: @@ -442,8 +429,7 @@ then: [T: "cos"] # phrase('cos' is the abbreviation for cosine) else: [T: "cosinus"] # phrase(find the 'cosine' in a right-angle triangle) -# audit-ignore -- name: tan +- name: tan # audit-ignore tag: mi match: ".='tan' or .='tg'" replace: @@ -453,8 +439,7 @@ then: [T: "tan"] # phrase(the 'tan' is the ratio of the opposite to the adjacent side of a right-angled triangle) else: [T: "tangens"] # phrase(a 'tangent' is a straight line that touches a curve) -# audit-ignore -- name: sec +- name: sec # audit-ignore tag: mi match: ".='sec'" replace: @@ -464,8 +449,7 @@ then: [T: "sec"] # phrase(to 'seek' a solution) else: [T: "sekans"] # phrase(a 'secant' intersects a curve at two or more points) -# audit-ignore -- name: csc +- name: csc # audit-ignore tag: mi match: ".='csc'" replace: @@ -475,8 +459,7 @@ then: [T: "cosec"] # phrase(we will 'cosecant' a solution) else: [T: "cosekans"] # phrase(the 'cosecant' is the reciprocal of the secant) -# audit-ignore -- name: cot +- name: cot # audit-ignore tag: mi match: ".='cot'" replace: @@ -557,9 +540,8 @@ then: [T: "exp"] # phrase('exp' means exponential function) else: [T: "eksponensialfunksjonen"] # phrase('exponential' function) #Norwegian: Spelled wrong for correct pronunciation -# audit-ignore # NORWEGIAN: Added this rule from English version, but removed test for verbosity. -- name: covariance +- name: covariance # audit-ignore tag: mi match: ".='Cov'" replace: @@ -602,9 +584,8 @@ else: [T: "den naturlige logaritmen"] # phrase(the 'natural log' function is used in mathematics) -# audit-ignore # NORWEGIAN: Changed from Swedish to English version. -- name: multi-line +- name: multi-line # audit-ignore # that eliminates the need for the if: else_if: ... # IDEA: set a variable with the word to say for the row (e.g., RowLabel = Row/Case/Line/...) tag: [piecewise, system-of-equations, lines] @@ -667,9 +648,8 @@ then: [x: "*[position()>1]"] else: [x: "*"] -# audit-ignore # NORWEGIAN: Changed from Swedish to English version. -- name: default-multiline +- name: default-multiline # audit-ignore tag: mtd match: "parent::*[parent::m:piecewise or parent::m:system-of-equations or parent::m:lines]" variables: [LongPause: "$SpeechStyle = 'ClearSpeak' and $ClearSpeak_MultiLinePausesBetweenColumns = 'Long'"] @@ -790,8 +770,7 @@ then: [T: "vektor"] # phrase(the 2 column 'vector') else: [T: "matrise"] # phrase(the 2 by 2 'matrix') -# audit-ignore -- name: default-column-matrix +- name: default-column-matrix # audit-ignore tag: matrix variables: [IsColumnSilent: true()] match: "*[self::m:mtr][count(*) = 1]" @@ -911,8 +890,7 @@ then: [T: "determinant"] # phrase(the 2 by 2 'determinant') else: [T: "matrise"] # phrase(the 2 by 2 'matrix's) -# audit-ignore -- name: chemistry-msub +- name: chemistry-msub # audit-ignore tag: [chemical-formula] match: "*[1][.='msub']" replace: diff --git a/Rules/Languages/nb/SharedRules/geometry.yaml b/Rules/Languages/nb/SharedRules/geometry.yaml index 9792c790a..58c78a33c 100644 --- a/Rules/Languages/nb/SharedRules/geometry.yaml +++ b/Rules/Languages/nb/SharedRules/geometry.yaml @@ -1,6 +1,5 @@ --- -# audit-ignore -- name: line-segment +- name: line-segment # audit-ignore tag: line-segment match: "count(*)=2" replace: @@ -16,8 +15,7 @@ - x: "*[1]" - x: "*[2]" -# audit-ignore -- name: geometry-ray +- name: geometry-ray # audit-ignore tag: ray match: "count(*)=2" replace: @@ -33,8 +31,7 @@ - x: "*[1]" - x: "*[2]" -# audit-ignore -- name: geometry-arc +- name: geometry-arc # audit-ignore tag: arc match: "count(*)=2" replace: @@ -42,8 +39,7 @@ - x: "*[1]" - x: "*[2]" -# audit-ignore -- name: measure-of-angle +- name: measure-of-angle # audit-ignore tag: measure-of-angle match: "count(*)=3" replace: @@ -57,8 +53,7 @@ - x: "*[2]" - x: "*[3]" -# audit-ignore -- name: coordinate +- name: coordinate # audit-ignore tag: coordinate match: "." replace: diff --git a/Rules/Languages/nb/SharedRules/linear-algebra.yaml b/Rules/Languages/nb/SharedRules/linear-algebra.yaml index 405316d91..c1c2afa86 100644 --- a/Rules/Languages/nb/SharedRules/linear-algebra.yaml +++ b/Rules/Languages/nb/SharedRules/linear-algebra.yaml @@ -1,6 +1,5 @@ --- -# audit-ignore -- name: scalar-determinant +- name: scalar-determinant # audit-ignore tag: determinant match: "count(*)=1 and not(*[1][self::m:mtr])" replace: @@ -12,8 +11,7 @@ if: "not(IsNode(*[1], 'simple'))" then: [T: "slutt determinant"] # phrase('end determinant' of a matrix) -# audit-ignore -- name: subscripted-norm +- name: subscripted-norm # audit-ignore tag: subscripted-norm match: "count(*)=2" replace: @@ -23,8 +21,7 @@ - T: "til" # phrase(systems 'of' linear equations) - x: "*[1]" -# audit-ignore -- name: homomorphism +- name: homomorphism # audit-ignore # can't use IntentMappings because this doesn't fit the function pattern tag: homomorphism match: "count(*)=1" @@ -42,9 +39,8 @@ then: [pause: short] else: [pause: auto] -# audit-ignore # NORWEGIAN: Removed test for Verbosity -- name: kernel +- name: kernel # audit-ignore # can't use IntentMappings because this doesn't fit the function pattern tag: kernel match: "count(*)=1" @@ -60,9 +56,8 @@ then: [pause: short] else: [pause: auto] -# audit-ignore # NORWEGIAN: Kept these rules here, cause we say "dimensjonen til" and "normen til" instead of "dimensjonen av" and "normen av". -- name: dimension +- name: dimension # audit-ignore tag: dimension match: "count(*)=1" replace: @@ -70,8 +65,7 @@ - T: "til" # phrase(systems 'of' linear equations) - x: "*[1]" -# audit-ignore -- name: norm +- name: norm # audit-ignore tag: norm match: "count(*)=1" replace: From 747fbca222d6ff459b51dcfb70de2031bcd210e8 Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 29 Apr 2026 09:52:00 +0200 Subject: [PATCH 13/43] Changed placement of comment # audit-ignore Removed # audit-ignore from rules that are similar in Norwegian and English. The comment is only added to rules that differ, but are reviewed. --- Rules/Languages/nb/SimpleSpeak_Rules.yaml | 42 ++++++----------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/Rules/Languages/nb/SimpleSpeak_Rules.yaml b/Rules/Languages/nb/SimpleSpeak_Rules.yaml index 7784d9377..befdbf333 100644 --- a/Rules/Languages/nb/SimpleSpeak_Rules.yaml +++ b/Rules/Languages/nb/SimpleSpeak_Rules.yaml @@ -1,5 +1,4 @@ --- -# audit-ignore - name: pause tag: "!*" match: "not(self::m:math) and not($MatchingPause) and @data-intent-property[contains(., ':pause')]" @@ -14,15 +13,13 @@ then: [pause: short] else: [pause: medium] - x: "." - -# audit-ignore + - name: intent-literal-silent tag: [mi, mo, mn] match: "contains(@data-intent-property, ':silent:')" # say nothing replace: [] -# audit-ignore # handling of negative numbers that come from 'intent' is hard -- we do something that is close to right here - name: intent-literal-negative-number tag: mn @@ -31,8 +28,7 @@ - T: "minus" # phrase(x 'minus' y) - x: "translate(text(), '-_', '')" -# audit-ignore -- name: default +- name: default # audit-ignore tag: square-root match: "." replace: @@ -46,8 +42,7 @@ then: [pause: short] else: [pause: short, T: "slutt rot", pause: short] # phrase(start the square root of x 'end of root') -# audit-ignore -- name: default +- name: default # audit-ignore tag: root match: "." replace: @@ -71,11 +66,10 @@ then: [pause: short] else: [pause: short, T: "slutt rot", pause: short] # phrase(start the fifth root of x 'end of root') -# audit-ignore # Fraction rules # Mixed numbers mostly "just work" because the invisible char reads as "and" and other parts read properly on their own # Note: if the bounds change for what is a common fraction, change them in general.yaml for units -- name: common-fraction +- name: common-fraction # audit-ignore tag: fraction match: - "*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" # NORWEGIAN: Changed decimal point to $DecimalSeparators @@ -122,10 +116,9 @@ then: [x: "DefinitionValue(*[2], 'Speech', 'OrdinalFractionalDenominatorsForUnits')"] else: [x: "*[2]", CT: "dels"] # this is wrong but shouldn't occur normally -- need to write a function to compute cardinal numbers as words -# audit-ignore # Units (e.g., meters per second, m^2/s^2, (3m^2)/s) # NORWEGIAN: Added rule for t="time" -- name: per-fraction +- name: per-fraction # audit-ignore tag: fraction match: - "BaseNode(*[1])[contains(@data-intent-property, ':unit') or" @@ -141,7 +134,6 @@ else: - x: "*[2]" -# audit-ignore - name: 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 @@ -156,8 +148,7 @@ - x: "*[2]" - pause: short -# audit-ignore -- name: default +- name: default # audit-ignore tag: fraction match: "." replace: @@ -176,7 +167,6 @@ - T: "slutt brøk" # phrase(start 7 over 8 'end of fraction') - pause: medium -# audit-ignore # rules for functions raised to a power # these could have been written on 'mrow' but putting them on msup seems more specific # to see if it is a function, we look right to see if the following sibling is apply-function @@ -187,7 +177,6 @@ - T: "invers" # phrase(the 'inverse' of f) - x: "*[1]" -# audit-ignore - name: function-squared-or-cubed tag: power match: @@ -201,7 +190,7 @@ then: [T: "i andre"] # phrase(5 'squared' equals 25) else: [T: "i tredje"] # phrase(5 'cubed' equals 125) -# audit-ignore +# The following element is invisible function application. Used for expressions like sin^n x. - name: function-power tag: power match: @@ -213,7 +202,6 @@ - x: "*[2]" - pause: short -# audit-ignore # non-function rules for power - name: squared-or-cubed tag: power @@ -226,8 +214,7 @@ then: [T: "i andre"] # phrase(5 'squared' equals 25) else: [T: "i tredje"] # phrase(5 'cubed' equals 125) -# audit-ignore -- name: simple-integer +- name: simple-integer # audit-ignore tag: power match: "*[2][self::m:mn][not(contains(., $DecimalSeparators))]" # NORWEGIAN: Changed decimal point to $DecimalSeparators replace: @@ -236,8 +223,7 @@ - x: "*[2]" - pause: short -# audit-ignore -- name: simple-negative-integer +- name: simple-negative-integer # audit-ignore tag: power match: - "*[2][self::m:minus and count(*)=1 and" @@ -248,7 +234,6 @@ - x: "*[2]" - pause: short -# audit-ignore - name: simple-var tag: power match: "*[2][self::m:mi][string-length(.)=1]" @@ -258,7 +243,6 @@ - x: "*[2]" - pause: short -# audit-ignore - name: simple tag: power match: "IsNode(*[2], 'leaf')" @@ -268,8 +252,7 @@ - x: "*[2]" - pause: short -# audit-ignore -- name: nested +- name: nested # audit-ignore # it won't end in "power" if the exponent is simple enough # FIX: not that important, but this misses the case where the nested exp is a negative integer (change test if this is fixed) # ending nested exponents with "...power power" sounds bad @@ -297,8 +280,7 @@ # # Some rules on mrows -# audit-ignore -- name: set +- name: set # audit-ignore tag: set match: "." replace: @@ -316,7 +298,6 @@ - T: "mengden" # phrase(here is a 'set' of numbers) - x: "*[1]" -# audit-ignore # NORWEGIAN: Added sqrt, so it, for example, says "sqrt a times sqrt b" - name: times tag: mo @@ -346,7 +327,6 @@ replace: - T: "ganger" # phrase(7 'times' 5 equals 35) -# audit-ignore - name: no-say-parens tag: mrow match: From 8483622f56d90ee6f9299c543171e10d730e104f Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 29 Apr 2026 11:56:40 +0200 Subject: [PATCH 14/43] Changed placement of comment # audit-ignore - Removed # audit-ignore for rules that are similar in Norwegian and English. The comment is only added to rules that differ, but are reviewed. - Rules for powers might need some changes. Made comments to remember that. - The rule for`ClearSpeak-multi-line` might need some changes. Made a comment to remember that. --- Rules/Languages/nb/ClearSpeak_Rules.yaml | 52 ++++++++---------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/Rules/Languages/nb/ClearSpeak_Rules.yaml b/Rules/Languages/nb/ClearSpeak_Rules.yaml index 61ce93d34..477c4c810 100644 --- a/Rules/Languages/nb/ClearSpeak_Rules.yaml +++ b/Rules/Languages/nb/ClearSpeak_Rules.yaml @@ -1,5 +1,4 @@ --- -# audit-ignore - name: pause tag: "!*" match: "not(self::m:math) and not($MatchingPause) and @data-intent-property[contains(., ':pause')]" @@ -15,14 +14,12 @@ else: [pause: medium] - x: "." -# audit-ignore - name: intent-literal-silent tag: [mi, mo, mn] match: "contains(@data-intent-property, ':silent:')" # say nothing replace: [] -# audit-ignore # handling of negative numbers that come from 'intent' is hard -- we do something that is close to right here - name: intent-literal-negative-number tag: mn @@ -31,8 +28,7 @@ - T: "minus" # phrase(10 'minus' 4 equals 6) - x: "translate(text(), '-_', '')" -# audit-ignore -- name: default +- name: default #audit-ignore tag: square-root match: "." replace: @@ -59,8 +55,7 @@ then: [pause: short] else: [pause: long] -# audit-ignore -- name: default +- name: default # audit-ignore tag: root match: "." replace: @@ -100,7 +95,6 @@ then: [pause: short] else: [pause: long] -# audit-ignore # The 'negative' rule interacts with the msqrt/mroot rules as those might pick off this case ("the negative square root of x") - name: negative_and_positive tag: [plus, minus] @@ -122,10 +116,9 @@ # Fraction rules # Mixed numbers mostly "just work" because the invisible char reads as "and" and other parts read properly on their own -# audit-ignore # Units (e.g., meters per second) # NORWEGIAN: Added rule for t="time" -- name: per-fraction +- name: per-fraction # audit-ignore tag: fraction match: - "$ClearSpeak_Fractions='Per' or" @@ -142,9 +135,8 @@ else: - x: "*[2]" -# audit-ignore # Note: if the bounds change for what is a common fraction, change them in general.yaml for units -- name: common-fraction +- name: common-fraction # audit-ignore tag: fraction match: - "($ClearSpeak_Fractions='Auto' or $ClearSpeak_Fractions='Ordinal' or $ClearSpeak_Fractions='EndFrac') and" @@ -194,9 +186,8 @@ then: [x: "DefinitionValue(*[2], 'Speech', 'OrdinalFractionalDenominatorsForUnits')"] else: [x: "*[2]", CT: "dels"] # this is wrong but shouldn't occur normally -- need to write a function to compute cardinal numbers as words -# audit-ignore # NORWEGIAN: Changed to English version, but changed decimal point to $DecimalSeparators -- name: fraction-over-simple +- name: fraction-over-simple # audit-ignore tag: fraction match: - "($ClearSpeak_Fractions='Over' or $ClearSpeak_Fractions='FracOver' or $ClearSpeak_Fractions='OverEndFrac') or" @@ -221,7 +212,6 @@ - T: "slutt brøk" # phrase(7 over 8 'end fraction') - pause: short -# audit-ignore - # fraction with text or numbers followed by text in both numerator and denominator name: fraction-over-text tag: fraction @@ -251,7 +241,6 @@ - T: "slutt brøk" # phrase(7 over 8 'end fraction') - pause: short -# audit-ignore # NORWEGIAN: Changed to English version - name: default tag: fraction @@ -273,7 +262,6 @@ - T: "slutt brøk" # phrase(the fraction with 3 over 4 'end fraction') - pause: short -# audit-ignore # rules for functions raised to a power # these could have been written on 'mrow' but putting them on msup seems more specific # to see if it is a function, we look right to see if the following sibling is apply-function @@ -289,7 +277,6 @@ then: [bookmark: "*[2]/@id", T: "arcus", x: "*[1]"] # phrase(the 'buelenge' of a circle) else: [bookmark: "*[2]/@id", T: "invers", x: "*[1]"] # default/Auto # phrase(8 over 5 is the 'inverse' of 5 over 8) -# audit-ignore - name: function-squared-or-cubed tag: power match: @@ -303,6 +290,7 @@ then: [T: "i andre"] # phrase(25 equals 5 'squared') else: [T: "i tredje"] # phrase(625 equals 5 'cubed') +# The following element is invisible function application. Used for expressions like sin^n x. - name: function-power tag: power match: @@ -394,6 +382,7 @@ # but the test cases all fall back to "raised to the exponent" when not "Auto" # If these are allowed for non-Auto values, then you end up with "...power power...". - # [xxx]^n + # Norwegian: Consider to find a word similar to "power". name: nested-squared-or-cubed tag: power match: @@ -412,6 +401,7 @@ - x: "*[2]" - # - [xxx]^n + # Norwegian: Consider to find a word similar to "power". name: nested-negative-squared-or-cubed tag: power match: @@ -432,6 +422,7 @@ - x: "*[2]" - # [xxx] var^n + # Norwegian: Consider to find a word similar to "power". name: nested-var-squared-or-cubed tag: power match: @@ -454,6 +445,7 @@ - x: "*[2]" - # -[xxx] var^n + # Norwegian: Consider to find a word similar to "power". name: nested-negative-var-squared-or-cubed tag: power match: @@ -489,6 +481,7 @@ - pause: short - T: "slutt eksponent" # phrase(and now 'end exponent' has been reached) +# Norwegian: Consider to find a word similar to "power". - name: default tag: power match: "." @@ -500,9 +493,8 @@ # # Some rules on mrows # -# audit-ignore - # the inference rules lump absolute value and cardinality together, so those rules are implemented here - name: ClearSpeak-absolute-value + name: ClearSpeak-absolute-value # audit-ignore tag: absolute-value match: "." # SWEDISH/NORWEGIAN: Differentiate between the initial and ending declaration of the terms. @@ -521,8 +513,7 @@ - x: "$EndToSay" - pause: short -# audit-ignore -- name: set +- name: set # audit-ignore tag: set match: "." replace: @@ -559,8 +550,7 @@ # SWEDISH/NORWEGIAN: rewrote the intervals function to better deal with Swedish/Norwegian convention of speaking intervals # NORWEGIAN: Removed test for verbosity, cause you should always say "det åpne" etc. - # audit-ignore -- name: ClearSpeak-intervals # avoid overriding with default "intervals" name +- name: ClearSpeak-intervals # avoid overriding with default "intervals" name # audit-ignore variables: - is_intervals_start_infinity: "*[1][self::m:minus and count(*)=1 and *[1][.='∞']]" - is_intervals_end_infinity: "*[2][.='∞'or (self::m:plus and count(*)=1 and *[1][.='∞'])]" @@ -585,7 +575,6 @@ then: [T: "og med"] - x: "*[2]" - # audit-ignore - name: binomial-frac-vector tag: matrix match: @@ -596,7 +585,6 @@ - T: "over" # phrase(the binomial coefficient n 'choose' m) - x: "*[2]/*[1]/*" - # audit-ignore - name: ClearSpeak-default tag: [mtr, mlabeledtr] match: "parent::m:matrix or parent::m:determinant" @@ -618,7 +606,7 @@ else: [x: "*"] - # handle both log and ln - name: ClearSpeak-log + name: ClearSpeak-log # audit-ignore tag: mi variables: [log_is_simple: "IsNode(following-sibling::*[2],'simple')"] # skip function apply match: ".='log' or .='ln' or .='lg'" @@ -653,8 +641,7 @@ then: [T: "den naturlige logaritmen"] # phrase(the 'natural log' of x) else: [SPELL: "'ln'"] -# audit-ignore -# NORWEGIAN: Changed to English version +# Norwegian: The preference MultiLineLabel = none is handled differently than it is for English. - name: ClearSpeak-multi-line tag: [piecewise, system-of-equations, lines] # these are ignored in favor of the ClearSpeak prefs match: "." @@ -708,7 +695,6 @@ - pause: short - x: "*" -# audit-ignore # NORWEGIAN: Changed from Swedish to English version - name: ClearSpeak-default-multiline tag: [mtr, mlabeledtr] @@ -749,8 +735,7 @@ then: [x: "*[position()>1]"] else: [x: "*"] -# audit-ignore -- name: ClearSpeak_Functions_None +- name: ClearSpeak_Functions_None # audit-ignore tag: mo match: - ".='⁡' and $ClearSpeak_Functions = 'None' and" @@ -761,7 +746,6 @@ then: [T: ""] else: [T: "ganger"] # phrase(5 'times' 3 equals 15) -# audit-ignore - name: no-times tag: mo match: @@ -770,7 +754,6 @@ replace: - T: "" -# audit-ignore # NORWEGIAN: Changed to English version - name: ClearSpeak-times tag: mo @@ -803,7 +786,6 @@ replace: - T: "ganger" # phrase(5 'times' 3 equals 15) -# audit-ignore - name: no-say-parens tag: mrow match: From 0416939bbfe95920baed4528139698fbcbdfdf26 Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 29 Apr 2026 12:04:26 +0200 Subject: [PATCH 15/43] Some changes to be up to date with English - Changed last else statement of the rule "literal, [msup, msubsup]". - Added the rule "power-indexed-by". - Changed from spell to SPELL - Add # audit-ignore to rules that differs from English, but are reviewed. --- Rules/Languages/nb/SharedRules/default.yaml | 29 +++++++++++++++------ 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/Rules/Languages/nb/SharedRules/default.yaml b/Rules/Languages/nb/SharedRules/default.yaml index 59a8d11a9..22ae8491f 100644 --- a/Rules/Languages/nb/SharedRules/default.yaml +++ b/Rules/Languages/nb/SharedRules/default.yaml @@ -60,7 +60,7 @@ - if: "string-length(.) = 1 and text() != '_'" # need unicode.tdl to kick in for single letter tokens then: [x: "text()"] - else_if: "@data-chem-element" # NavMode=Character needs this - then: [spell: "text()", pause: "short"] + then: [SPELL: "text()", pause: "short"] else: [x: "translate(., '-_\u00A0', ' ')"] # from intent literals or from extra spaces added (which get deleted) - name: default @@ -91,7 +91,7 @@ - x: "*[2]" - pause: short -- name: literal-default +- name: literal-default # audit-ignore tag: mfrac match: "." replace: @@ -110,10 +110,9 @@ - T: "slutt brøk" # phrase("start of fraction x over y 'end over'") - pause: medium - # not sure what really should be said for these since we should not assume they are square roots #NORWEGIAN: Removed test for verbosity -- name: literal-default +- name: literal-default # audit-ignore tag: msqrt match: "." replace: @@ -126,7 +125,7 @@ # not sure what really should be said for these since we should not assume they are square roots # NORWEGIAN: Changed to "med grad", and changed the order of the index and the variable/number in the root. Removed test for verbosity. -- name: literal-default +- name: literal-default # audit-ignore tag: mroot match: "." replace: @@ -145,6 +144,7 @@ then: [T: "slutt rottegn"] # phrase("root of x 'end root symbol'") +# Used for expressions where the subscript is an integer, and verbosity is terse. - name: simple-sub tag: indexed-by # invisible comma -- want "x 1 when subscript is an integer" @@ -154,9 +154,11 @@ - x: "*[2]" - pause: short + +# Used for expression where the subscript is a leaf or and mrow where the second element is a comma. # NORWEGIAN: Removed the following test: if: "$Verbosity!='Terse' or not(*[2][self::m:mn])", which is in the Swedish translation. # NORWEGIAN: Added "pause: short" before "senket" -- name: no-end-sub +- name: no-end-sub # audit-ignore tag: indexed-by # invisible comma -- want "x 1 when subscript is an integer" match: "count(*)=2 and (IsNode(*[2], 'leaf') or *[2][self::m:mrow][*[2][.='⁣']])" #NORWEGIAN: Don't change this to English version. Then the rule "indexed-by" in definitions.yaml kicks in instead. Want to keep the pause before "senket". @@ -166,6 +168,15 @@ - T: "senket" - x: "*[2]" - pause: short + +- name: power-indexed-by + tag: power-indexed-by + match: "." + replace: + - x: "*[1]" + - T: "senket" # phrase(x 'sub' 2) + - x: "*[2]" + - pause: short - name: literal tag: msub @@ -177,6 +188,7 @@ then: [T: "senket"] # phrase(x 'sub' 2) - x: "*[2]" +# Norwegian: Changed this to be more similar to the English rule. Can't find a way to trigger the last "else" statement. - name: literal tag: [msup, msubsup] match: "." @@ -199,9 +211,10 @@ if: "not(IsNode(*[last()], 'simple'))" then: [T: "slutt hevet"] # phrase(x super 2 'end of super') else: - - T: "opphøyd i" # phrase(5 'raised to the' second power equals 25) + - T: "hevet" # phrase(5 'raised to the' second power equals 25) - x: "*[last()]" - # - t: "power" # phrase(5 raised to the second 'power' equals 25) + - T: "slutt hevet" + #NORWEGIAN: Changed to English version. - name: default From bfc9894a712b606afe8d94d9e35cce08cd32029b Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 5 May 2026 08:43:36 +0200 Subject: [PATCH 16/43] Translated to Norwegian I hadn't reviewed this file before. Changed it to be up to date with the English file --- Rules/Languages/nb/overview.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Rules/Languages/nb/overview.yaml b/Rules/Languages/nb/overview.yaml index fb7112ac7..c901d5504 100644 --- a/Rules/Languages/nb/overview.yaml +++ b/Rules/Languages/nb/overview.yaml @@ -13,23 +13,23 @@ # That might mean that at the top level, we may want to allow the first few children to expand - name: overview-default - tag: mfrac + tag: [mfrac, fraction] match: "." replace: - test: if: "IsNode(*[1], 'simple') and IsNode(*[2], 'simple')" then: - x: "*[1]" - - T: "gjennom" + - T: "over" - x: "*[2]" else: - T: "brøk" - name: overview-default - tag: msqrt + tag: [msqrt, "square-root"] match: "." replace: - - T: "roten" + - T: "kvadratrot" - test: if: "IsNode(*[1], 'simple')" then: @@ -39,7 +39,7 @@ - x: "*[1]" - name: overview-default - tag: mroot + tag: [mroot, root] match: "." replace: - test: @@ -72,7 +72,7 @@ - T: "ganger" - x: count(*[2]/*[self::m:mtr][1]/*) - test: - if: "*[1][text()='|']" # just need to check the first bracket since we know it must be (, [, or | + if: "*[1][.='|']" # just need to check the first bracket since we know it must be (, [, or | then: [T: "determinant"] else: [T: "matrise"] From e90c1e262157fae4545c7116be84858846670aa1 Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 5 May 2026 09:50:33 +0200 Subject: [PATCH 17/43] Adjust Norwegian ClearSpeak power rules Enhances spoken output for mathematical power expressions. - Increases the pause after simple exponents (e.g., `simple-integer`, `simple-var`) to 'medium'. - Introduces conditional phrasing and pause adjustments for nested and default power rules. - In 'Verbose' mode, adds a short pause and "slutt eksponent" (end exponent). - For other verbosity levels, applies a medium pause. --- Rules/Languages/nb/ClearSpeak_Rules.yaml | 49 ++++++++++++++++++++---- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/Rules/Languages/nb/ClearSpeak_Rules.yaml b/Rules/Languages/nb/ClearSpeak_Rules.yaml index 477c4c810..f4180e48e 100644 --- a/Rules/Languages/nb/ClearSpeak_Rules.yaml +++ b/Rules/Languages/nb/ClearSpeak_Rules.yaml @@ -340,6 +340,7 @@ - bookmark: "*[2]/@id" - T: "i tredje" # phrase(5 'cubed' equals 125) +# Norwegian: Changed to longer pause at the end. - name: simple-integer tag: power match: "*[2][self::m:mn][not(contains(., $DecimalSeparators))]" # NORWEGIAN: Changed decimal point to $DecimalSeparators @@ -348,8 +349,9 @@ - T: "opphøyd i" - bookmark: "*[2]/@id" - x: "*[2]" - - pause: short + - pause: medium +# Norwegian: Changed to longer pause at the end. - name: simple-negative-integer tag: power match: @@ -361,8 +363,9 @@ - T: "opphøyd i" - bookmark: "*[2]/@id" - x: "*[2]" - - pause: short + - pause: medium +# Norwegian: Changed to longer pause at the end. - name: simple-var tag: power match: "*[2][self::m:mi][string-length(.)=1]" @@ -371,7 +374,7 @@ - T: "opphøyd i" - bookmark: "*[2]/@id" - x: "*[2]" - - pause: short + - pause: medium # match nested exponent, where the nested exponent is has the power 2 or 3 (n below) # [xxx]^n, - [xxx]^n, [xxx] var^n, -[xxx] var^n @@ -382,7 +385,7 @@ # but the test cases all fall back to "raised to the exponent" when not "Auto" # If these are allowed for non-Auto values, then you end up with "...power power...". - # [xxx]^n - # Norwegian: Consider to find a word similar to "power". + # Norwegian: Added "end exponent" for verbose, and longer pause for terse and medium. name: nested-squared-or-cubed tag: power match: @@ -399,9 +402,15 @@ - x: "*[1]" - T: "opphøyd i" # phrase(x 'raised to the' second power) - x: "*[2]" + - test: + if: "$Verbosity='Verbose'" + then: + - pause: short + - T: "slutt eksponent" + else: [pause: medium] - # - [xxx]^n - # Norwegian: Consider to find a word similar to "power". + # Norwegian: Added "end exponent" for verbose, and longer pause for terse and medium. name: nested-negative-squared-or-cubed tag: power match: @@ -420,9 +429,15 @@ - x: "*[1]" - T: "opphøyd i" # phrase(x 'raised to the' second power) - x: "*[2]" + - test: + if: "$Verbosity='Verbose'" + then: + - pause: short + - T: "slutt eksponent" + else: [pause: medium] - # [xxx] var^n - # Norwegian: Consider to find a word similar to "power". + # Norwegian: Added "end exponent" for verbose, and longer pause for terse and medium. name: nested-var-squared-or-cubed tag: power match: @@ -443,9 +458,15 @@ - x: "*[1]" - T: "opphøyd i" # phrase(x 'raised to the' second power) - x: "*[2]" + - test: + if: "$Verbosity='Verbose'" + then: + - pause: short + - T: "slutt eksponent" + else: [pause: medium] - # -[xxx] var^n - # Norwegian: Consider to find a word similar to "power". + # Norwegian: Added "end exponent" for verbose, and longer pause for terse and medium. name: nested-negative-var-squared-or-cubed tag: power match: @@ -468,6 +489,12 @@ - x: "*[1]" - T: "opphøyd i" # phrase(x 'raised to the' second power) - x: "*[2]" + - test: + if: "$Verbosity='Verbose'" + then: + - pause: short + - T: "slutt eksponent" + else: [pause: medium] - name: default-exponent-power tag: power @@ -481,7 +508,7 @@ - pause: short - T: "slutt eksponent" # phrase(and now 'end exponent' has been reached) -# Norwegian: Consider to find a word similar to "power". +# Norwegian: Added "end exponent" for verbose, and longer pause for terse and medium. - name: default tag: power match: "." @@ -489,6 +516,12 @@ - x: "*[1]" - T: "opphøyd i" # phrase(x 'raised to the' second power) - x: "*[2]" + - test: + if: "$Verbosity='Verbose'" + then: + - pause: short + - T: "slutt eksponent" + else: [pause: medium] # # Some rules on mrows From 99475b17c577ceffc67ea5fd3e2608e44b994992 Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 6 May 2026 10:27:50 +0200 Subject: [PATCH 18/43] Added "end exponent" for default power rule. Updated and added some tests for powers. Co-authored-by: Copilot --- Rules/Languages/nb/SimpleSpeak_Rules.yaml | 17 +++++- tests/Languages/nb/SimpleSpeak/msup.rs | 66 ++++++++++++++++++----- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/Rules/Languages/nb/SimpleSpeak_Rules.yaml b/Rules/Languages/nb/SimpleSpeak_Rules.yaml index befdbf333..4c06153a1 100644 --- a/Rules/Languages/nb/SimpleSpeak_Rules.yaml +++ b/Rules/Languages/nb/SimpleSpeak_Rules.yaml @@ -267,9 +267,17 @@ - T: "opphøyd i" # phrase(15 'raised to the' second power equals 225) - x: "*[2]" - pause: short - - T: "slutt eksponent" # phrase(start 2 raised to the exponent 4 'end of exponent') + - test: + if: "$Impairment = 'Blindness'" + then: + - T: "slutt eksponent" # phrase(start 2 raised to the exponent 4 'end of exponent') + - pause: short + else: + - pause: medium -# Norwegian: Need to find something similar to the word "power" or add a long pause. +# Norwegian: Added "end exponent" at the end. This doesn't apply if the parent is a power. +# For example: x^((4/5)^(n+1)) +# The outer power is caught by the nested rule. Avoid duplicated "end exponent". - name: default tag: power match: "." @@ -277,6 +285,11 @@ - x: "*[1]" - T: "opphøyd i" # phrase(15 'raised to the' second power equals 225) - x: "*[2]" + - test: + if: "not(parent::*[self::m:power or self::m:msup])" + then: + - pause: short + - T: "slutt eksponent" # # Some rules on mrows diff --git a/tests/Languages/nb/SimpleSpeak/msup.rs b/tests/Languages/nb/SimpleSpeak/msup.rs index 42b51ba16..749361298 100644 --- a/tests/Languages/nb/SimpleSpeak/msup.rs +++ b/tests/Languages/nb/SimpleSpeak/msup.rs @@ -76,7 +76,7 @@ fn non_simple_power() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "3 opphøyd i y pluss 2")?; + test("nb", "SimpleSpeak", expr, "3 opphøyd i y pluss 2, slutt eksponent")?; return Ok(()); } @@ -102,7 +102,7 @@ fn simple_fraction_power() -> Result<()> { 13 "; - test("nb", "SimpleSpeak", expr, "x opphøyd i 1 tredjedel")?; + test("nb", "SimpleSpeak", expr, "x opphøyd i 1 tredjedel, slutt eksponent")?; return Ok(()); } @@ -123,7 +123,7 @@ fn nested_squared_power_with_coef() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "3 opphøyd i 2 x i andre")?; + test("nb", "SimpleSpeak", expr, "3 opphøyd i 2 x i andre, slutt eksponent")?; return Ok(()); } @@ -145,7 +145,7 @@ fn nested_squared_power_with_neg_coef() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "3 opphøyd i minus 2 x i andre")?; + test("nb", "SimpleSpeak", expr, "3 opphøyd i minus 2 x i andre, slutt eksponent")?; return Ok(()); } @@ -162,7 +162,7 @@ fn nested_cubed_power() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "y opphøyd i 4 femtedeler i tredje")?; + test("nb", "SimpleSpeak", expr, "y opphøyd i 4 femtedeler i tredje, slutt eksponent")?; return Ok(()); } @@ -181,7 +181,7 @@ fn nested_cubed_power_with_neg_base() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "y opphøyd i minus 4 femtedeler i tredje")?; + test("nb", "SimpleSpeak", expr, "y opphøyd i minus 4 femtedeler i tredje, slutt eksponent")?; return Ok(()); } @@ -205,7 +205,7 @@ fn nested_number_times_squared() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "e opphøyd i 1 halv x i andre")?; + test("nb", "SimpleSpeak", expr, "e opphøyd i 1 halv x i andre, slutt eksponent")?; return Ok(()); } @@ -229,7 +229,7 @@ fn nested_negative_number_times_squared() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "e opphøyd i minus 1 halv x i andre")?; + test("nb", "SimpleSpeak", expr, "e opphøyd i minus 1 halv x i andre, slutt eksponent")?; return Ok(()); } @@ -250,7 +250,7 @@ fn nested_expr_to_tenth() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "3 opphøyd i 3 opphøyd i 10")?; + test("nb", "SimpleSpeak", expr, "3 opphøyd i 3 opphøyd i 10; slutt eksponent")?; return Ok(()); } @@ -274,7 +274,7 @@ fn nested_non_simple_squared_exp() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "3 opphøyd i, startparentes; x pluss 1; sluttparentes i andre")?; + test("nb", "SimpleSpeak", expr, "3 opphøyd i, startparentes; x pluss 1; sluttparentes i andre, slutt eksponent")?; return Ok(()); } @@ -290,7 +290,7 @@ fn nested_simple_power() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "t opphøyd i 4 femtedeler opphøyd i n")?; + test("nb", "SimpleSpeak", expr, "t opphøyd i 4 femtedeler opphøyd i n; slutt eksponent")?; return Ok(()); } @@ -308,7 +308,7 @@ fn nested_end_exponent_power() -> Result<()> { "; test("nb", "SimpleSpeak", expr, "t opphøyd i 4 femtedeler opphøyd i n pluss 1, slutt eksponent")?; test_prefs("nb", "SimpleSpeak", vec![("Impairment", "LearningDisability")], expr, - "t opphøyd i 4 femtedeler opphøyd i n pluss 1, slutt eksponent")?; + "t opphøyd i 4 femtedeler opphøyd i n pluss 1")?; return Ok(()); } @@ -357,7 +357,7 @@ fn nested_complex_power() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "e opphøyd i minus 1 halv ganger; startparentes; brøk, x minus my, over sigma, slutt brøk; sluttparentes i andre")?; + test("nb", "SimpleSpeak", expr, "e opphøyd i minus 1 halv ganger; startparentes; brøk, x minus my, over sigma, slutt brøk; sluttparentes i andre, slutt eksponent")?; return Ok(()); } @@ -373,7 +373,45 @@ fn default_power() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "t opphøyd i brøk, b pluss 1, over 3, slutt brøk")?; + test("nb", "SimpleSpeak", expr, "t opphøyd i brøk, b pluss 1, over 3, slutt brøk; slutt eksponent")?; return Ok(()); } + +#[test] +fn nested_default_extra() -> Result<()> { + let expr = " + + x + + 1+ + + 45 + n+1 + + + + "; + test("nb", "SimpleSpeak", expr, "x opphøyd i 1 pluss, 4 femtedeler opphøyd i n pluss 1, slutt eksponent, slutt eksponent")?; + return Ok(()); + +} + +#[test] +fn default_default_extra() -> Result<()> { + let expr = " + + x + + + 45 + n+1 + + +1 + + + "; + test("nb", "SimpleSpeak", expr, "x opphøyd i 4 femtedeler opphøyd i n pluss 1, slutt eksponent; pluss 1, slutt eksponent")?; + return Ok(()); + +} \ No newline at end of file From 709332641893f0ad208c9961111e8e7f0c75c40a Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 6 May 2026 10:28:57 +0200 Subject: [PATCH 19/43] Updated test after changes to power rules SimpleSpeak --- tests/Languages/nb/shared.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Languages/nb/shared.rs b/tests/Languages/nb/shared.rs index 45c9358e2..a3d10617d 100644 --- a/tests/Languages/nb/shared.rs +++ b/tests/Languages/nb/shared.rs @@ -297,7 +297,7 @@ fn ignore_comma() -> Result<()> { "; - test("nb", "SimpleSpeak", expr, "fi av x er lik, c ganger, e opphøyd i minus h i andre x i andre")?; + test("nb", "SimpleSpeak", expr, "fi av x er lik; c ganger, e opphøyd i minus h i andre x i andre, slutt eksponent")?; return Ok(()); } From 490ca4a4c5142789a08fd698e55554ba587c011f Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 6 May 2026 10:55:16 +0200 Subject: [PATCH 20/43] Changed multiline rule for preference "None". --- Rules/Languages/nb/ClearSpeak_Rules.yaml | 15 +++++++-------- tests/Languages/nb/ClearSpeak/multiline.rs | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Rules/Languages/nb/ClearSpeak_Rules.yaml b/Rules/Languages/nb/ClearSpeak_Rules.yaml index f4180e48e..7897b7847 100644 --- a/Rules/Languages/nb/ClearSpeak_Rules.yaml +++ b/Rules/Languages/nb/ClearSpeak_Rules.yaml @@ -674,7 +674,6 @@ then: [T: "den naturlige logaritmen"] # phrase(the 'natural log' of x) else: [SPELL: "'ln'"] -# Norwegian: The preference MultiLineLabel = none is handled differently than it is for English. - name: ClearSpeak-multi-line tag: [piecewise, system-of-equations, lines] # these are ignored in favor of the ClearSpeak prefs match: "." @@ -691,37 +690,37 @@ - if: "($ClearSpeak_MultiLineLabel = 'Auto' and self::m:piecewise) or $ClearSpeak_MultiLineLabel = 'Case'" then: - test: - - if: "$LineCount > 1 and $ClearSpeak_MultiLineLabel != 'None'" + - if: "$LineCount > 1" then: [T: "tilfeller"] else: [T: "tilfelle"] # phrase(this is the first 'case' of three cases) - - else_if: "$ClearSpeak_MultiLineLabel = 'Auto' or $ClearSpeak_MultiLineLabel = 'Line'" # already dealt with Auto/Case + - else_if: "$ClearSpeak_MultiLineLabel = 'Auto' or $ClearSpeak_MultiLineLabel = 'Line' or $ClearSpeak_MultiLineLabel = 'None'" # already dealt with Auto/Case then: - test: - - if: "$LineCount > 1 and $ClearSpeak_MultiLineLabel != 'None'" + - if: "$LineCount > 1" then: [T: "rader"] # phrase(this is the first 'line' of three lines) else: [T: "rad"] # phrase(this is the first 'line' of three lines) - else_if: "$ClearSpeak_MultiLineLabel = 'Constraint'" then: - test: - - if: "$LineCount > 1 and $ClearSpeak_MultiLineLabel != 'None'" + - if: "$LineCount > 1" then: [T: "betingelser"] # phrase(this is the first 'constraint' of three constraints) else: [T: "betingelse"] # phrase(this is the first 'constraint' of three constraints) - else_if: "$ClearSpeak_MultiLineLabel = 'Equation'" then: - test: - - if: "$LineCount > 1 and $ClearSpeak_MultiLineLabel != 'None'" + - if: "$LineCount > 1" then: [T: "likninger"] # phrase(this is the first 'equation' of three equations) else: [T: "likning"] # phrase(this is the first 'equation' of three equations) - else_if: "$ClearSpeak_MultiLineLabel = 'Row'" then: - test: - - if: "$LineCount > 1 and $ClearSpeak_MultiLineLabel != 'None'" + - if: "$LineCount > 1" then: [T: "rader"] # phrase(this is the first 'row' of three rows) else: [T: "rad"] # phrase(this is the first 'row' of three rows) - else_if: "$ClearSpeak_MultiLineLabel = 'Step'" then: - test: - - if: "$LineCount > 1 and $ClearSpeak_MultiLineLabel != 'None'" + - if: "$LineCount > 1" then: [T: "steg"] # phrase(this is the first 'step' of three steps) else: [T: "steg"] # phrase(this is the first 'step' of three steps) # SWEDISH/NORWEGIAN: Every expression had to be inflected separately. diff --git a/tests/Languages/nb/ClearSpeak/multiline.rs b/tests/Languages/nb/ClearSpeak/multiline.rs index 4a9ef6be5..385e7c173 100644 --- a/tests/Languages/nb/ClearSpeak/multiline.rs +++ b/tests/Languages/nb/ClearSpeak/multiline.rs @@ -138,7 +138,7 @@ fn equation_none() -> Result<()> { "; test_ClearSpeak("nb", "ClearSpeak_MultiLineLabel", "None", expr, - "2; x pluss y er lik 7; 2 x pluss 3 y; er lik 17")?; + "2 rader; x pluss y er lik 7; 2 x pluss 3 y; er lik 17")?; return Ok(()); } From d57cca9b0ead715beb9c4f90a97363a1706cb533 Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 13 May 2026 12:51:17 +0200 Subject: [PATCH 21/43] Work in progress --- Rules/Languages/nb/navigate.yaml | 3108 ++++++++++++++++++++++-------- 1 file changed, 2296 insertions(+), 812 deletions(-) diff --git a/Rules/Languages/nb/navigate.yaml b/Rules/Languages/nb/navigate.yaml index 98cbbca9f..da6aa7dcb 100644 --- a/Rules/Languages/nb/navigate.yaml +++ b/Rules/Languages/nb/navigate.yaml @@ -33,153 +33,131 @@ # ReadZoomLevel -- -1 for Enhanced, otherwise the distance from leaf the rules should maintain # PlaceMarkerIndex - -# Rules for speaking what happens when moving into or out of a notation -- name: into-or-out-of - tag: mfrac - match: "$Move2D != ''" - replace: - - x: "$Move2D" - - test: - if: "count($Child2D/preceding-sibling::*)=0" - then: [T: "telleren"] # phrase(the 'numerator' of a fraction) - else: [T: "nevneren"] # phrase(the 'denominator' of a fraction) - - pause: "medium" - -- name: into-or-out-of - tag: msqrt - match: "$Move2D != ''" - replace: - - x: "$Move2D" - - T: "kvadratroten" # phrase(the 'square root' of x) - - pause: "medium" - -- name: into-or-out-of - tag: mroot - match: "$Move2D != ''" - replace: - - x: "$Move2D" - - test: - if: "count($Child2D/preceding-sibling::*)=0" - then: [T: "roten"] # phrase(the cube 'root' of x) - else: [T: "rotindeksen"] # phrase(the 'root index' of x is 3) - - pause: "medium" - -#NORWEGIAN: For powers we say "grunntallet" for the base, but since this markup is used for other things than powers and subindexes, use the word "basen". -- name: into-or-out-of - tag: msub - match: "$Move2D != ''" - replace: - - x: "$Move2D" - - test: - if: "count($Child2D/preceding-sibling::*)=0" - then: [T: "basen"] # phrase(the 'base' of the power) - else: [T: "nedre indeks"] # phrase(x with 'subscript' 2) - - pause: "medium" - -- name: into-or-out-of - tag: msup - match: "$Move2D != ''" - replace: - - x: "$Move2D" - - test: - if: "count($Child2D/preceding-sibling::*)=0" - then: [T: "basen"] # phrase(the 'base' of the power) - else: [T: "øvre indeks"] # phrase(x with 'superscript' 2) # FIX: it would be better to use the word used when reading (power, exponent, ...) - - pause: "medium" - -- name: into-or-out-of - tag: msubsup - match: "$Move2D != ''" - replace: - - x: "$Move2D" - - test: - - if: "count($Child2D/preceding-sibling::*)=0" - then: [T: "basen"] # phrase(the 'base' of the power) - - else_if: "count($Child2D/preceding-sibling::*)=1" - then: [T: "nedre indeks"] # phrase(x with 'subscript' 2) - else: [T: "øvre indeks"] # phrase(x with 'superscript' 2) # FIX: it would be better to use the word used when reading (power, exponent, ...) - - pause: "medium" - -- name: into-or-out-of - tag: munder - match: "$Move2D != ''" - replace: - - x: "$Move2D" - - test: - if: "count($Child2D/preceding-sibling::*)=0" - then: [T: "basen"] # phrase(the 'base' of the power) - else: [T: "nedre indeks"] # phrase(the 'lower limit' of the function is zero) - - pause: "medium" - -- name: into-or-out-of - tag: mover - match: "$Move2D != ''" +# Rules for announcing the command +- name: say-command + tag: "!*" + match: "$SayCommand != ''" # value should be '', 'true', or 'false' + variables: [Prefix: "''"] replace: - - x: "$Move2D" - test: - if: "count($Child2D/preceding-sibling::*)=0" - then: [T: "basen"] # phrase(the 'base' of the power) - else: [T: "øvre indeks"] # phrase(the 'upper limit' of the function is zero) - - pause: "medium" + - if: "$MatchCounter = 0 and $SayCommand = 'true'" + then_test: + - if: "self::m:math and starts-with($NavCommand, 'ZoomOut')" + then: [T: "zoomet helt ut", pause: "medium"] + - else_if: "IsNode(., 'leaf') and starts-with($NavCommand, 'ZoomIn')" + then: + - test: + - if: "string-length(.) = 1" + then: [T: "zoomet helt inn"] # phrase('zoomed in all of the way') + - else_if: "$NavNodeOffset = 0" + then: [T: "zoomet inn til første tegn"] # phrase('zoomed in to first character') + else: [T: "zoomet inn til tegn"] # phrase('zoomed in to character') + - pause: "medium" + else: + - test: + - if: "starts-with($NavCommand, 'Zoom')" + then: [set_variables: [Prefix: "'zoom'"]] # phrase('zoom' in to see more details) + - else_if: "starts-with($NavCommand, 'Move')" + then: [set_variables: [Prefix: "'gå'"]] # phrase('move' to next entry in table) + - else_if: "starts-with($NavCommand, 'Read')" + then: [set_variables: [Prefix: "'les'"]] # phrase('read' to next entry in table) + - else_if: "starts-with($NavCommand, 'Describe')" + then: [set_variables: [Prefix: "'beskriv'"]] # phrase('describe' to next entry in table) + - test: + if: "$Prefix != ''" + then: + - x: "$Prefix" + - test: + - if: "substring($NavCommand, string-length($Prefix)+1) = 'In'" + then: [T: "inn"] # phrase(zoom 'in' to see more details) + - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'InAll'" + # HACK: '\uF8FE' is used internally for the concatenation char by 'ct' -- this gets "ed" concatenated to "zoom" + then: [T: "\uF8FEet helt inn"] # phrase(zoom 'out all of the way' to see more details) + - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Out'" + then: [T: "ut"] # phrase(zoom 'out' to see more details) + - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'OutAll'" + # HACK: '\uF8FE' is used internally for the concatenation char by 'ct' -- this gets "ed" concatenated to "zoom" + then: [T: "\uF8FEet helt ut"] # phrase(zoom 'out all of the way' to see more details) + - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Next'" + then: [T: "høyre"] # phrase(move to the 'right') + - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Previous'" + then: [T: "venstre"] # phrase(move to the 'left') + - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Current'" + then: [T: "nåværende"] # phrase(who is the 'current' president) + - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'LineStart'" + then: [T: "til starten av linja"] # phrase(move 'to start of line') + - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'LineEnd'" + then: [T: "til slutten av linja"] # phrase(move 'to end of line') + - pause: "medium" + - set_variables: [MatchCounter: "$MatchCounter + 1"] + +- name: into-or-out-of-silent + tag: "*" + # saying "out of row n" is not very useful, so skip it + match: "$Move2D != '' and (not(@data-from-mathml) or @data-from-mathml = name(.)) and + (name(.)='mrow' or name(.) = 'mtr' or name(.) = 'mlabeledtr' or @data-from-mathml = 'mtable')" + replace: [] -- name: into-or-out-of - tag: munderover - match: "$Move2D != ''" +- name: into-or-out-of-mtr + tag: [mtr, mlabeledtr] + match: "$Move2D = 'inn'" # Navigate into a 2D structure. replace: - - x: "$Move2D" - - test: - - if: "count($Child2D/preceding-sibling::*)=0" - then: [T: "basen"] # phrase(the 'base' of the power) - - else_if: "count($Child2D/preceding-sibling::*)=1" - then: [T: "nedre indeks"] # phrase(the 'lower limit' of the function is zero) - else: [T: "øvre indeks"] # phrase(the 'upper limit' of the function is zero) + - T: "kolonne" + - x: "count($Child2D/preceding-sibling::*)+1" # Teller antall søskennoder før Child2D (noden man beveger seg inn i) - pause: "medium" -- name: into-or-out-of - tag: mmultiscripts - match: "$Move2D != ''" +- name: into-or-out-of-mmultiscripts + tag: "*" + match: "$Move2D != '' and (@data-from-mathml='mmultiscripts' or self::m:mmultiscripts)" #Navigerer inn i en 2d struktur som er en mmultiscripts. replace: - test: - if: "name($Child2D)!='none'" + if: "name($Child2D)!='none'" # Sjekker at barnet man navigerer inn i ikke er tomt. then: - with: variables: - - NumPrecedingSiblings: "count($Child2D/preceding-sibling::*)" + - NumPrecedingSiblings: "count($Child2D/preceding-sibling::*)" # Lagrer antall søsken foran målnoden. replace: - - x: "$Move2D" + - x: "$Move2D" #Sier retningsordet (inn/ut av) - test: - - if: "$NumPrecedingSiblings=0" - then: [T: "basen"] # phrase(the 'base' of the power) - - else_if: "$Child2D/preceding-sibling::*[self::m:mprescripts]" # are we before mprescripts and hence are postscripts + - if: "$NumPrecedingSiblings=0" # Ingen søsken foran målnoden + then: [T: "base"] # phrase(the 'base' of the power) + - else_if: "$Child2D/preceding-sibling::*[self::m:mprescripts]" # Er vi etter -taggent. I så fall er vi i prescriptene. then: - test: # in postscripts -- base shifts by one - if: "$NumPrecedingSiblings mod 2 = 0" - then: [T: "nedre indeks"] # phrase(x with 'subscript' 2) - else: [T: "øvre indeks"] # phrase(x with 'superscript' 2) + if: "$NumPrecedingSiblings mod 2 = 0" + then: [T: "nedre venstre indeks"] # phrase(x with 'subscript' 2) + else: [T: "øvre venstre indeks"] # phrase(x with 'superscript' 2) else: - test: if: "$NumPrecedingSiblings mod 2 = 0" - then: [T: "øvre indeks"] # phrase(x with 'superscript' 2) - else: [T: "nedre indeks"] # phrase(x with 'subscript' 2) + then: [T: "øvre indeks"] # phrase(x with 'pre-superscript' 2) + else: [T: "nedre indeks"] # phrase(x with 'pre-subscript' 2) - pause: "medium" -- name: into-or-out-of - tag: mtd - match: "$Move2D = 'into'" - replace: - - x: "$Move2D" - - T: "kolonne" # phrase(the first 'column' in the table) - - x: "count($Child2D/preceding-sibling::*)+1" - - pause: "medium" - -- name: into-or-out-of - tag: [mtr, mlabeledtr] - match: "$Move2D = 'into'" +# Rules for speaking what happens when moving into or out of a notation +- name: into-or-out-of-default + tag: "*" + # saying "out of row n" is not very useful, so skip it + # match: "$Move2D != '' and @data-from-mathml and @data-from-mathml != name(.) and count(*)>1 and @data-from-mathml != 'mtable'" + match: "$Move2D != '' and not(self::m:math or @data-from-mathml = 'mtable' or @data-from-mathml = 'mtd') " replace: - - x: "$Move2D" - - x: "count($Child2D/preceding-sibling::*)+1" - - pause: "medium" + - with: + variables: + - PartNumber: "count($Child2D/preceding-sibling::*)" # antall søsken før målnoden + - PartName: "GetNavigationPartName(name(.), $PartNumber)" # finne navn på delen. F.eks. teller/nevner, base/eksponent + replace: + - x: "$Move2D" # inn/ut av + - test: + - if: "$PartName != ''" # hvis et navn på delen finnes + then: [x: "$PartName"] + - else_if: "count(*) = 1" # hvis noden har ett barn + then_test: + if: "$NavVerbosity = 'Verbose'" + then: [x: "translate(name(.), '-_', ' ')"] # e.g., "in absolute value" + else: + - T: "del" # phrase(the 'part' of the expression) + - x: "count($Child2D/preceding-sibling::*) + 1" + - pause: "medium" - name: default-move # nothing to do (not 2D) -- need to catch $Move2D though so rules based on NavCommand don't trigger @@ -200,20 +178,20 @@ then: - test: - if: "$PreviousNavCommand = 'ZoomIn'" - then: [T: "angre innzooming"] # phrase('undo zoom in') + then: [T: "angre zoom inn"] # phrase('undo zoom in') - else_if: "$PreviousNavCommand = 'ZoomOut'" - then: [T: "angre utzooming"] # phrase('undo zoom out') + then: [T: "angre zoom ut"] # phrase('undo zoom out') - else_if: "$PreviousNavCommand = 'ZoomInAll'" - then: [T: "angre innzooming hele veien"] # phrase('undo zooming in all the way') + then: [T: "angre zooming helt inn"] # phrase('undo zooming in all of the way') - else_if: "$PreviousNavCommand = 'ZoomOutAll'" - then: [T: "angre utzooming hele veien"] # phrase('undo zooming out all the way') + then: [T: "angre zooming helt ut"] # phrase('undo zooming out all of the way') - else_if: "$PreviousNavCommand = 'MovePrevious' or $PreviousNavCommand = 'MovePreviousZoom'" then: [T: "angre gå venstre"] # phrase('undo move left') - else_if: "$PreviousNavCommand = 'MoveNext' or $PreviousNavCommand = 'MoveNextZoom'" then: [T: "angre gå høyre"] # phrase('undo move right') - else_if: "$PreviousNavCommand = 'None'" then: [T: "ingen tidligere kommandoer"] # phrase('no previous command') - - pause: "long" + - pause: "medium" - set_variables: [NavNode: "@id"] # many times, for typographic reasons, people include punctuation at the end of a math expr @@ -229,46 +207,34 @@ # ********* ZoomIn *************** - name: zoom-in-leaf - tag: "*" match: "($NavCommand = 'ZoomIn' or $NavCommand = 'ZoomInAll') and IsNode(., 'leaf')" replace: + - with: + variables: [SayCommand: "string($NavVerbosity != 'Terse')"] + replace: [x: "."] - test: - if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" - then: [T: "innzoomet hele veien", pause: "long"] # phrase('zoomed in all of the way') - - test: - if: "$ReadZoomLevel!=-1" + if: "$ReadZoomLevel !=-1" then: - set_variables: [ReadZoomLevel: "0"] - - set_variables: [NavNode: "@id"] - -# special case of zooming into a matrix or determinant -- move to the first row -- name: zoom-in-matrix - - tag: mrow - match: - - "$NavCommand = 'ZoomIn' and count(*)=3 and " - - "*[2][self::m:mtable and (IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|'))]" - replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: [T: "zoom inn", pause: "long"] # phrase('zoom in') - - set_variables: [NavNode: "*[2]/*[1]/@id"] + - set_variables: + - NavNode: "@id" + - NavNodeOffset: "IfThenElse(string-length(.) > 1 and $MatchCounter = 1 and $NavNodeOffset = 0, '1', '0')" -# special case of zooming into a table -- move to the first row +# special case of zooming into a table -- move to the first row (if only one row, first column) - name: zoom-in-table - tag: mtable - match: "$NavCommand = 'ZoomIn'" + tag: "*" + match: "$NavCommand = 'ZoomIn' and (name(.) = 'mtable' or (count(*)=1 and *[1][@data-from-mathml='mtable']))" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: [T: "zoom inn", pause: "long"] # phrase('zoom in') - - set_variables: [NavNode: "*[1]/@id"] + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] + - set_variables: [NavNode: "IfThenElse(count(*)=1, (*[1]/*[1]/@id), (*[1]/@id))"] - name: zoom-in-mrow-in-math - # Moving to first or last is meaningless the 'math' has only an 'mrow' inside -- dig inside and do it again + # zooming in only once is meaningless because 'math' has only a single child and it was spoken at the math level -- dig inside and do it again tag: math - match: "count(*)=1 and ($NavCommand = 'ZoomIn' or $NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom')" + match: "$NavCommand = 'ZoomIn' or $NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom'" replace: - test: if: "$NavCommand = 'MovePreviousZoom'" @@ -276,33 +242,39 @@ else: [x: "*[1]"] - # For msqrt and menclose, if the single child isn't an mrow, don't zoom in + # Norwegian: Not sure if the word "in" should be translated or not. name: zoom-in-again - # If there is only one child, this isn't an interesting move -- zoom in again tag: "*" match: - "($NavCommand = 'ZoomIn' or " - " ($NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and $NavMode='Enhanced') and " - - "count(*)=1 and (*[1][self::m:mrow] and not(self::m:msqrt or self::m:menclose))" + - "count(*)=1 and + (*[1][self::m:mrow or @data-from-mathml='mrow'] and + not(@data-from-mathml='msqrt' or self::m:msqrt or @data-from-mathml='menclose' or self::m:menclose))" # nåværende node har ett barn som er en . Den nåværende noden er ikke msqrt ekker menclose. replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: [T: "zoom inn", pause: "long"] # phrase('zoom in') - with: - variables: [MatchCounter: "$MatchCounter + 1"] - replace: - - test: - if: "$NavCommand = 'MovePreviousZoom'" - then: [x: "*[last()]"] - else: [x: "*[1]"] + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] # hvis verbosity er verbose, blir SayCommand satt til true, ellers false + replace: [x: "."] # kjør videre med nåverende node + - test: + if: "not(*[1][self::m:mrow or @data-from-mathml='mrow'])" + then: + - with: + # Setter Move2d til "i". + # Setter Child2d til siste barn hvis kommandoen er "MovePreviousZoom", ellers første barn. + variables: [Move2D: "'i'", Child2D: "IfThenElse($NavCommand = 'MovePreviousZoom', (*[last()]), (*[1]))"] # phrase('in' the denominator) + replace: [x: "IfThenElse($NavCommand = 'MovePreviousZoom', 1, $Child2D)"] + - test: + if: "$NavCommand = 'MovePreviousZoom'" + then: [x: "*[last()]"] + else: [x: "*[1]"] - name: zoom-in-enhanced - tag: "*" match: "$NavCommand = 'ZoomIn' and $NavMode='Enhanced'" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: [T: "zoom inn", pause: "long"] # phrase('zoom in') + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: - if: "self::m:mtr or self::m:mlabeledtr" then: @@ -310,89 +282,91 @@ variables: [Move2D: "'i'", Child2D: "*[1]/*[1]"] # phrase('in' the denominator) replace: [x: "."] - set_variables: [NavNode: "*[1]/*[1]/@id"] # skip mtd - - else_if: "*[1][self::m:mrow and IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false)]" # auto zoom + - else_if: "*[1][self::m:mrow and (IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false))]" # auto zoom then: - with: - variables: [Move2D: "'i'", Child2D: "*[1]/*[2]"] # phrase('in' the denominator) + variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) replace: [x: "."] - - set_variables: [NavNode: "*[1]/*[2]/@id"] # skip mtd + - set_variables: [NavNode: "*[1]/*[2]/@id"] # skip parens/brackets else: - with: variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) replace: [x: "."] - - set_variables: [NavNode: "*[1]/@id"] + # "(...)" to get around some weird parse bug" + - set_variables: + - NavNode: "*[1]/@id" + - NavNodeOffset: "IfThenElse(*[1]/@data-id-offset, (*[1]/@data-id-offset), '0')" -- name: zoom-in-2D-not-enhanced +- name: zoom-in-simple tag: "*" - match: "$NavCommand = 'ZoomIn' and $NavMode!='Enhanced' and IsNode(., '2D')" + match: "$NavCommand = 'ZoomIn' and $NavMode='Simple'" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: [T: "zoom inn", pause: "long"] # phrase('zoom in') - with: - variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] replace: [x: "."] - - with: - variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"] - replace: [x: "*[1]"] + - test: + if: "$MatchCounter > 1 and IsNode(., '2D')" + then: + - set_variables: # time to stop, not going "in" to next thing, so before "Move2D" + - NavNode: "@id" + - NavNodeOffset: "IfThenElse(@data-id-offset, @data-id-offset, '0')" + else: + - with: + variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) + replace: [x: "."] + - x: "*[1]" -- name: zoom-in-default + # At this point, we are zooming in on a non-2D element, non-leaf in Character mode +- name: zoom-in-2D-character tag: "*" - match: "$NavCommand = 'ZoomIn'" + match: "$NavCommand = 'ZoomIn' and (IsNode(., '2D') or not(IsNode(., 'mathml')))" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: [T: "zoom inn", pause: "long"] # phrase('zoom in') - with: - variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] + - with: + variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) replace: [x: "."] - test: - if: "$NavMode='Character'" + if: "$NavMode = 'Simple'" then: + - set_variables: [NavNode: "*[1]/@id"] + else: - with: - variables: [MatchCounter: "$MatchCounter + 1"] + variables: [NavCommand: "'MoveNextZoom'"] replace: [x: "*[1]"] - else_test: - if: "self::m:mtd" - then: [x: "*[1]"] - else: - - test: - if: "$ReadZoomLevel!=-1" - then: - - set_variables: [ReadZoomLevel: "DistanceFromLeaf(*[1], true, $NavMode!='Character')"] - - set_variables: [NavNode: "*[1]/@id"] + + # At this point, we are zooming in on a non-2D element, non-leaf in Character mode +- name: zoom-in-default + tag: "*" + match: "$NavCommand = 'ZoomIn'" + replace: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] + - x: "*[1]" - name: zoom-in-all-default tag: "*" match: "$NavCommand = 'ZoomInAll'" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: [T: "zoom inn hele veien", pause: "medium"] # phrase('zoom in all the way') - with: - variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] replace: [x: "."] - with: - variables: [MatchCounter: "$MatchCounter + 1"] - replace: [x: "*[1]"] + variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) + replace: [x: "."] + - x: "*[1]" - name: zoom-out tag: math match: "$NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll'" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" - then: [T: "utzoomet hele veien", pause: "long"] # phrase('zoomed out all the the way') + - with: + variables: [SayCommand: "string($NavVerbosity != 'Terse')"] + replace: [x: "."] - set_variables: [NavNode: "*[1]/@id"] # no-op for $NavCommand = 'ZoomOut' -- name: zoom-out-top - tag: "*" - match: - - "($NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll') and" - - "parent::m:math " - replace: - - x: ".." # let math rule deal with it - - name: skip-punct-at-end-zoom-out tag: mrow match: @@ -402,19 +376,25 @@ replace: - x: ".." +- name: zoom-out-top + tag: "*" + match: + - "($NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll') and" + - "parent::m:math" + replace: + - x: ".." # let math rule deal with it + - name: zoom-out-all-default tag: "*" match: "$NavCommand = 'ZoomOutAll'" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" - then: [T: "utzoomet hele veien", pause: "medium"] # phrase('zoomed out all the the way') - with: - variables: [Move2D: "'ut av'", Child2D: "."] - replace: [x: ".."] + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - with: - variables: [MatchCounter: "$MatchCounter + 1"] + variables: [Move2D: "'out of'", Child2D: "."] replace: [x: ".."] + - x: ".." # deal with internal zooming: MoveNextZoom and MovePreviousZoom @@ -425,13 +405,16 @@ - "($NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and " - "$NavMode = 'Enhanced'" replace: - # don't bother with MatchCounter since we only get here if > 1 - with: variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) replace: [x: "."] - test: - - if: "count(*)> 1 or IsNode(., 'leaf') or self::m:msqrt or self::m:menclose" - then: [set_variables: [NavNode: "@id"]] + - if: "count(*)> 1 or IsNode(., 'leaf') or + @data-from-mathml='msqrt' or self::m:msqrt or @data-from-mathml='menclose' or self::m:menclose" + then: + - set_variables: + - NavNode: "@id" + - NavNodeOffset: "IfThenElse(@data-id-offset, @data-id-offset, '0')" else: [x: "*[1]"] - name: move-next-zoom-not-enhanced @@ -441,12 +424,14 @@ replace: #don't bother with MatchCounter since we only get here if > 1 - test: - if: "$ReadZoomLevel >= DistanceFromLeaf(., false, $NavMode!='Character')" + if: "IsNode(., 'leaf') or $ReadZoomLevel >= DistanceFromLeaf(., false, $NavMode!='Character')" then: # - with: # variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) # replace: [x: ".."] - - set_variables: [NavNode: "@id"] + - set_variables: + - NavNode: "@id" + - NavNodeOffset: "IfThenElse(@data-id-offset, @data-id-offset, '0')" else: - with: variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) @@ -463,9 +448,11 @@ if: "$ReadZoomLevel >= DistanceFromLeaf(., true, $NavMode!='Character')" then: # - with: - # variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) + # variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) # replace: [x: ".."] - - set_variables: [NavNode: "@id"] + - set_variables: + - NavNode: "@id" + - NavNodeOffset: "IfThenElse(@data-id-offset, @data-id-offset, '0')" else: - with: variables: [Move2D: "'i'", Child2D: "*[last()]"] # phrase('in' the denominator) @@ -474,20 +461,20 @@ # ********* ZoomOut *************** - name: zoom-out-default - - tag: mtd match: "$Move2D = '' and ($NavCommand = 'ZoomOut')" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: [T: "zoom ut", pause: "medium"] # phrase('zoom out' of expression) + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] # we need to speak it here - - T: "rad" # phrase(the first 'row' of the matrix) - # if we let the speech rules speak the row, it is given just the MathML for the row, so the row # will always be '1' - - x: "count(../preceding-sibling::*)+1" - - pause: medium - - set_variables: [NavNode: "../@id"] + # - t: "row" # phrase(the first 'row' of the matrix) + # # if we let the speech rules speak the row, it is given just the MathML for the row, so the row # will always be '1' + # - x: "count(../preceding-sibling::*)+1" + # - pause: medium + - set_variables: + - NavNode: "../@id" + - NavNodeOffset: "IfThenElse(../@data-id-offset, ../@data-id-offset, '0')" - name: zoom-out # a row around a single element -- these might duplicate the position/offset, so we jump an extra level here @@ -495,26 +482,29 @@ match: "$NavCommand = 'ZoomOut'" replace: - with: - variables: [MatchCounter: "$MatchCounter + 1"] - replace: - - test: - if: "$MatchCounter = 1 and $NavVerbosity = 'Verbose'" - then: [T: "zoom ut", pause: "medium"] # phrase('zoom out' of the expression) + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] + - test: + - if: "$NavNodeOffset > 0 and IsNode(., 'leaf')" # Inside leaf -- just reset offset, intent offset doesn't change + then: + - set_variables: [NavNodeOffset: "0"] + # NavNode remains the same + - else_if: "$NavMode='Enhanced' and parent::*[self::m:mrow and (IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false))]" + then: [x: ".."] # auto-zoom: move out a level and retry + else: + - with: + variables: [Move2D: "'out of'", Child2D: "."] # phrase('out of' the denominator) + replace: [x: ".."] - test: - if: "$NavMode='Enhanced' and parent::*[self::m:mrow and IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false)]" - then: [x: ".."] # auto-zoom: move out a level and retry + if: "parent::m:mtd" + then: [x: ".."] else: - - with: - variables: [Move2D: "'ut av'", Child2D: "."] - replace: [x: ".."] - test: - if: "parent::m:mtd" - then: [x: ".."] - else: - - test: - if: "$ReadZoomLevel!=-1" - then: [set_variables: [ReadZoomLevel: "DistanceFromLeaf(.., true, $NavMode!='Character')"]] - - set_variables: [NavNode: "../@id"] + if: "DEBUG($ReadZoomLevel)!=-1" + then: [set_variables: [ReadZoomLevel: "DistanceFromLeaf(.., true, $NavMode!='Character')"]] + - set_variables: + - NavNode: "../@id" + - NavNodeOffset: "IfThenElse(../@data-id-offset, ../@data-id-offset, '0')" # ********* MoveStart/End *************** - name: math-move-to-start-or-end @@ -529,42 +519,56 @@ then: - test: - if: "$NavCommand = 'MoveStart'" - then: [T: "gå til start matematikk"] # phrase('move to start of math') + then: [T: "gå til starten av uttrykket"] # phrase('move to start of math') - else_if: "$NavCommand = 'MoveLineStart'" - then: [T: "gå til starten av raden"] # phrase('move to start of line') + then: [T: "gå til starten av linja"] # phrase('move to start of line') - else_if: "$NavCommand = 'MoveEnd'" - then: [T: "gå til slutt matematikk"] # phrase('move to end of math') - else: [T: "gå til slutten av raden"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') + then: [T: "gå til slutten av uttrykket"] # phrase('move to end of math') + else: [T: "gå til slutten av linja"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') - pause: "medium" - test: if: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart'" then: # move inside of the mrow inside of 'math' or inside the fraction, etc (hence two levels down) + # Note: an apparent bug in the xpath code doesn't let me use IfThenElse for the 2 if: then: below - with: variables: [NavCommand: "'MoveNextZoom'"] - replace: [x: "*[1]/*[1]"] + replace: + - test: + if: "*[1]/*[1]" # could be a x, so no grandchild + then: [x: "*[1]/*[1]"] + else: [x: "*[1]"] else: - with: variables: [NavCommand: "'MovePreviousZoom'"] - replace: [x: "*[last()]/*[last()]"] + replace: + - test: + if: "*[last()]/*[last()]" # could be a x, so no grandchild + then: [x: "*[last()]/*[last()]"] + else: [x: "*[last()]"] # We stop when the parent is 2d (e.g., frac), but not if in leaf base of msub/msup/msubsup/mmultiscripts because that's really on the same line - name: move-to-start-or-end-2d tag: "*" match: - "($NavCommand = 'MoveLineStart' or $NavCommand = 'MoveLineEnd') and IsNode(.., '2D') and" - - "not( IsNode(., 'leaf') and (parent::m:msub or parent::m:msup or parent::m:msubsup or parent::m:mmultiscripts) )" + - "not( IsNode(., 'leaf') and" + - " parent::*[1][self::m:msub or self::m:msup or self::m:msubsup or self::m:mmultiscripts or" + - " @data-from-mathml and" + - " (@data-from-mathml='msub' or @data-from-mathml='msup' or" + - " @data-from-mathml='msubsup' or @data-from-mathml='mmultiscripts')" + - " ] )" replace: - test: if: "$NavVerbosity = 'Verbose'" then: - test: if: "$NavCommand = 'MoveLineStart'" - then: [T: "gå til starten av raden"] # phrase('move to start of line') - else: [T: "gå til slutten av raden"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') + then: [T: "gå til starten av linja"] # phrase('move to start of line') + else: [T: "gå til slutten av linja"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') - pause: "medium" - test: - if: "self::m:mrow" + if: "self::m:mrow or @data-from-mathml = 'mrow'" then_test: if: "$NavCommand = 'MoveLineStart'" then: @@ -628,7 +632,7 @@ else: - set_variables: [NavNode: "preceding-sibling::*[1]/*[1]/@id"] else: - - T: "ingen foregående kolonner" # phrase('no previous column' in the table) + - t: "ingen foregående kolonner" # phrase('no previous column' in the table) - set_variables: [SpeakExpression: "'false'"] - name: move-cell-next @@ -658,7 +662,7 @@ else: - set_variables: [NavNode: "following-sibling::*[1]/*[1]/@id"] else: - - T: "ingen påfølgende kolonner" # phrase('no next column' in the table) + - T: "ingen flere kolonner" # phrase('no next column' in the table) - set_variables: [SpeakExpression: "'false'"] - name: move-cell-up @@ -710,7 +714,7 @@ - test: if: "$NavVerbosity = 'Verbose'" then: - - T: "gå ned" # phrase('move down to the next row in the table) + - T: "gå ned" # phrase('move down' to the next row in the table) - pause: short - test: if: "$NavVerbosity != 'Terse'" @@ -730,27 +734,21 @@ else: - set_variables: [NavNode: "../following-sibling::*[1]/*[$Column]/*[1]/@id"] else: - - T: "ingen påfølgende rader" # phrase('no next row' in the table) + - T: "ingen flere rader" # phrase('no next row' in the table) - set_variables: [SpeakExpression: "'false'"] - name: move-cell-up tag: [mtr, mlabeledtr] match: "$NavCommand='MoveCellUp'" replace: + - test: + if: "$NavVerbosity = 'Verbose'" + then: + - T: "gå til forrige rad" # phrase('move to previous row' in the table) + - pause: medium - test: if: "preceding-sibling::*" then: - - test: - if: "$NavVerbosity = 'Verbose'" - then: - - T: "gå opp" # phrase('move up' to the previous row in the table) - - pause: medium - - test: - if: "$NavVerbosity != 'Terse'" - then: - - T: "rad" # phrase(the previous 'row' in the table) - - x: "count(preceding-sibling::*)" - - pause: medium - test: if: "$NavMode='Character'" then: @@ -767,20 +765,14 @@ tag: [mtr, mlabeledtr] match: "$NavCommand='MoveCellDown'" replace: + - test: + if: "$NavVerbosity = 'Verbose'" + then: + - T: "gå til neste rad" # phrase('move to next row' in the table) + - pause: medium - test: if: "following-sibling::*" then: - - test: - if: "$NavVerbosity = 'Verbose'" - then: - - T: "gå ned" # phrase('move down' to the next row in the table) - - pause: medium - - test: - if: "$NavVerbosity != 'Terse'" - then: - - T: "rad" # phrase(the previous 'row' in the table) - - x: "count(preceding-sibling::*)+2" - - pause: medium - test: if: "$NavMode='Character'" then: @@ -790,9 +782,35 @@ else: - set_variables: [NavNode: "following-sibling::*[1]/@id"] else: - - T: "ingen påfølgende rader" # phrase('no next row' in the table) + - T: "ingen flere rader" # phrase('no next row' in the table) - set_variables: [SpeakExpression: "'false'"] +- name: move-cell-previous + # if a row is selected, there is no previous/next column, so this is trivial + tag: [mtr, mlabeledtr] + match: "$NavCommand='MoveCellPrevious'" + replace: + - test: + if: "$NavVerbosity = 'Verbose'" + then: + - T: "gå til forrige kolonne" # phrase('move to previous column' in the table) + - pause: medium + - T: "ingen foregående kolonner" # phrase('no previous column' in the table) + - set_variables: [SpeakExpression: "'false'"] + +- name: move-cell-next + # if a row is selected, there is no previous/next column, so this is trivial + tag: [mtr, mlabeledtr] + match: "$NavCommand='MoveCellNext'" + replace: + - test: + if: "$NavVerbosity = 'Verbose'" + then: + - T: "gå til neste kolonne" # phrase('move to next column' in the table) + - pause: medium + - T: "ingen flere kolonner" # phrase('no next row' in the table) + - set_variables: [SpeakExpression: "'false'"] + - name: default-read-cell tag: "*" match: "$NavCommand='ReadCellCurrent'" @@ -806,13 +824,14 @@ - test: if: "$NavVerbosity = 'Verbose'" then: - - T: "les nåværende verdi" # phrase('read current entry' in the table) + - T: "les nåværende celle" # phrase('read current entry' in the table) - pause: medium - test: if: "$NavVerbosity != 'Terse'" then: - T: "rad" # phrase(the previous 'row' in the table) - x: "count($MTD[1]/../preceding-sibling::*)+1" + - pause: short - T: "kolonne" # phrase(the previous 'column' in the table) - x: "count($MTD[1]/preceding-sibling::*)+1" - pause: short @@ -822,229 +841,7 @@ - pause: long - set_variables: [SpeakExpression: "'false'"] -# mtd ? ( $NavCommand='MoveColumnStart' ) -# => MoveColStart { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^match[0][index(match)][0].dfs; -# ::EndPosition = ^^match[0][index(match)][0].offset; -# }; - -# mtd ? ( $NavCommand='MoveColumnEnd' ) -# => MoveColEnd { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^match[count(^^match)-1][index(match)][0].dfs; -# ::EndPosition = ^^match[count(^^match)-1][index(match)][0].offset; -# }; - - - -# # Rules for columnar math (mstack and mlongdiv) -- each row is an msrow or mscarries except for the start of mlongdiv -# # FIX: not dealing with different number of digits on different lines -# # FIX: not dealing with + (etc) on same line if they are on the right side (Dutch, others) -# # FIX: not dealing with intervening msline (say it and move on??) -# # FIX: not dealing with carries well -# # FIX: not dealing with navigation of first three children of mlongdiv -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') && has_previous(match) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "previous"; -# ::StartPosition = previous(match).dfs; -# ::EndPosition = previous(match).offset; -# }; - -# # no previous child -- in first column -- don't move -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious' ) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "previous"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; - -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') && has_next(match) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "next"; -# ::StartPosition = next(match).dfs; -# ::EndPosition = next(match).offset; -# }; - -# # no next child -- in first column -- don't move -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext' ) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "next"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; - -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveCellUp' && has_previous(^^match) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "up"; -# ::StartPosition = ^^^match[index(^^match)-1][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[index(^^match)-1][-1][index(match)-count(^match)].offset; -# }; - -# # no previous child -- in first column -- don't move -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveCellUp' ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "up"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; - -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveCellDown' && has_next(^^match) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "down"; -# ::StartPosition = ^^^match[index(^^match)+1][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[index(^^match)+1][-1][index(match)-count(^match)].offset; -# }; - -# # no previous child -- in first column -- don't move -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveCellDown' ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "down"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; - -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveColumnStart' ) -# => MoveColStart { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^^match[0][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[0][-1][index(match)-count(^match)].offset; -# }; - -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveColumnEnd' ) -# => MoveColEnd { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].offset; -# }; - -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') && has_previous(match) ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "previous"; -# ::StartPosition = previous(match).dfs; -# ::EndPosition = previous(match).offset; -# }; - -# # no previous child -- in first column -- don't move -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "previous"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; - -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') && has_next(match) ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "next"; -# ::StartPosition = next(match).dfs; -# ::EndPosition = next(match).offset; -# }; - -# # no next child -- in last column -- don't move -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "next"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; - -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# $NavCommand='MoveCellUp' && has_previous(^match) ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "up"; -# ::StartPosition = ^^match[index(^match)-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^match[index(^match)-1][index(match)-count(^match)].offset; -# }; - -# # no previous child -- in first row -- don't move -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# $NavCommand='MoveCellUp' ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "up"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; - -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# $NavCommand='MoveCellDown' && has_next(^match) ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "down"; -# ::StartPosition = ^^match[index(^match)+1][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^match[index(^match)+1][-1][index(match)-count(^match)].offset; -# }; - -# # no next child -- in last row -- don't move -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# $NavCommand='MoveCellDown' ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "down"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; - -# mn ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveColumnStart' ) -# => MoveColStart { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^^match[0][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[0][-1][index(match)-count(^match)].offset; -# }; - -# mn ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveColumnEnd' ) -# => MoveColEnd { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].offset; -# }; - - - -- name: default-cell-move +- name: default-cell-move tag: "*" match: @@ -1062,7 +859,26 @@ - pause: long - set_variables: [SpeakExpression: "'false'"] -# ======== Move/Read/Describe Next rules ================= +- name: move-next-character + tag: [mn, mi, mtext] + match: + - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext' or $NavCommand = 'MoveNextZoom') and" + - "$NavNodeOffset > 0 and" + - "($NavNodeOffset < string-length(.) or name(EdgeNode(., 'right', 'math'))!='math')" # not at edge of math + replace: + - test: + if: "$NavNodeOffset < string-length(.)" + then: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] + - set_variables: [NavNodeOffset: "$NavNodeOffset + 1"] + else: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] + - set_variables: [NavNodeOffset: "0"] + - x: "." # skip 'none' - name: move-next-none @@ -1080,36 +896,12 @@ then: [x: "$Following"] else: - with: - variables: [Move2D: "'i'", Child2D: "$Following"] # phrase('in' the denominator) + variables: [Move2D: "'in'", Child2D: "$Following"] # phrase('in' the denominator) replace: [x: ".."] - with: variables: [NavCommand: "'MoveNextZoom'"] replace: [x: "$Following"] -# skip 'none' -- name: move-previous-none - tag: [none, mprescripts] - match: - - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious' or $NavCommand = 'MovePreviousZoom') and" - - "parent::*[1][name(.)='mmultiscripts'] and preceding-sibling::*" - replace: - - with: - variables: [Preceding: "preceding-sibling::*[1]"] - replace: - # two 'none's in a row -- move over and try again; one 'none', zoom in on preceding - - test: - if: "$Preceding[name(.)='none']" - then: [x: "$Preceding"] - else: - - with: - variables: [Move2D: "'i'", Child2D: "$Preceding"] # phrase('in' the denominator) - replace: [x: ".."] - - with: - variables: [NavCommand: "'MovePreviousZoom'"] - replace: [x: "$Preceding"] - - - # skip invisible chars except for Enhanced mode when "times" should be read - name: move-next-invisible tag: "*" @@ -1117,24 +909,14 @@ - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" - "following-sibling::*[1][name(.)='mo' and translate(., '\u2061\u2062\u2063\u2064', '')='']" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: - - test: - - if: "$NavCommand = 'MoveNext'" - then: [T: "gå"] # phrase('move' to next entry in table) - - else_if: "$NavCommand = 'ReadNext'" - then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) - - T: "høyre" # phrase(move 'right') # phrase(move 'right') - - pause: short - with: - variables: [MatchCounter: "$MatchCounter + 1"] - replace: - - test: - if: "following-sibling::*[1][.='\u2062' or .='\u2064'] and $NavMode='Enhanced'" # invisible times and plus - then: [set_variables: [NavNode: "following-sibling::*[1]/@id"]] - else: [x: "following-sibling::*[1]"] + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] + - test: + if: "following-sibling::*[1][.='\u2062' or .='\u2064'] and + ($NavMode='Enhanced' or ($NavMode='Simple' and following-sibling::*[2][not(IsNode(., 'mathml'))]))" # invisible times and plus + then: [set_variables: [NavNode: "following-sibling::*[1]/@id"]] + else: [x: "following-sibling::*[1]"] - name: move-next-no-auto-zoom-at-edge # at edge of 2D and in a mode where moving right isn't an option @@ -1143,11 +925,15 @@ match: "$NavCommand = 'MoveNext' and $NavMode!='Character' and not($AutoZoomOut) and $EdgeNode/@id!=@id" replace: - test: - if: "$MatchCounter = 0 and $NavVerbosity != 'Terse' and $NavCommand = 'MoveNext'" + if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" then: - - T: "kan ikke gå til høyre" # phrase('cannot move right') + - T: "kan ikke gå høyre" # phrase('cannot move right') + - pause: medium - with: - variables: [Move2D: "'end of'", Child2D: "$EdgeNode/*[last()]"] #Should "end of" be translated? + variables: + - Move2D: "'end of'" + - Child2D: "$EdgeNode/*[last()]" + - MatchCounter: $MatchCounter + 1 replace: [x: "$EdgeNode"] - pause: long - set_variables: [SpeakExpression: "'false'"] @@ -1160,18 +946,20 @@ - "(self::m:math or name(EdgeNode(., 'right', 'math'))='math')" # at edge of math replace: - test: - if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" + if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" then: - T: "kan ikke" # phrase('cannot' move right in expression) - test: - if: "$NavCommand = 'MoveNext'" - then: [T: "gå"] # phrase('move' to next entry in table) + then: [t: "gå"] # phrase('move' to next entry in table) - else_if: "$NavCommand = 'ReadNext'" - then: [T: "lese"] # phrase('read' next entry in table) - else: [T: "beskrive"] # phrase('describe' next entry in table) - - T: "høyre, slutt matematikk" # phrase(move 'right, end of math') - - pause: long - - set_variables: [SpeakExpression: "'false'"] + then: [t: "lese"] # phrase('read' next entry in table) + else: [t: "beskrive"] # phrase('describe' next entry in table) + - T: "høyre" # phrase(move 'right') + - pause: short + - T: "slutt på uttrykk" # phrase(move 'end of math') + - pause: long + - set_variables: [SpeakExpression: "'false'"] - name: move-next-auto-zoom-up-one-level # Last child or in auto-zoom'd in-- move up a level and try again @@ -1185,48 +973,34 @@ - " )" - ")" replace: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" + if: "following-sibling::*" then: - - test: - - if: "$NavCommand = 'MoveNext'" - then: [T: "gå"] # phrase('move' to next entry in table) - - else_if: "$NavCommand = 'ReadNext'" - then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) - - T: "høyre" # phrase(move 'right') # phrase(move 'right') - - pause: short - - with: - variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNext'"] - replace: - - test: - if: "following-sibling::*" - then: - - with: - variables: [Move2D: "'i'", Child2D: "."] # phrase('in' the denominator) - replace: [x: ".."] - else: - - with: - variables: [Move2D: "'ut av'", Child2D: "."] - replace: [x: ".."] - - test: - if: "following-sibling::*" - then: - - x: ".." # move out of parens - else: - - x: ".." + - with: + variables: [Move2D: "'in'", Child2D: "."] # phrase('in' the denominator) + replace: [x: ".."] + else: + - with: + variables: [Move2D: "'out of'", Child2D: "."] + replace: [x: ".."] + - x: ".." # At this point, if XXXNext, then we know there is must be a right sibling - name: move-next-default tag: mtd match: "$Move2D = '' and ($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext')" replace: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: - # can't get here with MatchCounter=0, so no need to echo command if: "following-sibling::*" then: - test: - if: "$NavVerbosity != 'Terse'" + if: "$NavVerbosity = 'Verbose'" then: - T: "kolonne" # phrase(the previous 'column' in the table) - x: "count(preceding-sibling::*)+2" @@ -1243,25 +1017,21 @@ - name: move-next-default tag: [mtr, mlabeledtr] - match: "$Move2D = '' and ($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext')" + match: "$Move2D = '' and + ($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and + following-sibling::*" replace: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: - # can't get here with MatchCounter=0, so no need to echo command - if: "following-sibling::*" + if: "$NavMode = 'Character'" then: - - T: "rad" # phrase(the previous 'row' in the table) - - x: "count(preceding-sibling::*)+2" - - T: "kolonne 1" # phrase('column 1' in the table) - - pause: medium - - test: - if: "$NavMode = 'Character'" - then: - - with: - variables: [NavCommand: "'MoveNextZoom'"] - replace: [x: "following-sibling::*[1]"] - else: - - set_variables: [NavNode: "following-sibling::*[1]/*[1]/*[1]/@id"] - else: [x: ".."] # try again for after + - with: + variables: [NavCommand: "'MoveNextZoom'"] + replace: [x: "following-sibling::*[1]"] + else: + - set_variables: [NavNode: "following-sibling::*[1]/@id"] - name: move-next-auto-zoom-parens # auto-zoom into next child if next child is parenthesized expr @@ -1271,20 +1041,12 @@ - "$NavMode='Enhanced' and" - "parent::m:mrow and following-sibling::* and" - "following-sibling::*[1][self::m:mrow and count(*)=3 and " #exclude empty parens - - " (IsBracketed(., '(', ')') or IsBracketed(., '[', ']'))" - - " ]" + - " (IsBracketed(., '(', ')') or IsBracketed(., '[', ']'))" + - " ]" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: - - test: - - if: "$NavCommand = 'MoveNext'" - then: [T: "gå"] # phrase('move' to next entry in table) - - else_if: "$NavCommand = 'ReadNext'" - then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) - - T: "høyre" # phrase(move 'right') # phrase(move 'right') - - pause: short + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - set_variables: [NavNode: "following-sibling::*[1]/*[2]/@id"] # normal cases for MoveNext @@ -1295,60 +1057,68 @@ - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" - "$ReadZoomLevel>=0" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: - - test: - - if: "$NavCommand = 'MoveNext'" - then: [T: "gå"] # phrase('move' to next entry in table) - - else_if: "$NavCommand = 'ReadNext'" - then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) - - T: "høyre" # phrase(move 'right') # phrase(move 'right') - - pause: short + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: # if in base (nothing before), we must be moving to a script, so "in" will be said if: "preceding-sibling::* and following-sibling::*[1][name(.)='none']" then: - with: - variables: [Move2D: "'ut av'", Child2D: "."] + variables: [Move2D: "'out of'", Child2D: "."] replace: [x: ".."] - - with: - variables: [MatchCounter: "$MatchCounter + 1"] - replace: [x: "following-sibling::*[1]"] # skip over 'none' + - x: "following-sibling::*[1]" else: - with: - variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) + variables: [Move2D: "'in'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) replace: [x: ".."] - with: - variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"] + variables: [NavCommand: "'MoveNextZoom'"] replace: [x: "following-sibling::*[1]"] - name: move-next-default tag: "*" match: "$NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext'" replace: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: + if: "following-sibling::*[1][@data-from-mathml='none' or @data-from-mathml='mprescripts']" + then: [x: "following-sibling::*[1]"] + else: - test: - - if: "$NavCommand = 'MoveNext'" - then: [T: "gå"] # phrase('move' to next entry in table) - - else_if: "$NavCommand = 'ReadNext'" - then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) - - T: "høyre" # phrase(move 'right') # phrase(move 'right') - - pause: short - - test: - if: "IsNode(.., '2D')" - then: - - with: - variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) - replace: [x: ".."] - - set_variables: [NavNode: "following-sibling::*[1]/@id"] + if: "IsNode(.., '2D') or not(IsNode(.., 'mathml'))" + then: + - with: + variables: [Move2D: "'in'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) + replace: [x: ".."] + - set_variables: [NavNode: "following-sibling::*[1]/@id"] # ======== Move/Read/Describe Previous rules ================= +# skip 'none' +- name: move-previous-none + tag: [none, mprescripts] + match: + - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious' or $NavCommand = 'MovePreviousZoom') and" + - "parent::*[1][name(.)='mmultiscripts'] and preceding-sibling::*" + replace: + - with: + variables: [Preceding: "preceding-sibling::*[1]"] + replace: + # two 'none's in a row -- move over and try again; one 'none', zoom in on preceding + - test: + if: "$Preceding[name(.)='none']" + then: [x: "$Preceding"] + else: + - with: + variables: [Move2D: "'in'", Child2D: "$Preceding"] # phrase('in' the denominator) + replace: [x: ".."] + - with: + variables: [NavCommand: "'MovePreviousZoom'"] + replace: [x: "$Preceding"] + # skip invisible chars except for Enhanced mode when "times" should be read - name: move-previous-invisible tag: "*" @@ -1356,41 +1126,34 @@ - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" - "preceding-sibling::*[1][name(.)='mo' and translate(., '\u2061\u2062\u2063\u2064', '')='']" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: - - test: - - if: "$NavCommand = 'MovePrevious'" - then: [T: "gå"] # phrase('move' to next entry in table) - - else_if: "$NavCommand = 'ReadPrevious'" - then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) - - T: "venstre" # phrase(move 'left') - - pause: short - with: - variables: [MatchCounter: "$MatchCounter + 1"] - replace: - - test: - if: "preceding-sibling::*[1][.='\u2062' or .='\u2064'] and $NavMode='Enhanced'" # invisible times and plus - then: [set_variables: [NavNode: "preceding-sibling::*[1]/@id"]] - else: [x: "preceding-sibling::*[1]"] + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] + - test: + if: "preceding-sibling::*[1][.='\u2062' or .='\u2064'] and $NavMode='Enhanced'" # invisible times and plus + then: [set_variables: [NavNode: "preceding-sibling::*[1]/@id"]] + else: [x: "preceding-sibling::*[1]"] -# two rules for when can't move right +# two rules for when can't move left - name: move-previous-no-auto-zoom-at-edge - # at edge of 2D and in a mode where moving right isn't an option + # at edge of 2D and in a mode where moving left isn't an option tag: "*" variables: [EdgeNode: "EdgeNode(., 'left', '2D')"] match: "$NavCommand = 'MovePrevious' and $NavMode!='Character' and not($AutoZoomOut) and $EdgeNode/@id!=@id" replace: - test: - if: "$MatchCounter = 0 and $NavVerbosity != 'Terse' and $NavCommand = 'MovePrevious'" + if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose' and $NavCommand = 'MovePrevious'" then: - - T: "kan ikke gå til venstre" # phrase('cannot move left' in expression) + - T: "kan ikke gå venstre" # phrase('cannot move left' in expression) + - pause: medium - with: - variables: [Move2D: "'end of'", Child2D: "$EdgeNode/*[1]"] #Should "end of" be translated? + variables: + - Move2D: "'end of'" + - Child2D: "$EdgeNode/*[1]" + - MatchCounter: $MatchCounter + 1 replace: [x: "$EdgeNode"] - pause: long - + - name: move-previous-no-auto-zoom-at-edge-of-math # at edge of math -- no where to go (must be after we rule out being at the edge of 2D) because we want to speak that tag: "*" @@ -1398,7 +1161,7 @@ - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" - "(self::m:math or name(EdgeNode(., 'left', 'math'))='math')" replace: - - T: "start matematikk" # phrase('start of math') + - T: "start på uttrykk" # phrase('start of math') - pause: long - set_variables: [SpeakExpression: "'false'"] @@ -1409,12 +1172,37 @@ - "name(EdgeNode(., 'left', 'math'))='math'" # at edge of math replace: - test: - if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" + if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" then: - - T: "kan ikke gå til venstre, start matematikk" # phrase('cannot move left, start of math') - - pause: long + - T: "kan ikke gå venstre" # phrase('cannot move left') + - pause: short + - with: + variables: [Move2D: "'start of'", Child2D: "."] + replace: [x: "."] + - pause: long - set_variables: [SpeakExpression: "'false'"] +- name: move-prev-character + tag: [mn, mi, mtext] + match: + - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious' or $NavCommand = 'MovePreviousZoom') and" + - "$NavNodeOffset > 0 and" + - "($NavNodeOffset > 1 or name(EdgeNode(., 'left', 'math'))!='math')" # not at edge of math + replace: + - test: + if: "$NavNodeOffset > 1" + then: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] + - set_variables: [NavNodeOffset: "$NavNodeOffset - 1"] + else: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] + - set_variables: [NavNodeOffset: "0"] + - x: "." + - name: move-previous-auto-zoom-up-one-level # Last child or in auto-zoom'd in-- move up a level and try again # Note: we've already checked the for the case where we are at an edge and should not AutoZoomOut @@ -1427,36 +1215,20 @@ - " )" - ")" replace: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" + if: "preceding-sibling::*" then: - - test: - - if: "$NavCommand = 'MovePrevious'" - then: [T: "gå"] # phrase('move' to next entry in table) - - else_if: "$NavCommand = 'ReadPrevious'" - then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) - - T: "venstre" # phrase(move 'left') - - pause: short - - with: - variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MovePrevious'"] - replace: - - test: - if: "preceding-sibling::*" - then: - - with: - variables: [Move2D: "'i'", Child2D: "."] # phrase('in' the denominator) - replace: [x: ".."] - else: - - with: - variables: [Move2D: "'ut av'", Child2D: "."] - replace: [x: ".."] - - test: - if: "preceding-sibling::*" - then: - - x: .. # move out of parens - else: - - x: ".." + - with: + variables: [Move2D: "'in'", Child2D: "."] # phrase('in' the denominator) + replace: [x: ".."] + else: + - with: + variables: [Move2D: "'out of'", Child2D: "."] + replace: [x: ".."] + - x: ".." - name: move-previous-auto-zoom-parens # auto-zoom into previous child if previous child is parenthesized expr @@ -1473,22 +1245,14 @@ - " (IsBracketed(., '(', ')') or IsBracketed(., '[', ']'))" - " ]" replace: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: - - test: - - if: "$NavCommand = 'MovePrevious'" - then: [T: "gå"] # phrase('move' to next entry in table) - - else_if: "$NavCommand = 'ReadPrevious'" - then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) - - T: "venstre" # phrase(move 'left') - - pause: short + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: if: "not(parent::m:mrow)" then: - with: - variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) + variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) replace: [x: ".."] - set_variables: [NavNode: "preceding-sibling::*[1]/*[2]/@id"] @@ -1496,44 +1260,37 @@ - name: move-previous-default tag: mtd - match: "$Move2D = '' and ($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious')" + match: "$Move2D = '' and + ($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and + preceding-sibling::*" replace: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: - # can't get here with MatchCounter=0, so no need to echo command - if: "preceding-sibling::*" + if: "$NavVerbosity = 'Verbose'" then: - - test: - if: "$NavVerbosity != 'Terse'" - then: - - T: "kolonne" # phrase(the first 'column' in the table) - - x: "count(preceding-sibling::*)" - - pause: short - - test: - if: "$NavMode = 'Character'" - then: - - with: - variables: [NavCommand: "'MovePreviousZoom'"] - replace: [x: "preceding-sibling::*[1]"] - else: [set_variables: [NavNode: "preceding-sibling::*[1]/*[last()]/@id"]] - else: - - x: ".." # try again at the row level + - T: "kolonne" # phrase(the first 'column' in the table) + - x: "count(preceding-sibling::*)" + - pause: short + - test: + if: "$NavMode = 'Character'" + then: + - with: + variables: [NavCommand: "'MovePreviousZoom'"] + replace: [x: "preceding-sibling::*[1]"] + else: [set_variables: [NavNode: "preceding-sibling::*[1]/*[last()]/@id"]] - name: move-previous-default tag: [mtr, mlabeledtr] match: "$Move2D = '' and ($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious')" replace: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: - # can't get here with MatchCounter=0, so no need to echo command if: "preceding-sibling::*" then: - - test: - if: "$NavVerbosity != 'Terse'" - then: - - T: "rad" # phrase('row' five in table) - - x: "count(preceding-sibling::*)" - - T: "kolonne" # phrase('column' five in table) - - x: "count(*)" - - pause: medium - test: if: "$NavMode = 'Character'" then: @@ -1541,7 +1298,7 @@ variables: [NavCommand: "'MovePreviousZoom'"] replace: [x: "preceding-sibling::*[1]"] else: - - set_variables: [NavNode: "preceding-sibling::*[1]/*[last()]/*[last()]/@id"] + - set_variables: [NavNode: "preceding-sibling::*[1]/@id"] else: [x: ".."] # try again for after - name: move-previous-locked-zoom-level @@ -1551,57 +1308,43 @@ - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" - "$ReadZoomLevel>=0" replace: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: # if moving into base (nothing before), we must be moving to the base, so "in" will be said if: "count(preceding-sibling::*) > 2 and preceding-sibling::*[1][name(.)='none']" then: - with: - variables: [Move2D: "'ut av'", Child2D: "."] + variables: [Move2D: "'out of'", Child2D: "."] replace: [x: ".."] - - with: - variables: [MatchCounter: "$MatchCounter + 1"] - replace: [x: "preceding-sibling::*[1]"] # skip over 'none' + - x: "preceding-sibling::*[1]" # skip over 'none' else: - - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: - - test: - - if: "$NavCommand = 'MovePrevious'" - then: [T: "gå"] # phrase('move' to next entry in table) - - else_if: "$NavCommand = 'ReadPrevious'" - then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) - - T: "venstre" # phrase(move 'left') - - pause: short - with: - variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) + variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) replace: [x: ".."] - with: - variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MovePreviousZoom'"] + variables: [NavCommand: "'MovePreviousZoom'"] replace: [x: "preceding-sibling::*[1]"] - name: move-previous-default tag: "*" match: "$NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious'" replace: + - with: + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] + replace: [x: "."] - test: - if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" - then: + if: "preceding-sibling::*[1][@data-from-mathml='none' or @data-from-mathml='mprescripts']" + then: [x: "preceding-sibling::*[1]"] + else: - test: - - if: "$NavCommand = 'MovePrevious'" - then: [T: "gå"] # phrase('move' to next entry in table) - - else_if: "$NavCommand = 'ReadPrevious'" - then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) - - T: "venstre" # phrase(move 'left') - - pause: short - - test: - if: "IsNode(.., '2D')" - then: - - with: - variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) - replace: [x: ".."] - - set_variables: [NavNode: "preceding-sibling::*[1]/@id"] + if: "IsNode(.., '2D') or not(IsNode(.., 'mathml'))" + then: + - with: + variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) + replace: [x: ".."] + - set_variables: [NavNode: "preceding-sibling::*[1]/@id"] # ********* ReadZoomLevel toggle *************** # These set ::NavMode @@ -1617,13 +1360,11 @@ - set_variables: [NavMode: "'Character'", ReadZoomLevel: "1"] - else_if: "$NavMode = 'Character'" then: - - T: "forenklet modus" # phrase(a 'simple' way to do something) + - T: "enkelt modus" # phrase(a 'simple' way to do something) - set_variables: [NavMode: "'Simple'", ReadZoomLevel: "1"] - else: - T: "utvidet modus" # phrase(an 'enhanced' way to do something) - set_variables: [NavMode: "'Enhanced'", ReadZoomLevel: "-1"] - # - T: "läge" # phrase(a simple 'mode' of use) - # SWEDISH: Removed the ending "mode" string and added "läge" to the previous strings, for grammatical purposes. - pause: long - test: - if: "$NavMode != 'Enhanced'" # potentially need to zoom to the sibling @@ -1639,7 +1380,7 @@ - test: - if: "$NavMode = 'Enhanced'" then: - - T: "forenklet modus" # phrase(an 'simple' way to do something) + - T: "enkelt modus" # phrase(a 'simple' way to do something) - set_variables: [NavMode: "'Simple'", ReadZoomLevel: "1"] - else_if: "$NavMode = 'Character'" then: @@ -1648,8 +1389,6 @@ - else: - T: "symbolmodus" # phrase(a mathematical 'character') - set_variables: [NavMode: "'Character'", ReadZoomLevel: "1"] - # - T: "användningsläge" # phrase(a simple 'mode' of use) - # SWEDISH: Removed the ending "mode" string and added "läge" to the previous strings, for grammatical purposes. - pause: long - test: - if: "$NavMode != 'Enhanced'" # potentially need to zoom to the sibling @@ -1666,11 +1405,12 @@ if: "$Overview = 'true'" then: - T: "les uttrykk etter navigering" # phrase('speak expression after move') + - pause: long - set_variables: [Overview: "'false'"] else: - T: "oversikt over uttrykk etter navigering" # phrase('overview of expression after move') + - pause: long - set_variables: [Overview: "'true'"] - - pause: long - name: current tag: "*" @@ -1682,10 +1422,10 @@ - test: - if: "$NavCommand = 'ReadCurrent'" then: [T: "les"] # phrase('read' next entry in table) - else: [T: "beskriv"] # phrase('describe' next entry in table) + else: [t: "beskriv"] # phrase('describe' next entry in table) - T: "nåværende" # phrase('current' entry in table) + - pause: long - set_variables: [NavNode: "@id"] - - pause: long # this needs to be near the end because we only test for 'Describe', "Read", etc., and we don't want to get 'DescribeNext', etc. - name: placemarker @@ -1705,9 +1445,9 @@ - else_if: "starts-with($NavCommand, 'Describe')" then: [T: "beskriv"] # phrase('describe' next entry in table) - else_if: "starts-with($NavCommand, 'MoveTo')" - then: [T: "gå til"] # phrase('move to' the next entry in table) + then: [T: "gå til "] # phrase('move to' the next entry in table) else: [T: "angi"] # phrase('set' the value of the next entry in table) - - T: "plassholder" # phrase('placeholder' for the value) + - t: "plassholder" # phrase('placeholder' for the value) - x: "$PlaceMarkerIndex" - pause: long - set_variables: [NavNode: "$PlaceMarker"] @@ -1730,8 +1470,6 @@ # Alternatively, it could insert a special token that Rust code does a "replace" on with the speech (e.g. SPEECH_AT{id}) # or a new command "speak" which takes a node id - name: where-am-i-start - - tag: "*" match: "($NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll') and $MatchCounter = 0" replace: @@ -1741,6 +1479,7 @@ variables: [MatchCounter: "$MatchCounter + 1"] replace: [x: ".."] +# Marthe - name: where-am-i-stop tag: "*" match: @@ -1753,22 +1492,23 @@ - test: if: "$NavCommand = 'WhereAmI'" then: - - T: "ingenting mer" # phrase('inside of nothing more') + - t: "inside of nothing more" # phrase('inside of nothing more') - pause: long - set_variables: [SpeakExpression: "'false'"] else: - - T: "inne i" # phrase('inside' a big expression) + - t: "inside" # phrase('inside' a big expression) - pause: medium - set_variables: [NavNode: "@id"] +# Marthe - name: where-am-i-middle tag: "*" match: "$NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll'" replace: - - T: "inne i" # phrase('inside' a big expression) + - t: "inside" # phrase('inside' a big expression) - pause: medium - test: - - if: "$NavMode='Enhanced' and parent::*[self::m:mrow and IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false)]" + - if: "$NavMode='Enhanced' and parent::*[self::m:mrow and (IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false))]" then: [x: ".."] # auto-zoom up - else_if: "$NavCommand = 'WhereAmI'" then: [set_variables: [NavNode: "@id"]] @@ -1776,3 +1516,1747 @@ - translate: "@id" - pause: long - x: '..' + +# ********* Rules below are from old navigation file *************** +# Rules for speaking what happens when moving into or out of a notation +#- name: into-or-out-of +# #tag: mfrac +# #match: "$Move2D != ''" +# #replace: +# - x: "$Move2D" +# - test: +# if: "count($Child2D/preceding-sibling::*)=0" +# then: [T: "telleren"] # phrase(the 'numerator' of a fraction) +# else: [T: "nevneren"] # phrase(the 'denominator' of a fraction) +# - pause: "medium" +# +#- name: into-or-out-of +# tag: msqrt +# match: "$Move2D != ''" +# replace: +# - x: "$Move2D" +# - T: "kvadratroten" # phrase(the 'square root' of x) +# - pause: "medium" +# +#- name: into-or-out-of +# tag: mroot +# match: "$Move2D != ''" +# replace: +# - x: "$Move2D" +# - test: +# if: "count($Child2D/preceding-sibling::*)=0" +# then: [T: "roten"] # phrase(the cube 'root' of x) +# else: [T: "rotindeksen"] # phrase(the 'root index' of x is 3) +# - pause: "medium" +# +#NORWEGIAN: For powers we say "grunntallet" for the base, but since this markup is used for other things than powers and subindexes, use the word "basen". +#- name: into-or-out-of +# tag: msub +# match: "$Move2D != ''" +# replace: +# - x: "$Move2D" +# - test: +# if: "count($Child2D/preceding-sibling::*)=0" +# then: [T: "basen"] # phrase(the 'base' of the power) +# else: [T: "nedre indeks"] # phrase(x with 'subscript' 2) +# - pause: "medium" +# +#- name: into-or-out-of +# tag: msup +# match: "$Move2D != ''" +# replace: +# - x: "$Move2D" +# - test: +# if: "count($Child2D/preceding-sibling::*)=0" +# then: [T: "basen"] # phrase(the 'base' of the power) +# else: [T: "øvre indeks"] # phrase(x with 'superscript' 2) # FIX: it would be better to use the word used when reading (power, exponent, ...) +# - pause: "medium" +# +#- name: into-or-out-of +# tag: msubsup +# match: "$Move2D != ''" +# replace: +# - x: "$Move2D" +# - test: +# - if: "count($Child2D/preceding-sibling::*)=0" +# then: [T: "basen"] # phrase(the 'base' of the power) +# - else_if: "count($Child2D/preceding-sibling::*)=1" +# then: [T: "nedre indeks"] # phrase(x with 'subscript' 2) +# else: [T: "øvre indeks"] # phrase(x with 'superscript' 2) # FIX: it would be better to use the word used when reading (power, exponent, ...) +# - pause: "medium" +# +#- name: into-or-out-of +# tag: munder +# match: "$Move2D != ''" +# replace: +# - x: "$Move2D" +# - test: +# if: "count($Child2D/preceding-sibling::*)=0" +# then: [T: "basen"] # phrase(the 'base' of the power) +# else: [T: "nedre indeks"] # phrase(the 'lower limit' of the function is zero) +# - pause: "medium" +# +#- name: into-or-out-of +# tag: mover +# match: "$Move2D != ''" +# replace: +# - x: "$Move2D" +# - test: +# if: "count($Child2D/preceding-sibling::*)=0" +# then: [T: "basen"] # phrase(the 'base' of the power) +# else: [T: "øvre indeks"] # phrase(the 'upper limit' of the function is zero) +# - pause: "medium" +# +#- name: into-or-out-of +# tag: munderover +# match: "$Move2D != ''" +# replace: +# - x: "$Move2D" +# - test: +# - if: "count($Child2D/preceding-sibling::*)=0" +# then: [T: "basen"] # phrase(the 'base' of the power) +# - else_if: "count($Child2D/preceding-sibling::*)=1" +# then: [T: "nedre indeks"] # phrase(the 'lower limit' of the function is zero) +# else: [T: "øvre indeks"] # phrase(the 'upper limit' of the function is zero) +# - pause: "medium" +# +#- name: into-or-out-of +# tag: mmultiscripts +# match: "$Move2D != ''" +# replace: +# - test: +# if: "name($Child2D)!='none'" +# then: +# - with: +# variables: +# - NumPrecedingSiblings: "count($Child2D/preceding-sibling::*)" +# replace: +# - x: "$Move2D" +# - test: +# - if: "$NumPrecedingSiblings=0" +# then: [T: "basen"] # phrase(the 'base' of the power) +# - else_if: "$Child2D/preceding-sibling::*[self::m:mprescripts]" # are we before mprescripts and hence are postscripts +# then: +# - test: # in postscripts -- base shifts by one +# if: "$NumPrecedingSiblings mod 2 = 0" +# then: [T: "nedre indeks"] # phrase(x with 'subscript' 2) +# else: [T: "øvre indeks"] # phrase(x with 'superscript' 2) +# else: +# - test: +# if: "$NumPrecedingSiblings mod 2 = 0" +# then: [T: "øvre indeks"] # phrase(x with 'superscript' 2) +# else: [T: "nedre indeks"] # phrase(x with 'subscript' 2) +# - pause: "medium" +# +#- name: into-or-out-of +# tag: mtd +# match: "$Move2D = 'into'" +# replace: +# - x: "$Move2D" +# - T: "kolonne" # phrase(the first 'column' in the table) +# - x: "count($Child2D/preceding-sibling::*)+1" +# - pause: "medium" +# +#- name: into-or-out-of +# tag: [mtr, mlabeledtr] +# match: "$Move2D = 'into'" +# replace: +# - x: "$Move2D" +# - x: "count($Child2D/preceding-sibling::*)+1" +# - pause: "medium" +# +#- name: default-move +# # nothing to do (not 2D) -- need to catch $Move2D though so rules based on NavCommand don't trigger +# tag: "*" +# match: "$Move2D != ''" +# replace: [] +# +# ********* Go back to last position *************** +# This is first since start/end position shouldn't matter +#- name: move-last-location +# +# +# tag: "*" +# match: "$NavCommand = 'MoveLastLocation'" +# replace: +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - test: +# - if: "$PreviousNavCommand = 'ZoomIn'" +# then: [T: "angre innzooming"] # phrase('undo zoom in') +# - else_if: "$PreviousNavCommand = 'ZoomOut'" +# then: [T: "angre utzooming"] # phrase('undo zoom out') +# - else_if: "$PreviousNavCommand = 'ZoomInAll'" +# then: [T: "angre innzooming hele veien"] # phrase('undo zooming in all the way') +# - else_if: "$PreviousNavCommand = 'ZoomOutAll'" +# then: [T: "angre utzooming hele veien"] # phrase('undo zooming out all the way') +# - else_if: "$PreviousNavCommand = 'MovePrevious' or $PreviousNavCommand = 'MovePreviousZoom'" +# then: [T: "angre gå venstre"] # phrase('undo move left') +# - else_if: "$PreviousNavCommand = 'MoveNext' or $PreviousNavCommand = 'MoveNextZoom'" +# then: [T: "angre gå høyre"] # phrase('undo move right') +# - else_if: "$PreviousNavCommand = 'None'" +# then: [T: "ingen tidligere kommandoer"] # phrase('no previous command') +# - pause: "long" +# - set_variables: [NavNode: "@id"] +# +# many times, for typographic reasons, people include punctuation at the end of a math expr +# these rules detect that and skip speaking it (should be similar regular rule) +#- name: skip-punct-at-end-zoom-in +# tag: mrow +# match: +# - "($NavCommand = 'ZoomIn' or $NavCommand = 'ZoomInAll' or $NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and" +# - " parent::m:math and count(*)=2 and" +# - " *[2][translate(.,'.,;:?', '')='']" +# replace: +# - x: "*[1]" +# +# ********* ZoomIn *************** +#- name: zoom-in-leaf +# +# tag: "*" +# match: "($NavCommand = 'ZoomIn' or $NavCommand = 'ZoomInAll') and IsNode(., 'leaf')" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" +# then: [T: "innzoomet hele veien", pause: "long"] # phrase('zoomed in all of the way') +# - test: +# if: "$ReadZoomLevel!=-1" +# then: +# - set_variables: [ReadZoomLevel: "0"] +# - set_variables: [NavNode: "@id"] +# +# special case of zooming into a matrix or determinant -- move to the first row +#- name: zoom-in-matrix +# +# tag: mrow +# match: +# - "$NavCommand = 'ZoomIn' and count(*)=3 and " +# - "*[2][self::m:mtable and (IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|'))]" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') +# - set_variables: [NavNode: "*[2]/*[1]/@id"] +# +# special case of zooming into a table -- move to the first row +#- name: zoom-in-table +# tag: mtable +# match: "$NavCommand = 'ZoomIn'" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') +# - set_variables: [NavNode: "*[1]/@id"] +# +#- name: zoom-in-mrow-in-math +# # Moving to first or last is meaningless the 'math' has only an 'mrow' inside -- dig inside and do it again +# tag: math +# match: "count(*)=1 and ($NavCommand = 'ZoomIn' or $NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom')" +# replace: +# - test: +# if: "$NavCommand = 'MovePreviousZoom'" +# then: [x: "*[last()]"] +# else: [x: "*[1]"] +# +#- # For msqrt and menclose, if the single child isn't an mrow, don't zoom in +# name: zoom-in-again +# # If there is only one child, this isn't an interesting move -- zoom in again +# tag: "*" +# match: +# - "($NavCommand = 'ZoomIn' or " +# - " ($NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and $NavMode='Enhanced') and " +# - "count(*)=1 and (*[1][self::m:mrow] and not(self::m:msqrt or self::m:menclose))" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: +# - test: +# if: "$NavCommand = 'MovePreviousZoom'" +# then: [x: "*[last()]"] +# else: [x: "*[1]"] +# +#- name: zoom-in-enhanced +# +# tag: "*" +# match: "$NavCommand = 'ZoomIn' and $NavMode='Enhanced'" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') +# - test: +# - if: "self::m:mtr or self::m:mlabeledtr" +# then: +# - with: +# variables: [Move2D: "'i'", Child2D: "*[1]/*[1]"] # phrase('in' the denominator) +# replace: [x: "."] +# - set_variables: [NavNode: "*[1]/*[1]/@id"] # skip mtd +# - else_if: "*[1][self::m:mrow and IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false)]" # auto zoom +# then: +# - with: +# variables: [Move2D: "'i'", Child2D: "*[1]/*[2]"] # phrase('in' the denominator) +# replace: [x: "."] +# - set_variables: [NavNode: "*[1]/*[2]/@id"] # skip mtd +# else: +# - with: +# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) +# replace: [x: "."] +# - set_variables: [NavNode: "*[1]/@id"] +# +#- name: zoom-in-2D-not-enhanced +# tag: "*" +# match: "$NavCommand = 'ZoomIn' and $NavMode!='Enhanced' and IsNode(., '2D')" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') +# - with: +# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) +# replace: [x: "."] +# - with: +# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"] +# replace: [x: "*[1]"] +# +#- name: zoom-in-default +# tag: "*" +# match: "$NavCommand = 'ZoomIn'" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') +# - with: +# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) +# replace: [x: "."] +# - test: +# if: "$NavMode='Character'" +# then: +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: [x: "*[1]"] +# else_test: +# if: "self::m:mtd" +# then: [x: "*[1]"] +# else: +# - test: +# if: "$ReadZoomLevel!=-1" +# then: +# - set_variables: [ReadZoomLevel: "DistanceFromLeaf(*[1], true, $NavMode!='Character')"] +# - set_variables: [NavNode: "*[1]/@id"] +# +#- name: zoom-in-all-default +# tag: "*" +# match: "$NavCommand = 'ZoomInAll'" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: [T: "zoom inn hele veien", pause: "medium"] # phrase('zoom in all the way') +# - with: +# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) +# replace: [x: "."] +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: [x: "*[1]"] +# +#- name: zoom-out +# tag: math +# match: "$NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll'" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" +# then: [T: "utzoomet hele veien", pause: "long"] # phrase('zoomed out all the the way') +# - set_variables: [NavNode: "*[1]/@id"] # no-op for $NavCommand = 'ZoomOut' +# +#- name: zoom-out-top +# tag: "*" +# match: +# - "($NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll') and" +# - "parent::m:math " +# replace: +# - x: ".." # let math rule deal with it +# +#- name: skip-punct-at-end-zoom-out +# tag: mrow +# match: +# - "($NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll') and" +# - " parent::m:math and count(*)=2 and" +# - " *[2][translate(.,'.,;:?', '')='']" +# replace: +# - x: ".." +# +#- name: zoom-out-all-default +# tag: "*" +# match: "$NavCommand = 'ZoomOutAll'" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" +# then: [T: "utzoomet hele veien", pause: "medium"] # phrase('zoomed out all the the way') +# - with: +# variables: [Move2D: "'ut av'", Child2D: "."] +# replace: [x: ".."] +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: [x: ".."] +# +# deal with internal zooming: MoveNextZoom and MovePreviousZoom +# +# start with Enhanced mode +#- name: move-zoom-enhanced +# tag: "*" +# match: +# - "($NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and " +# - "$NavMode = 'Enhanced'" +# replace: +# # don't bother with MatchCounter since we only get here if > 1 +# - with: +# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) +# replace: [x: "."] +# - test: +# - if: "count(*)> 1 or IsNode(., 'leaf') or self::m:msqrt or self::m:menclose" +# then: [set_variables: [NavNode: "@id"]] +# else: [x: "*[1]"] +# +#- name: move-next-zoom-not-enhanced +# # $ReadZoomLevel must be >= 0 +# tag: "*" +# match: "$NavCommand = 'MoveNextZoom'" +# replace: +# #don't bother with MatchCounter since we only get here if > 1 +# - test: +# if: "$ReadZoomLevel >= DistanceFromLeaf(., false, $NavMode!='Character')" +# then: +# # - with: +# # variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) +# # replace: [x: ".."] +# - set_variables: [NavNode: "@id"] +# else: +# - with: +# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) +# replace: [x: "."] +# - x: "*[1]" +# +#- name: move-previous-zoom-not-enhanced +# # $ReadZoomLevel must be >= 0 +# tag: "*" +# match: "$NavCommand = 'MovePreviousZoom'" +# replace: +# #don't bother with MatchCounter since we only get here if > 1 +# - test: +# if: "$ReadZoomLevel >= DistanceFromLeaf(., true, $NavMode!='Character')" +# then: +# # - with: +# # variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) +# # replace: [x: ".."] +# - set_variables: [NavNode: "@id"] +# else: +# - with: +# variables: [Move2D: "'i'", Child2D: "*[last()]"] # phrase('in' the denominator) +# replace: [x: "."] +# - x: "*[last()]" +# +# ********* ZoomOut *************** +#- name: zoom-out-default +# +# +# tag: mtd +# match: "$Move2D = '' and ($NavCommand = 'ZoomOut')" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: [T: "zoom ut", pause: "medium"] # phrase('zoom out' of expression) +# # we need to speak it here +# - T: "rad" # phrase(the first 'row' of the matrix) +# # if we let the speech rules speak the row, it is given just the MathML for the row, so the row # will always be '1' +# - x: "count(../preceding-sibling::*)+1" +# - pause: medium +# - set_variables: [NavNode: "../@id"] +# +#- name: zoom-out +# # a row around a single element -- these might duplicate the position/offset, so we jump an extra level here +# tag: "*" +# match: "$NavCommand = 'ZoomOut'" +# replace: +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: +# - test: +# if: "$MatchCounter = 1 and $NavVerbosity = 'Verbose'" +# then: [T: "zoom ut", pause: "medium"] # phrase('zoom out' of the expression) +# - test: +# if: "$NavMode='Enhanced' and parent::*[self::m:mrow and IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false)]" +# then: [x: ".."] # auto-zoom: move out a level and retry +# else: +# - with: +# variables: [Move2D: "'ut av'", Child2D: "."] +# replace: [x: ".."] +# - test: +# if: "parent::m:mtd" +# then: [x: ".."] +# else: +# - test: +# if: "$ReadZoomLevel!=-1" +# then: [set_variables: [ReadZoomLevel: "DistanceFromLeaf(.., true, $NavMode!='Character')"]] +# - set_variables: [NavNode: "../@id"] +# +# ********* MoveStart/End *************** +#- name: math-move-to-start-or-end +# tag: math +# match: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart' or $NavCommand = 'MoveEnd' or $NavCommand = 'MoveLineEnd'" +# replace: +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: +# - test: +# if: "$NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MoveStart'" +# then: [T: "gå til start matematikk"] # phrase('move to start of math') +# - else_if: "$NavCommand = 'MoveLineStart'" +# then: [T: "gå til starten av raden"] # phrase('move to start of line') +# - else_if: "$NavCommand = 'MoveEnd'" +# then: [T: "gå til slutt matematikk"] # phrase('move to end of math') +# else: [T: "gå til slutten av raden"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') +# - pause: "medium" +# - test: +# if: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart'" +# then: +# # move inside of the mrow inside of 'math' or inside the fraction, etc (hence two levels down) +# - with: +# variables: [NavCommand: "'MoveNextZoom'"] +# replace: [x: "*[1]/*[1]"] +# else: +# - with: +# variables: [NavCommand: "'MovePreviousZoom'"] +# replace: [x: "*[last()]/*[last()]"] +# +# We stop when the parent is 2d (e.g., frac), but not if in leaf base of msub/msup/msubsup/mmultiscripts because that's really on the same line +#- name: move-to-start-or-end-2d +# tag: "*" +# match: +# - "($NavCommand = 'MoveLineStart' or $NavCommand = 'MoveLineEnd') and IsNode(.., '2D') and" +# - "not( IsNode(., 'leaf') and (parent::m:msub or parent::m:msup or parent::m:msubsup or parent::m:mmultiscripts) )" +# replace: +# - test: +# if: "$NavVerbosity = 'Verbose'" +# then: +# - test: +# if: "$NavCommand = 'MoveLineStart'" +# then: [T: "gå til starten av raden"] # phrase('move to start of line') +# else: [T: "gå til slutten av raden"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') +# - pause: "medium" +# - test: +# if: "self::m:mrow" +# then_test: +# if: "$NavCommand = 'MoveLineStart'" +# then: +# - with: +# variables: [NavCommand: "'MoveNextZoom'"] +# replace: [x: "*[1]"] +# else: +# - with: +# variables: [NavCommand: "'MovePreviousZoom'"] +# replace: [x: "*[last()]"] +# else: [set_variables: [NavNode: "@id"]] +# +#- name: move-to-start-or-end-default +# tag: "*" +# match: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart' or $NavCommand = 'MoveEnd' or $NavCommand = 'MoveLineEnd'" +# replace: +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: [x: ".."] +# +# Table-related movement +# Typically, we need to zoom out to the mtd level, then we move the appropriate direction +#- name: not-in-table +# +# +# tag: math +# match: +# - "$NavCommand='MoveCellPrevious' or $NavCommand='MoveCellNext' or" +# - "$NavCommand='MoveCellUp' or $NavCommand='MoveCellDown' or" +# - "$NavCommand='MoveColumnStart' or $NavCommand='MoveColumnEnd' or" +# - "$NavCommand='ReadCellCurrent'" +# replace: +# - T: "ikke i tabell" # phrase('not in table') +# - pause: long +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: move-cell-previous +# tag: mtd +# match: "$NavCommand='MoveCellPrevious'" +# replace: +# - test: +# if: "preceding-sibling::*" +# then: +# - test: +# if: "$NavVerbosity = 'Verbose'" +# then: +# - T: "gå venstre" # phrase('move left') +# - pause: short +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "kolonne" # phrase(the first 'column' of the table) +# - x: "count(preceding-sibling::*)" +# - pause: medium +# - test: +# if: "$NavMode='Character'" +# then: +# - with: +# variables: [NavCommand: "'MovePreviousZoom'"] +# replace: [x: "preceding-sibling::*[1]"] +# else: +# - set_variables: [NavNode: "preceding-sibling::*[1]/*[1]/@id"] +# else: +# - T: "ingen foregående kolonner" # phrase('no previous column' in the table) +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: move-cell-next +# tag: mtd +# match: "$NavCommand='MoveCellNext'" +# replace: +# - test: +# if: "following-sibling::*" +# then: +# - test: +# if: "$NavVerbosity = 'Verbose'" +# then: +# - T: "gå høyre" # phrase('move right') +# - pause: short +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "kolonne" # phrase(the first 'column' in the table) +# - x: "count(preceding-sibling::*)+2" +# - pause: medium +# - test: +# if: "$NavMode='Character'" +# then: +# - with: +# variables: [NavCommand: "'MoveNextZoom'"] +# replace: [x: "following-sibling::*[1]"] +# else: +# - set_variables: [NavNode: "following-sibling::*[1]/*[1]/@id"] +# else: +# - T: "ingen påfølgende kolonner" # phrase('no next column' in the table) +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: move-cell-up +# tag: mtd +# match: "$NavCommand='MoveCellUp'" +# replace: +# - test: +# if: "../preceding-sibling::*" +# then: +# - with: +# variables: [Column: "count(preceding-sibling::*)+1"] # store this because otherwise the value is used in the wrong context below +# replace: +# - test: +# if: "$NavVerbosity = 'Verbose'" +# then: +# - T: "gå opp" # phrase('move up' to previous row in the table) +# - pause: short +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "rad" # phrase(the previous 'row' in the table) +# - x: "count(../preceding-sibling::*)" +# - pause: short +# - T: "kolonne" # phrase(the previous 'column' in the table) +# - x: "count(preceding-sibling::*)+1" +# - pause: medium +# - test: +# if: "$NavMode='Character'" +# then: +# - with: +# variables: [NavCommand: "'MoveNextZoom'"] +# replace: [x: "../preceding-sibling::*[1]/*[$Column]"] +# else: +# - set_variables: [NavNode: "../preceding-sibling::*[1]/*[$Column]/*[1]/@id"] +# else: +# - T: "ingen foregående rader" # phrase('no previous row' in the table) +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: move-cell-down +# tag: mtd +# match: "$NavCommand='MoveCellDown'" +# replace: +# - test: +# if: "../following-sibling::*" +# then: +# - with: +# variables: [Column: "count(preceding-sibling::*)+1"] # store this because otherwise the value is used in the wrong context below +# replace: +# - test: +# if: "$NavVerbosity = 'Verbose'" +# then: +# - T: "gå ned" # phrase('move down to the next row in the table) +# - pause: short +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "rad" # phrase(the next 'row' in the table) +# - x: "count(../preceding-sibling::*)+2" +# - pause: short +# - T: "kolonne" # phrase(the next 'column' in the table) +# - x: "count(preceding-sibling::*)+1" +# - pause: medium +# - test: +# if: "$NavMode='Character'" +# then: +# - with: +# variables: [NavCommand: "'MoveNextZoom'"] +# replace: [x: "../following-sibling::*[1]/*[$Column]"] +# else: +# - set_variables: [NavNode: "../following-sibling::*[1]/*[$Column]/*[1]/@id"] +# else: +# - T: "ingen påfølgende rader" # phrase('no next row' in the table) +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: move-cell-up +# tag: [mtr, mlabeledtr] +# match: "$NavCommand='MoveCellUp'" +# replace: +# - test: +# if: "preceding-sibling::*" +# then: +# - test: +# if: "$NavVerbosity = 'Verbose'" +# then: +# - T: "gå opp" # phrase('move up' to the previous row in the table) +# - pause: medium +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "rad" # phrase(the previous 'row' in the table) +# - x: "count(preceding-sibling::*)" +# - pause: medium +# - test: +# if: "$NavMode='Character'" +# then: +# - with: +# variables: [NavCommand: "'MoveNextZoom'"] +# replace: [x: "preceding-sibling::*[1]"] +# else: +# - set_variables: [NavNode: "preceding-sibling::*[1]/@id"] +# else: +# - T: "ingen foregående rader" # phrase('no previous row' in the table) +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: move-cell-down +# tag: [mtr, mlabeledtr] +# match: "$NavCommand='MoveCellDown'" +# replace: +# - test: +# if: "following-sibling::*" +# then: +# - test: +# if: "$NavVerbosity = 'Verbose'" +# then: +# - T: "gå ned" # phrase('move down' to the next row in the table) +# - pause: medium +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "rad" # phrase(the previous 'row' in the table) +# - x: "count(preceding-sibling::*)+2" +# - pause: medium +# - test: +# if: "$NavMode='Character'" +# then: +# - with: +# variables: [NavCommand: "'MoveNextZoom'"] +# replace: [x: "following-sibling::*[1]"] +# else: +# - set_variables: [NavNode: "following-sibling::*[1]/@id"] +# else: +# - T: "ingen påfølgende rader" # phrase('no next row' in the table) +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: default-read-cell +# tag: "*" +# match: "$NavCommand='ReadCellCurrent'" +# replace: +# - with: +# variables: [MTD: "ancestor::m:mtd"] +# replace: +# - test: +# if: "$MTD" +# then: +# - test: +# if: "$NavVerbosity = 'Verbose'" +# then: +# - T: "les nåværende verdi" # phrase('read current entry' in the table) +# - pause: medium +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "rad" # phrase(the previous 'row' in the table) +# - x: "count($MTD[1]/../preceding-sibling::*)+1" +# - T: "kolonne" # phrase(the previous 'column' in the table) +# - x: "count($MTD[1]/preceding-sibling::*)+1" +# - pause: short +# - set_variables: [NavNode: "$MTD[1]/*[1]/@id"] +# else: +# - T: "ikke i tabell" # phrase('not in table' or matrix) +# - pause: long +# - set_variables: [SpeakExpression: "'false'"] +# +# mtd ? ( $NavCommand='MoveColumnStart' ) +# => MoveColStart { +# ruleRef = name(^^match); +# column = index(match); +# ::StartPosition = ^^match[0][index(match)][0].dfs; +# ::EndPosition = ^^match[0][index(match)][0].offset; +# }; +# +# mtd ? ( $NavCommand='MoveColumnEnd' ) +# => MoveColEnd { +# ruleRef = name(^^match); +# column = index(match); +# ::StartPosition = ^^match[count(^^match)-1][index(match)][0].dfs; +# ::EndPosition = ^^match[count(^^match)-1][index(match)][0].offset; +# }; +# +# +# +# # Rules for columnar math (mstack and mlongdiv) -- each row is an msrow or mscarries except for the start of mlongdiv +# # FIX: not dealing with different number of digits on different lines +# # FIX: not dealing with + (etc) on same line if they are on the right side (Dutch, others) +# # FIX: not dealing with intervening msline (say it and move on??) +# # FIX: not dealing with carries well +# # FIX: not dealing with navigation of first three children of mlongdiv +# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') && has_previous(match) ) +# => MoveCell { +# ruleRef = name(^^match); +# wordRef = "previous"; +# ::StartPosition = previous(match).dfs; +# ::EndPosition = previous(match).offset; +# }; +# +# # no previous child -- in first column -- don't move +# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious' ) ) +# => MoveCell { +# ruleRef = name(^^match); +# wordRef = "previous"; +# childIndex = -1; # key to know what to say for each notation +# ::SpeakAfterMove = false; +# }; +# +# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') && has_next(match) ) +# => MoveCell { +# ruleRef = name(^^match); +# wordRef = "next"; +# ::StartPosition = next(match).dfs; +# ::EndPosition = next(match).offset; +# }; +# +# # no next child -- in first column -- don't move +# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext' ) ) +# => MoveCell { +# ruleRef = name(^^match); +# wordRef = "next"; +# childIndex = -1; # key to know what to say for each notation +# ::SpeakAfterMove = false; +# }; +# +# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# $NavCommand='MoveCellUp' && has_previous(^^match) ) +# => MoveCell { +# ruleRef = name(^^match); +# wordRef = "up"; +# ::StartPosition = ^^^match[index(^^match)-1][-1][index(match)-count(^match)].dfs; +# ::EndPosition = ^^^match[index(^^match)-1][-1][index(match)-count(^match)].offset; +# }; +# +# # no previous child -- in first column -- don't move +# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# $NavCommand='MoveCellUp' ) +# => MoveCell { +# ruleRef = name(^^match); +# wordRef = "up"; +# childIndex = -1; # key to know what to say for each notation +# ::SpeakAfterMove = false; +# }; +# +# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# $NavCommand='MoveCellDown' && has_next(^^match) ) +# => MoveCell { +# ruleRef = name(^^match); +# wordRef = "down"; +# ::StartPosition = ^^^match[index(^^match)+1][-1][index(match)-count(^match)].dfs; +# ::EndPosition = ^^^match[index(^^match)+1][-1][index(match)-count(^match)].offset; +# }; +# +# # no previous child -- in first column -- don't move +# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# $NavCommand='MoveCellDown' ) +# => MoveCell { +# ruleRef = name(^^match); +# wordRef = "down"; +# childIndex = -1; # key to know what to say for each notation +# ::SpeakAfterMove = false; +# }; +# +# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# $NavCommand='MoveColumnStart' ) +# => MoveColStart { +# ruleRef = name(^^match); +# column = index(match); +# ::StartPosition = ^^^match[0][-1][index(match)-count(^match)].dfs; +# ::EndPosition = ^^^match[0][-1][index(match)-count(^match)].offset; +# }; +# +# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# $NavCommand='MoveColumnEnd' ) +# => MoveColEnd { +# ruleRef = name(^^match); +# column = index(match); +# ::StartPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].dfs; +# ::EndPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].offset; +# }; +# +# any ? ( (name(match)=="mn" || name(match)=="none") && +# has_parent(match) && name(^match)=="mscarries" && +# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') && has_previous(match) ) +# => MoveCell { +# ruleRef = name(^match); +# wordRef = "previous"; +# ::StartPosition = previous(match).dfs; +# ::EndPosition = previous(match).offset; +# }; +# +# # no previous child -- in first column -- don't move +# any ? ( (name(match)=="mn" || name(match)=="none") && +# has_parent(match) && name(^match)=="mscarries" && +# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') ) +# => MoveCell { +# ruleRef = name(^match); +# wordRef = "previous"; +# childIndex = -1; # key to know what to say for each notation +# ::SpeakAfterMove = false; +# }; +# +# any ? ( (name(match)=="mn" || name(match)=="none") && +# has_parent(match) && name(^match)=="mscarries" && +# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') && has_next(match) ) +# => MoveCell { +# ruleRef = name(^match); +# wordRef = "next"; +# ::StartPosition = next(match).dfs; +# ::EndPosition = next(match).offset; +# }; +# +# # no next child -- in last column -- don't move +# any ? ( (name(match)=="mn" || name(match)=="none") && +# has_parent(match) && name(^match)=="mscarries" && +# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') ) +# => MoveCell { +# ruleRef = name(^match); +# wordRef = "next"; +# childIndex = -1; # key to know what to say for each notation +# ::SpeakAfterMove = false; +# }; +# +# any ? ( (name(match)=="mn" || name(match)=="none") && +# has_parent(match) && name(^match)=="mscarries" && +# $NavCommand='MoveCellUp' && has_previous(^match) ) +# => MoveCell { +# ruleRef = name(^match); +# wordRef = "up"; +# ::StartPosition = ^^match[index(^match)-1][index(match)-count(^match)].dfs; +# ::EndPosition = ^^match[index(^match)-1][index(match)-count(^match)].offset; +# }; +# +# # no previous child -- in first row -- don't move +# any ? ( (name(match)=="mn" || name(match)=="none") && +# has_parent(match) && name(^match)=="mscarries" && +# $NavCommand='MoveCellUp' ) +# => MoveCell { +# ruleRef = name(^match); +# wordRef = "up"; +# childIndex = -1; # key to know what to say for each notation +# ::SpeakAfterMove = false; +# }; +# +# any ? ( (name(match)=="mn" || name(match)=="none") && +# has_parent(match) && name(^match)=="mscarries" && +# $NavCommand='MoveCellDown' && has_next(^match) ) +# => MoveCell { +# ruleRef = name(^match); +# wordRef = "down"; +# ::StartPosition = ^^match[index(^match)+1][-1][index(match)-count(^match)].dfs; +# ::EndPosition = ^^match[index(^match)+1][-1][index(match)-count(^match)].offset; +# }; +# +# # no next child -- in last row -- don't move +# any ? ( (name(match)=="mn" || name(match)=="none") && +# has_parent(match) && name(^match)=="mscarries" && +# $NavCommand='MoveCellDown' ) +# => MoveCell { +# ruleRef = name(^match); +# wordRef = "down"; +# childIndex = -1; # key to know what to say for each notation +# ::SpeakAfterMove = false; +# }; +# +# mn ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# $NavCommand='MoveColumnStart' ) +# => MoveColStart { +# ruleRef = name(^^match); +# column = index(match); +# ::StartPosition = ^^^match[0][-1][index(match)-count(^match)].dfs; +# ::EndPosition = ^^^match[0][-1][index(match)-count(^match)].offset; +# }; +# +# mn ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && +# $NavCommand='MoveColumnEnd' ) +# => MoveColEnd { +# ruleRef = name(^^match); +# column = index(match); +# ::StartPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].dfs; +# ::EndPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].offset; +# }; +# +# +# +#- name: default-cell-move +# +# tag: "*" +# match: +# - "$NavCommand='MoveCellPrevious' or $NavCommand='MoveCellNext' or" +# - "$NavCommand='MoveCellUp' or $NavCommand='MoveCellDown' or" +# - "$NavCommand='MoveColumnStart' or $NavCommand='MoveColumnEnd' or" +# - "$NavCommand='ReadCellCurrent'" +# replace: +# - test: +# if: "ancestor::m:mtd" +# then: +# - x: "ancestor::m:mtd[1]" # try again on an mtd node +# else: +# - T: "ikke i tabell" # phrase('not in table' or matrix) +# - pause: long +# - set_variables: [SpeakExpression: "'false'"] +# +# ======== Move/Read/Describe Next rules ================= +# +# skip 'none' +#- name: move-next-none +# tag: [none, mprescripts] +# match: +# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext' or $NavCommand = 'DescribePrevious' or $NavCommand = 'MoveNextZoom') and" +# - "parent::*[1][name(.)='mmultiscripts'] and following-sibling::*" +# replace: +# - with: +# variables: [Following: "following-sibling::*[1]"] +# replace: +# # two 'none's in a row -- move over and try again; one 'none', zoom in on next +# - test: +# if: "$Following[name(.)='none']" +# then: [x: "$Following"] +# else: +# - with: +# variables: [Move2D: "'i'", Child2D: "$Following"] # phrase('in' the denominator) +# replace: [x: ".."] +# - with: +# variables: [NavCommand: "'MoveNextZoom'"] +# replace: [x: "$Following"] +# +# skip 'none' +#- name: move-previous-none +# tag: [none, mprescripts] +# match: +# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious' or $NavCommand = 'MovePreviousZoom') and" +# - "parent::*[1][name(.)='mmultiscripts'] and preceding-sibling::*" +# replace: +# - with: +# variables: [Preceding: "preceding-sibling::*[1]"] +# replace: +# # two 'none's in a row -- move over and try again; one 'none', zoom in on preceding +# - test: +# if: "$Preceding[name(.)='none']" +# then: [x: "$Preceding"] +# else: +# - with: +# variables: [Move2D: "'i'", Child2D: "$Preceding"] # phrase('in' the denominator) +# replace: [x: ".."] +# - with: +# variables: [NavCommand: "'MovePreviousZoom'"] +# replace: [x: "$Preceding"] +# +# +# +# skip invisible chars except for Enhanced mode when "times" should be read +#- name: move-next-invisible +# tag: "*" +# match: +# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" +# - "following-sibling::*[1][name(.)='mo' and translate(., '\u2061\u2062\u2063\u2064', '')='']" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MoveNext'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadNext'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "høyre" # phrase(move 'right') # phrase(move 'right') +# - pause: short +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: +# - test: +# if: "following-sibling::*[1][.='\u2062' or .='\u2064'] and $NavMode='Enhanced'" # invisible times and plus +# then: [set_variables: [NavNode: "following-sibling::*[1]/@id"]] +# else: [x: "following-sibling::*[1]"] +# +#- name: move-next-no-auto-zoom-at-edge +# # at edge of 2D and in a mode where moving right isn't an option +# tag: "*" +# variables: [EdgeNode: "EdgeNode(., 'right', '2D')"] +# match: "$NavCommand = 'MoveNext' and $NavMode!='Character' and not($AutoZoomOut) and $EdgeNode/@id!=@id" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse' and $NavCommand = 'MoveNext'" +# then: +# - T: "kan ikke gå til høyre" # phrase('cannot move right') +# - with: +# variables: [Move2D: "'end of'", Child2D: "$EdgeNode/*[last()]"] #Should "end of" be translated? +# replace: [x: "$EdgeNode"] +# - pause: long +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: move-next-no-auto-zoom-at-edge-math +# # at edge of math -- no where to go (must be after we rule out being at the edge of 2D) because we want to speak that +# tag: "*" +# match: +# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" +# - "(self::m:math or name(EdgeNode(., 'right', 'math'))='math')" # at edge of math +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" +# then: +# - T: "kan ikke" # phrase('cannot' move right in expression) +# - test: +# - if: "$NavCommand = 'MoveNext'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadNext'" +# then: [T: "lese"] # phrase('read' next entry in table) +# else: [T: "beskrive"] # phrase('describe' next entry in table) +# - T: "høyre, slutt matematikk" # phrase(move 'right, end of math') +# - pause: long +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: move-next-auto-zoom-up-one-level +# # Last child or in auto-zoom'd in-- move up a level and try again +# # Note: we've already checked the for the case where we are at an edge and should not AutoZoomOut +# tag: "*" +# match: +# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" +# - "( not(following-sibling::*) or" +# - " ( $NavMode='Enhanced' and " +# - " count(following-sibling::*)=1 and (IsBracketed(.., '(', ')') or IsBracketed(.., '[', ']'))" +# - " )" +# - ")" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MoveNext'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadNext'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "høyre" # phrase(move 'right') # phrase(move 'right') +# - pause: short +# - with: +# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNext'"] +# replace: +# - test: +# if: "following-sibling::*" +# then: +# - with: +# variables: [Move2D: "'i'", Child2D: "."] # phrase('in' the denominator) +# replace: [x: ".."] +# else: +# - with: +# variables: [Move2D: "'ut av'", Child2D: "."] +# replace: [x: ".."] +# - test: +# if: "following-sibling::*" +# then: +# - x: ".." # move out of parens +# else: +# - x: ".." +# +# At this point, if XXXNext, then we know there is must be a right sibling +#- name: move-next-default +# tag: mtd +# match: "$Move2D = '' and ($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext')" +# replace: +# - test: +# # can't get here with MatchCounter=0, so no need to echo command +# if: "following-sibling::*" +# then: +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "kolonne" # phrase(the previous 'column' in the table) +# - x: "count(preceding-sibling::*)+2" +# - pause: short +# - test: +# if: "$NavMode = 'Character'" +# then: +# - with: +# variables: [NavCommand: "'MoveNextZoom'"] +# replace: [x: "following-sibling::*[1]"] +# else: [set_variables: [NavNode: "following-sibling::*[1]/*[1]/@id"]] +# else: +# - x: ".." # try again at the row level +# +#- name: move-next-default +# tag: [mtr, mlabeledtr] +# match: "$Move2D = '' and ($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext')" +# replace: +# - test: +# # can't get here with MatchCounter=0, so no need to echo command +# if: "following-sibling::*" +# then: +# - T: "rad" # phrase(the previous 'row' in the table) +# - x: "count(preceding-sibling::*)+2" +# - T: "kolonne 1" # phrase('column 1' in the table) +# - pause: medium +# - test: +# if: "$NavMode = 'Character'" +# then: +# - with: +# variables: [NavCommand: "'MoveNextZoom'"] +# replace: [x: "following-sibling::*[1]"] +# else: +# - set_variables: [NavNode: "following-sibling::*[1]/*[1]/*[1]/@id"] +# else: [x: ".."] # try again for after +# +#- name: move-next-auto-zoom-parens +# # auto-zoom into next child if next child is parenthesized expr +# tag: "*" +# match: +# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" +# - "$NavMode='Enhanced' and" +# - "parent::m:mrow and following-sibling::* and" +# - "following-sibling::*[1][self::m:mrow and count(*)=3 and " #exclude empty parens +# - " (IsBracketed(., '(', ')') or IsBracketed(., '[', ']'))" +# - " ]" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MoveNext'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadNext'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "høyre" # phrase(move 'right') # phrase(move 'right') +# - pause: short +# - set_variables: [NavNode: "following-sibling::*[1]/*[2]/@id"] +# +# normal cases for MoveNext +#- name: move-next-locked-zoom-level +# # locked zoom level +# tag: "*" +# match: +# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" +# - "$ReadZoomLevel>=0" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MoveNext'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadNext'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "høyre" # phrase(move 'right') # phrase(move 'right') +# - pause: short +# - test: +# # if in base (nothing before), we must be moving to a script, so "in" will be said +# if: "preceding-sibling::* and following-sibling::*[1][name(.)='none']" +# then: +# - with: +# variables: [Move2D: "'ut av'", Child2D: "."] +# replace: [x: ".."] +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: [x: "following-sibling::*[1]"] # skip over 'none' +# else: +# - with: +# variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) +# replace: [x: ".."] +# - with: +# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"] +# replace: [x: "following-sibling::*[1]"] +# +#- name: move-next-default +# tag: "*" +# match: "$NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext'" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MoveNext'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadNext'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "høyre" # phrase(move 'right') # phrase(move 'right') +# - pause: short +# - test: +# if: "IsNode(.., '2D')" +# then: +# - with: +# variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) +# replace: [x: ".."] +# - set_variables: [NavNode: "following-sibling::*[1]/@id"] +# +# ======== Move/Read/Describe Previous rules ================= +# +# skip invisible chars except for Enhanced mode when "times" should be read +#- name: move-previous-invisible +# tag: "*" +# match: +# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" +# - "preceding-sibling::*[1][name(.)='mo' and translate(., '\u2061\u2062\u2063\u2064', '')='']" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MovePrevious'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadPrevious'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "venstre" # phrase(move 'left') +# - pause: short +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: +# - test: +# if: "preceding-sibling::*[1][.='\u2062' or .='\u2064'] and $NavMode='Enhanced'" # invisible times and plus +# then: [set_variables: [NavNode: "preceding-sibling::*[1]/@id"]] +# else: [x: "preceding-sibling::*[1]"] +# +# two rules for when can't move right +#- name: move-previous-no-auto-zoom-at-edge +# # at edge of 2D and in a mode where moving right isn't an option +# tag: "*" +# variables: [EdgeNode: "EdgeNode(., 'left', '2D')"] +# match: "$NavCommand = 'MovePrevious' and $NavMode!='Character' and not($AutoZoomOut) and $EdgeNode/@id!=@id" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse' and $NavCommand = 'MovePrevious'" +# then: +# - T: "kan ikke gå til venstre" # phrase('cannot move left' in expression) +# - with: +# variables: [Move2D: "'end of'", Child2D: "$EdgeNode/*[1]"] #Should "end of" be translated? +# replace: [x: "$EdgeNode"] +# - pause: long +# +#- name: move-previous-no-auto-zoom-at-edge-of-math +# # at edge of math -- no where to go (must be after we rule out being at the edge of 2D) because we want to speak that +# tag: "*" +# match: +# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" +# - "(self::m:math or name(EdgeNode(., 'left', 'math'))='math')" +# replace: +# - T: "start matematikk" # phrase('start of math') +# - pause: long +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: move-previous-at-end +# tag: "*" +# match: +# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" +# - "name(EdgeNode(., 'left', 'math'))='math'" # at edge of math +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" +# then: +# - T: "kan ikke gå til venstre, start matematikk" # phrase('cannot move left, start of math') +# - pause: long +# - set_variables: [SpeakExpression: "'false'"] +# +#- name: move-previous-auto-zoom-up-one-level +# # Last child or in auto-zoom'd in-- move up a level and try again +# # Note: we've already checked the for the case where we are at an edge and should not AutoZoomOut +# tag: "*" +# match: +# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" +# - "( not(preceding-sibling::*) or" +# - " ( $NavMode='Enhanced' and " +# - " count(preceding-sibling::*)=1 and (IsBracketed(.., '(', ')') or IsBracketed(.., '[', ']'))" +# - " )" +# - ")" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MovePrevious'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadPrevious'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "venstre" # phrase(move 'left') +# - pause: short +# - with: +# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MovePrevious'"] +# replace: +# - test: +# if: "preceding-sibling::*" +# then: +# - with: +# variables: [Move2D: "'i'", Child2D: "."] # phrase('in' the denominator) +# replace: [x: ".."] +# else: +# - with: +# variables: [Move2D: "'ut av'", Child2D: "."] +# replace: [x: ".."] +# - test: +# if: "preceding-sibling::*" +# then: +# - x: .. # move out of parens +# else: +# - x: ".." +# +#- name: move-previous-auto-zoom-parens +# # auto-zoom into previous child if previous child is parenthesized expr +# # Note: there is an asymmetry here from MoveNext because the base of a scripted might have parens for grouping, but not true for the script +# tag: "*" +# match: +# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" +# - "$NavMode='Enhanced' and" +# - "preceding-sibling::* and" +# - "(parent::m:mrow or parent::m:msub or parent::m:msup or" +# - " (count(preceding-sibling::*)=1 and (parent::m:msubsup or parent::m:mmultiscripts))" # make sure moving into base +# - ") and" +# - "preceding-sibling::*[1][self::m:mrow and count(*)=3 and " #exclude empty parens +# - " (IsBracketed(., '(', ')') or IsBracketed(., '[', ']'))" +# - " ]" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MovePrevious'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadPrevious'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "venstre" # phrase(move 'left') +# - pause: short +# - test: +# if: "not(parent::m:mrow)" +# then: +# - with: +# variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) +# replace: [x: ".."] +# - set_variables: [NavNode: "preceding-sibling::*[1]/*[2]/@id"] +# +# normal cases for MovePrevious +# +#- name: move-previous-default +# tag: mtd +# match: "$Move2D = '' and ($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious')" +# replace: +# - test: +# # can't get here with MatchCounter=0, so no need to echo command +# if: "preceding-sibling::*" +# then: +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "kolonne" # phrase(the first 'column' in the table) +# - x: "count(preceding-sibling::*)" +# - pause: short +# - test: +# if: "$NavMode = 'Character'" +# then: +# - with: +# variables: [NavCommand: "'MovePreviousZoom'"] +# replace: [x: "preceding-sibling::*[1]"] +# else: [set_variables: [NavNode: "preceding-sibling::*[1]/*[last()]/@id"]] +# else: +# - x: ".." # try again at the row level +# +#- name: move-previous-default +# tag: [mtr, mlabeledtr] +# match: "$Move2D = '' and ($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious')" +# replace: +# - test: +# # can't get here with MatchCounter=0, so no need to echo command +# if: "preceding-sibling::*" +# then: +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "rad" # phrase('row' five in table) +# - x: "count(preceding-sibling::*)" +# - T: "kolonne" # phrase('column' five in table) +# - x: "count(*)" +# - pause: medium +# - test: +# if: "$NavMode = 'Character'" +# then: +# - with: +# variables: [NavCommand: "'MovePreviousZoom'"] +# replace: [x: "preceding-sibling::*[1]"] +# else: +# - set_variables: [NavNode: "preceding-sibling::*[1]/*[last()]/*[last()]/@id"] +# else: [x: ".."] # try again for after +# +#- name: move-previous-locked-zoom-level +# # locked zoom level +# tag: "*" +# match: +# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" +# - "$ReadZoomLevel>=0" +# replace: +# - test: +# # if moving into base (nothing before), we must be moving to the base, so "in" will be said +# if: "count(preceding-sibling::*) > 2 and preceding-sibling::*[1][name(.)='none']" +# then: +# - with: +# variables: [Move2D: "'ut av'", Child2D: "."] +# replace: [x: ".."] +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: [x: "preceding-sibling::*[1]"] # skip over 'none' +# else: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MovePrevious'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadPrevious'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "venstre" # phrase(move 'left') +# - pause: short +# - with: +# variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) +# replace: [x: ".."] +# - with: +# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MovePreviousZoom'"] +# replace: [x: "preceding-sibling::*[1]"] +# +#- name: move-previous-default +# tag: "*" +# match: "$NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious'" +# replace: +# - test: +# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'MovePrevious'" +# then: [T: "gå"] # phrase('move' to next entry in table) +# - else_if: "$NavCommand = 'ReadPrevious'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "venstre" # phrase(move 'left') +# - pause: short +# - test: +# if: "IsNode(.., '2D')" +# then: +# - with: +# variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) +# replace: [x: ".."] +# - set_variables: [NavNode: "preceding-sibling::*[1]/@id"] +# +# ********* ReadZoomLevel toggle *************** +# These set ::NavMode +# +#- name: toggle-mode-up +# tag: "*" +# match: "$NavCommand = 'ToggleZoomLockUp'" +# replace: +# - test: +# - if: "$NavMode = 'Enhanced'" +# then: +# - T: "symbolmodus" # phrase(a mathematical 'character') +# - set_variables: [NavMode: "'Character'", ReadZoomLevel: "1"] +# - else_if: "$NavMode = 'Character'" +# then: +# - T: "forenklet modus" # phrase(a 'simple' way to do something) +# - set_variables: [NavMode: "'Simple'", ReadZoomLevel: "1"] +# - else: +# - T: "utvidet modus" # phrase(an 'enhanced' way to do something) +# - set_variables: [NavMode: "'Enhanced'", ReadZoomLevel: "-1"] +# # - T: "läge" # phrase(a simple 'mode' of use) +# # SWEDISH: Removed the ending "mode" string and added "läge" to the previous strings, for grammatical purposes. +# - pause: long +# - test: +# - if: "$NavMode != 'Enhanced'" # potentially need to zoom to the sibling +# then: +# - with: +# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"] +# replace: [x: "."] +# +#- name: toggle-mode-down +# tag: "*" +# match: "$NavCommand = 'ToggleZoomLockDown'" +# replace: +# - test: +# - if: "$NavMode = 'Enhanced'" +# then: +# - T: "forenklet modus" # phrase(an 'simple' way to do something) +# - set_variables: [NavMode: "'Simple'", ReadZoomLevel: "1"] +# - else_if: "$NavMode = 'Character'" +# then: +# - T: "utvidet modus" # phrase(an 'enhanced' way to do something) +# - set_variables: [NavMode: "'Enhanced'", ReadZoomLevel: "-1"] +# - else: +# - T: "symbolmodus" # phrase(a mathematical 'character') +# - set_variables: [NavMode: "'Character'", ReadZoomLevel: "1"] +# # - T: "användningsläge" # phrase(a simple 'mode' of use) +# # SWEDISH: Removed the ending "mode" string and added "läge" to the previous strings, for grammatical purposes. +# - pause: long +# - test: +# - if: "$NavMode != 'Enhanced'" # potentially need to zoom to the sibling +# then: +# - with: +# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"] +# replace: [x: "."] +# +#- name: toggle-speech-describe +# tag: "*" +# match: "$NavCommand = 'ToggleSpeakMode'" +# replace: +# - test: +# if: "$Overview = 'true'" +# then: +# - T: "les uttrykk etter navigering" # phrase('speak expression after move') +# - set_variables: [Overview: "'false'"] +# else: +# - T: "oversikt over uttrykk etter navigering" # phrase('overview of expression after move') +# - set_variables: [Overview: "'true'"] +# - pause: long +# +#- name: current +# tag: "*" +# match: "$NavCommand = 'ReadCurrent' or $NavCommand = 'DescribeCurrent'" +# replace: +# - test: +# if: "$NavVerbosity = 'Verbose'" +# then: +# - test: +# - if: "$NavCommand = 'ReadCurrent'" +# then: [T: "les"] # phrase('read' next entry in table) +# else: [T: "beskriv"] # phrase('describe' next entry in table) +# - T: "nåværende" # phrase('current' entry in table) +# - set_variables: [NavNode: "@id"] +# - pause: long +# +# this needs to be near the end because we only test for 'Describe', "Read", etc., and we don't want to get 'DescribeNext', etc. +#- name: placemarker +# +# tag: "*" +# match: +# - "starts-with($NavCommand, 'Read') or " +# - "starts-with($NavCommand, 'Describe') or " +# - "starts-with($NavCommand, 'MoveTo')" +# replace: +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - test: +# - if: "starts-with($NavCommand, 'Read')" +# then: [T: "les"] # phrase('read' next entry in table) +# - else_if: "starts-with($NavCommand, 'Describe')" +# then: [T: "beskriv"] # phrase('describe' next entry in table) +# - else_if: "starts-with($NavCommand, 'MoveTo')" +# then: [T: "gå til"] # phrase('move to' the next entry in table) +# else: [T: "angi"] # phrase('set' the value of the next entry in table) +# - T: "plassholder" # phrase('placeholder' for the value) +# - x: "$PlaceMarkerIndex" +# - pause: long +# - set_variables: [NavNode: "$PlaceMarker"] +# +#- name: set-placemarker +# tag: "*" +# match: "starts-with($NavCommand, 'SetPlacemarker')" +# replace: +# - test: +# if: "$NavVerbosity != 'Terse'" +# then: +# - T: "angi plassholder" # phrase('set placeholder' to the value) +# - x: "$PlaceMarkerIndex" +# - pause: long +# - set_variables: [NavNode: "@id"] +# +# ********* WhereAmI *************** +# +# FIX: WhereAmI needs support from the Rust code to loop around and do speech at each iteration. +# Alternatively, it could insert a special token that Rust code does a "replace" on with the speech (e.g. SPEECH_AT{id}) +# or a new command "speak" which takes a node id +#- name: where-am-i-start +# +# +# tag: "*" +# match: "($NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll') and $MatchCounter = 0" +# replace: +# - translate: "@id" +# - pause: long +# - with: +# variables: [MatchCounter: "$MatchCounter + 1"] +# replace: [x: ".."] +# +#- name: where-am-i-stop +# tag: "*" +# match: +# - "($NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll') and $MatchCounter > 0 and" +# # stopping conditions +# - "(self::m:math or " +# - " parent::*[self::m:math and (count(*)=1 or (count(*)=2 and *[2][.=',' or .='.' or .=';' or .='?']) ) ] " +# - ")" +# replace: +# - test: +# if: "$NavCommand = 'WhereAmI'" +# then: +# - T: "ingenting mer" # phrase('inside of nothing more') +# - pause: long +# - set_variables: [SpeakExpression: "'false'"] +# else: +# - T: "inne i" # phrase('inside' a big expression) +# - pause: medium +# - set_variables: [NavNode: "@id"] +# +#- name: where-am-i-middle +# tag: "*" +# match: "$NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll'" +# replace: +# - T: "inne i" # phrase('inside' a big expression) +# - pause: medium +# - test: +# - if: "$NavMode='Enhanced' and parent::*[self::m:mrow and IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false)]" +# then: [x: ".."] # auto-zoom up +# - else_if: "$NavCommand = 'WhereAmI'" +# then: [set_variables: [NavNode: "@id"]] +# else: +# - translate: "@id" +# - pause: long +# - x: '..' From d58f08a0e26ece8c2b1de1ed09e3147cc0178a9e Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 13 May 2026 15:37:39 +0200 Subject: [PATCH 22/43] Updated Navigation file --- Rules/Languages/nb/navigate.yaml | 91 ++++++++++++++++---------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/Rules/Languages/nb/navigate.yaml b/Rules/Languages/nb/navigate.yaml index da6aa7dcb..e61b1270e 100644 --- a/Rules/Languages/nb/navigate.yaml +++ b/Rules/Languages/nb/navigate.yaml @@ -100,28 +100,28 @@ - name: into-or-out-of-mtr tag: [mtr, mlabeledtr] - match: "$Move2D = 'inn'" # Navigate into a 2D structure. + match: "$Move2D = 'i'" # Navigate into a 2D structure. replace: - T: "kolonne" - - x: "count($Child2D/preceding-sibling::*)+1" # Teller antall søskennoder før Child2D (noden man beveger seg inn i) + - x: "count($Child2D/preceding-sibling::*)+1" # Count number of sibling nodes before Child2D (the node being navigated into) and add 1 to get the column number. - pause: "medium" - name: into-or-out-of-mmultiscripts tag: "*" - match: "$Move2D != '' and (@data-from-mathml='mmultiscripts' or self::m:mmultiscripts)" #Navigerer inn i en 2d struktur som er en mmultiscripts. + match: "$Move2D != '' and (@data-from-mathml='mmultiscripts' or self::m:mmultiscripts)" # Navigate into a 2D structure that is a mmultiscripts. replace: - test: - if: "name($Child2D)!='none'" # Sjekker at barnet man navigerer inn i ikke er tomt. + if: "name($Child2D)!='none'" # Check that the child being navigated into is not empty. then: - with: variables: - - NumPrecedingSiblings: "count($Child2D/preceding-sibling::*)" # Lagrer antall søsken foran målnoden. + - NumPrecedingSiblings: "count($Child2D/preceding-sibling::*)" # Store the number of siblings before the target node. replace: - - x: "$Move2D" #Sier retningsordet (inn/ut av) + - x: "$Move2D" # Say the direction (into/out of) - test: - - if: "$NumPrecedingSiblings=0" # Ingen søsken foran målnoden + - if: "$NumPrecedingSiblings=0" # No siblings before the target node then: [T: "base"] # phrase(the 'base' of the power) - - else_if: "$Child2D/preceding-sibling::*[self::m:mprescripts]" # Er vi etter -taggent. I så fall er vi i prescriptene. + - else_if: "$Child2D/preceding-sibling::*[self::m:mprescripts]" # Are we after the tag? If so, we are in the prescripts. then: - test: # in postscripts -- base shifts by one if: "$NumPrecedingSiblings mod 2 = 0" @@ -143,14 +143,14 @@ replace: - with: variables: - - PartNumber: "count($Child2D/preceding-sibling::*)" # antall søsken før målnoden - - PartName: "GetNavigationPartName(name(.), $PartNumber)" # finne navn på delen. F.eks. teller/nevner, base/eksponent + - PartNumber: "count($Child2D/preceding-sibling::*)" # Count the number of siblings before the target node + - PartName: "GetNavigationPartName(name(.), $PartNumber)" # Find the name of the part. E.g., numerator/denominator, base/exponent replace: - - x: "$Move2D" # inn/ut av + - x: "$Move2D" # into/out of - test: - - if: "$PartName != ''" # hvis et navn på delen finnes + - if: "$PartName != ''" # if a name for the part exists then: [x: "$PartName"] - - else_if: "count(*) = 1" # hvis noden har ett barn + - else_if: "count(*) = 1" # if the node has one child then_test: if: "$NavVerbosity = 'Verbose'" then: [x: "translate(name(.), '-_', ' ')"] # e.g., "in absolute value" @@ -250,17 +250,17 @@ - " ($NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and $NavMode='Enhanced') and " - "count(*)=1 and (*[1][self::m:mrow or @data-from-mathml='mrow'] and - not(@data-from-mathml='msqrt' or self::m:msqrt or @data-from-mathml='menclose' or self::m:menclose))" # nåværende node har ett barn som er en . Den nåværende noden er ikke msqrt ekker menclose. + not(@data-from-mathml='msqrt' or self::m:msqrt or @data-from-mathml='menclose' or self::m:menclose))" # current node has one child that is an . The current node is not msqrt or menclose. replace: - with: - variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] # hvis verbosity er verbose, blir SayCommand satt til true, ellers false - replace: [x: "."] # kjør videre med nåverende node + variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] # if verbosity is verbose, SayCommand is set to true, otherwise false + replace: [x: "."] # continue with the current node - test: if: "not(*[1][self::m:mrow or @data-from-mathml='mrow'])" then: - with: - # Setter Move2d til "i". - # Setter Child2d til siste barn hvis kommandoen er "MovePreviousZoom", ellers første barn. + # Set Move2D to "i". + # Set Child2D to the last child if the command is "MovePreviousZoom", otherwise the first child. variables: [Move2D: "'i'", Child2D: "IfThenElse($NavCommand = 'MovePreviousZoom', (*[last()]), (*[1]))"] # phrase('in' the denominator) replace: [x: "IfThenElse($NavCommand = 'MovePreviousZoom', 1, $Child2D)"] - test: @@ -392,7 +392,7 @@ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"] replace: [x: "."] - with: - variables: [Move2D: "'out of'", Child2D: "."] + variables: [Move2D: "'ut av'", Child2D: "."] replace: [x: ".."] - x: ".." @@ -493,7 +493,7 @@ then: [x: ".."] # auto-zoom: move out a level and retry else: - with: - variables: [Move2D: "'out of'", Child2D: "."] # phrase('out of' the denominator) + variables: [Move2D: "'ut av'", Child2D: "."] # phrase('out of' the denominator) replace: [x: ".."] - test: if: "parent::m:mtd" @@ -632,7 +632,7 @@ else: - set_variables: [NavNode: "preceding-sibling::*[1]/*[1]/@id"] else: - - t: "ingen foregående kolonner" # phrase('no previous column' in the table) + - T: "ingen foregående kolonner" # phrase('no previous column' in the table) - set_variables: [SpeakExpression: "'false'"] - name: move-cell-next @@ -896,7 +896,7 @@ then: [x: "$Following"] else: - with: - variables: [Move2D: "'in'", Child2D: "$Following"] # phrase('in' the denominator) + variables: [Move2D: "'i'", Child2D: "$Following"] # phrase('in' the denominator) replace: [x: ".."] - with: variables: [NavCommand: "'MoveNextZoom'"] @@ -931,7 +931,7 @@ - pause: medium - with: variables: - - Move2D: "'end of'" + - Move2D: "'slutt på'" - Child2D: "$EdgeNode/*[last()]" - MatchCounter: $MatchCounter + 1 replace: [x: "$EdgeNode"] @@ -951,10 +951,10 @@ - T: "kan ikke" # phrase('cannot' move right in expression) - test: - if: "$NavCommand = 'MoveNext'" - then: [t: "gå"] # phrase('move' to next entry in table) + then: [T: "gå"] # phrase('move' to next entry in table) - else_if: "$NavCommand = 'ReadNext'" - then: [t: "lese"] # phrase('read' next entry in table) - else: [t: "beskrive"] # phrase('describe' next entry in table) + then: [T: "lese"] # phrase('read' next entry in table) + else: [T: "beskrive"] # phrase('describe' next entry in table) - T: "høyre" # phrase(move 'right') - pause: short - T: "slutt på uttrykk" # phrase(move 'end of math') @@ -980,11 +980,11 @@ if: "following-sibling::*" then: - with: - variables: [Move2D: "'in'", Child2D: "."] # phrase('in' the denominator) + variables: [Move2D: "'i'", Child2D: "."] # phrase('in' the denominator) replace: [x: ".."] else: - with: - variables: [Move2D: "'out of'", Child2D: "."] + variables: [Move2D: "'ut av'", Child2D: "."] replace: [x: ".."] - x: ".." @@ -1065,12 +1065,12 @@ if: "preceding-sibling::* and following-sibling::*[1][name(.)='none']" then: - with: - variables: [Move2D: "'out of'", Child2D: "."] + variables: [Move2D: "'ut av'", Child2D: "."] replace: [x: ".."] - x: "following-sibling::*[1]" else: - with: - variables: [Move2D: "'in'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) + variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) replace: [x: ".."] - with: variables: [NavCommand: "'MoveNextZoom'"] @@ -1091,7 +1091,7 @@ if: "IsNode(.., '2D') or not(IsNode(.., 'mathml'))" then: - with: - variables: [Move2D: "'in'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) + variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) replace: [x: ".."] - set_variables: [NavNode: "following-sibling::*[1]/@id"] @@ -1113,7 +1113,7 @@ then: [x: "$Preceding"] else: - with: - variables: [Move2D: "'in'", Child2D: "$Preceding"] # phrase('in' the denominator) + variables: [Move2D: "'i'", Child2D: "$Preceding"] # phrase('in' the denominator) replace: [x: ".."] - with: variables: [NavCommand: "'MovePreviousZoom'"] @@ -1148,7 +1148,7 @@ - pause: medium - with: variables: - - Move2D: "'end of'" + - Move2D: "'slutt på'" - Child2D: "$EdgeNode/*[1]" - MatchCounter: $MatchCounter + 1 replace: [x: "$EdgeNode"] @@ -1177,7 +1177,7 @@ - T: "kan ikke gå venstre" # phrase('cannot move left') - pause: short - with: - variables: [Move2D: "'start of'", Child2D: "."] + variables: [Move2D: "'start på'", Child2D: "."] replace: [x: "."] - pause: long - set_variables: [SpeakExpression: "'false'"] @@ -1222,11 +1222,11 @@ if: "preceding-sibling::*" then: - with: - variables: [Move2D: "'in'", Child2D: "."] # phrase('in' the denominator) + variables: [Move2D: "'i'", Child2D: "."] # phrase('in' the denominator) replace: [x: ".."] else: - with: - variables: [Move2D: "'out of'", Child2D: "."] + variables: [Move2D: "'ut av'", Child2D: "."] replace: [x: ".."] - x: ".." @@ -1252,7 +1252,7 @@ if: "not(parent::m:mrow)" then: - with: - variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) + variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) replace: [x: ".."] - set_variables: [NavNode: "preceding-sibling::*[1]/*[2]/@id"] @@ -1316,12 +1316,12 @@ if: "count(preceding-sibling::*) > 2 and preceding-sibling::*[1][name(.)='none']" then: - with: - variables: [Move2D: "'out of'", Child2D: "."] + variables: [Move2D: "'ut av'", Child2D: "."] replace: [x: ".."] - x: "preceding-sibling::*[1]" # skip over 'none' else: - with: - variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) + variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) replace: [x: ".."] - with: variables: [NavCommand: "'MovePreviousZoom'"] @@ -1342,7 +1342,7 @@ if: "IsNode(.., '2D') or not(IsNode(.., 'mathml'))" then: - with: - variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) + variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) replace: [x: ".."] - set_variables: [NavNode: "preceding-sibling::*[1]/@id"] @@ -1422,7 +1422,7 @@ - test: - if: "$NavCommand = 'ReadCurrent'" then: [T: "les"] # phrase('read' next entry in table) - else: [t: "beskriv"] # phrase('describe' next entry in table) + else: [T: "beskriv"] # phrase('describe' next entry in table) - T: "nåværende" # phrase('current' entry in table) - pause: long - set_variables: [NavNode: "@id"] @@ -1447,7 +1447,7 @@ - else_if: "starts-with($NavCommand, 'MoveTo')" then: [T: "gå til "] # phrase('move to' the next entry in table) else: [T: "angi"] # phrase('set' the value of the next entry in table) - - t: "plassholder" # phrase('placeholder' for the value) + - T: "plassholder" # phrase('placeholder' for the value) - x: "$PlaceMarkerIndex" - pause: long - set_variables: [NavNode: "$PlaceMarker"] @@ -1492,20 +1492,19 @@ - test: if: "$NavCommand = 'WhereAmI'" then: - - t: "inside of nothing more" # phrase('inside of nothing more') + - T: "inni ingenting mer" # phrase('inside of nothing more') - pause: long - set_variables: [SpeakExpression: "'false'"] else: - - t: "inside" # phrase('inside' a big expression) + - T: "inni" # phrase('inside' a big expression) - pause: medium - set_variables: [NavNode: "@id"] -# Marthe - name: where-am-i-middle tag: "*" match: "$NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll'" replace: - - t: "inside" # phrase('inside' a big expression) + - T: "inni" # phrase('inside' a big expression) - pause: medium - test: - if: "$NavMode='Enhanced' and parent::*[self::m:mrow and (IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false))]" From fbda57568613df5f21492bf925f14d0ba290a171 Mon Sep 17 00:00:00 2001 From: Marthe Date: Fri, 15 May 2026 16:06:59 +0200 Subject: [PATCH 23/43] Added some intent mapping + fix spaces --- Rules/Languages/nb/definitions.yaml | 57 ++++++++++++++++------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/Rules/Languages/nb/definitions.yaml b/Rules/Languages/nb/definitions.yaml index 6d686df36..8b44f365a 100644 --- a/Rules/Languages/nb/definitions.yaml +++ b/Rules/Languages/nb/definitions.yaml @@ -5,11 +5,11 @@ # name: [ "...", "..." "..." ], # If an "intent" is used, the 'terse:medium:verbose' speech for the intent name is given here for a prefix||infix||postfix||function fixity -# If only one ":" is used, it the first part is used for 'terse' and the second part is used for 'medium' and 'verbose' +# If only one ":" is used, the first part is used for 'terse' and the second part is used for 'medium' and 'verbose' # If no ":"s are used, the same speech is used for all forms # If bracketing words make sense, they are separated with ";"s # Intent mappings must specify whether they are "prefix", "infix", "postfix", or "function" with an "=" sign -# If there are multiple fixities (e.g., see transpose), they are separated with "|| +# If there are multiple fixities (e.g., see transpose), they are separated with "||" # for readability, spaces can be used around any of the delimiter characters # Note: if there are multiple fixities, the first one is used if the fixity is not given in the intent - IntentMappings: { @@ -20,24 +20,25 @@ "absolute-value": "function= ; absoluttverdien; slutt absoluttverdi", "binomial": "infix=binomialkoeffisient; over; slutt binomialkoeffisient", - #"greatest-common-divisor": "function=gcd: gcd: største felles divisor", #NORWEGIAN: We say "største felles divisor til 8 og 4" (greatest common divisor to 8 and 4) - #"imaginary-part": "function=den imaginære delen, den imaginære delen, den imaginære delen", - #"least-common-multiple": "function=lcm: lcm: minste felles multiplum" #NORWEGIAN: We say "minste felles multiplum til 2 og 6" (least common multiplum to 2 and 6) + "dimension-product": "infix=ganger", + #"greatest-common-divisor": "function=gcd: gcd: største felles divisor", # NORWEGIAN: We say "største felles divisor til 8 og 4" (greatest common divisor to 8 and 4) + "imaginary-part": "function=den imaginære delen", + #"least-common-multiple": "function=lcm: lcm: minste felles multiplum" # NORWEGIAN: We say "minste felles multiplum til 2 og 6" (least common multiplum to 2 and 6) "limit": "prefix=grenseverdien når", "lim-sup": "prefix=den øvre grenseverdien når", "lim-inf": "prefix=den nedre grenseverdien når", "logarithm-with-base": "prefix=log med grunntall: logaritmen med grunntall: logaritmen med grunntall", - #"natural-logarithm": "function=l n: den naturlige logaritmen: den naturlige logaritmen", + "natural-logarithm": "function=l n: den naturlige logaritmen: den naturlige logaritmen", "minus": "infix=minus || prefix=minus", "plus": "infix=pluss || prefix=pluss", - #"real-part": "function=den reelle delen", + "real-part": "function=den reelle delen", "transpose": "postfix=transponert || function=transponert", - #"norm": "function=; normen; slutt norm", #NORWEGIAN: We say "normen til" (the norm to), so this rule is in linear-algebra - "trace": "function=;sporet; slutt spor", - #"dimension": "function=; dimensjonen; slutt dimensjon", #NORWEGIAN: We say "dimensjonen til" (the dimension to), so this rule is in linear-algebra - # "homomorphism": "function= ; homomorfism; slut homomorfism", # doesn't fit function pattern - # "kernel": "function= ; noll-rummet : noll-rummet till: noll-rummet till; slut noll-rummet", # doesn't fit function pattern + #"norm": "function=; normen; slutt norm", # NORWEGIAN: We say "normen til" (the norm to), so this rule is in linear-algebra + "trace": "function= ; sporet; slutt spor", + #"dimension": "function=; dimensjonen; slutt dimensjon", # NORWEGIAN: We say "dimensjonen til" (the dimension to), so this rule is in linear-algebra + # "homomorphism": "function= ; homomorfi; slutt homomorfi", # doesn't fit function pattern + # "kernel": "function= ; nullrommet ; slutt nullrommet # NORWEGIAN: We say "nullrommet til" (the kernel to), so this rule is in linear-algebra "vector": "function= ; vektor: vektoren: vektoren || prefix=vektor: vektoren: vektoren", "cross-product": "infix=kryss: kryssprodukt: kryssprodukt", "dot-product": "infix=prikk: skalarprodukt: skalarprodukt", @@ -46,26 +47,30 @@ #"curl": "function= ; curl; slutt curl", #NORWEGIAN: We say "curlen til" (the curl to), so this rule is in calculus #"gradient": "function= ; grad: gradient: gradient; slutt gradient", #NORWEGIAN: We say "gradienten til" (the gradient to), so this rule is in calculus "laplacian": "function=laplace", # speech engines don't do a good job with "laplacian" (swedish ones might) + + "chemistry-concentration": "function= ; konsentrasjon: konsentrasjonen av: konsentrasjonen av; slutt konsentrasjon", } - NavigationParts: { "large-op": "base; nedre grense; øvre grense", - "mfrac": "teller;nevner", - "fraction": "teller;nevner", + "mfrac": "teller; nevner", + "fraction": "teller; nevner", "msqrt": "rot", "square-root": "rot", - "mroot": "rot;rotindeks", - "root": "rot;rotindeks", - "msub": "base;nedre indeks", - "sub": "base;nedre indeks", - "msup": "base;øvre indeks", - "say-super": "base;opphøyd", - "skip-super": "base;opphøyd", - "power": "base;eksponent", - "msubsup": "base;nedre indeks;øvre indeks", - "munder": "base;nedre grense", - "mover": "base;øvre grense", - "munderover": "base;nedre grense;øvre grense", + "mroot": "rot; rotindeks", + "root": "rot; rotindeks", + "msub": "base; nedre indeks", + "sub": "base; nedre indeks", + "logarithm-with-base": "base", + "indexed-by": "base; nedre indeks", + "msup": "base; øvre indeks", + "say-super": "base; øvre indeks", + "skip-super": "base; øvre indeks", + "power": "base; eksponent", + "msubsup": "base; nedre indeks; øvre indeks", + "munder": "base; nedre grense", + "mover": "base; øvre grense", + "munderover": "base; nedre grense; øvre grense", # words for moving into and out of one of the parts (e.g., "move right 'out of' numerator, 'in' denominator") # it's a hack to put them here, but at least they are grouped with the other navigation parts From bef19c1aacf068ec2cbb6ea12b1136a2d37c5642 Mon Sep 17 00:00:00 2001 From: Marthe Date: Mon, 18 May 2026 10:41:48 +0200 Subject: [PATCH 24/43] Refine Norwegian speech rules Adjust word usage from 'roten' to 'rot' for mathematical roots and add a short pause before 'gitt' (given). --- Rules/Languages/nb/overview.yaml | 8 ++++---- Rules/Languages/nb/unicode.yaml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Rules/Languages/nb/overview.yaml b/Rules/Languages/nb/overview.yaml index c901d5504..7b24c292c 100644 --- a/Rules/Languages/nb/overview.yaml +++ b/Rules/Languages/nb/overview.yaml @@ -46,13 +46,13 @@ if: "*[2][self::m:mn]" then_test: - if: "*[2][text()='2']" - then: [T: "kvadratroten"] + then: [T: "kvadratrot"] - else_if: "*[2][text()='3']" - then: [T: "kubikkroten"] + then: [T: "kubikkrot"] - else_if: "*[2][not(contains(., ','))]" - then: [x: "ToOrdinal(*[2])", T: "roten"] + then: [x: "ToOrdinal(*[2])", T: "rot"] else: - - T: "roten av grad" + - T: "rot av grad" - x: "*[2]" - test: if: "IsNode(*[1], 'simple')" diff --git a/Rules/Languages/nb/unicode.yaml b/Rules/Languages/nb/unicode.yaml index 4271fafee..4cb9c990c 100644 --- a/Rules/Languages/nb/unicode.yaml +++ b/Rules/Languages/nb/unicode.yaml @@ -156,7 +156,7 @@ - else_if: "$SpeechStyle != 'ClearSpeak'" then_test: - if: "$DefaultToGiven" - then: [T: "gitt"] + then: [pause: short, T: "gitt"] - else_if: "preceding-sibling::*[1][self::m:mn and not(contains(., $DecimalSeparators))] and following-sibling::*[1][self::m:mn and not(contains(., $DecimalSeparators))]" then: [T: "deler"] @@ -166,7 +166,7 @@ - else_if: "$ClearSpeak_VerticalLine = 'SuchThat'" then: [T: "slik at"] - else_if: "$ClearSpeak_VerticalLine = 'Given' or $DefaultToGiven" - then: [T: "gitt"] + then: [pause: short, T: "gitt"] - else: [T: "deler"] - "}": # 0x7d From 7cc88269d956bd669b4ab4f61a7e377d8b7cf24c Mon Sep 17 00:00:00 2001 From: Marthe Date: Mon, 18 May 2026 10:45:26 +0200 Subject: [PATCH 25/43] Update tests to align with last commit --- tests/Languages/nb/ClearSpeak/symbols_and_adornments.rs | 4 ++-- tests/Languages/nb/shared.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Languages/nb/ClearSpeak/symbols_and_adornments.rs b/tests/Languages/nb/ClearSpeak/symbols_and_adornments.rs index 5c7d9dbcb..5e1dd7964 100644 --- a/tests/Languages/nb/ClearSpeak/symbols_and_adornments.rs +++ b/tests/Languages/nb/ClearSpeak/symbols_and_adornments.rs @@ -181,7 +181,7 @@ fn vertical_line_divides() -> Result<()> { 3|6 "; test_ClearSpeak("nb", "ClearSpeak_VerticalLine", "Given", expr, - "3 gitt 6")?; + "3, gitt 6")?; return Ok(()); } @@ -201,7 +201,7 @@ fn vertical_line_divides() -> Result<()> { "; test_ClearSpeak_prefs("nb", vec![("ClearSpeak_VerticalLine", "Given"), ("ClearSpeak_ImpliedTimes", "None")] - , expr, "stor p; startparentes; stor a gitt stor b; sluttparentes")?; + , expr, "stor p; startparentes; stor a, gitt stor b; sluttparentes")?; return Ok(()); } diff --git a/tests/Languages/nb/shared.rs b/tests/Languages/nb/shared.rs index a3d10617d..4a7252b8f 100644 --- a/tests/Languages/nb/shared.rs +++ b/tests/Languages/nb/shared.rs @@ -149,8 +149,8 @@ fn prime() -> Result<()> { #[test] fn given() -> Result<()> { let expr = "P(A|B)"; - test("nb", "SimpleSpeak", expr, "stor p; startparentes; stor a gitt stor b; sluttparentes")?; - test("nb", "ClearSpeak", expr, "stor p; startparentes; stor a gitt stor b; sluttparentes")?; // not good, but follows the spec + test("nb", "SimpleSpeak", expr, "stor p; startparentes; stor a, gitt stor b; sluttparentes")?; + test("nb", "ClearSpeak", expr, "stor p; startparentes; stor a, gitt stor b; sluttparentes")?; // not good, but follows the spec return Ok(()); } From eeff1f5926a936f9d170504c25db335d4d7ea781 Mon Sep 17 00:00:00 2001 From: Marthe Date: Sun, 31 May 2026 15:32:37 +0200 Subject: [PATCH 26/43] Fix pluralization of Norwegian mixed number fractions Correctly apply pluralization of mixed numbers without an explicit following unit. Introduce `IsPluralNoUnit` to ensure the fraction's numerator dictates the plural form, resolving cases like "2 tredjedeler". --- Rules/Languages/nb/ClearSpeak_Rules.yaml | 3 ++- Rules/Languages/nb/SimpleSpeak_Rules.yaml | 3 ++- tests/Languages/nb/ClearSpeak/mfrac.rs | 24 +++++++++++++++++++++++ tests/Languages/nb/SimpleSpeak/mfrac.rs | 24 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/Rules/Languages/nb/ClearSpeak_Rules.yaml b/Rules/Languages/nb/ClearSpeak_Rules.yaml index 7897b7847..2d9efe396 100644 --- a/Rules/Languages/nb/ClearSpeak_Rules.yaml +++ b/Rules/Languages/nb/ClearSpeak_Rules.yaml @@ -144,6 +144,7 @@ - "*[2][self::m:mn][not(contains(., $DecimalSeparators)) and (2<= text() and text()<=10)]" # NORWEGIAN: Removed $ClearSpeak_Fractions='Ordinal', cause the pattern for ordinal fractions is not right. variables: - IsPlural: "not(*[1]=1 or preceding-sibling::*[1][self::m:mo and .='\u2064'])" # '\u2064' is invisible plus and is used in mixed fractions + - IsPluralNoUnit: "not(*[1]=1)" # mixed numbers without following units should pluralize on numerator # set right level for the location of the common fraction/mixed fraction - IsMixedFraction: "preceding-sibling::*[1][.='\u2064']" - UnitSibling: "IfThenElse($IsMixedFraction, .., .)" @@ -169,7 +170,7 @@ - if: "not($UnitNode)" then: - x: "*[1]" - - x: "ToOrdinal(*[2], true(), $IsPlural)" # extra args specify fractional ordinal and whether it is plural + - x: "ToOrdinal(*[2], true(), $IsPluralNoUnit)" # extra args specify fractional ordinal and whether it is plural # unit follows the fraction -- special cases - else: - test: diff --git a/Rules/Languages/nb/SimpleSpeak_Rules.yaml b/Rules/Languages/nb/SimpleSpeak_Rules.yaml index 4c06153a1..4cd49ec36 100644 --- a/Rules/Languages/nb/SimpleSpeak_Rules.yaml +++ b/Rules/Languages/nb/SimpleSpeak_Rules.yaml @@ -76,6 +76,7 @@ - "*[2][self::m:mn][not(contains(., $DecimalSeparators)) and 2<= text() and text()<=10]" variables: - IsPlural: "not(*[1]=1 or preceding-sibling::*[1][self::m:mo and .='\u2064'])" # '\u2064' is invisible plus and is used in mixed fractions + - IsPluralNoUnit: "not(*[1]=1)" # mixed numbers without following units should pluralize on numerator - UnitSibling: "IfThenElse(preceding-sibling::*[1][.='\u2064'], .., .)" # set the potential unit node -- otherwise set it to a empty node set (use a made up name) - UnitNodeLocation: "IfThenElse($UnitSibling/..[self::m:mrow and count(*)=3 and *[2][.='\u2062']], @@ -99,7 +100,7 @@ - if: "not($UnitNode)" then: - x: "*[1]" - - x: "ToOrdinal(*[2], true(), $IsPlural)" # extra args specify fractional ordinal and whether it is plural + - x: "ToOrdinal(*[2], true(), $IsPluralNoUnit)" # extra args specify fractional ordinal and whether it is plural # unit follows the fraction -- special cases - else: - test: diff --git a/tests/Languages/nb/ClearSpeak/mfrac.rs b/tests/Languages/nb/ClearSpeak/mfrac.rs index b1ac45e9f..9273f7e36 100644 --- a/tests/Languages/nb/ClearSpeak/mfrac.rs +++ b/tests/Languages/nb/ClearSpeak/mfrac.rs @@ -311,3 +311,27 @@ fn binomial() -> Result<()> { return Ok(()); } + +#[test] +fn mixed_number_1() -> Result<()> { + let expr = r#" + + 1 + 23 +"#; + test("nb", "ClearSpeak", expr, "1 og 2 tredjedeler")?; + return Ok(()); + +} + +#[test] +fn mixed_number_2() -> Result<()> { + let expr = r#" + + 2 + 44 +"#; + test("nb", "ClearSpeak", expr, "2 og 4 fjerdedeler")?; + return Ok(()); + +} \ No newline at end of file diff --git a/tests/Languages/nb/SimpleSpeak/mfrac.rs b/tests/Languages/nb/SimpleSpeak/mfrac.rs index 3f3d85f15..d8a602e0b 100644 --- a/tests/Languages/nb/SimpleSpeak/mfrac.rs +++ b/tests/Languages/nb/SimpleSpeak/mfrac.rs @@ -354,3 +354,27 @@ fn binomial_non_simple_top_and_bottom() -> Result<()> { return Ok(()); } + +#[test] +fn mixed_number_1() -> Result<()> { + let expr = r#" + + 1 + 23 +"#; + test("nb", "SimpleSpeak", expr, "1 og 2 tredjedeler")?; + return Ok(()); + +} + +#[test] +fn mixed_number_2() -> Result<()> { + let expr = r#" + + 2 + 44 +"#; + test("nb", "SimpleSpeak", expr, "2 og 4 fjerdedeler")?; + return Ok(()); + +} \ No newline at end of file From c7d4d8305c93d9d50bb8b4a532287b47b713269b Mon Sep 17 00:00:00 2001 From: Marthe Date: Mon, 1 Jun 2026 12:48:57 +0200 Subject: [PATCH 27/43] Fix mixed number pluralization logic - correct the last commit Mixed fractions without a following unit is now spoken correctly. --- Rules/Languages/nb/ClearSpeak_Rules.yaml | 7 ++- Rules/Languages/nb/SimpleSpeak_Rules.yaml | 5 +- tests/Languages/nb/ClearSpeak/mfrac.rs | 4 +- tests/Languages/nb/SimpleSpeak/mfrac.rs | 4 +- tests/Languages/nb/units.rs | 56 +++++++++++++++++++++++ 5 files changed, 65 insertions(+), 11 deletions(-) diff --git a/Rules/Languages/nb/ClearSpeak_Rules.yaml b/Rules/Languages/nb/ClearSpeak_Rules.yaml index 2d9efe396..1cd6fe39c 100644 --- a/Rules/Languages/nb/ClearSpeak_Rules.yaml +++ b/Rules/Languages/nb/ClearSpeak_Rules.yaml @@ -143,8 +143,7 @@ - "*[1][self::m:mn][not(contains(., $DecimalSeparators)) and ($ClearSpeak_Fractions='Ordinal' or text()<20)] and" # NORWEGIAN: Changed decimal point to $DecimalSeparators - "*[2][self::m:mn][not(contains(., $DecimalSeparators)) and (2<= text() and text()<=10)]" # NORWEGIAN: Removed $ClearSpeak_Fractions='Ordinal', cause the pattern for ordinal fractions is not right. variables: - - IsPlural: "not(*[1]=1 or preceding-sibling::*[1][self::m:mo and .='\u2064'])" # '\u2064' is invisible plus and is used in mixed fractions - - IsPluralNoUnit: "not(*[1]=1)" # mixed numbers without following units should pluralize on numerator + - IsPlural: "not(*[1]=1)" # set right level for the location of the common fraction/mixed fraction - IsMixedFraction: "preceding-sibling::*[1][.='\u2064']" - UnitSibling: "IfThenElse($IsMixedFraction, .., .)" @@ -170,11 +169,11 @@ - if: "not($UnitNode)" then: - x: "*[1]" - - x: "ToOrdinal(*[2], true(), $IsPluralNoUnit)" # extra args specify fractional ordinal and whether it is plural + - x: "ToOrdinal(*[2], true(), $IsPlural)" # extra args specify fractional ordinal and whether it is plural # unit follows the fraction -- special cases - else: - test: - if: "$NeuterUnitFollows and (*[1]=1 or ($IsMixedFraction and preceding-sibling::*[2][.=1]))" + if: "$NeuterUnitFollows and *[1]=1" then: [T: "ett"] else: [x: "*[1]"] - test: diff --git a/Rules/Languages/nb/SimpleSpeak_Rules.yaml b/Rules/Languages/nb/SimpleSpeak_Rules.yaml index 4cd49ec36..b10006a7d 100644 --- a/Rules/Languages/nb/SimpleSpeak_Rules.yaml +++ b/Rules/Languages/nb/SimpleSpeak_Rules.yaml @@ -75,8 +75,7 @@ - "*[1][self::m:mn][not(contains(., $DecimalSeparators)) and text()<20] and" # NORWEGIAN: Changed decimal point to $DecimalSeparators - "*[2][self::m:mn][not(contains(., $DecimalSeparators)) and 2<= text() and text()<=10]" variables: - - IsPlural: "not(*[1]=1 or preceding-sibling::*[1][self::m:mo and .='\u2064'])" # '\u2064' is invisible plus and is used in mixed fractions - - IsPluralNoUnit: "not(*[1]=1)" # mixed numbers without following units should pluralize on numerator + - IsPlural: "not(*[1]=1)" - UnitSibling: "IfThenElse(preceding-sibling::*[1][.='\u2064'], .., .)" # set the potential unit node -- otherwise set it to a empty node set (use a made up name) - UnitNodeLocation: "IfThenElse($UnitSibling/..[self::m:mrow and count(*)=3 and *[2][.='\u2062']], @@ -100,7 +99,7 @@ - if: "not($UnitNode)" then: - x: "*[1]" - - x: "ToOrdinal(*[2], true(), $IsPluralNoUnit)" # extra args specify fractional ordinal and whether it is plural + - x: "ToOrdinal(*[2], true(), $IsPlural)" # extra args specify fractional ordinal and whether it is plural # unit follows the fraction -- special cases - else: - test: diff --git a/tests/Languages/nb/ClearSpeak/mfrac.rs b/tests/Languages/nb/ClearSpeak/mfrac.rs index 9273f7e36..41fc7febc 100644 --- a/tests/Languages/nb/ClearSpeak/mfrac.rs +++ b/tests/Languages/nb/ClearSpeak/mfrac.rs @@ -313,7 +313,7 @@ fn binomial() -> Result<()> { } #[test] -fn mixed_number_1() -> Result<()> { +fn mixed_number_one() -> Result<()> { let expr = r#" 1 @@ -325,7 +325,7 @@ fn mixed_number_1() -> Result<()> { } #[test] -fn mixed_number_2() -> Result<()> { +fn mixed_number_two() -> Result<()> { let expr = r#" 2 diff --git a/tests/Languages/nb/SimpleSpeak/mfrac.rs b/tests/Languages/nb/SimpleSpeak/mfrac.rs index d8a602e0b..2a6624dab 100644 --- a/tests/Languages/nb/SimpleSpeak/mfrac.rs +++ b/tests/Languages/nb/SimpleSpeak/mfrac.rs @@ -356,7 +356,7 @@ fn binomial_non_simple_top_and_bottom() -> Result<()> { } #[test] -fn mixed_number_1() -> Result<()> { +fn mixed_number_one() -> Result<()> { let expr = r#" 1 @@ -368,7 +368,7 @@ fn mixed_number_1() -> Result<()> { } #[test] -fn mixed_number_2() -> Result<()> { +fn mixed_number_two() -> Result<()> { let expr = r#" 2 diff --git a/tests/Languages/nb/units.rs b/tests/Languages/nb/units.rs index 21bde49ac..50178f5b9 100644 --- a/tests/Languages/nb/units.rs +++ b/tests/Languages/nb/units.rs @@ -1064,4 +1064,60 @@ fn currency_plural() -> Result<()> { test("nb", "SimpleSpeak", expr, "10 kroner")?; return Ok(()); +} + +#[test] +fn common_fraction_mixed_unit_masculine() -> Result<()> { + let expr = r#" + + 1 + 34 + m +"#; + test("nb", "ClearSpeak", expr, "1 og 3 fjerdedels, meter")?; + test("nb", "SimpleSpeak", expr, "1 og 3 fjerdedels, meter")?; + return Ok(()); + +} + +#[test] +fn common_fraction_mixed_unit_neuter() -> Result<()> { + let expr = r#" + + 1 + 34 + s +"#; + test("nb", "ClearSpeak", expr, "ett og 3 fjerdedels, sekund")?; + test("nb", "SimpleSpeak", expr, "ett og 3 fjerdedels, sekund")?; + return Ok(()); + +} + +#[test] +fn common_fraction_mixed_unit_plural_neuter() -> Result<()> { + let expr = r#" + + 2 + 45 + s +"#; + test("nb", "ClearSpeak", expr, "2 og 4 femtedels, sekund")?; + test("nb", "SimpleSpeak", expr, "2 og 4 femtedels, sekund")?; + return Ok(()); + +} + +#[test] +fn common_fraction_mixed_unit_plural_masculine() -> Result<()> { + let expr = r#" + + 2 + 45 + hr +"#; + test("nb", "ClearSpeak", expr, "2 og 4 femtedels, time")?; + test("nb", "SimpleSpeak", expr, "2 og 4 femtedels, time")?; + return Ok(()); + } \ No newline at end of file From 641bdd24a73901ebd499c9f8ffcaf7e6e234b511 Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 2 Jun 2026 12:49:14 +0200 Subject: [PATCH 28/43] Correct Norwegian spelling of 'sec' to 'sek' for better pronunciation --- Rules/Languages/nb/SharedRules/general.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rules/Languages/nb/SharedRules/general.yaml b/Rules/Languages/nb/SharedRules/general.yaml index 377a38c17..076b9d344 100644 --- a/Rules/Languages/nb/SharedRules/general.yaml +++ b/Rules/Languages/nb/SharedRules/general.yaml @@ -446,7 +446,7 @@ - bookmark: "@id" - test: if: "$Verbosity='Terse'" - then: [T: "sec"] # phrase(to 'seek' a solution) + then: [T: "sek"] # phrase(to 'seek' a solution) else: [T: "sekans"] # phrase(a 'secant' intersects a curve at two or more points) - name: csc # audit-ignore @@ -506,7 +506,7 @@ - bookmark: "@id" - test: if: "$Verbosity='Terse'" - then: [T: "sec hyperbolicus"] # phrase('sheck' is shorthand for hyperbolic secant) + then: [T: "sek hyperbolicus"] # phrase('sheck' is shorthand for hyperbolic secant) else: [T: "sekans hyperbolicus"] # phrase('hyperbolic secant' is a mathematical function) - name: csch From bc0d8e9ddfcfef22c1a955a274bb2c13947702b5 Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 2 Jun 2026 12:49:34 +0200 Subject: [PATCH 29/43] Update t to T --- Rules/Languages/nb/unicode.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rules/Languages/nb/unicode.yaml b/Rules/Languages/nb/unicode.yaml index 4cb9c990c..37960c4f7 100644 --- a/Rules/Languages/nb/unicode.yaml +++ b/Rules/Languages/nb/unicode.yaml @@ -100,8 +100,8 @@ - "/": # 0x2f (en: 'divided by') - test: if: "ancestor-or-self::*[contains(@data-intent-property, ':literal:')]" - then: [t: "skråstrek"] # 0x2f - else: [t: "delt på"] # 0x2f + then: [T: "skråstrek"] # 0x2f + else: [T: "delt på"] # 0x2f - ":": [T: "kolon"] # 0x3a (en: 'colon') - ";": [T: "semikolon"] # 0x3b (en: 'semicolon') - "<": # 0x3c From e516225905b741e07346d5964cbc8f95e8c39600 Mon Sep 17 00:00:00 2001 From: Marthe Date: Thu, 4 Jun 2026 13:56:57 +0200 Subject: [PATCH 30/43] Refine Norwegian navigation command parsing and speech output --- Rules/Languages/nb/navigate.yaml | 47 ++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/Rules/Languages/nb/navigate.yaml b/Rules/Languages/nb/navigate.yaml index e61b1270e..a4330068c 100644 --- a/Rules/Languages/nb/navigate.yaml +++ b/Rules/Languages/nb/navigate.yaml @@ -56,38 +56,38 @@ else: - test: - if: "starts-with($NavCommand, 'Zoom')" - then: [set_variables: [Prefix: "'zoom'"]] # phrase('zoom' in to see more details) + then: [set_variables: [Prefix: "'zoom'", CommandOffset: "5"]] # phrase('zoom' in to see more details) - else_if: "starts-with($NavCommand, 'Move')" - then: [set_variables: [Prefix: "'gå'"]] # phrase('move' to next entry in table) + then: [set_variables: [Prefix: "'gå'", CommandOffset: "5"]] # phrase('move' to next entry in table) - else_if: "starts-with($NavCommand, 'Read')" - then: [set_variables: [Prefix: "'les'"]] # phrase('read' to next entry in table) + then: [set_variables: [Prefix: "'les'", CommandOffset: "5"]] # phrase('read' to next entry in table) - else_if: "starts-with($NavCommand, 'Describe')" - then: [set_variables: [Prefix: "'beskriv'"]] # phrase('describe' to next entry in table) + then: [set_variables: [Prefix: "'beskriv'", CommandOffset: "9"]] # phrase('describe' to next entry in table) - test: if: "$Prefix != ''" then: - x: "$Prefix" - test: - - if: "substring($NavCommand, string-length($Prefix)+1) = 'In'" + - if: "substring($NavCommand, $CommandOffset) = 'In'" then: [T: "inn"] # phrase(zoom 'in' to see more details) - - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'InAll'" + - else_if: "substring($NavCommand, $CommandOffset) = 'InAll'" # HACK: '\uF8FE' is used internally for the concatenation char by 'ct' -- this gets "ed" concatenated to "zoom" then: [T: "\uF8FEet helt inn"] # phrase(zoom 'out all of the way' to see more details) - - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Out'" + - else_if: "substring($NavCommand, $CommandOffset) = 'Out'" then: [T: "ut"] # phrase(zoom 'out' to see more details) - - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'OutAll'" + - else_if: "substring($NavCommand, $CommandOffset) = 'OutAll'" # HACK: '\uF8FE' is used internally for the concatenation char by 'ct' -- this gets "ed" concatenated to "zoom" then: [T: "\uF8FEet helt ut"] # phrase(zoom 'out all of the way' to see more details) - - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Next'" + - else_if: "substring($NavCommand, $CommandOffset) = 'Next'" then: [T: "høyre"] # phrase(move to the 'right') - - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Previous'" + - else_if: "substring($NavCommand, $CommandOffset) = 'Previous'" then: [T: "venstre"] # phrase(move to the 'left') - - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Current'" + - else_if: "substring($NavCommand, $CommandOffset) = 'Current'" then: [T: "nåværende"] # phrase(who is the 'current' president) - - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'LineStart'" - then: [T: "til starten av linja"] # phrase(move 'to start of line') - - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'LineEnd'" - then: [T: "til slutten av linja"] # phrase(move 'to end of line') + - else_if: "substring($NavCommand, $CommandOffset) = 'LineStart'" + then: [T: "til starten av raden"] # phrase(move 'to start of line') + - else_if: "substring($NavCommand, $CommandOffset) = 'LineEnd'" + then: [T: "til slutten av raden"] # phrase(move 'to end of line') - pause: "medium" - set_variables: [MatchCounter: "$MatchCounter + 1"] @@ -98,6 +98,11 @@ (name(.)='mrow' or name(.) = 'mtr' or name(.) = 'mlabeledtr' or @data-from-mathml = 'mtable')" replace: [] +- name: into-or-out-of-minus-silent-on-zoom-out + tag: "*" + match: "$Move2D != '' and name(.)='minus' and count(*)=1 and ($NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll')" + replace: [] + - name: into-or-out-of-mtr tag: [mtr, mlabeledtr] match: "$Move2D = 'i'" # Navigate into a 2D structure. @@ -521,10 +526,10 @@ - if: "$NavCommand = 'MoveStart'" then: [T: "gå til starten av uttrykket"] # phrase('move to start of math') - else_if: "$NavCommand = 'MoveLineStart'" - then: [T: "gå til starten av linja"] # phrase('move to start of line') + then: [T: "gå til starten av raden"] # phrase('move to start of line') - else_if: "$NavCommand = 'MoveEnd'" then: [T: "gå til slutten av uttrykket"] # phrase('move to end of math') - else: [T: "gå til slutten av linja"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') + else: [T: "gå til slutten av raden"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') - pause: "medium" - test: if: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart'" @@ -564,8 +569,8 @@ then: - test: if: "$NavCommand = 'MoveLineStart'" - then: [T: "gå til starten av linja"] # phrase('move to start of line') - else: [T: "gå til slutten av linja"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') + then: [T: "gå til starten av raden"] # phrase('move to start of line') + else: [T: "gå til slutten av raden"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') - pause: "medium" - test: if: "self::m:mrow or @data-from-mathml = 'mrow'" @@ -1447,7 +1452,7 @@ - else_if: "starts-with($NavCommand, 'MoveTo')" then: [T: "gå til "] # phrase('move to' the next entry in table) else: [T: "angi"] # phrase('set' the value of the next entry in table) - - T: "plassholder" # phrase('placeholder' for the value) + - T: "markør" # phrase('placeholder' for the value) - x: "$PlaceMarkerIndex" - pause: long - set_variables: [NavNode: "$PlaceMarker"] @@ -1459,7 +1464,7 @@ - test: if: "$NavVerbosity != 'Terse'" then: - - T: "angi plassholder" # phrase('set placeholder' to the value) + - T: "angi markør" # phrase('set placeholder' to the value) - x: "$PlaceMarkerIndex" - pause: long - set_variables: [NavNode: "@id"] From ab49018ddb88c011a13d10709264e13afe57559c Mon Sep 17 00:00:00 2001 From: Marthe Date: Thu, 4 Jun 2026 19:19:49 +0200 Subject: [PATCH 31/43] Added folder to document testing --- docs/Documentation testing/test_navigation_summer_2026.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/Documentation testing/test_navigation_summer_2026.html diff --git a/docs/Documentation testing/test_navigation_summer_2026.html b/docs/Documentation testing/test_navigation_summer_2026.html new file mode 100644 index 000000000..e69de29bb From 19733ee621c8ebe99dd25e83121cc5929ffc4af9 Mon Sep 17 00:00:00 2001 From: Marthe Date: Sat, 6 Jun 2026 09:31:17 +0200 Subject: [PATCH 32/43] =?UTF-8?q?Changed=20"mark=C3=B8r"=20to=20"plassmerk?= =?UTF-8?q?er"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The word "markør" is used for other things in screen readers. --- Rules/Languages/nb/navigate.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rules/Languages/nb/navigate.yaml b/Rules/Languages/nb/navigate.yaml index a4330068c..6f2a3eea3 100644 --- a/Rules/Languages/nb/navigate.yaml +++ b/Rules/Languages/nb/navigate.yaml @@ -1452,7 +1452,7 @@ - else_if: "starts-with($NavCommand, 'MoveTo')" then: [T: "gå til "] # phrase('move to' the next entry in table) else: [T: "angi"] # phrase('set' the value of the next entry in table) - - T: "markør" # phrase('placeholder' for the value) + - T: "plassmerker" # phrase('placeholder' for the value) - x: "$PlaceMarkerIndex" - pause: long - set_variables: [NavNode: "$PlaceMarker"] @@ -1464,7 +1464,7 @@ - test: if: "$NavVerbosity != 'Terse'" then: - - T: "angi markør" # phrase('set placeholder' to the value) + - T: "angi plassmerker" # phrase('set placeholder' to the value) - x: "$PlaceMarkerIndex" - pause: long - set_variables: [NavNode: "@id"] From 2df8da06457cbc458e897b58fa94c012a50d6e09 Mon Sep 17 00:00:00 2001 From: Marthe Date: Sat, 6 Jun 2026 09:35:15 +0200 Subject: [PATCH 33/43] Add pause for "terse" and "medium" for simple fractions Added a short pause after simple fractions for terse and medium. This shoud make it easier to know when you are out of the fraction. --- Rules/Languages/nb/ClearSpeak_Rules.yaml | 4 ++++ tests/Languages/nb/units.rs | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Rules/Languages/nb/ClearSpeak_Rules.yaml b/Rules/Languages/nb/ClearSpeak_Rules.yaml index 1cd6fe39c..40f0eb546 100644 --- a/Rules/Languages/nb/ClearSpeak_Rules.yaml +++ b/Rules/Languages/nb/ClearSpeak_Rules.yaml @@ -211,6 +211,8 @@ - pause: short - T: "slutt brøk" # phrase(7 over 8 'end fraction') - pause: short + else: + - pause: short - # fraction with text or numbers followed by text in both numerator and denominator name: fraction-over-text @@ -240,6 +242,8 @@ - pause: short - T: "slutt brøk" # phrase(7 over 8 'end fraction') - pause: short + else: + - pause: short # NORWEGIAN: Changed to English version - name: default diff --git a/tests/Languages/nb/units.rs b/tests/Languages/nb/units.rs index 50178f5b9..413de9178 100644 --- a/tests/Languages/nb/units.rs +++ b/tests/Languages/nb/units.rs @@ -796,7 +796,7 @@ fn fraction_not_ordinal_units_neuter() -> Result<()> { let expr = r#" 311min "#; - test("nb", "ClearSpeak", expr, "3 over 11 minutter")?; + test("nb", "ClearSpeak", expr, "3 over 11, minutter")?; test("nb", "SimpleSpeak", expr, "3 over 11, minutter")?; return Ok(()); @@ -808,7 +808,7 @@ fn fraction_not_ordinal_units_masculine_feminine() -> Result<()> { let expr = r#" 311hr "#; - test("nb", "ClearSpeak", expr, "3 over 11 timer")?; + test("nb", "ClearSpeak", expr, "3 over 11, timer")?; test("nb", "SimpleSpeak", expr, "3 over 11, timer")?; return Ok(()); @@ -819,7 +819,7 @@ fn fraction_not_ordinal_2_units_neuter() -> Result<()> { let expr = r#" 721min "#; - test("nb", "ClearSpeak", expr, "7 over 21 minutter")?; + test("nb", "ClearSpeak", expr, "7 over 21, minutter")?; test("nb", "SimpleSpeak", expr, "7 over 21, minutter")?; return Ok(()); @@ -831,7 +831,7 @@ fn fraction_not_ordinal_2_units_masculine_feminine() -> Result<()> { let expr = r#" 721hr "#; - test("nb", "ClearSpeak", expr, "7 over 21 timer")?; + test("nb", "ClearSpeak", expr, "7 over 21, timer")?; test("nb", "SimpleSpeak", expr, "7 over 21, timer")?; return Ok(()); @@ -929,7 +929,7 @@ fn fraction_not_ordinal_units_neuter_prefix() -> Result<()> { let expr = r#" 721nsek "#; - test("nb", "ClearSpeak", expr, "7 over 21 nano-sekunder")?; + test("nb", "ClearSpeak", expr, "7 over 21, nano-sekunder")?; test("nb", "SimpleSpeak", expr, "7 over 21, nano-sekunder")?; return Ok(()); @@ -941,7 +941,7 @@ fn fraction_not_ordinal_units_masculine_feminine_prefix() -> Result<()> { let expr = r#" 721ml "#; - test("nb", "ClearSpeak", expr, "7 over 21 milli-liter")?; + test("nb", "ClearSpeak", expr, "7 over 21, milli-liter")?; test("nb", "SimpleSpeak", expr, "7 over 21, milli-liter")?; return Ok(()); From 82e7902c11104638c92795a7c7ee2093db97b2b0 Mon Sep 17 00:00:00 2001 From: Marthe Date: Sat, 6 Jun 2026 09:43:26 +0200 Subject: [PATCH 34/43] Fix formatting in nested simple fractions test cases --- tests/Languages/nb/ClearSpeak/mfrac.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Languages/nb/ClearSpeak/mfrac.rs b/tests/Languages/nb/ClearSpeak/mfrac.rs index 41fc7febc..cc9712092 100644 --- a/tests/Languages/nb/ClearSpeak/mfrac.rs +++ b/tests/Languages/nb/ClearSpeak/mfrac.rs @@ -174,9 +174,9 @@ fn nested_simple_fractions() -> Result<()> { "; test_prefs("nb", "ClearSpeak", vec![("ClearSpeak_Fractions", "Auto")], expr, "1 halv over 2 tredjedeler")?; test_prefs("nb", "ClearSpeak", vec![("ClearSpeak_Fractions", "Ordinal")], expr, "1 halv over 2 tredjedeler")?; - test_prefs("nb", "ClearSpeak", vec![("ClearSpeak_Fractions", "Over")], expr, "1 over 2 over 2 over 3")?; + test_prefs("nb", "ClearSpeak", vec![("ClearSpeak_Fractions", "Over")], expr, "1 over 2, over 2 over 3")?; test_prefs("nb", "ClearSpeak", vec![("ClearSpeak_Fractions", "FracOver")], expr, - "brøken brøken 1 over 2 over brøken 2 over 3")?; + "brøken brøken 1 over 2, over brøken 2 over 3")?; test_prefs("nb", "ClearSpeak", vec![("ClearSpeak_Fractions", "General")], expr, "brøken med teller brøken med teller 1; og nevner 2; og nevner brøken med teller 2; og nevner 3")?; test_prefs("nb", "ClearSpeak", vec![("ClearSpeak_Fractions", "EndFrac")], expr, "1 halv over 2 tredjedeler")?; From 88d4ca154f012415ae3e2b85e498362d5a5fe87d Mon Sep 17 00:00:00 2001 From: Marthe Date: Sun, 7 Jun 2026 13:05:53 +0200 Subject: [PATCH 35/43] Added audit-ignore Added audit-ignore to rules I first was unsure about. They are now checked. --- Rules/Languages/nb/ClearSpeak_Rules.yaml | 22 +++++++++--------- Rules/Languages/nb/SimpleSpeak_Rules.yaml | 4 ++-- Rules/Languages/nb/overview.yaml | 2 +- Rules/Languages/nb/unicode.yaml | 28 +++++++++++------------ 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Rules/Languages/nb/ClearSpeak_Rules.yaml b/Rules/Languages/nb/ClearSpeak_Rules.yaml index 40f0eb546..2b0a6b628 100644 --- a/Rules/Languages/nb/ClearSpeak_Rules.yaml +++ b/Rules/Languages/nb/ClearSpeak_Rules.yaml @@ -215,7 +215,7 @@ - pause: short - # fraction with text or numbers followed by text in both numerator and denominator - name: fraction-over-text + name: fraction-over-text # audit-ignore tag: fraction match: - "not($ClearSpeak_Fractions='General' or $ClearSpeak_Fractions='GeneralEndFrac') and" @@ -295,7 +295,7 @@ else: [T: "i tredje"] # phrase(625 equals 5 'cubed') # The following element is invisible function application. Used for expressions like sin^n x. -- name: function-power +- name: function-power # audit-ignore tag: power match: - "following-sibling::*[1][self::m:mo][.='⁡']" #invisible function apply @@ -345,7 +345,7 @@ - T: "i tredje" # phrase(5 'cubed' equals 125) # Norwegian: Changed to longer pause at the end. -- name: simple-integer +- name: simple-integer # audit-ignore tag: power match: "*[2][self::m:mn][not(contains(., $DecimalSeparators))]" # NORWEGIAN: Changed decimal point to $DecimalSeparators replace: @@ -356,7 +356,7 @@ - pause: medium # Norwegian: Changed to longer pause at the end. -- name: simple-negative-integer +- name: simple-negative-integer # audit-ignore tag: power match: - "*[2][self::m:minus and count(*)=1 and" @@ -370,7 +370,7 @@ - pause: medium # Norwegian: Changed to longer pause at the end. -- name: simple-var +- name: simple-var # audit-ignore tag: power match: "*[2][self::m:mi][string-length(.)=1]" replace: @@ -390,7 +390,7 @@ # If these are allowed for non-Auto values, then you end up with "...power power...". - # [xxx]^n # Norwegian: Added "end exponent" for verbose, and longer pause for terse and medium. - name: nested-squared-or-cubed + name: nested-squared-or-cubed # audit-ignore tag: power match: - "$ClearSpeak_Exponents = 'Auto' and" @@ -415,7 +415,7 @@ - # - [xxx]^n # Norwegian: Added "end exponent" for verbose, and longer pause for terse and medium. - name: nested-negative-squared-or-cubed + name: nested-negative-squared-or-cubed # audit-ignore tag: power match: - "$ClearSpeak_Exponents = 'Auto' and" @@ -442,7 +442,7 @@ - # [xxx] var^n # Norwegian: Added "end exponent" for verbose, and longer pause for terse and medium. - name: nested-var-squared-or-cubed + name: nested-var-squared-or-cubed # audit-ignore tag: power match: - "$ClearSpeak_Exponents = 'Auto' and" @@ -471,7 +471,7 @@ - # -[xxx] var^n # Norwegian: Added "end exponent" for verbose, and longer pause for terse and medium. - name: nested-negative-var-squared-or-cubed + name: nested-negative-var-squared-or-cubed # audit-ignore tag: power match: - "$ClearSpeak_Exponents = 'Auto' and" @@ -513,7 +513,7 @@ - T: "slutt eksponent" # phrase(and now 'end exponent' has been reached) # Norwegian: Added "end exponent" for verbose, and longer pause for terse and medium. -- name: default +- name: default # audit-ignore tag: power match: "." replace: @@ -678,7 +678,7 @@ then: [T: "den naturlige logaritmen"] # phrase(the 'natural log' of x) else: [SPELL: "'ln'"] -- name: ClearSpeak-multi-line +- name: ClearSpeak-multi-line # audit-ignore tag: [piecewise, system-of-equations, lines] # these are ignored in favor of the ClearSpeak prefs match: "." variables: diff --git a/Rules/Languages/nb/SimpleSpeak_Rules.yaml b/Rules/Languages/nb/SimpleSpeak_Rules.yaml index b10006a7d..61ac1456e 100644 --- a/Rules/Languages/nb/SimpleSpeak_Rules.yaml +++ b/Rules/Languages/nb/SimpleSpeak_Rules.yaml @@ -191,7 +191,7 @@ else: [T: "i tredje"] # phrase(5 'cubed' equals 125) # The following element is invisible function application. Used for expressions like sin^n x. -- name: function-power +- name: function-power # audit-ignore tag: power match: - "following-sibling::*[1][self::m:mo][.='⁡']" #invisible function apply @@ -278,7 +278,7 @@ # Norwegian: Added "end exponent" at the end. This doesn't apply if the parent is a power. # For example: x^((4/5)^(n+1)) # The outer power is caught by the nested rule. Avoid duplicated "end exponent". -- name: default +- name: default # audit-ignore tag: power match: "." replace: diff --git a/Rules/Languages/nb/overview.yaml b/Rules/Languages/nb/overview.yaml index 7b24c292c..4de4de7d8 100644 --- a/Rules/Languages/nb/overview.yaml +++ b/Rules/Languages/nb/overview.yaml @@ -38,7 +38,7 @@ then: [T: "av"] - x: "*[1]" -- name: overview-default +- name: overview-default # audit-ignore tag: [mroot, root] match: "." replace: diff --git a/Rules/Languages/nb/unicode.yaml b/Rules/Languages/nb/unicode.yaml index 37960c4f7..81613d82a 100644 --- a/Rules/Languages/nb/unicode.yaml +++ b/Rules/Languages/nb/unicode.yaml @@ -109,7 +109,7 @@ if: "$Verbosity!='Terse'" then: [T: "er"] # (en: 'is', google translation) - T: "mindre enn" # (en: 'less than') - - "=": # 0x3d + - "=": # 0x3d # audit-ignore # SWEDISH: We remove "är" from all occurrences of = after consulting our mathematician advisor. - test: if: "$Verbosity!='Terse'" @@ -136,7 +136,7 @@ if: $SpeechStyle = 'ClearSpeak' or $SpeechStyle = 'SimpleSpeak' then: [T: "slutt hakeparentes"] # (en: 'close bracket', google translation) else: [T: "høyre hakeparentes"] # (en: 'right bracket') - - "^": [T: "hatt"] # 0x5e (en: 'hat') + - "^": [T: "hatt"] # 0x5e (en: 'hat') # audit-ignore - "_": [T: "understrek"] # 0x5f (en: 'under bar', MathPlayer: 'streck under', google: 'under bar') - "`": [T: "grav aksent"] # 0x60 (en: 'grave') - "{": # 0x7b @@ -283,7 +283,7 @@ then: [T: "og så videre"] # (en: 'and so on', google translation) else: [T: "og så videre opp til"] # (en: 'and so on up to') - - "⁡": # 0x2061 #NORWEGIAN: Changed to literal. Didn't add the test with "TrigFunctionName, cause want to say "sinus hyperbolicus av" + - "⁡": # 0x2061 # audit-ignore - test: if: "preceding-sibling::*[1][.='log' or .='ln' or .='lg' or .='exp'] or not( @@ -336,13 +336,13 @@ - "↓": [T: "nedoverpil"] # 0x2193 (en: 'downwards arrow') - "⇒": [T: "impliserer"] # 0x21d2 (en: 'rightwards double arrow') - "∀": [T: "for alle"] # 0x2200 (en: 'for all') - - "∂": [T: "partiell derivert"] # 0x2202 + - "∂": [T: "partiell derivert"] # 0x2202 # audit-ignore # SWEDISH: This is only refered to as "del" in Swedish, but we write "dell" for correct pronounciation. - "∃": [T: "det eksisterer"] # 0x2203 (en: 'there exists') - "∄": [T: "det eksisterer ikke"] # 0x2204 (en: 'there does not exist') - "∅": [T: "den tomme mengden"] # 0x2205 (en: 'empty set') - - "∆": [T: "laplace av"] # 0x2206 (en: 'laplacian of') - - "∈": # 0x2208 + - "∆": [T: "laplace av"] # 0x2206 (en: 'laplacian of') # audit-ignore + - "∈": # 0x2208 # audit-ignore - test: if: "$SpeechStyle != 'ClearSpeak'" then: @@ -364,7 +364,7 @@ - else_if: $ClearSpeak_SetMemberSymbol = 'Element' then: [T: "er et element i"] # (en: 'is in', google translation) - else: [T: "tilhører"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'belongs to') - - "∉": # 0x2209 + - "∉": # 0x2209 # audit-ignore # rule is identical to 0x2208 - test: if: "$SpeechStyle != 'ClearSpeak'" @@ -389,7 +389,7 @@ - else_if: $ClearSpeak_SetMemberSymbol = 'In' then: [T: "er ikke i"] # (en: 'is not in', google translation) - else: [T: "tilhører ikke"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'does not belong to') - - "∊": # 0x220a + - "∊": # 0x220a # audit-ignore - test: if: "$SpeechStyle != 'ClearSpeak'" then: @@ -418,7 +418,7 @@ - "∓": [T: "minus pluss"] # 0x2213 (en: 'minus or plus') - "∗": [T: "ganger"] # 0x2217 (en: 'times') - "∘": [T: "sammensatt med"] # 0x2218 (en: 'composed with') - - "√": [T: "kvadratroten av"] # 0x221a (en: 'square root of') + - "√": [T: "kvadratroten av"] # 0x221a (en: 'square root of') # audit-ignore - "∝": # 0x221d - test: if: "$Verbosity!='Terse'" @@ -453,15 +453,15 @@ - "∭": [T: "trippelintegralet"] # 0x222d (en: 'triple integral') - "∮": [T: "kurveintegralet"] # 0x222e (en: 'contour integral') - "∶": # 0x2236 - - T: "til" # (en: 'to') + - T: "til" # (en: 'to') # audit-ignore - "∷": [T: "som"] # 0x2237 (en: 'as', MathPlayer: 'proportion', google: 'som') - - "∼": # 0x223c (en: 'varies with') + - "∼": # 0x223c (en: 'varies with') # audit-ignore - test: if: "$Verbosity!='Terse'" then: [T: "er"] - T: "proporsjonal med" - "∽": [T: "omvendt tilde"] # 0x223d (en: 'reversed tilde') - - "∾": # 0x223e + - "∾": # 0x223e # audit-ignore # SWEDISH: Could not find any examples of how this character is used and what specific meaning it has. In ClearSpeak rules, it is # translated as "omvänt långdraget s". - T: "omvendt langstrakt s" # (en: 'most positive', MathPlayer: 'inverted lazy s', google: 'mest positiva') @@ -488,13 +488,13 @@ then: [T: "er"] - T: "større enn eller lik" - - "≦": # 0x2266 (en: 'less than over equal to') + - "≦": # 0x2266 (en: 'less than over equal to') # audit-ignore - test: if: "$Verbosity!='Terse'" then: [T: "er"] - T: "mindre enn eller lik" - - "≧": # 0x2267 (en: 'greater than over equal to') + - "≧": # 0x2267 (en: 'greater than over equal to') # audit-ignore - test: if: "$Verbosity!='Terse'" then: [T: "er"] From beaa1e053bfdc1c65ad667ea0c68f6ed4aa56374 Mon Sep 17 00:00:00 2001 From: Marthe Date: Sun, 7 Jun 2026 13:06:29 +0200 Subject: [PATCH 36/43] Removed comment with the old navigation rules --- Rules/Languages/nb/navigate.yaml | 1746 +----------------------------- 1 file changed, 1 insertion(+), 1745 deletions(-) diff --git a/Rules/Languages/nb/navigate.yaml b/Rules/Languages/nb/navigate.yaml index 6f2a3eea3..c9df6a762 100644 --- a/Rules/Languages/nb/navigate.yaml +++ b/Rules/Languages/nb/navigate.yaml @@ -1519,1748 +1519,4 @@ else: - translate: "@id" - pause: long - - x: '..' - -# ********* Rules below are from old navigation file *************** -# Rules for speaking what happens when moving into or out of a notation -#- name: into-or-out-of -# #tag: mfrac -# #match: "$Move2D != ''" -# #replace: -# - x: "$Move2D" -# - test: -# if: "count($Child2D/preceding-sibling::*)=0" -# then: [T: "telleren"] # phrase(the 'numerator' of a fraction) -# else: [T: "nevneren"] # phrase(the 'denominator' of a fraction) -# - pause: "medium" -# -#- name: into-or-out-of -# tag: msqrt -# match: "$Move2D != ''" -# replace: -# - x: "$Move2D" -# - T: "kvadratroten" # phrase(the 'square root' of x) -# - pause: "medium" -# -#- name: into-or-out-of -# tag: mroot -# match: "$Move2D != ''" -# replace: -# - x: "$Move2D" -# - test: -# if: "count($Child2D/preceding-sibling::*)=0" -# then: [T: "roten"] # phrase(the cube 'root' of x) -# else: [T: "rotindeksen"] # phrase(the 'root index' of x is 3) -# - pause: "medium" -# -#NORWEGIAN: For powers we say "grunntallet" for the base, but since this markup is used for other things than powers and subindexes, use the word "basen". -#- name: into-or-out-of -# tag: msub -# match: "$Move2D != ''" -# replace: -# - x: "$Move2D" -# - test: -# if: "count($Child2D/preceding-sibling::*)=0" -# then: [T: "basen"] # phrase(the 'base' of the power) -# else: [T: "nedre indeks"] # phrase(x with 'subscript' 2) -# - pause: "medium" -# -#- name: into-or-out-of -# tag: msup -# match: "$Move2D != ''" -# replace: -# - x: "$Move2D" -# - test: -# if: "count($Child2D/preceding-sibling::*)=0" -# then: [T: "basen"] # phrase(the 'base' of the power) -# else: [T: "øvre indeks"] # phrase(x with 'superscript' 2) # FIX: it would be better to use the word used when reading (power, exponent, ...) -# - pause: "medium" -# -#- name: into-or-out-of -# tag: msubsup -# match: "$Move2D != ''" -# replace: -# - x: "$Move2D" -# - test: -# - if: "count($Child2D/preceding-sibling::*)=0" -# then: [T: "basen"] # phrase(the 'base' of the power) -# - else_if: "count($Child2D/preceding-sibling::*)=1" -# then: [T: "nedre indeks"] # phrase(x with 'subscript' 2) -# else: [T: "øvre indeks"] # phrase(x with 'superscript' 2) # FIX: it would be better to use the word used when reading (power, exponent, ...) -# - pause: "medium" -# -#- name: into-or-out-of -# tag: munder -# match: "$Move2D != ''" -# replace: -# - x: "$Move2D" -# - test: -# if: "count($Child2D/preceding-sibling::*)=0" -# then: [T: "basen"] # phrase(the 'base' of the power) -# else: [T: "nedre indeks"] # phrase(the 'lower limit' of the function is zero) -# - pause: "medium" -# -#- name: into-or-out-of -# tag: mover -# match: "$Move2D != ''" -# replace: -# - x: "$Move2D" -# - test: -# if: "count($Child2D/preceding-sibling::*)=0" -# then: [T: "basen"] # phrase(the 'base' of the power) -# else: [T: "øvre indeks"] # phrase(the 'upper limit' of the function is zero) -# - pause: "medium" -# -#- name: into-or-out-of -# tag: munderover -# match: "$Move2D != ''" -# replace: -# - x: "$Move2D" -# - test: -# - if: "count($Child2D/preceding-sibling::*)=0" -# then: [T: "basen"] # phrase(the 'base' of the power) -# - else_if: "count($Child2D/preceding-sibling::*)=1" -# then: [T: "nedre indeks"] # phrase(the 'lower limit' of the function is zero) -# else: [T: "øvre indeks"] # phrase(the 'upper limit' of the function is zero) -# - pause: "medium" -# -#- name: into-or-out-of -# tag: mmultiscripts -# match: "$Move2D != ''" -# replace: -# - test: -# if: "name($Child2D)!='none'" -# then: -# - with: -# variables: -# - NumPrecedingSiblings: "count($Child2D/preceding-sibling::*)" -# replace: -# - x: "$Move2D" -# - test: -# - if: "$NumPrecedingSiblings=0" -# then: [T: "basen"] # phrase(the 'base' of the power) -# - else_if: "$Child2D/preceding-sibling::*[self::m:mprescripts]" # are we before mprescripts and hence are postscripts -# then: -# - test: # in postscripts -- base shifts by one -# if: "$NumPrecedingSiblings mod 2 = 0" -# then: [T: "nedre indeks"] # phrase(x with 'subscript' 2) -# else: [T: "øvre indeks"] # phrase(x with 'superscript' 2) -# else: -# - test: -# if: "$NumPrecedingSiblings mod 2 = 0" -# then: [T: "øvre indeks"] # phrase(x with 'superscript' 2) -# else: [T: "nedre indeks"] # phrase(x with 'subscript' 2) -# - pause: "medium" -# -#- name: into-or-out-of -# tag: mtd -# match: "$Move2D = 'into'" -# replace: -# - x: "$Move2D" -# - T: "kolonne" # phrase(the first 'column' in the table) -# - x: "count($Child2D/preceding-sibling::*)+1" -# - pause: "medium" -# -#- name: into-or-out-of -# tag: [mtr, mlabeledtr] -# match: "$Move2D = 'into'" -# replace: -# - x: "$Move2D" -# - x: "count($Child2D/preceding-sibling::*)+1" -# - pause: "medium" -# -#- name: default-move -# # nothing to do (not 2D) -- need to catch $Move2D though so rules based on NavCommand don't trigger -# tag: "*" -# match: "$Move2D != ''" -# replace: [] -# -# ********* Go back to last position *************** -# This is first since start/end position shouldn't matter -#- name: move-last-location -# -# -# tag: "*" -# match: "$NavCommand = 'MoveLastLocation'" -# replace: -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - test: -# - if: "$PreviousNavCommand = 'ZoomIn'" -# then: [T: "angre innzooming"] # phrase('undo zoom in') -# - else_if: "$PreviousNavCommand = 'ZoomOut'" -# then: [T: "angre utzooming"] # phrase('undo zoom out') -# - else_if: "$PreviousNavCommand = 'ZoomInAll'" -# then: [T: "angre innzooming hele veien"] # phrase('undo zooming in all the way') -# - else_if: "$PreviousNavCommand = 'ZoomOutAll'" -# then: [T: "angre utzooming hele veien"] # phrase('undo zooming out all the way') -# - else_if: "$PreviousNavCommand = 'MovePrevious' or $PreviousNavCommand = 'MovePreviousZoom'" -# then: [T: "angre gå venstre"] # phrase('undo move left') -# - else_if: "$PreviousNavCommand = 'MoveNext' or $PreviousNavCommand = 'MoveNextZoom'" -# then: [T: "angre gå høyre"] # phrase('undo move right') -# - else_if: "$PreviousNavCommand = 'None'" -# then: [T: "ingen tidligere kommandoer"] # phrase('no previous command') -# - pause: "long" -# - set_variables: [NavNode: "@id"] -# -# many times, for typographic reasons, people include punctuation at the end of a math expr -# these rules detect that and skip speaking it (should be similar regular rule) -#- name: skip-punct-at-end-zoom-in -# tag: mrow -# match: -# - "($NavCommand = 'ZoomIn' or $NavCommand = 'ZoomInAll' or $NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and" -# - " parent::m:math and count(*)=2 and" -# - " *[2][translate(.,'.,;:?', '')='']" -# replace: -# - x: "*[1]" -# -# ********* ZoomIn *************** -#- name: zoom-in-leaf -# -# tag: "*" -# match: "($NavCommand = 'ZoomIn' or $NavCommand = 'ZoomInAll') and IsNode(., 'leaf')" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" -# then: [T: "innzoomet hele veien", pause: "long"] # phrase('zoomed in all of the way') -# - test: -# if: "$ReadZoomLevel!=-1" -# then: -# - set_variables: [ReadZoomLevel: "0"] -# - set_variables: [NavNode: "@id"] -# -# special case of zooming into a matrix or determinant -- move to the first row -#- name: zoom-in-matrix -# -# tag: mrow -# match: -# - "$NavCommand = 'ZoomIn' and count(*)=3 and " -# - "*[2][self::m:mtable and (IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|'))]" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') -# - set_variables: [NavNode: "*[2]/*[1]/@id"] -# -# special case of zooming into a table -- move to the first row -#- name: zoom-in-table -# tag: mtable -# match: "$NavCommand = 'ZoomIn'" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') -# - set_variables: [NavNode: "*[1]/@id"] -# -#- name: zoom-in-mrow-in-math -# # Moving to first or last is meaningless the 'math' has only an 'mrow' inside -- dig inside and do it again -# tag: math -# match: "count(*)=1 and ($NavCommand = 'ZoomIn' or $NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom')" -# replace: -# - test: -# if: "$NavCommand = 'MovePreviousZoom'" -# then: [x: "*[last()]"] -# else: [x: "*[1]"] -# -#- # For msqrt and menclose, if the single child isn't an mrow, don't zoom in -# name: zoom-in-again -# # If there is only one child, this isn't an interesting move -- zoom in again -# tag: "*" -# match: -# - "($NavCommand = 'ZoomIn' or " -# - " ($NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and $NavMode='Enhanced') and " -# - "count(*)=1 and (*[1][self::m:mrow] and not(self::m:msqrt or self::m:menclose))" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: -# - test: -# if: "$NavCommand = 'MovePreviousZoom'" -# then: [x: "*[last()]"] -# else: [x: "*[1]"] -# -#- name: zoom-in-enhanced -# -# tag: "*" -# match: "$NavCommand = 'ZoomIn' and $NavMode='Enhanced'" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') -# - test: -# - if: "self::m:mtr or self::m:mlabeledtr" -# then: -# - with: -# variables: [Move2D: "'i'", Child2D: "*[1]/*[1]"] # phrase('in' the denominator) -# replace: [x: "."] -# - set_variables: [NavNode: "*[1]/*[1]/@id"] # skip mtd -# - else_if: "*[1][self::m:mrow and IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false)]" # auto zoom -# then: -# - with: -# variables: [Move2D: "'i'", Child2D: "*[1]/*[2]"] # phrase('in' the denominator) -# replace: [x: "."] -# - set_variables: [NavNode: "*[1]/*[2]/@id"] # skip mtd -# else: -# - with: -# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) -# replace: [x: "."] -# - set_variables: [NavNode: "*[1]/@id"] -# -#- name: zoom-in-2D-not-enhanced -# tag: "*" -# match: "$NavCommand = 'ZoomIn' and $NavMode!='Enhanced' and IsNode(., '2D')" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') -# - with: -# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) -# replace: [x: "."] -# - with: -# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"] -# replace: [x: "*[1]"] -# -#- name: zoom-in-default -# tag: "*" -# match: "$NavCommand = 'ZoomIn'" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: [T: "zoom inn", pause: "long"] # phrase('zoom in') -# - with: -# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) -# replace: [x: "."] -# - test: -# if: "$NavMode='Character'" -# then: -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: [x: "*[1]"] -# else_test: -# if: "self::m:mtd" -# then: [x: "*[1]"] -# else: -# - test: -# if: "$ReadZoomLevel!=-1" -# then: -# - set_variables: [ReadZoomLevel: "DistanceFromLeaf(*[1], true, $NavMode!='Character')"] -# - set_variables: [NavNode: "*[1]/@id"] -# -#- name: zoom-in-all-default -# tag: "*" -# match: "$NavCommand = 'ZoomInAll'" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: [T: "zoom inn hele veien", pause: "medium"] # phrase('zoom in all the way') -# - with: -# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) -# replace: [x: "."] -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: [x: "*[1]"] -# -#- name: zoom-out -# tag: math -# match: "$NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll'" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" -# then: [T: "utzoomet hele veien", pause: "long"] # phrase('zoomed out all the the way') -# - set_variables: [NavNode: "*[1]/@id"] # no-op for $NavCommand = 'ZoomOut' -# -#- name: zoom-out-top -# tag: "*" -# match: -# - "($NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll') and" -# - "parent::m:math " -# replace: -# - x: ".." # let math rule deal with it -# -#- name: skip-punct-at-end-zoom-out -# tag: mrow -# match: -# - "($NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll') and" -# - " parent::m:math and count(*)=2 and" -# - " *[2][translate(.,'.,;:?', '')='']" -# replace: -# - x: ".." -# -#- name: zoom-out-all-default -# tag: "*" -# match: "$NavCommand = 'ZoomOutAll'" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" -# then: [T: "utzoomet hele veien", pause: "medium"] # phrase('zoomed out all the the way') -# - with: -# variables: [Move2D: "'ut av'", Child2D: "."] -# replace: [x: ".."] -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: [x: ".."] -# -# deal with internal zooming: MoveNextZoom and MovePreviousZoom -# -# start with Enhanced mode -#- name: move-zoom-enhanced -# tag: "*" -# match: -# - "($NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and " -# - "$NavMode = 'Enhanced'" -# replace: -# # don't bother with MatchCounter since we only get here if > 1 -# - with: -# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) -# replace: [x: "."] -# - test: -# - if: "count(*)> 1 or IsNode(., 'leaf') or self::m:msqrt or self::m:menclose" -# then: [set_variables: [NavNode: "@id"]] -# else: [x: "*[1]"] -# -#- name: move-next-zoom-not-enhanced -# # $ReadZoomLevel must be >= 0 -# tag: "*" -# match: "$NavCommand = 'MoveNextZoom'" -# replace: -# #don't bother with MatchCounter since we only get here if > 1 -# - test: -# if: "$ReadZoomLevel >= DistanceFromLeaf(., false, $NavMode!='Character')" -# then: -# # - with: -# # variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) -# # replace: [x: ".."] -# - set_variables: [NavNode: "@id"] -# else: -# - with: -# variables: [Move2D: "'i'", Child2D: "*[1]"] # phrase('in' the denominator) -# replace: [x: "."] -# - x: "*[1]" -# -#- name: move-previous-zoom-not-enhanced -# # $ReadZoomLevel must be >= 0 -# tag: "*" -# match: "$NavCommand = 'MovePreviousZoom'" -# replace: -# #don't bother with MatchCounter since we only get here if > 1 -# - test: -# if: "$ReadZoomLevel >= DistanceFromLeaf(., true, $NavMode!='Character')" -# then: -# # - with: -# # variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) -# # replace: [x: ".."] -# - set_variables: [NavNode: "@id"] -# else: -# - with: -# variables: [Move2D: "'i'", Child2D: "*[last()]"] # phrase('in' the denominator) -# replace: [x: "."] -# - x: "*[last()]" -# -# ********* ZoomOut *************** -#- name: zoom-out-default -# -# -# tag: mtd -# match: "$Move2D = '' and ($NavCommand = 'ZoomOut')" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: [T: "zoom ut", pause: "medium"] # phrase('zoom out' of expression) -# # we need to speak it here -# - T: "rad" # phrase(the first 'row' of the matrix) -# # if we let the speech rules speak the row, it is given just the MathML for the row, so the row # will always be '1' -# - x: "count(../preceding-sibling::*)+1" -# - pause: medium -# - set_variables: [NavNode: "../@id"] -# -#- name: zoom-out -# # a row around a single element -- these might duplicate the position/offset, so we jump an extra level here -# tag: "*" -# match: "$NavCommand = 'ZoomOut'" -# replace: -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: -# - test: -# if: "$MatchCounter = 1 and $NavVerbosity = 'Verbose'" -# then: [T: "zoom ut", pause: "medium"] # phrase('zoom out' of the expression) -# - test: -# if: "$NavMode='Enhanced' and parent::*[self::m:mrow and IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false)]" -# then: [x: ".."] # auto-zoom: move out a level and retry -# else: -# - with: -# variables: [Move2D: "'ut av'", Child2D: "."] -# replace: [x: ".."] -# - test: -# if: "parent::m:mtd" -# then: [x: ".."] -# else: -# - test: -# if: "$ReadZoomLevel!=-1" -# then: [set_variables: [ReadZoomLevel: "DistanceFromLeaf(.., true, $NavMode!='Character')"]] -# - set_variables: [NavNode: "../@id"] -# -# ********* MoveStart/End *************** -#- name: math-move-to-start-or-end -# tag: math -# match: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart' or $NavCommand = 'MoveEnd' or $NavCommand = 'MoveLineEnd'" -# replace: -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: -# - test: -# if: "$NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MoveStart'" -# then: [T: "gå til start matematikk"] # phrase('move to start of math') -# - else_if: "$NavCommand = 'MoveLineStart'" -# then: [T: "gå til starten av raden"] # phrase('move to start of line') -# - else_if: "$NavCommand = 'MoveEnd'" -# then: [T: "gå til slutt matematikk"] # phrase('move to end of math') -# else: [T: "gå til slutten av raden"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') -# - pause: "medium" -# - test: -# if: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart'" -# then: -# # move inside of the mrow inside of 'math' or inside the fraction, etc (hence two levels down) -# - with: -# variables: [NavCommand: "'MoveNextZoom'"] -# replace: [x: "*[1]/*[1]"] -# else: -# - with: -# variables: [NavCommand: "'MovePreviousZoom'"] -# replace: [x: "*[last()]/*[last()]"] -# -# We stop when the parent is 2d (e.g., frac), but not if in leaf base of msub/msup/msubsup/mmultiscripts because that's really on the same line -#- name: move-to-start-or-end-2d -# tag: "*" -# match: -# - "($NavCommand = 'MoveLineStart' or $NavCommand = 'MoveLineEnd') and IsNode(.., '2D') and" -# - "not( IsNode(., 'leaf') and (parent::m:msub or parent::m:msup or parent::m:msubsup or parent::m:mmultiscripts) )" -# replace: -# - test: -# if: "$NavVerbosity = 'Verbose'" -# then: -# - test: -# if: "$NavCommand = 'MoveLineStart'" -# then: [T: "gå til starten av raden"] # phrase('move to start of line') -# else: [T: "gå til slutten av raden"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line') -# - pause: "medium" -# - test: -# if: "self::m:mrow" -# then_test: -# if: "$NavCommand = 'MoveLineStart'" -# then: -# - with: -# variables: [NavCommand: "'MoveNextZoom'"] -# replace: [x: "*[1]"] -# else: -# - with: -# variables: [NavCommand: "'MovePreviousZoom'"] -# replace: [x: "*[last()]"] -# else: [set_variables: [NavNode: "@id"]] -# -#- name: move-to-start-or-end-default -# tag: "*" -# match: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart' or $NavCommand = 'MoveEnd' or $NavCommand = 'MoveLineEnd'" -# replace: -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: [x: ".."] -# -# Table-related movement -# Typically, we need to zoom out to the mtd level, then we move the appropriate direction -#- name: not-in-table -# -# -# tag: math -# match: -# - "$NavCommand='MoveCellPrevious' or $NavCommand='MoveCellNext' or" -# - "$NavCommand='MoveCellUp' or $NavCommand='MoveCellDown' or" -# - "$NavCommand='MoveColumnStart' or $NavCommand='MoveColumnEnd' or" -# - "$NavCommand='ReadCellCurrent'" -# replace: -# - T: "ikke i tabell" # phrase('not in table') -# - pause: long -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: move-cell-previous -# tag: mtd -# match: "$NavCommand='MoveCellPrevious'" -# replace: -# - test: -# if: "preceding-sibling::*" -# then: -# - test: -# if: "$NavVerbosity = 'Verbose'" -# then: -# - T: "gå venstre" # phrase('move left') -# - pause: short -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "kolonne" # phrase(the first 'column' of the table) -# - x: "count(preceding-sibling::*)" -# - pause: medium -# - test: -# if: "$NavMode='Character'" -# then: -# - with: -# variables: [NavCommand: "'MovePreviousZoom'"] -# replace: [x: "preceding-sibling::*[1]"] -# else: -# - set_variables: [NavNode: "preceding-sibling::*[1]/*[1]/@id"] -# else: -# - T: "ingen foregående kolonner" # phrase('no previous column' in the table) -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: move-cell-next -# tag: mtd -# match: "$NavCommand='MoveCellNext'" -# replace: -# - test: -# if: "following-sibling::*" -# then: -# - test: -# if: "$NavVerbosity = 'Verbose'" -# then: -# - T: "gå høyre" # phrase('move right') -# - pause: short -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "kolonne" # phrase(the first 'column' in the table) -# - x: "count(preceding-sibling::*)+2" -# - pause: medium -# - test: -# if: "$NavMode='Character'" -# then: -# - with: -# variables: [NavCommand: "'MoveNextZoom'"] -# replace: [x: "following-sibling::*[1]"] -# else: -# - set_variables: [NavNode: "following-sibling::*[1]/*[1]/@id"] -# else: -# - T: "ingen påfølgende kolonner" # phrase('no next column' in the table) -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: move-cell-up -# tag: mtd -# match: "$NavCommand='MoveCellUp'" -# replace: -# - test: -# if: "../preceding-sibling::*" -# then: -# - with: -# variables: [Column: "count(preceding-sibling::*)+1"] # store this because otherwise the value is used in the wrong context below -# replace: -# - test: -# if: "$NavVerbosity = 'Verbose'" -# then: -# - T: "gå opp" # phrase('move up' to previous row in the table) -# - pause: short -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "rad" # phrase(the previous 'row' in the table) -# - x: "count(../preceding-sibling::*)" -# - pause: short -# - T: "kolonne" # phrase(the previous 'column' in the table) -# - x: "count(preceding-sibling::*)+1" -# - pause: medium -# - test: -# if: "$NavMode='Character'" -# then: -# - with: -# variables: [NavCommand: "'MoveNextZoom'"] -# replace: [x: "../preceding-sibling::*[1]/*[$Column]"] -# else: -# - set_variables: [NavNode: "../preceding-sibling::*[1]/*[$Column]/*[1]/@id"] -# else: -# - T: "ingen foregående rader" # phrase('no previous row' in the table) -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: move-cell-down -# tag: mtd -# match: "$NavCommand='MoveCellDown'" -# replace: -# - test: -# if: "../following-sibling::*" -# then: -# - with: -# variables: [Column: "count(preceding-sibling::*)+1"] # store this because otherwise the value is used in the wrong context below -# replace: -# - test: -# if: "$NavVerbosity = 'Verbose'" -# then: -# - T: "gå ned" # phrase('move down to the next row in the table) -# - pause: short -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "rad" # phrase(the next 'row' in the table) -# - x: "count(../preceding-sibling::*)+2" -# - pause: short -# - T: "kolonne" # phrase(the next 'column' in the table) -# - x: "count(preceding-sibling::*)+1" -# - pause: medium -# - test: -# if: "$NavMode='Character'" -# then: -# - with: -# variables: [NavCommand: "'MoveNextZoom'"] -# replace: [x: "../following-sibling::*[1]/*[$Column]"] -# else: -# - set_variables: [NavNode: "../following-sibling::*[1]/*[$Column]/*[1]/@id"] -# else: -# - T: "ingen påfølgende rader" # phrase('no next row' in the table) -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: move-cell-up -# tag: [mtr, mlabeledtr] -# match: "$NavCommand='MoveCellUp'" -# replace: -# - test: -# if: "preceding-sibling::*" -# then: -# - test: -# if: "$NavVerbosity = 'Verbose'" -# then: -# - T: "gå opp" # phrase('move up' to the previous row in the table) -# - pause: medium -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "rad" # phrase(the previous 'row' in the table) -# - x: "count(preceding-sibling::*)" -# - pause: medium -# - test: -# if: "$NavMode='Character'" -# then: -# - with: -# variables: [NavCommand: "'MoveNextZoom'"] -# replace: [x: "preceding-sibling::*[1]"] -# else: -# - set_variables: [NavNode: "preceding-sibling::*[1]/@id"] -# else: -# - T: "ingen foregående rader" # phrase('no previous row' in the table) -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: move-cell-down -# tag: [mtr, mlabeledtr] -# match: "$NavCommand='MoveCellDown'" -# replace: -# - test: -# if: "following-sibling::*" -# then: -# - test: -# if: "$NavVerbosity = 'Verbose'" -# then: -# - T: "gå ned" # phrase('move down' to the next row in the table) -# - pause: medium -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "rad" # phrase(the previous 'row' in the table) -# - x: "count(preceding-sibling::*)+2" -# - pause: medium -# - test: -# if: "$NavMode='Character'" -# then: -# - with: -# variables: [NavCommand: "'MoveNextZoom'"] -# replace: [x: "following-sibling::*[1]"] -# else: -# - set_variables: [NavNode: "following-sibling::*[1]/@id"] -# else: -# - T: "ingen påfølgende rader" # phrase('no next row' in the table) -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: default-read-cell -# tag: "*" -# match: "$NavCommand='ReadCellCurrent'" -# replace: -# - with: -# variables: [MTD: "ancestor::m:mtd"] -# replace: -# - test: -# if: "$MTD" -# then: -# - test: -# if: "$NavVerbosity = 'Verbose'" -# then: -# - T: "les nåværende verdi" # phrase('read current entry' in the table) -# - pause: medium -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "rad" # phrase(the previous 'row' in the table) -# - x: "count($MTD[1]/../preceding-sibling::*)+1" -# - T: "kolonne" # phrase(the previous 'column' in the table) -# - x: "count($MTD[1]/preceding-sibling::*)+1" -# - pause: short -# - set_variables: [NavNode: "$MTD[1]/*[1]/@id"] -# else: -# - T: "ikke i tabell" # phrase('not in table' or matrix) -# - pause: long -# - set_variables: [SpeakExpression: "'false'"] -# -# mtd ? ( $NavCommand='MoveColumnStart' ) -# => MoveColStart { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^match[0][index(match)][0].dfs; -# ::EndPosition = ^^match[0][index(match)][0].offset; -# }; -# -# mtd ? ( $NavCommand='MoveColumnEnd' ) -# => MoveColEnd { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^match[count(^^match)-1][index(match)][0].dfs; -# ::EndPosition = ^^match[count(^^match)-1][index(match)][0].offset; -# }; -# -# -# -# # Rules for columnar math (mstack and mlongdiv) -- each row is an msrow or mscarries except for the start of mlongdiv -# # FIX: not dealing with different number of digits on different lines -# # FIX: not dealing with + (etc) on same line if they are on the right side (Dutch, others) -# # FIX: not dealing with intervening msline (say it and move on??) -# # FIX: not dealing with carries well -# # FIX: not dealing with navigation of first three children of mlongdiv -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') && has_previous(match) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "previous"; -# ::StartPosition = previous(match).dfs; -# ::EndPosition = previous(match).offset; -# }; -# -# # no previous child -- in first column -- don't move -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious' ) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "previous"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; -# -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') && has_next(match) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "next"; -# ::StartPosition = next(match).dfs; -# ::EndPosition = next(match).offset; -# }; -# -# # no next child -- in first column -- don't move -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext' ) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "next"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; -# -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveCellUp' && has_previous(^^match) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "up"; -# ::StartPosition = ^^^match[index(^^match)-1][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[index(^^match)-1][-1][index(match)-count(^match)].offset; -# }; -# -# # no previous child -- in first column -- don't move -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveCellUp' ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "up"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; -# -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveCellDown' && has_next(^^match) ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "down"; -# ::StartPosition = ^^^match[index(^^match)+1][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[index(^^match)+1][-1][index(match)-count(^match)].offset; -# }; -# -# # no previous child -- in first column -- don't move -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveCellDown' ) -# => MoveCell { -# ruleRef = name(^^match); -# wordRef = "down"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; -# -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveColumnStart' ) -# => MoveColStart { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^^match[0][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[0][-1][index(match)-count(^match)].offset; -# }; -# -# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveColumnEnd' ) -# => MoveColEnd { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].offset; -# }; -# -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') && has_previous(match) ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "previous"; -# ::StartPosition = previous(match).dfs; -# ::EndPosition = previous(match).offset; -# }; -# -# # no previous child -- in first column -- don't move -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "previous"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; -# -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') && has_next(match) ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "next"; -# ::StartPosition = next(match).dfs; -# ::EndPosition = next(match).offset; -# }; -# -# # no next child -- in last column -- don't move -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "next"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; -# -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# $NavCommand='MoveCellUp' && has_previous(^match) ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "up"; -# ::StartPosition = ^^match[index(^match)-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^match[index(^match)-1][index(match)-count(^match)].offset; -# }; -# -# # no previous child -- in first row -- don't move -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# $NavCommand='MoveCellUp' ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "up"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; -# -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# $NavCommand='MoveCellDown' && has_next(^match) ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "down"; -# ::StartPosition = ^^match[index(^match)+1][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^match[index(^match)+1][-1][index(match)-count(^match)].offset; -# }; -# -# # no next child -- in last row -- don't move -# any ? ( (name(match)=="mn" || name(match)=="none") && -# has_parent(match) && name(^match)=="mscarries" && -# $NavCommand='MoveCellDown' ) -# => MoveCell { -# ruleRef = name(^match); -# wordRef = "down"; -# childIndex = -1; # key to know what to say for each notation -# ::SpeakAfterMove = false; -# }; -# -# mn ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveColumnStart' ) -# => MoveColStart { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^^match[0][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[0][-1][index(match)-count(^match)].offset; -# }; -# -# mn ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" && -# $NavCommand='MoveColumnEnd' ) -# => MoveColEnd { -# ruleRef = name(^^match); -# column = index(match); -# ::StartPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].dfs; -# ::EndPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].offset; -# }; -# -# -# -#- name: default-cell-move -# -# tag: "*" -# match: -# - "$NavCommand='MoveCellPrevious' or $NavCommand='MoveCellNext' or" -# - "$NavCommand='MoveCellUp' or $NavCommand='MoveCellDown' or" -# - "$NavCommand='MoveColumnStart' or $NavCommand='MoveColumnEnd' or" -# - "$NavCommand='ReadCellCurrent'" -# replace: -# - test: -# if: "ancestor::m:mtd" -# then: -# - x: "ancestor::m:mtd[1]" # try again on an mtd node -# else: -# - T: "ikke i tabell" # phrase('not in table' or matrix) -# - pause: long -# - set_variables: [SpeakExpression: "'false'"] -# -# ======== Move/Read/Describe Next rules ================= -# -# skip 'none' -#- name: move-next-none -# tag: [none, mprescripts] -# match: -# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext' or $NavCommand = 'DescribePrevious' or $NavCommand = 'MoveNextZoom') and" -# - "parent::*[1][name(.)='mmultiscripts'] and following-sibling::*" -# replace: -# - with: -# variables: [Following: "following-sibling::*[1]"] -# replace: -# # two 'none's in a row -- move over and try again; one 'none', zoom in on next -# - test: -# if: "$Following[name(.)='none']" -# then: [x: "$Following"] -# else: -# - with: -# variables: [Move2D: "'i'", Child2D: "$Following"] # phrase('in' the denominator) -# replace: [x: ".."] -# - with: -# variables: [NavCommand: "'MoveNextZoom'"] -# replace: [x: "$Following"] -# -# skip 'none' -#- name: move-previous-none -# tag: [none, mprescripts] -# match: -# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious' or $NavCommand = 'MovePreviousZoom') and" -# - "parent::*[1][name(.)='mmultiscripts'] and preceding-sibling::*" -# replace: -# - with: -# variables: [Preceding: "preceding-sibling::*[1]"] -# replace: -# # two 'none's in a row -- move over and try again; one 'none', zoom in on preceding -# - test: -# if: "$Preceding[name(.)='none']" -# then: [x: "$Preceding"] -# else: -# - with: -# variables: [Move2D: "'i'", Child2D: "$Preceding"] # phrase('in' the denominator) -# replace: [x: ".."] -# - with: -# variables: [NavCommand: "'MovePreviousZoom'"] -# replace: [x: "$Preceding"] -# -# -# -# skip invisible chars except for Enhanced mode when "times" should be read -#- name: move-next-invisible -# tag: "*" -# match: -# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" -# - "following-sibling::*[1][name(.)='mo' and translate(., '\u2061\u2062\u2063\u2064', '')='']" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MoveNext'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadNext'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "høyre" # phrase(move 'right') # phrase(move 'right') -# - pause: short -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: -# - test: -# if: "following-sibling::*[1][.='\u2062' or .='\u2064'] and $NavMode='Enhanced'" # invisible times and plus -# then: [set_variables: [NavNode: "following-sibling::*[1]/@id"]] -# else: [x: "following-sibling::*[1]"] -# -#- name: move-next-no-auto-zoom-at-edge -# # at edge of 2D and in a mode where moving right isn't an option -# tag: "*" -# variables: [EdgeNode: "EdgeNode(., 'right', '2D')"] -# match: "$NavCommand = 'MoveNext' and $NavMode!='Character' and not($AutoZoomOut) and $EdgeNode/@id!=@id" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse' and $NavCommand = 'MoveNext'" -# then: -# - T: "kan ikke gå til høyre" # phrase('cannot move right') -# - with: -# variables: [Move2D: "'end of'", Child2D: "$EdgeNode/*[last()]"] #Should "end of" be translated? -# replace: [x: "$EdgeNode"] -# - pause: long -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: move-next-no-auto-zoom-at-edge-math -# # at edge of math -- no where to go (must be after we rule out being at the edge of 2D) because we want to speak that -# tag: "*" -# match: -# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" -# - "(self::m:math or name(EdgeNode(., 'right', 'math'))='math')" # at edge of math -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" -# then: -# - T: "kan ikke" # phrase('cannot' move right in expression) -# - test: -# - if: "$NavCommand = 'MoveNext'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadNext'" -# then: [T: "lese"] # phrase('read' next entry in table) -# else: [T: "beskrive"] # phrase('describe' next entry in table) -# - T: "høyre, slutt matematikk" # phrase(move 'right, end of math') -# - pause: long -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: move-next-auto-zoom-up-one-level -# # Last child or in auto-zoom'd in-- move up a level and try again -# # Note: we've already checked the for the case where we are at an edge and should not AutoZoomOut -# tag: "*" -# match: -# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" -# - "( not(following-sibling::*) or" -# - " ( $NavMode='Enhanced' and " -# - " count(following-sibling::*)=1 and (IsBracketed(.., '(', ')') or IsBracketed(.., '[', ']'))" -# - " )" -# - ")" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MoveNext'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadNext'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "høyre" # phrase(move 'right') # phrase(move 'right') -# - pause: short -# - with: -# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNext'"] -# replace: -# - test: -# if: "following-sibling::*" -# then: -# - with: -# variables: [Move2D: "'i'", Child2D: "."] # phrase('in' the denominator) -# replace: [x: ".."] -# else: -# - with: -# variables: [Move2D: "'ut av'", Child2D: "."] -# replace: [x: ".."] -# - test: -# if: "following-sibling::*" -# then: -# - x: ".." # move out of parens -# else: -# - x: ".." -# -# At this point, if XXXNext, then we know there is must be a right sibling -#- name: move-next-default -# tag: mtd -# match: "$Move2D = '' and ($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext')" -# replace: -# - test: -# # can't get here with MatchCounter=0, so no need to echo command -# if: "following-sibling::*" -# then: -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "kolonne" # phrase(the previous 'column' in the table) -# - x: "count(preceding-sibling::*)+2" -# - pause: short -# - test: -# if: "$NavMode = 'Character'" -# then: -# - with: -# variables: [NavCommand: "'MoveNextZoom'"] -# replace: [x: "following-sibling::*[1]"] -# else: [set_variables: [NavNode: "following-sibling::*[1]/*[1]/@id"]] -# else: -# - x: ".." # try again at the row level -# -#- name: move-next-default -# tag: [mtr, mlabeledtr] -# match: "$Move2D = '' and ($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext')" -# replace: -# - test: -# # can't get here with MatchCounter=0, so no need to echo command -# if: "following-sibling::*" -# then: -# - T: "rad" # phrase(the previous 'row' in the table) -# - x: "count(preceding-sibling::*)+2" -# - T: "kolonne 1" # phrase('column 1' in the table) -# - pause: medium -# - test: -# if: "$NavMode = 'Character'" -# then: -# - with: -# variables: [NavCommand: "'MoveNextZoom'"] -# replace: [x: "following-sibling::*[1]"] -# else: -# - set_variables: [NavNode: "following-sibling::*[1]/*[1]/*[1]/@id"] -# else: [x: ".."] # try again for after -# -#- name: move-next-auto-zoom-parens -# # auto-zoom into next child if next child is parenthesized expr -# tag: "*" -# match: -# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" -# - "$NavMode='Enhanced' and" -# - "parent::m:mrow and following-sibling::* and" -# - "following-sibling::*[1][self::m:mrow and count(*)=3 and " #exclude empty parens -# - " (IsBracketed(., '(', ')') or IsBracketed(., '[', ']'))" -# - " ]" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MoveNext'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadNext'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "høyre" # phrase(move 'right') # phrase(move 'right') -# - pause: short -# - set_variables: [NavNode: "following-sibling::*[1]/*[2]/@id"] -# -# normal cases for MoveNext -#- name: move-next-locked-zoom-level -# # locked zoom level -# tag: "*" -# match: -# - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and" -# - "$ReadZoomLevel>=0" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MoveNext'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadNext'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "høyre" # phrase(move 'right') # phrase(move 'right') -# - pause: short -# - test: -# # if in base (nothing before), we must be moving to a script, so "in" will be said -# if: "preceding-sibling::* and following-sibling::*[1][name(.)='none']" -# then: -# - with: -# variables: [Move2D: "'ut av'", Child2D: "."] -# replace: [x: ".."] -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: [x: "following-sibling::*[1]"] # skip over 'none' -# else: -# - with: -# variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) -# replace: [x: ".."] -# - with: -# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"] -# replace: [x: "following-sibling::*[1]"] -# -#- name: move-next-default -# tag: "*" -# match: "$NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext'" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MoveNext'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadNext'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "høyre" # phrase(move 'right') # phrase(move 'right') -# - pause: short -# - test: -# if: "IsNode(.., '2D')" -# then: -# - with: -# variables: [Move2D: "'i'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator) -# replace: [x: ".."] -# - set_variables: [NavNode: "following-sibling::*[1]/@id"] -# -# ======== Move/Read/Describe Previous rules ================= -# -# skip invisible chars except for Enhanced mode when "times" should be read -#- name: move-previous-invisible -# tag: "*" -# match: -# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" -# - "preceding-sibling::*[1][name(.)='mo' and translate(., '\u2061\u2062\u2063\u2064', '')='']" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MovePrevious'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadPrevious'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "venstre" # phrase(move 'left') -# - pause: short -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: -# - test: -# if: "preceding-sibling::*[1][.='\u2062' or .='\u2064'] and $NavMode='Enhanced'" # invisible times and plus -# then: [set_variables: [NavNode: "preceding-sibling::*[1]/@id"]] -# else: [x: "preceding-sibling::*[1]"] -# -# two rules for when can't move right -#- name: move-previous-no-auto-zoom-at-edge -# # at edge of 2D and in a mode where moving right isn't an option -# tag: "*" -# variables: [EdgeNode: "EdgeNode(., 'left', '2D')"] -# match: "$NavCommand = 'MovePrevious' and $NavMode!='Character' and not($AutoZoomOut) and $EdgeNode/@id!=@id" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse' and $NavCommand = 'MovePrevious'" -# then: -# - T: "kan ikke gå til venstre" # phrase('cannot move left' in expression) -# - with: -# variables: [Move2D: "'end of'", Child2D: "$EdgeNode/*[1]"] #Should "end of" be translated? -# replace: [x: "$EdgeNode"] -# - pause: long -# -#- name: move-previous-no-auto-zoom-at-edge-of-math -# # at edge of math -- no where to go (must be after we rule out being at the edge of 2D) because we want to speak that -# tag: "*" -# match: -# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" -# - "(self::m:math or name(EdgeNode(., 'left', 'math'))='math')" -# replace: -# - T: "start matematikk" # phrase('start of math') -# - pause: long -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: move-previous-at-end -# tag: "*" -# match: -# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" -# - "name(EdgeNode(., 'left', 'math'))='math'" # at edge of math -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'" -# then: -# - T: "kan ikke gå til venstre, start matematikk" # phrase('cannot move left, start of math') -# - pause: long -# - set_variables: [SpeakExpression: "'false'"] -# -#- name: move-previous-auto-zoom-up-one-level -# # Last child or in auto-zoom'd in-- move up a level and try again -# # Note: we've already checked the for the case where we are at an edge and should not AutoZoomOut -# tag: "*" -# match: -# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" -# - "( not(preceding-sibling::*) or" -# - " ( $NavMode='Enhanced' and " -# - " count(preceding-sibling::*)=1 and (IsBracketed(.., '(', ')') or IsBracketed(.., '[', ']'))" -# - " )" -# - ")" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MovePrevious'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadPrevious'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "venstre" # phrase(move 'left') -# - pause: short -# - with: -# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MovePrevious'"] -# replace: -# - test: -# if: "preceding-sibling::*" -# then: -# - with: -# variables: [Move2D: "'i'", Child2D: "."] # phrase('in' the denominator) -# replace: [x: ".."] -# else: -# - with: -# variables: [Move2D: "'ut av'", Child2D: "."] -# replace: [x: ".."] -# - test: -# if: "preceding-sibling::*" -# then: -# - x: .. # move out of parens -# else: -# - x: ".." -# -#- name: move-previous-auto-zoom-parens -# # auto-zoom into previous child if previous child is parenthesized expr -# # Note: there is an asymmetry here from MoveNext because the base of a scripted might have parens for grouping, but not true for the script -# tag: "*" -# match: -# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" -# - "$NavMode='Enhanced' and" -# - "preceding-sibling::* and" -# - "(parent::m:mrow or parent::m:msub or parent::m:msup or" -# - " (count(preceding-sibling::*)=1 and (parent::m:msubsup or parent::m:mmultiscripts))" # make sure moving into base -# - ") and" -# - "preceding-sibling::*[1][self::m:mrow and count(*)=3 and " #exclude empty parens -# - " (IsBracketed(., '(', ')') or IsBracketed(., '[', ']'))" -# - " ]" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MovePrevious'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadPrevious'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "venstre" # phrase(move 'left') -# - pause: short -# - test: -# if: "not(parent::m:mrow)" -# then: -# - with: -# variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) -# replace: [x: ".."] -# - set_variables: [NavNode: "preceding-sibling::*[1]/*[2]/@id"] -# -# normal cases for MovePrevious -# -#- name: move-previous-default -# tag: mtd -# match: "$Move2D = '' and ($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious')" -# replace: -# - test: -# # can't get here with MatchCounter=0, so no need to echo command -# if: "preceding-sibling::*" -# then: -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "kolonne" # phrase(the first 'column' in the table) -# - x: "count(preceding-sibling::*)" -# - pause: short -# - test: -# if: "$NavMode = 'Character'" -# then: -# - with: -# variables: [NavCommand: "'MovePreviousZoom'"] -# replace: [x: "preceding-sibling::*[1]"] -# else: [set_variables: [NavNode: "preceding-sibling::*[1]/*[last()]/@id"]] -# else: -# - x: ".." # try again at the row level -# -#- name: move-previous-default -# tag: [mtr, mlabeledtr] -# match: "$Move2D = '' and ($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious')" -# replace: -# - test: -# # can't get here with MatchCounter=0, so no need to echo command -# if: "preceding-sibling::*" -# then: -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "rad" # phrase('row' five in table) -# - x: "count(preceding-sibling::*)" -# - T: "kolonne" # phrase('column' five in table) -# - x: "count(*)" -# - pause: medium -# - test: -# if: "$NavMode = 'Character'" -# then: -# - with: -# variables: [NavCommand: "'MovePreviousZoom'"] -# replace: [x: "preceding-sibling::*[1]"] -# else: -# - set_variables: [NavNode: "preceding-sibling::*[1]/*[last()]/*[last()]/@id"] -# else: [x: ".."] # try again for after -# -#- name: move-previous-locked-zoom-level -# # locked zoom level -# tag: "*" -# match: -# - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and" -# - "$ReadZoomLevel>=0" -# replace: -# - test: -# # if moving into base (nothing before), we must be moving to the base, so "in" will be said -# if: "count(preceding-sibling::*) > 2 and preceding-sibling::*[1][name(.)='none']" -# then: -# - with: -# variables: [Move2D: "'ut av'", Child2D: "."] -# replace: [x: ".."] -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: [x: "preceding-sibling::*[1]"] # skip over 'none' -# else: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MovePrevious'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadPrevious'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "venstre" # phrase(move 'left') -# - pause: short -# - with: -# variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) -# replace: [x: ".."] -# - with: -# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MovePreviousZoom'"] -# replace: [x: "preceding-sibling::*[1]"] -# -#- name: move-previous-default -# tag: "*" -# match: "$NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious'" -# replace: -# - test: -# if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'MovePrevious'" -# then: [T: "gå"] # phrase('move' to next entry in table) -# - else_if: "$NavCommand = 'ReadPrevious'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "venstre" # phrase(move 'left') -# - pause: short -# - test: -# if: "IsNode(.., '2D')" -# then: -# - with: -# variables: [Move2D: "'i'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator) -# replace: [x: ".."] -# - set_variables: [NavNode: "preceding-sibling::*[1]/@id"] -# -# ********* ReadZoomLevel toggle *************** -# These set ::NavMode -# -#- name: toggle-mode-up -# tag: "*" -# match: "$NavCommand = 'ToggleZoomLockUp'" -# replace: -# - test: -# - if: "$NavMode = 'Enhanced'" -# then: -# - T: "symbolmodus" # phrase(a mathematical 'character') -# - set_variables: [NavMode: "'Character'", ReadZoomLevel: "1"] -# - else_if: "$NavMode = 'Character'" -# then: -# - T: "forenklet modus" # phrase(a 'simple' way to do something) -# - set_variables: [NavMode: "'Simple'", ReadZoomLevel: "1"] -# - else: -# - T: "utvidet modus" # phrase(an 'enhanced' way to do something) -# - set_variables: [NavMode: "'Enhanced'", ReadZoomLevel: "-1"] -# # - T: "läge" # phrase(a simple 'mode' of use) -# # SWEDISH: Removed the ending "mode" string and added "läge" to the previous strings, for grammatical purposes. -# - pause: long -# - test: -# - if: "$NavMode != 'Enhanced'" # potentially need to zoom to the sibling -# then: -# - with: -# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"] -# replace: [x: "."] -# -#- name: toggle-mode-down -# tag: "*" -# match: "$NavCommand = 'ToggleZoomLockDown'" -# replace: -# - test: -# - if: "$NavMode = 'Enhanced'" -# then: -# - T: "forenklet modus" # phrase(an 'simple' way to do something) -# - set_variables: [NavMode: "'Simple'", ReadZoomLevel: "1"] -# - else_if: "$NavMode = 'Character'" -# then: -# - T: "utvidet modus" # phrase(an 'enhanced' way to do something) -# - set_variables: [NavMode: "'Enhanced'", ReadZoomLevel: "-1"] -# - else: -# - T: "symbolmodus" # phrase(a mathematical 'character') -# - set_variables: [NavMode: "'Character'", ReadZoomLevel: "1"] -# # - T: "användningsläge" # phrase(a simple 'mode' of use) -# # SWEDISH: Removed the ending "mode" string and added "läge" to the previous strings, for grammatical purposes. -# - pause: long -# - test: -# - if: "$NavMode != 'Enhanced'" # potentially need to zoom to the sibling -# then: -# - with: -# variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"] -# replace: [x: "."] -# -#- name: toggle-speech-describe -# tag: "*" -# match: "$NavCommand = 'ToggleSpeakMode'" -# replace: -# - test: -# if: "$Overview = 'true'" -# then: -# - T: "les uttrykk etter navigering" # phrase('speak expression after move') -# - set_variables: [Overview: "'false'"] -# else: -# - T: "oversikt over uttrykk etter navigering" # phrase('overview of expression after move') -# - set_variables: [Overview: "'true'"] -# - pause: long -# -#- name: current -# tag: "*" -# match: "$NavCommand = 'ReadCurrent' or $NavCommand = 'DescribeCurrent'" -# replace: -# - test: -# if: "$NavVerbosity = 'Verbose'" -# then: -# - test: -# - if: "$NavCommand = 'ReadCurrent'" -# then: [T: "les"] # phrase('read' next entry in table) -# else: [T: "beskriv"] # phrase('describe' next entry in table) -# - T: "nåværende" # phrase('current' entry in table) -# - set_variables: [NavNode: "@id"] -# - pause: long -# -# this needs to be near the end because we only test for 'Describe', "Read", etc., and we don't want to get 'DescribeNext', etc. -#- name: placemarker -# -# tag: "*" -# match: -# - "starts-with($NavCommand, 'Read') or " -# - "starts-with($NavCommand, 'Describe') or " -# - "starts-with($NavCommand, 'MoveTo')" -# replace: -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - test: -# - if: "starts-with($NavCommand, 'Read')" -# then: [T: "les"] # phrase('read' next entry in table) -# - else_if: "starts-with($NavCommand, 'Describe')" -# then: [T: "beskriv"] # phrase('describe' next entry in table) -# - else_if: "starts-with($NavCommand, 'MoveTo')" -# then: [T: "gå til"] # phrase('move to' the next entry in table) -# else: [T: "angi"] # phrase('set' the value of the next entry in table) -# - T: "plassholder" # phrase('placeholder' for the value) -# - x: "$PlaceMarkerIndex" -# - pause: long -# - set_variables: [NavNode: "$PlaceMarker"] -# -#- name: set-placemarker -# tag: "*" -# match: "starts-with($NavCommand, 'SetPlacemarker')" -# replace: -# - test: -# if: "$NavVerbosity != 'Terse'" -# then: -# - T: "angi plassholder" # phrase('set placeholder' to the value) -# - x: "$PlaceMarkerIndex" -# - pause: long -# - set_variables: [NavNode: "@id"] -# -# ********* WhereAmI *************** -# -# FIX: WhereAmI needs support from the Rust code to loop around and do speech at each iteration. -# Alternatively, it could insert a special token that Rust code does a "replace" on with the speech (e.g. SPEECH_AT{id}) -# or a new command "speak" which takes a node id -#- name: where-am-i-start -# -# -# tag: "*" -# match: "($NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll') and $MatchCounter = 0" -# replace: -# - translate: "@id" -# - pause: long -# - with: -# variables: [MatchCounter: "$MatchCounter + 1"] -# replace: [x: ".."] -# -#- name: where-am-i-stop -# tag: "*" -# match: -# - "($NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll') and $MatchCounter > 0 and" -# # stopping conditions -# - "(self::m:math or " -# - " parent::*[self::m:math and (count(*)=1 or (count(*)=2 and *[2][.=',' or .='.' or .=';' or .='?']) ) ] " -# - ")" -# replace: -# - test: -# if: "$NavCommand = 'WhereAmI'" -# then: -# - T: "ingenting mer" # phrase('inside of nothing more') -# - pause: long -# - set_variables: [SpeakExpression: "'false'"] -# else: -# - T: "inne i" # phrase('inside' a big expression) -# - pause: medium -# - set_variables: [NavNode: "@id"] -# -#- name: where-am-i-middle -# tag: "*" -# match: "$NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll'" -# replace: -# - T: "inne i" # phrase('inside' a big expression) -# - pause: medium -# - test: -# - if: "$NavMode='Enhanced' and parent::*[self::m:mrow and IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false)]" -# then: [x: ".."] # auto-zoom up -# - else_if: "$NavCommand = 'WhereAmI'" -# then: [set_variables: [NavNode: "@id"]] -# else: -# - translate: "@id" -# - pause: long -# - x: '..' + - x: '..' \ No newline at end of file From 0ce896d2cd7b2abb83f92680ad24519b847f3adc Mon Sep 17 00:00:00 2001 From: Marthe Date: Mon, 8 Jun 2026 08:32:17 +0200 Subject: [PATCH 37/43] Added test for "augmented matrices". Small change i rule for log. --- Rules/Languages/nb/SharedRules/general.yaml | 16 +++-- tests/Languages/nb/mtable.rs | 76 +++++++++++++++++++++ 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/Rules/Languages/nb/SharedRules/general.yaml b/Rules/Languages/nb/SharedRules/general.yaml index 076b9d344..78d34a82e 100644 --- a/Rules/Languages/nb/SharedRules/general.yaml +++ b/Rules/Languages/nb/SharedRules/general.yaml @@ -550,7 +550,7 @@ # consider to change this to be equal to the ClearSpeak rule. - # handle both log and ln - name: log + name: log # audit-ignore tag: mi variables: [log_is_simple: "IsNode(following-sibling::*[2],'simple')"] # skip function apply match: ".='log' or .='ln' or .='lg'" @@ -579,7 +579,7 @@ - if: "$Verbosity!='Verbose'" then: [SPELL: "'lg'"] # phrase(the 'lg' of x) else: [T: "tier-logaritmen"] - - else_if: "$Verbosity='Terse'" + - else_if: "$Verbosity!='Verbose'" then: [SPELL: "'ln'"] else: [T: "den naturlige logaritmen"] # phrase(the 'natural log' function is used in mathematics) @@ -855,7 +855,11 @@ - test: if: "self::m:determinant" then: [T: "determinant"] # phrase(the 2 by 2 'determinant') - else: [T: "matrise"] # phrase(the 2 by 2 'matrix') + else: + - test: + if: "@columnlines and (contains(normalize-space(@columnlines), 'solid') or contains(normalize-space(@columnlines), 'dashed'))" + then: [T: "utvidet matrise"] # phrase(the 2 by 2 'augmented matrix') + else: [T: "matrise"] # phrase(the 2 by 2 'matrix') - pause: long - x: "*" - test: @@ -878,7 +882,11 @@ - test: if: "self::m:determinant" then: [T: "determinant"] # phrase(the 2 by 2 'determinant') - else: [T: "matrise"] # phrase(the 2 by 2 'matrix') + else: + - test: + if: "@columnlines and (contains(normalize-space(@columnlines), 'solid') or contains(normalize-space(@columnlines), 'dashed'))" + then: [T: "utvidet matrise"] # phrase(the 2 by 2 'augmented matrix') + else: [T: "matrise"] # phrase(the 2 by 2 'matrix') - pause: long - x: "*" - test: diff --git a/tests/Languages/nb/mtable.rs b/tests/Languages/nb/mtable.rs index a9f74b4d3..d3906d753 100644 --- a/tests/Languages/nb/mtable.rs +++ b/tests/Languages/nb/mtable.rs @@ -238,6 +238,44 @@ fn matrix_2x3() -> Result<()> { } +#[test] +fn augmented_matrix_2x3() -> Result<()> { + let expr = " + + + [ + + + + 3 + + + 1 + + + 4 + + + + + 0 + + + 2 + + + 6 + + + + ] + + "; + test("nb", "ClearSpeak", expr, "2 ganger 3 utvidet matrise; rad 1; 3, 1, 4; rad 2; 0, 2, 6")?; + test("nb", "SimpleSpeak", expr, "2 ganger 3 utvidet matrise; rad 1; 3, 1, 4; rad 2; 0, 2, 6")?; + Ok(()) +} + #[test] fn matrix_2x3_labeled() -> Result<()> { let expr = " @@ -854,6 +892,44 @@ let expr = "( return Ok(()); } +#[test] +fn augmented_matrix_3x4_end_matrix() -> Result<()> { +let expr = " + + [ + + + 1 + 2 + -1 + 3 + + + -3 + 3 + -1 + 2 + + + 2 + 3 + 2 + -1 + + + ] + +"; +test_ClearSpeak("nb", "ClearSpeak_Matrix", "EndMatrix", + expr, "3 ganger 4 utvidet matrise; rad 1; kolonne 1; 1, kolonne 2; 2, kolonne 3; minus 1, kolonne 4; 3; \ + rad 2; kolonne 1; minus 3, kolonne 2; 3, kolonne 3; minus 1, kolonne 4; 2; \ + rad 3; kolonne 1; 2, kolonne 2; 3, kolonne 3; 2, kolonne 4; minus 1; slutt matrise")?; + test("nb", "SimpleSpeak", + expr, "3 ganger 4 utvidet matrise; rad 1; kolonne 1; 1, kolonne 2; 2, kolonne 3; minus 1, kolonne 4; 3; \ + rad 2; kolonne 1; minus 3, kolonne 2; 3, kolonne 3; minus 1, kolonne 4; 2; \ + rad 3; kolonne 1; 2, kolonne 2; 3, kolonne 3; 2, kolonne 4; minus 1; slutt matrise")?; + Ok(()) + } #[test] fn simple_matrix_vector() -> Result<()> { From 6caa2a1b2007493882dfdc85f67dc8fff85532dc Mon Sep 17 00:00:00 2001 From: Marthe Date: Mon, 8 Jun 2026 08:44:12 +0200 Subject: [PATCH 38/43] Enhance Norwegian speech for Roman numerals and intent handling Roman numerals are now spelled out consistently for better pronunciation. Introduces a new `nofix-intent` rule for specific intent properties. Adjusts `function-intent` speech to respect verbosity settings. --- Rules/Languages/nb/SharedRules/default.yaml | 20 +++++++++++++++----- Rules/Languages/nb/definitions.yaml | 1 + 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Rules/Languages/nb/SharedRules/default.yaml b/Rules/Languages/nb/SharedRules/default.yaml index c8d8d3dc8..60de110bd 100644 --- a/Rules/Languages/nb/SharedRules/default.yaml +++ b/Rules/Languages/nb/SharedRules/default.yaml @@ -42,7 +42,10 @@ match: "." replace: - bookmark: "@id" - - x: "translate(., $BlockSeparators, '')" # remove digit block separators + - test: + - if: "@data-roman-numeral" + then: [SPELL: "text()", pause: "short"] + else: [x: "translate(., $BlockSeparators, '')"] # remove digit block separators - name: default tag: [mo, mtext] @@ -59,7 +62,7 @@ - test: - if: "string-length(.) = 1 and text() != '_'" # need unicode.tdl to kick in for single letter tokens then: [x: "text()"] - - else_if: "@data-chem-element" # NavMode=Character needs this + - else_if: "@data-chem-element or @data-roman-numeral" # NavMode=Character needs this then: [SPELL: "text()", pause: "short"] else: [x: "translate(., '-_\u00A0', ' ')"] # from intent literals or from extra spaces added (which get deleted) @@ -189,7 +192,7 @@ - x: "*[2]" # Norwegian: Changed this to be more similar to the English rule. Can't find a way to trigger the last "else" statement. -- name: literal +- name: literal # audit-ignore tag: [msup, msubsup] match: "." replace: @@ -652,6 +655,13 @@ then: [pause: short] else: [pause: auto] +- name: nofix-intent + # uncaught intent -- the args have been inserted in the order of speech + tag: "*" + match: "contains(@data-intent-property, ':nofix:') " + replace: + - x: "SpeakIntentName(name(.), $Verbosity, 'nofix')" + - name: prefix-intent # uncaught intent -- the args have been inserted in the order of speech tag: "*" @@ -704,14 +714,14 @@ then: [pause: short] else: [pause: auto] -- name: function-intent +- name: function-intent # audit-ignore # uncaught intent -- speak as foo of arg1 comma arg2 .... The MathML spec requires arguments to functions tag: "*" match: "count(*)>0" replace: - x: "SpeakIntentName(name(.), $Verbosity, 'function')" - test: - if: "not(contains(@data-intent-property, ':literal:')) and + if: "$Verbosity != 'Terse' and not(contains(@data-intent-property, ':literal:')) and not(count(*)=2 and (IsInDefinition(*[1], 'Speech', 'TrigFunctionNames') or IsInDefinition(name(.), 'Speech', 'TerseFunctionNames')) and diff --git a/Rules/Languages/nb/definitions.yaml b/Rules/Languages/nb/definitions.yaml index 8b44f365a..08a5520f4 100644 --- a/Rules/Languages/nb/definitions.yaml +++ b/Rules/Languages/nb/definitions.yaml @@ -32,6 +32,7 @@ "minus": "infix=minus || prefix=minus", "plus": "infix=pluss || prefix=pluss", "real-part": "function=den reelle delen", + "set-of-integers": "nofix=mengden av alle heltallene", "transpose": "postfix=transponert || function=transponert", #"norm": "function=; normen; slutt norm", # NORWEGIAN: We say "normen til" (the norm to), so this rule is in linear-algebra From ca7744902c38b49e545d86062eeeb7f8d23c065b Mon Sep 17 00:00:00 2001 From: Marthe Date: Mon, 8 Jun 2026 08:45:35 +0200 Subject: [PATCH 39/43] Forgot to change rule for commit #0ce896d --- tests/Languages/nb/SimpleSpeak/functions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Languages/nb/SimpleSpeak/functions.rs b/tests/Languages/nb/SimpleSpeak/functions.rs index 8f119fc38..772160ac9 100644 --- a/tests/Languages/nb/SimpleSpeak/functions.rs +++ b/tests/Languages/nb/SimpleSpeak/functions.rs @@ -116,7 +116,7 @@ fn normal_ln() -> Result<()> { test_prefs("nb", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "l n av; startparentes; x pluss y; sluttparentes")?; test_prefs("nb", "SimpleSpeak", vec![("Verbosity", "Medium")], - expr, "den naturlige logaritmen av; startparentes; x pluss y; sluttparentes")?; + expr, "l n av; startparentes; x pluss y; sluttparentes")?; test_prefs("nb", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr, "den naturlige logaritmen av; startparentes; x pluss y; sluttparentes")?; return Ok(()); From 4ddaea2f1dbbaa76851438eb5b27030280cf7362 Mon Sep 17 00:00:00 2001 From: Marthe Date: Mon, 8 Jun 2026 09:26:10 +0200 Subject: [PATCH 40/43] Added the comment audit-ignore to some symbols --- Rules/Languages/nb/unicode-full.yaml | 60 ++++++++++++++-------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/Rules/Languages/nb/unicode-full.yaml b/Rules/Languages/nb/unicode-full.yaml index 6737e72a1..e862fd707 100644 --- a/Rules/Languages/nb/unicode-full.yaml +++ b/Rules/Languages/nb/unicode-full.yaml @@ -723,9 +723,9 @@ #---------------------------------------------------------------------------------------------------------------- #Mathematical operators OK - "∀": [T: "for alle"] # 0x2200 (en: 'for all') - - "∁": # 0x2201 + - "∁": # 0x2201 # audit-ignore - T: "komplementet til" # (en: 'complement of') - - "∂": # 0x2202 + - "∂": # 0x2202 # audit-ignore - T: "partiell derivert" - "∃": [T: "det eksisterer"] # 0x2203 (en: 'there exists') - "∄": [T: "det eksisterer ikke"] # 0x2204 (en: 'there does not exist') @@ -755,7 +755,7 @@ - else_if: $ClearSpeak_SetMemberSymbol = 'Element' then: [T: "er et element i"] # (en: 'is in', google translation) - else: [T: "tilhører"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'belongs to') - - "∉": # 0x2209 + - "∉": # 0x2209 # audit-ignore # rule is identical to 0x2208 - test: if: "$SpeechStyle != 'ClearSpeak'" @@ -780,7 +780,7 @@ - else_if: $ClearSpeak_SetMemberSymbol = 'In' then: [T: "er ikke i"] # (en: 'is not in', google translation) - else: [T: "tilhører ikke"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'does not belong to') - - "∊": # 0x220a + - "∊": # 0x220a # audit-ignore - test: if: "$SpeechStyle != 'ClearSpeak'" then: @@ -822,11 +822,11 @@ then: [T: "ganger"] # (en: 'dot', google translation) else: [T: "ganger"] # (en: 'times') - - "√": # 0x221a + - "√": # 0x221a # audit-ignore - T: "kvadratroten av" # (en: 'square root of') - - "∛": # 0x221b + - "∛": # 0x221b # audit-ignore - T: "kubikkroten av" # (en: 'cube root of') - - "∜": # 0x221c + - "∜": # 0x221c # audit-ignore - T: "fjerderoten av" # (en: 'fourth root of') - "∝": # 0x221d - test: @@ -855,7 +855,7 @@ - "∳": [T: "kurveintegralet mot klokken"] # 0x2233 (en: 'anticlockwise contour integral', MathPlayer: 'anticlockwise contour integral', google: 'antikvis konturintegral') - "∴": [T: "derfor"] # 0x2234 (en: 'therefore') - "∵": [T: "ettersom"] # 0x2235 (en: 'because') - - "∶": # 0x2236 + - "∶": # 0x2236 # audit-ignore - T: "til" # (en: 'to') - "∷": [T: "som"] # 0x2237 (en: 'as', MathPlayer: 'proportion', google: 'som') - "∸": [T: "prikk minus"] # 0x2238 (en: 'dot minus') @@ -870,17 +870,17 @@ if: "$Verbosity!='Terse'" then: [T: "er"] # (en: 'is', google translation) - T: "homotetisk til" # (en: 'homothetic to', MathPlayer: 'homothetic', google: 'homotetisk till') - - "∼": # 0x223c (en: 'varies with') + - "∼": # 0x223c (en: 'varies with') # audit-ignore - test: if: "$Verbosity!='Terse'" then: [T: "er"] - T: "proporsjonal med" - "∽": [T: "omvendt tilde"] # 0x223d (en: 'reversed tilde') - - "∾": # 0x223e + - "∾": # 0x223e # audit-ignore - T: "omvendt langstrakt s" # (en: 'most positive', MathPlayer: 'inverted lazy s', google: 'mest positiva') - "∿": [T: "sinuskurve"] # 0x223f (en: 'sine wave') - "≀": [T: "kransprodukt"] # 0x2240 (en: 'wreath product') - - "≁": # 0x2241 (en: 'not tilde') + - "≁": # 0x2241 (en: 'not tilde') # audit-ignore - test: if: "$Verbosity!='Terse'" then: [T: "er"] @@ -938,19 +938,19 @@ if: "$Verbosity!='Terse'" then: [T: "er"] # (en: 'is', google translation) - T: "geometrisk ekvivalent med" # (en: 'geometrically equivalent to', MathPlayer: 'geometriskt lika med', google: 'geometriskt motsvarande') - - "≏": # 0x224f + - "≏": # 0x224f # audit-ignore - T: "differansen mellom" # (en: 'difference between') - "≐": [T: "nærmer seg grenseverdien"] # 0x2250 (en: 'approaches the limit') - - "≑": # 0x2251 + - "≑": # 0x2251 # audit-ignore - T: "geometrisk lik" # (en: 'geometrically equal to', SRE: 'är geometriskt lika med') - - "≒": # 0x2252 + - "≒": # 0x2252 # audit-ignore - T: "tilnærmet lik" # (en: 'approximately equal to or the image of', MathPlayer: 'uppskattningsvis lika med eller i likhet med', google: 'ungefär lika med eller bilden av') - - "≓": # 0x2253 + - "≓": # 0x2253 # audit-ignore - T: "tilnærmet lik" # (en: 'image of or approximately equal to', MathPlayer: 'i likhet med eller uppskattningsvis lika med', google: 'bild av eller ungefär lika med') - "≔": [T: "definert som"] # 0x2254 (en: 'colon equals', MathPlayer: 'kolon lika med', google: 'kolon är lika med') - "≕": [T: "lik kolon"] # 0x2255 (en: 'equals colon', MathPlayer: 'lika med kolon') - "≖": [T: "ring i likhetstegn"] # 0x2256 (en: 'ring in equal to', SRE: 'är ring i lika med') - - "≗": # 0x2257 + - "≗": # 0x2257 # audit-ignore - T: "ring likhetstegn" # (en: 'approximately equal to') - "≘": [T: "tilsvarer"] # 0x2258 (en: 'corresponds to') - "≙": [T: "anslår"] # 0x2259 (en: 'estimates') @@ -963,7 +963,7 @@ # SWEDISH: misspelled delta to fix pronunciation - "≜": [T: "delta lik"] # 0x225c (en: 'delta equals') - "≝": [T: "er per definisjon lik"] # 0x225d (en: 'is defined to be') - - "≞": # 0x225e + - "≞": # 0x225e # audit-ignore - T: "måles med" # (en: 'measured by') - "≟": [T: "spørsmål ved likhet"] # 0x225f (en: 'has an unknown relationship with') - "≠": # 0x2260 @@ -987,12 +987,12 @@ if: "$Verbosity!='Terse'" then: [T: "er"] # (en: 'is', google translation) - T: "strengt ekvivalent med" # (en: 'strictly equivalent to') - - "≦": # 0x2266 (en: 'less than over equal to') + - "≦": # 0x2266 (en: 'less than over equal to') # audit-ignore - test: if: "$Verbosity!='Terse'" then: [T: "er"] - T: "mindre enn eller lik" - - "≧": # 0x2267 (en: 'greater than over equal to') + - "≧": # 0x2267 (en: 'greater than over equal to') # audit-ignore - test: if: "$Verbosity!='Terse'" then: [T: "er"] @@ -1135,13 +1135,13 @@ if: "$Verbosity!='Terse'" then: [T: "er"] # (en: 'is', google translation) - T: "verken en overmengde av eller lik" # (en: 'neither a superset of nor equal to') - - "⊊": # 0x228a (en: 'subset of with not equal to') + - "⊊": # 0x228a (en: 'subset of with not equal to') # audit-ignore # SWEDISH: added test - test: if: "$Verbosity!='Terse'" then: [T: "er en"] - T: "ekte delmengde av" - - "⊋": # 0x228b (en: 'superset of with not equal to') + - "⊋": # 0x228b (en: 'superset of with not equal to') # audit-ignore # SWEDISH: added test - test: if: "$Verbosity!='Terse'" @@ -1173,7 +1173,7 @@ - "⊢": [T: "beviser"] # 0x22a2 (en: 'proves') - "⊣": [T: "beviser ikke"] # 0x22a3 (en: 'does not yield') - "⊤": [T: "topp"] # 0x22a4 (en: 'top') - - "⊥": # 0x22a5 + - "⊥": # 0x22a5 # audit-ignore - T: "bunn" # (en: 'bottom', MathPlayer: 'up tack', google: 'botten') - "⊦": [T: "reduseres til"] # 0x22a6 (en: 'reduces to') - "⊧": [T: "modellerer"] # 0x22a7 (en: 'models', MathPlayer: 'models') @@ -1240,13 +1240,13 @@ - "⋆": [T: "stjerne"] # 0x22c6 (en: 'times') - "⋇": [T: "divisjon ganger"] # 0x22c7 (en: 'division times') - "⋈": [T: "naturlig join"] # 0x22c8 (en: 'bowtie', MathPlayer: 'bowtie') - - "⋉": # 0x22c9 + - "⋉": # 0x22c9 # audit-ignore - T: "venstre semi-join" # (en: 'the left normal factor semidirect product of') - - "⋊": # 0x22ca + - "⋊": # 0x22ca # audit-ignore - T: "høyre semi-join" # (en: 'the right normal factor semidirect product of') - - "⋋": # 0x22cb + - "⋋": # 0x22cb # audit-ignore - T: "venstre semi-direkte produkt" # (en: 'the left semidirect product of') - - "⋌": # 0x22cc + - "⋌": # 0x22cc # audit-ignore - T: "høyre semi-direkte produkt" # (en: 'the right semidirect product of') - "⋍": [T: "omvendt tilde likhetstegn"] # 0x22cd (en: 'reversed tilde equals') - "⋎": [T: "krøllete logisk eller"] # 0x22ce @@ -1261,13 +1261,13 @@ if: "$Verbosity!='Terse'" then: [T: "er en"] # (en: 'is', google translation) - T: "dobbel overmengde av" # (en: 'a double superset of') - - "⋒": # 0x22d2 + - "⋒": # 0x22d2 # audit-ignore - T: "det doble snittet av" # (en: 'double intersection of') - - "⋓": # 0x22d3 + - "⋓": # 0x22d3 # audit-ignore - T: "den doble unionen av" # (en: 'double union of') - - "⋔": # 0x22d4 + - "⋔": # 0x22d4 # audit-ignore - T: "det ekte snittet av" # (en: 'proper intersection of', MathPlayer: 'pitchfork', google: 'korrekt skärningspunkt av') - - "⋕": # 0x22d5 + - "⋕": # 0x22d5 # audit-ignore - T: "lik og parallell med" # (en: 'equal to and parallel to') - "⋖": [T: "mindre enn med prikk"] # 0x22d6 (en: 'less than with dot') - "⋗": [T: "større enn med prikk"] # 0x22d7 (en: 'greater than with dot') From 891f8be9a6167e30f95b2dc7c2dfe28642c876ba Mon Sep 17 00:00:00 2001 From: Marthe Date: Tue, 16 Jun 2026 08:57:50 +0200 Subject: [PATCH 41/43] Fix typo --- Rules/Languages/nb/SharedRules/default.yaml | 2 +- Rules/Languages/nb/unicode-full.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Rules/Languages/nb/SharedRules/default.yaml b/Rules/Languages/nb/SharedRules/default.yaml index 60de110bd..910592f24 100644 --- a/Rules/Languages/nb/SharedRules/default.yaml +++ b/Rules/Languages/nb/SharedRules/default.yaml @@ -158,7 +158,7 @@ - pause: short -# Used for expression where the subscript is a leaf or and mrow where the second element is a comma. +# Used for expression where the subscript is a leaf or an mrow where the second element is a comma. # NORWEGIAN: Removed the following test: if: "$Verbosity!='Terse' or not(*[2][self::m:mn])", which is in the Swedish translation. # NORWEGIAN: Added "pause: short" before "senket" - name: no-end-sub # audit-ignore diff --git a/Rules/Languages/nb/unicode-full.yaml b/Rules/Languages/nb/unicode-full.yaml index e862fd707..07ff5e44d 100644 --- a/Rules/Languages/nb/unicode-full.yaml +++ b/Rules/Languages/nb/unicode-full.yaml @@ -3691,7 +3691,7 @@ - SPELL: "translate('.', '', '∂εθκφρπ')" - "": [T: "fet nabla"] # 0xf509 (en: 'bold nabla', google translation) - - "𝞩": [T: "fet nabla"] # 0x1d7a9 (en: 'bold nabla', google translation + - "𝞩": [T: "fet nabla"] # 0x1d7a9 (en: 'bold nabla', google translation) - "-": # 0xf52e - 0xf537 (old MathType) - test: From cf8e5131d2022d71a1488b604d132e62d4f5739f Mon Sep 17 00:00:00 2001 From: Marthe Date: Wed, 17 Jun 2026 12:58:01 +0200 Subject: [PATCH 42/43] Refine Norwegian speech for laplacian operator Correct pronunciation of "laplace" to "laplas" in Norwegian, as "laplace" is not pronounced correctly. Improve phrasing to distinguish between "laplacian" and "laplacian of X" based on context. --- Rules/Languages/nb/SharedRules/calculus.yaml | 15 +++++++++++++++ Rules/Languages/nb/unicode-full.yaml | 7 +++++-- Rules/Languages/nb/unicode.yaml | 6 +++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Rules/Languages/nb/SharedRules/calculus.yaml b/Rules/Languages/nb/SharedRules/calculus.yaml index 704d86c06..1404e8456 100644 --- a/Rules/Languages/nb/SharedRules/calculus.yaml +++ b/Rules/Languages/nb/SharedRules/calculus.yaml @@ -1,4 +1,19 @@ --- + +- name: laplacian + tag: laplacian + match: "count(*) <= 1" # can be on ∇^2 or on enclosing mrow + replace: + - T: "laplas" # phrase('laplacian' of x) # Norwegian: "laplace" is not pronounced correctly + - test: + if: "count(*) = 1" + then: + - T: "av" + - test: + if: "not(IsNode(*[1], 'leaf'))" + then: [pause: short] + - x: "*[1]" + - name: divergence # audit-ignore tag: divergence match: "count(*) = 1" diff --git a/Rules/Languages/nb/unicode-full.yaml b/Rules/Languages/nb/unicode-full.yaml index 07ff5e44d..414cb4128 100644 --- a/Rules/Languages/nb/unicode-full.yaml +++ b/Rules/Languages/nb/unicode-full.yaml @@ -730,8 +730,11 @@ - "∃": [T: "det eksisterer"] # 0x2203 (en: 'there exists') - "∄": [T: "det eksisterer ikke"] # 0x2204 (en: 'there does not exist') - "∅": [T: "den tomme mengden"] # 0x2205 (en: 'empty set') - - "∆": # 0x2206 - - T: "laplace av" # (en: 'laplacian of') + - "∆": # 0x2206 + - test: + if: "following-sibling::*" + then: [T: "laplas av"] # (en: 'laplacian of') # Norwegian: "laplace" is not pronounced correctly + else: [T: "laplas"] - "∇": [T: "nabla"] # 0x2207 (en: 'gradient of', google: 'lutning av') - "∈": # 0x2208 - test: diff --git a/Rules/Languages/nb/unicode.yaml b/Rules/Languages/nb/unicode.yaml index 81613d82a..fa068e9ea 100644 --- a/Rules/Languages/nb/unicode.yaml +++ b/Rules/Languages/nb/unicode.yaml @@ -341,7 +341,11 @@ - "∃": [T: "det eksisterer"] # 0x2203 (en: 'there exists') - "∄": [T: "det eksisterer ikke"] # 0x2204 (en: 'there does not exist') - "∅": [T: "den tomme mengden"] # 0x2205 (en: 'empty set') - - "∆": [T: "laplace av"] # 0x2206 (en: 'laplacian of') # audit-ignore + - "∆": # 0x2206 + - test: + if: "following-sibling::*" + then: [T: "laplas av"] # (en: 'laplacian of') # Norwegian: "laplace" is not pronounced correctly + else: [T: "laplas"] - "∈": # 0x2208 # audit-ignore - test: if: "$SpeechStyle != 'ClearSpeak'" From 9ca7fa12c48b516657d4cfe5f84f333fe44b8b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gaute=20R=C3=B8nningen?= Date: Wed, 17 Jun 2026 14:15:44 +0200 Subject: [PATCH 43/43] Update .gitignore Added 'docs/nb_of_norway/' to .gitignore --- .gitignore | 4 +++- docs/Documentation testing/test_navigation_summer_2026.html | 0 2 files changed, 3 insertions(+), 1 deletion(-) delete mode 100644 docs/Documentation testing/test_navigation_summer_2026.html diff --git a/.gitignore b/.gitignore index db15d2058..e4976a529 100644 --- a/.gitignore +++ b/.gitignore @@ -57,4 +57,6 @@ Rules/*/*/*.zip # local caches when building Jekyll docs/_site docs/.jekyll-cache -docs/Gemfile.lock \ No newline at end of file +docs/Gemfile.lock + +docs/nb_of_norway/ \ No newline at end of file diff --git a/docs/Documentation testing/test_navigation_summer_2026.html b/docs/Documentation testing/test_navigation_summer_2026.html deleted file mode 100644 index e69de29bb..000000000