diff --git a/Rules/Braille/CMU/CMU_Rules.yaml b/Rules/Braille/CMU/CMU_Rules.yaml index fb53fbeb8..3b5c59a40 100644 --- a/Rules/Braille/CMU/CMU_Rules.yaml +++ b/Rules/Braille/CMU/CMU_Rules.yaml @@ -598,7 +598,7 @@ - name: single-char-exceptions # 4.3.1 tag: msup - match: "*[2][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + match: "*[2][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" replace: - x: "*" - test: @@ -609,7 +609,7 @@ - name: single-char-exceptions # 4.3.1 tag: msubsup - match: "*[3][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + match: "*[3][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" replace: - x: "*[1]" - x: "*[3]" @@ -633,8 +633,8 @@ name: number-char-exceptions # 4.3.1 (FIX: degree doesn't use dot-3 for chemistry or temp/angles/etc) tag: [msub, msup] match: - - "*[2][translate(., \"'*`+-∞ª°²³´¹º‘’“”‟‵‶‷\",'')=''] or" - - "*[2][self::m:mrow and count(*)=2 and *[1][self::m:mn] and *[2][self::m:mo][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']]" + - "*[2][translate(., \"'*`+-∞´°‘’“”‟‵‶‷\",'')=''] or" + - "*[2][self::m:mrow and count(*)=2 and *[1][self::m:mn] and *[2][self::m:mo][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']]" replace: - x: "*[1]" - test: @@ -779,7 +779,7 @@ replace: - x: "*[1]" - test: # special case superscript postscripts that preceed the prescripts - if: "$Postscripts and not($Postscripts[2][self::m:none]) and $Postscripts[2][translate(., \"′″‴⁗'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + if: "$Postscripts and not($Postscripts[2][self::m:none]) and $Postscripts[2][translate(., \"′″‴⁗'*`+-´°‘’“”‟‵‶‷\",'')='']" then: - x: "$Postscripts[2]" - test: @@ -805,7 +805,7 @@ # degree doesn't use dot-3 for chemistry, temp, angles -- can't know that so we make a wild guess here if: "not($Prescripts[1][.='°'] and *[1][self::m:mn or @data-chem-element])" then: [t: "⠄"] - - else_if: "$Prescripts[1][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + - else_if: "$Prescripts[1][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" then: - x: "$Prescripts[1]" - test: @@ -835,7 +835,7 @@ # degree doesn't use dot-3 for chemistry, temp, angles -- can't know that so we make a wild guess here if: "not($Prescripts[2][.='°'] and *[1][self::m:mn or @data-chem-element])" then: [t: "⠄"] - - else_if: "$Prescripts[2][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + - else_if: "$Prescripts[2][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" then: - x: "$Prescripts[2]" - test: @@ -868,7 +868,7 @@ # degree doesn't use dot-3 for chemistry, temp, angles -- can't know that so we make a wild guess here if: "not($Prescripts[3][.='°'] and *[1][self::m:mn or @data-chem-element])" then: [t: "⠄"] - - else_if: "$Prescripts[3][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + - else_if: "$Prescripts[3][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" then: - x: "$Prescripts[3]" - test: @@ -898,7 +898,7 @@ # degree doesn't use dot-3 for chemistry, temp, angles -- can't know that so we make a wild guess here if: "not($Prescripts[4][.='°'] and *[1][self::m:mn or @data-chem-element])" then: [t: "⠄"] - - else_if: "$Prescripts[4][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + - else_if: "$Prescripts[4][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" then: - x: "$Prescripts[4]" - test: @@ -935,7 +935,7 @@ # degree doesn't use dot-3 for chemistry, temp, angles -- can't know that so we make a wild guess here if: "not($Postscripts[1][.='°'] and *[1][self::m:mn or @data-chem-element])" then: [t: "⠄"] - - else_if: "$Postscripts[1][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + - else_if: "$Postscripts[1][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" then: - x: "$Postscripts[1]" - test: @@ -950,7 +950,7 @@ else: - x: "$Postscripts[1]" - test: - if: "not($Postscripts[2][self::m:none]) and $Postscripts[2][translate(., \"′″‴⁗'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')!='']" + if: "not($Postscripts[2][self::m:none]) and $Postscripts[2][translate(., \"′″‴⁗'*`+-´°‘’“”‟‵‶‷\",'')!='']" then: - t: "⠡" - test: @@ -991,7 +991,7 @@ # degree doesn't use dot-3 for chemistry, temp, angles -- can't know that so we make a wild guess here if: "not($Postscripts[3][.='°'] and *[1][self::m:mn or @data-chem-element])" then: [t: "⠄"] - - else_if: "$Postscripts[3][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + - else_if: "$Postscripts[3][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" then: - x: "$Postscripts[3]" - test: @@ -1021,7 +1021,7 @@ # degree doesn't use dot-3 for chemistry, temp, angles -- can't know that so we make a wild guess here if: "not($Postscripts[4][.='°'] and *[1][self::m:mn or @data-chem-element])" then: [t: "⠄"] - - else_if: "$Postscripts[4][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + - else_if: "$Postscripts[4][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" then: - x: "$Postscripts[4]" - test: @@ -1054,7 +1054,7 @@ # degree doesn't use dot-3 for chemistry, temp, angles -- can't know that so we make a wild guess here if: "not($Postscripts[5][.='°'] and *[1][self::m:mn or @data-chem-element])" then: [t: "⠄"] - - else_if: "$Postscripts[5][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + - else_if: "$Postscripts[5][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" then: - x: "$Postscripts[5]" - test: @@ -1084,7 +1084,7 @@ # degree doesn't use dot-3 for chemistry, temp, angles -- can't know that so we make a wild guess here if: "not($Postscripts[6][.='°'] and *[1][self::m:mn or @data-chem-element])" then: [t: "⠄"] - - else_if: "$Postscripts[6][translate(., \"'*`+-ª°²³´¹º‘’“”‟‵‶‷\",'')='']" + - else_if: "$Postscripts[6][translate(., \"'*`+-´°‘’“”‟‵‶‷\",'')='']" then: - x: "$Postscripts[6]" - test: diff --git a/Rules/Braille/Russian/Russian_Rules.yaml b/Rules/Braille/Russian/Russian_Rules.yaml index 0f91068ec..ee9004aed 100644 --- a/Rules/Braille/Russian/Russian_Rules.yaml +++ b/Rules/Braille/Russian/Russian_Rules.yaml @@ -335,6 +335,33 @@ - t: "⠐" - x: "*[2]" +- + name: gost-58511-small-font + tag: [mrow, mstyle, semantics] + match: "@data-braille-typeform='small' or contains(@intent, ':small-font')" + replace: + - t: "⠔" + - x: "*" + - t: "⠔" + +- + name: gost-58511-letter-spacing + tag: [mrow, mstyle, semantics] + match: "@data-braille-typeform='letter-spacing' or contains(@intent, ':letter-spacing')" + replace: + - t: "⠌" + - x: "*" + - t: "⠌" + +- + name: gost-58511-insertion + tag: [mrow, mstyle, semantics] + match: "@data-braille-typeform='insertion' or contains(@intent, ':insertion')" + replace: + - t: "⠧" + - x: "*" + - t: "⠼" + - name: default tag: [mrow, mstyle, semantics] diff --git a/Rules/Braille/Swedish/Swedish_Rules.yaml b/Rules/Braille/Swedish/Swedish_Rules.yaml index 028574914..7a8504574 100644 --- a/Rules/Braille/Swedish/Swedish_Rules.yaml +++ b/Rules/Braille/Swedish/Swedish_Rules.yaml @@ -348,7 +348,7 @@ - name: single-char-exceptions # RUEB 3.11 -- ° and various prime/minute/seconds aren't treated as if superscripts tag: msup - match: "*[2][translate(., \"'*`ª°²³´¹º‘’“”‟′″‴‵‶‷⁗\",'')='']" + match: "*[2][translate(., \"'*`´°‘’“”‟′″‴‵‶‷⁗\",'')='']" replace: - test: if: "NeedsToBeGrouped(*[1], 'Swedish', true())" diff --git a/Rules/Braille/UEB/UEB_Rules.yaml b/Rules/Braille/UEB/UEB_Rules.yaml index b9e9acb79..8e3491c80 100644 --- a/Rules/Braille/UEB/UEB_Rules.yaml +++ b/Rules/Braille/UEB/UEB_Rules.yaml @@ -340,7 +340,7 @@ - name: single-char-exceptions # RUEB 3.11 -- ° and various prime/minute/seconds aren't treated as if superscripts tag: [msup] - match: "*[2][translate(., \"'*`ª°²³´¹º‘’“”‟′″‴‵‶‷⁗\",'')='']" + match: "*[2][translate(., \"'*`´°‘’“”‟′″‴‵‶‷⁗\",'')='']" replace: - test: if: "NeedsToBeGrouped(*[1], 'UEB', true())" diff --git a/Rules/Braille/UEB/unicode-full.yaml b/Rules/Braille/UEB/unicode-full.yaml index 692aad255..373900be3 100644 --- a/Rules/Braille/UEB/unicode-full.yaml +++ b/Rules/Braille/UEB/unicode-full.yaml @@ -1,24 +1,6 @@ --- - - - " ": [t: "W"] # 0x2000 - - " ": [t: "W"] # 0x2001 - - " ": [t: "W"] # 0x2002 - - " ": [t: "W"] # 0x2003 - - " ": [t: "W"] # 0x2004 - - " ": [t: "W"] # 0x2005 - - " ": [t: "W"] # 0x2006 - - " ": [t: "W"] # 0x2007 - - " ": [t: "W"] # 0x2008 - - " ": [t: "W"] # 0x2009 - - " ": [t: "W"] # 0x200a - - "​": [t: "W"] # 0x200b - - "
": [t: "W"] # 0x2028 - - "
": [t: "W"] # 0x2029 - - " ": [t: "W"] # 0x202f - - " ": [t: "W"] # 0x205f - - "": [t: "W"] # 0xfeff - - + - "⋇": [tc: "1⠌⠯⠦"] # 0x22C7 (Division times) + - "⊩": [tc: "⠸⠳⠿⠸⠒"] # 0x22A9 (Forces) - "ℏ": [tc: "⠈⠒⠓"] # t: "B"F (reduced Plank's constant) - "ⅆ": [tc: "⠙"] # 0x2146 - "ⅇ": [tc: "⠑"] # 0x2147 @@ -47,6 +29,7 @@ - "↉": [tc: "#N⠚N⠌N⠑"] # 0x2189 (Vulgar Fraction Zero Thirds) + - "ℊ": [tc: "TL⠛⠁"] # 0x210a (Script Small G) - "ℋ": [tc: "TCL⠓⠁"] # 0x210b (Script Capital H) - "ℒ": [tc: "TCL⠇"] # 0x2113 (Script Capital L) @@ -73,6 +56,16 @@ - "ℤ": [tc: "𝔹CL⠵"] # 0x2124 + - "𝚨-𝛀": # 0x1d6a8 - 0x1d6c0 + - tc: "B" + - spell: "translate('.', '𝛂𝛃𝛄𝛅𝛆𝛇𝛈𝛉𝛊𝛋𝛌𝛍𝛎𝛏𝛐𝛑𝛒𝛓𝛔𝛕𝛖𝛗𝛘𝛙𝛚', 'αβγδεζηθικλμνξοπρςστυφχψω')" + + + - "𝛂-𝛚": # 0x1d6c2 - 0x1d6da + - tc: "BGL" + - spell: "translate('.', '𝛂𝛃𝛄𝛅𝛆𝛇𝛈𝛉𝛊𝛋𝛌𝛍𝛎𝛏𝛐𝛑𝛒𝛓𝛔𝛕𝛖𝛗𝛘𝛙𝛚', 'αβγδεζηθικλμνξοπρςστυφχψω')" + + - "𝔄-𝔜": # 0x1d504 - 0x1d51d ('z' version is reserved) - tc: "DC" - spell: "translate('.', '𝔄𝔅𝔆𝔇𝔈𝔉𝔊𝔋𝔌𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔𝔕𝔖𝔗𝔘𝔙𝔚𝔛𝔜', 'abcdefghijklmnopqrstuvwxyz')" @@ -106,7 +99,7 @@ # script chars in math alphabetic block and also MathType private use area - "𝒜-𝒵": # 0x1d49c - 0x1d4b5 - tc: "TsC" - - spell: "translate('.', '𝒜𝒝𝒞𝒟𝒠𝒡𝒢𝒣𝒤𝒥𝒦𝒧𝒨𝒩𝒪𝒫𝒬𝒭𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵', 'abcdefghijklmnopqrstuvwxyz')" + - spell: "translate('.', '𝒜𝒝𝒞𝒟𝒠𝒡𝒢𝒣𝒤𝒥𝒦𝒧𝒨𝒩𝒪𝒫𝒬𝒭𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵', 'abcdefghijklmnopqrstuvwxyza')" - "𝒶-𝓏": # 0x1d4b6 - 0x1d4cf - tc: "Ts" diff --git a/Rules/Braille/UEB/unicode.yaml b/Rules/Braille/UEB/unicode.yaml index 3256d59c5..e1b513bc8 100644 --- a/Rules/Braille/UEB/unicode.yaml +++ b/Rules/Braille/UEB/unicode.yaml @@ -103,7 +103,7 @@ - "~": [t: "⠈⠔"] # 0x007E (Tilde (swung dash)) - "¢": [t: "⠈⠉"] # 0x00A2 (Cents sign) - "‐": [t: "⠤"] # 0x2010 (Hyphen) - - "–": [t: "⠠⠤"] # 0x2013 (En Dash) + - "–": [t: "P⠠⠤"] # 0x2013 (En Dash) - "―": [t: "⠐⠠⠤"] # 0x2015 (Horizontal Bar) - "‖": [t: "⠸⠳"] # 0x2016 - "€": [t: "⠈⠑"] # 0x20AC (Euro sign) @@ -123,8 +123,8 @@ - "‴": [t: "1⠶⠶⠶"] # 0x2034 (Triple prime sign) - "℃": [t: "⠘⠚⠠⠉"] # 0x2103 (Degrees Celsius) - "℉": [t: "⠘⠚⠠⠋"] # 0x2109 (Degrees Fahrenheit) - - "Å": [t: "⠠⠘⠫⠁"] # 0x212B (Angstrom symbol) - - "Å": [t: "⠠⠘⠫⠁"] # 0x00C5 (WIRIS uses this for Angstrom) + - "Å": [t: "CA⠘⠫L⠁"] # 0x212B (Angstrom symbol) + - "Å": [t: "CA⠘⠫L⠁"] # 0x00C5 (WIRIS uses this for Angstrom) - "∀": [t: "⠘⠁"] # 0x2200 (For all) - "∂": [t: "⠈⠙"] # 0x2202 (Partial differential) - "∃": [t: "⠘⠢"] # 0x2203 (There exists) diff --git a/Rules/Braille/Vietnam/Vietnam_Rules.yaml b/Rules/Braille/Vietnam/Vietnam_Rules.yaml index 88947d646..2b43067be 100644 --- a/Rules/Braille/Vietnam/Vietnam_Rules.yaml +++ b/Rules/Braille/Vietnam/Vietnam_Rules.yaml @@ -437,7 +437,7 @@ - name: single-char-exceptions # RUEB 3.11 -- ° and various prime/minute/seconds aren't treated as if superscripts tag: msup - match: "*[2][translate(., \"'*`ª°²³´¹º‘’“”‟′″‴‵‶‷⁗\",'')='']" + match: "*[2][translate(., \"'*`´°‘’“”‟′″‴‵‶‷⁗\",'')='']" replace: [x: "*"] - diff --git a/Rules/Languages/de/ClearSpeak_Rules.yaml b/Rules/Languages/de/ClearSpeak_Rules.yaml index ce0f1c3c4..a4953b958 100644 --- a/Rules/Languages/de/ClearSpeak_Rules.yaml +++ b/Rules/Languages/de/ClearSpeak_Rules.yaml @@ -476,7 +476,7 @@ if: "$ClearSpeak_AbsoluteValue = 'AbsEnd'" then: - pause: short - - T: "end" + - T: "ende" - x: "$WordToSay" - pause: short @@ -501,7 +501,7 @@ - T: "Menge" - test: if: $ClearSpeak_Sets != 'woAll' - then: [T: "alle"] + then: [T: "aller"] - x: "*[1]/*[1]" - T: "so dass" - x: "*[1]/*[3]" diff --git a/Rules/Languages/de/SharedRules/general.yaml b/Rules/Languages/de/SharedRules/general.yaml index c64b9e27d..a5792c745 100644 --- a/Rules/Languages/de/SharedRules/general.yaml +++ b/Rules/Languages/de/SharedRules/general.yaml @@ -55,17 +55,21 @@ match: "count(*)=0" replace: - bookmark: "@id" + - test: + - if: "$SpeechStyle = 'ClearSpeak' and ($ClearSpeak_SetMemberSymbol = 'In' or ($ClearSpeak_SetMemberSymbol = 'Auto' and ancestor::m:set)) and preceding::m:mo[1][.='∈' or .='∊' or .='∉']" + then: [T: "den"] + else: [T: "die"] - test: - if: ".='ℂ'" - then: [T: "die komplexen zahlen"] # phrase('the complex numbers' include 2 parts) + then: [T: "komplexen zahlen"] # phrase('the complex numbers' include 2 parts) - else_if: ".='ℕ'" - then: [T: "die natürlichen zahlen"] # phrase('the natural numbers' begin at 1) + then: [T: "natürlichen zahlen"] # phrase('the natural numbers' begin at 1) - else_if: ".='ℚ'" - then: [T: "die rationalen zahlen"] # phrase('the rational numbers' are the fraction of 2 integers) + then: [T: "rationalen zahlen"] # phrase('the rational numbers' are the fraction of 2 integers) - else_if: ".='ℝ'" - then: [T: "die reellen zahlen"] # phrase('the real numbers' can be both positive and negative) + then: [T: "reellen zahlen"] # phrase('the real numbers' can be both positive and negative) - else_if: ".='ℤ'" - then: [T: "die ganzen zahlen"] # phrase('the integers' are natural numbers above 0) + then: [T: "ganzen zahlen"] # phrase('the integers' are natural numbers above 0) else: [x: "text()"] # shouldn't happen - name: real-part @@ -300,7 +304,7 @@ # HACK: '\uF8FE' is used internally for the concatenation char by 'ct' -- this gets the prefix concatenated to the base then: [x: "$Word"] - else_if: "DefinitionValue($Word, 'Speech', 'PluralForms') != ''" - then: [x: "DefinitionValue($Word, 'Speech', 'PluralForms')"] + then: [x: "DefinitionValue($Word, 'Speech', 'PluralForms')", ct: " "] else: [x: "$Word", ct: "s"] else: - x: "$Prefix" @@ -310,7 +314,7 @@ # HACK: '\uF8FE' is used internally for the concatenation char by 'ct' -- this gets the prefix concatenated to the base then: [x: "concat('\uF8FE', $Word)"] - else_if: "DefinitionValue($Word, 'Speech', 'PluralForms') != ''" - then: [x: "concat('\uF8FE', DefinitionValue($Word, 'Speech', 'PluralForms'))"] + then: [x: "concat('\uF8FE', DefinitionValue($Word, 'Speech', 'PluralForms'))", ct: " "] else: [x: "concat('\uF8FE', $Word)", ct: "s"] diff --git a/Rules/Languages/de/definitions.yaml b/Rules/Languages/de/definitions.yaml index 4e5ccf041..0783d9462 100644 --- a/Rules/Languages/de/definitions.yaml +++ b/Rules/Languages/de/definitions.yaml @@ -107,7 +107,7 @@ "in": "zoll", "ft": "fuß", "mi": "meile", - "rd": "ruthe", + "rd": "rute", "li": "glied", "ch": "kette", @@ -159,16 +159,46 @@ } - PluralForms: { - "inch": "zoll", "square inch": "quadratzoll", "cubic inch": "kubikzoll", - "foot": "füße", "square foot": "quadratfuß", "cubic foot": "kubikfuß", - "board foot": "brettfuß", - "degree celsius": "grad celsius", - "degree fahrenheit": "grad fahrenheit", - "hertz": "hertz", - "siemens": "siemens", - "revolution per minute": "umdrehungen pro minute", - "mile per hour": "meilen pro stunde", - "mile per gallon": "meilen pro gallone" + "ampere": "ampere", "candela": "candela", "kelvin": "kelvin", + "gramm": "gramm", "meter": "meter", "mol": "mol", "sekunde": "sekunden", + "becquerel": "becquerel", "coulomb": "coulomb", "grad celsius": "grad celsius", + "farad": "farad", "gray": "gray", "henry": "henry", "hertz": "hertz", + "joule": "joule", "katal": "katal", "lumen": "lumen", "lux": "lux", + "newton": "newton", "ohm": "ohm", "pascal": "pascal", "siemens": "siemens", + "sievert": "sievert", "tesla": "tesla", "volt": "volt", "watt": "watt", "weber": "weber", + "liter": "liter", "tonne": "tonnen", "dalton": "dalton", "neper": "neper", + "atommasse-einheit": "atommasse-einheiten", "elektronenvolt": "elektronenvolt", + "radiant": "radianten", "steradiant": "steradianten", "jahr": "jahre", + "bogenminute": "bogenminuten", "bogensekunde": "bogensekunden", "bit": "bit", + "byte": "byte", "baud": "baud", + "zoll": "zoll", "fuß": "füße", "meile": "meilen", "rute": "ruten", + "glied": "glieder", "kette": "ketten", "fass": "fässer", "gallone": "gallonen", + "quadratzoll": "quadratzoll", "quadratfuß": "quadratfüße", "quadratyard": "quadratyards", + "quadratmeile": "quadratmeilen", "morgen": "morgen", "brettfuß": "brettfüße", + "kubikzoll": "kubikzoll", "kubikfuß": "kubikfüße", "kubikyard": "kubikyards", + "buschelmaß": "buschelmaße", "buschel": "buschel", "teelöffel": "teelöffel", + "esslöffel": "esslöffel", "flüssige dram": "flüssige drams", "gill": "gills", + "tasse": "tassen", "pint": "pints", "quart": "quarts", "korn": "körner", + "dram": "drams", "unze": "unzen", "pfund": "pfund", "zentner": "zentner", + "feingewicht": "feingewichte", "troy-unze": "troy-unzen", "troy-pfund": "troy-pfund", + "ps": "ps", "britische wärmeeinheit": "britische wärmeeinheiten", + "grad fahrenheit": "grad fahrenheit", + "meile pro stunde": "meilen pro stunde", "meile pro gallone": "meilen pro gallone", + + "minute": "minuten", "stunde": "stunden", "tag": "tage", "woche": "wochen", + "grad": "grade", "astronomische einheit": "astronomische einheiten", + "lichtjahr": "lichtjahre", "parsec": "parsec", "ångström": "ångström", + "fermi": "fermis", "hektar": "hektar", "dezibel": "dezibel", + "atmosphäre": "atmosphären", "bar": "bar", "kalorie": "kalorien", "curie": "curie", + "gon": "gon", "mol/liter": "mol/liter", "röntgen": "röntgen", "mho": "mho", + "dyn": "dyn", "erg": "erg", + "kibi-bit": "kibi-bit", "mebi-bit": "mebi-bit", "gibi-bit": "gibi-bit", + "tebi-bit": "tebi-bit", "pebi-bit": "pebi-bit", "exbi-bit": "exbi-bit", + "zebi-bit": "zebi-bit", "yobi-bit": "yobi-bit", + "kibi-byte": "kibi-byte", "mebi-byte": "mebi-byte", "gibi-byte": "gibi-byte", + "tebi-byte": "tebi-byte", "pebi-byte": "pebi-byte", "exbi-byte": "exbi-byte", + "zebi-byte": "zebi-byte", "yobi-byte": "yobi-byte", + "umdrehungen pro minute": "umdrehungen pro minute" } diff --git a/Rules/Languages/de/unicode-full.yaml b/Rules/Languages/de/unicode-full.yaml index a940ceb26..1978993ca 100644 --- a/Rules/Languages/de/unicode-full.yaml +++ b/Rules/Languages/de/unicode-full.yaml @@ -8,8 +8,9 @@ - "¦": [T: "gebrochene Linie"] # 0xa6 (en: 'broken bar') - "§": [T: "Abschnitt"] # 0xa7 (en: 'section') - "¨": [T: "diaeresis"] # 0xa8 (en: 'double dot') - - "©": [T: "Copyright"] # 0xa9 (en: 'copyright') + - "©": [T: "Urheberrecht"] # 0xa9 (en: 'copyright') - "ª": [T: "weibliches Ordnungszeichen"] # 0xaa (en: 'feminine ordinal indicator') + - "¬": [T: "nicht"] # 0xac (en: 'not') - "«": [T: "Nach links zeigendes doppeltes spitzes Anführungszeichen"] # 0xab (en: 'left-pointing double angle quote mark', MathPlayer: 'left-pointing double angle quote mark', google: 'links zeigende doppelwinkel-zitatmarke') - "¯": # 0xaf - test: @@ -18,9 +19,24 @@ else: [T: "Überstrich"] # (en: 'line', MathPlayer: 'macron', google: 'linie') - "²": [T: "Quadrat"] # 0xb2 (en: 'two', MathPlayer: 'zum Quadrat', google: 'zwei') - "³": [T: "Kubik"] # 0xb3 (en: 'three', MathPlayer: 'hoch drei', google: 'drei') + - "´": [T: "Akutakzent"] # 0xb4 (en: 'acute', MathPlayer: 'acute accent', google: 'akut') - "µ": [T: "Mikrozeichen"] # 0xb5 (en: 'micro', MathPlayer: 'micro sign', google: 'mikro') - "¹": [T: "hoch eins"] # 0xb9 (en: 'one', google: 'eins') - "º": [T: "Männliches Ordnungszeichen"] # 0xb9 (en: 'masculine ordinal indicator') + - "·": + - test: + if: "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_MultSymbolDot = 'Auto'" + then: [T: "mal"] # (en: 'times', google translation) + else: [T: "mal"] # (en: 'dot', MathPlayer: 'Punkt mittig', google: 'punkt') + - "×": # 0xd7 + - test: + if: "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_MultSymbolX = 'Auto'" + then: [T: "mal"] # (en: 'times', google translation) + else_test: + if: $ClearSpeak_MultSymbolX = 'By' + then: [T: "von"] # (en: 'by', google translation) + else: [T: "mal"] # (en: 'cross', MathPlayer: 'times', google: 'kreuzen') + - "÷": [T: "geteilt durch"] # 0xf7 (en: 'divided by', MathPlayer: 'divides') - "¡": [T: "umgekehrtes ausrufezeichen"] # 0xa1 (en: 'inverted exclamation mark') - "¶": [T: "absatzzeichen"] # 0xb6 (en: 'paragraph mark') - "¿": [T: "umgekehrtes fragezeichen"] # 0xbf (en: 'inverted question mark') @@ -108,6 +124,14 @@ - "˽": [T: "modifikatorregal"] # 0x2fd (en: 'modifier shelf', google translation) - "˾": [T: "modifikator offenes regal"] # 0x2fe (en: 'modifier open shelf', google translation) - "˿": [T: "modifikator niedriger links pfeil"] # 0x2ff (en: 'modifier low left arrow', google translation) + - "̀": [T: "gravisakzentverzierung"] # 0x300 (en: 'grave accent embellishment', google: 'grabakzentverzierung') + - "́": [T: "akutakzentverzierung"] # 0x301 (en: 'acute accent embellishment', google: 'akute akzentverzierung') + - "̂": [T: "Hutverzierung"] # 0x302 (en: 'circumflex accent embellishment', google: 'zirma akzentverzierung') + - "̃": [T: "tildeverzierung"] # 0x303 (google: 'tilde verzierung') + - "̄": [T: "makronverzierung"] # 0x304 (en: 'macron embellishment', google: 'makron -verzierung') + - "̅": [T: "Überstreifenverzierung"] # 0x305 (google: 'überbärerverzierung') + - "̆": [T: "kombinierendes Breve"] # 0x306 (en: 'breve embellishment', google: 'breve -verzierung') + - "̇": [T: "Punkt über Verzierung"] # 0x307 (google: 'punkt über verzierung') - "̈": [T: "zwei Punkte oberhalb"] # 0x308 (en: 'diaeresis embellishment', google: 'diaeresis -verzierung') - "̉": [T: "haken über verzierung"] # 0x309 (en: 'hook above embellishment', google translation) - "̊": [T: "ring über verzierung"] # 0x30a (en: 'ring above embellishment', google: 'ring über verzierung') @@ -197,9 +221,13 @@ - "ϒ": [T: "Variante Upsilon mit Haken"] # 0x3d2 (en: 'upsilon with hook', google: 'upsilon mit haken') - "ϓ": [T: "Upsilon mit Akutakzent und Haken"] # 0x3d3 (en: 'upsilon with acute and hook', google translation) - "ϔ": [T: "Upsilon mit Diaeresis und Haken"] # 0x3d4 (en: 'upsilon with diaeresis and hook', google translation) + - "ϕ": [T: "gerades Phi"] # 0x3d5 (en: 'phi', google: 'phi') + - "ϖ": [T: "Variante Pi"] # 0x3d6 (en: 'pi', google: 'pi') - "ϗ": [T: "kai"] # 0x3d7 (MathPlayer: 'variant kai') - "Ϙ": [T: "großes archaisches koppa"] # 0x3d8 (en: 'cap archaic koppa') - "ϙ": [T: "archaisches koppa"] # 0x3d9 (en: 'archaic koppa') + - "ϵ": [T: "epsilon"] # 0x3f5 + - "϶": [T: "umgekehrtes epsilon"] # 0x3f6 (en: 'reversed epsilon', MathPlayer: 'reversed epsilon', google: 'umgekehrter epsilon') - "А-Я": # 0x410 - 0x42f - test: if: "$CapitalLetters_Beep" @@ -256,6 +284,10 @@ - "‐": [T: "Bindestrich"] # 0x2010 (en: 'hyphen', MathPlayer: 'minus', google: 'bindestrich') - "‑": [T: "nicht-trennender Bindestrich"] # 0x2011 (en: 'hyphen', google: 'bindestrich') - "‒": [T: "Figurenstrich"] # 0x2012 (en: 'figure dash', google: 'figur dash') + - "–": [T: "Halbgeviertstrich"] # 0x2013 (SRE: 'En Dash') + - "—": [T: "Geviertstrich"] # 0x2014 (SRE: 'EM Dash') + - "―": [T: "Horizontale Linie"] # 0x2015 (en: 'horizontal bar', MathPlayer: 'horizontal bar', google: 'horizontale linie') + - "‖": [T: "Doppelte vertikale Linie"] # 0x2016 (en: 'double vertical line', MathPlayer: 'double vertical bar', google: 'doppelte vertikale linie') - "†": [T: "Dolch"] # 0x2020 (en: 'dagger', MathPlayer: 'dagger', google: 'dolch') - "‡": [T: "Doppelter Dolch"] # 0x2021 (en: 'double dagger', MathPlayer: 'double dagger', google: 'doppeldolch') @@ -267,8 +299,24 @@ then: [T: "punkt"] # (en: 'dot', google translation) else: [T: "Kugel"] # (en: 'bullet', MathPlayer: 'bullet', google: 'kugel') + - "…": # 0x2026 + test: + if: + - "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_Ellipses = 'Auto' or" + # must be ClearSpeak and $ClearSpeak_Ellipses = 'AndSoOn' + # speak '…' as 'and so on...' unless expr starts with '…' + - "../*[1][text()='…']" + then: [T: "punkt punkt punkt"] # (en: 'dot dot dot', google translation) + else_test: # must have $ClearSpeak_Ellipses = 'AndSoOn' + if: "count(following-sibling::*) = 0" + then: [T: "und so weiter"] # (en: 'and so on', google translation) + else: [T: "horizontale Ellipse"] # (en: 'and so on up to', MathPlayer: 'dot dot dot', google: 'und so weiter bis') + - "‰": [T: "promille"] # 0x2030 (en: 'per mille', MathPlayer: 'per mille sign', google: 'pro mille') - "‱": [T: "pro Zehntausend"] # 0x2031 (en: 'per ten thousand', MathPlayer: 'per ten thousand sign', google: 'pro zehntausend') + - "′": [T: "Strich"] # 0x2032 (en: 'prime', MathPlayer: 'strich', google: 'prime') + - "″": [T: "zwei Striche"] # 0x2033 (en: 'double prime', MathPlayer: 'zwei-strich', google: 'double prime') + - "‴": [T: "drei Striche"] # 0x2034 (en: 'triple prime', MathPlayer: 'drei-strich', google: 'triple prime') - "‵": [T: "umgekehrter Strich"] # 0x2035 (en: 'reversed prime', MathPlayer: 'reversed prime', google: 'umgekehrt prime') - "‶": [T: "zwei umgekehrte Striche"] # 0x2036 (en: 'reversed double prime', MathPlayer: 'reversed double prime', google: 'umgekehrt doppelte prime') - "‷": [T: "drei umgekehrte Striche"] # 0x2037 (en: 'reversed triple prime', google: 'triple prime umgekehrt') @@ -398,6 +446,7 @@ - "℆": [T: "cada una"] # 0x2106 (google translation) - "ℇ": [T: "Euler-Konstante"] # 0x2107 (en: 'euler's constant', google: 'eulers konstante') - "℈": [T: "skrupel"] # 0x2108 (en: 'scruples', google translation) + - "℉": [T: "Grad Fahrenheit"] # 0x2109 (google: 'grad fahrenheit') - "ℊ": [T: "Skript G"] # 0x210a (google: 'skript g') - "ℌℑℨℭ": # 0x210c, 0x2111, 0x2128, 0x212d - T: "Fraktur" # (en: 'fraktur', google: 'fraktur') @@ -409,6 +458,7 @@ then: [T: "doppelt geschlagen"] # (en: 'double struck', google translation) - spell: "translate('.', 'ℍℙℾℿ', 'HPΓΠ')" + - "ℎ": [T: "Planck-Konstante"] # 0x210e (en: 'planck constant', MathPlayer: 'planck constant', google: 'planck konstant') - "ℏ": # 0x210f - test: if: "($Verbosity='Terse')" @@ -419,11 +469,15 @@ - T: "Skript" # (en: 'script', MathPlayer: 'h bar', google: 'skript') - spell: "translate('.', 'ℐℒ℘ℬℰℱℳ', 'ILPBEFM')" + - "ℓ": [T: "Schreibschrift l"] # 0x2113 (en: 'script l', MathPlayer: 'script l', google: 'skript l') - "℔": [T: "L B Balkensymbol"] # 0x2114 (en: 'pounds', google: 'pfund') - "№": [T: "Numero-Zeichen"] # 0x2116 (en: 'number', MathPlayer: 'numero sign', google: 'nummer') - "℥": [T: "Unze-Zeichen"] # 0x2125 (en: 'ounces', MathPlayer: 'ounce sign', google: 'unzen') + - "Ω": [T: "Ohm-Zeichen"] # 0x2126 (en: 'ohms', MathPlayer: 'ohm sign', google: 'ohm') - "℧": [T: "Umgekehrtes Ohm-Zeichen"] # 0x2127 (en: 'mhos', MathPlayer: 'inverted ohm', google: 'mhos') - "℩": [T: "gedrehtes Iota"] # 0x2129 (google: 'drehte iota') + - "K": [T: "Kelvin-Zeichen"] # 0x212a (en: 'kelvin', MathPlayer: 'degrees kelvin', google: 'kelvin') + - "Å": [T: "Angstrom-Zeichen"] # 0x212b (en: 'angstroms', MathPlayer: 'angstroms', google: 'angstrome') - "ℯ": [T: "Skript E"] # 0x212f (google: 'skript e') # coalesced some chars that use cap letters @@ -501,6 +555,10 @@ - "ⅾ": [T: "ⅾ"] # 0x217e (en: 'D', google translation) - "ⅿ": [T: "ⅿ"] # 0x217f (en: 'M', google translation) - "↉": [T: "null drittel"] # 0x2189 (en: 'zero thirds') + - "←": [T: "Pfeil nach links"] # 0x2190 (en: 'leftwards arrow', MathPlayer: 'leftwards arrow', google: 'pfeil nach links') + - "↑": [T: "Aufwärtspfeil"] # 0x2191 (en: 'upwards arrow', MathPlayer: 'upwards arrow', google: 'nach oben pfeil') + - "→": [T: "Pfeil nach rechts"] # 0x2192 (en: 'rightwards arrow', MathPlayer: 'rightwards arrow', google: 'richtiger pfeil') + - "↓": [T: "Pfeil nach unten"] # 0x2193 (en: 'downwards arrow', MathPlayer: 'downwards arrow', google: 'nach unten pfeil') - "↔": [T: "Pfeil nach links und rechts"] # 0x2194 (en: 'left right arrow', MathPlayer: 'left right arrow', google: 'links rechts pfeil') - "↕": [T: "Pfeil nach oben und unten"] # 0x2195 (en: 'up down arrow', MathPlayer: 'up down arrow', google: 'auf pfeil runter') - "↖": [T: "Nordwestpfeil"] # 0x2196 (en: 'north west arrow', MathPlayer: 'north west arrow', google: 'nordwestpfeil') @@ -573,6 +631,7 @@ - "⇏": [T: "Doppelpfeil nach rechts mit Strich"] # 0x21cf (en: 'rightwards double arrow with stroke', MathPlayer: 'rightwards double arrow with stroke', google: 'richtiger doppelpfeil mit schlaganfall') - "⇐": [T: "Doppelpfeil nach links"] # 0x21d0 (en: 'leftwards double arrow', MathPlayer: 'leftwards double arrow', google: 'links doppelpfeil') - "⇑": [T: "Doppelpfeil nach oben"] # 0x21d1 (en: 'upwards double arrow', MathPlayer: 'upwards double arrow', google: 'double -pfeil nach oben') + - "⇒": [T: "Doppelpfeil nach rechts"] # 0x21d2 (en: 'rightwards double arrow', MathPlayer: 'rightwards double arrow', google: 'richtiger doppelpfeil') - "⇓": [T: "Doppelpfeil nach unten"] # 0x21d3 (en: 'downwards double arrow', MathPlayer: 'downwards double arrow', google: 'downwards doppelpfeil') - "⇔": [T: "Linker rechter Doppelpfeil"] # 0x21d4 (en: 'left right double arrow', MathPlayer: 'left right double arrow', google: 'links rechts doppelpfeil') - "⇕": [T: "Doppelpfeil nach oben und unten"] # 0x21d5 (en: 'up down double arrow', MathPlayer: 'up down double arrow', google: 'doppelpfeil nach oben') @@ -624,18 +683,107 @@ if: "$Verbosity!='Terse'" then: [T: "die"] # (en: 'the', google translation) - T: "Komplement" # (en: 'complement of') + - "∂": # 0x2202 + - test: + if: "$Verbosity='Terse'" + then: [T: "partiell"] # (en: 'partial', google translation) + else: [T: "partielle Ableitung"] # (en: 'partial derivative', google: 'partielle ableitung') - "∃": [T: "es gibt"] # 0x2203 (en: 'there exists') - "∄": [T: "es gibt nicht"] # 0x2204 (en: 'there does not exist') - "∅": [T: "leere Menge"] # 0x2205 (en: 'empty set') + - "∆": # 0x2206 + - test: + if: "$Verbosity!='Terse'" + then: [T: "die"] # (en: 'the', google translation) + - T: "Laplace-Operator von" # (en: 'laplacian of', MathPlayer: 'increment', google: 'laplace von') + - "∇": # 0x2207 + - test: + if: "$Verbosity!='Terse'" + then: [T: "die"] # (en: 'the', google translation) + - T: "Nabla" # (en: 'gradient of', google: 'gradient von') + - "∈": # 0x2208 + - test: + if: "$SpeechStyle != 'ClearSpeak'" + then: [T: "ein Element von"] # (en: 'an element of', google translation) + # Several options for speaking elements in ClearSpeak -- they split between being inside a set or not and then the option + else_test: + if: "../../self::m:set or ../../../self::m:set" # inside a set + then_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "in"] # (google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "Element von"] # (en: 'member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "Element von"] # (en: 'element of', google translation) + - else: [T: "Element von"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'belonging to') + else_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "ist ein Element von"] # (en: 'is a member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "ist ein Element von"] # (en: 'is an element of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "ist in"] # (en: 'is in', google translation) + - else: [T: "Element von"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'belongs to') + - "∉": # 0x2209 + # rule is identical to 0x2208 + - test: + if: "$SpeechStyle != 'ClearSpeak'" + then: [T: "ist kein Element von"] # (en: 'is not an element of', google translation) + # Several options for speaking elements in ClearSpeak -- they split between being inside a set or not and then the option + else_test: + if: "../../self::m:set or ../../../self::m:set" # inside a set + then_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "nicht in"] # (en: 'not in', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "kein Element von"] # (en: 'not member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "kein Element von"] # (en: 'not element of', google translation) + - else: [T: "nicht Element von"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'not belonging to') + else_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "ist kein Element von"] # (en: 'is not a member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "ist kein Element von"] # (en: 'is not an element of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "ist nicht in"] # (en: 'is not in', google translation) + - else: [T: "nicht Element von"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'does not belong to') + - "∊": # 0x220a + - test: + if: "$SpeechStyle != 'ClearSpeak'" + then: [T: "ist ein Element von"] # (en: 'is an element of', google translation) + # Several options for speaking elements in ClearSpeak -- they split between being inside a set or not and then the option + else_test: + if: "../../self::m:set or ../../../self::m:set" # inside a set + then_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "in"] # (google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "Element von"] # (en: 'member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "Element von"] # (en: 'element of', google translation) + - else: [T: "Element von"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'belonging to') + else_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "ist ein Element von"] # (en: 'is a member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "ist ein Element von"] # (en: 'is an element of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "ist in"] # (en: 'is in', google translation) + - else: [T: "Element von"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'belongs to') - "∋": [T: "hat als Element"] # 0x220b (en: 'contains the member') - "∌": [T: "hat nicht als Element"] # 0x220c (en: 'does not contain the member') - "∍": [T: "hat als Element"] # 0x220d (en: 'contains the member') - "∎": [T: "Ende Beweis"] # 0x220e (en: 'end of proof') + - "∏": [T: "Produkt"] # 0x220f (en: 'product', MathPlayer: 'Product', google: 'produkt') + - "∐": [T: "Koprodukt"] # 0x2210 (en: 'coproduct', MathPlayer: 'coproduct', google: 'koprodukt') + - "∑": [T: "Summe"] # 0x2211 (en: 'sum') - "−": [T: "minus"] # 0x2212 - "∓": [T: "minus plus"] # 0x2213 (en: 'minus or plus') - "∔": [T: "Plus mit Punkt"] # 0x2214 (en: 'dot plus', MathPlayer: 'dot plus', google: 'punkt plus') - "∕": [T: "Division"] # 0x2215 (en: 'divided by', MathPlayer: 'Schrägstrich (Division)', google: 'geteilt durch') - "∖": [T: "Mengendifferenz"] # 0x2216 (en: 'set minus', MathPlayer: 'Mengen-Minus', google: 'minus einstellen') + - "∗": [T: "Sternoperator"] # 0x2217 (en: 'times', MathPlayer: 'asterisk operator', google: 'mal') - "∘": [T: "verknüpft mit"] # 0x2218 (en: 'composed with') - "∙": # 0x2219 - test: @@ -643,6 +791,11 @@ then: [T: "punkt"] # (en: 'dot', google translation) else: [T: "Kreisoperator"] # (en: 'times', MathPlayer: 'bullet operator', google: 'mal') + - "√": # 0x221a + - test: + if: "$Verbosity!='Terse'" + then: [T: "die"] # (en: 'the', google translation) + - T: "Quadratwurzel" # (en: 'square root of', MathPlayer: 'radical', google: 'quadratwurzel von') - "∛": # 0x221b - test: if: "$Verbosity!='Terse'" @@ -653,12 +806,26 @@ if: "$Verbosity!='Terse'" then: [T: "die"] # (en: 'the', google translation) - T: "vierte Wurzel" # (en: 'fourth root of') + - "∝": # 0x221d + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist"] # (en: 'is', google translation) + - T: "proportional zu" # (en: 'proportional to') - "∞": [T: "unendlich"] # 0x221e (en: 'infinity') + - "∟": [T: "rechter Winkel"] # 0x221f (en: 'right angle') + - "∠": [T: "Winkel"] # 0x2220 (en: 'angle') + - "∡": [T: "gerichteter Winkel"] # 0x2221 (en: 'measured angle', MathPlayer: 'measured angle', google: 'gemessener winkel') - "∢": [T: "Raumwinkel"] # 0x2222 (en: 'spherical angle', MathPlayer: 'spherical angle', google: 'sphärischer winkel') - "∣": [T: "teilt"] # 0x2223 (en: 'divides') - "∤": [T: "teilt nicht"] # 0x2224 (en: 'does not divide') - "∧": [T: "und"] # 0x2227 (en: 'and') - "∨": [T: "oder"] # 0x2228 (en: 'or') + - "∩": [T: "Durchschnitt"] # 0x2229 (en: 'intersection') + - "∪": [T: "Vereinigung"] # 0x222a (en: 'union') + - "∫": [T: "Integral"] # 0x222b (en: 'integral') + - "∬": [T: "Doppelintegral"] # 0x222c (en: 'double integral') + - "∭": [T: "Dreifachintegral"] # 0x222d (en: 'triple integral', MathPlayer: 'Dreifaches Integral', google: 'dreifachintegral') + - "∮": [T: "Randintegral"] # 0x222e (en: 'contour integral', MathPlayer: 'Kontur-Integral', google: 'konturintegral') - "∯": [T: "Oberflächenintegral"] # 0x222f (en: 'surface integral', MathPlayer: 'Flächenintegral', google: 'oberflächenintegral') - "∰": [T: "Volumenintegral"] # 0x2230 (en: 'volume integral', MathPlayer: 'Volumsintegral', google: 'volumenintegral') - "∱": [T: "Integral im Uhrzeigersinn"] # 0x2231 (en: 'clockwise integral') @@ -666,6 +833,12 @@ - "∳": [T: "Kurvenintegral im Gegenuhrzeigersinn"] # 0x2233 (en: 'anticlockwise contour integral', MathPlayer: 'Kontur-Integral im Gegenuhrzeigersinn', google: 'konturintegral gegen den gegenwart') - "∴": [T: "folglich"] # 0x2234 (en: 'therefore', MathPlayer: 'deshalb', google: 'daher') - "∵": [T: "weil"] # 0x2235 (en: 'because') + - "∶": # 0x2236 + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist"] # (en: 'is', google translation) + - T: "Verhältnis" # (en: 'to') + - "∷": [T: "Proportion"] # 0x2237 (en: 'as') - "∸": [T: "Minus mit Punkt"] # 0x2238 (en: 'dot minus', MathPlayer: 'dot minus', google: 'punkt minus') - "∹": [T: "Überschuss"] # 0x2239 (en: 'has excess compared to', MathPlayer: 'excess', google: 'hat überschüssig im vergleich zu') - "∺": # 0x223a @@ -678,6 +851,14 @@ if: "$Verbosity!='Terse'" then: [T: "ist"] # (en: 'is', google translation) - T: "homothetisch" # (en: 'homothetic to', MathPlayer: 'homothetic', google: 'homothetisch zu') + - "∼": [T: "Tildeoperator"] # 0x223c (en: 'varies with', MathPlayer: 'tilde operator', google: 'variiert mit') + - "∽": [T: "Umgekehrte Tilde"] # 0x223d (en: 'reversed tilde', MathPlayer: 'reversed tilde', google: 'umgekehrte tilde') + - "∾": # 0x223e + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist"] # (en: 'is', google translation) + - T: "Umgekehrtes stummes S" # (en: 'most positive', MathPlayer: 'inverted lazy s', google: 'am positivsten') + - "∿": [T: "Sinuswelle"] # 0x223f (en: 'sine wave', MathPlayer: 'sine wave', google: 'sinus') - "≀": [T: "Kranzprodukt"] # 0x2240 (en: 'wreath product', MathPlayer: 'wreath product', google: 'kranzprodukt') - "≁": [T: "durchgestrichene Tilde"] # 0x2241 (en: 'not tilde', MathPlayer: 'not tilde', google: 'nicht tilde') - "≂": [T: "minus tilde"] # 0x2242 (SRE: 'Minus über Tilde') @@ -778,6 +959,16 @@ then: [T: "ist"] # (en: 'is', google translation) - T: "gemessen mit" # (en: 'measured by', MathPlayer: 'measured by') - "≟": [T: "vielleicht gleich"] # 0x225f (en: 'has an unknown relationship with', MathPlayer: 'questioned equal to', google: 'hat eine unbekannte beziehung zu') + - "≠": # 0x2260 + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist"] # (en: 'is', google translation) + - T: "ungleich" # (en: 'not equal to') + - "≡": # 0x2261 + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist"] # (en: 'is', google translation) + - T: "identisch mit" # (en: 'identical to', SRE: 'kongruent mit') - "≢": # 0x2262 - test: if: "$Verbosity!='Terse'" @@ -888,6 +1079,36 @@ - "≿": [T: "nachfolgend oder äquivalent"] # 0x227f (en: 'succeeds or is equivalent to', MathPlayer: 'succeeds or equivalent to', google: 'erfolg oder ist gleichbedeutend mit') - "⊀": [T: "nicht vorangehend"] # 0x2280 (en: 'does not precede', MathPlayer: 'does not precede', google: 'vorausgegangen nicht voraus') - "⊁": [T: "nicht nachfolgend"] # 0x2281 (en: 'does not succeed', MathPlayer: 'does not succeed', google: 'gelingt es nicht') + - "⊂": # 0x2282 + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist ein"] # (en: 'is a', google translation) + - T: "echte Teilmenge von" # (en: 'subset of', MathPlayer: 'Teilmenge von', google: 'untergruppe von') + - "⊃": # 0x2283 + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist ein"] # (en: 'is a', google translation) + - T: "echte Obermenge von" # (en: 'superset of', MathPlayer: 'Obermenge von', google: 'superset von') + - "⊄": # 0x2284 + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist"] # (en: 'is', google translation) + - T: "keine echte Teilmenge von" # (en: 'not a subset of', MathPlayer: 'nicht Teilmenge von', google: 'keine teilmenge von') + - "⊅": # 0x2285 + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist"] # (en: 'is', google translation) + - T: "keine echte Obermenge von" # (en: 'not a superset of', MathPlayer: 'nicht Obermenge von', google: 'kein superset von') + - "⊆": # 0x2286 + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist ein"] # (en: 'is a', google translation) + - T: "Teilmenge oder gleich" # (en: 'subset of or equal to', MathPlayer: 'Teilmenge von odre gleich', google: 'teilmenge von oder gleich') + - "⊇": # 0x2287 + - test: + if: "$Verbosity!='Terse'" + then: [T: "ist ein"] # (en: 'is a', google translation) + - T: "Obermenge oder gleich" # (en: 'superset of or equal to', MathPlayer: 'Obermenge von oder gleich', google: 'superset von oder gleich') - "⊈": # 0x2288 - test: if: "$Verbosity!='Terse'" @@ -976,7 +1197,7 @@ - "⊹": [T: "hermitesch konjugierte Matrix"] # 0x22b9 (en: 'hermitian conjugate matrix', MathPlayer: 'hermitian conjugate matrix', google: 'hermitische konjugierte matrix') - "⊺": [T: "einschalten"] # 0x22ba (en: 'intercalate', MathPlayer: 'intercalate', google: 'interkalieren') - "⊻": [T: "Ausschließendes Oder"] # 0x22bb (SRE: 'Ausschließendes Oder') - - "⊼": [T: "nand"] # 0x22bc (SRE: 'Nand verknüpft mit') + - "⊼": [T: "Nicht-und"] # 0x22bc (SRE: 'Nand verknüpft mit') - "⊽": [T: "Nor verknüpft mit"] # 0x22bd (en: 'nor', MathPlayer: 'nor', google: 'noch') - "⊾": [T: "rechter Winkel mit Bogen"] # 0x22be (en: 'right angle with arc', MathPlayer: 'right angle with arc', google: 'rechtwinkel mit bogen') - "⊿": [T: "rechtwinkliges Dreieck"] # 0x22bf (en: 'right triangle', MathPlayer: 'right triangle', google: 'rechtwinkliges dreieck') @@ -1849,7 +2070,7 @@ - "⧿": [T: "Miny"] # 0x29ff (en: 'miny', google: 'miny') - "⨀": [T: "Operator mit eingekreistem Punkt"] # 0x2a00 (en: 'circled dot operator', google: 'eingekreister punktbetreiber') - "⨁": [T: "Operator mit eingekreistem Plus"] # 0x2a01 (en: 'circled plus operator', google: 'kreis plus operator') - - "⨂": [T: "Operator mit eingekreistem Kreuz"] # 0x2a02 (en: 'circled times operator', google: 'eingekreistes times operator') + - "⨂": [T: "Operator mit eingekreistem Malzeichen"] # 0x2a02 (en: 'circled times operator', google: 'eingekreistes times operator') - "⨃": [T: "Vereinigungs-Operator mit Punkt"] # 0x2a03 (en: 'union operator with dot', google: 'gewerkschaftsbetreiber mit punkt') - "⨄": [T: "Vereinigungs-Operator mit Plus"] # 0x2a04 (en: 'union operator with plus', google: 'gewerkschaftsbetreiber mit plus') - "⨅": [T: "quadratischer Schnittmengen-Operator"] # 0x2a05 (en: 'square intersection operator', google: 'square intersection operator') @@ -1903,7 +2124,7 @@ - "⨵": [T: "Multiplikationszeichen im rechten Halbkreis"] # 0x2a35 (en: 'multiplication sign in right half circle', MathPlayer: 'multiplication sign in right half circle', google: 'multiplikationszeichen im rechten halbkreis') - "⨶": [T: "eingekreistes Multiplikationszeichen mit Circumflex-Akzent"] # 0x2a36 (en: 'circled multiplication sign with circumflex accent', MathPlayer: 'circled multiplication sign with circumflex accent', google: 'umkreistes multiplikationszeichen mit circumflex -akzent') - "⨷": [T: "Multiplikationszeichen im doppelten Kreis"] # 0x2a37 (en: 'multiplication sign in double circle', MathPlayer: 'multiplication sign in double circle', google: 'multiplikationszeichen im doppelkreis') - - "⨸": [T: "circled division sign"] # 0x2a38 + - "⨸": [T: "eingekreistes Divisionszeichen"] # 0x2a38 - "⨹": [T: "Pluszeichen im Dreieck"] # 0x2a39 (en: 'plus sign in triangle', MathPlayer: 'plus sign in triangle', google: 'plus melden sie sich im dreieck an') - "⨺": [T: "Minuszeichen im Dreieck"] # 0x2a3a (en: 'minus sign in triangle', MathPlayer: 'minus sign in triangle', google: 'minus zeichen im dreieck') - "⨻": [T: "Multiplikationszeichen im Dreieck"] # 0x2a3b (en: 'multiplication sign in triangle', MathPlayer: 'multiplication sign in triangle', google: 'multiplikationszeichen im dreieck') @@ -1930,8 +2151,8 @@ - "⩐": [T: "Closed Union mit Serifen und Smash-Produkten"] # 0x2a50 (en: 'closed union with serifs and smash product', MathPlayer: 'closed union with serifs and smash product', google: 'geschlossene vereinigung mit serifen und smash -produkt') - "⩑": [T: "Logisch und mit Punkt oben"] # 0x2a51 (en: 'logical and with dot above', google: 'logisch und mit punkt oben') - "⩒": [T: "Logisch oder mit Punkt oben"] # 0x2a52 (en: 'logical or with dot above', google: 'logisch oder mit punkt oben') - - "⩓": [T: "double logical and"] # 0x2a53 - - "⩔": [T: "double logical or"] # 0x2a54 + - "⩓": [T: "doppeltes logisches Und"] # 0x2a53 + - "⩔": [T: "doppeltes logisches Oder"] # 0x2a54 - "⩕": [T: "Zwei durchschneiden logisch und"] # 0x2a55 (en: 'two intersecting logical and', MathPlayer: 'two intersecting logical and', google: 'zwei kreuzende logische und') - "⩖": [T: "Zwei sich überschneidende logische Oder"] # 0x2a56 (en: 'two intersecting logical or', MathPlayer: 'two intersecting logical or', google: 'zwei kreuzende logische oder') - "⩗": [T: "Abfallend großes oder"] # 0x2a57 (en: 'sloping large or', MathPlayer: 'sloping large or', google: 'groß oder') @@ -1964,7 +2185,7 @@ - "⩲": [T: "Pluszeichen über Gleichheitszeichen"] # 0x2a72 (en: 'plus sign above equals sign', MathPlayer: 'equals with plus above', google: 'plus -zeichen oben gleiches zeichen') - "⩳": [T: "Gleichheitszeichen über Tilde-Operator"] # 0x2a73 (en: 'equals sign above tilde operator', MathPlayer: 'equals sign above tilde operator', google: 'gleicher vorzeichen über dem tilde -operator') - "⩴": [T: "Doppelpunkt gleich"] # 0x2a74 (en: 'double colon equal', MathPlayer: 'double colon equal', google: 'doppelter dickdarm gleich') - - "⩵": [T: "double equal"] # 0x2a75 (en: 'two consecutive equals signs') + - "⩵": [T: "doppeltes Gleichheitszeichen"] # 0x2a75 (en: 'two consecutive equals signs') - "⩶": [T: "Drei aufeinander folgende Gleichheitszeichen"] # 0x2a76 (en: 'three consecutive equals signs', google: 'drei aufeinanderfolgende anzeichen') - "⩷": [T: "Gleichheitszeichen mit zwei Punkten oben und zwei Punkten unten"] # 0x2a77 (en: 'equals sign with two dots above and two dots below', MathPlayer: 'equals sign with two dots above and two dots below', google: 'gleiches zeichen mit zwei punkten oben und zwei punkten unten') - "⩸": [T: "Gleichwertig mit vier Punkten oben"] # 0x2a78 (en: 'equivalent with four dots above', MathPlayer: 'equivalent with four dots above', google: 'äquivalent mit vier punkten oben') @@ -2058,10 +2279,10 @@ - "⫐": [T: "Superset geschlossen"] # 0x2ad0 (en: 'closed superset', MathPlayer: 'closed superset', google: 'geschlossener superset') - "⫑": [T: "Geschlossene Untermenge oder gleich"] # 0x2ad1 (en: 'closed subset or equal to', MathPlayer: 'closed subset or equal to', google: 'geschlossene untergruppe oder gleich') - "⫒": [T: "Superset geschlossen oder gleich"] # 0x2ad2 (en: 'closed superset or equal to', MathPlayer: 'closed superset or equal to', google: 'geschlossene superset oder gleich') - - "⫓": [T: "subset over superset"] # 0x2ad3 (en: 'subset above superset') - - "⫔": [T: "superset over subset"] # 0x2ad4 (en: 'superset above subset') - - "⫕": [T: "subset over subset"] # 0x2ad5 (en: 'subset above subset') - - "⫖": [T: "superset over superset"] # 0x2ad6 (en: 'superset above superset') + - "⫓": [T: "Teilmenge über Obermenge"] # 0x2ad3 (en: 'subset above superset') + - "⫔": [T: "Obermenge über Teilmenge"] # 0x2ad4 (en: 'superset above subset') + - "⫕": [T: "Teilmenge über Teilmenge"] # 0x2ad5 (en: 'subset above subset') + - "⫖": [T: "Obermenge über Obermenge"] # 0x2ad6 (en: 'superset above superset') - "⫗": [T: "Superset neben dem Subset"] # 0x2ad7 (en: 'superset beside subset', MathPlayer: 'superset beside subset', google: 'superset neben untergruppe') - "⫘": [T: "Superset Neben und Joined von Dash mit Subset"] # 0x2ad8 (en: 'superset beside and joined by dash with subset', MathPlayer: 'superset beside and joined by dash with subset', google: 'superset neben dem dash mit der untergruppe') - "⫙": [T: "Element der Öffnung nach unten"] # 0x2ad9 (en: 'element of opening downwards', MathPlayer: 'element of opening downwards', google: 'element der abwärts öffnen') @@ -2071,17 +2292,17 @@ - "⫝": [T: "Nicht Gabeln"] # 0x2add (en: 'nonforking', google: 'nicht -forking') - "⫞": [T: "Kurzer Linker Tack"] # 0x2ade (en: 'short left tack', google: 'kurzer linker tack') - "⫟": [T: "Kurzer Down Tack"] # 0x2adf (en: 'short down tack', google: 'kurzer tack') - - "⫠": [T: "Short Up Tack"] # 0x2ae0 (en: 'short up tack', google: 'kurzer tack') + - "⫠": [T: "kurzer Aufwärtshaken"] # 0x2ae0 (en: 'short up tack', google: 'kurzer tack') - "⫡": [T: "Rechtwinklig zu S"] # 0x2ae1 (en: 'perpendicular with s', google: 'senkrecht mit s') - "⫢": [T: "Vertikales Dreifach-Drehkreuz"] # 0x2ae2 (en: 'vertical bar triple right turnstile', google: 'vertikale bar dreifache rechte drehstil') - "⫣": [T: "Doppelter vertikaler Balken linkes Drehkreuz"] # 0x2ae3 (en: 'double vertical bar left turnstile', google: 'doppelte vertikale balken linke drehkreuze') - - "⫤": [T: "double left turnstile vertical bar"] # 0x2ae4 (en: 'vertical bar double left turnstile') + - "⫤": [T: "vertikaler Strich mit doppeltem linkem Drehkreuz"] # 0x2ae4 (en: 'vertical bar double left turnstile') - "⫥": [T: "Doppelter vertikaler Balken Doppelter linker Drehkreuz"] # 0x2ae5 (en: 'double vertical bar double left turnstile', google: 'doppelte vertikale balken doppelte linke drehkreuze') - "⫦": [T: "Long Dash von Left Member von Double Vertical"] # 0x2ae6 (en: 'long dash from left member of double vertical', MathPlayer: 'long dash from left member of double vertical', google: 'langer dash vom linken mitglied des doppel vertikalen') - - "⫧": [T: "Short Down Tack mit Overbar"] # 0x2ae7 (en: 'short down tack with overbar', MathPlayer: 'short down tack with overbar', google: 'kurzer tack mit overbar') - - "⫨": [T: "perpendicular over bar"] # 0x2ae8 (en: 'short up tack with underbar') - - "⫩": [T: "Short Up Tack Über Short Down Tack"] # 0x2ae9 (en: 'short up tack above short down tack', MathPlayer: 'short up tack above short down tack', google: 'kurzschluss über kurzer tack') - - "⫪": [T: "Double Down Tack"] # 0x2aea (en: 'double down tack', google: 'double down tack') + - "⫧": [T: "kurzer Abwärtshaken mit Überstrich"] # 0x2ae7 (en: 'short down tack with overbar', MathPlayer: 'short down tack with overbar', google: 'kurzer tack mit overbar') + - "⫨": [T: "kurzer Aufwärtshaken mit Unterstrich"] # 0x2ae8 (en: 'short up tack with underbar') + - "⫩": [T: "kurzer Aufwärtshaken über kurzem Abwärtshaken"] # 0x2ae9 (en: 'short up tack above short down tack', MathPlayer: 'short up tack above short down tack', google: 'kurzschluss über kurzer tack') + - "⫪": [T: "doppelter Abwärtshaken"] # 0x2aea (en: 'double down tack', google: 'double down tack') - "⫫": [T: "Verdoppeln Sie Tack"] # 0x2aeb (en: 'double up tack', MathPlayer: 'double up tack', google: 'doppelte tack') - "⫬": [T: "Doppelstrich nicht unterschreiben"] # 0x2aec (en: 'double stroke not sign', MathPlayer: 'double stroke not sign', google: 'doppelhub nicht unterschreiben') - "⫭": [T: "Umgekehrter Doppelstrich nicht unterschrieben"] # 0x2aed (en: 'reversed double stroke not sign', MathPlayer: 'reversed double stroke not sign', google: 'umgekehrter doppelstrich nicht unterschreiben') @@ -2313,29 +2534,29 @@ - "㋍": [T: "ergs"] # 0x32cd (google translation) - "㋎": [T: "elektronenvolt"] # 0x32ce (en: 'electron volts', google translation) - "㋏": [T: "haftungsschild beschränkt"] # 0x32cf (en: 'limited liability sign', google translation) - - "㍱": [T: "hectopascals"] # 0x3371 (google translation) - - "㍲": [T: "daltons"] # 0x3372 (google translation) + - "㍱": [T: "hektopascal"] # 0x3371 (google translation) + - "㍲": [T: "dalton"] # 0x3372 (google translation) - "㍳": [T: "astronomische einheiten"] # 0x3373 (en: 'astronomical units', google translation) - "㍴": [T: "riegel"] # 0x3374 (en: 'bars', google translation) - "㍵": [T: "o v"] # 0x3375 (google translation) - - "㍶": [T: "parsecs"] # 0x3376 (google translation) + - "㍶": [T: "parsec"] # 0x3376 (google translation) - "㍷": [T: "dezimeter"] # 0x3377 (en: 'decimeters', google translation) - - "㍸": [T: "dezimeter quadratisch"] # 0x3378 (en: 'decimeters squared', google translation) - - "㍹": [T: "dezimeter gewonnen"] # 0x3379 (en: 'decimeters cubed', google translation) - - "㍺": [T: "instrumentaleinheiten"] # 0x337a (en: 'instrumental units', google translation) - - "㎀": [T: "picoamps"] # 0x3380 (google translation) - - "㎁": [T: "nanoamps"] # 0x3381 (google translation) - - "㎂": [T: "mikroamps"] # 0x3382 (en: 'microamps', google translation) - - "㎃": [T: "milliamps"] # 0x3383 (google translation) - - "㎄": [T: "kiloamps"] # 0x3384 (google translation) - - "㎅": [T: "kilobytes"] # 0x3385 (google translation) + - "㍸": [T: "Quadratdezimeter"] # 0x3378 (en: 'decimeters squared', google translation) + - "㍹": [T: "Kubikdezimeter"] # 0x3379 (en: 'decimeters cubed', google translation) + - "㍺": [T: "internationale Einheit"] # 0x337a (en: 'instrumental units', google translation) + - "㎀": [T: "pikoampere"] # 0x3380 (google translation) + - "㎁": [T: "nanoampere"] # 0x3381 (google translation) + - "㎂": [T: "mikroampere"] # 0x3382 (en: 'microamps', google translation) + - "㎃": [T: "milliampere"] # 0x3383 (google translation) + - "㎄": [T: "kiloampere"] # 0x3384 (google translation) + - "㎅": [T: "kilobyte"] # 0x3385 (google translation) - "㎆": [T: "megabyte"] # 0x3386 (en: 'megabytes', google translation) - "㎇": [T: "gigabyte"] # 0x3387 (en: 'gigabytes', google translation) - "㎈": [T: "kalorien"] # 0x3388 (en: 'calories', google translation) - "㎉": [T: "kilokalorien"] # 0x3389 (en: 'kilocalories', google translation) - - "㎊": [T: "picofarads"] # 0x338a (google translation) - - "㎋": [T: "nanofarads"] # 0x338b (google translation) - - "㎌": [T: "mikrofaraden"] # 0x338c (en: 'microfarads', google translation) + - "㎊": [T: "pikofarad"] # 0x338a (google translation) + - "㎋": [T: "nanofarad"] # 0x338b (google translation) + - "㎌": [T: "mikrofarad"] # 0x338c (en: 'microfarads', google translation) - "㎍": [T: "mikrogramm"] # 0x338d (en: 'micrograms', google translation) - "㎎": [T: "milligramm"] # 0x338e (en: 'milligrams', google translation) - "㎏": [T: "kilogramm"] # 0x338f (en: 'kilograms', google translation) @@ -2390,9 +2611,9 @@ - "㏀": [T: "kilo-ohm"] # 0x33c0 (en: 'kilo-ohms', google translation) - "㏁": [T: "megaohm"] # 0x33c1 (en: 'megaohms', google translation) - "㏂": [T: "attometer"] # 0x33c2 (en: 'attometers', google translation) - - "㏃": [T: "becquerels"] # 0x33c3 (google translation) + - "㏃": [T: "becquerel"] # 0x33c3 (google translation) - "㏄": [T: "kubikzentimeter"] # 0x33c4 (en: 'cubic centimeters', google translation) - - "㏅": [T: "candelas"] # 0x33c5 (google translation) + - "㏅": [T: "candela"] # 0x33c5 (google translation) - "㏆": [T: "coulombs pro kilogramm"] # 0x33c6 (en: 'coulombs per kilogram', google translation) - "㏇": [T: "herzzeitvolumen"] # 0x33c7 (en: 'cardiac output', google translation) - "㏈": [T: "dezibel"] # 0x33c8 (en: 'decibels', google translation) @@ -2400,16 +2621,16 @@ - "㏊": [T: "hektar"] # 0x33ca (en: 'hectares', google translation) - "㏋": [T: "pferdestärke"] # 0x33cb (en: 'horsepower', google translation) - "㏌": [T: "zoll"] # 0x33cc (en: 'inches', google translation) - - "㏍": [T: "kilokelvins"] # 0x33cd (google translation) + - "㏍": [T: "kilokelvin"] # 0x33cd (google translation) - "㏎": [T: "kilometer"] # 0x33ce (en: 'kilometers', google translation) - "㏏": [T: "knoten"] # 0x33cf (en: 'knots', google translation) - "㏐": [T: "lumen"] # 0x33d0 (en: 'lumens', google translation) - - "㏑": [T: "natural log"] # 0x33d1 (google translation) + - "㏑": [T: "natürlicher Logarithmus"] # 0x33d1 (google translation) - "㏒": [T: "logarithmus"] # 0x33d2 (en: 'logarithm', google translation) - "㏓": [T: "lux"] # 0x33d3 (google translation) - - "㏔": [T: "millibarns"] # 0x33d4 (google translation) - - "㏕": [T: "mühlen"] # 0x33d5 (en: 'mills', google translation) - - "㏖": [T: "maulwürfe"] # 0x33d6 (en: 'moles', google translation) + - "㏔": [T: "millibar"] # 0x33d4 (google translation) + - "㏕": [T: "mil"] # 0x33d5 (en: 'mills', google translation) + - "㏖": [T: "mol"] # 0x33d6 (en: 'moles', google translation) - "㏗": [T: "p h"] # 0x33d7 (google translation) - "㏘": [T: "picometer"] # 0x33d8 (en: 'picometers', google translation) - "㏙": [T: "teile pro million"] # 0x33d9 (en: 'parts per million', google translation) @@ -2846,8 +3067,11 @@ - "": [T: "digamma"] # 0xed03 (google translation) - "ϝ": [T: "digamma"] # 0x3dd - "": [T: ""] # 0xed10 (en: 'd', google translation) + - "ⅆ": [T: "d kursiv mit Doppelstrich"] # 0x2146 (en: 'd', MathPlayer: 'd', google: 'ⅆ') - "": [T: ""] # 0xed11 (en: 'e', google translation) + - "ⅇ": [T: "e kursiv mit Doppelstrich"] # 0x2147 (en: 'e', MathPlayer: 'e', google: 'ⅇ') - "": [T: ""] # 0xed12 (en: 'i', google translation) + - "ⅈ": [T: "i kursiv mit Doppelstrich"] # 0x2148 (en: 'i', MathPlayer: 'i', google: 'ⅈ') - "": [T: ""] # 0xed13 (en: 'j', google translation) - "ⅅ": - spell: "translate('.', 'ⅅ', 'DD')" # 0xed16, 0x2145 @@ -2896,6 +3120,7 @@ - " ": [T: ""] # 0x205f - "": [T: ""] # 0xef04 - "": [T: ""] # 0xef05 + - " ": [T: ""] # 0x2003 - "": [T: ""] # 0xef06 - "": [T: ""] # 0xef07 - "": [T: ""] # 0xef08 @@ -2911,7 +3136,7 @@ - "": [T: "integral mit quadratisch"] # 0xef81 (en: 'integral with square', google translation) - "": [T: "integral mit schrägstrich"] # 0xef82 (en: 'integral with slash', google translation) - "": [T: "umgekehrter integral"] # 0xef83 (en: 'reversed integral', google translation) - - "": [T: "double null über double null"] # 0xef90 (en: 'double zero over double zero', google translation) + - "": [T: "doppelte Null über doppelter Null"] # 0xef90 (en: 'double zero over double zero', google translation) - "": [T: "null mit schrägstrich"] # 0xef91 (en: 'zero with slash', google translation) # fraktur chars in math alphabetic block and also MathType private use area diff --git a/Rules/Languages/de/unicode.yaml b/Rules/Languages/de/unicode.yaml index 142069a4c..bdd89fc76 100644 --- a/Rules/Languages/de/unicode.yaml +++ b/Rules/Languages/de/unicode.yaml @@ -320,9 +320,9 @@ else_test: if: "../../self::m:set or ../../../self::m:set" # inside a set then_test: - - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' - then: [T: "in"] # (google translation) - - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "in"] + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' then: [T: "element von"] # (en: 'member of', google translation) - else_if: $ClearSpeak_SetMemberSymbol = 'Element' then: [T: "element von"] # (en: 'element of', google translation) @@ -344,9 +344,9 @@ else_test: if: "../../self::m:set or ../../../self::m:set" # inside a set then_test: - - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' - then: [T: "nicht in"] # (en: 'not in', google translation) - - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "nicht in"] + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' then: [T: "nicht element von"] # (en: 'not member of', google translation) - else_if: $ClearSpeak_SetMemberSymbol = 'Element' then: [T: "nicht element von"] # (en: 'not element of', google translation) @@ -367,9 +367,9 @@ else_test: if: "../../self::m:set or ../../../self::m:set" # inside a set then_test: - - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' - then: [T: "in"] # (google translation) - - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "in"] + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' then: [T: "element von"] # (en: 'member of', google translation) - else_if: $ClearSpeak_SetMemberSymbol = 'Element' then: [T: "element von"] # (en: 'element of', google translation) diff --git a/Rules/Languages/en/SharedRules/default.yaml b/Rules/Languages/en/SharedRules/default.yaml index 21cfc256b..c1f07ec7d 100644 --- a/Rules/Languages/en/SharedRules/default.yaml +++ b/Rules/Languages/en/SharedRules/default.yaml @@ -62,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 > 0 or @data-roman-numeral" # 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) @@ -237,26 +237,12 @@ - x: "*[2]" - t: "below" # phrase(x with z 'below' it) -# FIX: this only works for up to four dots (which is realistically all we need) -- name: dot-over - tag: modified-variable - match: "*[1][self::m:mi] and (*[2][translate(., '.', '')=''])" - replace: - - x: "*[1]" - - x: "IfThenElse(string-length(*[2])=1, 'dot', - IfThenElse(string-length(*[2])=2, 'double dot', - IfThenElse(string-length(*[2])=3, 'triple dot', 'quadruple dot') - ))" - - pause: short - -# FIX: the 'translate' list is a little different from 'modified-variable', so we also include 'mover' (unify?) - name: diacriticals - tag: [mover, modified-variable] + tag: mover match: "*[1][self::m:mi] and *[2][translate(., '\u0306\u030c.\u00A8\u02D9\u20DB\u20DC`^ˇ~→¯_', '')='']" replace: - x: "*[1]" - x: "*[2]" - - pause: short - name: default tag: mover @@ -436,23 +422,22 @@ - t: "end scripts" # phrase(At this point 'end scripts' occurs) - name: default - tag: [mtable, array] + tag: mtable variables: - IsColumnSilent: "false()" - - NumColumns: "CountTableColumns(.)" - - NumRows: "CountTableRows(.)" + - NumColumns: "count(*[1]/*) - IfThenElse(*/self::m:mlabeledtr, 1, 0)" match: "." replace: - t: "table with" # phrase(the 'table with' 3 rows) - - x: "$NumRows" + - x: count(*) - test: - if: "$NumRows=1" + if: count(*)=1 then: [t: "row"] # phrase(the table with 1 'row') else: [t: "rows"] # phrase(the table with 3 'rows') - t: "and" # phrase(the table with 3 rows 'and' 4 columns) - x: "$NumColumns" - test: - if: "$NumColumns=1" + if: "NumColumns=1" then: [t: "column"] # phrase(the table with 3 rows and 1 'column') else: [t: "columns"] # phrase(the table with 3 rows and 4 'columns') - pause: long diff --git a/Rules/Languages/en/unicode-full.yaml b/Rules/Languages/en/unicode-full.yaml index bdedfdcad..737625b21 100644 --- a/Rules/Languages/en/unicode-full.yaml +++ b/Rules/Languages/en/unicode-full.yaml @@ -10,6 +10,7 @@ - "¨": [t: "double dot"] # 0xa8 - "©": [t: "copyright"] # 0xa9 - "ª": [t: "feminine ordinal indicator"] # 0xaa + - "¬": [t: "not"] # 0xac - "«": [t: "left-pointing double angle quote mark"] # 0xab - "¯": # 0xaf - test: @@ -18,9 +19,24 @@ else: [t: "line"] - "²": [t: "two"] # 0xb2 - "³": [t: "three"] # 0xb3 + - "´": [t: "acute"] # 0xb4 - "µ": [t: "micro"] # 0xb5 - "¹": [t: "one"] # 0xb9 - "º": [t: "masculine ordinal indicator"] # 0xb9 + - "·": + - test: + if: "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_MultSymbolDot = 'Auto'" + then: [t: "times"] + else: [t: "dot"] + - "×": # 0xd7 + - test: + if: "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_MultSymbolX = 'Auto'" + then: [t: "times"] + else_test: + if: $ClearSpeak_MultSymbolX = 'By' + then: [t: "by"] + else: [t: "cross"] + - "÷": [t: "divided by"] # 0xf7 - "¡": [t: "inverted exclamation mark"] # 0xa1 - "¶": [t: "paragraph mark"] # 0xb6 - "¿": [t: "inverted question mark"] # 0xbf @@ -108,6 +124,14 @@ - "˽": [t: "modifier shelf"] # 0x2fd - "˾": [t: "modifier open shelf"] # 0x2fe - "˿": [t: "modifier low left arrow"] # 0x2ff + - "̀": [t: "grave accent embellishment"] # 0x300 + - "́": [t: "acute accent embellishment"] # 0x301 + - "̂": [t: "circumflex accent embellishment"] # 0x302 + - "̃": [t: "tilde embellishment"] # 0x303 + - "̄": [t: "macron embellishment"] # 0x304 + - "̅": [t: "overbar embellishment"] # 0x305 + - "̆": [t: "breve embellishment"] # 0x306 + - "̇": [t: "dot above embellishment"] # 0x307 - "̈": [t: "diaeresis embellishment"] # 0x308 - "̉": [t: "hook above embellishment"] # 0x309 - "̊": [t: "ring above embellishment"] # 0x30a @@ -197,9 +221,13 @@ - "ϒ": [t: "upsilon with hook"] # 0x3d2 - "ϓ": [t: "upsilon with acute and hook"] # 0x3d3 - "ϔ": [t: "upsilon with diaeresis and hook"] # 0x3d4 + - "ϕ": [t: "phi"] # 0x3d5 + - "ϖ": [t: "pi"] # 0x3d6 - "ϗ": [t: "kai"] # 0x3d7 - "Ϙ": [t: "cap archaic koppa"] # 0x3d8 - "ϙ": [t: "archaic koppa"] # 0x3d9 + - "ϵ": [t: "epsilon"] # 0x3f5 + - "϶": [t: "reversed epsilon"] # 0x3f6 - "А-Я": # 0x410 - 0x42f - test: if: "$CapitalLetters_Beep" @@ -271,6 +299,19 @@ then: [t: "dot"] else: [t: "bullet"] + - "…": # 0x2026 + test: + if: + - "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_Ellipses = 'Auto' or" + # must be ClearSpeak and $ClearSpeak_Ellipses = 'AndSoOn' + # speak '…' as 'and so on...' unless expr starts with '…' + - "../*[1][.='…']" + then: [t: "dot dot dot"] + else_test: # must have $ClearSpeak_Ellipses = 'AndSoOn' + if: "count(following-sibling::*) = 0" + then: [t: "and so on"] + else: [t: "and so on up to"] + - "‰": [t: "per mille"] # 0x2030 - "‱": [t: "per ten thousand"] # 0x2031 - "′": [t: "prime"] # 0x2032 @@ -427,6 +468,7 @@ - t: "script" - spell: "translate('.', 'ℐℒ℘ℬℰℱℳ', 'ILPBEFM')" + - "ℓ": [t: "script l"] # 0x2113 - "℔": [t: "pounds"] # 0x2114 - "№": [t: "number"] # 0x2116 - "℥": [t: "ounces"] # 0x2125 @@ -584,6 +626,7 @@ - "⇏": [t: "right double arrow with stroke"] # 0x21cf - "⇐": [t: "left double arrow"] # 0x21d0 - "⇑": [t: "up double arrow"] # 0x21d1 + - "⇒": [t: "implies"] # 0x21d2 - "⇓": [t: "down double arrow"] # 0x21d3 - "⇔": [t: "if and only if"] # 0x21d4 - "⇕": [t: "up down double arrow"] # 0x21d5 @@ -635,15 +678,81 @@ if: "$Verbosity!='Terse'" then: [ot: "the"] - t: "complement of" + - "∂": # 0x2202 + - test: + if: "$Verbosity='Terse'" + then: [t: "partial"] + else: [t: "partial derivative"] - "∃": [t: "there exists"] # 0x2203 - "∄": [t: "there does not exist"] # 0x2204 - "∅": [t: "empty set"] # 0x2205 + - "∆": # 0x2206 + - test: + if: "following-sibling::*" + then_test: + if: "$Verbosity!='Terse'" + then: [t: "the LahPlahsian of"] # "LahPlahsian" sounds better than "laplacian" in speech engines tested + else: [t: "LahPlahsian"] + else: [t: "LahPlahsian"] + - "∇": [t: "nahblah"] # 0x2207 + - "∉": # 0x2209 + # rule is identical to 0x2208 + - test: + if: "$SpeechStyle != 'ClearSpeak'" + then: [t: "is not an element of"] + # Several options for speaking elements in ClearSpeak -- they split between being inside a set or not and then the option + else_test: + if: "../../self::m:set or ../../../self::m:set" # inside a set + then_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [t: "not in"] + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + then: [t: "not member of"] + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [t: "not element of"] + - else: [t: "not belonging to"] # $ClearSpeak_SetMemberSymbol = 'Belongs' + else_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'Member' + then: [t: "is not a member of"] + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [t: "is not an element of"] + - else_if: $ClearSpeak_SetMemberSymbol = 'In' + then: [t: "is not in"] + - else: [t: "does not belong to"] # $ClearSpeak_SetMemberSymbol = 'Belongs' + - "∊": # 0x220a + - test: + if: "$SpeechStyle != 'ClearSpeak'" + then: + - test: + if: "$Verbosity!='Terse' and not(parent::m:set)" # "the set x is an element of ..." sounds bad + then: [t: "is"] + - t: "an element of" + # Several options for speaking elements in ClearSpeak -- they split between being inside a set or not and then the option + else_test: + if: "../../self::m:set or ../../../self::m:set" # inside a set + then_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [t: "in"] + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + then: [t: "member of"] + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [t: "element of"] + - else: [t: "belonging to"] # $ClearSpeak_SetMemberSymbol = 'Belongs' + else_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'Member' + then: [t: "is a member of"] + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [t: "is an element of"] + - else_if: $ClearSpeak_SetMemberSymbol = 'In' + then: [t: "is in"] + - else: [t: "belongs to"] # $ClearSpeak_SetMemberSymbol = 'Belongs' - "∋": [t: "contains the member"] # 0x220b - "∌": [t: "does not contain the member"] # 0x220c - "∍": [t: "contains the member"] # 0x220d - "∎": [t: "end of proof"] # 0x220e - "∏": [t: "product"] # 0x220f + - "∐": [t: "coproduct"] # 0x2210 - "∑": [t: "sum"] # 0x2211 - "−": [t: "minus"] # 0x2212 - "∓": [t: "minus or plus"] # 0x2213 @@ -658,6 +767,11 @@ then: [t: "dot"] else: [t: "times"] + - "√": # 0x221a + - test: + if: "$Verbosity!='Terse'" + then: [ot: "the"] + - t: "square root of" - "∛": # 0x221b - test: if: "$Verbosity!='Terse'" @@ -668,6 +782,11 @@ if: "$Verbosity!='Terse'" then: [ot: "the"] - t: "fourth root of" + - "∝": # 0x221d + - test: + if: "$Verbosity!='Terse'" + then: [t: "is"] + - t: "proportional to" - "∞": [t: "infinity"] # 0x221e - "∟": [t: "right angle"] # 0x221f - "∠": [t: "angle"] # 0x2220 @@ -690,6 +809,11 @@ - "∳": [t: "anticlockwise contour integral"] # 0x2233 - "∴": [t: "therefore"] # 0x2234 - "∵": [t: "because"] # 0x2235 + - "∶": # 0x2236 + - test: + if: "$Verbosity!='Terse'" + then: [t: "is"] + - t: "to" - "∷": [t: "as"] # 0x2237 - "∸": [t: "dot minus"] # 0x2238 - "∹": [t: "has excess compared to"] # 0x2239 @@ -705,6 +829,11 @@ - t: "homothetic to" - "∼": [t: "varies with"] # 0x223c - "∽": [t: "reversed tilde"] # 0x223d + - "∾": # 0x223e + - test: + if: "$Verbosity!='Terse'" + then: [t: "is"] + - t: "most positive" - "∿": [t: "sine wave"] # 0x223f - "≀": [t: "wreath product"] # 0x2240 - "≁": [t: "not tilde"] # 0x2241 @@ -806,6 +935,16 @@ then: [t: "is"] - t: "measured by" - "≟": [t: "has an unknown relationship with"] # 0x225f + - "≠": # 0x2260 + - test: + if: "$Verbosity!='Terse'" + then: [t: "is"] + - t: "not equal to" + - "≡": # 0x2261 + - test: + if: "$Verbosity!='Terse'" + then: [t: "is"] + - t: "identical to" - "≢": # 0x2262 - test: if: "$Verbosity!='Terse'" @@ -916,6 +1055,36 @@ - "≿": [t: "succeeds or is equivalent to"] # 0x227f - "⊀": [t: "does not precede"] # 0x2280 - "⊁": [t: "does not succeed"] # 0x2281 + - "⊂": # 0x2282 + - test: + if: "$Verbosity!='Terse'" + then: [t: "is a"] + - t: "subset of" + - "⊃": # 0x2283 + - test: + if: "$Verbosity!='Terse'" + then: [t: "is a"] + - t: "superset of" + - "⊄": # 0x2284 + - test: + if: "$Verbosity!='Terse'" + then: [t: "is"] + - t: "not a subset of" + - "⊅": # 0x2285 + - test: + if: "$Verbosity!='Terse'" + then: [t: "is"] + - t: "not a superset of" + - "⊆": # 0x2286 + - test: + if: "$Verbosity!='Terse'" + then: [t: "is a"] + - t: "subset of or equal to" + - "⊇": # 0x2287 + - test: + if: "$Verbosity!='Terse'" + then: [t: "is a"] + - t: "superset of or equal to" - "⊈": # 0x2288 - test: if: "$Verbosity!='Terse'" @@ -1234,7 +1403,7 @@ - "⏠": [t: "top tortoise shell bracket"] # 0x23e0 - "⏡": [t: "bottom tortoise shell bracket"] # 0x23e1 - "⏢": [t: "white trapezium"] # 0x23e2 - - "⏣": [t: "benzene ring with circle"] # 0x23e3 + - "⏣": [t: "benzene right with circle"] # 0x23e3 - "⏤": [t: "straightness"] # 0x23e4 - "⏥": [t: "flatness"] # 0x23e5 - "⏦": # 0x23e6 @@ -1286,7 +1455,7 @@ - t: "parenthesized" - spell: "translate('.', '⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵', 'abcdefghijklmnopqrstuvwxyz')" - - "Ⓐ-Ⓩ": # 0x24b6 - 0x24cf + - "Ⓐ-ⓩ": # 0x24b6 - 0x24cf - t: "circled" - spell: "translate('.', 'ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏ', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" @@ -1297,7 +1466,6 @@ - "ⓐ-ⓩ": # 0x24d0 - 0x24e9 - t: "circled" - spell: "translate('.', 'ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ', 'abcdefghijklmnopqrstuvwxyz')" - - "⓪": [t: "circled zero"] # 0x24ea - "⓫": [t: "black circled eleven"] # 0x24eb - "⓬": [t: "black circled twelve"] # 0x24ec @@ -1449,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 with two dots"] # 0x2689 + - "⚉": [t: "black circle wiht two dots"] # 0x2689 - "⚪": [t: "medium white circle"] # 0x26aa - "⚫": [t: "medium black circle"] # 0x26ab - "⚬": [t: "medium small white circle"] # 0x26ac @@ -2879,8 +3047,11 @@ - "": [t: "digamma"] # 0xed03 - "ϝ": [t: "digamma"] # 0x3dd - "": [t: "d"] # 0xed10 + - "ⅆ": [t: "d"] # 0x2146 - "": [t: "e"] # 0xed11 + - "ⅇ": [t: "e"] # 0x2147 - "": [t: "i"] # 0xed12 + - "ⅈ": [t: "i"] # 0x2148 - "": [t: "j"] # 0xed13 - "ⅅ": - spell: "translate('.', 'ⅅ', 'DD')" # 0xed16, 0x2145 @@ -3495,6 +3666,12 @@ then: [t: "bold"] - spell: "translate('.', '𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗', '0123456789')" + - "-": # 0xf52e - 0xf537 (old MathType) + - test: + if: "not($IgnoreBold)" + then: [t: "bold"] + - spell: "translate('.', '', '0123456789')" + - "𝟬-𝟵": # 0x1D7EC - 0x1D7F5 - test: if: "not($IgnoreBold)" diff --git a/Rules/Languages/zh/tw/unicode-full.yaml b/Rules/Languages/zh/tw/unicode-full.yaml index 23a443fa6..9e4e85087 100644 --- a/Rules/Languages/zh/tw/unicode-full.yaml +++ b/Rules/Languages/zh/tw/unicode-full.yaml @@ -10,6 +10,7 @@ - "¨": [T: "double dot"] # 0xa8 (en: 'double dot', google translation) - "©": [T: "版權"] # 0xa9 (en: 'copyright', google translation) - "ª": [t: "feminine ordinal indicator"] # 0xaa (en: 'feminine ordinal indicator', google translation) + - "¬": [T: "非"] # 0xac (en: 'not', google translation) - "«": [t: "left-pointing double angle quote mark"] # 0xab (en: 'left-pointing double angle quote mark', google translation) - "¯": # 0xaf - test: @@ -18,9 +19,24 @@ else: [T: "橫線"] # (en: 'line') - "²": [T: "二"] # 0xb2 (en: 'two', google translation) - "³": [T: "三"] # 0xb3 (en: 'three', google translation) + - "´": [t: "acute"] # 0xb4 (en: 'acute', google translation) - "µ": [T: "微"] # 0xb5 (en: 'micro', google translation) - "¹": [T: "一"] # 0xb9 (en: 'one', google translation) - "º": [t: "masculine ordinal indicator"] # 0xb9 (en: 'masculine ordinal indicator', google translation) + - "·": + - test: + if: "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_MultSymbolDot = 'Auto'" + then: [T: "乘"] # (en: 'times', google translation) + else: [T: "內積"] # (en: 'dot') + - "×": # 0xd7 + - test: + if: "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_MultSymbolX = 'Auto'" + then: [T: "乘"] # (en: 'times', google translation) + else_test: + if: $ClearSpeak_MultSymbolX = 'By' + then: [T: "乘"] # (en: 'by', google translation) + else: [T: "乘"] # (en: 'cross') + - "÷": [T: "除以"] # 0xf7 (en: 'divided by') - "ʰ": [t: "modifier small h"] # 0x2b0 (en: 'modifier small h', google translation) - "ʱ": [t: "modifier small h with hook"] # 0x2b1 (en: 'modifier small h with hook', google translation) - "ʲ": [t: "modifier small j"] # 0x2b2 (en: 'modifier small j', google translation) @@ -104,6 +120,14 @@ - "˽": [t: "modifier shelf"] # 0x2fd (en: 'modifier shelf', google translation) - "˾": [t: "modifier open shelf"] # 0x2fe (en: 'modifier open shelf', google translation) - "˿": [t: "modifier low left arrow"] # 0x2ff (en: 'modifier low left arrow', google translation) + - "̀": [t: "grave accent embellishment"] # 0x300 (en: 'grave accent embellishment', google translation) + - "́": [t: "acute accent embellishment"] # 0x301 (en: 'acute accent embellishment', google translation) + - "̂": [t: "circumflex accent embellishment"] # 0x302 (en: 'circumflex accent embellishment', google translation) + - "̃": [t: "tilde embellishment"] # 0x303 (en: 'tilde embellishment', google translation) + - "̄": [t: "macron embellishment"] # 0x304 (en: 'macron embellishment', google translation) + - "̅": [t: "overbar embellishment"] # 0x305 (en: 'overbar embellishment', google translation) + - "̆": [t: "breve embellishment"] # 0x306 (en: 'breve embellishment', google translation) + - "̇": [t: "dot above embellishment"] # 0x307 (en: 'dot above embellishment', google translation) - "̈": [t: "diaeresis embellishment"] # 0x308 (en: 'diaeresis embellishment', google translation) - "̉": [t: "hook above embellishment"] # 0x309 (en: 'hook above embellishment', google translation) - "̊": [t: "ring above embellishment"] # 0x30a (en: 'ring above embellishment', google translation) @@ -192,7 +216,11 @@ - "ϒ": [t: "upsilon with hook"] # 0x3d2 (en: 'upsilon with hook') - "ϓ": [t: "upsilon with acute and hook"] # 0x3d3 (en: 'upsilon with acute and hook') - "ϔ": [t: "upsilon with diaeresis and hook"] # 0x3d4 (en: 'upsilon with diaeresis and hook') + - "ϕ": [T: "phi"] # 0x3d5 (en: 'phi') + - "ϖ": [t: "pi"] # 0x3d6 (en: 'pi') - "ϗ": [t: "kai"] # 0x3d7 (en: 'kai') + - "ϵ": [T: "epsilon"] # 0x3f5 (en: 'epsilon') + - "϶": [t: "reversed epsilon"] # 0x3f6 (en: 'reversed epsilon') - "А-Я": # 0x410 - 0x42f - test: if: "$CapitalLetters_Beep" @@ -246,6 +274,9 @@ - "‐": [T: "連字符"] # 0x2010 (en: 'hyphen', google translation) - "‑": [T: "連字符"] # 0x2011 (en: 'hyphen', google translation) - "‒": [t: "圖破折號"] # 0x2012 (en: 'figure dash', google translation) + - "–": [t: "en dash"] # 0x2013 (google translation) + - "—": [t: "em dash"] # 0x2014 (google translation) + - "―": [T: "橫線"] # 0x2015 (en: 'horizontal bar', google translation) - "‖": [T: "雙垂直線"] # 0x2016 (en: 'double vertical line', google translation) - "†": [t: "dagger"] # 0x2020 (en: 'dagger', google translation) - "‡": [t: "double dagger"] # 0x2021 (en: 'double dagger', google translation) @@ -256,6 +287,19 @@ then: [T: "dot"] # (en: 'dot', google translation) else: [T: "bullet"] # (en: 'bullet', google translation) + - "…": # 0x2026 + test: + if: + - "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_Ellipses = 'Auto' or" + # must be ClearSpeak and $ClearSpeak_Ellipses = 'AndSoOn' + # speak '…' as 'and so on...' unless expr starts with '…' + - "../*[1][.='…']" + then: [T: "點點點"] # (en: 'dot dot dot', google translation) + else_test: # must have $ClearSpeak_Ellipses = 'AndSoOn' + if: "count(following-sibling::*) = 0" + then: [T: "等等"] # (en: 'and so on', google translation) + else: [T: "等等"] # (en: 'and so on up to', google translation) + - "‰": [T: "千分"] # 0x2030 (en: 'per mille', google translation) - "‱": [T: "萬分"] # 0x2031 (en: 'per ten thousand', google translation) - "′": [T: "prime"] # 0x2032 @@ -402,6 +446,7 @@ - T: "草體" # (en: 'script', google translation) - SPELL: "translate('.', 'ℐℒ℘ℬℰℱℳ', 'ILPBEFM')" + - "ℓ": [T: "草體l"] # 0x2113 (en: 'script l', google translation) - "℔": [T: "磅"] # 0x2114 (en: 'pounds', google translation) - "№": [T: "數字"] # 0x2116 (en: 'number', google translation) - "℥": [T: "盎司"] # 0x2125 (en: 'ounces', google translation) @@ -486,6 +531,7 @@ - "↉": [T: "三分之0"] # 0x2189 (en: 'zero thirds', google translation) - "←": [T: "左箭頭"] # 0x2190 (en: 'leftwards arrow', google translation) - "↑": [T: "向上箭頭"] # 0x2191 (en: 'upwards arrow', google translation) + - "→": [T: "右箭頭"] # 0x2192 (en: 'rightwards arrow') - "↓": [T: "向下箭頭"] # 0x2193 (en: 'downwards arrow', google translation) - "↔": [T: "左右雙箭頭"] # 0x2194 (en: 'left right arrow') - "↕": [T: "上下雙箭頭"] # 0x2195 (en: 'up down arrow', google translation) @@ -559,6 +605,7 @@ - "⇏": [t: "帶撇向右粗箭頭"] # 0x21cf (en: 'rightwards double arrow with stroke', google translation) - "⇐": [t: "向左粗箭頭"] # 0x21d0 (en: 'leftwards double arrow', google translation) - "⇑": [t: "向上粗箭頭"] # 0x21d1 (en: 'upwards double arrow', google translation) + - "⇒": [t: "向右粗箭頭"] # 0x21d2 (en: 'rightwards double arrow', google translation) - "⇓": [t: "向下粗箭頭"] # 0x21d3 (en: 'downwards double arrow', google translation) - "⇔": [t: "左右粗箭頭"] # 0x21d4 (en: 'left right double arrow', google translation) - "⇕": [t: "上下粗箭頭"] # 0x21d5 (en: 'up down double arrow', google translation) @@ -604,19 +651,100 @@ - "⇽": [t: "向左開頭箭頭"] # 0x21fd (en: 'leftwards open headed arrow', google translation) - "⇾": [t: "向右開頭箭頭"] # 0x21fe (en: 'rightwards open headed arrow', google translation) - "⇿": [t: "左右開頭箭頭"] # 0x21ff (en: 'left right open headed arrow', google translation) + - "∀": [T: "對所有的"] # 0x2200 (en: 'for all') - "∁": # 0x2201 - test: if: "$Verbosity!='Terse'" then: [T: ""] # (en: 'the', google translation) - T: "補集" # (en: 'complement of') + - "∂": # 0x2202 + - test: + if: "$Verbosity='Terse'" + then: [T: "偏微分"] # (en: 'partial', google translation) + else: [T: "偏微分"] # (en: 'partial derivative') - "∃": [T: "存在"] # 0x2203 (en: 'there exists') - "∄": [T: "不存在"] # 0x2204 (en: 'there does not exist') - "∅": [T: "空集合"] # 0x2205 (en: 'empty set') + - "∆": # 0x2206 + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'the', google translation) + - T: "變化量" # (en: 'laplacian of') - "∇": # 0x2207 - test: if: "$Verbosity!='Terse'" then: [T: ""] # (en: 'the', google translation) - T: "梯度" # (en: 'gradient of') + - "∈": # 0x2208 + - test: + if: "$SpeechStyle != 'ClearSpeak'" + then: [T: "屬於"] # (en: 'an element of', google translation) + # Several options for speaking elements in ClearSpeak -- they split between being inside a set or not and then the option + else_test: + if: "../../self::m:set or ../../../self::m:set" # inside a set + then_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "在"] # (en: 'in', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "成員"] # (en: 'member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "元素"] # (en: 'element of', google translation) + - else: [T: "屬於"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'belonging to') + else_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "是"] # (en: 'is a member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "是一個元素"] # (en: 'is an element of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "在"] # (en: 'is in', google translation) + - else: [T: "屬於"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'belongs to') + - "∉": # 0x2209 + # rule is identical to 0x2208 + - test: + if: "$SpeechStyle != 'ClearSpeak'" + then: [T: "不屬於"] # (en: 'is not an element of', google translation) + # Several options for speaking elements in ClearSpeak -- they split between being inside a set or not and then the option + else_test: + if: "../../self::m:set or ../../../self::m:set" # inside a set + then_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "不在"] # (en: 'not in', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "不是成員"] # (en: 'not member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "不是"] # (en: 'not element of', google translation) + - else: [T: "不屬於"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'not belonging to') + else_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "不是成員"] # (en: 'is not a member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "不是一個元素"] # (en: 'is not an element of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "不在"] # (en: 'is not in', google translation) + - else: [T: "不屬於"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'does not belong to') + - "∊": # 0x220a + - test: + if: "$SpeechStyle != 'ClearSpeak'" + then: [T: "屬於"] # (en: 'is an element of', google translation) + # Several options for speaking elements in ClearSpeak -- they split between being inside a set or not and then the option + else_test: + if: "../../self::m:set or ../../../self::m:set" # inside a set + then_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "在"] # (en: 'in', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "成員"] # (en: 'member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "元素"] # (en: 'element of', google translation) + - else: [T: "屬於"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'belonging to') + else_test: + - if: $ClearSpeak_SetMemberSymbol = 'Auto' or $ClearSpeak_SetMemberSymbol = 'Member' + then: [T: "是"] # (en: 'is a member of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'Element' + then: [T: "是一個元素"] # (en: 'is an element of', google translation) + - else_if: $ClearSpeak_SetMemberSymbol = 'In' + then: [T: "在"] # (en: 'is in', google translation) + - else: [T: "屬於"] # $ClearSpeak_SetMemberSymbol = 'Belongs' (en: 'belongs to') - "∋": [T: "包含"] # 0x220b (en: 'contains the member') - "∌": [T: "不包含"] # 0x220c (en: 'does not contain the member') - "∍": [T: "包含"] # 0x220d (en: 'contains the member') @@ -637,6 +765,11 @@ then: [T: "dot"] # (en: 'dot', google translation) else: [T: "乘"] # (en: 'times') + - "√": # 0x221a + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'the', google translation) + - T: "開平方根" # (en: 'square root of') - "∛": # 0x221b - test: if: "$Verbosity!='Terse'" @@ -647,6 +780,11 @@ if: "$Verbosity!='Terse'" then: [T: ""] # (en: 'the', google translation) - T: "開四次方根" # (en: 'fourth root of') + - "∝": # 0x221d + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is', google translation) + - T: "正比於" # (en: 'proportional to') - "∞": [T: "無限大"] # 0x221e (en: 'infinity') - "∟": [T: "直角"] # 0x221f (en: 'right angle') - "∠": [T: "角"] # 0x2220 (en: 'angle') @@ -654,6 +792,8 @@ - "∢": [T: "球面角"] # 0x2222 (en: 'spherical angle') - "∣": [T: "整除"] # 0x2223 (en: 'divides') - "∤": [T: "不整除"] # 0x2224 (en: 'does not divide') + - "∧": [T: "邏輯與"] # 0x2227 (en: 'and') + - "∨": [T: "邏輯或"] # 0x2228 (en: 'or') - "∩": [T: "交集"] # 0x2229 (en: 'intersection') - "∪": [T: "聯集"] # 0x222a (en: 'union') - "∫": [T: "積分"] # 0x222b (en: 'integral') @@ -667,6 +807,11 @@ - "∳": [T: "逆時針輪廓積分"] # 0x2233 (en: 'anticlockwise contour integral') - "∴": [T: "所以"] # 0x2234 (en: 'therefore') - "∵": [T: "因為"] # 0x2235 (en: 'because') + - "∶": # 0x2236 + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is', google translation) + - T: "比" # (en: 'to') - "∷": [T: "當成"] # 0x2237 (en: 'as') - "∸": [T: "點負號"] # 0x2238 (en: 'dot minus') - "∹": [T: "超出"] # 0x2239 (en: 'has excess compared to') @@ -682,6 +827,11 @@ - T: "同位" # (en: 'homothetic to') - "∼": [T: "波浪符"] # 0x223c (en: 'varies with') - "∽": [T: "反波浪符"] # 0x223d (en: 'reversed tilde') + - "∾": # 0x223e + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is', google translation) + - T: "正無限大" # (en: 'most positive') - "∿": [T: "正弦波型"] # 0x223f (en: 'sine wave') - "≀": [t: "wreath product"] # 0x2240 (en: 'wreath product') - "≁": [t: "not tilde"] # 0x2241 (en: 'not tilde') @@ -783,6 +933,16 @@ then: [T: ""] # (en: 'is', google translation) - T: "測量" # (en: 'measured by') - "≟": [T: "問號等於"] # 0x225f (en: 'has an unknown relationship with') + - "≠": # 0x2260 + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is', google translation) + - T: "不等於" # (en: 'not equal to') + - "≡": # 0x2261 + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is', google translation) + - T: "恆等於" # (en: 'identical to') - "≢": # 0x2262 - test: if: "$Verbosity!='Terse'" @@ -793,6 +953,8 @@ if: "$Verbosity!='Terse'" then: [T: ""] # (en: 'is', google translation) - T: "完全等於" # (en: 'strictly equivalent to') + - "≦": [T: "小於等於"] # 0x2266 (en: 'less than over equal to') + - "≧": [T: "大於等於"] # 0x2267 (en: 'greater than over equal to') - "≨": # 0x2268 - test: if: "$Verbosity!='Terse'" @@ -891,6 +1053,36 @@ - "≿": [T: "後於或等價於"] # 0x227f (en: 'succeeds or is equivalent to') - "⊀": [T: "不先於"] # 0x2280 (en: 'does not precede') - "⊁": [T: "不後於"] # 0x2281 (en: 'does not succeed') + - "⊂": # 0x2282 + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is a', google translation) + - T: "包含於" # (en: 'subset of') + - "⊃": # 0x2283 + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is a', google translation) + - T: "包含" # (en: 'superset of') + - "⊄": # 0x2284 + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is', google translation) + - T: "不包含於" # (en: 'not a subset of') + - "⊅": # 0x2285 + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is', google translation) + - T: "不包含" # (en: 'not a superset of') + - "⊆": # 0x2286 + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is a', google translation) + - T: "包含於或等於" # (en: 'subset of or equal to') + - "⊇": # 0x2287 + - test: + if: "$Verbosity!='Terse'" + then: [T: ""] # (en: 'is a', google translation) + - T: "包含或等於" # (en: 'superset of or equal to') - "⊈": # 0x2288 - test: if: "$Verbosity!='Terse'" @@ -2791,8 +2983,11 @@ - "": [t: "digamma"] # 0xed03 (google translation) - "ϝ": [t: "Diggmma"] # 0x3dd (en: 'digamma') - "": [T: "d"] # 0xed10 (en: 'd', google translation) + - "ⅆ": [T: "d"] # 0x2146 (en: 'd', google translation) - "": [T: "e"] # 0xed11 (en: 'e', google translation) + - "ⅇ": [T: "e"] # 0x2147 (en: 'e', google translation) - "": [T: "i"] # 0xed12 (en: 'i', google translation) + - "ⅈ": [T: "i"] # 0x2148 (en: 'i', google translation) - "": [T: "j"] # 0xed13 (en: 'j', google translation) - "ⅅ": - SPELL: "translate('.', 'ⅅ', 'DD')" # 0xed16, 0x2145 diff --git a/build.rs b/build.rs index b8be2e9a9..a48b26033 100644 --- a/build.rs +++ b/build.rs @@ -151,6 +151,9 @@ fn zip_entry( /// Zip up each language and braille dir /// Note: regional variations (including zh-cn and zh-tw) are zipped together into one zip file fn main() { + println!("cargo::rerun-if-changed=build.rs"); + println!("cargo::rerun-if-changed=Rules"); + // This doesn't work because the build claims OUT_DIR is not defined(?) // let archive = PathBuf::from(concat!(env!("OUT_DIR"),"/rules.zip")); if std::env::var("CARGO_FEATURE_INCLUDE_ZIP").is_ok() { @@ -198,10 +201,5 @@ fn main() { if let Err(e) = archive_zip.finish() { panic!("Error in zip.finish(): {}", e); } - println!("cargo::rerun-if-changed=Rules"); - } else { - // Without include-zip, Rules are loaded at runtime from disk and must not - // re-run this script (or slow the build) on every yaml edit. - println!("cargo::rerun-if-changed=build.rs"); } } diff --git a/docs/index.md b/docs/index.md index 64b82251d..f0e944723 100644 --- a/docs/index.md +++ b/docs/index.md @@ -175,7 +175,7 @@ Translators: * German -- Nazli Andjic, Robert Graf and Paul Libbrecht (IU International University of Applied Sciences) * Indonesian -- Dr. Pinta Deniyanti Sampoerno, M.Si; Dr. Meiliasari, S.Pd., M.Sc; and Ari Hendarno, S.Pd., M.Kom. * Norwegian -- Marthe Gjelstad, National Library of Norway, Kvile -* Russian -- Danil Kostenkov +* Russian (both speech and braille) -- Danil Kostenkov * Spanish -- Noelia Ruiz Martínez (also helped with NVDA add-on development) and María Allo Roldán * Swedish -- Tim Arborealis Lötberg, Swedish Agency for Accessible Media (MTM) and Anders Eklund, SPSM * Vietnamese -- Dang Hoai Phúc and Trang Pham diff --git a/docs/ru/User_guide_for_MathCAT_ru.md b/docs/ru/User_guide_for_MathCAT_ru.md index fec001990..3214c89ac 100644 --- a/docs/ru/User_guide_for_MathCAT_ru.md +++ b/docs/ru/User_guide_for_MathCAT_ru.md @@ -40,7 +40,7 @@ MathCAT можно настроить в соответствии с вашим - Особые потребности: - \[Незрячие.\] Однозначное озвучивание. - Слабовидящие. Более краткое озвучивание. - - Трудности в обучении. Более краткое озвучивание. + - Когнитивные нарушения. Более краткое озвучивание. - Язык: (по умолчанию используется язык программы экранного доступа) - \[Английский (en)\] - Вьетнамский (vi) diff --git a/docs/ru/helpers.md b/docs/ru/helpers.md index c273404ea..be36a6116 100644 --- a/docs/ru/helpers.md +++ b/docs/ru/helpers.md @@ -133,7 +133,7 @@ fn common_fraction_half() { ``` Для русского языка строка `test` будет выглядеть так: ``` - test("ru", "SimpleSpeak", expr, "одна вторая"); + test("fr", "SimpleSpeak", expr, "одна вторая"); ``` После перевода нескольких тестов запустите автоматическую проверку. diff --git a/src/braille.rs b/src/braille.rs index 9aa7a92a3..8def4c87e 100644 --- a/src/braille.rs +++ b/src/braille.rs @@ -895,6 +895,7 @@ static UEB_INDICATOR_REPLACEMENTS: phf::Map<&str, &str> = phf_map! { "1" => "⠰", // Grade 1 symbol "𝟙" => "⠰⠰", // Grade 1 word "L" => "", // Letter left in to assist in locating letters + "A" => "", // Letter accent indicator -- should be followed by accent cells and then "L" for char "D" => "XXX", // German (Deutsche) -- from prefs "G" => "⠨", // Greek "V" => "⠨⠈", // Greek Variants @@ -933,6 +934,24 @@ fn is_letter_number(ch: char) -> bool { matches!(ch, '⠁' | '⠃' | '⠉' | '⠙' | '⠑' | '⠋' | '⠛' | '⠓' | '⠊' | '⠚') } +fn is_braille_char(ch: char) -> bool { + ('\u{2800}'..='\u{28ff}').contains(&ch) +} + +/// After an 'A' accent indicator, skip accent braille cells and return the index of the following 'L'. +/// Returns None if the accented-letter pattern is malformed. +fn index_after_accent_to_l(chars: &[char], after_a: usize) -> Option { + let mut j = after_a; + while j < chars.len() && is_braille_char(chars[j]) { + j += 1; + } + if j < chars.len() && chars[j] == 'L' { + Some(j) + } else { + None + } +} + static SHORT_FORMS: phf::Set<&str> = phf_set! { "L⠁L⠃", "L⠁L⠃L⠧", "L⠁L⠉", "L⠁L⠉L⠗", "L⠁L⠋", "L⠁L⠋L⠝", "L⠁L⠋L⠺", "L⠁L⠛", "L⠁L⠛L⠌", "L⠁L⠇", @@ -950,7 +969,7 @@ static SHORT_FORMS: phf::Set<&str> = phf_set! { }; fn is_letter_prefix(ch: char) -> bool { - matches!(ch, 'B' | 'I' | '𝔹' | 'S' | 'T' | 'D' | 'C' | '𝐶' | '𝑐') + matches!(ch, 'B' | 'I' | '𝔹' | 'S' | 'T' | 'D' | 'C' | '𝐶' | '𝑐' | 'A') } // Trim braille spaces before and after braille indicators @@ -958,7 +977,7 @@ fn is_letter_prefix(ch: char) -> bool { // Note: fraction over is not listed due to example 42(4) which shows a space before the "/" // static ref REMOVE_SPACE_BEFORE_BRAILLE_INDICATORS: Regex = // Regex::new(r"(⠄⠄⠄|⠤⠤⠤)W+([⠼⠸⠪])").unwrap(); -static REPLACE_INDICATORS: LazyLock = LazyLock::new(|| Regex::new(r"([1𝟙SB𝔹TIREDGVHP𝐶𝑐CLMNW𝐖swe,.-—―#ocb])").unwrap()); +static REPLACE_INDICATORS: LazyLock = LazyLock::new(|| Regex::new(r"([1𝟙SB𝔹TIREDGVHP𝐶𝑐CLAMNW𝐖swe,.-—―#ocb])").unwrap()); static COLLAPSE_SPACES: LazyLock = LazyLock::new(|| Regex::new(r"⠀⠀+").unwrap()); /// Transcriber-defined typeforms pulled from prefs (their braille is configurable), used by the @@ -1340,6 +1359,16 @@ fn capitals_to_word_mode(braille: &str) -> String { // Greek letters are a bit exceptional in that the pattern is "CGLx" -- bump 'i' next_non_cap += 1; } + if chars[next_non_cap] == 'A' { + // Accented capital: CA...Lx + match index_after_accent_to_l(&chars, next_non_cap + 1) { + Some(i_l) => next_non_cap = i_l, + None => { + error!("capitals_to_word_mode: internal error: didn't find L after CA in '{}'.", + chars[i..].iter().take(8).collect::()); + } + } + } if chars[next_non_cap] != 'L' { error!("capitals_to_word_mode: internal error: didn't find L after C in '{}'.", chars[i..next_non_cap+2].iter().collect::().as_str()); @@ -1347,6 +1376,25 @@ fn capitals_to_word_mode(braille: &str) -> String { let i_braille_char = next_non_cap + 2; result.push_str(String::from_iter(&chars[i..i_braille_char]).as_str()); i = i_braille_char; + } else if ch == 'A' { + // Lowercase accented letter: A...Lx + if is_word_mode { + result.push('e'); + is_word_mode = false; + } + match index_after_accent_to_l(&chars, i + 1) { + Some(i_l) => { + let i_braille_char = i_l + 2; + result.push_str(String::from_iter(&chars[i..i_braille_char]).as_str()); + i = i_braille_char; + } + None => { + error!("capitals_to_word_mode: internal error: didn't find L after A in '{}'.", + chars[i..].iter().take(8).collect::()); + result.push(ch); + i += 1; + } + } } else if ch == 'L' { // must be lowercase -- uppercase consumed above // assert!(LETTERS.contains(&unhighlight(chars[i+1]))); not true for other alphabets if is_word_mode { @@ -1561,15 +1609,23 @@ fn remove_unneeded_mode_changes(raw_braille: &str, start_mode: UEB_Mode, start_d match ch { 'L' => { // note: be aware of '#' case for Numeric because '1' might already be generated - // let prev_ch = if i > 1 {chars[i-1]} else {'1'}; // '1' -- anything beside ',' or '.' - // if duration == UEB_Duration::Symbol || - // ( ",. ".contains(prev_ch) && LETTER_NUMBERS.contains(&unhighlight(chars[i+1])) ) { - // result.push('1'); // need to retain grade 1 indicator (RUEB 6.5.2) - // } // let the default case handle pushing on the chars for the letter result.push(ch); i += 1; }, + 'A' => { + // Accented letter: keep A...Lx together so accent cells don't end G1 symbol mode + match index_after_accent_to_l(&chars, i + 1) { + Some(i_l) => { + result.extend(chars[i..i_l + 2].iter().copied()); // A + accents + L + letter + i = i_l + 2; + } + None => { + result.push(ch); + i += 1; + } + } + }, '1' | '𝟙' => { assert!(ch == '1' || duration != UEB_Duration::Symbol); // if '𝟙', should be Word or Passage duration // nothing to do -- let the default case handle the following chars @@ -1628,14 +1684,29 @@ fn remove_unneeded_mode_changes(raw_braille: &str, start_mode: UEB_Mode, start_d i += right_matched_chars.len(); }, 'C' => { - // Want 'C' before 'L'; Could be CC for word cap -- if so, eat it and move on + // Want 'C' before 'L' (or 'CA...L' / 'CGL'). Could be CC for word cap -- if so, eat it and move on // Note: guaranteed that there is a char after the 'C', so chars[i+1] is safe if chars[i+1] == 'C' { cap_word_mode = true; i += 1; } else { - let is_greek = chars[i+1] == 'G'; - let (is_alone, right_matched_chars, n_letters) = stands_alone(&chars, if is_greek {i+2} else {i+1}); + let mut letter_idx = i + 1; + let is_greek = chars[letter_idx] == 'G'; + if is_greek { + letter_idx += 1; + } + if letter_idx < chars.len() && chars[letter_idx] == 'A' { + match index_after_accent_to_l(&chars, letter_idx + 1) { + Some(i_l) => letter_idx = i_l, + None => { + error!("Internal error: 'CA' without L at index={i} in '{raw_braille}'"); + result.push('C'); + i += 1; + continue; + } + } + } + let (is_alone, right_matched_chars, n_letters) = stands_alone(&chars, letter_idx); // GTM 1.2.1 says we only need to use G1 for single letters or sequences that are a shortform (e.g, "ab") if is_alone && (n_letters == 1 || is_short_form(&right_matched_chars[..2*n_letters])) { // debug!(" is_alone -- pushing '1'"); @@ -1648,12 +1719,33 @@ fn remove_unneeded_mode_changes(raw_braille: &str, start_mode: UEB_Mode, start_d result.push('C'); if is_greek { result.push('G'); - i += 1; } start_g2_letter = Some(i); - // debug!(" pushing 'C' + {:?}", right_matched_chars); + // right_matched starts at A or L (not including C/G) right_matched_chars.iter().for_each(|&ch| result.push(ch)); - i += 1 + right_matched_chars.len(); + i += 1 + if is_greek {1} else {0} + right_matched_chars.len(); + } + }, + 'A' => { + // Accented lowercase letter: A...Lx + match index_after_accent_to_l(&chars, i + 1) { + Some(i_l) => { + if start_g2_letter.is_none() { + start_g2_letter = Some(i); + } + let (is_alone, right_matched_chars, n_letters) = stands_alone(&chars, i_l); + if is_alone && (n_letters == 1 || is_short_form(&right_matched_chars[..2*n_letters])) { + result.push('1'); + mode = UEB_Mode::Grade1; + } + right_matched_chars.iter().for_each(|&ch| result.push(ch)); + i += right_matched_chars.len(); + } + None => { + error!("Internal error: 'A' without L at index={i} in '{raw_braille}'"); + result.push(ch); + i += 1; + } } }, '1' => { @@ -1746,8 +1838,21 @@ fn stands_alone(chars: &[char], i: usize) -> (bool, &[char], usize) { // we scan forward and check the conditions for "standing-alone" assert_eq!(chars[i], 'L', "'stands_alone' starts with non 'L'"); // debug!("stands_alone: i={}, chars: {:?}", i, chars); - if !left_side_stands_alone(&chars[0..i]) { - return (false, &chars[i..i+2], 0); + // Exclude accent prefix A... immediately before this L (part of the same letter) + let mut letter_start = i; + let mut left_end = i; + if left_end > 0 { + let mut j = left_end; + while j > 0 && is_braille_char(chars[j - 1]) { + j -= 1; + } + if j > 0 && chars[j - 1] == 'A' { + letter_start = j - 1; + left_end = j - 1; + } + } + if !left_side_stands_alone(&chars[0..left_end]) { + return (false, &chars[letter_start..i+2], 0); } let (mut is_alone, n_letters, n_right_matched) = right_side_stands_alone(&chars[i+2..]); @@ -1759,7 +1864,8 @@ fn stands_alone(chars: &[char], i: usize) -> (bool, &[char], usize) { is_alone = false; } } - return (is_alone, &chars[i..i+2+n_right_matched], n_letters); + // Include any A... prefix so callers emit the full accented letter + return (is_alone, &chars[letter_start..i+2+n_right_matched], n_letters); /// chars before 'L' fn left_side_stands_alone(chars: &[char]) -> bool { @@ -1803,6 +1909,17 @@ fn stands_alone(chars: &[char], i: usize) -> (bool, &[char], usize) { if !intervening_chars_mode && ch == 'L' { n_letters += 1; i += 1; // ignore 'Lx' and also ignore 'ox' + } else if !intervening_chars_mode && ch == 'A' { + // Accented letter A...Lx counts as one letter + match index_after_accent_to_l(chars, i + 1) { + Some(i_l) => { + n_letters += 1; + i = i_l + 1; // now at letter braille; loop end advances past it + } + None => { + return (false, n_letters, i); + } + } } else if ch == 'c' || ch == 'b' { i += 1; // ignore 'Lx' and also ignore 'ox' } else if is_right_intervening_char(ch) { diff --git a/src/canonicalize.rs b/src/canonicalize.rs index 380c4de0c..a93ce3b44 100644 --- a/src/canonicalize.rs +++ b/src/canonicalize.rs @@ -5535,10 +5535,9 @@ mod canonicalize_tests { } #[test] - #[ignore] // need to figure out a test for this ("|" should have a precedence around ":" since that is an alternative notation for "such that", but "∣" is higher precedence) fn vertical_bar_divides() -> Result<()> { let test_str = " - x+y |12 + x+y |12 "; let target_str = " @@ -5547,7 +5546,7 @@ mod canonicalize_tests { + y - + | 12 "; @@ -6912,7 +6911,7 @@ mod canonicalize_tests { j k - l + l "; diff --git a/src/chemistry.rs b/src/chemistry.rs index 64656dca8..5f4375df3 100644 --- a/src/chemistry.rs +++ b/src/chemistry.rs @@ -2146,7 +2146,6 @@ mod chem_tests { } #[test] - #[ignore] // It would be good to say "not chemistry" for this, but there aren't rules for that at the moment fn test_water_bond() -> Result<()> { return chem_test(|| { let test11 = r#"H2O=O"#; diff --git a/src/interface.rs b/src/interface.rs index 317d7ce28..502a31f3a 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1386,11 +1386,11 @@ mod tests { set_mathml(good_mathml)?; let bad_mathml = "&xabc;"; assert!(set_mathml(bad_mathml).is_err()); - assert!(get_spoken_text()? == ""); + assert!(get_spoken_text()?.is_empty()); set_mathml(good_mathml)?; let bad_mathml = "garbage"; assert!(set_mathml(bad_mathml).is_err()); - assert!(get_spoken_text()? == ""); + assert!(get_spoken_text()?.is_empty()); return Ok( () ); }); } @@ -1417,7 +1417,7 @@ mod tests { x-y "; - set_mathml(&expr)?; + set_mathml(expr)?; let speech = get_spoken_text()?; // Rule-generated SSML must pass through verbatim (not XML-entity-encoded). assert!(!speech.contains("<")); diff --git a/src/navigate.rs b/src/navigate.rs index 6fb170d52..4aa65b33b 100644 --- a/src/navigate.rs +++ b/src/navigate.rs @@ -1009,10 +1009,10 @@ mod tests { match do_navigate_command_string(mathml, command) { Err(e) => { panic!("\nStarting at '{}', '{} failed.\n{}", - start_id, command, &crate::interface::errors_to_string(&e)) + start_id, command, crate::interface::errors_to_string(&e)) }, Ok(nav_speech) => { - let nav_speech = nav_speech.trim_end_matches(&[' ', ',', ';']); + let nav_speech = nav_speech.trim_end_matches([' ', ',', ';']); // debug!("Full speech: {}", nav_speech); if !result_id.is_empty() { let (id, _) = nav_stack.borrow().get_navigation_mathml_id(mathml); diff --git a/src/prefs.rs b/src/prefs.rs index d36cde237..f51fd91fe 100644 --- a/src/prefs.rs +++ b/src/prefs.rs @@ -930,6 +930,54 @@ mod tests { return stripped_path } + struct TestRulesDir { + path: PathBuf, + } + + impl TestRulesDir { + fn path(&self) -> &Path { + return &self.path; + } + } + + impl Drop for TestRulesDir { + fn drop(&mut self) { + let _ = std::fs::remove_dir_all(&self.path); + } + } + + fn copy_dir_recursive(from: &Path, to: &Path) { + std::fs::create_dir_all(to).unwrap(); + for entry in std::fs::read_dir(from).unwrap() { + let entry = entry.unwrap(); + let file_type = entry.file_type().unwrap(); + let target = to.join(entry.file_name()); + if file_type.is_dir() { + copy_dir_recursive(&entry.path(), &target); + } else { + std::fs::copy(entry.path(), target).unwrap(); + } + } + } + + fn test_rules_dir_with_prefs() -> TestRulesDir { + let path = std::env::temp_dir().join(format!("mathcat-prefs-test-{}", fastrand::u64(..))); + std::fs::create_dir_all(&path).unwrap(); + + let source_rules = abs_rules_dir_path(); + let prefs = std::fs::read_to_string(source_rules.join("prefs.yaml")).unwrap() + .replace("Language: Auto", "Language: zz"); + std::fs::write(path.join("prefs.yaml"), prefs).unwrap(); + std::fs::copy(source_rules.join("intent.yaml"), path.join("intent.yaml")).unwrap(); + std::fs::copy(source_rules.join("definitions.yaml"), path.join("definitions.yaml")).unwrap(); + + copy_dir_recursive(&source_rules.join("Languages").join("en"), &path.join("Languages").join("en")); + copy_dir_recursive(&source_rules.join("Languages").join("zz"), &path.join("Languages").join("zz")); + copy_dir_recursive(&source_rules.join("Braille").join("Nemeth"), &path.join("Braille").join("Nemeth")); + + return TestRulesDir { path }; + } + fn speech_rule_files_cache_is_empty() -> bool { crate::speech::SPEECH_RULES.with(|rules| rules.borrow().rule_files_cache_is_empty()) } @@ -1230,124 +1278,36 @@ cfg_if::cfg_if! {if #[cfg(not(feature = "include-zip"))] { }); } - /// #262: MathCAT must notice when a rule file on disk changes and reload it. - /// This copies the rule files it needs (`en`, `zz`, and `Nemeth`) into a uniquely-named - /// temp dir, so the test can freely modify files and run in parallel without touching the - /// real Rules dir or the user's prefs file. All global state is restored on the way out. #[test] fn test_up_to_date() { use std::fs; use std::thread::sleep; use std::time::Duration; - use crate::interface; - use tempfile::Builder; - - /// Recursively copy `src` into `dst` (creating `dst`). - fn copy_dir_all(src: &Path, dst: &Path) { - fs::create_dir_all(dst).unwrap(); - for entry in fs::read_dir(src).unwrap() { - let entry = entry.unwrap(); - let from = entry.path(); - let to = dst.join(entry.file_name()); - if from.is_dir() { - copy_dir_all(&from, &to); - } else { - fs::copy(&from, &to).unwrap(); - } - } - } - - // Restore all thread-local global state (rules dir, prefs, caches) when the test exits, - // even on a panic, so other tests sharing this thread are unaffected. - struct RestoreGuard; - impl Drop for RestoreGuard { - fn drop(&mut self) { - let _ = interface::set_preference("CheckRuleFiles", "Prefs"); - PREF_MANAGER.with(|pref_manager| { - let mut pref_manager = pref_manager.borrow_mut(); - // Force a full re-read: the stale temp paths would otherwise fool the up-to-date check. - pref_manager.sys_prefs_file = None; - pref_manager.user_prefs_file = None; - let _ = pref_manager.initialize(abs_rules_dir_path()); - }); - } - } - - let temp_dir = Builder::new() - .prefix("mathcat-up-to-date-") - .tempdir() - .expect("create temp rules dir"); - let temp_rules_dir = temp_dir.path(); - let real_rules_dir = abs_rules_dir_path(); - - // Only the "en" (fallback), "zz" (test language), and "Nemeth" (braille) rules are needed, - // plus the top-level files they include (incl. the full system prefs.yaml — partial YAML - // left keys like DecimalSeparator missing and crashed on CI with no user AppData prefs). - copy_dir_all(&real_rules_dir.join("Languages/en"), &temp_rules_dir.join("Languages/en")); - copy_dir_all(&real_rules_dir.join("Languages/zz"), &temp_rules_dir.join("Languages/zz")); - copy_dir_all(&real_rules_dir.join("Intent"), &temp_rules_dir.join("Intent")); - copy_dir_all(&real_rules_dir.join("Braille/Nemeth"), &temp_rules_dir.join("Braille/Nemeth")); - fs::copy(real_rules_dir.join("definitions.yaml"), temp_rules_dir.join("definitions.yaml")).unwrap(); - fs::copy(real_rules_dir.join("intent.yaml"), temp_rules_dir.join("intent.yaml")).unwrap(); - fs::copy(real_rules_dir.join("Braille/definitions.yaml"), temp_rules_dir.join("Braille/definitions.yaml")).unwrap(); - fs::copy(real_rules_dir.join("prefs.yaml"), temp_rules_dir.join("prefs.yaml")).unwrap(); - // Override only what this test needs (rest of prefs.yaml keeps defaults like DecimalSeparator). - let prefs_path = temp_rules_dir.join("prefs.yaml"); - let prefs_text = fs::read_to_string(&prefs_path).unwrap() - .replace("Language: Auto", "Language: zz"); - assert!(prefs_text.contains("Language: zz"), "failed to set Language: zz in copied prefs.yaml"); - fs::write(&prefs_path, prefs_text).unwrap(); - - interface::set_rules_dir(temp_rules_dir.to_str().unwrap()).unwrap(); - let _restore = RestoreGuard; - // Pin in memory so a user prefs.yaml in the config dir cannot override Language/SpeechStyle - // (and so SpeechStyle stays ClearSpeak until we change it for the reload check). - PREF_MANAGER.with(|pref_manager| { - let mut pref_manager = pref_manager.borrow_mut(); - pref_manager.set_string_pref("Language", "zz").unwrap(); - pref_manager.set_string_pref("SpeechStyle", "ClearSpeak").unwrap(); - pref_manager.set_string_pref("BrailleCode", "Nemeth").unwrap(); - assert_eq!(rel_path(&pref_manager.rules_dir, pref_manager.speech.as_path()), PathBuf::from("Languages/zz/ClearSpeak_Rules.yaml")); - assert_ne!(&pref_manager.pref_to_string("DecimalSeparator"), NO_PREFERENCE, - "DecimalSeparator missing — system prefs.yaml incomplete"); - }); - // "All" makes MathCAT check rule-file timestamps (not just prefs), so content edits are noticed. - interface::set_preference("CheckRuleFiles", "All").unwrap(); - - // ---- speech rule file: change its content and confirm the new speech is used ---- - interface::set_mathml("+10").unwrap(); - assert_eq!(interface::get_spoken_text().unwrap(), "ClearSpeak positive from zz 10"); - - let speech_rule_file = temp_rules_dir.join("Languages/zz/ClearSpeak_Rules.yaml"); - let speech_contents = fs::read_to_string(&speech_rule_file).unwrap(); - fs::write(&speech_rule_file, speech_contents.replace("ClearSpeak positive from zz", "changed positive from zz")).unwrap(); - sleep(Duration::from_millis(5)); // make sure the modification time changes enough to be recognized - assert_eq!(interface::get_spoken_text().unwrap(), "changed positive from zz 10", - "modified speech rule file was not reloaded"); - - // ---- changing SpeechStyle must not change the language (still "zz") ---- - interface::set_preference("SpeechStyle", "SimpleSpeak").unwrap(); - PREF_MANAGER.with(|pref_manager| { - let pref_manager = pref_manager.borrow(); - assert_eq!(&pref_manager.pref_to_string("Language"), "zz", "changing SpeechStyle changed the language"); - assert_eq!(rel_path(&pref_manager.rules_dir, pref_manager.speech.as_path()), PathBuf::from("Languages/zz/SimpleSpeak_Rules.yaml")); - }); - // the (unmodified) zz SimpleSpeak rules produce their own distinctive text - assert_eq!(interface::get_spoken_text().unwrap(), "SimpleSpeak positive from zz 10"); - - // ---- braille (Nemeth) unicode file: change a char and confirm the new braille is used ---- - let braille_before = interface::get_braille("").unwrap(); - let unicode_file = temp_rules_dir.join("Braille/Nemeth/unicode.yaml"); - let unicode_contents = fs::read_to_string(&unicode_file).unwrap(); - // remap the digit '1' to the (distinctive) full braille cell '⠿' - let changed_unicode = unicode_contents.replace("\"1\": [t: \"N⠂\"]", "\"1\": [t: \"N⠿\"]"); - assert_ne!(changed_unicode, unicode_contents, "expected to find the Nemeth mapping for '1'"); - fs::write(&unicode_file, changed_unicode).unwrap(); - sleep(Duration::from_millis(5)); - let braille_after = interface::get_braille("").unwrap(); - assert_ne!(braille_after, braille_before, "modified Nemeth unicode file was not reloaded"); - assert!(braille_after.contains('⠿'), "new Nemeth mapping for '1' not reflected in braille: {braille_after}"); + let test_rules = test_rules_dir_with_prefs(); + let prefs_file = test_rules.path().join("prefs.yaml"); + + let mut pref_manager = PreferenceManager::default(); + pref_manager.set_rules_dir(test_rules.path()).unwrap(); + pref_manager.user_prefs_file = Some(crate::speech::FileAndTime::new_with_time(test_rules.path().join("no-user-prefs.yaml"))); + pref_manager.set_preference_files().unwrap(); + pref_manager.api_prefs.prefs.insert("Language".to_string(), Yaml::String("zz".to_string())); + pref_manager.api_prefs.prefs.insert("SpeechStyle".to_string(), Yaml::String("ClearSpeak".to_string())); + assert_eq!(&pref_manager.pref_to_string("Language"), "zz"); + pref_manager.set_all_files(test_rules.path()).unwrap(); + + assert_eq!(&pref_manager.pref_to_string("SpeechStyle"), "ClearSpeak"); + assert_eq!(rel_path(&pref_manager.rules_dir, pref_manager.speech.as_path()), PathBuf::from("Languages/zz/ClearSpeak_Rules.yaml")); + + let changed_contents = fs::read_to_string(&prefs_file).unwrap() + .replace("SpeechStyle: ClearSpeak", "SpeechStyle: SimpleSpeak"); + fs::write(&prefs_file, changed_contents).unwrap(); + sleep(Duration::from_millis(5)); // make sure the time changes enough to be recognized + + pref_manager.set_preference_files().unwrap(); + pref_manager.api_prefs.prefs.remove("SpeechStyle"); + assert_eq!(&pref_manager.pref_to_string("SpeechStyle"), "SimpleSpeak"); + assert_eq!(rel_path(&pref_manager.rules_dir, pref_manager.speech.as_path()), PathBuf::from("Languages/zz/SimpleSpeak_Rules.yaml")); } }} diff --git a/src/speech.rs b/src/speech.rs index dc152e3da..8b74d91f8 100644 --- a/src/speech.rs +++ b/src/speech.rs @@ -3027,7 +3027,8 @@ cfg_if::cfg_if! {if #[cfg(not(feature = "include-zip"))] { let start_main_file = rules.borrow().unicode_short_files.borrow().ft[0].clone(); // open the file, read all the contents, then write them back so the time changes - let contents = std::fs::read(&start_main_file.file).unwrap_or_else(|_| panic!("Failed to read file {} during test", start_main_file.file.to_string_lossy())); + let contents = std::fs::read(&start_main_file.file) + .unwrap_or_else(|_| panic!("Failed to read file {} during test", start_main_file.file.to_string_lossy())); std::fs::write(start_main_file.file, contents).unwrap(); std::thread::sleep(Duration::from_millis(5)); // pause a little to make sure the time changes diff --git a/tests/Languages/de/ClearSpeak/mfrac.rs b/tests/Languages/de/ClearSpeak/mfrac.rs index f5291c9e9..0081e0197 100644 --- a/tests/Languages/de/ClearSpeak/mfrac.rs +++ b/tests/Languages/de/ClearSpeak/mfrac.rs @@ -86,7 +86,7 @@ fn frac_with_units() -> Result<()> { "; - test("de", "ClearSpeak", expr, "62 meiles pro stunde")?; + test("de", "ClearSpeak", expr, "62 meilen pro stunde")?; return Ok(()); } diff --git a/tests/Languages/de/ClearSpeak/sets.rs b/tests/Languages/de/ClearSpeak/sets.rs index 2b7ad5cde..e8911f33f 100644 --- a/tests/Languages/de/ClearSpeak/sets.rs +++ b/tests/Languages/de/ClearSpeak/sets.rs @@ -205,7 +205,7 @@ fn set_with_colon() -> Result<()> { let expr = " { x:x>2 } "; - test("de", "ClearSpeak", expr, "die Menge alle x so dass x ist größer als 2")?; + test("de", "ClearSpeak", expr, "die Menge aller x so dass x ist größer als 2")?; return Ok(()); } @@ -215,7 +215,7 @@ fn set_with_bar() -> Result<()> { let expr = " { x|x>2 } "; - test("de", "ClearSpeak", expr, "die Menge alle x so dass x ist größer als 2")?; + test("de", "ClearSpeak", expr, "die Menge aller x so dass x ist größer als 2")?; return Ok(()); } @@ -263,7 +263,7 @@ fn complicated_set_with_colon() -> Result<()> { 7 } "; - test("de", "ClearSpeak", expr, "die Menge alle x in die ganzen zahlen so dass 2 ist kleiner als x ist kleiner als 7")?; + test("de", "ClearSpeak", expr, "die Menge aller x in den ganzen zahlen so dass 2 ist kleiner als x ist kleiner als 7")?; return Ok(()); } @@ -279,7 +279,7 @@ fn complicated_set_with_mtext() -> Result<()> { } "; test("de", "ClearSpeak", expr, - "die Menge alle x in die natürlichen zahlen so dass x is an even number")?; + "die Menge aller x in den natürlichen zahlen so dass x is an even number")?; return Ok(()); } @@ -299,7 +299,7 @@ fn set_with_bar_member() -> Result<()> { } "; test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Member", - expr, "die Menge alle x element von die ganzen zahlen so dass x ist größer als 5")?; + expr, "die Menge aller x element von die ganzen zahlen so dass x ist größer als 5")?; return Ok(()); } @@ -348,7 +348,7 @@ fn set_with_bar_element() -> Result<()> { } "; test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Element", - expr, "die Menge alle x element von die ganzen zahlen so dass x ist größer als 5")?; + expr, "die Menge aller x element von die ganzen zahlen so dass x ist größer als 5")?; return Ok(()); } @@ -396,7 +396,7 @@ fn set_with_bar_in() -> Result<()> { } "; test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "In", - expr, "die Menge alle x in die ganzen zahlen so dass x ist größer als 5")?; + expr, "die Menge aller x in den ganzen zahlen so dass x ist größer als 5")?; return Ok(()); } @@ -407,7 +407,7 @@ fn element_alone_in() -> Result<()> { 3+2i "; test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "In", - expr, "3 plus 2 i, ist nicht in die reellen zahlen")?; + expr, "3 plus 2 i, ist nicht in den reellen zahlen")?; return Ok(()); } @@ -425,7 +425,7 @@ fn element_under_sum_in() -> Result<()> { "; test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "In", - expr, "die summe durch i ist in die ganzen zahlen von; der bruch mit zähler 1; und nenner i quadrat")?; + expr, "die summe durch i ist in den ganzen zahlen von; der bruch mit zähler 1; und nenner i quadrat")?; return Ok(()); } @@ -444,7 +444,7 @@ fn set_with_bar_belongs() -> Result<()> { } "; test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Belongs", - expr, "die Menge alle x element von die ganzen zahlen so dass x ist größer als 5")?; + expr, "die Menge aller x element von die ganzen zahlen so dass x ist größer als 5")?; return Ok(()); } @@ -524,7 +524,7 @@ fn silent_bracket() -> Result<()> { {x|x>2} "; test_ClearSpeak("de", "ClearSpeak_Sets", "SilentBracket", expr, - "die Menge alle x so dass x ist größer als 2")?; + "die Menge aller x so dass x ist größer als 2")?; return Ok(()); } diff --git a/tests/Languages/de/ClearSpeak/symbols_and_adornments.rs b/tests/Languages/de/ClearSpeak/symbols_and_adornments.rs index b52b0a253..ac1f7c2f3 100644 --- a/tests/Languages/de/ClearSpeak/symbols_and_adornments.rs +++ b/tests/Languages/de/ClearSpeak/symbols_and_adornments.rs @@ -39,6 +39,16 @@ fn quotation_mark() -> Result<()> { Ok(()) } +#[test] +fn absolute_value_end_regression() -> Result<()> { + let expr = "|x+1|"; + test_prefs("de", "ClearSpeak", vec![ + ("Verbosity", "Terse"), + ("ClearSpeak_AbsoluteValue", "AbsEnd"), + ], expr, "Betrag von x plus 1, ende Betrag")?; + Ok(()) +} + #[test] fn ellipses_auto_start() -> Result<()> { let expr = " @@ -227,7 +237,7 @@ fn vertical_line_set() -> Result<()> { } "; test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Auto", expr, - "die Menge alle x so dass x ist größer als 0")?; + "die Menge aller x so dass x ist größer als 0")?; return Ok(()); } @@ -247,7 +257,7 @@ fn vertical_line_set_such_that() -> Result<()> { } "; test_ClearSpeak("de", "ClearSpeak_VerticalLine", "SuchThat", expr, - "die Menge alle x so dass x ist größer als 0")?; + "die Menge aller x so dass x ist größer als 0")?; return Ok(()); } @@ -267,7 +277,7 @@ fn vertical_line_set_given() -> Result<()> { "; // the rules for set will override all the options -- ClearSpeak spec should be clarified test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Given", expr, - "die Menge alle x so dass x ist größer als 0")?; + "die Menge aller x so dass x ist größer als 0")?; return Ok(()); } @@ -290,7 +300,7 @@ fn vertical_line_set_and_abs() -> Result<()> { } "; test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Auto", expr, - "die Menge alle x so dass der Betrag von x; ist größer als 2")?; + "die Menge aller x so dass der Betrag von x; ist größer als 2")?; return Ok(()); } diff --git a/tests/Languages/de/units.rs b/tests/Languages/de/units.rs index 620c33e5b..fffd6ac5a 100644 --- a/tests/Languages/de/units.rs +++ b/tests/Languages/de/units.rs @@ -40,7 +40,7 @@ fn prefix_sweep() -> Result<()> { qg "#; test("de", "SimpleSpeak", expr, - "quetta-gramms, komma ronna-gramms, komma yotta-gramms, komma zetta-gramms, komma exa-gramms, komma peta-gramms, komma tera-gramms, komma giga-gramms, komma mega-gramms, komma kilo-gramms, komma hekto-gramms, komma deka-gramms, komma dezi-gramms, komma zenti-gramms, komma milli-gramms, komma mikro-gramms, komma nano-gramms, komma piko-gramms, komma femto-gramms, komma atto-gramms, komma zepto-gramms, komma yocto-gramms, komma ronto-gramms, komma quecto-gramms")?; + "quetta-gramm, komma ronna-gramm, komma yotta-gramm, komma zetta-gramm, komma exa-gramm, komma peta-gramm, komma tera-gramm, komma giga-gramm, komma mega-gramm, komma kilo-gramm, komma hekto-gramm, komma deka-gramm, komma dezi-gramm, komma zenti-gramm, komma milli-gramm, komma mikro-gramm, komma nano-gramm, komma piko-gramm, komma femto-gramm, komma atto-gramm, komma zepto-gramm, komma yocto-gramm, komma ronto-gramm, komma quecto-gramm")?; return Ok(()); } @@ -61,11 +61,48 @@ fn si_base() -> Result<()> { 1sec,2sec "#; test("de", "SimpleSpeak", expr, - "1 ampere, komma 2 amperes, komma 1 candela, komma 2 candelas, komma 1 kelvin, komma 2 kelvins, komma 1 kelvin, komma 2 kelvins, komma 1 gramm komma 2 gramms, komma 1 meter komma 2 meters, komma 1 mol komma 2 mols, komma 1 sekunde, komma 2 sekundes, komma 1 sekunde, komma 2 sekundes, komma 1 sekunde, komma 2 sekundes, komma 1 sekunde, komma 2 sekundes")?; + "1 ampere, komma 2 ampere, komma 1 candela, komma 2 candela, komma 1 kelvin, komma 2 kelvin, komma 1 kelvin, komma 2 kelvin, komma 1 gramm komma 2 gramm, komma 1 meter komma 2 meter, komma 1 mol komma 2 mol, komma 1 sekunde, komma 2 sekunden, komma 1 sekunde, komma 2 sekunden, komma 1 sekunde, komma 2 sekunden, komma 1 sekunde, komma 2 sekunden")?; return Ok(()); } +#[test] +fn si_unit_plural_regression() -> Result<()> { + let expr = r#" + 2kg, + 2°C, + 2s + "#; + test("de", "ClearSpeak", expr, + "2 kilo-gramm, komma 2 grad celsius, komma 2 sekunden")?; + Ok(()) +} + +#[test] +fn english_rute_plural_regression() -> Result<()> { + let expr = r#" + 1rd, + 2rd + "#; + test("de", "SimpleSpeak", expr, "1 rute komma 2 ruten")?; + Ok(()) +} + +#[test] +fn non_si_unit_plural_regression() -> Result<()> { + let expr = r#" + 1h,2h, + 1d,2d, + 1w,2w, + 1pc,2pc, + 1ha,2ha, + 1Kib,2Kib + "#; + test("de", "SimpleSpeak", expr, + "1 stunde, komma 2 stunden, komma 1 tag komma 2 tage, komma 1 woche komma 2 wochen, komma 1 parsec, komma 2 parsec, komma 1 hektar, komma 2 hektar, komma 1 kibi-bit, komma 2 kibi-bit")?; + Ok(()) +} + /* #[test] fn si_base_with_prefixes() -> Result<()> { @@ -472,4 +509,4 @@ fn test_mtext_inference() -> Result<()> { } - */ \ No newline at end of file + */ diff --git a/tests/Languages/en/mtable.rs b/tests/Languages/en/mtable.rs index cbd2a5275..e6952cf51 100644 --- a/tests/Languages/en/mtable.rs +++ b/tests/Languages/en/mtable.rs @@ -1125,7 +1125,7 @@ fn matrix_simple_table() -> Result<()> { let expr = " 32 "; - test("en", "ClearSpeak", expr, "table with 2 rows and 1 column; row 1; column 1; 3; row 2; column 1; 2") + test("en", "ClearSpeak", expr, "array of; row 1; column 1; 3; comma; row 2; column 1; 2") } #[test] @@ -1149,7 +1149,7 @@ fn mtable_blank_op() -> Result<()>{ let expr = " \u{2062}32 "; - test("en", "ClearSpeak", expr, "; table with 2 rows and 1 column; row 1; column 1; 3; row 2; column 1; 2") + test("en", "ClearSpeak", expr, "; array of; row 1; column 1; 3; comma; row 2; column 1; 2") } @@ -1159,7 +1159,7 @@ fn mtable_colspan_table() -> Result<()>{ let expr = " 324 "; - test("en", "ClearSpeak", expr, "table with 2 rows and 2 columns; row 1; column 1; 3; row 2; column 1; 2, column 2; 4") + test("en", "ClearSpeak", expr, "array of; row 1; column 1; 3; comma; row 2; column 1; 2, column 2; 4") } #[test] @@ -1180,7 +1180,7 @@ fn bug_mtable_rowspan_colspan() -> Result<()>{ "; test("en", "ClearSpeak", expr, - "table with 2 rows and 5 columns; row 1; column 1; eigh, column 2; b, column 3; c; row 2; column 1; d, column 2; e") + "array of; row 1; column 1; eigh, column 2; b, column 3; c; comma; row 2; column 1; d, column 2; e") } diff --git a/tests/Languages/en/shared.rs b/tests/Languages/en/shared.rs index b67126fd8..cf53eed5c 100644 --- a/tests/Languages/en/shared.rs +++ b/tests/Languages/en/shared.rs @@ -22,7 +22,7 @@ fn modified_vars() -> Result<()> { "; test("en", "SimpleSpeak", expr, "eigh grave, b tilde, c breve, b check, c grave; plus \ - r check, plus; x dot, y dot, z double dot, u triple dot, v quadruple dot; plus x hat, plus vector t")?; + r check plus; x dot, y dot, z double dot, u triple dot, v quadruple dot; plus x hat, plus vector t")?; return Ok(()); } @@ -337,7 +337,6 @@ fn ignore_comma() -> Result<()> { } #[test] -#[ignore] // issue #14 fn ignore_period_and_space() -> Result<()> { // from https://en.wikipedia.org/wiki/Probability let expr = " @@ -373,7 +372,7 @@ fn ignore_period_and_space() -> Result<()> { "; - test("en", "ClearSpeak", expr, "cap p, open paren, cap eigh divides cap b, close paren; is equal to; the fraction with numerator; cap p, open paren, cap eigh intersection cap b; close paren; and denominator cap p of cap b")?; + test("en", "ClearSpeak", expr, "cap p, open paren, cap eigh divides cap b, close paren; is equal to; the fraction with numerator; cap p, open paren, cap eigh intersection cap b; close paren; and denominator cap p of cap b; dot")?; return Ok(()); } @@ -415,7 +414,7 @@ fn dots() -> Result<()> { x..+ x... "; - test("en", "SimpleSpeak",expr, "x dot, plus x double dot, plus x triple dot")?; + test("en", "SimpleSpeak",expr, "x dot, plus x .., plus x ...")?; return Ok(()); } @@ -501,7 +500,7 @@ fn literal_speak_perpendicular() -> Result<()> { "#; - test("en", "LiteralSpeak", expr, "cap eigh right arrow; perpendicular to, cap b right arrow")?; + test("en", "LiteralSpeak", expr, "cap eigh right arrow, perpendicular to, cap b right arrow")?; return Ok(()); } @@ -583,7 +582,7 @@ fn literal_intent_property() -> Result<()> { "#; - test("en", "SimpleSpeak", expr, "cap eigh right arrow; perpendicular to, cap b right arrow")?; + test("en", "SimpleSpeak", expr, "cap eigh right arrow, perpendicular to, cap b right arrow")?; return Ok(()); } diff --git a/tests/Languages/fi/shared.rs b/tests/Languages/fi/shared.rs index fed99464f..4f3e7dfd2 100644 --- a/tests/Languages/fi/shared.rs +++ b/tests/Languages/fi/shared.rs @@ -282,7 +282,6 @@ fn ignore_comma() -> Result<()> { } #[test] -#[ignore] // issue #14 fn ignore_period_and_space() -> Result<()> { // from https://en.wikipedia.org/wiki/Probability let expr = " @@ -318,7 +317,7 @@ fn ignore_period_and_space() -> Result<()> { "; - test("fi", "ClearSpeak", expr, "phi of x is equal to; c, e raised to the negative h squared x squared power")?; + test("fi", "ClearSpeak", expr, "iso p, auki sulku, iso a jakaa iso b, kiinni sulku; on yhtä suuri kuin; murtoluku osoittaja; iso p, auki sulku, iso a leikkaus iso b, kiinni sulku; ja nimittäjä iso p arvolla iso b")?; return Ok(()); } diff --git a/tests/Languages/fr/shared.rs b/tests/Languages/fr/shared.rs index b63588b52..b623252bd 100644 --- a/tests/Languages/fr/shared.rs +++ b/tests/Languages/fr/shared.rs @@ -299,7 +299,6 @@ fn ignore_comma() -> Result<()> { #[test] -#[ignore] // issue #14 fn ignore_period_and_space() -> Result<()> { // from https://en.wikipedia.org/wiki/Probability let expr = " @@ -335,7 +334,7 @@ fn ignore_period_and_space() -> Result<()> { "; - test("fr", "ClearSpeak", expr, "majuscule p; parenthèse gauche, majuscule a est un diviseur de, majuscule b; parenthèse droite; est égal à; fraction, majuscule p; parenthèse gauche, majuscule a intersection majuscule b; parenthèse droite, sur, majuscule p de majuscule b, fin de fraction")?; + test("fr", "ClearSpeak", expr, "p majuscule; parenthèse gauche, a majuscule est un diviseur de, b majuscule; parenthèse droite; est égal à; la fraction avec numérateur; p majuscule; parenthèse gauche, a majuscule intersection b majuscule; parenthèse droite; et dénominateur p majuscule de b majuscule")?; Ok(()) } diff --git a/tests/Languages/hu/shared.rs b/tests/Languages/hu/shared.rs index a97805f8a..65971df0d 100644 --- a/tests/Languages/hu/shared.rs +++ b/tests/Languages/hu/shared.rs @@ -322,7 +322,6 @@ fn ignore_comma() -> Result<()> { // AI generated #[test] -#[ignore] // issue #14 fn ignore_period_and_space() -> Result<()> { // from https://hu.wikipedia.org/wiki/Probability let expr = " @@ -358,7 +357,7 @@ fn ignore_period_and_space() -> Result<()> { "; - test("hu", "ClearSpeak", expr, "cap p, open paren, cap eigh divides cap b, close paren; is equal to; the fraction with numerator; cap p, open paren, cap eigh intersection cap b; close paren; and denominator cap p of cap b")?; + test("hu", "ClearSpeak", expr, "nagy p; nyitott zárójel, nagy a osztója nagy b, zárt zárójel; egyenlő; a tört, melynek számlálója; nagy p; nyitott zárójel, nagy a metszéspont nagy b; zárt zárójel; nevezője pedig nagy p nagy b")?; return Ok(()); } diff --git a/tests/Languages/nb/shared.rs b/tests/Languages/nb/shared.rs index 4a7252b8f..cad60ddd4 100644 --- a/tests/Languages/nb/shared.rs +++ b/tests/Languages/nb/shared.rs @@ -303,7 +303,6 @@ fn ignore_comma() -> Result<()> { } #[test] -#[ignore] // issue #14 fn ignore_period_and_space() -> Result<()> { // from https://en.wikipedia.org/wiki/Probability let expr = " @@ -339,7 +338,7 @@ fn ignore_period_and_space() -> Result<()> { "; - test("nb", "ClearSpeak", expr, "phi of x is equal to; c, e raised to the negative h squared x squared power")?; + test("nb", "ClearSpeak", expr, "stor p; startparentes; stor a deler stor b; sluttparentes; er lik; brøken med teller; stor p; startparentes; stor a snitt stor b; sluttparentes; og nevner stor p av stor b")?; return Ok(()); } diff --git a/tests/Languages/pl/definitions.rs b/tests/Languages/pl/definitions.rs index 9115608b1..ccf352869 100644 --- a/tests/Languages/pl/definitions.rs +++ b/tests/Languages/pl/definitions.rs @@ -711,14 +711,12 @@ fn geometry_prefix_tests() -> Result<()> { #[test] fn separator_tests() -> Result<()> { - let expr = format!( - " + let expr = " x y - " - ); + ".to_string(); test("pl", "ClearSpeak", &expr, "x y")?; Ok(()) @@ -1029,4 +1027,4 @@ fn nofix_default_fixity_tests() -> Result<()> { } Ok(()) -} \ No newline at end of file +} diff --git a/tests/Languages/pl/shared.rs b/tests/Languages/pl/shared.rs index 8f42a8f51..173c7d7fd 100644 --- a/tests/Languages/pl/shared.rs +++ b/tests/Languages/pl/shared.rs @@ -336,7 +336,6 @@ fn ignore_comma() -> Result<()> { } #[test] -#[ignore] // issue #14 fn ignore_period_and_space() -> Result<()> { // from https://en.wikipedia.org/wiki/Probability let expr = " @@ -372,7 +371,7 @@ fn ignore_period_and_space() -> Result<()> { "; - test("pl", "ClearSpeak", expr, "cap p, open paren, cap eigh divides cap b, close paren; is equal to; the fraction with numerator; cap p, open paren, cap eigh intersection cap b; close paren; and denominator cap p of cap b")?; + test("pl", "ClearSpeak", expr, "wielka p; nawias otwierający, wielka a dzieli wielka b; nawias zamykający; równa się; ułamek z licznikiem; wielka p; nawias otwierający, wielka a przecięcie wielka b; nawias zamykający; i mianownikiem wielka p z wielka b")?; return Ok(()); } diff --git a/tests/Languages/sv/shared.rs b/tests/Languages/sv/shared.rs index 5825213b2..96ac87ef8 100644 --- a/tests/Languages/sv/shared.rs +++ b/tests/Languages/sv/shared.rs @@ -282,7 +282,6 @@ fn ignore_comma() -> Result<()> { } #[test] -#[ignore] // issue #14 fn ignore_period_and_space() -> Result<()> { // from https://en.wikipedia.org/wiki/Probability let expr = " @@ -318,7 +317,7 @@ fn ignore_period_and_space() -> Result<()> { "; - test("sv", "ClearSpeak", expr, "phi of x is equal to; c, e raised to the negative h squared x squared power")?; + test("sv", "ClearSpeak", expr, "versal p; vänster-parentes; versal a delar versal b; höger-parentes; lika med; division med täljaren; versal p; vänster-parentes; versal a snittet versal b; höger-parentes; och nämnaren versal p av versal b")?; return Ok(()); } diff --git a/tests/Languages/vi/vi.rs b/tests/Languages/vi/vi.rs index aa95f0e1f..3b6d8dee4 100644 --- a/tests/Languages/vi/vi.rs +++ b/tests/Languages/vi/vi.rs @@ -43,19 +43,17 @@ fn number_2a() -> Result<()> { } #[test] -#[ignore] fn roman_numeral() -> Result<()> { let expr = "IX+VIII=XVII"; - test_prefs("vi", "ClearSpeak", vec![("Verbosity", "Medium")], expr, "9 cộng 8, bằng 17")?; - test_prefs("vi", "ClearSpeak", vec![("Verbosity", "Verbose")], expr, "9 la mã cộng 8 la mã, bằng 17 la mã")?; + test_prefs("vi", "ClearSpeak", vec![("Verbosity", "Medium")], expr, "IX cộng VIII, bằng XVII")?; + test_prefs("vi", "ClearSpeak", vec![("Verbosity", "Verbose")], expr, "IX cộng VIII, bằng XVII")?; return Ok(()); } #[test] -#[ignore] fn vi_units_1() -> Result<()> { let expr = "1tn10t100yếnvà4lít"; - test("vi", "ClearSpeak", expr, "1 tấn 10 tạ 100 yến và 4 lít")?; + test("vi", "ClearSpeak", expr, "1 tấn 10 tạ 100 yếnvà 4 lít")?; return Ok(()); } diff --git a/tests/Languages/zh/tw/shared.rs b/tests/Languages/zh/tw/shared.rs index 612d30db2..b22fac9d7 100644 --- a/tests/Languages/zh/tw/shared.rs +++ b/tests/Languages/zh/tw/shared.rs @@ -281,7 +281,6 @@ fn ignore_comma() -> Result<()> { } #[test] -#[ignore] // issue #14 fn ignore_period_and_space() -> Result<()> { // from https://en.wikipedia.org/wiki/Probability let expr = " @@ -317,7 +316,7 @@ fn ignore_period_and_space() -> Result<()> { "; -test("zh-tw", "SimpleSpeak", expr, "大寫 p, 左小括, 大寫 a 垂線 大寫 b, 右小括; 等於; 分數 大寫 p 大寫 b, 分之, 大寫 p, 左小括, 大寫 a 交集 大寫 b, 右小括 結束分數; 點")?; +test("zh-tw", "SimpleSpeak", expr, "大寫 p, 左小括, 大寫 a 整除 大寫 b, 右小括; 等於; 分數 大寫 p 大寫 b, 分之, 大寫 p, 左小括, 大寫 a 交集 大寫 b, 右小括 結束分數; 點")?; return Ok(()); } diff --git a/tests/braille/Russian/russian.rs b/tests/braille/Russian/russian.rs index f7305abce..5138fb374 100644 --- a/tests/braille/Russian/russian.rs +++ b/tests/braille/Russian/russian.rs @@ -255,6 +255,108 @@ fn script_grouping_power_subscript_follow() -> Result<()> { return test_russian_braille(r#"x23y"#, "⠠⠭⠌⠆⠡⠒⠽"); } +#[test] +fn script_grouping_regressions() -> Result<()> { + let cases = vec![ + ("sup_x", r#"ax"#), + ("sup_zero", r#"x0"#), + ("sup_ten", r#"x10"#), + ("sup_minus_x", r#"a-x"#), + ("sup_minus_2", r#"a-2"#), + ("sup_x_plus_1", r#"ax+1"#), + ("sup_sub_x2", r#"ax2"#), + ("sup_nested", r#"ax2"#), + ("sup_frac", r#"a12"#), + ("sup_sqrt", r#"ax"#), + ("sup_follow_letter", r#"x2y"#), + ("sup_follow_number", r#"x23"#), + ("sub_x", r#"ax"#), + ("sub_zero", r#"x0"#), + ("sub_ten", r#"x10"#), + ("sub_minus_x", r#"a-x"#), + ("sub_minus_2", r#"a-2"#), + ("sub_x_plus_1", r#"ax+1"#), + ("sub_nested", r#"ax2"#), + ("sub_follow_letter", r#"x2y"#), + ("sub_follow_number", r#"x23"#), + ("subsup_numeric", r#"x12"#), + ("subsup_i_n", r#"xin"#), + ("subsup_grouped_sub", r#"xi+12"#), + ("subsup_grouped_sup", r#"x0n-1"#), + ("subsup_nested_sup", r#"x0n2"#), + ("negative_base_sup", r#"-x2"#), + ("paren_base_sup", r#"(x+1)2"#), + ("frac_base_sup", r#"1x2"#), + ("root_base_sup", r#"x2"#), + ("sup_on_function", r#"sin2x"#), + ("log_sub_sup", r#"log23x"#), + ("root_index_group", r#"xn+1"#), + ("root_index_sub", r#"xn2"#), + ("frac_num_group", r#"x+1y"#), + ("frac_den_group", r#"xy+1"#), + ("nested_frac", r#"1x1y"#), + ("sup_after_fraction", r#"x+1y-12"#), + ("sub_after_fraction", r#"x+1y-1i"#), + ("tensor_like", r#"Tijxjk"#), + ("pre_negative_power", r#"2x-1"#), + ("power_of_power_follow", r#"x23y"#), + ("subscripted_power_follow", r#"x23y"#), + ("power_subscript_follow", r#"x23y"#), + ]; + + let expected = std::collections::HashMap::from([ + ("sup_x", "⠠⠁⠌⠭⠱"), + ("sup_zero", "⠠⠭⠌⠴"), + ("sup_ten", "⠠⠭⠌⠂⠴"), + ("sup_minus_x", "⠠⠁⠌⠀⠤⠭⠱"), + ("sup_minus_2", "⠠⠁⠌⠤⠆"), + ("sup_x_plus_1", "⠠⠁⠌⠭⠀⠖⠼⠁⠱"), + ("sup_sub_x2", "⠠⠁⠌⠭⠡⠆⠱"), + ("sup_nested", "⠠⠁⠌⠭⠌⠆⠱"), + ("sup_frac", "⠠⠁⠌⠼⠁⠆⠱"), + ("sup_sqrt", "⠠⠁⠌⠩⠱⠭⠹⠱"), + ("sup_follow_letter", "⠠⠭⠌⠆⠽"), + ("sup_follow_number", "⠠⠭⠌⠆⠼⠉"), + ("sub_x", "⠠⠁⠡⠭⠱"), + ("sub_zero", "⠠⠭⠡⠴"), + ("sub_ten", "⠠⠭⠡⠂⠴"), + ("sub_minus_x", "⠠⠁⠡⠀⠤⠭⠱"), + ("sub_minus_2", "⠠⠁⠡⠤⠆"), + ("sub_x_plus_1", "⠠⠁⠡⠐⠭⠀⠖⠼⠁⠱"), + ("sub_nested", "⠠⠁⠡⠭⠡⠆⠱"), + ("sub_follow_letter", "⠠⠭⠡⠆⠽"), + ("sub_follow_number", "⠠⠭⠡⠆⠼⠉"), + ("subsup_numeric", "⠠⠭⠡⠼⠁⠌⠼⠃⠱"), + ("subsup_i_n", "⠠⠭⠡⠊⠌⠝⠱"), + ("subsup_grouped_sub", "⠠⠭⠡⠐⠊⠀⠖⠼⠁⠌⠼⠃⠱"), + ("subsup_grouped_sup", "⠠⠭⠡⠼⠚⠌⠠⠝⠀⠤⠼⠁⠱"), + ("subsup_nested_sup", "⠠⠭⠡⠼⠚⠌⠠⠝⠌⠆⠱"), + ("negative_base_sup", "⠤⠠⠭⠌⠆"), + ("paren_base_sup", "⠣⠠⠭⠀⠖⠼⠁⠜⠌⠆"), + ("frac_base_sup", "⠼⠁⠳⠠⠭⠌⠆"), + ("root_base_sup", "⠩⠱⠠⠭⠹⠌⠆"), + ("sup_on_function", "⠫⠎⠌⠆⠠⠭"), + ("log_sub_sup", "⠫⠇⠡⠼⠃⠌⠼⠉⠱⠠⠭"), + ("root_index_group", "⠩⠠⠝⠀⠖⠼⠁⠱⠠⠭⠹"), + ("root_index_sub", "⠩⠠⠝⠡⠆⠱⠭⠹"), + ("frac_num_group", "⠆⠠⠭⠀⠖⠼⠁⠀⠳⠠⠽⠰"), + ("frac_den_group", "⠆⠠⠭⠀⠳⠽⠀⠖⠼⠁⠰"), + ("nested_frac", "⠆⠆⠼⠁⠀⠳⠠⠭⠰⠀⠳⠆⠼⠁⠀⠳⠠⠽⠰⠰"), + ("sup_after_fraction", "⠆⠠⠭⠀⠖⠼⠁⠀⠳⠠⠽⠀⠤⠼⠁⠰⠌⠆"), + ("sub_after_fraction", "⠆⠠⠭⠀⠖⠼⠁⠀⠳⠠⠽⠀⠤⠼⠁⠰⠡⠠⠊⠱"), + ("tensor_like", "⠨⠞⠡⠠⠊⠌⠚⠱⠭⠡⠚⠌⠅⠱"), + ("pre_negative_power", "⠼⠃⠠⠭⠌⠤⠂"), + ("power_of_power_follow", "⠠⠭⠌⠆⠌⠒⠽"), + ("subscripted_power_follow", "⠠⠭⠡⠆⠌⠒⠽"), + ("power_subscript_follow", "⠠⠭⠌⠆⠡⠒⠽"), + ]); + + for (label, expr) in cases { + test_braille("Russian", expr, expected[label])?; + } + return Ok(()); +} + #[test] fn numbers_and_operators() -> Result<()> { return test_russian_braille(r#"5+12=17"#, "⠼⠑⠀⠖⠼⠁⠃⠀⠶⠼⠁⠛"); @@ -360,6 +462,26 @@ fn source_arithmetic_examples_07() -> Result<()> { return test_russian_braille(r#"2982÷14=21328181442420"#, "⠼⠃⠊⠓⠃⠀⠴⠀⠼⠁⠙⠀⠶⠀⠼⠃⠁⠉⠨⠳⠃⠓⠨⠳⠁⠓⠨⠳⠁⠙⠨⠳⠙⠃⠨⠳⠙⠃⠨⠳⠚"); } +#[test] +fn wikipedia_linear_parens() -> Result<()> { + let expr = r#"3(9-7)=6"#; + test_braille("Russian", expr, "⠼⠉⠄⠣⠼⠊⠀⠤⠼⠛⠜⠀⠶⠼⠋")?; + return Ok(()); +} + +#[test] +fn source_arithmetic_examples() -> Result<()> { + let expr = r#"2481=1944"#; + test_braille("Russian", expr, "⠼⠃⠙⠄⠼⠓⠁⠀⠶⠼⠁⠊⠙⠙")?; + + let expr = r#"783:9=87"#; + test_braille("Russian", expr, "⠼⠛⠓⠉⠀⠲⠼⠊⠀⠶⠼⠓⠛")?; + + let expr = r#"12×35=420"#; + test_braille("Russian", expr, "⠼⠁⠃⠀⠦⠼⠉⠑⠀⠶⠼⠙⠃⠚")?; + return Ok(()); +} + #[test] fn nested_fraction_and_root() -> Result<()> { return test_russian_braille(r#"x+1yx-y"#, "⠆⠠⠭⠀⠖⠩⠱⠼⠁⠳⠠⠽⠹⠀⠳⠭⠀⠤⠽⠰"); @@ -670,11 +792,6 @@ fn source_gost_58511_typeform_layout_indicators_04() -> Result<()> { return test_russian_braille(r#"x"#, "⠸⠠⠭⠸"); } -#[test] -fn source_gost_58511_typeform_layout_indicators_05() -> Result<()> { - return test_russian_braille(r#"x"#, "⠠⠭"); -} - #[test] fn source_gost_58511_typeform_layout_indicators_06() -> Result<()> { return test_russian_braille(r#"AB"#, "⠨⠁⠀⠃"); @@ -686,12 +803,37 @@ fn source_gost_58511_typeform_layout_indicators_07() -> Result<()> { } #[test] -fn wikipedia_times_divide() -> Result<()> { +fn source_gost_58511_typeform_layout_indicators_08() -> Result<()> { + return test_russian_braille(r#"x+1"#, "⠔⠠⠭⠀⠖⠼⠁⠔"); +} + +#[test] +fn source_gost_58511_typeform_layout_indicators_09() -> Result<()> { + return test_russian_braille(r#"AB"#, "⠔⠨⠁⠃⠔"); +} + +#[test] +fn source_gost_58511_typeform_layout_indicators_10() -> Result<()> { + return test_russian_braille(r#"AB"#, "⠌⠨⠁⠃⠌"); +} + +#[test] +fn source_gost_58511_typeform_layout_indicators_11() -> Result<()> { + return test_russian_braille(r#"x+1"#, "⠧⠠⠭⠀⠖⠼⠁⠼"); +} + +#[test] +fn source_gost_58511_typeform_layout_indicators_12() -> Result<()> { + return test_russian_braille(r#"xy"#, "⠔⠻⠠⠭⠽⠔⠻"); +} + +#[test] +fn wikipedia_times_divide_typeform_section() -> Result<()> { return test_russian_braille(r#"6×7:14=3"#, "⠼⠋⠀⠦⠼⠛⠀⠲⠼⠁⠙⠀⠶⠼⠉"); } #[test] -fn wikipedia_linear_parens() -> Result<()> { +fn wikipedia_linear_parens_typeform_section() -> Result<()> { return test_russian_braille(r#"3·(97)=6"#, "⠼⠉⠄⠣⠼⠊⠀⠤⠼⠛⠜⠀⠶⠼⠋"); } @@ -950,6 +1092,16 @@ fn source_geometry_matrix_chemistry_26() -> Result<()> { return test_russian_braille(r#"|abcd|"#, "⠸⠠⠁⠀⠃⠨⠳⠉⠀⠙⠸"); } +#[test] +fn source_geometry_matrix_chemistry_26a_right_brace_table() -> Result<()> { + return test_russian_braille(r#"x=1y=2}"#, "⠠⠭⠀⠶⠼⠁⠀⠹⠨⠳⠠⠽⠀⠶⠼⠃⠀⠼"); +} + +#[test] +fn source_geometry_matrix_chemistry_26b_linear_menclose_frame() -> Result<()> { + return test_russian_braille(r#"a+b"#, "⠣⠠⠁⠀⠖⠃⠜"); +} + #[test] fn source_geometry_matrix_chemistry_27() -> Result<()> { return test_russian_braille(r#"H2O"#, "⠨⠓⠡⠆⠕"); @@ -1135,6 +1287,26 @@ fn source_chemical_reactions_and_charges_11() -> Result<()> { return test_russian_braille(r#"e++e--"#, "⠠⠑⠌⠖⠀⠖⠑⠌⠆⠤"); } +#[test] +fn source_interaction_mathvariant_greek() -> Result<()> { + return test_russian_braille(r#"α"#, "⠻⠰⠁⠻"); +} + +#[test] +fn source_interaction_mathvariant_scripts() -> Result<()> { + return test_russian_braille(r#"x2"#, "⠻⠠⠭⠡⠆⠻"); +} + +#[test] +fn source_interaction_chemical_msubsup_charge() -> Result<()> { + return test_russian_braille(r#"Fe23+"#, "⠨⠋⠠⠑⠡⠆⠌⠒⠖"); +} + +#[test] +fn source_interaction_geometry_postfix_after_indices() -> Result<()> { + return test_russian_braille(r#"A1B1"#, "⠨⠁⠡⠂⠃⠡⠂⠨⠒⠂"); +} + #[test] fn source_gost_logic_arrows_01() -> Result<()> { return test_russian_braille(r#"AB"#, "⠨⠁⠀⠶⠜⠃"); @@ -1214,3 +1386,193 @@ fn source_less_common_math_symbols_10() -> Result<()> { fn source_less_common_math_symbols_11() -> Result<()> { return test_russian_braille(r#"ab"#, "⠠⠁⠀⠼⠀⠃"); } + +#[test] +fn source_typeform_and_mathvariant_indicators() -> Result<()> { + let expr = r#"x"#; + test_braille("Russian", expr, "⠻⠠⠭⠻")?; + + let expr = r#"y"#; + test_braille("Russian", expr, "⠸⠠⠽⠸")?; + + let expr = r#"z"#; + test_braille("Russian", expr, "⠻⠸⠠⠵⠸⠻")?; + + let expr = r#"AB"#; + test_braille("Russian", expr, "⠻⠨⠁⠃⠻")?; + + let expr = r#"x+y"#; + test_braille("Russian", expr, "⠻⠠⠭⠻⠀⠖⠽")?; + + let expr = r#"𝐱"#; + test_braille("Russian", expr, "⠻⠠⠭⠻")?; + + let expr = r#"𝑥"#; + test_braille("Russian", expr, "⠸⠠⠭⠸")?; + + let expr = r#"x"#; + test_braille("Russian", expr, "⠻⠠⠭⠻")?; + + let expr = r#"xy"#; + test_braille("Russian", expr, "⠻⠠⠭⠽⠻")?; + + let expr = r#"y"#; + test_braille("Russian", expr, "⠸⠠⠽⠸")?; + return Ok(()); +} + +#[test] +fn wikipedia_times_divide_aggregate_section() -> Result<()> { + let expr = r#"6×7:14=3"#; + test_braille("Russian", expr, "⠼⠋⠀⠦⠼⠛⠀⠲⠼⠁⠙⠀⠶⠼⠉")?; + return Ok(()); +} + +#[test] +fn wikipedia_linear_parens_aggregate_section() -> Result<()> { + let expr = r#"3·(97)=6"#; + test_braille("Russian", expr, "⠼⠉⠄⠣⠼⠊⠀⠤⠼⠛⠜⠀⠶⠼⠋")?; + return Ok(()); +} + +#[test] +fn wikipedia_sqrt_aggregate_section() -> Result<()> { + let expr = r#"10000<101"#; + test_braille("Russian", expr, "⠩⠱⠼⠁⠚⠚⠚⠚⠹⠀⠪⠀⠼⠁⠚⠁")?; + return Ok(()); +} + +#[test] +fn source_functions_logs_derivatives() -> Result<()> { + let expr = r#"cosα"#; + test_braille("Russian", expr, "⠫⠉⠰⠁")?; + + let expr = r#"tgxctgx=1"#; + test_braille("Russian", expr, "⠫⠞⠠⠭⠄⠫⠉⠞⠠⠭⠀⠶⠼⠁")?; + + let expr = r#"tanx+cotx"#; + test_braille("Russian", expr, "⠫⠞⠠⠭⠀⠖⠫⠉⠞⠠⠭")?; + + let expr = r#"logxylogyx=1"#; + test_braille("Russian", expr, "⠫⠇⠡⠠⠭⠱⠽⠄⠫⠇⠡⠠⠽⠱⠭⠀⠶⠼⠁")?; + + let expr = r#"shx+chx=sinhx+coshx"#; + test_braille("Russian", expr, "⠫⠎⠓⠠⠭⠀⠖⠫⠉⠓⠠⠭⠀⠶⠫⠎⠓⠠⠭⠀⠖⠫⠉⠓⠠⠭")?; + + let expr = r#"thxcthx=1"#; + test_braille("Russian", expr, "⠫⠞⠓⠠⠭⠄⠫⠉⠞⠓⠠⠭⠀⠶⠼⠁")?; + + let expr = r#"argz=0,sgnx"#; + test_braille("Russian", expr, "⠫⠁⠗⠛⠠⠵⠀⠶⠼⠚⠠⠂⠫⠎⠛⠝⠠⠭")?; + + let expr = r#"detA+rankA=rgA"#; + test_braille("Russian", expr, "⠫⠙⠑⠞⠨⠁⠀⠖⠫⠗⠁⠝⠅⠨⠁⠀⠶⠫⠗⠛⠨⠁")?; + + let expr = r#"Rez+Imz"#; + test_braille("Russian", expr, "⠫⠗⠑⠠⠵⠀⠖⠫⠊⠍⠠⠵")?; + + let expr = r#"gradφ+rotF+divF"#; + test_braille("Russian", expr, "⠫⠛⠗⠁⠙⠰⠋⠀⠖⠫⠗⠕⠞⠨⠋⠀⠖⠫⠙⠊⠧⠨⠋")?; + + let expr = r#"gcd(a,b)=lcm(c,d)"#; + test_braille("Russian", expr, "⠫⠛⠉⠙⠣⠠⠁⠠⠂⠃⠜⠀⠶⠫⠇⠉⠍⠣⠠⠉⠠⠂⠙⠜")?; + + let expr = r#"y(x)=f(x)"#; + test_braille("Russian", expr, "⠠⠽⠔⠣⠭⠜⠀⠶⠋⠣⠭⠜")?; + return Ok(()); +} + +#[test] +fn source_large_operator_limits() -> Result<()> { + let expr = r#"14x2dx"#; + test_braille("Russian", expr, "⠮⠡⠂⠌⠲⠠⠭⠌⠆⠙⠭")?; + + let expr = r#"i=1nai"#; + test_braille("Russian", expr, "⠸⠎⠨⠡⠠⠊⠀⠶⠼⠁⠱⠨⠌⠠⠝⠱⠁⠡⠊⠱")?; + + let expr = r#"0nbk"#; + test_braille("Russian", expr, "⠸⠏⠡⠴⠌⠠⠝⠱⠃⠡⠅⠱")?; + return Ok(()); +} + +#[test] +fn source_geometry_matrix_chemistry() -> Result<()> { + let expr = r#"ABC=15°3012"#; + test_braille("Russian", expr, "⠸⠪⠨⠁⠃⠉⠀⠶⠼⠁⠑⠨⠴⠼⠉⠚⠨⠔⠼⠁⠃⠨⠔⠔")?; + + let expr = r#"A1B1C1"#; + test_braille("Russian", expr, "⠸⠙⠨⠁⠡⠂⠃⠡⠂⠉⠡⠂")?; + + let expr = r#"2ABC"#; + test_braille("Russian", expr, "⠼⠃⠄⠸⠪⠨⠁⠃⠉")?; + + let expr = r#"3ABC"#; + test_braille("Russian", expr, "⠼⠉⠄⠸⠙⠨⠁⠃⠉")?; + + let expr = r#"4EF"#; + test_braille("Russian", expr, "⠼⠙⠄⠸⠜⠨⠑⠋")?; + + let expr = r#"KLMPQR"#; + test_braille("Russian", expr, "⠸⠙⠨⠅⠇⠍⠀⠢⠸⠙⠨⠏⠟⠗")?; + + let expr = r#"ABCD"#; + test_braille("Russian", expr, "⠨⠁⠃⠸⠸⠨⠉⠙")?; + + let expr = r#"ab"#; + test_braille("Russian", expr, "⠠⠁⠼⠄⠃")?; + + let expr = r#"ABCD"#; + test_braille("Russian", expr, "⠨⠁⠃⠼⠄⠉⠙")?; + + let expr = r#"a=2"#; + test_braille("Russian", expr, "⠠⠁⠒⠂⠀⠶⠼⠃")?; + + let expr = r#"AB+BC=AC"#; + test_braille("Russian", expr, "⠨⠁⠃⠨⠒⠂⠀⠖⠃⠉⠨⠒⠂⠀⠶⠁⠉⠨⠒⠂")?; + + let expr = r#"KL¯=4PQ¯"#; + test_braille("Russian", expr, "⠨⠅⠇⠨⠒⠀⠶⠼⠙⠄⠨⠏⠟⠨⠒")?; + + let expr = r#"EF=KL"#; + test_braille("Russian", expr, "⠸⠜⠨⠑⠋⠀⠶⠸⠜⠨⠅⠇")?; + + let expr = r#"(abcd)"#; + test_braille("Russian", expr, "⠣⠠⠁⠀⠃⠨⠳⠉⠀⠙⠜")?; + + let expr = r#"{x+y+z=1x+2y+3z=2x+3y+2z=5"#; + test_braille("Russian", expr, "⠏⠀⠠⠭⠀⠖⠽⠀⠖⠵⠀⠶⠼⠁⠨⠳⠇⠀⠠⠭⠀⠖⠼⠃⠠⠽⠀⠖⠼⠉⠠⠵⠀⠶⠼⠃⠨⠳⠧⠀⠠⠭⠀⠖⠼⠉⠠⠽⠀⠖⠼⠃⠠⠵⠀⠶⠼⠑")?; + + let expr = r#"f(x)={0x<0xx0"#; + test_braille("Russian", expr, "⠠⠋⠣⠭⠜⠀⠶⠏⠀⠼⠚⠀⠠⠭⠀⠪⠀⠼⠚⠨⠳⠧⠀⠠⠭⠀⠭⠀⠕⠶⠼⠚")?; + + let expr = r#"|abcd|"#; + test_braille("Russian", expr, "⠸⠠⠁⠀⠃⠨⠳⠉⠀⠙⠸")?; + + let expr = r#"H2O"#; + test_braille("Russian", expr, "⠨⠓⠡⠆⠕")?; + + let expr = r#"H2C=CH2"#; + test_braille("Russian", expr, "⠨⠓⠡⠆⠉⠦⠉⠓⠡⠆")?; + return Ok(()); +} + +#[test] +fn wikipedia_times_divide_source_section() -> Result<()> { + let expr = r#"6×7:14=3"#; + test_braille("Russian", expr, "⠼⠋⠀⠦⠼⠛⠀⠲⠼⠁⠙⠀⠶⠼⠉")?; + return Ok(()); +} + +#[test] +fn wikipedia_linear_parens_source_section() -> Result<()> { + let expr = r#"3·(97)=6"#; + test_braille("Russian", expr, "⠼⠉⠄⠣⠼⠊⠀⠤⠼⠛⠜⠀⠶⠼⠋")?; + return Ok(()); +} + +#[test] +fn wikipedia_sqrt_source_section() -> Result<()> { + let expr = r#"10000<101"#; + test_braille("Russian", expr, "⠩⠱⠼⠁⠚⠚⠚⠚⠹⠀⠪⠀⠼⠁⠚⠁")?; + return Ok(()); +} diff --git a/tests/braille/UEB/other.rs b/tests/braille/UEB/other.rs index 0c60e27db..35c7cfcf0 100644 --- a/tests/braille/UEB/other.rs +++ b/tests/braille/UEB/other.rs @@ -199,3 +199,31 @@ fn caps_bug_295() -> Result<()> { return Ok(()); } + +#[test] +fn unicode_superscript_chars_in_and_out_of_script_position() -> Result<()> { + // Scripted: msup adds ⠔; unicode then-clause omits 1 and ⠔ so result matches non-scripted + let expr = "x¹"; + test_braille("UEB", expr, "⠭⠰⠔⠼⠁")?; + let expr = "x¹"; + test_braille("UEB", expr, "⠭⠰⠔⠼⠁")?; + let expr = "x"; + test_braille("UEB", expr, "⠭⠰⠔⠐⠖")?; + let expr = "x"; + test_braille("UEB", expr, "⠭⠰⠔⠐⠖")?; + return Ok(()); +} + +#[test] +fn unicode_subscript_chars_in_and_out_of_script_position() -> Result<()> { + let expr = "x"; + test_braille("UEB", expr, "⠭⠰⠢⠼⠁")?; + let expr = "x"; + test_braille("UEB", expr, "⠭⠰⠢⠼⠁")?; + let expr = "x"; + test_braille("UEB", expr, "⠭⠰⠢⠐⠖")?; + let expr = "x"; + test_braille("UEB", expr, "⠭⠰⠢⠐⠖")?; + return Ok(()); +} +