diff --git a/.gitignore b/.gitignore
index 43514cfa..939c367e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.idea
target
build.rs.orig
Python/libmathcat.pyd
diff --git a/README.md b/README.md
index d9c3219a..a6d46af0 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,19 @@
-# MathCAT: Math Capable Assistive Technology
+# MathCATde: German Translation for MathCAT: Math Capable Assistive Technology
is a library that supports conversion of MathML to:
* Speech strings (in several languages) with embedded speech engine commands
-* Braille (Nemeth, UEB Technical, CMU, and many others)
+* (later: Braille (Nemeth, UEB Technical, CMU, and many others))
* Navigation of math (in multiple ways including overviews)
+This is the fork of [MathCAT](https://github.com/NSoiffer/MathCAT) of Neil Soiffer focussed on the translations to the German speaking contexts.
-There are four related projects that make use of MathCAT:
-- [MathCATDemo](https://nsoiffer.github.io/MathCATDemo/) -- an online demonstration of some of what can be done with MathCAT
-- [A python interface for MathCAT](https://github.com/NSoiffer/MathCATForPython) -- used by a [MathCAT NVDA add-on](https://addons.nvda-project.org/addons/MathCAT.en.html).
-- [A C/C++ interface for MathCAT](https://github.com/NSoiffer/MathCATForC)
-- [A Java interface for MathCAT](https://github.com/mwhapples/MathCAT4J) (thanks to Michael Whapples for working on that)
+## Status
+This translation project was launched in the summer 2025 it is quite new still.
-MathCAT is used in many assistive technologies including NVDA and JAWS.
+## How to contribute?
+This project is untertaken by the team of IT&Tech at the [IU University of Applied Sciences](https://www.iu.org/) and welcomes test-reports in the form of issues and proposed changes in the form of pull-requests.
-For more information, see the [full documentation](https://nsoiffer.github.io/MathCAT/).
+For process questions, raising an issue is probably the best idea too.
\ No newline at end of file
diff --git a/Rules/Languages/de/ClearSpeak_Rules.yaml b/Rules/Languages/de/ClearSpeak_Rules.yaml
new file mode 100644
index 00000000..6a7b28be
--- /dev/null
+++ b/Rules/Languages/de/ClearSpeak_Rules.yaml
@@ -0,0 +1,786 @@
+---
+- name: intent-literal-silent
+ tag: [mi, mo, mn]
+ match: "contains(@data-intent-property, ':silent:')"
+ # say nothing
+ replace: []
+
+# handling of negative numbers that come from 'intent' is hard -- we do something that is close to right here
+- name: intent-literal-negative-number
+ tag: mn
+ match: "starts-with(text(), '-')"
+ replace:
+ - T: "minus"
+ - x: "translate(text(), '-_', '')"
+
+- name: default
+ tag: square-root
+ match: "."
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: {T: "die"}
+ - test:
+ if: $ClearSpeak_Roots = 'PosNegSqRoot' or $ClearSpeak_Roots = 'PosNegSqRootEnd'
+ then:
+ - bookmark: "*[1]/@id"
+ - test:
+ if: parent::*[self::m:minus and count(*)=1]
+ then: [{T: "minus"}]
+ else: [{T: "plus"}]
+ - T: "quadratwurzel"
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: {T: "von"}
+ else: {pause: short}
+ - x: "*[1]"
+ - test:
+ - if: "$ClearSpeak_Roots = 'RootEnd' or $ClearSpeak_Roots = 'PosNegSqRootEnd'"
+ then:
+ - pause: short
+ - T: "ende der wurzel"
+ - pause: medium
+ - else_if: "IsNode(*[1], 'simple')"
+ then: [{pause: short}]
+ else: [{pause: long}]
+
+- name: default
+ tag: root
+ match: "."
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: {T: "die"}
+ - test:
+ if: $ClearSpeak_Roots = 'PosNegSqRoot' or $ClearSpeak_Roots = 'PosNegSqRootEnd'
+ then:
+ - test:
+ if: "parent::*[(self::m:minus or self::m:plus) and count(*)=1]"
+ then: [{bookmark: "parent/@id"}]
+ - test:
+ if: parent::m:minus
+ then: [{T: "negative"}]
+ else: [{T: "positive"}]
+ - test:
+ if: "*[2][self::m:mn]"
+ then_test:
+ - if: "*[2][.='2']"
+ then: {T: "quadratwurzel"}
+ - else_if: "*[2][.='3']"
+ then: {T: "kubikwurzel"}
+ - else_if: "*[2][not(contains(., '.'))]"
+ then: [{x: "ToOrdinal(*[2])"}, {T: "Wurzel"}]
+ else:
+ - test:
+ if: "*[2][self::m:mi][string-length(.)=1]"
+ then:
+ - x: "*[2]"
+ - pronounce: [{text: "-th"}, {ipa: "θ"}, {sapi5: "th"}, {eloquence: "T"}]
+ else: {x: "*[2]"}
+ - T: "wurzel"
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: {T: "von"}
+ - x: "*[1]"
+ - test:
+ if: $ClearSpeak_Roots = 'RootEnd' or $ClearSpeak_Roots = 'PosNegSqRootEnd'
+ then:
+ - pause: short
+ - T: "ende der wurzel"
+ - pause: medium
+ else_test:
+ if: IsNode(*[1], 'simple')
+ then: [{pause: short}]
+ else: [{pause: long}]
+
+# The 'negative' rule interacts with the msqrt/mroot rules as those might pick off this case ("the negative square root of x")
+- name: negative_and_positive
+ tag: [plus, minus]
+ match: "count(*)=1 and contains(@data-intent-property, ':prefix:')"
+ replace:
+ - test:
+ if:
+ - "*[1][self::m:square-root or self::m:root] and"
+ - "($ClearSpeak_Roots = 'PosNegSqRoot' or $ClearSpeak_Roots = 'PosNegSqRootEnd')"
+ then: {T: ""}
+ else:
+ - bookmark: "@id"
+ - test:
+ if: "self::m:minus"
+ then: [{T: "negative"}]
+ else: [{T: "positive"}]
+ - x: "*[1]"
+
+# Fraction rules
+# Mixed numbers mostly "just work" because the invisible char reads as "and" and other parts read properly on their own
+
+# Units (e.g., meters per second)
+- name: per-fraction
+ tag: fraction
+ match:
+ - "$ClearSpeak_Fractions='Per' or"
+ - "(BaseNode(*[1])[contains(@data-intent-property, ':unit') or"
+ - " ( self::m:mrow and count(*)=3 and" # maybe a bit paranoid checking the structure...
+ - " *[1][self::m:mn] and *[2][.='\u2062'] and BaseNode(*[3])[contains(@data-intent-property, ':unit')] ) ] and"
+ - " BaseNode(*[2])[contains(@data-intent-property, ':unit')] )"
+ replace:
+ - x: "*[1]"
+ - t: "pro" # phrase('5 meters 'per' second)
+ - x: "*[2]"
+
+- name: common-fraction
+ tag: fraction
+ match:
+ - "($ClearSpeak_Fractions='Auto' or $ClearSpeak_Fractions='Ordinal' or $ClearSpeak_Fractions='EndFrac') and"
+ - "*[1][self::m:mn][not(contains(., '.')) and ($ClearSpeak_Fractions='Ordinal' or text()<20)] and"
+ - "*[2][self::m:mn][not(contains(., '.')) and ($ClearSpeak_Fractions='Ordinal' or (2<= text() and text()<=10))]"
+ replace: [{x: ToCommonFraction(.)}]
+
+- name: common-fraction-mixed-number
+ tag: fraction
+ match:
+ - "preceding-sibling::*[1][self::m:mo][.=''] and" # preceding element is invisible plus
+ - "($ClearSpeak_Fractions='Auto' or $ClearSpeak_Fractions='Ordinal' or $ClearSpeak_Fractions='EndFrac') and"
+ - "*[1][self::m:mn][not(contains(., '.')) and ($ClearSpeak_Fractions='Ordinal' or text()<20)] and"
+ - "*[2][self::m:mn][not(contains(., '.')) and ($ClearSpeak_Fractions='Ordinal' or (2<= text() and text()<=10))]"
+ replace: [{x: ToCommonFraction(.)}]
+
+- name: fraction-over-simple
+ tag: fraction
+ match:
+ - "($ClearSpeak_Fractions='Over' or $ClearSpeak_Fractions='FracOver' or $ClearSpeak_Fractions='OverEndFrac') or"
+ - "( not($ClearSpeak_Fractions='General' or $ClearSpeak_Fractions='GeneralEndFrac') and"
+ - " (IsNode(*[1],'simple') and IsNode(*[2],'simple')) )" # simple fraction in ClearSpeak spec
+ replace:
+ - test:
+ if: "$ClearSpeak_Fractions='FracOver'"
+ then:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [{OT: "der"}]
+ - T: "bruch"
+ - x: "*[1]"
+ - T: "durch"
+ - x: "*[2]"
+ - test:
+ # very ugly!!! -- replicate nested ordinal fraction as they are an exception
+ if: "$ClearSpeak_Fractions='OverEndFrac' or ($ClearSpeak_Fractions='EndFrac' and not( ($ClearSpeak_Fractions='Auto' or $ClearSpeak_Fractions='Ordinal' or $ClearSpeak_Fractions='EndFrac') and *[1][*[1][self::m:mn][not(contains(., '.')) and ($ClearSpeak_Fractions='Ordinal' or text()<20)] and *[2][self::m:mn][not(contains(., '.')) and ($ClearSpeak_Fractions='Ordinal' or (2<= text() and text()<=10))] ] and *[2][*[1][self::m:mn][not(contains(., '.')) and ($ClearSpeak_Fractions='Ordinal' or text()<20)] and *[2][self::m:mn][not(contains(., '.')) and ($ClearSpeak_Fractions='Ordinal' or (2<= text() and text()<=10))] ] ) )"
+ then:
+ - pause: short
+ - T: "ende des bruchs"
+ - pause: short
+
+- # fraction with text or numbers followed by text in both numerator and denominator
+ name: fraction-over-text
+ tag: fraction
+ match:
+ - "not($ClearSpeak_Fractions='General' or $ClearSpeak_Fractions='GeneralEndFrac') and"
+ - "( "
+ - " ((*[1][self::m:mi or self::m:mtext][string-length(.)>1]) or " # fractions with text
+ - " (*[1][self::m:mrow][count(*)=3][ "
+ - " *[1][self::m:mn] and "
+ - " *[2][self::m:mo][.=''] and " # invisible times
+ - " *[3][self::m:mi or self::m:mtext][string-length(.)>1] ]) ) and"
+ - " ((*[2][self::m:mi or self::m:mtext][string-length(.)>1]) or " # fractions with text
+ - " (*[2][self::m:mrow][count(*)=3][ "
+ - " *[1][self::m:mn] and "
+ - " *[2][self::m:mo][.=''] and " # invisible times
+ - " *[3][self::m:mi or self::m:mtext][string-length(.)>1] ]) )"
+ - ")"
+ replace:
+ - x: "*[1]"
+ - T: "durch"
+ - x: "*[2]"
+ - test:
+ if: "$ClearSpeak_Fractions='EndFrac' or $ClearSpeak_Fractions='OverEndFrac'"
+ then:
+ - pause: short
+ - T: "ende des bruchs"
+ - pause: short
+
+- name: default
+ tag: fraction
+ match: "."
+ replace:
+ - OT: "der"
+ - T: "bruch mit zähler"
+ - test:
+ if: not(IsNode(*[1], 'simple'))
+ then: {pause: medium}
+ - x: "*[1]"
+ - pause: medium
+ - T: "und nenner"
+ - x: "*[2]"
+ - pause: long
+ - test:
+ if: "$ClearSpeak_Fractions='EndFrac' or $ClearSpeak_Fractions='GeneralEndFrac'"
+ then:
+ - pause: short
+ - T: "ende des bruchs"
+ - pause: short
+
+# rules for functions raised to a power
+# these could have been written on 'mrow' but putting them on msup seems more specific
+# to see if it is a function, we look right to see if the following sibling is apply-function
+- name: ClearSpeak-function-inverse
+ tag: inverse-function
+ match: "."
+ replace:
+ - test:
+ if: $ClearSpeak_Trig = 'TrigInverse'
+ then: [{x: "*[1]"}, {bookmark: "*[2]/@id"}, {T: "umgekehrte"}]
+ else_test:
+ if: $ClearSpeak_Trig = 'ArcTrig'
+ then: [{bookmark: "*[2]/@id"}, {T: "ark"}, {x: "*[1]"}]
+ else: [{bookmark: "*[2]/@id"}, {T: "umgekehrte"}, {x: "*[1]"}] # default/Auto
+
+- name: function-squared-or-cubed
+ tag: power
+ match:
+ - "*[2][self::m:mn][.='2' or .='3'] and"
+ - "following-sibling::*[1][self::m:mo][.='']" #invisible function apply
+ replace:
+ - x: "*[1]"
+ - bookmark: "*[2]/@id"
+ - test:
+ if: "*[2][.='2']"
+ then_test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "hoch zwei"]
+ else: [T: "quadrat"]
+ else: {T: "hoch 3"}
+
+- name: function-power
+ tag: power
+ match:
+ - "following-sibling::*[1][self::m:mo][.='']" #invisible function apply
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: {T: ""}
+ - bookmark: "*[2]/@id"
+ - test:
+ if: "*[2][self::m:mn][not(contains(., '.'))]"
+ then: [{x: "ToOrdinal(*[2])"}]
+ else: [{x: "*[2]"}]
+ - T: "hoch"
+ - pause: short
+ - x: "*[1]"
+
+- name: AfterPower-nested
+ tag: power
+ match: # directly a superscript or an mrow that contains a superscript
+ - "$ClearSpeak_Exponents = 'AfterPower' and"
+ - "*[2][self::m:power or self::m:power or self::m:mrow[m:power]]"
+ replace:
+ - x: "*[1]"
+ - T: "zum exponent"
+ - pause: short
+ - x: "*[2]"
+ - pause: short
+ - T: "ende exponent"
+
+- name: AfterPower-default
+ tag: power
+ match: "$ClearSpeak_Exponents = 'AfterPower'"
+ replace:
+ - x: "*[1]"
+ - T: "zum exponent"
+ - x: "*[2]"
+ - pause: short
+
+- name: squared
+ tag: power
+ match: "*[2][self::m:mn][.='2'] and $ClearSpeak_Exponents = 'Auto'"
+ replace:
+ - x: "*[1]"
+ - bookmark: "*[2]/@id"
+ - T: "quadrat"
+
+- name: cubed
+ tag: power
+ match: "*[2][self::m:mn][.='3'] and $ClearSpeak_Exponents = 'Auto'"
+ replace:
+ - x: "*[1]"
+ - bookmark: "*[2]/@id"
+ - T: "hoch 3"
+
+- name: simple-integer
+ tag: power
+ match: "*[2][self::m:mn][not(contains(., '.'))]"
+ replace:
+ - x: "*[1]"
+ - T: "hoch"
+ - test:
+ if: "*[2][.>0]"
+ then: {x: "ToOrdinal(*[2])"}
+ else: {x: "*[2]"}
+ - test:
+ if: "$ClearSpeak_Exponents != 'Ordinal'"
+ then: [{T: "hoch"}]
+
+- name: simple-negative-integer
+ tag: power
+ match:
+ - "*[2][self::m:minus and count(*)=1 and"
+ - " *[1][self::m:mn][not(contains(., '.'))]"
+ - " ]"
+ replace:
+ - x: "*[1]"
+ - T: "hoch"
+ - x: "*[2]"
+ - test:
+ if: "$ClearSpeak_Exponents != 'Ordinal'"
+ then: [{T: "hoch"}]
+
+- name: simple-var
+ tag: power
+ match: "*[2][self::m:mi][string-length(.)=1]"
+ replace:
+ - x: "*[1]"
+ - T: "hoch"
+ - x: "*[2]"
+ - pronounce: [{text: "-th"}, {ipa: "θ"}, {sapi5: "th"}, {eloquence: "T"}]
+ - test:
+ if: "$ClearSpeak_Exponents != 'Ordinal'"
+ then: [{T: "hoch"}]
+
+# match nested exponent, where the nested exponent is has the power 2 or 3 (n below)
+# [xxx]^n, - [xxx]^n, [xxx] var^n, -[xxx] var^n
+# where xxx is a number or common fraction (or a var in the first two forms)
+# short of creating a specialized built-in function, I don't see a way to eliminate a lot of repetition in the matches
+# also really bad is that the test of a common fraction is replicated here (four times!)
+# Note: the ClearSpeak doc doesn't say these only apply when the pref is "Auto",
+# but the test cases all fall back to "raised to the exponent" when not "Auto"
+# If these are allowed for non-Auto values, then you end up with "...power power...".
+- # [xxx]^n
+ name: nested-squared-or-cubed
+ tag: power
+ match:
+ - "$ClearSpeak_Exponents = 'Auto' and"
+ - "*[2][self::m:power]["
+ - " *[2][self::m:mn][.='2' or .='3'] and " # exp is 2 or 3
+ # base is mn, mi, common fraction ([xxx] case)
+ - " *[1][self::m:mn or self::m:mi or "
+ - " self::m:fraction[*[1][self::m:mn][not(contains(., '.')) and text()<20] and"
+ - " *[2][self::m:mn][not(contains(., '.')) and 2<= text() and text()<=10]]"
+ - " ]"
+ - " ]"
+ replace:
+ - x: "*[1]"
+ - T: "zum exponent"
+ - x: "*[2]"
+
+- # - [xxx]^n
+ name: nested-negative-squared-or-cubed
+ tag: power
+ match:
+ - "$ClearSpeak_Exponents = 'Auto' and"
+ - " *[2][self::m:minus and count(*)=1 and "
+ - " *[1]/*[1][self::m:power]["
+ - " *[2][self::m:mn][.='2' or .='3'] and " # exp is 2 or 3"
+ # base is mn, mi, common fraction ([xxx] case)
+ - " *[1][self::m:mn or self::m:mi or "
+ - " self::m:fraction[*[1][self::m:mn][not(contains(., '.')) and text()<20] and"
+ - " *[2][self::m:mn][not(contains(., '.')) and 2<= text() and text()<=10]]"
+ - " ]"
+ - " ]"
+ - " ]"
+ replace:
+ - x: "*[1]"
+ - T: "hoch"
+ - x: "*[2]"
+
+- # [xxx] var^n
+ name: nested-var-squared-or-cubed
+ tag: power
+ match:
+ - "$ClearSpeak_Exponents = 'Auto' and"
+ - " *[2][self::m:mrow][count(*)=3][ "
+ - " *[3][self::m:power]["
+ - " *[2][self::m:mn][.='2' or .='3'] and " # exp is 2 or 3
+ - " *[1][self::m:mi]"
+ - " ] and "
+ - " *[2][self::m:mo][.=''] and " # invisible times
+ # base is mn, or common fraction ([xxx] case)
+ - " *[1][self::m:mn or "
+ - " self::m:fraction[*[1][self::m:mn][not(contains(., '.')) and text()<20] and"
+ - " *[2][self::m:mn][not(contains(., '.')) and 2<= text() and text()<=10]]"
+ - " ]"
+ - " ]"
+ replace:
+ - x: "*[1]"
+ - T: "hoch"
+ - x: "*[2]"
+
+- # -[xxx] var^n
+ name: nested-negative-var-squared-or-cubed
+ tag: power
+ match:
+ - "$ClearSpeak_Exponents = 'Auto' and"
+ - " *[2][self::m:mrow][count(*)=3][ "
+ - " *[3][self::m:power]["
+ - " *[2][self::m:mn][.='2' or .='3'] and " # exp is 2 or 3
+ - " *[1][self::m:mi]"
+ - " ] and "
+ - " *[2][self::m:mo][.=''] and " # invisible times
+ - " *[1][self::m:minus and count(*)=1 and "
+ # base is mn, or common fraction ([xxx] case)
+ - " *[1][self::m:mn or "
+ - " self::m:fraction[*[1][self::m:mn][not(contains(., '.')) and text()<20] and"
+ - " *[2][self::m:mn][not(contains(., '.')) and 2<= text() and text()<=10]]"
+ - " ]"
+ - " ]"
+ - " ]"
+ replace:
+ - x: "*[1]"
+ - T: "hoch"
+ - x: "*[2]"
+
+- name: default-exponent-power
+ tag: power
+ match: # directly a superscript or an mrow that contains a superscript
+ - "*[2][self::m:power or self::m:power or self::m:mrow[m:power]]"
+ replace:
+ - x: "*[1]"
+ - T: "zum Exponent"
+ - pause: short
+ - x: "*[2]"
+ - pause: short
+ - T: "Ende Exponent"
+
+- name: default
+ tag: power
+ match: "."
+ replace:
+ - x: "*[1]"
+ - T: "hoch"
+ - x: "*[2]"
+
+#
+# Some rules on mrows
+#
+- # the inference rules lump absolute value and cardinality together, so those rules are implemented here
+ name: ClearSpeak-absolute-value
+ tag: absolute-value
+ match: "."
+ variables: [{WordToSay: "IfThenElse($ClearSpeak_AbsoluteValue = 'Kardinalität', 'Kardinalität', 'Betrag')"}]
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: {T: "der"}
+ - x: "$WordToSay"
+ - T: "von"
+ - x: "*[1]"
+ - test:
+ if: "$ClearSpeak_AbsoluteValue = 'AbsEnd'"
+ then:
+ - pause: short
+ - T: "end"
+ - x: "$WordToSay"
+ - pause: short
+
+- name: set
+ tag: set
+ match: "."
+ replace:
+ - test:
+ - if: "count(*)=0"
+ then: [{T: "leere Menge"}]
+ - else_if: "count(*)=2"
+ then:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: {T: "die"}
+ - T: "leere Menge"
+ - else_if: "count(*[1]/*)=3 and *[1]/*[2][self::m:mo][.=':' or .='|' or .='∣']"
+ then:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: {T: "die"}
+ - T: "Menge"
+ - test:
+ if: $ClearSpeak_Sets != 'woAll'
+ then: [{T: "alle"}]
+ - x: "*[1]/*[1]"
+ - T: "so dass"
+ - x: "*[1]/*[3]"
+ else:
+ - test:
+ if: $ClearSpeak_Sets != 'SilentBracket'
+ then:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: {T: "die"}
+ - T: "Menge"
+ - x: "*[1]"
+
+- # intervals are controlled by a ClearSpeak Preference -- parens/brackets don't have to match, so we avoid IsBracketed
+ # alternatively, we could have four (or ten) rules, but there is a lot of duplication if we do that
+ # this one rule handles all ten cases listed as part $ClearSpeak_Paren = 'Interval'
+ # note that *[2] is an mrow with X, ",", Y, so getting X or Y is a double index
+ name: ClearSpeak-intervals # avoid overriding with default "intervals" name
+ variables:
+ - is_intervals_start_infinity: "*[1][self::m:minus and count(*)=1 and *[1][.='∞']]"
+ - is_intervals_end_infinity: "*[2][.='∞'or (self::m:plus and count(*)=1 and *[1][.='∞'])]"
+ tag: [open-interval, open-closed-interval, closed-interval, closed-open-interval]
+ match: "."
+ replace:
+ - T: "das Intervall"
+ - x: "*[1]"
+ - T: "bis"
+ - x: "*[2]"
+ - pause: short
+ - test:
+ if: "not($is_intervals_start_infinity)"
+ then:
+ - test:
+ if: "starts-with(name(.), 'open')"
+ then: [{T: "no"}]
+ - T: "einschließlich"
+ - x: "*[1]"
+ # logic to deal with [not] arg #1
+ - test:
+ if: "not($is_intervals_start_infinity or $is_intervals_end_infinity)"
+ then_test:
+ - if: "name(.)='open-interval'"
+ then: [{T: "ohne"}]
+ - else_if: "name(.)='closed-interval'"
+ then: [{T: "mit"}]
+ else: [{T: "ohne"}]
+ # some ugly logic dealing with connectives: or, but, but, and (cleaner to be part of next clause?)
+ - test:
+ if: not($is_intervals_end_infinity)
+ then:
+ - test:
+ # there is some asymmetry to the test because of the and/or/but logic above
+ if: not( name(.)='open-interval' or name(.)='closed-interval' ) or $is_intervals_start_infinity
+ then:
+ - test:
+ if: "name(.) = 'open-interval' or name(.) = 'closed-open-interval'"
+ then: [{T: "ohne"}]
+ - T: "einschließlich"
+ - x: "*[2]"
+
+ # onto the [not] [including]... part
+- name: binomial-frac-vector
+ tag: matrix
+ match:
+ - "$ClearSpeak_Matrix = 'Combinatorics' and "
+ - "count(*[1]/*)=1 and count(*)=2"
+ replace:
+ - T: "wähle"
+ - x: "*[1]/*[1]/*" # mtable/mtr/mtd
+ - T: "aus"
+ - x: "*[2]/*[1]/*"
+
+- name: ClearSpeak-default
+ tag: [mtr, mlabeledtr]
+ match: "parent::m:matrix or parent::m:determinant"
+ replace:
+ - pause: medium
+ - T: "zeile"
+ - x: "count(preceding-sibling::*)+1"
+ - test:
+ if: .[self::m:mlabeledtr]
+ then:
+ - T: "mit bezeichnung"
+ - x: "*[1]/*"
+ - pause: short
+ - pause: medium
+ - test:
+ if: .[self::m:mlabeledtr]
+ then: [{x: "*[position()>1]"}]
+ else: {x: "*"}
+
+- name: matrix-default
+ tag: mtd
+ match: "parent::*[parent::m:matrix or parent::m:determinant]"
+ replace:
+ - test:
+ # ClearSpeak normally speaks "column 1" even though it says the row number, which is a waste...
+ # The following is commented out but the count(...)!=0 probably belongs in other rule sets
+ # if: not($IsColumnSilent) and ($ClearSpeak_Matrix = 'SpeakColNum' or count(preceding-sibling::*) != 0)
+ if: "not($IsColumnSilent)"
+ then:
+ - T: "spalte"
+ - x: "count(preceding-sibling::*)+1"
+ - pause: medium
+ - x: "*"
+ - test:
+ # short pause after each element; medium pause if last element in a row; long pause for last element in matrix
+ - if: count(following-sibling::*) > 0
+ then: {pause: short}
+ - else_if: count(../following-sibling::*) > 0
+ then: {pause: medium}
+ else: {pause: long}
+
+- # handle both log and ln
+ name: ClearSpeak-log
+ tag: mrow
+ variables: [{log_is_simple: "IsNode(*[3],'simple')"}]
+ match:
+ - "count(*)=3 and"
+ - "*[1][self::m:mi][.='log' or .='ln'] and"
+ - "*[2][self::m:mo][.='']"
+ replace:
+ - test:
+ if: "$log_is_simple"
+ then_test:
+ - if: "*[1][.='log']"
+ then: [{T: "log"}]
+ - else_if: $ClearSpeak_Log = 'LnAsNaturalLog'
+ then: [{T: "Natürliche Logarithmus"}]
+ else: [{spell: "'ln'"}]
+ else:
+ - test:
+ if: "$Verbosity!='Terse' and not(log_is_simple)"
+ then: {T: "der"}
+ - test:
+ - if: "*[1][.='log']"
+ then: [{T: "log"}]
+ - else_if: $ClearSpeak_Log = 'LnAsNaturalLog'
+ then: [{T: "Natürliche Logarithmus"}]
+ else: [{spell: "'ln'"}]
+ - T: "von"
+ - pause: short
+ - x: "*[3]"
+
+- name: ClearSpeak-multi-line
+ tag: [piecewise, system-of-equations, lines] # these are ignored in favor of the ClearSpeak prefs
+ match: "."
+ variables:
+ # Wikipedia has some tables where all the entire first column is empty (e.g., https://en.wikipedia.org/wiki/List_of_trigonometric_identities)
+ - LineCount: "count(*[not(contains(@data-intent-property, ':continued-row:'))])"
+ - NextLineIsContinuedRow: "false()" # default value
+ - IsColumnSilent: true()
+ replace:
+ - test:
+ - if: $ClearSpeak_MultiLineOverview = 'Auto'
+ then:
+ - x: "$LineCount"
+ - test:
+ - if: "($ClearSpeak_MultiLineLabel = 'Auto' and self::m:piecewise) or $ClearSpeak_MultiLineLabel = 'Case'"
+ then: [t: "fall"] # phrase(this is the first 'case' of three cases)
+ - else_if: "$ClearSpeak_MultiLineLabel = 'Auto' or $ClearSpeak_MultiLineLabel = 'Line' or $ClearSpeak_MultiLineLabel = 'None'" # already dealt with Auto/Case
+ then: [t: "zeile"] # phrase(this is the first 'line' of three lines)
+ - else_if: "$ClearSpeak_MultiLineLabel = 'Constraint'"
+ then: [t: "bedingung"] # phrase(this is the first 'constraint' of three constraints)
+ - else_if: "$ClearSpeak_MultiLineLabel = 'Equation'"
+ then: [t: "gleichung"] # phrase(this is the first 'equation' of three equations)
+ - else_if: "$ClearSpeak_MultiLineLabel = 'Row'"
+ then: [t: "reihe"] # phrase(this is the first 'row' of three rows)
+ - else_if: "$ClearSpeak_MultiLineLabel = 'Step'"
+ then: [t: "stufe"] # phrase(this is the first 'step' of three steps)
+ # else 'None -- don't say anything'
+ - test:
+ - if: "$LineCount != 1"
+ then: [ct: "s"] # plural # phrase(shown by the letter 's')
+ - pause: short
+ - x: "*"
+ - pause: long
+
+- name: ClearSpeak-default-multiline
+ tag: [mtr, mlabeledtr]
+ match: "parent::m:piecewise or parent::m:system-of-equations or parent::m:lines"
+ variables: [NextLineIsContinuedRow: "following-sibling::*[1][contains(@data-intent-property, ':continued-row:')]"]
+ replace:
+ - test:
+ if: "not($LineCount=1 or $ClearSpeak_MultiLineLabel='None' or contains(@data-intent-property, ':continued-row:'))"
+ then:
+ - pause: medium
+ - test:
+ - if: "($ClearSpeak_MultiLineLabel = 'Auto' and parent::m:piecewise) or $ClearSpeak_MultiLineLabel = 'Case'"
+ then: [t: "fall"] # phrase(in this 'case' x is not equal to y)
+ - else_if: "$ClearSpeak_MultiLineLabel = 'Auto' or $ClearSpeak_MultiLineLabel = 'Line'" # already dealt with Auto/Case
+ then: [t: "zeile"] # phrase(the straight 'line' between x and y)
+ - else_if: "$ClearSpeak_MultiLineLabel = 'Constraint'"
+ then: [t: "bedingung"] # phrase(there is a 'constraint' on possible values)
+ - else_if: "$ClearSpeak_MultiLineLabel = 'Equation'"
+ then: [t: "gleichung"] # phrase(the 'equation' pi r squared gives the area of a circle)
+ - else_if: "$ClearSpeak_MultiLineLabel = 'Row'"
+ then: [t: "reihe"] # phrase(the values on the top 'row' are relevant)
+ - else_if: "$ClearSpeak_MultiLineLabel = 'Step'"
+ then: [t: "stufe"] # phrase(this is a 'step' by step process)
+ # else 'None -- don't say anything'
+ - x: "count(preceding-sibling::*[not(contains(@data-intent-property, ':continued-row:'))]) + 1"
+ - test:
+ if: "self::m:mlabeledtr"
+ then:
+ - t: "with label" # phrase(the diagram is complete 'with label')
+ - x: "*[1]/*"
+ - test:
+ - if: "$ClearSpeak_MultiLineLabel='None'"
+ then: [pause: xlong] # need a very long pause with no line labels
+ - else_if: "not(contains(@data-intent-property, ':continued-row:'))"
+ then: [pause: medium]
+ - test:
+ if: "self::m:mlabeledtr"
+ then: [x: "*[position()>1]"]
+ else: [x: "*"]
+
+- name: ClearSpeak_Functions_None
+ tag: mo
+ match:
+ - ".='' and $ClearSpeak_Functions = 'None' and"
+ - "not(preceding-sibling::*[1][IsInDefinition(., 'TrigFunctionNames')])" # Functions=None does not apply to "trig" functions
+ replace:
+ test:
+ if: "$ClearSpeak_ImpliedTimes = 'None'"
+ then: [{T: ""}]
+ else: [{T: "mal"}]
+
+- name: no-times
+ tag: mo
+ match:
+ # Note: this rule is also part of the paren rule so that the parens speak
+ - ".='' and $ClearSpeak_ImpliedTimes = 'None'"
+ replace:
+ - T: ""
+
+- name: ClearSpeak-times
+ tag: mo
+ match:
+ # say "times" when invisible times is followed by parens or a superscript that has a base with parens or "|"s
+ # if we aren't sure if it is times or not, don't say anything
+ - ".='' and (not(@data-function-guess) or $ClearSpeak_Functions = 'None') and ("
+ - " $ClearSpeak_ImpliedTimes = 'MoreImpliedTimes'"
+ - " or "
+ - " following-sibling::*[1]["
+ - " IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|') or "
+ - " self::m:matrix or self::m:determinant or self::m:binomial or" # followed by parens
+ - " ( (self::m:msup or self::m:msub or self::m:msubsup or self::m:power) and " # followed by msup, etc.
+ - " *[1][self::m:mrow[IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|')] or "
+ - " self::m:matrix or self::m:determinant]" # base has parens
+ - " )"
+ - " ]"
+ # other possibility is the preceding element has parens (but not the following)
+ # this is not mentioned in the ClearSpeak rules or examples but seems like it should say "times". E.g, |x| y
+ - " or "
+ - " preceding-sibling::*[1]["
+ - " IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|')]" # followed by parens
+ - " )"
+ replace:
+ - T: "mal"
+
+- name: no-say-parens
+ tag: mrow
+ match:
+ - "parent::*[not(self::m:msup) and not(self::m:msub) and not(self::m:msubsup) and not(self::m:power) and"
+ - " not(self::m:math) ] and " # rule out [x] standing alone
+ - "( IsBracketed(., '(', ')') or IsBracketed(., '[', ']') ) and "
+ - "not( $ClearSpeak_Functions = 'None' and "
+ - " (preceding-sibling::*[1][.=''] or following-sibling::*[1][.='']) ) and "
+ - "not( $ClearSpeak_ImpliedTimes = 'None' and "
+ - " (preceding-sibling::*[1][.=''] or following-sibling::*[1][.='']) ) and "
+ - "( IsNode(*[2], 'simple') )"
+ # missing clause: 'a positive fraction that is spoken as an ordinal
+ # (either by the Ordinal preference or by the default rules)'
+ replace:
+ - x: "*[2]"
+
+- include: "SharedRules/geometry.yaml"
+- include: "SharedRules/linear-algebra.yaml"
+- include: "SharedRules/calculus.yaml"
+- include: "SharedRules/general.yaml"
+- include: "SharedRules/default.yaml"
diff --git a/Rules/Languages/de/SharedRules/calculus.yaml b/Rules/Languages/de/SharedRules/calculus.yaml
new file mode 100644
index 00000000..0a86ce5e
--- /dev/null
+++ b/Rules/Languages/de/SharedRules/calculus.yaml
@@ -0,0 +1,38 @@
+---
+
+- name: divergence
+ tag: divergence
+ match: "."
+ replace:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [t: "divergenz"] # phrase('divergence' from the mean)
+ else: [t: "div"] # phrase('divergence' from the mean)
+ - t: "von" # phrase(systems 'of' linear equations)
+ - test:
+ if: "not(IsNode(*[1], 'leaf'))"
+ then: [pause: short]
+ - x: "*[1]"
+
+- name: curl
+ tag: curl
+ match: "."
+ replace:
+ - t: "rotation von" # phrase(the 'curl of' a field)
+ - test:
+ if: "not(IsNode(*[1], 'leaf'))"
+ then: [pause: short]
+ - x: "*[1]"
+
+- name: gradient
+ tag: gradient
+ match: "."
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [t: "gradient von"] # phrase('divergence' from the mean)
+ else: [t: "grad"] # phrase('divergence' from the mean)
+ - test:
+ if: "not(IsNode(*[1], 'leaf'))"
+ then: [pause: short]
+ - x: "*[1]"
diff --git a/Rules/Languages/de/SharedRules/default.yaml b/Rules/Languages/de/SharedRules/default.yaml
new file mode 100644
index 00000000..7dd92d02
--- /dev/null
+++ b/Rules/Languages/de/SharedRules/default.yaml
@@ -0,0 +1,716 @@
+---
+#default rules shared among several speech rules
+- name: default
+ tag: math
+ match: "."
+ replace:
+ - with:
+ variables:
+ - ClearSpeak_Fractions: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Fractions='Auto', 'EndFrac', $ClearSpeak_Fractions)"
+ - ClearSpeak_AbsoluteValue: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_AbsoluteValue='Auto', 'AbsEnd', $ClearSpeak_AbsoluteValue)"
+ - ClearSpeak_Roots: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Roots='Auto', 'RootEnd', $ClearSpeak_Roots)"
+ - ClearSpeak_Matrix: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Matrix='Auto', 'EndMatrix', $ClearSpeak_Matrix)"
+
+ - MatchingPause: false()
+ # should be set at mtable level, but unknown intents make that impossible to know
+ - IsColumnSilent: false()
+ replace:
+ - test:
+ if: "$MathRate = 100"
+ then: [x: "*"]
+ else:
+ - rate:
+ value: "$MathRate"
+ replace: [x: "*"]
+
+- name: empty-mrow
+ tag: mrow
+ match: "not(*)"
+ replace:
+ - T: "" # say nothing -- placeholder
+
+- name: default
+ tag: mrow
+ match: "."
+ replace:
+ - insert:
+ nodes: "*"
+ replace: [pause: auto]
+
+- name: default
+ tag: mn
+ match: "."
+ replace:
+ - bookmark: "@id"
+ - x: "translate(., $BlockSeparators, '')" # remove digit block separators
+
+- name: default
+ tag: [mo, mtext]
+ match: "."
+ replace:
+ - bookmark: "@id"
+ - x: "text()"
+
+- name: default
+ tag: mi
+ match: "."
+ replace:
+ - bookmark: "@id"
+ - test:
+ - if: "string-length(.) = 1 and text() != '_'" # need unicode.tdl to kick in for single letter tokens
+ then: [x: "text()"]
+ - else_if: "@data-chem-element" # NavMode=Character needs this
+ then: [spell: "text()", pause: "short"]
+ else: [x: "translate(., '-_\u00A0', ' ')"] # from intent literals or from extra spaces added (which get deleted)
+
+- name: default
+ tag: ms
+ match: "."
+ replace:
+ - T: "die Zeichenfolge" # phrase('the string' is long)
+ - pause: short
+ - x: "text()"
+
+- name: default
+ tag: mstyle
+ match: "."
+ replace: [x: "*"]
+
+
+- name: literal-simple
+ # don't include nested fractions. E.g, fraction a plus b over c + 1 end fraction" is ambiguous
+ # by simplistic SimpleSpeak's rules "b over c" is a fraction, but if we say nested fractions
+ # are never simple, then any 'over' applies only to enclosing "fraction...end fraction" pair.
+ tag: mfrac
+ match:
+ - "(IsNode(*[1],'leaf') and IsNode(*[2],'leaf')) and"
+ - "not(ancestor::*[name() != 'mrow'][1]/self::m:fraction)" # FIX: can't test for mrow -- what should be used???
+ replace:
+ - x: "*[1]"
+ - T: "durch" # phrase("the fraction x 'over' y")
+ - x: "*[2]"
+ - pause: short
+
+- name: literal-default
+ tag: mfrac
+ match: "."
+ replace:
+ - T: "beginn" # phrase("'start' fraction x over y end of fraction")
+ - pause: short
+ - x: "*[1]"
+ - test:
+ if: "not(IsNode(*[1],'leaf'))"
+ then: [pause: short]
+ - T: "durch" # phrase("the fraction x 'over' y")
+ - test:
+ if: "not(IsNode(*[2],'leaf'))"
+ then: [pause: short]
+ - x: "*[2]"
+ - pause: short
+ - test:
+ if: "$Impairment = 'Blindness'"
+ then: [T: "ende des bruchs"] # phrase("start of fraction x over y 'end over'")
+ - pause: medium
+
+
+# not sure what really should be said for these since we should not assume they are square roots
+- name: literal-default
+ tag: msqrt
+ match: "."
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # phrase("'the' root of x")
+ - T: "wurzel"
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "aus"] # phrase("the root 'of' x")
+ - x: "*[1]"
+ - pause: short
+ - test:
+ if: "not(IsNode(*[1],'leaf')) or $Impairment = 'Blindness'"
+ then: [T: "ende der wurzel"] # phrase("root of x 'end root symbol'")
+
+# not sure what really should be said for these since we should not assume they are square roots
+- name: literal-default
+ tag: mroot
+ match: "."
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # phrase("'the' root of x")
+ - T: "wurzel mit index " # phrase("the 'root with index' 3 of 5")
+ - x: "*[1]"
+ - pause: short
+ - T: "von" # phrase("the root 'of' x")
+ - x: "*[2]"
+ - pause: short
+ - test:
+ if: "not(IsNode(*[2],'leaf'))"
+ then: [T: "ende der wurzel"] # phrase("root of x 'end root symbol'")
+
+
+- name: simple-sub
+ tag: indexed-by
+ # invisible comma -- want "x 1 when subscript is an integer"
+ match: "count(*)=2 and $Verbosity='Terse' and *[2][self::m:mn and translate(., '.,', '')=.]"
+ replace:
+ - x: "*[1]"
+ - x: "*[2]"
+ - pause: short
+
+- name: no-end-sub
+ tag: indexed-by
+ match: "count(*)=2 and *[2][self::m:mrow and *[2][.='']]"
+ replace:
+ - x: "*[1]"
+ - T: "Index" # phrase(x 'sub' 2)
+ - x: "*[2]"
+ - pause: short
+
+# otherwise let definitions/default infix handle it
+
+- name: literal
+ tag: msub
+ match: "."
+ replace:
+ - x: "*[1]"
+ - test:
+ if: "not($Verbosity='Terse' and *[2][self::m:mn and not(translate(., '.,', '')!=.)])" # just say "x 1" for terse vs "x sub 1"
+ then: [T: "index"] # phrase(x 'sub' 2)
+ - x: "*[2]"
+
+
+- name: literal
+ tag: [msup, msubsup]
+ match: "."
+ replace:
+ - x: "*[1]"
+ - test:
+ if: "name(.)='msubsup'"
+ then:
+ - T: "index" # phrase(x 'sub' 2)
+ - x: "*[2]"
+ - test:
+ if: "*[last()][translate(., '′″‴⁗†‡°*', '')='']"
+ then: [x: "*[last()]"]
+ else_test:
+ if: "ancestor-or-self::*[contains(@data-intent-property, ':literal:')]" # FIX: is this test necessary?
+ then:
+ - T: "hoch" # phrase(x 'super' 2)
+ - x: "*[last()]"
+ - test:
+ if: "not(IsNode(*[last()], 'simple')) or $Impairment = 'Blindness'"
+ then: [T: "ende der hochstellung"] # phrase(x super 2 'end of super')
+ else:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "hochstellung"]
+ else: [T: "hochstellung"]
+ - x: "*[last()]"
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "ende der hochstellung"]
+ else: [T: "ende der hochstellung"]
+
+- name: default
+ tag: munder
+ match: "."
+ replace:
+ - test:
+ if: "not(IsNode(*[1], 'leaf'))"
+ then: [T: "größe"] # phrase(phrase(x 'quantity' with y above it)
+ - x: "*[1]"
+ - T: "mit" # phrase(x 'with' z below it)
+ - x: "*[2]"
+ - T: "darunter" # phrase(x with z 'below' it)
+
+- name: diacriticals
+ tag: mover
+ match: "*[1][self::m:mi] and *[2][translate(., '\u0306\u030c.\u00A8\u02D9\u20DB\u20DC`^ˇ~→¯_', '')='']"
+ replace:
+ - x: "*[1]"
+ - x: "*[2]"
+
+- name: default
+ tag: mover
+ match: "."
+ replace:
+ - test:
+ if: "not(IsNode(*[1], 'leaf'))"
+ then: [T: "größe"] # phrase(phrase(the 'quantity' x plus 1 with y above it)
+ - x: "*[1]"
+ - T: "mit" # phrase(x modified 'with' y above it)
+ - x: "*[2]"
+ - T: "darüber" # phrase(x modified with y 'above' it)
+
+- name: default
+ tag: munderover
+ match: "."
+ replace:
+ - test:
+ if: "not(IsNode(*[1], 'leaf'))"
+ then: [T: "größe"] # phrase(the 'quantity' x plus 1 with y above it)
+ - x: "*[1]"
+ - T: "mit" # phrase(x modified 'with' y above it)
+ - x: "*[2]"
+ - T: "darunter und" # phrase(x modified with y 'below and' y above it)
+ - x: "*[3]"
+ - T: "darüber" # phrase(x modified with y 'above' it)
+
+- name: default
+ # Here we support up to 2 prescripts and up to 4 postscripts -- that should cover all reasonable cases
+ # If there are more, we just dump them out without regard to sup/super :-(
+ # FIX: this could use more special cases
+ # There is (currently) no way in MathCAT to deal with n-ary arguments other than "all" ('*') or an individual entry ('*[1]').
+ tag: mmultiscripts
+ match: "."
+ variables:
+ # computing the number of postscripts is messy because of being optionally present -- we use "mod" to get the count right
+ - Prescripts: "m:mprescripts/following-sibling::*"
+ - NumChildren: "count(*)" # need to stash this since the count is wrong inside '*[...]' below
+ - Postscripts: "*[position()>1 and position() < (last() + ($NumChildren mod 2) -count($Prescripts))]"
+ replace:
+ - x: "*[1]"
+ - test:
+ if: "$Prescripts" # more common case
+ then:
+ - with:
+ variables:
+ - PreSubscript: "IfThenElse($Verbosity='Verbose', 'pre subscript', 'pre sub')"
+ - PreSuperscript: "IfThenElse($Verbosity='Verbose', 'pre superscript', 'pre super')"
+ replace:
+ - test: # only bother announcing if there is more than one prescript
+ if: "count($Prescripts) > 2"
+ then:
+ - T: "durch" # phrase(substitute x 'with' y)
+ - x: "count($Prescripts) div 2"
+ - T: "präskripte" # phrase(in this equation certain 'prescripts' apply)
+ - pause: short
+ - test:
+ if: "not($Prescripts[1][self::m:none])"
+ then:
+ - x: "$PreSubscript"
+ - x: "$Prescripts[1]"
+ - test:
+ if: "not($Prescripts[1][self::m:none] or $Prescripts[2][self::m:none])"
+ then: [T: "und"] # phrase(10 is greater than 8 'and' less than 15)
+ - test:
+ if: "not($Prescripts[2][self::m:none])"
+ then:
+ - x: "$PreSuperscript"
+ - x: "$Prescripts[2]"
+ - pause: short
+ - test:
+ if: "count($Prescripts) > 2" # more common case
+ then:
+ - test:
+ if: "not($Prescripts[3][self::m:none])"
+ then:
+ - x: "$PreSubscript"
+ - x: "$Prescripts[3]"
+ - test:
+ if: "not($Prescripts[3][self::m:none] or $Prescripts[4][self::m:none])"
+ then: [T: "und"] # phrase(10 is grater than 8 'and' less than 15)
+ - test:
+ if: "not($Prescripts[4][self::m:none])"
+ then:
+ - x: "$PreSuperscript"
+ - x: "$Prescripts[4]"
+ - test:
+ if: "count($Prescripts) > 4" # give up and just dump them out so at least the content is there
+ then:
+ - T: "und abwechselnde präskripte" # phrase(in this case there are values 'and alternating prescripts')
+ - x: "$Prescripts[position() > 4]"
+ - T: "ende der präskripte" # phrase(This is where 'end prescripts' occurs)
+ - test:
+ if: "$Postscripts"
+ then:
+ - with:
+ variables:
+ - PostSubscript: "IfThenElse($Verbosity='Verbose', 'subscript', 'sub')"
+ - PostSuperscript: "IfThenElse($Verbosity='Verbose', 'superscript', 'super')"
+ replace:
+ - test: # only bother announcing if there is more than one postscript
+ if: "count($Postscripts) > 2"
+ then:
+ - test:
+ if: "$Prescripts"
+ then: [T: "und"] # phrase(10 is greater than 8 'and' less than 15)
+ - T: "durch" # phrase(substitute x 'with' y)
+ - x: "count($Postscripts) div 2"
+ - T: "postskripte" # phrase(this material includes several 'postscripts')
+ - pause: short
+ - test:
+ if: "not($Postscripts[1][self::m:none])"
+ then:
+ - x: "$PostSubscript"
+ - x: "$Postscripts[1]"
+ - test:
+ if: "not($Postscripts[1][self::m:none] or $Postscripts[2][self::m:none])"
+ then: [T: "und"] # phrase(10 is greater than 8 'and' less than 15)
+ - test:
+ if: "not($Postscripts[2][self::m:none])"
+ then:
+ - x: "$PostSuperscript"
+ - x: "$Postscripts[2]"
+ - test:
+ if: "count($Postscripts) > 2"
+ then:
+ - test:
+ if: "not($Postscripts[3][self::m:none])"
+ then:
+ - x: "$PostSubscript"
+ - x: "$Postscripts[3]"
+ - test:
+ if: "not($Postscripts[3][self::m:none] or $Postscripts[4][self::m:none])"
+ then: [T: "und"] # phrase(10 is greater than 8 'and' less than 15)
+ - test:
+ if: "not($Postscripts[4][self::m:none])"
+ then:
+ - x: "$PostSuperscript"
+ - x: "$Postscripts[4]"
+ - test:
+ if: "count($Postscripts) > 4"
+ then:
+ - test:
+ if: "not($Postscripts[5][self::m:none])"
+ then:
+ - x: "$PostSubscript"
+ - x: "$Postscripts[5]"
+ - test:
+ if: "not($Postscripts[5][self::m:none] or $Postscripts[6][self::m:none])"
+ then: [T: "und"] # phrase(10 is greater than 8 'and' less than 15)
+ - test:
+ if: "not($Postscripts[6][self::m:none])"
+ then:
+ - x: "$PostSuperscript"
+ - x: "$Postscripts[6]"
+ - test:
+ if: "count($Postscripts) > 6"
+ then:
+ - test:
+ if: "not($Postscripts[7][self::m:none])"
+ then:
+ - x: "$PostSubscript"
+ - x: "$Postscripts[7]"
+ - test:
+ if: "not($Postscripts[7][self::m:none] or $Postscripts[8][self::m:none])"
+ then: [T: "und"] # phrase(10 is less than 15 'and' greater than 5)
+ - test:
+ if: "not($Postscripts[8][self::m:none])"
+ then:
+ - x: "$PostSuperscript"
+ - x: "$Postscripts[8]"
+ - test:
+ if: "count($Postscripts) > 8" # give up and just dump them out so at least the content is there
+ then:
+ - T: "und wechselnde skripte" # phrase(this situation involves complexities 'and alternating scripts')
+ - x: "$Postscripts[position() > 8]"
+ - T: "ende der skripte" # phrase(At this point 'end scripts' occurs)
+
+- name: default
+ tag: mtable
+ variables:
+ - IsColumnSilent: "false()"
+ - NumColumns: "count(*[1]/*) - IfThenElse(*/self::m:mlabeledtr, 1, 0)"
+ match: "."
+ replace:
+ - T: "tabelle mit" # phrase(the 'table with' 3 rows)
+ - x: count(*)
+ - test:
+ if: count(*)=1
+ then: [T: "zeile"] # phrase(the table with 1 'row')
+ else: [T: "zeilen"] # phrase(the table with 3 'rows')
+ - T: "und" # phrase(the table with 3 rows 'and' 4 columns)
+ - x: "$NumColumns"
+ - test:
+ if: "NumColumns=1"
+ then: [T: "spalte"] # phrase(the table with 3 rows and 1 'column')
+ else: [T: "spalten"] # phrase(the table with 3 rows and 4 'columns')
+ - pause: long
+ - x: "*"
+
+- name: default
+ # callers/context should do that.
+ # this may get called from navigation -- in that case, there is no context to speak the row #, so don't do it
+ tag: [mtr, mlabeledtr]
+ match: "."
+ replace:
+ - pause: medium
+ - T: "zeile" # phrase(the first 'row' of a matrix)
+ - x: "count(preceding-sibling::*)+1"
+ - test:
+ if: "self::m:mlabeledtr"
+ then:
+ - T: "mit der bezeichnung" # phrase(the line 'with label' first equation)
+ - x: "*[1]/*"
+ - pause: short
+ - pause: medium
+ - test:
+ if: "self::m:mlabeledtr"
+ then: [x: "*[position()>1]"]
+ else: {x: "*"}
+
+- name: default
+ tag: mtd
+ match: "."
+ replace:
+ - test:
+ # ClearSpeak normally speaks "column 1" even though it says the row number, which is a waste...
+ # The following is commented out but the count(...)!=0 probably belongs in other rule sets
+ # if: not($IsColumnSilent) and ($ClearSpeak_Matrix = 'SpeakColNum' or count(preceding-sibling::*) != 0)
+ if: "not($IsColumnSilent)"
+ then:
+ - T: "spalte" # phrase(the first 'column' of the matrix)
+ - x: "count(preceding-sibling::*)+IfThenElse(parent::m:mlabeledtr, 0, 1)"
+ - pause: medium
+ - x: "*"
+ - test:
+ # short pause after each element; medium pause if last element in a row; long pause for last element in matrix
+ - if: count(following-sibling::*) > 0
+ then: [pause: short]
+ - else_if: count(../following-sibling::*) > 0
+ then: [pause: medium]
+ else: [pause: long]
+
+
+- name: empty-box
+ # The ordering below is the order in which words come out when there is more than one value
+ # Note: @notation can contain more than one value
+ tag: menclose
+ match: "@notation='box' and *[self::m:mtext and .=' ']"
+ replace:
+ - T: "leere box" # phrase(the 'empty box' contains no values)
+
+- name: default
+ # The ordering below is the order in which words come out when there is more than one value
+ # Note: @notation can contain more than one value
+ tag: menclose
+ match: "."
+ replace:
+ - test:
+ if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' box ')]"
+ then: [T: "box", pause: short] # phrase(the 'box' around the expression)
+ - test:
+ if: ".[contains(@notation,'roundedbox')]"
+ then: [T: "runde box", pause: short] # phrase(the 'round box' around the expression)
+ - test:
+ if: ".[contains(@notation,'circle')]"
+ then: [T: "kreis", pause: short] # phrase(the 'circle' around the expression)
+ - test:
+ if: ".[ contains(concat(' ', normalize-space(@notation), ' '), ' left ') or contains(concat(' ', normalize-space(@notation), ' '), ' right ') or contains(@notation,'top') or contains(@notation,'bottom') ]"
+ then:
+ - T: "linie" # phrase(draw a straight 'line' on the page)
+ - test:
+ if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' left ')]"
+ then: [T: "links", pause: short] # phrase(line on 'left' of the expression)
+ - test:
+ if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' right ')]"
+ then: [T: "rechts", pause: short] # phrase(line on 'right' of the expression)
+ - test:
+ if: ".[contains(@notation,'top')]"
+ then: [T: "oben", pause: short] # phrase(line on 'top' of the expression)
+ - test:
+ if: ".[contains(@notation,'bottom')]"
+ then: [T: "unten", pause: short] # phrase(line on the 'bottom' of the expression)
+ - test:
+ if: ".[ contains(@notation,'updiagonalstrike') or contains(@notation,'downdiagonalstrike') or contains(@notation,'verticalstrike') or contains(@notation,'horizontalstrike') ]"
+ then:
+ - test:
+ if: ".[contains(@notation,'updiagonalstrike') and contains(@notation,'downdiagonalstrike')]"
+ then: [spell: "'x'", pause: short] # seems better to say 'x cross out' than 'up diagonal, down diagonal cross out'
+ else:
+ - test:
+ if: ".[contains(@notation,'updiagonalstrike')]"
+ then: [T: "diagonal nach oben", pause: short] # phrase(the line runs 'up diagonal')
+ - test:
+ if: ".[contains(@notation,'downdiagonalstrike')]"
+ then: [T: "diagonal nach unten", pause: short] # phrase(the line runs 'down diagonal')
+ - test:
+ if: ".[contains(@notation,'verticalstrike')]"
+ then: [T: "vertikal", pause: short] # phrase(the line is 'vertical')
+ - test:
+ if: ".[contains(@notation,'horizontalstrike')]"
+ then: [T: "horizontal", pause: short] # phrase(the line is 'horizontal')
+ - T: "durchstreichen" # phrase(please 'cross out' the incorrect answer)
+ - pause: short
+ - test:
+ if: ".[contains(@notation,'uparrow')]"
+ then: [T: "pfeil nach oben", pause: short] # phrase(direction is shown by the 'up arrow')
+ - test:
+ if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' downarrow ')]"
+ then: [T: "pfeil nach unten", pause: short] # phrase(the trend is shown by the 'down arrow')
+ - test:
+ if: ".[contains(@notation,'leftarrow')]"
+ then: [T: "pfeil nach links", pause: short] # phrase(the 'left arrow' indicates going back)
+ - test:
+ if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' rightarrow ')]"
+ then: [T: "pfeil nach rechts", pause: short] # phrase(the 'right arrow' indicates moving forward)
+ - test:
+ if: ".[contains(@notation,'northeastarrow')]"
+ then: [T: "pfeil nach nordost", pause: short] # phrase(direction is indicated by the 'northeast arrow')
+ - test:
+ if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' southeastarrow ')]"
+ then: [T: "pfeil nach südost", pause: short] # phrase(direction is shown by the 'southeast arrow')
+ - test:
+ if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' southwestarrow ')]"
+ then: [T: "pfeil nach südwest", pause: short] # phrase(direction is shown by the 'southwest arrow')
+ - test:
+ if: ".[contains(@notation,'northwestarrow')]"
+ then: [T: "pfeil nach nordwest", pause: short] # phrase(direction is shown by the 'northwest arrow')
+ - test:
+ if: ".[contains(@notation,'updownarrow')]"
+ then: [T: "doppelpfeil nach oben und unten", pause: short] # phrase(upward movement is indicated by the 'double ended vertical arrow')
+ - test:
+ if: ".[contains(@notation,'leftrightarrow')]"
+ then: [T: "doppelpfeil nach links und rechts", pause: short] # phrase(progress is indicated by the 'double ended horizontal arrow')
+ - test:
+ if: ".[contains(@notation,'northeastsouthwestarrow')]"
+ then: [T: "doppelpfeil diagonal nach oben", pause: short] # phrase(trend is indicated by the 'double ended up diagonal arrow')
+ - test:
+ if: ".[contains(@notation,'northwestsoutheastarrow')]"
+ then: [T: "doppelpfeil diagonal nach unten", pause: short] # phrase(trend is indicated by the 'double ended down diagonal arrow')
+ - test:
+ if: ".[contains(@notation,'actuarial')]"
+ then: [T: "versicherungsmathematische symbol", pause: short] # phrase(the 'actuarial symbol' represents a specific quantity)
+ - test:
+ if: ".[contains(@notation,'madrub')]"
+ then: [T: "arabisches faktor-symbol", pause: short] # phrase(the 'arabic factorial symbol' represents a factorial operation)
+ - test:
+ if: ".[contains(@notation,'phasorangle')]"
+ then: [T: "phasenwinkel", pause: short] # phrase(the 'phasor angle' is used to measure electrical current)
+ - test:
+ if: ".[contains(@notation,'longdiv') or not(@notation) or normalize-space(@notation) ='']" # default
+ then: [T: "symbol für schriftliche division", pause: short] # phrase(the 'long division symbol' indicates a long division calculation)
+ - test:
+ if: ".[contains(@notation,'radical')]"
+ then: [T: "quadratwurzel", pause: short] # phrase(5 is the 'square root' of 25)
+ - T: "einschließen" # phrase(parentheses are 'enclosing' part of the equation)
+ - test:
+ if: "*[self::m:mtext and .=' ']"
+ then: [T: "leerzeichen"] # otherwise there is complete silence # phrase(there is a 'space' between the words)
+ else: [x: "*"]
+ - test:
+ if: "$Impairment = 'Blindness' and ( $SpeechStyle != 'SimpleSpeak' or not(IsNode(*[1], 'leaf')) )"
+ then: [T: "ende der einschliessung"] # phrase(reached the 'end enclosure' point)
+ - pause: short
+
+- name: semantics
+ tag: "semantics"
+ match: "*[@encoding='MathML-Presentation']"
+ replace:
+ - x: "*[@encoding='MathML-Presentation']/*[1]"
+
+- name: semantics-default
+ tag: "semantics"
+ match: .
+ replace:
+ - x: "*[1]"
+
+- name: apply-function
+ tag: "apply-function"
+ match: .
+ replace:
+ - x: "*[1]"
+ - T: "angewandt auf" # phrase(the function sine 'applied to' x plus y)
+ - x: "*[2]"
+
+
+# Here are the intent hints that need to be handled: 'prefix' | 'infix' | 'postfix' | 'function' | 'silent'
+- name: silent-intent
+ # uncaught intent -- the args have been inserted in the order of speech
+ tag: "*"
+ match: "count(*)>0 and contains(@data-intent-property, ':silent:')"
+ replace:
+ - x: "*"
+ - test:
+ if: "IsNode(., '2D')"
+ then: [pause: short]
+ else: [pause: auto]
+
+- name: prefix-intent
+ # uncaught intent -- the args have been inserted in the order of speech
+ tag: "*"
+ match: "count(*)>0 and contains(@data-intent-property, ':prefix:')"
+ replace:
+ - x: "SpeakIntentName(name(.), $Verbosity, 'prefix')"
+ - x: "*"
+ - test:
+ if: "not( IsBracketed(., '', '') or IsNode(*[last()], 'simple') )"
+ then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'prefix', 'end')"]
+ - test:
+ if: "IsNode(., '2D')"
+ then: [pause: short]
+ else: [pause: auto]
+
+- name: postfix-intent
+ # uncaught intent -- the args have been inserted in the order of speech
+ tag: "*"
+ match: "count(*)>0 and contains(@data-intent-property, ':postfix:')"
+ replace:
+ - test:
+ if: "$Impairment = 'Blindness' and not( IsBracketed(., '', '') or IsNode(*[1], 'simple') )"
+ then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'postfix', 'start')"]
+ - x: "*"
+ - x: "SpeakIntentName(name(.), $Verbosity, 'postfix')"
+
+- name: infix-intent
+ # uncaught intent -- the args have been inserted in the order of speech
+ tag: "*"
+ match: "count(*)>0 and contains(@data-intent-property, ':infix:')"
+ replace:
+ - test:
+ if: "$Impairment = 'Blindness' and not( IsBracketed(., '', '') or IsNode(*[1], 'simple') )"
+ then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'infix', 'start')"]
+ - test:
+ if: "count(*) = 1" # in cases such as continued-row, plus/minus might have just one child
+ then:
+ - x: "SpeakIntentName(name(.), $Verbosity, 'infix')"
+ - pause: auto
+ - x: "*[1]"
+ else:
+ - insert:
+ nodes: "*"
+ replace: [x: "SpeakIntentName(name(.), $Verbosity, 'infix')", pause: auto]
+ - test:
+ if: "$Impairment = 'Blindness' and not( IsBracketed(., '', '') or IsNode(*[last()], 'simple') )"
+ then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'infix', 'end')"]
+ - test:
+ if: "IsNode(., '2D')" # add (probably) a slightly longer pause if this came from a 2D node
+ then: [pause: short]
+ else: [pause: auto]
+
+- name: function-intent
+ # uncaught intent -- speak as foo of arg1 comma arg2 .... The MathML spec requires arguments to functions
+ tag: "*"
+ match: "count(*)>0"
+ replace:
+ - x: "SpeakIntentName(name(.), $Verbosity, 'function')"
+ - test:
+ if: "$Verbosity != 'Terse' and not(contains(@data-intent-property, ':literal:')) and
+ not(count(*)=2 and (IsInDefinition(*[1], 'TrigFunctionNames') or IsInDefinition(name(.), 'TerseFunctionNames')) and IsNode(*[2], 'simple'))"
+ then: [T: "von", pause: auto] # phrase(sine 'of' 5)
+ - insert:
+ nodes: "*"
+ replace:
+ - test:
+ if: "not(contains(@data-intent-property, ':literal:'))"
+ then: [x: "','"]
+ - pause: auto
+ - test:
+ # speak "end ..." if not bracketed or last child is not simple and not last node
+ if: "$Impairment = 'Blindness' and not(*[last()][IsBracketed(., '', '') or IsNode(., 'simple')] )"
+ then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'function', 'end')"]
+ - test:
+ if: "IsNode(., '2D')"
+ then: [pause: short]
+ else: [pause: auto]
+
+
+- name: default-text
+ # unknown leaf -- just speak the text -- could be a literal intent
+ tag: "*"
+ match: "."
+ replace:
+ - x: "translate(name(), '-_', ' ')"
diff --git a/Rules/Languages/de/SharedRules/general.yaml b/Rules/Languages/de/SharedRules/general.yaml
new file mode 100644
index 00000000..27b95dda
--- /dev/null
+++ b/Rules/Languages/de/SharedRules/general.yaml
@@ -0,0 +1,1056 @@
+---
+
+# number-sets are a little messy in that the base was converted to a number-set, so we have to match that (simple) case last
+- name: pos-neg-number-sets
+ tag: number-sets
+ match: "count(*)=2 and *[2][.='+' or .='-']"
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then:
+ - T: "die" # phrase('the' square root of 25 equals 5)
+ - bookmark: "*[2]/@id"
+ - test:
+ - if: "*[2][.='+']"
+ then: [T: "positiven"] # phrase(set of all 'positive' integers less than 10)
+ else: [T: "negativen"] # phrase(set of all 'negative' integers less than minus 10)
+ - bookmark: "*[1]/@id"
+ - test:
+ - if: "*[1][.='ℂ']"
+ then: [T: "komplexe zahlen"] # phrase('complex numbers' consist of two parts)
+ - else_if: "*[1][.='ℕ']"
+ then: [T: "natürliche zahlen"] # phrase('natural numbers' are numbers from 1 to infinity)
+ - else_if: "*[1][.='ℚ']"
+ then: [T: "rationale zahlen"] # phrase('rational numbers' are the fraction of 2 integers)
+ - else_if: "*[1][.='ℝ']"
+ then: [T: "reelle zahlen"] # phrase('real numbers' can be both positive and negative)
+ - else_if: "*[1][.='ℤ']"
+ then: [T: "ganze zahlen"] # phrase(positive 'integers' are natural numbers above 0)
+ else: [x: "*[1][text()]"] # shouldn't happen
+
+- name: dimension-number-sets
+
+ # should be single digit integer at this point (e.g, R^3)
+ tag: number-sets
+ match: "count(*)=2"
+ replace:
+ - bookmark: "*[1]/@id"
+ - test:
+ - if: "*[1][.='ℂ']"
+ then: [T: "c"] # phrase(the letter 'C' used to represent complex number)
+ - else_if: "*[1][.='ℕ']"
+ then: [T: "n"] # phrase(the letter 'N' may represent natural numbers)
+ - else_if: "*[1][.='ℚ']"
+ then: [T: "q"] # phrase(the letter 'Q' may represent rational numbers)
+ - else_if: "*[1][.='ℝ']"
+ then: [T: "r"] # phrase(the letter 'R' may represent real numbers)
+ - else_if: "*[1][.='ℤ']"
+ then: [T: "z"] # phrase(the letter 'Z' may represent integers)
+ else: [x: "*[1][text()]"] # shouldn't happen
+ - bookmark: "*[2]/@id"
+ - x: "*[2]"
+
+- name: simple-number-sets
+ tag: number-sets
+ match: "count(*)=0"
+ replace:
+ - bookmark: "@id"
+ - test:
+ - if: ".='ℂ'"
+ then: [T: "die komplexen zahlen"] # phrase('the complex numbers' include 2 parts)
+ - else_if: ".='ℕ'"
+ then: [T: "die 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)
+ - else_if: ".='ℝ'"
+ then: [T: "die 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)
+ else: [x: "text()"] # shouldn't happen
+
+- name: real-part
+ tag: real-part
+ match: "."
+ replace:
+ - bookmark: "@id"
+ - T: "realteil" # phrase('the real part' of a complex number does not include the imaginary part)
+
+- name: imaginary-part
+ tag: imaginary-part
+ match: "."
+ replace:
+ - bookmark: "@id"
+ - T: "imaginärteil" # phrase('the imaginary part' is part of a complex number)
+
+# rules on scripted vertical bars ('evaluated at')
+- name: evaluated-at-2
+ tag: evaluate
+ match: "count(*)=2"
+ replace:
+ - x: "*[1]"
+ - pause: auto
+ - T: "ausgewertet bei" # phrase(results were 'evaluated at' a given point)
+ - pause: auto
+ - x: "*[2]"
+
+- name: evaluated-at-3
+ tag: evaluate
+ match: "count(*)=3"
+ replace:
+ - x: "*[1]"
+ - pause: auto
+ - T: "ausgewertet zwischen" # phrase(results were 'evaluated at' this point)
+ - pause: auto
+ - x: "*[3]"
+ - T: "und" # phrase(this result is 'minus the same expression evaluated at' an earlier point)
+ - x: "*[2]"
+
+- name: permutation
+ # Not a default because the order of the args is reversed
+ tag: pochhammer
+ match: "count(*)=2 and contains(@data-intent-property, ':infix:')"
+ replace:
+ - x: "*[2]"
+ - T: "permutationen von" # phrase(the solution involves several 'permutations of' values)
+ - x: "*[1]"
+
+- name: intervals
+ tag: [open-interval, open-closed-interval, closed-interval, closed-open-interval]
+ match: "count(*)=2"
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then:
+ - T: "die" # phrase('the' square root of 25 equals 5)
+ - x: "translate(name(.),'-', ' ')"
+ - test:
+ if: "$Verbosity!='Terse'"
+ then:
+ - T: "von" # phrase(subtracting 5 'from' 10 gives 5)
+ - x: "*[1]"
+ - T: "bis" # phrase(adding 6 'to' 6 equals 12)
+ - x: "*[2]"
+ else:
+ - x: "*[1]"
+ - T: "komma" # phrase(use a 'comma' to divide large numbers or as a decimal point)
+ - x: "*[2]"
+
+- name: default-point
+ tag: point
+ match: "count(*)=2"
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then:
+ - T: "die" # phrase('the' square root of 25 equals 5)
+ - T: "punkt" # phrase(a decimal 'point' indicates the fraction component of a number)
+ - x: "*[1]"
+ - T: "komma" # phrase(use a 'comma' to divide large numbers or as a decimal point)
+ - x: "*[2]"
+
+- name: bigop-both
+ tag: large-op
+ match: "count(*) = 3"
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # phrase('the' square root of 25 equals 5)
+ - x: "*[1]"
+ - T: "von" # phrase(subtracting 5 'from' 10 gives 5)
+ - x: "*[2]"
+ - T: "bis" # phrase(adding 6 'to' 6 equals 12)
+ - x: "*[3]"
+ - test:
+ if: "following-sibling::*"
+ then: [T: "von"] # phrase(the square root 'of' 25 equals 5)
+
+- name: bigop-under
+ tag: large-op
+ match: "count(*)=2"
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # phrase('the' square root of 25 equals 5)
+ - x: "*[1]"
+ - T: "durch" # phrase(2 'over' 3 equals two thirds)
+ - x: "*[2]"
+ - test:
+ if: "following-sibling::*"
+ then: [T: "von"] # phrase(the square root 'of' 25 equals 5)
+
+- name: largeop
+ tag: mrow
+ match: "count(*)=2 and IsInDefinition(*[1], 'LargeOperators')"
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # phrase('the' square root of 25 equals 5)
+ - x: "*[1]"
+ - T: "von" # phrase(the square root 'of' 25 equals 5)
+ - x: "*[2]"
+
+- name: repeating-decimal
+ tag: repeating-decimal
+ match: "."
+ replace:
+ - x: "*[1]"
+ - T: "mit wiederholten ziffern" # phrase('with repeating digits')
+ - spell: "*[2]"
+
+- name: msubsup-skip-super
+ # handles single, double, etc., prime
+ tag: [skip-super, say-super]
+ match: "count(*)=3"
+ replace:
+ - x: "*[1]"
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "index"] # phrase(a 'subscript' may be used to indicate an index)
+ else: [T: "sub"] # phrase(the result is 'sub' optimal)
+ - x: "*[2]"
+ - test:
+ if: "not(IsNode(*[2],'leaf') and $Impairment = 'Blindness')"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "ende -index"] # phrase(this is the 'end subscript' position)
+ else: [T: "ende -sub"] # phrase(this is the 'end sub' position)
+ - pause: short
+ else_test:
+ if: "*[2][self::m:mi]" # need a pause in "x sub k prime" so the prime is not associated with the 'k'
+ then: [pause: short]
+ - test:
+ if: "name(.)='say-super'"
+ then_test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "superscript"] # phrase(a 'superscript' number indicates raised to a power)
+ else: [T: "super"] # phrase(this is a 'super' set of numbers)
+ - x: "*[3]"
+ - pause: short
+
+
+# the order of matching is
+# 1. does it match the base of an SI unit
+# 2. does it match an English unit (if in an English language)
+# 3. does it match an SI prefix followed by an SI that accepts SI prefixes
+# Due to this order, some things like "ft" and "cd" mean "feet" vs "femto-tonnes" and "pints" vs "pico-tonnes"
+- name: unit
+ tag: unit
+ match: "$Verbosity != 'Terse' and contains(@data-intent-property, ':unit')"
+ variables:
+ # If the coefficient is singular, we don't add the plural ending. Finding the coefficient is tricky
+ # Normal case (A) "3m" (parents is mrow), but could also be (B) "3 m^2" (etc.) (parent is power/mrow)
+ # But it might be in a fraction as (C) "3 m/s" (parent is fraction/mrow) or (D) "3 m^2/s^2" (parent is power/fraction/mrow)
+ # or even (E) {3 m^2}/s (parent is power/mrow)
+ # If in a fraction, only look in the numerator to find the coefficient
+ # Note: we have a special case for pseudo-scripts like "°" (degrees) which are not powers -- they are essentially "1^°"
+ # The following "IfThenElse" logic returns the mrow that potentially contains the coefficient, if it exists
+ # The tests are in the order A, B & E, C, D
+ - MRowForCoefficient: "IfThenElse(parent::m:mrow, parent::m:mrow,
+ IfThenElse(parent::m:power, ancestor::*[2][self::m:mrow],
+ IfThenElse(parent::m:fraction and not(preceding-sibling::*), ancestor::*[2][self::m:mrow],
+ IfThenElse(parent::m:power[parent::m:fraction and not(preceding-sibling::*)], ancestor::*[3][self::m:mrow], false()) ) ) )"
+ - IsSingular: "(not(DEBUG($MRowForCoefficient)) and parent::*[name(.)!='skip-super' or *[1][.=1]]) or
+ ($MRowForCoefficient and $MRowForCoefficient[(count(*) = 3 and *[1][self::m:mn and .=1] and *[2]='\u2062')])"
+ - Prefix: "''"
+ - Word: "''"
+ replace:
+ - bookmark: "@id"
+ - test:
+ # is the whole string match a SI Unit without a prefix?
+ - if: "DefinitionValue(., 'Speech', 'SIUnits') != ''"
+ then:
+ - set_variables: [Word: "DefinitionValue(., 'Speech', 'SIUnits')"]
+ - else_if: "DefinitionValue(., 'Speech', 'UnitsWithoutPrefixes') != ''"
+ then:
+ - set_variables: [Word: "DefinitionValue(., 'Speech', 'UnitsWithoutPrefixes')"]
+ - else_if: "DefinitionValue(., 'Speech', 'EnglishUnits') != ''"
+ then:
+ - set_variables: [Word: "DefinitionValue(., 'Speech', 'EnglishUnits')"]
+
+ # do the first two chars match "da" and the remainder match an SIUnit
+ - else_if: "string-length(.) >= 3 and
+ substring(., 1, 2) = 'da' and
+ DefinitionValue(substring(., 3), 'Speech', 'SIUnits') != ''"
+ then:
+ - set_variables:
+ - Prefix: "DefinitionValue('da', 'Speech', 'SIPrefixes')"
+ - Word: "DefinitionValue(substring(., 3), 'Speech', 'SIUnits')"
+
+ # does the first char match a prefix and the remainder match an SIUnit
+ - else_if: "string-length(.) >= 2 and
+ DefinitionValue(substring(., 1, 1), 'Speech', 'SIPrefixes') != '' and
+ DefinitionValue(substring(., 2), 'Speech', 'SIUnits') != ''"
+ then:
+ - set_variables:
+ - Prefix: "DefinitionValue(substring(., 1, 1), 'Speech', 'SIPrefixes')"
+ - Word: "DefinitionValue(substring(., 2), 'Speech', 'SIUnits')"
+
+ # not a known unit -- just speak the text, possibly as a plural
+ - else:
+ - set_variables:
+ - Word: "text()"
+
+ # somewhat complicated logic to avoid spaces around "-" as in "centi-grams" vs "centi - grams" -- probably doesn't matter
+ - test:
+ if: "$Prefix = ''"
+ then:
+ - test:
+ - if: "$IsSingular"
+ # 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')"]
+ else: [x: "$Word", ct: "s"]
+ else:
+ - x: "$Prefix"
+ - ct: "-"
+ - test:
+ - if: "$IsSingular"
+ # 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'))"]
+ else: [x: "concat('\uF8FE', $Word)", ct: "s"]
+
+
+- name: sin
+ tag: mi
+ match: ".='sin'"
+ replace:
+ - bookmark: "@id"
+ - T: "sinus" # phrase(the 'sine' of the angle)
+- name: cos
+ tag: mi
+ match: ".='cos'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "cos"] # phrase('cos' is the abbreviation for cosine)
+ else: [T: "kosinus"] # phrase(find the 'cosine' in a right-angle triangle)
+- name: tan
+ tag: mi
+ match: ".='tan' or .='tg'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "tan"] # phrase(the 'tan' is the ratio of the opposite to the adjacent side of a right-angled triangle)
+ else: [T: "tangens"] # phrase(a 'tangent' is a straight line that touches a curve)
+- name: sec
+ tag: mi
+ match: ".='sec'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "sekans"] # phrase(to 'seek' a solution)
+ else: [T: "sekans"] # phrase(a 'secant' intersects a curve at two or more points)
+- name: csc
+ tag: mi
+ match: ".='csc'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "kosekans"] # phrase(we will 'cosecant' a solution)
+ else: [T: "kosekans"] # phrase(the 'cosecant' is the reciprocal of the secant)
+- name: cot
+ tag: mi
+ match: ".='cot'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "kotangens"] # phrase(find the 'cotangent' in a right-angle triangle)
+ else: [T: "kotangens"] # phrase(the 'cotangent' is the reciprocal of the tangent)
+
+- name: sinh
+ tag: mi
+ match: ".='sinh'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "sinch"] # phrase(the word 'sinch' is an abbreviation for hyperbolic sine)
+ else: [T: "hyperbolischer sinus"] # phrase(the 'hyperbolic sine' is used in mathematics)
+- name: cosh
+ tag: mi
+ match: ".='cosh'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "cosh"] # phrase('cosh' is an abbreviation of hyperbolic cosine)
+ else: [T: "hyperbolischer cosinus"] # phrase(the 'hyperbolic cosine' is a mathematical function)
+- name: tanh
+ tag: mi
+ match: ".='tanh'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "tanch"] # phrase('tanch' is shorthand for hyperbolic tangent)
+ else: [T: "hyperbolischer tangens"] # phrase('hyperbolic tangent' is a mathematical function)
+- name: sech
+ tag: mi
+ match: ".='sech'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "sheck"] # phrase('sheck' is shorthand for hyperbolic secant)
+ else: [T: "hyperbolischer sekans"] # phrase('hyperbolic secant' is a mathematical function)
+- name: csch
+ tag: mi
+ match: ".='csch'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "cosheck"] # phrase('cosheck' is shorthand for hyperbolic cosecant)
+ else: [T: "hyperbolischer kosekans"] # phrase('hyperbolic cosecant' is a mathematical function)
+- name: coth
+ tag: mi
+ match: ".='coth'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "cotanch"] # phrase('cotanch' is shorthand for hyperbolic cotangent)
+ else: [T: "hyperbolischer kotangens"] # phrase(the 'hyperbolic cotangent' is a mathematical function)
+- name: exponential
+ tag: mi
+ match: ".='exp'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "exp"] # phrase('exp' means exponential function)
+ else: [T: "exponent"] # phrase('exponential' function)
+- name: covariance
+ tag: mi
+ match: ".='Cov'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "cov"] # phrase('Cov' is shorthand for the covariance function)
+ else: [T: "kovarianz"] # phrase('covariance' function)
+
+-
+ name: log # handle both log and ln (if in an mrow, 'intents' are used)
+ tag: mi
+ match: ".='log' or .='ln'"
+ replace:
+ - bookmark: "@id"
+ - test:
+ - if: "$Verbosity!='Terse'"
+ then: [T: "der"] # phrase('the' logarithm function is used in mathematics)
+
+ - test:
+ - if: ".= 'log'"
+ then: [T: "log"] # phrase(the 'log' function is used in mathematics)
+ - else_if: "$Verbosity='Terse'"
+ then: [spell: "'ln'"]
+ else: [T: "natürliche logarithmus"] # phrase(the 'natural log' function is used in mathematics)
+
+
+- name: multi-line
+ # that eliminates the need for the if: else_if: ...
+ # IDEA: set a variable with the word to say for the row (e.g., RowLabel = Row/Case/Line/...)
+ tag: [piecewise, system-of-equations, lines]
+ match: "."
+ variables:
+ # Wikipedia has some tables where all the entire first column is empty (e.g., https://en.wikipedia.org/wiki/List_of_trigonometric_identities)
+ - LineCount: "count(*[not(contains(@data-intent-property, ':continued-row:'))])"
+ - NextLineIsContinuedRow: "false()" # default value
+ - IsColumnSilent: true()
+ replace:
+ - x: "$LineCount"
+ - test:
+ - if: "self::m:piecewise"
+ then: [T: "fall"] # phrase(this is the first 'case' of three cases)
+ - else_if: "self::m:system-of-equations"
+ then: [T: "gleichung"] # phrase(this is the first 'equation' of three equations)
+ else: [T: "zeile"] # phrase(this is the first 'line' of three lines)
+ - test:
+ - if: "$LineCount != 1"
+ then: [ct: "s"] # plural
+ - pause: short
+ - x: "*"
+ - pause: long
+
+
+- name: default-multiline
+ tag: [mtr, mlabeledtr]
+ match: "parent::m:piecewise or parent::m:system-of-equations or parent::m:lines"
+ variables: [NextLineIsContinuedRow: "following-sibling::*[1][contains(@data-intent-property, ':continued-row:')]"]
+ replace:
+ - test:
+ if: "not($LineCount=1 or contains(@data-intent-property, ':continued-row:'))"
+ then:
+ - pause: medium
+ - test:
+ - if: "parent::m:piecewise"
+ then: [T: "fall"] # phrase('case' 1 of 10 cases)
+ - else_if: "parent::m:system-of-equations"
+ then: [T: "gleichung"] # phrase('equation' 1 of 10 equations)
+ else: [T: "zeile"] # phrase('line 1 of 10 lines)
+ - x: "count(preceding-sibling::*[not(contains(@data-intent-property, ':continued-row:'))]) + 1"
+ - test:
+ if: "self::m:mlabeledtr"
+ then:
+ - T: "mit der bezeichnung" # phrase(the diagram is complete 'with label')
+ - x: "*[1]/*"
+ - test:
+ if: "not(contains(@data-intent-property, ':continued-row:'))"
+ then: [pause: medium]
+ - test:
+ if: "self::m:mlabeledtr"
+ then: [x: "*[position()>1]"]
+ else: [x: "*"]
+
+- name: default-multiline
+ tag: mtd
+ match: "parent::*[parent::m:piecewise or parent::m:system-of-equations or parent::m:lines]"
+ variables: [LongPause: "$SpeechStyle = 'ClearSpeak' and $ClearSpeak_MultiLinePausesBetweenColumns = 'Long'"]
+ replace:
+ - test:
+ if: "IsInDefinition(*[1], 'ComparisonOperators')"
+ then: [pause: short]
+ - test:
+ if: "*[1][@data-added!='missing-content']"
+ then: [x: "*"]
+ - test:
+ # no pause after each element; medium pause if last element in a row; long pause for last element in matrix unless ClearSpeak override
+ - if: "count(following-sibling::*) = 0 and not($NextLineIsContinuedRow)"
+ then_test:
+ if: "count(../following-sibling::*) > 0"
+ then_test:
+ if: "$LongPause"
+ then: [pause: long]
+ else: [pause: medium]
+ else_test:
+ if: "IsInDefinition(*[1], 'ComparisonOperators')"
+ then: [pause: short]
+ else: [pause: auto]
+
+# Matrix/Determinant rules
+# matrix and determinant are the same other than "matrix"/"determinant" based on the bracketing chars
+# the pausing logic is pushed down to the
+# the rules either speak the s (to get "row n") or the s. "column n" spoken if $IsColumnSilent is false
+- name: 1x1-matrix
+ tag: [matrix, determinant]
+ variables: [IsColumnSilent: true()]
+ match: "count(*)=1 and *[self::m:mtr][count(*) = 1]"
+ replace:
+ - ot: "die" # phrase('the' 1 by 1 matrix M)
+ - T: "1 mal 1" # phrase(the '1 by 1' matrix)
+ - test:
+ if: "self::m:determinant" # just need to check the first bracket since we know it must be (, [, or |
+ then: [T: "determinante"] # phrase(the 2 by 2 'determinant'))
+ else: [T: "matrix"] # phrase(the 2 by 2 'matrix')
+
+ - T: "mit eintrag" # phrase(the 2 by 2 matrix 'with entry' x)
+ - x: "*[1]/*"
+
+# simpler reading methods for special case matrices
+- name: zero-matrix
+ tag: matrix
+ # select all the non-zero entries -- if there are none of them, then it is a zero matrix
+ match: "not( */*/*[not(self::m:mn and .= 0)] )"
+ replace:
+ - T: "die" # phrase('the' 1 by 2 matrix M)
+ - x: count(*)
+ - T: "mal" # phrase(the 1 'by' 2 matrix)
+ - x: count(*[self::m:mtr][1]/*)
+ - T: "nullmatrix" # phrase(the 2 by 2 'zero matrix')
+ - pause: long
+
+- name: identity-matrix
+ tag: matrix
+ # select all the non-zero entries...if they are not on the diagonal, or are != 1
+ # if there are any of them, then this isn't an identity matrix
+ match:
+ - "count(*) = count(*[1]/*) and "
+ - "not( */*/*[not(self::m:mn and .= 0)]"
+ - " [count(../preceding-sibling::*)!=count(../../preceding-sibling::*) or .!= 1]"
+ - " )"
+ replace:
+ - T: "die" # phrase('the' 1 by 2 matrix M)
+ - x: count(*)
+ - T: "mal" # phrase(the 1 'by' 2 matrix)
+ - x: count(*[self::m:mtr][1]/*)
+ - T: "identitätsmatrix" # phrase(the 2 by 2 'identity matrix')
+ - pause: long
+
+- name: diagonal-matrix
+ tag: matrix
+ # select all the non-zero entries...if they are not on the diagonal
+ # if there are any of them, then this isn't an identity matrix
+ match:
+ - "count(*) = count(*[1]/*) and "
+ - "not( */*/*[not(self::m:mn and .= 0)]"
+ - " [count(../preceding-sibling::*)!=count(../../preceding-sibling::*)]"
+ - " )"
+ replace:
+ - T: "die" # phrase('the' 1 by 2 matrix)
+ - x: count(*)
+ - T: "mal" # phrase(the 1 'by' 2 matrix)
+ - x: count(*[self::m:mtr][1]/*)
+ - T: "diagonalmatrix" # phrase(the 2 by 2 'diagonal matrix')
+ - pause: long
+ - insert:
+ # this lists the diagonal 'mtd's to be read, and they say "column nnn" before reading the contents
+ # there seems to be an xpath bug -- without the parens, the match fails for the
+ # test Languages::en::mtable::diagonal_matrix due to match failure (the third matching element seems to be missing)
+ nodes: "(*/*/*[not(self::m:mn and .= 0)]/..)"
+ replace: [pause: auto]
+ - pause: long
+
+# simpler reading methods for smaller matrices if the entries are simple
+- name: 2-or-3x1-matrix
+ tag: matrix
+ variables: [IsColumnSilent: true()]
+ match:
+ - "$ClearSpeak_Matrix != 'SpeakColNum' and " # "simple" isn't used for this preference
+ - "*[self::m:mtr][count(*) = 1] and " # one column
+ - count(*)<=3 and # at least two rows
+ - IsNode(*/*/*,'simple') # IsNode() returns true if all the nodes are simple
+ replace:
+ - T: "die" # phrase('the' 2 by 2 matrix M)
+ - x: count(*)
+ - T: "mal 1 spalte" # phrase(the 2 'by 1 column' matrix)
+ - test:
+ if: "$ClearSpeak_Matrix = 'Vector' or $ClearSpeak_Matrix = 'EndVector'"
+ then: [T: "vektor"] # phrase(the 2 by 2 'vector')
+ else: [T: "matrix"] # phrase(the 2 by 2 'matrix')
+ - pause: long
+ - x: "*/*"
+ - test:
+ if: "$ClearSpeak_Matrix = 'EndMatrix' or $ClearSpeak_Matrix = 'EndVector'"
+ then:
+ - T: "ende" # phrase('end' of matrix)
+ - test:
+ if: $ClearSpeak_Matrix = 'EndVector'
+ then: [T: "vektor"] # phrase(the 2 column 'vector')
+ else: [T: "matrix"] # phrase(the 2 by 2 'matrix')
+
+- name: default-column-matrix
+ tag: matrix
+ variables: [IsColumnSilent: true()]
+ match: "*[self::m:mtr][count(*) = 1]"
+ replace:
+ - T: "die" # phrase('the' 2 by 2 matrix M)
+ - x: "count(*)"
+ - T: "mal 1 spalte" # phrase(the 2 'by 1 column' matrix)
+ - test:
+ if: "$ClearSpeak_Matrix = 'Vector' or $ClearSpeak_Matrix = 'EndVector'"
+ then: [T: "vektor"] # phrase(the 2 column 'vector')
+ else: [T: "matrix"] # phrase(the 2 by 2 'matrix')
+ - pause: long
+ - x: "*" # select the rows (mtr)
+ - test:
+ if: "$ClearSpeak_Matrix = 'EndMatrix' or $ClearSpeak_Matrix = 'EndVector'"
+ then: [T: "ende der matrix"] # phrase(the 'end of matrix' has been reached)
+
+- name: 1x2-or-3-matrix
+ tag: matrix
+ variables: [IsColumnSilent: "$SpeechStyle = 'SimpleSpeak' or ($SpeechStyle = 'ClearSpeak' and $ClearSpeak_Matrix != 'SpeakColNum')"]
+ match:
+ - "$ClearSpeak_Matrix != 'SpeakColNum' and " # "simple" isn't used for this preference
+ - count(*)=1 and # one row
+ - count(*[1]/*)<=3 and # at least two cols
+ - IsNode(*/*/*,'simple') # IsNode() returns true if all the nodes are simple
+ replace:
+ - T: "die 1 mal" # phrase('the 1 by' 2 matrix)
+ - x: count(*/*)
+ - T: "Zeile" # phrase(the 1 by 4 'row' matrix)
+ - test:
+ if: "$ClearSpeak_Matrix = 'Vector' or $ClearSpeak_Matrix = 'EndVector'"
+ then: [T: "die 1 mal"] # phrase('the 1 by' 2 row 'vector')
+ else: [T: "die 1 mal"] # phrase('the 1 by' 2 'matrix')
+ - pause: long
+ - x: "*/*"
+ - test:
+ if: "$ClearSpeak_Matrix = 'EndMatrix' or $ClearSpeak_Matrix = 'EndVector'"
+ then:
+ - T: "ende" # phrase(the 'end' of matrix has been reached)
+ - test:
+ if: $ClearSpeak_Matrix = 'EndMatrix'
+ then: [T: "matrix"] # phrase(the 2 by 2 'matrix')
+ else: [T: "vektor"] # phrase(the 2 by 1 'vector')
+
+- name: default-row-matrix
+ tag: matrix
+ variables: [IsColumnSilent: "$SpeechStyle = 'ClearSpeak' and $ClearSpeak_Matrix = 'SilentColNum'"]
+ match: "count(*)=1" # one row
+ replace:
+ - T: "die 1 mal" # phrase('the 1 by' 2 matrix)
+ - x: "count(*/*)"
+ - T: "zeile" # phrase(the 1 by 2 'row' matrix)
+ - test:
+ if: "$ClearSpeak_Matrix = 'Vector' or $ClearSpeak_Matrix = 'EndVector'"
+ then: [T: "vektor"] # phrase(the 2 by 1 'vector')
+ else: [T: "matrix"] # phrase(the 2 by 2 'matrix')
+ - pause: long
+ - pause: medium
+ - x: "*/*" # select the cols (mtd)
+ - test:
+ if: "$ClearSpeak_Matrix = 'EndMatrix' or $ClearSpeak_Matrix = 'EndVector'"
+ then:
+ - T: "ende" # phrase(the 'end' of matrix has been reached)
+ - test:
+ if: $ClearSpeak_Matrix = 'EndMatrix'
+ then: [T: "matrix"] # phrase(the 2 by 2 'matrix')
+ else: [T: "vektor"] # phrase(the 2 by 1 'vector')
+
+- name: simple-small-matrix
+ tag: [matrix, determinant]
+ match:
+ - "$ClearSpeak_Matrix != 'SpeakColNum' and " # "simple" isn't used for this preference
+ - (count(*)<=3 and count(*[1]/*)<=3) and # no bigger than a 3x3 matrix
+ - IsNode(*/*/*,'simple') # IsNode() returns true if all the nodes are simple
+ variables: [IsColumnSilent: "$SpeechStyle = 'SimpleSpeak' or ($SpeechStyle = 'ClearSpeak' and $ClearSpeak_Matrix != 'SpeakColNum')"]
+ replace:
+ - T: "die" # phrase('the' 1 by 2 matrix M)
+ - x: count(*)
+ - T: "mal" # phrase(the 1 'by' 2 matrix)
+ - x: count(*[self::m:mtr][1]/*)
+ - test:
+ if: "self::m:determinant"
+ then: [T: "determinante"] # phrase(the 2 by 2 'determinant')
+ else: [T: "matrix"] # phrase(the 2 by 2 'matrix')
+ - pause: long
+ - x: "*"
+ - test:
+ if: "$ClearSpeak_Matrix = 'EndMatrix' or $ClearSpeak_Matrix = 'EndVector'"
+ then:
+ - T: "ende" # phrase(the 'end' of matrix has been reached)
+ - test:
+ if: "self::m:determinant"
+ then: [T: "determinante"] # phrase(the 2 by 2 'determinant')
+ else: [T: "matrix"] # phrase(the 2 by 2 'matrix')
+
+- name: default-matrix
+ tag: [matrix, determinant]
+ variables: [IsColumnSilent: "$SpeechStyle = 'ClearSpeak' and $ClearSpeak_Matrix = 'SilentColNum'"]
+ match: "."
+ replace:
+ - T: "die" # phrase('the' 1 by 2 matrix M)
+ - x: "count(*)"
+ - T: "mal" # phrase(the 1 'by' 2 matrix)
+ - x: "count(*[self::m:mtr][1]/*)"
+ - test:
+ if: "self::m:determinant"
+ then: [T: "determinante"] # phrase(the 2 by 2 'determinant')
+ else: [T: "matrix"] # phrase(the 2 by 2 'matrix')
+ - pause: long
+ - x: "*"
+ - test:
+ if: "$ClearSpeak_Matrix = 'EndMatrix' or $ClearSpeak_Matrix = 'EndVector'"
+ then:
+ - T: "ende" # phrase(the 'end' of matrix has been reached)
+ - test:
+ if: "self::m:determinant"
+ then: [T: "determinante"] # phrase(the 2 by 2 'determinant')
+ else: [T: "matrix"] # phrase(the 2 by 2 'matrix's)
+
+- name: chemistry-msub
+ tag: [chemical-formula]
+ match: "*[1][.='msub']"
+ replace:
+ - x: "*[2]"
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "index"] # phrase(H 'subscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "sub"] # phrase(H 'sub' 2)
+ - x: "*[3]"
+
+- name: dimension-by
+ tag: mrow
+ match: dimension-product
+ replace:
+ - insert:
+ nodes: "*"
+ replace: [T: "mal", pause: auto] # phrase(3 'by' 5 matrix)
+
+- name: chemistry-msup
+ tag: [chemical-formula]
+ match: "count(*)=3 and *[1][.='msup']"
+ replace:
+ - x: "*[2]"
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "superscript"] # phrase(H 'superscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "super"] # phrase(H 'super' 2)
+ - x: "*[3]"
+ - test:
+ if: "following-sibling::*[1][.='+' or .='-']" # a little lazy -- assumes chemistry superscripts end with + or -
+ then: [pause: medium]
+
+-
+ # There currently is no way to do sub/super for n-ary number of args
+ # Instead, we just deal with up to two prescripts and up to four postscripts (repeating blocks of similar code [UGLY!])
+ # This hopefully covers all reasonable cases...
+ name: chemistry-scripts
+ tag: [chemical-formula, chemical-nuclide]
+ variables:
+ # computing the number of postscripts is messy because of being optionally present -- we use "mod" to get the count right
+ - Prescripts: "m:mprescripts/following-sibling::*"
+ - NumChildren: "count(*)" # need to stash this since the count is wrong inside '*[...]' below
+ - Postscripts: "*[position()>1 and position() < (last() + ($NumChildren mod 2) -count($Prescripts))]"
+ match: . # should only be msubsup or mmultiscripts at this point
+ replace:
+ - test:
+ if: "$Prescripts" # we have at least one pre sub/super
+ then:
+ # nuclide: speak the superscript first
+ - test:
+ if: "not($Prescripts[2][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "superscript"] # phrase(H 'superscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "super"] # phrase(H 'super' 2)
+ - x: "$Prescripts[2]"
+ - pause: "short"
+ - test:
+ if: "not($Prescripts[1][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "index"] # phrase(a 'subscript' may be used to indicate an index)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "sub"] # phrase(here is a 'sub' total)
+ - x: "$Prescripts[1]"
+ - pause: "short"
+ - test:
+ if: "count($Prescripts) > 2" # can this happen for chemistry??? we allow for one *extra* pre sub/super pair
+ then:
+ - test:
+ if: "not($Prescripts[4][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "superscript"] # phrase(H 'superscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "super"] # phrase(H 'super' 2)
+ - x: "$Prescripts[4]"
+ - pause: "short"
+ - test:
+ if: "not($Prescripts[3][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "index"] # phrase(H 'subscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "sub"] # phrase(H 'sub' 2)
+ - x: "$Prescripts[3]"
+ - pause: "short"
+ - x: "*[1]" # base
+ - test:
+ if: "$Postscripts"
+ then:
+ - test:
+ if: "not($Postscripts[1][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "index"] # phrase(phrase(H 'subscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "sub"] # phrase(phrase(H 'sub' 2)
+ - x: "$Postscripts[1]"
+ - pause: "short"
+ - test:
+ if: "not($Postscripts[2][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "superscript"] # phrase(H 'superscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "super"] # phrase(H 'super' 2)
+ - x: "$Postscripts[2]"
+ - pause: "short"
+ - test:
+ if: "count($Postscripts) > 2"
+ then:
+ - test:
+ if: "not($Postscripts[3][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "index"] # phrase(H 'subscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "sub"] # phrase(H 'sub' 2)
+ - x: "$Postscripts[3]"
+ - pause: "short"
+ - test:
+ if: "not($Postscripts[4][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "superscript"] # phrase(H 'superscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "super"] # phrase(H 'super' 2)
+ - x: "$Postscripts[4]"
+ - pause: "short"
+ - test:
+ if: "count($Postscripts) > 4"
+ then:
+ - test:
+ if: "not($Postscripts[5][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "index"] # phrase(H 'subscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "sub"] # phrase(H 'sub' 2)
+ - x: "$Postscripts[5]"
+ - pause: "short"
+ - test:
+ if: "not($Postscripts[6][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "superscript"] # phrase(H 'superscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "super"] # phrase(H 'super' 2)
+ - x: "$Postscripts[6]"
+ - pause: "short"
+ - test:
+ if: "count($Postscripts) > 6"
+ then:
+ - test:
+ if: "not($Postscripts[7][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "index"] # phrase(H 'subscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "sub"] # phrase(H 'sub' 2)
+ - x: "$Postscripts[7]"
+ - pause: "short"
+ - test:
+ if: "not($Postscripts[8][self::m:none])"
+ then:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "superscript"] # phrase(H 'superscript' 2)
+ else_test:
+ if: "$Verbosity='Medium'"
+ then: [T: "super"] # phrase(H 'super' 2)
+ - x: "$Postscripts[8]"
+ - pause: "short"
+ - test:
+ if: "$Postscripts[last()][not(self::m:none)] and following-sibling::*[1][.='+' or .='-']"
+ then: [pause: medium]
+
+- name: chemistry
+ tag: chemical-equation
+ match: "."
+ replace:
+ - x: "*"
+
+- name: chemical-element
+ tag: chemical-element
+ match: "."
+ replace:
+ - bookmark: "@id"
+ - spell: text()
+ - pause: short
+
+- name: chemical-state
+ tag: chemical-state
+ match: "count(*)=1"
+ replace:
+ - bookmark: "*[1]/@id"
+ - test:
+ - if: ".='s'"
+ then: [T: "solide"] # phrase(Boron is a 'solid' in its natural state)
+ - else_if: ".='l'"
+ then: [T: "flüssigkeit"] # phrase(water is a 'liquid')
+ - else_if: ".='g'"
+ then: [T: "gas"] # phrase(hydrogen is a 'gas' )
+ else: [T: "wässrige"] # phrase(an 'aqueous' solution is contained in water)
+ - pause: short
+
+- name: chemical-formula-operator-bond
+ tag: chemical-formula-operator
+ match: "@data-chemical-bond"
+ replace:
+ # FIX: this might be better/more efficient if in unicode.yaml
+ - bookmark: "@id"
+ - test:
+ - if: ".='-' or .=':'"
+ then: [T: "einzelbindung"] # phrase(a 'single bond' is formed when two atoms share one pair of electrons)
+ - else_if: ".='=' or .='∷'"
+ then: [T: "doppelbindung"] # phrase(a 'double bond' may occur when two atoms share two pairs of electrons)
+ - else_if: ".='≡'"
+ then: [T: "dreifachbindung"] # phrase(a 'triple bond' occurs when two atoms share three pairs of electrons)
+ - else_if: ".='≣'"
+ then: [T: "vierfachbindung"] # phrase(a 'quadruple bond' occurs when two atoms share four pairs of electrons)
+ else: [x: "text()"]
+
+- name: chemical-formula-operator
+ tag: chemical-formula-operator
+ match: "."
+ replace:
+ x: "text()"
+
+- name: chemical-arrow-operator
+ tag: chemical-arrow-operator
+ match: "."
+ replace:
+ # FIX: this might be better/more efficient if in unicode.yaml
+ - bookmark: "@id"
+ - test:
+ - if: ".='→' or .='⟶'"
+ then_test:
+ if: "$Verbosity='Terse'"
+ then: [T: "formen"] # phrase(hydrogen and oxygen 'forms' water )
+ else: [T: "reagiert auf die form"] # phrase(hydrogen and oxygen 'reacts to form' water)
+ - else_if: ".='⇌' or .='\u1f8d2'"
+ then: [T: "ist im gleichgewicht mit"] # phrase(a reactant 'is in equilibrium with' a product)
+ - else_if: ".='\u1f8d4'"
+ then: [T: "ist im gleichgewicht nach links vorgespannt mit"] # phrase(the reactant 'is in equilibrium biased to the left with' the product)
+ - else_if: ".='\u1f8d3'"
+ then: [T: "ist im gleichgewicht nach rechts vorgespannt mit"] # phrase(the reactant 'is in equilibrium biased to the right with' the product)
+ else: [x: "*"]
+
+- name: chemical-equation-operator
+ tag: chemical-equation-operator
+ match: "."
+ replace:
+ - bookmark: "@id"
+ - x: "text()"
+
+- name: none
+ tag: none
+ match: "../../*[self::m:chemical-formula or self::m:chemical-nuclide]"
+ replace:
+ - T: "" # don't say anything
+
+- name: ignore-intent-wrapper
+ tag: intent-wrapper
+ match: "."
+ replace:
+ - x: "*"
diff --git a/Rules/Languages/de/SharedRules/geometry.yaml b/Rules/Languages/de/SharedRules/geometry.yaml
new file mode 100644
index 00000000..4ac49066
--- /dev/null
+++ b/Rules/Languages/de/SharedRules/geometry.yaml
@@ -0,0 +1,79 @@
+---
+
+- name: line-segment
+ tag: line-segment
+ match: "count(*)=2"
+ replace:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then:
+ - T: "die strecke von" # phrase('the line segment from' A to B)
+ - x: "*[1]"
+ - T: "nach" # phrase(the line segment from A 'to' B)
+ - x: "*[2]"
+ else:
+ - T: "strecke" # phrase(the 'line segment' A B)
+ - x: "*[1]"
+ - x: "*[2]"
+
+- name: geometry-ray
+ tag: ray
+ match: "count(*)=2"
+ replace:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then:
+ - T: "der strahl von" # phrase('the ray from' A to B)
+ - x: "*[1]"
+ - T: "nach" # phrase(the ray from A 'to' B)
+ - x: "*[2]"
+ else:
+ - T: "ray" # phrase(the 'ray'A B)
+ - x: "*[1]"
+ - x: "*[2]"
+
+- name: geometry-arc
+ tag: arc
+ match: "count(*)=2"
+ replace:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "der"] # phrase('the' arc A B C)
+ - T: "bogen" # phrase(the 'arc' A B C)
+ - x: "*[1]"
+ - x: "*[2]"
+
+- name: measure-of-angle
+ tag: measure-of-angle
+ match: "count(*)=3"
+ replace:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then:
+ - T: "das maß des winkels" # phrase('the measure of the angle' ABC)
+ else:
+ - T: "maß für den winkel" # phrase('measure of angle' ABC)
+ - x: "*[1]"
+ - x: "*[2]"
+ - x: "*[3]"
+
+
+- name: coordinate
+ tag: coordinate
+ match: "."
+ replace:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "der"] # phrase('the' point at 1, 2)
+ - T: "punkt" # phrase(the 'point' at 1, 2)
+ - test:
+ if: "$Verbosity='Verbose'"
+ then: [T: "bei"] # phrase(the point 'at' 1, 2)
+ - pause: short
+ - insert:
+ nodes: "*"
+ replace: [T: "komma", pause: auto] # phrase(f of x 'comma' y)
+ - pause: short
+ - test:
+ if: "($SpeechStyle='ClearSpeak' and $Verbosity='Verbose') or not(IsNode(*[last()],'leaf'))"
+ then: [T: "ende des punktes"] # phrase(start point, 'end point')
diff --git a/Rules/Languages/de/SharedRules/linear-algebra.yaml b/Rules/Languages/de/SharedRules/linear-algebra.yaml
new file mode 100644
index 00000000..4969c062
--- /dev/null
+++ b/Rules/Languages/de/SharedRules/linear-algebra.yaml
@@ -0,0 +1,36 @@
+---
+
+- name: scalar-determinant
+ tag: determinant
+ match: "count(*)=1 and not(*[1][self::m:mtr])"
+ replace:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then:
+ - T: "die" # phrase('the' square root of 25 equals 5)
+ - T: "determinante" # phrase(the 'determinant' of a matrix)
+ - test:
+ if: "$Verbosity!='Terse'"
+ then:
+ - T: "von" # phrase(systems 'of' linear equations)
+ - x: "*[1]"
+ - test:
+ if: "not(IsNode(*[1], 'simple')) and $Impairment = 'Blindness'"
+ then: [T: "ende der determinante"] # phrase('end determinant' of a matrix)
+
+
+- name: subscripted-norm
+ tag: subscripted-norm
+ match: "count(*)=2"
+ replace:
+ - test:
+ if: "$Verbosity='Verbose'"
+ then:
+ - T: "die" # phrase('the' square root of 25 equals 5)
+ - x: "*[2]"
+ - T: "norm" # phrase(the 'norm' can be a measure of distance)
+ - test:
+ if: "$Verbosity!='Terse'"
+ then:
+ - T: "von" # phrase(systems 'of' linear equations)
+ - x: "*[1]"
diff --git a/Rules/Languages/de/SimpleSpeak_Rules.yaml b/Rules/Languages/de/SimpleSpeak_Rules.yaml
new file mode 100644
index 00000000..3ba520e8
--- /dev/null
+++ b/Rules/Languages/de/SimpleSpeak_Rules.yaml
@@ -0,0 +1,350 @@
+---
+- name: pause
+ tag: "!*"
+ match: "not(self::m:math) and not($MatchingPause) and @data-intent-property[contains(., ':pause')]"
+ replace:
+ - with:
+ variables: [MatchingPause: "true()"]
+ replace:
+ - test:
+ - if: "contains(@data-intent-property, ':pause-long')"
+ then: [pause: long]
+ - else_if: "contains(@data-intent-property, ':pause-short')"
+ then: [pause: short]
+ else: [pause: medium]
+ - x: "."
+
+- name: intent-literal-silent
+ tag: [mi, mo, mn]
+ match: "contains(@data-intent-property, ':silent:')"
+ # say nothing
+ replace: []
+
+# handling of negative numbers that come from 'intent' is hard -- we do something that is close to right here
+- name: intent-literal-negative-number
+ tag: mn
+ match: "starts-with(text(), '-')"
+ replace:
+ - T: "minus" # phrase(x 'minus' y)
+ - x: "translate(text(), '-_', '')"
+
+- name: default
+ tag: square-root
+ match: "."
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # phrase('the' square root of x)
+ - T: "quadratwurzel" # phrase(the 'square root' of x)
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "von"] # phrase(the square root 'of' x)
+ else: [pause: short]
+ - x: "*[1]"
+ - test:
+ if: "IsNode(*[1], 'leaf') or $Impairment != 'Blindness'"
+ then: [pause: short]
+ else: [T: "ende der wurzel", pause: short] # phrase(start the square root of x 'end of root')
+
+- name: default
+ tag: root
+ match: "."
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"]
+ - test:
+ if: "*[2][self::m:mn and not(contains(., '.'))]"
+ then_test:
+ - if: "*[2][.='2']"
+ then: [T: "quadratwurzel"] # phrase(the 'square root' of x)
+ - else_if: "*[2][.='3']"
+ then: [T: "kubikwurzel"] # phrase(the 'cube root' of x)
+ - else: [x: "ToOrdinal(*[2])",T: "wurzel"] # phrase(the square 'root' of 25)
+ else:
+ - test:
+ if: "*[2][self::m:mi][string-length(.)=1]"
+ then:
+ - x: "*[2]"
+ - pronounce: [{text: "-th"}, {ipa: "θ"}, {sapi5: "th"}, {eloquence: "T"}]
+ else: [x: "*[2]"]
+ - T: "wurzel" # phrase(the square 'root' of)
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "von"] # phrase(the square root 'of' x)
+ - x: "*[1]"
+ - test:
+ if: "IsNode(*[1], 'leaf') or $Impairment != 'Blindness'"
+ then: [pause: short]
+ else: [T: "ende der wurzel", pause: short] # phrase(start the fifth root of x 'end of root')
+
+# Fraction rules
+# Mixed numbers mostly "just work" because the invisible char reads as "and" and other parts read properly on their own
+- name: common-fraction
+ tag: fraction
+ match:
+ - "*[1][self::m:mn][not(contains(., '.')) and text()<20] and"
+ - "*[2][self::m:mn][not(contains(., '.')) and 2<= text() and text()<=10]"
+ variables: [IsPlural: "*[1]!=1"]
+ replace:
+ - x: "*[1]"
+ - x: "ToOrdinal(*[2], true(), $IsPlural)" # extra args specify fractional ordinal and whether it is plural
+
+- name: common-fraction-mixed-number
+ tag: fraction
+ match:
+ - "preceding-sibling::*[1][self::m:mo][.=''] and" # preceding element is invisible plus
+ - "*[1][self::m:mn][not(contains(., '.'))] and"
+ - "*[2][self::m:mn][not(contains(., '.'))]"
+ variables: [IsPlural: "*[1]!=1"]
+ replace:
+ - x: "*[1]"
+ - x: "ToOrdinal(*[2], true(), $IsPlural)" # extra args specify fractional ordinal and whether it is plural
+
+
+# Units (e.g., meters per second, m^2/s^2, (3m^2)/s)
+- name: per-fraction
+ tag: fraction
+ match:
+ - "BaseNode(*[1])[contains(@data-intent-property, ':unit') or"
+ - " ( self::m:mrow and count(*)=3 and" # maybe a bit paranoid checking the structure...
+ - " *[1][self::m:mn] and *[2][.='\u2062'] and BaseNode(*[3])[contains(@data-intent-property, ':unit')] ) ] and"
+ - "BaseNode(*[2])[contains(@data-intent-property, ':unit')] "
+ replace:
+ - x: "*[1]"
+ - T: "5 meter" # phrase('5 meters 'per' second)
+ - x: "*[2]"
+
+- name: simple
+ # don't include nested fractions. E.g, fraction a plus b over c + 1 end fraction" is ambiguous
+ # by simplistic SimpleSpeak's rules "b over c" is a fraction, but if we say nested fractions
+ # are never simple, then any 'over' applies only to enclosing "fraction...end fraction" pair.
+ tag: fraction
+ match:
+ - "(IsNode(*[1],'leaf') and IsNode(*[2],'leaf')) and"
+ - "not(ancestor::*[name() != 'mrow'][1]/self::m:fraction)" # FIX: can't test for mrow -- what should be used???
+ replace:
+ - x: "*[1]"
+ - T: "über" # phrase(the fraction 3 'over' 4)
+ - x: "*[2]"
+ - pause: short
+
+- name: default
+ tag: fraction
+ match: "."
+ replace:
+ - test:
+ if: "$Impairment = 'Blindness'"
+ then: [T: "bruch"] # phrase(the 'fraction' 3 over 4)
+ - pause: short
+ - x: "*[1]"
+ - test:
+ if: "not(IsNode(*[1],'leaf'))"
+ then: [pause: short]
+ - T: "über" # phrase(the fraction 3 'over' 4)
+ - test:
+ if: "not(IsNode(*[2],'leaf'))"
+ then: [pause: short]
+ - x: "*[2]"
+ - pause: short
+ - test:
+ if: "$Impairment = 'Blindness'"
+ then: [T: "ende des bruchs"] # phrase(start 7 over 8 'end of fraction')
+ - pause: medium
+
+# rules for functions raised to a power
+# these could have been written on 'mrow' but putting them on msup seems more specific
+# to see if it is a function, we look right to see if the following sibling is apply-function
+- name: inverse-function
+ tag: inverse-function
+ match: "."
+ replace:
+ - T: "umgekehrte" # phrase(the 'inverse' of f)
+ - x: "*[1]"
+
+- name: function-squared-or-cubed
+ tag: power
+ match:
+ - "*[2][self::m:mn][.='2' or .='3'] and"
+ - "following-sibling::*[1][self::m:mo][.='']" #invisible function apply
+ replace:
+ - x: "*[1]"
+ - bookmark: "*[2]/@id"
+ - test:
+ if: "*[2][.=2]"
+ then: [T: "quadrat"] # phrase(5 'squared' equals 25)
+ else: [T: "hoch drei"] # phrase(5 'cubed' equals 125)
+- name: function-power
+ tag: power
+ match:
+ - "following-sibling::*[1][self::m:mo][.='']" #invisible function apply
+ replace:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # # phrase('the' fourth power of 10)
+ - bookmark: "*[2]/@id"
+ - test:
+ if: "*[2][self::m:mn][not(contains(., '.'))]"
+ then: [x: "ToOrdinal(*[2])"]
+ else: [x: "*[2]"]
+ - T: "potenz von" # phrase(the fourth 'power of' 2)
+ - pause: short
+ - x: "*[1]"
+
+# non-function rules for power
+- name: squared-or-cubed
+ tag: power
+ match: "*[2][self::m:mn][.='2' or .='3']"
+ replace:
+ - x: "*[1]"
+ - bookmark: "*[2]/@id"
+ - test:
+ if: "*[2][.=2]"
+ then: [T: "quadrat"] # phrase(5 'squared' equals 25)
+ else: [T: "hoch drei"] # phrase(5 'cubed' equals 125)
+
+- name: simple-integer
+ tag: power
+ match: "*[2][self::m:mn][not(contains(., '.'))]"
+ replace:
+ - x: "*[1]"
+ - T: "zu dem" # phrase(15 raised 'to the' second power equals 225)
+ - test:
+ if: "*[2][.>0]"
+ then: {x: "ToOrdinal(*[2])"}
+ else: {x: "*[2]"}
+- name: simple-negative-integer
+ tag: power
+ match:
+ - "*[2][self::m:minus and count(*)=1 and"
+ - " *[1][self::m:mn][not(contains(., '.'))]]"
+ replace:
+ - x: "*[1]"
+ - T: "hoch" # phrase(15 raised 'to the' second power equals 225)
+ - x: "*[2]"
+- name: simple-var
+ tag: power
+ match: "*[2][self::m:mi][string-length(.)=1]"
+ replace:
+ - x: "*[1]"
+ - T: "hoch" # phrase(15 raised 'to the' second power equals 225)
+ - x: "*[2]"
+ - pronounce: [{text: "-th"}, {ipa: "θ"}, {sapi5: "th"}, {eloquence: "T"}]
+
+- name: simple
+ tag: power
+ match: "IsNode(*[2], 'leaf')"
+ replace:
+ - x: "*[1]"
+ - T: "hoch" # phrase(15 raised 'to the' second power equals 225)
+ - x: "*[2]"
+
+- name: nested
+ # it won't end in "power" if the exponent is simple enough
+ # FIX: not that important, but this misses the case where the nested exp is a negative integer (change test if this is fixed)
+ # ending nested exponents with "...power power" sounds bad
+ tag: power
+ match:
+ - "*[2]["
+ - " (self::m:power and not(IsNode(*[2], 'leaf'))) or" # non-simple nested superscript
+ - " self::m:mrow[*[last()][self::m:power[not(IsNode(*[2], 'leaf'))]]]" # same as above but at the end of an mrow # FIX: need to figure out linear replacement
+ - " ]"
+ replace:
+ - x: "*[1]"
+ - T: "hoch" # phrase(15 'raised to the' second power equals 225)
+ - x: "*[2]"
+ - pause: short
+ - test:
+ if: "$Impairment = 'Blindness'"
+ then:
+ - T: "ende des exponenten" # phrase(start 2 raised to the exponent 4 'end of exponent')
+ - pause: short
+ else:
+ - pause: medium
+
+- name: default
+ tag: power
+ match: "."
+ replace:
+ - x: "*[1]"
+ - T: "hoch" # phrase(15 'raised to the' second power equals 225)
+ - x: "*[2]"
+ - T: "potenz" # phrase(15 raised to the second 'power' equals 225)
+ - pause: short
+
+#
+# Some rules on mrows
+#
+- name: set
+ tag: set
+ match: "."
+ replace:
+ - test:
+ - if: "count(*)=0"
+ then:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "das"] # phrase('the' empty set)
+ - T: "leere Menge" # phrase(when a set contains no value it is called an 'empty set' and this is valid)
+ - else_if: "count(*[1]/*)=3 and *[1]/*[2][self::m:mo][.=':' or .='|' or .='∣']"
+ then:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # phrase('the' set of all integers)
+ - T: "Menge aller" # phrase(the 'set of all' positive integers less than 10)
+ - x: "*[1]/*[1]"
+ - T: "so dass" # phrase(x 'such that' x is less than y)
+ - x: "*[1]/*[3]"
+ else:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # phrase('the' set of integers)
+ - T: "Menge" # phrase(here is a 'set' of numbers)
+ - x: "*[1]"
+
+- name: times
+ tag: mo
+ match:
+ # say "times" when invisible times is followed by parens or a superscript that has a base with parens or "|"s
+ # added: say times is the superscript is not simple
+ # if we aren't sure if it is times or not, don't say anything
+ - ".='' and"
+ - "not(@data-function-guess) and ("
+ - "not(ancestor-or-self::*[contains(@data-intent-property, ':literal:')]) and "
+ - " following-sibling::*[1]["
+ - " IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|') or "
+ - " self::m:matrix or self::m:determinant or self::m:binomial or" # followed by parens
+ - " self::m:square-root or self::m:msqrt or self::m:root or self::m:mroot or"
+ - " (self::m:msub or self::m:msubsup or"
+ - " ((self::m:msup or self::m:power) and not(IsNode(*[1], 'leaf') and *[2][self::m:mn and (.=2 or '.=3')]))) and " # followed by msup, etc.
+ - " (*[1][self::m:mrow[IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|')] or "
+ - " self::m:matrix or self::m:determinant] or" # base has parens
+ - " not(IsNode(*[2], 'simple')) or "
+ - " (self::m:msubsup and not(IsNode(*[3], 'simple')))"
+ - " )"
+ - " ]" # other possibility is the preceding element has parens (but not the following)
+ - " or "
+ - " preceding-sibling::*[1]["
+ - " IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|')]" # followed by parens
+ - " )"
+ replace:
+ - T: "mal" # phrase(7 'times' 5 equals 35)
+
+- name: no-say-parens
+ tag: mrow
+ match:
+ - "parent::*[not(self::m:msup) and not(self::m:msub) and not(self::m:msubsup) and not(self::m:power) and"
+ - " not(self::m:math) ] and " # rule out [x] standing alone
+ - "( IsBracketed(., '(', ')') or IsBracketed(., '[', ']') ) and "
+ - "( IsNode(*[2], 'simple') ) and"
+ - "not(preceding-sibling::*[1][.='\u2062' and @data-function-guess]) and"
+ - "not(ancestor-or-self::*[contains(@data-intent-property, ':literal:')])"
+ # missing clause: 'a positive fraction that is spoken as an ordinal
+ # (either by the Ordinal preference or by the default rules_'
+ replace:
+ - x: "*[2]"
+
+- include: "SharedRules/geometry.yaml"
+- include: "SharedRules/linear-algebra.yaml"
+- include: "SharedRules/general.yaml"
+- include: "SharedRules/default.yaml"
diff --git a/Rules/Languages/de/definitions.yaml b/Rules/Languages/de/definitions.yaml
new file mode 100644
index 00000000..4e5ccf04
--- /dev/null
+++ b/Rules/Languages/de/definitions.yaml
@@ -0,0 +1,267 @@
+---
+- include: "../../definitions.yaml"
+
+# If an "intent" is used, the 'terse:medium:verbose' speech for the intent name is given here for a prefix||infix||postfix||function fixity
+# If only one ":" is used, it the first part is used for 'terse' and the second part is used for 'medium' and 'verbose'
+# If no ":"s are used, the same speech is used for all forms
+# If bracketing words make sense, they are separated with ";"s
+# Intent mappings must specify whether they are "prefix", "infix", "postfix", or "function" with an "=" sign
+# If there are multiple fixities (e.g., see transpose), they are separated with "||
+# for readability, spaces can be used around any of the delimiter characters
+# Note: if there are multiple fixities, the first one is used if the fixity is not given in the intent
+- IntentMappings: {
+ "indexed-by": "infix= ; sub; ende sub: ende sub: ende subskript",
+ "modified-variable": "silent= ",
+ "say-super": "infix=super: hochstellung: hochstellung",
+ "skip-super": "silent=",
+ "absolute-value": "function= ; absoluter wert: der absolute wert: der absolute wert; ende absoluter wert",
+ "binomial": "infix=binomial; wählen; ende binomial",
+ "dimension-product": "infix=mal",
+ "greatest-common-divisor": "function=gcd: der gcd: der größte gemeinsame teiler",
+ "imaginary-part": "function=imaginärer teil, der imaginäre teil, der imaginäre teil",
+ "least-common-multiple": "function=lcm:der lcm:das kleinste gemeinsame vielfache",
+ "limit": "prefix=grenzwert bei: der grenzwert bei: der grenzwert bei",
+ "lim-sup": "prefix=lim sup bei: der obere grenzwert bei: der obere grenzwert bei",
+ "lim-inf": "prefix=lim inf bei: der untere grenzwert bei : der untere grenzwert bei",
+ "logarithm-with-base": "prefix=logarithmus basis: der logarithmus basis: der logarithmus basis",
+ "natural-logarithm": "function=ln: natürlicher logarithmus: natürlicher logarithmus",
+ "minus": "infix=minus || prefix=negativ",
+ "plus": "infix=plus || prefix=positiv",
+ "real-part": "function=der reale teil",
+ "transpose": "postfix=transponieren || function=transponieren",
+ "norm": "function=; norm: norm: norm; ende norm",
+ "trace": "function=; spur : spur: die spur; ende spur",
+ "dimension": "function=; dimension : dimension: die dimension; ende dimension",
+ "homomorphism": "function= ; homomorphismus : homomorphismus: der homomorphismus; ende homomorphismus",
+ "kernel": "function= ; kern : kern: der kern; ende kern",
+ "vector": "function= ; vektor || prefix=vektor",
+ "cross-product": "infix=kreuz: kreuzprodukt: kreuzprodukt",
+ "dot-product": "infix=punkt: punktprodukt: punkt:punktprodukt",
+ "divergence": "function= ; div: divergenz: divergenz; ende divergenz",
+ "curl": "function= ; rotation; ende rotation",
+ "gradient": "function= ; grad: gradient: gradient; ende gradient",
+ "laplacian": "function=laplace",
+ "chemistry-concentration": "function= ; konzentration: konzentration von: die konzentration von; ende konzentration"
+ }
+
+- NavigationParts: {
+ "large-op": "basis; untergrenze; obergrenze",
+ "mfrac": "zähler; nenner",
+ "fraction": "zähler; nenner",
+ "msqrt": "wurzel",
+ "square-root": "wurzel",
+ "mroot": "wurzel; wurzelexponent",
+ "root": "wurzel; wurzelexponent",
+ "msub": "basis; subskript",
+ "sub": "basis; subskript",
+ "msup": "basis; hochstellung",
+ "say-super": "basis; hochstellung",
+ "skip-super": "basis; hochstellung",
+ "power": "basis; exponent",
+ "msubsup": "basis; subskript; hochstellung",
+ "munder": "basis; untere grenze",
+ "mover": "basis; obere grenze",
+ "munderover": "basis; untere grenze; obere grenze",
+ "in": "in",
+ "out": "außerhalb von"
+ }
+
+- SIPrefixes: {
+ "Q": "quetta", "R": "ronna", "Y": "yotta", "Z": "zetta", "E": "exa", "P": "peta", "T": "tera", "G": "giga",
+ "M": "mega", "k": "kilo", "h": "hekto", "da": "deka", "d": "dezi", "c": "zenti", "m": "milli", "µ": "mikro",
+ "n": "nano", "p": "piko", "f": "femto", "a": "atto", "z": "zepto", "y": "yocto", "r": "ronto", "q": "quecto"
+ }
+
+- SIUnits: {
+ "A": "ampere", "cd": "candela", "K": "kelvin", "K": "kelvin",
+ "g": "gramm", "m": "meter", "mol": "mol", "s": "sekunde", "sec": "sekunde",
+ "Bq": "becquerel", "C": "coulomb", "°C": "grad celsius", "℃": "grad celsius",
+ "F": "farad", "Gy": "gray", "H": "henry", "Hz": "hertz", "J": "joule", "kat": "katal",
+ "lm": "lumen", "lx": "lux", "N": "newton", "Ω": "ohm", "Ω": "ohm", "Pa": "pascal",
+ "S": "siemens", "Sv": "sievert", "T": "tesla", "V": "volt", "W": "watt", "Wb": "weber",
+ "l": "liter", "L": "liter", "ℓ": "liter", "t": "tonne", "Da": "dalton", "Np": "neper",
+ "u": "atommasse-einheit", "eV": "elektronenvolt", "rad": "radiant", "sr": "steradiant",
+ "a": "jahr", "as": "bogensekunde", "b": "bit", "B": "byte", "Bd": "baud"
+ }
+
+- UnitsWithoutPrefixes: {
+ "″": "sekunde", "\"": "sekunde",
+ "′": "minute", "'": "minute", "min": "minute",
+ "h": "stunde", "hr": "stunde", "Hr": "stunde",
+ "d": "tag", "dy": "tag", "w": "woche", "wk": "woche", "y": "jahr", "yr": "jahr",
+ "°": "grad", "deg": "grad", "arcmin": "bogenminute", "amin": "bogenminute", "am": "bogenminute",
+ "MOA": "bogenminute", "arcsec": "bogensekunde", "asec": "bogensekunde",
+ "au": "astronomische einheit", "AU": "astronomische einheit", "ltyr": "lichtjahr", "ly": "lichtjahr",
+ "pc": "parsec", "Å": "ångström", "Å": "ångström", "fm": "fermi",
+ "ha": "hektar", "dB": "dezibel", "amu": "atommasse-einheit", "atm": "atmosphäre",
+ "bar": "bar", "cal": "kalorie", "Ci": "curie", "grad": "gon", "M": "mol/liter",
+ "R": "röntgen", "rpm": "umdrehungen pro minute", "℧": "mho", "dyn": "dyn", "erg": "erg",
+ "Kib": "kibi-bit", "Mib": "mebi-bit", "Gib": "gibi-bit", "Tib": "tebi-bit", "Pib": "pebi-bit",
+ "Eib": "exbi-bit", "Zib": "zebi-bit", "Yib": "yobi-bit", "KiB": "kibi-byte", "MiB": "mebi-byte",
+ "GiB": "gibi-byte", "TiB": "tebi-byte", "PiB": "pebi-byte", "EiB": "exbi-byte",
+ "ZiB": "zebi-byte", "YiB": "yobi-byte"
+ }
+
+- EnglishUnits: {
+ # length
+ "in": "zoll",
+ "ft": "fuß",
+ "mi": "meile",
+ "rd": "ruthe",
+ "li": "glied",
+ "ch": "kette",
+
+ # area
+ "sq in": "quadratzoll", "sq. in": "quadratzoll", "sq. in.": "quadratzoll",
+ "sq ft": "quadratfuß", "sq. ft": "quadratfuß", "sq. ft.": "quadratfuß",
+ "sq yd": "quadratyard", "sq. yd": "quadratyard", "sq. yd.": "quadratyard",
+ "sq mi": "quadratmeile", "sq. mi": "quadratmeile", "sq. mi.": "quadratmeile",
+ "ac": "morgen",
+ "FBM": "brettfuß",
+
+ # volume
+ "cu in": "kubikzoll", "cu. in": "kubikzoll", "cu. in.": "kubikzoll",
+ "cu ft": "kubikfuß", "cu. ft": "kubikfuß", "cu. ft.": "kubikfuß",
+ "cu yd": "kubikyard", "cu. yd": "kubikyard", "cu. yd.": "kubikyard",
+ "bbl": "fass", "BBL": "fass",
+ "pk": "buschelmaß",
+ "bu": "buschel",
+ "tsp": "teelöffel",
+ "tbl": "esslöffel",
+
+ # liquid
+ "fl dr": "flüssige dram",
+ "fl oz": "flüssige unze",
+ "gi": "gill",
+ "cp": "tasse", "cup": "tasse",
+ "pt": "pint",
+ "qt": "quart",
+ "gal": "gallone",
+
+ # weight
+ "gr": "korn",
+ "dr": "dram",
+ "oz": "unze", "℥": "unze",
+ "lb": "pfund",
+ "cwt": "zentner",
+ "dwt": "feingewicht",
+ "oz t": "troy-unze",
+ "lb t": "troy-pfund",
+
+ # energy
+ "hp": "ps",
+ "BTU": "britische wärmeeinheit",
+ "°F": "grad fahrenheit", "℉": "grad fahrenheit",
+
+ # other
+ "mph": "meile pro stunde",
+ "mpg": "meile pro gallone",
+ }
+
+- 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"
+ }
+
+
+# ---------------- Cardinal and Ordinal Numbers --------------------------
+# The following definitions are used to convert numbers to words
+# The are mainly used for ordinals, of which there are two cases:
+# 1. Regular ordinals: first, second, third, ...
+# 2. Ordinals used in the denominator of fractions (e.g, one half, one third)
+# When used in the denominator of fractions, a plural version might be
+# used (e.g., two halves, two thirds)
+# Although a lot of languages are regular after a few entries, for generality,
+# the following lists should be filled out even though they are the same
+# or easily derived from others in many languages (e.g, an 's' is added for plurals).
+# The larger ordinal numbers (e.g, millionth) is used when there are only
+# '0's after that decimal place (e.g., 23000000).:w
+
+# All definitions start 0, 10, 100, etc.
+
+# The definitions for the "ones" should extend until a regular pattern begins
+# The minimum length is 10.
+
+# For English, a regular pattern starts at twenty
+- NumbersOnes: [
+ "null", "eins", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun",
+ "zehn", "elf", "zwölf", "dreizehn", "vierzehn", "fünfzehn", "sechzehn",
+ "siebzehn", "achtzehn", "neunzehn"
+ ]
+
+- NumbersOrdinalOnes: [
+ "nullte", "erste", "zweite", "dritte", "vierte", "fünfte", "sechste", "siebte", "achte", "neunte",
+ "zehnte", "elfte", "zwölfte", "dreizehnte", "vierzehnte", "fünfzehnte", "sechzehnte",
+ "siebzehnte", "achtzehnte", "neunzehnte"
+ ]
+
+- NumbersOrdinalPluralOnes: [
+ "nullte", "erste", "zweite", "dritte", "vierte", "fünfte", "sechste", "siebte", "achte", "neunte",
+ "zehnte", "elfte", "zwölfte", "dreizehnte", "vierzehnte", "fünfzehnte", "sechzehnte",
+ "siebzehnte", "achtzehnte", "neunzehnte"
+ ]
+
+ # stop when regularity begins
+- NumbersOrdinalFractionalOnes: [
+ "null", "erste", "hälfte", "drittel", "viertel", "fünftel", "sechstel", "siebtel", "achtel", "neuntel", "zehntel",
+ "elftel", "zwölftel", "dreizehntel", "vierzehntel", "fünfzehntel", "sechzehntel",
+ "siebzehntel", "achtzehntel", "neunzehntel"
+ ]
+
+ # stop when regularity begins
+- NumbersOrdinalFractionalPluralOnes: [
+ "nulle", "erste", "hälften"
+ ]
+
+ # What to use for multiples of 10
+- NumbersTens: [
+ "", "zehn", "zwanzig", "dreißig", "vierzig", "fünfzig", "sechzig", "siebzig", "achtzig", "neunzig"
+ ]
+
+- NumbersOrdinalTens: [
+ "", "zehnte", "zwanzigste", "dreißigste", "vierzigste", "fünfzigste", "sechzigste", "siebzigste", "achtzigste", "neunzigste"
+ ]
+
+- NumbersOrdinalPluralTens: [
+ "", "zehnte", "zwanzigste", "dreißigste", "vierzigste", "fünfzigste", "sechzigste", "siebzigste", "achtzigste", "neunzigste"
+ ]
+
+- NumbersHundreds: [
+ "", "einhundert", "zweihundert", "dreihundert", "vierhundert", "fünfhundert",
+ "sechshundert", "siebenhundert", "achthundert", "neunhundert"
+ ]
+
+- NumbersOrdinalHundreds: [
+ "", "einhundertste", "zweihundertste", "dreihundertste", "vierhundertste", "fünfhundertste",
+ "sechshundertste", "siebenhundertste", "achthundertste", "neunhundertste"
+ ]
+
+- NumbersOrdinalPluralHundreds: [
+ "", "einhundertste", "zweihundertste", "dreihundertste", "vierhundertste", "fünfhundertste",
+ "sechshundertste", "siebenhundertste", "achthundertste", "neunhundertste"
+ ]
+
+ # At this point, hopefully the language is regular. If not, code needs to be written
+- NumbersLarge: [
+ "", "tausend", "million", "milliarde", "billion", "billiarde",
+ "trillion", "trilliarde", "quadrillion", "quadrilliarde", "quintillion"
+ ]
+
+- NumbersOrdinalLarge: [
+ "", "tausendste", "millionste", "milliardste", "billionste", "billiardste",
+ "trillionste", "trilliardste", "quadrillionste", "quadrilliardste", "quintillionste"
+ ]
+
+- NumbersOrdinalPluralLarge: [
+ "", "tausendste", "millionste", "milliardste", "billionste", "billiardste",
+ "trillionste", "trilliardste", "quadrillionste", "quadrilliardste", "quintillionste"
+ ]
+
diff --git a/Rules/Languages/de/navigate.yaml b/Rules/Languages/de/navigate.yaml
new file mode 100644
index 00000000..72ad5bb5
--- /dev/null
+++ b/Rules/Languages/de/navigate.yaml
@@ -0,0 +1,1669 @@
+---
+# Documentation:
+#
+# The general form for many rules is:
+# 1. Say the command if this is first rule to fire (MatchCounter) and depending upon "NavVerbosity"s value
+# 2. Say info about moving into/out of 2D structures
+# 3. Set some variables and possibly recurse.
+# If recursing, "MatchCounter" should be incremented.
+# If stopping, "NavNode" should be set.
+#
+# The meaning of NavVerbosity:
+# * Verbose -- always echo the command and end points (e.g., "can't move right")
+# * Medium -- only echo the command for obscure commands like the placemarker commands; also say end points
+# * Terse -- no echo of commands or end points
+#
+# For the second item, a common set of rules is used. These rules require the variable "Move2D"
+# to be set along with "Child2D", where "Move2D" is either 'in' or 'out'.
+#
+# In addition, the navigation rules make use of two functions:
+#
+# int DistanceFromLeaf(node, leftSide, treat2DElementsAsTokens)
+# Returns the distance (number of children) until a leaf is reached by traversing the leftmost/rightmost child
+# If 'treat2DElementsAsTokens' is true, then 2D notations such as fractions are treated like leaves
+# A leaf has distance == 0
+#
+# EdgeNode(node, "left"/"right", stopNodeName)
+# Returns the stopNode if at left/right edge of named ancestor node. 'stopNodeName' can also be "2D"
+# If the stopNode isn't found, the original node is returned
+# Note: if stopNodeName=="math", then punctuation is taken into account since it isn't really part of the math
+#
+# A few other variables are of importance to Navigation
+# NavMode -- Enhanced, Simple, Character
+# ReadZoomLevel -- -1 for Enhanced, otherwise the distance from leaf the rules should maintain
+# PlaceMarkerIndex
+
+# Note: the rules for saying a command and announcing what is said when moving in/out of a 2d exprs are hacks
+# They depend upon special variables "SayCommand" and "Move2D" being set and if they are, the rules are activated.
+# If/when functions can be defined in a rules file, it is likely these would be much better done via those functions
+# as they would likely be much more efficient and also cleaner.
+
+# Rules for announcing the command
+- name: say-command
+ tag: "!*"
+ match: "$SayCommand != ''" # value should be '', 'true', or 'false'
+ variables: [Prefix: "''"]
+ replace:
+ - test:
+ - if: "$MatchCounter = 0 and $SayCommand = 'true'"
+ then_test:
+ - if: "self::m:math and starts-with($NavCommand, 'ZoomOut')"
+ then: [T: "den ganzen weg vergrenzt", pause: "medium"]
+ - else_if: "IsNode(., 'leaf') and starts-with($NavCommand, 'ZoomIn')"
+ then: [T: "auf den ganzen weg vergrenzt", pause: "medium"]
+ else:
+ - test:
+ - if: "starts-with($NavCommand, 'Zoom')"
+ then: [set_variables: [Prefix: "'zoom'"]] # phrase('zoom' in to see more details)
+ - else_if: "starts-with($NavCommand, 'Move')"
+ then: [set_variables: [Prefix: "'move'"]] # phrase('move' to next entry in table)
+ - else_if: "starts-with($NavCommand, 'Read')"
+ then: [set_variables: [Prefix: "'read'"]] # phrase('read' to next entry in table)
+ - else_if: "starts-with($NavCommand, 'Describe')"
+ then: [set_variables: [Prefix: "'describe'"]] # phrase('describe' to next entry in table)
+ - test:
+ if: "$Prefix != ''"
+ then:
+ - x: "$Prefix"
+ - test:
+ - if: "substring($NavCommand, string-length($Prefix)+1) = 'In'"
+ then: [T: "in"] # phrase(zoom 'in' to see more details)
+ - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'InAll'"
+ # HACK: '\uF8FE' is used internally for the concatenation char by 'ct' -- this gets "ed" concatenated to "zoom"
+ then: [T: "den ganzen weg"] # phrase(zoom 'out all the way' to see more details)
+ - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Out'"
+ then: [T: "raus"] # phrase(zoom 'out' to see more details)
+ - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'OutAll'"
+ # HACK: '\uF8FE' is used internally for the concatenation char by 'ct' -- this gets "ed" concatenated to "zoom"
+ then: [T: "den ganzen weg"] # phrase(zoom 'out all the way' to see more details)
+ - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Next'"
+ then: [T: "rechten"] # phrase(move to the 'right')
+ - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Previous'"
+ then: [T: "linken"] # phrase(move to the 'left')
+ - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'Current'"
+ then: [T: "aktuelle"] # phrase(who is the 'current' president)
+ - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'LineStart'"
+ then: [T: "start der linie"] # phrase(move 'to start of line')
+ - else_if: "substring($NavCommand, string-length($Prefix)+1) = 'LineEnd'"
+ then: [T: "bis zum ende der linie"] # phrase(move 'to end of line')
+ - pause: "medium"
+ - set_variables: [MatchCounter: "1"]
+
+- name: into-or-out-of-silent
+ tag: "*"
+ # saying "out of row n" is not very useful, so skip it
+ match: "$Move2D != '' and (not(@data-from-mathml) or @data-from-mathml = name(.)) and
+ (name(.)='mrow' or name(.) = 'mtr' or name(.) = 'mlabeledtr' or @data-from-mathml = 'mtable')"
+ replace: []
+
+- name: into-or-out-of-mtr
+ tag: [mtr, mlabeledtr]
+ match: "$Move2D = 'in'"
+ replace:
+ - T: "spalte"
+ - x: "count($Child2D/preceding-sibling::*)+1"
+ - pause: "medium"
+
+- name: into-or-out-of-mmultiscripts
+ tag: "*"
+ match: "$Move2D != '' and (@data-from-mathml='mmultiscripts' or self::m:mmultiscripts)"
+ replace:
+ - test:
+ if: "name($Child2D)!='none'"
+ then:
+ - with:
+ variables:
+ - NumPrecedingSiblings: "count($Child2D/preceding-sibling::*)"
+ replace:
+ - x: "$Move2D"
+ - test:
+ - if: "$NumPrecedingSiblings=0"
+ then: [T: "basis"] # phrase(the 'base' of the power)
+ - else_if: "$Child2D/preceding-sibling::*[self::m:mprescripts]" # are we before mprescripts and hence are postscripts
+ then:
+ - test: # in postscripts -- base shifts by one
+ if: "$NumPrecedingSiblings mod 2 = 0"
+ then: [T: "index"] # phrase(x with 'subscript' 2)
+ else: [T: "superscript"] # phrase(x with 'superscript' 2)
+ else:
+ - test:
+ if: "$NumPrecedingSiblings mod 2 = 0"
+ then: [T: "pre-superscript"] # phrase(x with 'pre-superscript' 2)
+ else: [T: "pre-subscript"] # phrase(x with 'pre-subscript' 2)
+ - pause: "medium"
+
+# Rules for speaking what happens when moving into or out of a notation
+- name: into-or-out-of-intent
+ tag: "*"
+ # saying "out of row n" is not very useful, so skip it
+ # match: "$Move2D != '' and @data-from-mathml and @data-from-mathml != name(.) and count(./*)>1 and @data-from-mathml != 'mtable'"
+ match: "$Move2D != '' and count(./*)>1 and @data-from-mathml != 'mtable'"
+ replace:
+ - with:
+ variables:
+ - PartNumber: "count($Child2D/preceding-sibling::*)"
+ - PartName: "GetNavigationPartName(name(.), $PartNumber)"
+ replace:
+ - x: "$Move2D"
+ - test:
+ if: "$PartName != ''"
+ then: [x: "$PartName"]
+ else:
+ - T: "teil" # phrase(the 'part' of the expression)
+ - x: "count($Child2D/preceding-sibling::*) + 1"
+ - pause: "medium"
+
+- name: default-move
+ # nothing to do (not 2D) -- need to catch $Move2D though so rules based on NavCommand don't trigger
+ tag: "*"
+ match: "$Move2D != ''"
+ replace: []
+
+# ********* Go back to last position ***************
+# This is first since start/end position shouldn't matter
+- name: move-last-location
+
+
+ tag: "*"
+ match: "$NavCommand = 'MoveLastLocation'"
+ replace:
+ - test:
+ if: "$NavVerbosity != 'Terse'"
+ then:
+ - test:
+ - if: "$PreviousNavCommand = 'ZoomIn'"
+ then: [T: "zoom in"] # phrase('undo zoom in')
+ - else_if: "$PreviousNavCommand = 'ZoomOut'"
+ then: [T: "zoomen"] # phrase('undo zoom out')
+ - else_if: "$PreviousNavCommand = 'ZoomInAll'"
+ then: [T: "das reinzoomen ganz ausschalten"] # phrase('undo zooming in all the way')
+ - else_if: "$PreviousNavCommand = 'ZoomOutAll'"
+ then: [T: "das auszoomen ganz ausschalten"] # phrase('undo zooming out all the way')
+ - else_if: "$PreviousNavCommand = 'MovePrevious' or $PreviousNavCommand = 'MovePreviousZoom'"
+ then: [T: "rückgängig links"] # phrase('undo move left')
+ - else_if: "$PreviousNavCommand = 'MoveNext' or $PreviousNavCommand = 'MoveNextZoom'"
+ then: [T: "rückgängig rechts"] # phrase('undo move right')
+ - else_if: "$PreviousNavCommand = 'None'"
+ then: [T: "kein vorheriger befehl"] # phrase('no previous command')
+ - pause: "medium"
+ - set_variables: [NavNode: "@id"]
+
+# many times, for typographic reasons, people include punctuation at the end of a math expr
+# these rules detect that and skip speaking it (should be similar regular rule)
+- name: skip-punct-at-end-zoom-in
+ tag: mrow
+ match:
+ - "($NavCommand = 'ZoomIn' or $NavCommand = 'ZoomInAll' or $NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and"
+ - " parent::m:math and count(*)=2 and"
+ - " *[2][translate(.,'.,;:?', '')='']"
+ replace:
+ - x: "*[1]"
+
+# ********* ZoomIn ***************
+- name: zoom-in-leaf
+
+ tag: "*"
+ match: "($NavCommand = 'ZoomIn' or $NavCommand = 'ZoomInAll') and IsNode(., 'leaf')"
+ replace:
+ - test:
+ if: "$MatchCounter = 0 and $NavVerbosity != 'Terse'"
+ then: [T: "ganz eingezommt", pause: "long"] # phrase('zoomed in all of the way')
+ - test:
+ if: "$ReadZoomLevel!=-1"
+ then:
+ - set_variables: [ReadZoomLevel: "0"]
+ - set_variables: [NavNode: "@id"]
+
+# special case of zooming into a table -- move to the first row (if only one row, first column)
+- name: zoom-in-table
+ tag: "*"
+ match: "$NavCommand = 'ZoomIn' and (name(.) = 'mtable' or (count(*)=1 and *[1][@data-from-mathml='mtable']))"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "count(*)=1"
+ then:
+ - set_variables: [NavNode: "*[1]/*[1]/@id"]
+ else:
+ - set_variables: [NavNode: "*[1]/@id"]
+
+- name: zoom-in-mrow-in-math
+ # zooming in only once is meaningless because 'math' has only a single child and it was spoken at the math level -- dig inside and do it again
+ tag: math
+ match: "$NavCommand = 'ZoomIn' or $NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom'"
+ replace:
+ - test:
+ if: "$NavCommand = 'MovePreviousZoom'"
+ then: [x: "*[last()]"]
+ else: [x: "*[1]"]
+
+- # For msqrt and menclose, if the single child isn't an mrow, don't zoom in
+ name: zoom-in-again
+ # If there is only one child, this isn't an interesting move -- zoom in again
+ tag: "*"
+ match:
+ - "($NavCommand = 'ZoomIn' or "
+ - " ($NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and $NavMode='Enhanced') and "
+ - "count(*)=1 and
+ (*[1][self::m:mrow or @data-from-mathml='mrow'] and
+ not(@data-from-mathml='msqrt' or self::m:msqrt or @data-from-mathml='menclose' or self::m:menclose))"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "name(*[1]) != 'mrow'"
+ then:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "IfThenElse(count(*)=0, $Move2D, $Move2D)"] # phrase('in' the denominator)
+ replace: [x: "IfThenElse($NavCommand = 'MovePreviousZoom', 1, $Child2D)"]
+ - test:
+ if: "$NavCommand = 'MovePreviousZoom'"
+ then: [x: "*[last()]"]
+ else: [x: "*[1]"]
+
+- name: zoom-in-enhanced
+ tag: "*"
+ match: "$NavCommand = 'ZoomIn' and $NavMode='Enhanced'"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ - if: "self::m:mtr or self::m:mlabeledtr"
+ then:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "*[1]/*[1]"] # phrase('in' the denominator)
+ replace: [x: "."]
+ - set_variables: [NavNode: "*[1]/*[1]/@id"] # skip mtd
+ - else_if: "*[1][self::m:mrow and (IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false))]" # auto zoom
+ then:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "*[1]"] # phrase('in' the denominator)
+ replace: [x: "."]
+ - set_variables: [NavNode: "*[1]/*[2]/@id"] # skip parens/brackets
+ else:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "*[1]"] # phrase('in' the denominator)
+ replace: [x: "."]
+ - set_variables: [NavNode: "*[1]/@id"]
+
+- name: zoom-in-2D-not-enhanced
+ tag: "*"
+ match: "$NavCommand = 'ZoomIn' and $NavMode!='Enhanced' and (IsNode(., '2D') or not(IsNode(., 'mathml')))"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - with:
+ variables: [Move2D: "'in'", Child2D: "*[1]"] # phrase('in' the denominator)
+ replace: [x: "."]
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace: [x: "*[1]"]
+
+- name: zoom-in-default
+ tag: "*"
+ match: "$NavCommand = 'ZoomIn'"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - with:
+ variables: [Move2D: "'in'", Child2D: "*[1]"] # phrase('in' the denominator)
+ replace: [x: "."]
+ - test:
+ if: "$NavMode='Character'"
+ then: [x: "*[1]"]
+ else_test:
+ if: "self::m:mtd"
+ then: [x: "*[1]"]
+ else:
+ - test:
+ if: "$ReadZoomLevel!=-1"
+ then:
+ - set_variables: [ReadZoomLevel: "DistanceFromLeaf(*[1], true, $NavMode!='Character')"]
+ - set_variables: [NavNode: "*[1]/@id"]
+
+- name: zoom-in-all-default
+ tag: "*"
+ match: "$NavCommand = 'ZoomInAll'"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - with:
+ variables: [Move2D: "'in'", Child2D: "*[1]"] # phrase('in' the denominator)
+ replace: [x: "."]
+ - x: "*[1]"
+
+- name: zoom-out
+ tag: math
+ match: "$NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll'"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - set_variables: [NavNode: "*[1]/@id"] # no-op for $NavCommand = 'ZoomOut'
+
+- name: skip-punct-at-end-zoom-out
+ tag: mrow
+ match:
+ - "($NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll') and"
+ - " parent::m:math and count(*)=2 and"
+ - " *[2][translate(.,'.,;:?', '')='']"
+ replace:
+ - x: ".."
+
+- name: zoom-out-top
+ tag: "*"
+ match:
+ - "($NavCommand = 'ZoomOut' or $NavCommand = 'ZoomOutAll') and"
+ - "parent::m:math "
+ replace:
+ - x: ".." # let math rule deal with it
+
+- name: zoom-out-all-default
+ tag: "*"
+ match: "$NavCommand = 'ZoomOutAll'"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - with:
+ variables: [Move2D: "'aus'", Child2D: "."]
+ replace: [x: ".."]
+ - x: ".."
+
+# deal with internal zooming: MoveNextZoom and MovePreviousZoom
+
+# start with Enhanced mode
+- name: move-zoom-enhanced
+ tag: "*"
+ match:
+ - "($NavCommand = 'MoveNextZoom' or $NavCommand = 'MovePreviousZoom') and "
+ - "$NavMode = 'Enhanced'"
+ replace:
+ - with:
+ variables: [Move2D: "'im'", Child2D: "*[1]"] # phrase('in' the denominator)
+ replace: [x: "."]
+ - test:
+ - if: "count(*)> 1 or IsNode(., 'leaf') or
+ @data-from-mathml='msqrt' or self::m:msqrt or @data-from-mathml='menclose' or self::m:menclose"
+ then: [set_variables: [NavNode: "@id"]]
+ else: [x: "*[1]"]
+
+- name: move-next-zoom-not-enhanced
+ # $ReadZoomLevel must be >= 0
+ tag: "*"
+ match: "$NavCommand = 'MoveNextZoom'"
+ replace:
+ #don't bother with MatchCounter since we only get here if > 1
+ - test:
+ if: "$ReadZoomLevel >= DistanceFromLeaf(., false, $NavMode!='Character')"
+ then:
+ # - with:
+ # variables: [Move2D: "'in'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator)
+ # replace: [x: ".."]
+ - set_variables: [NavNode: "@id"]
+ else:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "*[1]"] # phrase('in' the denominator)
+ replace: [x: "."]
+ - x: "*[1]"
+
+- name: move-previous-zoom-not-enhanced
+ # $ReadZoomLevel must be >= 0
+ tag: "*"
+ match: "$NavCommand = 'MovePreviousZoom'"
+ replace:
+ #don't bother with MatchCounter since we only get here if > 1
+ - test:
+ if: "$ReadZoomLevel >= DistanceFromLeaf(., true, $NavMode!='Character')"
+ then:
+ # - with:
+ # variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator)
+ # replace: [x: ".."]
+ - set_variables: [NavNode: "@id"]
+ else:
+ - with:
+ variables: [Move2D: "'im'", Child2D: "*[last()]"] # phrase('in' the denominator)
+ replace: [x: "."]
+ - x: "*[last()]"
+
+# ********* ZoomOut ***************
+- name: zoom-out-default
+
+
+ tag: mtd
+ match: "$Move2D = '' and ($NavCommand = 'ZoomOut')"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ # we need to speak it here
+ # - T: "Zeile" # phrase(the first 'row' of the matrix)
+ # # if we let the speech rules speak the row, it is given just the MathML for the row, so the row # will always be '1'
+ # - x: "count(../preceding-sibling::*)+1"
+ # - pause: medium
+ - set_variables: [NavNode: "../@id"]
+
+- name: zoom-out
+ # a row around a single element -- these might duplicate the position/offset, so we jump an extra level here
+ tag: "*"
+ match: "$NavCommand = 'ZoomOut'"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "$NavMode='Enhanced' and parent::*[self::m:mrow and (IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false))]"
+ then: [x: ".."] # auto-zoom: move out a level and retry
+ else:
+ - with:
+ variables: [Move2D: "'aus'", Child2D: "."]
+ replace: [x: ".."]
+ - test:
+ if: "parent::m:mtd"
+ then: [x: ".."]
+ else:
+ - test:
+ if: "$ReadZoomLevel!=-1"
+ then: [set_variables: [ReadZoomLevel: "DistanceFromLeaf(.., true, $NavMode!='Character')"]]
+ - set_variables: [NavNode: "../@id"]
+
+# ********* MoveStart/End ***************
+- name: math-move-to-start-or-end
+ tag: math
+ match: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart' or $NavCommand = 'MoveEnd' or $NavCommand = 'MoveLineEnd'"
+ replace:
+ - with:
+ variables: [MatchCounter: "$MatchCounter + 1"]
+ replace:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - test:
+ - if: "$NavCommand = 'MoveStart'"
+ then: [T: "gehe zum start der formel"] # phrase('move to start of math')
+ - else_if: "$NavCommand = 'MoveLineStart'"
+ then: [T: "gehe zum start der linie"] # phrase('move to start of line')
+ - else_if: "$NavCommand = 'MoveEnd'"
+ then: [T: "gehe zum ende der formel"] # phrase('move to end of math')
+ else: [T: "gehe zur ende der linie"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line')
+ - pause: "medium"
+ - test:
+ if: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart'"
+ then:
+ # move inside of the mrow inside of 'math' or inside the fraction, etc (hence two levels down)
+ # Note: an apparent bug in the xpath code doesn't let me use IfThenElse for the 2 if: then: below
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace:
+ - test:
+ if: "*[1]/*[1]" # could be a , so no grandchild
+ then: [x: "*[1]/*[1]"]
+ else: [x: "*[1]"]
+ else:
+ - with:
+ variables: [NavCommand: "'MovePreviousZoom'"]
+ replace:
+ - test:
+ if: "*[last()]/*[last()]" # could be a , so no grandchild
+ then: [x: "*[last()]/*[last()]"]
+ else: [x: "*[last()]"]
+
+# We stop when the parent is 2d (e.g., frac), but not if in leaf base of msub/msup/msubsup/mmultiscripts because that's really on the same line
+- name: move-to-start-or-end-2d
+ tag: "*"
+ match:
+ - "($NavCommand = 'MoveLineStart' or $NavCommand = 'MoveLineEnd') and IsNode(.., '2D') and"
+ - "not( IsNode(., 'leaf') and"
+ - " parent::*[1][self::m:msub or self::m:msup or self::m:msubsup or self::m:mmultiscripts or"
+ - " @data-from-mathml and"
+ - " (@data-from-mathml='msub' or @data-from-mathml='msup' or"
+ - " @data-from-mathml='msubsup' or @data-from-mathml='mmultiscripts')"
+ - " ] )"
+ replace:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - test:
+ if: "$NavCommand = 'MoveLineStart'"
+ then: [T: "bewegen sie sich zum start der linie"] # phrase('move to start of line')
+ else: [T: "bewegen sie sich zum ende der linie"] # "$NavCommand = 'MoveLineEnd'" # phrase('move to end of line')
+ - pause: "medium"
+ - test:
+ if: "self::m:mrow or @data-from-mathml = 'mrow'"
+ then_test:
+ if: "$NavCommand = 'MoveLineStart'"
+ then:
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace: [x: "*[1]"]
+ else:
+ - with:
+ variables: [NavCommand: "'MovePreviousZoom'"]
+ replace: [x: "*[last()]"]
+ else: [set_variables: [NavNode: "@id"]]
+
+- name: move-to-start-or-end-default
+ tag: "*"
+ match: "$NavCommand = 'MoveStart' or $NavCommand = 'MoveLineStart' or $NavCommand = 'MoveEnd' or $NavCommand = 'MoveLineEnd'"
+ replace:
+ - with:
+ variables: [MatchCounter: "$MatchCounter + 1"]
+ replace: [x: ".."]
+
+# Table-related movement
+# Typically, we need to zoom out to the mtd level, then we move the appropriate direction
+- name: not-in-table
+
+
+ tag: math
+ match:
+ - "$NavCommand='MoveCellPrevious' or $NavCommand='MoveCellNext' or"
+ - "$NavCommand='MoveCellUp' or $NavCommand='MoveCellDown' or"
+ - "$NavCommand='MoveColumnStart' or $NavCommand='MoveColumnEnd' or"
+ - "$NavCommand='ReadCellCurrent'"
+ replace:
+ - T: "nicht in der tabelle" # phrase('not in table')
+ - pause: long
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-cell-previous
+ tag: mtd
+ match: "$NavCommand='MoveCellPrevious'"
+ replace:
+ - test:
+ if: "preceding-sibling::*"
+ then:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "nach links" # phrase('move left')
+ - pause: short
+ - test:
+ if: "$NavVerbosity != 'Terse'"
+ then:
+ - T: "spalte" # phrase(the first 'column' of the table)
+ - x: "count(preceding-sibling::*)"
+ - pause: medium
+ - test:
+ if: "$NavMode='Character'"
+ then:
+ - with:
+ variables: [NavCommand: "'MovePreviousZoom'"]
+ replace: [x: "preceding-sibling::*[1]"]
+ else:
+ - set_variables: [NavNode: "preceding-sibling::*[1]/*[1]/@id"]
+ else:
+ - T: "keine vorherige spalte" # phrase('no previous column' in the table)
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-cell-next
+ tag: mtd
+ match: "$NavCommand='MoveCellNext'"
+ replace:
+ - test:
+ if: "following-sibling::*"
+ then:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "rechts" # phrase('move right')
+ - pause: short
+ - test:
+ if: "$NavVerbosity != 'Terse'"
+ then:
+ - T: "spalte" # phrase(the first 'column' in the table)
+ - x: "count(preceding-sibling::*)+2"
+ - pause: medium
+ - test:
+ if: "$NavMode='Character'"
+ then:
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace: [x: "following-sibling::*[1]"]
+ else:
+ - set_variables: [NavNode: "following-sibling::*[1]/*[1]/@id"]
+ else:
+ - T: "keine nächste spalte" # phrase('no next column' in the table)
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-cell-up
+ tag: mtd
+ match: "$NavCommand='MoveCellUp'"
+ replace:
+ - test:
+ if: "../preceding-sibling::*"
+ then:
+ - with:
+ variables: [Column: "count(preceding-sibling::*)+1"] # store this because otherwise the value is used in the wrong context below
+ replace:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "gehe nach oben in der tabelle" # phrase('move up' to previous row in the table)
+ - pause: short
+ - test:
+ if: "$NavVerbosity != 'Terse'"
+ then:
+ - T: "zeile" # phrase(the previous 'row' in the table)
+ - x: "count(../preceding-sibling::*)"
+ - pause: short
+ - T: "spalte" # phrase(the previous 'column' in the table)
+ - x: "count(preceding-sibling::*)+1"
+ - pause: medium
+ - test:
+ if: "$NavMode='Character'"
+ then:
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace: [x: "../preceding-sibling::*[1]/*[$Column]"]
+ else:
+ - set_variables: [NavNode: "../preceding-sibling::*[1]/*[$Column]/*[1]/@id"]
+ else:
+ - T: "keine vorherige zeile" # phrase('no previous row' in the table)
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-cell-down
+ tag: mtd
+ match: "$NavCommand='MoveCellDown'"
+ replace:
+ - test:
+ if: "../following-sibling::*"
+ then:
+ - with:
+ variables: [Column: "count(preceding-sibling::*)+1"] # store this because otherwise the value is used in the wrong context below
+ replace:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "gehe nach unten" # phrase('move down to the next row in the table)
+ - pause: short
+ - test:
+ if: "$NavVerbosity != 'Terse'"
+ then:
+ - T: "reihe" # phrase(the next 'row' in the table)
+ - x: "count(../preceding-sibling::*)+2"
+ - pause: short
+ - T: "spalte" # phrase(the next 'column' in the table)
+ - x: "count(preceding-sibling::*)+1"
+ - pause: medium
+ - test:
+ if: "$NavMode='Character'"
+ then:
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace: [x: "../following-sibling::*[1]/*[$Column]"]
+ else:
+ - set_variables: [NavNode: "../following-sibling::*[1]/*[$Column]/*[1]/@id"]
+ else:
+ - T: "keine nächste Zeile" # phrase('no next row' in the table)
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-cell-up
+ tag: [mtr, mlabeledtr]
+ match: "$NavCommand='MoveCellUp'"
+ replace:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "zur vorherigen zeile" # phrase('move to previous row' to the previous row in the table)
+ - pause: medium
+ - test:
+ if: "preceding-sibling::*"
+ then:
+ - test:
+ if: "$NavMode='Character'"
+ then:
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace: [x: "preceding-sibling::*[1]"]
+ else:
+ - set_variables: [NavNode: "preceding-sibling::*[1]/@id"]
+ else:
+ - T: "keine vorherige zeile" # phrase('no previous row' in the table)
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-cell-down
+ tag: [mtr, mlabeledtr]
+ match: "$NavCommand='MoveCellDown'"
+ replace:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "zur nächsten Zeile" # phrase('move to next row' to the next row in the table)
+ - pause: medium
+ - test:
+ if: "following-sibling::*"
+ then:
+ - test:
+ if: "$NavMode='Character'"
+ then:
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace: [x: "following-sibling::*[1]"]
+ else:
+ - set_variables: [NavNode: "following-sibling::*[1]/@id"]
+ else:
+ - T: "keine nächste Zeile" # phrase('no next row' in the table)
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-cell-previous
+ # if a row is selected, there is no previous/next column, so this is trivial
+ tag: [mtr, mlabeledtr]
+ match: "$NavCommand='MoveCellPrevious'"
+ replace:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "übergehen sie zur vorherigen spalte" # phrase('move to previous column' to the previous row in the table)
+ - pause: medium
+ - T: "keine vorherige spalte" # phrase('no previous column' in the table)
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-cell-next
+ # if a row is selected, there is no previous/next column, so this is trivial
+ tag: [mtr, mlabeledtr]
+ match: "$NavCommand='MoveCellNext'"
+ replace:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "gehe nach oben" # phrase('move up' to the previous row in the table)
+ - pause: medium
+ - T: "keine nächste Zeile" # phrase('no next row' in the table)
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: default-read-cell
+ tag: "*"
+ match: "$NavCommand='ReadCellCurrent'"
+ replace:
+ - with:
+ variables: [MTD: "ancestor::m:mtd"]
+ replace:
+ - test:
+ if: "$MTD"
+ then:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "aktuelle eintrag lesen" # phrase('read current entry' in the table)
+ - pause: medium
+ - test:
+ if: "$NavVerbosity != 'Terse'"
+ then:
+ - T: "zeile" # phrase(the previous 'row' in the table)
+ - x: "count($MTD[1]/../preceding-sibling::*)+1"
+ - pause: short
+ - T: "spalte" # phrase(the previous 'column' in the table)
+ - x: "count($MTD[1]/preceding-sibling::*)+1"
+ - pause: short
+ - set_variables: [NavNode: "$MTD[1]/*[1]/@id"]
+ else:
+ - T: "nicht in tabelle" # phrase('not in table' or matrix)
+ - pause: long
+ - set_variables: [SpeakExpression: "'false'"]
+
+# mtd ? ( $NavCommand='MoveColumnStart' )
+# => MoveColStart {
+# ruleRef = name(^^match);
+# column = index(match);
+# ::StartPosition = ^^match[0][index(match)][0].dfs;
+# ::EndPosition = ^^match[0][index(match)][0].offset;
+# };
+
+# mtd ? ( $NavCommand='MoveColumnEnd' )
+# => MoveColEnd {
+# ruleRef = name(^^match);
+# column = index(match);
+# ::StartPosition = ^^match[count(^^match)-1][index(match)][0].dfs;
+# ::EndPosition = ^^match[count(^^match)-1][index(match)][0].offset;
+# };
+
+
+
+# # Rules for columnar math (mstack and mlongdiv) -- each row is an msrow or mscarries except for the start of mlongdiv
+# # FIX: not dealing with different number of digits on different lines
+# # FIX: not dealing with + (etc) on same line if they are on the right side (Dutch, others)
+# # FIX: not dealing with intervening msline (say it and move on??)
+# # FIX: not dealing with carries well
+# # FIX: not dealing with navigation of first three children of mlongdiv
+# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') && has_previous(match) )
+# => MoveCell {
+# ruleRef = name(^^match);
+# wordRef = "previous";
+# ::StartPosition = previous(match).dfs;
+# ::EndPosition = previous(match).offset;
+# };
+
+# # no previous child -- in first column -- don't move
+# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious' ) )
+# => MoveCell {
+# ruleRef = name(^^match);
+# wordRef = "previous";
+# childIndex = -1; # key to know what to say for each notation
+# ::SpeakAfterMove = false;
+# };
+
+# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') && has_next(match) )
+# => MoveCell {
+# ruleRef = name(^^match);
+# wordRef = "next";
+# ::StartPosition = next(match).dfs;
+# ::EndPosition = next(match).offset;
+# };
+
+# # no next child -- in first column -- don't move
+# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext' ) )
+# => MoveCell {
+# ruleRef = name(^^match);
+# wordRef = "next";
+# childIndex = -1; # key to know what to say for each notation
+# ::SpeakAfterMove = false;
+# };
+
+# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# $NavCommand='MoveCellUp' && has_previous(^^match) )
+# => MoveCell {
+# ruleRef = name(^^match);
+# wordRef = "up";
+# ::StartPosition = ^^^match[index(^^match)-1][-1][index(match)-count(^match)].dfs;
+# ::EndPosition = ^^^match[index(^^match)-1][-1][index(match)-count(^match)].offset;
+# };
+
+# # no previous child -- in first column -- don't move
+# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# $NavCommand='MoveCellUp' )
+# => MoveCell {
+# ruleRef = name(^^match);
+# wordRef = "up";
+# childIndex = -1; # key to know what to say for each notation
+# ::SpeakAfterMove = false;
+# };
+
+# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# $NavCommand='MoveCellDown' && has_next(^^match) )
+# => MoveCell {
+# ruleRef = name(^^match);
+# wordRef = "down";
+# ::StartPosition = ^^^match[index(^^match)+1][-1][index(match)-count(^match)].dfs;
+# ::EndPosition = ^^^match[index(^^match)+1][-1][index(match)-count(^match)].offset;
+# };
+
+# # no previous child -- in first column -- don't move
+# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# $NavCommand='MoveCellDown' )
+# => MoveCell {
+# ruleRef = name(^^match);
+# wordRef = "down";
+# childIndex = -1; # key to know what to say for each notation
+# ::SpeakAfterMove = false;
+# };
+
+# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# $NavCommand='MoveColumnStart' )
+# => MoveColStart {
+# ruleRef = name(^^match);
+# column = index(match);
+# ::StartPosition = ^^^match[0][-1][index(match)-count(^match)].dfs;
+# ::EndPosition = ^^^match[0][-1][index(match)-count(^match)].offset;
+# };
+
+# char ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# $NavCommand='MoveColumnEnd' )
+# => MoveColEnd {
+# ruleRef = name(^^match);
+# column = index(match);
+# ::StartPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].dfs;
+# ::EndPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].offset;
+# };
+
+# any ? ( (name(match)=="mn" || name(match)=="none") &&
+# has_parent(match) && name(^match)=="mscarries" &&
+# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') && has_previous(match) )
+# => MoveCell {
+# ruleRef = name(^match);
+# wordRef = "previous";
+# ::StartPosition = previous(match).dfs;
+# ::EndPosition = previous(match).offset;
+# };
+
+# # no previous child -- in first column -- don't move
+# any ? ( (name(match)=="mn" || name(match)=="none") &&
+# has_parent(match) && name(^match)=="mscarries" &&
+# ($NavCommand="MovePrevious" || $NavCommand='MoveCellPrevious') )
+# => MoveCell {
+# ruleRef = name(^match);
+# wordRef = "previous";
+# childIndex = -1; # key to know what to say for each notation
+# ::SpeakAfterMove = false;
+# };
+
+# any ? ( (name(match)=="mn" || name(match)=="none") &&
+# has_parent(match) && name(^match)=="mscarries" &&
+# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') && has_next(match) )
+# => MoveCell {
+# ruleRef = name(^match);
+# wordRef = "next";
+# ::StartPosition = next(match).dfs;
+# ::EndPosition = next(match).offset;
+# };
+
+# # no next child -- in last column -- don't move
+# any ? ( (name(match)=="mn" || name(match)=="none") &&
+# has_parent(match) && name(^match)=="mscarries" &&
+# ($NavCommand="MoveNext" || $NavCommand='MoveCellNext') )
+# => MoveCell {
+# ruleRef = name(^match);
+# wordRef = "next";
+# childIndex = -1; # key to know what to say for each notation
+# ::SpeakAfterMove = false;
+# };
+
+# any ? ( (name(match)=="mn" || name(match)=="none") &&
+# has_parent(match) && name(^match)=="mscarries" &&
+# $NavCommand='MoveCellUp' && has_previous(^match) )
+# => MoveCell {
+# ruleRef = name(^match);
+# wordRef = "up";
+# ::StartPosition = ^^match[index(^match)-1][index(match)-count(^match)].dfs;
+# ::EndPosition = ^^match[index(^match)-1][index(match)-count(^match)].offset;
+# };
+
+# # no previous child -- in first row -- don't move
+# any ? ( (name(match)=="mn" || name(match)=="none") &&
+# has_parent(match) && name(^match)=="mscarries" &&
+# $NavCommand='MoveCellUp' )
+# => MoveCell {
+# ruleRef = name(^match);
+# wordRef = "up";
+# childIndex = -1; # key to know what to say for each notation
+# ::SpeakAfterMove = false;
+# };
+
+# any ? ( (name(match)=="mn" || name(match)=="none") &&
+# has_parent(match) && name(^match)=="mscarries" &&
+# $NavCommand='MoveCellDown' && has_next(^match) )
+# => MoveCell {
+# ruleRef = name(^match);
+# wordRef = "down";
+# ::StartPosition = ^^match[index(^match)+1][-1][index(match)-count(^match)].dfs;
+# ::EndPosition = ^^match[index(^match)+1][-1][index(match)-count(^match)].offset;
+# };
+
+# # no next child -- in last row -- don't move
+# any ? ( (name(match)=="mn" || name(match)=="none") &&
+# has_parent(match) && name(^match)=="mscarries" &&
+# $NavCommand='MoveCellDown' )
+# => MoveCell {
+# ruleRef = name(^match);
+# wordRef = "down";
+# childIndex = -1; # key to know what to say for each notation
+# ::SpeakAfterMove = false;
+# };
+
+# mn ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# $NavCommand='MoveColumnStart' )
+# => MoveColStart {
+# ruleRef = name(^^match);
+# column = index(match);
+# ::StartPosition = ^^^match[0][-1][index(match)-count(^match)].dfs;
+# ::EndPosition = ^^^match[0][-1][index(match)-count(^match)].offset;
+# };
+
+# mn ? ( has_parent(match, 2) && name(^match)=="mn" && name(^^match)=="msrow" &&
+# $NavCommand='MoveColumnEnd' )
+# => MoveColEnd {
+# ruleRef = name(^^match);
+# column = index(match);
+# ::StartPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].dfs;
+# ::EndPosition = ^^^match[count(^^^match)-1][-1][index(match)-count(^match)].offset;
+# };
+
+
+
+- name: default-cell-move
+
+ tag: "*"
+ match:
+ - "$NavCommand='MoveCellPrevious' or $NavCommand='MoveCellNext' or"
+ - "$NavCommand='MoveCellUp' or $NavCommand='MoveCellDown' or"
+ - "$NavCommand='MoveColumnStart' or $NavCommand='MoveColumnEnd' or"
+ - "$NavCommand='ReadCellCurrent'"
+ replace:
+ - test:
+ if: "ancestor::m:mtd"
+ then:
+ - x: "ancestor::m:mtd[1]" # try again on an mtd node
+ else:
+ - T: "nicht in tabelle" # phrase('not in table' or matrix)
+ - pause: long
+ - set_variables: [SpeakExpression: "'false'"]
+
+# ======== Move/Read/Describe Next rules =================
+
+# skip 'none'
+- name: move-next-none
+ tag: "none"
+ match:
+ - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext' or $NavCommand = 'DescribePrevious' or $NavCommand = 'MoveNextZoom') and"
+ - "parent::*[1][name(.)='mmultiscripts'] and following-sibling::*"
+ replace:
+ - with:
+ variables: [Following: "following-sibling::*[1]"]
+ replace:
+ # two 'none's in a row -- move over and try again; one 'none', zoom in on next
+ - test:
+ if: "$Following[name(.)='none']"
+ then: [x: "$Following"]
+ else:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "$Following"] # phrase('in' the denominator)
+ replace: [x: ".."]
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace: [x: "$Following"]
+
+# skip 'none'
+- name: move-previous-none
+ tag: "none"
+ match:
+ - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious' or $NavCommand = 'MovePreviousZoom') and"
+ - "parent::*[1][name(.)='mmultiscripts'] and preceding-sibling::*"
+ replace:
+ - with:
+ variables: [Preceding: "preceding-sibling::*[1]"]
+ replace:
+ # two 'none's in a row -- move over and try again; one 'none', zoom in on preceding
+ - test:
+ if: "$Preceding[name(.)='none']"
+ then: [x: "$Preceding"]
+ else:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "$Preceding"] # phrase('in' the denominator)
+ replace: [x: ".."]
+ - with:
+ variables: [NavCommand: "'MovePreviousZoom'"]
+ replace: [x: "$Preceding"]
+
+
+
+# skip invisible chars except for Enhanced mode when "times" should be read
+- name: move-next-invisible
+ tag: "*"
+ match:
+ - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and"
+ - "following-sibling::*[1][name(.)='mo' and translate(., '\u2061\u2062\u2063\u2064', '')='']"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "following-sibling::*[1][.='\u2062' or .='\u2064'] and
+ ($NavMode='Enhanced' or ($NavMode='Simple' and following-sibling::*[2][not(IsNode(., 'mathml'))]))" # invisible times and plus
+ then: [set_variables: [NavNode: "following-sibling::*[1]/@id"]]
+ else: [x: "following-sibling::*[1]"]
+
+- name: move-next-no-auto-zoom-at-edge
+ # at edge of 2D and in a mode where moving right isn't an option
+ tag: "*"
+ variables: [EdgeNode: "EdgeNode(., 'right', '2D')"]
+ match: "$NavCommand = 'MoveNext' and $NavMode!='Character' and not($AutoZoomOut) and $EdgeNode/@id!=@id"
+ replace:
+ - test:
+ if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'"
+ then:
+ - T: "kann nicht nach rechts bewegen" # phrase('cannot move right')
+ - pause: medium
+ - with:
+ variables: [Move2D: "'end of'", Child2D: "$EdgeNode/*[last()]"]
+ replace: [x: "$EdgeNode"]
+ - pause: long
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-next-no-auto-zoom-at-edge-math
+ # at edge of math -- no where to go (must be after we rule out being at the edge of 2D) because we want to speak that
+ tag: "*"
+ match:
+ - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and"
+ - "(self::m:math or name(EdgeNode(., 'right', 'math'))='math')" # at edge of math
+ replace:
+ - test:
+ if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'"
+ then:
+ - T: "kann nicht" # phrase('cannot' move right in expression)
+ - test:
+ - if: "$NavCommand = 'MoveNext'"
+ then: [T: "bewegen sie"] # phrase('move' to next entry in table)
+ - else_if: "$NavCommand = 'ReadNext'"
+ then: [T: "lesen sie"] # phrase('read' next entry in table)
+ else: [T: "beschreiben"] # phrase('describe' next entry in table)
+ - T: "rechts" # phrase(move 'right')
+ - pause: short
+ - T: "ende der formel" # phrase(move 'end of math')
+ - pause: long
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-next-auto-zoom-up-one-level
+ # Last child or in auto-zoom'd in-- move up a level and try again
+ # Note: we've already checked the for the case where we are at an edge and should not AutoZoomOut
+ tag: "*"
+ match:
+ - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and"
+ - "( not(following-sibling::*) or"
+ - " ( $NavMode='Enhanced' and "
+ - " count(following-sibling::*)=1 and (IsBracketed(.., '(', ')') or IsBracketed(.., '[', ']'))"
+ - " )"
+ - ")"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "following-sibling::*"
+ then:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "."] # phrase('in' the denominator)
+ replace: [x: ".."]
+ else:
+ - with:
+ variables: [Move2D: "'out of'", Child2D: "."]
+ replace: [x: ".."]
+ - x: ".."
+
+# At this point, if XXXNext, then we know there is must be a right sibling
+- name: move-next-default
+ tag: mtd
+ match: "$Move2D = '' and ($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext')"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "following-sibling::*"
+ then:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "spalte" # phrase(the previous 'column' in the table)
+ - x: "count(preceding-sibling::*)+2"
+ - pause: short
+ - test:
+ if: "$NavMode = 'Character'"
+ then:
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace: [x: "following-sibling::*[1]"]
+ else: [set_variables: [NavNode: "following-sibling::*[1]/*[1]/@id"]]
+ else:
+ - x: ".." # try again at the row level
+
+- name: move-next-default
+ tag: [mtr, mlabeledtr]
+ match: "$Move2D = '' and
+ ($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and
+ following-sibling::*"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "$NavMode = 'Character'"
+ then:
+ - with:
+ variables: [NavCommand: "'MoveNextZoom'"]
+ replace: [x: "following-sibling::*[1]"]
+ else:
+ - set_variables: [NavNode: "following-sibling::*[1]/@id"]
+
+- name: move-next-auto-zoom-parens
+ # auto-zoom into next child if next child is parenthesized expr
+ tag: "*"
+ match:
+ - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and"
+ - "$NavMode='Enhanced' and"
+ - "parent::m:mrow and following-sibling::* and"
+ - "following-sibling::*[1][self::m:mrow and count(*)=3 and " #exclude empty parens
+ - " (IsBracketed(., '(', ')') or IsBracketed(., '[', ']'))"
+ - " ]"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - set_variables: [NavNode: "following-sibling::*[1]/*[2]/@id"]
+
+# normal cases for MoveNext
+- name: move-next-locked-zoom-level
+ # locked zoom level
+ tag: "*"
+ match:
+ - "($NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext') and"
+ - "$ReadZoomLevel>=0"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ # if in base (nothing before), we must be moving to a script, so "in" will be said
+ if: "preceding-sibling::* and following-sibling::*[1][name(.)='none']"
+ then:
+ - with:
+ variables: [Move2D: "'out of'", Child2D: "."]
+ replace: [x: ".."]
+ - with:
+ variables: [MatchCounter: "$MatchCounter + 1"]
+ replace: [x: "following-sibling::*[1]"] # skip over 'none'
+ else:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator)
+ replace: [x: ".."]
+ - with:
+ variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"]
+ replace: [x: "following-sibling::*[1]"]
+
+- name: move-next-default
+ tag: "*"
+ match: "$NavCommand = 'MoveNext' or $NavCommand = 'ReadNext' or $NavCommand = 'DescribeNext'"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "following-sibling::*[1][@data-from-mathml='none' or @data-from-mathml='mprescripts']"
+ then: [x: "following-sibling::*[1]"]
+ else:
+ - test:
+ if: "IsNode(.., '2D') or not(IsNode(.., 'mathml'))"
+ then:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "following-sibling::*[1]"] # phrase('in' the denominator)
+ replace: [x: ".."]
+ - set_variables: [NavNode: "following-sibling::*[1]/@id"]
+
+# ======== Move/Read/Describe Previous rules =================
+
+# skip invisible chars except for Enhanced mode when "times" should be read
+- name: move-previous-invisible
+ tag: "*"
+ match:
+ - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and"
+ - "preceding-sibling::*[1][name(.)='mo' and translate(., '\u2061\u2062\u2063\u2064', '')='']"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - with:
+ variables: [MatchCounter: "$MatchCounter + 1"]
+ replace:
+ - test:
+ if: "preceding-sibling::*[1][.='\u2062' or .='\u2064'] and $NavMode='Enhanced'" # invisible times and plus
+ then: [set_variables: [NavNode: "preceding-sibling::*[1]/@id"]]
+ else: [x: "preceding-sibling::*[1]"]
+
+# two rules for when can't move left
+- name: move-previous-no-auto-zoom-at-edge
+ # at edge of 2D and in a mode where moving left isn't an option
+ tag: "*"
+ variables: [EdgeNode: "EdgeNode(., 'left', '2D')"]
+ match: "$NavCommand = 'MovePrevious' and $NavMode!='Character' and not($AutoZoomOut) and $EdgeNode/@id!=@id"
+ replace:
+ - test:
+ if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose' and $NavCommand = 'MovePrevious'"
+ then:
+ - T: "kann sich nicht links bewegen" # phrase('cannot move left' in expression)
+ - pause: medium
+ - with:
+ variables: [Move2D: "'end of'", Child2D: "$EdgeNode/*[1]"]
+ replace: [x: "$EdgeNode"]
+ - pause: long
+
+- name: move-previous-no-auto-zoom-at-edge-of-math
+ # at edge of math -- no where to go (must be after we rule out being at the edge of 2D) because we want to speak that
+ tag: "*"
+ match:
+ - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and"
+ - "(self::m:math or name(EdgeNode(., 'left', 'math'))='math')"
+ replace:
+ - T: "start der mathematik" # phrase('start of math')
+ - pause: long
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-previous-at-end
+ tag: "*"
+ match:
+ - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and"
+ - "name(EdgeNode(., 'left', 'math'))='math'" # at edge of math
+ replace:
+ - test:
+ if: "$MatchCounter = 0 and $NavVerbosity = 'Verbose'"
+ then:
+ - T: "kann nicht nach links bewegen" # phrase('cannot move left')
+ - pause: short
+ - with:
+ variables: [Move2D: "'start of'", Child2D: "."]
+ replace: [x: "."]
+ - pause: long
+ - set_variables: [SpeakExpression: "'false'"]
+
+- name: move-previous-auto-zoom-up-one-level
+ # Last child or in auto-zoom'd in-- move up a level and try again
+ # Note: we've already checked the for the case where we are at an edge and should not AutoZoomOut
+ tag: "*"
+ match:
+ - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and"
+ - "( not(preceding-sibling::*) or"
+ - " ( $NavMode='Enhanced' and "
+ - " count(preceding-sibling::*)=1 and (IsBracketed(.., '(', ')') or IsBracketed(.., '[', ']'))"
+ - " )"
+ - ")"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "preceding-sibling::*"
+ then:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "."] # phrase('in' the denominator)
+ replace: [x: ".."]
+ else:
+ - with:
+ variables: [Move2D: "'out of'", Child2D: "."]
+ replace: [x: ".."]
+ - x: ".."
+
+- name: move-previous-auto-zoom-parens
+ # auto-zoom into previous child if previous child is parenthesized expr
+ # Note: there is an asymmetry here from MoveNext because the base of a scripted might have parens for grouping, but not true for the script
+ tag: "*"
+ match:
+ - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and"
+ - "$NavMode='Enhanced' and"
+ - "preceding-sibling::* and"
+ - "(parent::m:mrow or parent::m:msub or parent::m:msup or"
+ - " (count(preceding-sibling::*)=1 and (parent::m:msubsup or parent::m:mmultiscripts))" # make sure moving into base
+ - ") and"
+ - "preceding-sibling::*[1][self::m:mrow and count(*)=3 and " #exclude empty parens
+ - " (IsBracketed(., '(', ')') or IsBracketed(., '[', ']'))"
+ - " ]"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "not(parent::m:mrow)"
+ then:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator)
+ replace: [x: ".."]
+ - set_variables: [NavNode: "preceding-sibling::*[1]/*[2]/@id"]
+
+# normal cases for MovePrevious
+
+- name: move-previous-default
+ tag: mtd
+ match: "$Move2D = '' and
+ ($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and
+ preceding-sibling::*"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - T: "spalte" # phrase(the first 'column' in the table)
+ - x: "count(preceding-sibling::*)"
+ - pause: short
+ - test:
+ if: "$NavMode = 'Character'"
+ then:
+ - with:
+ variables: [NavCommand: "'MovePreviousZoom'"]
+ replace: [x: "preceding-sibling::*[1]"]
+ else: [set_variables: [NavNode: "preceding-sibling::*[1]/*[last()]/@id"]]
+
+- name: move-previous-default
+ tag: [mtr, mlabeledtr]
+ match: "$Move2D = '' and ($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious')"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "preceding-sibling::*"
+ then:
+ - test:
+ if: "$NavMode = 'Character'"
+ then:
+ - with:
+ variables: [NavCommand: "'MovePreviousZoom'"]
+ replace: [x: "preceding-sibling::*[1]"]
+ else:
+ - set_variables: [NavNode: "preceding-sibling::*[1]/@id"]
+ else: [x: ".."] # try again for after
+
+- name: move-previous-locked-zoom-level
+ # locked zoom level
+ tag: "*"
+ match:
+ - "($NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious') and"
+ - "$ReadZoomLevel>=0"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ # if moving into base (nothing before), we must be moving to the base, so "in" will be said
+ if: "count(preceding-sibling::*) > 2 and preceding-sibling::*[1][name(.)='none']"
+ then:
+ - with:
+ variables: [Move2D: "'out of'", Child2D: "."]
+ replace: [x: ".."]
+ - x: "preceding-sibling::*[1]" # skip over 'none'
+ else:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator)
+ replace: [x: ".."]
+ - with:
+ variables: [NavCommand: "'MovePreviousZoom'"]
+ replace: [x: "preceding-sibling::*[1]"]
+
+- name: move-previous-default
+ tag: "*"
+ match: "$NavCommand = 'MovePrevious' or $NavCommand = 'ReadPrevious' or $NavCommand = 'DescribePrevious'"
+ replace:
+ - with:
+ variables: [SayCommand: "string($NavVerbosity = 'Verbose')"]
+ replace: [x: "."]
+ - test:
+ if: "preceding-sibling::*[1][@data-from-mathml='none' or @data-from-mathml='mprescripts']"
+ then: [x: "preceding-sibling::*[1]"]
+ else:
+ - test:
+ if: "IsNode(.., '2D') or not(IsNode(.., 'mathml'))"
+ then:
+ - with:
+ variables: [Move2D: "'in'", Child2D: "preceding-sibling::*[1]"] # phrase('in' the denominator)
+ replace: [x: ".."]
+ - set_variables: [NavNode: "preceding-sibling::*[1]/@id"]
+
+# ********* ReadZoomLevel toggle ***************
+# These set ::NavMode
+
+- name: toggle-mode-up
+ tag: "*"
+ match: "$NavCommand = 'ToggleZoomLockUp'"
+ replace:
+ - test:
+ - if: "$NavMode = 'Enhanced'"
+ then:
+ - T: "Zeichen" # phrase(a mathematical 'character')
+ - set_variables: [NavMode: "'Character'", ReadZoomLevel: "1"]
+ - else_if: "$NavMode = 'Character'"
+ then:
+ - T: "einfache" # phrase(a 'simple' way to do something)
+ - set_variables: [NavMode: "'Simple'", ReadZoomLevel: "1"]
+ - else:
+ - T: "verbesserte" # phrase(an 'enhanced' way to do something)
+ - set_variables: [NavMode: "'Enhanced'", ReadZoomLevel: "-1"]
+ - T: "Art" # phrase(a simple 'mode' of use)
+ - pause: long
+ - test:
+ - if: "$NavMode != 'Enhanced'" # potentially need to zoom to the sibling
+ then:
+ - with:
+ variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"]
+ replace: [x: "."]
+
+- name: toggle-mode-down
+ tag: "*"
+ match: "$NavCommand = 'ToggleZoomLockDown'"
+ replace:
+ - test:
+ - if: "$NavMode = 'Enhanced'"
+ then:
+ - T: "einfache" # phrase(an 'simple' way to do something)
+ - set_variables: [NavMode: "'Simple'", ReadZoomLevel: "1"]
+ - else_if: "$NavMode = 'Character'"
+ then:
+ - T: "verbesserte" # phrase(an 'enhanced' way to do something)
+ - set_variables: [NavMode: "'Enhanced'", ReadZoomLevel: "-1"]
+ - else:
+ - T: "Zeichen" # phrase(a mathematical 'character')
+ - set_variables: [NavMode: "'Character'", ReadZoomLevel: "1"]
+ - T: "modus" # phrase(a simple 'mode' of use)
+ - pause: long
+ - test:
+ - if: "$NavMode != 'Enhanced'" # potentially need to zoom to the sibling
+ then:
+ - with:
+ variables: [MatchCounter: "$MatchCounter + 1", NavCommand: "'MoveNextZoom'"]
+ replace: [x: "."]
+
+- name: toggle-speech-describe
+ tag: "*"
+ match: "$NavCommand = 'ToggleSpeakMode'"
+ replace:
+ - test:
+ if: "$Overview = 'true'"
+ then:
+ - T: "ausdruck nach der bewegung sprechen" # phrase('speak expression after move')
+ - pause: long
+ - set_variables: [Overview: "'false'"]
+ else:
+ - T: "überblick des ausdrucks nach der bewegung sprechen" # phrase('overview of expression after move')
+ - pause: long
+ - set_variables: [Overview: "'true'"]
+
+- name: current
+ tag: "*"
+ match: "$NavCommand = 'ReadCurrent' or $NavCommand = 'DescribeCurrent'"
+ replace:
+ - test:
+ if: "$NavVerbosity = 'Verbose'"
+ then:
+ - test:
+ - if: "$NavCommand = 'ReadCurrent'"
+ then: [T: "lese"] # phrase('read' next entry in table)
+ else: [T: "beschreibe"] # phrase('describe' next entry in table)
+ - T: "aktueller" # phrase('current' entry in table)
+ - pause: long
+ - set_variables: [NavNode: "@id"]
+
+# this needs to be near the end because we only test for 'Describe', "Read", etc., and we don't want to get 'DescribeNext', etc.
+- name: placemarker
+
+ tag: "*"
+ match:
+ - "starts-with($NavCommand, 'Read') or "
+ - "starts-with($NavCommand, 'Describe') or "
+ - "starts-with($NavCommand, 'MoveTo')"
+ replace:
+ - test:
+ if: "$NavVerbosity != 'Terse'"
+ then:
+ - test:
+ - if: "starts-with($NavCommand, 'Read')"
+ then: [T: "lese"] # phrase('read' next entry in table)
+ - else_if: "starts-with($NavCommand, 'Describe')"
+ then: [T: "beschreibe"] # phrase('describe' next entry in table)
+ - else_if: "starts-with($NavCommand, 'MoveTo')"
+ then: [T: "wechsel zu"] # phrase('move to' the next entry in table)
+ else: [T: "setze"] # phrase('set' the value of the next entry in table)
+ - T: "platzhalter" # phrase('placeholder' for the value)
+ - x: "$PlaceMarkerIndex"
+ - pause: long
+ - set_variables: [NavNode: "$PlaceMarker"]
+
+- name: set-placemarker
+ tag: "*"
+ match: "starts-with($NavCommand, 'SetPlacemarker')"
+ replace:
+ - test:
+ if: "$NavVerbosity != 'Terse'"
+ then:
+ - T: "platzhalter" # phrase('set placeholder' to the value)
+ - x: "$PlaceMarkerIndex"
+ - pause: long
+ - set_variables: [NavNode: "@id"]
+
+# ********* WhereAmI ***************
+
+# FIX: WhereAmI needs support from the Rust code to loop around and do speech at each iteration.
+# Alternatively, it could insert a special token that Rust code does a "replace" on with the speech (e.g. SPEECH_AT{id})
+# or a new command "speak" which takes a node id
+- name: where-am-i-start
+ tag: "*"
+ match: "($NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll') and $MatchCounter = 0"
+ replace:
+ - translate: "@id"
+ - pause: long
+ - with:
+ variables: [MatchCounter: "$MatchCounter + 1"]
+ replace: [x: ".."]
+
+- name: where-am-i-stop
+ tag: "*"
+ match:
+ - "($NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll') and $MatchCounter > 0 and"
+ # stopping conditions
+ - "(self::m:math or "
+ - " parent::*[self::m:math and (count(*)=1 or (count(*)=2 and *[2][.=',' or .='.' or .=';' or .='?']) ) ] "
+ - ")"
+ replace:
+ - test:
+ if: "$NavCommand = 'WhereAmI'"
+ then:
+ - T: "in nichts mehr" # phrase('inside of nothing more')
+ - pause: long
+ - set_variables: [SpeakExpression: "'false'"]
+ else:
+ - T: "inside" # phrase('inside' a big expression)
+ - pause: medium
+ - set_variables: [NavNode: "@id"]
+
+- name: where-am-i-middle
+ tag: "*"
+ match: "$NavCommand = 'WhereAmI' or $NavCommand = 'WhereAmIAll'"
+ replace:
+ - T: "in" # phrase('inside' a big expression)
+ - pause: medium
+ - test:
+ - if: "$NavMode='Enhanced' and parent::*[self::m:mrow and (IsBracketed(., '(', ')', false) or IsBracketed(., '[', ']', false))]"
+ then: [x: ".."] # auto-zoom up
+ - else_if: "$NavCommand = 'WhereAmI'"
+ then: [set_variables: [NavNode: "@id"]]
+ else:
+ - translate: "@id"
+ - pause: long
+ - x: '..'
diff --git a/Rules/Languages/de/overview.yaml b/Rules/Languages/de/overview.yaml
new file mode 100644
index 00000000..346734e2
--- /dev/null
+++ b/Rules/Languages/de/overview.yaml
@@ -0,0 +1,121 @@
+---
+# Provide an overview/outline/description of the math
+# MathPlayer just tried to shorten things like "mfrac" by just saying "fraction"
+# For mrow, it say up to 5 operands and just say "and n more things" for the rest
+# This results in strings of varying length. Given human memory is about 7 words long,
+# it would be better to aim for 7 words (maybe aim for a range of 6-10 words).
+# Idea:
+# Start by generating a terse form of the speech
+# At every step when the strings are being joined
+# a) if the #words <= 7, return the joined string
+# b) otherwise, set verbosity to 'overview' and regenerate the expression and use that
+# There is a balance that you want to maximize the info given, so 10 words is likely better then 3.
+# That might mean that at the top level, we may want to allow the first few children to expand
+
+
+- name: overview-default
+ tag: [mfrac, fraction]
+ match: "."
+ replace:
+ - test:
+ if: "IsNode(*[1], 'simple') and IsNode(*[2], 'simple')"
+ then:
+ - x: "*[1]"
+ - T: "durch"
+ - x: "*[2]"
+ else:
+ - T: "bruch"
+
+- name: overview-default
+ tag: [msqrt, "square-root"]
+ match: "."
+ replace:
+ - T: "quadratwurzel"
+ - test:
+ if: "IsNode(*[1], 'simple')"
+ then:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "von"]
+ - x: "*[1]"
+
+- name: overview-default
+ tag: [mroot, root]
+ match: "."
+ replace:
+ - test:
+ if: "*[2][self::m:mn]"
+ then_test:
+ - if: "*[2][.='2']"
+ then: [T: "quadratwurzel"]
+ - else_if: "*[2][.='3']"
+ then: [T: "dritte wurzel"]
+ - else_if: "*[2][not(contains(., '.'))]"
+ then: [x: "ToOrdinal(*[2])", T: "wurzel"]
+ else:
+ - test:
+ if: "*[2][self::m:mi][string-length(.)=1]"
+ then:
+ - x: "*[2]"
+ - pronounce: [{text: "-te"}, {ipa: "te"}, {sapi5: "te"}, {eloquence: "T"}]
+ else: {x: "*[2]"}
+ - T: "wurzel"
+ - test:
+ if: "IsNode(*[1], 'simple')"
+ then:
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "von"]
+ - x: "*[1]"
+
+- name: matrix-override
+ tag: mrow
+ match:
+ - "*[2][self::m:mtable] and"
+ - "(IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|'))"
+ replace:
+ - T: "die"
+ - x: count(*[2]/*)
+ - T: "von"
+ - x: count(*[2]/*[self::m:mtr][1]/*)
+ - test:
+ if: "*[1][.='|']" # just need to check the first bracket since we know it must be (, [, or |
+ then: [T: "determinante"]
+ else: [T: "matrix"]
+
+- name: overview-default
+ tag: mtable
+ match: "."
+ replace:
+ - T: "die"
+ - x: count(*[2]/*)
+ - T: "von"
+ - x: count(*[2]/*[self::m:mtr][1]/*)
+ - T: "tabelle"
+
+- name: short-mrow
+ tag: mrow
+ match: "count(*)<6"
+ replace:
+ - insert:
+ nodes: "*"
+ replace: [pause: auto]
+
+- name: long-mrow
+ tag: mrow
+ match: "."
+ replace:
+ - x: "*[1]"
+ - pause: auto
+ - x: "*[2]"
+ - pause: auto
+ - x: "*[3]"
+ - pause: auto
+ - x: "*[4]"
+ - pause: auto
+ - x: "*[5]"
+ - pause: auto
+ - T: "und so weiter"
+
+- T "dd"
+- include: "SimpleSpeak_Rules.yaml"
diff --git a/Rules/Languages/de/unicode-full.yaml b/Rules/Languages/de/unicode-full.yaml
new file mode 100644
index 00000000..a3a8d6be
--- /dev/null
+++ b/Rules/Languages/de/unicode-full.yaml
@@ -0,0 +1,3623 @@
+---
+
+
+ - "¢": [T: "Cent"] # 0xa2 (en: 'cents')
+ - "£": [T: "Pfund"] # 0xa3 (en: 'pounds')
+ - "¤": [T: "währungszeichen"] # 0xa4 (en: 'currency sign')
+ - "¥": [T: "yen"] # 0xa5
+ - "¦": [T: "gebrochene Linie"] # 0xa6 (en: 'broken bar')
+ - "§": [T: "Abschnitt"] # 0xa7 (en: 'section')
+ - "¨": [T: "diaeresis"] # 0xa8 (en: 'double dot')
+ - "©": [T: "Copyright"] # 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:
+ if: "ancestor::m:modified-variable and preceding-sibling::*[1][self::m:mi]"
+ then: [T: "bar"] # (google translation)
+ 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: "Acuteakzent"] # 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: "modifikator klein h"] # 0x2b0 (en: 'modifier small h', google translation)
+ - "ʱ": [T: "modifikator klein h mit haken"] # 0x2b1 (en: 'modifier small h with hook', google translation)
+ - "ʲ": [T: "modifikator klein j"] # 0x2b2 (en: 'modifier small j', google translation)
+ - "ʳ": [T: "modifikator klein r"] # 0x2b3 (en: 'modifier small r', google translation)
+ - "ʴ": [T: "modifikator gedrehtes kleines r"] # 0x2b4 (en: 'modifier small turned r', google translation)
+ - "ʵ": [T: "modifikator gedrehtes kleines r mit haken"] # 0x2b5 (en: 'modifier small turned r with hook', google translation)
+ - "ʶ": # 0x2b6
+ - T: "modifikator klein invertiert" # (en: 'modifier small inverted', google translation)
+ - spell: "translate('R', 'R', 'R')"
+
+ - "ʷ": [T: "modifikator klein w"] # 0x2b7 (en: 'modifier small w', google translation)
+ - "ʸ": [T: "modifikator klein y"] # 0x2b8 (en: 'modifier small y', google translation)
+ - "ʹ": [T: "Strich"] # 0x2b9 (en: 'modifier prime', google: 'modifikator prime')
+ - "ʺ": [T: "zwei Striche"] # 0x2ba (en: 'modifier double prime', google: 'modifikator double prime')
+ - "ʻ": [T: "modifikator wurde komma"] # 0x2bb (en: 'modifier turned comma', google translation)
+ - "ʼ": [T: "modifikator apostroph"] # 0x2bc (en: 'modifier apostrophe', google translation)
+ - "ʽ": [T: "modifikator umgekehrtes Komma"] # 0x2bd (en: 'modifier reversed comma', google translation)
+ - "ʾ": [T: "modifikator halber ring rechts"] # 0x2be (en: 'modifier right half ring', google: 'modifikator rechts halbe ring')
+ - "ʿ": [T: "modifikator halber ring links"] # 0x2bf (en: 'modifier left half ring', google: 'modifikator verließ den halben ring')
+ - "ˀ": [T: "modifikator glottal stop"] # 0x2c0 (en: 'modifier glottal stop', google translation)
+ - "ˁ": [T: "modifikator umgekehrt glottal stop"] # 0x2c1 (en: 'modifier reversed glottal stop', google translation)
+ - "˂": [T: "modifikator pfeilspitze von links"] # 0x2c2 (en: 'modifier left arrowhead', google translation)
+ - "˃": [T: "modifikator pfeilspitze von rechts"] # 0x2c3 (en: 'modifier right arrowhead', google translation)
+ - "˄": [T: "modifikator pfeil aufwärts"] # 0x2c4 (en: 'modifier up arrowhead', google translation)
+ - "˅": [T: "modifikator pfeil abwärts"] # 0x2c5 (en: 'modifier down arrowhead', google translation)
+ - "ˆ": [T: "modifier letter circumflex accent"] # 0x2c6 (en: 'modifier circumflex accent', google: 'modifikator circumflex akzent')
+ - "ˇ": [T: "caron"] # 0x2c7
+ - "ˈ": [T: "modifikator vertikale linie"] # 0x2c8 (en: 'modifier vertical line', google translation)
+ - "ˉ": [T: "modifikator macron"] # 0x2c9 (en: 'modifier macron', google translation)
+ - "ˊ": [T: "modifikator akuter akzent"] # 0x2ca (en: 'modifier acute accent', google translation)
+ - "ˋ": [T: "modifikator grabakzent"] # 0x2cb (en: 'modifier grave accent', google translation)
+ - "ˌ": [T: "modifikator niedrige vertikale linie"] # 0x2cc (en: 'modifier low vertical line', google translation)
+ - "ˍ": [T: "modifikator low macron"] # 0x2cd (en: 'modifier low macron', google translation)
+ - "ˎ": [T: "modifikator niedriger schwerer akzent"] # 0x2ce (en: 'modifier low grave accent', google translation)
+ - "ˏ": [T: "modifikator niedriger akuter akzent"] # 0x2cf (en: 'modifier low acute accent', google translation)
+ - "ː": [T: "modifikator dreieckiger doppelpunkt"] # 0x2d0 (en: 'modifier triangular colon', google translation)
+ - "ˑ": [T: "modifikator halbdreiecksdoppelpunkt"] # 0x2d1 (en: 'modifier half triangular colon', google translation)
+ - "˒": [T: "modifikator zentrierter halbring von rechts"] # 0x2d2 (en: 'modifier centered right half ring', google translation)
+ - "˓": [T: "modifikator zentrierter halbring von links"] # 0x2d3 (en: 'modifier centered left half ring', google translation)
+ - "˔": [T: "modifikator aufgerichtet"] # 0x2d4 (en: 'modifier up tadck', google translation)
+ - "˕": [T: "modifikator abwärts gerichtet"] # 0x2d5 (en: 'modifier down tack', google translation)
+ - "˖": [T: "modifikator pluszeichen"] # 0x2d6 (en: 'modifier plus sign', google translation)
+ - "˗": [T: "modifikator minuszeichen"] # 0x2d7 (en: 'modifier minus sign', google translation)
+ - "˘": [T: "kurz"] # 0x2d8 (SRE: 'Breve')
+ - "˙": [T: "Punkt oberhalb"] # 0x2d9 (en: 'dot', MathPlayer: 'Punkt darüber', google: 'punkt')
+ - "˚": [T: "Ring oberhalb"] # 0x2da (en: 'ring above', MathPlayer: 'Ring darüber', google: 'oben läuten')
+ - "˛": [T: "ogonek"] # 0x2db (SRE: 'Ogonek')
+ - "˜": [T: "Tilde"] # 0x2dc (en: 'small tilde')
+ - "˝": [T: "Doppleakutakzent"] # 0x2dd (en: 'double acute accent', MathPlayer: 'double acute accent', google: 'doppelter akuter akzent')
+ - "˞": [T: "modifikator rhotischer haken"] # 0x2de (en: 'modifier rhotic hook', google translation)
+ - "˟": [T: "modifikator kreuzakzent"] # 0x2df (en: 'modifier cross accent', google translation)
+ - "ˠ": [T: "modifikator kleines gamma"] # 0x2e0 (en: 'modifier small gamma', google translation)
+ - "ˡ": [T: "modifikator klein l"] # 0x2e1 (en: 'modifier small l', google translation)
+ - "ˢ": [T: "modifikator klein s"] # 0x2e2 (en: 'modifier small s', google translation)
+ - "ˣ": [T: "modifikator klein x"] # 0x2e3 (en: 'modifier small x', google translation)
+ - "ˤ": [T: "modifikator kleiner umgekehrter glottal stopp"] # 0x2e4 (en: 'modifier small reversed glottal stop', google translation)
+ - "˥": [T: "modifikator extra hoher Tonbalken"] # 0x2e5 (en: 'modifier extra-high tone bar', google translation)
+ - "˦": [T: "modifikator hoher Tonbalken"] # 0x2e6 (en: 'modifier high tone bar', google translation)
+ - "˧": [T: "modifikator mittlerer Balken"] # 0x2e7 (en: 'modifier mid tone bar', google translation)
+ - "˨": [T: "modifikator niedrige tonleiste"] # 0x2e8 (en: 'modifier low tone bar', google translation)
+ - "˩": [T: "modifikator extra niedrige tonleiste"] # 0x2e9 (en: 'modifier extra-low tone bar', google translation)
+ - "˪": [T: "modifikator yin abgabetonmarke"] # 0x2ea (en: 'modifier yin departing tone mark', google translation)
+ - "˫": [T: "modifikator yang abgassing tonmarke"] # 0x2eb (en: 'modifier yang departing tone mark', google translation)
+ - "ˬ": [T: "modifikator -stimmen"] # 0x2ec (en: 'modifier voicing', google translation)
+ - "˭": [T: "modifikator ungebildet"] # 0x2ed (en: 'modifier unaspirated', google translation)
+ - "ˮ": [T: "modifikator doppel apostroph"] # 0x2ee (en: 'modifier double apostrophe', google translation)
+ - "˯": [T: "modifikator niedrige pfeilspitze nach unten gerichtet"] # 0x2ef (en: 'modifier low down arrowhead', google translation)
+ - "˰": [T: "modifikator niedrige pfeilspitze aufwärts gerichtet"] # 0x2f0 (en: 'modifier low up arrowhead', google translation)
+ - "˱": [T: "modifikator niedrige pfeilspitze nach links gerichtet"] # 0x2f1 (en: 'modifier low left arrowhead', google translation)
+ - "˲": [T: "modifikator niedrige pfeilspitze nach rechts gerichtet"] # 0x2f2 (en: 'modifier low right arrowhead', google translation)
+ - "˳": [T: "modifikator niedriger ring"] # 0x2f3 (en: 'modifier low ring', google translation)
+ - "˴": [T: "modifikator mittlerer grabakzent"] # 0x2f4 (en: 'modifier middle grave accent', google translation)
+ - "˵": [T: "modifikator mittlerer doppelt grabakzent"] # 0x2f5 (en: 'modifier middle double grave accent', google translation)
+ - "˶": [T: "modifikator mit mittlerem doppelt akutem akzent"] # 0x2f6 (en: 'modifier middle double acute accent', google translation)
+ - "˷": [T: "modifikator niedrige tilde"] # 0x2f7 (en: 'modifier low tilde', google translation)
+ - "˸": [T: "modifikator hoch gestellter Doppelpunkt"] # 0x2f8 (en: 'modifier raised colon', google translation)
+ - "˹": [T: "der modifikator beginnt mit hohem ton"] # 0x2f9 (en: 'modifier begin high tone', google translation)
+ - "˺": [T: "modifikator endet mit hohem ton"] # 0x2fa (en: 'modifier end high tone', google translation)
+ - "˻": [T: "der modifikator beginnt niedrig"] # 0x2fb (en: 'modifier begin low tone', google translation)
+ - "˼": [T: "modifikator ende niedriger ton"] # 0x2fc (en: 'modifier end low tone', google translation)
+ - "˽": [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: "Akzent auf dem Grave"] # 0x300 (en: 'grave accent embellishment', google: 'grabakzentverzierung')
+ - "́": [T: "Akzentverzierung"] # 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: "Macronkombination"] # 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: "combining ring above"] # 0x30a (en: 'ring above embellishment', google: 'ring über verzierung')
+ - "̋": [T: "doppelte akute akzentverzierung"] # 0x30b (en: 'double acute accent embellishment', google translation)
+ - "̌": [T: "combining caron"] # 0x30c (en: 'check', google: 'überprüfen')
+ - "̍": [T: "vertikale linie über verzierung"] # 0x30d (en: 'vertical line above embellishment', google translation)
+ - "̎": [T: "doppelte vertikale linie über verzierung"] # 0x30e (en: 'double vertical line above embellishment', google translation)
+ - "̏": [T: "doppelgrabes akzentverzierung"] # 0x30f (en: 'double grave accent embellishment', google translation)
+ - "̐": [T: "candrabindu -verzierung"] # 0x310 (en: 'candrabindu embellishment', google translation)
+ - "̑": [T: "combining inverted breve"] # 0x311 (en: 'inverted breve embellishment', google: 'umgekehrte breve -verzierung')
+ - "̒": [T: "komma über der verzierung gedreht"] # 0x312 (en: 'turned comma above embellishment', google translation)
+ - "̓": [T: "komma über verzierung"] # 0x313 (en: 'comma above embellishment', google translation)
+ - "̔": [T: "umgekehrter komma über verzierung"] # 0x314 (en: 'reversed comma above embellishment', google translation)
+ - "̕": [T: "komma über der rechten verzierung"] # 0x315 (en: 'comma above right embellishment', google translation)
+ - "̖": [T: "grabakzent unter der verzierung"] # 0x316 (en: 'grave accent below embellishment', google translation)
+ - "̗": [T: "akuter akzent unter der verzierung"] # 0x317 (en: 'acute accent below embellishment', google translation)
+ - "̘": [T: "linke Klammer unter Verzierung"] # 0x318 (en: 'left tack below embellishment', google translation)
+ - "̙": [T: "rechte Klammer unter Verzierung"] # 0x319 (en: 'right tack below embellishment', google translation)
+ - "̚": [T: "linker winkel über verzierung"] # 0x31a (en: 'left angle above embellishment', google translation)
+ - "̛": [T: "hornverzierung"] # 0x31b (en: 'horn embellishment', google translation)
+ - "̜": [T: "halber ring links unter der verzierung"] # 0x31c (en: 'left half ring below embellishment', google translation)
+ - "̝": [T: "aufwärtsklammer unter Verzierung"] # 0x31d (en: 'up tack below embellishment', google translation)
+ - "̞": [T: "abwärtsklammer unter der verzierung"] # 0x31e (en: 'down tack below embellishment', google translation)
+ - "̟": [T: "plus unterschreiben unten verschönern"] # 0x31f (en: 'plus sign below embellishment', google translation)
+ - "̠": [T: "minus zeichen unten verzierung"] # 0x320 (en: 'minus sign below embellishment', google translation)
+ - "̡": [T: "palatalisierter haken unter der verzierung"] # 0x321 (en: 'palatalized hook below embellishment', google translation)
+ - "̢": [T: "retroflex -haken unter der verzierung"] # 0x322 (en: 'retroflex hook below embellishment', google translation)
+ - "̣": [T: "dot below embellishment"] # 0x323 (google: 'punkt unter der verzierung')
+ - "̤": [T: "double dot below embellishment"] # 0x324 (en: 'diaeresis below embellishment', google: 'diaerese unter der verzierung')
+ - "̥": [T: "ring unter der verzierung"] # 0x325 (en: 'ring below embellishment', google translation)
+ - "̦": [T: "komma unter der verzierung"] # 0x326 (en: 'comma below embellishment', google translation)
+ - "̧": [T: "cedilla embellishment"] # 0x327 (google: 'cedilla -verzierung')
+ - "̨": [T: "ogonek -verzierung"] # 0x328 (en: 'ogonek embellishment', google translation)
+ - "̩": [T: "vertikale linie unter der verzierung"] # 0x329 (en: 'vertical line below embellishment', google translation)
+ - "̪": [T: "brücke unterhalb der verzierung"] # 0x32a (en: 'bridge below embellishment', google translation)
+ - "̫": [T: "umgekehrter doppelbogen unter der verzierung"] # 0x32b (en: 'inverted double arch below embellishment', google translation)
+ - "̬": [T: "caron unter der verzierung"] # 0x32c (en: 'caron below embellishment', google translation)
+ - "̭": [T: "circumflex -akzent unter der verzierung"] # 0x32d (en: 'circumflex accent below embellishment', google translation)
+ - "̮": [T: "combining breve below"] # 0x32e (en: 'breve below embellishment', google: 'breve unter der verzierung')
+ - "̯": [T: "umgekehrte breve unterhalb der verzierung"] # 0x32f (en: 'inverted breve below embellishment', google translation)
+ - "̰": [T: "tilde below embellishment"] # 0x330 (google: 'tilde unter der verzierung')
+ - "̱": [T: "macron below embellishment"] # 0x331 (google: 'macron unter der verzierung')
+ - "̲": [T: "combining low line"] # 0x332 (en: 'low line embellishment', google: 'niedriglinienverzerrung')
+ - "̳": [T: "doppelte leitung verschönern"] # 0x333 (en: 'double low line embellishment', google translation)
+ - "̴": [T: "tilde overlay -verzierung"] # 0x334 (en: 'tilde overlay embellishment', google translation)
+ - "̵": [T: "kurzhub -overlay -verzierung"] # 0x335 (en: 'short stroke overlay embellishment', google translation)
+ - "̶": [T: "langstreicher -overlay -verzierung"] # 0x336 (en: 'long stroke overlay embellishment', google translation)
+ - "̷": [T: "kurze solidus -overlay -verzierung"] # 0x337 (en: 'short solidus overlay embellishment', google translation)
+ - "̸": [T: "forward slash embellishment"] # 0x338 (en: 'long solidus overlay embellishment', google: 'long solidus overlay -verzierung')
+ - "̹": [T: "halber ring rechts unter der verzierung"] # 0x339 (en: 'right half ring below embellishment', google translation)
+ - "̺": [T: "umgekehrte brücke unter der verzierung"] # 0x33a (en: 'inverted bridge below embellishment', google translation)
+ - "̻": [T: "quadrat unterhalb der verzierung"] # 0x33b (en: 'square below embellishment', google translation)
+ - "̼": [T: "möwen unter der verzierung"] # 0x33c (en: 'seagull below embellishment', google translation)
+ - "̽": [T: "x über verzierung"] # 0x33d (en: 'x above embellishment', google translation)
+ - "̾": [T: "vertikale tilde verzierung"] # 0x33e (en: 'vertical tilde embellishment', google translation)
+ - "̿": [T: "doppelte überlaufverzerrung"] # 0x33f (en: 'double overline embellishment', google translation)
+ - "̀": [T: "grabtonmarke verzierung"] # 0x340 (en: 'grave tone mark embellishment', google translation)
+ - "́": [T: "akute tonmarkierungsverzerrung"] # 0x341 (en: 'acute tone mark embellishment', google translation)
+
+ - "ΪΫϏ": # 0x3aa, 0x3ab, 0x3cf
+ - test:
+ if: "$CapitalLetters_Beep"
+ then:
+ - audio:
+ value: "beep.mp4"
+ replace: []
+ - test:
+ if: "$CapitalLetters_UseWord"
+ then_test:
+ if: "$SpeechOverrides_CapitalLetters = ''"
+ then_test:
+ if: "$Impairment = 'Blindness'"
+ then: [T: "großbuchstaben"] # (en: 'cap', google translation)
+ else: [x: "$SpeechOverrides_CapitalLetters"]
+ - pitch:
+ value: "$CapitalLetters_Pitch"
+ replace: [spell: "translate('.', 'ΪΫϏ', 'ιυϗ')"]
+ - T: "mit dialytika" # (en: 'with dialytika', google translation)
+ - "ϊ": [T: "iota mit dialytika"] # 0x3ca (en: 'iota with dialytika', google translation)
+ - "ϋ": [T: "upsilon mit dialytika"] # 0x3cb (en: 'upsilon with dialytika', google translation)
+ - "ό": [T: "omicron mit tonos"] # 0x3cc (en: 'omicron with tonos', google translation)
+ - "ύ": [T: "upsilon mit tonos"] # 0x3cd (en: 'upsilon with tonos', google translation)
+ - "ώ": [T: "omega mit tonos"] # 0x3ce (en: 'omega with tonos', google translation)
+ - "ϐ": [T: "beta"] # 0x3d0 (MathPlayer: 'greek beta')
+ - "ϑ": [T: "variant theta"] # 0x3d1 (en: 'theta', google: 'theta')
+ - "ϒ": [T: "variant upsilon with hook"] # 0x3d2 (en: 'upsilon with hook', google: 'upsilon mit haken')
+ - "ϓ": [T: "upsilon mit akuter und haken"] # 0x3d3 (en: 'upsilon with acute and hook', google translation)
+ - "ϔ": [T: "upsilon mit diaerse und haken"] # 0x3d4 (en: 'upsilon with diaeresis and hook', google translation)
+ - "ϕ": [T: "straight phi"] # 0x3d5 (en: 'phi', google: 'phi')
+ - "ϖ": [T: "variant pi"] # 0x3d6 (en: 'pi', google: 'pi')
+ - "ϗ": [T: "kai"] # 0x3d7 (MathPlayer: 'variant kai')
+ - "ϵ": [T: "epsilon"] # 0x3f5
+ - "϶": [T: "umgekehrtes epsilon"] # 0x3f6 (en: 'reversed epsilon', MathPlayer: 'reversed epsilon', google: 'umgekehrter epsilon')
+ - "А-Я": # 0x410 - 0x42f
+ - test:
+ if: "$CapitalLetters_Beep"
+ then:
+ - audio:
+ value: "beep.mp4"
+ replace: []
+ - test:
+ if: "$CapitalLetters_UseWord"
+ then_test:
+ if: "$SpeechOverrides_CapitalLetters = ''"
+ then_test:
+ if: "$Impairment = 'Blindness'"
+ then: [T: "großbuchstaben"] # (en: 'cap', google translation)
+ else: [x: "$SpeechOverrides_CapitalLetters"]
+ - pitch:
+ value: "$CapitalLetters_Pitch"
+ replace: [spell: "translate('.', 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ', 'абвгдежзийклмнопрстуфхцчшщъыьэюя')"]
+ - "а": [T: "a"] # 0x430 (google: 'а')
+ - "б": [T: "be"] # 0x431 (google: 'sei')
+ - "в": [T: "ve"] # 0x432
+ - "г": [T: "ghe"] # 0x433
+ - "д": [T: "de"] # 0x434
+ - "е": [T: "ie"] # 0x435 (google: 'dh')
+ - "ж": [T: "zhe"] # 0x436
+ - "з": [T: "ze"] # 0x437
+ - "и": [T: "i"] # 0x438 (google: 'и')
+ - "й": [T: "short i"] # 0x439 (google: 'kurz ich')
+ - "к": [T: "ka"] # 0x43a
+ - "л": [T: "el"] # 0x43b
+ - "м": [T: "em"] # 0x43c
+ - "н": [T: "en"] # 0x43d
+ - "о": [T: "o"] # 0x43e (google: 'о')
+ - "п": [T: "pe"] # 0x43f (google: 'sport')
+ - "р": [T: "er"] # 0x440 (google: 'ähm')
+ - "с": [T: "es"] # 0x441
+ - "т": [T: "te"] # 0x442
+ - "у": [T: "u"] # 0x443 (google: 'у')
+ - "ф": [T: "ef"] # 0x444
+ - "х": [T: "ha"] # 0x445
+ - "ц": [T: "tse"] # 0x446
+ - "ч": [T: "che"] # 0x447
+ - "ш": [T: "sha"] # 0x448
+ - "щ": [T: "shcha"] # 0x449
+ - "ъ": [T: "hard sign"] # 0x44a (google: 'hartes zeichen')
+ - "ы": [T: "yeru"] # 0x44b
+ - "ь": [T: "soft sign"] # 0x44c (google: 'weiches zeichen')
+ - "э": [T: "e"] # 0x44d (google: 'э')
+ - "ю": [T: "yu"] # 0x44e
+ - "я": [T: "ya"] # 0x44f
+ - "‐": [T: "Bindestrich"] # 0x2010 (en: 'hyphen', MathPlayer: 'minus', google: 'bindestrich')
+ - "‑": [T: "Nicht brechender Bindestrich"] # 0x2011 (en: 'hyphen', google: 'bindestrich')
+ - "‒": [T: "Abbildung Bindestrich"] # 0x2012 (en: 'figure dash', google: 'figur dash')
+ - "–": [T: "en dash"] # 0x2013 (SRE: 'En Dash')
+ - "—": [T: "em dash"] # 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')
+
+ - "•": # 0x2022
+ - test:
+ if: "@data-chem-formula-op"
+ 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: "strich invertiert"] # 0x2035 (en: 'reversed prime', MathPlayer: 'reversed prime', google: 'umgekehrt prime')
+ - "‶": [T: "zwei Striche invertiert"] # 0x2036 (en: 'reversed double prime', MathPlayer: 'reversed double prime', google: 'umgekehrt doppelte prime')
+ - "‷": [T: "drei Striche invertiert"] # 0x2037 (en: 'reversed triple prime', google: 'triple prime umgekehrt')
+ - "‸": [T: "Caret"] # 0x2038 (en: 'to the', google: 'zum')
+ - "‹": [T: "einfaches linkes Anführungszeichen"] # 0x2039 (en: 'single left pointing angle quote mark', MathPlayer: 'single left pointing angle quote mark', google: 'single linke zitat angle -zitat marke')
+ - "›": [T: "einfaches rechtes Anführungszeichen"] # 0x203a (en: 'single right pointing angle quote mark', MathPlayer: 'single right pointing angle quote mark', google: 'single rechts zeigewinkel zitatmarke')
+ - "‼": [T: "Doppelausrufezeichen"] # 0x203c (en: 'double factorial', google: 'doppelfaktor')
+ - "⁄": [T: "Schrägstrich"] # 0x2044 (en: 'divided by', MathPlayer: 'slash', google: 'geteilt durch')
+ - "⁅": [T: "Linke eckige Klammer mit Feder"] # 0x2045 (en: 'left square bracket with quill', google: 'linksquadratische klammer mit feder')
+ - "⁆": [T: "Rechte eckige Klammer mit Feder"] # 0x2046 (en: 'right square bracket with quill', google: 'rechte quadratische halterung mit feder')
+ - "⁗": [T: "vier Striche"] # 0x2057 (en: 'quadruple prime', MathPlayer: 'quadruple prime', google: 'vierfache prime')
+ - "": [T: ""] # 0x2060
+ - "‵": [T: "strich invertiert"] # 0x2035 (en: 'reversed prime', MathPlayer: 'reversed prime', google: 'umgekehrt prime')
+ - "‶": [T: "zwei Striche invertiert"] # 0x2036 (en: 'reversed double prime', MathPlayer: 'reversed double prime', google: 'umgekehrt doppelte prime')
+ - "‷": [T: "drei Striche invertiert"] # 0x2037 (en: 'reversed triple prime', google: 'triple prime umgekehrt')
+ - "⁰": [T: "zur nullten Potenz"] # 0x2070 (en: 'to the zeroth power', google translation)
+ - "ⁱ": [T: "zur i-ten Potenz"] # 0x2071 (en: 'to the ith power', google: 'zur eihth -macht')
+ - "⁴": [T: "zur vierten Potenz"] # 0x2074 (en: 'to the fourth power', google translation)
+ - "⁵": [T: "zur fünften Potenz"] # 0x2075 (en: 'to the fifth power', google translation)
+ - "⁶": [T: "zur sechsten Potenz"] # 0x2076 (en: 'to the sixth power', google translation)
+ - "⁷": [T: "zur siebten Potenz"] # 0x2077 (en: 'to the seventh power', google translation)
+ - "⁸": [T: "zur achten Potenz"] # 0x2078 (en: 'to the eighth power', google translation)
+ - "⁹": [T: "zur neunten Potenz"] # 0x2079 (en: 'to the ninth power', google translation)
+ - "⁺": [T: "Hochgestelltes Pluszeichen"] # 0x207a (en: 'superscript plus sign', google: 'superscript plus zeichen')
+ - "⁻": [T: "Hochgestelltes Minus"] # 0x207b (en: 'superscript minus', google: 'superscript minus')
+ - "⁼": [T: "Hochgestelltes Gleichheitszeichen"] # 0x207c (en: 'superscript equals sign', google: 'superscript ist gleichzeichen')
+ - "⁽": [T: "Hochgestellte linke Klammer"] # 0x207d (en: 'superscript left parenthesis', google: 'superscript links klammern')
+ - "⁾": [T: "Hochgestellte rechte Klammer"] # 0x207e (en: 'superscript right parenthesis', google: 'superscript right parenthesisthese')
+ - "ⁿ": [T: "hochgestelltes n"] # 0x207f (en: 'to the ennth power', google: 'zur ahnten kraft')
+ - "₀": [T: "unter null"] # 0x2080 (en: 'sub zero', google translation)
+ - "₁": [T: "sub eins"] # 0x2081 (en: 'sub one', google translation)
+ - "₂": [T: "sub zwei"] # 0x2082 (en: 'sub two', google translation)
+ - "₃": [T: "unter drei"] # 0x2083 (en: 'sub three', google translation)
+ - "₄": [T: "unter vier"] # 0x2084 (en: 'sub four', google translation)
+ - "₅": [T: "sub fünf"] # 0x2085 (en: 'sub five', google translation)
+ - "₆": [T: "sub sechs"] # 0x2086 (en: 'sub six', google translation)
+ - "₇": [T: "sub sieben"] # 0x2087 (en: 'sub seven', google translation)
+ - "₈": [T: "sub acht"] # 0x2088 (en: 'sub eight', google translation)
+ - "₉": [T: "sub neun"] # 0x2089 (google translation)
+ - "₊": [T: "Index Pluszeichen"] # 0x208a (en: 'subscript plus sign', google: 'index plus -zeichen')
+ - "₋": [T: "Tiefgestelltes Minuszeichen"] # 0x208b (en: 'subscript minus sign', google: 'index minuszeichen')
+ - "₌": [T: "Tiefgestelltes Gleichheitszeichen"] # 0x208c (en: 'subscript equals sign', google: 'index gleicher bestandteil des zeichens')
+ - "₍": [T: "Tiefgestellte linke Klammer"] # 0x208d (en: 'subscript left parenthesis', google: 'untergangsklammern von klammern')
+ - "₎": [T: "Tiefgestellte rechte Klammer"] # 0x208e (en: 'subscript right parenthesis', google: 'index right parenthesisthese')
+ - "ₐ": [T: "tiefgestelltes a"] # 0x2090 (en: 'sub A', google: 'sub a')
+ - "ₑ": [T: "tiefgestelltes e"] # 0x2091 (en: 'sub E', google: 'sub e')
+ - "ₒ": [T: "tiefgestelltes o"] # 0x2092 (en: 'sub O', google: 'sub o')
+ - "ₓ": [T: "tiefgestelltes x"] # 0x2093 (en: 'sub X', google: 'sub x')
+ - "ₕ": [T: "tiefgestelltes h"] # 0x2095 (en: 'sub H', google: 'sub h')
+ - "ₖ": [T: "tiefgestelltes k"] # 0x2096 (en: 'sub K', google: 'subk')
+ - "ₗ": [T: "tiefgestelltes l"] # 0x2097 (en: 'sub L', google: 'sub l')
+ - "ₘ": [T: "tiefgestelltes m"] # 0x2098 (en: 'sub M', google: 'sub m')
+ - "ₙ": [T: "tiefgestelltes n"] # 0x2099 (en: 'sub N', google: 'sub n')
+ - "ₚ": [T: "tiefgestelltes p"] # 0x209a (en: 'sub P', google: 'sub p')
+ - "ₛ": [T: "tiefgestelltes s"] # 0x209b (en: 'sub S', google: 'sub s')
+ - "ₜ": [T: "tiefgestelltes t"] # 0x209c (en: 'sub T', google: 'sub t')
+ - "₠": [T: "europäische Währungseinheiten"] # 0x20a0 (en: 'european currenty units', google translation)
+ - "₡": [T: "colons"] # 0x20a1 (google: 'kolons')
+ - "₢": [T: "cruzeiro"] # 0x20a2
+ - "₣": [T: "franc"] # 0x20a3
+ - "₤": [T: "lira"] # 0x20a4
+ - "₥": [T: "mills"] # 0x20a5 (google: 'mühlen')
+ - "₦": [T: "naira"] # 0x20a6
+ - "₧": [T: "peseta"] # 0x20a7
+ - "₨": [T: "rupees"] # 0x20a8 (google: 'rupien')
+ - "₩": [T: "won"] # 0x20a9 (google: 'gewonnen')
+ - "₪": [T: "new sheqels"] # 0x20aa (google: 'neue sheqels')
+ - "₫": [T: "dong"] # 0x20ab
+ - "€": [T: "euros"] # 0x20ac (google: 'euro')
+ - "₭": [T: "kip"] # 0x20ad (google: 'pennen')
+ - "₮": [T: "tugrik"] # 0x20ae
+ - "₯": [T: "drachma"] # 0x20af (google: 'drachme')
+ - "₰": [T: "german pennies"] # 0x20b0 (google: 'deutsche pennys')
+ - "₱": [T: "pesos"] # 0x20b1
+ - "₲": [T: "guaranis"] # 0x20b2
+ - "₳": [T: "australs"] # 0x20b3 (google: 'österrale')
+ - "₴": [T: "hryvnias"] # 0x20b4
+ - "₵": [T: "cedis"] # 0x20b5
+ - "₶": [T: "livre tournois"] # 0x20b6 (google translation)
+ - "₷": [T: "spesmilos"] # 0x20b7 (google translation)
+ - "₸": [T: "tenges"] # 0x20b8 (google translation)
+ - "₹": [T: "indische rupien"] # 0x20b9 (en: 'indian rupees', google translation)
+ - "₺": [T: "türkische liras"] # 0x20ba (en: 'turkish liras', google translation)
+ - "⃐": [T: "linke Harpune über Verzierung"] # 0x20d0 (en: 'left harpoon above embellishment', google: 'links harpoon über verzierung')
+ - "⃑": [T: 'rechte Harpune über Verzierung"] # 0x20d1 (en: 'right harpoon above embellishment', google: 'rechte harpoon über verzierung')
+ - "⃒": [T: "Verzierung mit langer vertikaler Linie] # 0x20d2 (en: 'long vertical line overlay embellishment', google translation)
+ - "⃓": [T: "Verzierung mit kurzer vertikaler Linie"] # 0x20d3 (en: 'short vertical line overlay embellishment', google translation)
+ - "⃔": [T: "Pfeil gegen den Uhrzeigersinn über Verzierung"] # 0x20d4 (en: 'anticlockwise arrow above embellishment', google translation)
+ - "⃕": [T: "Pfeil im Uhrzeigersinn über Verzierung"] # 0x20d5 (en: 'clockwise arrow above embellishment', google translation)
+ - "⃖": [T: "Pfeil nach links über Verzierung"] # 0x20d6 (en: 'left arrow above embellishment', google: 'links pfeil über die verzierung')
+ - "⃗": [T: "Pfeil nach rechts über Verzierung"] # 0x20d7 (en: 'right arrow above embellishment', google: 'richtiger pfeil über die verzierung')
+ - "⃘": [T: "Ringüberlagerung als Verzierung"] # 0x20d8 (en: 'ring overlay embellishment', google translation)
+ - "⃙": [T: "ringüberlagerung im uhrzeigersinn"] # 0x20d9 (en: 'clockwise ring overlay embellishment', google translation)
+ - "⃚": [T: "ringüberlagerung gegen den uhrzeigersinn"] # 0x20da (en: 'anticlockwise ring overlay embellishment', google translation)
+ - "⃛": [T: "dreifacher punkt"] # 0x20db (en: 'triple dot', google: 'dreifacher punkt')
+ - "⃜": [T: "vierfacher punkt"] # 0x20dc (en: 'quadruple dot', google: 'vierfachpunkt punkt')
+ - "⃝": [T: "umschließender Kreis als Verzierung"] # 0x20dd (en: 'enclosing circle embellishment', google translation)
+ - "⃞": [T: "umschließendes Quadrat als Verzierung"] # 0x20de (en: 'enclosing square embellishment', google translation)
+ - "⃟": [T: "umschließender Diamant als Verzierung"] # 0x20df (en: 'enclosing diamond embellishment', google translation)
+ - "⃠": [T: "schließen sie den kreis -rückstand verschönern"] # 0x20e0 (en: 'enclosing circle backslash embellishment', google translation)
+ - "⃡": [T: "left right arrow embellishment"] # 0x20e1 (en: 'left right arrow above embellishment', google: 'links rechts pfeil über verzierung')
+ - "⃢": [T: "einschließende bildschirmverzierung"] # 0x20e2 (en: 'enclosing screen embellishment', google translation)
+ - "⃣": [T: "Umschließende Tastenkappenverzierung"] # 0x20e3 (en: 'enclosing keycap embellishment', google translation)
+ - "⃤": [T: "umschließende, nach oben zeigende Dreiecksverzierung"] # 0x20e4 (en: 'enclosing upward pointing triangle embellishment', google translation)
+ - "⃥": [T: "Umgekehrte Solidus-Überlagerung als Verzierung"] # 0x20e5 (en: 'reverse solidus overlay embellishment', google translation)
+ - "⃦": [T: "Doppelte vertikale Strichverzierung"] # 0x20e6 (en: 'double verticle stroke embellishment', google translation)
+ - "⃧": [T: "rentensymbol verzierung"] # 0x20e7 (en: 'Verzierung mit Annuitätensymbol', google translation)
+ - "⃨": [T: "Dreifach-Unterpunkt"] # 0x20e8 (en: 'triple underdot', google translation)
+ - "⃩": [T: "breite brücke über verzierung"] # 0x20e9 (en: 'wide bridge above embellishment', google translation)
+ - "⃪": [T: "Verzierung mit nach links zeigendem Pfeil"] # 0x20ea (en: 'leftwards arrow overlay embellishment', google translation)
+ - "⃫": [T: "Verzierung mit langem, doppeltem Strichüberzug"] # 0x20eb (en: 'long double solidus overlay embellishment', google translation)
+ - "⃬": [T: "Rechtshaken mit Widerhaken nach unten verziert"] # 0x20ec (en: 'rightwards harpoon with barb downwards embellishment', google translation)
+ - "⃭": [T: "Linkshaken mit Widerhaken nach unten verziert"] # 0x20ed (en: 'leftwards harpoon with barb downwards embellishment', google translation)
+ - "⃮": [T: "Pfeil nach links unter Verzierung"] # 0x20ee (en: 'left arrow below embellishment', google translation)
+ - "⃯": [T: "Pfeil nach rechts unter Verzierung"] # 0x20ef (en: 'right arrow below embellishment', google translation)
+ - "⃰": [T: "sternchen über verzierung"] # 0x20f0 (en: 'asterisk above embellishment', google translation)
+ - "℄": [T: "mittelliniensymbol"] # 0x2104 (en: 'center line symbol', google translation)
+ - "℅": [T: "im Auftrag von"] # 0x2105 (google: 'pflege von')
+ - "℆": [T: "cada una"] # 0x2106 (google translation)
+ - "ℇ": [T: "euler constant"] # 0x2107 (en: 'euler's constant', google: 'eulers konstante')
+ - "℈": [T: "skrupel"] # 0x2108 (en: 'scruples', google translation)
+ - "℉": [T: "degrees fahrenheit"] # 0x2109 (google: 'grad fahrenheit')
+ - "ℊ": [T: "script g"] # 0x210a (google: 'skript g')
+ - "ℌℑℨℭ": # 0x210c, 0x2111, 0x2128, 0x212d
+ - T: "script g" # (en: 'fraktur', google: 'fraktur')
+ - spell: "translate('.', 'ℌℑℨℭ', 'HIZC')"
+
+ - "ℍℙℾℿ": # 0x210d, 0x2119, 0x213e, 0x213f
+ - test:
+ if: "$Verbosity!='Terse'"
+ 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')"
+ then: [T: "h bar"] # (google translation)
+ else: [T: "Planck-Konstante über zwei Pi"] # (en: 'reduced planck constant', MathPlayer: 'h bar', google: 'reduzierte planckkonstante')
+
+ - "ℐℒ℘ℬℰℱℳ": # 0x2110, 0x2112, 0x2118, 0x2130, 0x2131, 0x2133
+ - T: "Planck-Konstante über zwei Pi" # (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: "turned 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: "script e"] # 0x212f (google: 'skript e')
+
+ # coalesced some chars that use cap letters
+ - "Ⅎ℺⅁⅂⅃⅄": # 0x2132, 0x213a, 0x2141, 0x2142, 0x2143, 0x2144
+ - test:
+ - if: "'.' = '℺'"
+ then: [T: "gedreht"] # (en: 'rotated', google translation)
+ - else_if: "'.' = 'Ⅎ'"
+ then: [T: "gedreht"] # (en: 'turned', google translation)
+ - else_if: "'.' = '⅃'"
+ then: [T: "umgekehrt ohne serif"] # (en: 'reversed sans-serif', google translation)
+ else: [T: "script e"] # (en: 'turned sans-serif', google: 'drehte ohne serif')
+ - spell: "translate('.', 'Ⅎ℺⅁⅂⅃⅄', 'FQGLLY')"
+
+ - "ℴ": [T: "script o"] # 0x2134 (google: 'skript o')
+ - "ℵ": [T: "Alef-Symbol"] # 0x2135 (en: 'first transfinite cardinal', MathPlayer: 'alef', google: 'erster transfinite kardinal')
+ - "ℶ": [T: "Bet-Symbol"] # 0x2136 (en: 'second transfinite cardinal', MathPlayer: 'bet', google: 'zweiter transfinite kardinal')
+ - "ℷ": [T: "Gimel-Symbol"] # 0x2137 (en: 'third transfinite cardinal', MathPlayer: 'gimel', google: 'dritter transfinite kardinal')
+ - "ℸ": [T: "Dalet-Symbol"] # 0x2138 (en: 'fourth transfinite cardinal', MathPlayer: 'dalet', google: 'viertes transfinite kardinal')
+ - "ℼ": [T: "pi mit Doppelstrich"] # 0x213c (en: 'double struck pi', google: 'doppelt geschlagen pi')
+ - "ℽ": [T: "gamma mit Doppelstrich"] # 0x213d (en: 'double struck gamma', google: 'doppelt geschlagen gamma')
+ - "⅀": [T: "Summenzeichen mit Doppelstrich"] # 0x2140 (en: 'double struck n-ary summation', google: 'doppelte n-ary-summierung')
+ - "⅋": [T: "Ampersand gedreht"] # 0x214b (en: 'turned ampersand', google: 'ampers umgedreht')
+ - "⅌": [T: "Pro Zeichen"] # 0x214c (en: 'per', google: 'pro')
+ - "ⅎ": [T: "Gedreht klein F"] # 0x214e (en: 'turned F', google: 'drehte f')
+ - "⅐": [T: "ein siebtel"] # 0x2150 (en: 'one seventh')
+ - "⅑": [T: "ein neuntel"] # 0x2151 (en: 'one ninth', google: 'ein neunter')
+ - "⅒": [T: "ein zehntel"] # 0x2152 (en: 'one tenth')
+ - "⅓": [T: "ein drittel"] # 0x2153 (en: 'one third', MathPlayer: 'vulgar fraction one third')
+ - "⅔": [T: "zwei drittel"] # 0x2154 (en: 'two thirds', MathPlayer: 'vulgar fraction two thirds')
+ - "⅕": [T: "ein fünftel"] # 0x2155 (en: 'one fifth', MathPlayer: 'vulgar fraction one fifth')
+ - "⅖": [T: "zwei fünftel"] # 0x2156 (en: 'two fifths', MathPlayer: 'vulgar fraction two fifths')
+ - "⅗": [T: "drei fünftel"] # 0x2157 (en: 'three fifths', MathPlayer: 'vulgar fraction three fifths')
+ - "⅘": [T: "vier fünftel"] # 0x2158 (en: 'four fifths', MathPlayer: 'vulgar fraction four fifths')
+ - "⅙": [T: "ein sechstel"] # 0x2159 (en: 'one sixth', MathPlayer: 'vulgar fraction one sixth')
+ - "⅚": [T: "fünf sechstel"] # 0x215a (en: 'five sixths', MathPlayer: 'vulgar fraction five sixths')
+ - "⅛": [T: "ein achtel"] # 0x215b (en: 'one eighth', MathPlayer: 'vulgar fraction one eighth', google: 'ein ath')
+ - "⅜": [T: "drei achtel"] # 0x215c (en: 'three eighths', MathPlayer: 'vulgar fraction three eighths', google: 'drei aths')
+ - "⅝": [T: "fünf achtel"] # 0x215d (en: 'five eighths', MathPlayer: 'vulgar fraction five eighths', google: 'fünf aths')
+ - "⅞": [T: "sieben achtel"] # 0x215e (en: 'seven eighths', MathPlayer: 'vulgar fraction seven eighths', google: 'sieben aths')
+ - "⅟": [T: "Bruchzähler eins"] # 0x215f (en: 'one over', google: 'eins vorbei')
+ - "Ⅰ": [T: "Ⅰ"] # 0x2160 (en: 'I', google translation)
+ - "Ⅱ": [T: "i i"] # 0x2161 (en: 'I I', google translation)
+ - "Ⅲ": [T: "i i i"] # 0x2162 (en: 'I I I', google translation)
+ - "Ⅳ": [T: "i v"] # 0x2163 (en: 'I V', google translation)
+ - "Ⅴ": [T: "Ⅴ"] # 0x2164 (en: 'V', google translation)
+ - "Ⅵ": [T: "v i"] # 0x2165 (en: 'V I', google translation)
+ - "Ⅶ": [T: "v i i"] # 0x2166 (en: 'V I I', google translation)
+ - "Ⅷ": [T: "v i i i"] # 0x2167 (en: 'V I I I', google translation)
+ - "Ⅸ": [T: "i x"] # 0x2168 (en: 'I X', google translation)
+ - "Ⅹ": [T: "Ⅹ"] # 0x2169 (en: 'X', google translation)
+ - "Ⅺ": [T: "x i"] # 0x216a (en: 'X I', google translation)
+ - "Ⅻ": [T: "x i i"] # 0x216b (en: 'X I I', google translation)
+ - "Ⅼ": [T: "Ⅼ"] # 0x216c (en: 'L', google translation)
+ - "Ⅽ": [T: "Ⅽ"] # 0x216d (en: 'C', google translation)
+ - "Ⅾ": [T: "Ⅾ"] # 0x216e (en: 'D', google translation)
+ - "Ⅿ": [T: "Ⅿ"] # 0x216f (en: 'M', google translation)
+ - "ⅰ": [T: "ⅰ"] # 0x2170 (en: 'I', google translation)
+ - "ⅱ": [T: "i i"] # 0x2171 (en: 'I I', google translation)
+ - "ⅲ": [T: "i i i"] # 0x2172 (en: 'I I I', google translation)
+ - "ⅳ": [T: "i v"] # 0x2173 (en: 'I V', google translation)
+ - "ⅴ": [T: "ⅴ"] # 0x2174 (en: 'V', google translation)
+ - "ⅵ": [T: "v i"] # 0x2175 (en: 'V I', google translation)
+ - "ⅶ": [T: "v i i"] # 0x2176 (en: 'V I I', google translation)
+ - "ⅷ": [T: "v i i i"] # 0x2177 (en: 'V I I I', google translation)
+ - "ⅸ": [T: "i x"] # 0x2178 (en: 'I X', google translation)
+ - "ⅹ": [T: "ⅹ"] # 0x2179 (en: 'X', google translation)
+ - "ⅺ": [T: "x i"] # 0x217a (en: 'X I', google translation)
+ - "ⅻ": [T: "x i i"] # 0x217b (en: 'X I I', google translation)
+ - "ⅼ": [T: "ⅼ"] # 0x217c (en: 'L', google translation)
+ - "ⅽ": [T: "ⅽ"] # 0x217d (en: 'C', google translation)
+ - "ⅾ": [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: "Linker rechter Pfeil"] # 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')
+ - "↗": # 0x2197
+ - test:
+ if: "ancestor::*[2][self::m:limit]"
+ then: [T: "annähernd von unten"] # (en: 'approaches from below', google translation)
+ else: [T: "Nordostpfeil"] # (en: 'north east arrow', MathPlayer: 'north east arrow', google: 'nordostpfeil')
+
+ - "↘": # 0x2198
+ - test:
+ if: "ancestor::*[2][self::m:limit]"
+ then: [T: "nähert sich von oben"] # (en: 'approaches from above', google translation)
+ else: [T: "Südostpfeil"] # (en: 'south east arrow', MathPlayer: 'south east arrow', google: 'south east pfeil')
+
+ - "↙": [T: "Südwestpfeil"] # 0x2199 (en: 'south west arrow', MathPlayer: 'south west arrow', google: 'südwestpfeil')
+ - "↚": [T: "Pfeil nach links mit Strich"] # 0x219a (en: 'leftwards arrow with stroke', MathPlayer: 'leftwards arrow with stroke', google: 'links pfeil mit schlaganfall')
+ - "↛": [T: "Pfeil nach rechts mit Strich"] # 0x219b (en: 'rightwards arrow with stroke', MathPlayer: 'rightwards arrow with stroke', google: 'richtiger pfeil mit schlaganfall')
+ - "↜": [T: "Wellenpfeil nach links"] # 0x219c (en: 'leftwards wave arrow', MathPlayer: 'leftwards wave arrow', google: 'linkswellenpfeil')
+ - "↝": [T: "Wellenpfeil nach rechts"] # 0x219d (en: 'rightwards wave arrow', MathPlayer: 'rightwards wave arrow', google: 'rightwards wave pfeil')
+ - "↞": [T: "Pfeil mit zwei Spitzen nach links "] # 0x219e (en: 'leftwards two headed arrow', MathPlayer: 'leftwards two headed arrow', google: 'links zwei köpfe pfeil')
+ - "↟": [T: "Aufwärts gerichteter Doppelpfeil"] # 0x219f (en: 'upwards two headed arrow', MathPlayer: 'upwards two headed arrow', google: 'auf zwei köpfe pfeil')
+ - "↠": [T: "Pfeil mit zwei Spitzen nach rechts"] # 0x21a0 (en: 'rightwards two headed arrow', MathPlayer: 'rightwards two headed arrow', google: 'richtig zwei köpfe pfeil')
+ - "↡": [T: "Abwärts gerichteter Doppelpfeil"] # 0x21a1 (en: 'downwards two headed arrow', MathPlayer: 'downwards two headed arrow', google: 'nach unten zwei köpfe pfeil')
+ - "↢": [T: "Pfeil nach links mit Schwanz"] # 0x21a2 (en: 'leftwards arrow with tail', MathPlayer: 'leftwards arrow with tail', google: 'linkspfeil mit schwanz')
+ - "↣": [T: "Pfeil nach rechts mit Schwanz"] # 0x21a3 (en: 'rightwards arrow with tail', MathPlayer: 'rightwards arrow with tail', google: 'richtiger pfeil mit schwanz')
+ - "↤": [T: "Pfeil nach links von der Leiste"] # 0x21a4 (en: 'leftwards arrow from bar', MathPlayer: 'leftwards arrow from bar', google: 'links pfeil aus der bar')
+ - "↥": [T: "Aufwärtspfeil von der Leiste"] # 0x21a5 (en: 'upwards arrow from bar', MathPlayer: 'upwards arrow from bar', google: 'aufwärter pfeil aus der bar')
+ - "↦": [T: "Pfeil nach rechts von der Leiste"] # 0x21a6 (en: 'rightwards arrow from bar', MathPlayer: 'rightwards arrow from bar', google: 'richtiger pfeil aus der bar')
+ - "↧": [T: "Abwärtspfeil von der Leiste"] # 0x21a7 (en: 'downwards arrow from bar', MathPlayer: 'downwards arrow from bar', google: 'nach unten pfeil aus der bar')
+ - "↨": [T: "Aufwärts-/Abwärtspfeil mit Sockel"] # 0x21a8 (en: 'up down arrow with base', MathPlayer: 'up down arrow with base', google: 'mit der basis auf pfeil runter')
+ - "↩": [T: "Pfeil nach links mit Haken"] # 0x21a9 (en: 'leftwards arrow with hook', MathPlayer: 'leftwards arrow with hook', google: 'links pfeil mit haken')
+ - "↪": [T: "Pfeil nach rechts mit Haken"] # 0x21aa (en: 'rightwards arrow with hook', MathPlayer: 'rightwards arrow with hook', google: 'richtiger pfeil mit haken')
+ - "↫": [T: "Pfeil nach links mit Schleife"] # 0x21ab (en: 'leftwards arrow with loop', MathPlayer: 'leftwards arrow with loop', google: 'linkspfeil mit schleife')
+ - "↬": [T: "Pfeil nach rechts mit Schleife"] # 0x21ac (en: 'rightwards arrow with loop', MathPlayer: 'rightwards arrow with loop', google: 'richtiger pfeil mit schleife')
+ - "↭": [T: "Linker rechter Wellenpfeil"] # 0x21ad (en: 'left right wave arrow', MathPlayer: 'left right wave arrow', google: 'linke rechte wellenpfeil')
+ - "↮": [T: "Linker rechter Pfeil mit Strich"] # 0x21ae (en: 'left right arrow with stroke', MathPlayer: 'left right arrow with stroke', google: 'links rechts pfeil mit schlaganfall')
+ - "↯": [T: "Zickzack-Pfeil nach unten"] # 0x21af (en: 'downwards zigzag arrow', MathPlayer: 'downwards zigzag arrow', google: 'nach unten zickzack pfeil')
+ - "↰": [T: "Aufwärtspfeil mit Spitze nach links"] # 0x21b0 (en: 'upwards arrow with tip leftwards', MathPlayer: 'upwards arrow with tip leftwards', google: 'aufwärts mit tipp links nach oben')
+ - "↱": [T: "Aufwärtspfeil mit Spitze nach rechts"] # 0x21b1 (en: 'upwards arrow with tip rightwards', MathPlayer: 'upwards arrow with tip rightwards', google: 'aufwärts mit tipp nach oben nach oben')
+ - "↲": [T: "Abwärtspfeil mit Spitze nach links"] # 0x21b2 (en: 'downwards arrow with tip leftwards', MathPlayer: 'downwards arrow with tip leftwards', google: 'nach links nach unten pfeil nach unten')
+ - "↳": [T: "Abwärtspfeil mit Spitze nach rechts"] # 0x21b3 (en: 'downwards arrow with tip rightwards', MathPlayer: 'downwards arrow with tip rightwards', google: 'nach unten pfeil mit tipp nach rechts')
+ - "↴": [T: "Pfeil nach rechts mit nach unten gerichteter Ecke"] # 0x21b4 (en: 'rightwards arrow with corner downwards', MathPlayer: 'rightwards arrow with corner downwards', google: 'richtiger pfeil mit ecke nach unten')
+ - "↵": [T: "Pfeil nach unten mit Ecke nach links"] # 0x21b5 (en: 'downwards arrow with corner leftwards', MathPlayer: 'downwards arrow with corner leftwards', google: 'nach links von ecke nach unten pfeil nach unten')
+ - "↶": [T: "oberer halbkreisförmiger Pfeil gegen den Uhrzeigersinn "] # 0x21b6 (en: 'anticlockwise top semicircle arrow', MathPlayer: 'anticlockwise top semicircle arrow', google: 'top -semicircle -pfeil gegen den uhrzeigersinn')
+ - "↷": [T: "oberer halbkreisförmiger Pfeil im Uhrzeigersinn"] # 0x21b7 (en: 'clockwise top semicircle arrow', MathPlayer: 'clockwise top semicircle arrow', google: 'im uhrzeigersinn oberen halbkreispfeil')
+ - "↸": [T: "Nordwestpfeil zu langem Sockel"] # 0x21b8 (en: 'north west arrow to long bar', MathPlayer: 'north west arrow to long bar', google: 'nordwestpfeil in die lange bar')
+ - "↹": [T: "Pfeil nach links über Pfeil nach rechts"] # 0x21b9 (en: 'leftwards arrow to bar over rightwards arrow to bar', MathPlayer: 'leftwards arrow to bar over rightwards arrow to bar', google: 'der pfeil nach links, um über den pfeil nach rechts in die bar zu barken')
+ - "↺": [T: "Offener Kreispfeil gegen den Uhrzeigersinn"] # 0x21ba (en: 'anticlockwise open circle arrow', MathPlayer: 'anticlockwise open circle arrow', google: 'open circle arrow gegen den uhrzeigersinn')
+ - "↻": [T: "Offener Kreispfeil im Uhrzeigersinn"] # 0x21bb (en: 'clockwise open circle arrow', MathPlayer: 'clockwise open circle arrow', google: 'pfeil im uhrzeigersinn')
+ - "↼": [T: "Linke Harpune oben"] # 0x21bc (en: 'left harpoon up', MathPlayer: 'left harpoon up', google: 'ließ harpoon hoch')
+ - "↽": [T: "Linke Harpune unten"] # 0x21bd (en: 'left harpoon down', MathPlayer: 'left harpoon down', google: 'ließ harpoon nieder')
+ - "↾": [T: "Harpune rechts oben"] # 0x21be (en: 'up harpoon right', MathPlayer: 'up harpoon right', google: 'harpoon rechts')
+ - "↿": [T: "Harpune links oben"] # 0x21bf (en: 'up harpoon left', MathPlayer: 'up harpoon left', google: 'harpune nach oben')
+ - "⇀": [T: "Rechte Harpune oben"] # 0x21c0 (en: 'right harpoon up', MathPlayer: 'right harpoon up', google: 'richtige harpoon hoch')
+ - "⇁": [T: "Rechte Harpune unten"] # 0x21c1 (en: 'right harpoon down', MathPlayer: 'right harpoon down', google: 'richtige harpune unten')
+ - "⇂": [T: "Harpune rechts unten"] # 0x21c2 (en: 'down harpoon right', MathPlayer: 'down harpoon right', google: 'harpoon rechts')
+ - "⇃": [T: "Harpune links unten"] # 0x21c3 (en: 'down harpoon left', MathPlayer: 'down harpoon left', google: 'harpoon nach unten')
+ - "⇄": [T: "Pfeil nach rechts über Pfeil nach links"] # 0x21c4 (en: 'rightwards arrow over leftwards arrow', MathPlayer: 'rightwards arrow over leftwards arrow', google: 'rechten pfeil über den linken pfeil')
+ - "⇅": [T: "Pfeil nach oben links neben Pfeil nach unten"] # 0x21c5 (en: 'upwards arrow leftwards of downwards arrow', MathPlayer: 'upwards arrow leftwards of downwards arrow', google: 'aufwärts links vom abwärtsspfeil nach oben')
+ - "⇆": [T: "Pfeil nach links über Pfeil nach rechts"] # 0x21c6 (en: 'leftwards arrow over rightwards arrow', MathPlayer: 'leftwards arrow over rightwards arrow', google: 'links pfeil über rechts pfeil')
+ - "⇇": [T: "Links gepaarte Pfeile"] # 0x21c7 (en: 'leftwards paired arrows', MathPlayer: 'leftwards paired arrows', google: 'links gepaarte pfeile')
+ - "⇈": [T: "Aufwärts gepaarte Pfeile"] # 0x21c8 (en: 'upwards paired arrows', MathPlayer: 'upwards paired arrows', google: 'nach oben gepaarte pfeile')
+ - "⇉": [T: "Rechts gepaarte Pfeile"] # 0x21c9 (en: 'rightwards paired arrows', MathPlayer: 'rightwards paired arrows', google: 'rechtspaare pfeile')
+ - "⇊": [T: "Abwärts gepaarte Pfeile"] # 0x21ca (en: 'downwards paired arrows', MathPlayer: 'downwards paired arrows', google: 'abwärts gepaarte pfeile')
+ - "⇋": [T: "Harpune nach links über Harpune nach rechts"] # 0x21cb (en: 'left harpoon over right harpoon', MathPlayer: 'left harpoon over right harpoon', google: 'linke harpoon über die rechte harpune')
+ - "⇌": [T: "Harpune nach rechts über Harpune nach links"] # 0x21cc (en: 'right harpoon over left harpoon', MathPlayer: 'right harpoon over left harpoon', google: 'rechte harpune über die linke harpune')
+ - "⇍": [T: "Doppelpfeil nach links mit Strich"] # 0x21cd (en: 'leftwards double arrow with stroke', MathPlayer: 'leftwards double arrow with stroke', google: 'links -doppelpfeil mit schlaganfall')
+ - "⇎": [T: "Links Rechts Doppelpfeil mit Strich"] # 0x21ce (en: 'left right double arrow with stroke', MathPlayer: 'left right double arrow with stroke', google: 'links rechts doppelpfeil mit schlaganfall')
+ - "⇏": [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')
+ - "⇖": [T: "Nordwest-Doppelpfeil"] # 0x21d6 (en: 'north west double arrow', MathPlayer: 'north west double arrow', google: 'nordwesten doppelpfeil')
+ - "⇗": [T: "Nordost-Doppelpfeil"] # 0x21d7 (en: 'north east double arrow', MathPlayer: 'north east double arrow', google: 'nordost -doppelpfeil')
+ - "⇘": [T: "Südost Doppelpfeil"] # 0x21d8 (en: 'south east double arrow', MathPlayer: 'south east double arrow', google: 'south east doppelpfeil')
+ - "⇙": [T: "Südwest-Doppelpfeil"] # 0x21d9 (en: 'south west double arrow', MathPlayer: 'south west double arrow', google: 'south west doppelpfeil')
+ - "⇚": [T: "Dreifacher Pfeil nach links"] # 0x21da (en: 'leftwards triple arrow', MathPlayer: 'leftwards triple arrow', google: 'links dreifach pfeil')
+ - "⇛": [T: "Dreifacher Pfeil nach rechts"] # 0x21db (SRE: 'Dreifacher Pfeil nach rechts')
+ - "⇜": [T: "Nach links gekrümmter Pfeil"] # 0x21dc (en: 'leftwards squiggle arrow', MathPlayer: 'leftwards squiggle arrow', google: 'linkskundgier pfeil')
+ - "⇝": [T: "Nach rechts gekrümmter Pfeil"] # 0x21dd (en: 'rightwards squiggle arrow', MathPlayer: 'rightwards squiggle arrow', google: 'rightwards squiggle pfeil')
+ - "⇞": [T: "Aufwärtspfeil mit Doppelstrich"] # 0x21de (en: 'upwards arrow with double stroke', MathPlayer: 'upwards arrow with double stroke', google: 'aufwärts mit doppelhub')
+ - "⇟": [T: "Abwärtspfeil mit Doppelstrich"] # 0x21df (en: 'downwards arrow with double stroke', MathPlayer: 'downwards arrow with double stroke', google: 'nach unten pfeil mit doppelhub')
+ - "⇠": [T: "Gestrichelter Pfeil nach links"] # 0x21e0 (en: 'leftwards dashed arrow', MathPlayer: 'leftwards dashed arrow', google: 'links gestrichelten pfeil')
+ - "⇡": [T: "Gestrichelter Pfeil nach oben"] # 0x21e1 (en: 'upwards dashed arrow', MathPlayer: 'upwards dashed arrow', google: 'nach oben gestrichelter pfeil')
+ - "⇢": [T: "Gestrichelter Pfeil nach rechts"] # 0x21e2 (en: 'rightwards dashed arrow', MathPlayer: 'rightwards dashed arrow', google: 'rightwards gestrichelten pfeil')
+ - "⇣": [T: "Abwärts gestrichelter Pfeil"] # 0x21e3 (en: 'downwards dashed arrow', MathPlayer: 'downwards dashed arrow', google: 'abwärts gestrichelten pfeil')
+ - "⇤": [T: "Pfeil nach links zur Sockel"] # 0x21e4 (en: 'leftwards arrow to bar', MathPlayer: 'leftwards arrow to bar', google: 'links pfeil in die bar')
+ - "⇥": [T: "Pfeil nach rechts zur Sockel"] # 0x21e5 (en: 'rightwards arrow to bar', MathPlayer: 'rightwards arrow to bar', google: 'rightwards pfeil in die bar')
+ - "⇦": [T: "Weißer Pfeil nach links"] # 0x21e6 (en: 'leftwards white arrow', MathPlayer: 'leftwards white arrow', google: 'links weißer pfeil')
+ - "⇧": [T: "Aufwärts weißer Pfeil"] # 0x21e7 (en: 'upwards white arrow', MathPlayer: 'upwards white arrow', google: 'nach oben weißer pfeil')
+ - "⇨": [T: "Rechts weißer Pfeil"] # 0x21e8 (en: 'rightwards white arrow', MathPlayer: 'rightwards white arrow', google: 'richtiger weißer pfeil')
+ - "⇩": [T: "Abwärts weißer Pfeil"] # 0x21e9 (en: 'downwards white arrow', MathPlayer: 'downwards white arrow', google: 'nach unten weißer pfeil')
+ - "⇪": [T: "Aufwärts weißer Pfeil von der Stange"] # 0x21ea (en: 'upwards white arrow from bar', MathPlayer: 'upwards white arrow from bar', google: 'nach oben weißer pfeil aus der bar')
+ - "⇫": [T: "Aufwärts weißer Pfeil auf Sockel"] # 0x21eb (en: 'upwards white arrow on pedestal', google: 'nach oben weißer pfeil auf sockel')
+ - "⇬": [T: "Aufwärts weißer Pfeil auf Sockel mit horizontaler Stange"] # 0x21ec (en: 'upwards white arrow on pedestal with horizontal bar', google: 'nach oben weißer pfeil auf sockel mit horizontaler balken')
+ - "⇭": [T: "Aufwärts weißer Pfeil auf Sockel mit vertikaler Stange"] # 0x21ed (en: 'upwards white arrow on pedestal with vertical bar', google: 'nach oben weißer pfeil auf sockel mit vertikaler balken')
+ - "⇮": [T: "Aufwärts weißer Doppelpfeil"] # 0x21ee (en: 'upwards white double arrow', google: 'nach oben weißer doppelpfeil')
+ - "⇯": [T: "Aufwärts weißer doppelter Pfeil auf Sockel"] # 0x21ef (en: 'upwards white double arrow on pedestal', google: 'nach oben weißer doppelpfeil auf sockel')
+ - "⇰": [T: "Rechts weißer Pfeil von der Wand"] # 0x21f0 (en: 'rightwards white arrow from wall', google: 'richtiger weißer pfeil von der wand')
+ - "⇱": [T: "Nordwestpfeil zur Ecke"] # 0x21f1 (en: 'north west arrow to corner', google: 'nordwestpfeil zur ecke')
+ - "⇲": [T: "Südostpfeil zur Ecke"] # 0x21f2 (en: 'south east arrow to corner', google: 'south east pfeil zur ecke')
+ - "⇳": [T: "Weißer Pfeil nach unten und oben"] # 0x21f3 (en: 'up down white arrow', google: 'runter weißer pfeil')
+ - "⇴": [T: "rechter Pfeil mit kleinem Kreis"] # 0x21f4 (en: 'right arrow with small circle', google: 'rechts pfeil mit kleinem kreis')
+ - "⇵": [T: "Abwärtspfeil links von Aufwärtspfeil"] # 0x21f5 (en: 'downwards arrow leftwards of upwards arrow', MathPlayer: 'upwards arrow to the right of downwards arrow', google: 'abwärts links nach oben auf pfeil')
+ - "⇶": [T: "Drei nach rechts gerichtete Pfeile"] # 0x21f6 (en: 'three rightwards arrows', google: 'drei rechts pfeile')
+ - "⇷": [T: "Pfeil nach links mit vertikalem Strich"] # 0x21f7 (en: 'leftwards arrow with vertical stroke', google: 'linkspfeil mit vertikalem schlaganfall')
+ - "⇸": [T: "Pfeil nach rechts mit vertikalem Strich"] # 0x21f8 (en: 'rightwards arrow with vertical stroke', google: 'richtiger pfeil mit vertikalem schlaganfall')
+ - "⇹": [T: "Linker rechter Pfeil mit vertikalem Strich"] # 0x21f9 (en: 'left right arrow with vertical stroke', google: 'links rechts pfeil mit vertikalem schlaganfall')
+ - "⇺": [T: "Pfeil nach links mit doppeltem vertikalem Strich"] # 0x21fa (en: 'leftwards arrow with double vertical stroke', google: 'linkspfeil mit doppelter vertikaler hub')
+ - "⇻": [T: "Pfeil nach rechts mit doppeltem vertikalem Strich"] # 0x21fb (en: 'rightwards arrow with double vertical stroke', google: 'richtiger pfeil mit doppelter vertikaler schlaganfall')
+ - "⇼": [T: "Linker rechter Pfeil mit doppeltem vertikalem Strich"] # 0x21fc (en: 'left right arrow with double vertical stroke', google: 'links rechts pfeil mit doppelter vertikaler hub')
+ - "⇽": [T: "Pfeil nach links mit offenem Kopf"] # 0x21fd (en: 'leftwards open headed arrow', MathPlayer: 'leftwards open headed arrow', google: 'links offene köpfe pfeil')
+ - "⇾": [T: "Pfeil nach rechts mit offenem Kopf"] # 0x21fe (en: 'rightwards open headed arrow', MathPlayer: 'rightwards open headed arrow', google: 'rightwards open headed pfeil')
+ - "⇿": [T: "Linker rechter Pfeil mit offenem Kopf"] # 0x21ff (en: 'left right open headed arrow', MathPlayer: 'left right open headed arrow', google: 'links rechts geöffneter köpfe')
+ - "∀": [T: "für alle"] # 0x2200 (en: 'for all')
+ - "∁": # 0x2201
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # (en: 'the', google translation)
+ - T: "Komplement" # (en: 'complement of')
+ - "∂": # 0x2202
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "teilweise"] # (en: 'partial', google translation)
+ else: [T: "rundes d"] # (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: "Differenz" # (en: 'laplacian of', MathPlayer: 'increment', google: 'laplace von')
+ - "∇": # 0x2207
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # (en: 'the', google translation)
+ - T: "gradient (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: "Mitglied 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 Mitglied 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: "nicht Mitglied 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 Mitglied 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: "Mitglied 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 Mitglied 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:
+ if: "@data-chem-formula-op"
+ 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'"
+ then: [T: "die"] # (en: 'the', google translation)
+ - T: "Kubikwurzel" # (en: 'cube root of', MathPlayer: 'dritte Wurzel', google: 'würfelwurzel von')
+ - "∜": # 0x221c
+ - test:
+ 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')
+ - "∲": [T: "Kurvenintegral im Uhrzeigersinn"] # 0x2232 (en: 'clockwise contour integral', MathPlayer: 'Kontur-Integral im Uhrzeigersinn', google: 'konturintegral im uhrzeigersinn')
+ - "∳": [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
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "geometrische Proportion" # (en: 'geometrically proportional to')
+ - "∻": # 0x223b
+ - test:
+ 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')
+ - "≃": # 0x2243
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "asymptotisch gleich" # (en: 'asymptotically equal to')
+ - "≄": # 0x2244
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "nicht asymptotisch gleich" # (en: 'not asymptotically equal to')
+ - "≅": # 0x2245
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "ungefähr gleich" # (en: 'approximately equal to')
+ - "≆": # 0x2246
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "ungefähr, aber nicht ganz gleich" # (en: 'approximately but not actually equal to')
+ - "≇": # 0x2247
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "weder ungefähr noch ganz gleich" # (en: 'neither approximately nor actually equal to')
+ - "≈": # 0x2248
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "beinahe gleich" # (en: 'almost equal to')
+ - "≉": # 0x2249
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "nicht beinahe gleich" # (en: 'not almost equal to')
+ - "≊": # 0x224a
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "beinahe gleich oder gleich" # (en: 'almost equal or equal to', MathPlayer: 'beinahe oder ganz gleich', google: 'fast gleich oder gleich')
+ - "≋": [T: "dreifache Tilde"] # 0x224b (en: 'triple tilde', MathPlayer: 'triple tilde', google: 'dreifach tilde')
+ - "≌": [T: "alles gleich"] # 0x224c (en: 'are all equal to', MathPlayer: 'all equal to', google: 'sind alle gleich')
+ - "≍": # 0x224d
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "äquivalent zu" # (en: 'equivalent to')
+ - "≎": # 0x224e
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "geometrisch äquivalent zu" # (en: 'geometrically equivalent to')
+ - "≏": # 0x224f
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # (en: 'the', google translation)
+ - T: "Differenz zwischen" # (en: 'difference between')
+ - "≐": [T: "nähert sich der Grenze"] # 0x2250 (en: 'approaches the limit')
+ - "≑": # 0x2251
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "geometrisch gleich" # (en: 'geometrically equal to')
+ - "≒": # 0x2252
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "Ungefähr gleich oder das Bild von" # (en: 'approximately equal to or the image of', MathPlayer: 'approximately equal to or the image of', google: 'ungefähr gleich oder das bild von')
+ - "≓": # 0x2253
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist der"] # (en: 'is the', google translation)
+ - T: "Bild von oder ungefähr gleich" # (en: 'image of or approximately equal to', MathPlayer: 'image of or approximately equal to', google: 'bild von oder ungefähr gleich')
+ - "≔": [T: "definiert als"] # 0x2254 (en: 'colon equals')
+ - "≕": [T: "definiert als von rechts"] # 0x2255 (en: 'equals colon', MathPlayer: 'equals colon', google: 'gleich')
+ - "≖": [T: "ungefähr gleich"] # 0x2256 (en: 'ring in equal to', MathPlayer: 'ring in equal to', google: 'in gleich rufen')
+ - "≗": # 0x2257
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "ungefähr gleich" # (en: 'approximately equal to', MathPlayer: 'ring equal to')
+ - "≘": [T: "entspricht"] # 0x2258 (en: 'corresponds to')
+ - "≙": [T: "entspricht"] # 0x2259 (en: 'estimates', MathPlayer: 'estimates', google: 'schätzungen')
+ - "≚": # 0x225a
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "gleichwinklig zu" # (en: 'equiangular to', MathPlayer: 'equiangular to', google: 'gleiche zu')
+ - "≛": [T: "gleich mit Stern"] # 0x225b (en: 'star equals', MathPlayer: 'star equals', google: 'stern ist gleich')
+ - "≜": [T: "gleich mit Delta"] # 0x225c (en: 'delta equals', MathPlayer: 'delta equal to', google: 'delta gleich')
+ - "≝": [T: "definitionsgemäß gleich"] # 0x225d (en: 'is defined to be')
+ - "≞": # 0x225e
+ - test:
+ if: "$Verbosity!='Terse'"
+ 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'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "nicht identisch mit" # (en: 'not identical to', SRE: 'nicht kongruent mit')
+ - "≣": # 0x2263
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "genau äquivalent mit" # (en: 'strictly equivalent to', MathPlayer: 'streng äquivalent mit', google: 'streng äquivalent zu')
+ - "≦": [T: "kleiner als über gleich"] # 0x2266 (en: 'less than over equal to', MathPlayer: 'less than over equal to', google: 'weniger als überweg')
+ - "≧": [T: "größer als über gleich"] # 0x2267 (en: 'greater than over equal to', MathPlayer: 'greater than over equal to', google: 'größer als überweg')
+ - "≨": # 0x2268
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "kleiner als, aber nicht gleich" # (en: 'less than but not equal to')
+ - "≩": # 0x2269
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "größer als, aber nicht gleich" # (en: 'greater than but not equal to')
+ - "≪": # 0x226a
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "viel kleiner als" # (en: 'much less than')
+ - "≫": # 0x226b
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "viel größer als" # (en: 'much greater than')
+ - "≬": # 0x226c
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "zwischen" # (en: 'between')
+ - "≭": # 0x226d
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "nicht äquivalent mit" # (en: 'not equivalent to')
+ - "≮": # 0x226e
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "nicht kleiner als" # (en: 'not less than')
+ - "≯": # 0x226f
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "nicht größer als" # (en: 'not greater than')
+ - "≰": # 0x2270
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "weder kleiner als noch gleich" # (en: 'neither less than nor equal to')
+ - "≱": # 0x2271
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "weder größer als noch gleich" # (en: 'neither greater than nor equal to')
+ - "≲": # 0x2272
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "kleiner als oder äquivalent" # (en: 'less than or equivalent to')
+ - "≳": # 0x2273
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "größer als oder äquivalent" # (en: 'greater than or equivalent to')
+ - "≴": # 0x2274
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "weder kleiner als noch äquivalent" # (en: 'neither less than nor equivalent to')
+ - "≵": # 0x2275
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "weder größer als noch äquivalent" # (en: 'neither greater than nor equivalent to')
+ - "≶": # 0x2276
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "kleiner oder größer als" # (en: 'less than or greater than')
+ - "≷": # 0x2277
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "größer oder kleiner als" # (en: 'greater than or less than')
+ - "≸": # 0x2278
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "weder kleiner noch größer als" # (en: 'neither less than nor greater than')
+ - "≹": # 0x2279
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "weder größer noch kleiner als" # (en: 'neither greater than nor less than')
+ - "≺": [T: "vorangehend"] # 0x227a (en: 'precedes', MathPlayer: 'precedes', google: 'voraus')
+ - "≻": [T: "nachfolgend"] # 0x227b (en: 'succeeds', MathPlayer: 'succeeds', google: 'gelingt es')
+ - "≼": [T: "vorangehend oder gleich"] # 0x227c (en: 'precedes or is equal to', MathPlayer: 'precedes or equal to', google: 'vorausgeht oder ist gleich')
+ - "≽": [T: "nachfolgend oder gleich"] # 0x227d (en: 'succeeds or is equal to', MathPlayer: 'succeeds or equal to', google: 'erfolg oder ist gleich')
+ - "≾": [T: "vorangehend oder äquivalent"] # 0x227e (en: 'precedes or is equivalent to', MathPlayer: 'precedes or equivalent to', google: 'vorausgeht oder ist gleichbedeutend mit')
+ - "≿": [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: "kein 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'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "weder Teilmenge noch gleich" # (en: 'neither a subset of nor equal to', MathPlayer: 'weder Teilmenge von noch gleich', google: 'weder eine untergruppe von noch gleich')
+ - "⊉": # 0x2289
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "weder Obermenge noch gleich" # (en: 'neither a superset of nor equal to', MathPlayer: 'weder Obermenge von noch gleich', google: 'weder ein superset von noch gleich')
+ - "⊊": [T: "Teilmenge aber nicht gleich"] # 0x228a (en: 'subset of with not equal to', MathPlayer: 'Teilmenge von, aber nicht gleich', google: 'teilmenge von mit nicht gleich')
+ - "⊋": [T: "Obermenge aber nicht gleich"] # 0x228b (en: 'superset of with not equal to', MathPlayer: 'Obermenge von, aber nicht gleich', google: 'superset von mit nicht gleich')
+ - "⊌": [T: "Mehrfachmenget"] # 0x228c (SRE: 'Multimenge')
+ - "⊍": [T: "Multimengenmultiplikation"] # 0x228d (en: 'multiset multiplication', MathPlayer: 'multiset multiplication', google: 'multiset -multiplikation')
+ - "⊎": [T: "Multimengenvereinigung"] # 0x228e (SRE: 'Multimengenvereinigung')
+ - "⊏": [T: "quadratisches Bild von"] # 0x228f (en: 'square image of', MathPlayer: 'square image of', google: 'square bild von')
+ - "⊐": [T: "quadratisches Original von"] # 0x2290 (en: 'square original of', MathPlayer: 'square original of', google: 'square original von')
+ - "⊑": [T: "quadratisches Bild oder gleich"] # 0x2291 (en: 'square image of or equal to', MathPlayer: 'square image of or equal to', google: 'quadratisches bild von oder gleich')
+ - "⊒": [T: "quadratisches Original oder gleich"] # 0x2292 (en: 'square original of or equal to', MathPlayer: 'square original of or equal to', google: 'square original von oder gleich')
+ - "⊓": [T: "quadratische Schnittmenge"] # 0x2293 (en: 'square cap', MathPlayer: 'square cap', google: 'quadratische großbuchstaben')
+ - "⊔": [T: "quadratische Vereinigungsmenge"] # 0x2294 (en: 'square cup', MathPlayer: 'square cup', google: 'quadratbecher')
+ - "⊕": [T: "eingekreistes Pluszeichen"] # 0x2295 (en: 'circled plus', MathPlayer: 'circle plus', google: 'umgekreist plus')
+ - "⊖": [T: "eingekreistes Minuszeichen"] # 0x2296 (en: 'circled minus', MathPlayer: 'circle minus', google: 'eingekreist minus')
+ - "⊗": [T: "eingekreiste Multiplikation"] # 0x2297 (en: 'circled times', MathPlayer: 'circle times', google: 'kreiste zeiten')
+ - "⊘": [T: "eingekreiste Division"] # 0x2298 (en: 'circled slash', MathPlayer: 'circle slash', google: 'eingekreist')
+ - "⊙": [T: "eingekreister Punktoperator"] # 0x2299 (en: 'circled dot operator', MathPlayer: 'circle dot', google: 'eingekreister punktbetreiber')
+ - "⊚": [T: "eingekreister Ringoperator"] # 0x229a (en: 'circled ring', MathPlayer: 'circle ring', google: 'eingekreister ring')
+ - "⊛": [T: "eingekreister Sternoperator"] # 0x229b (en: 'circled asterisk', MathPlayer: 'circle asterisk', google: 'eingekreistes sternchen')
+ - "⊜": [T: "eingekreistes Gleich"] # 0x229c (en: 'circled equals', MathPlayer: 'circle equals', google: 'kreist gleich')
+ - "⊝": [T: "eingekreister Gedankenstrich"] # 0x229d (en: 'circled dash', MathPlayer: 'circle dash', google: 'kreislauf')
+ - "⊞": [T: "eingerahmtes Plus"] # 0x229e (en: 'squared plus', MathPlayer: 'square plus', google: 'quadrat plus')
+ - "⊟": [T: "eingerahmtes Minus"] # 0x229f (en: 'squared minus', MathPlayer: 'square minus', google: 'quadratisch minus')
+ - "⊠": [T: "eingerahmte Multiplikation"] # 0x22a0 (en: 'squared times', MathPlayer: 'square times', google: 'quadratische zeiten')
+ - "⊡": [T: "eingerahmter Punktoperator"] # 0x22a1 (en: 'squared dot operator', MathPlayer: 'square dot', google: 'quadratischer punktbetreiber')
+ - "⊢": [T: "ergibt"] # 0x22a2 (en: 'proves', MathPlayer: 'right tack', google: 'beweist')
+ - "⊣": [T: "ergibt nicht"] # 0x22a3 (en: 'does not yield', MathPlayer: 'left tack', google: 'ergeben nicht')
+ - "⊤": [T: "senkrecht von"] # 0x22a4 (en: 'top', MathPlayer: 'down tack', google: 'spitze')
+ - "⊥": # 0x22a5
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "senkrecht auf" # (en: 'bottom', MathPlayer: 'up tack', google: 'unten')
+ - "⊦": [T: "Behauptung"] # 0x22a6 (en: 'reduces to', MathPlayer: 'assertion', google: 'reduziert zu')
+ - "⊧": [T: "Model"] # 0x22a7 (en: 'models', MathPlayer: 'models', google: 'modelle')
+ - "⊨": # 0x22a8
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "wahr" # (en: 'true', MathPlayer: 'true')
+ - "⊩": [T: "erzwingen"] # 0x22a9 (en: 'forces', MathPlayer: 'forces', google: 'kräfte')
+ - "⊪": [T: "dreifache vertikale Leiste mit rechtem Drehkreuz"] # 0x22aa (en: 'triple vertical bar right turnstile', MathPlayer: 'triple vertical bar right turnstile', google: 'triple vertikale bar rechtsummens')
+ - "⊫": [T: "doppelte vertikale Leiste mit doppeltem rechtem Drehkreuz"] # 0x22ab (en: 'double vertical bar double right turnstile', MathPlayer: 'double vertical bar double right turnstile', google: 'doppelte vertikale balken doppelte rechte kurve')
+ - "⊬": [T: "beweist nicht"] # 0x22ac (en: 'does not prove', MathPlayer: 'does not prove')
+ - "⊭": # 0x22ad
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "nicht wahr" # (en: 'not true', MathPlayer: 'not true')
+ - "⊮": [T: "nicht erzwingen"] # 0x22ae (en: 'does not force', MathPlayer: 'does not force', google: 'zwingt nicht')
+ - "⊯": [T: "negierte doppelte vertikale Leiste mit doppeltem rechten Drehkreuz"] # 0x22af (en: 'negated double vertical bar double right turnstile', MathPlayer: 'negated double vertical bar double right turnstile', google: 'negierter doppelter vertikaler balken doppelte rechte kurve')
+ - "⊰": [T: "vorangehend in Relation"] # 0x22b0 (en: 'precedes under relation', MathPlayer: 'precedes under relation', google: 'vorausgegangen in beziehung')
+ - "⊱": [T: "nachfolgend in Relation"] # 0x22b1 (en: 'succeeds under relation', MathPlayer: 'succeeds under relation', google: 'erfolgreich in beziehung')
+ - "⊲": # 0x22b2
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "normale Untergruppe" # (en: 'a normal subgroup of', MathPlayer: 'normal subgroup of', google: 'eine normale untergruppe von')
+ - "⊳": [T: "enthält normale Untergruppe"] # 0x22b3 (en: 'contains as a normal subgroup', MathPlayer: 'contains as normal subgroup', google: 'enthält als normale untergruppe')
+ - "⊴": # 0x22b4
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "normale Untergruppe von oder gleich" # (en: 'a normal subgroup of or equal to', MathPlayer: 'normal subgroup of or equal to', google: 'eine normale untergruppe von oder gleich')
+ - "⊵": [T: "enthält normale Untergruppe oder gleich"] # 0x22b5 (en: 'contains as a normal subgroup or equal to', MathPlayer: 'contains as normal subgroup or equal to', google: 'enthält als normale untergruppe oder gleich')
+ - "⊶": # 0x22b6
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "Original von" # (en: 'the original of', MathPlayer: 'original of', google: 'das original von')
+ - "⊷": # 0x22b7
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "Bild von" # (en: 'an image of', MathPlayer: 'image of', google: 'ein bild von')
+ - "⊸": [T: "multimap"] # 0x22b8 (SRE: 'Mehrfachzuordnung')
+ - "⊹": [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: "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')
+ - "⋀": [T: "logisch und"] # 0x22c0 (en: 'logical and', SRE: 'N-stufiges logisches Und')
+ - "⋁": [T: "logisch oder"] # 0x22c1 (en: 'logical or', SRE: 'N-stufiges logisches Oder')
+ - "⋂": [T: "N-stufiger Durchschnitt"] # 0x22c2 (en: 'intersection', MathPlayer: 'Durchschnitt', google: 'überschneidung')
+ - "⋃": [T: "N-stufige Vereinigung"] # 0x22c3 (en: 'union', MathPlayer: 'Vereinigung', google: 'union')
+ - "⋄": [T: "Rautenoperator"] # 0x22c4 (en: 'diamond operator', MathPlayer: 'diamond operator', google: 'diamantbetreiber')
+ - "⋅": # 0x22c5
+ - test:
+ if: "@data-chem-formula-op"
+ then: [T: "punkt"] # (en: 'dot', google translation)
+ else: [T: "mal"] # (en: 'times', MathPlayer: 'dot')
+
+ - "⋆": [T: "Sternoperator"] # 0x22c6 (en: 'times', MathPlayer: 'star', google: 'mal')
+ - "⋇": [T: "Divisionsanzahl"] # 0x22c7 (en: 'division times', MathPlayer: 'division times', google: 'divisionszeiten')
+ - "⋈": [T: "Schleife"] # 0x22c8 (en: 'bowtie', MathPlayer: 'bowtie', google: 'krawatte')
+ - "⋉": # 0x22c9
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "linkes halbdirektes Produkt" # (en: 'the left normal factor semidirect product of', MathPlayer: 'left normal factor semidirect product', google: 'das linke normale faktor semidirekte produkt von')
+ - "⋊": # 0x22ca
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "rechtes halbdirektes Produkt" # (en: 'the right normal factor semidirect product of', MathPlayer: 'right normal factor semidirect product', google: 'der richtige normale faktor semidirect -produkt von')
+ - "⋋": # 0x22cb
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "linkes halbdirektes Produkt" # (en: 'the left semidirect product of', MathPlayer: 'left semidirect product', google: 'das linke semidirect -produkt von')
+ - "⋌": # 0x22cc
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "rechtes halbdirektes Produkt" # (en: 'the right semidirect product of', MathPlayer: 'right semidirect product', google: 'das richtige semidirect -produkt von')
+ - "⋍": [T: "umgekehrte Tilde gleich"] # 0x22cd (en: 'reversed tilde equals', MathPlayer: 'reversed tilde equals', google: 'umgekehrte tilde gleich')
+ - "⋎": [T: "geschweiftes logisches Oder"] # 0x22ce (en: 'curly logical or', MathPlayer: 'curly logical or', google: 'lockiges logisch oder')
+ - "⋏": [T: "geschweiftes logisches Und"] # 0x22cf (en: 'curly logical and', MathPlayer: 'curly logical and', google: 'lockiges logisch und')
+ - "⋐": # 0x22d0
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "doppelte Teilmenge" # (en: 'a double subset of', MathPlayer: 'double subset', google: 'eine doppelte untergruppe von')
+ - "⋑": # 0x22d1
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "doppelte Obermenge" # (en: 'a double superset of', MathPlayer: 'double superset', google: 'ein doppeltes superset von')
+ - "⋒": # 0x22d2
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # (en: 'the', google translation)
+ - T: "doppelter Durchschnitt" # (en: 'double intersection of', MathPlayer: 'double intersection', google: 'doppelte kreuzung von')
+ - "⋓": # 0x22d3
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # (en: 'the', google translation)
+ - T: "doppelte Vereinigung" # (en: 'double union of', MathPlayer: 'double union', google: 'doppelte vereinigung von')
+ - "⋔": # 0x22d4
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # (en: 'the', google translation)
+ - T: "echter Durchschnitt" # (en: 'proper intersection of', MathPlayer: 'pitchfork', google: 'richtige schnittpunkt von')
+ - "⋕": # 0x22d5
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "gleich und parallel" # (en: 'equal to and parallel to', MathPlayer: 'equal and parallel to', google: 'gleich und parallel zu')
+ - "⋖": [T: "kleiner als mit Punkt"] # 0x22d6 (en: 'less than with dot', MathPlayer: 'less than with dot', google: 'weniger als mit punkt')
+ - "⋗": [T: "größer als mit Punkt"] # 0x22d7 (en: 'greater than with dot', MathPlayer: 'greater than with dot', google: 'größer als mit punkt')
+ - "⋘": # 0x22d8
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "sehr viel kleiner als" # (en: 'very much less than', MathPlayer: 'very much less than', google: 'sehr viel weniger als')
+ - "⋙": # 0x22d9
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "sehr viel größer als" # (en: 'very much greater than', MathPlayer: 'very much greater than')
+ - "⋚": # 0x22da
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "kleiner als, gleich oder größer als" # (en: 'less than equal to or greater than', MathPlayer: 'less than equal to or greater than', google: 'weniger als gleich oder größer als')
+ - "⋛": # 0x22db
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "größer als, gleich oder kleiner als" # (en: 'greater than equal to or less than', MathPlayer: 'greater than equal to or less than', google: 'größer als gleich oder weniger als')
+ - "⋜": # 0x22dc
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "gleich oder kleiner als" # (en: 'equal to or less than', MathPlayer: 'equal to or less than', google: 'gleich oder weniger als')
+ - "⋝": # 0x22dd
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "gleich oder größer als" # (en: 'equal to or greater than', MathPlayer: 'equal to or greater than')
+ - "⋞": # 0x22de
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "gleich oder vorangehend" # (en: 'equal to or precedes', MathPlayer: 'equal to or precedes', google: 'gleich oder voraus')
+ - "⋟": # 0x22df
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "gleich oder nachfolgend" # (en: 'equal to or succeeds', MathPlayer: 'equal to or succeeds', google: 'gleich oder erfolgreich')
+ - "⋠": [T: "weder vorangehend oder gleich"] # 0x22e0 (en: 'does not precede nor is equal to', MathPlayer: 'does not precede or equal', google: 'geht nicht voraus und ist nicht gleich')
+ - "⋡": [T: "weder nachfolgend oder gleich"] # 0x22e1 (en: 'does not succeed nor is equal to', MathPlayer: 'does not succeed or equal', google: 'gelingt weder noch ist es gleich')
+ - "⋢": [T: "kein quadratisches Bild oder gleich"] # 0x22e2 (en: 'not square image of or equal to', MathPlayer: 'not square image of or equal to', google: 'kein quadratisches bild von oder gleich')
+ - "⋣": [T: "kein quadratisches Original oder gleich"] # 0x22e3 (en: 'not square original of or equal to', MathPlayer: 'not square original of or equal to', google: 'kein quadratisches original von oder gleich')
+ - "⋤": [T: "quadratisches Bild oder nicht gleich"] # 0x22e4 (en: 'square image of or not equal to', MathPlayer: 'square image of or not equal to', google: 'quadratisches bild von oder nicht gleich')
+ - "⋥": [T: "quadratisches Original oder nicht gleich"] # 0x22e5 (en: 'square original of or not equal to', MathPlayer: 'square original of or not equal to', google: 'square original von oder nicht gleich')
+ - "⋦": # 0x22e6
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "kleiner als, aber nicht äquivalent" # (en: 'less than but not equivalent to', MathPlayer: 'less than but not equivalent to', google: 'weniger als aber nicht gleichbedeutend mit')
+ - "⋧": # 0x22e7
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "größer als, aber nicht äquivalent" # (en: 'greater than but not equivalent to', MathPlayer: 'greater than but not equivalent to', google: 'größer als aber nicht gleichbedeutend mit')
+ - "⋨": [T: "vorangehend, aber nicht äquivalent"] # 0x22e8 (en: 'precedes but is not equivalent to', MathPlayer: 'precedes but not equivalent to', google: 'vorausgesetzt, ist aber nicht gleichwertig zu')
+ - "⋩": [T: "nachfolgend, aber nicht äquivalent"] # 0x22e9 (en: 'succeeds but is not equivalent to', MathPlayer: 'succeeds but not equivalent to', google: 'erfolg, ist aber nicht gleichwertig zu')
+ - "⋪": # 0x22ea
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "nicht normale Untergruppe von" # (en: 'not a normal subgroup of', MathPlayer: 'not normal subgroup of', google: 'keine normale untergruppe von')
+ - "⋫": [T: "enthält keine normale Untergruppe"] # 0x22eb (en: 'does not contain as a normal subgroup', MathPlayer: 'does not contain as normal subgroup', google: 'enthält nicht als normale untergruppe')
+ - "⋬": # 0x22ec
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "keine normale Untergruppe von oder gleich" # (en: 'not a normal subgroup of nor is equal to', MathPlayer: 'not normal subgroup of or equal to', google: 'keine normale untergruppe von und nicht gleich')
+ - "⋭": [T: "enthält nicht als normale Untergruppe oder gleich"] # 0x22ed (en: 'does not contain as a normal subgroup nor is equal to', MathPlayer: 'does not contain as normal subgroup or equal', google: 'enthält weder eine normale untergruppe noch')
+ - "⋮": [T: "Vertikale Ellipsis"] # 0x22ee (en: 'vertical ellipsis', MathPlayer: 'vertical ellipsis', google: 'vertikale ellipse')
+ - "⋯": [T: "Zentrierte horizontale Ellipse"] # 0x22ef (en: 'dot dot dot', MathPlayer: 'math axis ellipsis', google: 'punkt punkt punkt')
+ - "⋰": [T: "Diagonale Ellipse unten links nach oben rechts"] # 0x22f0 (en: 'upwards diagonal ellipsis', MathPlayer: 'up right diagonal ellipsis', google: 'aufwärts diagonale ellipsis')
+ - "⋱": [T: "Diagonale Ellipse, oben links nach unten rechts"] # 0x22f1 (en: 'diagonal ellipsis', MathPlayer: 'down right diagonal ellipsis', google: 'diagonale ellipsis')
+ - "⋲": [T: "Element mit langem horizontalen Strich"] # 0x22f2 (en: 'element of with long horizontal stroke', MathPlayer: 'element of with long horizontal stroke', google: 'element von mit langem horizontalem schlaganfall')
+ - "⋳": [T: "Element mit vertikalem Strich am Ende des horizontalen Strichs"] # 0x22f3 (en: 'element of with vertical bar at end of horizontal stroke', MathPlayer: 'element of with vertical bar at end of horizontal stroke', google: 'element von mit vertikalem balken am ende des horizontalen strich')
+ - "⋴": [T: "kleines Element mit vertikalem Strich am Ende des horizontalen Strichs"] # 0x22f4 (en: 'element of with vertical bar at end of horizontal stroke', MathPlayer: 'element of with vertical bar at end of horizontal stroke', google: 'element von mit vertikalem balken am ende des horizontalen strich')
+ - "⋵": [T: "Element mit Punkt"] # 0x22f5 (en: 'element of with dot above', MathPlayer: 'element of with dot above', google: 'element von mit punkt oben')
+ - "⋶": [T: "Element mit Überstrich"] # 0x22f6 (en: 'element of with overbar', MathPlayer: 'element of with overbar', google: 'element von overbar')
+ - "⋷": [T: "kleines Element mit Überstrich"] # 0x22f7 (en: 'element of with overbar', MathPlayer: 'element of or equal to', google: 'element von overbar')
+ - "⋸": [T: "Element mit Unterstrich"] # 0x22f8 (en: 'element of with underbar', MathPlayer: 'element of with underbar', google: 'element von mit unterbar')
+ - "⋹": [T: "Element mit 2 horizontalen Strichen"] # 0x22f9 (en: 'element of with two horizontal strokes', MathPlayer: 'element of with two horizontal strokes', google: 'element von mit zwei horizontalen strichen')
+ - "⋺": [T: "umgekehrtes Elementzeichen mit langem horizontalen Strich"] # 0x22fa (en: 'contains with long horizontal stroke', MathPlayer: 'contains with long horizontal stroke', google: 'enthält mit langem horizontalem schlaganfall')
+ - "⋻": [T: "umgekehrtes Elementzeichen mit vertikalem Strich am Ende des horizontalen Strichs"] # 0x22fb (en: 'contains with vertical bar at end of horizontal stroke', MathPlayer: 'contains with vertical bar at end of horizontal stroke', google: 'enthält mit vertikaler balken am ende des horizontalen schlaganfalls')
+ - "⋼": [T: "kleines umgekehrtes Elementzeichen mit vertikalem Strich am Ende des horizontalen Strichs"] # 0x22fc (en: 'contains with vertical bar at end of horizontal stroke', MathPlayer: 'contains with vertical bar at end of horizontal stroke', google: 'enthält mit vertikaler balken am ende des horizontalen schlaganfalls')
+ - "⋽": [T: "umgekehrtes Elementzeichen mit Überstrich"] # 0x22fd (en: 'contains with overbar', MathPlayer: 'contains or equal to', google: 'enthält mit überbar')
+ - "⋾": [T: "kleines umgekehrtes Elementzeichen mit Überstrich"] # 0x22fe (en: 'contains with overbar', MathPlayer: 'small contains with overbar', google: 'enthält mit überbar')
+ - "⋿": [T: "Z-Notation-Bag-Mitgliedschaft"] # 0x22ff (en: 'z notation bag membership', MathPlayer: 'z notation bag membership', google: 'z notation bag mitgliedschaft')
+ - "⌀": [T: "Durchmesser-Zeichen"] # 0x2300 (en: 'diameter', MathPlayer: 'diameter', google: 'durchmesser')
+ - "⌁": [T: "Elektrischer Pfeil"] # 0x2301 (en: 'electric arrow', google: 'elektrischer pfeil')
+ - "⌂": [T: "Haus"] # 0x2302 (en: 'house', MathPlayer: 'house', google: 'haus')
+ - "⌃": [T: "Pfeilkopf nach oben"] # 0x2303 (en: 'up arrowhead', google: 'auf pfeilspitze')
+ - "⌄": [T: "Pfeilkopf nach unten"] # 0x2304 (en: 'down arrowhead', google: 'pfeilspitze')
+ - "⌅": [T: "Projektiv"] # 0x2305 (en: 'projective', MathPlayer: 'projective', google: 'projektiv')
+ - "⌆": [T: "Perspektive"] # 0x2306 (en: 'perspective', MathPlayer: 'perspective', google: 'perspektive')
+ - "⌇": [T: "Schlangenlinie"] # 0x2307 (en: 'wavy line', google: 'schlangenlinie')
+ - "⌈": [T: "linke Aufrundungsklammer"] # 0x2308 (en: 'left ceiling', MathPlayer: 'left ceiling', google: 'linke decke')
+ - "⌉": [T: "rechte Aufrundungsklammer"] # 0x2309 (en: 'right ceiling', MathPlayer: 'right ceiling', google: 'rechte decke')
+ - "⌊": [T: "linke Abrundungsklammer"] # 0x230a (en: 'left floor', MathPlayer: 'left floor', google: 'linker boden')
+ - "⌋": [T: "rechter Abrundungsklammer"] # 0x230b (en: 'right floor', MathPlayer: 'right floor', google: 'rechts boden')
+ - "⌌": [T: "unterer rechter Abschnitt"] # 0x230c (en: 'bottom right crop', MathPlayer: 'bottom right crop', google: 'unten rechts ernte')
+ - "⌍": [T: "Unterer linker Abschnitt"] # 0x230d (en: 'bottom left crop', MathPlayer: 'bottom left crop', google: 'unten linke ernte')
+ - "⌎": [T: "Oberer rechter Abschnitt"] # 0x230e (en: 'top right crop', MathPlayer: 'top right crop', google: 'oben rechts ernte')
+ - "⌏": [T: "Oberer linker Abschnitt"] # 0x230f (en: 'top left crop', MathPlayer: 'top left crop', google: 'oben linke ernte')
+ - "⌐": [T: "Umgekehrtes Nichtzeichen"] # 0x2310 (en: 'reversed not sign', MathPlayer: 'reversed not', google: 'umgekehrt nicht unterschreiben')
+ - "⌑": [T: "Quadratische Raute"] # 0x2311 (en: 'square lozenge', google: 'square rautege')
+ - "⌒": [T: "Bogen"] # 0x2312 (en: 'arc', MathPlayer: 'arc', google: 'bogen')
+ - "⌓": [T: "segment"] # 0x2313 (SRE: 'Segment')
+ - "⌔": [T: "Sektor"] # 0x2314 (en: 'sector', google: 'sektor')
+ - "⌕": [T: "telephone recorder"] # 0x2315 (google: 'telefonrekorder')
+ - "⌖": [T: "position indicator; crosshairs"] # 0x2316 (en: 'position indicator crosshairs', google: 'positionsindikator crosshairs')
+ - "⌗": [T: "Datenanzeigefeld"] # 0x2317 (google translation)
+ - "⌘": [T: "Sehenswürdigkeitszeichen"] # 0x2318 (google: 'spole von interschlage')
+ - "⌙": [T: "nicht gedrehtes zeichen"] # 0x2319 (en: 'turned not sign', google translation)
+ - "⌚": [T: "Uhr"] # 0x231a (google: 'betrachten')
+ - "⌛": [T: "sanduhr"] # 0x231b (en: 'hourglass', google translation)
+ - "⌜": [T: "Obere linke Ecke"] # 0x231c (en: 'top left corner', MathPlayer: 'top left corner', google: 'obere linke ecke')
+ - "⌝": [T: "Obere rechte Ecke"] # 0x231d (en: 'top right corner', MathPlayer: 'top right corner', google: 'obere rechte ecke')
+ - "⌞": [T: "Untere linke Ecke"] # 0x231e (en: 'bottom left corner', MathPlayer: 'bottom left corner', google: 'untere linke ecke')
+ - "⌟": [T: "Rechte untere Ecke"] # 0x231f (en: 'bottom right corner', MathPlayer: 'bottom right corner', google: 'rechte untere ecke')
+ - "⌠": [T: "Obere Hälfte eines Integrals"] # 0x2320 (en: 'top half integral', MathPlayer: 'top half integral', google: 'top -hälfte integral')
+ - "⌡": [T: "Untere Hälfte eines Integrals"] # 0x2321 (en: 'bottom half integral', MathPlayer: 'bottom half integral', google: 'untere hälfte integral')
+ - "⌢": [T: "Stirnrunzeln"] # 0x2322 (google: 'stirnrunzeln')
+ - "⌣": [T: "Lächeln"] # 0x2323 (google: 'lächeln')
+ - "⌤": [T: "Pfeilspitze zwischen zwei horizontalen Balken"] # 0x2324 (en: 'up arrowhead between two horizontal bars', google: 'auf der pfeilspitze zwischen zwei horizontalen balken')
+ - "⌥": [T: "optionschlüssel"] # 0x2325 (en: 'option key', google translation)
+ - "⌦": [T: "nach rechts löschen"] # 0x2326 (en: 'erase to the right', google translation)
+ - "⌧": [T: "x in einer rechteckbox"] # 0x2327 (en: 'x in a rectangle box', google translation)
+ - "⌨": [T: "tastatur"] # 0x2328 (en: 'keyboard', google translation)
+ - "〈": [T: "Linke spitze Klammer"] # 0x2329 (en: 'left pointing angle bracket', MathPlayer: 'left pointing angle bracket', google: 'links zeigewinkelhalterung')
+ - "〉": [T: "Rechte spitze Klammer"] # 0x232a (en: 'right pointing angle bracket', MathPlayer: 'right pointing angle bracket', google: 'rechte zeigewinkelhalterung')
+ - "⌫": [T: "links löschen"] # 0x232b (en: 'erase to the left', google translation)
+ - "⌬": [T: "benzolring"] # 0x232c (en: 'benzene ring', google translation)
+ - "⌭": [T: "Zylindrizität"] # 0x232d (google: 'zylinderheit')
+ - "⌮": [T: "Runsumpfeil"] # 0x232e (google: 'rund um das profil')
+ - "⌯": [T: "symmetrie"] # 0x232f (en: 'symmetry', google translation)
+ - "⌰": [T: "totaler auslauf"] # 0x2330 (en: 'total runout', google translation)
+ - "⌱": [T: "dimension ursprung"] # 0x2331 (en: 'dimension origin', google translation)
+ - "⌲": [T: "konische verjüngung"] # 0x2332 (en: 'conical taper', google translation)
+ - "⌳": [T: "neigung"] # 0x2333 (en: 'slope', google translation)
+ - "⌴": [T: "gegenbore"] # 0x2334 (en: 'counterbore', google translation)
+ - "⌵": [T: "versenken"] # 0x2335 (en: 'countersink', google translation)
+ - "⍰": [T: "eingerahmtes Fragezeichen"] # 0x2370 (en: 'unknown box', google: 'unbekannte box')
+ - "⎕": [T: "kasten"] # 0x2395 (en: 'box', google translation)
+ - "⏞": [T: "Obere geschweifte Klammer"] # 0x23DE (en: 'top brace', MathPlayer: 'top curly bracket', google: 'spitzenklammer')
+ - "⏟": [T: "Untere geschweifte Klammer"] # 0x23DF (en: 'bottom brace', MathPlayer: 'bottom curly bracket', google: 'bottom -klammer')
+ - "①-⑨": # 0x2460 - 0x2469
+ - T: "umkreiste" # (en: 'circled', MathPlayer: 'bottom curly bracket', google: 'eingekreist')
+ - spell: "translate('.', '①②③④⑤⑥⑦⑧⑨', '123456789')"
+ - "⑩": [T: "zehn umkreist"] # 0x2469 (en: 'circled ten', google translation)
+ - "⑪": [T: "elf umkreist"] # 0x246a (en: 'circled eleven', google translation)
+ - "⑫": [T: "zwölf umkreist"] # 0x246b (en: 'circled twelve', google translation)
+ - "⑬": [T: "dreizehn umkreist"] # 0x246c (en: 'circled thirteen', google translation)
+ - "⑭": [T: "vierzehn umkreist"] # 0x246d (en: 'circled fourteen', google translation)
+ - "⑮": [T: "fünfzehn umkreist"] # 0x246e (en: 'circled fifteen', google translation)
+ - "⑯": [T: "umkreiste sechzehn"] # 0x246f (en: 'circled sixteen', google translation)
+ - "⑰": [T: "siebzehn umkreist"] # 0x2470 (en: 'circled seventeen', google translation)
+ - "⑱": [T: "eingekreist"] # 0x2471 (en: 'circled eighteen', google translation)
+ - "⑳": [T: "zwanzig umkreist"] # 0x2473 (en: 'circled twenty', google translation)
+ - "⑴-⑼": # 0x2474 - 0x247d
+ - T: "klammern" # (en: 'parenthesized', google translation)
+ - spell: "translate('.', '⑴⑵⑶⑷⑸⑹⑺⑻⑼', '123456789')"
+ - "⑽": [T: "klammern zehn"] # 0x247d (en: 'parenthesized ten', google translation)
+ - "⑾": [T: "klammern elf"] # 0x247e (en: 'parenthesized eleven', google translation)
+ - "⑿": [T: "klammern zwölf"] # 0x247f (en: 'parenthesized twelve', google translation)
+ - "⒀": [T: "klammern dreizehn"] # 0x2480 (en: 'parenthesized thirteen', google translation)
+ - "⒁": [T: "klammern vierzehn"] # 0x2481 (en: 'parenthesized fourteen', google translation)
+ - "⒂": [T: "klammern fünfzehn"] # 0x2482 (en: 'parenthesized fifteen', google translation)
+ - "⒃": [T: "klammern sechzehn"] # 0x2483 (en: 'parenthesized sixteen', google translation)
+ - "⒄": [T: "klammern siebzehn"] # 0x2484 (en: 'parenthesized seventeen', google translation)
+ - "⒅": [T: "klammern"] # 0x2485 (en: 'parenthesized eighteen', google translation)
+ - "⒆": [T: "klammern neunzehn"] # 0x2486 (en: 'parenthesized nineteen', google translation)
+ - "⒇": [T: "klammern von zwanzig"] # 0x2487 (en: 'parenthesized twenty', google translation)
+ - "⒈-⒐": # 0x2488 - 0x2491
+ - spell: "translate('.', '⒈⒉⒊⒋⒌⒍⒎⒏⒐', '123456789')"
+ - T: "mit periode" # (en: 'with period', google translation)
+ - "⒑": [T: "zehn mit periode"] # 0x2491 (en: 'ten with period', google translation)
+ - "⒒": [T: "elf mit periode"] # 0x2492 (en: 'eleven with period', google translation)
+ - "⒓": [T: "zwölf mit periode"] # 0x2493 (en: 'twelve with period', google translation)
+ - "⒔": [T: "dreizehn mit periode"] # 0x2494 (en: 'thirteen with period', google translation)
+ - "⒕": [T: "vierzehn mit periode"] # 0x2495 (en: 'fourteen with period', google translation)
+ - "⒖": [T: "fünfzehn mit periode"] # 0x2496 (en: 'fifteen with period', google translation)
+ - "⒗": [T: "16 mit periode"] # 0x2497 (en: 'sixteen with period', google translation)
+ - "⒘": [T: "siebzehn mit periode"] # 0x2498 (en: 'seventeen with period', google translation)
+ - "⒙": [T: "mit periode gefressen"] # 0x2499 (en: 'eighteen with period', google translation)
+ - "⒚": [T: "neunzehn mit periode"] # 0x249a (en: 'nineteen with period', google translation)
+ - "⒛": [T: "zwanzig mit periode"] # 0x249b (en: 'twenty with period', google translation)
+ - "⒜-⒵": # 0x249c - 0x24b5
+ - T: "klammern" # (en: 'parenthesized', google translation)
+ - spell: "translate('.', '⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "Ⓐ-Ⓩ":
+ - T: "eingekreist" # (en: 'circled', google translation)
+ - spell: "translate('.', 'ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏ', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "ⓐ-ⓩ": # 0x24d0 - 0x24e9
+ - T: "eingekreist" # (en: 'circled', google translation)
+ - spell: "translate('.', 'ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ', 'abcdefghijklmnopqrstuvwxyz')"
+ - "⓪": [T: "eingekreist null"] # 0x24ea (en: 'circled zero', google translation)
+ - "⓫": [T: "schwarz eingekreiste elf"] # 0x24eb (en: 'black circled eleven', google translation)
+ - "⓬": [T: "schwarz eingekreiste zwölf"] # 0x24ec (en: 'black circled twelve', google translation)
+ - "⓭": [T: "schwarz eingekreiste dreizehn"] # 0x24ed (en: 'black circled thirteen', google translation)
+ - "⓮": [T: "schwarz eingekreiste vierzehn"] # 0x24ee (en: 'black circled fourteen', google translation)
+ - "⓯": [T: "schwarz eingekreiste fünfzehn"] # 0x24ef (en: 'black circled fifteen', google translation)
+ - "⓰": [T: "schwarz eingekreiste sechzehn"] # 0x24f0 (en: 'black circled sixteen', google translation)
+ - "⓱": [T: "schwarz eingekreiste siebzehn"] # 0x24f1 (en: 'black circled seventeen', google translation)
+ - "⓲": [T: "schwarz eingekreiste achtzehn"] # 0x24f2 (en: 'black circled eighteen', google translation)
+ - "⓳": [T: "schwarz eingekreiste neunzehn"] # 0x24f3 (en: 'black circled nineteen', google translation)
+ - "⓴": [T: "schwarz eingekreiste zwanzig"] # 0x24f4 (en: 'black circled twenty', google translation)
+ - "⓵-⓽": # 0x24f5 - 0x24fe
+ - T: "doppelt umkreist" # (en: 'double circled', google translation)
+ - spell: "translate('.', '⓵⓶⓷⓸⓹⓺⓻⓼⓽', '123456789')"
+ - "⓾": [T: "doppelt umgekreiste zehn"] # 0x24fe (en: 'double circled ten', google translation)
+ - "⓿": [T: "schwarz eingekreiste null"] # 0x24ff (en: 'black circled zero', google translation)
+ - "■": [T: "Schwarzes Quadrat"] # 0x25a0 (en: 'black square', MathPlayer: 'black square', google: 'schwarzes quadrat')
+ - "□": [T: "Weißes Quadrat"] # 0x25a1 (en: 'white square', MathPlayer: 'white square', google: 'weißes quadrat')
+ - "▢": [T: "Weißes Quadrat mit abgerundeten Ecken"] # 0x25a2 (en: 'white square with rounded corners', google: 'weißes quadrat mit abgerundeten ecken')
+ - "▣": [T: "Weißes Quadrat, das schwarzes kleines Quadrat enthält"] # 0x25a3 (en: 'white square containing small black square', google: 'weißes quadrat mit kleinem schwarzem quadrat')
+ - "▤": [T: "Quadrat mit horizontaler Füllung"] # 0x25a4 (en: 'square with horizontal fill', google: 'quadrat mit horizontaler füllung')
+ - "▥": [T: "Quadrat mit vertikaler Füllung"] # 0x25a5 (en: 'square with vertical fill', google: 'quadrat mit vertikaler füllung')
+ - "▦": [T: "Quadrat mit orthogonaler Schraffurfüllung"] # 0x25a6 (en: 'square with orthogonal crosshatch fill', google: 'quadrat mit orthogonaler kreuzungsfüllung')
+ - "▧": [T: "Quadrat mit Füllung von oben links nach rechts unten"] # 0x25a7 (en: 'square with upper left to lower right fill', google: 'quadratisch mit oberen links nach unten rechts füllung')
+ - "▨": [T: "Quadrat mit Füllung von oben recht nach links unten"] # 0x25a8 (en: 'square with upper right to lower left fill', google: 'quadrat mit der oberen rechten linken füllung')
+ - "▩": [T: "Quadrat mit diagonaler Schraffurfüllung"] # 0x25a9 (en: 'square with diagonal crosshatch fill', google: 'quadrat mit diagonaler kreuzungsfüllung')
+ - "▪": [T: "Schwarzes kleines Quadrat"] # 0x25aa (en: 'black small square', MathPlayer: 'black square', google: 'schwarzes kleines quadrat')
+ - "▫": [T: "Weißes kleines Quadrat"] # 0x25ab (en: 'white small square', MathPlayer: 'white square', google: 'weißes kleines quadrat')
+ - "▬": [T: "Schwarzes Rechteck"] # 0x25ac (en: 'black rectangle', google: 'schwarzes rechteck')
+ - "▭": [T: "Weißes Rechteck"] # 0x25ad (en: 'white rectangle', MathPlayer: 'white rectangle', google: 'weißes rechteck')
+ - "▮": [T: "Schwarzes vertikales Rechteck"] # 0x25ae (en: 'black vertical rectangle', MathPlayer: 'black vertical rectangle', google: 'schwarzes vertikales rechteck')
+ - "▯": [T: "Weißes vertikales Rechteck"] # 0x25af (en: 'white vertical rectangle', MathPlayer: 'white vertical rectangle', google: 'weißes vertikales rechteck')
+ - "▰": [T: "Schwarzes Parallelogramm"] # 0x25b0 (en: 'black parallelogram', google: 'schwarzes parallelogramm')
+ - "▱": [T: "Weißes Parallelogramm"] # 0x25b1 (en: 'white parallelogram', MathPlayer: 'white parallelogram', google: 'weißes parallelogramm')
+ - "▲": [T: "Schwarzes nach oben zeigendes Dreieck"] # 0x25b2 (en: 'black up pointing triangle', MathPlayer: 'black up pointing triangle', google: 'schwarz nach oben zeigt dreieck')
+ - "△": [T: "Weißes nach oben zeigendes Dreieck"] # 0x25b3 (en: 'white up pointing triangle', MathPlayer: 'white up pointing triangle', google: 'weiß nach oben zeigendreieck')
+ - "▴": [T: "Schwarzes nach oben zeigendes kleines Dreieck"] # 0x25b4 (en: 'black up pointing small triangle', MathPlayer: 'black up pointing triangle', google: 'schwarz nach oben zeigt ein kleines dreieck')
+ - "▵": [T: "Weißes nach oben zeigendes kleines Dreieck"] # 0x25b5 (en: 'white up pointing small triangle', MathPlayer: 'white up pointing triangle', google: 'weiß nach oben zeigt ein kleines dreieck')
+ - "▶": [T: "Schwarzes nach rechts zeigendes Dreieck"] # 0x25b6 (en: 'black right pointing triangle', MathPlayer: 'black right pointing triangle', google: 'schwarzes rechte dreieck')
+ - "▷": [T: "Weißes nach rechts zeigendes Dreieck"] # 0x25b7 (en: 'white right pointing triangle', MathPlayer: 'white right pointing triangle', google: 'weißes rechtes dreieck')
+ - "▸": [T: "Schwarzes nach rechts zeigendes kleines Dreieck"] # 0x25b8 (en: 'black right pointing small triangle', MathPlayer: 'black right pointing triangle', google: 'schwarzer rechts kleines dreieck')
+ - "▹": [T: "Weißes nach rechts zeigendes kleines Dreieck"] # 0x25b9 (en: 'white right pointing small triangle', MathPlayer: 'right pointing triangle', google: 'weißer rechts kleines dreieck')
+ - "►": [T: "Schwarzer nach rechts zeigender Zeiger"] # 0x25ba (en: 'black right pointing pointer', google: 'schwarzer rechter zeiger')
+ - "▻": [T: "Weißer nach rechts zeigender Zeiger"] # 0x25bb (en: 'white right pointing pointer', google: 'weißer rechts zeiger')
+ - "▼": [T: "Schwarzes Abwärtsdreieck"] # 0x25bc (en: 'black down pointing triangle', MathPlayer: 'black down pointing triangle', google: 'schwarzes down -dreieck')
+ - "▽": [T: "Weißes Abwärtsdreieck"] # 0x25bd (en: 'white down pointing triangle', MathPlayer: 'white down pointing triangle', google: 'weiß down dreieck')
+ - "▾": [T: "Schwarzes kleines Abwärtsdreieck"] # 0x25be (en: 'black down pointing small triangle', MathPlayer: 'black down pointing triangle', google: 'schwarz unten zeigt ein kleines dreieck')
+ - "▿": [T: "Weißes kleines Abwärtsdreieck"] # 0x25bf (en: 'white down pointing small triangle', MathPlayer: 'white down pointing triangle', google: 'weiß down zeigt kleines dreieck')
+ - "◀": [T: "Schwarzes nach links zeigendes Dreieck"] # 0x25c0 (en: 'black left pointing triangle', MathPlayer: 'black left pointing triangle', google: 'schwarzes linker dreieck')
+ - "◁": [T: "Weißes nach links zeigendes Dreieck"] # 0x25c1 (en: 'white left pointing triangle', MathPlayer: 'white left pointing triangle', google: 'weißes linker dreieck')
+ - "◂": [T: "Schwarzes nach links zeigendes kleines Dreieck"] # 0x25c2 (en: 'black left pointing small triangle', MathPlayer: 'black left pointing triangle', google: 'schwarz links zeigt ein kleines dreieck')
+ - "◃": [T: "Weißes nach links zeigendes kleines Dreieck"] # 0x25c3 (en: 'white left pointing small triangle', MathPlayer: 'white left pointing triangle', google: 'weiß links kleines dreieck')
+ - "◄": [T: "Schwarzer nach links zeigender Zeiger"] # 0x25c4 (en: 'black left pointing pointer', MathPlayer: 'black left pointing pointer', google: 'schwarzer links zeigter zeiger')
+ - "◅": [T: "Weißer nach links zeigender Zeiger"] # 0x25c5 (en: 'white left pointing pointer', MathPlayer: 'white left pointing pointer', google: 'weißer links zeiger zeiger')
+ - "◆": [T: "Schwarzer Diamant"] # 0x25c6 (en: 'black diamond', MathPlayer: 'black diamond', google: 'schwarzer diamant')
+ - "◇": [T: "Weißer Diamant"] # 0x25c7 (en: 'white diamond', MathPlayer: 'white diamond', google: 'weißer diamant')
+ - "◈": [T: "Weißer Diamant mit schwarzem kleinem Diamant"] # 0x25c8 (en: 'white diamond containing black small diamond', MathPlayer: 'white diamond containing black diamond', google: 'weißer diamant mit schwarzem kleinem diamanten')
+ - "◉": [T: "Fischauge"] # 0x25c9 (SRE: 'Fischauge')
+ - "◊": [T: "Raute"] # 0x25ca (en: 'lozenge', MathPlayer: 'lozenge', google: 'pastille')
+ - "○": [T: "Weißer Kreis"] # 0x25cb (en: 'white circle', MathPlayer: 'white circle', google: 'weißer kreis')
+ - "◌": [T: "Gepunkteter weißer Kreis"] # 0x25cc (en: 'dotted circle', MathPlayer: 'dotted circle', google: 'gepunkteter kreis')
+ - "◍": [T: "Kreis mit vertikaler Füllung"] # 0x25cd (en: 'circle with vertical fill', MathPlayer: 'circle with vertical fill', google: 'kreis mit vertikaler füllung')
+ - "◎": [T: "Volltreffer"] # 0x25ce (SRE: 'Bullseye')
+ - "●": [T: "Schwarzer Kreis"] # 0x25cf (en: 'black circle', MathPlayer: 'black circle', google: 'schwarzer kreis')
+ - "◐": [T: "Kreis mit linker Hälfte schwarz"] # 0x25d0 (en: 'circle with left half black', MathPlayer: 'circle with left half black', google: 'kreis mit dem linken halben schwarz')
+ - "◑": [T: "Kreis mit rechter Hälfte schwarz"] # 0x25d1 (en: 'circle with right half black', MathPlayer: 'circle with right half black', google: 'kreis mit dem rechten halb schwarz')
+ - "◒": [T: "Kreis mit unterer Hälfte schwarz"] # 0x25d2 (en: 'circle with lower half black', MathPlayer: 'circle with lower half black', google: 'kreis mit unterer halb schwarz')
+ - "◓": [T: "Kreis mit oberer Hälfte schwarz"] # 0x25d3 (en: 'circle with upper half black', MathPlayer: 'circle with upper half black', google: 'kreis mit der oberen hälfte schwarz')
+ - "◔": [T: "Kreis mit oberem rechten Quadranten schwarz"] # 0x25d4 (en: 'circle with upper right quadrant black', MathPlayer: 'circle with upper right quadrant black', google: 'kreis mit dem oberen rechten quadranten schwarz')
+ - "◕": [T: "Kreis mit ganzem oberen linken Quadranten schwarz"] # 0x25d5 (en: 'circle with all but upper left quadrant black', MathPlayer: 'circle with all but upper left quadrant black', google: 'kreisen sie mit allen außer oberen linken quadranten schwarz')
+ - "◖": [T: "Linker halber schwarzer Kreis"] # 0x25d6 (en: 'left half black circle', MathPlayer: 'left half black circle', google: 'links halb schwarzer kreis')
+ - "◗": [T: "rechter halber schwarzer Kreis"] # 0x25d7 (en: 'right half black circle', MathPlayer: 'right half black circle', google: 'rechte halbe schwarze kreis')
+ - "◘": [T: "Inverse Kugel"] # 0x25d8 (en: 'inverse bullet', MathPlayer: 'inverse bullet', google: 'inverse kugel')
+ - "◙": [T: "Inverser weißer Kreis"] # 0x25d9 (en: 'inverse white circle', MathPlayer: 'inverse white circle', google: 'inverser weißer kreis')
+ - "◚": [T: "Umgekehrter weißer Kreis der oberen Hälfte"] # 0x25da (en: 'upper half inverse white circle', MathPlayer: 'upper half inverse white circle', google: 'inverse weißer kreis der oberen hälfte')
+ - "◛": [T: "Umgekehrter weißer Kreis der unteren Hälfte"] # 0x25db (en: 'lower half inverse white circle', MathPlayer: 'lower half inverse white circle', google: 'untere hälfte inverser weißer kreis')
+ - "◜": [T: "Kreisbogen im oberen linken Quadranten"] # 0x25dc (en: 'upper left quadrant circular arc', MathPlayer: 'upper left quadrant circular arc', google: 'oberer linker quadrantenkreisbogen')
+ - "◝": [T: "Kreisbogen im oberen rechten Quadranten"] # 0x25dd (en: 'upper right quadrant circular arc', MathPlayer: 'upper right quadrant circular arc', google: 'oberer rechter quadrant kreisbogen')
+ - "◞": [T: "Kreisbogen im rechten unteren Quadranten"] # 0x25de (en: 'lower right quadrant circular arc', MathPlayer: 'lower right quadrant circular arc', google: 'unterer rechts quadrant zirkularbogen')
+ - "◟": [T: "Kreisbogen im unteren linken Quadranten"] # 0x25df (en: 'lower left quadrant circular arc', MathPlayer: 'lower left quadrant circular arc', google: 'unterer linker quadrantenkreisbogen')
+ - "◠": [T: "Oberer Halbkreis"] # 0x25e0 (en: 'upper half circle', MathPlayer: 'upper half circle', google: 'oberer halbkreis')
+ - "◡": [T: "Unterer Halbkreis"] # 0x25e1 (en: 'lower half circle', MathPlayer: 'lower half circle', google: 'unterer halbkreis')
+ - "◢": [T: "Schwarzes unteres rechtes Dreieck"] # 0x25e2 (en: 'black lower right triangle', MathPlayer: 'black lower right triangle', google: 'schwarz unten rechts dreieck')
+ - "◣": [T: "Schwarzes unteres linkes Dreieck"] # 0x25e3 (en: 'black lower left triangle', MathPlayer: 'black lower left triangle', google: 'schwarzes unteres linke dreieck')
+ - "◤": [T: "Schwarzes oberes linkes Dreieck"] # 0x25e4 (en: 'black upper left triangle', MathPlayer: 'black upper left triangle', google: 'schwarzes oberes linksdreieck')
+ - "◥": [T: "Schwarzes oberes rechtes Dreieck"] # 0x25e5 (en: 'black upper right triangle', MathPlayer: 'black upper right triangle', google: 'schwarzes oberes rechtes dreieck')
+ - "◦": [T: "Weiße Kugel"] # 0x25e6 (en: 'composition', MathPlayer: 'composition', google: 'komposition')
+ - "◧": [T: "Quadrat mit linker Hälfte schwarz"] # 0x25e7 (en: 'square with left half black', MathPlayer: 'square with left half black', google: 'quadrat mit linksem halb schwarz')
+ - "◨": [T: "Quadrat mit rechter Hälfte schwarz"] # 0x25e8 (en: 'square with right half black', MathPlayer: 'square with right half black', google: 'quadrat mit dem rechten halben schwarz')
+ - "◩": [T: "Quadrat mit der oberen linken Diagonalenhälfte schwarz"] # 0x25e9 (en: 'square with upper left half black', MathPlayer: 'square with upper left half black', google: 'quadrat mit oberen linken halben schwarz')
+ - "◪": [T: "Quadrat mit unterer rechter Diagonalhälfte schwarz"] # 0x25ea (en: 'square with lower right half black', MathPlayer: 'square with lower right half black', google: 'quadratisch mit unterer rechter halb schwarz')
+ - "◫": [T: "Weißes Quadrat mit senkrechter Linie"] # 0x25eb (en: 'white square with bisecting line', MathPlayer: 'white square with bisecting line', google: 'weißes quadrat mit halbierender linie')
+ - "◬": [T: "Weißes nach oben zeigendes Dreieck mit Punkt"] # 0x25ec (en: 'white up pointing triangle with dot', MathPlayer: 'white up pointing triangle with dot', google: 'weiß nach oben zeigte dreieck mit punkt')
+ - "◭": [T: "Aufwärtszeigendes Dreieck mit linker Hälfte schwarz"] # 0x25ed (en: 'up pointing triangle with left half black', MathPlayer: 'up pointing triangle with left half black', google: 'dreieck mit dem linken halben schwarz zeigen')
+ - "◮": [T: "Aufwärtszeigendes Dreieck mit rechter Hälfte schwarz"] # 0x25ee (en: 'up pointing triangle with right half black', MathPlayer: 'up pointing triangle with right half black', google: 'dreieck mit dem rechten halben schwarz zeigen')
+ - "◯": [T: "Großer Kreis"] # 0x25ef (en: 'large circle', MathPlayer: 'large circle', google: 'großer kreis')
+ - "◰": [T: "Weißes Quadrat mit kleinem Quadrat im oberem linken Quadranten"] # 0x25f0 (en: 'white square with upper left quadrant', google: 'weißes quadrat mit oberen linken quadrant')
+ - "◱": [T: "Weißes Quadrat mit kleinem Quadrat im unterem linken Quadranten"] # 0x25f1 (en: 'white square with lower left quadrant', google: 'weißes quadrat mit unteren linken quadranten')
+ - "◲": [T: "Weißes Quadrat mit kleinem Quadrat im unterem rechten Quadranten"] # 0x25f2 (en: 'white square with lower right quadrant', google: 'weißes quadrat mit unten rechts quadrant')
+ - "◳": [T: "Weißes Quadrat mit kleinem Quadrat im rechtem oberen Quadranten"] # 0x25f3 (en: 'white square with upper right quadrant', google: 'weißes quadrat mit oberen rechten quadrant')
+ - "◴": [T: "Weißer Kreis mit kleinem Kreis im oberem linkem Quadranten"] # 0x25f4 (en: 'white circle with upper left quadrant', google: 'weißer kreis mit oberen linken quadrant')
+ - "◵": [T: "Weißer Kreis mit kleinem Kreis im unterem linken Quadranten"] # 0x25f5 (en: 'white circle with lower left quadrant', google: 'weißer kreis mit unteren linken quadranten')
+ - "◶": [T: "Weißer Kreis mit kleinem Kreis im unterem rechten Quadranten"] # 0x25f6 (en: 'white circle with lower right quadrant', google: 'weißer kreis mit unten rechts quadrant')
+ - "◷": [T: "Weißer Kreis mit kleinem Kreis im rechtem oberen Quadranten"] # 0x25f7 (en: 'white circle with upper right quadrant', google: 'weißer kreis mit oben rechts quadrant')
+ - "◸": [T: "Oberes linkes Dreieck"] # 0x25f8 (en: 'upper left triangle', MathPlayer: 'upper left triangle', google: 'oberes linker dreieck')
+ - "◹": [T: "Oberes rechtes Dreieck"] # 0x25f9 (en: 'upper right triangle', MathPlayer: 'upper right triangle triangle', google: 'ober rechtes dreieck')
+ - "◺": [T: "Unteres linkes Dreieck"] # 0x25fa (en: 'lower left triangle', MathPlayer: 'lower left triangle', google: 'unteres linker dreieck')
+ - "◻": [T: "Weißes mittleres Quadrat"] # 0x25fb (en: 'white medium square', MathPlayer: 'white medium square', google: 'weißes mittleres quadrat')
+ - "◼": [T: "Schwarzes mittleres kleines Quadrat"] # 0x25fc (en: 'black medium square', MathPlayer: 'black medium square', google: 'schwarzes mittleres quadrat')
+ - "◽": [T: "Weißes mittleres Quadrat"] # 0x25fd (en: 'white medium small square', MathPlayer: 'white medium square', google: 'weißes mittleres kleines quadrat')
+ - "◾": [T: "Schwarzes mittleres Quadrat"] # 0x25fe (en: 'black medium small square', MathPlayer: 'black medium square', google: 'schwarzes mittel kleiner quadrat')
+ - "◿": [T: "Unteres rechtes Dreieck"] # 0x25ff (en: 'lower right triangle', MathPlayer: 'lower right triangle', google: 'unten rechts dreieck')
+ - "♠": [T: "schwarzes Piksymbol"] # 0x2660 (google: 'schwarzer spatenanzug')
+ - "♡": [T: "weißes Herz"] # 0x2661 (google: 'weißer herzanzug')
+ - "♢": [T: "weißes Karo"] # 0x2662 (google: 'weißer diamantanzug')
+ - "♣": [T: "schwarzes Kreuzsymbol"] # 0x2663 (google: 'schwarzer clubanzug')
+ - "♤": [T: "weißes Piksymbol"] # 0x2664 (google: 'weißer spatenanzug')
+ - "♥": [T: "schwarzes Herz"] # 0x2665 (google: 'schwarzer herzanzug')
+ - "♦": [T: "schwarzes Karo"] # 0x2666 (google: 'schwarzer diamantanzug')
+ - "♧": [T: "weißes Kreuzsymbol"] # 0x2667 (google: 'weißer clubanzug')
+ - "❨": [T: "Mittlere linke Klammerverzierung"] # 0x2768 (en: 'medium left parentheses ornament', google: 'mittel linke klammern')
+ - "❩": [T: "Mittlere rechte Klammerverzierung"] # 0x2769 (en: 'medium right parentheses ornament', google: 'mittel rechts klammernsthesis ornament')
+ - "❪": [T: "Mittlere abgeflachte linke Klammerverzierung"] # 0x276a (en: 'medium flattened left parentheses ornament', google: 'medium abgeflachtes linker klammern')
+ - "❫": [T: "Mittlere abgeflachte rechte Klammerverzierung"] # 0x276b (en: 'medium flattened right parentheses ornament', google: 'mittel abgeflacht rechte klammerthese -ornament')
+ - "❬": [T: "Mittlere nach links weisende Winkelhalterung"] # 0x276c (en: 'medium left-pointing angle bracket ornament', google: 'mittelgroße linkswinkel-klammerverzierung')
+ - "❭": [T: "Mittlere, rechtwinklige Winkelhalterung"] # 0x276d (en: 'medium right-pointing angle bracket ornament', google: 'mittel mit dem rechten zeigungswinkelhalterung')
+ - "❮": [T: "Dickes nach links weisendes Anführungszeichen"] # 0x276e (en: 'heavy left-pointing angle quotation mark ornament', google: 'schwerer zitat für den linken zeigungswinkel mark ornament')
+ - "❯": [T: "Dickes nach links weisendes Anführungszeichen"] # 0x276f (en: 'heavy right-pointing angle quotation mark ornament', google: 'schwerer rechts zeigter winkel zitat mark ornament')
+ - "❰": [T: "schweres, nach links zeigendes eckiges Klammerornament"] # 0x2770 (en: 'heavy left-pointing angle bracket ornament', google: 'schwere linkswinkel-halterung')
+ - "❱": [T: "schweres, nach rechts zeigendes eckiges Klammerornament"] # 0x2771 (en: 'heavy right-pointing angle bracket ornament', google: 'schwere rechtshalterung mit rechts zeigter winkel')
+ - "❲": [T: "Leichte Halterung aus Schildpatt, links"] # 0x2772 (en: 'light left tortoise shell bracket ornament', google: 'leichte linke schildkröte -hülle -halterung')
+ - "❳": [T: "Leichte Halterung aus Schildpatt, rechts"] # 0x2773 (en: 'light right tortoise shell bracket ornament', google: 'leichte rechte schildkröte -hülle -halterung')
+ - "❴": [T: "Mittlere linke geschweifte Klammerverzierung"] # 0x2774 (en: 'medium left brace ornament', google: 'medium linke klammerverzierung')
+ - "❵": [T: "Mittlere rechte geschweifte Klammerverzierung"] # 0x2775 (en: 'medium right brace ornament', google: 'mittlere rechte klammerverzierung')
+ - "❶": [T: "schwarz umkreiste eins"] # 0x2776 (en: 'black circled one', google translation)
+ - "❷": [T: "schwarz umkreiste zwei"] # 0x2777 (en: 'black circled two', google translation)
+ - "❸": [T: "schwarz umkreiste drei"] # 0x2778 (en: 'black circled three', google translation)
+ - "❹": [T: "schwarz umkreiste vier"] # 0x2779 (en: 'black circled four', google translation)
+ - "❺": [T: "schwarz umkreiste fünf"] # 0x277a (en: 'black circled five', google translation)
+ - "❻": [T: "schwarz umkreiste sechs"] # 0x277b (en: 'black circled six', google translation)
+ - "❼": [T: "schwarz umkreiste sieben"] # 0x277c (en: 'black circled seven', google translation)
+ - "❽": [T: "schwarz umumkreist nach"] # 0x277d (en: 'black circled eight', google translation)
+ - "❾": [T: "schwarz umreiste neun"] # 0x277e (en: 'black circled nine', google translation)
+ - "❿": [T: "schwarz umkreiste zehn"] # 0x277f (en: 'black circled ten', google translation)
+ - "➀": [T: "umkreiste eins ohne serife"] # 0x2780 (en: 'circled sans serif one', google translation)
+ - "➁": [T: "umkreiste zwei ohne serife"] # 0x2781 (en: 'circled sans serif two', google translation)
+ - "➂": [T: "umkreiste drei hne serife "] # 0x2782 (en: 'circled sans serif three', google translation)
+ - "➃": [T: "umkreiste vier ohne serife"] # 0x2783 (en: 'circled sans serif four', google translation)
+ - "➄": [T: "umkreite fünf ohne serife"] # 0x2784 (en: 'circled sans serif five', google translation)
+ - "➅": [T: "umkreiste sechs ohne serife"] # 0x2785 (en: 'circled sans serif six', google translation)
+ - "➆": [T: "umkreiste sieben ohne serife"] # 0x2786 (en: 'circled sans serif seven', google translation)
+ - "➇": [T: "umkreiste acht ohne serife"] # 0x2787 (en: 'circled sans serif eight', google translation)
+ - "➈": [T: "umkreiste neun ohne serife"] # 0x2788 (en: 'circled sans serif nine', google translation)
+ - "➉": [T: "umkreiste zehn ohne serife"] # 0x2789 (en: 'circled sans serif ten', google translation)
+ - "➊": [T: "schwarz umkreiste eins ohne serife"] # 0x278a (en: 'black circled sans serif one', google translation)
+ - "➋": [T: "schwarz umkreiste zwei ohne serife"] # 0x278b (en: 'black circled sans serif two', google translation)
+ - "➌": [T: "schwarz umkreiste drei ohne serife"] # 0x278c (en: 'black circled sans serif three', google translation)
+ - "➍": [T: "schwarz umkreiste vier ohne serife"] # 0x278d (en: 'black circled sans serif four', google translation)
+ - "➎": [T: "schwarz umkreiste fünf ohne serife"] # 0x278e (en: 'black circled sans serif five', google translation)
+ - "➏": [T: "schwarz umkreiste sechs ohne serife"] # 0x278f (en: 'black circled sans serif six', google translation)
+ - "➐": [T: "schwarz umkreiste sieben ohne serife"] # 0x2790 (en: 'black circled sans serif seven', google translation)
+ - "➑": [T: "schwarz umkreiste acht ohne serife "] # 0x2791 (en: 'black circled sans serif eight', google translation)
+ - "➒": [T: "schwarz umkreiste neun ohne serife"] # 0x2792 (en: 'black circled sans serif nine', google translation)
+ - "➓": [T: "schwarz umkreiste zehn ohne serife"] # 0x2793 (en: 'black circled sans serif ten', google translation)
+ - "➔": [T: "Schwerer, breitköpfiger nach rechts gerichteter Pfeil"] # 0x2794 (en: 'heavy wide-headed rightwards arrow', google: 'schwerer breiter arrow')
+ - "➕": [T: "dickes großes Pluszeichen"] # 0x2795 (en: 'heavy plus sign', google: 'schweres pluszeichen')
+ - "➖": [T: "dickes großes Minuszeichen"] # 0x2796 (en: 'heavy minus sign', google: 'schweres minuszeichen')
+ - "➗": [T: "dickes großes Divisionszeichen"] # 0x2797 (en: 'heavy division sign', google: 'schweres divisionszeichen')
+ - "➘": [T: "Starker Südostpfeil"] # 0x2798 (en: 'heavy south east arrow', google: 'schwerer südostpfeil')
+ - "➙": [T: "Starker Pfeil nach rechts"] # 0x2799 (en: 'heavy rightwards arrow', google: 'schwerer rechts pfeil')
+ - "➚": [T: "Starker Nordostpfeil"] # 0x279a (en: 'heavy north east arrow', google: 'schwerer nordostpfeil')
+ - "➛": [T: "Zeichnungszeichen Pfeil nach rechts"] # 0x279b (en: 'drafting point rightwards arrow', google: 'ausgangspunkt rechts von pfeil')
+ - "➜": [T: "Starker Pfeil mit runder Spitze nach rechts"] # 0x279c (en: 'heavy round-tipped rightwards arrow', google: 'schwerer pfeil nach rechts')
+ - "➝": [T: "Dreieckköpfiger Pfeil nach rechts"] # 0x279d (en: 'triangle-headed rightwards arrow', google: 'dreieck köpfig mit rechtsem pfeil')
+ - "➞": [T: "Schwerer Dreieckspfeil nach rechts"] # 0x279e (en: 'heavy triangle-headed rightwards arrow', google: 'schwerer pfeil mit dreieck-köpfen')
+ - "➟": [T: "Dicker Pfeil nach rechts"] # 0x279f (en: 'dashed triangle-headed rightwards arrow', google: 'dreieck köpfig nach rechtsem pfeil')
+ - "➠": [T: "Dicker, gestrichelter Dreieckspfeil nach rechts"] # 0x27a0 (en: 'heavy dashed triangle-headed rightwards arrow', google: 'schwerer, geschnittenes dreieck-köpfiger pfeil nach rechts')
+ - "➡": [T: "Dicker Pfeil nach rechts"] # 0x27a1 (en: 'black rightwards arrow', google: 'schwarzer pfeil nach rechts')
+ - "➢": [T: "Dreidimensionale, nach oben beleuchtete Pfeilspitze nach rechts"] # 0x27a2 (en: 'three d top lighted rightwards arrow', google: 'drei d top leuchtet nach rechts')
+ - "➣": [T: "Dreidimensionale, von unten beleuchtete Pfeilspitze nach rechts"] # 0x27a3 (en: 'three d bottom lighted rightwards arrow', google: 'drei d bottom beleuchtet nach rechts')
+ - "➤": [T: "Schwarze Pfeilspitze nach rechts"] # 0x27a4 (en: 'black rightwards arrowhead', google: 'schwarz rechts pfeilspitze')
+ - "➥": [T: "Schwerer schwarzer Pfeil nach unten und rechts gebogen"] # 0x27a5 (en: 'heavy black curved downwards and rightwards arrow', google: 'schwerer schwarz gebrüht nach unten und rechts pfeil')
+ - "➦": [T: "Schwerer schwarzer Pfeil nach oben und rechts gebogen"] # 0x27a6 (en: 'heavy black curved upwards and rightwards arrow', google: 'schwerer schwarz nach oben gebogen und rechts pfeil')
+ - "➧": [T: "Schwarzer kurzer nach rechts gerichteter Pfeil"] # 0x27a7 (en: 'squat black rightwards arrow', google: 'hocke black rightwards pfeil')
+ - "➨": [T: "Schwerer konkaver Spitze-Pfeil nach rechts"] # 0x27a8 (en: 'heavy concave-pointed black rightwards arrow', google: 'schwerer konkavspunkter schwarzer pfeil nach rechts')
+ - "➩": [T: "Rechts geschatteter weißer Pfeil nach rechts"] # 0x27a9 (en: 'right-shaded white rightwards arrow', google: 'right shaded white rightwards pfeil')
+ - "➪": [T: "Links schattierter weißer Pfeil nach rechts"] # 0x27aa (en: 'left-shaded white rightwards arrow', google: 'linksschattierte weiße pfeil nach rechts')
+ - "➫": [T: "Zurückgekippter, beschatteter weißer Pfeil nach rechts"] # 0x27ab (en: 'back-tilted shadowed white rightwards arrow', google: 'rückgedünnter weißer weißer pfeil nach rechts')
+ - "➬": [T: "Vorne geneigter, beschatteter weißer Pfeil nach rechts"] # 0x27ac (en: 'front-tilted shadowed white rightwards arrow', google: 'frontgeflodeltes weißer weißer pfeil nach rechts')
+ - "➭": [T: "Schwerer unterer rechter Schatten mit weißem Pfeil nach rechts"] # 0x27ad (en: 'heavy lower right-shadowed white rightwards arrow', google: 'schwere, rechte schatten mit weißem recht nach rechts')
+ - "➮": [T: "Schwerer oberer rechter Schatten mit weißem Pfeil nach rechts"] # 0x27ae (en: 'heavy upper right-shadowed white rightwards arrow', google: 'schwere obere rechte schattenhafte weiße rechts pfeil')
+ - "➯": [T: "Unten gekerbter Pfeil nach rechts"] # 0x27af (en: 'notched lower right-shadowed white rightwards arrow', google: 'gekerbte rechte rechten weißen pfeil nach rechts')
+ - "➱": [T: "Uben gekerbter Pfeil nach rechts"] # 0x27b1 (en: 'notched upper right-shadowed white rightwards arrow', google: 'gekerbte obere rechte schattenhafte weiße pfeil nach rechts')
+ - "➲": [T: "Eingekreister schwerer weißer Pfeil nach rechts"] # 0x27b2 (en: 'circled heavy white rightwards arrow', google: 'umgekreist schweren weißen pfeil nach rechts')
+ - "➳": [T: "Pfeil mit weißer Feder nach rechts"] # 0x27b3 (en: 'white-feathered rightwards arrow', google: 'weiß gefiederter pfeil nach rechts')
+ - "➴": [T: "Schwarz-gefiederter Südostpfeil"] # 0x27b4 (en: 'black-feathered south east arrow', google: 'schwarz gefiederter südöstlicher pfeil')
+ - "➵": [T: "chwarz-gefiederter Pfeil nach rechts"] # 0x27b5 (en: 'black-feathered rightwards arrow', google: 'schwarz gefiederter pfeil nach rechts')
+ - "➶": [T: "Schwarzgefiederter Nordostpfeil"] # 0x27b6 (en: 'black-feathered north east arrow', google: 'schwarz gefiederter nordostpfeil')
+ - "➷": [T: "Schwerer schwarzgefiederter Südostpfeil"] # 0x27b7 (en: 'heavy black-feathered south east arrow', google: 'schwerer schwarz gefiederter südostpfeil')
+ - "➸": [T: "Schwarzgefiederter Pfeil nach rechts"] # 0x27b8 (en: 'heavy black-feathered rightwards arrow', google: 'schwerer schwarz gefiederter pfeil nach rechts')
+ - "➹": [T: "Schwarzgefiederter Nordostpfeil"] # 0x27b9 (en: 'heavy black-feathered north east arrow', google: 'schwerer schwarz gefiederter nordostpfeil')
+ - "➺": [T: "Teradrop-Pfeil nach rechts mit Haken"] # 0x27ba (en: 'teradrop-barbed rightwards arrow', google: 'teradrop-barded mit rechtsem pfeil')
+ - "➻": [T: "Schwerer Pfeil mit tropfenförmigem Schaft, nach rechts gebogen"] # 0x27bb (en: 'heavy teardrop-shanked rightwards arrow', google: 'schwere tränenverschiebung nach rechts pfeil')
+ - "➼": [T: "Keilförmiger Pfeil nach rechts"] # 0x27bc (en: 'wedge-tailed rightwards arrow', google: 'keilschwanz rechts pfeil')
+ - "➽": [T: "Schwerer, nach rechts gekeilter Pfeil"] # 0x27bd (en: 'heavy wedge-tailed rightwards arrow', google: 'schwerer keilschwanz rechts pfeil')
+ - "➾": [T: "Offener Pfeil nach rechts"] # 0x27be (en: 'open-outlined rightwards arrow', google: 'open-out-line-rightwards-pfeil')
+ - "⟀": [T: "Dreidimensionaler Winkel"] # 0x27c0 (en: 'three dimensional angle', MathPlayer: 'three dimensional angle', google: 'dreidimensionaler winkel')
+ - "⟁": [T: "Weißes Dreieck, das ein kleines weißes Dreieck enthält"] # 0x27c1 (en: 'white triangle containing small white triangle', MathPlayer: 'white triangle containing small white triangle', google: 'weißes dreieck mit einem kleinen weißen dreieck')
+ - "⟂": # 0x27c2
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "Aufrecht" # (en: 'perpendicular to', MathPlayer: 'perpendicular', google: 'senkrecht zu')
+ - "⟃": # 0x27c3
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "Subset öffnen" # (en: 'an open subset of', MathPlayer: 'open subset', google: 'eine offene teilmenge von')
+ - "⟄": # 0x27c4
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "Superset öffnen" # (en: 'an open superset of', MathPlayer: 'open superset', google: 'ein offenes superet von')
+ - "⟅": [T: "Linker S-förmiger Taschenbegrenzer"] # 0x27c5 (en: 'left s-shaped bag delimiter', MathPlayer: 'left s-shaped bag delimiter', google: 'links s-förmiger tasche gremiter')
+ - "⟆": [T: "rechter S-förmiger Taschenbegrenzer"] # 0x27c6 (en: 'right s-shaped bag delimiter', MathPlayer: 'right s-shaped bag delimiter', google: 'rechte s-förmige tasche grenzwerbung')
+ - "⟇": [T: "Oder mit innerem Punkt"] # 0x27c7 (en: 'or with dot inside', MathPlayer: 'or with dot inside', google: 'oder mit punkt im inneren')
+ - "⟈": [T: "Umgekehrter Schrägstrich Vorhergehender Teilsatz"] # 0x27c8 (en: 'reverse solidus preceding subset', MathPlayer: 'back slash preceeding subset', google: 'reverse solidus vor der untergruppe')
+ - "⟉": [T: "Superset Vorgänger Schrägstrich"] # 0x27c9 (en: 'superset preceding solidus', MathPlayer: 'superset preceeding slash', google: 'superset vor solidus')
+ - "⟊": [T: "Vertikaler Balken mit horizontalem Hub"] # 0x27ca (en: 'vertical bar with horizontal stroke', MathPlayer: 'vertical bar with horizontal stroke', google: 'vertikale balken mit horizontalem schlaganfall')
+ - "⟋": [T: "Mathematische aufsteigende Diagonale"] # 0x27cb (en: 'mathematical rising diagonal', google: 'mathematische steigende diagonale')
+ - "⟌": [T: "Lange Abteilung"] # 0x27cc (en: 'long division', MathPlayer: 'long division', google: 'lange division')
+ - "⟍": [T: "Mathematische fallende Diagonale"] # 0x27cd (en: 'mathematical falling diagonal', google: 'mathematische fallende diagonale')
+ - "⟎": [T: "quadratisches und"] # 0x27ce (en: 'squared logical and', google: 'quadratisch logisch und')
+ - "⟏": [T: "quadratisches oder"] # 0x27cf (en: 'squared logical or', google: 'quadratisch logisch oder')
+ - "⟐": [T: "Weißer Diamant mit zentriertem Punkt"] # 0x27d0 (en: 'white diamond with centered dot', google: 'weißer diamant mit zentriertem punkt')
+ - "⟑": [T: "Und mit Punkt"] # 0x27d1 (en: 'and with dot', MathPlayer: 'and with dot inside', google: 'und mit punkt')
+ - "⟒": [T: "Element der Öffnung nach oben"] # 0x27d2 (en: 'element of opening upwards', MathPlayer: 'element of openning upwards', google: 'element der öffnung nach oben')
+ - "⟓": [T: "Untere rechte Ecke mit Punkt"] # 0x27d3 (en: 'lower right corner with dot', MathPlayer: 'lower right corner with dot', google: 'untere rechte ecke mit punkt')
+ - "⟔": [T: "Obere linke Ecke mit Punkt"] # 0x27d4 (en: 'upper left corner with dot', MathPlayer: 'lower left corner with dot', google: 'obere linke ecke mit punkt')
+ - "⟕": [T: "Linke äußere Verbindung"] # 0x27d5 (en: 'left outer join', MathPlayer: 'left outer join', google: 'linke äußere verbindung')
+ - "⟖": [T: "Rechte äußere Verbindung"] # 0x27d6 (en: 'right outer join', MathPlayer: 'right outer join', google: 'rechts äußerer join')
+ - "⟗": [T: "Volle äußere Verbindung"] # 0x27d7 (en: 'full outer join', MathPlayer: 'full outer join', google: 'voller äußerer join')
+ - "⟘": [T: "Großer Aufwärtsstrich"] # 0x27d8 (en: 'large up tack', MathPlayer: 'large up tack', google: 'groß nach oben')
+ - "⟙": [T: "Großer Abwärtsstrich"] # 0x27d9 (en: 'large down tack', MathPlayer: 'large down tack', google: 'groß nach unten')
+ - "⟚": [T: "Linkes und rechtes doppeltes Drehkreuz"] # 0x27da (en: 'left and right double turnstile', MathPlayer: 'left and right double turnstile', google: 'linke und rechte doppeldrehung')
+ - "⟛": [T: "Linker und rechter Tack"] # 0x27db (en: 'left and right tack', MathPlayer: 'left and right tack', google: 'linker und rechter angriff')
+ - "⟜": [T: "Linke Multikarte"] # 0x27dc (en: 'left multimap', MathPlayer: 'left multimap', google: 'links multimap')
+ - "⟝": [T: "Langer rechter Strich"] # 0x27dd (en: 'long right tack', MathPlayer: 'long right tack', google: 'langer richtiger tack')
+ - "⟞": [T: "Langer linker Strich"] # 0x27de (en: 'long left tack', MathPlayer: 'long left tack', google: 'lange linke tack')
+ - "⟟": [T: "Aufwärtsstrich mit Kreis oben"] # 0x27df (en: 'up tack with circle above', MathPlayer: 'up tack with circle above', google: 'auf kreis oben')
+ - "⟠": [T: "Raute durch horizontale Regel geteilt"] # 0x27e0 (en: 'lozenge divided by horizontal rule', MathPlayer: 'lozenge divided by horizontal rule', google: 'rautengeschwindigkeit geteilt durch horizontale herrschaft')
+ - "⟡": [T: "Weißer konkavseitiger Diamant"] # 0x27e1 (en: 'white concave sided diamond', MathPlayer: 'white concave sided diamond', google: 'weißer konkaves diamant')
+ - "⟢": [T: "Weißer konkavseitiger Diamant mit Häkchen nach links"] # 0x27e2 (en: 'white concave sided diamond with leftwards tick', MathPlayer: 'white concave sided diamond with leftwards tick', google: 'weißer konkaves diamant mit linkser zecke')
+ - "⟣": [T: "Weißer konkavseitiger Diamant mit Häkchen nach rechts"] # 0x27e3 (en: 'white concave sided diamond with rightwards tick', MathPlayer: 'white concave sided diamond with rightwards tick', google: 'weißer konkaves diamant mit rightwards tick')
+ - "⟤": [T: "Weißes Quadrat mit Häkchen nach links"] # 0x27e4 (en: 'white square with leftwards tick', MathPlayer: 'white square with leftwards tick', google: 'weißes quadrat mit links. tick')
+ - "⟥": [T: "Weißes Quadrat mit Häkchen nach rechts"] # 0x27e5 (en: 'white square with rightwards tick', MathPlayer: 'white square with rightwards tick', google: 'weißes quadrat mit rechtsem häkchen')
+ - "⟦": [T: "Mathematische linke weiße eckige Klammer"] # 0x27e6 (en: 'left white square bracket', MathPlayer: 'left white square bracket', google: 'linke weiße quadratklammer')
+ - "⟧": [T: "Mathematische rechte weiße eckige Klammer"] # 0x27e7 (en: 'right white square bracket', MathPlayer: 'right white square bracket', google: 'rechte weiße quadratklasse')
+ - "⟨": [T: "Mathematische linke Winkelklammer"] # 0x27e8 (en: 'left angle bracket', MathPlayer: 'left angle bracket', google: 'linkswinkelhalter')
+ - "⟩": [T: "Mathematische rechtwinklige Klammer"] # 0x27e9 (en: 'right angle bracket', MathPlayer: 'right angle bracket', google: 'rechtswinkelhalterung')
+ - "⟪": [T: "Mathematische linke doppelte Winkelklammer"] # 0x27ea (en: 'left double angle bracket', MathPlayer: 'left double angle bracket', google: 'links zwei winkelhalterungen')
+ - "⟫": [T: "Mathematische rechtwinklige eckige Klammer"] # 0x27eb (en: 'right double angle bracket', MathPlayer: 'right double angle bracket', google: 'rechte doppelwinkelhalterung')
+ - "⟬": [T: "Mathematische linke weiße Schildpatt-Klammer"] # 0x27ec (en: 'left white tortoise shell bracket', MathPlayer: 'left white tortoise shell bracket', google: 'links weiße schildkröte')
+ - "⟭": [T: "Mathematische rechte weiße Schildpatt-Klammer"] # 0x27ed (en: 'right white tortoise shell bracket', MathPlayer: 'right white tortoise shell bracket', google: 'richtige weiße schildkrabbungshalterung')
+ - "⟮": [T: "Mathematische linke abgeflachte Klammer"] # 0x27ee (en: 'left flattened parenthesis', MathPlayer: 'left flattened parenthesis', google: 'links abgeflachte klammern')
+ - "⟯": [T: "Mathematische rechte abgeflachte Klammer"] # 0x27ef (en: 'right flattened parenthesis', MathPlayer: 'right flattened parenthesis', google: 'rechte abgeflachte klammern')
+ - "⟰": [T: "Vierfachpfeil nach oben"] # 0x27f0 (en: 'upwards quadruple arrow', google: 'vierfache pfeil nach oben')
+ - "⟱": [T: "Vierfacher Pfeil nach unten"] # 0x27f1 (en: 'downwards quadruple arrow', google: 'abwärtsvervierter pfeil')
+ - "⟲": [T: "Kreispfeil gegen den Uhrzeigersinn"] # 0x27f2 (en: 'anticlockwise gapped circle arrow', google: 'gezitterkreis pfeil gegen den gegen den lockzuseigersinn')
+ - "⟳": [T: "Kreispfeil im Uhrzeigersinn"] # 0x27f3 (en: 'clockwise gapped circle arrow', google: 'geteilte kreispfeil im uhrzeigersinn')
+ - "⟴": [T: "rechter Pfeil mit Circled Plus"] # 0x27f4 (en: 'right arrow with circled plus', google: 'richtiger pfeil mit eingekreistem plus')
+ - "⟵": [T: "Langer Pfeil nach links"] # 0x27f5 (en: 'long leftwards arrow', MathPlayer: 'long leftwards arrow', google: 'langer pfeil nach links')
+ - "⟶": [T: "Langer Pfeil nach rechts"] # 0x27f6 (en: 'long rightwards arrow', MathPlayer: 'long rightwards arrow', google: 'langer rechts pfeil')
+ - "⟷": [T: "Langer linker rechter Pfeil"] # 0x27f7 (en: 'long left right arrow', MathPlayer: 'long left right arrow', google: 'langer links rechts pfeil')
+ - "⟸": [T: "Langer Doppelpfeil nach links"] # 0x27f8 (en: 'long leftwards double arrow', MathPlayer: 'long leftwards double arrow', google: 'langer links doppelpfeil')
+ - "⟹": [T: "Langer Doppelpfeil nach rechts"] # 0x27f9 (en: 'long rightwards double arrow', MathPlayer: 'long rightwards double arrow', google: 'langer rechts doppelpfeil')
+ - "⟺": [T: "Langer linker rechter Doppelpfeil"] # 0x27fa (en: 'long left right double arrow', MathPlayer: 'long left right double arrow', google: 'langer links rechts doppelpfeil')
+ - "⟻": [T: "Langer Pfeil nach links mit Sockel"] # 0x27fb (en: 'long leftwards arrow from bar', google: 'langer links pfeil aus der bar')
+ - "⟼": [T: "Langer Pfeil nach rechts mit Sockel"] # 0x27fc (en: 'long rightwards arrow from bar', MathPlayer: 'long rightwards arrow from bar', google: 'langer rechts pfeil aus der bar')
+ - "⟽": [T: "Langer Doppelpfeil nach links mit Sockel"] # 0x27fd (en: 'long leftwards double arrow from bar', google: 'langer links doppelpfeil aus der bar')
+ - "⟾": [T: "Langer Doppelpfeil nach rechts mit Sockel"] # 0x27fe (en: 'long rightwards double arrow from bar', google: 'langer rechts doppelpfeil aus der bar')
+ - "⟿": [T: "Langer, nach rechts gekrümmter Pfeil"] # 0x27ff (en: 'long rightwards squiggle arrow', MathPlayer: 'long rightwards squiggle arrow', google: 'langer rechts squiggle -pfeil')
+ - "⤀": [T: "Nach rechts gerichteter Doppelpfeil mit vertikalem Strich"] # 0x2900 (en: 'rightwards two headed arrow with vertical stroke', google: 'rechten zweiköpfigen pfeil mit vertikalem schlaganfall')
+ - "⤁": [T: "Nach rechts gerichteter Doppelpfeil mit doppeltem vertikalem Strich"] # 0x2901 (en: 'rightwards two headed arrow with double vertical stroke', google: 'rechten zweiköpfigen pfeil mit doppelter vertikaler hub')
+ - "⤂": [T: "Doppelpfeil nach links mit vertikalem Strich"] # 0x2902 (en: 'leftwards double arrow with vertical stroke', google: 'links doppelpfeil mit vertikalem schlaganfall')
+ - "⤃": [T: "Doppelpfeil nach rechts mit vertikalem Strich"] # 0x2903 (en: 'rightwards double arrow with vertical stroke', google: 'richtiger doppelpfeil mit vertikalem schlaganfall')
+ - "⤄": [T: "Linker rechter Doppelpfeil mit vertikalem Strich"] # 0x2904 (en: 'left right double arrow with vertical stroke', google: 'links rechts doppelpfeil mit vertikalem schlaganfall')
+ - "⤅": [T: "Zwei Pfeile nach rechts mit Sockel "] # 0x2905 (en: 'rightwards two headed arrow from bar', MathPlayer: 'rightwards two headed arrow from bar', google: 'rightwards zwei köpfe pfeil aus der bar')
+ - "⤆": [T: "Doppelpfeil nach links mit Sockel"] # 0x2906 (en: 'leftwards double arrow from bar', google: 'links doppelpfeil aus der bar')
+ - "⤇": [T: "Doppelter Pfeil nach rechts mit Sockel"] # 0x2907 (en: 'rightwards double arrow from bar', google: 'richtiger doppelpfeil aus der bar')
+ - "⤈": [T: "Abwärtspfeil mit horizontalem Strich"] # 0x2908 (en: 'downwards arrow with horizontal stroke', google: 'nach unten pfeil mit horizontalem schlaganfall nach unten')
+ - "⤉": [T: "Aufwärtspfeil mit horizontalem Anschlag"] # 0x2909 (en: 'upwards arrow with horizontal stroke', google: 'aufwärter pfeil mit horizontalem schlaganfall')
+ - "⤊": [T: "Dreifachpfeil nach oben"] # 0x290a (en: 'upwards triple arrow', google: 'dreifach pfeil nach oben')
+ - "⤋": [T: "Dreifacher Pfeil nach unten"] # 0x290b (en: 'downwards triple arrow', google: 'dreifach pfeil nach unten')
+ - "⤌": [T: "Doppelpfeil nach links"] # 0x290c (en: 'leftwards double dash arrow', MathPlayer: 'leftwards double dash arrow', google: 'links -doppel -dash -pfeil')
+ - "⤍": [T: "Doppelpfeil nach rechts"] # 0x290d (en: 'rightwards double dash arrow', MathPlayer: 'rightwards double dash arrow', google: 'rightwards double dash -pfeil')
+ - "⤎": [T: "Dreifacher Strichpfeil nach links"] # 0x290e (en: 'leftwards triple dash arrow', MathPlayer: 'leftwards triple dash arrow', google: 'links dreifach dash -pfeil')
+ - "⤏": [T: "Dreifacher Strichpfeil nach rechts"] # 0x290f (en: 'rightwards triple dash arrow', MathPlayer: 'rightwards triple dash arrow', google: 'rightwards triple dash pfeil')
+ - "⤐": [T: "Dreipoliger Pfeil nach rechts"] # 0x2910 (en: 'rightwards two headed triple dash arrow', MathPlayer: 'rightwards two headed triple dash arrow', google: 'rightwards zwei köpfe triple dash -pfeil')
+ - "⤑": [T: "Pfeil nach rechts mit gepunktetem Stamm"] # 0x2911 (en: 'rightwards arrow with dotted stem', MathPlayer: 'rightwards arrow with dotted stem', google: 'richtiger pfeil mit gepunktetem stiel')
+ - "⤒": [T: "Aufwärtspfeil zur Sockel"] # 0x2912 (en: 'upwards arrow to bar', MathPlayer: 'upwards arrow to bar', google: 'aufwärter pfeil in die bar')
+ - "⤓": [T: "Abwärtspfeil zur Sockel"] # 0x2913 (en: 'downwards arrow to bar', MathPlayer: 'downwards arrow to bar', google: 'nach unten pfeil in die bar')
+ - "⤔": [T: "Pfeil nach rechts mit Schwanz mit vertikalem Strich"] # 0x2914 (en: 'rightwards arrow with tail and vertical stroke', google: 'rechten pfeil mit schwanz und vertikalem schlaganfall')
+ - "⤕": [T: "Pfeil nach rechts mit Schwanz mit doppeltem vertikalen Strich"] # 0x2915 (en: 'rightwards arrow with tail and double vertical stroke', google: 'rechten pfeil mit schwanz und doppelter vertikaler schlaganfall')
+ - "⤖": [T: "Nach rechts gerichteter zweiköpfiger Pfeil mit Schwanz"] # 0x2916 (en: 'rightwards two headed arrow with tail', MathPlayer: 'rightwards two headed arrow with tail', google: 'rechten zweiköpfigen pfeil mit schwanz')
+ - "⤗": [T: "Nach rechts gerichteter Doppelpfeil mit Schwanz mit senkrechtem Anschlag"] # 0x2917 (en: 'rightwards two headed arrow with tail with vertical stroke', google: 'rechten zweiköpfigen pfeil mit schwanz mit vertikalem schlaganfall')
+ - "⤘": [T: "Nach rechts gerichteter Doppelpfeil mit Schwanz mit doppeltem vertikalen Strich"] # 0x2918 (en: 'rightwards two headed arrow with tail with double vertical stroke', google: 'rechten zweiköpfigen pfeil mit schwanz mit doppelter vertikaler hub')
+ - "⤙": [T: "Pfeilspitze nach links"] # 0x2919 (en: 'leftwards arrow tail', MathPlayer: 'leftwards arrow tail', google: 'links pfeilschwanz')
+ - "⤚": [T: "Pfeilspitze nach rechts"] # 0x291a (en: 'rightwards arrow tail', google: 'richtiger pfeilschwanz')
+ - "⤛": [T: "Doppelter Pfeilschwanz nach links"] # 0x291b (en: 'leftwards double arrow tail', MathPlayer: 'leftwards double arrow tail', google: 'links doppelpfeilschwanz')
+ - "⤜": [T: "Doppelter Pfeilschwanz nach rechts"] # 0x291c (en: 'rightwards double arrow tail', MathPlayer: 'rightwards double arrow tail', google: 'rightwards double pfeilschwanz')
+ - "⤝": [T: "Pfeil nach links zu Black Diamond"] # 0x291d (en: 'leftwards arrow to filled diamond', MathPlayer: 'leftwards arrow to filled diamond', google: 'pfeil nach links zum gefüllten diamanten')
+ - "⤞": [T: "Pfeil nach rechts zu Black Diamond"] # 0x291e (en: 'rightwards arrow to filled diamond', MathPlayer: 'rightwards arrow to filled diamond', google: 'richtiger pfeil zum gefüllten diamanten')
+ - "⤟": [T: "Pfeil nach links von Bar zu Black Diamond"] # 0x291f (en: 'leftwards arrow from bar to filled diamond', MathPlayer: 'leftwards arrow from bar to filled diamond', google: 'pfeil von der bar zum gefüllten diamanten links')
+ - "⤠": [T: "Pfeil nach rechts von Bar zu Black Diamond"] # 0x2920 (en: 'rightwards arrow from bar to filled diamond', MathPlayer: 'rightwards arrow from bar to filled diamond', google: 'richtiger pfeil von bar zum gefüllten diamanten')
+ - "⤡": [T: "Nordwest- und Südostpfeil"] # 0x2921 (en: 'north west and south east arrow', google: 'nordwest- und südostpfeil')
+ - "⤢": [T: "Nordost- und Südwestpfeil"] # 0x2922 (en: 'north east and south west arrow', google: 'nordost- und südwestpfeil')
+ - "⤣": [T: "Nordwestpfeil mit Haken"] # 0x2923 (en: 'north west arrow with hook', MathPlayer: 'north west arrow with hook', google: 'nordwestpfeil mit haken')
+ - "⤤": [T: "Nordostpfeil mit Haken"] # 0x2924 (en: 'north east arrow with hook', MathPlayer: 'north east arrow with hook', google: 'nordostpfeil mit haken')
+ - "⤥": [T: "Südostpfeil mit Haken"] # 0x2925 (en: 'south east arrow with hook', MathPlayer: 'south east arrow with hook', google: 'südostpfeil mit haken')
+ - "⤦": [T: "Südwestpfeil mit Haken"] # 0x2926 (en: 'south west arrow with hook', MathPlayer: 'south west arrow with hook', google: 'südwestpfeil mit haken')
+ - "⤧": [T: "Nordwestpfeil und Nordostpfeil"] # 0x2927 (en: 'north west arrow and north east arrow', MathPlayer: 'north west arrow and north east arrow', google: 'north west arrow und north east pfeil')
+ - "⤨": [T: "Nordostpfeil und Südostpfeil"] # 0x2928 (en: 'north east arrow and south east arrow', MathPlayer: 'north east arrow and south east arrow', google: 'north east arrow und south east pfeil')
+ - "⤩": [T: "Südostpfeil und Südwestpfeil"] # 0x2929 (en: 'south east arrow and south west arrow', MathPlayer: 'south east arrow and south west arrow', google: 'south east arrow und south west arrow')
+ - "⤪": [T: "Südwestpfeil und Nordwestpfeil"] # 0x292a (en: 'south west arrow and north west arrow', MathPlayer: 'south west arrow and north west arrow', google: 'südwestpfeil und nordwestpfeil')
+ - "⤫": [T: "Steigende diagonale Kreuzung fallende Diagonale"] # 0x292b (en: 'rising diagonal crossing falling diagonal', google: 'steigende diagonale kreuzung fallende diagonale')
+ - "⤬": [T: "Fallende diagonale Kreuzung steigende Diagonale"] # 0x292c (en: 'falling diagonal crossing rising diagonal', google: 'fallende diagonale kreuzende diagonale diagonale kreuzung')
+ - "⤭": [T: "Südostpfeil Kreuzung Nordostpfeil"] # 0x292d (en: 'south east arrow crossing north east arrow', google: 'south east arrow crossed north east pfeil')
+ - "⤮": [T: "Nordostpfeil Kreuzung Südostpfeil"] # 0x292e (en: 'north east arrow crossing south east arrow', google: 'north east arrow crossed south east pfeil')
+ - "⤯": [T: "Fallende Diagonale, die Nordostpfeil kreuzt"] # 0x292f (en: 'falling diagonal crossing north east arrow', google: 'fallende diagonale kreuzung north east pfeil')
+ - "⤰": [T: "Steigende Diagonale, die Südostpfeil kreuzt"] # 0x2930 (en: 'rising diagonal crossing south east arrow', google: 'steigende diagonale kreuzung südostpfeil')
+ - "⤱": [T: "Nordostpfeilüberquerung Nordwestpfeil"] # 0x2931 (en: 'north east arrow crossing north west arrow', google: 'nordostpfeil der nordwestpfeil')
+ - "⤲": [T: "Nordwestpfeilüberquerung Nordostpfeil"] # 0x2932 (en: 'north west arrow crossing north east arrow', google: 'nordwest -pfeil überqueren north east pfeil')
+ - "⤳": [T: "Wellenpfeil, der nach rechts zeigt"] # 0x2933 (en: 'wave arrow pointing directly right', MathPlayer: 'wave arrow pointing directly to the right', google: 'wellenpfeil direkt nach rechts zeigen')
+ - "⤴": [T: "Pfeil nach rechts, dann nach oben gekrümmt"] # 0x2934 (en: 'arrow pointing rightwards then curving upwards', google: 'pfeil nach rechts zeigt und dann nach oben krümmt')
+ - "⤵": [T: "Pfeil nach rechts, dann nach unten gekrümmt"] # 0x2935 (en: 'arrow pointing rightwards then curving downwards', MathPlayer: 'arrow pointing rightwards then curving downwards', google: 'pfeil nach rechts zeigt und dann nach unten krümmt')
+ - "⤶": [T: "Pfeil nach unten, dann nach links gekrümmt"] # 0x2936 (en: 'arrow pointing downwards then curving leftwards', MathPlayer: 'arrow pointing downwards then curving leftwards', google: 'pfeil nach unten zeigt und dann nach links krümmt')
+ - "⤷": [T: "Pfeil nach unten, dann nach rechts gekrümmt"] # 0x2937 (en: 'arrow pointing downwards then curving rightwards', MathPlayer: 'arrow pointing downwards then curving rightwards', google: 'pfeil nach unten zeigt und dann nach rechts krümmt')
+ - "⤸": [T: "Rechtsseitiger Bogen im Uhrzeigersinn"] # 0x2938 (en: 'right side arc clockwise arrow', MathPlayer: 'clockwise right semicircle arrow', google: 'rechte seite arc im uhrzeigersinn')
+ - "⤹": [T: "Bogen von der linken Seite gegen den Uhrzeigersinn"] # 0x2939 (en: 'left side arc anticlockwise arrow', MathPlayer: 'anticlockwise left semicircle arrow', google: 'linker side arc arc gegen den pfeil gegen gesamtzusehen')
+ - "⤺": [T: "Pfeil von rechts oben gegen den Uhrzeigersinn"] # 0x293a (en: 'top arc anticlockwise arrow', google: 'top -arc -arc gegen den pfeil gegen den uhrzeigersinn')
+ - "⤻": [T: "Pfeil von links unten gegen den Uhrzeigersinn"] # 0x293b (en: 'bottom arc anticlockwise arrow', google: 'bogenzeigero -pfeil gegen den unteren lichtbogen')
+ - "⤼": [T: "Pfeil von links unten im Uhrzeigersinn mit Minuszeichen links"] # 0x293c (en: 'top arc clockwise arrow with minus', MathPlayer: 'clockwise top semicircle arrow with minus', google: 'bogenzusuell -pfeil mit minus')
+ - "⤽": [T: "Pfeil von rechts unten gegen den Uhrzeigersinn mit Pluszeichen rechts"] # 0x293d (en: 'top arc anticlockwise arrow with plus', MathPlayer: 'anticlockwise top semicircle arrow with plus', google: 'top -arc -arc gegen plus gegen den arrow')
+ - "⤾": [T: "Rechter halbkreisförmiger Pfeil im Uhrzeigersinn"] # 0x293e (en: 'lower right semicircular clockwise arrow', google: 'unterhalb des rechten halbkreisförmigen pfeils im uhrzeigersinn')
+ - "⤿": [T: "Linker halbkreisförmiger Pfeil gegen den Uhrzeigersinn"] # 0x293f (en: 'lower left semicircular anticlockwise arrow', google: 'unterer linker halbkreisförmiger arrow gegen den gegen den gegen den uhrzeigersinn')
+ - "⥀": [T: "Geschlossener Kreispfeil gegen den Uhrzeigersinn"] # 0x2940 (en: 'anticlockwise closed circle arrow', google: 'schleigender kirckeisprohl')
+ - "⥁": [T: "Geschlossener Kreispfeil im Uhrzeigersinn"] # 0x2941 (en: 'clockwise closed circle arrow', google: 'pfeil im uhrzeigersinn geschlossen')
+ - "⥂": [T: "Pfeil nach rechts über einem kurzen Pfeil nach links"] # 0x2942 (en: 'rightwards arrow above short leftwards arrow', google: 'rechten pfeil über dem kurzen linken pfeil')
+ - "⥃": [T: "Pfeil nach links über einem kurzen Pfeil nach rechts"] # 0x2943 (en: 'leftwards arrow above short rightwards arrow', google: 'links pfeil über kurzer rechts pfeil')
+ - "⥄": [T: "Kurzer Pfeil nach rechts Über Pfeil nach links"] # 0x2944 (en: 'short rightwards arrow above leftwards arrow', google: 'kurz nach rechts pfeil über links')
+ - "⥅": [T: "Pfeil nach rechts mit Pluszeichen unten"] # 0x2945 (en: 'rightwards arrow with plus below', MathPlayer: 'rightwards arrow with plus below', google: 'rightwards pfeil mit plus unten')
+ - "⥆": [T: "Pfeil nach links mit Pluszeichen unten"] # 0x2946 (en: 'leftwards arrow with plus below', google: 'links pfeil mit plus unten')
+ - "⥇": [T: "Pfeil nach rechts durch X"] # 0x2947 (en: 'rightwards arrow through x', google: 'richtiger pfeil durch x')
+ - "⥈": [T: "Linker rechter Pfeil durch kleinen Kreis"] # 0x2948 (en: 'left right arrow through circle', MathPlayer: 'left right arrow through circle', google: 'links rechts pfeil durch den kreis')
+ - "⥉": [T: "Aufwärts zweiköpfiger Pfeil vom kleinen Kreis ausgehend"] # 0x2949 (en: 'upwards two headed arrow from circle', MathPlayer: 'upwards two headed arrow from circle', google: 'auf zwei köpfe pfeil aus dem kreis')
+ - "⥊": [T: "Linker Haken oben mit rechtem Haken unten"] # 0x294a (en: 'left barb up right barb down harpoon', MathPlayer: 'left barb up right barb down harpoon', google: 'links barb oben rechte barb down harpoon')
+ - "⥋": [T: "Linker Haken unten mit rechtem Haken oben"] # 0x294b (en: 'left barb down right barb up harpoon', MathPlayer: 'left barb down right barb up harpoon', google: 'linker barb unten rechte barb auf harpoon')
+ - "⥌": [T: "Aufwärtshaken rechts, Abwärtshaken links"] # 0x294c (en: 'up barb right down barb left harpoon', google: 'auf barb rechts runter barb links harpune')
+ - "⥍": [T: "Aufwärtshaken links, Abwärtshaken rechts"] # 0x294d (en: 'up barb left down barb right harpoon', google: 'auf barb nach links nach unten abharpoon')
+ - "⥎": [T: "Linker Haken oben mit rechtem Haken oben"] # 0x294e (en: 'left barb up right barb up harpoon', MathPlayer: 'left right harpoon up', google: 'links barby up up barb up harpoon')
+ - "⥏": [T: "Aufwärtshaken rechts, Abwärtshaken rechts"] # 0x294f (en: 'up barb right down barb right harpoon', MathPlayer: 'up down harpoon right', google: 'auf barb direkt nach barb rechts rechts harpune')
+ - "⥐": [T: "Linker Haken unten mit rechtem Haken unten"] # 0x2950 (en: 'left barb down right barb down harpoon', MathPlayer: 'left right harpoon down', google: 'linker barb unten rechte barb nach unten harpoon')
+ - "⥑": [T: "Aufwärtshaken links, Abwärtshaken links"] # 0x2951 (en: 'up barb left down barb left harpoon', MathPlayer: 'up down harpoon left', google: 'auf barb ließ barb nach barb ließ harpoon')
+ - "⥒": [T: "Linker Haken oben mit Sockel links"] # 0x2952 (en: 'leftwards harpoon with barb up to bar', MathPlayer: 'leftwards harpoon to bar with barb upwards', google: 'links harpoon mit barb bis zur bar')
+ - "⥓": [T: "rechter Haken oben mit Sockel rechts"] # 0x2953 (en: 'rightwards harpoon with barb up to bar', MathPlayer: 'rightwards harpoon to bar with barb upwards', google: 'rightwards harpoon mit barb bis zur bar')
+ - "⥔": [T: "Aufwärtshaken rechts mit Sockel oben"] # 0x2954 (en: 'upwards harpoon with barb right to bar', MathPlayer: 'upwards harpoon to bar with barb rightwards', google: 'harpune nach oben mit barb right to bar')
+ - "⥕": [T: "Abwärtshaken rechts mit Sockel unten"] # 0x2955 (en: 'downwards harpoon with barb right to bar', MathPlayer: 'downwards harpoon to bar with barb rightwards', google: 'nach unten harpoon mit barb right to bar')
+ - "⥖": [T: "Linker Haken unten mit Sockel links"] # 0x2956 (en: 'leftwards harpoon with barb down to bar', MathPlayer: 'leftwards harpoon to bar with barb downwards', google: 'links harpoon mit barb in die bar')
+ - "⥗": [T: "Rechter Haken unten mit Sockel rechts"] # 0x2957 (en: 'rightwards harpoon with barb down to bar', MathPlayer: 'rightwards harpoon to bar with barb downwards', google: 'rightwards harpoon mit barb nach unten in die bar')
+ - "⥘": [T: "Aufwärtshaken links mit Sockel oben"] # 0x2958 (en: 'upwards harpoon with barb left to bar', MathPlayer: 'upwards harpoon to bar with barb leftwards', google: 'harpoon mit barb in der bar nach oben')
+ - "⥙": [T: "Abwärtshaken links mit Sockel unten"] # 0x2959 (en: 'downwards harpoon with barb left to bar', MathPlayer: 'downwards harpoon to bar with barb leftwards', google: 'abwärtsharpune mit barb in der bar nach unten')
+ - "⥚": [T: "Linker Haken oben mit Sockel rechts"] # 0x295a (en: 'leftwards harpoon with barb up from bar', MathPlayer: 'leftwards harpoon from bar with barb upwards', google: 'links -harpoon mit barb aus der bar')
+ - "⥛": [T: "Rechter Haken oben mit Sockel links"] # 0x295b (en: 'rightwards harpoon with barb up from bar', MathPlayer: 'rightwards harpoon from bar with barb upwards', google: 'rightwards harpoon mit barb auf der bar')
+ - "⥜": [T: "Aufwärtshaken rechts mit Sockel unten"] # 0x295c (en: 'upwards harpoon with barb right from bar', MathPlayer: 'upwards harpoon from bar with barb rightwards', google: 'harpune nach oben mit barb direkt aus der bar')
+ - "⥝": [T: "Abwärtshaken rechts mit Sockel oben"] # 0x295d (en: 'downwards harpoon with barb right from bar', MathPlayer: 'downwards harpoon from bar with barb rightwards', google: 'harpunen nach unten mit barb direkt aus der bar')
+ - "⥞": [T: "Linker Haken unten mit Sockel rechts"] # 0x295e (en: 'leftwards harpoon with barb down from bar', MathPlayer: 'leftwards harpoon from bar with barb downwards', google: 'links harpoon mit barb von bar aus der bar')
+ - "⥟": [T: "Rechter Haken unten mit Sockel links"] # 0x295f (en: 'rightwards harpoon with barb down from bar', MathPlayer: 'rightwards harpoon from bar with barb downwards', google: 'rightwards harpoon mit barb von bar aus der bar')
+ - "⥠": [T: "Aufwärtshaken links mit Sockel unten"] # 0x2960 (en: 'upwards harpoon with barb left from bar', MathPlayer: 'upwards harpoon from bar with barb leftwards', google: 'harpoon mit barb aus der bar nach oben')
+ - "⥡": [T: "Abwärtshaken links mit Sockel oben"] # 0x2961 (en: 'downwards harpoon with barb left from bar', MathPlayer: 'downwards harpoon from bar with barb leftwards', google: 'abwärtsharpune mit barb aus der bar weg')
+ - "⥢": [T: "Harpune nach links mit Widerhaken nach oben Harpune nach links mit Widerhaken nach unten"] # 0x2962 (en: 'leftwards harpoon with barb up above leftwards harpoon with barb down', MathPlayer: 'leftwards harpoon with barb up above leftwards harpoon with barb down', google: 'links harpoon mit barb oben links harpoon mit barb nach unten')
+ - "⥣": [T: "Harpune nach oben mit Widerhaken links neben Harpune nach oben Widerhaken Barb rechts"] # 0x2963 (en: 'upwards harpoon with barb left beside upwards harpoon with barb right', MathPlayer: 'upwards harpoon with barb left beside upwards harpoon with barb right', google: 'harpoon nach oben mit barb neben harpoon nach oben mit barb rechts')
+ - "⥤": [T: "Harpune nach rechts mit Widerhaken nach oben Harpune nach rechts mit Widerhaken nach unten"] # 0x2964 (en: 'rightwards harpoon with barb up above rightwards harpoon with barb down', MathPlayer: 'rightwards harpoon with barb up above rightwards harpoon with barb down', google: 'rightwards harpoon mit barb oben rechts harpoon mit barb down')
+ - "⥥": [T: "Harpune nach unten mit Widerhaken nach unten Harpune nach unten mit Widerhaken nach rechts"] # 0x2965 (en: 'downwards harpoon with barb left beside downwards harpoon with barb right', MathPlayer: 'downwards harpoon with barb left beside downwards harpoon with barb right', google: 'harpoon nach unten mit barb neben der abwärtsharpoon mit barb rechts')
+ - "⥦": [T: "Harpune nach links mit Widerhaken nach oben Harpune nach rechts mit Widerhaken nach oben"] # 0x2966 (en: 'leftwards harpoon with barb up above rightwards harpoon with barb up', MathPlayer: 'leftwards harpoon with barb up above rightwards harpoon with barb up', google: 'links harpoon mit barb oben rechts harpoon mit barb hoch')
+ - "⥧": [T: "Linke Harpune mit Widerhaken nach unten rechts Harpune mit Widerhaken nach unten"] # 0x2967 (en: 'leftwards harpoon with barb down above rightwards harpoon with barb down', MathPlayer: 'leftwards harpoon with barb down above rightwards harpoon with barb down', google: 'links harpoon mit barb oben rechts harpoon mit barb nach unten')
+ - "⥨": [T: "Harpune nach rechts mit Widerhaken nach oben Harpune nach links mit Widerhaken nach oben"] # 0x2968 (en: 'rightwards harpoon with barb up above leftwards harpoon with barb up', MathPlayer: 'rightwards harpoon with barb up above leftwards harpoon with barb up', google: 'harpoon nach rechts mit barb oben links mit barb auf harpoon')
+ - "⥩": [T: "Harpune nach rechts mit Widerhaken nach unten Harpune nach links mit Widerhaken nach unten"] # 0x2969 (en: 'rightwards harpoon with barb down above leftwards harpoon with barb down', MathPlayer: 'rightwards harpoon with barb down above leftwards harpoon with barb down', google: 'harpoon nach rechts mit barb oben links mit barb mit barb')
+ - "⥪": [T: "nach links gerichtete Harpune mit Widerhaken über einem langen Strich"] # 0x296a (en: 'leftwards harpoon with barb up above long dash', MathPlayer: 'leftwards harpoon over bar', google: 'links -harpoon mit barb über langen schuss')
+ - "⥫": [T: "nach links gerichtete Harpune mit Widerhaken unten, lang gestrichelt"] # 0x296b (en: 'leftwards harpoon with barb down below long dash', MathPlayer: 'leftwards harpoon under bar', google: 'links -harpoon mit barb unter longem armaturenbrett')
+ - "⥬": [T: "Rechtshaken mit Widerhaken über langem Strich"] # 0x296c (en: 'rightwards harpoon with barb up above long dash', MathPlayer: 'rightwards harpoon over bar', google: 'rightwards harpoon mit barb über langen schuss')
+ - "⥭": [T: "Rechtshaken mit Widerhaken unten, lang"] # 0x296d (en: 'rightwards harpoon with barb down below long dash', MathPlayer: 'rightwards harpoon under bar', google: 'rightwards harpoon mit barb unter longem armaturenbrett')
+ - "⥮": [T: "aufwärts gerichtete Harpune mit Widerhaken links neben unten gerichteter Harpune mit Widerhaken rechts"] # 0x296e (en: 'upwards harpoon with barb left beside downwards harpoon with barb right', MathPlayer: 'upwards harpoon to the left of downwards harpoon', google: 'harpune nach oben mit barb, der neben der abwärtsharpoon mit barb rechts bleibt')
+ - "⥯": [T: "Abwärtsharpune mit Widerhaken links neben Abwärtsharpune mit Widerhaken rechts"] # 0x296f (en: 'downwards harpoon with barb left beside upwards harpoon with barb right', MathPlayer: 'upwards harpoon to the right of downwards harpoon', google: 'harpoon nach unten mit barb neben harpoon nach oben mit barb rechts')
+ - "⥰": [T: "Rechter Doppelpfeil mit abgerundeter Spitze"] # 0x2970 (en: 'right double arrow with rounded head')
+ - "⥱": [T: "Gleichheitszeichen über dem Pfeil nach rechts"] # 0x2971 (en: 'equals above rightwards arrow', MathPlayer: 'equals above rightwards arrow', google: 'entspricht dem rechten pfeil')
+ - "⥲": [T: "Tilde-Operator über dem Pfeil nach rechts"] # 0x2972 (en: 'tilde operator above rightwards arrow', MathPlayer: 'tilde operator above rightwards arrow', google: 'tilde -operator über rechtsem pfeil')
+ - "⥳": [T: "Pfeil nach links über Tilde-Operator"] # 0x2973 (en: 'leftwards arrow above tilde operator', MathPlayer: 'leftwards arrow over tilde', google: 'pfeil links über dem tilde -operator')
+ - "⥴": [T: "Pfeil nach rechts über Tilde-Operator"] # 0x2974 (en: 'rightwards arrow above tilde operator', MathPlayer: 'rightwards arrow over tilde', google: 'rightwards pfeil über dem tilde -operator')
+ - "⥵": [T: "Pfeil nach rechts über fast gleich"] # 0x2975 (en: 'rightwards arrow above almost equal to', MathPlayer: 'rightwards arrow above almost equal to', google: 'richtiger pfeil über fast gleich')
+ - "⥶": [T: "Weniger als über Pfeil nach links"] # 0x2976 (en: 'less than above leftwards arrow', MathPlayer: 'less than above leftwards arrow', google: 'weniger als links in pfeil')
+ - "⥷": [T: "Pfeil nach links durch weniger als"] # 0x2977 (en: 'leftwards arrow through less than', google: 'links pfeil durch weniger als')
+ - "⥸": [T: "Größer als über dem Pfeil nach rechts"] # 0x2978 (en: 'greater than above rightwards arrow', MathPlayer: 'greater than above rightwards arrow', google: 'größer als über rechts nach rechts')
+ - "⥹": [T: "Untersatz über dem Pfeil nach rechts"] # 0x2979 (en: 'subset above rightwards arrow', MathPlayer: 'subset above rightwards arrow', google: 'untergruppe über rechts nach rechts')
+ - "⥺": [T: "Pfeil nach links durch Teilmenge"] # 0x297a (en: 'leftwards arrow through subset', google: 'pfeil durch die teilmenge links')
+ - "⥻": [T: "Superset über dem Pfeil nach links"] # 0x297b (en: 'superset above leftwards arrow', MathPlayer: 'superset above leftwards arrow', google: 'superset über dem linken pfeil')
+ - "⥼": [T: "linker Fischschwanz"] # 0x297c (en: 'left fish tail', MathPlayer: 'left fish tail', google: 'links fischschwanz')
+ - "⥽": [T: "rechter Fischschwanz"] # 0x297d (en: 'right fish tail', MathPlayer: 'right fish tail', google: 'rechts fischschwanz')
+ - "⥾": [T: "Fischschwanz oben"] # 0x297e (en: 'up fish tail', MathPlayer: 'vertical bar with double hook', google: 'up fischschwanz')
+ - "⥿": [T: "Fischschwanz unten"] # 0x297f (en: 'down fish tail', MathPlayer: 'down fish tail', google: 'down fischschwanz')
+ - "⦀": [T: "Dreifacher vertikaler Balkenbegrenzer"] # 0x2980 (en: 'triple vertical bar delimiter', google: 'triple vertical bar gremiter')
+ - "⦁": [T: "Z Notationspunkt"] # 0x2981 (en: 'z notation spot', google: 'z notationspunkt')
+ - "⦂": [T: "Z Notationstyp Doppelpunkt"] # 0x2982 (en: 'z notation type colon', google: 'z notation typ dickdarm')
+ - "⦃": [T: "Linke weiße geschweifte Klammer"] # 0x2983 (en: 'left white brace', google: 'links weiße klammer')
+ - "⦄": [T: "Rechte weiße geschweifte Klammer"] # 0x2984 (en: 'right white brace', google: 'rechte weiße klammer')
+ - "⦅": [T: "Linke weiße Klammer"] # 0x2985 (en: 'left white parenthesis', MathPlayer: 'left white paren', google: 'linke weiße klammern')
+ - "⦆": [T: "Rechte weiße Klammer"] # 0x2986 (en: 'right white parenthesis', MathPlayer: 'right white paren', google: 'rechte weiße klammern')
+ - "⦇": [T: "Z-Notation linke Bildklammer"] # 0x2987 (en: 'z notation left image bracket', google: 'z notation linke bildklasse')
+ - "⦈": [T: "Z-Notation rechte Bildklammer"] # 0x2988 (en: 'z notation right image bracket', google: 'z notation rechtsbildklasse')
+ - "⦉": [T: "Z-Notation linke Klammer"] # 0x2989 (en: 'z notation left binding bracket', MathPlayer: 'z notation left binding bracket', google: 'z notation links bindungshalterung')
+ - "⦊": [T: "Z-Notation rechte Klammer"] # 0x298a (en: 'z notation right binding bracket', MathPlayer: 'z notation right binding bracket', google: 'z notation recht bindungshalterung')
+ - "⦋": [T: "Linke eckige Klammer mit Unterlenker"] # 0x298b (en: 'left square bracket with underbar', MathPlayer: 'left bracket with underbar', google: 'linksquadratische klammer mit unterbar')
+ - "⦌": [T: "Rechte eckige Klammer mit Unterlenker"] # 0x298c (en: 'right square bracket with underbar', MathPlayer: 'right bracket with underbar', google: 'rechte quadratische halterung mit unterbar')
+ - "⦍": [T: "Linke eckige Klammer mit Häkchen in der oberen Ecke"] # 0x298d (en: 'left square bracket with tick in top corner', MathPlayer: 'left bracket with tick in top corner', google: 'linksquadratische halterung mit zecke in der oberen ecke')
+ - "⦎": [T: "Rechte eckige Klammer mit Tick in der unteren Ecke"] # 0x298e (en: 'right square bracket with tick in bottom corner', MathPlayer: 'right bracket with tick in bottom corner', google: 'rechte quadratische halterung mit tick in der unteren ecke')
+ - "⦏": [T: "Linke eckige Klammer mit Tick in der unteren Ecke"] # 0x298f (en: 'left square bracket with tick in bottom corner', MathPlayer: 'left bracket with tick in bottom corner', google: 'links quadratische halterung mit tick in der unteren ecke')
+ - "⦐": [T: "Rechte eckige Klammer mit Tick in der oberen Ecke"] # 0x2990 (en: 'right square bracket with tick in top corner', MathPlayer: 'right bracket with tick in top corner', google: 'rechte quadratische halterung mit zecke in der oberen ecke')
+ - "⦑": [T: "Linke Winkelklammer mit Punkt"] # 0x2991 (en: 'left angle bracket with dot', MathPlayer: 'left angle bracket with dot', google: 'linkswinkelhalter mit punkt')
+ - "⦒": [T: "Rechtwinklige Klammer mit Punkt"] # 0x2992 (en: 'right angle bracket with dot', MathPlayer: 'right angle bracket with dot', google: 'rechtswinkelhalterung mit punkt')
+ - "⦓": [T: "Linker Bogen weniger als Halterung"] # 0x2993 (en: 'left arc less than bracket', MathPlayer: 'left arc less than bracket', google: 'links bogen weniger als klammer')
+ - "⦔": [T: "rechter Bogen größer als Halterung"] # 0x2994 (en: 'right arc greater than bracket', MathPlayer: 'right arc greater than bracket', google: 'richtiger bogen größer als die klammer')
+ - "⦕": [T: "Doppelter linker Bogen größer als Halterung"] # 0x2995 (en: 'double left arc greater than bracket', MathPlayer: 'double left arc greater than bracket', google: 'doppelter linker bogen größer als die klammer')
+ - "⦖": [T: "Doppelter rechter Bogen weniger als Halterung"] # 0x2996 (en: 'double right arc less than bracket', MathPlayer: 'double right arc less than bracket', google: 'doppeler rechts bogen weniger als klammer')
+ - "⦗": [T: "Linke schwarze Schildpatt-Klammer"] # 0x2997 (en: 'left black tortoise shell bracket', google: 'links black tortoise muschelhalterung')
+ - "⦘": [T: "Rechte schwarze Schildpatt-Klammer"] # 0x2998 (en: 'right black tortoise shell bracket', google: 'rechte schwarze schildkröte')
+ - "⦙": [T: "Gepunkteter Zaun"] # 0x2999 (en: 'dotted fence', google: 'gepunkteter zaun')
+ - "⦚": [T: "Vertikale Zickzacklinie"] # 0x299a (en: 'vertical zigzag line', MathPlayer: 'vertical zigzag line', google: 'vertikale zick -zack -linie')
+ - "⦛": [T: "Gemessene Winkelöffnung links"] # 0x299b (en: 'measured angle opening left', google: 'gemessene winkelöffnung links')
+ - "⦜": [T: "Rechtwinklige Variante mit Quadrat"] # 0x299c (en: 'right angle variant with square', google: 'rechtswinkelvariante mit quadrat')
+ - "⦝": [T: "rechter Winkel mit Punkt gemessen"] # 0x299d (en: 'measured right angle with dot', MathPlayer: 'measured right angle with dot', google: 'gemessener rechter winkel mit punkt')
+ - "⦞": [T: "Winkel mit S nach innen"] # 0x299e (en: 'angle with s inside', google: 'winkel mit s im inneren')
+ - "⦟": [T: "Spitzer Winkel"] # 0x299f (en: 'acute angle', google: 'spitzer winkel')
+ - "⦠": [T: "Sphärischer Öffnungswinkel nach links"] # 0x29a0 (en: 'spherical angle opening left', google: 'kugelwinkelöffnung nach links')
+ - "⦡": [T: "Sphärischer Öffnungswinkel nach unten"] # 0x29a1 (en: 'spherical angle opening up', google: 'kugelwinkel öffnen sich')
+ - "⦢": [T: "Gedrehter Winkel"] # 0x29a2 (en: 'turned angle', google: 'drehwinkel')
+ - "⦣": [T: "Umgekehrter Winkel"] # 0x29a3 (en: 'reversed angle', google: 'umgekehrter winkel')
+ - "⦤": [T: "Winkel mit Unterstrich"] # 0x29a4 (en: 'angle with underbar', MathPlayer: 'angle with underbar', google: 'winkel mit unterbar')
+ - "⦥": [T: "Umgekehrter Winkel mit Unterstrich"] # 0x29a5 (en: 'reversed angle with underbar', MathPlayer: 'reversed angle with underbar', google: 'umgekehrter winkel mit unterbar')
+ - "⦦": [T: "Schräger Winkel, der sich nach oben öffnet"] # 0x29a6 (en: 'oblique angle opening up', MathPlayer: 'oblique angle opening up', google: 'schräge winkelöffnung')
+ - "⦧": [T: "Schräger Winkel, der sich nach unten öffnet"] # 0x29a7 (en: 'oblique angle opening down', MathPlayer: 'oblique angle opening down', google: 'schräge winkel öffnet sich')
+ - "⦨": [T: "Gemessener Winkel mit offenem Arm endet im Pfeil nach oben und rechts"] # 0x29a8 (en: 'measured angle with open arm ending in arrow pointing up and to the right', MathPlayer: 'measured angle with open arm ending in arrow pointing up and to the right', google: 'der gemessene winkel mit offenem arm in pfeil und nach rechts')
+ - "⦩": [T: "Gemessener Winkel mit offenem Arm und Pfeil nach oben und links"] # 0x29a9 (en: 'measured angle with open arm ending in arrow pointing up and to the left', MathPlayer: 'measured angle with open arm ending in arrow pointing up and to the left', google: 'der gemessene winkel mit offenem arm in pfeil und nach links')
+ - "⦪": [T: "Gemessener Winkel mit offenem Arm endet im nach unten zeigenden Pfeil und rechts"] # 0x29aa (en: 'measured angle with open arm ending in arrow pointing down and to the right', MathPlayer: 'measured angle with open arm ending in arrow pointing down and to the right', google: 'der gemessene winkel mit offenem arm in pfeil nach unten und nach rechts')
+ - "⦫": [T: "Gemessener Winkel mit offenem Arm endet im nach unten zeigenden Pfeil"] # 0x29ab (en: 'measured angle with open arm ending in arrow pointing down and to the left', MathPlayer: 'measured angle with open arm ending in arrow pointing down and to the left', google: 'der gemessene winkel mit offenem arm in pfeil, der nach unten und nach links zeigt')
+ - "⦬": [T: "Gemessener Winkel mit offenem Arm endet im Pfeil nach rechts und oben"] # 0x29ac (en: 'measured angle with open arm ending in arrow pointing right and up', MathPlayer: 'measured angle with open arm ending in arrow pointing right and up', google: 'der gemessene winkel mit offenem arm in pfeil nach rechts und nach oben zeigt')
+ - "⦭": [T: "Gemessener Winkel mit offenem Arm endet im Pfeil nach links und oben"] # 0x29ad (en: 'measured angle with open arm ending in arrow pointing left and up', MathPlayer: 'measured angle with open arm ending in arrow pointing left and up', google: 'der gemessene winkel mit offenem arm in pfeil nach links und nach oben zeigt')
+ - "⦮": [T: "Gemessener Winkel mit offenem Arm endet im nach rechts und unten zeigenden Pfeil"] # 0x29ae (en: 'measured angle with open arm ending in arrow pointing right and down', MathPlayer: 'measured angle with open arm ending in arrow pointing right and down', google: 'der gemessene winkel mit offenem arm in pfeil nach rechts und unten zeigt')
+ - "⦯": [T: "Gemessener Winkel mit offenem Arm und Pfeil nach links und unten"] # 0x29af (en: 'measured angle with open arm ending in arrow pointing left and down', MathPlayer: 'measured angle with open arm ending in arrow pointing left and down', google: 'der gemessene winkel mit offenem arm in pfeil nach links und unten zeigt')
+ - "⦰": [T: "Umgekehrte leere Menge"] # 0x29b0 (en: 'reversed empty set', MathPlayer: 'reversed empty set', google: 'umgekehrter leerer satz')
+ - "⦱": [T: "Leere Menge mit Strich oberhalb"] # 0x29b1 (en: 'empty set with overbar', MathPlayer: 'empty set with overbar', google: 'leeres set mit überbar')
+ - "⦲": [T: "Leere Menge mit kleinem Kreis oben"] # 0x29b2 (en: 'empty set with small circle above', MathPlayer: 'empty set with circle above', google: 'leeres set mit kleinem kreis oben')
+ - "⦳": [T: "Leere Menge mit Pfeil rechts oben"] # 0x29b3 (en: 'empty set with right arrow above', MathPlayer: 'empty set with right arrow above', google: 'leer mit dem rechten pfeil oben')
+ - "⦴": [T: "Leere Menge mit linkem Pfeil oben"] # 0x29b4 (en: 'empty set with left arrow above', MathPlayer: 'empty set with left arrow above', google: 'leeres set mit dem linken pfeil oben')
+ - "⦵": [T: "Kreis mit horizontaler Leiste"] # 0x29b5 (en: 'circle with horizontal bar', MathPlayer: 'circle with horizontal bar', google: 'kreis mit horizontaler balken')
+ - "⦶": [T: "Kreis mit vertikaler Linie"] # 0x29b6
+ - "⦷": [T: "eingekreiste Parallele"] # 0x29b7 (en: 'circled parallel', MathPlayer: 'circled parallel', google: 'parallel eingekreist')
+ - "⦸": [T: "eingekreister umgekehrter Schrägstrich"] # 0x29b8 (en: 'circled reverse solidus', google: 'umgekreist reverse solidus')
+ - "⦹": [T: "eingekreistes Senkrecht"] # 0x29b9 (en: 'circled perpendicular', MathPlayer: 'circled perpendicular', google: 'senkrecht umkreist')
+ - "⦺": [T: "Kreis geteilt durch horizontale Leiste und obere Hälfte geteilt durch vertikale Leiste"] # 0x29ba (en: 'circled divided by horizontal bar and top half divided by vertical bar', google: 'durch den horizontalen balken und die obere hälfte geteilt durch vertikale balken eingekreist')
+ - "⦻": [T: "Kreis mit überlagertem X"] # 0x29bb (en: 'circle with superimposed x', MathPlayer: 'circle with superimposed x', google: 'kreis mit überlagertem x')
+ - "⦼": [T: "eingekreistes, gegen den Uhrzeigersinn gedrehtes Divisionszeichen"] # 0x29bc (en: 'circled anticlockwise rotated division sign', MathPlayer: 'circled anticlockwise rotated division', google: 'umgedrehtes divisionszeichen gegen den uhrzeigersinn')
+ - "⦽": [T: "Pfeil nach oben durch Kreis"] # 0x29bd (en: 'up arrow through circle', google: 'pfeil durch den kreis')
+ - "⦾": [T: "eingekreiste weiße Kugel"] # 0x29be (en: 'circled white bullet', MathPlayer: 'circled white bullet', google: 'eingekreiste weiße kugel')
+ - "⦿": [T: "eingekreiste Kugel"] # 0x29bf (en: 'circled bullet', MathPlayer: 'circled bullet', google: 'eingekreist')
+ - "⧀": [T: "eingekreist weniger als"] # 0x29c0 (en: 'circled less than', MathPlayer: 'circled less than', google: 'kreiste weniger als')
+ - "⧁": [T: "eingekreist größer als"] # 0x29c1 (en: 'circled greater than', MathPlayer: 'circled greater than', google: 'umgekreist größer als')
+ - "⧂": [T: "Kreis mit kleinem Kreis nach rechts"] # 0x29c2 (en: 'circle with small circle to the right', MathPlayer: 'circle with circle to the right', google: 'kreis mit kleinem kreis nach rechts')
+ - "⧃": [T: "Kreis mit zwei horizontalen Strichen nach rechts"] # 0x29c3 (en: 'circle with two horizontal strokes to the right', MathPlayer: 'circle with two horizontal strokes to the right', google: 'kreisen sie mit zwei horizontalen strichen rechts')
+ - "⧄": [T: "Quadrat mit Diagonale links unten nach rechts oben"] # 0x29c4 (en: 'squared rising diagonal slash', MathPlayer: 'squared rising diagonal slash', google: 'quadratischer steigender diagonaler schrägstrich')
+ - "⧅": [T: "Quadrat mit Diagonale links oben nach rechts unten"] # 0x29c5 (en: 'squared falling diagonal slash', MathPlayer: 'squared falling diagonal slash', google: 'quadratische fallende diagonale schrägstriche')
+ - "⧆": [T: "Quadrat mit Sternchen"] # 0x29c6 (en: 'squared asterisk', google: 'quadratischer sternchen')
+ - "⧇": [T: "Quadrat mir kleinem Kreis"] # 0x29c7 (en: 'squared small circle', google: 'quadratischer kleiner kreis')
+ - "⧈": [T: "Doppelquadrat"] # 0x29c8 (en: 'squared square', google: 'quadratisch quadratisch')
+ - "⧉": [T: "Zwei verbundene Quadrate"] # 0x29c9 (en: 'two joined squares', MathPlayer: 'two joined squares', google: 'zwei traten quadrate an')
+ - "⧊": [T: "Dreieck mit Punkt oben"] # 0x29ca (en: 'triangle with dot above', google: 'dreieck mit punkt oben')
+ - "⧋": [T: "Dreieck mit Unterleiste"] # 0x29cb (en: 'triangle with underbar', google: 'dreieck mit underbar')
+ - "⧌": [T: "S im Dreieck"] # 0x29cc (en: 's in triangle', google: 's im dreieck')
+ - "⧍": [T: "Dreieck mit Serifen unten"] # 0x29cd (en: 'triangle with serifs at bottom', MathPlayer: 'triangle with serifs at bottom', google: 'dreieck mit serifen unten')
+ - "⧎": [T: "Rechtes Dreieck über linkem Dreieck"] # 0x29ce (en: 'right triangle above left triangle', MathPlayer: 'right triangle above left triangle', google: 'rechts dreieck über dem linken dreieck')
+ - "⧏": [T: "Linkes Dreieck neben vertikaler Leiste"] # 0x29cf (en: 'left triangle beside vertical bar', MathPlayer: 'normal subgroup of with bar', google: 'links dreieck neben vertikaler balken')
+ - "⧐": [T: "Vertikale Leiste neben rechtem Dreieck"] # 0x29d0 (en: 'vertical bar beside right triangle', MathPlayer: 'contains as normal subgroup with bar', google: 'vertikale bar neben dem rechten dreieck')
+ - "⧑": [T: "Fliege mit linker Hälfte schwarz"] # 0x29d1 (en: 'bowtie with left half black', google: 'bowtie mit linksem halb schwarz')
+ - "⧒": [T: "Fliege mit rechter Hälfte schwarz"] # 0x29d2 (en: 'bowtie with right half black', google: 'bowtie mit rechts halb schwarz')
+ - "⧓": [T: "Schwarze Fliege"] # 0x29d3 (en: 'black bowtie', google: 'schwarzer bowtie')
+ - "⧔": [T: "Zeiten mit linker Hälfte schwarz"] # 0x29d4 (en: 'times with left half black', google: 'mal mit links halb schwarz')
+ - "⧕": [T: "Mal mit rechter Hälfte Schwarz"] # 0x29d5 (en: 'times with right half black', google: 'mal mit dem rechten halb schwarz')
+ - "⧖": [T: "Weiße Sanduhr"] # 0x29d6 (en: 'white hourglass', google: 'weiße sanduhr')
+ - "⧗": [T: "Schwarze Sanduhr"] # 0x29d7 (en: 'black hourglass', google: 'schwarze sanduhr')
+ - "⧘": [T: "Linker wackeliger Zaun"] # 0x29d8 (en: 'left wiggly fence', google: 'links wackeliger zaun')
+ - "⧙": [T: "rechter wackeliger Zaun"] # 0x29d9 (en: 'right wiggly fence', google: 'rechts wackeliges zaun')
+ - "⧚": [T: "Linker doppelter wackeliger Zaun"] # 0x29da (en: 'left double wiggly fence', MathPlayer: 'left double wiggly fence', google: 'links doppelter wackeliger zaun')
+ - "⧛": [T: "rechter doppelter wackeliger Zaun"] # 0x29db (en: 'right double wiggly fence', MathPlayer: 'right double wiggly fence', google: 'rechts doppelter wackeliger zaun')
+ - "⧜": [T: "Unvollständige Unendlichkeit"] # 0x29dc (en: 'incomplete infinity', MathPlayer: 'incomplete infinity', google: 'unvollständige unendlichkeit')
+ - "⧝": [T: "Krawatte über Unendlichkeit"] # 0x29dd (en: 'tie over infinity', google: 'unendlich binden')
+ - "⧞": [T: "Unendlichkeit mit vertikaler Leiste negiert"] # 0x29de (en: 'infinity negated with vertical bar', MathPlayer: 'infinity negated with vertical bar', google: 'unendlich negiert mit vertikaler balken')
+ - "⧟": [T: "Doppelter Multimap"] # 0x29df (en: 'double-ended multimap', google: 'doppel-multimap')
+ - "⧠": [T: "Quadrat mit konturierter Kontur"] # 0x29e0 (en: 'square with contoured outline', google: 'quadrat mit konturierten umriss')
+ - "⧡": [T: "Erhöht als"] # 0x29e1 (en: 'increases as', google: 'erhöht sich als')
+ - "⧢": [T: "Produkt mischen"] # 0x29e2 (en: 'shuffle product', google: 'shuffle -produkt')
+ - "⧣": [T: "Gleichheitszeichen und geneigte Parallele"] # 0x29e3 (en: 'equals sign and slanted parallel', MathPlayer: 'equals sign and slanted parallel', google: 'gleicher zeichen und schräg parallel')
+ - "⧤": [T: "Gleichheitszeichen und schräge Parallele zu Tilde oben"] # 0x29e4 (en: 'equals sign and slanted parallel with tilde above', MathPlayer: 'equals sign and slanted parallel with tilde above', google: 'gleicher zeichen und schräg parallel zu tilde oben')
+ - "⧥": [T: "Identisch und schräg parallel"] # 0x29e5 (en: 'identical to and slanted parallel', MathPlayer: 'identical to with double slash', google: 'identisch mit und schräg parallel')
+ - "⧦": [T: "Gleich Stark"] # 0x29e6 (en: 'gleich stark', google: 'gleich stark')
+ - "⧧": [T: "Thermodynamisch"] # 0x29e7 (en: 'thermodynamic', google: 'thermodynamisch')
+ - "⧨": [T: "Abwärtszeigendes Dreieck mit linker Hälfte schwarz"] # 0x29e8 (en: 'down pointing triangle with left half black', google: 'down dreieck mit linksem halb schwarz')
+ - "⧩": [T: "Abwärtszeigendes Dreieck mit rechter Hälfte schwarz"] # 0x29e9 (en: 'down pointing triangle with right half black', google: 'down dreieck mit dem rechten halben schwarz')
+ - "⧪": [T: "Schwarzer Diamant mit Pfeil nach unten"] # 0x29ea (en: 'black diamond with down arrow', google: 'schwarzer diamant mit pfeil')
+ - "⧫": [T: "Schwarze Raute"] # 0x29eb (en: 'black lozenge', MathPlayer: 'filled lozenge', google: 'schwarze raute')
+ - "⧬": [T: "Weißer Kreis mit Pfeil nach unten"] # 0x29ec (en: 'white circle with down arrow', google: 'weißer kreis mit pfeil')
+ - "⧭": [T: "Schwarzer Kreis mit Pfeil nach unten"] # 0x29ed (en: 'black circle with down arrow', google: 'schwarzer kreis mit pfeil')
+ - "⧮": [T: "Fehlergesperrtes weißes Quadrat"] # 0x29ee (en: 'error-barred white square', google: 'irrtum mit dem irrtümlichen weißen quadrat')
+ - "⧯": [T: "Fehlerfreies schwarzes Quadrat"] # 0x29ef (en: 'error-barred black square', google: 'fehler mit dem schwarzen quadrat')
+ - "⧰": [T: "Fehlergesperrter weißer Diamant"] # 0x29f0 (en: 'error-barred white diamond', google: 'fehler mit dem fehler mit weißem diamanten')
+ - "⧱": [T: "Fehlergesperrter schwarzer Diamant"] # 0x29f1 (en: 'error-barred black diamond', google: 'fehlerfreier schwarzer diamant')
+ - "⧲": [T: "Fehlergesperrter weißer Kreis"] # 0x29f2 (en: 'error-barred white circle', google: 'fehlerer weißer weißer kreis')
+ - "⧳": [T: "Fehlergesperrter schwarzer Kreis"] # 0x29f3 (en: 'error-barred black circle', google: 'fehlerer schwarzer kreis')
+ - "⧴": [T: "regelverzögert"] # 0x29f4 (en: 'rule-delayed')
+ - "⧵": [T: "Umgekehrter Schrägstrich Operator"] # 0x29f5 (en: 'reverse solidus operator', google: 'umgekehrter solidus -operator')
+ - "⧶": [T: "Schrägstrich mit vertikaler Leiste oben"] # 0x29f6 (en: 'solidus with overbar', MathPlayer: 'solidus with overbar', google: 'solidus mit overbar')
+ - "⧷": [T: "Umgekehrter Schrägstrich mit horizontalem Hub"] # 0x29f7 (en: 'reverse solidus with horizontal stroke', google: 'mit horizontalem schlaganfall solidus umkehren')
+ - "⧸": [T: "Großer Schrägstrich"] # 0x29f8 (en: 'big solidus', google: 'big solidus')
+ - "⧹": [T: "Großer umgekehrter Schrägstrich"] # 0x29f9 (en: 'big reverse solidus', google: 'big reverse solidus')
+ - "⧺": [T: "Doppel plus"] # 0x29fa (en: 'double plus', google: 'doppelte plus')
+ - "⧻": [T: "Triple Plus"] # 0x29fb (en: 'triple plus', google: 'triple plus')
+ - "⧼": [T: "Nach links zeigender gebogener Winkelhalter"] # 0x29fc (en: 'left pointing curved angle bracket', google: 'links gezeigt, gekrümmte winkelhalterung')
+ - "⧽": [T: "Nach rechts zeigender gebogener Winkelhalter"] # 0x29fd (en: 'right pointing curved angle bracket', google: 'rechte spitze gekrümmte winkelhalterung')
+ - "⧾": [T: "Winzig"] # 0x29fe (en: 'tiny', google: 'winzig')
+ - "⧿": [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: "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')
+ - "⨆": [T: "quadratischer Vereinigungs-Operator"] # 0x2a06 (en: 'square union operator', google: 'square union operator')
+ - "⨇": [T: "Zwei logische Und-Operator"] # 0x2a07 (en: 'two logical and operator', google: 'zwei logische und operator')
+ - "⨈": [T: "Zwei logische Oder-Operator"] # 0x2a08 (en: 'two logical or operator', google: 'zwei logische oder operator')
+ - "⨉": [T: "Kreuz-Operator"] # 0x2a09 (en: 'times operator', google: 'times operator')
+ - "⨊": [T: "Modulo Zwei Summe"] # 0x2a0a (en: 'modulo two sum', google: 'modulo zwei summe')
+ - "⨋": [T: "Summation mit Integral"] # 0x2a0b (en: 'summation with integral', google: 'summierung mit integral')
+ - "⨌": [T: "Vierfach-Integral-Operator"] # 0x2a0c (SRE: 'Vierfach-Integral-Operator')
+ - "⨍": [T: "endliches Teilintegral"] # 0x2a0d (en: 'finite part integral', MathPlayer: 'finite part integral', google: 'finite -teil -integral')
+ - "⨎": [T: "Integral mit Doppelhub"] # 0x2a0e (en: 'integral with double stroke', google: 'integral mit doppelter hub')
+ - "⨏": [T: "Integraler Durchschnitt mit Schrägstrich"] # 0x2a0f (en: 'integral average with slash', google: 'integraler durchschnitt mit schrägstrich')
+ - "⨐": [T: "Zirkulationsfunktion"] # 0x2a10 (en: 'circulation function', MathPlayer: 'circulation function', google: 'zirkulationsfunktion')
+ - "⨑": [T: "Integration gegen den Uhrzeigersinn"] # 0x2a11 (en: 'anticlockwise integration', MathPlayer: 'anticlockwise integration', google: 'integration gegen den uhrzeigersinn')
+ - "⨒": [T: "Linienintegration mit rechteckigem Pfad um die Pole"] # 0x2a12 (en: 'line integration with rectangular path around pole', MathPlayer: 'line integration with rectangular path around pole', google: 'linienintegration mit einem rechteckigen pfad um pol')
+ - "⨓": [T: "Linienintegration mit halbkreisförmigem Pfad um den Pol"] # 0x2a13 (en: 'line integration with semicircular path around pole', MathPlayer: 'line integration with semicircular path around pole', google: 'linienintegration mit halbkreisförmigem pfad um pol')
+ - "⨔": [T: "Leitungsintegration ohne Pole"] # 0x2a14 (en: 'line integration not including the pole', MathPlayer: 'line integration not including the pole', google: 'linienintegration ohne stange')
+ - "⨕": [T: "Integral um einen Punktoperator"] # 0x2a15 (en: 'integral around a point operator', MathPlayer: 'integral around a point operator', google: 'integral um einen punktbetreiber')
+ - "⨖": [T: "quaternion Integral-Operator"] # 0x2a16 (SRE: 'Quaternion Integral Operator')
+ - "⨗": [T: "Integral mit Pfeil nach links mit Haken"] # 0x2a17 (en: 'integral with leftwards arrow with hook', MathPlayer: 'integral with leftwards arrow with hook', google: 'integraler mit linksem pfeil mit haken')
+ - "⨘": [T: "Integral mit Kreuzproduktzeichen"] # 0x2a18 (en: 'integral with times sign', google: 'integral mit times sign')
+ - "⨙": [T: "Integral mit Schnittmenge-Zeichen"] # 0x2a19 (en: 'integral with intersection', google: 'integral mit der kreuzung')
+ - "⨚": [T: "Integral mit Vereinigungs-Zeichen"] # 0x2a1a (en: 'integral with union', google: 'integral mit union')
+ - "⨛": [T: "Integral mit Overbar"] # 0x2a1b (en: 'integral with overbar', google: 'integral mit overbar')
+ - "⨜": [T: "Integral mit Underbar"] # 0x2a1c (en: 'integral with underbar', google: 'integral mit underbar')
+ - "⨝": [T: "Beitreten"] # 0x2a1d (en: 'join', google: 'verbinden')
+ - "⨞": [T: "Großes linkes Dreieckbediener"] # 0x2a1e (en: 'large left triangle operator', google: 'großer linker dreieck operator')
+ - "⨟": [T: "Z-Notationsschema-Zusammensetzung"] # 0x2a1f (en: 'z notation schema composition', google: 'z notationschema -zusammensetzung')
+ - "⨠": [T: "Z-Notationsschema-Piping"] # 0x2a20 (en: 'z notation schema piping', google: 'z notationschema -rohrleitungen')
+ - "⨡": [T: "Z-Notationsschema-Projektion"] # 0x2a21 (en: 'z notation schema projection', google: 'z notationschemaprojektion')
+ - "⨢": [T: "Pluszeichen mit kleinem Kreis oben"] # 0x2a22 (en: 'plus sign with circle above', MathPlayer: 'plus sign with circle above', google: 'plus zeichen mit kreis oben')
+ - "⨣": [T: "Pluszeichen mit Zirkumflex-Akzent oben"] # 0x2a23 (en: 'plus sign with circumflex accent above', MathPlayer: 'plus sign with circumflex accent above', google: 'plus -zeichen mit dem obigen zirkelakzent')
+ - "⨤": [T: "Pluszeichen mit Tilde oben"] # 0x2a24 (en: 'plus sign with tilde above', MathPlayer: 'tilde with plus below', google: 'plus zeichen mit tilde oben')
+ - "⨥": [T: "Pluszeichen mit Punkt unten"] # 0x2a25 (en: 'plus sign with dot below', MathPlayer: 'plus sign with dot below', google: 'plus zeichen mit punkt unten')
+ - "⨦": [T: "Pluszeichen mit Tilde unter"] # 0x2a26 (en: 'plus sign with tilde below', MathPlayer: 'tilde with plus above', google: 'plus zeichen mit tilde unten')
+ - "⨧": [T: "Pluszeichen mit Index Zwei"] # 0x2a27 (en: 'plus sign with subscript two', MathPlayer: 'plus sign with subscript two', google: 'plus sign sign mit dem index two')
+ - "⨨": [T: "Pluszeichen mit schwarzem Dreieck"] # 0x2a28 (en: 'plus sign with black triangle', google: 'plus zeichen mit schwarzem dreieck')
+ - "⨩": [T: "Minuszeichen mit Komma oben"] # 0x2a29 (en: 'minus sign with comma above', MathPlayer: 'minus sign with comma above', google: 'minus zeichen mit komma oben')
+ - "⨪": [T: "Minuszeichen mit Punkt unten"] # 0x2a2a (en: 'minus sign with dot below', MathPlayer: 'minus sign with dot below', google: 'minus zeichen mit punkt unten')
+ - "⨫": [T: "Minuszeichen mit fallenden Punkten"] # 0x2a2b (en: 'minus sign with falling dots', google: 'minus zeichen mit fallenden punkten')
+ - "⨬": [T: "Minuszeichen mit steigenden Punkten"] # 0x2a2c (en: 'minus sign with rising dots', google: 'minus zeichen mit steigenden punkten')
+ - "⨭": [T: "Pluszeichen Im linken Halbkreis"] # 0x2a2d (en: 'plus sign in left half circle', MathPlayer: 'plus sign in left half circle', google: 'plus melden sie sich im linken halbkreis an')
+ - "⨮": [T: "Pluszeichen Im rechten Halbkreis"] # 0x2a2e (en: 'plus sign in right half circle', MathPlayer: 'plus sign in right half circle', google: 'plus im rechten halbkreis anzeigen')
+ - "⨯": [T: "Vektor- oder Kreuzprodukt"] # 0x2a2f (en: 'cross product', MathPlayer: 'vector or cross product', google: 'kreuzprodukt')
+ - "⨰": [T: "Multiplikationszeichen mit Punkt oben"] # 0x2a30 (en: 'multiplication sign with dot above', MathPlayer: 'multiplication sign with dot above', google: 'multiplikationszeichen mit punkt oben')
+ - "⨱": [T: "Multiplikationszeichen mit Unterleiste"] # 0x2a31 (en: 'multiplication sign with underbar', MathPlayer: 'multiplication sign with underbar', google: 'multiplikationszeichen mit underbar')
+ - "⨲": [T: "Semidirektprodukt mit geschlossenem Boden"] # 0x2a32 (en: 'semidirect product with bottom closed', google: 'semidirect -produkt mit unten geschlossen')
+ - "⨳": [T: "smash product"] # 0x2a33
+ - "⨴": [T: "Multiplikationszeichen im linken Halbkreis"] # 0x2a34 (en: 'multiplication sign in left half circle', MathPlayer: 'multiplication sign in left half circle', google: 'multiplikationszeichen im linken halbkreis')
+ - "⨵": [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: "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')
+ - "⨼": [T: "Innenprodukt"] # 0x2a3c (en: 'interior product', MathPlayer: 'interior product', google: 'innenprodukt')
+ - "⨽": [T: "Produkt für den rechten Innenraum"] # 0x2a3d (en: 'righthand interior product', google: 'righthand innenprodukt')
+ - "⨿": [T: "Verschmelzung oder Koprodukt"] # 0x2a3f (en: 'amalgamation or coproduct', MathPlayer: 'amalgamation or coproduct', google: 'verschmelzung oder koprodukt')
+ - "⩀": [T: "Schnittpunkt mit Punkt"] # 0x2a40 (en: 'intersection with dot', MathPlayer: 'intersection with dot', google: 'kreuzung mit punkt')
+ - "⩁": [T: "Union mit Minuszeichen"] # 0x2a41 (en: 'union with minus sign', google: 'gewerkschaft mit minus zeichen')
+ - "⩂": [T: "Union mit Overbar"] # 0x2a42 (en: 'union with overbar', MathPlayer: 'union with overbar', google: 'gewerkschaft mit overbar')
+ - "⩃": [T: "Kreuzung mit Overbar"] # 0x2a43 (en: 'intersection with overbar', MathPlayer: 'intersection with overbar', google: 'kreuzung mit überbär')
+ - "⩄": [T: "Überschneidung mit logischem und"] # 0x2a44 (en: 'intersection with logical and', MathPlayer: 'intersection with logical and', google: 'schnittpunkt mit logisch und')
+ - "⩅": [T: "Vereinigung mit logischem Or"] # 0x2a45 (en: 'union with logical or', MathPlayer: 'union with logical or', google: 'vereinigung mit logisch oder')
+ - "⩆": [T: "Vereinigung über dem Schnittpunkt"] # 0x2a46 (en: 'union above intersection', MathPlayer: 'union above intersection', google: 'union über der kreuzung')
+ - "⩇": [T: "Schnittpunkt über Union"] # 0x2a47 (en: 'intersection above union', MathPlayer: 'intersection above union', google: 'kreuzung über union')
+ - "⩈": [T: "Vereinigung über Stab über Kreuzung"] # 0x2a48 (en: 'union above bar above intersection', MathPlayer: 'union above bar above intersection', google: 'gewerkschaft über der bar über der kreuzung')
+ - "⩉": [T: "Schnittpunkt oberhalb der Stange oberhalb der Union"] # 0x2a49 (en: 'intersection above bar above union', MathPlayer: 'intersection above bar above union', google: 'kreuzung über bar über union')
+ - "⩊": [T: "Union daneben und mit Union verbunden"] # 0x2a4a (en: 'union beside and joined with union', MathPlayer: 'union beside and joined with union', google: 'gewerkschaft neben der union')
+ - "⩋": [T: "Kreuzung neben und mit Kreuzung verbunden"] # 0x2a4b (en: 'intersection beside and joined with intersection', MathPlayer: 'intersection beside and joined with intersection', google: 'kreuzung neben und zusammen mit der kreuzung')
+ - "⩌": [T: "Geschlossene Vereinigung mit Serifen"] # 0x2a4c (en: 'closed union with serifs', MathPlayer: 'closed union with serifs', google: 'geschlossene vereinigung mit serifen')
+ - "⩍": [T: "Geschlossener Schnittpunkt mit Serifen"] # 0x2a4d (en: 'closed intersection with serifs', MathPlayer: 'closed intersection with serifs', google: 'geschlossener kreuzung mit serifen')
+ - "⩎": [T: "Doppelter Quadratschnitt"] # 0x2a4e (en: 'double square intersection', google: 'doppelquadratische kreuzung')
+ - "⩏": [T: "Double Square Union"] # 0x2a4f (en: 'double square union', google: 'doppelquadratische gewerkschaft')
+ - "⩐": [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: "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')
+ - "⩘": [T: "Abfallend großes und"] # 0x2a58 (en: 'sloping large and', MathPlayer: 'sloping large and', google: 'groß und')
+ - "⩙": [T: "Logisch oder Überlappend Logisch Und"] # 0x2a59 (en: 'logical or overlapping logical and', google: 'logisch oder überlappend logisch und')
+ - "⩚": [T: "Logisch und mit Middle Stem"] # 0x2a5a (en: 'logical and with middle stem', MathPlayer: 'logical and with middle stem', google: 'logisch und mit mittlerem stiel')
+ - "⩛": [T: "Logisch oder mit Middle Stem"] # 0x2a5b (en: 'logical or with middle stem', MathPlayer: 'logical or with middle stem', google: 'logisch oder mit mittlerem stiel')
+ - "⩜": [T: "Logisch und mit Horizontalstrich"] # 0x2a5c (en: 'logical and with horizontal dash', MathPlayer: 'logical and with horizontal dash', google: 'logisch und mit horizontalem armaturenbrett')
+ - "⩝": [T: "Logisch oder mit Horizontalstrich"] # 0x2a5d (en: 'logical or with horizontal dash', MathPlayer: 'logical or with horizontal dash', google: 'logisch oder mit horizontalem strich')
+ - "⩞": [T: "Logisch und mit Double Overbar"] # 0x2a5e (en: 'logical and with double overbar', google: 'logisch und mit doppelter überbärung')
+ - "⩟": [T: "Logisch und mit Underbar"] # 0x2a5f (en: 'logical and with underbar', MathPlayer: 'logical and with underbar', google: 'logisch und mit unterbar')
+ - "⩠": [T: "Logisch und mit Double Underbar"] # 0x2a60 (en: 'logical and with double underbar', google: 'logisch und mit doppelter unterbarung')
+ - "⩡": [T: "kleines Vee mit Underbar"] # 0x2a61 (en: 'small vee with underbar', google: 'kleiner vee mit unterbar')
+ - "⩢": [T: "Logisch oder mit Double Overbar"] # 0x2a62 (en: 'logical or with double overbar', google: 'logisch oder mit doppelter überbärung')
+ - "⩣": [T: "Logisch oder mit doppelter Unterleiste"] # 0x2a63 (en: 'logical or with double underbar', google: 'logisch oder mit doppelter unterbarung')
+ - "⩤": [T: "Z-Notation Domain Antirestriction"] # 0x2a64 (en: 'z notation domain antirestriction', google: 'z notation domain antirestriktion')
+ - "⩥": [T: "Z Notationsbereich Antirestriction"] # 0x2a65 (en: 'z notation range antirestriction', google: 'z notation range antirestriktion')
+ - "⩦": [T: "Gleichheitszeichen mit Punkt unten"] # 0x2a66 (en: 'equals sign with dot below', MathPlayer: 'equal with dot below', google: 'gleiches zeichen mit punkt unten')
+ - "⩧": [T: "Identisch mit dem obigen Punkt"] # 0x2a67 (en: 'identical with dot above', google: 'identisch mit punkt oben')
+ - "⩨": [T: "Dreifacher Horizontalbalken mit doppeltem vertikalem Hub"] # 0x2a68 (en: 'triple horizontal bar with double vertical stroke', google: 'dreifache horizontale balken mit doppelter vertikaler hub')
+ - "⩩": [T: "Dreifacher Horizontalbalken mit dreifachem vertikalem Hub"] # 0x2a69 (en: 'triple horizontal bar with triple vertical stroke', google: 'dreifache horizontale stange mit dreifachem vertikalem schlaganfall')
+ - "⩪": [T: "Tilde-Operator mit Punkt oben"] # 0x2a6a (en: 'tilde operator with dot above', MathPlayer: 'tilde with dot', google: 'tilde -operator mit punkt oben')
+ - "⩫": [T: "Tilde-Operator mit steigenden Punkten"] # 0x2a6b (en: 'tilde operator with rising dots', google: 'tilde -operator mit steigenden punkten')
+ - "⩬": [T: "Ähnlich Minus Ähnlich"] # 0x2a6c (en: 'similar minus similar', google: 'ähnlich minus ähnlich')
+ - "⩭": [T: "Kongruent mit Punkt oben"] # 0x2a6d (en: 'congruent with dot above', MathPlayer: 'congruent with dot above', google: 'kongruent mit punkten oben')
+ - "⩮": [T: "Entspricht Asterisk"] # 0x2a6e (en: 'equals with asterisk', google: 'entspricht mit sternchen')
+ - "⩯": [T: "Fast gleichwertig mit dem Circumflex Accent"] # 0x2a6f (en: 'almost equal to with circumflex accent', MathPlayer: 'almost equal to with circumflex accent', google: 'fast gleich mit dem zirkumflexakzent')
+ - "⩰": [T: "Ungefähr gleich oder gleich zu"] # 0x2a70 (en: 'approximately equal to or equal to', google: 'ungefähr gleich oder gleich')
+ - "⩱": [T: "Gleichheitszeichen über Pluszeichen"] # 0x2a71 (en: 'equals sign above plus sign', MathPlayer: 'equals with plus below', google: 'gleiches zeichen oben plus zeichen')
+ - "⩲": [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: "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')
+ - "⩹": [T: "Weniger als mit Circle Inside"] # 0x2a79 (en: 'less than with circle inside', MathPlayer: 'less than with circle inside', google: 'weniger als mit kreis im inneren')
+ - "⩺": [T: "Größer als mit Kreis nach innen"] # 0x2a7a (en: 'greater than with circle inside', MathPlayer: 'greater than with circle inside', google: 'größer als mit kreis im inneren')
+ - "⩻": [T: "Weniger als mit Fragezeichen oben"] # 0x2a7b (en: 'less than with question mark above', MathPlayer: 'less than with question mark above', google: 'weniger als mit fragezeichen oben')
+ - "⩼": [T: "Größer als mit Fragezeichen oben"] # 0x2a7c (en: 'greater than with question mark above', MathPlayer: 'greater than with question mark above', google: 'größer als mit dem obigen fragezeichen')
+ - "⩽": [T: "Weniger als oder schräg gleich"] # 0x2a7d (en: 'less than or slanted equal to', MathPlayer: 'less than or slanted equal to', google: 'weniger als oder schräg gleich')
+ - "⩾": [T: "Größer als oder schräg gleich"] # 0x2a7e (en: 'greater than or slanted equal to', MathPlayer: 'greater than or slanted equal', google: 'größer als oder schräg gleich')
+ - "⩿": [T: "Weniger als oder schräg gleich mit Punkt nach innen"] # 0x2a7f (en: 'less than or slanted equal to with dot inside', MathPlayer: 'less than or slanted equal to with dot inside', google: 'weniger als oder schräg gleich mit punkt im inneren')
+ - "⪀": [T: "Größer als oder schräg gleich mit Punkt nach innen"] # 0x2a80 (en: 'greater than or slanted equal to with dot inside', MathPlayer: 'greater than or slanted equal to with dot inside', google: 'größer als oder schräg gleich mit punkt im inneren')
+ - "⪁": [T: "Weniger als oder schräg gleich mit Punkt oben"] # 0x2a81 (en: 'less than or slanted equal to with dot above', MathPlayer: 'less than or slanted equal to with dot above', google: 'weniger als oder schräg gleich mit punkt oben')
+ - "⪂": [T: "Größer als oder schräg gleich mit Punkt oben"] # 0x2a82 (en: 'greater than or slanted equal to with dot above', MathPlayer: 'greater than or slanted equal to with dot above', google: 'größer als oder schräg gleich mit punkt oben')
+ - "⪃": [T: "Weniger als oder schräg gleich mit Punkt oben rechts"] # 0x2a83 (en: 'less than or slanted equal to with dot above right', MathPlayer: 'less than or slanted equal to with dot above right', google: 'weniger oder schräg gleich mit dem punkt oben rechts')
+ - "⪄": [T: "Größer als oder schräg gleich mit Punkt oben links"] # 0x2a84 (en: 'greater than or slanted equal to with dot above left', MathPlayer: 'greater than or slanted equal to with dot above left', google: 'größer als oder schräg gleich mit punkt oben links')
+ - "⪅": [T: "Weniger als oder ungefähr"] # 0x2a85 (en: 'less than or approximate', google: 'weniger als oder ungefähr')
+ - "⪆": [T: "Größer als oder ungefähr"] # 0x2a86 (en: 'greater than or approximate', google: 'größer als oder ungefähr')
+ - "⪇": [T: "Kleiner als aber nicht gleich"] # 0x2a87 (en: 'less than and single line not equal to', google: 'weniger als und eine einzelne linie nicht gleich')
+ - "⪈": [T: "Größer als aber nicht gleich"] # 0x2a88 (en: 'greater than and single line not equal to', google: 'größer als und eine einzelne linie nicht gleich')
+ - "⪉": [T: "Kleiner als aber nicht ungefähr gleich"] # 0x2a89 (en: 'less than and not approximate', MathPlayer: 'less than but not approximately equal to', google: 'weniger als und nicht ungefähr')
+ - "⪊": [T: "Größer als aber nicht ungefähr gleich"] # 0x2a8a (en: 'greater than and not approximate', MathPlayer: 'greater than but not approximately equal to', google: 'größer als und nicht ungefähr')
+ - "⪋": [T: "Weniger als aber größer als oben"] # 0x2a8b (en: 'less than above double line equal above greater than', google: 'weniger als über der doppelten linie gleich über größer als höher als')
+ - "⪌": [T: "Größer als aber weniger als unten und größer als oben"] # 0x2a8c (en: 'greater than above double line equal above less than', google: 'größer als über der doppelten linie, die über weniger als über weniger als übertroffen werden')
+ - "⪍": [T: "Weniger als oben ähnlich oder gleich"] # 0x2a8d (en: 'less than above similar or equal', MathPlayer: 'less than above similar or equal', google: 'weniger als über ähnlich oder gleich')
+ - "⪎": [T: "Größer als oben ähnlich oder gleich"] # 0x2a8e (en: 'greater than above similar or equal', MathPlayer: 'greater than above similar or equal', google: 'größer als über ähnlich oder gleich')
+ - "⪏": [T: "Weniger als oben ähnlich oben größer als"] # 0x2a8f (en: 'less than above similar above greater than', MathPlayer: 'less than above similar above greater than', google: 'weniger als über ähnlich oben höher als größer als')
+ - "⪐": [T: "Größer als oben Ähnlich oben"] # 0x2a90 (en: 'greater than above similar above less than', MathPlayer: 'greater than above similar above less than', google: 'größer als über ähnlich über ähnlichem')
+ - "⪑": [T: "less than greater than or equal to"] # 0x2a91 (en: 'less than above greater than above double line equal')
+ - "⪒": [T: "greater than less than or equal to"] # 0x2a92 (en: 'greater than above less than above double line equal')
+ - "⪓": [T: "Weniger als oben schräg gleich oben Größer als oben schräg gleich"] # 0x2a93 (en: 'less than above slanted equal above greater than above slanted equal', MathPlayer: 'less than above slanted equal above greater than above slanted equal', google: 'weniger als über dem überdurchschnittlich überdurchschnittlich überdurchschnittlich ist es gleich')
+ - "⪔": [T: "Größer als oben schräg gleich oben kleiner als oben schräg gleich groß"] # 0x2a94 (en: 'greater than above slanted equal above less than above slanted equal', MathPlayer: 'greater than above slanted equal above less than above slanted equal', google: 'größer als über dem schrägen gleich über dem gleichen schrägen gleich')
+ - "⪕": [T: "Schräg gleich oder kleiner als"] # 0x2a95 (en: 'slanted equal to or less than', google: 'schräg gleich oder weniger als')
+ - "⪖": [T: "Schräg gleich oder größer als"] # 0x2a96 (en: 'slanted equal to or greater than', google: 'schräg gleich oder größer als')
+ - "⪗": [T: "Schräg gleich oder kleiner als mit innenliegendem Punkt"] # 0x2a97 (en: 'slanted equal to or less than with dot inside', MathPlayer: 'slanted equal to or less than with dot inside', google: 'schräg gleich oder weniger als mit punkt im inneren')
+ - "⪘": [T: "Schräg gleich oder größer als mit Punkt nach innen"] # 0x2a98 (en: 'slanted equal to or greater than with dot inside', MathPlayer: 'slanted equal to or greater than with dot inside', google: 'schräg gleich oder größer als mit punkt im inneren')
+ - "⪙": [T: "Gleich oder kleiner als"] # 0x2a99 (en: 'double line equal to or less than', MathPlayer: 'equal (double) over less than', google: 'doppellinie gleich oder weniger als')
+ - "⪚": [T: "Gleich oder größer als"] # 0x2a9a (en: 'double line equal to or greater than', MathPlayer: 'equal to or greater than', google: 'doppellinie gleich oder größer als')
+ - "⪛": [T: "Doppelte Linie schräg gleich oder kleiner als"] # 0x2a9b (en: 'double line slanted equal to or less than', google: 'doppelzeile, die gleich oder weniger als weniger als')
+ - "⪜": [T: "Doppelte Linie schräg gleich oder größer als"] # 0x2a9c (en: 'double line slanted equal to or greater than', google: 'doppelte linie schräg gleich oder größer als')
+ - "⪝": [T: "Äquivalent oder kleiner als"] # 0x2a9d (en: 'similar or less than', MathPlayer: 'equivalent to or less than', google: 'ähnlich oder weniger als')
+ - "⪞": [T: "Ähnlich oder größer als"] # 0x2a9e (en: 'similar or greater than', MathPlayer: 'similar or greater than', google: 'ähnlich oder größer als')
+ - "⪟": [T: "Ähnlich oben Weniger als Gleiches Gleichheitszeichen"] # 0x2a9f (en: 'similar above less than above equals sign', MathPlayer: 'similar above less than above equals sign', google: 'ähnlich oben weniger als über oben gleiches zeichen')
+ - "⪠": [T: "Ähnlich oben größer als oben Gleichheitszeichen"] # 0x2aa0 (en: 'similar above greater than above equals sign', MathPlayer: 'similar above greater than above equals sign', google: 'ähnlich oben größer als über oben gleiches zeichen')
+ - "⪡": [T: "Verschachteltes kleiner als"] # 0x2aa1 (en: 'double nested less than', MathPlayer: 'nested less than', google: 'doppelt weniger verschachtelt als')
+ - "⪢": [T: "Verschachteltes größer als"] # 0x2aa2 (en: 'double nested greater than', MathPlayer: 'nested greater than', google: 'doppelt verschachtelt größer als')
+ - "⪣": [T: "Doppelt verschachtelt, weniger als mit Unterleiste"] # 0x2aa3 (en: 'double nested less than with underbar', google: 'doppelte verschachtel weniger als mit underbar')
+ - "⪤": [T: "less than greater than overlay"] # 0x2aa4 (en: 'greater than overlapping less than')
+ - "⪥": [T: "Größer als weniger als"] # 0x2aa5 (en: 'greater than beside less than', MathPlayer: 'greater than beside less than', google: 'größer als weniger als weniger als')
+ - "⪦": [T: "Weniger als durch Kurve geschlossen"] # 0x2aa6 (en: 'less than closed by curve', MathPlayer: 'less than closed by curve', google: 'weniger als durch kurve geschlossen')
+ - "⪧": [T: "Größer als durch Kurve geschlossen"] # 0x2aa7 (en: 'greater than closed by curve', MathPlayer: 'greater than closed by curve', google: 'größer als durch kurve geschlossen')
+ - "⪨": [T: "Weniger als dann geschlossen durch Kurve oberhalb der gleichen Neigung"] # 0x2aa8 (en: 'less than closed by curve above slanted equal', MathPlayer: 'less than closed by curve above slanted equal', google: 'weniger als geschlossen durch kurve über schräg gleich')
+ - "⪩": [T: "Größer als geschlossen durch Kurve oberhalb der gleichen Neigung"] # 0x2aa9 (en: 'greater than closed by curve above slanted equal', MathPlayer: 'greater than closed by curve above slanted equal', google: 'größer als durch kurve über schräg gleich geschlossen')
+ - "⪪": [T: "kleiner als"] # 0x2aaa (en: 'smaller than', MathPlayer: 'smaller than')
+ - "⪫": [T: "Größer als"] # 0x2aab (en: 'larger than', MathPlayer: 'larger than', google: 'größer als')
+ - "⪬": [T: "kleiner als oder gleich"] # 0x2aac (en: 'smaller than or equal to', MathPlayer: 'smaller than or equal to')
+ - "⪭": [T: "Größer als oder gleich"] # 0x2aad (en: 'larger than or equal to', MathPlayer: 'larger than or equal to', google: 'größer als oder gleich')
+ - "⪮": [T: "difference between (variant"] # 0x2aae (en: 'equals sign with bumpy above', MathPlayer: 'difference between (variant)', google: 'gleiches zeichen mit holprigem oben')
+ - "⪯": [T: "Stellt über dem einzeiligen Gleichheitszeichen ein"] # 0x2aaf (en: 'precedes above single line equals sign', MathPlayer: 'precedes above single line equals sign', google: 'vorausgesetzt über ein einzelner zeile ist gleich ein zeichen')
+ - "⪰": [T: "Erfolg über dem einzeiligen Gleichheitszeichen"] # 0x2ab0 (en: 'succeeds above single line equals sign', google: 'nachfolger über eine einzelne zeile gleich zeichen')
+ - "⪱": [T: "Vorangehende Single-Line ist nicht gleich"] # 0x2ab1 (en: 'precedes above single line not equal to', google: 'vor voraussichtlich nicht gleich einzelner linie gleich')
+ - "⪲": [T: "Erfolg über Single-Line nicht gleich"] # 0x2ab2 (en: 'succeeds above single line not equal to', google: 'nachfolger über eine einzelne linie nicht gleich')
+ - "⪳": [T: "Vorangegangenes Gleichheitszeichen"] # 0x2ab3 (en: 'precedes above equals sign', google: 'vor dem gleichen vorzeichen voraus')
+ - "⪴": [T: "Erfolgreich über Gleichheitszeichen"] # 0x2ab4 (en: 'succeeds above equals sign', google: 'nachfolger über gleiches zeichen')
+ - "⪵": [T: "precedes but not equal to"] # 0x2ab5 (en: 'precedes above not equal to')
+ - "⪶": [T: "succeeds but not equal to"] # 0x2ab6 (en: 'succeeds above not equal to')
+ - "⪷": [T: "Vorangegangenes fast gleich zu"] # 0x2ab7 (en: 'precedes above almost equal to', google: 'vor voraussichtlich fast gleich gleich')
+ - "⪸": [T: "Erreicht über fast gleich viel"] # 0x2ab8 (en: 'succeeds above almost equal to', google: 'erfolgreich ist über fast gleich')
+ - "⪹": [T: "Vorangegangene nicht annähernd gleich"] # 0x2ab9 (en: 'precedes above not almost equal to', google: 'vorkommen oben nicht annähernd gleich')
+ - "⪺": [T: "Erreicht oben nicht annähernd gleich"] # 0x2aba (en: 'succeeds above not almost equal to', google: 'es ist nicht annähernd gleich')
+ - "⪻": [T: "Doppelter Vorgänger"] # 0x2abb (en: 'double precedes', MathPlayer: 'double precedes', google: 'double geht vor')
+ - "⪼": [T: "Doppelter Erfolg"] # 0x2abc (en: 'double succeeds', MathPlayer: 'double succeeds', google: 'doppelt erfolgreich')
+ - "⪽": [T: "Teilmenge mit Punkt"] # 0x2abd (en: 'subset with dot', MathPlayer: 'subset of with dot; is included in as sub relation', google: 'untergruppe mit punkt')
+ - "⪾": [T: "Superset mit Punkt"] # 0x2abe (en: 'superset with dot', MathPlayer: 'superset of with dot; includes as sub relation', google: 'superset mit punkt')
+ - "⪿": [T: "Teilmenge mit Pluszeichen unten"] # 0x2abf (en: 'subset with plus sign below', MathPlayer: 'subset with plus sign below', google: 'untergruppe mit pluszeichen unten')
+ - "⫀": [T: "Superset mit Pluszeichen unten"] # 0x2ac0 (en: 'superset with plus sign below', MathPlayer: 'superset with plus sign below', google: 'superset mit plus -zeichen unten')
+ - "⫁": [T: "Teilmenge mit Multiplikationszeichen unten"] # 0x2ac1 (en: 'subset with multiplication sign below', MathPlayer: 'subset with multiplication sign below', google: 'untergruppe mit multiplikationszeichen unten')
+ - "⫂": [T: "Superset mit Multiplikationszeichen unten"] # 0x2ac2 (en: 'superset with multiplication sign below', MathPlayer: 'superset with multiplication sign below', google: 'superset mit multiplikationszeichen unten')
+ - "⫃": [T: "Teilmenge oder gleich mit dem obigen Punkt"] # 0x2ac3 (en: 'subset of or equal to with dot above', MathPlayer: 'subset of or equal to with dot above', google: 'teilmenge von oder gleich mit punkt oben')
+ - "⫄": [T: "Superset von oder gleich mit Punkt oben"] # 0x2ac4 (en: 'superset of or equal to with dot above', MathPlayer: 'superset of or equal to with dot above', google: 'superset von oder gleich mit punkt oben')
+ - "⫅": [T: "Teilmenge des obigen Gleichheitszeichens"] # 0x2ac5 (en: 'subset of above equals sign', google: 'teilmenge von oben gleichen vorzeichen')
+ - "⫆": [T: "Superset des obigen Gleichheitszeichens"] # 0x2ac6 (en: 'superset of above equals sign', google: 'superset von oben gleichen vorzeichen')
+ - "⫇": [T: "approximate subset of"] # 0x2ac7 (en: 'subset of above tilde operator')
+ - "⫈": [T: "approximate superset of"] # 0x2ac8 (en: 'superset of above tilde operator')
+ - "⫉": [T: "Teilmenge von oben fast gleich"] # 0x2ac9 (en: 'subset of above almost equal to', google: 'untergruppe von oben fast gleich')
+ - "⫊": [T: "Superset von oben fast gleichwertig"] # 0x2aca (en: 'superset of above almost equal to', google: 'superset von oben fast gleich')
+ - "⫋": [T: "Teilmenge von oben nicht gleich"] # 0x2acb (en: 'subset above not equal to', google: 'untergruppe oben nicht gleich')
+ - "⫌": [T: "Superset von oben nicht gleich"] # 0x2acc (en: 'superset of above not equal to', google: 'superset von oben nicht gleich')
+ - "⫍": [T: "Platz links Feldbetreiber geöffnet"] # 0x2acd (en: 'square left open box operator', google: 'quadratische linke offene box -bediener')
+ - "⫎": [T: "Rechteckige Box mit offener Box"] # 0x2ace (en: 'square right open box operator', google: 'square right open box operator')
+ - "⫏": [T: "Geschlossener Teilsatz"] # 0x2acf (en: 'closed subset', MathPlayer: 'closed subset', google: 'geschlossene untergruppe')
+ - "⫐": [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: "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')
+ - "⫚": [T: "Heugabel mit T-Stück"] # 0x2ada (en: 'pitchfork with tee top', MathPlayer: 'pitchfork with tee top', google: 'pitchfork mit t -shirt top')
+ - "⫛": [T: "Transversalschnitt"] # 0x2adb (en: 'transversal intersection', MathPlayer: 'transversal intersection', google: 'transversal -kreuzung')
+ - "⫝̸": [T: "Gabelung"] # 0x2adc (en: 'forking', google: 'gabel')
+ - "⫝": [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: "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: "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: "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')
+ - "⫮": [T: "Teilt sich nicht mit umgekehrten Negationsschrägstrich"] # 0x2aee (en: 'does not divide with reversed negation slash', MathPlayer: 'does not divide with reversed negation slash', google: 'teilt sich nicht mit umgekehrter negationsschrägung')
+ - "⫯": [T: "Vertikale Linie mit Kreis oben"] # 0x2aef (en: 'vertical line with circle above', MathPlayer: 'vertical line with circle above', google: 'vertikale linie mit dem obigen kreis')
+ - "⫰": [T: "Vertikale Linie mit Kreis unten"] # 0x2af0 (en: 'vertical line with circle below', MathPlayer: 'vertical line with circle below', google: 'vertikale linie mit kreis unten')
+ - "⫱": [T: "Down Tack mit Kreis unten"] # 0x2af1 (en: 'down tack with circle below', MathPlayer: 'down tack with circle below', google: 'down tack mit kreis unten')
+ - "⫲": [T: "Parallel zum horizontalen Anschlag"] # 0x2af2 (en: 'parallel with horizontal stroke', MathPlayer: 'parallel with horizontal stroke', google: 'parallel zu horizontalem schlaganfall')
+ - "⫳": [T: "Parallel zu Tilde Operator"] # 0x2af3 (en: 'parallel with tilde operator', MathPlayer: 'parallel with tilde operator', google: 'parallel zum tilde -operator')
+ - "⫴": [T: "Dreifache vertikale Balken-Binärbeziehung"] # 0x2af4 (en: 'triple vertical bar binary relation', google: 'triple vertical bar binärbeziehung')
+ - "⫵": [T: "Dreifacher vertikaler Strich mit horizontalem Hub"] # 0x2af5 (en: 'triple vertical bar with horizontal stroke', google: 'dreifache vertikale balken mit horizontalem schlaganfall')
+ - "⫶": [T: "Triple Colon Operator"] # 0x2af6 (en: 'triple colon operator', google: 'dreifacher dickdarmbetreiber')
+ - "⫷": [T: "Dreifach verschachtelt weniger als"] # 0x2af7 (en: 'triple nested less than', google: 'dreifach verschachtelte weniger als')
+ - "⫸": [T: "Dreifach verschachteltes Größeres als"] # 0x2af8 (en: 'triple nested greater than', google: 'dreifach verschachteltes als')
+ - "⫹": [T: "Doppellinie schräg, weniger als oder gleich"] # 0x2af9 (en: 'double line slanted less than or equal to', google: 'doppelzeile, die weniger oder gleich sind')
+ - "⫺": [T: "Doppelte Linie schräg größer als oder gleich"] # 0x2afa (en: 'double line slanted greater than or equal to', google: 'doppelte linie schräg größer als oder gleich')
+ - "⫻": [T: "Dreifache Schrägstrich-Binärbeziehung"] # 0x2afb (en: 'triple solidus binary relation', google: 'triple solidus binärbeziehung')
+ - "⫼": [T: "Großer dreifacher vertikaler Barbediener"] # 0x2afc (en: 'large triple vertical bar operator', google: 'großer dreifacher vertikaler barbetreiber')
+ - "⫽": [T: "Doppelter Schrägstrich-Operator"] # 0x2afd (en: 'double solidus operator', google: 'doppeler solidus -operator')
+ - "⫾": [T: "Weiße vertikale Leiste"] # 0x2afe (en: 'white vertical bar', google: 'weiße vertikale balken')
+ - "⫿": [T: "N-Ary White Vertical Bar"] # 0x2aff (en: 'white vertical bar', google: 'weiße vertikale balken')
+ - "⬀": [T: "North East White Arrow"] # 0x2b00 (en: 'north east white arrow', google: 'north east white arrow')
+ - "⬁": [T: "Nordwestlicher weißer Pfeil"] # 0x2b01 (en: 'north west white arrow', google: 'north west white arrow')
+ - "⬂": [T: "Südostweißer Pfeil"] # 0x2b02 (en: 'south east white arrow', google: 'südostweißer pfeil')
+ - "⬃": [T: "Südwestweißer Pfeil"] # 0x2b03 (en: 'south west white arrow', google: 'south west white arrow')
+ - "⬄": [T: "Linker rechter weißer Pfeil"] # 0x2b04 (en: 'left right white arrow', google: 'links rechts weißer pfeil')
+ - "⬅": [T: "Schwarzer Pfeil nach links"] # 0x2b05 (en: 'leftwards black arrow', google: 'links schwarzer pfeil')
+ - "⬆": [T: "Aufwärts schwarzer Pfeil"] # 0x2b06 (en: 'upwards black arrow', google: 'aufwärts schwarze pfeil')
+ - "⬇": [T: "Abwärts schwarzer Pfeil"] # 0x2b07 (en: 'downwards black arrow', google: 'nach unten schwarzen pfeil')
+ - "⬈": [T: "Schwarzer Nordostpfeil"] # 0x2b08 (en: 'north east black arrow', google: 'nordostschwarzer pfeil')
+ - "⬉": [T: "Nordwestlicher schwarzer Pfeil"] # 0x2b09 (en: 'north west black arrow', google: 'nordwesten schwarzer pfeil')
+ - "⬊": [T: "Schwarzer Südostpfeil"] # 0x2b0a (en: 'south east black arrow', google: 'südostschwarzer pfeil')
+ - "⬋": [T: "Südwestlicher schwarzer Pfeil"] # 0x2b0b (en: 'south west black arrow', google: 'südwesten schwarzer pfeil')
+ - "⬌": [T: "Linker rechter schwarzer Pfeil"] # 0x2b0c (en: 'left right black arrow', google: 'links rechts schwarzer pfeil')
+ - "⬍": [T: "Schwarzer Pfeil nach unten"] # 0x2b0d (en: 'up down black arrow', google: 'runter schwarze pfeil')
+ - "⬎": [T: "Pfeil nach rechts mit Spitze nach unten"] # 0x2b0e (en: 'rightwards arrow with tip downwards', google: 'richtiger pfeil mit tipp nach unten')
+ - "⬏": [T: "Pfeil nach rechts mit Spitze nach oben"] # 0x2b0f (en: 'rightwards arrow with tip upwards', google: 'richtiger pfeil mit tipp nach oben')
+ - "⬐": [T: "Pfeil nach links mit Spitze nach unten"] # 0x2b10 (en: 'leftwards arrow with tip downwards', google: 'links pfeil mit tipp nach unten')
+ - "⬑": [T: "Pfeil nach links mit Spitze nach oben"] # 0x2b11 (en: 'leftwards arrow with tip upwards', google: 'linkspfeil mit tipp nach oben')
+ - "⬒": [T: "Quadrat mit oberer Hälfte schwarz"] # 0x2b12 (en: 'square with top half black', google: 'quadrat mit der oberen halbzeit')
+ - "⬓": [T: "Quadrat mit unterer Hälfte schwarz"] # 0x2b13 (en: 'square with bottom half black', google: 'quadrat mit unterer halb schwarz')
+ - "⬔": [T: "Quadrat mit oberer rechter diagonaler Hälfte schwarz"] # 0x2b14 (en: 'square with upper right diagonal half black', google: 'quadrat mit der oberen rechten diagonalen halbschwarz')
+ - "⬕": [T: "Quadrat mit unterer linker diagonaler Hälfte schwarz"] # 0x2b15 (en: 'square with lower left diagonal half black', google: 'quadrat mit der unteren linken diagonalen halbschwarz')
+ - "⬖": [T: "Diamant mit linker Hälfte schwarz"] # 0x2b16 (en: 'diamond with left half black', google: 'diamant mit linksem halb schwarz')
+ - "⬗": [T: "Diamant mit rechter Hälfte schwarz"] # 0x2b17 (en: 'diamond with right half black', google: 'diamant mit rechter halb schwarz')
+ - "⬘": [T: "Diamant mit oberer Hälfte schwarz"] # 0x2b18 (en: 'diamond with top half black', google: 'diamant mit oberem halben schwarz')
+ - "⬙": [T: "Diamant mit unterer Hälfte schwarz"] # 0x2b19 (en: 'diamond with bottom half black', google: 'diamant mit unterer halb schwarz')
+ - "⬚": [T: "Gepunktetes Quadrat"] # 0x2b1a (en: 'box', google: 'kasten')
+ - "⬛": [T: "Schwarzes großes Quadrat"] # 0x2b1b (en: 'black large square', google: 'schwarzes großes quadrat')
+ - "⬜": [T: "Weißes großes Quadrat"] # 0x2b1c (en: 'white large square', google: 'weiß großes quadrat')
+ - "⬝": [T: "Schwarzes sehr kleines Quadrat"] # 0x2b1d (en: 'black very small square', google: 'schwarz, sehr kleines quadrat')
+ - "⬞": [T: "Weißes sehr kleines Quadrat"] # 0x2b1e (en: 'white very small square', google: 'weiß sehr kleines quadrat')
+ - "⬟": [T: "Schwarzes Pentagon"] # 0x2b1f (en: 'black pentagon', google: 'schwarzes pentagon')
+ - "⬠": [T: "Weißes Pentagon"] # 0x2b20 (en: 'white pentagon', google: 'weißes pentagon')
+ - "⬡": [T: "Weißes Sechseck"] # 0x2b21 (en: 'white hexagon', google: 'weißes sechseck')
+ - "⬢": [T: "Schwarzes Sechseck"] # 0x2b22 (en: 'black hexagon', google: 'schwarzes sechseck')
+ - "⬣": [T: "Horizontales schwarzes Sechseck"] # 0x2b23 (en: 'horizontal black hexagon', google: 'horizontales schwarzes sechseck')
+ - "⬤": [T: "Schwarzer großer Kreis"] # 0x2b24 (en: 'black large circle', google: 'schwarzer großer kreis')
+ - "⬥": [T: "Schwarzer mittlerer Diamant"] # 0x2b25 (en: 'black medium diamond', google: 'schwarzer medium diamond')
+ - "⬦": [T: "Weißer mittlerer Diamant"] # 0x2b26 (en: 'white medium diamond', google: 'weißer medium diamant')
+ - "⬧": [T: "Schwarze mittlere Raute"] # 0x2b27 (en: 'black medium lozenge', google: 'schwarze mittelgroße rauten')
+ - "⬨": [T: "Weiße mittlere Raute"] # 0x2b28 (en: 'white medium lozenge', google: 'weiße mittelgroße rauten')
+ - "⬩": [T: "Schwarzer kleiner Diamant"] # 0x2b29 (en: 'black small diamond', google: 'schwarzer kleiner diamant')
+ - "⬪": [T: "Schwarze kleine Raute"] # 0x2b2a (en: 'black small lozenge', google: 'schwarze kleine rauten')
+ - "⬫": [T: "Weiße kleine Raute"] # 0x2b2b (en: 'white small lozenge', google: 'weiße kleine raute')
+ - "⬬": [T: "Schwarze horizontale Ellipse"] # 0x2b2c (en: 'black horizontal ellipse', google: 'schwarze horizontale ellipse')
+ - "⬭": [T: "Weiße horizontale Ellipse"] # 0x2b2d (en: 'white horizontal ellipse', google: 'weiße horizontale ellipse')
+ - "⬮": [T: "Schwarze vertikale Ellipse"] # 0x2b2e (en: 'black vertical ellipse', google: 'schwarze vertikale ellipse')
+ - "⬯": [T: "Weiße vertikale Ellipse"] # 0x2b2f (en: 'white vertical ellipse', google: 'weiße vertikale ellipse')
+ - "⬰": [T: "Linker Pfeil mit kleinem Kreis"] # 0x2b30 (en: 'left arrow with small circle', google: 'links pfeil mit kleinem kreis')
+ - "⬱": [T: "Drei nach links gerichtete Pfeile"] # 0x2b31 (en: 'three leftwards arrows', google: 'drei linke pfeile')
+ - "⬲": [T: "Linker Pfeil mit Circled Plus"] # 0x2b32 (en: 'left arrow with circled plus', google: 'links pfeil mit eingekreistem plus')
+ - "⬳": [T: "Langer nach links gerichteter Squiggle-Pfeil"] # 0x2b33 (en: 'long leftwards squiggle arrow', google: 'langer linkskundiger pfeil')
+ - "⬴": [T: "Pfeil nach links mit senkrechtem Strich"] # 0x2b34 (en: 'leftwards two headed arrow with vertical stroke', google: 'links zwei köpfe pfeil mit vertikalem schlaganfall')
+ - "⬵": [T: "Doppelpfeil nach links mit doppeltem vertikalem Strich"] # 0x2b35 (en: 'leftwards two headed arrow with double vertical stroke', google: 'links zwei köpfe pfeil mit doppelter vertikaler hub')
+ - "⬶": [T: "Doppelpfeil nach links von der Bar"] # 0x2b36 (en: 'leftwards two headed arrow from bar', google: 'links zwei köpfe pfeil aus der bar')
+ - "⬷": [T: "Pfeil nach links mit zwei Köpfen"] # 0x2b37 (en: 'leftwards two headed triple dash arrow', google: 'links zwei köpfe triple dash pfeil')
+ - "⬸": [T: "Pfeil nach links mit gepunktetem Stamm"] # 0x2b38 (en: 'leftwards arrow with dotted stem', google: 'links pfeil mit gepunktetem stiel')
+ - "⬹": [T: "Pfeil nach links mit Schwanz mit vertikalem Strich"] # 0x2b39 (en: 'leftwards arrow with tail with vertical stroke', google: 'linkspfeil mit schwanz mit vertikalem schlaganfall')
+ - "⬺": [T: "Pfeil nach links mit Schwanz mit doppeltem vertikalem Strich"] # 0x2b3a (en: 'leftwards arrow with tail with double vertical stroke', google: 'linkspfeil mit schwanz mit doppelter vertikaler hub')
+ - "⬻": [T: "Nach links gerichteter zweiköpfiger Pfeil mit Schwanz"] # 0x2b3b (en: 'leftwards two headed arrow with tail', google: 'links zwei köpfe pfeil mit schwanz')
+ - "⬼": [T: "Nach links gerichteter zweiköpfiger Pfeil mit Schwanz mit vertikalem Strich"] # 0x2b3c (en: 'leftwards two headed arrow with tail with vertical stroke', google: 'links zwei köpfe pfeil mit schwanz mit vertikalem schlaganfall')
+ - "⬽": [T: "Nach links gerichteter zweiköpfiger Pfeil mit Schwanz mit doppeltem vertikalem Strich"] # 0x2b3d (en: 'leftwards two headed arrow with tail with double vertical stroke', google: 'links zwei köpfe pfeil mit schwanz mit doppelter vertikaler hub')
+ - "⬾": [T: "Pfeil nach links durch X"] # 0x2b3e (en: 'leftwards arrow through x', google: 'links pfeil durch x')
+ - "⬿": [T: "Wellenpfeil, der direkt nach links zeigt"] # 0x2b3f (en: 'wave arrow pointing directly left', google: 'wellenpfeil direkt nach links zeigen')
+ - "⭀": [T: "Gleichheitszeichen über dem Pfeil nach links"] # 0x2b40 (en: 'equals sign above leftwards arrow', google: 'gleiches zeichen über dem linken pfeil')
+ - "⭁": [T: "Reverse-Tilde-Operator Über Linkspfeil"] # 0x2b41 (en: 'reverse tilde operator above leftwards arrow', google: 'operator umgekehrter tilde über dem linken pfeil')
+ - "⭂": [T: "Pfeil nach links über der Rückseite fast gleich"] # 0x2b42 (en: 'leftwards arrow above reverse almost equal to', google: 'linksspfeil über der rückseite fast gleich')
+ - "⭃": [T: "Pfeil nach rechts durch mehr als"] # 0x2b43 (en: 'rightwards arrow through greater than', google: 'richtiger pfeil durch größer als')
+ - "⭄": [T: "Pfeil nach rechts durch Superset"] # 0x2b44 (en: 'rightwards arrow through superset', google: 'richtiger pfeil durch superset')
+ - "⭅": [T: "Vierfachpfeil nach links"] # 0x2b45 (en: 'leftwards quadruple arrow', google: 'linksvierter pfeil')
+ - "⭆": [T: "Vierfachpfeil nach rechts"] # 0x2b46 (en: 'rightwards quadruple arrow', google: 'richtiger vierfachpfeil')
+ - "⭇": [T: "Reverse-Tilde-Operator über dem Pfeil nach rechts"] # 0x2b47 (en: 'reverse tilde operator above rightwards arrow', google: 'operator umgekehrter tilde oberhalb rechts pfeil')
+ - "⭈": [T: "Pfeil nach rechts oben fast gleich"] # 0x2b48 (en: 'rightwards arrow above reverse almost equal to', google: 'rightwards pfeil über der rückseite fast gleich')
+ - "⭉": [T: "Tilde-Operator über dem Pfeil nach links"] # 0x2b49 (en: 'tilde operator above leftwards arrow', google: 'tilde -operator über linksem pfeil')
+ - "⭊": [T: "Pfeil nach links oben fast gleich"] # 0x2b4a (en: 'leftwards arrow above almost equal to', google: 'links über den pfeil über fast gleich')
+ - "⭋": [T: "Pfeil nach links über Reverse-Tilde-Operator"] # 0x2b4b (en: 'leftwards arrow above reverse tilde operator', google: 'links -pfeil über dem operator des umgekehrten tilde')
+ - "⭌": [T: "Pfeil nach rechts über Reverse-Tilde-Operator"] # 0x2b4c (en: 'rightwards arrow above reverse tilde operator', google: 'rightwards pfeil über dem operator des umgekehrten tilde')
+ - "⭐": [T: "Weißer mittlerer Stern"] # 0x2b50 (en: 'white medium star', MathPlayer: 'white medium star', google: 'weißer mittelstern')
+ - "⭑": [T: "Schwarzer kleiner Stern"] # 0x2b51 (en: 'black small star', MathPlayer: 'black small star', google: 'schwarzer kleiner stern')
+ - "⭒": [T: "Weißer kleiner Stern"] # 0x2b52 (en: 'white small star', MathPlayer: 'white small star', google: 'weißer kleiner stern')
+ - "⭓": [T: "Schwarzes nach rechts zeigendes Pentagon"] # 0x2b53 (en: 'black right pointing pentagon', google: 'schwarzer rechter pentagon')
+ - "⭔": [T: "Weißes nach rechts zeigendes Pentagon"] # 0x2b54 (en: 'white right pointing pentagon', google: 'weißer rechts pentagon')
+ - "⭕": [T: "Schwerer großer Kreis"] # 0x2b55 (en: 'heavy large circle', google: 'schwerer großer kreis')
+ - "⭖": [T: "Schweres Oval mit innenliegendem Oval"] # 0x2b56 (en: 'heavy oval with oval inside', google: 'schweres oval mit oval im inneren')
+ - "⭗": [T: "Schwerer Kreis mit Kreis nach innen"] # 0x2b57 (en: 'heavy circle with circle inside', google: 'schwerer kreis mit kreis im inneren')
+ - "⭘": [T: "Schwerer Kreis"] # 0x2b58 (en: 'heavy circle', google: 'schwerer kreis')
+ - "⭙": [T: "Schwerer eingekreister Saltire"] # 0x2b59 (en: 'heavy circled saltire', google: 'schwer umgekreistes salzire')
+ - "⸀": [T: "rechtswinkel -substitutionsmarker"] # 0x2e00 (en: 'right angle substitution marker', google translation)
+ - "⸁": [T: "rechtswinkel gepunkteter substitutionsmarker"] # 0x2e01 (en: 'right angle dotted substitution marker', google translation)
+ - "⸂": [T: "links -substitution -halterung"] # 0x2e02 (en: 'left substitution bracket', google translation)
+ - "⸃": [T: "richtige substitutionshalterung"] # 0x2e03 (en: 'right substitution bracket', google translation)
+ - "⸄": [T: "links gepunktete substitutionshalterung"] # 0x2e04 (en: 'left dotted substitution bracket', google translation)
+ - "⸅": [T: "richtig gepunktete substitutionshalterung"] # 0x2e05 (en: 'right dotted substitution bracket', google translation)
+ - "⸆": [T: "erhöhter interpolationsmarker"] # 0x2e06 (en: 'raised interpolation marker', google translation)
+ - "⸇": [T: "erhöhter gepunkteter interpolationsmarker"] # 0x2e07 (en: 'raised dotted interpolation marker', google translation)
+ - "⸈": [T: "gepunktete transpositionsmarkermarker"] # 0x2e08 (en: 'dotted transposition marker marker', google translation)
+ - "⸉": [T: "linke transpositionshalterung"] # 0x2e09 (en: 'left transposition bracket', google translation)
+ - "⸊": [T: "rechte transpositionsklasse"] # 0x2e0a (en: 'right transposition bracket', google translation)
+ - "⸋": [T: "erhöhter quadrat"] # 0x2e0b (en: 'raised square', google translation)
+ - "⸌": [T: "links erhöhte unterlassungshalterung"] # 0x2e0c (en: 'left raised omission bracket', google translation)
+ - "⸍": [T: "rechte auslassungshalterung"] # 0x2e0d (en: 'right raised omission bracket', google translation)
+ - "⸎": [T: "redaktionelle coronis"] # 0x2e0e (en: 'editorial coronis', google translation)
+ - "⸏": [T: "absatz"] # 0x2e0f (en: 'paragraphos', google translation)
+ - "⸐": [T: "gabel absätze"] # 0x2e10 (en: 'forked paragraphos', google translation)
+ - "⸑": [T: "umgekehrte gabel absätze"] # 0x2e11 (en: 'reversed forked paragraphos', google translation)
+ - "⸒": [T: "hypodiastole"] # 0x2e12 (google translation)
+ - "⸓": [T: "gepunktete obelos"] # 0x2e13 (en: 'dotted obelos', google translation)
+ - "⸔": [T: "abwärts ancora"] # 0x2e14 (en: 'downwards ancora', google translation)
+ - "⸕": [T: "nach oben ancora"] # 0x2e15 (en: 'upwards ancora', google translation)
+ - "⸖": [T: "gepunktete rechte zeigewinkel"] # 0x2e16 (en: 'dotted right pointing angle', google translation)
+ - "⸗": [T: "doppelter schräger bindestrich"] # 0x2e17 (en: 'double oblique hyphen', google translation)
+ - "⸘": [T: "umgekehrter interrobang"] # 0x2e18 (en: 'inverted interrobang', google translation)
+ - "⸙": [T: "palmenzweig"] # 0x2e19 (en: 'palm branch', google translation)
+ - "⸚": [T: "bindestrich mit diaerese"] # 0x2e1a (en: 'hyphen with diaeresis', google translation)
+ - "⸛": [T: "tilde mit ring oben"] # 0x2e1b (en: 'tilde with ring above', google translation)
+ - "⸜": [T: "links niedrige paraphrasklasse"] # 0x2e1c (en: 'left low paraphrase bracket', google translation)
+ - "⸝": [T: "rechte niedrige paraphrase -klammer"] # 0x2e1d (en: 'right low paraphrase bracket', google translation)
+ - "⸞": [T: "tilde mit punkt oben"] # 0x2e1e (en: 'tilde with dot above', google translation)
+ - "⸟": [T: "tilde mit punkt unten"] # 0x2e1f (en: 'tilde with dot below', google translation)
+ - "⸠": [T: "links vertikale balken mit feder"] # 0x2e20 (en: 'left vertical bar with quill', google translation)
+ - "⸡": [T: "rechte vertikale balken mit feder"] # 0x2e21 (en: 'right vertical bar with quill', google translation)
+ - "⸢": [T: "Obere linke halbe Halterung"] # 0x2e22 (en: 'top left half bracket', google: 'oben links halbe halterung')
+ - "⸣": [T: "Obere rechte halbe Klammer"] # 0x2e23 (en: 'top right half bracket', google: 'oben rechts halbhalterung')
+ - "⸤": [T: "Linke halbe halterung unten"] # 0x2e24 (en: 'bottom left half bracket', google: 'unten linke halbe klammer')
+ - "⸥": [T: "Untere rechte halbe Halterung"] # 0x2e25 (en: 'bottom right half bracket', google: 'unten rechts halbe klammer')
+ - "⸦": [T: "U-Halterung links seitlich"] # 0x2e26 (en: 'left sideways u bracket', google: 'links seitwärts u klammer')
+ - "⸧": [T: "U-Halterung rechts seitlich"] # 0x2e27 (en: 'right sideways u bracket', google: 'rechte seitwärtshalterung')
+ - "⸨": [T: "Linke doppelte Klammer"] # 0x2e28 (en: 'left double parentheses', google: 'links doppelte klammern')
+ - "⸩": [T: "Rechte doppelte Klammer"] # 0x2e29 (en: 'right double parentheses', google: 'rechte doppelte klammern')
+ - "⸪": [T: "zwei punkte über eine punktzahl"] # 0x2e2a (en: 'two dots over one dot punctuation', google translation)
+ - "⸫": [T: "ein punkt über zwei punkte"] # 0x2e2b (en: 'one dot over two dots punctuation', google translation)
+ - "⸬": [T: "quadratische vier punkt -interpunktion"] # 0x2e2c (en: 'squared four dot punctuation', google translation)
+ - "⸭": [T: "fünf punkt mark"] # 0x2e2d (en: 'five dot mark', google translation)
+ - "⸮": [T: "umgekehrter fragezeichen"] # 0x2e2e (en: 'reversed question mark', google translation)
+ - "ⸯ": [T: "vertikale tilde"] # 0x2e2f (en: 'vertical tilde', google translation)
+ - "⸰": [T: "ringpunkt"] # 0x2e30 (en: 'ring point', google translation)
+ - "⸱": [T: "wortseparator mittlerer punkt"] # 0x2e31 (en: 'word separator middle dot', google translation)
+ - "⸲": [T: "drehte komma"] # 0x2e32 (en: 'turned comma', google translation)
+ - "⸳": [T: "erhöhter punkt"] # 0x2e33 (en: 'raised dot', google translation)
+ - "⸴": [T: "erhöhter komma"] # 0x2e34 (en: 'raised comma', google translation)
+ - "⸵": [T: "drehte semikolon"] # 0x2e35 (en: 'turned semicolon', google translation)
+ - "⸶": [T: "dolch mit der linken wache"] # 0x2e36 (en: 'dagger with left guard', google translation)
+ - "⸷": [T: "dolch mit der rechten wache"] # 0x2e37 (en: 'dagger with right guard', google translation)
+ - "⸸": [T: "drehte dolch"] # 0x2e38 (en: 'turned dagger', google translation)
+ - "⸹": [T: "abschnittszeichen der oberen halbzeit"] # 0x2e39 (en: 'top half section sign', google translation)
+ - "⸺": [T: "zwei em -dash"] # 0x2e3a (en: 'two em dash', google translation)
+ - "⸻": [T: "drei em -dash"] # 0x2e3b (en: 'three em dash', google translation)
+ - "〃": [T: "dito mark"] # 0x3003 (en: 'ditto mark', google translation)
+ - "〈": [T: "Linke Winkelklammer"] # 0x3008 (en: 'left angle bracket', google: 'linkswinkelhalter')
+ - "〉": [T: "Rechtwinklige Halterung"] # 0x3009 (en: 'right angle bracket', google: 'rechtswinkelhalterung')
+ - "《": [T: "Linke Doppelwinkelhalterung"] # 0x300a (en: 'left double angle bracket', MathPlayer: 'left double angle bracket', google: 'links zwei winkelhalterungen')
+ - "》": [T: "Rechte Doppelwinkelhalterung"] # 0x300b (en: 'right double angle bracket', MathPlayer: 'right double angle bracket', google: 'rechte doppelwinkelhalterung')
+ - "「": [T: "Linke Eckklammer"] # 0x300c (en: 'left corner bracket', google: 'linke eckhalterung')
+ - "」": [T: "Rechte Eckhalterung"] # 0x300d (en: 'right corner bracket', google: 'rechte eckhalterung')
+ - "『": [T: "Linke weiße Eckhalterung"] # 0x300e (en: 'left white corner bracket', google: 'links weiße eckhalterung')
+ - "』": [T: "Rechte weiße Eckhalterung"] # 0x300f (en: 'right white corner bracket', google: 'rechte weiße eckhalterung')
+ - "【": [T: "Linke schwarze linsenförmige Halterung"] # 0x3010 (en: 'left black lenticular bracket', google: 'links schwarze linsenhalterung')
+ - "】": [T: "Rechte schwarze linsenförmige Halterung"] # 0x3011 (en: 'right black lenticular bracket', google: 'rechte schwarze linsenhalterung')
+ - "〔": [T: "Linke Schildpatt-Klammer"] # 0x3014 (en: 'left tortoise shell bracket', MathPlayer: 'left tortoise shell bracket', google: 'links schildkrötenhalterung')
+ - "〕": [T: "Rechte Schildpattlasche"] # 0x3015 (en: 'right tortoise shell bracket', MathPlayer: 'right tortoise shell bracket', google: 'rechte schildkrötenhalterung')
+ - "〖": [T: "Linke weiße linsenförmige Halterung"] # 0x3016 (en: 'left white lenticular bracket', google: 'links weiße linsenhalterung')
+ - "〗": [T: "Rechte weiße linsenförmige Halterung"] # 0x3017 (en: 'right white lenticular bracket', google: 'rechte weiße linsenhalterung')
+ - "〘": [T: "Linke weiße Schildpatt-Klammer"] # 0x3018 (en: 'left white tortoise shell bracket', google: 'links weiße schildkröte')
+ - "〙": [T: "Rechte weiße Schildpatt-Klammer"] # 0x3019 (en: 'right white tortoise shell bracket', google: 'richtige weiße schildkrabbungshalterung')
+ - "〚": [T: "Linke weiße eckige Klammer"] # 0x301a (en: 'left white square bracket', MathPlayer: 'left white square bracket', google: 'linke weiße quadratklammer')
+ - "〛": [T: "Rechte weiße eckige Klammer"] # 0x301b (en: 'right white square bracket', MathPlayer: 'right white square bracket', google: 'rechte weiße quadratklasse')
+ - "〜": [T: "Wave Dash"] # 0x301c (en: 'wave dash', google: 'wave dash')
+ - "〰": [T: "zigzag"] # 0x3030 (en: 'wavy dash', google: 'welliger armaturenbrett')
+ - "㉈": [T: "eingekreiste Zehn auf schwarzem Quadrat"] # 0x3248 (en: 'circled number ten on black square', google: 'kreiste nummer zehn auf black square')
+ - "㉉": [T: "eingekreiste Zwanzig auf schwarzem Quadrat"] # 0x3249 (en: 'circled number twenty on black square', google: 'kreiste nummer zwanzig auf dem schwarzen quadrat')
+ - "㉊": [T: "eingekreiste Dreißig auf schwarzem Quadrat"] # 0x324a (en: 'circled number thirty on black square', google: 'kreiste nummer dreißig auf dem schwarzen platz')
+ - "㉋": [T: "eingekreiste Vierzig auf schwarzem Quadrat"] # 0x324b (en: 'circled number forty on blacks square', google: 'kreiste nummer vierzig auf dem blacks square')
+ - "㉌": [T: "eingekreiste Fünfzig auf schwarzem Quadrat"] # 0x324c (en: 'circled number fifty on black square', google: 'auf dem schwarzen platz um fünfzig umkreiste')
+ - "㉍": [T: "eingekreiste Sechzig auf schwarzem Quadrat"] # 0x324d (en: 'circled number sixty on black square', google: 'kreiste nummer sechzig auf black square')
+ - "㉎": [T: "eingekreiste Siebzig auf schwarzem Quadrat"] # 0x324e (en: 'circled number seventy on black square', google: 'kreiste nummer siebzig auf dem schwarzen quadrat')
+ - "㉏": [T: "eingekreiste Achtzig auf schwarzem Quadrat"] # 0x324f (en: 'circled number eighty on black square', google: 'eingekreiste nummer auf dem black square')
+ - "㉑": [T: "umkreiste nummer einundzwanzig"] # 0x3251 (en: 'circled number twenty one', google translation)
+ - "㉒": [T: "umkreiste nummer zweiundzwanzig"] # 0x3252 (en: 'circled number twenty two', google translation)
+ - "㉓": [T: "umgekreiste nummer dreiundzwanzig"] # 0x3253 (en: 'circled number twenty three', google translation)
+ - "㉔": [T: "umgekreiste nummer vierundzwanzig"] # 0x3254 (en: 'circled number twenty four', google translation)
+ - "㉕": [T: "umgekreiste nummer fünfundzwanzig"] # 0x3255 (en: 'circled number twenty five', google translation)
+ - "㉖": [T: "umgekreiste nummer 26"] # 0x3256 (en: 'circled number twenty six', google translation)
+ - "㉗": [T: "umgekreiste nummer siebenundzwanzig"] # 0x3257 (en: 'circled number twenty seven', google translation)
+ - "㉘": [T: "umkreiste nummer zwanzig bei"] # 0x3258 (en: 'circled number twenty eight', google translation)
+ - "㉙": [T: "umkreiste nummer neunundzwanzig"] # 0x3259 (en: 'circled number twenty nine', google translation)
+ - "㉚": [T: "umkreiste nummer dreißig"] # 0x325a (en: 'circled number thirty', google translation)
+ - "㉛": [T: "umkreiste nummer einunddreißig"] # 0x325b (en: 'circled number thirty one', google translation)
+ - "㉜": [T: "umkreiste nummer dreiunddreißig"] # 0x325c (en: 'circled number thirty two', google translation)
+ - "㉝": [T: "umkreiste nummer dreiunddreißig"] # 0x325d (en: 'circled number thirty three', google translation)
+ - "㉞": [T: "umkreiste nummer vierunddreißig"] # 0x325e (en: 'circled number thirty four', google translation)
+ - "㉟": [T: "umkreiste nummer fünfunddreißig"] # 0x325f (en: 'circled number thirty five', google translation)
+ - "㊱": [T: "umkreiste nummer dreiunddreißig"] # 0x32b1 (en: 'circled number thirty six', google translation)
+ - "㋌": [T: "quecksilber"] # 0x32cc (en: 'mercury', google translation)
+ - "㋍": [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: "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: "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: "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: "mikrogramm"] # 0x338d (en: 'micrograms', google translation)
+ - "㎎": [T: "milligramm"] # 0x338e (en: 'milligrams', google translation)
+ - "㎏": [T: "kilogramm"] # 0x338f (en: 'kilograms', google translation)
+ - "㎐": [T: "hertz"] # 0x3390 (google translation)
+ - "㎑": [T: "kilohertz"] # 0x3391 (google translation)
+ - "㎒": [T: "megahertz"] # 0x3392 (google translation)
+ - "㎓": [T: "gigahertz"] # 0x3393 (google translation)
+ - "㎔": [T: "terahertz"] # 0x3394 (google translation)
+ - "㎕": [T: "mikroliter"] # 0x3395 (en: 'microliters', google translation)
+ - "㎖": [T: "milliliter"] # 0x3396 (en: 'milliliters', google translation)
+ - "㎗": [T: "dezilierer"] # 0x3397 (en: 'deciliters', google translation)
+ - "㎘": [T: "kiloliter"] # 0x3398 (en: 'kiloliters', google translation)
+ - "㎙": [T: "femtometer"] # 0x3399 (en: 'femtometers', google translation)
+ - "㎚": [T: "nanometer"] # 0x339a (en: 'nanometers', google translation)
+ - "㎛": [T: "mikrometer"] # 0x339b (en: 'micrometers', google translation)
+ - "㎜": [T: "millimeter"] # 0x339c (en: 'millimeters', google translation)
+ - "㎝": [T: "zentimeter"] # 0x339d (en: 'centimeters', google translation)
+ - "㎞": [T: "kilometer"] # 0x339e (en: 'kilometers', google translation)
+ - "㎟": [T: "millimeter quadratisch"] # 0x339f (en: 'millimeters squared', google translation)
+ - "㎠": [T: "zentimeter quadratisch"] # 0x33a0 (en: 'centimeters squared', google translation)
+ - "㎡": [T: "quadratmeter"] # 0x33a1 (en: 'meters squared', google translation)
+ - "㎢": [T: "kilometer quadratisch"] # 0x33a2 (en: 'kilometers squared', google translation)
+ - "㎣": [T: "millimeter gewonnen"] # 0x33a3 (en: 'millimeters cubed', google translation)
+ - "㎤": [T: "zentimeter gewonnen"] # 0x33a4 (en: 'centimeters cubed', google translation)
+ - "㎥": [T: "meter gewonnen"] # 0x33a5 (en: 'meters cubed', google translation)
+ - "㎦": [T: "kilometer gewonnen"] # 0x33a6 (en: 'kilometers cubed', google translation)
+ - "㎧": [T: "meter pro sekunde"] # 0x33a7 (en: 'meters per second', google translation)
+ - "㎨": [T: "meter pro sekunde quadrat"] # 0x33a8 (en: 'meters per second squared', google translation)
+ - "㎩": [T: "pascals"] # 0x33a9 (google translation)
+ - "㎪": [T: "kilopascals"] # 0x33aa (google translation)
+ - "㎫": [T: "megapascals"] # 0x33ab (google translation)
+ - "㎬": [T: "gigapascals"] # 0x33ac (google translation)
+ - "㎭": [T: "rads"] # 0x33ad (google translation)
+ - "㎮": [T: "rads pro sekunde"] # 0x33ae (en: 'rads per second', google translation)
+ - "㎯": [T: "rads pro sekunde quadrat"] # 0x33af (en: 'rads per second squared', google translation)
+ - "㎰": [T: "pikosekunden"] # 0x33b0 (en: 'picoseconds', google translation)
+ - "㎱": [T: "nanosekunden"] # 0x33b1 (en: 'nanoseconds', google translation)
+ - "㎲": [T: "mikrosekunde"] # 0x33b2 (en: 'microseconds', google translation)
+ - "㎳": [T: "millisekunden"] # 0x33b3 (en: 'milliseconds', google translation)
+ - "㎴": [T: "picovolts"] # 0x33b4 (google translation)
+ - "㎵": [T: "nanovolts"] # 0x33b5 (google translation)
+ - "㎶": [T: "mikrovolte"] # 0x33b6 (en: 'microvolts', google translation)
+ - "㎷": [T: "millivolts"] # 0x33b7 (google translation)
+ - "㎸": [T: "kilovolts"] # 0x33b8 (google translation)
+ - "㎹": [T: "megavolts"] # 0x33b9 (google translation)
+ - "㎺": [T: "picowatts"] # 0x33ba (google translation)
+ - "㎻": [T: "nanowatts"] # 0x33bb (google translation)
+ - "㎼": [T: "mikrowatt"] # 0x33bc (en: 'microwatts', google translation)
+ - "㎽": [T: "milliwatt"] # 0x33bd (en: 'milliwatts', google translation)
+ - "㎾": [T: "kilowatt"] # 0x33be (en: 'kilowatts', google translation)
+ - "㎿": [T: "megawatt"] # 0x33bf (en: 'megawatts', google translation)
+ - "㏀": [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: "kubikzentimeter"] # 0x33c4 (en: 'cubic centimeters', google translation)
+ - "㏅": [T: "candelas"] # 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)
+ - "㏉": [T: "grautöne"] # 0x33c9 (en: 'grays', google translation)
+ - "㏊": [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: "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: "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: "p h"] # 0x33d7 (google translation)
+ - "㏘": [T: "picometer"] # 0x33d8 (en: 'picometers', google translation)
+ - "㏙": [T: "teile pro million"] # 0x33d9 (en: 'parts per million', google translation)
+ - "㏚": [T: "petaroentgens"] # 0x33da (google translation)
+ - "㏛": [T: "steradier"] # 0x33db (en: 'steradians', google translation)
+ - "㏜": [T: "sieverts"] # 0x33dc (google translation)
+ - "㏝": [T: "webers"] # 0x33dd (google translation)
+ - "㏞": [T: "volt pro meter"] # 0x33de (en: 'volts per meter', google translation)
+ - "㏟": [T: "verstärker pro meter"] # 0x33df (en: 'amps per meter', google translation)
+ - "㏿": [T: "gallonen"] # 0x33ff (en: 'gallons', google translation)
+ - "": [T: "entspricht mit hut unten"] # 0xe900 (en: 'equals with hat below', google translation)
+ - "": [T: "entspricht plus oben"] # 0xe901 (en: 'equals with plus above', google translation)
+ - "": [T: "entspricht plus unten"] # 0xe902 (en: 'equals with plus below', google translation)
+ - "": [T: "tilde mit plus oben"] # 0xe903 (en: 'tilde with plus above', google translation)
+ - "": [T: "tilde mit plus unten"] # 0xe904 (en: 'tilde with plus below', google translation)
+ - "": [T: "gleich doppelt doppelt über größer als"] # 0xe908 (en: 'equal double over greater than', google translation)
+ - "": [T: "gleich doppelt über weniger als"] # 0xe909 (en: 'equal double over less than', google translation)
+ - "": [T: "enthält oder gleich"] # 0xe90a (en: 'contains or equal to', google translation)
+ - "": [T: "superset von oder gleich"] # 0xe90b (en: 'superset of or equal to', google translation)
+ - "": [T: "teilmenge von oder gleich"] # 0xe90c (en: 'subset of or equal to', google translation)
+ - "": [T: "gleich über weniger als"] # 0xe90d (en: 'equal over less than', google translation)
+ - "": [T: "element von oder gleich"] # 0xe912 (en: 'element of or equal to', google translation)
+ - "": [T: "gleich oder größer als"] # 0xe913 (en: 'equal to or greater than', google translation)
+ - "": [T: "ungefähre superset von"] # 0xe914 (en: 'approximate superset of', google translation)
+ - "": [T: "ungefähre teilmenge von"] # 0xe915 (en: 'approximate subset of', google translation)
+ - "": [T: "superset von with dot enthält als unterbeziehung"] # 0xe916 (en: 'superset of with dot includes as sub relation', google translation)
+ - "": [T: "die teilmenge von mit punkt ist in als sub -relation enthalten"] # 0xe917 (en: 'subset of with dot is included in as sub relation', google translation)
+ - "": [T: "gleich mit punkt unten"] # 0xe918 (en: 'equal with dot below', google translation)
+ - "": [T: "links punkt über minus über den rechten punkt"] # 0xe919 (en: 'left dot over minus over right dot', google translation)
+ - "": [T: "rechter punkt über minus über den linken punkt"] # 0xe91a (en: 'right dot over minus over left dot', google translation)
+ - "": [T: "fast gleich minus"] # 0xe91f (en: 'almost equal to minus', google translation)
+ - "": [T: "doppelter quadratbecher"] # 0xe920 (en: 'double square cup', google translation)
+ - "": [T: "doppelter quadrat in großbuchstaben"] # 0xe921 (en: 'double square cap', google translation)
+ - "": [T: "weniger als gleich oder größer als"] # 0xe922 (en: 'less than equal to or greater than', google translation)
+ - "": [T: "tilde mit punkt"] # 0xe924 (en: 'tilde with dot', google translation)
+ - "": [T: "tilde mit zwei punkten"] # 0xe925 (en: 'tilde with two dots', google translation)
+ - "": [T: "weniger als größer als oder gleich"] # 0xe926 (en: 'less than greater than or equal to', google translation)
+ - "": [T: "größer als weniger als oder gleich"] # 0xe927 (en: 'greater than less than or equal to', google translation)
+ - "": [T: "äquivalent zu oder weniger als"] # 0xe928 (en: 'equivalent to or less than', google translation)
+ - "": [T: "äquivalent zu oder größer als"] # 0xe929 (en: 'equivalent to or greater than', google translation)
+ - "": [T: "links geöffneter box -bediener"] # 0xe92a (en: 'left open box operator', google translation)
+ - "": [T: "rechts öffnen sie den box -bediener"] # 0xe92b (en: 'right open box operator', google translation)
+ - "": [T: "identisch mit punkt"] # 0xe92c (en: 'identical to with dot', google translation)
+ - "": [T: "größer als gleich oder weniger als"] # 0xe92d (en: 'greater than equal to or less than', google translation)
+ - "": [T: "barbetreiber"] # 0xe92e (en: 'bar operator', google translation)
+ - "": [T: "doppelbalkenbetreiber"] # 0xe92f (en: 'double bar operator', google translation)
+ - "": [T: "dreifachbetreiber"] # 0xe930 (en: 'triple bar operator', google translation)
+ - "": [T: "weniger als oder ungefähr gleich"] # 0xe932 (en: 'less than or approximately equal to', google translation)
+ - "": [T: "größer als oder ungefähr gleich"] # 0xe933 (en: 'greater than or approximately equal to', google translation)
+ - "": [T: "weniger als"] # 0xe936 (en: 'nested less than', google translation)
+ - "": [T: "verschachtelt größer als"] # 0xe937 (en: 'nested greater than', google translation)
+ - "": [T: "vorausgeht oder gleichwertig zu"] # 0xe93a (en: 'precedes or equivalent to', google translation)
+ - "": [T: "erfolg oder gleichwertig zu"] # 0xe93b (en: 'succeeds or equivalent to', google translation)
+ - "": [T: "geht über gleich"] # 0xe940 (en: 'precedes over equal', google translation)
+ - "": [T: "erfolgreich über gleich"] # 0xe941 (en: 'succeeds over equal', google translation)
+ - "": [T: "weniger gleicher neigung größer"] # 0xe942 (en: 'less equal slanted greater', google translation)
+ - "": [T: "mehr gleicher neigung weniger"] # 0xe943 (en: 'greater equal slanted less', google translation)
+ - "": [T: "zufrieden von"] # 0xe948 (en: 'satisfied by', google translation)
+ - "": [T: "faul s"] # 0xe949 (en: 'lazy s', google translation)
+ - "": [T: "keine behauptung"] # 0xe94a (en: 'not assertion', google translation)
+ - "": [T: "doppelt gleich"] # 0xe94b (en: 'double equal', google translation)
+ - "": [T: "dreifach gleich"] # 0xe94c (en: 'triple equal', google translation)
+ - "": [T: "regel verzögert"] # 0xe94d (en: 'rule delayed', google translation)
+ - "": [T: "alias gremiter"] # 0xe94e (en: 'alias delimiter', google translation)
+ - "": [T: "normale untergruppe mit bar"] # 0xe950 (en: 'normal subgroup of with bar', google translation)
+ - "": [T: "enthält als normale untergruppe mit balken"] # 0xe951 (en: 'contains as normal subgroup with bar', google translation)
+ - "": [T: "runde impliziert"] # 0xe954 (en: 'round implies', google translation)
+ - "": [T: "lächeln unter der bar"] # 0xe955 (en: 'smile under bar', google translation)
+ - "": [T: "stirnrunzeln über die bar"] # 0xe956 (en: 'frown over bar', google translation)
+ - "": [T: "superset von oder fast gleich"] # 0xe957 (en: 'superset of or almost equal to', google translation)
+ - "": [T: "teilmenge von oder fast gleich"] # 0xe958 (en: 'subset of or almost equal to', google translation)
+ - "": [T: "größer als fast gleich oder weniger als"] # 0xe959 (en: 'greater than almost equal to or less than', google translation)
+ - "": [T: "weniger als fast gleich oder größer als"] # 0xe95a (en: 'less than almost equal or greater than', google translation)
+ - "": [T: "doppelt logisch oder"] # 0xe95c (en: 'double logical or', google translation)
+ - "": [T: "doppelt logisch und"] # 0xe95d (en: 'double logical and', google translation)
+ - "": [T: "logisch oder mit einer doppelten balken unten"] # 0xe95e (en: 'logical or with double bar below', google translation)
+ - "": [T: "logisch oder mit bar unten"] # 0xe95f (en: 'logical or with bar below', google translation)
+ - "": [T: "fast gleich über gleich"] # 0xe962 (en: 'almost equal over equal', google translation)
+ - "": [T: "links zeigter dreieck mit halbierender stange"] # 0xe964 (en: 'left pointing triangle with bisecting bar', google translation)
+ - "": [T: "rechte dreieck mit halbierender balken"] # 0xe965 (en: 'right pointing triangle with bisecting bar', google translation)
+ - "": [T: "entspricht mit gepunkteten top -linien"] # 0xe966 (en: 'equals with dotted top line', google translation)
+ - "": [T: "geht mit dickdarm voraus"] # 0xe967 (en: 'precedes with colon', google translation)
+ - "": [T: "erfolg mit colon"] # 0xe968 (en: 'succeeds with colon', google translation)
+ - "": [T: "kleiner als oder gleich schräg"] # 0xe969 (en: 'smaller than or equal slanted', google translation)
+ - "": [T: "größer oder gleich schräg"] # 0xe96a (en: 'larger than or equal slanted', google translation)
+ - "": [T: "sehr viel weniger verschachtelt als"] # 0xe96b (en: 'nested very much less than', google translation)
+ - "": [T: "sehr viel größer als"] # 0xe96c (en: 'nested very much greater than', google translation)
+ - "": [T: "unterschied zwischen variante"] # 0xe96d (en: 'difference between variant', google translation)
+ - "": [T: "weniger als größer als overlay"] # 0xe96e (en: 'less than greater than overlay', google translation)
+ - "": [T: "logisch oder logisch und overlay"] # 0xe96f (en: 'logical or logical and overlay', google translation)
+ - "": [T: "superset über superset"] # 0xe970 (en: 'superset over superset', google translation)
+ - "": [T: "untergruppe über teilmenge"] # 0xe971 (en: 'subset over subset', google translation)
+ - "": [T: "superset über untergruppe"] # 0xe972 (en: 'superset over subset', google translation)
+ - "": [T: "untergruppe über superset"] # 0xe973 (en: 'subset over superset', google translation)
+ - "": [T: "dreifache vertikale bar"] # 0xe979 (en: 'triple vertical bar', google translation)
+ - "": [T: "gekoppelte vierfache vertikale punkte"] # 0xe97a (en: 'paired quadruple vertical dots', google translation)
+ - "": [T: "senkrecht über bar"] # 0xe97b (en: 'perpendicular over bar', google translation)
+ - "": [T: "linke drehkreuze doppelte vertikale balken"] # 0xe97c (en: 'left turnstile double vertical bar', google translation)
+ - "": [T: "doppelte linke drehklemme doppelte vertikale balken"] # 0xe97d (en: 'double left turnstile double vertical bar', google translation)
+ - "": [T: "senkrecht über invertierte senkrechte"] # 0xe97e (en: 'perpendicular over inverted perpendicular', google translation)
+ - "": [T: "vertikale balken mit doppelter linke"] # 0xe97f (en: 'double left turnstile vertical bar', google translation)
+ - "": [T: "kugelwinkel öffnen sich"] # 0xe980 (en: 'spherical angle opening up', google translation)
+ - "": [T: "doppelter schrägstrich"] # 0xe981 (en: 'double slash', google translation)
+ - "": [T: "rechtwinkel mit ecke"] # 0xe982 (en: 'right angle with corner', google translation)
+ - "": [T: "vertikaler balken"] # 0xe984 (en: 'circled vertical bar', google translation)
+ - "": [T: "umkreiste divisionszeichen"] # 0xe985 (en: 'circled division sign', google translation)
+ - "": [T: "gestrichelten solidus"] # 0xe986 (en: 'dashed solidus', google translation)
+ - "": [T: "gestürztes backslash"] # 0xe987 (en: 'dashed backslash', google translation)
+ - "": [T: "mitten in der mitte"] # 0xe988 (en: 'dashed mid line', google translation)
+ - "": [T: "gestrichelte vertikale balken"] # 0xe989 (en: 'dashed vertical bar', google translation)
+ - "": [T: "senkrecht mit s"] # 0xe98a (en: 'perpendicular with s', google translation)
+ - "": [T: "winkel mit s"] # 0xe98b (en: 'angle with s', google translation)
+ - "": [T: "kugelwinkelöffnung nach links"] # 0xe98c (en: 'spherical angle opening left', google translation)
+ - "": [T: "winkelöffnung links"] # 0xe98d (en: 'angle opening left', google translation)
+ - "": [T: "vertikale balken mit doppelhaken"] # 0xe98e (en: 'vertical bar with double hook', google translation)
+ - "": [T: "mittlerer punktbetreiber freie radikal"] # 0xe98f (en: 'medium dot operator free radical', google translation)
+ - "": [T: "weiß nach oben zeigte dreieck über die bar"] # 0xe990 (en: 'white up pointing triangle above bar', google translation)
+ - "": [T: "identisch und parallel zu"] # 0xe991 (en: 'identical and parallel to', google translation)
+ - "": [T: "produkt zerschlagen"] # 0xe992 (en: 'smash product', google translation)
+ - "": [T: "triple bar operator mit horizontaler balken"] # 0xe993 (en: 'triple bar operator with horizontal bar', google translation)
+ - "": [T: "identisch mit doppelter schrägstrich"] # 0xe994 (en: 'identical to with double slash', google translation)
+ - "": [T: "dreifach gekreuzte riegel"] # 0xe995 (en: 'triple crossed bars', google translation)
+ - "": [T: "vertikaler balken über den kreis"] # 0xe996 (en: 'vertical bar over circle', google translation)
+ - "": [T: "vertikal proportional zu"] # 0xe997 (en: 'vertical proportional to', google translation)
+ - "": [T: "schwarz im letzten quartal mond"] # 0xe998 (en: 'black last quarter moon', google translation)
+ - "": [T: "schwarzer mond im ersten quartal"] # 0xe999 (en: 'black first quarter moon', google translation)
+ - "": [T: "negative sinuswelle"] # 0xe9a0 (en: 'negative sine wave', google translation)
+ - "": [T: "klammern"] # 0xe9a1 (en: 'parenthesized dot', google translation)
+ - "": [T: "klammern"] # 0xe9a2 (en: 'parens', google translation)
+ - "": [T: "weißes lächeln"] # 0xe9a3 (en: 'white smile', google translation)
+ - "": [T: "weißes stirnrunzeln"] # 0xe9a4 (en: 'white frown', google translation)
+ - "": [T: "hexagon"] # 0xe9a5 (google translation)
+ - "": [T: "entspricht über plus"] # 0xe9a6 (en: 'equivalent to over plus', google translation)
+ - "": [T: "plus über gleichwertig zu"] # 0xe9a7 (en: 'plus over equivalent to', google translation)
+ - "": [T: "kreuzungserife"] # 0xe9b0 (en: 'intersection serifs', google translation)
+ - "": [T: "union serife"] # 0xe9b1 (en: 'union serifs', google translation)
+ - "": [T: "square intersection serifen"] # 0xe9b2 (en: 'square intersection serifs', google translation)
+ - "": [T: "square union serifen"] # 0xe9b3 (en: 'square union serifs', google translation)
+ - "": [T: "vor voraussichtlich dem gleichwertigen oder erfolgreich"] # 0xe9e0 (en: 'precedes equivalent to or succeeds', google translation)
+ - "": [T: "erfolgreich ist äquivalent zu oder geht voraus"] # 0xe9e1 (en: 'succeeds equivalent to or precedes', google translation)
+ - "": [T: "vor voraussichtlich fast gleich oder erfolgreich"] # 0xe9e2 (en: 'precedes almost equal to or succeeds', google translation)
+ - "": [T: "ist fast gleich oder voraus"] # 0xe9e3 (en: 'succeeds almost equal to or precedes', google translation)
+ - "": [T: "weniger als äquivalent zu oder größer als"] # 0xe9f0 (en: 'less than equivalent to or greater than', google translation)
+ - "": [T: "größer als äquivalent zu oder weniger als"] # 0xe9f1 (en: 'greater than equivalent to or less than', google translation)
+ - "": [T: "nicht viel weniger als"] # 0xea00 (en: 'not vert much less than', google translation)
+ - "": [T: "nicht viel größer als"] # 0xea01 (en: 'not vert much greater than', google translation)
+ - "": [T: "nicht viel weniger als variante"] # 0xea02 (en: 'not much less than variant', google translation)
+ - "": [T: "nicht viel größer als variante"] # 0xea03 (en: 'not much greater than variant', google translation)
+ - "": [T: "weniger vert doppelt nicht gleich"] # 0xea04 (en: 'less vert not double equals', google translation)
+ - "": [T: "gt vert doppelt nicht gleich"] # 0xea05 (en: 'gt vert not double equals', google translation)
+ - "": [T: "nicht weniger als oder gleich"] # 0xea06 (en: 'not less than or equal to', google translation)
+ - "": [T: "nicht größer als oder gleich"] # 0xea07 (en: 'not greater than or equal to', google translation)
+ - "": [T: "weder gleich noch weniger als"] # 0xea09 (en: 'neither equal to nor less than', google translation)
+ - "": [T: "enthält nicht oder gleich"] # 0xea0a (en: 'does not contain or equal to', google translation)
+ - "": [T: "weder superset von noch gleich"] # 0xea0b (en: 'neither superset of nor equal to', google translation)
+ - "": [T: "weder teilmenge von noch gleich"] # 0xea0c (en: 'neither subset of nor equal to', google translation)
+ - "": [T: "umgekehrte solidus -untergruppe"] # 0xea0d (en: 'reverse solidus subset', google translation)
+ - "": [T: "weder gleich noch größer als"] # 0xea0e (en: 'neither equal to nor greater than', google translation)
+ - "": [T: "nicht minus tilde -operator"] # 0xea0f (en: 'not minus tilde operator', google translation)
+ - "": [T: "weder gleich noch weniger als"] # 0xea10 (en: 'neither equal to nor less than', google translation)
+ - "": [T: "nicht tilde -operator"] # 0xea11 (en: 'not tilde operator', google translation)
+ - "": [T: "kein element von oder gleich"] # 0xea12 (en: 'not element of or equal to', google translation)
+ - "": [T: "weder gleich noch größer als"] # 0xea13 (en: 'neither equal to nor greater than', google translation)
+ - "": [T: "nicht fast gleich"] # 0xea14 (en: 'not almost equal', google translation)
+ - "": [T: "es ist nicht ähnlich erfolgreich"] # 0xea15 (en: 'not succeeds similar', google translation)
+ - "": [T: "weniger oder schräg gleich mit dem schrägstrich"] # 0xea16 (en: 'less than or slanted equal to with slash', google translation)
+ - "": [T: "größer als oder schräg gleich mit dem schrägstrich"] # 0xea17 (en: 'greater than or slanted equal to with slash', google translation)
+ - "": [T: "superset solidus"] # 0xea1a (google translation)
+ - "": [T: "beinhaltet nicht"] # 0xea1b (en: 'does not contain', google translation)
+ - "": [T: "nicht weniger als oder gleich"] # 0xea1d (en: 'not less than or equal to', google translation)
+ - "": [T: "nicht größer als oder gleich"] # 0xea1e (en: 'not greater than or equal to', google translation)
+ - "": [T: "nicht fast gleich minus"] # 0xea1f (en: 'not almost equal to minus', google translation)
+ - "": [T: "negated set -mitgliedschaftsdot oben"] # 0xea22 (en: 'negated set membership dot above', google translation)
+ - "": [T: "kein vertgle"] # 0xea2c (en: 'not vert angle', google translation)
+ - "": [T: "nicht parallel schräg"] # 0xea2d (en: 'not parallel slanted', google translation)
+ - "": [T: "kein barbetreiber"] # 0xea2e (en: 'not bar operator', google translation)
+ - "": [T: "nicht doppelbalkenbetreiber"] # 0xea2f (en: 'not double bar operator', google translation)
+ - "": [T: "nicht dreifacher barbetreiber"] # 0xea30 (en: 'not triple bar operator', google translation)
+ - "": [T: "weniger als aber nicht ungefähr gleich"] # 0xea32 (en: 'less than but not approximately equal to', google translation)
+ - "": [T: "größer als aber nicht ungefähr gleich"] # 0xea33 (en: 'greater than but not approximately equal to', google translation)
+ - "": [T: "weniger als oder nicht gleich"] # 0xea34 (en: 'less than or not equal to', google translation)
+ - "": [T: "größer als oder nicht gleich"] # 0xea35 (en: 'greater than or not equal to', google translation)
+ - "": [T: "nicht weniger verschachtelt als"] # 0xea36 (en: 'not nested less than', google translation)
+ - "": [T: "nicht mehr verschachtelt als"] # 0xea37 (en: 'not nested greater than', google translation)
+ - "": [T: "nicht viel weniger als"] # 0xea38 (en: 'not much less than', google translation)
+ - "": [T: "nicht viel größer als"] # 0xea39 (en: 'not much greater than', google translation)
+ - "": [T: "vor voraussichtlich, aber nicht gleichbedeutend mit"] # 0xea3a (en: 'precedes but not equivalent to', google translation)
+ - "": [T: "erfolg, aber nicht gleichwertig zu"] # 0xea3b (en: 'succeeds but not equivalent to', google translation)
+ - "": [T: "voraus, aber nicht gleich"] # 0xea3c (en: 'precedes but not equal to', google translation)
+ - "": [T: "erfolg, aber nicht gleich"] # 0xea3d (en: 'succeeds but not equal to', google translation)
+ - "": [T: "gleich oder vorausgegangen"] # 0xea3e (en: 'does not equal or precede', google translation)
+ - "": [T: "ist nicht gleich oder erfolgreich"] # 0xea3f (en: 'does not equal or succeed', google translation)
+ - "": [T: "voraus, aber nicht gleich"] # 0xea40 (en: 'precedes but not equal to', google translation)
+ - "": [T: "erfolg, aber nicht gleich"] # 0xea41 (en: 'succeeds but not equal to', google translation)
+ - "": [T: "keine untergruppe von oder gleich"] # 0xea42 (en: 'not subset of nor equal to', google translation)
+ - "": [T: "nicht superset von oder gleich"] # 0xea43 (en: 'not superset of nor equal to', google translation)
+ - "": [T: "teilmenge von oder nicht gleich"] # 0xea44 (en: 'subset of or not equal to', google translation)
+ - "": [T: "superset von oder nicht gleich"] # 0xea45 (en: 'superset of or not equal to', google translation)
+ - "": [T: "keine untergruppe von oder gleich"] # 0xea46 (en: 'not subset of nor equal to', google translation)
+ - "": [T: "nicht superset von oder gleich"] # 0xea47 (en: 'not superset of nor equal to', google translation)
+ - "": [T: "nicht dreifach weniger als"] # 0xea48 (en: 'not triple less than', google translation)
+ - "": [T: "nicht dreifach größer als"] # 0xea49 (en: 'not triple greater than', google translation)
+ - "": [T: "nicht vorausgeht"] # 0xea4c (en: 'not precedes equals', google translation)
+ - "": [T: "nicht erfolgreich ist gleich"] # 0xea4d (en: 'not succeeds equals', google translation)
+ - "": [T: "nicht normale untergruppe mit bar"] # 0xea50 (en: 'not normal subgroup of with bar', google translation)
+ - "": [T: "enthält nicht als normale untergruppe mit balken"] # 0xea51 (en: 'does not contain as normal subgroup with bar', google translation)
+ - "": [T: "kein unterschied zwischen"] # 0xea52 (en: 'not difference between', google translation)
+ - "": [T: "nicht geometrisch äquivalent zu"] # 0xea53 (en: 'not geometrically equivalent to', google translation)
+ - "": [T: "nicht vert ähnlich"] # 0xea54 (en: 'not vert similar', google translation)
+ - "": [T: "nicht gleich oder ähnlich"] # 0xea55 (en: 'not equal or similar', google translation)
+ - "": [T: "nicht verthergestellt"] # 0xea56 (en: 'not vert approximate', google translation)
+ - "": [T: "nicht ungefähr identisch mit"] # 0xea57 (en: 'not approximately identical to', google translation)
+ - "": [T: "nicht holprig gleich"] # 0xea58 (en: 'not bumpy equals', google translation)
+ - "": [T: "keine holprige single gleich"] # 0xea59 (en: 'not bumpy single equals', google translation)
+ - "": [T: "nicht gleicher punkt"] # 0xea5a (en: 'not equal dot', google translation)
+ - "": [T: "umgekehrt nicht äquivalent"] # 0xea5b (en: 'reverse not equivalent', google translation)
+ - "": [T: "nicht quadratische untergruppe"] # 0xea60 (en: 'not square subset', google translation)
+ - "": [T: "nicht quadratischer superset"] # 0xea61 (en: 'not square superset', google translation)
+ - "": [T: "nicht fast gleich über gleich"] # 0xea62 (en: 'not almost equal over equal', google translation)
+ - "": [T: "nicht streng gleich gleich zu"] # 0xea63 (en: 'not strictly equivalent to', google translation)
+ - "": [T: "nicht kongruenter punkt"] # 0xea64 (en: 'not congruent dot', google translation)
+ - "": [T: "rückwärts nicht gleich"] # 0xea65 (en: 'reverse not equal', google translation)
+ - "": [T: "nicht vert -dreieck ist gleich"] # 0xea70 (en: 'not vert left triangle equals', google translation)
+ - "": [T: "nicht vert rechtes dreieck ist gleich"] # 0xea71 (en: 'not vert right triangle equals', google translation)
+ - "": [T: "nicht teilweise"] # 0xea80 (en: 'not partial', google translation)
+ - "": [T: "pfeilverschmutzung extender"] # 0xeb00 (en: 'arrow embellishment extender', google translation)
+ - "": [T: "pfeil nach rechts über pfeil nach links"] # 0xeb01 (en: 'arrow rightwards over arrow leftwards', google translation)
+ - "": [T: "pfeil nach rechts über pfeil nach links"] # 0xeb02 (en: 'arrow rightwards over arrow leftwards', google translation)
+ - "": [T: "harpoon direkt über harpoon links"] # 0xeb03 (en: 'harpoon right over harpoon left', google translation)
+ - "": [T: "harpoon direkt über harpoon links"] # 0xeb04 (en: 'harpoon right over harpoon left', google translation)
+ - "": [T: "doppelpfeil nordöstlich südwest"] # 0xeb05 (en: 'double arrow northeast southwest', google translation)
+ - "": [T: "doppelpfeil nordwestlich südöstlich"] # 0xeb06 (en: 'double arrow northwest southeast', google translation)
+ - "": [T: "horizontaler harpoon -extender"] # 0xeb07 (en: 'horizontal harpoon extender', google translation)
+ - "": [T: "arc links -pfeil gegen den uhrzeigersinn"] # 0xeb08 (en: 'anticlockwise arc leftwards arrow', google translation)
+ - "": [T: "gegen den gegensatz zum arc rightwards pfeil"] # 0xeb09 (en: 'anticlockwise arc rightwards arrow', google translation)
+ - "": [T: "großer rechts pfeilakzent"] # 0xeb0b (en: 'large rightwards arrow accent', google translation)
+ - "": [T: "großer links pfeilakzent"] # 0xeb0c (en: 'large leftwards arrow accent', google translation)
+ - "": [T: "links pfeilspitze"] # 0xeb0d (en: 'leftwards arrowhead', google translation)
+ - "": [T: "rightwards pfeilspitze"] # 0xeb0e (en: 'rightwards arrowhead', google translation)
+ - "": [T: "großer links rechts pfeil mit schlaganfall"] # 0xeb0f (en: 'large left right arrow with stroke', google translation)
+ - "": [T: "horizontaler doppelpfeil -extender"] # 0xeb10 (en: 'horizontal double arrow extender', google translation)
+ - "": [T: "großer links rechts doppelpfeil mit schlaganfall"] # 0xeb11 (en: 'large left right double arrow with stroke', google translation)
+ - "": [T: "abwärts links nach oben auf pfeil"] # 0xeb12 (en: 'downwards arrow leftwards of upwards arrow', google translation)
+ - "": [T: "linkspfeil mit ecke nach unten"] # 0xeb13 (en: 'leftwards arrow with corner downwards', google translation)
+ - "": [T: "rightwards pfeil mit ecke nach oben"] # 0xeb14 (en: 'rightwards arrow with corner upwards', google translation)
+ - "": [T: "links pfeil mit ecke nach oben"] # 0xeb15 (en: 'leftwards arrow with corner upwards', google translation)
+ - "": [T: "gegen den top -semikkreis -pfeil gegen plus gegenüber dem gegen den gegenwart"] # 0xeb16 (en: 'anticlockwise top semicircle arrow with plus', google translation)
+ - "": [T: "im uhrzeigersinn oberen halbkreispfeil mit minus"] # 0xeb17 (en: 'clockwise top semicircle arrow with minus', google translation)
+ - "": [T: "richtiger pfeil mit schwanz mit schlaganfall"] # 0xeb18 (en: 'rightwards arrow with tail with stroke', google translation)
+ - "": [T: "richtige harpune unten"] # 0xeb19 (en: 'right harpoon down', google translation)
+ - "": [T: "ließ harpoon nieder"] # 0xeb1a (en: 'left harpoon down', google translation)
+ - "": [T: "linke rechte harpoon nach unten"] # 0xeb1b (en: 'left right harpoon down', google translation)
+ - "": [T: "linke rechte harpune hoch"] # 0xeb1c (en: 'left right harpoon up', google translation)
+ - "": [T: "die harpune runter links"] # 0xeb1d (en: 'up down harpoon left', google translation)
+ - "": [T: "runter harpoon rechts"] # 0xeb1e (en: 'up down harpoon right', google translation)
+ - "": [T: "auf den pfeil nach unten nach unten am pfeil"] # 0xeb1f (en: 'upwards arrow to the right of downwards arrow', google translation)
+ - "": [T: "links harpoon zur bar mit barb nach oben"] # 0xeb20 (en: 'leftwards harpoon to bar with barb upwards', google translation)
+ - "": [T: "rightwards harpoon zur bar mit barb nach oben"] # 0xeb21 (en: 'rightwards harpoon to bar with barb upwards', google translation)
+ - "": [T: "links harpoon zur bar mit barb nach unten"] # 0xeb22 (en: 'leftwards harpoon to bar with barb downwards', google translation)
+ - "": [T: "rightwards harpoon zur bar mit barb nach unten"] # 0xeb23 (en: 'rightwards harpoon to bar with barb downwards', google translation)
+ - "": [T: "links harpune aus der bar mit barb nach oben"] # 0xeb24 (en: 'leftwards harpoon from bar with barb upwards', google translation)
+ - "": [T: "richtige harpoon aus der bar mit barb nach oben"] # 0xeb25 (en: 'rightwards harpoon from bar with barb upwards', google translation)
+ - "": [T: "links harpoon aus der bar mit barb nach unten"] # 0xeb26 (en: 'leftwards harpoon from bar with barb downwards', google translation)
+ - "": [T: "rightwards harpoon aus der bar mit barb nach unten"] # 0xeb27 (en: 'rightwards harpoon from bar with barb downwards', google translation)
+ - "": [T: "harpune nach oben mit barb nach links"] # 0xeb28 (en: 'upwards harpoon to bar with barb leftwards', google translation)
+ - "": [T: "harpoon nach unten mit barb nach links"] # 0xeb29 (en: 'downwards harpoon to bar with barb leftwards', google translation)
+ - "": [T: "nach oben harpunieren zur bar mit barb rightwards"] # 0xeb2a (en: 'upwards harpoon to bar with barb rightwards', google translation)
+ - "": [T: "harpoon nach unten mit barb rightwards nach unten"] # 0xeb2b (en: 'downwards harpoon to bar with barb rightwards', google translation)
+ - "": [T: "harpoon von bar mit barb nach links nach oben"] # 0xeb2c (en: 'upwards harpoon from bar with barb leftwards', google translation)
+ - "": [T: "harpoon nach unten mit barb links nach unten"] # 0xeb2d (en: 'downwards harpoon from bar with barb leftwards', google translation)
+ - "": [T: "harpoon von bar mit barb rechts nach oben"] # 0xeb2e (en: 'upwards harpoon from bar with barb rightwards', google translation)
+ - "": [T: "harpoon nach unten aus barb mit barb rightwards"] # 0xeb2f (en: 'downwards harpoon from bar with barb rightwards', google translation)
+ - "": [T: "aufwärter pfeil in die bar"] # 0xeb30 (en: 'upwards arrow to bar', google translation)
+ - "": [T: "nach unten pfeil in die bar"] # 0xeb31 (en: 'downwards arrow to bar', google translation)
+ - "": [T: "harpune nach oben links von der abwärtsharpune"] # 0xeb32 (en: 'upwards harpoon to the left of downwards harpoon', google translation)
+ - "": [T: "harpunen nach oben rechts von der abwärtsharpune"] # 0xeb33 (en: 'upwards harpoon to the right of downwards harpoon', google translation)
+ - "": [T: "nach oben pfeilspitze"] # 0xeb34 (en: 'upwards arrowhead', google translation)
+ - "": [T: "nach unten pfeilspitze"] # 0xeb35 (en: 'downwards arrowhead', google translation)
+ - "": [T: "doppelte harpoon mit links nach unten nach rechts barb hoch"] # 0xeb36 (en: 'double harpoon with leftwards barb down rightwards barb up', google translation)
+ - "": [T: "doppelte harpoon mit links nach oben nach oben nach oben nach unten"] # 0xeb37 (en: 'double harpoon with leftwards barb up rightwards barb down', google translation)
+ - "": [T: "pfeil über die bar links"] # 0xeb38 (en: 'leftwards arrow over bar', google translation)
+ - "": [T: "richtiger pfeil über die bar"] # 0xeb39 (en: 'rightwards arrow over bar', google translation)
+ - "": [T: "links pfeil unter der bar"] # 0xeb3a (en: 'leftwards arrow under bar', google translation)
+ - "": [T: "richtiger pfeil unter der bar"] # 0xeb3b (en: 'rightwards arrow under bar', google translation)
+ - "": [T: "links rechts triple pfeil"] # 0xeb3c (en: 'left right triple arrow', google translation)
+ - "": [T: "doppelpfeil nordöstlich südost"] # 0xeb3f (en: 'double arrow northeast southeast', google translation)
+ - "": [T: "gegen den linken halbkreispfeil gegen den uhrzeigersinn"] # 0xeb40 (en: 'anticlockwise left semicircle arrow', google translation)
+ - "": [T: "linker semicircle -pfeil im uhrzeigersinn"] # 0xeb41 (en: 'clockwise left semicircle arrow', google translation)
+ - "": [T: "links geöffneter kreis links rechts pfeil"] # 0xeb42 (en: 'left open circle left right arrow', google translation)
+ - "": [T: "richtiger pfeil über tilde"] # 0xeb44 (en: 'rightwards arrow over tilde', google translation)
+ - "": [T: "links pfeil über tilde"] # 0xeb45 (en: 'leftwards arrow over tilde', google translation)
+ - "": [T: "links harpoon über der bar"] # 0xeb48 (en: 'leftwards harpoon over bar', google translation)
+ - "": [T: "richtige harpoon über bar"] # 0xeb49 (en: 'rightwards harpoon over bar', google translation)
+ - "": [T: "links harpun unter bar"] # 0xeb4a (en: 'leftwards harpoon under bar', google translation)
+ - "": [T: "rightwards harpoon unter bar"] # 0xeb4b (en: 'rightwards harpoon under bar', google translation)
+ - "": [T: "hocke schwarze pfeil nach links"] # 0xeb4c (en: 'squat black leftwards arrow', google translation)
+ - "": [T: "im uhrzeigersinn rechte halbkreispfeil"] # 0xeb50 (en: 'clockwise right semicircle arrow', google translation)
+ - "": [T: "gegen den rechten halbkreisspfeil gegen den uhrzeigersinn"] # 0xeb51 (en: 'anticlockwise right semicircle arrow', google translation)
+ - "": [T: "links offener kreis links rechts harpune"] # 0xeb52 (en: 'left open circle left right harpoon', google translation)
+ - "": [T: "aufwärtsspurte pfeil links von vertikaler balken"] # 0xeb58 (en: 'upwards arrow leftwards of vertical bar', google translation)
+ - "": [T: "abwärts links von vertikaler balken nach unten"] # 0xeb59 (en: 'downwards arrow leftwards of vertical bar', google translation)
+ - "": [T: "aufwärts nach rechts von vertikaler balken"] # 0xeb5a (en: 'upwards arrow rightwards of vertical bar', google translation)
+ - "": [T: "nach unten pfeil nach rechts von vertikaler balken"] # 0xeb5b (en: 'downwards arrow rightwards of vertical bar', google translation)
+ - "": [T: "rightwards pfeil mit erweitertem abwärtshaken"] # 0xeb5c (en: 'rightwards arrow with extended downwards hook', google translation)
+ - "": [T: "pfeil mit linksem pfeil mit verlängertem haken"] # 0xeb5d (en: 'leftwards arrow with extended hook', google translation)
+ - "": [T: "der pfeil nach links mit einem ausgedehnten abwärtshaken"] # 0xeb5e (en: 'leftwards arrow with extended downwards hook', google translation)
+ - "": [T: "richtiger pfeil mit verlängertem haken"] # 0xeb5f (en: 'rightwards arrow with extended hook', google translation)
+ - "": [T: "nicht richtig pfeil wellig"] # 0xeb60 (en: 'not right arrow wavy', google translation)
+ - "": [T: "nicht richtig pfeil gebogen"] # 0xeb61 (en: 'not right arrow curved', google translation)
+ - "": [T: "nach oben harpunieren links von vertikaler bar"] # 0xeb68 (en: 'upwards harpoon leftwards of vertical bar', google translation)
+ - "": [T: "abwärtsharpune links von vertikaler bar"] # 0xeb69 (en: 'downwards harpoon leftwards of vertical bar', google translation)
+ - "": [T: "nach oben harpoon rechts von vertikaler bar"] # 0xeb6a (en: 'upwards harpoon rightwards of vertical bar', google translation)
+ - "": [T: "abwärts harpoon rechts von vertikaler bar"] # 0xeb6b (en: 'downwards harpoon rightwards of vertical bar', google translation)
+ - "": [T: "vertikaler doppelpfeil -extender"] # 0xeb6c (en: 'vertical double arrow extender', google translation)
+ - "": [T: "vertikale harpune mit barb links extender"] # 0xeb6d (en: 'vertical harpoon with barb left extender', google translation)
+ - "": [T: "vertikale harpune mit barb right extender"] # 0xeb6e (en: 'vertical harpoon with barb right extender', google translation)
+ - "": [T: "rechte harpoon über die linke harpoon rechts"] # 0xeb6f (en: 'right harpoon over left harpoon right', google translation)
+ - "": [T: "rechte harpoon über linker harpoon links"] # 0xeb70 (en: 'right harpoon over left harpoon left', google translation)
+ - "": [T: "linke harpoon über die rechte harpoon rechts"] # 0xeb71 (en: 'left harpoon over right harpoon right', google translation)
+ - "": [T: "linke harpoon über die rechte harpoon links"] # 0xeb72 (en: 'left harpoon over right harpoon left', google translation)
+ - "": [T: "pfeil von links von der bar pfeilspitze"] # 0xeb73 (en: 'leftwards arrow from bar arrowhead', google translation)
+ - "": [T: "links nach rechts pfeil von bar extender"] # 0xeb74 (en: 'leftwards rightwards arrow from bar extender', google translation)
+ - "": [T: "links pfeil vom stangenschwanz"] # 0xeb75 (en: 'leftwards arrow from bar tail', google translation)
+ - "": [T: "richtiger pfeil vom stangenschwanz"] # 0xeb76 (en: 'rightwards arrow from bar tail', google translation)
+ - "": [T: "rightwards pfeil von der bar pfeilspitze"] # 0xeb77 (en: 'rightwards arrow from bar arrowhead', google translation)
+ - "": [T: "harpune nach oben aus der bar mit barb links pfeilspitze"] # 0xeb78 (en: 'upwards harpoon from bar with barb leftwards arrowhead', google translation)
+ - "": [T: "rechten pfeil über den linken pfeil nach rechts"] # 0xeb79 (en: 'rightwards arrow over leftwards arrow right', google translation)
+ - "": [T: "rechten pfeil über den linken pfeil nach links"] # 0xeb7a (en: 'rightwards arrow over leftwards arrow left', google translation)
+ - "": [T: "der pfeil nach links nach rechts nach rechts"] # 0xeb7b (en: 'leftwards arrow over rightwards arrow right', google translation)
+ - "": [T: "der pfeil nach links über den pfeil nach rechts links"] # 0xeb7c (en: 'leftwards arrow over rightwards arrow left', google translation)
+ - "": [T: "aufwärter pfeil von der bar pfeilspitze"] # 0xeb7d (en: 'upwards arrow from bar arrowhead', google translation)
+ - "": [T: "aufwärter pfeil vom stangenschwanz"] # 0xeb7e (en: 'upwards arrow from bar tail', google translation)
+ - "": [T: "nach unten pfeil vom stangenschwanz"] # 0xeb7f (en: 'downwards arrow from bar tail', google translation)
+ - "": [T: "nach unten pfeil von pfeilspitzen nach unten"] # 0xeb80 (en: 'downwards arrow from bar arrowhead', google translation)
+ - "": [T: "harpoon nach unten aus der bar mit barb rightwards arrowhead"] # 0xeb81 (en: 'downwards harpoon from bar with barb rightwards arrowhead', google translation)
+ - "": [T: "harpunen nach oben links von harpunenboden nach unten"] # 0xeb82 (en: 'upwards harpoon to the left of downwards harpoon bottom', google translation)
+ - "": [T: "harpunen nach oben links von der abwärtsharpoon extender"] # 0xeb83 (en: 'upwards harpoon to the left of downwards harpoon extender', google translation)
+ - "": [T: "harpoon nach unten links von der harpunenoberseite nach oben"] # 0xeb84 (en: 'downwards harpoon to the left of upwards harpoon top', google translation)
+ - "": [T: "harpunen nach oben links von der abwärtsharpoon -oberseite"] # 0xeb85 (en: 'upwards harpoon to the left of downwards harpoon top', google translation)
+ - "": [T: "harpunen nach unten links von der nach oben nach oben genannten harpoon -extender"] # 0xeb86 (en: 'downwards harpoon to the left of the upwards harpoon extender', google translation)
+ - "": [T: "harpunen nach unten links von der nach oben nach oben genannten harpunenboden"] # 0xeb87 (en: 'downwards harpoon to the left of the upwards harpoon bottom', google translation)
+ - "": [T: "aufwärts nach links nach unten pfeilboden"] # 0xeb88 (en: 'upwards arrow leftwards of downwards arrow bottom', google translation)
+ - "": [T: "nach unten pfeil nach oben von pfeiltop nach oben"] # 0xeb89 (en: 'downwards arrow leftwards of upwards arrow top', google translation)
+ - "": [T: "aufwärts links nach unten pfeiltop"] # 0xeb8a (en: 'upwards arrow leftwards of downwards arrow top', google translation)
+ - "": [T: "abwärts nach links nach oben am pfeil nach oben"] # 0xeb8b (en: 'downwards arrow leftwards of upwards arrow bottom', google translation)
+ - "": [T: "links nach rechts pfeile extender"] # 0xeb8c (en: 'leftwards rightwards arrows extender', google translation)
+ - "": [T: "north east arrow extender"] # 0xeb8d (google translation)
+ - "": [T: "north west arrow extender"] # 0xeb8e (google translation)
+ - "": [T: "daunen zeigen, links"] # 0xec00 (en: 'down pointing brace left', google translation)
+ - "": [T: "daunen zeigen mitte"] # 0xec01 (en: 'down pointing brace mid', google translation)
+ - "": [T: "runter zeigen klammer richtig"] # 0xec02 (en: 'down pointing brace right', google translation)
+ - "": [T: "horizontaler klammer -extender"] # 0xec03 (en: 'horizontal brace extender', google translation)
+ - "": [T: "nach dem zeigen links"] # 0xec04 (en: 'up pointing brace left', google translation)
+ - "": [T: "mitte zeigende klammer"] # 0xec05 (en: 'up pointing brace mid', google translation)
+ - "": [T: "ups-taste-klammer rechts"] # 0xec06 (en: 'up-pointing brace right', google translation)
+ - "": [T: "links vertikale balken"] # 0xec07 (en: 'left vertical bar', google translation)
+ - "": [T: "rechte vertikale balken"] # 0xec08 (en: 'right vertical bar', google translation)
+ - "": [T: "links doppelte vertikale balken"] # 0xec09 (en: 'left double vertical bar', google translation)
+ - "": [T: "rechte doppelte vertikale balken"] # 0xec0a (en: 'right double vertical bar', google translation)
+ - "": [T: "horizontaler bracket extender"] # 0xec0b (en: 'horizontal bracket extender', google translation)
+ - "": [T: "unter quadratischer klammer"] # 0xec0c (en: 'under square bracket', google translation)
+ - "⎵": [T: "Untere eckige Klammer"] # 0x23b5 (en: 'under square bracket', MathPlayer: 'under square bracket', google: 'unter quadratischer klammer')
+ - "": [T: "über quadratischer klammer"] # 0xec0d (en: 'over square bracket', google translation)
+ - "⎴": [T: "Obere eckige Klammer"] # 0x23b4 (en: 'over square bracket', MathPlayer: 'over square bracket', google: 'über quadratischer klammer')
+ - "": [T: "unter der klammer links"] # 0xec0e (en: 'under bracket left', google translation)
+ - "": [T: "unter der klammer rechts"] # 0xec0f (en: 'under bracket right', google translation)
+ - "": [T: "über die klammer ging"] # 0xec10 (en: 'over bracket left', google translation)
+ - "": [T: "über die klammer richtig"] # 0xec11 (en: 'over bracket right', google translation)
+ - "": [T: "links klammern 1"] # 0xec12 (en: 'left parens 1', google translation)
+ - "": [T: "links klammern 2"] # 0xec13 (en: 'left parens 2', google translation)
+ - "": [T: "links klammern 3"] # 0xec14 (en: 'left parens 3', google translation)
+ - "": [T: "links klammern 4"] # 0xec15 (en: 'left parens 4', google translation)
+ - "": [T: "rechte klammer 1"] # 0xec16 (en: 'right parens 1', google translation)
+ - "": [T: "rechte klammer 2"] # 0xec17 (en: 'right parens 2', google translation)
+ - "": [T: "rechte klammer 3"] # 0xec18 (en: 'right parens 3', google translation)
+ - "": [T: "rechte klammer 4"] # 0xec19 (en: 'right parens 4', google translation)
+ - "": [T: "radikal 1"] # 0xec1a (en: 'radical 1', google translation)
+ - "": [T: "radikal 2"] # 0xec1b (en: 'radical 2', google translation)
+ - "": [T: "radikal 3"] # 0xec1c (en: 'radical 3', google translation)
+ - "": [T: "radikal 4"] # 0xec1d (en: 'radical 4', google translation)
+ - "": [T: "radikal 5"] # 0xec1e (en: 'radical 5', google translation)
+ - "": [T: "radikaler boden"] # 0xec1f (en: 'radical bottom', google translation)
+ - "": [T: "radikaler vertikaler erweiterung"] # 0xec20 (en: 'radical vertical extender', google translation)
+ - "": [T: "radikaler oberteil"] # 0xec21 (en: 'radical top', google translation)
+ - "": [T: "links weiße halterung"] # 0xec22 (en: 'left white bracket top', google translation)
+ - "": [T: "links weiße klammer extender"] # 0xec23 (en: 'left white bracket extender', google translation)
+ - "": [T: "links weiße halterung"] # 0xec24 (en: 'left white bracket bottom', google translation)
+ - "": [T: "rechte weiße halterung"] # 0xec25 (en: 'right white bracket top', google translation)
+ - "": [T: "rechte weiße klammer extender"] # 0xec26 (en: 'right white bracket extender', google translation)
+ - "": [T: "rechte weiße halterung unten"] # 0xec27 (en: 'right white bracket bottom', google translation)
+ - "": [T: "links weiße lockige klammer"] # 0xec30 (en: 'left white curly bracket', google translation)
+ - "": [T: "rechte weiße lockige klammer"] # 0xec31 (en: 'right white curly bracket', google translation)
+ - "": [T: "langes divisionszeichen"] # 0xec32 (en: 'long division sign', google translation)
+ - "": [T: "langes divisionszeichen extender"] # 0xec33 (en: 'long division sign extender', google translation)
+ - "": [T: "kurze division"] # 0xec34 (en: 'short division', google translation)
+ - "": [T: "doppelte südwest nach nordost -em bond"] # 0xec40 (en: 'double southwest to northeast em bond', google translation)
+ - "": [T: "doppelte nordwestlich nach südost -em bond"] # 0xec41 (en: 'double northwest to southeast em bond', google translation)
+ - "": [T: "einzelne horizontale em -bindung"] # 0xec42 (en: 'single horizontal em bond', google translation)
+ - "": [T: "doppelte horizontale em -bindung"] # 0xec43 (en: 'double horizontal em bond', google translation)
+ - "": [T: "dreifache horizontale em -bond"] # 0xec44 (en: 'triple horizontal em bond', google translation)
+ - "": [T: "single vertikale em -bindung"] # 0xec45 (en: 'single vertical em bond', google translation)
+ - "": [T: "doppelte vertikale em -bindung"] # 0xec46 (en: 'double vertical em bond', google translation)
+ - "": [T: "dreifache vertikale em -bond"] # 0xec47 (en: 'triple vertical em bond', google translation)
+ - "": [T: "weniger als em bond"] # 0xec48 (en: 'less than em bond', google translation)
+ - "": [T: "größer als die em -bindung"] # 0xec49 (en: 'greater than em bond', google translation)
+ - "": [T: "einzelne horizontale bond"] # 0xec4a (en: 'single horizontal en bond', google translation)
+ - "": [T: "doppelte horizontale bond"] # 0xec4b (en: 'double horizontal en bond', google translation)
+ - "": [T: "dreifache horizontaler bond"] # 0xec4c (en: 'triple horizontal en bond', google translation)
+ - "": [T: "oben links rechteck"] # 0xec80 (en: 'top left rectangle', google translation)
+ - "": [T: "unten links rechteck"] # 0xec81 (en: 'bottom left rectangle', google translation)
+ - "": [T: "oben rechts rechteck"] # 0xec90 (en: 'top right rectangle', google translation)
+ - "": [T: "unten rechts rechteck"] # 0xec91 (en: 'bottom right rectangle', google translation)
+ - "": [T: "synthetische division ecke"] # 0xec92 (en: 'synthetic division corner', google translation)
+ - "": [T: "horizontale erweiterung der synthetischen teilung"] # 0xec93 (en: 'synthetic division horizontal extender', google translation)
+ - "": [T: "vertikale extender der synthetischen spaltung"] # 0xec94 (en: 'synthetic division vertical extender', google translation)
+ - "": [T: "verlängerung des linken deckenbodens"] # 0xec95 (en: 'left ceiling floor extender', google translation)
+ - "": [T: "rechte deckenboden erweiterung"] # 0xec96 (en: 'right ceiling floor extender', google translation)
+ - "": [T: "über klammer extender"] # 0xec97 (en: 'over bracket extender', google translation)
+ - "": [T: "vertikaler balken -erweiterung"] # 0xec98 (en: 'vertical bar extender', google translation)
+ - "": [T: "links doppelter vertikaler balken -extender"] # 0xec99 (en: 'left double vertical bar extender', google translation)
+ - "": [T: "horizontaler balken -erweiterung"] # 0xec9a (en: 'horizontal bar extender', google translation)
+ - "": [T: "unter der klammer extender"] # 0xec9c (en: 'under bracket extender', google translation)
+ - "": [T: "runter zeigen klammern nach rechts"] # 0xec9d (en: 'down pointing paren right', google translation)
+ - "": [T: "down -zeigen von klammern extender"] # 0xec9e (en: 'down pointing paren extender', google translation)
+ - "": [T: "down -zeigen von klammern übrig"] # 0xec9f (en: 'down pointing paren left', google translation)
+ - "": [T: "überzüge klammer -extender"] # 0xeca0 (en: 'up pointing brace extender', google translation)
+ - "": [T: "übergreifende klammern übrig"] # 0xeca1 (en: 'up pointing paren left', google translation)
+ - "": [T: "übergezeigte klammern"] # 0xeca2 (en: 'up pointing paren extender', google translation)
+ - "": [T: "übereinstimmung mit klammern richtig"] # 0xeca3 (en: 'up pointing paren right', google translation)
+ - "": [T: "down spointing acker extender"] # 0xeca4 (en: 'down pointing brace extender', google translation)
+ - "": [T: "planck konstant über zwei pi -bar"] # 0xed00 (en: 'planck constant over two pi bar', google translation)
+ - "": [T: "spiegel g"] # 0xed01 (en: 'mirror g', google translation)
+ - "": [T: "dotless j"] # 0xed02 (google translation)
+ - "": [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
+
+# The private use chars are from MathType
+ - "": [T: "integralschleife gegen den gegensatz zu contour -kontur"] # 0xee00 (en: 'anticlockwise contour integral loop', google translation)
+ - "": [T: "contour integral loop im uhrzeigersinn"] # 0xee01 (en: 'clockwise contour integral loop', google translation)
+ - "": [T: ""] # 0xee04
+ - "": [T: ""] # 0xee05
+ - "": [T: ""] # 0xee06
+ - "": [T: ""] # 0xee07
+ - "": [T: ""] # 0xee08
+ - "": [T: ""] # 0xee09
+ - "": [T: ""] # 0xee0a
+ - "": [T: ""] # 0xee0b
+ - "": [T: ""] # 0xee0c
+ - "": [T: "gemeinsame statusverzerrung"] # 0xee0d (en: 'joint status embellishment', google translation)
+ - "": [T: "gemeinsame statusverzerrung übrig"] # 0xee0e (en: 'joint status embellishment left', google translation)
+ - "": [T: "gemeinsame statusverzerrung recht"] # 0xee0f (en: 'joint status embellishment right', google translation)
+ - "": [T: "gemeinsamer statusverzerrungserweiterung"] # 0xee10 (en: 'joint status embellishment extender', google translation)
+ - "": [T: "integralschleife"] # 0xee11 (en: 'integral loop', google translation)
+ - "": [T: "integral loop double"] # 0xee12 (google translation)
+ - "": [T: "integral loop triple"] # 0xee13 (google translation)
+ - "": [T: "erweiterung integraler schleife doppel"] # 0xee15 (en: 'expanding integral loop double', google translation)
+ - "": [T: "erweiterung integraler schleife triple"] # 0xee16 (en: 'expanding integral loop triple', google translation)
+ - "": [T: "asymptotisch gleich dem akzent"] # 0xee17 (en: 'asymptotically equal to accent', google translation)
+ - "": [T: "gleicher zeichenakzent"] # 0xee18 (en: 'equal sign accent', google translation)
+ - "": [T: "vierfache prime"] # 0xee19 (en: 'quadruple prime', google translation)
+ - "": [T: "balkenakzent mit offenem kreis links"] # 0xee1a (en: 'bar accent with open circle left', google translation)
+ - "": [T: "barakzent mit geschlossenem kreis links"] # 0xee1b (en: 'bar accent with closed circle left', google translation)
+ - "": [T: "barakzent mit offenem kreis rechts"] # 0xee1c (en: 'bar accent with open circle right', google translation)
+ - "": [T: "barakzent mit over dot"] # 0xee1d (en: 'bar accent with over dot', google translation)
+ - "": [T: "barakzent mit under dot"] # 0xee1e (en: 'bar accent with under dot', google translation)
+ - "": [T: "barakzent mit double over dot"] # 0xee1f (en: 'bar accent with double over dot', google translation)
+ - "": [T: "barakzent mit double under dot"] # 0xee20 (en: 'bar accent with double under dot', google translation)
+ - "": [T: "barakzent mit pflege"] # 0xee21 (en: 'bar accent with caret', google translation)
+ - "": [T: "dick unter dem stabakzent"] # 0xee22 (en: 'thick under bar accent', google translation)
+ - "": [T: "barakzent mit geschlossenem kreis rechts"] # 0xee23 (en: 'bar accent with closed circle right', google translation)
+ - "": [T: "großer punkt oben"] # 0xee24 (en: 'large dot above', google translation)
+ - "": [T: "ausrichtung mark"] # 0xef00 (en: 'alignment mark', google translation)
+ - "": [T: ""] # 0xef01
+ - "": [T: ""] # 0x200b
+ - "": [T: ""] # 0xef02
+ - " ": [T: ""] # 0x2009
+ - "": [T: ""] # 0xef03
+ - " ": [T: ""] # 0x205f
+ - "": [T: ""] # 0xef04
+ - "": [T: ""] # 0xef05
+ - " ": [T: ""] # 0x2003
+ - "": [T: ""] # 0xef06
+ - "": [T: ""] # 0xef07
+ - "": [T: ""] # 0xef08
+ - "": [T: ""] # 0xef09
+ - "": [T: ""] # 0xef0a
+ - " ": [T: ""] # 0x200a
+ - "": [T: ""] # 0xef22
+ - "": [T: ""] # 0xef23
+ - "": [T: ""] # 0xef24
+ - "": [T: ""] # 0xef29
+ - "": [T: "fehlender begriff"] # 0xef41 (en: 'missing term', google translation)
+ - "": [T: "contour -integralpfeil im uhrzeigersinn links"] # 0xef80 (en: 'clockwise contour integral arrow on left', google translation)
+ - "": [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: "null mit schrägstrich"] # 0xef91 (en: 'zero with slash', google translation)
+
+ # fraktur chars in math alphabetic block and also MathType private use area
+ # Some of these are reserved because they were used in Plane 0 -- that shouldn't be an issue other than causing the other chars to not display
+ - "𝔄-𝔜": # 0x1d504 - 0x1d51d ('z' version is reserved)
+ - T: "fraktur" # (google translation)
+ - spell: "translate('.', '𝔄𝔅𝔇𝔈𝔉𝔊𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔𝔖𝔗𝔘𝔙𝔚𝔛𝔜', 'ABCDEFGHIJKLMNOPQRSTUVWXY')"
+
+ - "-": # 0xf000 - 0xf018
+ - T: "fraktur" # (google translation)
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXY')"
+
+ - "𝔞-𝔷": # 0x1d51e - 0x1d537
+ - T: "fraktur" # (google translation)
+ - spell: "translate('.', '𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷', 'abcdefghijklmnopqrstuvwxyz')"
+ - "-": # 0xf01a - 0xf033
+ - T: "fraktur" # (google translation)
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "𝕬-𝖅": # 0x1D56C - 0x1D585
+ - T: "fraktur mutig" # (en: 'fraktur bold', google translation)
+ - spell: "translate('.', '𝕬𝕭𝕮𝕯𝕰𝕱𝕲𝕳𝕴𝕵𝕶𝕷𝕸𝕹𝕺𝕻𝕼𝕽𝕾𝕿𝖀𝖁𝖂𝖃𝖄𝖅', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf040 - 0xf059
+ - T: "fraktur mutig" # (en: 'fraktur bold', google translation)
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝖆-𝖟": # 0x1d586 - 0x1d59f
+ - T: "fraktur mutig" # (en: 'fraktur bold', google translation)
+ - spell: "translate('.', '𝖆𝖇𝖈𝖉𝖊𝖋𝖌𝖍𝖎𝖏𝖐𝖑𝖒𝖓𝖔𝖕𝖖𝖗𝖘𝖙𝖚𝖛𝖜𝖝𝖞𝖟', 'abcdefghijklmnopqrstuvwxyz')"
+ - "-": # 0xf05a - 0xf073
+ - T: "fraktur mutig" # (en: 'fraktur bold', google translation)
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ # double struck (blackboard bold) chars in math alphabetic block and also MathType private use area
+ # Some of these are reserved because they were used in Plane 0 -- that shouldn't be an issue other than causing the other chars to not display
+ - "𝔸-𝕐": # 0x1d504 - 0x1d51d ('z' version is reserved)
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "doppelt geschlagen"] # (en: 'double struck', google translation)
+ - spell: "translate('.', '𝔸𝔹𝔻𝔼𝔽𝔾𝕀𝕁𝕂𝕃𝕄𝕆𝕊𝕋𝕌𝕍𝕎𝕏𝕐', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf080 - 0xf098
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "doppelt geschlagen"] # (en: 'double struck', google translation)
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝕒-𝕫": # 0x1d552 - 0x1d56b
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "doppelt geschlagen"] # (en: 'double struck', google translation)
+ - spell: "translate('.', '𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫', 'abcdefghijklmnopqrstuvwxyz')"
+ - "-": # 0xf09a - 0xf0b3
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "doppelt geschlagen"] # (en: 'double struck', google translation)
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+ - "𝟘-𝟡": # 0x1d7d8 - 0x1d7e1
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "doppelt geschlagen"] # (en: 'double struck', google translation)
+ - spell: "translate('.', '𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡', '0123456789')"
+ - "-": # 0xf0c0 - 0xf0c9
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "doppelt geschlagen"] # (en: 'double struck', google translation)
+ - spell: "translate('.', '', '0123456789')"
+
+ - "": [T: "doppelt geschlagen nabla"] # 0xf0ca (en: 'double struck nabla', google translation)
+ - "": [T: "doppelt geschlagene euler konstant"] # 0xf0cb (en: 'double struck euler constant', google translation)
+
+ # script chars in math alphabetic block and also MathType private use area
+ - "𝒜-𝒵": # 0x1d49c - 0x1d4b5
+ - T: "skript" # (en: 'script', google translation)
+ - spell: "translate('.', '𝒜𝒞𝒟𝒢𝒥𝒦𝒩𝒪𝒫𝒬𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf100 - 0xf119
+ - T: "skript" # (en: 'script', google translation)
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝒶-𝓏": # 0x1d4b6 - 0x1d4cf
+ - T: "skript" # (en: 'script', google translation)
+ - spell: "translate('.', '𝒶𝒷𝒸𝒹𝒻𝒽𝒾𝒿𝓀𝓁𝓂𝓃𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏', 'abcdefghijklmnopqrstuvwxyz')"
+ - "-": # 0xf11a - 0xf133
+ - T: "skript" # (en: 'script', google translation)
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ # bold script chars in math alphabetic block and also MathType private use area
+ - "𝓐-𝓩": # 0x1d4d0 - 0x1d4e9
+ - T: "skript mutig" # (en: 'script bold', google translation)
+ - spell: "translate('.', '𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf140 - 0xf159
+ - T: "skript mutig" # (en: 'script bold', google translation)
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝓪-𝔃": # 0x1d4ea - 0x1d503
+ - T: "skript mutig" # (en: 'script bold', google translation)
+ - spell: "translate('.', '𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃', 'abcdefghijklmnopqrstuvwxyz')"
+ - "-": # 0xf15a - 0xf173
+ - T: "skript mutig" # (en: 'script bold', google translation)
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "-": # 0xf180 - 0xf199
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "": # 0xf19a
+ - test:
+ if: "$CapitalLetters_Beep"
+ then:
+ - audio:
+ value: "beep.mp4"
+ replace: []
+ - test:
+ if: "$CapitalLetters_UseWord"
+ then_test:
+ if: "$SpeechOverrides_CapitalLetters = ''"
+ then_test:
+ if: "$Impairment = 'Blindness'"
+ then: [T: "großbuchstaben"] # (en: 'cap', google translation)
+ else: [x: "$SpeechOverrides_CapitalLetters"]
+ - pitch:
+ value: "$CapitalLetters_Pitch"
+ replace: [T: "ligatur ae"] # (en: 'ligature ae', google translation)
+ - "": # 0xf19b
+ - test:
+ if: "$CapitalLetters_Beep"
+ then:
+ - audio:
+ value: "beep.mp4"
+ replace: []
+ - test:
+ if: "$CapitalLetters_UseWord"
+ then_test:
+ if: "$SpeechOverrides_CapitalLetters = ''"
+ then_test:
+ if: "$Impairment = 'Blindness'"
+ then: [T: "großbuchstaben"] # (en: 'cap', google translation)
+ else: [x: "$SpeechOverrides_CapitalLetters"]
+ - pitch:
+ value: "$CapitalLetters_Pitch"
+ replace: [T: "scharfes s"] # (en: 'sharp s', google translation)
+ - "": # 0xf19c
+ - test:
+ if: "$CapitalLetters_Beep"
+ then:
+ - audio:
+ value: "beep.mp4"
+ replace: []
+ - test:
+ if: "$CapitalLetters_UseWord"
+ then_test:
+ if: "$SpeechOverrides_CapitalLetters = ''"
+ then_test:
+ if: "$Impairment = 'Blindness'"
+ then: [T: "großbuchstaben"] # (en: 'cap', google translation)
+ else: [x: "$SpeechOverrides_CapitalLetters"]
+ - pitch:
+ value: "$CapitalLetters_Pitch"
+ replace: [T: "o mit schlaganfall"] # (en: 'o with stroke', google translation)
+
+ # MathType only has a few of the cap Greek letters in PUA
+ - "": # 0xf201 - 0xf209
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "doppelt geschlagen"] # (en: 'double struck', google translation)
+ - spell: "translate('.', '', 'ΔΨΛΠΣΘΓΩΥ')"
+
+ - "-": # 0xf220 - 0xf236
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "doppelt geschlagen"] # (en: 'double struck', google translation)
+ - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+
+ - "": [T: "doppelt geschlagenes final sigma"] # 0xf237 (en: 'double struck final sigma', google translation)
+ - "": [T: "doppelte rho geschlagen"] # 0xf250 (en: 'double struck rho', google translation)
+ - "": [T: "doppelt geschlagen phi"] # 0xf251 (en: 'double struck phi', google translation)
+ - "𝐀-𝐙": # 0x1d400 - 0x1d419
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf260 - 0xf279
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝐚-𝐳": # 0x1d41a - 0x1d433
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "-": # 0xf27a - 0xf293
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "𝐴-𝑍": # 0x1d434 - 0x1d44d
+ - spell: "translate('.', '𝐴𝐵𝐶𝐷𝐸𝐹𝐺𝐻𝐼𝐽𝐾𝐿𝑀𝑁𝑂𝑃𝑄𝑅𝑆𝑇𝑈𝑉𝑊𝑋𝑌𝑍', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf294 - 0xf2ad
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝑎-𝑧": # 0x1d44e - 0x1d467
+ - spell: "translate('.', '𝑎𝑏𝑐𝑑𝑒𝑓𝑔𝑖𝑗𝑘𝑙𝑚𝑛𝑜𝑝𝑞𝑟𝑠𝑡𝑢𝑣𝑤𝑥𝑦𝑧', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "-": # 0xf2ae - 0xf2c7
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "𝑨-𝒁": # 0x1d468 - 0x1d481
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf2c8 - 0xf2e1
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝒂-𝒛": # 0x1d482 - 0x1d49b
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "-": # 0xf2e2 - 0xf2fb
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "𝖠-𝖹": # 0x1d5a0 - 0x1d5b9
+ - spell: "translate('.', '𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf300 - 0xf319
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝖺-𝗓": # 0x1d5ba - 0x1d5d3
+ - spell: "translate('.', '𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "-": # 0xf31a - 0xf333
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "𝗔-𝗭": # 0x1d5d4 - 0x1d5ed
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf334 - 0xf34d
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝗮-𝘇": # 0x1d5ee - 0x1d607
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "-": # 0xf34e - 0xf367
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+ - "𝘈-𝘡": # 0x1d608 - 0x1d621
+ # - T: "italic"
+ - spell: "translate('.', '𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+ - "-": # 0xf368 - 0xf381
+ # - T: "italic"
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝘢-𝘻": # 0x1d622 - 0x1d63b
+ # - T: "italic"
+ - spell: "translate('.', '𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "-": # 0xf382 - 0xf39b
+ # - T: "italic"
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "𝘼-𝙕": # 0x1d63c - 0x1d655
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf39c - 0xf3b5
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝙖-𝙯": # 0x1d656 - 0x1d66f
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "-": # 0xf3b6 - 0xf3cf
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "𝙰-𝚉": # 0x1d670 - 0x1d689
+ - spell: "translate('.', '𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "-": # 0xf3d0 - 0xf3e9
+ - spell: "translate('.', '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
+
+ - "𝚊-𝚣": # 0x1d68a - 0x1d6a3
+ - spell: "translate('.', '𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "-": # 0xf3ea - 0xf403
+ - spell: "translate('.', '', 'abcdefghijklmnopqrstuvwxyz')"
+
+ - "": [T: "dotless i"] # 0xf404 (google translation)
+ - "𝚤": [T: "punktloses i kursiv"] # 0x1d6a4 (en: 'dotless i', google: 'dotless i')
+ - "𝚥": [T: "punktloses j kursiv"] # 0x1d6a5 (en: 'dotless j', google: 'dotless j')
+
+ - "𝚨-𝛀": # 0x1d6a8 - 0x1d6c0
+ - T: "punktloses j kursiv" # (en: 'bold', google: 'deutlich')
+ - spell: "translate('.', '𝚨𝚩𝚪𝚫𝚬𝚭𝚮𝚯𝚰𝚱𝚲𝚳𝚴𝚵𝚶𝚷𝚸𝚹𝚺𝚻𝚼𝚽𝚾𝚿𝛀', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+
+ - "-": # 0xf408 - 0xf420
+ - T: "punktloses j kursiv" # (en: 'bold', google: 'deutlich')
+ - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+
+ - "𝛂-𝛚": # 0x1d6c2 - 0x1d6da
+ - T: "punktloses j kursiv" # (en: 'bold', google: 'deutlich')
+ - spell: "translate('.', '𝛂𝛃𝛄𝛅𝛆𝛇𝛈𝛉𝛊𝛋𝛌𝛍𝛎𝛏𝛐𝛑𝛒𝛓𝛔𝛕𝛖𝛗𝛘𝛙𝛚', 'αβγδεζηθικλμνξοπρςστυφχψω')"
+
+ - "-": # 0xf422 - 0xf43a
+ - T: "punktloses j kursiv" # (en: 'bold', google: 'deutlich')
+ - spell: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')"
+
+ - "": [T: "mutiger nabla"] # 0xf421 (en: 'bold nabla', google translation)
+ - "𝛁": [T: "mutiger nabla"] # 0x1d6c1 (en: 'bold nabla', google translation)
+
+ - "𝛛𝛜𝛝𝛞𝛟𝛠𝛡": # 0x1D6DB - 0x1D6E1
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝛛𝛜𝛝𝛞𝛟𝛠𝛡', '∂εθκφρπ')"
+
+ - "": # 0xF43C - 0xF441
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', '∂εθκφρπ')"
+
+ - "𝛢-𝛺": # 0x1d6e2 - 0x1d6fa
+ # - T: "italic"
+ - spell: "translate('.', '𝛢𝛣𝛤𝛥𝛦𝛧𝛨𝛩𝛪𝛫𝛬𝛭𝛮𝛯𝛰𝛱𝛲𝛳𝛴𝛵𝛶𝛷𝛸𝛹𝛺', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+
+ - "-": # 0xf442 - 0xf45a
+ # - T: "italic"
+ - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+
+ - "𝛼-𝜔": # 0x1d6fc - 0x1d714
+ # - T: "italic"
+ - spell: "translate('.', '𝛼𝛽𝛾𝛿𝜀𝜁𝜂𝜃𝜄𝜅𝜆𝜇𝜈𝜉𝜊𝜋𝜌𝜍𝜎𝜏𝜐𝜑𝜒𝜓𝜔', 'αβγδεζηθικλμνξοπρςστυφχψω')"
+
+ - "-": # 0xf45c - 0xf474
+ # - T: "italic"
+ - spell: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')"
+
+ - "": [T: "kursiv nabla"] # 0xf45b (en: 'italic nabla', google translation)
+ - "𝛻": [T: "kursiv nabla"] # 0x1d6fb (en: 'italic nabla', google translation)
+
+ - "𝜕𝜖𝜗𝜘𝜙𝜚𝜛": # 0x1d715 - 0x1d71b
+ # - T: "italic"
+ - spell: "translate('.', '𝜕𝜖𝜗𝜘𝜙𝜚𝜛', '∂εθκφρπ')"
+
+ - "": # 0xf475 - 0xf47b
+ # - T: "italic"
+ - spell: "translate('.', '', '∂εθκφρπ')"
+
+ - "𝜜-𝜴": # 0x1d71c - 0x1d734
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝜜𝜝𝜞𝜟𝜠𝜡𝜢𝜣𝜤𝜥𝜦𝜧𝜨𝜩𝜪𝜫𝜬𝜭𝜮𝜯𝜰𝜱𝜲𝜳𝜴', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+
+ - "-": # 0xf47c - 0xf494
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+
+ - "𝜶-𝝎": # 0x1d736 - 0x1d74e
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝜶𝜷𝜸𝜹𝜺𝜻𝜼𝜽𝜾𝜿𝝀𝝁𝝂𝝃𝝄𝝅𝝆𝝇𝝈𝝉𝝊𝝋𝝌𝝍𝝎', 'αβγδεζηθικλμνξοπρςστυφχψω')"
+
+ - "-": # 0xf496 - 0xf4ae
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')"
+
+ - "𝝏𝝐𝝑𝝒𝝓𝝔𝝕": # 0x1d74f - 0x1d755
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝝏𝝐𝝑𝝒𝝓𝝔𝝕', '∂εθκφρπ')"
+
+ - "": # 0xf422 - 0xf43a
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', '∂εθκφρπ')"
+
+ - "𝜵": [T: "mutiges kursives nabla"] # 0x1d735 (en: 'bold italic nabla', google translation)
+ - "": [T: "mutiges kursives nabla"] # 0xf495 (en: 'bold italic nabla', google translation)
+
+ - "𝝖-𝝮": # 0x1d756 - 0x1d76e
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝝖𝝗𝝘𝝙𝝚𝝛𝝜𝝝𝝞𝝟𝝠𝝡𝝢𝝣𝝤𝝥𝝦𝝧𝝨𝝩𝝪𝝫𝝬𝝭𝝮', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+ - "-": # 0xf4b6 - 0xf4ce
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+
+ - "𝝰-𝞈": # 0x1d770 - 0x1d788
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝝰𝝱𝝲𝝳𝝴𝝵𝝶𝝷𝝸𝝹𝝺𝝻𝝼𝝽𝝾𝝿𝞀𝞁𝞂𝞃𝞄𝞅𝞆𝞇𝞈', 'αβγδεζηθικλμνξοπρςστυφχψω')"
+
+ - "-": # 0xf4d0 - 0xf4e8
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')"
+
+ - "𝞉𝞊𝞋𝞌𝞍𝞎𝞏": # 0x1d789 - 0x1d78f
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝞉𝞊𝞋𝞌𝞍𝞎𝞏', '∂εθκφρπ')"
+
+ - "": # 0xf4e9 - 0xf4ef
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', '∂εθκφρπ')"
+
+ - "": [T: "mutiger nabla"] # 0xf4cf (en: 'bold nabla', google translation)
+ - "𝝯": [T: "mutiger nabla"] # 0x1d76f (en: 'bold nabla', google translation)
+
+ - "𝞐-𝞨": # 0x1d790 - 0x1d7a8
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝞐𝞑𝞒𝞓𝞔𝞕𝞖𝞗𝞘𝞙𝞚𝞛𝞜𝞝𝞞𝞟𝞠𝞡𝞢𝞣𝞤𝞥𝞦𝞧𝞨', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+
+ - "-": # 0xf4f0 - 0xf508
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ')"
+
+ - "𝞪-𝟂": # 0x1d7aa - 0x1d7c2
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝞪𝞫𝞬𝞭𝞮𝞯𝞰𝞱𝞲𝞳𝞴𝞵𝞶𝞷𝞸𝞹𝞺𝞻𝞼𝞽𝞾𝞿𝟀𝟁𝟂', 'αβγδεζηθικλμνξοπρςστυφχψω')"
+
+ - "-": # 0xf50a - 0xf522
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', 'αβγδεζηθικλμνξοπρςστυφχψω')"
+
+ - "𝟃𝟄𝟅𝟆𝟇𝟈𝟉": # 0x1d7c3 - 0x1d7c9
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '𝟃𝟄𝟅𝟆𝟇𝟈𝟉', '∂εθκφρπ')"
+
+ - "": # 0xf523 - 0xf529
+ # - T: "bold italic"
+ - T: "deutlich" # (en: 'bold', google translation)
+ - spell: "translate('.', '', '∂εθκφρπ')"
+
+ - "": [T: "mutiger nabla"] # 0xf509 (en: 'bold nabla', google translation)
+ - "𝞩": [T: "mutiger nabla"] # 0x1d7a9 (en: 'bold nabla', google translation)
+
+ - "": [T: "bold null"] # 0xf52e (en: 'bold zero', google translation)
+ - "𝟎": [T: "bold null"] # 0x1d7ce (en: 'bold zero', google translation)
+ - "": [T: "mutig"] # 0xf52f (en: 'bold one', google translation)
+ - "𝟏": [T: "mutig"] # 0x1d7cf (en: 'bold one', google translation)
+ - "": [T: "fett zwei"] # 0xf530 (en: 'bold two', google translation)
+ - "𝟐": [T: "fett zwei"] # 0x1d7d0 (en: 'bold two', google translation)
+ - "": [T: "fett drei"] # 0xf531 (en: 'bold three', google translation)
+ - "𝟑": [T: "fett drei"] # 0x1d7d1 (en: 'bold three', google translation)
+ - "": [T: "fett vier"] # 0xf532 (en: 'bold four', google translation)
+ - "𝟒": [T: "fett vier"] # 0x1d7d2 (en: 'bold four', google translation)
+ - "": [T: "fett fünf"] # 0xf533 (en: 'bold five', google translation)
+ - "𝟓": [T: "fett fünf"] # 0x1d7d3 (en: 'bold five', google translation)
+ - "": [T: "mutige sechs"] # 0xf534 (en: 'bold six', google translation)
+ - "𝟔": [T: "mutige sechs"] # 0x1d7d4 (en: 'bold six', google translation)
+ - "": [T: "fett sieben"] # 0xf535 (en: 'bold seven', google translation)
+ - "𝟕": [T: "fett sieben"] # 0x1d7d5 (en: 'bold seven', google translation)
+ - "": [T: "mutig bei"] # 0xf536 (en: 'bold eight', google translation)
+ - "𝟖": [T: "mutig bei"] # 0x1d7d6 (en: 'bold eight', google translation)
+ - "": [T: "fett neun"] # 0xf537 (en: 'bold nine', google translation)
+ - "𝟗": [T: "fett neun"] # 0x1d7d7 (en: 'bold nine', google translation)
+ - "": [T: "null"] # 0xf542 (en: 'zero', google translation)
+ - "𝟢": [T: "null"] # 0x1d7e2 (en: 'zero', google translation)
+ - "": [T: "eins"] # 0xf543 (en: 'one', google translation)
+ - "𝟣": [T: "eins"] # 0x1d7e3 (en: 'one', google translation)
+ - "": [T: "zwei"] # 0xf544 (en: 'two', google translation)
+ - "𝟤": [T: "zwei"] # 0x1d7e4 (en: 'two', google translation)
+ - "": [T: "drei"] # 0xf545 (en: 'three', google translation)
+ - "𝟥": [T: "drei"] # 0x1d7e5 (en: 'three', google translation)
+ - "": [T: "vier"] # 0xf546 (en: 'four', google translation)
+ - "𝟦": [T: "vier"] # 0x1d7e6 (en: 'four', google translation)
+ - "": [T: "fünf"] # 0xf547 (en: 'five', google translation)
+ - "𝟧": [T: "fünf"] # 0x1d7e7 (en: 'five', google translation)
+ - "": [T: "sechs"] # 0xf548 (en: 'six', google translation)
+ - "𝟨": [T: "sechs"] # 0x1d7e8 (en: 'six', google translation)
+ - "": [T: "sieben"] # 0xf549 (en: 'seven', google translation)
+ - "𝟩": [T: "sieben"] # 0x1d7e9 (en: 'seven', google translation)
+ - "": [T: "bei"] # 0xf54a (en: 'eight', google translation)
+ - "𝟪": [T: "bei"] # 0x1d7ea (en: 'eight', google translation)
+ - "": [T: "neun"] # 0xf54b (en: 'nine', google translation)
+ - "𝟫": [T: "neun"] # 0x1d7eb (en: 'nine', google translation)
+ - "": [T: "bold null"] # 0xf54c (en: 'bold zero', google translation)
+ - "𝟬": [T: "bold null"] # 0x1d7ec (en: 'bold zero', google translation)
+ - "": [T: "mutig"] # 0xf54d (en: 'bold one', google translation)
+ - "𝟭": [T: "mutig"] # 0x1d7ed (en: 'bold one', google translation)
+ - "": [T: "fett zwei"] # 0xf54e (en: 'bold two', google translation)
+ - "𝟮": [T: "fett zwei"] # 0x1d7ee (en: 'bold two', google translation)
+ - "": [T: "fett drei"] # 0xf54f (en: 'bold three', google translation)
+ - "𝟯": [T: "fett drei"] # 0x1d7ef (en: 'bold three', google translation)
+ - "": [T: "fett vier"] # 0xf550 (en: 'bold four', google translation)
+ - "𝟰": [T: "fett vier"] # 0x1d7f0 (en: 'bold four', google translation)
+ - "": [T: "fett fünf"] # 0xf551 (en: 'bold five', google translation)
+ - "𝟱": [T: "fett fünf"] # 0x1d7f1 (en: 'bold five', google translation)
+ - "": [T: "mutige sechs"] # 0xf552 (en: 'bold six', google translation)
+ - "𝟲": [T: "mutige sechs"] # 0x1d7f2 (en: 'bold six', google translation)
+ - "": [T: "fett sieben"] # 0xf553 (en: 'bold seven', google translation)
+ - "𝟳": [T: "fett sieben"] # 0x1d7f3 (en: 'bold seven', google translation)
+ - "": [T: "mutig bei"] # 0xf554 (en: 'bold eight', google translation)
+ - "𝟴": [T: "mutig bei"] # 0x1d7f4 (en: 'bold eight', google translation)
+ - "": [T: "fett neun"] # 0xf555 (en: 'bold nine', google translation)
+ - "𝟵": [T: "fett neun"] # 0x1d7f5 (en: 'bold nine', google translation)
+ - "": [T: "null"] # 0xf556 (en: 'zero', google translation)
+ - "𝟶": [T: "null"] # 0x1d7f6 (en: 'zero', google translation)
+ - "": [T: "eins"] # 0xf557 (en: 'one', google translation)
+ - "𝟷": [T: "eins"] # 0x1d7f7 (en: 'one', google translation)
+ - "": [T: "zwei"] # 0xf558 (en: 'two', google translation)
+ - "𝟸": [T: "zwei"] # 0x1d7f8 (en: 'two', google translation)
+ - "": [T: "drei"] # 0xf559 (en: 'three', google translation)
+ - "𝟹": [T: "drei"] # 0x1d7f9 (en: 'three', google translation)
+ - "": [T: "vier"] # 0xf55a (en: 'four', google translation)
+ - "𝟺": [T: "vier"] # 0x1d7fa (en: 'four', google translation)
+ - "": [T: "fünf"] # 0xf55b (en: 'five', google translation)
+ - "𝟻": [T: "fünf"] # 0x1d7fb (en: 'five', google translation)
+ - "": [T: "sechs"] # 0xf55c (en: 'six', google translation)
+ - "𝟼": [T: "sechs"] # 0x1d7fc (en: 'six', google translation)
+ - "": [T: "sieben"] # 0xf55d (en: 'seven', google translation)
+ - "𝟽": [T: "sieben"] # 0x1d7fd (en: 'seven', google translation)
+ - "": [T: "bei"] # 0xf55e (en: 'eight', google translation)
+ - "𝟾": [T: "bei"] # 0x1d7fe (en: 'eight', google translation)
+ - "": [T: "neun"] # 0xf55f (en: 'nine', google translation)
+ - "𝟿": [T: "neun"] # 0x1d7ff (en: 'nine', google translation)
+ - "": [T: "unbekannter charakter"] # 0xf700 (en: 'unknown character', google translation)
+ - "": [T: "unter rechts und untere linke dreiecke"] # 0xf726 (en: 'lower right and lower left triangles', google translation)
+ - "": [T: "horizontaler ellipsis extender"] # 0xf72d (en: 'horizontal ellipsis extender', google translation)
+ - "": [T: "mittellinienhorizontale ellipsis extender"] # 0xf72e (en: 'midline horizontal ellipsis extender', google translation)
+ - "": [T: "radikaler erweiterung"] # 0xf8e5 (en: 'radical extender', google translation)
+ - "": [T: "vertikaler pfeiler extender"] # 0xf8e6 (en: 'vertical arrow extender', google translation)
+ - "": [T: "horizontaler pfeil extender"] # 0xf8e7 (en: 'horizontal arrow extender', google translation)
+ - "": [T: "registriertes zeichen sans serif"] # 0xf8e8 (en: 'registered sign sans serif', google translation)
+ - "": [T: "copyright zeichen sans serif"] # 0xf8e9 (en: 'copyright sign sans serif', google translation)
+ - "": [T: "markzeichen zeichen ohne serife"] # 0xf8ea (en: 'trade mark sign sans serif', google translation)
+ - "": [T: "links -klammern"] # 0xf8eb (en: 'left paren top', google translation)
+ - "": [T: "links -klammern extender"] # 0xf8ec (en: 'left paren extender', google translation)
+ - "": [T: "linke klammern"] # 0xf8ed (en: 'left paren bottom', google translation)
+ - "": [T: "linker halterung"] # 0xf8ee (en: 'left bracket top', google translation)
+ - "": [T: "linke klammer extender"] # 0xf8ef (en: 'left bracket extender', google translation)
+ - "": [T: "linke halterung unten"] # 0xf8f0 (en: 'left bracket bottom', google translation)
+ - "": [T: "links leichte oberseite"] # 0xf8f1 (en: 'left brace top', google translation)
+ - "": [T: "linksklammer mitten"] # 0xf8f2 (en: 'left brace mid', google translation)
+ - "": [T: "linker blace boden"] # 0xf8f3 (en: 'left brace bottom', google translation)
+ - "": [T: "absprace externen"] # 0xf8f4 (en: 'brace extender', google translation)
+ - "": [T: "integraler extender"] # 0xf8f5 (en: 'integral extender', google translation)
+ - "": [T: "rechte klammern"] # 0xf8f6 (en: 'right paren top', google translation)
+ - "": [T: "rechte klammer extender"] # 0xf8f7 (en: 'right paren extender', google translation)
+ - "": [T: "rechte klammer unten"] # 0xf8f8 (en: 'right paren bottom', google translation)
+ - "": [T: "rechte halterung"] # 0xf8f9 (en: 'right bracket top', google translation)
+ - "": [T: "rechte klammer extender"] # 0xf8fa (en: 'right bracket extender', google translation)
+ - "": [T: "rechte halterung unten"] # 0xf8fb (en: 'right bracket bottom', google translation)
+ - "": [T: "rechte klammerobertop"] # 0xf8fc (en: 'right brace top', google translation)
+ - "": [T: "richtige klammer in der mitte"] # 0xf8fd (en: 'right brace mid', google translation)
+ - "": [T: "rechtshalle unten"] # 0xf8fe (en: 'right brace bottom', google translation)
+ - "": [T: "apple logo"] # 0xf8ff (google translation)
+ - "ff": [T: "ligature ff"] # 0xfb00 (en: 'ff', google: 'ff')
+ - "fi": [T: "ligature fi"] # 0xfb01 (en: 'fi', google: 'fi')
+ - "fl": [T: "ligature fl"] # 0xfb02 (en: 'fl', google: 'fl')
+ - "ffi": [T: "ligature ffi"] # 0xfb03 (en: 'ffi', google: 'ffi')
+ - "ffl": [T: "ligature ffl"] # 0xfb04 (en: 'ffl', google: 'ffl')
+ - "ſt": [T: "ft"] # 0xfb05 (google translation)
+ - "st": [T: "st"] # 0xfb06 (google translation)
+ - "︠": [T: "die ligatur verließ die halbe verzierung"] # 0xfe20 (en: 'ligature left half embellishment', google translation)
+ - "︡": [T: "ligature rechte halbe verzierung"] # 0xfe21 (en: 'ligature right half embellishment', google translation)
+ - "︢": [T: "doppelte tilde verließ die halbe verzierung"] # 0xfe22 (en: 'double tilde left half embellishment', google translation)
+ - "︣": [T: "doppelte tilde rechte halbe verzierung"] # 0xfe23 (en: 'double tilde right half embellishment', google translation)
+ - "︤": [T: "macron verließ die halbe verzierung"] # 0xfe24 (en: 'macron left half embellishment', google translation)
+ - "︥": [T: "macron rechte halbe verzierung"] # 0xfe25 (en: 'macron right half embellishment', google translation)
+ - "︦": [T: "konjazieren von macron -verzierung"] # 0xfe26 (en: 'conjoining macron embellishment', google translation)
+ - "︵": [T: "Präsentationsformular für vertikale linke Klammer"] # 0xfe35 (en: 'over paren', MathPlayer: 'over paren', google: 'über klammern')
+ - "︶": [T: "Präsentationsformular für vertikale rechte Klammer"] # 0xfe36 (en: 'under paren', MathPlayer: 'under paren', google: 'unter klammern')
+ - "︷": [T: "Präsentationsformular für vertikale linke geschweifte Klammer"] # 0xfe37 (en: 'over brace', MathPlayer: 'over curly bracket', google: 'über klammer')
+ - "︸": [T: "Präsentationsformular für vertikale, recht geschweifte Klammer"] # 0xfe38 (en: 'under brace', MathPlayer: 'under curly bracket', google: 'unter klammer')
+ - "︿": [T: "Präsentationsformular für vertikale linke Winkelhalterung"] # 0xfe3f (en: 'over angle bracket', MathPlayer: 'over angle bracket', google: 'über winkelhalterung')
+ - "﹀": [T: "Präsentationsformular für vertikale rechtwinklige Halterung"] # 0xfe40 (en: 'under angle bracket', MathPlayer: 'under angle bracket', google: 'unter winkelklasse')
+ - "﹨": [T: "kleiner umgekehrter Schrägstrich"] # 0xfe68 (en: 'integer divide', MathPlayer: 'integer divide', google: 'ganzzahl teilt')
+ - "": [T: "unbekanntes oder fehlendes objekt"] # 0xfffc (en: 'unknown or missing object', google translation)
+ - "�": [T: "unknown or missing character"] # 0xfffd (google: 'unbekannter oder fehlender charakter')
diff --git a/Rules/Languages/de/unicode.yaml b/Rules/Languages/de/unicode.yaml
new file mode 100644
index 00000000..fa1edf93
--- /dev/null
+++ b/Rules/Languages/de/unicode.yaml
@@ -0,0 +1,497 @@
+---
+ # Note to translators:
+ # most languages don't have two ways to pronounce 'a' -- if not need, remove the rules and change "B-Z" to "A-Z"
+ # some languages say the word for "uppercase" after the letter. Make sure to change that where appropriate by moving some code around
+ - "a-z":
+ - test:
+ if: "$TTS='none'"
+ then: [ T: "." ] # (en: '.', google translation)
+ else: [ spell: "'.'" ]
+
+# Capital letters are a little tricky: users can pick their favorite word (something that was requested) and
+ # screen readers have options to use pitch changes or beeps instead of or in addition to say "cap"
+ # Also, if a user can see the screen, they probably don't need to hear "cap", but if they specified an override, they must want to hear the override.
+
+ - "A-Z":
+ - test:
+ if: "$CapitalLetters_Beep"
+ then:
+ - audio:
+ value: "beep.mp4"
+ replace: []
+ - test:
+ if: "$CapitalLetters_UseWord"
+ then_test:
+ if: "$SpeechOverrides_CapitalLetters = ''"
+ then_test:
+ if: "$Impairment = 'Blindness'"
+ then: [T: "groß"] # (en: 'cap', google translation)
+ else: [x: "$SpeechOverrides_CapitalLetters"]
+ - pitch:
+ value: "$CapitalLetters_Pitch"
+ # note: processing of ranges converts '.' into the character, so it needs to be in quotes below
+ replace: [spell: "translate('.', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"]
+
+ - "0-9": [T: "."] # (en: '.', google: 'A')
+
+ - "!": # 0x21
+ - test:
+ if: "ancestor-or-self::*[contains(@data-intent-property, ':structure:')]"
+ then_test:
+ if: "$Verbosity = ' '"
+ then: [T: "knall"] # 0x21 (en: 'bang', google translation)
+ else: [T: "ausrufezeichen"] # 0x21 (en: 'exclamation point')
+ else: [T: "fakultät"] # 0x21 (en: 'factorial')
+
+ - "\"": [T: "backslash"] # 0x22 (en: 'quotation mark') #backslash??
+ - "#": [T: "nummernzeichen"] # 0x23 (en: 'number')
+ - "$": [T: "dollar"] # 0x24 (en: 'dollars')
+ - "%": [T: "prozent"] # 0x25 (en: 'percent')
+ - "&": [T: "kaufmännisches und"] # 0x26 (en: 'ampersand')
+ - "'": [T: "hochkomma"] # 0x27 (en: 'apostrophe', MathPlayer: 'Hochkomma', google: 'apostroph')
+ - "(": # 0x28
+ - test:
+ if: $SpeechStyle = 'ClearSpeak' or $SpeechStyle = 'SimpleSpeak'
+ then_test:
+ if: "$Verbosity='Terse'"
+ then: [T: "klammer auf"] # 0x28 (en: 'open', google translation) #unklar
+ else: [T: "klammer auf"] # 0x28 (en: 'open paren')
+ else: [T: "klammer auf"] # 0x28 (en: 'left paren')
+ - ")": # 0x29
+ - test:
+ if: $SpeechStyle = 'ClearSpeak' or $SpeechStyle = 'SimpleSpeak'
+ then_test:
+ if: "$Verbosity='Terse'"
+ then: [T: "klammer zu"] # 0x29 (en: 'close', google translation) #unklar
+ else: [T: "klammer zu"] # 0x29 (en: 'close paren')
+ else: [T: "klammer zu"] # 0x29 (en: 'right paren')
+
+ - "*": # 0x2a
+ test:
+ if: "parent::*[name(.)='msup' or name(.)='msubsup' or name(.)='skip-super']"
+ then: [T: "stern"] # 0x2a (en: 'star', google translation)
+ else: [T: "mal"] # 0x2a
+ - "+": [T: "plus"] # 0x2b
+ - ",": # 0x2c
+ # the following deals with the interaction of "," with "…" which sometimes wants the ',' to be silent
+ # that this test is here and not with "…" is not ideal, but seems simplest
+ test:
+ if:
+ - "$SpeechStyle != 'ClearSpeak' or $ClearSpeak_Ellipses = 'Auto' or "
+ # must be ClearSpeak and $ClearSpeak_Ellipses = 'AndSoOn'
+ # speak "comma" when not adjacent to '…'
+ - "( following-sibling::*[1][text()!= '…'] and preceding-sibling::*[1][text()!='…'] ) or "
+ # except if expression starts with '…'
+ - "../*[1][text()='…'] "
+ then: [T: "komma"] # (en: 'comma', google translation)
+ # else silent
+
+ - "-": [T: "minus"] # 0x2d
+ - ".": # 0x2e
+ - test:
+ if: "parent::*[1][self::m:mn]"
+ then: [T: "punkt"] # (en: 'point', google translation)
+ else: [T: "punkt"] # (en: 'dot', google: 'punkt')
+ - "/": [T: "schrägstrich"] # 0x2f (en: 'divided by')
+ - ":": [T: "doppelpunkt"] # 0x3a (en: 'colon')
+ - ";": [T: "strichpunkt"] # 0x3b (en: 'semicolon')
+ - "<": # 0x3c
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "kleiner als" # (en: 'less than')
+ - "=": # 0x3d
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist gleich"] # (en: 'is equal to', google translation)
+ else: [T: "ist gleich"] # (en: 'equals')
+
+ - ">": # 0x3e
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "größer als" # (en: 'greater than')
+ - "?": [T: "fragezeichen"] # 0x3f (en: 'question mark', MathPlayer: 'Frgezeichen', google: 'fragezeichen')
+ - "@": [T: "ät-zeichen"] # 0x40 (en: 'at sign')
+ - "[": # 0x5b
+ - test:
+ if: $SpeechStyle = 'ClearSpeak' or $SpeechStyle = 'SimpleSpeak'
+ then: [T: "offene eckige klammer"] # (en: 'open bracket', google translation) #unklar
+ else: [T: "eckige klammer auf"] # (en: 'left bracket', MathPlayer: 'eckig Klammer auf', google: 'linke klammer')
+ - "\\": [T: "eckige klammer auf"] # 0x5c (en: 'back slash', MathPlayer: 'eckig Klammer auf', google: 'rückenstrich')
+ - "]": # 0x5d
+ - test:
+ if: $SpeechStyle = 'ClearSpeak' or $SpeechStyle = 'SimpleSpeak'
+ then: [T: "schließende eckige klammer"] # (en: 'close bracket', google translation) #unklar
+ else: [T: "eckige klammer zu"] # (en: 'right bracket')
+ - "^": [T: "zirkumflex"] # 0x5e (en: 'hat')
+ - "_": [T: "unterstrich"] # 0x5f (en: 'under bar', MathPlayer: 'under bar', google: 'unter bar')
+ - "`": [T: "gravis akzent"] # 0x60 (en: 'grave', MathPlayer: 'grave accent', google: 'grab')
+ - "{": # 0x7b
+ - test:
+ if: $SpeechStyle = 'ClearSpeak' or $SpeechStyle = 'SimpleSpeak'
+ then: [T: "offene geschweifte klammer"] # (en: 'open brace', google translation)
+ else: [T: "geschweifte klammer auf"] # (en: 'left brace')
+ - "|": # 0x7c
+ # note: for ClearSpeak and SimpleSpeak, "|" inside of sets is handled at the mrow level, same for 'sets'
+ - test:
+ - if: "$SpeechStyle != 'ClearSpeak' or not(preceding-sibling::*) or not(following-sibling::*)"
+ then: [T: "senkrechter strich"] # (en: 'vertical line', google translation)
+ - else_if: "$ClearSpeak_VerticalLine = 'SuchThat'"
+ then: [T: "so dass"] # (en: 'such that', google translation)
+ - else_if: "$ClearSpeak_VerticalLine = 'Given'"
+ then: [T: "gegeben"] # (en: 'given', google translation)
+ - else: [T: "teilt"] # (en: 'divides')
+
+ - "}": # 0x7d
+ - test:
+ if: $SpeechStyle = 'ClearSpeak' or $SpeechStyle = 'SimpleSpeak'
+ then: [T: "schließende geschweifte klammer"] # (en: 'close brace', google translation)
+ else: [T: "geschweifte klammer zu"] # (en: 'right brace')
+
+ - "~": [T: "tilde"] # 0x7e
+ - " ": # 0xa0
+ - test:
+ if: "@data-empty-in-2D and ../../../../*[name(.)!='equations']"
+ then: [T: "leer"] # want to say something for fraction (etc) with empty child (en: 'empty', google translation)
+ else: [T: ""]
+
+ - "¬": [T: "nicht"] # 0xac (en: 'not')
+ - "°": [T: "grad"] # 0xb0 (en: 'degrees')
+ - "±": [T: "plus minus"] # 0xb1 (en: 'plus or minus')
+ - "´": [T: "akut akzent"] # 0xb4 (en: 'acute', MathPlayer: 'acute accent', google: 'akut')
+ - "·": # 0xB7
+ - 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') #unklar
+ - "÷": [T: "geteilt durch"] # 0xf7 (en: 'divided by', MathPlayer: 'divides')
+ - "̀": [T: "accent grave"] # 0x300 (en: 'grave accent embellishment', google: 'grabakzentverzierung')
+ - "́": [T: "accent aigu"] # 0x301 (en: 'acute accent embellishment', google: 'akute akzentverzierung')
+ - "̂": [T: "zirkumflex"] # 0x302 (en: 'circumflex accent embellishment', google: 'zirma akzentverzierung')
+ - "̃": [T: "tilde"] # 0x303 (google: 'tilde verzierung')
+ - "̄": [T: "makron"] # 0x304 (en: 'macron embellishment', google: 'makron -verzierung')
+ - "̅": [T: "überstrich"] # 0x305 (google: 'überbärerverzierung')
+ - "̆": [T: "brevis"] # 0x306 (en: 'breve', google: 'breve')
+ - "̇": [T: "punkt darüber"] # 0x307 (google: 'punkt über verzierung')
+
+ # Note: ClearSpeak has pref TriangleSymbol for "Δ", but that is wrong
+ - "Α-Ω":
+ - test:
+ if: "$CapitalLetters_Beep"
+ then:
+ - audio:
+ value: "beep.mp4"
+ replace: []
+ - test:
+ if: "$CapitalLetters_UseWord"
+ then_test:
+ if: "$SpeechOverrides_CapitalLetters = ''"
+ then_test:
+ if: "$Impairment = 'Blindness'"
+ then: [T: "großbuchstabe"] # (en: 'cap', google translation) #großbuchstaben?
+ else: [x: "$SpeechOverrides_CapitalLetters"]
+ - pitch:
+ value: "$CapitalLetters_Pitch"
+ # note: processing of ranges converts '.' into the character, so it needs to be in quotes below
+ replace: [spell: "translate('.', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ', 'αβγδεζηθικλμνξοπρςστυφχψω')"]
+
+ - "α": [T: "alpha"] # 0x3b1
+ - "β": [T: "beta"] # 0x3b2
+ - "γ": [T: "gamma"] # 0x3b3
+ - "δ": [T: "delta"] # 0x3b4
+ - "ε": [T: "epsilon"] # 0x3b5
+ - "ζ": [T: "zeta"] # 0x3b6
+ - "η": [T: "eta"] # 0x3b7
+ - "θ": [T: "theta"] # 0x3b8
+ - "ι": [T: "iota"] # 0x3b9 (google: 'jota')
+ - "κ": [T: "kappa"] # 0x3ba
+ - "λ": [T: "lamda"] # 0x3bb (en: 'lambda', google: 'lambda')
+ - "μ": [T: "mü"] # 0x3bc
+ - "ν": [T: "nü"] # 0x3bd
+ - "ξ": [T: "xi"] # 0x3be (en: 'zai', google: 'zai')
+ - "ο": [T: "omicron"] # 0x3bf
+ - "π": [T: "pi"] # 0x3c0
+ - "ρ": [T: "rho"] # 0x3c1
+ - "ς": [T: "sigma am wortende"] # 0x3c2
+ - "σ": [T: "sigma"] # 0x3c3
+ - "τ": [T: "tau"] # 0x3c4
+ - "υ": [T: "üpsilon"] # 0x3c5 #ypsilon
+ - "φ": [T: "phi"] # 0x3c6
+ - "χ": [T: "chi"] # 0x3c7
+ - "ψ": [T: "psi"] # 0x3c8
+ - "ω": [T: "omega"] # 0x3c9
+ - "ϕ": [T: "phi"] # 0x3d5 (en: 'phi', google: 'phi')
+ - "ϖ": [T: "pi"] # 0x3d6 (en: 'pi', google: 'pi')
+ - "ϵ": [T: "epsilon"] # 0x3f5
+ - "϶": [T: "umgekehrtes epsilon"] # 0x3f6 (en: 'reversed epsilon', MathPlayer: 'reversed epsilon', google: 'umgekehrter epsilon')
+
+ - "–": [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 senkrechte linie"] # 0x2016 (en: 'double vertical line', MathPlayer: 'double vertical bar', google: 'doppelte vertikale linie')
+ - "…": # 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: "punkt punkt punkt"] # (en: 'and so on up to', MathPlayer: 'dot dot dot', google: 'und so weiter bis') #horizontale Ellipsis
+
+ - "": # 0x2061
+ - test:
+ if: "$Verbosity!='Terse' and not(preceding-sibling::*[1][IsInDefinition(., 'GeometryShapes')]) and
+ not(@data-changed='added' and ancestor-or-self::*[contains(@data-intent-property, ':structure:')])"
+ then: [T: "von"] # (en: 'of', google translation)
+ - "": [T: ""] # 0x2062
+ - "": [T: ""] # 0x2063
+ - "": [T: "und"] # 0x2064 (en: 'and', google: 'und')
+ - "′": [T: "strich"] # 0x2032 (en: 'prime', MathPlayer: 'strich', google: 'prime')
+ - "″": [T: "zwei strich"] # 0x2033 (en: 'double prime', MathPlayer: 'zwei-strich', google: 'double prime')
+ - "‴": [T: "drei strich"] # 0x2034 (en: 'triple prime', MathPlayer: 'drei-strich', google: 'triple prime')
+
+ - "ℂℕℚℝℤ": # here we rely on this running through the table again to speak "cap xxx"
+ - T: "drei Strich" # (en: 'double-struck', MathPlayer: 'drei-strich', google: 'doppelter takt')
+ - spell: "translate('.', 'ℂℕℚℝℤ', 'CNQRZ')"
+
+ - "℃": [T: "grad celsius"] # 0x2103 (google: 'grad celsius')
+ - "℉": [T: "grad fahrenheit"] # 0x2109 (google: 'grad fahrenheit')
+ - "ℋℛℓ": # 0x210b #klären
+ - T: "schreibschrift" # (en: 'script', google: 'skript')
+ - spell: "translate('.', 'ℋℛℓ', 'HRl')"
+ - "ℎ": [T: "planck-konstante"] # 0x210e (en: 'planck constant', MathPlayer: 'planck constant', google: 'planck konstant')
+ - "ℜ": # 0x211c
+ - T: "frakturschrift groß r" # (en: 'fraktur', google: 'fraktur')
+ - spell: "'R'"
+
+ - "Ω": [T: "ohm"] # 0x2126 (en: 'ohms', MathPlayer: 'ohm sign', google: 'ohm')
+ - "K": [T: "kelvin"] # 0x212a (en: 'kelvin', MathPlayer: 'degrees kelvin', google: 'kelvin')
+ - "Å": [T: "angström"] # 0x212b (en: 'angstroms', MathPlayer: 'angstroms', google: 'angstrome')
+ - "ⅆⅇⅈⅉ": # 0x2146-9
+ - T: "doppelstrich kursiv" # (en: 'double-struck italic', MathPlayer: 'angstroms', google: 'doppelt übertroffene kursivschrift')
+ - spell: "translate('.', 'ⅆⅇⅈⅉ', 'deij')"
+
+ - "←": [T: "pfeil nach links"] # 0x2190 (en: 'leftwards arrow', MathPlayer: 'leftwards arrow', google: 'pfeil nach links')
+ - "↑": [T: "pfeil nach oben"] # 0x2191 (en: 'upwards arrow', MathPlayer: 'upwards arrow', google: 'nach oben pfeil')
+ - "→": # 0x2192
+ - test:
+ if: "ancestor::*[2][self::m:limit]"
+ then: [T: "gegen"] # (en: 'approaches', google translation)
+ else: [T: "pfeil nach rechts"] # (en: 'right arrow', MathPlayer: 'rightwards arrow', google: 'rechter pfeil')
+
+ - "↓": [T: "pfeil nach unten"] # 0x2193 (en: 'downwards arrow', MathPlayer: 'downwards arrow', google: 'nach unten pfeil')
+ - "⇒": [T: "doppelpfeil nach rechts"] # 0x21d2 (en: 'rightwards double arrow', MathPlayer: 'rightwards double arrow', google: 'richtiger doppelpfeil')
+ - "∀": [T: "für alle"] # 0x2200 (en: 'for all')
+ - "∂": # 0x2202
+ - test:
+ if: "$Verbosity='Terse'"
+ then: [T: "teilweise"] # (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: ""] # (en: 'the', google translation)
+ - T: "delta" # (en: 'laplacian of', MathPlayer: 'increment', google: 'laplace von') #unklar, sehr kontextabhängig
+ - "∇": # 0x2207
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "der"] # (en: 'the', google translation)
+ - T: "nabla-operator" # (en: 'gradient of', google: 'gradient von') #gradient nur einer der drei möglichen differentialoperatoren
+ - "∈": # 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: "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)
+ - 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: "produkt"] # 0x220f (en: 'product', MathPlayer: 'Product', google: 'produkt')
+ - "∐": [T: "koprodukt"] # 0x2210 (en: 'co-product', MathPlayer: 'coproduct', google: 'ko-produkt')
+ - "∑": [T: "summe"] # 0x2211 (en: 'sum')
+ - "−": [T: "minus"] # 0x2212
+ - "∓": [T: "minus plus"] # 0x2213 (en: 'minus or plus')
+ - "∗": [T: "mal"] # 0x2217 (en: 'times', MathPlayer: 'asterisk operator', google: 'mal')
+ - "∘": [T: "verknüpft mit"] # 0x2218 (en: 'composed with')
+ - "√": # 0x221a
+<<<<<<< HEAD
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "die"] # (en: 'the', google translation)
+=======
+>>>>>>> 2a2157c1f21e828e4d827022e1e0fc5490837efe
+ - T: "quadratwurzel" # (en: 'square root of', MathPlayer: 'radical', google: 'quadratwurzel von')
+ - "∝": # 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: "teilt"] # 0x2223 (en: 'divides')
+ - "∤": [T: "teilt nicht"] # 0x2224 (en: 'does not divide')
+ - "∥": # 0x2225
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "parallel zu" # (en: 'parallel to')
+ - "∦": # 0x2226
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "nicht parallel zu" # (en: 'not parallel to')
+ - "∧": [T: "und"] # 0x2227 (en: 'and')
+ - "∨": [T: "oder"] # 0x2228 (en: 'or')
+ - "∩": [T: "schnitt mit"] # 0x2229 (en: 'intersection') #Problem: Schnittmenge wenn alleinstehend vor Bezeichnung, schnitt wenn zwischen 2 Mengen
+ - "∪": [T: "vereinigt mit"] # 0x222a (en: 'union') #Problem: vereinigungsmenge wenn alleinstehend vor Bezeichnung, vereinigt mit wenn zwischen 2 Mengen
+ - "∫": [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')
+ - "∶": # 0x2236
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation) #unklar
+ - T: "zu" # (en: 'to')
+ - "∷": [T: "proportional"] # 0x2237 (en: 'as')
+ - "∼": [T: "tilde"] # 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')
+ - "≠": # 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')
+ - "≤": # 0x2264
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "kleiner gleich"
+ - "≥": # 0x2265
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist"] # (en: 'is', google translation)
+ - T: "größer gleich" # (en: 'greater than or equal to')
+ - "≦": [T: "kleiner als über gleich"] # 0x2266 (en: 'less than over equal to', MathPlayer: 'less than over equal to', google: 'weniger als überweg')
+ - "≧": [T: "größer als über gleich"] # 0x2267 (en: 'greater than over equal to', MathPlayer: 'greater than over equal to', google: 'größer als überweg')
+ - "≺": [T: "vorangehend"] # 0x227a (en: 'precedes', MathPlayer: 'precedes', google: 'voraus')
+ - "≻": [T: "nachfolgend"] # 0x227b (en: 'succeeds', MathPlayer: 'succeeds', google: 'gelingt es')
+ - "⊂": # 0x2282
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist eine"] # (en: 'is a', google translation)
+ - T: "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: "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 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 obermenge von" # (en: 'not a superset of', MathPlayer: 'nicht Obermenge von', google: 'kein superset von')
+ - "⊆": # 0x2286
+ - test:
+ if: "$Verbosity!='Terse'"
+ then: [T: "ist eine"] # (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 eine"] # (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')
diff --git a/tests/Languages/de.rs b/tests/Languages/de.rs
new file mode 100644
index 00000000..45bce3f9
--- /dev/null
+++ b/tests/Languages/de.rs
@@ -0,0 +1,34 @@
+#![allow(non_snake_case)]
+
+mod ClearSpeak {
+ mod functions;
+ mod large_ops;
+ mod menclose;
+ mod mfrac;
+ mod mroot;
+ mod msup;
+ mod sets;
+ mod symbols_and_adornments;
+ mod multiline;
+}
+
+mod SimpleSpeak {
+ mod functions;
+ mod large_ops;
+ // mod menclose;
+ mod mfrac;
+ // mod mroot;
+ mod msup;
+ mod sets;
+ mod geometry;
+ mod linear_algebra;
+ mod multiline;
+ mod subscripts;
+}
+mod shared;
+mod units;
+mod chemistry;
+mod alphabets;
+mod intent;
+mod mtable;
+
diff --git a/tests/Languages/de/ClearSpeak/functions.rs b/tests/Languages/de/ClearSpeak/functions.rs
new file mode 100644
index 00000000..134fb3f8
--- /dev/null
+++ b/tests/Languages/de/ClearSpeak/functions.rs
@@ -0,0 +1,471 @@
+/// Tests for:
+/// * functions including trig functions, logs, and functions to powers
+/// * implied times/functional call and explicit times/function call
+/// * parens
+/// These are all intertwined, so they are in one file
+use crate::common::*;
+
+#[test]
+fn trig_names() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "sinus von x, plus kosinus von y, plus tangens von z, plus sekans von alpha, plus kosekans von phi, plus kotangens von phi");
+}
+
+#[test]
+fn hyperbolic_trig_names() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "hyperbolischer sinus von x, plus hyperbolischer cosinus von y, plus hyperbolischer tangens von z, plus, hyperbolischer sekans von alpha, plus, hyperbolischer kosekans, von phi; plus, hyperbolischer kotangens, von phi");
+}
+
+
+#[test]
+fn inverse_trig() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "umgekehrte sinus von x");
+}
+
+#[test]
+fn inverse_trig_trig_inverse() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Trig", "TrigInverse",expr,
+ "tangens umgekehrte von x");
+}
+
+#[test]
+fn inverse_trig_arc() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Trig", "ArcTrig",expr,
+ "ark hyperbolischer cosinus, von x");
+}
+
+#[test]
+fn trig_squared() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "sinus quadrat von x");
+}
+
+#[test]
+fn trig_cubed() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "tangens hoch 3 von x");
+}
+
+
+/*
+#[test]
+fn trig_fourth() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "the fourth power of, secant of x");
+}
+
+
+#[test]
+fn trig_power_other() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "the n minus 1 power of, hyperbolic sine of x");
+}
+ */
+#[test]
+fn simple_log() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "log x");
+}
+
+#[test]
+fn normal_log() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "der log von, klammer auf x plus y, klammer zu");
+}
+
+#[test]
+fn simple_log_with_base() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "der logarithmus basis b; von x");
+}
+
+#[test]
+fn normal_log_with_base() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "der logarithmus basis b; von, klammer auf x plus y, klammer zu");
+}
+
+#[test]
+fn simple_ln() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "l n x");
+}
+
+#[test]
+fn normal_ln() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "der l n von, klammer auf x plus y, klammer zu");
+}
+
+
+#[test]
+fn simple_natural_log() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Log", "LnAsNaturalLog",expr,
+ "Natürliche Logarithmus x");
+}
+
+
+#[test]
+fn natural_log() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Log", "LnAsNaturalLog",expr,
+ "der Natürliche Logarithmus von, klammer auf x plus y, klammer zu");
+}
+
+
+#[test]
+fn explicit_function_call_with_parens() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "t von x");
+}
+
+
+#[test]
+fn explicit_times_with_parens() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "t mal x");
+}
+
+#[test]
+fn explicit_function_call() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "t von x");
+}
+
+#[test]
+fn explicit_times() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "t x");
+}
+
+
+#[test]
+fn test_functions_none_pref() {
+ let expr = "";
+ // TODO: this should not succeed!
+ test_ClearSpeak("de", "ClearSpeak_Functions", "None",expr,
+ "der log von, klammer auf x plus y, klammer zu; plus, f mal, klammer auf x plus y, klammer zu");
+}
+
+#[test]
+fn test_functions_none_pref_multiple_args() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Functions", "None",expr,
+ "groß b mal, klammer auf 2 komma 6, klammer zu");
+}
+
+
+/*
+ * Tests for times
+ */
+#[test]
+fn no_times_binomial() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "x y");
+}
+
+#[test]
+fn times_following_paren() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "2 mal 3");
+}
+
+#[test]
+fn times_preceding_paren() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "2 mal 3");
+}
+
+
+/*
+
+#[test]
+fn times_sqrt() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "the square root of eigh; times the square root of b; is equal to, the square root of eigh b");
+}
+
+#[test]
+fn more_implied_times() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_ImpliedTimes", "MoreImpliedTimes",expr,
+ "open paren 2 times x, close paren squared");
+}
+
+#[test]
+fn explicit_times_more_implied_times() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_ImpliedTimes", "MoreImpliedTimes",expr, "t times x");
+}
+
+#[test]
+fn explicit_times_none_simple_right() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_ImpliedTimes", "None",
+ expr, "2, open bracket 3 close bracket");
+}
+
+#[test]
+fn explicit_times_none_simple_left() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_ImpliedTimes", "None",
+ expr, "open paren 2 minus 1, close paren; x");
+}
+
+#[test]
+fn explicit_times_none_superscript() {
+ let expr = "";
+ test_ClearSpeak_prefs("en",
+ vec![("ClearSpeak_ImpliedTimes", "None"), ("ClearSpeak_Functions", "None")],
+ expr, "f open paren x close paren; is equal to; x squared, open paren x plus 1, close paren");
+}
+
+/*
+ * Tests for parens
+ */
+ #[test]
+ fn no_parens_number() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "25 times x");
+ }
+
+ #[test]
+ fn no_parens_monomial() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "b, open paren x y close paren");
+ }
+
+ #[test]
+ fn no_parens_negative_number() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "2 plus negative 2");
+ }
+
+
+ #[test]
+ fn no_parens_negative_number_with_var() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "negative 2 x, plus 1");
+ }
+
+ #[test]
+ fn parens_superscript() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "open paren 2 x close paren squared");
+ }
+
+ #[test]
+ fn no_parens_fraction() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "2 plus 1 half");
+ }
+
+
+ // Tests for the ten types of intervals in ClearSpeak
+ #[test]
+ fn parens_interval_open_open() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Paren", "Interval",expr,
+ "the interval from c to d, not including c or d");
+}
+
+#[test]
+ fn parens_interval_closed_open() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Paren", "Interval ",expr,
+ "the interval from c to d, including c but not including d");
+}
+
+
+#[test]
+fn parens_interval_open_closed() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Paren", "Interval ",expr,
+ "the interval from c to d, not including c but including d");
+}
+
+
+#[test]
+fn parens_interval_closed_closed() {
+ let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Paren", "Interval ",expr,
+"the interval from c to d, including c and d");
+}
+
+ #[test]
+ fn parens_interval_neg_infinity_open_open() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Paren", "Interval ",expr,
+ "the interval from negative infinity to d, not including d");
+}
+
+ #[test]
+ fn parens_interval_neg_infinity_closed_open() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Paren", "Interval ",expr,
+ "the interval from negative infinity to d, including d");
+}
+
+
+#[test]
+fn parens_interval_open_open_infinity() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Paren", "Interval ",expr,
+ "the interval from c to infinity, not including c");
+}
+
+
+#[test]
+fn parens_interval_closed_open_infinity() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Paren", "Interval ",expr,
+"the interval from c to infinity, including c");
+}
+
+#[test]
+fn parens_interval_neg_infinity_to_infinity() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Paren", "Interval ",expr,
+ "the interval from negative infinity to infinity");
+}
+
+#[test]
+fn parens_interval_neg_infinity_to_pos_infinity() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Paren", "Interval ",expr,
+ "the interval from negative infinity to positive infinity");
+}
+*/
\ No newline at end of file
diff --git a/tests/Languages/de/ClearSpeak/large_ops.rs b/tests/Languages/de/ClearSpeak/large_ops.rs
new file mode 100644
index 00000000..7b52fc2c
--- /dev/null
+++ b/tests/Languages/de/ClearSpeak/large_ops.rs
@@ -0,0 +1,200 @@
+use crate::common::*;
+
+#[test]
+fn sum_both() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die summe von n ist gleich 1 bis 10 von n");
+}
+
+#[test]
+fn sum_under() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die summe durch groß s von i");
+}
+#[test]
+fn sum_both_msubsup() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die summe von n ist gleich 1 bis 10 von n");
+}
+
+#[test]
+fn sum_sub() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die summe durch groß s von i");
+}
+
+#[test]
+fn sum() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die summe von a sub i");
+}
+
+#[test]
+fn product_both() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die produkt von n ist gleich 1 bis 10 von n");
+}
+
+#[test]
+fn product_under() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die produkt durch groß s von i");
+}
+
+#[test]
+fn product() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die produkt von a sub i");
+}
+
+#[test]
+fn intersection_both() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die N-stufiger Durchschnitt von i ist gleich 1 bis 10 von; groß s sub i");
+}
+
+#[test]
+fn intersection_under() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die N-stufiger Durchschnitt durch groß c von; groß s sub i");
+}
+
+#[test]
+fn intersection() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die N-stufiger Durchschnitt von groß s sub i");
+}
+
+#[test]
+fn union_both() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die N-stufige Vereinigung von i ist gleich 1 bis 10 von; groß s sub i");
+}
+
+#[test]
+fn union_under() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die N-stufige Vereinigung durch groß c von; groß s sub i");
+}
+
+#[test]
+fn union() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die N-stufige Vereinigung von groß s sub i");
+}
+
+#[test]
+fn integral_both() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die integral von 0 bis 1 von, f von x; d x");
+}
+
+#[test]
+fn integral_under() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die integral durch die reelen zahlen von; f von x d x");
+}
+
+#[test]
+fn integral() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die integral von f von x d x");
+}
\ No newline at end of file
diff --git a/tests/Languages/de/ClearSpeak/menclose.rs b/tests/Languages/de/ClearSpeak/menclose.rs
new file mode 100644
index 00000000..38a92b8b
--- /dev/null
+++ b/tests/Languages/de/ClearSpeak/menclose.rs
@@ -0,0 +1,197 @@
+use crate::common::*;
+
+#[test]
+fn menclose_actuarial() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "versicherungsmathematische symbol, einschließen 3 plus 2 i ende der einschliessung");
+}
+
+#[test]
+fn menclose_box() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "box, kreis, einschließen 3 plus 2 i ende der einschliessung");
+}
+
+#[test]
+fn menclose_left() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "linie links, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_right() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "linie rechts, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_top_bottom() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "linie oben, unten, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_updiagonalstrike() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "diagonal nach oben, durchstreichen, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_downdiagonalstrike() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "diagonal nach unten, durchstreichen, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_cross_out() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "x, durchstreichen, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_vertical_horizontal_strike() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "vertikal, horizontal, durchstreichen, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_leftarrow() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "pfeil nach links, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_right_up_down_arrow() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "pfeil nach oben, pfeil nach unten, pfeil nach rechts, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_northeastarrow() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "pfeil nach nordost, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_other_single_arrows() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "pfeil nach südost, pfeil nach südwest, pfeil nach nordwest, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_northwestsoutheastarrow() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "doppelpfeil diagonal nach unten, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_other_double_arrows() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "doppelpfeil nach oben und unten, doppelpfeil nach links und rechts, doppelpfeil diagonal nach oben, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_madrub() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "arabisches faktor-symbol, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_phasorangle() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "phasenwinkel, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_circle_phasorangle() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "kreis, phasenwinkel, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn menclose_longdiv() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "symbol für schriftliche division, einschließen 3 hälften ende der einschliessung");
+}
+
+/*
+#[test]
+fn menclose_longdiv_default() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "symbol für schriftliche division, einschließen 3 hälften ende der einschliessung");
+}
+
+
+#[test]
+fn menclose_longdiv_empty_string() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "long division symbol, enclosing 3 halves end enclosure");
+}
+
+#[test]
+fn menclose_longdiv_whitespace_string() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "long division symbol, enclosing 3 halves end enclosure");
+}
+
+ */
+
+#[test]
+fn menclose_radical() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "quadratwurzel, einschließen 3 hälften ende der einschliessung");
+}
+
+#[test]
+fn simple_speak_menclose_top_bottom() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "linie oben, unten, einschließen 3 hälften ende der einschliessung");
+}
diff --git a/tests/Languages/de/ClearSpeak/mfrac.rs b/tests/Languages/de/ClearSpeak/mfrac.rs
new file mode 100644
index 00000000..18fc8284
--- /dev/null
+++ b/tests/Languages/de/ClearSpeak/mfrac.rs
@@ -0,0 +1,274 @@
+/// Tests for fractions
+/// includes simple fractions and more complex fractions
+/// also tests mixed fractions (implicit and explicit)
+use crate::common::*;
+
+#[test]
+fn common_fraction_half() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "1 hälfte");
+}
+
+#[test]
+fn common_fraction_thirds() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "2 dritte");
+}
+
+#[test]
+fn common_fraction_tenths() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Auto")], expr, "17 zehnte");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Ordinal")], expr, "17 zehnte");
+}
+
+#[test]
+#[allow(non_snake_case)]
+fn not_ClearSpeak_common_fraction_tenths() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Auto")], expr, "89 durch 10");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Ordinal")], expr, "89 zehnte");
+}
+
+#[test]
+fn non_simple_fraction() {
+ let expr = "
+ ";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Auto")], expr, "der bruch mit zähler; x plus y; und nenner x minus y");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Ordinal")], expr, "der bruch mit zähler; x plus y; und nenner x minus y");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Over")], expr, "x plus y durch x minus y");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "FracOver")], expr, "der bruch x plus y durch x minus y");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "General")], expr, "der bruch mit zähler; x plus y; und nenner x minus y");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "EndFrac")], expr, "der bruch mit zähler; x plus y; und nenner x minus y; ende des bruchs");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "GeneralEndFrac")], expr, "der bruch mit zähler; x plus y; und nenner x minus y; ende des bruchs");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "OverEndFrac")], expr, "x plus y durch x minus y, ende des bruchs");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Per")], expr, "x plus y pro x minus y");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Verbose"),("ClearSpeak_Fractions", "Auto")], expr, "der bruch mit zähler; x plus y; und nenner x minus y; ende des bruchs");
+}
+
+#[test]
+fn frac_with_units() {
+ let expr = "
+ ";
+ test("de", "ClearSpeak", expr, "62 meiles pro stunde");
+}
+
+
+#[test]
+fn mixed_number() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "3 und 1 hälfte");
+}
+
+#[test]
+fn explicit_mixed_number() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "3 und 1 achtel");
+}
+
+#[test]
+fn mixed_number_big() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "3 und 7 durch 83");
+}
+
+#[test]
+fn simple_text() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "rise durch run");
+}
+
+#[test]
+fn number_and_text() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "2 miles durch 3 gallons");
+}
+
+
+#[test]
+fn nested_simple_fractions() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("ClearSpeak_Fractions", "Auto")], expr, "1 hälfte durch 2 dritte");
+ test_prefs("de", "ClearSpeak", vec![("ClearSpeak_Fractions", "Ordinal")], expr, "1 hälfte durch 2 dritte");
+ test_prefs("de", "ClearSpeak", vec![("ClearSpeak_Fractions", "Over")], expr, "1 durch 2 durch 2 durch 3");
+ test_prefs("de", "ClearSpeak", vec![("ClearSpeak_Fractions", "FracOver")], expr,
+ "der bruch der bruch 1 durch 2 durch der bruch 2 durch 3");
+ test_prefs("de", "ClearSpeak", vec![("ClearSpeak_Fractions", "General")], expr,
+ "der bruch mit zähler der bruch mit zähler 1; und nenner 2; und nenner der bruch mit zähler 2; und nenner 3");
+ test_prefs("de", "ClearSpeak", vec![("ClearSpeak_Fractions", "EndFrac")], expr, "1 hälfte durch 2 dritte");
+ test_prefs("de", "ClearSpeak", vec![("ClearSpeak_Fractions", "GeneralEndFrac")], expr,
+ "der bruch mit zähler der bruch mit zähler 1; und nenner 2; ende des bruchs; und nenner der bruch mit zähler 2; und nenner 3; ende des bruchs; ende des bruchs");
+ test_prefs("de", "ClearSpeak", vec![("ClearSpeak_Fractions", "OverEndFrac")], expr,
+ "1 durch 2, ende des bruchs, durch 2 durch 3, ende des bruchs; ende des bruchs");
+}
+
+
+#[test]
+fn semi_nested_fraction() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "2 dritte x durch 6");
+}
+
+#[test]
+fn general_nested_fraction() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "der bruch mit zähler; 10 durch n; und nenner 2 durch n");
+}
+
+#[test]
+fn complex_nested_fraction() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "der bruch mit zähler; der bruch mit zähler; n plus 10; und nenner n; und nenner 2 durch n");
+}
+
+#[test]
+fn simple_function() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Auto")], expr, "f von x durch 2");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Verbose"), ("ClearSpeak_Fractions", "Auto")], expr, "f von x durch 2, ende des bruchs");
+}
+
+#[test]
+fn function_over_function() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Auto")], expr, "f von x durch g von x");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Verbose"), ("ClearSpeak_Fractions", "Auto")], expr, "f von x durch g von x, ende des bruchs");
+}
+
+#[test]
+fn non_simple_function_over_function() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Fractions", "Auto")], expr,
+ "der bruch mit zähler; f von, klammer auf x plus 1, klammer zu; und nenner g von x");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Verbose"), ("ClearSpeak_Fractions", "Auto")], expr,
+ "der bruch mit zähler; f von, klammer auf x plus 1, klammer zu; und nenner g von x; ende des bruchs");
+}
+
+#[test]
+fn binomial() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "2 mal 7 wählen 3");
+}
diff --git a/tests/Languages/de/ClearSpeak/mroot.rs b/tests/Languages/de/ClearSpeak/mroot.rs
new file mode 100644
index 00000000..b90312e8
--- /dev/null
+++ b/tests/Languages/de/ClearSpeak/mroot.rs
@@ -0,0 +1,136 @@
+use crate::common::*;
+
+#[test]
+fn msqrt_simple() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die quadratwurzel von x");
+}
+
+#[test]
+fn msqrt_simple_end_root() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Roots", "RootEnd", expr, "die quadratwurzel von x, ende der wurzel");
+}
+
+#[test]
+fn msqrt_simple_positive() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Roots", "PosNegSqRoot", expr, "die plus quadratwurzel von x");
+}
+
+#[test]
+fn msqrt_simple_pos_end_root() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Roots", "PosNegSqRootEnd", expr, "die plus quadratwurzel von x, ende der wurzel");
+}
+
+#[test]
+fn msqrt_simple_pos_end_with_neg_root() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Roots", "PosNegSqRootEnd", expr,
+ "die minus quadratwurzel von x, ende der wurzel; minus, die positive kubikwurzel von x, ende der wurzel");
+}
+
+#[test]
+fn mroot_simple_pos_end_with_neg_root() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Roots", "PosNegSqRoot", expr,
+ "die negative kubikwurzel von x; minus die plus quadratwurzel von x");
+}
+
+#[test]
+fn neg_without_root() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "negative x minus y");
+}
+
+#[test]
+fn msqrt() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die quadratwurzel von x plus y");
+}
+
+#[test]
+fn mroot_as_square_root() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die quadratwurzel von x");
+}
+
+#[test]
+fn cube_root() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die kubikwurzel von x");
+}
+
+#[test]
+fn ordinal_root() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die neunte Wurzel von x");
+}
+
+
+/* // should have n-te wurze
+#[test]
+fn simple_mi_root() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die n-th wurzel von x");
+}
+
+#[test]
+fn mroot_simple_pos_end_root() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Roots", "PosNegSqRootEnd", expr, "the positive t-th root of x, end root");
+}
+
+ */
+
+#[test]
+fn mroot_simple_end_root() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Roots", "RootEnd", expr, "die zwanzig erste Wurzel von x plus y, ende der wurzel");
+}
+
+#[test]
+fn simple_fraction_power() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die 1 drittel wurzel von x");
+}
diff --git a/tests/Languages/de/ClearSpeak/msup.rs b/tests/Languages/de/ClearSpeak/msup.rs
new file mode 100644
index 00000000..8dc876ec
--- /dev/null
+++ b/tests/Languages/de/ClearSpeak/msup.rs
@@ -0,0 +1,351 @@
+/// Tests for superscripts
+/// simple superscripts
+/// complex/nested superscripts
+use crate::common::*;
+
+#[test]
+fn squared() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "x quadrat");
+/* test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "x to the second");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "x to the second power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "x raised to the power 2");
+*/
+}
+
+#[test]
+fn cubed() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "x hoch 3");
+
+/* test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "x to the third");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "x to the third power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "x raised to the power 3");
+ */
+}
+
+/*
+#[test]
+fn ordinal_power() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "3 to the fifth power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "3 to the fifth");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "3 to the fifth power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "3 raised to the power 5");
+}
+
+
+#[test]
+fn zero_power() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "3 to the 0 power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "3 to the 0");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "3 to the 0 power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "3 raised to the power 0");
+}
+#[test]
+fn simple_mi_power() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "4 to the x-th power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "4 to the x-th");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "4 to the x-th power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "4 raised to the power x");
+}
+
+
+#[test]
+fn decimal_power() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "3 raised to the 5.0 power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "3 raised to the 5.0 power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "3 raised to the 5.0 power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "3 raised to the power 5.0");
+}
+
+#[test]
+fn non_simple_power() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "3 raised to the y plus 2 power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "3 raised to the y plus 2 power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "3 raised to the y plus 2 power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "3 raised to the power y plus 2");
+}
+
+
+#[test]
+fn negative_power() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "3 to the negative 2 power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "3 to the negative 2");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "3 to the negative 2 power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "3 raised to the power negative 2");
+}
+*/
+
+#[test]
+fn simple_fraction_power() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "x hoch 1 drittel");
+}
+
+#[test]
+fn nested_squared_power_with_coef() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "3 hoch 2 x quadrat");
+ /*
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "3 raised to the exponent, 2 x to the second, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "3 raised to the exponent, 2 x to the second power, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "3 raised to the exponent, 2 x raised to the power 2; end exponent");
+ */
+
+}
+
+/*
+#[test]
+fn nested_squared_power_with_neg_coef() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "3 raised to the negative 2 x squared power");
+}
+
+
+#[test]
+fn nested_cubed_power() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "y raised to the 4 fifths cubed power");
+}
+
+#[test]
+fn nested_cubed_power_with_neg_base() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "y raised to the negative 4 fifths cubed power");
+}
+
+#[test]
+fn nested_number_times_squared() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "e raised to the 1 half x squared power");
+}
+
+#[test]
+fn nested_negative_number_times_squared() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "e raised to the negative 1 half x squared power");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "e raised to the exponent, negative 1 half x to the second, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "e raised to the exponent, negative 1 half x to the second power, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "e raised to the exponent, negative 1 half x raised to the power 2; end exponent");
+}
+
+#[test]
+fn nested_expr_to_tenth() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "3 raised to the exponent, 3 to the tenth power, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "3 raised to the exponent, 3 to the tenth, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "3 raised to the exponent, 3 to the tenth power, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "3 raised to the exponent, 3 raised to the power 10; end exponent");
+
+}
+
+#[test]
+fn nested_non_simple_squared_exp() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr, "3 raised to the exponent, open paren x plus 1, close paren squared, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr, "3 raised to the exponent, open paren x plus 1, close paren to the second, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr, "3 raised to the exponent, open paren x plus 1, close paren to the second power, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr, "3 raised to the exponent, open paren x plus 1, close paren raised to the power 2; end exponent");
+}
+
+#[test]
+fn nested_default_power() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "t raised to the exponent, 4 fifths to the n-th power, end exponent");
+}
+
+#[test]
+fn nested_complex_power() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Auto")], expr,
+ "e raised to the exponent, negative 1 half times; open paren; the fraction with numerator; x minus mu; and denominator sigma; close paren squared, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "Ordinal")], expr,
+ "e raised to the exponent, negative 1 half times; open paren; the fraction with numerator; x minus mu; and denominator sigma; close paren to the second, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "OrdinalPower")], expr,
+ "e raised to the exponent, negative 1 half times; open paren; the fraction with numerator; x minus mu; and denominator sigma; close paren to the second power, end exponent");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_Exponents", "AfterPower")], expr,
+ "e raised to the exponent, negative 1 half times; open paren; the fraction with numerator; x minus mu; and denominator sigma; close paren raised to the power 2; end exponent");
+}
+
+#[test]
+fn default_power() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "t raised to the fraction with numerator; b plus 1; and denominator 3; power");
+}
+
+ */
\ No newline at end of file
diff --git a/tests/Languages/de/ClearSpeak/multiline.rs b/tests/Languages/de/ClearSpeak/multiline.rs
new file mode 100644
index 00000000..c324c9db
--- /dev/null
+++ b/tests/Languages/de/ClearSpeak/multiline.rs
@@ -0,0 +1,196 @@
+use crate::common::*;
+
+/* // need to fix: 3 falls => 3 fälle
+#[test]
+fn case_1() {
+ let expr = "
+ ";
+ test_ClearSpeak("de", "ClearSpeak_MultiLineLabel", "Auto", expr,
+ "f of x is equal to; 3 cases; \
+ case 1; negative 1 if x is less than 0; \
+ case 2; 0 if x is equal to 0; \
+ case 3; 1 if x is greater than 0"
+ )
+}
+
+ */
+
+#[test]
+fn equation_auto() {
+ let expr = "
+ ";
+ test_ClearSpeak("de", "ClearSpeak_MultiLineLabel", "Auto", expr,
+ "2 zeiles; zeile 1; x plus y, ist gleich 7; zeile 2; 2 x plus 3 y; ist gleich 17");
+}
+
+
+/* // fixme: zeiles => zeilen
+#[test]
+fn equation_plus_at_start() {
+ let expr = "
+ ";
+ test_ClearSpeak("de", "ClearSpeak_MultiLineLabel", "Auto", expr, "2 lines; \
+ line 1; x plus y is equal to 7; \
+ line 2; 2 x, plus 3 y, is equal to 17");
+}
+
+ */
+
+/*
+#[test]
+fn equation_case() {
+ let expr = "
+ ";
+ test_ClearSpeak("de", "ClearSpeak_MultiLineLabel", "Case", expr,
+ "2 cases; case 1; x plus y, is equal to 7; case 2; 2 x plus 3 y; is equal to 17");
+}
+
+ */
+
+/* // fixme: Bedingungs => Bedingungen
+#[test]
+fn equation_constraint() {
+ let expr = "
+ ";
+ test_ClearSpeak("de", "ClearSpeak_MultiLineLabel", "Constraint", expr, "2 constraints; \
+ constraint 1; x plus y, is equal to 7; \
+ constraint 2; 2 x plus 3 y; is equal to 17");
+}
+*/
+
+/* // fixme: Gleichungs => Gleichungen
+#[test]
+fn equation_equation() {
+ let expr = "
+ ";
+ test_ClearSpeak("de", "ClearSpeak_MultiLineLabel", "Equation", expr, "2 equations; \
+ equation 1; x plus y, is equal to 7; \
+ equation 2; 2 x plus 3 y; is equal to 17");
+}
+
+ */
+
+/* // FIXME: Zeiles => Zeilen
+#[test]
+fn equation_line() {
+ let expr = "
+ ";
+ test_ClearSpeak("de", "ClearSpeak_MultiLineLabel", "Line", expr, "2 lines; \
+ line 1; x plus y, is equal to 7; \
+ line 2; 2 x plus 3 y; is equal to 17");
+}
+
+
+#[test]
+fn equation_none() {
+ let expr = "
+ ";
+ test_ClearSpeak("de", "ClearSpeak_MultiLineLabel", "None", expr,
+ "2 lines; \
+ x plus y, is equal to 7; \
+ 2 x plus 3 y; is equal to 17");
+}
+
+#[test]
+fn equation_row() {
+ let expr = "
+ ";
+ test_ClearSpeak("de", "ClearSpeak_MultiLineLabel", "Row", expr, "2 rows; \
+ row 1; x plus y, is equal to 7; \
+ row 2; 2 x plus 3 y; is equal to 17");
+}
+ */
+
+/* // FIXME: stufes => Stufen
+#[test]
+fn equation_step() {
+ let expr = "
+ ";
+ test_ClearSpeak("de", "ClearSpeak_MultiLineLabel", "Step", expr, "2 steps; \
+ step 1; x plus y, is equal to 7; \
+ step 2; 2 x plus 3 y; is equal to 17");
+}
+
+#[test]
+fn continued_row() {
+ let expr = "";
+test("de", "SimpleSpeak", expr,
+ "2 equations; equation 1; x is equal to y plus 1; equation 2; y is equal to 1");
+}
+*/
\ No newline at end of file
diff --git a/tests/Languages/de/ClearSpeak/sets.rs b/tests/Languages/de/ClearSpeak/sets.rs
new file mode 100644
index 00000000..2a400006
--- /dev/null
+++ b/tests/Languages/de/ClearSpeak/sets.rs
@@ -0,0 +1,452 @@
+use crate::common::*;
+
+#[test]
+fn complex() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die komplexen zahlen");
+}
+
+#[test]
+fn natural() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die natürlichen zahlen");
+}
+
+#[test]
+fn rationals() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die rationalen zahlen");
+}
+
+#[test]
+fn reals() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die reelen zahlen");
+}
+
+#[test]
+fn integers() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die ganzen zahlen");
+}
+
+
+
+#[test]
+fn msup_complex() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "c 2");
+}
+
+#[test]
+fn msup_natural() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "n 2");
+}
+
+#[test]
+fn msup_rationals() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "q 2");
+}
+
+#[test]
+fn msup_reals() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "r 3");
+}
+
+#[test]
+fn msup_integers() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "z 4");
+}
+
+#[test]
+fn msup_positive_integers() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die positiven ganze zahlen");
+}
+
+#[test]
+fn msup_negative_integers() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die negativen ganze zahlen");
+}
+
+#[test]
+fn msup_positive_rationals() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die positiven rationale zahlen");
+}
+
+#[test]
+fn msup_negative_rationals() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die negativen rationale zahlen");
+}
+
+#[test]
+fn empty_set() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "leere Menge");
+}
+
+#[test]
+fn single_element_set() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die Menge 12");
+}
+
+#[test]
+fn multiple_element_set() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die Menge 5 komma 10 komma 15");
+}
+
+#[test]
+fn set_with_colon() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die Menge alle x so dass x ist größer als 2");
+}
+
+#[test]
+fn set_with_bar() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die Menge alle x so dass x ist größer als 2");
+}
+
+#[test]
+fn element_alone() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "3 plus 2 i, ist kein element von, die reelen zahlen");
+}
+
+#[test]
+fn element_under_sum() {
+ let expr = "";
+ test("de", "ClearSpeak", expr,
+ "die summe durch i ist ein element von, die ganzen zahlen von; der bruch mit zähler 1; und nenner i quadrat");
+}
+
+#[test]
+fn complicated_set_with_colon() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "die Menge alle x in die ganzen zahlen so dass 2 ist kleiner als x ist kleiner als 7");
+}
+
+#[test]
+fn complicated_set_with_mtext() {
+ // as of 8/5/21, parsing of "|" is problematic in the example, so are needed for this test
+ let expr = "";
+ test("de", "ClearSpeak", expr,
+ "die Menge alle x in die natürlichen zahlen so dass x is an even number");
+}
+
+
+#[test]
+fn set_with_bar_member() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Member",
+ expr, "die Menge alle x element von die ganzen zahlen so dass x ist größer als 5");
+}
+
+#[test]
+fn element_alone_member() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Member",
+ expr, "3 plus 2 i, ist kein element von, die reelen zahlen");
+}
+
+#[test]
+fn element_under_sum_member() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Member",
+ expr, "die summe durch i ist ein element von, die ganzen zahlen von; der bruch mit zähler 1; und nenner i quadrat");
+}
+
+
+#[test]
+fn set_with_bar_element() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Element",
+ expr, "die Menge alle x element von die ganzen zahlen so dass x ist größer als 5");
+}
+
+#[test]
+fn element_alone_element() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Element",
+ expr, "3 plus 2 i, ist kein element von, die reelen zahlen");
+}
+
+#[test]
+fn element_under_sum_element() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Element",
+ expr, "die summe durch i ist ein element von, die ganzen zahlen von; der bruch mit zähler 1; und nenner i quadrat");
+}
+
+#[test]
+fn set_with_bar_in() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "In",
+ expr, "die Menge alle x in die ganzen zahlen so dass x ist größer als 5");
+}
+
+#[test]
+fn element_alone_in() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "In",
+ expr, "3 plus 2 i, ist nicht in die reelen zahlen");
+}
+
+#[test]
+fn element_under_sum_in() {
+ let expr = "";
+ 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");
+}
+
+#[test]
+fn set_with_bar_belongs() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Belongs",
+ expr, "die Menge alle x element von die ganzen zahlen so dass x ist größer als 5");
+}
+
+#[test]
+fn element_alone_belongs() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Belongs",
+ expr, "3 plus 2 i, nicht element von, die reelen zahlen");
+}
+
+#[test]
+fn element_under_sum_belongs() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_SetMemberSymbol", "Belongs",
+ expr, "die summe durch i element von die ganzen zahlen von; der bruch mit zähler 1; und nenner i quadrat");
+}
+
+
+#[test]
+fn set_member_woall() {
+ let expr = "";
+ test_ClearSpeak_prefs("en", vec![("ClearSpeak_SetMemberSymbol", "Member"), ("ClearSpeak_Sets", "woAll")],
+ expr, "the set of x member of the integers such that x is greater than 5");
+}
+
+#[test]
+fn multiple_element_set_woall() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Sets", "woAll", expr, "die Menge 5 komma 10 komma 15");
+}
+
+#[test]
+fn multiple_element_set_silent_bracket() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Sets", "SilentBracket", expr, "5 komma 10 komma 15");
+ }
+
+#[test]
+fn silent_bracket() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Sets", "SilentBracket", expr,
+ "die Menge alle x so dass x ist größer als 2");
+ }
+
diff --git a/tests/Languages/de/ClearSpeak/symbols_and_adornments.rs b/tests/Languages/de/ClearSpeak/symbols_and_adornments.rs
new file mode 100644
index 00000000..2633fcd7
--- /dev/null
+++ b/tests/Languages/de/ClearSpeak/symbols_and_adornments.rs
@@ -0,0 +1,332 @@
+use crate::common::*;
+
+#[test]
+fn multiplication() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "2 mal 3");
+}
+
+/*
+#[test]
+fn multiplication_by() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_MultSymbolX", "By", expr, "2 by 3");
+}*/
+
+#[test]
+fn multiplication_cross() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_MultSymbolX", "Cross", expr, "u mal v");
+}
+
+#[test]
+fn ellipses_auto_start() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "punkt punkt punkt komma negative 2 komma negative 1 komma 0");
+}
+
+#[test]
+fn ellipses_auto_end() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Ellipses", "Auto", expr, "1 komma 2 komma 3 komma punkt punkt punkt");
+}
+
+#[test]
+fn ellipses_auto_middle() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Ellipses", "Auto", expr,
+ "1 komma 2 komma 3 komma punkt punkt punkt komma 20");
+}
+
+#[test]
+fn ellipses_auto_both() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Ellipses", "Auto", expr,
+ "punkt punkt punkt komma negative 2 komma negative 1 komma 0 komma 1 komma 2 komma punkt punkt punkt");
+}
+
+#[test]
+fn ellipses_and_so_on_start() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Ellipses", "AndSoOn", expr, "punkt punkt punkt komma negative 2 komma negative 1 komma 0");
+}
+
+#[test]
+fn ellipses_and_so_on_end() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Ellipses", "AndSoOn", expr, "1 komma 2 komma 3 und so weiter");
+}
+
+#[test]
+fn ellipses_and_so_on_middle() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Ellipses", "AndSoOn", expr,
+ "1 komma 2 komma 3 punkt punkt punkt 20");
+}
+
+#[test]
+fn ellipses_and_so_on_both() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Ellipses", "AndSoOn", expr,
+ "punkt punkt punkt komma negative 2 komma negative 1 komma 0 komma 1 komma 2 komma punkt punkt punkt");
+}
+
+#[test]
+fn vertical_line_auto() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Auto", expr,
+ "3 teilt 6");
+}
+
+#[test]
+fn vertical_line_divides() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Divides", expr,
+ "3 teilt 6");
+}
+
+ #[test]
+ fn vertical_line_given() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Given", expr,
+ "3 gegeben 6");
+ }
+
+ #[test]
+ fn vertical_line_probability_given() {
+ let expr = "";
+ test_ClearSpeak_prefs("en", vec![("ClearSpeak_VerticalLine", "Given"), ("ClearSpeak_ImpliedTimes", "None")]
+ , expr, "cap p, open paren, cap eigh given cap b, close paren");
+ }
+
+#[test]
+fn vertical_line_set() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Auto", expr,
+ "die Menge alle x so dass x ist größer als 0");
+}
+
+
+#[test]
+fn vertical_line_set_such_that() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_VerticalLine", "SuchThat", expr,
+ "die Menge alle x so dass x ist größer als 0");
+}
+
+#[test]
+fn vertical_line_set_given() {
+ let expr = "";
+ // 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");
+}
+
+#[test]
+fn vertical_line_set_and_abs() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Auto", expr,
+ "die Menge alle x so dass der Betrag von x; ist größer als 2");
+}
+
+#[test]
+fn vertical_line_evaluated_at() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Auto", expr,
+ "f von x, ausgewertet bei, x ist gleich 5");
+}
+
+#[test]
+fn vertical_line_evaluated_at_both() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Auto", expr,
+ "x quadrat plus x, ausgewertet zwischen 1 und 0");
+}
+#[test]
+fn vertical_line_evaluated_at_divides() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Divides", expr,
+ "f von x, ausgewertet bei, x ist gleich 5");
+}
+
+#[test]
+fn vertical_line_evaluated_at_both_given() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_VerticalLine", "Given", expr,
+ "x quadrat plus x, ausgewertet zwischen 1 und 0");
+}
\ No newline at end of file
diff --git a/tests/Languages/de/SimpleSpeak/functions.rs b/tests/Languages/de/SimpleSpeak/functions.rs
new file mode 100644
index 00000000..f6634643
--- /dev/null
+++ b/tests/Languages/de/SimpleSpeak/functions.rs
@@ -0,0 +1,340 @@
+/// Tests for:
+/// * functions including trig functions, logs, and functions to powers
+/// * implied times/functional call and explicit times/function call
+/// * parens
+/// These are all intertwined, so they are in one file
+use crate::common::*;
+
+#[test]
+fn trig_names() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "sine of x plus cosine of y plus tangent of z plus secant of alpha, plus cosecant of phi, plus cotangent of phi");
+}
+
+#[test]
+fn hyperbolic_trig_names() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "hyperbolic sine of x, plus \
+ hyperbolic cosine of y, plus \
+ hyperbolic tangent of z, plus \
+ hyperbolic secant of alpha, plus \
+ hyperbolic cosecant of phi, plus \
+ hyperbolic cotangent of phi");
+}
+
+
+#[test]
+fn inverse_trig() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "inverse sine of x");
+}
+
+#[test]
+fn trig_squared() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "sine squared of x");
+}
+
+#[test]
+fn trig_cubed() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "tangent cubed of x");
+}
+
+#[test]
+fn trig_fourth() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the fourth power of, secant of x");
+}
+
+
+#[test]
+fn trig_power_other() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the n minus 1 power of, hyperbolic sine of x");
+}
+
+#[test]
+fn simple_log() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the log of x");
+}
+
+#[test]
+fn normal_log() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the log of, open paren x plus y, close paren");
+}
+
+#[test]
+fn simple_log_with_base() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the log base b, of x");
+}
+
+#[test]
+fn normal_log_with_base() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the log base b, of, open paren x plus y, close paren");
+}
+
+#[test]
+fn normal_ln() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "l n, open x plus y close");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Medium")],
+ expr, "the natural log of, open paren x plus y, close paren");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")],
+ expr, "the natural log of, open paren x plus y, close paren");
+}
+
+#[test]
+fn simple_ln() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "l n x");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Medium")],
+ expr, "the natural log of x");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")],
+ expr, "the natural log of x");
+}
+
+#[test]
+fn other_names() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "Cov x");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Medium")],
+ expr, "covariance x");
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "exp of x");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Medium")],
+ expr, "exponential of x");
+}
+
+#[test]
+fn explicit_function_call_with_parens() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "t of x");
+}
+
+
+#[test]
+fn explicit_times_with_parens() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "t times x");
+}
+
+#[test]
+fn explicit_function_call() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "t of x");
+}
+
+#[test]
+fn explicit_times() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "t x");
+}
+
+
+/*
+ * Tests for times
+ */
+#[test]
+fn no_times_binomial() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "x y");
+}
+
+#[test]
+fn times_following_paren() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2 times 3");
+}
+
+#[test]
+fn times_preceding_paren() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2 times 3");
+}
+
+#[test]
+fn no_times_sqrt() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr,
+ "the square root of eigh; times the square root of b; is equal to, the square root of eigh b end root");
+ test_prefs("de", "SimpleSpeak", vec![("Impairment", "LearningDisability")], expr,
+ "the square root of eigh; times the square root of b; is equal to, the square root of eigh b");
+}
+
+/*
+ * Tests for parens
+ */
+ #[test]
+ fn no_parens_number() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "25 times x");
+ }
+
+ #[test]
+ fn no_parens_monomial() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "b, open paren x y close paren");
+ }
+
+ #[test]
+ fn no_parens_negative_number() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2 plus negative 2");
+ }
+
+
+ #[test]
+ fn no_parens_negative_number_with_var() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "negative 2 x, plus 1");
+ }
+
+ #[test]
+ fn parens_superscript() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "open paren 2 x close paren squared");
+ }
+
+ #[test]
+ fn no_parens_fraction() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2 plus 1 half");
+ }
+
+
+ // Tests for the four types of intervals in SimpleSpeak
+ #[test]
+ fn parens_interval_open_open() {
+ let expr = "";
+ test("de", "SimpleSpeak",expr, "the open interval from c to d");
+}
+
+#[test]
+ fn parens_interval_closed_open() {
+ let expr = "";
+ test("de", "SimpleSpeak",expr, "the closed open interval from c to d");
+}
+
+
+#[test]
+fn parens_interval_open_closed() {
+ let expr = "";
+ test("de", "SimpleSpeak",expr,"the open closed interval from c to d");
+}
+
+
+#[test]
+fn parens_interval_closed_closed() {
+ let expr = "";
+ test("de", "SimpleSpeak",expr, "the closed interval from c to d");
+}
+
+ #[test]
+ fn parens_interval_neg_infinity_open_open() {
+ let expr = "";
+ test("de", "SimpleSpeak",expr,
+ "the open interval from negative infinity to d");
+}
+
+ #[test]
+ fn parens_interval_neg_infinity_open_closed() {
+ let expr = "";
+ test("de", "SimpleSpeak",expr,
+ "the open closed interval from negative infinity to d");
+}
+
diff --git a/tests/Languages/de/SimpleSpeak/geometry.rs b/tests/Languages/de/SimpleSpeak/geometry.rs
new file mode 100644
index 00000000..d1fc2438
--- /dev/null
+++ b/tests/Languages/de/SimpleSpeak/geometry.rs
@@ -0,0 +1,27 @@
+/// Tests for geometry listed in intent
+/// ABC as mtext and as separated letters
+use crate::common::*;
+
+#[test]
+fn arc() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "arc cap b cap c");
+}
+
+#[test]
+fn ray() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "line segment cap x cap y");
+}
+
+#[test]
+fn arc_mtext() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "arc cap b cap c");
+}
+
+#[test]
+fn ray_mtext() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "ray cap x cap y");
+}
diff --git a/tests/Languages/de/SimpleSpeak/large_ops.rs b/tests/Languages/de/SimpleSpeak/large_ops.rs
new file mode 100644
index 00000000..213b2ab3
--- /dev/null
+++ b/tests/Languages/de/SimpleSpeak/large_ops.rs
@@ -0,0 +1,200 @@
+use crate::common::*;
+
+#[test]
+fn sum_both() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the sum from n is equal to 1 to 10 of n");
+}
+
+#[test]
+fn sum_under() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the sum over cap s of i");
+}
+#[test]
+fn sum_both_msubsup() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the sum from n is equal to 1 to 10 of n");
+}
+
+#[test]
+fn sum_sub() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the sum over cap s of i");
+}
+
+#[test]
+fn sum() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the sum of eigh sub i");
+}
+
+#[test]
+fn product_both() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the product from n is equal to 1 to 10 of n");
+}
+
+#[test]
+fn product_under() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the product over cap s of i");
+}
+
+#[test]
+fn product() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the product of eigh sub i");
+}
+
+#[test]
+fn intersection_both() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the intersection from i is equal to 1 to 10 of; cap s sub i");
+}
+
+#[test]
+fn intersection_under() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the intersection over cap c of, cap s sub i");
+}
+
+#[test]
+fn intersection() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the intersection of cap s sub i");
+}
+
+#[test]
+fn union_both() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the union from i is equal to 1 to 10 of; cap s sub i");
+}
+
+#[test]
+fn union_under() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the union over cap c of, cap s sub i");
+}
+
+#[test]
+fn union() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the union of cap s sub i");
+}
+
+#[test]
+fn integral_both() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the integral from 0 to 1 of, f of x; d x");
+}
+
+#[test]
+fn integral_under() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the integral over the real numbers of; f of x d x");
+}
+
+#[test]
+fn integral() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the integral of f of x d x");
+}
\ No newline at end of file
diff --git a/tests/Languages/de/SimpleSpeak/linear_algebra.rs b/tests/Languages/de/SimpleSpeak/linear_algebra.rs
new file mode 100644
index 00000000..2eebfbae
--- /dev/null
+++ b/tests/Languages/de/SimpleSpeak/linear_algebra.rs
@@ -0,0 +1,92 @@
+use crate::common::*;
+
+#[test]
+fn transpose() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap m transpose");
+}
+
+#[test]
+fn trace() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "trace of cap m");
+}
+
+#[test]
+fn dimension() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "dimension of cap m");
+}
+
+#[test]
+fn homomorphism() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "homomorphism of cap m");
+}
+
+#[test]
+fn kernel() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "kernel of cap l");
+}
+
+#[test]
+fn norm() {
+ let expr = "
+";
+ test("de", "SimpleSpeak", expr, "norm of f");
+}
+
+#[test]
+fn norm_non_simple() {
+ let expr = "
+";
+ test("de", "SimpleSpeak", expr, "norm of x plus y end norm");
+}
+
+#[test]
+fn norm_subscripted() {
+ let expr = "
+";
+ test("de", "SimpleSpeak", expr, "p norm of f");
+}
+
+#[test]
+fn not_gradient() {
+ // the nabla is at the end, so it can't be gradient because it doesn't operate on anything
+ let expr = r#"
+"#;
+ test("de", "SimpleSpeak", expr, "open paren, b times nahblah, close paren; times eigh");
+}
\ No newline at end of file
diff --git a/tests/Languages/de/SimpleSpeak/mfrac.rs b/tests/Languages/de/SimpleSpeak/mfrac.rs
new file mode 100644
index 00000000..286eba6c
--- /dev/null
+++ b/tests/Languages/de/SimpleSpeak/mfrac.rs
@@ -0,0 +1,307 @@
+/// Tests for fractions
+/// includes simple fractions and more complex fractions
+/// also tests mixed fractions (implicit and explicit)
+use crate::common::*;
+
+#[test]
+fn common_fraction_half() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "1 half");
+}
+
+#[test]
+fn common_fraction_thirds() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2 thirds");
+}
+
+#[test]
+fn common_fraction_tenths() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "17 tenths");
+}
+
+#[test]
+#[allow(non_snake_case)]
+fn not_SimpleSpeak_common_fraction_tenths() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "89 over 10");
+}
+
+#[test]
+fn non_simple_fraction() {
+ let expr = "
+
+ ";
+ test("de", "SimpleSpeak", expr, "fraction, x plus y, over, x minus y, end fraction");
+}
+
+#[test]
+fn nested_fraction() {
+ let expr = "
+
+ ";
+ test("de", "SimpleSpeak", expr, "fraction, x plus, fraction, 1 over y, end fraction; over, x minus y, end fraction");
+}
+
+
+#[test]
+fn deeply_nested_fraction_msqrt() {
+ let expr = "
+
+ ";
+ test("de", "SimpleSpeak", expr, "fraction, x plus, the square root of 1 over y, end root; over, x minus y, end fraction");
+}
+
+#[test]
+fn deeply_nested_fraction_mrow_msqrt() {
+ let expr = "
+
+ ";
+ test("de", "SimpleSpeak", expr, "fraction, x plus, the square root of 2 plus 1 over y, end root; over, x minus y, end fraction");
+}
+
+#[test]
+fn numerator_simple_fraction() {
+ let expr = "
+
+ ";
+ test("de", "SimpleSpeak", expr, "fraction, x over, x minus y, end fraction");
+}
+
+#[test]
+fn denominator_simple_fraction() {
+ let expr = "
+
+ ";
+ test("de", "SimpleSpeak", expr, "fraction, x minus y, over x, end fraction");
+}
+
+
+#[test]
+fn frac_with_units() {
+ let expr = "
+ ";
+ test("de", "SimpleSpeak", expr, "62 miles per hour");
+}
+
+#[test]
+fn singular_frac_with_units() {
+ let expr = "
+ ";
+ test("de", "SimpleSpeak", expr, "1 gallon per mile");
+}
+
+#[test]
+fn number_in_numerator_with_units() {
+ let expr = "
+ ";
+ test("de", "SimpleSpeak", expr, "3 gallons per mile");
+}
+
+#[test]
+fn units_with_powers() {
+ let expr = "
+ ";
+ test("de", "SimpleSpeak", expr, "3 metres per second squared");
+}
+
+
+#[test]
+fn mixed_number() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "3 and 1 half");
+}
+
+#[test]
+fn explicit_mixed_number() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "3 and 1 eighth");
+}
+
+#[test]
+fn mixed_number_big() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "3 and 7 eighty thirds");
+}
+
+#[test]
+fn simple_text() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "rise over run");
+}
+
+#[test]
+fn number_and_text() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraction, 2 miles, over, 3 gallons, end fraction");
+}
+
+
+#[test]
+fn nested_simple_fractions() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraction, 1 half, over, 2 thirds, end fraction");
+}
+
+#[test]
+fn binomial() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2 times 7 choose 3");
+}
+
+#[test]
+fn binomial_non_simple_top() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2 times, binomial n plus 7 choose 3");
+}
+
+#[test]
+fn binomial_non_simple_bottom() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2 times, 7 choose k plus 3 end binomial");
+}
+
+#[test]
+fn binomial_non_simple_top_and_bottom() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2 times, binomial n plus 7 choose k plus 3 end binomial");
+}
diff --git a/tests/Languages/de/SimpleSpeak/msup.rs b/tests/Languages/de/SimpleSpeak/msup.rs
new file mode 100644
index 00000000..f292051a
--- /dev/null
+++ b/tests/Languages/de/SimpleSpeak/msup.rs
@@ -0,0 +1,334 @@
+/// Tests for superscripts
+/// simple superscripts
+/// complex/nested superscripts
+use crate::common::*;
+
+#[test]
+fn squared() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "x squared");
+}
+
+#[test]
+fn cubed() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "x cubed");
+}
+
+#[test]
+ fn ordinal_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "x to the fourth");
+ }
+
+#[test]
+fn simple_mi_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "x to the n-th");
+}
+
+#[test]
+fn zero_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "x to the 0");
+}
+
+
+#[test]
+fn decimal_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "x to the 2.0");
+}
+
+#[test]
+fn non_simple_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "3 raised to the y plus 2 power");
+}
+
+#[test]
+fn negative_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "x to the negative 2");
+}
+
+#[test]
+fn simple_fraction_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "x raised to the 1 third power");
+}
+
+#[test]
+fn nested_squared_power_with_coef() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "3 raised to the 2 x squared power");
+}
+
+#[test]
+fn nested_squared_power_with_neg_coef() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "3 raised to the negative 2 x squared power");
+}
+
+
+#[test]
+fn nested_cubed_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "y raised to the 4 fifths cubed power");
+}
+
+#[test]
+fn nested_cubed_power_with_neg_base() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "y raised to the negative 4 fifths cubed power");
+}
+
+#[test]
+fn nested_number_times_squared() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "e raised to the 1 half x squared power");
+}
+
+#[test]
+fn nested_negative_number_times_squared() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "e raised to the negative 1 half x squared power");
+}
+
+#[test]
+fn nested_expr_to_tenth() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "3 raised to the 3 to the tenth power");
+}
+
+#[test]
+fn nested_non_simple_squared_exp() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "3 raised to the open paren x plus 1, close paren squared power");
+}
+
+#[test]
+fn nested_simple_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "t raised to the 4 fifths to the n-th power");
+}
+
+#[test]
+fn nested_end_exponent_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "t raised to the 4 fifths raised to the n plus 1 power; end exponent");
+ test_prefs("de", "SimpleSpeak", vec![("Impairment", "LearningDisability")], expr,
+ "t raised to the 4 fifths raised to the n plus 1 power");
+}
+
+#[test]
+fn nested_end_exponent_neg_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "t raised to the 4 fifths to the negative 3, end exponent");
+}
+
+#[test]
+fn nested_complex_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "e raised to the negative 1 half times; open paren, fraction, x minus mu, over sigma, end fraction; close paren squared power");
+}
+
+#[test]
+fn default_power() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "t raised to the fraction, b plus 1, over 3, end fraction; power");
+}
diff --git a/tests/Languages/de/SimpleSpeak/multiline.rs b/tests/Languages/de/SimpleSpeak/multiline.rs
new file mode 100644
index 00000000..8edc9d65
--- /dev/null
+++ b/tests/Languages/de/SimpleSpeak/multiline.rs
@@ -0,0 +1,75 @@
+use crate::common::*;
+
+#[test]
+fn case_1() {
+ let expr = "
+ ";
+ test("de", "SimpleSpeak", expr, "f of x is equal to; 3 cases; \
+ case 1; negative 1 if x; is less than 0; \
+ case 2; 0 if x, is equal to 0; \
+ case 3; 1 if x, is greater than 0");
+}
+
+#[test]
+fn equation_1() {
+ let expr = "
+ ";
+ test("de", "SimpleSpeak", expr, "2 equations; \
+ equation 1; x plus y, is equal to 7; \
+ equation 2; 2 x plus 3 y; is equal to 17");
+}
diff --git a/tests/Languages/de/SimpleSpeak/sets.rs b/tests/Languages/de/SimpleSpeak/sets.rs
new file mode 100644
index 00000000..41f76755
--- /dev/null
+++ b/tests/Languages/de/SimpleSpeak/sets.rs
@@ -0,0 +1,238 @@
+use crate::common::*;
+
+#[test]
+fn complex() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the complex numbers");
+}
+
+#[test]
+fn natural() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the natural numbers");
+}
+
+#[test]
+fn rationals() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the rational numbers");
+}
+
+#[test]
+fn reals() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the real numbers");
+}
+
+#[test]
+fn integers() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the integers");
+}
+
+
+
+#[test]
+fn msup_complex() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "C 2");
+}
+
+#[test]
+fn msup_natural() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "N 2");
+}
+
+#[test]
+fn msup_rationals() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "Q 2");
+}
+
+#[test]
+fn msup_reals() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "R 3");
+}
+
+#[test]
+fn msup_integers() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "Z 4");
+}
+
+#[test]
+fn msup_positive_integers() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the positive integers");
+}
+
+#[test]
+fn msup_negative_integers() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the negative integers");
+}
+
+#[test]
+fn msup_positive_rationals() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the positive rational numbers");
+}
+
+#[test]
+fn msup_negative_rationals() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the negative rational numbers");
+}
+
+#[test]
+fn empty_set() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the empty set");
+}
+
+#[test]
+fn single_element_set() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the set 12");
+}
+
+#[test]
+fn multiple_element_set() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the set 5 comma, 10 comma, 15");
+}
+
+#[test]
+fn set_with_colon() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the set of all x such that x is greater than 2");
+}
+
+#[test]
+fn set_with_bar() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the set of all x such that x is greater than 2");
+}
+
+#[test]
+fn element_alone() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "3 plus 2 i, is not an element of, the real numbers");
+}
+
+#[test]
+fn element_under_sum() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr,
+ "the sum over i is an element of the integers of; fraction, 1 over, i squared, end fraction");
+}
+
+#[test]
+fn complicated_set_with_colon() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the set of all x an element of the integers such that 2 is less than x is less than 7");
+}
+
+#[test]
+fn complicated_set_with_mtext() {
+ // as of 8/5/21, parsing of "|" is problematic an element of the example, so are needed for this test
+ let expr = "";
+ test("de", "SimpleSpeak", expr,
+ "the set of all x an element of the natural numbers such that x is an even number");
+}
diff --git a/tests/Languages/de/SimpleSpeak/subscripts.rs b/tests/Languages/de/SimpleSpeak/subscripts.rs
new file mode 100644
index 00000000..82b022e0
--- /dev/null
+++ b/tests/Languages/de/SimpleSpeak/subscripts.rs
@@ -0,0 +1,49 @@
+use crate::common::*;
+
+#[test]
+fn msub_simple() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "x 1");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Medium")], expr, "x sub 1");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr, "x sub 1");
+ }
+
+#[test]
+fn msub_not_simple() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "x sub 1.2");
+ }
+
+#[test]
+fn msubsup_not_simple() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "x sub 1.2, cubed");
+ }
+
+#[test]
+fn msub_simple_mi() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "x sub i");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr, "x sub i");
+}
+
+#[test]
+fn msub_simple_number_follows() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "x 1, 10 squared");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr, "x sub 1, 10 squared");
+}
+
+#[test]
+fn msub_simple_non_number_follows() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "x 1, squared");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr, "x sub 1, squared");
+}
+
+#[test]
+fn msubsup_simple() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "x 1, x squared");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr, "x sub 1, x squared");
+}
\ No newline at end of file
diff --git a/tests/Languages/de/alphabets.rs b/tests/Languages/de/alphabets.rs
new file mode 100644
index 00000000..731e77c3
--- /dev/null
+++ b/tests/Languages/de/alphabets.rs
@@ -0,0 +1,344 @@
+/// Tests for rules shared between various speech styles:
+/// * this has tests focused on the various alphabets
+use crate::common::*;
+
+
+/*
+#[test]
+fn special_alphabet_chars() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraktur cap h comma, fraktur cap c");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "double struck cap h, comma, double struck cap pi");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "script cap i comma, script cap m");
+}
+
+#[test]
+fn greek() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap alpha comma, cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "alpha comma, omega");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "double struck cap delta, comma, double struck cap upsilon");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "alpha comma, omega");
+}
+
+#[test]
+fn cap_cyrillic() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap a comma, cap ya");
+}
+
+#[test]
+fn parenthesized() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "parenthesized eigh comma, parenthesized z");
+}
+
+#[test]
+fn circled() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "circled cap eigh comma, circled cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "circled eigh comma, circled z");
+}
+
+#[test]
+fn fraktur() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraktur cap eigh comma, fraktur cap y");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraktur eigh comma, fraktur z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraktur cap eigh comma, fraktur cap y");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraktur eigh comma, fraktur z");
+}
+
+#[test]
+fn bold_fraktur() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraktur bold cap eigh, comma, fraktur bold cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraktur bold eigh comma, fraktur bold z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraktur bold cap eigh, comma, fraktur bold cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "fraktur bold eigh comma, fraktur bold z");
+}
+
+#[test]
+fn double_struck() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "double struck cap eigh, comma, double struck cap y");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "double struck eigh comma, double struck z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "double struck 0 comma, double struck 9");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "double struck cap eigh, comma, double struck cap y");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "double struck eigh comma, double struck z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "double struck 0 comma, double struck 9");
+}
+
+#[test]
+fn script() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "script cap eigh comma, script cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "script eigh comma, script z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "script cap eigh comma, script cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "script eigh comma, script z");
+}
+
+#[test]
+fn bold_script() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "eingekreist groß a komma eingekreist groß z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "script bold eigh comma, script bold z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "script bold cap eigh, comma, script bold cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "script bold eigh comma, script bold z");
+}
+
+#[test]
+fn bold() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap eigh comma, bold cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold eigh comma, bold z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap eigh comma, bold cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold eigh comma, bold z");
+}
+
+#[test]
+fn italic() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap eigh comma, cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "eigh comma, z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap eigh comma, cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "eigh comma, z");
+}
+
+#[test]
+fn sans_serif() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap eigh comma, cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "eigh comma, z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap eigh comma, cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "eigh comma, z");
+}
+
+#[test]
+fn sans_serif_bold() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap eigh comma, bold cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold eigh comma, bold z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap eigh comma, bold cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold eigh comma, bold z");
+}
+
+#[test]
+fn sans_serif_italic() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap eigh comma, cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "eigh comma, z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap eigh comma, cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "eigh comma, z");
+}
+
+#[test]
+fn sans_serif_bold_italic() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap eigh comma, bold cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold eigh comma, bold z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap eigh comma, bold cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold eigh comma, bold z");
+}
+
+#[test]
+fn monospace() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap eigh comma, cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "eigh comma, z");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap eigh comma, cap z");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "eigh comma, z");
+}
+
+
+#[test]
+fn bold_greek() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap alpha comma, bold cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold alpha comma, bold omega");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap alpha comma, bold cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold alpha comma, bold omega");
+}
+
+#[test]
+fn bold_greek_others() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold partial derivative, comma, bold pi");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold partial derivative, comma, bold pi");
+}
+
+
+#[test]
+fn italic_greek() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap alpha comma, cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "alpha comma, omega");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap alpha comma, cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "alpha comma, omega");
+}
+
+#[test]
+fn italic_greek_others() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "partial derivative comma, pi");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "partial derivative comma, pi");
+}
+
+#[test]
+fn bold_italic_greek() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap alpha comma, bold cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold alpha comma, bold omega");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap alpha comma, bold cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold alpha comma, bold omega");
+}
+
+#[test]
+fn bold_italic_greek_others() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold partial derivative, comma, bold pi");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold partial derivative, comma, bold pi");
+}
+
+#[test]
+fn sans_serif_bold_greek() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap alpha comma, bold cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold alpha comma, bold omega");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap alpha comma, bold cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold alpha comma, bold omega");
+}
+
+#[test]
+fn sans_serif_bold_greek_others() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold partial derivative, comma, bold pi");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold partial derivative, comma, bold pi");
+}
+
+#[test]
+fn sans_serif_bold_italic_greek() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap alpha comma, bold cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold alpha comma, bold omega");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold cap alpha comma, bold cap omega");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold alpha comma, bold omega");
+}
+
+#[test]
+fn sans_serif_bold_italic_greek_others() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold partial derivative, comma, bold pi");
+ // MathType private space versions
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "bold partial derivative, comma, bold pi");
+}
+
+#[test]
+fn pua_regular() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap eigh comma, cap z");
+}
+
+#[test]
+fn turned() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "turned cap f comma, turned sans-serif cap y");
+ }
+*/
+#[test]
+fn enclosed_numbers() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "umkreiste 1 komma umkreiste 9");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "klammern 1 komma klammern 9");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "1 mit periode komma 9 mit periode");
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "doppelt umkreist 1 komma doppelt umkreist 9");
+}
diff --git a/tests/Languages/de/chemistry.rs b/tests/Languages/de/chemistry.rs
new file mode 100644
index 00000000..e65763e4
--- /dev/null
+++ b/tests/Languages/de/chemistry.rs
@@ -0,0 +1,737 @@
+/// Tests for rules shared between various speech styles:
+/// * modified var
+use crate::common::*;
+
+#[test]
+fn salt() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "groß n a, groß c l");
+}
+
+#[test]
+fn water() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Terse")], expr, "groß h, 2 groß o");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium")], expr, "groß h, sub 2 groß o");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Verbose")], expr, "groß h, index 2, groß o");
+}
+
+#[test]
+fn carbon() {
+ let expr = ""; // not enough to trigger recognition
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "groß c");
+}
+
+#[test]
+fn sulfate() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium")], expr, "offene eckige klammer, groß s, groß o, sub 4; schließende eckige klammer super 2 minus");
+}
+
+
+/* // ignored below
+#[test]
+fn aluminum_sulfate() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Terse")], expr, "groß a l, 2, open groß s, groß o, 4, close 3");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium")], expr, "groß a l, sub 2; open paren, groß s, groß o, sub 4; close paren sub 3");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Verbose")], expr, "groß a l, subscript 2; open paren, groß s, groß o, subscript 4; close paren subscript 3");
+}
+
+#[test]
+fn ethanol_bonds() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Terse")], expr, "groß c, groß h, 3 single bond groß c, groß h, 2 single bond groß o, groß h");
+
+}
+
+#[test]
+fn dichlorine_hexoxide() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "open bracket, groß c l, groß o, 2, close bracket plus; \
+ open bracket, groß c l, groß o, 4, close bracket minus");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Medium")],
+ expr, "open bracket, groß c l, groß o, sub 2; close bracket super plus; \
+ open bracket, groß c l, groß o, sub 4; close bracket super minus");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")],
+ expr, "open bracket, groß c l, groß o, subscript 2; close bracket superscript plus; \
+ open bracket, groß c l, groß o, subscript 4; close bracket superscript minus");
+}
+
+
+#[test]
+fn ethylene_with_bond() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "groß h, 2 groß c, double bond groß c, groß h, 2");
+}
+
+#[test]
+fn ferric_chloride_aq() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "groß f e, groß c l, 3 aqueous");
+ }
+
+#[test]
+fn ethylene_with_colon_bond() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "groß h, 2 groß c, double bond groß c, groß h, 2");
+}
+
+#[test]
+fn beta_decay() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Terse")], expr,
+ "14, 6, groß c; forms, 14, 7, groß n; plus 0, negative 1, e");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium")], expr,
+ "super 14, sub 6, groß c; reacts to form; super 14, sub 7, groß n; plus super 0, sub negative 1, e");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Verbose")], expr,
+ "superscript 14, subscript 6, groß c; reacts to form; superscript 14, subscript 7, groß n; plus, superscript 0, subscript negative 1, e");
+}
+
+#[test]
+fn mhchem_beta_decay() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Terse")], expr,
+ "14, 6, groß c; forms, 14, 7, groß n; plus 0, negative 1, e");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium")], expr,
+ "super 14, sub 6, groß c; reacts to form; super 14, sub 7, groß n; plus super 0, sub negative 1, e");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Verbose")], expr,
+ "superscript 14, subscript 6, groß c; reacts to form; superscript 14, subscript 7, groß n; plus, superscript 0, subscript negative 1, e");
+}
+
+#[test]
+fn hcl_na_yields() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr,
+ "2, groß h, groß c l; plus 2 groß n a; reacts to form; 2, groß n a, groß c l; plus groß h, subscript 2");
+}
+
+#[test]
+fn mhchem_so4_2plus() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "groß s; groß o, 4, 2 plus");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Medium")], expr, "groß s; groß o, sub 4, super 2 plus");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr, "groß s; groß o, subscript 4, superscript 2 plus");
+}
+
+
+#[test]
+fn mhchem_hcl_aq_etc() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "2, groß h, groß c l, aqueous; plus, 2, groß n a, solid; forms; 2, groß n a, groß c l, aqueous; plus, groß h, 2, gas");
+
+}
+
+
+#[test]
+fn mhchem_barbed_equilibrium() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "groß h, 2, gas; plus; groß i, 2, gas; is in equilibrium with, 2, groß h, groß i, gas");
+}
+
+
+
+#[test]
+fn mhchem_roman_in_superscript() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "groß f e, 2; groß f e, 3; groß o, 4");
+}
+
+
+#[test]
+fn dropped_msubsup_bug_358() {
+ let expr = r#""#;
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "2, groß s, groß o, 2; plus; groß o, 2 is in equilibrium with, 2, groß s, groß o, 3");
+}
+
+
+
+ */
+
diff --git a/tests/Languages/de/intent.rs b/tests/Languages/de/intent.rs
new file mode 100644
index 00000000..6faaa664
--- /dev/null
+++ b/tests/Languages/de/intent.rs
@@ -0,0 +1,117 @@
+/// Tests for rules shared between various speech styles:
+/// * this has tests focused on the various alphabets
+use crate::common::*;
+
+
+#[test]
+fn silent_intent() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2 x");
+ test("de", "LiteralSpeak", expr, "2 x");
+}
+
+#[test]
+fn prefix_intent() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr, "testing x");
+}
+
+#[test]
+fn postfix_intent() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr, "x testing");
+}
+
+#[test]
+fn infix_intent() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr, "x testing y testing z testing 2");
+}
+
+#[test]
+fn infix_intent_no_args() {
+ // this is illegal intent, so it is just an mrow with one child
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr, "x");
+}
+
+#[test]
+fn infix_intent_one_arg() {
+ let expr = r#""#;
+ // Note: we say the intent name because there are infix plus/minus with a single arg due to continued rows or combined columns
+ test("de", "SimpleSpeak", expr, "testing x");
+}
+
+#[test]
+fn function_intent() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr, "testing von x komma y komma z komma 2");
+}
+
+#[test]
+fn function_no_args_intent() {
+ // this is illegal intent, so it is just an mrow with one child
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr, "x");
+}
+
+#[test]
+fn function_one_arg_intent() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr, "testing von x");
+}
+
+#[test]
+fn silent_intent_mi() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "2");
+ test("de", "ClearSpeak", expr, "2");
+}
+
+#[test]
+fn silent_intent_msup() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "groß h 2");
+ test("de", "ClearSpeak", expr, "groß h 2");
+}
+
+#[test]
+fn silent_intent_underscore() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "groß h 2");
+ test("de", "ClearSpeak", expr, "groß h 2");
+}
+
+#[test]
+fn intent_prob_x() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "wahrscheinlichtkeit von x");
+}
diff --git a/tests/Languages/de/mtable.rs b/tests/Languages/de/mtable.rs
new file mode 100644
index 00000000..32d33e62
--- /dev/null
+++ b/tests/Languages/de/mtable.rs
@@ -0,0 +1,1103 @@
+use crate::common::*;
+
+#[test]
+fn matrix_1x1() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "die 1 mal 1 matrix mit eintrag 3");
+ test("de", "SimpleSpeak", expr, "die 1 mal 1 matrix mit eintrag 3");
+}
+
+#[test]
+fn determinant_1x1() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "die 1 mal 1 determinante mit eintrag 3");
+ test("de", "SimpleSpeak", expr, "die 1 mal 1 determinante mit eintrag 3");
+}
+
+
+/*
+#[test]
+fn matrix_1x2() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "the 1 by 2 row matrix; 3, 5");
+ test("de", "SimpleSpeak", expr, "the 1 by 2 row matrix; 3, 5");
+}
+
+
+#[test]
+fn matrix_1x3() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "the 1 by 3 row matrix; negative x, 5, 12");
+ test("de", "SimpleSpeak", expr, "the 1 by 3 row matrix; negative x, 5, 12");
+}
+
+#[test]
+fn matrix_2x1_not_simple() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "the 2 by 1 column matrix; row 1; x plus 1; row 2; x minus 1");
+ test("de", "SimpleSpeak", expr, "the 2 by 1 column matrix; row 1; x plus 1; row 2; x minus 1");
+}
+#[test]
+fn matrix_3x1_not_simple() {
+ let expr = "
+ ";
+ test("de", "SimpleSpeak", expr, "the 3 by 1 column matrix; \
+ row 1; x; \
+ row 2; eigh; \
+ row 3; fraction, x over, x plus 1, end fraction");
+ test("de", "ClearSpeak", expr, "the 3 by 1 column matrix; \
+ row 1; x; \
+ row 2; eigh; \
+ row 3; the fraction with numerator x; and denominator x plus 1");
+}
+
+#[test]
+fn determinant_2x2() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "the 2 by 2 determinant; row 1; 2, 1; row 2; 7, 5");
+ test("de", "SimpleSpeak", expr, "the 2 by 2 determinant; row 1; 2, 1; row 2; 7, 5");
+}
+
+#[test]
+fn matrix_2x3() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "the 2 by 3 matrix; row 1; 3, 1, 4; row 2; 0, 2, 6");
+ test("de", "SimpleSpeak", expr, "the 2 by 3 matrix; row 1; 3, 1, 4; row 2; 0, 2, 6");
+}
+
+#[test]
+fn matrix_2x3_labeled() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr,
+ "the 2 by 3 matrix; row 1 with label (3.1); column 1; 3, column 2; 1, column 3; 4; \
+ row 2; column 1; 0, column 2; 2, column 3; 6");
+ test("de", "SimpleSpeak", expr,
+ "the 2 by 3 matrix; row 1 with label (3.1); column 1; 3, column 2; 1, column 3; 4; \
+ row 2; column 1; 0, column 2; 2, column 3; 6");
+}
+
+#[test]
+fn matrix_3x1() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "the 3 by 1 column matrix; 1; 2; 3");
+ test("de", "SimpleSpeak", expr, "the 3 by 1 column matrix; 1; 2; 3");
+}
+
+#[test]
+fn matrix_4x1() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "die 4 nach 1 spalte matrix; reihe 1; 3; reihe 2; 6; reihe 3; 1; reihe 4; 2");
+ test("de", "SimpleSpeak", expr, "die 4 nach 1 spalte matrix; reihe 1; 3; reihe 2; 6; reihe 3; 1; reihe 4; 2");
+}
+
+#[test]
+fn matrix_4x1_labeled() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr,
+ "die 4 nach 1 spalte matrix; reihe 1; 3; reihe 2; 6; reihe 3; 1; reihe 4 determinant (3.1); 2");
+ test("de", "SimpleSpeak", expr,
+ "die 4 nach 1 spalte matrix; reihe 1; 3; reihe 2; 6; reihe 3; 1; reihe 4 mit der etikette (3.1); 2");
+}
+
+#[test]
+fn matrix_1x4() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "the 1 by 4 row matrix; column 1; 3, column 2; 6, column 3; 1, column 4; 2");
+ test("de", "SimpleSpeak", expr, "the 1 by 4 row matrix; column 1; 3, column 2; 6, column 3; 1, column 4; 2");
+}
+
+#[test]
+fn matrix_4x4() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "the 4 by 4 matrix; \
+ row 1; column 1; 0, column 2; 3, column 3; 4, column 4; 3; \
+ row 2; column 1; 2, column 2; 1, column 3; 0, column 4; 9; \
+ row 3; column 1; 3, column 2; 0, column 3; 2, column 4; 1; \
+ row 4; column 1; 6, column 2; 2, column 3; 9, column 4; 0");
+ test("de", "SimpleSpeak", expr, "the 4 by 4 matrix; \
+ row 1; column 1; 0, column 2; 3, column 3; 4, column 4; 3; \
+ row 2; column 1; 2, column 2; 1, column 3; 0, column 4; 9; \
+ row 3; column 1; 3, column 2; 0, column 3; 2, column 4; 1; \
+ row 4; column 1; 6, column 2; 2, column 3; 9, column 4; 0");}
+
+#[test]
+fn matrix_4x2() {
+ let expr = "
+
+ ";
+ test("de", "ClearSpeak", expr, "the 4 by 2 matrix; \
+ row 1; column 1; 1, column 2; 3; \
+ row 2; column 1; 4, column 2; 2; \
+ row 3; column 1; 2, column 2; 1; \
+ row 4; column 1; 0, column 2; 5\
+ ");
+ test("de", "SimpleSpeak", expr, "the 4 by 2 matrix; \
+ row 1; column 1; 1, column 2; 3; \
+ row 2; column 1; 4, column 2; 2; \
+ row 3; column 1; 2, column 2; 1; \
+ row 4; column 1; 0, column 2; 5\
+ ");}
+
+// put absolute value test here since it is related to determinate and is small for its own file
+#[test]
+fn simple_absolute_value() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the absolute value of x");
+ test("de", "ClearSpeak", expr, "the absolute value of x");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Terse"), ("ClearSpeak_AbsoluteValue", "Auto")], expr, "absolute value of x");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Verbose"), ("ClearSpeak_AbsoluteValue", "AbsEnd")],
+ expr, "the absolute value of x, end absolute value");
+}
+
+#[test]
+fn absolute_value_plus_1() {
+let expr = "";
+ test("de", "ClearSpeak", expr, "der Betrag von x plus 1");
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Terse"), ("ClearSpeak_AbsoluteValue", "AbsEnd")],
+ expr, "der betrag von x plus 1, end betrag");
+}
+
+#[test]
+fn simple_cardinality_value() {
+ let expr = "";
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Medium"), ("ClearSpeak_AbsoluteValue", "Cardinality")], expr,
+ "the cardinality of cap s");
+}
+
+// Test preferences
+#[test]
+fn simple_matrix_speak_col_num() {
+let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Matrix", "SpeakColNum",
+ expr, "the 2 by 2 matrix; row 1; column 1; 2, column 2; 1; row 2; column 1; 7, column 2; 5");
+}
+
+#[test]
+fn col_matrix_3x1_speak_col_num() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "SpeakColNum",
+ expr, "the 3 by 1 column matrix; row 1; 1; row 2; 2; row 3; 3");
+}
+
+#[test]
+fn row_matrix_1x2_speak_col_num() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "SpeakColNum",
+ expr, "the 1 by 2 row matrix; column 1; 1, column 2; 2");
+}
+
+#[test]
+fn matrix_2x2_speak_col_num() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "SpeakColNum",
+ expr, "the 2 by 2 matrix; row 1; column 1; b sub 1 1; column 2; b sub 1 2; \
+ row 2; column 1; b sub 2 1; column 2; b sub 2 2");
+}
+
+
+#[test]
+fn simple_matrix_silent_col_num() {
+let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Matrix", "SilentColNum",
+ expr, "the 2 by 2 matrix; row 1; 2, 1; row 2; 7, 5");
+}
+
+#[test]
+fn col_matrix_3x1_silent_col_num() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "SilentColNum",
+ expr, "the 3 by 1 column matrix; 1; 2; 3");
+}
+
+#[test]
+fn row_matrix_1x2_silent_col_num() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "SilentColNum",
+ expr, "the 1 by 2 row matrix; 1, 2");
+}
+
+#[test]
+fn matrix_2x2_silent_col_num() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "SilentColNum",
+ expr, "the 2 by 2 matrix; row 1; b sub 1 1; b sub 1 2; \
+ row 2; b sub 2 1; b sub 2 2");
+}
+
+
+#[test]
+fn simple_matrix_end_matrix() {
+let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Matrix", "EndMatrix",
+ expr, "the 2 by 2 matrix; row 1; 2, 1; row 2; 7, 5; end matrix");
+}
+
+#[test]
+fn col_matrix_3x1_end_matrix() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "EndMatrix",
+ expr, "the 3 by 1 column matrix; 1; 2; 3; end matrix");
+}
+
+#[test]
+fn row_matrix_1x2_end_matrix() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "EndMatrix",
+ expr, "the 1 by 2 row matrix; 1, 2; end matrix");
+}
+
+#[test]
+fn matrix_2x2_end_matrix() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "EndMatrix",
+ expr, "the 2 by 2 matrix; row 1; column 1; b sub 1 1; column 2; b sub 1 2; \
+ row 2; column 1; b sub 2 1; column 2; b sub 2 2; end matrix");
+}
+
+
+#[test]
+fn simple_matrix_vector() {
+let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Matrix", "Vector",
+ expr, "the 2 by 2 matrix; row 1; 2, 1; row 2; 7, 5");
+}
+
+#[test]
+fn col_matrix_3x1_vector() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "Vector",
+ expr, "the 3 by 1 column vector; 1; 2; 3");
+}
+
+#[test]
+fn row_matrix_1x2_vector() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "Vector",
+ expr, "the 1 by 2 row vector; 1, 2");
+}
+
+#[test]
+fn matrix_2x2_vector() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "Vector",
+ expr, "the 2 by 2 matrix; row 1; column 1; b sub 1 1; column 2; b sub 1 2; \
+ row 2; column 1; b sub 2 1; column 2; b sub 2 2");
+}
+
+
+#[test]
+fn simple_matrix_end_vector() {
+let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Matrix", "EndVector",
+ expr, "the 2 by 2 matrix; row 1; 2, 1; row 2; 7, 5; end matrix");
+}
+
+#[test]
+fn col_matrix_3x1_end_vector() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "EndVector",
+ expr, "the 3 by 1 column vector; 1; 2; 3; end vector");
+}
+
+#[test]
+fn row_matrix_1x2_end_vector() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "EndVector",
+ expr, "the 1 by 2 row vector; 1, 2; end vector");
+}
+
+#[test]
+fn matrix_2x2_end_vector() {
+let expr = "";
+test_ClearSpeak("de", "ClearSpeak_Matrix", "EndVector",
+ expr, "the 2 by 2 matrix; row 1; column 1; b sub 1 1; column 2; b sub 1 2; \
+ row 2; column 1; b sub 2 1; column 2; b sub 2 2; end matrix");
+}
+
+
+
+#[test]
+fn matrix_binomial() {
+ let expr = "";
+ test_ClearSpeak("de", "ClearSpeak_Matrix", "Combinatorics", expr, "3 choose 2");
+}
+
+#[test]
+fn matrix_times() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr,
+ "the 2 by 2 matrix; row 1; 1, 2; row 2; 3, 4; times, the 2 by 2 matrix; row 1; eigh, b; row 2; c, d");
+}
+
+#[test]
+fn unknown_mtable_property() {
+ let expr = "";
+ test("de", "ClearSpeak", expr,
+ "2 lines; line 1; eigh is equal to, b plus c minus d; line 2; plus e minus f");
+}
+
+
+#[test]
+fn zero_matrix() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr,
+ "the 2 by 2 zero matrix");
+}
+
+#[test]
+fn identity_matrix() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr,
+ "the 3 by 3 identity matrix");
+}
+
+#[test]
+fn diagonal_matrix() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "the 3 by 3 diagonal matrix; column 1; 2; column 2; 1; column 3; x squared");
+ // test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")],
+ // expr, "the 3 by 3 diagonal matrix; row 1, column 1, 2; row 2, column 2, 1; row 3, column 3, x squared");
+}
+
+#[test]
+fn single_line_with_label() {
+ let expr = r#""#;
+ test_prefs("de", "ClearSpeak", vec![("Verbosity", "Terse")],
+ expr, "1 line, with label 2; b equals 2");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")],
+ expr, "1 equation, with label 2; b equals 2");
+}
+
+*/
\ No newline at end of file
diff --git a/tests/Languages/de/shared.rs b/tests/Languages/de/shared.rs
new file mode 100644
index 00000000..9c4b8432
--- /dev/null
+++ b/tests/Languages/de/shared.rs
@@ -0,0 +1,459 @@
+/// Tests for rules shared between various speech styles:
+/// * modified var
+use crate::common::*;
+
+#[test]
+fn modified_vars() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr,
+ "a gravis akzent; b tilde, c brevis, b combining caron; c gravis akzent; plus r caron plus; x punkt, y Überpunkt, z diaeresis; u dreifacher punkt verschönerung; v vierfacher punkt drüber; plus x zirkumflex, plus vektor t");
+}
+
+#[test]
+fn limit() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "der grenzwert bei x gegen 0; von, bruch, sinus von x, über x, ende der fraktion");
+ test_prefs("de", "SimpleSpeak", vec![("Impairment", "LearningDisability")], expr,
+ "der grenzwert bei x gegen 0; von; sinus von x, über x");
+}
+
+#[test]
+fn limit_from_below() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "der grenzwert bei x annähernd von unten 0; von sinus von x");
+}
+
+
+#[test]
+fn binomial_mmultiscripts() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "n wählen m");
+}
+
+#[test]
+fn binomial_mmultiscripts_other() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "n wählen m");
+}
+
+#[test]
+fn binomial_subscript() { // C_{n,k}
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "n wählen m");
+}
+
+#[test]
+fn permutation_mmultiscripts() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "k permutationen von n");
+}
+
+#[test]
+fn permutation_mmultiscripts_sup() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "k permutationen von n");
+}
+
+#[test]
+fn permutation_msubsup() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "k permutationen von n");
+}
+
+#[test]
+fn tensor_mmultiscripts() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr,
+ "groß r durch 4 postskripte, subscript i superscript j subscript k subscript l");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Medium")], expr,
+ "groß r durch 4 postskripte, sub i super j sub k sub l");
+}
+
+#[test]
+fn huge_num_mmultiscripts() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr,
+ "groß r durch 4 präskripte, pre subscript groß i, pre superscript groß j und abwechselnde präskripte groß k none groß l none ende der präskripte und durch 5 postskripte, subscript i superscript j subscript k subscript l und wechselnde skripte m none ende der skripte");
+}
+
+#[test]
+fn prime() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "x strich");
+}
+
+/*
+#[test]
+fn given() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap p, open paren, cap a given cap b, close paren");
+ test("de", "ClearSpeak", expr, "cap p, open paren, cap a given cap b, close paren"); // not good, but follows the spec
+}
+
+#[test]
+fn simple_msubsup() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "x sub k, to the i-th power");
+}
+
+#[test]
+fn non_simple_msubsup() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "i sub j minus 2 end sub, to the k-th");
+ test("de", "ClearSpeak", expr, "i sub j minus 2 end sub, to the k-th power");
+ test_prefs("de", "SimpleSpeak", vec![("Impairment", "LearningDisability")], expr,
+ "i sub j minus 2, to the k-th");
+}
+
+#[test]
+fn presentation_mathml_in_semantics() {
+ let expr = "";
+ test("de", "ClearSpeak", expr, "x sub k, to the i-th power");
+}
+
+#[test]
+fn ignore_period() {
+ // from https://en.wikipedia.org/wiki/Probability
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "cap p; open paren, cap a and cap b; close paren; is equal to; cap p, open paren, cap a intersection cap b; close paren; is equal to, cap p of cap eigh, cap p of cap b");
+}
+
+#[test]
+fn ignore_mtext_period() {
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "the set 2");
+}
+
+#[test]
+fn ignore_comma() {
+ // from https://en.wikipedia.org/wiki/Probability
+ let expr = "";
+ test("de", "SimpleSpeak", expr, "phi of x is equal to; c times, e raised to the negative h squared, x squared power");
+}
+
+#[test]
+#[ignore] // issue #14
+fn ignore_period_and_space() {
+ // from https://en.wikipedia.org/wiki/Probability
+ let expr = "";
+ test("de", "ClearSpeak", expr, "phi of x is equal to; c, e raised to the negative h squared x squared power");
+}
+
+
+#[test]
+fn bug_199_2pi() {
+ let expr = "";
+ test("de", "SimpleSpeak",expr, "the closed open interval from 0 to 2 pi");
+}
+
+#[test]
+fn caret_and_hat() {
+ let expr = "";
+ test("de", "SimpleSpeak",expr, "x caret 2 plus y hat");
+}
+
+#[test]
+fn mn_with_space() {
+ let expr = "";
+ test_prefs("de", "SimpleSpeak", vec![("DecimalSeparators", "."), ("BlockSeparators", " ,")], expr, "1234567");
+}
+
+#[test]
+fn mn_with_block_and_decimal_separators() {
+ let expr = ""; // may want to change this for another language
+ test_prefs("de", "SimpleSpeak", vec![("DecimalSeparators", "."), ("BlockSeparators", " ,")], expr, "1234.56");
+}
+
+#[test]
+fn divergence() {
+ let expr = ""; // may want to change this for another language
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "dihv cap f");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr, "divergence of cap f");
+}
+
+#[test]
+fn curl() {
+ let expr = "";
+ // may want to change this for another language
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "curl cap f");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr, "curl of cap f");
+}
+
+#[test]
+fn gradient() {
+ let expr = "";
+ // may want to change this for another language
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Terse")], expr, "del cap f");
+ test_prefs("de", "SimpleSpeak", vec![("Verbosity", "Verbose")], expr, "gradient of cap f");
+}
+
+#[test]
+fn literal_speak() {
+ let expr = r#""#;
+ test("de", "LiteralSpeak", expr, "cap a right arrow, perpendicular to, cap b right arrow");
+}
+
+#[test]
+fn literal_speak_with_name() {
+ let expr = r#""#;
+ test("de", "LiteralSpeak", expr, "forced f, left paren x exclamation point, right paren");
+}
+
+#[test]
+fn literal_speak_with_property() {
+ let expr = r#""#;
+ test("de", "LiteralSpeak", expr, "f, left paren x exclamation point, right paren");
+}
+
+#[test]
+fn literal_intent_property() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr, "cap a right arrow, perpendicular to, cap b right arrow");
+}
+
+#[test]
+fn literal_intent_property_with_name() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr, "forced f, open paren x exclamation point, close paren");
+}
+*/
\ No newline at end of file
diff --git a/tests/Languages/de/units.rs b/tests/Languages/de/units.rs
new file mode 100644
index 00000000..c6a39d8f
--- /dev/null
+++ b/tests/Languages/de/units.rs
@@ -0,0 +1,442 @@
+/// Tests for rules shared between various speech styles:
+/// * modified var
+use crate::common::*;
+
+// The basic layout of the tests is:
+// 1. Sweep through all the SI prefixes
+// 2. Sweep through each group of SI units
+// a) with both singular and plural without prefixes
+// b) with both singular and plural with one prefix
+// 3. Sweep through each group of units that don't take SI prefixes
+// These are broken into chunks so it is easier to see errors, when there are errors
+
+#[test]
+fn prefix_sweep() {
+ let expr = r#""#;
+ 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");
+}
+
+#[test]
+fn si_base() {
+ let expr = r#""#;
+ 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");
+}
+
+/*
+#[test]
+fn si_base_with_prefixes() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 quetta-ampere, komma, 2 ronna-amperes, komma 1 yotta-candela, komma, 2 zetta-candelas, komma 1 exa-kelvin, komma, 2 peta-kelvins, komma 1 tera-kelvin, komma, 2 giga-kelvins, komma 1 mega-gramm, komma, 2 kilo-gramms, komma 1 hekto-meter, komma, 2 deka-meters, komma 1 dezi-mol, komma, 2 zenti-mols, komma 1 milli-sekunde, komma, 2 mikro-sekundes, komma 1 nano-sekunde, komma, 2 piko-sekundes");
+}
+
+
+#[test]
+fn si_derived_1() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 becquerel, comma; 2 becquerels, komma \
+ 1 coulomb, comma; 2 coulombs, comma; \
+ 1 degree celsius, comma; 2 degrees celsius, comma; \
+ 1 degree celsius, comma; 2 degrees celsius, komma \
+ 1 farad, komma 2 farads, komma \
+ 1 gray, komma 2 grays, komma \
+ 1 henry, komma 2 henrys, komma \
+ 1 hertz, komma 2 hertz, komma \
+ 1 joule, komma 2 joules, komma \
+ 1 kattel, komma 2 kattels, komma \
+ 1 lumen, komma 2 lumens, komma \
+ 1 lux, komma 2 luxs");
+}
+
+#[test]
+fn si_derived_1_with_prefixes() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 quetta-becquerel, comma; 2 ronna-becquerels; comma; \
+ 1 yotta-coulomb, comma; 2 zetta-coulombs, comma; \
+ 1 exa-farad, comma; 2 peta-farads, comma; \
+ 1 tera-gray, comma; 2 giga-grays, comma; \
+ 1 mega-henry, comma; 2 kilo-henrys, comma; \
+ 1 deka-hertz, comma; 2 dezi-hertz, comma; \
+ 1 zenti-joule, comma; 2 milli-joules, comma; \
+ 1 micro-kattel, comma; 2 nano-kattels, comma; \
+ 1 pico-lumen, comma; 2 femto-lumens, comma; \
+ 1 atto-lux, comma; 2 zepto-luxs, comma; \
+ 1 milli-degree celsius; comma; 2 micro-degrees celsius; comma; \
+ 1 pico-degree celsius; comma; 2 nano-degrees celsius");
+}
+
+#[test]
+fn si_derived_2() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 newton, komma 2 newtons, komma \
+ 1 ohm, komma 2 ohms, komma \
+ 1 ohm, komma 2 ohms, komma \
+ 1 pascal, komma 2 pascals, komma \
+ 1 siemens, komma 2 siemens, komma \
+ 1 sievert, comma; 2 sieverts, komma \
+ 1 tesla, komma 2 teslas, komma \
+ 1 volt, komma 2 volts, komma \
+ 1 watt, komma 2 watts, komma \
+ 1 weber, komma 2 webers");
+}
+
+#[test]
+fn si_derived_2_with_prefixes() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 quecto-newton, comma; 2 ronto-newtons, comma; \
+ 1 yocto-ohm, comma; 2 zepto-ohms, comma; \
+ 1 atto-ohm, comma; 2 femto-ohms, comma; \
+ 1 pico-pascal, comma; 2 nano-pascals, comma; \
+ 1 micro-siemens, comma; 2 milli-siemens, comma; \
+ 1 zenti-sievert, comma; 2 dezi-sieverts, comma; \
+ 1 deka-tesla, comma; 2 hekto-teslas, comma; \
+ 1 kilo-volt, comma; 2 mega-volts, comma; \
+ 1 giga-watt, comma; 2 tera-watts, comma; \
+ 1 peta-weber, comma; 2 exa-webers");
+}
+
+
+#[test]
+fn si_accepted() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 litre, komma 2 litres, komma \
+ 1 litre, komma 2 litres, komma \
+ 1 litre, komma 2 litres, komma \
+ 1 metric ton, comma; 2 metric tons, komma \
+ 1 dalton, komma 2 daltons, komma \
+ 1 neper, komma 2 nepers, comma; \
+ 1 atomic mass unit, comma; 2 atomic mass units, comma; \
+ 1 electronvolt, comma; 2 electronvolts, komma \
+ 1 radian, komma 2 radians, komma \
+ 1 sterradion, comma; 2 sterradions, komma \
+ 1 annum, komma 2 annums, komma \
+ 1 arcsecond, comma; 2 arcseconds, komma \
+ 1 bit, komma 2 bits, komma \
+ 1 byte, komma 2 bytes, komma \
+ 1 baud, komma 2 bauds");
+}
+
+#[test]
+fn si_accepted_with_prefixes() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 quetta-liter, komma, 2 ronna-liters, komma 1 yotta-liter, komma, 2 zetta-liters, komma 1 exa-liter, komma, 2 peta-liters, komma 1 tera-tonne, komma, 2 giga-tonnes, komma 1 mega-dalton, komma, 2 kilo-daltons, komma 1 dezi-neper, komma, 2 zenti-nepers, komma, 1 hekto-atommasse-einheit; komma, 2 deka-atommasse-einheits; komma, 1 milli-elektronenvolt, komma, 2 mikro-elektronenvolts; komma 1 nano-radiant, komma, 2 piko-radiants, komma, 1 femto-steradiant, komma, 2 atto-steradiants, komma 1 giga-jahr, komma, 2 mega-jahrs, komma, 1 zepto-bogensekunde, komma, 2 yocto-bogensekundes; komma 1 kilo-bit, komma 2 mega-bits, komma 1 giga-byte, komma, 2 tera-bytes, komma 1 tera-baud, komma 2 exa-bauds");
+}
+
+#[test]
+fn without_prefix_time() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 second, komma 2 seconds, komma \
+ 1 second, komma 2 seconds, komma \
+ 1 minute, komma 2 minutes, komma \
+ 1 minute, komma 2 minutes, komma \
+ 1 minute, komma 2 minutes, komma \
+ 1 hour, komma 2 hours, komma \
+ 1 hour, komma 2 hours, komma \
+ 1 hour, komma 2 hours, komma \
+ 1 day, komma 2 days, komma \
+ 1 day, komma 2 days, komma \
+ 1 week, komma 2 weeks, komma \
+ 1 week, komma 2 weeks, komma \
+ 1 year, komma 2 years, komma \
+ 1 year, komma 2 years");
+}
+
+#[test]
+fn without_prefix_angles() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 degree, komma 2 degrees, komma \
+ 1 degree, komma 2 degrees, komma \
+ 1 arcminute, comma; 2 arcminutes, komma \
+ 1 arcminute, comma; 2 arcminutes, komma \
+ 1 arcminute, comma; 2 arcminutes, komma \
+ 1 arcminute, comma; 2 arcminutes, komma \
+ 1 arcsecond, comma; 2 arcseconds, komma \
+ 1 arcsecond, comma; 2 arcseconds");
+}
+
+#[test]
+fn without_prefix_distance() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 astronomical unit, comma; 2 astronomical units, komma \
+ 1 light year, comma; 2 light years, komma \
+ 1 parsec, komma 2 parsecs, komma \
+ 1 angstrom, comma; 2 angstroms, komma \
+ 1 angstrom, comma; 2 angstroms, komma \
+ 1 fermi, komma 2 fermis");
+}
+
+#[test]
+fn without_prefix_other() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 hectare, comma; 2 hectares, komma \
+ 1 dezibel, comma; 2 dezibels, komma \
+ 1 atmosphere, comma; 2 atmospheres, comma; \
+ 1 atomic mass unit, comma; 2 atomic mass units, komma \
+ 1 bar, komma 2 bars, komma \
+ 1 calorie, comma; 2 calories, komma \
+ 1 curie, komma 2 curies, komma \
+ 1 gradian, comma; 2 gradians, komma \
+ 1 molar, komma 2 molars, komma \
+ 1 roentgen, comma; 2 roentgens, comma; \
+ 1 revolution per minute, comma; 2 revolutions per minute, komma \
+ 1 m-h-o, komma 2 m-h-os, komma \
+ 1 dyne, komma 2 dynes, komma \
+ 1 erg, komma 2 ergs");
+}
+
+#[test]
+fn without_prefix_powers_of_2() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1 kibi-bit, comma; 2 kibi-bits, komma \
+ 1 mebi-bit, comma; 2 mebi-bits, komma \
+ 1 gibi-bit, comma; 2 gibi-bits, komma \
+ 1 tebi-bit, comma; 2 tebi-bits, komma \
+ 1 pebi-bit, comma; 2 pebi-bits, komma \
+ 1 exbi-bit, comma; 2 exbi-bits, komma \
+ 1 zebi-bit, comma; 2 zebi-bits, komma \
+ 1 yobi-bit, comma; 2 yobi-bits, komma \
+ 1 kibi-byte, comma; 2 kibi-bytes, komma \
+ 1 mebi-byte, comma; 2 mebi-bytes, komma \
+ 1 gibi-byte, comma; 2 gibi-bytes, komma \
+ 1 tebi-byte, comma; 2 tebi-bytes, komma \
+ 1 pebi-byte, comma; 2 pebi-bytes, komma \
+ 1 exbi-byte, comma; 2 exbi-bytes, komma \
+ 1 zebi-byte, comma; 2 zebi-bytes, komma \
+ 1 yobi-byte, comma; 2 yobi-bytes");
+}
+
+
+#[test]
+fn si_other_numbers() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "1.0 litre, comma; 2.0 metres, comma; x milli-seconds, comma; y micro-seconds, komma \
+ deka-grams, comma; 1235 deka-newtons; comma; 2.5 micro-seconds; comma; 32.34 moles");
+}
+
+
+#[test]
+fn test_mtext_inference() {
+ let expr = r#""#;
+ test("de", "SimpleSpeak", expr,
+ "open bracket; 1 metric ton, comma; 2 peta-amps, komma \
+ 3 pascals, comma; 4.5 milli-teslas; close bracket");
+}
+
+
+ */
\ No newline at end of file