From c70de56d86ce774d385be0f1b35d678bef0a37c7 Mon Sep 17 00:00:00 2001
From: Danil <81031453+Kostenkov-2021@users.noreply.github.com>
Date: Fri, 30 Oct 2026 11:33:54 +0300
Subject: [PATCH 1/3] Expand Russian W3C intent speech support
Add Russian translations and grammatical handling for W3C core intents, including calculus, function sets, relations, and variadic lists. Add regression coverage across speech styles, verbosity levels, and navigation modes.
---
Rules/Languages/ru/SharedRules/calculus.yaml | 91 +++++++
Rules/Languages/ru/SharedRules/default.yaml | 4 +-
Rules/Languages/ru/SharedRules/general.yaml | 200 +++++++++++++++-
Rules/Languages/ru/SharedRules/geometry.yaml | 10 +
Rules/Languages/ru/definitions.yaml | 235 +++++++++++++++++-
tests/Languages/ru/intent.rs | 236 ++++++++++++++++++-
tests/Languages/ru/navigate.rs | 36 +++
7 files changed, 795 insertions(+), 17 deletions(-)
diff --git a/Rules/Languages/ru/SharedRules/calculus.yaml b/Rules/Languages/ru/SharedRules/calculus.yaml
index e6288aec2..8fcbadccc 100644
--- a/Rules/Languages/ru/SharedRules/calculus.yaml
+++ b/Rules/Languages/ru/SharedRules/calculus.yaml
@@ -1,5 +1,96 @@
---
+# W3C definite-integral arguments are the integration domain or the two bounds, not the sign.
+- name: definite-integral-intent
+ tag: definite-integral
+ match: "(count(*)=1 or count(*)=2) and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "интеграл"
+ - test:
+ if: "count(*)=1"
+ then: [T: "по", x: "*[1]"]
+ else:
+ - T: "от"
+ - test:
+ - if: "*[1][self::m:minus and count(*)=1 and *[1][.='∞']]"
+ then: [T: "минус бесконечности"]
+ - else_if: "*[1][self::m:plus and count(*)=1 and *[1][.='∞']]"
+ then: [T: "плюс бесконечности"]
+ - else_if: "*[1][.='∞']"
+ then: [T: "бесконечности"]
+ else: [x: "*[1]"]
+ - T: "до"
+ - test:
+ - if: "*[2][self::m:minus and count(*)=1 and *[1][.='∞']]"
+ then: [T: "минус бесконечности"]
+ - else_if: "*[2][self::m:plus and count(*)=1 and *[1][.='∞']]"
+ then: [T: "плюс бесконечности"]
+ - else_if: "*[2][.='∞']"
+ then: [T: "бесконечности"]
+ else: [x: "*[2]"]
+
+# A semantic reading also works for prime notation; the numeric-order phrase avoids case-dependent ordinals.
+- name: derivative-intent
+ tag: derivative
+ match: "count(*)=3 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "производная"
+ - test:
+ if: "not(*[3][self::m:mn and .='1'])"
+ then: [T: "порядка", x: "*[3]"]
+ - test:
+ if: "not(IsNode(*[1], 'simple'))"
+ then: [T: "выражения"]
+ - x: "*[1]"
+ - T: "по"
+ - x: "*[2]"
+
+- name: core-sum-product
+ tag: [sum, product]
+ match: "count(*)>=1 and count(*)<=3 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - x: "SpeakIntentName(name(.), $Verbosity, 'function')"
+ - test:
+ - if: "count(*)=2"
+ then: [T: "по", x: "*[1]"]
+ - else_if: "count(*)=3"
+ then: [T: "от", x: "*[1]", T: "до", x: "*[2]"]
+ - test:
+ if: "count(*)>1 or not(IsNode(*[last()], 'simple'))"
+ then: [T: "выражения"]
+ - x: "*[last()]"
+ - test:
+ if: "$Impairment='Blindness' and not(IsNode(*[last()], 'simple') or IsBracketed(*[last()], '', ''))"
+ then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'function', 'end')"]
+
+# Pair each variable with its following order. InsertIndex is supplied by insert;
+# the previous variable's order is at 2*InsertIndex-1 in the full child list.
+
+- name: core-partial-derivative
+ tag: partial-derivative
+ match: "count(*)>=3 and count(*) mod 2=1 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "частная производная"
+ - test:
+ if: "not(IsNode(*[1], 'simple'))"
+ then: [T: "выражения"]
+ - x: "*[1]"
+ - T: "по"
+ - insert:
+ nodes: "*[position() mod 2=0]"
+ replace:
+ - test:
+ if: "not(*[2*$InsertIndex - 1][self::m:mn and .='1'])"
+ then: [T: "порядка", x: "*[2*$InsertIndex - 1]"]
+ - T: "и по"
+ - test:
+ if: "not(*[last()][self::m:mn and .='1'])"
+ then: [T: "порядка", x: "*[last()]"]
+
- name: laplacian
tag: laplacian
match: "count(*) <= 1" # can be on ∇^2 or on enclosing mrow
diff --git a/Rules/Languages/ru/SharedRules/default.yaml b/Rules/Languages/ru/SharedRules/default.yaml
index ad8a44f7d..709a57c60 100644
--- a/Rules/Languages/ru/SharedRules/default.yaml
+++ b/Rules/Languages/ru/SharedRules/default.yaml
@@ -569,12 +569,12 @@
tag: mi
match:
- "string-length(.)=1 and"
- - "(parent::*[self::m:trace or self::m:dimension or self::m:homomorphism or self::m:kernel or self::m:norm or self::m:determinant or self::m:real-part or self::m:imaginary-part or self::m:laplacian or self::m:divergence or self::m:curl or self::m:gradient or self::m:subscripted-norm or self::m:limit or self::m:line-segment or self::m:ray or self::m:open-interval or self::m:closed-interval or self::m:open-closed-interval or self::m:closed-open-interval or self::m:binomial or self::m:pochhammer or self::m:square-root or self::m:root or self::m:absolute-value] or parent::m:large-op or parent::m:logarithm-with-base or (parent::m:power and preceding-sibling::*) or (parent::m:fraction and preceding-sibling::* and IsNode(../*[1], 'simple') and IsNode(., 'simple')) or (parent::m:apply-function and preceding-sibling::*) or (parent::m:evaluate and preceding-sibling::*) or preceding-sibling::*[1][.='' or .='∈' or .='∉' or .='∊'] or parent::m:mrow[IsBracketed(., '(', ')') and count(*)=3 and parent::*[self::m:kernel or self::m:homomorphism]])"
+ - "((preceding-sibling::* and (IsInDefinition(name(..), 'RussianGenitiveRightOperandIntents') or IsInDefinition(name(..), 'RussianAccusativeRightOperandIntents'))) or DefinitionValue(name(..), 'Speech', 'RussianCoreGenitiveNames')!='' or parent::*[self::m:partial-derivative or self::m:quotient or self::m:remainder or self::m:ratio or self::m:conditional-probability or self::m:logarithm or self::m:ordered-pair or self::m:inverse or self::m:set-difference or self::m:binomial-coefficient] or parent::*[self::m:definite-integral or self::m:derivative or self::m:image or self::m:domain or self::m:codomain or self::m:trace or self::m:dimension or self::m:homomorphism or self::m:kernel or self::m:norm or self::m:determinant or self::m:real-part or self::m:imaginary-part or self::m:laplacian or self::m:divergence or self::m:curl or self::m:gradient or self::m:subscripted-norm or self::m:limit or self::m:line-segment or self::m:ray or self::m:open-interval or self::m:closed-interval or self::m:open-closed-interval or self::m:closed-open-interval or self::m:binomial or self::m:pochhammer or self::m:square-root or self::m:root or self::m:absolute-value] or parent::m:large-op or parent::m:logarithm-with-base or (parent::m:power and preceding-sibling::*) or (parent::m:fraction and preceding-sibling::* and IsNode(../*[1], 'simple') and IsNode(., 'simple')) or (parent::m:apply-function and preceding-sibling::*) or (parent::m:evaluate and preceding-sibling::*) or preceding-sibling::*[1][.='' or .='∈' or .='∉' or .='∊'] or parent::m:mrow[IsBracketed(., '(', ')') and count(*)=3 and parent::*[self::m:kernel or self::m:homomorphism]])"
replace:
- bookmark: "@id"
- with:
variables:
- - RuCapitalWord: "IfThenElse((parent::m:ray or parent::m:fraction) and preceding-sibling::*, 'заглавную', 'заглавной')"
+ - RuCapitalWord: "IfThenElse(((parent::m:ray or parent::m:fraction or parent::m:quotient or parent::m:remainder) or IsInDefinition(name(..), 'RussianAccusativeRightOperandIntents')) and preceding-sibling::*, 'заглавную', 'заглавной')"
- RuInflectCapital: "not(parent::m:large-op and not(preceding-sibling::*)) and not(parent::m:line-segment and $Verbosity!='Verbose') and not(parent::m:ray and $Verbosity!='Verbose') and not($Verbosity='Terse' and (parent::m:square-root or (parent::m:root and not(preceding-sibling::*))))"
replace:
- with:
diff --git a/Rules/Languages/ru/SharedRules/general.yaml b/Rules/Languages/ru/SharedRules/general.yaml
index f2964d2b9..c20cd1fa3 100644
--- a/Rules/Languages/ru/SharedRules/general.yaml
+++ b/Rules/Languages/ru/SharedRules/general.yaml
@@ -1,4 +1,19 @@
---
+
+- name: blank-intent
+ tag: blank
+ match: "count(*)=0"
+ replace: [bookmark: "@id", T: "пустое место"]
+
+# Preserve operands while suppressing the default-silent operator, including a bare operator leaf.
+- name: invisible-operator-intent
+ tag: [invisible-times, invisible-separator]
+ match: "not(@data-intent-property) or contains(@data-intent-property, ':silent:')"
+ replace:
+ - test:
+ if: "*"
+ then: [x: "*"]
+ else: [T: ""]
# Names confirmed in Russian mathematical notation. Do not rewrite MathML.
- name: russian-function-alias
tag: [mi, mtext]
@@ -128,7 +143,165 @@
if: "count(*)>0"
then: [x: "*"]
+# Function sets take a genitive operand, without the generic connector "от".
+- name: function-set
+ tag: [image, domain, codomain]
+ match: "count(*)<=1 and not(contains(@data-intent-property, ':silent:') or contains(@data-intent-property, ':postfix:') or contains(@data-intent-property, ':infix:') or contains(@data-intent-property, ':nofix:'))"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "parent::*[self::m:image or self::m:domain or self::m:codomain][count(*)=1] or DefinitionValue(name(..), 'Speech', 'RussianCoreGenitiveNames')!=''"
+ then: [x: "DefinitionValue(name(.), 'Speech', 'RussianGenitiveFunctionSets')"]
+ else: [x: "SpeakIntentName(name(.), $Verbosity, 'function')"]
+ - test:
+ if: "count(*)=1"
+ then:
+ - test:
+ if: "not(IsNode(*[1], 'simple')) and not(*[1][self::m:image or self::m:domain or self::m:codomain]) and DefinitionValue(name(*[1]), 'Speech', 'RussianCoreGenitiveNames')=''"
+ then: [T: "выражения"]
+ - with:
+ variables:
+ - SpeechOverrides_CapitalLetters: "IfThenElse(*[1][self::m:mi and string-length(.)=1 and contains('ABCDEFGHIJKLMNOPQRSTUVWXYZ', .)] and $SpeechOverrides_CapitalLetters='' and $Impairment='Blindness', 'заглавной', $SpeechOverrides_CapitalLetters)"
+ replace: [x: "*[1]"]
+
# rules on scripted vertical bars ('evaluated at')
+- name: core-noun-function
+ tag: [adjugate, area, cardinality, ceiling, complement, complex-arg, complex-conjugate, diameter, distance, floor, fractional-part, least-common-denominator, length, max, mean, median, min, mode, probability, radius, round, span, standard-deviation, variance, volume]
+ match: "count(*)=1 and not(contains(@data-intent-property, ':silent:') or contains(@data-intent-property, ':postfix:') or contains(@data-intent-property, ':infix:'))"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "DefinitionValue(name(..), 'Speech', 'RussianCoreGenitiveNames')!='' or DefinitionValue(name(..), 'Speech', 'RussianGenitiveFunctionSets')!=''"
+ then: [x: "DefinitionValue(name(.), 'Speech', 'RussianCoreGenitiveNames')"]
+ else: [x: "SpeakIntentName(name(.), $Verbosity, 'function')"]
+ - test:
+ if: "not(IsNode(*[1], 'simple')) and not(DefinitionValue(name(*[1]), 'Speech', 'RussianCoreGenitiveNames')!='' or DefinitionValue(name(*[1]), 'Speech', 'RussianGenitiveFunctionSets')!='')"
+ then: [T: "выражения"]
+ - x: "*[1]"
+
+- name: core-coordinate-list
+ tag: [cartesian-coordinate, polar-coordinate, spherical-coordinate, list, tuple, permutation-cycle]
+ match: "count(*)>0 and not(contains(@data-intent-property, ':silent:') or contains(@data-intent-property, ':postfix:') or contains(@data-intent-property, ':infix:'))"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "DefinitionValue(name(..), 'Speech', 'RussianCoreGenitiveNames')!='' or DefinitionValue(name(..), 'Speech', 'RussianGenitiveFunctionSets')!=''"
+ then: [x: "DefinitionValue(name(.), 'Speech', 'RussianCoreGenitiveNames')"]
+ else: [x: "SpeakIntentName(name(.), $Verbosity, 'function')"]
+ - test:
+ if: "*"
+ then:
+ - insert:
+ nodes: "*"
+ replace: [T: "запятая"]
+
+- name: core-ordered-pair
+ tag: ordered-pair
+ match: "count(*)=2 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "упорядоченная пара"
+ - x: "*[1]"
+ - T: "и"
+ - x: "*[2]"
+
+- name: core-conditional-probability
+ tag: conditional-probability
+ match: "count(*)=2 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "вероятность"
+ - x: "*[1]"
+ - T: "при условии"
+ - x: "*[2]"
+
+- name: core-logarithm-with-base
+ tag: logarithm
+ match: "count(*)=2 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "логарифм по основанию"
+ - x: "*[2]"
+ - T: "от"
+ - x: "*[1]"
+
+- name: core-division-result
+ tag: [quotient, remainder]
+ match: "count(*)=2 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - test:
+ if: "self::m:quotient"
+ then: [T: "целая часть результата деления"]
+ else: [T: "остаток от деления"]
+ - test:
+ if: "not(IsNode(*[1], 'simple'))"
+ then: [T: "выражения"]
+ - x: "*[1]"
+ - T: "на"
+ - test:
+ if: "not(IsNode(*[2], 'simple'))"
+ then: [T: "выражение"]
+ - x: "*[2]"
+
+- name: core-common-denominator
+ tag: least-common-denominator
+ match: "count(*)>=2 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "наименьший общий знаменатель"
+ - insert:
+ nodes: "*"
+ replace: [T: "и"]
+
+- name: core-extrema
+ tag: [max, min]
+ match: "count(*)>=2 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - x: "SpeakIntentName(name(.), $Verbosity, 'function')"
+ - T: "из"
+ - insert:
+ nodes: "*"
+ replace: [T: "запятая"]
+
+- name: core-set-difference
+ tag: set-difference
+ match: "count(*)=2 and not(contains(@data-intent-property, ':silent:') or contains(@data-intent-property, ':infix:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "разность множеств"
+ - x: "*[1]"
+ - T: "и"
+ - x: "*[2]"
+
+- name: core-ratio
+ tag: ratio
+ match: "count(*)=2 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "отношение"
+ - test:
+ if: "not(IsNode(*[1], 'simple'))"
+ then: [T: "выражения"]
+ - x: "*[1]"
+ - T: "к"
+ - test:
+ if: "not(IsNode(*[2], 'simple'))"
+ then: [T: "выражению"]
+ - x: "*[2]"
+
+- name: core-inverse
+ tag: inverse
+ match: "count(*)=1 and not(contains(@data-intent-property, ':silent:') or contains(@data-intent-property, ':postfix:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "обратный к"
+ - test:
+ if: "not(IsNode(*[1], 'simple'))"
+ then: [T: "выражению"]
+ - x: "*[1]"
+
- name: evaluated-at-2
tag: evaluate
match: "count(*)=2"
@@ -181,7 +354,7 @@
- x: "*[2]"
- name: binomial
- tag: binomial
+ tag: [binomial, binomial-coefficient]
match: "count(*)=2"
replace:
- T: "число сочетаний из"
@@ -210,11 +383,11 @@
if: "not(IsNode(*[2], 'simple'))"
then: [T: "конец числа сочетаний"]
-# Read an infix pochhammer intent as a number of arrangements.
+# Accept W3C's default function fixity as well as the inferred infix representation.
- name: permutation
# Use Russian arrangements wording rather than the generic infix intent mapping
tag: pochhammer
- match: "count(*)=2 and contains(@data-intent-property, ':infix:')"
+ match: "count(*)=2 and (contains(@data-intent-property, ':infix:') or contains(@data-intent-property, ':function:'))"
replace:
- T: "число размещений из"
- x: "*[1]"
@@ -255,15 +428,15 @@
then: [T: "бесконечности"]
else: [x: "*[2]"]
-# Read a two-coordinate point with a spoken comma between coordinates.
+# W3C points have one or more coordinates, separated by spoken commas.
- name: default-point
tag: point
- match: "count(*)=2"
+ match: "count(*)>=1 and not(contains(@data-intent-property, ':silent:'))"
replace:
- T: "точка" # phrase(the 'point' with coordinates x and y)
- - x: "*[1]"
- - T: "запятая"
- - x: "*[2]"
+ - insert:
+ nodes: "*"
+ replace: [T: "запятая"]
- name: bigop-both
tag: large-op
@@ -327,13 +500,16 @@
then: [T: "от"] # phrase(the square root 'of' 25 equals 5)
- x: "*[2]"
+# W3C supplies the period alone; inferred MathCAT intents also carry a non-repeating prefix.
- name: repeating-decimal
tag: repeating-decimal
- match: "."
+ match: "(count(*)=1 or count(*)=2) and not(contains(@data-intent-property, ':silent:'))"
replace:
- - x: "*[1]"
- - T: "с повторяющимися цифрами" # phrase('with repeating digits')
- - SPELL: "*[2]"
+ - test:
+ if: "count(*)=2"
+ then: [x: "*[1]", T: "с повторяющимися цифрами"]
+ else: [T: "период"]
+ - SPELL: "*[last()]"
- name: msubsup-skip-super
# handles single, double, etc., prime
diff --git a/Rules/Languages/ru/SharedRules/geometry.yaml b/Rules/Languages/ru/SharedRules/geometry.yaml
index d16ae3f69..eef4d2b1b 100644
--- a/Rules/Languages/ru/SharedRules/geometry.yaml
+++ b/Rules/Languages/ru/SharedRules/geometry.yaml
@@ -1,5 +1,15 @@
---
+- name: core-translation
+ tag: translation
+ match: "count(*)=2 and not(contains(@data-intent-property, ':silent:'))"
+ replace:
+ - bookmark: "@id"
+ - T: "перенос на"
+ - x: "*[1]"
+ - T: "запятая"
+ - x: "*[2]"
+
- name: line-segment
tag: line-segment
match: "count(*)=2"
diff --git a/Rules/Languages/ru/definitions.yaml b/Rules/Languages/ru/definitions.yaml
index b3509614e..3daac3335 100644
--- a/Rules/Languages/ru/definitions.yaml
+++ b/Rules/Languages/ru/definitions.yaml
@@ -108,12 +108,192 @@
# "ratio": "function=ratio : to | the ratio : to | the ratio : to" # verbosity of name:glue pairs
#
- IntentMappings: {
+ # W3C core concept names; explicit intent does not change inferred notation.
+ "adjugate": "function=присоединённая матрица",
+ "and": "infix=и",
+ "angle": "prefix=угол",
+ "angle-measure": "prefix=мера угла",
+ "annotation": "infix=с пояснением",
+ "applied-to": "infix=от",
+ "approximately": "infix=приблизительно равно",
+ "arc-hyperbolic-cosecant": "function=обратная функция гиперболического косеканса",
+ "arc-hyperbolic-cosine": "function=обратная функция гиперболического косинуса",
+ "arc-hyperbolic-cotangent": "function=обратная функция гиперболического котангенса",
+ "arc-hyperbolic-secant": "function=обратная функция гиперболического секанса",
+ "arc-hyperbolic-sine": "function=обратная функция гиперболического синуса",
+ "arc-hyperbolic-tangent": "function=обратная функция гиперболического тангенса",
+ "arccosecant": "function=арккосеканс",
+ "arccosine": "function=арккосинус",
+ "arccotangent": "function=арккотангенс",
+ "arcsecant": "function=арксеканс",
+ "arcsine": "function=арксинус",
+ "arctangent": "function=арктангенс",
+ "area": "function=площадь",
+ "binomial-coefficient": "infix=число сочетаний из; по; конец числа сочетаний",
+ "braced-group": "prefix=; группа; конец группы",
+ "cardinality": "function=мощность",
+ "cartesian-coordinate": "function=декартовы координаты",
+ "cartesian-product": "infix=декартово произведение",
+ "ceiling": "function=округление вверх",
+ "change": "prefix=изменение",
+ "complement": "function=дополнение",
+ "complex-arg": "function=аргумент",
+ "complex-conjugate": "function=комплексное сопряжение",
+ "composed-with": "infix=композиция с",
+ "conditional-probability": "function=вероятность: при условии",
+ "congruent": "infix=конгруэнтно",
+ "constraint": "infix=при условии",
+ "cosecant": "function=косеканс",
+ "cosine": "function=косинус",
+ "cotangent": "function=котангенс",
+ "defined-as": "infix=определяется как",
+ "diameter": "nofix=диаметр || function=диаметр",
+ "differential-d": "nofix=дэ",
+ "dimensional-product": "infix=на",
+ "direct-product": "infix=прямое произведение",
+ "directed-line-segment": "prefix=направленный отрезок",
+ "distance": "nofix=расстояние || function=расстояние",
+ "divided-by": "infix=разделить на",
+ "divides": "infix=делит",
+ "does-not-belong-to": "infix=не принадлежит",
+ "does-not-divide": "infix=не делит",
+ "downwards-diagonal-ellipsis": "infix=диагональное многоточие вниз",
+ "element-of": "infix=принадлежит",
+ "ellipsis": "infix=многоточие",
+ "embellished-name": "infix=с обозначением",
+ "empty-set": "nofix=пустое множество",
+ "equals": "infix=равно",
+ "equivalent-to": "infix=эквивалентно",
+ "evaluated-at": "infix=вычисленное при",
+ "evaluates-to": "infix=вычисляется как",
+ "exponential": "function=экспонента",
+ "exponential-e": "nofix=число е",
+ "factorial": "postfix=факториал",
+ "fenced-group": "prefix=; выражение в скобках; конец выражения в скобках",
+ "floor": "function=округление вниз",
+ "for-all": "prefix=для всех",
+ "fractional-part": "function=дробная часть",
+ "given": "infix=при условии",
+ "golden-ratio": "nofix=золотое сечение",
+ "greater-than": "infix=больше",
+ "greater-than-or-equal-to": "infix=больше или равно",
+ "highlight": "postfix=выделено",
+ "hyperbolic-cosecant": "function=гиперболический косеканс",
+ "hyperbolic-cosine": "function=гиперболический косинус",
+ "hyperbolic-cotangent": "function=гиперболический котангенс",
+ "hyperbolic-secant": "function=гиперболический секанс",
+ "hyperbolic-sine": "function=гиперболический синус",
+ "hyperbolic-tangent": "function=гиперболический тангенс",
+ "identically-equals": "infix=тождественно равно",
+ "identity-matrix": "nofix=единичная матрица",
+ "if-and-only-if": "infix=тогда и только тогда когда",
+ "imaginary-i": "nofix=мнимая единица",
+ "implies": "infix=влечёт",
+ "inner-product": "infix=скалярное произведение",
+ "intersection": "infix=пересечение",
+ "inverse": "function=обратный к || postfix=обратный",
+ "least-common-denominator": "function=наименьший общий знаменатель",
+ "length": "function=длина",
+ "less-than": "infix=меньше",
+ "less-than-or-equal-to": "infix=меньше или равно",
+ "line": "prefix=прямая",
+ "list": "nofix=список || function=список",
+ "list-separator": "infix=запятая",
+ "logarithm": "function=логарифм",
+ "maps-to": "infix=отображается в",
+ "max": "function=максимум",
+ "mean": "function=среднее",
+ "measured-angle": "prefix=измеренный угол",
+ "median": "function=медиана",
+ "member-of": "infix=принадлежит",
+ "min": "function=минимум",
+ "minus-or-plus": "infix=минус плюс",
+ "mixed-fraction": "infix=и",
+ "mode": "function=мода",
+ "not": "prefix=не",
+ "not-equal-to": "infix=не равно",
+ "not-member-of": "infix=не принадлежит",
+ "not-parallel-to": "infix=не параллельно",
+ "not-subset": "infix=не является подмножеством",
+ "not-superset": "infix=не является надмножеством",
+ "number-of": "prefix=число",
+ "obtained-from": "infix=получено из",
+ "or": "infix=или",
+ "ordered-pair": "function=упорядоченная пара: и",
+ "outer-product": "infix=внешнее произведение",
+ "parallel-to": "infix=параллельно",
+ "partial-derivative": "other=частная производная",
+ "percent": "postfix=процентов",
+ "permutation-cycle": "function=цикл перестановки",
+ "plus-or-minus": "infix=плюс минус",
+ "polar-coordinate": "function=полярные координаты",
+ "precedes": "infix=предшествует",
+ "probability": "nofix=вероятность || function=вероятность",
+ "product": "function=; произведение; конец произведения",
+ "proportional": "infix=пропорционально",
+ "quotient": "function=целая часть частного",
+ "radius": "nofix=радиус || function=радиус",
+ "range-separator": "infix=до",
+ "rate": "infix=на",
+ "ratio": "function=отношение: к",
+ "remainder": "function=остаток",
+ "right-angle": "prefix=прямой угол",
+ "round": "function=округлённое значение",
+ "secant": "function=секанс",
+ "set-difference": "function=разность множеств: и || infix=минус",
+ "set-of-complex-numbers": "nofix=комплексные числа",
+ "set-of-integers": "nofix=целые числа",
+ "set-of-natural-numbers": "nofix=натуральные числа",
+ "set-of-primes": "nofix=простые числа",
+ "set-of-rationals": "nofix=рациональные числа",
+ "set-of-reals": "nofix=действительные числа",
+ "similar": "infix=подобно",
+ "sine": "function=синус",
+ "span": "function=линейная оболочка",
+ "spherical-coordinate": "function=сферические координаты",
+ "square-root-of": "prefix=квадратный корень из",
+ "standard-deviation": "function=стандартное отклонение",
+ "subset": "infix=является подмножеством",
+ "subset-or-equal": "infix=является подмножеством или равно",
+ "succeeds": "infix=следует за",
+ "such-that": "infix=таких что",
+ "sum": "function=; сумма; конец суммы",
+ "superset": "infix=является надмножеством",
+ "superset-or-equal": "infix=является надмножеством или равно",
+ "tangent": "function=тангенс",
+ "tends-to": "infix=стремится к",
+ "tends-to-from-above": "infix=стремится сверху к",
+ "tends-to-from-below": "infix=стремится снизу к",
+ "there-does-not-exist": "prefix=не существует",
+ "there-exists": "prefix=существует",
+ "tilde": "infix=тильда",
+ "time-separator": "infix=",
+ "times": "infix=умножить на",
+ "translation": "function=перенос на",
+ "tuple": "nofix=кортеж || function=кортеж",
+ "union": "infix=объединение",
+ "unit-vector": "prefix=единичный вектор",
+ "upwards-diagonal-ellipsis": "infix=диагональное многоточие вверх",
+ "variance": "function=дисперсия",
+ "vertical-ellipsis": "infix=вертикальное многоточие",
+ "volume": "nofix=объём || function=объём",
+ "xor": "infix=исключающее или",
+ "blank": "nofix=пустое место",
+ "definite-integral": "other=интеграл",
+ "derivative": "other=производная",
+ "invisible-separator": "silent=",
+ "invisible-times": "silent=",
+ "point": "other=точка",
+ "pochhammer": "function=число размещений",
"indexed-by": "infix= ; с индексом; конец индекса| с индексом| с индексом",
"modified-variable": "silent= ",
"say-super": "infix=верхний индекс| верхний индекс| верхний индекс", # used with 'mo' for superscripts (e.g, "<")
"skip-super": "silent=", # used with 'mo' for superscripts (e.g, "*")
"absolute-value": "function= ; модуль| модуль| модуль; конец модуля",
+ "domain": "function=область определения",
+ "codomain": "function=целевое множество",
+ "image": "function=образ",
"binomial": "infix=число сочетаний из; по; конец числа сочетаний",
# "closed-interval": "other=closed-interval; от,до; end closed-interval",
"greatest-common-divisor": "function=нод| нод| наибольший общий делитель",
@@ -127,7 +307,6 @@
"natural-logarithm": "function=эл эн| натуральный логарифм| натуральный логарифм",
"minus": "infix=минус || prefix=минус",
"plus": "infix=плюс || prefix=плюс",
- # "pochhammer": "infix=permutations of", # arguments are in reverse order, so can't work here
"real-part": "function=действительная часть",
"transpose": "postfix=транспонирование || function=транспонированная",
@@ -153,6 +332,60 @@
}
# Names of functions that in terse mode don't say "of" (or it's equivalent in other languages)
+- RussianGenitiveFunctionSets: {
+ "image": "образа",
+ "domain": "области определения",
+ "codomain": "целевого множества",
+ }
+
+- RussianCoreGenitiveNames: {
+ "adjugate": "присоединённой матрицы",
+ "area": "площади",
+ "cardinality": "мощности",
+ "ceiling": "округления вверх",
+ "complement": "дополнения",
+ "complex-arg": "аргумента",
+ "complex-conjugate": "комплексного сопряжения",
+ "diameter": "диаметра",
+ "distance": "расстояния",
+ "floor": "округления вниз",
+ "fractional-part": "дробной части",
+ "least-common-denominator": "наименьшего общего знаменателя",
+ "length": "длины",
+ "max": "максимума",
+ "mean": "среднего",
+ "median": "медианы",
+ "min": "минимума",
+ "mode": "моды",
+ "probability": "вероятности",
+ "radius": "радиуса",
+ "round": "округлённого значения",
+ "span": "линейной оболочки",
+ "standard-deviation": "стандартного отклонения",
+ "variance": "дисперсии",
+ "volume": "объёма",
+ "list": "списка",
+ "tuple": "кортежа",
+ "permutation-cycle": "цикла перестановки",
+ "cartesian-coordinate": "декартовых координат",
+ "polar-coordinate": "полярных координат",
+ "spherical-coordinate": "сферических координат",
+ }
+
+# Case of a capital-letter right operand of a named relation or operation.
+- RussianGenitiveRightOperandIntents: {
+ "applied-to", "approximately", "composed-with", "congruent", "does-not-belong-to",
+ "element-of", "equals", "equivalent-to", "given", "greater-than", "greater-than-or-equal-to",
+ "identically-equals", "less-than", "less-than-or-equal-to", "member-of", "not-equal-to",
+ "not-member-of", "not-parallel-to", "not-subset", "not-superset", "obtained-from",
+ "parallel-to", "precedes", "proportional", "range-separator", "similar", "subset",
+ "subset-or-equal", "succeeds", "superset", "superset-or-equal", "tends-to",
+ "tends-to-from-above", "tends-to-from-below",
+ }
+- RussianAccusativeRightOperandIntents: {
+ "divided-by", "implies", "maps-to", "rate", "times",
+ }
+
- TerseFunctionNames: {
"divergence", "gradient", "curl"
}
diff --git a/tests/Languages/ru/intent.rs b/tests/Languages/ru/intent.rs
index 40dd2e1c5..93be30d2e 100644
--- a/tests/Languages/ru/intent.rs
+++ b/tests/Languages/ru/intent.rs
@@ -1,9 +1,108 @@
/// Тесты для правил, общих для различных стилей речи:
-/// * здесь собраны тесты, посвящённые различным алфавитам
+/// * явный intent, русская локализация и грамматика аргументов
use crate::common::*;
use anyhow::Result;
+fn all_russian_speech_modes(expr: &str, expected: &str) -> Result<()> {
+ for style in ["ClearSpeak", "SimpleSpeak"] {
+ for verbosity in ["Terse", "Medium", "Verbose"] {
+ test_prefs("ru", style, vec![("Verbosity", verbosity), ("IntentErrorRecovery", "Error")], expr, expected)?;
+ }
+ }
+ Ok(())
+}
+
+#[test]
+fn w3c_point_dimensions() -> Result<()> {
+ // W3C permits one or more coordinates; retain the established two-coordinate reading.
+ all_russian_speech_modes("", "точка 1")?;
+ all_russian_speech_modes("", "точка 1 запятая 2")?;
+ all_russian_speech_modes("", "точка 1 запятая 2 запятая 3")
+}
+
+#[test]
+fn w3c_point_compound_coordinate() -> Result<()> {
+ // A coordinate expression remains a single coordinate, with the separator after the whole expression.
+ all_russian_speech_modes("", "точка 1 плюс 2 запятая 3")
+}
+
+#[test]
+fn w3c_pochhammer_function() -> Result<()> {
+ // W3C's default function form keeps n=5 and k=2 in the Russian 'из n по k' order.
+ all_russian_speech_modes("", "число размещений из 5 по 2")?;
+ all_russian_speech_modes("", "число размещений из 5 по 2")
+}
+
+#[test]
+fn w3c_pochhammer_infix_compatibility() -> Result<()> {
+ // Existing inferred intents use infix fixity; their wording and argument order must remain unchanged.
+ all_russian_speech_modes("", "число размещений из 5 по 2")
+}
+
+#[test]
+fn function_set_image() -> Result<()> {
+ // An explicit image intent names the image, with a genitive capital-letter operand.
+ all_russian_speech_modes("", "образ заглавной эр")
+}
+
+#[test]
+fn function_set_domain() -> Result<()> {
+ // The domain is the set of allowed inputs, not an ordinary function applied with "от".
+ all_russian_speech_modes("", "область определения заглавной эф")
+}
+
+#[test]
+fn function_set_codomain() -> Result<()> {
+ // The codomain is the target set; it must remain distinct from the image.
+ all_russian_speech_modes("", "целевое множество заглавной эф")
+}
+
+#[test]
+fn function_set_nested_genitive() -> Result<()> {
+ // Nested concept names themselves take the genitive, without an extra expression cue.
+ all_russian_speech_modes("", "образ области определения заглавной эф")?;
+ all_russian_speech_modes("", "область определения целевого множества образа заглавной эф")
+}
+
+#[test]
+fn function_set_compound_operand() -> Result<()> {
+ // A compound operand is introduced with genitive "выражения"; its internal letters stay nominative.
+ all_russian_speech_modes("", "образ выражения заглавная эф плюс заглавная гэ")
+}
+
+#[test]
+fn function_set_name_only() -> Result<()> {
+ // A standalone operator name has no operand to inflect and needs no connector.
+ all_russian_speech_modes("", "образ")?;
+ all_russian_speech_modes("", "область определения")?;
+ all_russian_speech_modes("", "целевое множество")
+}
+
+#[test]
+fn complex_parts_with_style_wrappers() -> Result<()> {
+ // TeX4ht splits upright function names into mi children of mstyle; neither name may disappear.
+ let expr = "";
+ test("ru", "ClearSpeak", expr, "а равно действительная часть от зэт запятая, бэ равно мнимая часть от зэт")?;
+ test("ru", "SimpleSpeak", expr, "а равно действительная часть от зэт запятая, бэ равно мнимая часть от зэт")
+}
+
+#[test]
+fn complex_parts_without_style_wrappers() -> Result<()> {
+ // Access8Math removes mstyle wrappers; split Re and Im still denote functions of z.
+ let expr = "";
+ test("ru", "ClearSpeak", expr, "а равно действительная часть от зэт запятая, бэ равно мнимая часть от зэт")?;
+ test("ru", "SimpleSpeak", expr, "а равно действительная часть от зэт запятая, бэ равно мнимая часть от зэт")
+}
+
+#[test]
+fn complex_parts_lowercase() -> Result<()> {
+ // Lowercase re/im must be recognized just like Re/Im, without an explicit apply operator.
+ let expr = "";
+ test("ru", "ClearSpeak", expr, "действительная часть от зэт запятая, мнимая часть от зэт")?;
+ test("ru", "SimpleSpeak", expr, "действительная часть от зэт запятая, мнимая часть от зэт")
+}
+
#[test]
fn imaginary_part_name() -> Result<()> {
// The imaginary part is a real component of a complex number, not a "complex part".
@@ -135,6 +234,139 @@ fn intent_prob_x() -> Result<()> {
x
P
";
- test("ru", "ClearSpeak", expr, "probability от икс")?;
+ // An indirectly referenced W3C name keeps its Russian noun grammar in every speech mode.
+ all_russian_speech_modes(expr, "вероятность икс")?;
return Ok(());
}
+
+// Reviewed W3C names and argument-grammar regressions.
+#[test]
+fn w3c_core_translations() -> Result<()> {
+ // Each previously missing core name has a reviewed speech contract in both styles and all verbosities.
+ // Inventory source: https://w3c.github.io/mathml-docs/intent-core-concepts/ (reviewed 2026-10-30).
+ let mut count=0;
+ for line in include_str!("w3c_core_expected.tsv").lines().skip(1) {
+ let fields: Vec<_>=line.splitn(4,'\t').collect();
+ let name=fields[0];
+ let arity: usize=fields[1].parse()?;
+ let references=(0..arity).map(|i|format!("$a{i}")).collect::>().join(",");
+ let children=(0..arity).map(|i|format!("{}",['x','y','z','n'][i%4])).collect::();
+ let mathml=if arity==0 {format!("")} else {format!("")};
+ for style in ["ClearSpeak", "SimpleSpeak"] {
+ for verbosity in ["Terse", "Medium", "Verbose"] {
+ // Existing generic function speech omits 'от' in terse mode.
+ let expected=if verbosity=="Terse" {fields[2]} else {fields[3]};
+ test_prefs("ru",style,vec![("Verbosity",verbosity),("IntentErrorRecovery","Error")],&mathml,expected)?;
+ }
+ }
+ count+=1;
+ }
+ assert_eq!(count,169,"The audited core inventory must not silently lose cases");
+ Ok(())
+}
+
+#[test]
+fn w3c_logarithm_argument_and_base() -> Result<()> {
+ // W3C orders arguments as value, base; Russian speech says 'по основанию base от value'.
+ all_russian_speech_modes("","логарифм по основанию 2 от 8")?;
+ for style in ["ClearSpeak", "SimpleSpeak"] {
+ for verbosity in ["Terse", "Medium", "Verbose"] {
+ let expected=if verbosity=="Terse" {"логарифм 8"} else {"логарифм от 8"};
+ test_prefs("ru",style,vec![("Verbosity",verbosity)],"",expected)?;
+ }
+ }
+ Ok(())
+}
+
+#[test]
+fn w3c_sum_arities() -> Result<()> {
+ // Domain/bound arguments precede the summand in the two- and three-argument W3C forms.
+ all_russian_speech_modes("","сумма 2")?;
+ all_russian_speech_modes("","сумма по 2 выражения 3")?;
+ all_russian_speech_modes("","сумма от 2 до 3 выражения 5")
+}
+
+#[test]
+fn w3c_product_arities() -> Result<()> {
+ // The last argument is the factor expression, never an upper bound or an extra factor.
+ all_russian_speech_modes("","произведение 2")?;
+ all_russian_speech_modes("","произведение по 2 выражения 3")?;
+ all_russian_speech_modes("","произведение от 2 до 3 выражения 5")
+}
+
+#[test]
+fn w3c_partial_derivative_mixed_orders() -> Result<()> {
+ // Every variable stays paired with its own order, including an implicit first-order variable.
+ all_russian_speech_modes("","частная производная эф по икс порядка 2 и по игрек")?;
+ all_russian_speech_modes("","частная производная эф по икс порядка эн и по игрек порядка 3")
+}
+
+#[test]
+fn w3c_variadic_lists_and_coordinates() -> Result<()> {
+ // Every entry/coordinate of a longer list must be spoken once; arity-zero names are in the inventory test.
+ all_russian_speech_modes("","список 1 запятая 2 запятая 3")?;
+ all_russian_speech_modes("","кортеж 1 запятая 2 запятая 3")?;
+ all_russian_speech_modes("","декартовы координаты 1 запятая 2 запятая 3 запятая 4")
+}
+
+#[test]
+fn w3c_variadic_extrema() -> Result<()> {
+ // max/min accept more than one value and must not drop the final value.
+ all_russian_speech_modes("","максимум из 1 запятая 2 запятая 3")?;
+ all_russian_speech_modes("","минимум из 1 запятая 2 запятая 3")
+}
+
+#[test]
+fn w3c_nested_noun_cases() -> Result<()> {
+ // Nested noun heads take genitive forms, in either order of old and newly supported concepts.
+ all_russian_speech_modes("","мощность образа заглавной эр")?;
+ all_russian_speech_modes("","образ мощности заглавной эр")?;
+ all_russian_speech_modes("","среднее списка 1 запятая 2 запятая 3")
+}
+
+#[test]
+fn w3c_division_and_condition_argument_order() -> Result<()> {
+ // Non-symmetric numeric operands expose accidental reversal of dividend/divisor or event/condition.
+ all_russian_speech_modes("","целая часть результата деления 7 на 3")?;
+ all_russian_speech_modes("","остаток от деления 7 на 3")?;
+ all_russian_speech_modes("","отношение 7 к 3")?;
+ all_russian_speech_modes("","вероятность 7 при условии 3")
+}
+
+#[test]
+fn w3c_relation_and_operation_cases() -> Result<()> {
+ // Check grammatical words independently of automatically generated pauses.
+ for style in ["ClearSpeak","SimpleSpeak"] {
+ for (name,operator,expected) in [
+ ("equals","=","заглавная ку равно заглавной эр"),
+ ("element-of","∈","заглавная ку принадлежит заглавной эр"),
+ ("times","×","заглавная ку умножить на заглавную эр"),
+ ("implies","⇒","заглавная ку влечёт заглавную эр"),
+ ] {
+ let mathml=format!("");
+ init_nav("ru",&mathml)?;
+ set_preference("SpeechStyle",style)?;
+ set_preference("SpeechOverrides_CapitalLetters","")?;
+ set_preference("Impairment","Blindness")?;
+ let actual=get_spoken_text()?.replace([',',';'],"").split_whitespace().collect::>().join(" ");
+ assert_eq!(actual,expected,"{style}/{name}");
+ }
+ }
+ Ok(())
+}
+
+#[test]
+fn w3c_read_named_logarithm_and_relation() -> Result<()> {
+ // Semantic ReadCurrent must retain both argument order and Russian relation wording.
+ for style in ["ClearSpeak","SimpleSpeak"] {
+ init_nav("ru","")?;
+ set_preference("SpeechStyle",style)?;
+ let speech=do_navigate_command("ReadCurrent")?.split_whitespace().collect::>().join(" ");
+ assert!(speech.contains("логарифм по основанию 2 от 8"),"{style}: {speech}");
+ init_nav("ru","")?;
+ set_preference("SpeechStyle",style)?;
+ let speech=do_navigate_command("ReadCurrent")?.split_whitespace().collect::>().join(" ");
+ assert!(speech.contains("2 равно 3"),"{style}: {speech}");
+ }
+ Ok(())
+}
diff --git a/tests/Languages/ru/navigate.rs b/tests/Languages/ru/navigate.rs
index 1d83e6dc7..74ff26e0b 100644
--- a/tests/Languages/ru/navigate.rs
+++ b/tests/Languages/ru/navigate.rs
@@ -17,6 +17,42 @@ fn overview_modes(expr: &str, expected: [&str; 3]) -> Result<()> {
Ok(())
}
+#[test]
+fn read_function_set_intents() -> Result<()> {
+ // Semantic modes read the explicit image intent; Character mode keeps its literal notation.
+ for style in ["ClearSpeak", "SimpleSpeak"] {
+ for mode in ["Enhanced", "Simple", "Character"] {
+ init_nav("ru", "")?;
+ set_preference("SpeechStyle", style)?;
+ set_preference("NavMode", mode)?;
+ let speech = do_navigate_command("ReadCurrent")?.split_whitespace().collect::>().join(" ");
+ let expected = if mode == "Character" {"Im заглавной эр"} else {"образ заглавной эр"};
+ assert!(speech.contains(expected), "{style}/{mode}: {speech}");
+ }
+ }
+ Ok(())
+}
+
+#[test]
+fn read_w3c_point_and_pochhammer() -> Result<()> {
+ // Semantic navigation must retain all coordinates and the asymmetric permutation arguments.
+ for style in ["ClearSpeak", "SimpleSpeak"] {
+ for mode in ["Enhanced", "Simple"] {
+ init_nav("ru", "")?;
+ set_preference("SpeechStyle", style)?;
+ set_preference("NavMode", mode)?;
+ let speech=do_navigate_command("ReadCurrent")?.split_whitespace().collect::>().join(" ");
+ assert!(speech.contains("точка 1 запятая 2 запятая 3"), "{style}/{mode}: {speech}");
+ init_nav("ru", "")?;
+ set_preference("SpeechStyle", style)?;
+ set_preference("NavMode", mode)?;
+ let speech=do_navigate_command("ReadCurrent")?.split_whitespace().collect::>().join(" ");
+ assert!(speech.contains("число размещений из 5 по 2"), "{style}/{mode}: {speech}");
+ }
+ }
+ Ok(())
+}
+
#[test]
fn overview_labeled_table() -> Result<()> {
// A row label is not a data column; both rows have two data cells.
From 84ae872b0ff454b41f77ae22ad0ad5089250d5f8 Mon Sep 17 00:00:00 2001
From: Danil <81031453+Kostenkov-2021@users.noreply.github.com>
Date: Fri, 30 Oct 2026 12:18:25 +0300
Subject: [PATCH 2/3] Expand Russian W3C intent speech tests
Replace the TSV-driven core intent test with per-concept regression tests covering ClearSpeak and SimpleSpeak across all verbosity levels. Add separate terse and normal expectations for function speech.
---
tests/Languages/ru/intent.rs | 1208 +++++++++++++++++++++++++++++++++-
1 file changed, 1186 insertions(+), 22 deletions(-)
diff --git a/tests/Languages/ru/intent.rs b/tests/Languages/ru/intent.rs
index 93be30d2e..9b1f28bef 100644
--- a/tests/Languages/ru/intent.rs
+++ b/tests/Languages/ru/intent.rs
@@ -5,8 +5,13 @@ use crate::common::*;
use anyhow::Result;
fn all_russian_speech_modes(expr: &str, expected: &str) -> Result<()> {
+ russian_speech_verbosities(expr, expected, expected)
+}
+
+fn russian_speech_verbosities(expr: &str, terse: &str, normal: &str) -> Result<()> {
for style in ["ClearSpeak", "SimpleSpeak"] {
for verbosity in ["Terse", "Medium", "Verbose"] {
+ let expected = if verbosity == "Terse" { terse } else { normal };
test_prefs("ru", style, vec![("Verbosity", verbosity), ("IntentErrorRecovery", "Error")], expr, expected)?;
}
}
@@ -240,29 +245,1188 @@ fn intent_prob_x() -> Result<()> {
}
// Reviewed W3C names and argument-grammar regressions.
+// W3C Core Concept List, reviewed 2026-10-30: https://w3c.github.io/mathml-docs/intent-core-concepts/
#[test]
-fn w3c_core_translations() -> Result<()> {
- // Each previously missing core name has a reviewed speech contract in both styles and all verbosities.
- // Inventory source: https://w3c.github.io/mathml-docs/intent-core-concepts/ (reviewed 2026-10-30).
- let mut count=0;
- for line in include_str!("w3c_core_expected.tsv").lines().skip(1) {
- let fields: Vec<_>=line.splitn(4,'\t').collect();
- let name=fields[0];
- let arity: usize=fields[1].parse()?;
- let references=(0..arity).map(|i|format!("$a{i}")).collect::>().join(",");
- let children=(0..arity).map(|i|format!("{}",['x','y','z','n'][i%4])).collect::();
- let mathml=if arity==0 {format!("")} else {format!("")};
- for style in ["ClearSpeak", "SimpleSpeak"] {
- for verbosity in ["Terse", "Medium", "Verbose"] {
- // Existing generic function speech omits 'от' in terse mode.
- let expected=if verbosity=="Terse" {fields[2]} else {fields[3]};
- test_prefs("ru",style,vec![("Verbosity",verbosity),("IntentErrorRecovery","Error")],&mathml,expected)?;
- }
- }
- count+=1;
- }
- assert_eq!(count,169,"The audited core inventory must not silently lose cases");
- Ok(())
+fn w3c_core_adjugate() -> Result<()> {
+ // W3C adjugate: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "присоединённая матрица икс")
+}
+
+#[test]
+fn w3c_core_and() -> Result<()> {
+ // W3C and: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс и игрек")
+}
+
+#[test]
+fn w3c_core_angle() -> Result<()> {
+ // W3C angle: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "угол икс")
+}
+
+#[test]
+fn w3c_core_angle_measure() -> Result<()> {
+ // W3C angle-measure: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "мера угла икс")
+}
+
+#[test]
+fn w3c_core_annotation() -> Result<()> {
+ // W3C annotation: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс с пояснением, игрек")
+}
+
+#[test]
+fn w3c_core_applied_to() -> Result<()> {
+ // W3C applied-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс от игрек")
+}
+
+#[test]
+fn w3c_core_approximately() -> Result<()> {
+ // W3C approximately: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс приблизительно равно, игрек")
+}
+
+#[test]
+fn w3c_core_arc_hyperbolic_cosecant() -> Result<()> {
+ // W3C arc-hyperbolic-cosecant: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "обратная функция гиперболического косеканса икс", "обратная функция гиперболического косеканса от икс")
+}
+
+#[test]
+fn w3c_core_arc_hyperbolic_cosine() -> Result<()> {
+ // W3C arc-hyperbolic-cosine: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "обратная функция гиперболического косинуса икс", "обратная функция гиперболического косинуса от икс")
+}
+
+#[test]
+fn w3c_core_arc_hyperbolic_cotangent() -> Result<()> {
+ // W3C arc-hyperbolic-cotangent: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "обратная функция гиперболического котангенса икс", "обратная функция гиперболического котангенса от икс")
+}
+
+#[test]
+fn w3c_core_arc_hyperbolic_secant() -> Result<()> {
+ // W3C arc-hyperbolic-secant: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "обратная функция гиперболического секанса икс", "обратная функция гиперболического секанса от икс")
+}
+
+#[test]
+fn w3c_core_arc_hyperbolic_sine() -> Result<()> {
+ // W3C arc-hyperbolic-sine: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "обратная функция гиперболического синуса икс", "обратная функция гиперболического синуса от икс")
+}
+
+#[test]
+fn w3c_core_arc_hyperbolic_tangent() -> Result<()> {
+ // W3C arc-hyperbolic-tangent: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "обратная функция гиперболического тангенса икс", "обратная функция гиперболического тангенса от икс")
+}
+
+#[test]
+fn w3c_core_arccosecant() -> Result<()> {
+ // W3C arccosecant: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "арккосеканс икс", "арккосеканс от икс")
+}
+
+#[test]
+fn w3c_core_arccosine() -> Result<()> {
+ // W3C arccosine: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "арккосинус икс", "арккосинус от икс")
+}
+
+#[test]
+fn w3c_core_arccotangent() -> Result<()> {
+ // W3C arccotangent: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "арккотангенс икс", "арккотангенс от икс")
+}
+
+#[test]
+fn w3c_core_arcsecant() -> Result<()> {
+ // W3C arcsecant: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "арксеканс икс", "арксеканс от икс")
+}
+
+#[test]
+fn w3c_core_arcsine() -> Result<()> {
+ // W3C arcsine: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "арксинус икс", "арксинус от икс")
+}
+
+#[test]
+fn w3c_core_arctangent() -> Result<()> {
+ // W3C arctangent: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "арктангенс икс", "арктангенс от икс")
+}
+
+#[test]
+fn w3c_core_area() -> Result<()> {
+ // W3C area: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "площадь икс")
+}
+
+#[test]
+fn w3c_core_binomial_coefficient() -> Result<()> {
+ // W3C binomial-coefficient: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "число сочетаний из икс по игрек")
+}
+
+#[test]
+fn w3c_core_braced_group() -> Result<()> {
+ // W3C braced-group: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "группа икс")
+}
+
+#[test]
+fn w3c_core_cardinality() -> Result<()> {
+ // W3C cardinality: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "мощность икс")
+}
+
+#[test]
+fn w3c_core_cartesian_coordinate() -> Result<()> {
+ // W3C cartesian-coordinate: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "декартовы координаты икс запятая игрек")
+}
+
+#[test]
+fn w3c_core_cartesian_product() -> Result<()> {
+ // W3C cartesian-product: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс декартово произведение; игрек")
+}
+
+#[test]
+fn w3c_core_ceiling() -> Result<()> {
+ // W3C ceiling: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "округление вверх икс")
+}
+
+#[test]
+fn w3c_core_change() -> Result<()> {
+ // W3C change: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "изменение икс")
+}
+
+#[test]
+fn w3c_core_complement() -> Result<()> {
+ // W3C complement: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "дополнение икс")
+}
+
+#[test]
+fn w3c_core_complex_arg() -> Result<()> {
+ // W3C complex-arg: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "аргумент икс")
+}
+
+#[test]
+fn w3c_core_complex_conjugate() -> Result<()> {
+ // W3C complex-conjugate: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "комплексное сопряжение икс")
+}
+
+#[test]
+fn w3c_core_composed_with() -> Result<()> {
+ // W3C composed-with: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс композиция с, игрек")
+}
+
+#[test]
+fn w3c_core_conditional_probability() -> Result<()> {
+ // W3C conditional-probability: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "вероятность икс при условии игрек")
+}
+
+#[test]
+fn w3c_core_congruent() -> Result<()> {
+ // W3C congruent: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс конгруэнтно, игрек")
+}
+
+#[test]
+fn w3c_core_constraint() -> Result<()> {
+ // W3C constraint: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс при условии, игрек")
+}
+
+#[test]
+fn w3c_core_cosecant() -> Result<()> {
+ // W3C cosecant: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "косеканс икс", "косеканс от икс")
+}
+
+#[test]
+fn w3c_core_cosine() -> Result<()> {
+ // W3C cosine: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "косинус икс", "косинус от икс")
+}
+
+#[test]
+fn w3c_core_cotangent() -> Result<()> {
+ // W3C cotangent: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "котангенс икс", "котангенс от икс")
+}
+
+#[test]
+fn w3c_core_defined_as() -> Result<()> {
+ // W3C defined-as: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс определяется как, игрек")
+}
+
+#[test]
+fn w3c_core_diameter() -> Result<()> {
+ // W3C diameter: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "диаметр икс")
+}
+
+#[test]
+fn w3c_core_differential_d() -> Result<()> {
+ // W3C differential-d: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "дэ")
+}
+
+#[test]
+fn w3c_core_dimensional_product() -> Result<()> {
+ // W3C dimensional-product: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс на игрек")
+}
+
+#[test]
+fn w3c_core_direct_product() -> Result<()> {
+ // W3C direct-product: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс прямое произведение, игрек")
+}
+
+#[test]
+fn w3c_core_directed_line_segment() -> Result<()> {
+ // W3C directed-line-segment: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "направленный отрезок икс игрек")
+}
+
+#[test]
+fn w3c_core_distance() -> Result<()> {
+ // W3C distance: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "расстояние икс")
+}
+
+#[test]
+fn w3c_core_divided_by() -> Result<()> {
+ // W3C divided-by: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс разделить на, игрек")
+}
+
+#[test]
+fn w3c_core_divides() -> Result<()> {
+ // W3C divides: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс делит игрек")
+}
+
+#[test]
+fn w3c_core_does_not_belong_to() -> Result<()> {
+ // W3C does-not-belong-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс не принадлежит, игрек")
+}
+
+#[test]
+fn w3c_core_does_not_divide() -> Result<()> {
+ // W3C does-not-divide: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс не делит игрек")
+}
+
+#[test]
+fn w3c_core_downwards_diagonal_ellipsis() -> Result<()> {
+ // W3C downwards-diagonal-ellipsis: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс диагональное многоточие вниз; игрек")
+}
+
+#[test]
+fn w3c_core_element_of() -> Result<()> {
+ // W3C element-of: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс принадлежит, игрек")
+}
+
+#[test]
+fn w3c_core_ellipsis() -> Result<()> {
+ // W3C ellipsis: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс многоточие, игрек")
+}
+
+#[test]
+fn w3c_core_embellished_name() -> Result<()> {
+ // W3C embellished-name: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс с обозначением, игрек")
+}
+
+#[test]
+fn w3c_core_empty_set() -> Result<()> {
+ // W3C empty-set: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "пустое множество")
+}
+
+#[test]
+fn w3c_core_equals() -> Result<()> {
+ // W3C equals: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс равно игрек")
+}
+
+#[test]
+fn w3c_core_equivalent_to() -> Result<()> {
+ // W3C equivalent-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс эквивалентно, игрек")
+}
+
+#[test]
+fn w3c_core_evaluated_at() -> Result<()> {
+ // W3C evaluated-at: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс вычисленное при, игрек")
+}
+
+#[test]
+fn w3c_core_evaluates_to() -> Result<()> {
+ // W3C evaluates-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс вычисляется как, игрек")
+}
+
+#[test]
+fn w3c_core_exponential() -> Result<()> {
+ // W3C exponential: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "экспонента икс", "экспонента от икс")
+}
+
+#[test]
+fn w3c_core_exponential_e() -> Result<()> {
+ // W3C exponential-e: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "число е")
+}
+
+#[test]
+fn w3c_core_factorial() -> Result<()> {
+ // W3C factorial: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс факториал")
+}
+
+#[test]
+fn w3c_core_fenced_group() -> Result<()> {
+ // W3C fenced-group: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "выражение в скобках икс")
+}
+
+#[test]
+fn w3c_core_floor() -> Result<()> {
+ // W3C floor: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "округление вниз икс")
+}
+
+#[test]
+fn w3c_core_for_all() -> Result<()> {
+ // W3C for-all: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "для всех икс")
+}
+
+#[test]
+fn w3c_core_fractional_part() -> Result<()> {
+ // W3C fractional-part: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "дробная часть икс")
+}
+
+#[test]
+fn w3c_core_given() -> Result<()> {
+ // W3C given: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс при условии, игрек")
+}
+
+#[test]
+fn w3c_core_golden_ratio() -> Result<()> {
+ // W3C golden-ratio: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "золотое сечение")
+}
+
+#[test]
+fn w3c_core_greater_than() -> Result<()> {
+ // W3C greater-than: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс больше игрек")
+}
+
+#[test]
+fn w3c_core_greater_than_or_equal_to() -> Result<()> {
+ // W3C greater-than-or-equal-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс больше или равно, игрек")
+}
+
+#[test]
+fn w3c_core_highlight() -> Result<()> {
+ // W3C highlight: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс выделено")
+}
+
+#[test]
+fn w3c_core_hyperbolic_cosecant() -> Result<()> {
+ // W3C hyperbolic-cosecant: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "гиперболический косеканс икс", "гиперболический косеканс от икс")
+}
+
+#[test]
+fn w3c_core_hyperbolic_cosine() -> Result<()> {
+ // W3C hyperbolic-cosine: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "гиперболический косинус икс", "гиперболический косинус от икс")
+}
+
+#[test]
+fn w3c_core_hyperbolic_cotangent() -> Result<()> {
+ // W3C hyperbolic-cotangent: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "гиперболический котангенс икс", "гиперболический котангенс от икс")
+}
+
+#[test]
+fn w3c_core_hyperbolic_secant() -> Result<()> {
+ // W3C hyperbolic-secant: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "гиперболический секанс икс", "гиперболический секанс от икс")
+}
+
+#[test]
+fn w3c_core_hyperbolic_sine() -> Result<()> {
+ // W3C hyperbolic-sine: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "гиперболический синус икс", "гиперболический синус от икс")
+}
+
+#[test]
+fn w3c_core_hyperbolic_tangent() -> Result<()> {
+ // W3C hyperbolic-tangent: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "гиперболический тангенс икс", "гиперболический тангенс от икс")
+}
+
+#[test]
+fn w3c_core_identically_equals() -> Result<()> {
+ // W3C identically-equals: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс тождественно равно, игрек")
+}
+
+#[test]
+fn w3c_core_identity_matrix() -> Result<()> {
+ // W3C identity-matrix: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "единичная матрица")
+}
+
+#[test]
+fn w3c_core_if_and_only_if() -> Result<()> {
+ // W3C if-and-only-if: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс тогда и только тогда когда; игрек")
+}
+
+#[test]
+fn w3c_core_imaginary_i() -> Result<()> {
+ // W3C imaginary-i: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "мнимая единица")
+}
+
+#[test]
+fn w3c_core_implies() -> Result<()> {
+ // W3C implies: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс влечёт игрек")
+}
+
+#[test]
+fn w3c_core_inner_product() -> Result<()> {
+ // W3C inner-product: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс скалярное произведение; игрек")
+}
+
+#[test]
+fn w3c_core_intersection() -> Result<()> {
+ // W3C intersection: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс пересечение, игрек")
+}
+
+#[test]
+fn w3c_core_inverse() -> Result<()> {
+ // W3C inverse: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "обратный к икс")
+}
+
+#[test]
+fn w3c_core_least_common_denominator() -> Result<()> {
+ // W3C least-common-denominator: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "наименьший общий знаменатель икс и игрек")
+}
+
+#[test]
+fn w3c_core_length() -> Result<()> {
+ // W3C length: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "длина икс")
+}
+
+#[test]
+fn w3c_core_less_than() -> Result<()> {
+ // W3C less-than: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс меньше игрек")
+}
+
+#[test]
+fn w3c_core_less_than_or_equal_to() -> Result<()> {
+ // W3C less-than-or-equal-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс меньше или равно, игрек")
+}
+
+#[test]
+fn w3c_core_line() -> Result<()> {
+ // W3C line: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "прямая икс игрек")
+}
+
+#[test]
+fn w3c_core_list() -> Result<()> {
+ // W3C list: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "список")
+}
+
+#[test]
+fn w3c_core_list_separator() -> Result<()> {
+ // W3C list-separator: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс запятая игрек")
+}
+
+#[test]
+fn w3c_core_logarithm() -> Result<()> {
+ // W3C logarithm: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "логарифм по основанию игрек от икс")
+}
+
+#[test]
+fn w3c_core_maps_to() -> Result<()> {
+ // W3C maps-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс отображается в, игрек")
+}
+
+#[test]
+fn w3c_core_max() -> Result<()> {
+ // W3C max: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "максимум икс")
+}
+
+#[test]
+fn w3c_core_mean() -> Result<()> {
+ // W3C mean: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "среднее икс")
+}
+
+#[test]
+fn w3c_core_measured_angle() -> Result<()> {
+ // W3C measured-angle: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "измеренный угол икс")
+}
+
+#[test]
+fn w3c_core_median() -> Result<()> {
+ // W3C median: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "медиана икс")
+}
+
+#[test]
+fn w3c_core_member_of() -> Result<()> {
+ // W3C member-of: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс принадлежит, игрек")
+}
+
+#[test]
+fn w3c_core_min() -> Result<()> {
+ // W3C min: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "минимум икс")
+}
+
+#[test]
+fn w3c_core_minus_or_plus() -> Result<()> {
+ // W3C minus-or-plus: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс минус плюс, игрек")
+}
+
+#[test]
+fn w3c_core_mixed_fraction() -> Result<()> {
+ // W3C mixed-fraction: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс и игрек")
+}
+
+#[test]
+fn w3c_core_mode() -> Result<()> {
+ // W3C mode: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "мода икс")
+}
+
+#[test]
+fn w3c_core_not() -> Result<()> {
+ // W3C not: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "не икс")
+}
+
+#[test]
+fn w3c_core_not_equal_to() -> Result<()> {
+ // W3C not-equal-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс не равно игрек")
+}
+
+#[test]
+fn w3c_core_not_member_of() -> Result<()> {
+ // W3C not-member-of: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс не принадлежит, игрек")
+}
+
+#[test]
+fn w3c_core_not_parallel_to() -> Result<()> {
+ // W3C not-parallel-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс не параллельно, игрек")
+}
+
+#[test]
+fn w3c_core_not_subset() -> Result<()> {
+ // W3C not-subset: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс не является подмножеством; игрек")
+}
+
+#[test]
+fn w3c_core_not_superset() -> Result<()> {
+ // W3C not-superset: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс не является надмножеством; игрек")
+}
+
+#[test]
+fn w3c_core_number_of() -> Result<()> {
+ // W3C number-of: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "число икс")
+}
+
+#[test]
+fn w3c_core_obtained_from() -> Result<()> {
+ // W3C obtained-from: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс получено из, игрек")
+}
+
+#[test]
+fn w3c_core_or() -> Result<()> {
+ // W3C or: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс или игрек")
+}
+
+#[test]
+fn w3c_core_ordered_pair() -> Result<()> {
+ // W3C ordered-pair: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "упорядоченная пара икс и игрек")
+}
+
+#[test]
+fn w3c_core_outer_product() -> Result<()> {
+ // W3C outer-product: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс внешнее произведение, игрек")
+}
+
+#[test]
+fn w3c_core_parallel_to() -> Result<()> {
+ // W3C parallel-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс параллельно, игрек")
+}
+
+#[test]
+fn w3c_core_partial_derivative() -> Result<()> {
+ // W3C partial-derivative: localizes the concept and retains all 3 arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "частная производная икс по игрек порядка зэт")
+}
+
+#[test]
+fn w3c_core_percent() -> Result<()> {
+ // W3C percent: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс процентов")
+}
+
+#[test]
+fn w3c_core_permutation_cycle() -> Result<()> {
+ // W3C permutation-cycle: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "цикл перестановки икс запятая игрек")
+}
+
+#[test]
+fn w3c_core_plus_or_minus() -> Result<()> {
+ // W3C plus-or-minus: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс плюс минус, игрек")
+}
+
+#[test]
+fn w3c_core_polar_coordinate() -> Result<()> {
+ // W3C polar-coordinate: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "полярные координаты икс запятая игрек")
+}
+
+#[test]
+fn w3c_core_precedes() -> Result<()> {
+ // W3C precedes: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс предшествует, игрек")
+}
+
+#[test]
+fn w3c_core_probability() -> Result<()> {
+ // W3C probability: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "вероятность икс")
+}
+
+#[test]
+fn w3c_core_product() -> Result<()> {
+ // W3C product: localizes the concept and retains all 3 arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "произведение от икс до игрек выражения зэт")
+}
+
+#[test]
+fn w3c_core_proportional() -> Result<()> {
+ // W3C proportional: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс пропорционально, игрек")
+}
+
+#[test]
+fn w3c_core_quotient() -> Result<()> {
+ // W3C quotient: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "целая часть результата деления икс на игрек")
+}
+
+#[test]
+fn w3c_core_radius() -> Result<()> {
+ // W3C radius: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "радиус икс")
+}
+
+#[test]
+fn w3c_core_range_separator() -> Result<()> {
+ // W3C range-separator: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс до игрек")
+}
+
+#[test]
+fn w3c_core_rate() -> Result<()> {
+ // W3C rate: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс на игрек")
+}
+
+#[test]
+fn w3c_core_ratio() -> Result<()> {
+ // W3C ratio: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "отношение икс к игрек")
+}
+
+#[test]
+fn w3c_core_remainder() -> Result<()> {
+ // W3C remainder: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "остаток от деления икс на игрек")
+}
+
+#[test]
+fn w3c_core_right_angle() -> Result<()> {
+ // W3C right-angle: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "прямой угол икс")
+}
+
+#[test]
+fn w3c_core_round() -> Result<()> {
+ // W3C round: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "округлённое значение икс")
+}
+
+#[test]
+fn w3c_core_secant() -> Result<()> {
+ // W3C secant: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "секанс икс", "секанс от икс")
+}
+
+#[test]
+fn w3c_core_set_difference() -> Result<()> {
+ // W3C set-difference: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "разность множеств икс и игрек")
+}
+
+#[test]
+fn w3c_core_set_of_complex_numbers() -> Result<()> {
+ // W3C set-of-complex-numbers: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "комплексные числа")
+}
+
+#[test]
+fn w3c_core_set_of_integers() -> Result<()> {
+ // W3C set-of-integers: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "целые числа")
+}
+
+#[test]
+fn w3c_core_set_of_natural_numbers() -> Result<()> {
+ // W3C set-of-natural-numbers: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "натуральные числа")
+}
+
+#[test]
+fn w3c_core_set_of_primes() -> Result<()> {
+ // W3C set-of-primes: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "простые числа")
+}
+
+#[test]
+fn w3c_core_set_of_rationals() -> Result<()> {
+ // W3C set-of-rationals: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "рациональные числа")
+}
+
+#[test]
+fn w3c_core_set_of_reals() -> Result<()> {
+ // W3C set-of-reals: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "действительные числа")
+}
+
+#[test]
+fn w3c_core_similar() -> Result<()> {
+ // W3C similar: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс подобно игрек")
+}
+
+#[test]
+fn w3c_core_sine() -> Result<()> {
+ // W3C sine: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "синус икс", "синус от икс")
+}
+
+#[test]
+fn w3c_core_span() -> Result<()> {
+ // W3C span: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "линейная оболочка икс")
+}
+
+#[test]
+fn w3c_core_spherical_coordinate() -> Result<()> {
+ // W3C spherical-coordinate: localizes the concept and retains all 3 arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "сферические координаты икс запятая игрек запятая зэт")
+}
+
+#[test]
+fn w3c_core_square_root_of() -> Result<()> {
+ // W3C square-root-of: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "квадратный корень из икс")
+}
+
+#[test]
+fn w3c_core_standard_deviation() -> Result<()> {
+ // W3C standard-deviation: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "стандартное отклонение икс")
+}
+
+#[test]
+fn w3c_core_subset() -> Result<()> {
+ // W3C subset: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс является подмножеством; игрек")
+}
+
+#[test]
+fn w3c_core_subset_or_equal() -> Result<()> {
+ // W3C subset-or-equal: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс является подмножеством или равно; игрек")
+}
+
+#[test]
+fn w3c_core_succeeds() -> Result<()> {
+ // W3C succeeds: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс следует за, игрек")
+}
+
+#[test]
+fn w3c_core_such_that() -> Result<()> {
+ // W3C such-that: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс таких что игрек")
+}
+
+#[test]
+fn w3c_core_sum() -> Result<()> {
+ // W3C sum: localizes the concept and retains all 3 arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "сумма от икс до игрек выражения зэт")
+}
+
+#[test]
+fn w3c_core_superset() -> Result<()> {
+ // W3C superset: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс является надмножеством; игрек")
+}
+
+#[test]
+fn w3c_core_superset_or_equal() -> Result<()> {
+ // W3C superset-or-equal: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс является надмножеством или равно; игрек")
+}
+
+#[test]
+fn w3c_core_tangent() -> Result<()> {
+ // W3C tangent: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ russian_speech_verbosities(expr, "тангенс икс", "тангенс от икс")
+}
+
+#[test]
+fn w3c_core_tends_to() -> Result<()> {
+ // W3C tends-to: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс стремится к, игрек")
+}
+
+#[test]
+fn w3c_core_tends_to_from_above() -> Result<()> {
+ // W3C tends-to-from-above: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс стремится сверху к, игрек")
+}
+
+#[test]
+fn w3c_core_tends_to_from_below() -> Result<()> {
+ // W3C tends-to-from-below: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс стремится снизу к, игрек")
+}
+
+#[test]
+fn w3c_core_there_does_not_exist() -> Result<()> {
+ // W3C there-does-not-exist: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "не существует икс")
+}
+
+#[test]
+fn w3c_core_there_exists() -> Result<()> {
+ // W3C there-exists: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "существует икс")
+}
+
+#[test]
+fn w3c_core_tilde() -> Result<()> {
+ // W3C tilde: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс тильда игрек")
+}
+
+#[test]
+fn w3c_core_time_separator() -> Result<()> {
+ // W3C time-separator: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс игрек")
+}
+
+#[test]
+fn w3c_core_times() -> Result<()> {
+ // W3C times: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс умножить на, игрек")
+}
+
+#[test]
+fn w3c_core_translation() -> Result<()> {
+ // W3C translation: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "перенос на икс запятая игрек")
+}
+
+#[test]
+fn w3c_core_tuple() -> Result<()> {
+ // W3C tuple: localizes the standalone concept name, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "кортеж")
+}
+
+#[test]
+fn w3c_core_union() -> Result<()> {
+ // W3C union: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс объединение, игрек")
+}
+
+#[test]
+fn w3c_core_unit_vector() -> Result<()> {
+ // W3C unit-vector: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "единичный вектор икс")
+}
+
+#[test]
+fn w3c_core_upwards_diagonal_ellipsis() -> Result<()> {
+ // W3C upwards-diagonal-ellipsis: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс диагональное многоточие вверх; игрек")
+}
+
+#[test]
+fn w3c_core_variance() -> Result<()> {
+ // W3C variance: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "дисперсия икс")
+}
+
+#[test]
+fn w3c_core_vertical_ellipsis() -> Result<()> {
+ // W3C vertical-ellipsis: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс вертикальное многоточие; игрек")
+}
+
+#[test]
+fn w3c_core_volume() -> Result<()> {
+ // W3C volume: localizes the concept and retains its argument, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "объём икс")
+}
+
+#[test]
+fn w3c_core_xor() -> Result<()> {
+ // W3C xor: localizes the concept and retains both arguments, in both styles and all verbosities.
+ let expr = "";
+ all_russian_speech_modes(expr, "икс исключающее или, игрек")
}
#[test]
From b5099c325646f38a9841d9673451f59cf9b7bb5e Mon Sep 17 00:00:00 2001
From: Danil <81031453+Kostenkov-2021@users.noreply.github.com>
Date: Mon, 2 Nov 2026 02:03:46 +0300
Subject: [PATCH 3/3] Remove duplicate Russian intent definitions
Comment out Russian mappings now handled by shared or mode-specific speech rules, while retaining the Pochhammer function mapping needed for fixity.
---
Rules/Languages/ru/definitions.yaml | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/Rules/Languages/ru/definitions.yaml b/Rules/Languages/ru/definitions.yaml
index 3daac3335..d9ab453f8 100644
--- a/Rules/Languages/ru/definitions.yaml
+++ b/Rules/Languages/ru/definitions.yaml
@@ -222,7 +222,8 @@
"ordered-pair": "function=упорядоченная пара: и",
"outer-product": "infix=внешнее произведение",
"parallel-to": "infix=параллельно",
- "partial-derivative": "other=частная производная",
+ # Speech rules defined elsewhere: SharedRules/calculus.yaml (core-partial-derivative).
+ # "partial-derivative": "other=частная производная",
"percent": "postfix=процентов",
"permutation-cycle": "function=цикл перестановки",
"plus-or-minus": "infix=плюс минус",
@@ -278,12 +279,18 @@
"vertical-ellipsis": "infix=вертикальное многоточие",
"volume": "nofix=объём || function=объём",
"xor": "infix=исключающее или",
- "blank": "nofix=пустое место",
- "definite-integral": "other=интеграл",
- "derivative": "other=производная",
- "invisible-separator": "silent=",
- "invisible-times": "silent=",
- "point": "other=точка",
+ # Speech rules defined elsewhere: SharedRules/general.yaml (blank-intent).
+ # "blank": "nofix=пустое место",
+ # Speech rules defined elsewhere: SharedRules/calculus.yaml (definite-integral-intent, derivative-intent).
+ # "definite-integral": "other=интеграл",
+ # "derivative": "other=производная",
+ # Speech rules defined elsewhere: SharedRules/general.yaml (invisible-operator-intent).
+ # "invisible-separator": "silent=",
+ # "invisible-times": "silent=",
+ # Speech rules defined elsewhere: SharedRules/general.yaml (default-point).
+ # "point": "other=точка",
+ # Speech rules defined elsewhere: SharedRules/general.yaml (permutation).
+ # Keep this mapping to supply the default function fixity required by that rule.
"pochhammer": "function=число размещений",
"indexed-by": "infix= ; с индексом; конец индекса| с индексом| с индексом",
"modified-variable": "silent= ",
@@ -295,10 +302,17 @@
"codomain": "function=целевое множество",
"image": "function=образ",
"binomial": "infix=число сочетаний из; по; конец числа сочетаний",
+ # Speech rules for open-interval, open-closed-interval, closed-interval, and closed-open-interval
+ # are defined elsewhere: SharedRules/general.yaml (intervals, numeric-half-open-interval).
# "closed-interval": "other=closed-interval; от,до; end closed-interval",
+ # Speech rules defined elsewhere: ClearSpeak_Rules.yaml and SimpleSpeak_Rules.yaml.
+ # "fraction": "function=дробь; делить на; конец дроби",
+ # Speech rules defined elsewhere: SharedRules/general.yaml (repeating-decimal).
+ # "repeating-decimal": "function=период",
"greatest-common-divisor": "function=нод| нод| наибольший общий делитель",
"imaginary-part": "function=мнимая часть",
"least-common-multiple": "function=нок|нок|наименьшее общее кратное",
+ # Speech rules defined elsewhere: SharedRules/general.yaml (bigop-both, bigop-under).
# "large-op": "infix=над || other=от,до",
"limit": "prefix=предел при| предел при| предел при",
"lim-sup": "prefix=верхний предел при| верхний предел при| верхний предел при",