diff --git a/README.md b/README.md index 678495f1de..e028acf03b 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ cargo run --release -p gridcraft -- --sample sales --control 7979 # + JSON con cargo xtask ci # fmt, clippy, tests, assets, layering, wasm ``` -Choose Español under View → Interface language for [Spanish formula names, decimal commas, and semicolon arguments](docs/formula-input.md). +Choose Español, Deutsch, Português (Brasil) or Русский under View → Interface language for [local formula names, booleans, errors and separators](docs/formula-input.md). Workbooks, clipboard exchange, and programmatic APIs retain canonical English syntax. ### Web diff --git a/ROADMAP.md b/ROADMAP.md index e8e1c06b38..82ea7fce9e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -93,8 +93,11 @@ The ribbon is translated into Japanese, Simplified Chinese, Korean, Brazilian Po and German (266–268 labels each, ~12% of ~2,200 strings; merged 10-10 in #31, #104, #82, German added 10-11), the interface follows the system language, and CJK, Thai and Hebrew text falls back to system fonts -(#38). Dialogs, menus and messages are English; formulas and number formats are en-US only. -Localized German formulas and numbers are in PR #163. Detail: [localization-parity.md](docs/localization-parity.md). +(#38). Dialogs, menus and messages are English. Formulas follow the interface language in +Spanish, German, Brazilian Portuguese, Russian and Italian (function names, booleans, errors, table +specifiers and separators at the editor; files keep English: [formula-input.md](docs/formula-input.md)); +number formats are en-US only. PR #163 (German formulas and numbers) is open. Detail: +[localization-parity.md](docs/localization-parity.md). | Language | Code | Status | UI strings | |---|---|---|---| @@ -111,7 +114,7 @@ Localized German formulas and numbers are in PR #163. Detail: [localization-pari | Korean | ko | menus only | ~12% | | Vietnamese | vi | none | 0% | -Other shipped languages: 2 (Russian and German, menus only, ~12%). +Other shipped languages: 3 (Russian, German and Italian, menus only, ~12%). ## Upcoming @@ -133,6 +136,7 @@ Ranked; estimates in Opus 5.5 agent-hours. Detail and the full beta-gate list in | Date | What landed | |---|---| | 2026-10-12 | File › Print selects a system printer, copies, duplex and grayscale, submits PDF jobs through craft-print on a worker and shows spooler errors; browser printing and PDF export remain available | +| 2026-10-11 | Formulas in German, Brazilian Portuguese and Russian, and the full Spanish table: 403–459 local function names per language, local booleans, errors and table specifiers, each language's separators, Unicode autocomplete and Insert Function search; files and APIs keep English | | 2026-10-11 | Command-sequence fuzzing: random command sequences checked against undo/redo, XLSX round-trip and full recalculation; fixes for the table, legacy-array, spill, AutoSum, Watch Window and sheet-copy bugs it found | | 2026-10-11 | Password-protected workbooks open: GridCraft asks for the password and decrypts Agile and Standard encryption (#11) | | 2026-10-11 | Text boxes keep their formatting: run size, bold, italic, typeface, text colour and outline, alignment, vertical anchor and "no outline" (#377) | @@ -179,6 +183,7 @@ Ranked; estimates in Opus 5.5 agent-hours. Detail and the full beta-gate list in | Date | Change | Summary | |---|---|---| | 2026-10-12 | minor | Desktop File > Print now discovers printers and submits PDF jobs through pinned craft-print with printer choice, copies, duplex and grayscale; browser printing and PDF export remain available. Remaining print parity includes page ranges and driver-specific tray/options UI; physical printer fidelity needs hardware validation. | +| 2026-10-11 | minor | Languages: formulas follow the interface language in es, de, pt-BR and ru; progress log row | | 2026-10-11 | minor | Password-encrypted workbooks open (#11); progress log row | | 2026-10-11 | minor | Forecast Sheet (#322); progress log row | | 2026-10-11 | minor | Worksheet functions 505 / 523 (ODD* bond functions); progress log row | diff --git a/contributors/people.toml b/contributors/people.toml index 5d343e9c35..a4d8166e89 100644 --- a/contributors/people.toml +++ b/contributors/people.toml @@ -61,3 +61,7 @@ sync_github_name = true real_name = "James Symes" sync_github_name = true + +[people.alb308] +real_name = "Alberto Giunta" +sync_github_name = false diff --git a/crates/calc/src/tests.rs b/crates/calc/src/tests.rs index 5133409833..df70e36eb6 100644 --- a/crates/calc/src/tests.rs +++ b/crates/calc/src/tests.rs @@ -968,3 +968,12 @@ fn trim_references() { t.set("K20", "=SUM(Q1:.Q9)"); assert_eq!(t.get("K20"), Value::Error(CellError::Calc)); } + +#[test] +fn formula_language_tables_only_name_functions_the_engine_knows() { + // A typo'd canonical name in a language table would turn a valid local name into #NAME?. + for locale in gridcraft_formula::FormulaLocale::ALL { + let unknown: Vec<&str> = locale.translations().iter().map(|(en, _)| *en).filter(|en| !crate::eval::is_known_function(en)).collect(); + assert!(unknown.is_empty(), "{locale:?}: {unknown:?}"); + } +} diff --git a/crates/formula/src/input.rs b/crates/formula/src/input.rs index 8568023ed1..e4bbb7d9c0 100644 --- a/crates/formula/src/input.rs +++ b/crates/formula/src/input.rs @@ -1,61 +1,223 @@ //! Localized aliases accepted at user-entry boundaries; file syntax stays English. +//! +//! Each formula language is a [`Dialect`]: function names, booleans, error literals and +//! structured-reference specifiers as that language's Excel spells them, and its separators. +//! Functions a language doesn't list keep their English name, and English names are accepted in +//! every language. + +use gridcraft_core::CellError; use crate::{Expr, ParseError, parser}; -/// Formula-entry syntax selected by the interface language. Other interface languages -/// currently use the canonical English function table until a translation table is supplied. +mod de; +mod es; +mod it; +mod pt; +mod ru; + +/// Formula-entry syntax selected by the interface language. Interface languages without a +/// formula table (Japanese, Chinese and Korean Excel use English names; Czech has no table yet) +/// use [`FormulaLocale::En`]. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub enum FormulaLocale { #[default] En, Es, + De, + PtBr, + Ru, + It, +} + +/// One formula language's words and separators. +pub(crate) struct Dialect { + list: char, + decimal: char, + array_column: char, + array_row: char, + bool_true: &'static str, + bool_false: &'static str, + /// Every error literal, as this language spells it. + errors: &'static [(CellError, &'static str)], + /// The local spellings of [`TABLE_ITEMS`], in the same order. + table_items: [&'static str; 5], + /// `(canonical, local)` for the functions spelled differently from English, sorted by the + /// canonical name. + functions: &'static [(&'static str, &'static str)], } -const SPANISH: &[(&str, &str)] = &[ - ("SUM", "SUMA"), - ("AVERAGE", "PROMEDIO"), - ("IF", "SI"), - ("COUNT", "CONTAR"), - ("SUMIF", "SUMAR.SI"), - ("COUNTIF", "CONTAR.SI"), - ("VLOOKUP", "BUSCARV"), - ("TODAY", "HOY"), - ("TRUE", "VERDADERO"), - ("FALSE", "FALSO"), -]; +/// Structured-reference specifiers in canonical syntax. +const TABLE_ITEMS: [&str; 5] = ["#All", "#Data", "#Headers", "#Totals", "#This Row"]; impl FormulaLocale { + pub const ALL: [Self; 6] = [Self::En, Self::Es, Self::De, Self::PtBr, Self::Ru, Self::It]; + + fn dialect(self) -> Option<&'static Dialect> { + match self { + Self::En => None, + Self::Es => Some(&es::DIALECT), + Self::De => Some(&de::DIALECT), + Self::PtBr => Some(&pt::DIALECT), + Self::Ru => Some(&ru::DIALECT), + Self::It => Some(&it::DIALECT), + } + } + pub fn list_separator(self) -> char { - if self == Self::Es { ';' } else { ',' } + self.dialect().map_or(',', |d| d.list) } pub fn decimal_separator(self) -> char { - if self == Self::Es { ',' } else { '.' } + self.dialect().map_or('.', |d| d.decimal) } pub fn array_column_separator(self) -> char { - if self == Self::Es { '\\' } else { ',' } + self.dialect().map_or(',', |d| d.array_column) + } + pub fn array_row_separator(self) -> char { + self.dialect().map_or(';', |d| d.array_row) } + + /// The local name of a canonical function name (itself when the language keeps English). pub fn function_name(self, canonical: &str) -> &str { - if self == Self::Es { - SPANISH.iter().find(|(en, _)| en.eq_ignore_ascii_case(canonical)).map(|(_, es)| *es).unwrap_or(canonical) - } else { - canonical - } + self.dialect() + .and_then(|d| d.functions.binary_search_by(|(en, _)| cmp_ascii_ignore_case(en, canonical)).ok().and_then(|i| d.functions.get(i))) + .map_or(canonical, |(_, local)| *local) } + + /// The canonical name of a local function name, case-insensitively (itself when it isn't one). pub fn canonical_name(self, localized: &str) -> &str { - if self == Self::Es { - SPANISH.iter().find(|(_, es)| es.eq_ignore_ascii_case(localized)).map(|(en, _)| *en).unwrap_or(localized) + self.dialect().and_then(|d| d.functions.iter().find(|(_, local)| eq_ignore_case(local, localized))).map_or(localized, |(en, _)| *en) + } + + /// `(canonical, local)` for every function this language spells differently from English, + /// sorted by the canonical name. + pub fn translations(self) -> &'static [(&'static str, &'static str)] { + self.dialect().map_or(&[], |d| d.functions) + } + + pub fn boolean_name(self, value: bool) -> &'static str { + match (self.dialect(), value) { + (Some(d), true) => d.bool_true, + (Some(d), false) => d.bool_false, + (None, true) => "TRUE", + (None, false) => "FALSE", + } + } + + /// The boolean a local word spells, case-insensitively. English `TRUE`/`FALSE` are lexed as + /// booleans in every language, so only the local words are matched here. + pub(crate) fn boolean(self, word: &str) -> Option { + let d = self.dialect()?; + if eq_ignore_case(word, d.bool_true) { + Some(true) + } else if eq_ignore_case(word, d.bool_false) { + Some(false) } else { - localized + None + } + } + + pub fn error_name(self, error: CellError) -> &'static str { + self.dialect().and_then(|d| d.errors.iter().find(|(e, _)| *e == error)).map_or_else(|| error.as_str(), |(_, local)| *local) + } + + /// The longest local error literal `text` starts with, and its length in characters. + pub(crate) fn error_prefix(self, text: &str) -> Option<(CellError, usize)> { + let d = self.dialect()?; + d.errors + .iter() + .filter(|(_, local)| starts_with_ignore_case(text, local)) + .map(|(e, local)| (*e, local.chars().count())) + .max_by_key(|(_, len)| *len) + } + + /// Converts the inside of a local structured reference (`[...]` without its outer brackets) + /// to canonical syntax: specifiers in English, `,` between bracketed items. + pub(crate) fn struct_to_canonical(self, inner: &str) -> String { + match self.dialect() { + Some(d) => translate_struct(inner, &d.table_items, &TABLE_ITEMS, d.list, ','), + None => inner.to_string(), + } + } + + /// Converts the inside of a canonical structured reference to this language. + pub(crate) fn struct_to_local(self, inner: &str) -> String { + match self.dialect() { + Some(d) => translate_struct(inner, &TABLE_ITEMS, &d.table_items, ',', d.list), + None => inner.to_string(), + } + } +} + +fn cmp_ascii_ignore_case(a: &str, b: &str) -> std::cmp::Ordering { + a.bytes().map(|c| c.to_ascii_uppercase()).cmp(b.bytes().map(|c| c.to_ascii_uppercase())) +} + +/// Unicode case-insensitive equality (`zählenwenn` = `ZÄHLENWENN`, `сумм` = `СУММ`). +fn eq_ignore_case(a: &str, b: &str) -> bool { + a.chars().flat_map(char::to_uppercase).eq(b.chars().flat_map(char::to_uppercase)) +} + +fn starts_with_ignore_case(text: &str, prefix: &str) -> bool { + text.chars().take(prefix.chars().count()).flat_map(char::to_uppercase).eq(prefix.chars().flat_map(char::to_uppercase)) +} + +/// Rewrites specifiers (`#Headers` <-> `#Kopfzeilen`) and the separator between bracketed +/// items, leaving column names and `'` escapes alone. +fn translate_struct(inner: &str, from: &[&'static str; 5], to: &[&'static str; 5], from_sep: char, to_sep: char) -> String { + let item = |text: &str| -> Option<&'static str> { from.iter().position(|f| eq_ignore_case(text.trim(), f)).and_then(|i| to.get(i).copied()) }; + if !inner.starts_with('[') { + return item(inner).map_or_else(|| inner.to_string(), str::to_string); + } + let mut out = String::with_capacity(inner.len()); + let mut group = String::new(); + let mut depth = 0usize; + let mut chars = inner.chars(); + while let Some(c) = chars.next() { + match c { + '\'' => { + let target = if depth > 0 { &mut group } else { &mut out }; + target.push(c); + if let Some(escaped) = chars.next() { + target.push(escaped); + } + } + '[' => { + if depth == 0 { + group.clear(); + } else { + group.push(c); + } + depth += 1; + } + ']' if depth > 0 => { + depth -= 1; + if depth == 0 { + out.push('['); + out.push_str(item(&group).unwrap_or(&group)); + out.push(']'); + } else { + group.push(c); + } + } + c if depth == 0 && c == from_sep => out.push(to_sep), + c if depth > 0 => group.push(c), + c => out.push(c), } } + if depth > 0 { + // Unbalanced input: keep what was read so the parser reports the error. + out.push('['); + out.push_str(&group); + } + out } /// Parses UI input using the selected function table and separators. Existing names and /// LET/LAMBDA bindings take precedence over aliases. File and API syntax uses [`crate::parse`]. pub fn parse_input(src: &str, locale: FormulaLocale, known_name: impl Fn(&str) -> bool) -> Result { let mut expr = parser::parse_syntax(src, locale)?; - if locale == FormulaLocale::Es { - normalize(&mut expr, &known_name, &mut Vec::new(), 0, false)?; + if locale != FormulaLocale::En { + normalize(&mut expr, locale, &known_name, &mut Vec::new(), 0, false)?; } Ok(expr) } @@ -89,7 +251,7 @@ pub fn print_input(expr: &Expr, locale: FormulaLocale, known_name: impl Fn(&str) return Ok(crate::print(expr)); } let mut expr = expr.clone(); - normalize(&mut expr, &known_name, &mut Vec::new(), 0, true)?; + normalize(&mut expr, locale, &known_name, &mut Vec::new(), 0, true)?; let canonical = crate::print(&expr); let tokens = crate::lexer::tokenize(&canonical).map_err(|e| ParseError { msg: e.msg, pos: e.pos })?; let mut out = String::new(); @@ -108,36 +270,41 @@ pub fn print_input(expr: &Expr, locale: FormulaLocale, known_name: impl Fn(&str) } Tok::Number(_) => out.push_str(&text.replace('.', &locale.decimal_separator().to_string())), Tok::Comma => out.push(if array_depth > 0 { locale.array_column_separator() } else { locale.list_separator() }), + Tok::Semicolon if array_depth > 0 => out.push(locale.array_row_separator()), + Tok::Error(e) => out.push_str(locale.error_name(e)), + Tok::Struct(inner) => { + out.push('['); + out.push_str(&locale.struct_to_local(&inner)); + out.push(']'); + } _ => out.push_str(text), } } Ok(out) } -pub(crate) fn boolean_alias(name: &str) -> Option { - if name.eq_ignore_ascii_case("VERDADERO") { - Some(true) - } else if name.eq_ignore_ascii_case("FALSO") { - Some(false) - } else { - None - } -} - -fn normalize(expr: &mut Expr, known_name: &impl Fn(&str) -> bool, bindings: &mut Vec, depth: usize, display: bool) -> Result<(), ParseError> { +fn normalize( + expr: &mut Expr, + locale: FormulaLocale, + known_name: &impl Fn(&str) -> bool, + bindings: &mut Vec, + depth: usize, + display: bool, +) -> Result<(), ParseError> { if depth > parser::MAX_DEPTH { return Err(ParseError { msg: "formula is nested too deeply".into(), pos: 0 }); } - let bound = |name: &str, bindings: &[String]| bindings.iter().rev().any(|n| n.eq_ignore_ascii_case(name)) || known_name(name); + // Names ignore case in any script, so a binding `zählenwenn` shadows the call `ZÄHLENWENN(…)`. + let bound = |name: &str, bindings: &[String]| bindings.iter().rev().any(|n| eq_ignore_case(n, name)) || known_name(name); match expr { Expr::Bool(value) if display => { - let alias = if *value { "VERDADERO" } else { "FALSO" }; + let alias = locale.boolean_name(*value); if !bound(alias, bindings) { *expr = Expr::Name(alias.into()); } } Expr::Name(name) if !display && !bound(name, bindings) => { - if let Some(value) = boolean_alias(name) { + if let Some(value) = locale.boolean(name) { *expr = Expr::Bool(value); } } @@ -147,13 +314,13 @@ fn normalize(expr: &mut Expr, known_name: &impl Fn(&str) -> bool, bindings: &mut for pair in pairs.chunks_mut(2) { if let [declaration, value] = pair { // The new name is not in scope in its own value expression. - normalize(value, known_name, bindings, depth + 1, display)?; + normalize(value, locale, known_name, bindings, depth + 1, display)?; if let Expr::Name(name) = declaration { bindings.push(name.clone()); } } } - normalize(body, known_name, bindings, depth + 1, display)?; + normalize(body, locale, known_name, bindings, depth + 1, display)?; } bindings.truncate(saved); } @@ -165,34 +332,34 @@ fn normalize(expr: &mut Expr, known_name: &impl Fn(&str) -> bool, bindings: &mut bindings.push(name.clone()); } } - normalize(body, known_name, bindings, depth + 1, display)?; + normalize(body, locale, known_name, bindings, depth + 1, display)?; } bindings.truncate(saved); } Expr::Call(name, args) => { - let alias = if display { FormulaLocale::Es.function_name(name) } else { FormulaLocale::Es.canonical_name(name) }; + let alias = if display { locale.function_name(name) } else { locale.canonical_name(name) }; if !bound(name, bindings) && (!display || !bound(alias, bindings)) { *name = alias.to_string(); } for arg in args { - normalize(arg, known_name, bindings, depth + 1, display)?; + normalize(arg, locale, known_name, bindings, depth + 1, display)?; } } Expr::Invoke(callee, args) => { - normalize(callee, known_name, bindings, depth + 1, display)?; + normalize(callee, locale, known_name, bindings, depth + 1, display)?; for arg in args { - normalize(arg, known_name, bindings, depth + 1, display)?; + normalize(arg, locale, known_name, bindings, depth + 1, display)?; } } - Expr::Unary(_, child) | Expr::Paren(child) => normalize(child, known_name, bindings, depth + 1, display)?, + Expr::Unary(_, child) | Expr::Paren(child) => normalize(child, locale, known_name, bindings, depth + 1, display)?, Expr::Binary(_, left, right) => { - normalize(left, known_name, bindings, depth + 1, display)?; - normalize(right, known_name, bindings, depth + 1, display)?; + normalize(left, locale, known_name, bindings, depth + 1, display)?; + normalize(right, locale, known_name, bindings, depth + 1, display)?; } Expr::Array(rows) if display => { for row in rows { for child in row { - normalize(child, known_name, bindings, depth + 1, display)?; + normalize(child, locale, known_name, bindings, depth + 1, display)?; } } } diff --git a/crates/formula/src/input/de.rs b/crates/formula/src/input/de.rs new file mode 100644 index 0000000000..bdf4727b21 --- /dev/null +++ b/crates/formula/src/input/de.rs @@ -0,0 +1,476 @@ +//! Deutsch (Deutschland): the formula words German Excel shows (function names, booleans, errors, +//! structured-reference specifiers) and its formula separators. +//! +//! Function names come from Microsoft Support's de-de Excel function pages (retrieved +//! 2026-10-10; the pages are machine-translated): per page, a vote among the title, the meta +//! description, the syntax paragraph (aligned with the en-US page) and `=NAME(` examples, and an +//! entry needs two agreeing signals. Entries marked `reviewed` were decided by hand from the page +//! evidence and independent function-name references. Functions not listed keep their English name. +//! +//! Sources for the other words: +//! - bool: https://support.microsoft.com/de-de/excel/functions/cell-function (WAHR/FALSCH) | https://support.microsoft.com/de-de/excel/is-functions +//! - table_items: https://it-service-ruhr.de/excel-strukturierte-verweise/ ([#Alle] [#Kopfzeilen] [#Daten] [#Ergebnisse] [#Diese Zeile]) | https://fasteasy.at/tippshop/index.php?mp=1&id=1&id2=17&id3=1728 (#Alle #Daten #Kopfzeilen #Ergebnisse, "[#Diese Zeile]") +//! - errors.#WERT!..#NV,#DATEN_ABRUFEN: https://support.microsoft.com/de-de/excel/functions/error-type-function (ERROR.TYPE table) | https://support.microsoft.com/de-de/excel/functions/cubemember-function ("#DATEN_ABRUFEN…") +//! - errors.#SPILL!: https://support.microsoft.com/de-de/excel/how-to-correct-a-spill-error (title "#ÜBERLAUF!-Fehler") +//! - errors.#CALC!: https://support.microsoft.com/de-de/excel/functions/lambda-function ("#KALK!-Fehlermeldung") | https://excelhero.de/funktionen/excel-filter-funktion/ | https://www.tabellenexperte.de/die-neue-filter-funktion-mit-jokersuche/ | https://www.tippscout.de/excel-daten-filtern-ganz-einfach.html + +use super::Dialect; +use gridcraft_core::CellError; + +pub(super) const DIALECT: Dialect = Dialect { + list: ';', + decimal: ',', + array_column: '.', + array_row: ';', + bool_true: "WAHR", + bool_false: "FALSCH", + errors: &[ + (CellError::Null, "#NULL!"), + (CellError::Div0, "#DIV/0!"), + (CellError::Value, "#WERT!"), + (CellError::Ref, "#BEZUG!"), + (CellError::Name, "#NAME?"), + (CellError::Num, "#ZAHL!"), + (CellError::NA, "#NV"), + (CellError::GettingData, "#DATEN_ABRUFEN"), + (CellError::Spill, "#ÜBERLAUF!"), + (CellError::Calc, "#KALK!"), + ], + table_items: ["#Alle", "#Daten", "#Kopfzeilen", "#Ergebnisse", "#Diese Zeile"], + functions: &[ + ("ACCRINT", "AUFGELZINS"), + ("ACCRINTM", "AUFGELZINSF"), + ("ACOS", "ARCCOS"), + ("ACOSH", "ARCCOSHYP"), + ("ACOT", "ARCCOT"), + ("ACOTH", "ARCCOTHYP"), + ("ADDRESS", "ADRESSE"), + ("AGGREGATE", "AGGREGAT"), + ("AMORDEGRC", "AMORDEGRK"), + ("AMORLINC", "AMORLINEARK"), + ("AND", "UND"), + ("ARABIC", "ARABISCH"), + ("AREAS", "BEREICHE"), + ("ARRAYTOTEXT", "MATRIXZUTEXT"), + ("ASIN", "ARCSIN"), + ("ASINH", "ARCSINHYP"), + ("ATAN", "ARCTAN"), + ("ATAN2", "ARCTAN2"), + ("ATANH", "ARCTANHYP"), + ("AVEDEV", "MITTELABW"), + ("AVERAGE", "MITTELWERT"), + ("AVERAGEA", "MITTELWERTA"), + ("AVERAGEIF", "MITTELWERTWENN"), + ("AVERAGEIFS", "MITTELWERTWENNS"), + ("BASE", "BASIS"), + ("BETA.DIST", "BETA.VERT"), + ("BETADIST", "BETAVERT"), + ("BIN2DEC", "BININDEZ"), + ("BIN2HEX", "BININHEX"), + ("BIN2OCT", "BININOKT"), + ("BINOM.DIST", "BINOM.VERT"), + ("BINOM.DIST.RANGE", "BINOM.VERT.BEREICH"), + ("BINOMDIST", "BINOMVERT"), + ("BITAND", "BITUND"), + ("BITLSHIFT", "BITLVERSCHIEB"), + ("BITOR", "BITODER"), + ("BITRSHIFT", "BITRVERSCHIEB"), + ("BITXOR", "BITXODER"), + // reviewed: sidebar link on MS de-de function pages (page body left BYCOL); pairs with BYROW=NACHZEILE | sources: https://support.microsoft.com/de-de/excel/functions/bycol-function + ("BYCOL", "NACHSPALTE"), + // reviewed: sidebar link on MS de-de function pages (page body left BYROW) | sources: https://support.microsoft.com/de-de/excel/functions/byrow-function + ("BYROW", "NACHZEILE"), + ("CEILING", "OBERGRENZE"), + ("CEILING.MATH", "OBERGRENZE.MATHEMATIK"), + ("CEILING.PRECISE", "OBERGRENZE.GENAU"), + ("CELL", "ZELLE"), + ("CHAR", "ZEICHEN"), + ("CHIDIST", "CHIVERT"), + ("CHISQ.DIST", "CHIQU.VERT"), + ("CHISQ.DIST.RT", "CHIQU.VERT.RE"), + ("CHISQ.INV", "CHIQU.INV"), + ("CHISQ.INV.RT", "CHIQU.INV.RE"), + ("CHISQ.TEST", "CHIQU.TEST"), + ("CHOOSE", "WAHL"), + ("CHOOSECOLS", "SPALTENWAHL"), + // reviewed: sidebar link; pairs with CHOOSECOLS=SPALTENWAHL (agreeing vote); page example uses MT variant ZEILENAUSWAHL | sources: https://support.microsoft.com/de-de/excel/functions/chooserows-function + ("CHOOSEROWS", "ZEILENWAHL"), + ("CLEAN", "SÄUBERN"), + ("COLUMN", "SPALTE"), + ("COLUMNS", "SPALTEN"), + ("COMBIN", "KOMBINATIONEN"), + ("COMBINA", "KOMBINATIONEN2"), + ("COMPLEX", "KOMPLEXE"), + ("CONCAT", "TEXTKETTE"), + ("CONCATENATE", "VERKETTEN"), + ("CONFIDENCE", "KONFIDENZ"), + ("CONFIDENCE.NORM", "KONFIDENZ.NORM"), + ("CONFIDENCE.T", "KONFIDENZ.T"), + ("CONVERT", "UMWANDELN"), + ("CORREL", "KORREL"), + ("COSH", "COSHYP"), + ("COTH", "COTHYP"), + ("COUNT", "ANZAHL"), + ("COUNTA", "ANZAHL2"), + // reviewed: page title ANZAHLLEEREZELLEN; meta/syntax ANZAHLLEERE/ANZAHLLEER are MT truncations; en-US COUNTBLANK page | sources: https://support.microsoft.com/de-de/excel/functions/countblank-function + ("COUNTBLANK", "ANZAHLLEEREZELLEN"), + ("COUNTIF", "ZÄHLENWENN"), + ("COUNTIFS", "ZÄHLENWENNS"), + ("COUPDAYBS", "ZINSTERMTAGVA"), + ("COUPDAYS", "ZINSTERMTAGE"), + ("COUPDAYSNC", "ZINSTERMTAGNZ"), + ("COUPNCD", "ZINSTERMNZ"), + ("COUPNUM", "ZINSTERMZAHL"), + ("COUPPCD", "ZINSTERMVZ"), + ("COVAR", "KOVAR"), + ("COVARIANCE.P", "KOVARIANZ.P"), + ("COVARIANCE.S", "KOVARIANZ.S"), + ("CRITBINOM", "KRITBINOM"), + ("CSC", "COSEC"), + ("CSCH", "COSECHYP"), + ("CUBEKPIMEMBER", "CUBEKPIELEMENT"), + ("CUBEMEMBER", "CUBEELEMENT"), + ("CUBEMEMBERPROPERTY", "CUBEELEMENTEIGENSCHAFT"), + ("CUBERANKEDMEMBER", "CUBERANGELEMENT"), + ("CUBESET", "CUBEMENGE"), + ("CUBESETCOUNT", "CUBEMENGENANZAHL"), + ("CUBEVALUE", "CUBEWERT"), + ("CUMIPMT", "KUMZINSZ"), + ("CUMPRINC", "KUMKAPITAL"), + ("DATE", "DATUM"), + ("DATEVALUE", "DATWERT"), + ("DAVERAGE", "DBMITTELWERT"), + ("DAY", "TAG"), + ("DAYS", "TAGE"), + ("DAYS360", "TAGE360"), + ("DB", "GDA2"), + ("DCOUNT", "DBANZAHL"), + ("DCOUNTA", "DBANZAHL2"), + ("DDB", "GDA"), + ("DEC2BIN", "DEZINBIN"), + ("DEC2HEX", "DEZINHEX"), + ("DEC2OCT", "DEZINOKT"), + ("DECIMAL", "DEZIMAL"), + ("DEGREES", "GRAD"), + ("DEVSQ", "SUMQUADABW"), + ("DGET", "DBAUSZUG"), + ("DISC", "DISAGIO"), + ("DMAX", "DBMAX"), + ("DMIN", "DBMIN"), + // reviewed: page title "DM"; German Excel DOLLAR is DM (meta/syntax left English) | sources: https://support.microsoft.com/de-de/excel/functions/dollar-function + ("DOLLAR", "DM"), + ("DOLLARDE", "NOTIERUNGDEZ"), + ("DOLLARFR", "NOTIERUNGBRU"), + ("DPRODUCT", "DBPRODUKT"), + ("DROP", "WEGLASSEN"), + ("DSTDEV", "DBSTDABW"), + ("DSTDEVP", "DBSTDABWN"), + ("DSUM", "DBSUMME"), + ("DVAR", "DBVARIANZ"), + ("DVARP", "DBVARIANZEN"), + ("EDATE", "EDATUM"), + ("EFFECT", "EFFEKTIV"), + ("ENCODEURL", "URLCODIEREN"), + ("EOMONTH", "MONATSENDE"), + ("ERF", "GAUSSFEHLER"), + ("ERF.PRECISE", "GAUSSF.GENAU"), + ("ERFC", "GAUSSFKOMPL"), + ("ERFC.PRECISE", "GAUSSFKOMPL.GENAU"), + ("ERROR.TYPE", "FEHLER.TYP"), + ("EVEN", "GERADE"), + ("EXACT", "IDENTISCH"), + ("EXPAND", "ERWEITERN"), + ("EXPON.DIST", "EXPON.VERT"), + ("EXPONDIST", "EXPONVERT"), + // reviewed: page title F.VERT + sidebar; F.DIST.RT=F.VERT.RE agrees | sources: https://support.microsoft.com/de-de/excel/functions/f-dist-function + ("F.DIST", "F.VERT"), + ("F.DIST.RT", "F.VERT.RE"), + ("F.INV.RT", "F.INV.RE"), + ("FACT", "FAKULTÄT"), + ("FACTDOUBLE", "ZWEIFAKULTÄT"), + ("FALSE", "FALSCH"), + ("FDIST", "FVERT"), + ("FILTERXML", "XMLFILTERN"), + // reviewed: SEARCH page: "…Groß- und Kleinschreibung… können Sie FINDEN verwenden" (FIND page retired) | sources: https://support.microsoft.com/de-de/excel/functions/search-function + ("FIND", "FINDEN"), + // reviewed: B-variant pattern of FINDEN (LINKSB, TEILB, RECHTSB, LÄNGEB, SUCHENB documented); name itself not on a cached page [inferred] | sources: https://support.microsoft.com/de-de/excel/functions/c7912941-af2a-4bdf-a553-d0d89b0a0628 + ("FINDB", "FINDENB"), + ("FIXED", "FEST"), + ("FLOOR", "UNTERGRENZE"), + ("FLOOR.MATH", "UNTERGRENZE.MATHEMATIK"), + ("FLOOR.PRECISE", "UNTERGRENZE.GENAU"), + // reviewed: page: "PROGNOSE.LINEAR(x;Y_Werte;X_Werte) oder SCHÄTZER(x;Y_Werte;X_Werte)"; PROGNOSE replaced SCHÄTZER only as .LINEAR | sources: https://support.microsoft.com/de-de/excel/forecast-and-forecast-linear-functions + ("FORECAST", "SCHÄTZER"), + // reviewed: same page syntax and example =PROGNOSE.LINEAR(30,A2:A6,B2:B6) | sources: https://support.microsoft.com/de-de/excel/forecast-and-forecast-linear-functions + ("FORECAST.LINEAR", "PROGNOSE.LINEAR"), + ("FORMULATEXT", "FORMELTEXT"), + ("FREQUENCY", "HÄUFIGKEIT"), + ("FV", "ZW"), + ("FVSCHEDULE", "ZW2"), + ("GAMMA.DIST", "GAMMA.VERT"), + ("GAMMADIST", "GAMMAVERT"), + ("GAMMALN.PRECISE", "GAMMALN.GENAU"), + ("GCD", "GGT"), + ("GEOMEAN", "GEOMITTEL"), + ("GESTEP", "GGANZZAHL"), + ("GROUPBY", "GRUPPIERENNACH"), + ("GROWTH", "VARIATION"), + ("HARMEAN", "HARMITTEL"), + ("HEX2BIN", "HEXINBIN"), + ("HEX2DEC", "HEXINDEZ"), + ("HEX2OCT", "HEXINOKT"), + ("HLOOKUP", "WVERWEIS"), + ("HOUR", "STUNDE"), + ("HSTACK", "HSTAPELN"), + ("HYPGEOM.DIST", "HYPGEOM.VERT"), + ("HYPGEOMDIST", "HYPGEOMVERT"), + ("IF", "WENN"), + ("IFERROR", "WENNFEHLER"), + ("IFNA", "WENNNV"), + ("IFS", "WENNS"), + ("IMAGINARY", "IMAGINÄRTEIL"), + ("IMCONJUGATE", "IMKONJUGIERTE"), + ("IMCOSH", "IMCOSHYP"), + ("IMCSC", "IMCOSEC"), + ("IMCSCH", "IMCOSECHYP"), + ("IMPOWER", "IMAPOTENZ"), + ("IMPRODUCT", "IMPRODUKT"), + ("IMREAL", "IMREALTEIL"), + ("IMSECH", "IMSECHYP"), + ("IMSINH", "IMSINHYP"), + ("IMSQRT", "IMWURZEL"), + ("IMSUM", "IMSUMME"), + ("INDIRECT", "INDIREKT"), + ("INT", "GANZZAHL"), + ("INTERCEPT", "ACHSENABSCHNITT"), + ("INTRATE", "ZINSSATZ"), + ("IPMT", "ZINSZ"), + ("IRR", "IKV"), + // reviewed: IS-functions page syntax list and examples =ISTLEER(A2) | sources: https://support.microsoft.com/de-de/excel/is-functions + ("ISBLANK", "ISTLEER"), + // reviewed: IS-functions page syntax list, example =ISTFEHL(A6) | sources: https://support.microsoft.com/de-de/excel/is-functions + ("ISERR", "ISTFEHL"), + // reviewed: IS-functions page syntax list, example =WENN(ISTFEHLER(A1)… | sources: https://support.microsoft.com/de-de/excel/is-functions + ("ISERROR", "ISTFEHLER"), + ("ISEVEN", "ISTGERADE"), + ("ISFORMULA", "ISTFORMEL"), + // reviewed: IS-functions page syntax list, example =ISTLOG(WAHR) | sources: https://support.microsoft.com/de-de/excel/is-functions + ("ISLOGICAL", "ISTLOG"), + // reviewed: IS-functions page syntax list, example =ISTNV(A4) | sources: https://support.microsoft.com/de-de/excel/is-functions + ("ISNA", "ISTNV"), + // reviewed: IS-functions page syntax list ISTKTEXT(Wert) and description row | sources: https://support.microsoft.com/de-de/excel/is-functions + ("ISNONTEXT", "ISTKTEXT"), + // reviewed: IS-functions page syntax list, example =ISTZAHL(4) | sources: https://support.microsoft.com/de-de/excel/is-functions + ("ISNUMBER", "ISTZAHL"), + ("ISO.CEILING", "ISO.OBERGRENZE"), + // reviewed: live MS page https://support.microsoft.com/de-de/excel/functions/isodd-function: title/syntax/examples ISTUNGERADE (the IS-functions page shows MT-garbled "ISUNGERADE") + ("ISODD", "ISTUNGERADE"), + // reviewed: ISOMITTED page syntax and example | sources: https://support.microsoft.com/de-de/excel/functions/isomitted-function + ("ISOMITTED", "WURDEAUSGELASSEN"), + ("ISOWEEKNUM", "ISOKALENDERWOCHE"), + // reviewed: IS-functions page syntax list, example =ISTBEZUG(G8) | sources: https://support.microsoft.com/de-de/excel/is-functions + ("ISREF", "ISTBEZUG"), + // reviewed: IS-functions page syntax list, example =ISTTEXT(A3) | sources: https://support.microsoft.com/de-de/excel/is-functions + ("ISTEXT", "ISTTEXT"), + ("LARGE", "KGRÖSSTE"), + ("LCM", "KGV"), + ("LEFT", "LINKS"), + ("LEFTB", "LINKSB"), + ("LEN", "LÄNGE"), + ("LENB", "LÄNGEB"), + ("LINEST", "RGP"), + ("LOGEST", "RKP"), + ("LOGNORM.DIST", "LOGNORM.VERT"), + ("LOGNORMDIST", "LOGNORMVERT"), + ("LOOKUP", "VERWEIS"), + ("LOWER", "KLEIN"), + // reviewed: sidebar link on MS de-de function pages (page body left MAKEARRAY) | sources: https://support.microsoft.com/de-de/excel/functions/makearray-function + ("MAKEARRAY", "MATRIXERSTELLEN"), + // reviewed: MAP page syntax "=ZUORDNEN (Array1; lambda_or_array<#>)" and example; sidebar says KARTE (MT of the title) – rejected | sources: https://support.microsoft.com/de-de/excel/functions/map-function + ("MAP", "ZUORDNEN"), + ("MATCH", "VERGLEICH"), + ("MAXIFS", "MAXWENNS"), + ("MDETERM", "MDET"), + ("MID", "TEIL"), + ("MIDB", "TEILB"), + ("MINIFS", "MINWENNS"), + ("MINVERSE", "MINV"), + ("MIRR", "QIKV"), + ("MOD", "REST"), + ("MODE", "MODALWERT"), + ("MODE.MULT", "MODUS.VIELF"), + ("MODE.SNGL", "MODUS.EINF"), + ("MONTH", "MONAT"), + ("MROUND", "VRUNDEN"), + ("MULTINOMIAL", "POLYNOMIAL"), + ("MUNIT", "MEINHEIT"), + ("NA", "NV"), + ("NEGBINOM.DIST", "NEGBINOM.VERT"), + ("NEGBINOMDIST", "NEGBINOMVERT"), + ("NETWORKDAYS", "NETTOARBEITSTAGE"), + ("NETWORKDAYS.INTL", "NETTOARBEITSTAGE.INTL"), + ("NORM.DIST", "NORM.VERT"), + ("NORM.S.DIST", "NORM.S.VERT"), + ("NORMDIST", "NORMVERT"), + ("NORMSDIST", "STANDNORMVERT"), + ("NORMSINV", "STANDNORMINV"), + ("NOT", "NICHT"), + ("NOW", "JETZT"), + ("NPER", "ZZR"), + ("NPV", "NBW"), + ("NUMBERVALUE", "ZAHLENWERT"), + ("OCT2BIN", "OKTINBIN"), + ("OCT2DEC", "OKTINDEZ"), + ("OCT2HEX", "OKTINHEX"), + ("ODD", "UNGERADE"), + ("OFFSET", "BEREICH.VERSCHIEBEN"), + ("OR", "ODER"), + ("PERCENTILE", "QUANTIL"), + ("PERCENTILE.EXC", "QUANTIL.EXKL"), + ("PERCENTILE.INC", "QUANTIL.INKL"), + ("PERCENTRANK", "QUANTILSRANG"), + ("PERCENTRANK.EXC", "QUANTILSRANG.EXKL"), + ("PERCENTRANK.INC", "QUANTILSRANG.INKL"), + ("PERMUT", "VARIATIONEN"), + ("PERMUTATIONA", "VARIATIONEN2"), + ("PIVOTBY", "PIVOTMIT"), + ("PMT", "RMZ"), + ("POISSON.DIST", "POISSON.VERT"), + ("POWER", "POTENZ"), + ("PPMT", "KAPZ"), + ("PRICE", "KURS"), + ("PRICEDISC", "KURSDISAGIO"), + ("PRICEMAT", "KURSFÄLLIG"), + ("PROB", "WAHRSCHBEREICH"), + ("PRODUCT", "PRODUKT"), + ("PROPER", "GROSS2"), + ("PV", "BW"), + ("QUARTILE.EXC", "QUARTILE.EXKL"), + ("QUARTILE.INC", "QUARTILE.INKL"), + ("RADIANS", "BOGENMASS"), + ("RAND", "ZUFALLSZAHL"), + ("RANDARRAY", "ZUFALLSMATRIX"), + ("RANDBETWEEN", "ZUFALLSBEREICH"), + ("RANK", "RANG"), + ("RANK.AVG", "RANG.MITTELW"), + ("RANK.EQ", "RANG.GLEICH"), + ("RATE", "ZINS"), + ("RECEIVED", "AUSZAHLUNG"), + ("REPLACE", "ERSETZEN"), + // reviewed: B-variant pattern of ERSETZEN; not named on a cached page [inferred] | sources: https://support.microsoft.com/de-de/excel/functions/replace-function + ("REPLACEB", "ERSETZENB"), + ("REPT", "WIEDERHOLEN"), + ("RIGHT", "RECHTS"), + ("RIGHTB", "RECHTSB"), + ("ROMAN", "RÖMISCH"), + ("ROUND", "RUNDEN"), + ("ROUNDDOWN", "ABRUNDEN"), + ("ROUNDUP", "AUFRUNDEN"), + ("ROW", "ZEILE"), + ("ROWS", "ZEILEN"), + ("RRI", "ZSATZINVEST"), + ("RSQ", "BESTIMMTHEITSMASS"), + ("SEARCH", "SUCHEN"), + ("SEARCHB", "SUCHENB"), + ("SECH", "SECHYP"), + ("SECOND", "SEKUNDE"), + ("SEQUENCE", "SEQUENZ"), + ("SERIESSUM", "POTENZREIHE"), + ("SHEET", "BLATT"), + ("SHEETS", "BLÄTTER"), + ("SIGN", "VORZEICHEN"), + ("SINH", "SINHYP"), + ("SKEW", "SCHIEFE"), + ("SKEW.P", "SCHIEFE.P"), + ("SLN", "LIA"), + ("SLOPE", "STEIGUNG"), + ("SMALL", "KKLEINSTE"), + ("SORT", "SORTIEREN"), + ("SORTBY", "SORTIERENNACH"), + ("SQRT", "WURZEL"), + ("SQRTPI", "WURZELPI"), + ("STANDARDIZE", "STANDARDISIERUNG"), + ("STDEV", "STABW"), + ("STDEV.P", "STABW.N"), + ("STDEV.S", "STABW.S"), + ("STDEVA", "STABWA"), + ("STDEVP", "STABWN"), + ("STDEVPA", "STABWNA"), + ("STEYX", "STFEHLERYX"), + ("SUBSTITUTE", "WECHSELN"), + ("SUBTOTAL", "TEILERGEBNIS"), + ("SUM", "SUMME"), + ("SUMIF", "SUMMEWENN"), + ("SUMIFS", "SUMMEWENNS"), + ("SUMPRODUCT", "SUMMENPRODUKT"), + ("SUMSQ", "QUADRATESUMME"), + ("SUMX2MY2", "SUMMEX2MY2"), + ("SUMX2PY2", "SUMMEX2PY2"), + ("SUMXMY2", "SUMMEXMY2"), + // reviewed: SWITCH page meta + examples + sidebar | sources: https://support.microsoft.com/de-de/excel/functions/switch-function + ("SWITCH", "ERSTERWERT"), + ("SYD", "DIA"), + ("T.DIST", "T.VERT"), + ("T.DIST.2T", "T.VERT.2S"), + ("T.DIST.RT", "T.VERT.RE"), + ("T.INV.2T", "T.INV.2S"), + ("TAKE", "ÜBERNEHMEN"), + ("TANH", "TANHYP"), + ("TBILLEQ", "TBILLÄQUIV"), + ("TBILLPRICE", "TBILLKURS"), + ("TBILLYIELD", "TBILLRENDITE"), + ("TDIST", "TVERT"), + // reviewed: TEXTAFTER page title + meta (TEXTNACH); syntax paragraph left English | sources: https://support.microsoft.com/de-de/excel/functions/textafter-function + ("TEXTAFTER", "TEXTNACH"), + // reviewed: page syntax + examples + sidebar (title/meta left English) | sources: https://support.microsoft.com/de-de/excel/functions/textbefore-function + ("TEXTBEFORE", "TEXTVOR"), + ("TEXTJOIN", "TEXTVERKETTEN"), + // reviewed: page syntax/examples and MS TEXTSPLIT page example =TEXTTEILEN(A1,{",","."}) | sources: https://support.microsoft.com/de-de/excel/functions/textsplit-function | https://support.microsoft.com/de-de/office/textsplit-funktion-b1ca414e-4c21-4ca0-b1b7-bdecace8a6e7 + ("TEXTSPLIT", "TEXTTEILEN"), + ("TIME", "ZEIT"), + ("TIMEVALUE", "ZEITWERT"), + ("TOCOL", "ZUSPALTE"), + ("TODAY", "HEUTE"), + ("TOROW", "ZUZEILE"), + ("TRANSPOSE", "MTRANS"), + ("TRIM", "GLÄTTEN"), + ("TRIMMEAN", "GESTUTZTMITTEL"), + ("TRUE", "WAHR"), + ("TRUNC", "KÜRZEN"), + ("TYPE", "TYP"), + ("UNICHAR", "UNIZEICHEN"), + ("UNIQUE", "EINDEUTIG"), + ("UPPER", "GROSS"), + ("VALUE", "WERT"), + // reviewed: page syntax "WERTZUTEXT(Wert;[Format])" + sidebar; pairs with ARRAYTOTEXT=MATRIXZUTEXT | sources: https://support.microsoft.com/de-de/excel/functions/valuetotext-function + ("VALUETOTEXT", "WERTZUTEXT"), + ("VAR", "VARIANZ"), + ("VARA", "VARIANZA"), + ("VARP", "VARIANZEN"), + ("VARPA", "VARIANZENA"), + ("VLOOKUP", "SVERWEIS"), + ("VSTACK", "VSTAPELN"), + ("WEBSERVICE", "WEBDIENST"), + ("WEEKDAY", "WOCHENTAG"), + ("WEEKNUM", "KALENDERWOCHE"), + ("WEIBULL.DIST", "WEIBULL.VERT"), + ("WORKDAY", "ARBEITSTAG"), + ("WORKDAY.INTL", "ARBEITSTAG.INTL"), + // reviewed: sidebar link (page body left WRAPCOLS) | sources: https://support.microsoft.com/de-de/excel/functions/wrapcols-function + ("WRAPCOLS", "SPALTENUMBRUCH"), + // reviewed: page example =ZEILENUMBRUCH + sidebar | sources: https://support.microsoft.com/de-de/excel/functions/wraprows-function + ("WRAPROWS", "ZEILENUMBRUCH"), + ("XIRR", "XINTZINSFUSS"), + ("XLOOKUP", "XVERWEIS"), + ("XMATCH", "XVERGLEICH"), + ("XNPV", "XKAPITALWERT"), + ("XOR", "XODER"), + ("YEAR", "JAHR"), + ("YEARFRAC", "BRTEILJAHRE"), + ("YIELD", "RENDITE"), + ("YIELDDISC", "RENDITEDIS"), + ("YIELDMAT", "RENDITEFÄLL"), + ("Z.TEST", "G.TEST"), + ("ZTEST", "GTEST"), + ], +}; diff --git a/crates/formula/src/input/es.rs b/crates/formula/src/input/es.rs new file mode 100644 index 0000000000..b5a51b142c --- /dev/null +++ b/crates/formula/src/input/es.rs @@ -0,0 +1,506 @@ +//! Español (España): the formula words Spanish Excel shows (function names, booleans, errors, +//! structured-reference specifiers) and its formula separators. +//! +//! Function names come from Microsoft Support's es-es Excel function pages (retrieved +//! 2026-10-10; the pages are machine-translated): per page, a vote among the title, the meta +//! description, the syntax paragraph (aligned with the en-US page) and `=NAME(` examples, and an +//! entry needs two agreeing signals. Entries marked `reviewed` were decided by hand from the page +//! evidence and independent function-name references. Functions not listed keep their English name. +//! +//! Sources for the other words: +//! - bool: https://support.microsoft.com/es-es/excel/functions/true-function | https://raw.githubusercontent.com/PHPOffice/PhpSpreadsheet/master/src/PhpSpreadsheet/Calculation/locale/es/functions | https://raw.githubusercontent.com/handsontable/hyperformula/master/src/i18n/languages/esES.ts +//! - table_items: https://github.com/GrapeCity/spreadjs-resources (SpreadJS v18 ES resource: #Todo,#Datos,#Encabezados,#Totales,#Esta Fila) | https://support.microsoft.com/es-es/excel/using-structured-references-with-excel-tables (lists #Todas for #All; same #Datos,#Encabezados,#Totales,#Esta Fila) +//! - errors.numeric: https://support.microsoft.com/es-es/excel/functions/error-type-function | https://raw.githubusercontent.com/PHPOffice/PhpSpreadsheet/master/src/PhpSpreadsheet/Calculation/locale/es/config | https://github.com/LibreOffice/translations/blob/master/source/es/formula/messages.po +//! - errors.#N/A: https://support.microsoft.com/es-es/excel/functions/na-function (#N/D) | https://raw.githubusercontent.com/handsontable/hyperformula/master/src/i18n/languages/esES.ts (#N/D) | https://github.com/LibreOffice/translations/blob/master/source/es/formula/messages.po (#N/D) | https://es.stackoverflow.com/questions/538707 (cell value #N/D); error-type page table says #N/A +//! - errors.#SPILL!: https://raw.githubusercontent.com/handsontable/hyperformula/master/src/i18n/languages/esES.ts | https://github.com/LibreOffice/translations/blob/master/source/es/formula/messages.po (#¡DESBORDAMIENTO!) | https://support.microsoft.com/es-es/excel/how-to-correct-a-spill-error (drops the ¡) +//! - errors.#CALC!: https://github.com/ibarrasuarez22-ux/MC_regiduria (real Spanish Excel CSV exports contain #¡CALC!) | https://github.com/Carlos1200/gridcalc/blob/main/src/i18n/es.ts +//! - errors.#GETTING_DATA: https://support.microsoft.com/es-es/excel/functions/error-type-function + +use super::Dialect; +use gridcraft_core::CellError; + +pub(super) const DIALECT: Dialect = Dialect { + list: ';', + decimal: ',', + array_column: '\\', + array_row: ';', + bool_true: "VERDADERO", + bool_false: "FALSO", + errors: &[ + (CellError::Null, "#¡NULO!"), + (CellError::Div0, "#¡DIV/0!"), + (CellError::Value, "#¡VALOR!"), + (CellError::Ref, "#¡REF!"), + (CellError::Name, "#¿NOMBRE?"), + (CellError::Num, "#¡NUM!"), + (CellError::NA, "#N/D"), + (CellError::GettingData, "#OBTENIENDO_DATOS"), + (CellError::Spill, "#¡DESBORDAMIENTO!"), + (CellError::Calc, "#¡CALC!"), + ], + table_items: ["#Todo", "#Datos", "#Encabezados", "#Totales", "#Esta fila"], + functions: &[ + ("ACCRINT", "INT.ACUM"), + ("ACCRINTM", "INT.ACUM.V"), + ("ADDRESS", "DIRECCION"), + ("AGGREGATE", "AGREGAR"), + ("AMORDEGRC", "AMORTIZ.PROGRE"), + ("AMORLINC", "AMORTIZ.LIN"), + ("AND", "Y"), + ("ARABIC", "NUMERO.ARABE"), + ("ARRAYTOTEXT", "MATRIZATEXTO"), + ("ASIN", "ASENO"), + ("ASINH", "ASENOH"), + ("AVEDEV", "DESVPROM"), + ("AVERAGE", "PROMEDIO"), + ("AVERAGEA", "PROMEDIOA"), + ("AVERAGEIF", "PROMEDIO.SI"), + ("AVERAGEIFS", "PROMEDIO.SI.CONJUNTO"), + ("BETA.DIST", "DISTR.BETA.N"), + ("BETA.INV", "INV.BETA.N"), + ("BETADIST", "DISTR.BETA"), + ("BETAINV", "DISTR.BETA.INV"), + ("BIN2DEC", "BIN.A.DEC"), + ("BIN2HEX", "BIN.A.HEX"), + ("BIN2OCT", "BIN.A.OCT"), + ("BINOM.DIST", "DISTR.BINOM.N"), + ("BINOM.DIST.RANGE", "DISTR.BINOM.SERIE"), + ("BINOM.INV", "INV.BINOM"), + ("BINOMDIST", "DISTR.BINOM"), + ("BITAND", "BIT.Y"), + ("BITLSHIFT", "BIT.DESPLIZQDA"), + ("BITOR", "BIT.O"), + ("BITRSHIFT", "BIT.DESPLDCHA"), + ("BITXOR", "BIT.XO"), + ("CEILING", "MULTIPLO.SUPERIOR"), + // reviewed: vote was truncated "MATH"; page title/examples MULTIPLO.SUPERIOR.MAT; ONLYOFFICE, zekke, PhpSpreadsheet agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("CEILING.MATH", "MULTIPLO.SUPERIOR.MAT"), + ("CEILING.PRECISE", "MULTIPLO.SUPERIOR.EXACTO"), + ("CELL", "CELDA"), + ("CHAR", "CARACTER"), + ("CHIDIST", "DISTR.CHI"), + ("CHIINV", "PRUEBA.CHI.INV"), + ("CHISQ.DIST", "DISTR.CHICUAD"), + ("CHISQ.DIST.RT", "DISTR.CHICUAD.CD"), + ("CHISQ.INV", "INV.CHICUAD"), + ("CHISQ.INV.RT", "INV.CHICUAD.CD"), + ("CHISQ.TEST", "PRUEBA.CHICUAD"), + ("CHITEST", "PRUEBA.CHI"), + ("CHOOSE", "ELEGIR"), + ("CHOOSECOLS", "ELEGIRCOLS"), + // reviewed: page example ELEGIRFILAS; ONLYOFFICE, zekke agree; page syntax is untranslated MT | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("CHOOSEROWS", "ELEGIRFILAS"), + ("CLEAN", "LIMPIAR"), + ("CODE", "CODIGO"), + ("COLUMN", "COLUMNA"), + ("COLUMNS", "COLUMNAS"), + ("COMBIN", "COMBINAT"), + ("COMPLEX", "COMPLEJO"), + ("CONCATENATE", "CONCATENAR"), + ("CONFIDENCE", "INTERVALO.CONFIANZA"), + ("CONFIDENCE.NORM", "INTERVALO.CONFIANZA.NORM"), + ("CONFIDENCE.T", "INTERVALO.CONFIANZA.T"), + ("CONVERT", "CONVERTIR"), + ("CORREL", "COEF.DE.CORREL"), + ("COUNT", "CONTAR"), + ("COUNTA", "CONTARA"), + ("COUNTBLANK", "CONTAR.BLANCO"), + ("COUNTIF", "CONTAR.SI"), + ("COUNTIFS", "CONTAR.SI.CONJUNTO"), + ("COUPDAYBS", "CUPON.DIAS.L1"), + ("COUPDAYS", "CUPON.DIAS"), + ("COUPDAYSNC", "CUPON.DIAS.L2"), + ("COUPNCD", "CUPON.FECHA.L2"), + ("COUPNUM", "CUPON.NUM"), + ("COUPPCD", "CUPON.FECHA.L1"), + ("COVARIANCE.P", "COVARIANZA.P"), + ("COVARIANCE.S", "COVARIANZA.M"), + ("CRITBINOM", "BINOM.CRIT"), + ("CUBEKPIMEMBER", "MIEMBROKPICUBO"), + ("CUBEMEMBER", "MIEMBROCUBO"), + ("CUBEMEMBERPROPERTY", "PROPIEDADMIEMBROCUBO"), + ("CUBERANKEDMEMBER", "MIEMBRORANGOCUBO"), + ("CUBESET", "CONJUNTOCUBO"), + ("CUBESETCOUNT", "RECUENTOCONJUNTOCUBO"), + ("CUBEVALUE", "VALORCUBO"), + ("CUMIPMT", "PAGO.INT.ENTRE"), + ("CUMPRINC", "PAGO.PRINC.ENTRE"), + ("DATE", "FECHA"), + ("DATEDIF", "SIFECHA"), + ("DATEVALUE", "FECHANUMERO"), + ("DAVERAGE", "BDPROMEDIO"), + ("DAY", "DIA"), + ("DAYS", "DIAS"), + ("DAYS360", "DIAS360"), + ("DCOUNT", "BDCONTAR"), + ("DCOUNTA", "BDCONTARA"), + ("DEC2BIN", "DEC.A.BIN"), + ("DEC2HEX", "DEC.A.HEX"), + ("DEC2OCT", "DEC.A.OCT"), + ("DECIMAL", "CONV.DECIMAL"), + ("DEGREES", "GRADOS"), + ("DEVSQ", "DESVIA2"), + ("DGET", "BDEXTRAER"), + ("DISC", "TASA.DESC"), + ("DMAX", "BDMAX"), + ("DMIN", "BDMIN"), + ("DOLLAR", "MONEDA"), + ("DOLLARDE", "MONEDA.DEC"), + ("DOLLARFR", "MONEDA.FRAC"), + ("DPRODUCT", "BDPRODUCTO"), + // reviewed: page syntax/examples EXCLUIR; ONLYOFFICE, zekke agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("DROP", "EXCLUIR"), + ("DSTDEV", "BDDESVEST"), + ("DSTDEVP", "BDDESVESTP"), + ("DSUM", "BDSUMA"), + ("DURATION", "DURACION"), + ("DVAR", "BDVAR"), + ("DVARP", "BDVARP"), + ("EDATE", "FECHA.MES"), + ("EFFECT", "INT.EFECTIVO"), + // reviewed: page syntax URLCODIF(texto); zekke, PhpSpreadsheet agree; title is untranslated MT | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("ENCODEURL", "URLCODIF"), + ("EOMONTH", "FIN.MES"), + ("ERF", "FUN.ERROR"), + ("ERF.PRECISE", "FUN.ERROR.EXACTO"), + ("ERFC", "FUN.ERROR.COMPL"), + ("ERFC.PRECISE", "FUN.ERROR.COMPL.EXACTO"), + ("ERROR.TYPE", "TIPO.DE.ERROR"), + ("EVEN", "REDONDEA.PAR"), + ("EXACT", "IGUAL"), + // reviewed: page syntax/examples and nav; ONLYOFFICE, zekke agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("EXPAND", "EXPANDIR"), + ("EXPON.DIST", "DISTR.EXP.N"), + ("EXPONDIST", "DISTR.EXP"), + ("F.DIST", "DISTR.F.N"), + ("F.DIST.RT", "DISTR.F.CD"), + ("F.INV", "INV.F"), + ("F.INV.RT", "INV.F.CD"), + ("F.TEST", "PRUEBA.F.N"), + ("FACTDOUBLE", "FACT.DOBLE"), + ("FALSE", "FALSO"), + ("FDIST", "DISTR.F"), + ("FILTER", "FILTRAR"), + // reviewed: page meta/syntax; zekke, PhpSpreadsheet agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("FILTERXML", "XMLFILTRO"), + // reviewed: FIND/FINDB page absent/retired in cache; ONLYOFFICE, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("FIND", "ENCONTRAR"), + // reviewed: B-variant of ENCONTRAR; ONLYOFFICE only (zekke has English FINDB) | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("FINDB", "ENCONTRARB"), + ("FINV", "DISTR.F.INV"), + ("FISHERINV", "PRUEBA.FISHER.INV"), + ("FIXED", "DECIMAL"), + ("FLOOR", "MULTIPLO.INFERIOR"), + ("FLOOR.MATH", "MULTIPLO.INFERIOR.MAT"), + ("FLOOR.PRECISE", "MULTIPLO.INFERIOR.EXACTO"), + ("FORECAST", "PRONOSTICO"), + // reviewed: page syntax and meta; PhpSpreadsheet agrees | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("FORECAST.LINEAR", "PRONOSTICO.LINEAL"), + ("FORMULATEXT", "FORMULATEXTO"), + ("FREQUENCY", "FRECUENCIA"), + ("FTEST", "PRUEBA.F"), + ("FV", "VF"), + ("FVSCHEDULE", "VF.PLAN"), + ("GAMMA.DIST", "DISTR.GAMMA.N"), + ("GAMMA.INV", "INV.GAMMA"), + ("GAMMADIST", "DISTR.GAMMA"), + ("GAMMAINV", "DISTR.GAMMA.INV"), + ("GAMMALN", "GAMMA.LN"), + ("GAMMALN.PRECISE", "GAMMA.LN.EXACTO"), + ("GCD", "M.C.D"), + ("GEOMEAN", "MEDIA.GEOM"), + ("GESTEP", "MAYOR.O.IGUAL"), + ("GROUPBY", "AGRUPARPOR"), + ("GROWTH", "CRECIMIENTO"), + ("HARMEAN", "MEDIA.ARMO"), + ("HEX2BIN", "HEX.A.BIN"), + ("HEX2DEC", "HEX.A.DEC"), + ("HEX2OCT", "HEX.A.OCT"), + ("HLOOKUP", "BUSCARH"), + // reviewed: page title/syntax/examples HORA; all independent sources agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("HOUR", "HORA"), + ("HSTACK", "APILARH"), + ("HYPERLINK", "HIPERVINCULO"), + ("HYPGEOM.DIST", "DISTR.HIPERGEOM.N"), + ("HYPGEOMDIST", "DISTR.HIPERGEOM"), + ("IF", "SI"), + ("IFERROR", "SI.ERROR"), + ("IFNA", "SI.ND"), + ("IFS", "SI.CONJUNTO"), + ("IMABS", "IM.ABS"), + ("IMAGINARY", "IMAGINARIO"), + ("IMARGUMENT", "IM.ANGULO"), + ("IMCONJUGATE", "IM.CONJUGADA"), + ("IMCOS", "IM.COS"), + ("IMCOSH", "IM.COSH"), + ("IMCOT", "IM.COT"), + ("IMCSC", "IM.CSC"), + ("IMCSCH", "IM.CSCH"), + ("IMDIV", "IM.DIV"), + ("IMEXP", "IM.EXP"), + ("IMLN", "IM.LN"), + ("IMLOG10", "IM.LOG10"), + ("IMLOG2", "IM.LOG2"), + ("IMPOWER", "IM.POT"), + ("IMPRODUCT", "IM.PRODUCT"), + ("IMREAL", "IM.REAL"), + ("IMSEC", "IM.SEC"), + ("IMSECH", "IM.SECH"), + ("IMSIN", "IM.SENO"), + ("IMSINH", "IM.SENOH"), + ("IMSQRT", "IM.RAIZ2"), + ("IMSUB", "IM.SUSTR"), + ("IMSUM", "IM.SUM"), + ("IMTAN", "IM.TAN"), + ("INDEX", "INDICE"), + ("INDIRECT", "INDIRECTO"), + ("INT", "ENTERO"), + ("INTERCEPT", "INTERSECCION.EJE"), + ("INTRATE", "TASA.INT"), + ("IPMT", "PAGOINT"), + ("IRR", "TIR"), + // reviewed: IS* page examples/meta list ESBLANCO; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("ISBLANK", "ESBLANCO"), + // reviewed: IS* page examples/meta list ESERR; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("ISERR", "ESERR"), + // reviewed: IS* page examples/meta list ESERROR; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("ISERROR", "ESERROR"), + ("ISEVEN", "ES.PAR"), + ("ISFORMULA", "ESFORMULA"), + // reviewed: IS* page examples/meta list ESLOGICO; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("ISLOGICAL", "ESLOGICO"), + // reviewed: IS* page examples/meta list ESNOD; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("ISNA", "ESNOD"), + // reviewed: IS* page examples/meta list ESNOTEXTO; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("ISNONTEXT", "ESNOTEXTO"), + // reviewed: IS* page examples/meta list ESNUMERO; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("ISNUMBER", "ESNUMERO"), + ("ISO.CEILING", "MULTIPLO.SUPERIOR.ISO"), + ("ISODD", "ES.IMPAR"), + ("ISOWEEKNUM", "ISO.NUM.DE.SEMANA"), + ("ISPMT", "INT.PAGO.DIR"), + // reviewed: IS* page examples/meta list ESREF; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("ISREF", "ESREF"), + // reviewed: IS* page examples/meta list ESTEXTO; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("ISTEXT", "ESTEXTO"), + ("KURT", "CURTOSIS"), + ("LARGE", "K.ESIMO.MAYOR"), + ("LCM", "M.C.M"), + ("LEFT", "IZQUIERDA"), + ("LEFTB", "IZQUIERDAB"), + // reviewed: page meta/syntax: LARGO(texto), LARGOB; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree; vote picked English page title | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("LEN", "LARGO"), + // reviewed: page meta says LARGOB devuelve el número de bytes; ONLYOFFICE, zekke agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("LENB", "LARGOB"), + ("LINEST", "ESTIMACION.LINEAL"), + ("LOGEST", "ESTIMACION.LOGARITMICA"), + ("LOGINV", "DISTR.LOG.INV"), + ("LOGNORM.DIST", "DISTR.LOGNORM"), + ("LOGNORM.INV", "INV.LOGNORM"), + ("LOGNORMDIST", "DISTR.LOG.NORM"), + ("LOOKUP", "BUSCAR"), + ("LOWER", "MINUSC"), + ("MATCH", "COINCIDIR"), + ("MAXIFS", "MAX.SI.CONJUNTO"), + ("MDURATION", "DURACION.MODIF"), + ("MEDIAN", "MEDIANA"), + ("MID", "EXTRAE"), + ("MIDB", "EXTRAEB"), + ("MINIFS", "MIN.SI.CONJUNTO"), + ("MINUTE", "MINUTO"), + ("MINVERSE", "MINVERSA"), + ("MIRR", "TIRM"), + ("MOD", "RESIDUO"), + ("MODE", "MODA"), + ("MODE.MULT", "MODA.VARIOS"), + ("MODE.SNGL", "MODA.UNO"), + ("MONTH", "MES"), + ("MROUND", "REDOND.MULT"), + ("MUNIT", "M.UNIDAD"), + ("NA", "NOD"), + ("NETWORKDAYS", "DIAS.LAB"), + ("NETWORKDAYS.INTL", "DIAS.LAB.INTL"), + ("NOMINAL", "TASA.NOMINAL"), + ("NORM.DIST", "DISTR.NORM.N"), + ("NORM.INV", "INV.NORM"), + ("NORM.S.DIST", "DISTR.NORM.ESTAND.N"), + ("NORM.S.INV", "INV.NORM.ESTAND"), + ("NORMDIST", "DISTR.NORM"), + ("NORMINV", "DISTR.NORM.INV"), + ("NORMSDIST", "DISTR.NORM.ESTAND"), + ("NORMSINV", "DISTR.NORM.ESTAND.INV"), + ("NOT", "NO"), + ("NOW", "AHORA"), + ("NPV", "VNA"), + ("NUMBERVALUE", "VALOR.NUMERO"), + ("OCT2BIN", "OCT.A.BIN"), + ("OCT2DEC", "OCT.A.DEC"), + ("OCT2HEX", "OCT.A.HEX"), + ("ODD", "REDONDEA.IMPAR"), + ("OFFSET", "DESREF"), + ("OR", "O"), + ("PDURATION", "P.DURACION"), + ("PERCENTILE", "PERCENTIL"), + // reviewed: vote was truncated "EXC"; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula and Microsoft nav list agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("PERCENTILE.EXC", "PERCENTIL.EXC"), + ("PERCENTILE.INC", "PERCENTIL.INC"), + ("PERCENTRANK", "RANGO.PERCENTIL"), + ("PERCENTRANK.EXC", "RANGO.PERCENTIL.EXC"), + ("PERCENTRANK.INC", "RANGO.PERCENTIL.INC"), + ("PERMUT", "PERMUTACIONES"), + ("PERMUTATIONA", "PERMUTACIONES.A"), + ("PHI", "FI"), + ("PHONETIC", "FONETICO"), + ("PIVOTBY", "PIVOTARPOR"), + ("PMT", "PAGO"), + ("POWER", "POTENCIA"), + ("PPMT", "PAGOPRIN"), + ("PRICE", "PRECIO"), + ("PRICEDISC", "PRECIO.DESCUENTO"), + ("PRICEMAT", "PRECIO.VENCIMIENTO"), + ("PROB", "PROBABILIDAD"), + ("PRODUCT", "PRODUCTO"), + ("PROPER", "NOMPROPIO"), + ("PV", "VA"), + ("QUARTILE", "CUARTIL"), + ("QUARTILE.EXC", "CUARTIL.EXC"), + ("QUARTILE.INC", "CUARTIL.INC"), + ("QUOTIENT", "COCIENTE"), + ("RADIANS", "RADIANES"), + // reviewed: vote was truncated "ALEAT"; page examples contain ALEATORIO; ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("RAND", "ALEATORIO"), + ("RANDARRAY", "MATRIZALEAT"), + ("RANDBETWEEN", "ALEATORIO.ENTRE"), + ("RANK", "JERARQUIA"), + ("RANK.AVG", "JERARQUIA.MEDIA"), + ("RANK.EQ", "JERARQUIA.EQV"), + ("RATE", "TASA"), + ("RECEIVED", "CANTIDAD.RECIBIDA"), + ("REGEXEXTRACT", "REGEXEXTRACCION"), + // reviewed: page title/meta; ONLYOFFICE agrees (zekke English) | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("REGEXREPLACE", "REGEXREEMPLAZAR"), + // reviewed: page title/meta; ONLYOFFICE agrees (zekke English) | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("REGEXTEST", "REGEXPRUEBA"), + ("REPLACE", "REEMPLAZAR"), + // reviewed: REEMPLAZAR page meta lists REEMPLAZARB; ONLYOFFICE, zekke agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("REPLACEB", "REEMPLAZARB"), + ("REPT", "REPETIR"), + ("RIGHT", "DERECHA"), + ("RIGHTB", "DERECHAB"), + ("ROMAN", "NUMERO.ROMANO"), + ("ROUND", "REDONDEAR"), + ("ROUNDDOWN", "REDONDEAR.MENOS"), + ("ROUNDUP", "REDONDEAR.MAS"), + ("ROW", "FILA"), + ("ROWS", "FILAS"), + ("RSQ", "COEFICIENTE.R2"), + ("SEARCH", "HALLAR"), + ("SEARCHB", "HALLARB"), + ("SECOND", "SEGUNDO"), + ("SEQUENCE", "SECUENCIA"), + ("SERIESSUM", "SUMA.SERIES"), + ("SHEET", "HOJA"), + ("SHEETS", "HOJAS"), + ("SIGN", "SIGNO"), + ("SIN", "SENO"), + // reviewed: page syntax SENOH(número); ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree; consistent with SENO/ASENOH | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("SINH", "SENOH"), + ("SKEW", "COEFICIENTE.ASIMETRIA"), + ("SKEW.P", "COEFICIENTE.ASIMETRIA.P"), + ("SLOPE", "PENDIENTE"), + ("SMALL", "K.ESIMO.MENOR"), + ("SORT", "ORDENAR"), + ("SORTBY", "ORDENARPOR"), + ("SQRT", "RAIZ"), + ("SQRTPI", "RAIZ2PI"), + ("STANDARDIZE", "NORMALIZACION"), + ("STDEV", "DESVEST"), + ("STDEV.P", "DESVEST.P"), + ("STDEV.S", "DESVEST.M"), + ("STDEVA", "DESVESTA"), + ("STDEVP", "DESVESTP"), + ("STDEVPA", "DESVESTPA"), + ("STEYX", "ERROR.TIPICO.XY"), + ("SUBSTITUTE", "SUSTITUIR"), + ("SUBTOTAL", "SUBTOTALES"), + ("SUM", "SUMA"), + ("SUMIF", "SUMAR.SI"), + ("SUMIFS", "SUMAR.SI.CONJUNTO"), + ("SUMPRODUCT", "SUMAPRODUCTO"), + ("SUMSQ", "SUMA.CUADRADOS"), + ("SUMX2MY2", "SUMAX2MENOSY2"), + ("SUMX2PY2", "SUMAX2MASY2"), + ("SUMXMY2", "SUMAXMENOSY2"), + ("SWITCH", "CAMBIAR"), + ("T.DIST", "DISTR.T.N"), + ("T.DIST.2T", "DISTR.T.2C"), + ("T.DIST.RT", "DISTR.T.CD"), + ("T.INV", "INV.T"), + ("T.INV.2T", "INV.T.2C"), + ("T.TEST", "PRUEBA.T.N"), + ("TAKE", "TOMAR"), + // reviewed: syntax+examples+Microsoft nav list say TEST; page title/meta and ONLYOFFICE say TES; zekke/PhpSpreadsheet/HyperFormula say TEST | sources: MS nav+syntax, PhpSpreadsheet, zekke, HyperFormula (TEST); ONLYOFFICE TES + ("TBILLEQ", "LETRA.DE.TEST.EQV.A.BONO"), + ("TBILLPRICE", "LETRA.DE.TES.PRECIO"), + ("TBILLYIELD", "LETRA.DE.TES.RENDTO"), + ("TDIST", "DISTR.T"), + ("TEXT", "TEXTO"), + // reviewed: page meta and example TEXTODESPUES; ONLYOFFICE, zekke agree; syntax line is untranslated MT | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("TEXTAFTER", "TEXTODESPUES"), + // reviewed: page example TEXTOANTES; ONLYOFFICE, zekke agree; syntax line is untranslated MT | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("TEXTBEFORE", "TEXTOANTES"), + ("TEXTJOIN", "UNIRCADENAS"), + // reviewed: page syntax/examples, nav; ONLYOFFICE, zekke agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("TEXTSPLIT", "DIVIDIRTEXTO"), + // reviewed: page meta/examples NSHORA (HORA is HOUR); ONLYOFFICE, zekke, PhpSpreadsheet, HyperFormula agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("TIME", "NSHORA"), + ("TIMEVALUE", "HORANUMERO"), + ("TINV", "DISTR.T.INV"), + // reviewed: page syntax/examples, nav; ONLYOFFICE, zekke agree | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("TOCOL", "ENCOL"), + ("TODAY", "HOY"), + // reviewed: Microsoft nav list ENFILA; ONLYOFFICE, zekke agree; page body untranslated MT | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("TOROW", "ENFILA"), + ("TRANSPOSE", "TRANSPONER"), + ("TREND", "TENDENCIA"), + ("TRIM", "ESPACIOS"), + ("TRIMMEAN", "MEDIA.ACOTADA"), + // reviewed: page meta/examples VERDADERO; all independent sources agree; vote picked truncated "VERDAD" | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("TRUE", "VERDADERO"), + ("TRUNC", "TRUNCAR"), + ("TTEST", "PRUEBA.T"), + ("TYPE", "TIPO"), + ("UNICHAR", "UNICAR"), + // reviewed: page title "Función UNICOS" and meta; HyperFormula UNICOS; ONLYOFFICE/zekke only have English fallback | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("UNIQUE", "UNICOS"), + ("UPPER", "MAYUSC"), + ("VALUE", "VALOR"), + ("VALUETOTEXT", "VALORATEXTO"), + ("VDB", "DVS"), + ("VLOOKUP", "BUSCARV"), + ("VSTACK", "APILARV"), + ("WEBSERVICE", "SERVICIOWEB"), + ("WEEKDAY", "DIASEM"), + ("WEEKNUM", "NUM.DE.SEMANA"), + ("WEIBULL", "DIST.WEIBULL"), + ("WEIBULL.DIST", "DISTR.WEIBULL"), + ("WORKDAY", "DIA.LAB"), + ("WORKDAY.INTL", "DIA.LAB.INTL"), + // reviewed: Microsoft nav list AJUSTARCOLS + ONLYOFFICE; zekke English; page body untranslated MT | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("WRAPCOLS", "AJUSTARCOLS"), + // reviewed: Microsoft nav list AJUSTARFILAS + ONLYOFFICE; zekke English; page body untranslated MT | sources: OO=https://raw.githubusercontent.com/ONLYOFFICE/web-apps/master/apps/spreadsheeteditor/main/resources/formula-lang/es.json | ZK=https://raw.githubusercontent.com/zekke-io/zekke/main/src/lib/spreadsheets/function-names/es.json + ("WRAPROWS", "AJUSTARFILAS"), + ("XIRR", "TIR.NO.PER"), + ("XLOOKUP", "BUSCARX"), + ("XMATCH", "COINCIDIRX"), + ("XNPV", "VNA.NO.PER"), + ("XOR", "XO"), + ("YEAR", "AÑO"), + ("YEARFRAC", "FRAC.AÑO"), + ("YIELD", "RENDTO"), + ("YIELDDISC", "RENDTO.DESC"), + ("YIELDMAT", "RENDTO.VENCTO"), + ("Z.TEST", "PRUEBA.Z.N"), + ("ZTEST", "PRUEBA.Z"), + ], +}; diff --git a/crates/formula/src/input/it.rs b/crates/formula/src/input/it.rs new file mode 100644 index 0000000000..9e79444ddc --- /dev/null +++ b/crates/formula/src/input/it.rs @@ -0,0 +1,505 @@ +//! Italiano (Italia): the formula words Italian Excel shows (function names, booleans, errors, +//! structured-reference specifiers) and its formula separators. +//! +//! Function names are the ones Italian Excel uses (feature names, as `AGENTS.md` allows), written +//! from knowledge of Italian Excel with an AI agent; ERRORE.TIPO was checked against its it-it +//! Microsoft Support page. The names have not yet been observed one by one in a licensed Italian +//! Excel, nor reviewed by a second native speaker. Functions not listed keep their English name there (MAX, MIN, INT, +//! LAMBDA, LET, the LAMBDA helpers, CONCAT, SWITCH, XOR…). GROUPBY, PIVOTBY, PERCENTOF, +//! TRIMRANGE, ISOMITTED and the REGEX functions also keep English names here until their Italian +//! spelling is observed. +//! +//! Sources for the other words: +//! - separators: `;` between arguments and `,` as the decimal mark (Italian regional format). +//! Array constants: `\` between columns and `.` between rows, from the example +//! `={1\2\3\4.5\6\7\8.9\10\11\12}` on https://support.microsoft.com/it-it/excel/use-array-constants-in-array-formulas +//! and the accepted answer at https://learn.microsoft.com/it-it/answers/questions/adff5f1f-3e7d-4f10-96b1-c9e77f51ecd8 +//! (`={1\2\3\4\5}` horizontal, `={1.2.3.4.5}` vertical, `;` rejected inside braces). +//! - bool: `VERO`, `FALSO`. +//! - errors.#NULLO!..#N/D,#ESTRAZIONE_DATI_IN_CORSO: https://support.microsoft.com/it-it/excel/functions/error-type-function (ERRORE.TIPO table). +//! - errors.#ESPANSIONE!, #CALC!: the names Italian Excel shows for #SPILL! and #CALC!; not observed here. +//! - table_items: `#Tutti`, `#Dati`, `#Intestazioni`, `#Totali`, `#Questa riga`; the it-it +//! structured-references page keeps the English specifiers in its (machine-translated) +//! examples, so these are not confirmed by a Microsoft page. + +use super::Dialect; +use gridcraft_core::CellError; + +pub(super) const DIALECT: Dialect = Dialect { + list: ';', + decimal: ',', + array_column: '\\', + array_row: '.', + bool_true: "VERO", + bool_false: "FALSO", + errors: &[ + (CellError::Null, "#NULLO!"), + (CellError::Div0, "#DIV/0!"), + (CellError::Value, "#VALORE!"), + (CellError::Ref, "#RIF!"), + (CellError::Name, "#NOME?"), + (CellError::Num, "#NUM!"), + (CellError::NA, "#N/D"), + (CellError::GettingData, "#ESTRAZIONE_DATI_IN_CORSO"), + (CellError::Spill, "#ESPANSIONE!"), + (CellError::Calc, "#CALC!"), + ], + table_items: ["#Tutti", "#Dati", "#Intestazioni", "#Totali", "#Questa riga"], + functions: &[ + ("ABS", "ASS"), + ("ACCRINT", "INT.MATURATO.PER"), + ("ACCRINTM", "INT.MATURATO.SCAD"), + ("ACOS", "ARCCOS"), + ("ACOSH", "ARCCOSH"), + ("ACOT", "ARCCOT"), + ("ACOTH", "ARCCOTH"), + ("ADDRESS", "INDIRIZZO"), + ("AGGREGATE", "AGGREGA"), + ("AMORDEGRC", "AMMORT.DEGR"), + ("AMORLINC", "AMMORT.PER"), + ("AND", "E"), + ("ARABIC", "ARABO"), + ("AREAS", "AREE"), + ("ARRAYTOTEXT", "MATRICE.A.TESTO"), + ("ASIN", "ARCSEN"), + ("ASINH", "ARCSENH"), + ("ATAN", "ARCTAN"), + ("ATAN2", "ARCTAN.2"), + ("ATANH", "ARCTANH"), + ("AVEDEV", "MEDIA.DEV"), + ("AVERAGE", "MEDIA"), + ("AVERAGEA", "MEDIA.VALORI"), + ("AVERAGEIF", "MEDIA.SE"), + ("AVERAGEIFS", "MEDIA.PIÙ.SE"), + ("BAHTTEXT", "BAHTTESTO"), + ("BESSELI", "BESSEL.I"), + ("BESSELJ", "BESSEL.J"), + ("BESSELK", "BESSEL.K"), + ("BESSELY", "BESSEL.Y"), + ("BETA.DIST", "DISTRIB.BETA.N"), + ("BETA.INV", "INV.BETA.N"), + ("BETADIST", "DISTRIB.BETA"), + ("BETAINV", "INV.BETA"), + ("BIN2DEC", "BINARIO.DECIMALE"), + ("BIN2HEX", "BINARIO.HEX"), + ("BIN2OCT", "BINARIO.OCT"), + ("BINOM.DIST", "DISTRIB.BINOM.N"), + ("BINOM.DIST.RANGE", "INTERVALLO.DISTRIB.BINOM.N"), + ("BINOM.INV", "INV.BINOM"), + ("BINOMDIST", "DISTRIB.BINOM"), + ("BITLSHIFT", "BIT.SPOSTA.SX"), + ("BITRSHIFT", "BIT.SPOSTA.DX"), + ("CEILING", "ARROTONDA.ECCESSO"), + ("CEILING.MATH", "ARROTONDA.ECCESSO.MAT"), + ("CEILING.PRECISE", "ARROTONDA.ECCESSO.PRECISA"), + ("CELL", "CELLA"), + ("CHAR", "CODICE.CARATT"), + ("CHIDIST", "DISTRIB.CHI"), + ("CHIINV", "INV.CHI"), + ("CHISQ.DIST", "DISTRIB.CHI.QUAD"), + ("CHISQ.DIST.RT", "DISTRIB.CHI.QUAD.DS"), + ("CHISQ.INV", "INV.CHI.QUAD"), + ("CHISQ.INV.RT", "INV.CHI.QUAD.DS"), + ("CHISQ.TEST", "TEST.CHI.QUAD"), + ("CHITEST", "TEST.CHI"), + ("CHOOSE", "SCEGLI"), + ("CHOOSECOLS", "SCEGLI.COL"), + ("CHOOSEROWS", "SCEGLI.RIGA"), + ("CLEAN", "LIBERA"), + ("CODE", "CODICE"), + ("COLUMN", "RIF.COLONNA"), + ("COLUMNS", "COLONNE"), + ("COMBIN", "COMBINAZIONE"), + ("COMBINA", "COMBINAZIONE.VALORI"), + ("COMPLEX", "COMPLESSO"), + ("CONCATENATE", "CONCATENA"), + ("CONFIDENCE", "CONFIDENZA"), + ("CONFIDENCE.NORM", "CONFIDENZA.NORM"), + ("CONFIDENCE.T", "CONFIDENZA.T"), + ("CONVERT", "CONVERTI"), + ("CORREL", "CORRELAZIONE"), + ("COUNT", "CONTA.NUMERI"), + ("COUNTA", "CONTA.VALORI"), + ("COUNTBLANK", "CONTA.VUOTE"), + ("COUNTIF", "CONTA.SE"), + ("COUNTIFS", "CONTA.PIÙ.SE"), + ("COUPDAYBS", "GIORNI.CED.INIZ.LIQ"), + ("COUPDAYS", "GIORNI.CED"), + ("COUPDAYSNC", "GIORNI.CED.NUOVA"), + ("COUPNCD", "DATA.CED.SUCC"), + ("COUPNUM", "NUM.CED"), + ("COUPPCD", "DATA.CED.PREC"), + ("COVAR", "COVARIANZA"), + ("COVARIANCE.P", "COVARIANZA.P"), + ("COVARIANCE.S", "COVARIANZA.C"), + ("CRITBINOM", "CRIT.BINOM"), + ("CUBEKPIMEMBER", "MEMBRO.KPI.CUBO"), + ("CUBEMEMBER", "MEMBRO.CUBO"), + ("CUBEMEMBERPROPERTY", "PROPRIETÀ.MEMBRO.CUBO"), + ("CUBERANKEDMEMBER", "MEMBRO.CUBO.CON.RANGO"), + ("CUBESET", "SET.CUBO"), + ("CUBESETCOUNT", "CONTA.SET.CUBO"), + ("CUBEVALUE", "VALORE.CUBO"), + ("CUMIPMT", "INT.CUMUL"), + ("CUMPRINC", "CAP.CUM"), + ("DATE", "DATA"), + ("DATEDIF", "DATA.DIFF"), + ("DATEVALUE", "DATA.VALORE"), + ("DAVERAGE", "DB.MEDIA"), + ("DAY", "GIORNO"), + ("DAYS", "GIORNI"), + ("DAYS360", "GIORNO360"), + ("DB", "AMMORT.FISSO"), + ("DCOUNT", "DB.CONTA.NUMERI"), + ("DCOUNTA", "DB.CONTA.VALORI"), + ("DDB", "AMMORT"), + ("DEC2BIN", "DECIMALE.BINARIO"), + ("DEC2HEX", "DECIMALE.HEX"), + ("DEC2OCT", "DECIMALE.OCT"), + ("DECIMAL", "DECIMALE"), + ("DEGREES", "GRADI"), + ("DEVSQ", "DEV.Q"), + ("DGET", "DB.VALORI"), + ("DISC", "TASSO.SCONTO"), + ("DMAX", "DB.MAX"), + ("DMIN", "DB.MIN"), + ("DOLLAR", "VALUTA"), + ("DOLLARDE", "VALUTA.DEC"), + ("DOLLARFR", "VALUTA.FRAZ"), + ("DPRODUCT", "DB.PRODOTTO"), + ("DROP", "ESCLUDI"), + ("DSTDEV", "DB.DEV.ST"), + ("DSTDEVP", "DB.DEV.ST.POP"), + ("DSUM", "DB.SOMMA"), + ("DURATION", "DURATA"), + ("DVAR", "DB.VAR"), + ("DVARP", "DB.VAR.POP"), + ("EDATE", "DATA.MESE"), + ("EFFECT", "EFFETTIVO"), + ("ENCODEURL", "CODIFICA.URL"), + ("EOMONTH", "FINE.MESE"), + ("ERF", "FUNZ.ERRORE"), + ("ERF.PRECISE", "FUNZ.ERRORE.PRECISA"), + ("ERFC", "FUNZ.ERRORE.COMP"), + ("ERFC.PRECISE", "FUNZ.ERRORE.COMP.PRECISA"), + ("ERROR.TYPE", "ERRORE.TIPO"), + ("EVEN", "PARI"), + ("EXACT", "IDENTICO"), + ("EXPAND", "ESPANDI"), + ("EXPON.DIST", "DISTRIB.EXP.N"), + ("EXPONDIST", "DISTRIB.EXP"), + ("F.DIST", "DISTRIBF"), + ("F.DIST.RT", "DISTRIB.F.DS"), + ("F.INV", "INVF"), + ("F.INV.RT", "INV.F.DS"), + ("F.TEST", "TESTF"), + ("FACT", "FATTORIALE"), + ("FACTDOUBLE", "FATT.DOPPIO"), + ("FALSE", "FALSO"), + ("FDIST", "DISTRIB.F"), + ("FILTER", "FILTRO"), + ("FILTERXML", "FILTRO.XML"), + ("FIND", "TROVA"), + ("FINDB", "TROVA.B"), + ("FINV", "INV.F"), + ("FISHERINV", "INV.FISHER"), + ("FIXED", "FISSO"), + ("FLOOR", "ARROTONDA.DIFETTO"), + ("FLOOR.MATH", "ARROTONDA.DIFETTO.MAT"), + ("FLOOR.PRECISE", "ARROTONDA.DIFETTO.PRECISA"), + ("FORECAST", "PREVISIONE"), + ("FORECAST.ETS", "PREVISIONE.ETS"), + ("FORECAST.ETS.CONFINT", "PREVISIONE.ETS.INTCONF"), + ("FORECAST.ETS.SEASONALITY", "PREVISIONE.ETS.STAGIONALITÀ"), + ("FORECAST.ETS.STAT", "PREVISIONE.ETS.STAT"), + ("FORECAST.LINEAR", "PREVISIONE.LINEARE"), + ("FORMULATEXT", "TESTO.FORMULA"), + ("FREQUENCY", "FREQUENZA"), + ("FTEST", "TEST.F"), + ("FV", "VAL.FUT"), + ("FVSCHEDULE", "VAL.FUT.CAPITALE"), + ("GAMMA.DIST", "DISTRIB.GAMMA.N"), + ("GAMMA.INV", "INV.GAMMA.N"), + ("GAMMADIST", "DISTRIB.GAMMA"), + ("GAMMAINV", "INV.GAMMA"), + ("GAMMALN", "LN.GAMMA"), + ("GAMMALN.PRECISE", "LN.GAMMA.PRECISA"), + ("GCD", "MCD"), + ("GEOMEAN", "MEDIA.GEOMETRICA"), + ("GESTEP", "SOGLIA"), + ("GROWTH", "CRESCITA"), + ("HARMEAN", "MEDIA.ARMONICA"), + ("HEX2BIN", "HEX.BINARIO"), + ("HEX2DEC", "HEX.DECIMALE"), + ("HEX2OCT", "HEX.OCT"), + ("HLOOKUP", "CERCA.ORIZZ"), + ("HOUR", "ORA"), + ("HSTACK", "STACK.ORIZ"), + ("HYPERLINK", "COLLEG.IPERTESTUALE"), + ("HYPGEOM.DIST", "DISTRIB.IPERGEOM.N"), + ("HYPGEOMDIST", "DISTRIB.IPERGEOM"), + ("IF", "SE"), + ("IFERROR", "SE.ERRORE"), + ("IFNA", "SE.NON.DISP."), + ("IFS", "PIÙ.SE"), + ("IMABS", "COMP.MODULO"), + ("IMAGINARY", "COMP.IMMAGINARIO"), + ("IMARGUMENT", "COMP.ARGOMENTO"), + ("IMCONJUGATE", "COMP.CONIUGATO"), + ("IMCOS", "COMP.COS"), + ("IMCOSH", "COMP.COSH"), + ("IMCOT", "COMP.COT"), + ("IMCSC", "COMP.CSC"), + ("IMCSCH", "COMP.CSCH"), + ("IMDIV", "COMP.DIV"), + ("IMEXP", "COMP.EXP"), + ("IMLN", "COMP.LN"), + ("IMLOG10", "COMP.LOG10"), + ("IMLOG2", "COMP.LOG2"), + ("IMPOWER", "COMP.POTENZA"), + ("IMPRODUCT", "COMP.PRODOTTO"), + ("IMREAL", "COMP.PARTE.REALE"), + ("IMSEC", "COMP.SEC"), + ("IMSECH", "COMP.SECH"), + ("IMSIN", "COMP.SEN"), + ("IMSINH", "COMP.SENH"), + ("IMSQRT", "COMP.RADQ"), + ("IMSUB", "COMP.DIFF"), + ("IMSUM", "COMP.SOMMA"), + ("IMTAN", "COMP.TAN"), + ("INDEX", "INDICE"), + ("INDIRECT", "INDIRETTO"), + ("INFO", "AMBIENTE.INFO"), + ("INTERCEPT", "INTERCETTA"), + ("INTRATE", "TASSO.INT"), + ("IPMT", "INTERESSI"), + ("IRR", "TIR.COST"), + ("ISBLANK", "VAL.VUOTO"), + ("ISERR", "VAL.ERR"), + ("ISERROR", "VAL.ERRORE"), + ("ISEVEN", "VAL.PARI"), + ("ISFORMULA", "VAL.FORMULA"), + ("ISLOGICAL", "VAL.LOGICO"), + ("ISNA", "VAL.NON.DISP"), + ("ISNONTEXT", "VAL.NON.TESTO"), + ("ISNUMBER", "VAL.NUMERO"), + ("ISO.CEILING", "ISO.ARROTONDA.ECCESSO"), + ("ISODD", "VAL.DISPARI"), + ("ISOWEEKNUM", "NUM.SETTIMANA.ISO"), + ("ISPMT", "INTERESSE.RATA"), + ("ISREF", "VAL.RIF"), + ("ISTEXT", "VAL.TESTO"), + ("KURT", "CURTOSI"), + ("LARGE", "GRANDE"), + ("LCM", "MCM"), + ("LEFT", "SINISTRA"), + ("LEFTB", "SINISTRA.B"), + ("LEN", "LUNGHEZZA"), + ("LENB", "LUNGB"), + ("LINEST", "REGR.LIN"), + ("LOGEST", "REGR.LOG"), + ("LOGINV", "INV.LOGNORM"), + ("LOGNORM.DIST", "DISTRIB.LOGNORM.N"), + ("LOGNORM.INV", "INV.LOGNORM.N"), + ("LOGNORMDIST", "DISTRIB.LOGNORM"), + ("LOOKUP", "CERCA"), + ("LOWER", "MINUSC"), + ("MATCH", "CONFRONTA"), + ("MAXA", "MAX.VALORI"), + ("MAXIFS", "MAX.PIÙ.SE"), + ("MDETERM", "MATR.DETERM"), + ("MDURATION", "DURATA.M"), + ("MEDIAN", "MEDIANA"), + ("MID", "STRINGA.ESTRAI"), + ("MIDB", "MEDIA.B"), + ("MINA", "MIN.VALORI"), + ("MINIFS", "MIN.PIÙ.SE"), + ("MINUTE", "MINUTO"), + ("MINVERSE", "MATR.INVERSA"), + ("MIRR", "TIR.VAR"), + ("MMULT", "MATR.PRODOTTO"), + ("MOD", "RESTO"), + ("MODE", "MODA"), + ("MODE.MULT", "MODA.MULT"), + ("MODE.SNGL", "MODA.SNGL"), + ("MONTH", "MESE"), + ("MROUND", "ARROTONDA.MULTIPLO"), + ("MULTINOMIAL", "MULTINOMIALE"), + ("MUNIT", "MATR.UNIT"), + ("N", "NUM"), + ("NA", "NON.DISP"), + ("NEGBINOM.DIST", "DISTRIB.BINOM.NEG.N"), + ("NEGBINOMDIST", "DISTRIB.BINOM.NEG"), + ("NETWORKDAYS", "GIORNI.LAVORATIVI.TOT"), + ("NETWORKDAYS.INTL", "GIORNI.LAVORATIVI.TOT.INTL"), + ("NOMINAL", "NOMINALE"), + ("NORM.DIST", "DISTRIB.NORM.N"), + ("NORM.INV", "INV.NORM.N"), + ("NORM.S.DIST", "DISTRIB.NORM.ST.N"), + ("NORM.S.INV", "INV.NORM.S"), + ("NORMDIST", "DISTRIB.NORM"), + ("NORMINV", "INV.NORM"), + ("NORMSDIST", "DISTRIB.NORM.ST"), + ("NORMSINV", "INV.NORM.ST"), + ("NOT", "NON"), + ("NOW", "ADESSO"), + ("NPER", "NUM.RATE"), + ("NPV", "VAN"), + ("NUMBERVALUE", "NUMERO.VALORE"), + ("OCT2BIN", "OCT.BINARIO"), + ("OCT2DEC", "OCT.DECIMALE"), + ("OCT2HEX", "OCT.HEX"), + ("ODD", "DISPARI"), + ("ODDFPRICE", "PREZZO.PRIMO.IRR"), + ("ODDFYIELD", "REND.PRIMO.IRR"), + ("ODDLPRICE", "PREZZO.ULTIMO.IRR"), + ("ODDLYIELD", "REND.ULTIMO.IRR"), + ("OFFSET", "SCARTO"), + ("OR", "O"), + ("PDURATION", "DURATA.P"), + ("PERCENTILE.EXC", "ESC.PERCENTILE"), + ("PERCENTILE.INC", "INC.PERCENTILE"), + ("PERCENTRANK", "PERCENT.RANGO"), + ("PERCENTRANK.EXC", "ESC.PERCENT.RANGO"), + ("PERCENTRANK.INC", "INC.PERCENT.RANGO"), + ("PERMUT", "PERMUTAZIONE"), + ("PERMUTATIONA", "PERMUTAZIONE.VALORI"), + ("PHONETIC", "FURIGANA"), + ("PI", "PI.GRECO"), + ("PMT", "RATA"), + ("POISSON.DIST", "DISTRIB.POISSON"), + ("POWER", "POTENZA"), + ("PPMT", "P.RATA"), + ("PRICE", "PREZZO"), + ("PRICEDISC", "PREZZO.SCONT"), + ("PRICEMAT", "PREZZO.SCAD"), + ("PROB", "PROBABILITÀ"), + ("PRODUCT", "PRODOTTO"), + ("PROPER", "MAIUSC.INIZ"), + ("PV", "VA"), + ("QUARTILE.EXC", "ESC.QUARTILE"), + ("QUARTILE.INC", "INC.QUARTILE"), + ("QUOTIENT", "QUOZIENTE"), + ("RADIANS", "RADIANTI"), + ("RAND", "CASUALE"), + ("RANDARRAY", "MATR.CASUALE"), + ("RANDBETWEEN", "CASUALE.TRA"), + ("RANK", "RANGO"), + ("RANK.AVG", "RANGO.MEDIA"), + ("RANK.EQ", "RANGO.UG"), + ("RATE", "TASSO"), + ("RECEIVED", "RICEV.SCAD"), + ("REPLACE", "RIMPIAZZA"), + ("REPLACEB", "SOSTITUISCI.B"), + ("REPT", "RIPETI"), + ("RIGHT", "DESTRA"), + ("RIGHTB", "DESTRA.B"), + ("ROMAN", "ROMANO"), + ("ROUND", "ARROTONDA"), + ("ROUNDDOWN", "ARROTONDA.PER.DIF"), + ("ROUNDUP", "ARROTONDA.PER.ECC"), + ("ROW", "RIF.RIGA"), + ("ROWS", "RIGHE"), + ("RRI", "RIT.INVEST.EFFETT"), + ("RSQ", "RQ"), + ("SEARCH", "RICERCA"), + ("SEARCHB", "CERCA.B"), + ("SECOND", "SECONDO"), + ("SEQUENCE", "SEQUENZA"), + ("SERIESSUM", "SOMMA.SERIE"), + ("SHEET", "FOGLIO"), + ("SHEETS", "FOGLI"), + ("SIGN", "SEGNO"), + ("SIN", "SEN"), + ("SINH", "SENH"), + ("SKEW", "ASIMMETRIA"), + ("SKEW.P", "ASIMMETRIA.P"), + ("SLN", "AMMORT.COST"), + ("SLOPE", "PENDENZA"), + ("SMALL", "PICCOLO"), + ("SORT", "DATI.ORDINA"), + ("SORTBY", "DATI.ORDINA.PER"), + ("SQRT", "RADQ"), + ("SQRTPI", "RADQ.PI.GRECO"), + ("STANDARDIZE", "NORMALIZZA"), + ("STDEV", "DEV.ST"), + ("STDEV.P", "DEV.ST.P"), + ("STDEV.S", "DEV.ST.C"), + ("STDEVA", "DEV.ST.VALORI"), + ("STDEVP", "DEV.ST.POP"), + ("STDEVPA", "DEV.ST.POP.VALORI"), + ("STEYX", "ERR.STD.YX"), + ("SUBSTITUTE", "SOSTITUISCI"), + ("SUBTOTAL", "SUBTOTALE"), + ("SUM", "SOMMA"), + ("SUMIF", "SOMMA.SE"), + ("SUMIFS", "SOMMA.PIÙ.SE"), + ("SUMPRODUCT", "MATR.SOMMA.PRODOTTO"), + ("SUMSQ", "SOMMA.Q"), + ("SUMX2MY2", "SOMMA.DIFF.Q"), + ("SUMX2PY2", "SOMMA.SOMMA.Q"), + ("SUMXMY2", "SOMMA.Q.DIFF"), + ("SYD", "AMMORT.ANNUO"), + ("T.DIST", "DISTRIB.T.N"), + ("T.DIST.2T", "DISTRIB.T.2T"), + ("T.DIST.RT", "DISTRIB.T.DS"), + ("T.INV", "INVT"), + ("T.INV.2T", "INV.T.2T"), + ("T.TEST", "TESTT"), + ("TAKE", "PRENDI"), + ("TBILLEQ", "BOT.EQUIV"), + ("TBILLPRICE", "BOT.PREZZO"), + ("TBILLYIELD", "BOT.REND"), + ("TDIST", "DISTRIB.T"), + ("TEXT", "TESTO"), + ("TEXTAFTER", "TESTO.DOPO"), + ("TEXTBEFORE", "TESTO.PRIMA"), + ("TEXTJOIN", "TESTO.UNISCI"), + ("TEXTSPLIT", "DIVIDI.TESTO"), + ("TIME", "ORARIO"), + ("TIMEVALUE", "ORARIO.VALORE"), + ("TINV", "INV.T"), + ("TOCOL", "A.COL"), + ("TODAY", "OGGI"), + ("TOROW", "A.RIGA"), + ("TRANSPOSE", "MATR.TRASPOSTA"), + ("TREND", "TENDENZA"), + ("TRIM", "ANNULLA.SPAZI"), + ("TRIMMEAN", "MEDIA.TRONCATA"), + ("TRUE", "VERO"), + ("TRUNC", "TRONCA"), + ("TTEST", "TEST.T"), + ("TYPE", "TIPO"), + ("UNICHAR", "CARATT.UNI"), + ("UNIQUE", "UNICI"), + ("UPPER", "MAIUSC"), + ("VALUE", "VALORE"), + ("VALUETOTEXT", "VALORE.A.TESTO"), + ("VAR.S", "VAR.C"), + ("VARA", "VAR.VALORI"), + ("VARP", "VAR.POP"), + ("VARPA", "VAR.POP.VALORI"), + ("VDB", "AMMORT.VAR"), + ("VLOOKUP", "CERCA.VERT"), + ("VSTACK", "STACK.VERT"), + ("WEBSERVICE", "SERVIZIO.WEB"), + ("WEEKDAY", "GIORNO.SETTIMANA"), + ("WEEKNUM", "NUM.SETTIMANA"), + ("WEIBULL.DIST", "DISTRIB.WEIBULL"), + ("WORKDAY", "GIORNO.LAVORATIVO"), + ("WORKDAY.INTL", "GIORNO.LAVORATIVO.INTL"), + ("WRAPCOLS", "DISPONI.COL"), + ("WRAPROWS", "DISPONI.RIGA"), + ("XIRR", "TIR.X"), + ("XLOOKUP", "CERCA.X"), + ("XMATCH", "CONFRONTA.X"), + ("XNPV", "VAN.X"), + ("YEAR", "ANNO"), + ("YEARFRAC", "FRAZIONE.ANNO"), + ("YIELD", "REND"), + ("YIELDDISC", "REND.TITOLI.SCONT"), + ("YIELDMAT", "REND.SCAD"), + ("Z.TEST", "TESTZ"), + ("ZTEST", "TEST.Z"), + ], +}; diff --git a/crates/formula/src/input/pt.rs b/crates/formula/src/input/pt.rs new file mode 100644 index 0000000000..92a8df7977 --- /dev/null +++ b/crates/formula/src/input/pt.rs @@ -0,0 +1,490 @@ +//! Português (Brasil): the formula words Brazilian Portuguese Excel shows (function names, booleans, errors, +//! structured-reference specifiers) and its formula separators. +//! +//! Function names come from Microsoft Support's pt-br Excel function pages (retrieved +//! 2026-10-10; the pages are machine-translated): per page, a vote among the title, the meta +//! description, the syntax paragraph (aligned with the en-US page) and `=NAME(` examples, and an +//! entry needs two agreeing signals. Entries marked `reviewed` were decided by hand from the page +//! evidence and independent function-name references. Functions not listed keep their English name. +//! +//! Sources for the other words: +//! - bool/errors: https://support.microsoft.com/pt-br/excel/functions/error-type-function +//! - errors.#GETTING_DATA: https://support.microsoft.com/pt-br/excel/functions/cubesetcount-function | tudoexcel.com.br +//! - errors.#SPILL!: https://support.microsoft.com/pt-br/excel/how-to-correct-a-spill-error | https://www.guiadoexcel.com.br/erro-despejar-no-excel-o-porque-ocorre-como-corrigir-e-evitar/ | https://ninjadoexcel.com.br/ +//! - errors.#CALC!: https://support.microsoft.com/pt-br/excel/how-to-correct-a-calc-error (page keeps #CALC!) +//! - table_items: https://support.microsoft.com/pt-br/excel/using-structured-references-with-excel-tables | blogs [[#Tudo];...] [#Cabeçalhos] + +use super::Dialect; +use gridcraft_core::CellError; + +pub(super) const DIALECT: Dialect = Dialect { + list: ';', + decimal: ',', + array_column: '\\', + array_row: ';', + bool_true: "VERDADEIRO", + bool_false: "FALSO", + errors: &[ + (CellError::Null, "#NULO!"), + (CellError::Div0, "#DIV/0!"), + (CellError::Value, "#VALOR!"), + (CellError::Ref, "#REF!"), + (CellError::Name, "#NOME?"), + (CellError::Num, "#NÚM!"), + (CellError::NA, "#N/D"), + (CellError::GettingData, "#OBTENDO_DADOS"), + (CellError::Spill, "#DESPEJAR!"), + (CellError::Calc, "#CALC!"), + ], + table_items: ["#Tudo", "#Dados", "#Cabeçalhos", "#Totais", "#Esta Linha"], + functions: &[ + ("ACCRINT", "JUROSACUM"), + ("ACCRINTM", "JUROSACUMV"), + ("ADDRESS", "ENDEREÇO"), + ("AGGREGATE", "AGREGAR"), + ("AND", "E"), + ("ARABIC", "ARÁBICO"), + ("AREAS", "ÁREAS"), + ("ARRAYTOTEXT", "MATRIZPARATEXTO"), + ("ASIN", "ASEN"), + ("ASINH", "ASENH"), + ("AVEDEV", "DESV.MÉDIO"), + ("AVERAGE", "MÉDIA"), + ("AVERAGEA", "MÉDIAA"), + ("AVERAGEIF", "MÉDIASE"), + ("AVERAGEIFS", "MÉDIASES"), + ("BETA.DIST", "DIST.BETA"), + ("BETA.INV", "INV.BETA"), + ("BETADIST", "DISTBETA"), + ("BETAINV", "BETA.ACUM.INV"), + ("BIN2DEC", "BINADEC"), + ("BIN2HEX", "BINAHEX"), + ("BIN2OCT", "BINAOCT"), + ("BINOM.DIST", "DISTR.BINOM"), + ("BINOM.DIST.RANGE", "INTERV.DISTR.BINOM"), + ("BINOM.INV", "INV.BINOM"), + ("BINOMDIST", "DISTRBINOM"), + ("BITLSHIFT", "DESLOCESQBIT"), + ("BITRSHIFT", "DESLOCDIRBIT"), + ("CEILING", "TETO"), + // reviewed: MS title/examples give TETO.MAT; real blog formula uses TETO.MAT + ("CEILING.MATH", "TETO.MAT"), + ("CEILING.PRECISE", "TETO.PRECISO"), + ("CELL", "CÉL"), + ("CHAR", "CARACT"), + ("CHIDIST", "DIST.QUI"), + ("CHIINV", "INV.QUI"), + ("CHISQ.DIST", "DIST.QUIQUA"), + ("CHISQ.DIST.RT", "DIST.QUIQUA.CD"), + ("CHISQ.INV", "INV.QUIQUA"), + ("CHISQ.INV.RT", "INV.QUIQUA.CD"), + ("CHISQ.TEST", "TESTE.QUIQUA"), + ("CHITEST", "TESTE.QUI"), + ("CHOOSE", "ESCOLHER"), + ("CHOOSECOLS", "ESCOLHERCOLS"), + // reviewed: real formulas | sources: https://www.guiadoexcel.com.br/funcao-escolherlins-excel/ + ("CHOOSEROWS", "ESCOLHERLINS"), + ("CLEAN", "TIRAR"), + ("CODE", "CÓDIGO"), + ("COLUMN", "COL"), + ("COLUMNS", "COLS"), + ("COMPLEX", "COMPLEXO"), + ("CONCATENATE", "CONCATENAR"), + ("CONFIDENCE", "INT.CONFIANÇA"), + ("CONFIDENCE.NORM", "INT.CONFIANÇA.NORM"), + ("CONFIDENCE.T", "INT.CONFIANÇA.T"), + ("CONVERT", "CONVERTER"), + ("COUNT", "CONT.NÚM"), + ("COUNTA", "CONT.VALORES"), + // reviewed: MS title; 5 blog pages + ("COUNTBLANK", "CONTAR.VAZIO"), + // reviewed: MS syntax/examples CONT.SE; ~139 blog pages use CONT.SE in formulas + ("COUNTIF", "CONT.SE"), + ("COUNTIFS", "CONT.SES"), + ("COUPDAYBS", "CUPDIASINLIQ"), + ("COUPDAYS", "CUPDIAS"), + ("COUPDAYSNC", "CUPDIASPRÓX"), + ("COUPNCD", "CUPDATAPRÓX"), + ("COUPNUM", "CUPNÚM"), + ("COUPPCD", "CUPDATAANT"), + ("COVARIANCE.P", "COVARIAÇÃO.P"), + ("COVARIANCE.S", "COVARIAÇÃO.S"), + ("CRITBINOM", "CRIT.BINOM"), + ("CSC", "COSEC"), + ("CSCH", "COSECH"), + ("CUBEKPIMEMBER", "MEMBROKPICUBO"), + ("CUBEMEMBER", "MEMBROCUBO"), + ("CUBEMEMBERPROPERTY", "PROPRIEDADEMEMBROCUBO"), + ("CUBERANKEDMEMBER", "MEMBROCLASSIFICADOCUBO"), + ("CUBESET", "CONJUNTOCUBO"), + ("CUBESETCOUNT", "CONTAGEMCONJUNTOCUBO"), + ("CUBEVALUE", "VALORCUBO"), + ("CUMIPMT", "PGTOJURACUM"), + ("CUMPRINC", "PGTOCAPACUM"), + ("DATE", "DATA"), + ("DATEDIF", "DATADIF"), + ("DATEVALUE", "DATA.VALOR"), + ("DAVERAGE", "BDMÉDIA"), + ("DAY", "DIA"), + ("DAYS", "DIAS"), + ("DAYS360", "DIAS360"), + ("DB", "BD"), + ("DCOUNT", "BDCONTAR"), + ("DCOUNTA", "BDCONTARA"), + ("DDB", "BDD"), + ("DEC2BIN", "DECABIN"), + ("DEC2HEX", "DECAHEX"), + ("DEC2OCT", "DECAOCT"), + ("DEGREES", "GRAUS"), + ("DEVSQ", "DESVQ"), + ("DGET", "BDEXTRAIR"), + ("DISC", "DESC"), + ("DMAX", "BDMÁX"), + ("DMIN", "BDMÍN"), + ("DOLLAR", "MOEDA"), + ("DOLLARDE", "MOEDADEC"), + ("DOLLARFR", "MOEDAFRA"), + ("DPRODUCT", "BDMULTIPL"), + // reviewed: blog formulas + ("DROP", "DESCARTAR"), + ("DSTDEV", "BDEST"), + ("DSTDEVP", "BDDESVPA"), + ("DSUM", "BDSOMA"), + ("DURATION", "DURAÇÃO"), + ("DVAR", "BDVAREST"), + ("DVARP", "BDVARP"), + ("EDATE", "DATAM"), + ("EFFECT", "EFETIVA"), + ("ENCODEURL", "CODIFURL"), + ("EOMONTH", "FIMMÊS"), + ("ERF", "FUNERRO"), + ("ERF.PRECISE", "FUNERRO.PRECISO"), + ("ERFC", "FUNERROCOMPL"), + ("ERFC.PRECISE", "FUNERROCOMPL.PRECISO"), + ("ERROR.TYPE", "TIPO.ERRO"), + ("EVEN", "PAR"), + ("EXACT", "EXATO"), + // reviewed: real formulas | sources: https://www.guiadoexcel.com.br/funcao-expandir-excel/ + ("EXPAND", "EXPANDIR"), + ("EXPON.DIST", "DISTR.EXPON"), + ("EXPONDIST", "DISTEXPON"), + ("F.DIST", "DIST.F"), + ("F.DIST.RT", "DIST.F.CD"), + ("F.INV", "INV.F"), + ("F.INV.RT", "INV.F.CD"), + ("F.TEST", "TESTE.F"), + ("FACT", "FATORIAL"), + ("FACTDOUBLE", "FATDUPLO"), + ("FALSE", "FALSO"), + ("FDIST", "DISTF"), + ("FILTER", "FILTRO"), + ("FILTERXML", "FILTROXML"), + // reviewed: blog formulas use PROCURAR (MS vote weak) | sources: https://www.guiadoexcel.com.br/funcoes-de-texto/ + ("FIND", "PROCURAR"), + // reviewed: B-variant of PROCURAR; follows ESQUERDAB/DIREITAB/NÚM.CARACTB/LOCALIZARB pattern; no direct source for the B form + ("FINDB", "PROCURARB"), + ("FINV", "INVF"), + // reviewed: MS syntax/examples; blog | sources: https://www.guiadoexcel.com.br/funcoes-de-texto/ + ("FIXED", "DEF.NÚM.DEC"), + ("FLOOR", "ARREDMULTB"), + ("FLOOR.MATH", "ARREDMULTB.MAT"), + ("FLOOR.PRECISE", "ARREDMULTB.PRECISO"), + ("FORECAST", "PREVISÃO"), + ("FORECAST.LINEAR", "PREVISÃO.LINEAR"), + ("FORMULATEXT", "FÓRMULATEXTO"), + ("FREQUENCY", "FREQÜÊNCIA"), + ("FTEST", "TESTEF"), + ("FV", "VF"), + ("FVSCHEDULE", "VFPLANO"), + ("GAMMA", "GAMA"), + ("GAMMA.DIST", "DIST.GAMA"), + ("GAMMA.INV", "INV.GAMA"), + ("GAMMADIST", "DISTGAMA"), + ("GAMMAINV", "INVGAMA"), + ("GAMMALN", "LNGAMA"), + ("GAMMALN.PRECISE", "LNGAMA.PRECISO"), + ("GCD", "MDC"), + ("GEOMEAN", "MÉDIA.GEOMÉTRICA"), + ("GESTEP", "DEGRAU"), + // reviewed: blog | sources: https://ninjadoexcel.com.br/funcao-agruparpor-no-excel/ + ("GROUPBY", "AGRUPARPOR"), + ("GROWTH", "CRESCIMENTO"), + ("HARMEAN", "MÉDIA.HARMÔNICA"), + ("HEX2BIN", "HEXABIN"), + ("HEX2DEC", "HEXADEC"), + ("HEX2OCT", "HEXAOCT"), + ("HLOOKUP", "PROCH"), + ("HOUR", "HORA"), + ("HSTACK", "EMPILHARH"), + // reviewed: ~12 blog pages use HIPERLINK in formulas + ("HYPERLINK", "HIPERLINK"), + ("HYPGEOM.DIST", "DIST.HIPERGEOM.N"), + ("HYPGEOMDIST", "DIST.HIPERGEOM"), + ("IF", "SE"), + ("IFERROR", "SEERRO"), + ("IFNA", "SENÃODISP"), + ("IFS", "SES"), + ("IMAGINARY", "IMAGINÁRIO"), + ("IMARGUMENT", "IMARG"), + ("IMCONJUGATE", "IMCONJ"), + ("IMCSC", "IMCOSEC"), + ("IMCSCH", "IMCOSECH"), + ("IMPOWER", "IMPOT"), + ("IMPRODUCT", "IMPROD"), + ("IMSIN", "IMSENO"), + ("IMSINH", "IMSENH"), + ("IMSQRT", "IMRAIZ"), + ("IMSUB", "IMSUBTR"), + ("IMSUM", "IMSOMA"), + ("INDEX", "ÍNDICE"), + ("INDIRECT", "INDIRETO"), + ("INFO", "INFORMAÇÃO"), + ("INTERCEPT", "INTERCEPÇÃO"), + ("INTRATE", "TAXAJUROS"), + ("IPMT", "IPGTO"), + ("IRR", "TIR"), + // reviewed: blog formulas ÉCÉL.VAZIA; MS is-functions table + ("ISBLANK", "ÉCÉL.VAZIA"), + // reviewed: MS is-functions table: ÉERRO = "exceto #N/D" (ISERR) | sources: https://support.microsoft.com/pt-br/excel/is-functions + ("ISERR", "ÉERRO"), + // reviewed: blog formulas show ÉERROS = ISERROR; ÉERRO is ISERR + ("ISERROR", "ÉERROS"), + ("ISEVEN", "ÉPAR"), + ("ISFORMULA", "ÉFÓRMULA"), + // reviewed: MS is-functions table and blogs + ("ISLOGICAL", "ÉLÓGICO"), + // reviewed: MS is-functions table and blogs + ("ISNA", "É.NÃO.DISP"), + // reviewed: MS is-functions table and blogs + ("ISNONTEXT", "É.NÃO.TEXTO"), + // reviewed: 34 blog pages use ÉNÚM; MS table ÉNÚMERO is MT noise + ("ISNUMBER", "ÉNÚM"), + ("ISO.CEILING", "ISO.TETO"), + // reviewed: blog formulas; MS iseven page gives ÉPAR for ISEVEN + ("ISODD", "ÉIMPAR"), + ("ISOWEEKNUM", "NÚMSEMANAISO"), + ("ISPMT", "ÉPGTO"), + // reviewed: MS is-functions table + ("ISREF", "ÉREF"), + // reviewed: MS is-functions table and blogs + ("ISTEXT", "ÉTEXTO"), + ("KURT", "CURT"), + ("LARGE", "MAIOR"), + ("LCM", "MMC"), + ("LEFT", "ESQUERDA"), + ("LEFTB", "ESQUERDAB"), + ("LEN", "NÚM.CARACT"), + ("LENB", "NÚM.CARACTB"), + ("LINEST", "PROJ.LIN"), + ("LOGEST", "PROJ.LOG"), + ("LOGINV", "INVLOG"), + ("LOGNORM.DIST", "DIST.LOGNORMAL.N"), + ("LOGNORM.INV", "INV.LOGNORMAL"), + ("LOGNORMDIST", "DIST.LOGNORMAL"), + ("LOOKUP", "PROC"), + ("LOWER", "MINÚSCULA"), + ("MATCH", "CORRESP"), + ("MAX", "MÁXIMO"), + ("MAXA", "MÁXIMOA"), + ("MAXIFS", "MÁXIMOSES"), + ("MDETERM", "MATRIZ.DETERM"), + ("MDURATION", "MDURAÇÃO"), + ("MEDIAN", "MED"), + ("MID", "EXT.TEXTO"), + // reviewed: B-variant of EXT.TEXTO; pattern ESQUERDAB/DIREITAB; no direct source + ("MIDB", "EXT.TEXTOB"), + ("MIN", "MÍNIMO"), + ("MINA", "MÍNIMOA"), + ("MINIFS", "MÍNIMOSES"), + ("MINUTE", "MINUTO"), + ("MINVERSE", "MATRIZ.INVERSO"), + ("MIRR", "MTIR"), + ("MMULT", "MATRIZ.MULT"), + ("MODE", "MODO"), + ("MODE.MULT", "MODO.MULT"), + ("MODE.SNGL", "MODO.ÚNICO"), + ("MONTH", "MÊS"), + ("MROUND", "MARRED"), + ("NA", "NÃO.DISP"), + ("NEGBINOM.DIST", "DIST.BIN.NEG.N"), + ("NEGBINOMDIST", "DIST.BIN.NEG"), + ("NETWORKDAYS", "DIATRABALHOTOTAL"), + ("NETWORKDAYS.INTL", "DIATRABALHOTOTAL.INTL"), + ("NORM.DIST", "DIST.NORM.N"), + ("NORM.INV", "INV.NORM.N"), + ("NORM.S.DIST", "DIST.NORMP.N"), + ("NORM.S.INV", "INV.NORMP.N"), + ("NORMDIST", "DISTNORM"), + ("NORMINV", "INV.NORM"), + ("NORMSDIST", "DISTNORMP"), + ("NORMSINV", "INV.NORMP"), + ("NOT", "NÃO"), + ("NOW", "AGORA"), + ("NPV", "VPL"), + ("NUMBERVALUE", "VALORNUMÉRICO"), + ("OCT2BIN", "OCTABIN"), + ("OCT2DEC", "OCTADEC"), + ("OCT2HEX", "OCTAHEX"), + ("ODD", "ÍMPAR"), + ("OFFSET", "DESLOC"), + ("OR", "OU"), + ("PDURATION", "DURAÇÃOP"), + ("PERCENTILE", "PERCENTIL"), + // reviewed: vote wrongly gave EXC; MS title/syntax + ("PERCENTILE.EXC", "PERCENTIL.EXC"), + ("PERCENTILE.INC", "PERCENTIL.INC"), + ("PERCENTRANK", "ORDEM.PORCENTUAL"), + ("PERCENTRANK.EXC", "ORDEM.PORCENTUAL.EXC"), + ("PERCENTRANK.INC", "ORDEM.PORCENTUAL.INC"), + ("PERMUTATIONA", "PERMUTAS"), + ("PHONETIC", "FONÉTICA"), + // reviewed: blog | sources: https://ninjadoexcel.com.br/novidade-funcao-pivotar-do-excel/ + ("PIVOTBY", "PIVOTAR"), + ("PMT", "PGTO"), + ("POISSON.DIST", "DIST.POISSON"), + ("POWER", "POTÊNCIA"), + ("PPMT", "PPGTO"), + ("PRICE", "PREÇO"), + ("PRICEDISC", "PREÇODESC"), + ("PRICEMAT", "PREÇOVENC"), + ("PRODUCT", "MULT"), + ("PROPER", "PRI.MAIÚSCULA"), + ("PV", "VP"), + ("QUARTILE", "QUARTIL"), + ("QUARTILE.EXC", "QUARTIL.EXC"), + ("QUARTILE.INC", "QUARTIL.INC"), + ("QUOTIENT", "QUOCIENTE"), + ("RADIANS", "RADIANOS"), + ("RAND", "ALEATÓRIO"), + ("RANDARRAY", "MATRIZALEATÓRIA"), + ("RANDBETWEEN", "ALEATÓRIOENTRE"), + ("RANK", "ORDEM"), + ("RANK.AVG", "ORDEM.MÉD"), + ("RANK.EQ", "ORDEM.EQ"), + ("RATE", "TAXA"), + ("RECEIVED", "RECEBER"), + // reviewed: real formula in blog | sources: https://www.guiadoexcel.com.br/como-usar-procx-e-regex-excel/ + ("REGEXREPLACE", "REGEX.SUBSTITUIR"), + // reviewed: real formula in blog | sources: https://www.guiadoexcel.com.br/como-usar-procx-e-regex-excel/ + ("REGEXTEST", "REGEX.TESTAR"), + ("REPLACE", "MUDAR"), + // reviewed: B-variant of MUDAR; pattern ESQUERDAB/DIREITAB; no direct source + ("REPLACEB", "MUDARB"), + ("RIGHT", "DIREITA"), + ("RIGHTB", "DIREITAB"), + ("ROMAN", "ROMANO"), + ("ROUND", "ARRED"), + ("ROUNDDOWN", "ARREDONDAR.PARA.BAIXO"), + ("ROUNDUP", "ARREDONDAR.PARA.CIMA"), + ("ROW", "LIN"), + ("ROWS", "LINS"), + ("RRI", "TAXAJURO"), + ("RSQ", "RQUAD"), + ("SEARCH", "LOCALIZAR"), + ("SEARCHB", "LOCALIZARB"), + ("SECOND", "SEGUNDO"), + ("SEQUENCE", "SEQUÊNCIA"), + ("SERIESSUM", "SOMASEQÜÊNCIA"), + ("SHEET", "PLAN"), + ("SHEETS", "PLANS"), + ("SIGN", "SINAL"), + ("SIN", "SEN"), + ("SINH", "SENH"), + ("SKEW", "DISTORÇÃO"), + ("SKEW.P", "DISTORÇÃO.P"), + ("SLN", "DPD"), + ("SLOPE", "INCLINAÇÃO"), + ("SMALL", "MENOR"), + ("SORT", "CLASSIFICAR"), + ("SORTBY", "CLASSIFICARPOR"), + ("SQRT", "RAIZ"), + ("SQRTPI", "RAIZPI"), + ("STANDARDIZE", "PADRONIZAR"), + ("STDEV", "DESVPAD"), + ("STDEV.P", "DESVPAD.P"), + ("STDEV.S", "DESVPAD.A"), + ("STDEVA", "DESVPADA"), + ("STDEVP", "DESVPADP"), + ("STDEVPA", "DESVPADPA"), + ("STEYX", "EPADYX"), + ("SUBSTITUTE", "SUBSTITUIR"), + ("SUM", "SOMA"), + ("SUMIF", "SOMASE"), + ("SUMIFS", "SOMASES"), + ("SUMPRODUCT", "SOMARPRODUTO"), + ("SUMSQ", "SOMAQUAD"), + ("SUMX2MY2", "SOMAX2DY2"), + ("SUMX2PY2", "SOMAX2SY2"), + ("SUMXMY2", "SOMAXMY2"), + ("SWITCH", "PARÂMETRO"), + ("SYD", "SDA"), + ("T.DIST", "DIST.T"), + ("T.DIST.2T", "DIST.T.BC"), + ("T.DIST.RT", "DIST.T.CD"), + ("T.INV", "INV.T"), + ("T.INV.2T", "INV.T.BC"), + ("T.TEST", "TESTE.T"), + // reviewed: real formulas | sources: https://www.guiadoexcel.com.br/funcao-pegar-excel/ + ("TAKE", "PEGAR"), + ("TBILLEQ", "OTN"), + ("TBILLPRICE", "OTNVALOR"), + ("TBILLYIELD", "OTNLUCRO"), + ("TDIST", "DISTT"), + ("TEXT", "TEXTO"), + // reviewed: 23 blog pages + ("TEXTAFTER", "TEXTODEPOIS"), + // reviewed: 19 blog pages + ("TEXTBEFORE", "TEXTOANTES"), + ("TEXTJOIN", "UNIRTEXTO"), + // reviewed: MS syntax/examples; 23 blog pages; older TEXTODIVISÃO kept as alias | sources: https://ninjadoexcel.com.br/como-dividir-texto-no-excel-funcao-dividirtexto/ + ("TEXTSPLIT", "DIVIDIRTEXTO"), + ("TIME", "TEMPO"), + ("TIMEVALUE", "VALOR.TEMPO"), + ("TINV", "INVT"), + // reviewed: real formulas | sources: https://www.hashtagtreinamentos.com/funcoes-paracol-e-paralin-excel + ("TOCOL", "PARACOL"), + ("TODAY", "HOJE"), + // reviewed: real formulas | sources: https://www.hashtagtreinamentos.com/funcoes-paracol-e-paralin-excel + ("TOROW", "PARALIN"), + ("TRANSPOSE", "TRANSPOR"), + // reviewed: blog formulas + ("TREND", "TENDÊNCIA"), + ("TRIM", "ARRUMAR"), + ("TRIMMEAN", "MÉDIA.INTERNA"), + ("TRUE", "VERDADEIRO"), + ("TRUNC", "TRUNCAR"), + ("TTEST", "TESTET"), + ("TYPE", "TIPO"), + ("UNICHAR", "CARACTUNICODE"), + ("UNIQUE", "ÚNICO"), + ("UPPER", "MAIÚSCULA"), + ("VALUE", "VALOR"), + ("VALUETOTEXT", "VALORPARATEXTO"), + // reviewed: MS title/examples only (no blog source) + ("VAR", "VAREST"), + ("VAR.S", "VAR.A"), + ("VDB", "BDV"), + ("VLOOKUP", "PROCV"), + ("VSTACK", "EMPILHARV"), + ("WEBSERVICE", "SERVIÇOWEB"), + ("WEEKDAY", "DIA.DA.SEMANA"), + ("WEEKNUM", "NÚMSEMANA"), + ("WEIBULL.DIST", "DIST.WEIBULL"), + ("WORKDAY", "DIATRABALHO"), + ("WORKDAY.INTL", "DIATRABALHO.INTL"), + ("WRAPCOLS", "QUEBRARCOLS"), + // reviewed: blog; sibling WRAPCOLS=QUEBRARCOLS + ("WRAPROWS", "QUEBRARLINS"), + ("XIRR", "XTIR"), + ("XLOOKUP", "PROCX"), + ("XMATCH", "CORRESPX"), + ("XNPV", "XVPL"), + ("YEAR", "ANO"), + ("YEARFRAC", "FRAÇÃOANO"), + ("YIELD", "LUCRO"), + ("YIELDDISC", "LUCRODESC"), + ("YIELDMAT", "LUCROVENC"), + ("Z.TEST", "TESTE.Z"), + ("ZTEST", "TESTEZ"), + ], +}; diff --git a/crates/formula/src/input/ru.rs b/crates/formula/src/input/ru.rs new file mode 100644 index 0000000000..6773413207 --- /dev/null +++ b/crates/formula/src/input/ru.rs @@ -0,0 +1,870 @@ +//! Русский (Россия): the formula words Russian Excel shows (function names, booleans, errors, +//! structured-reference specifiers) and its formula separators. +//! +//! Function names come from Microsoft Support's ru-ru Excel function pages (retrieved +//! 2026-10-10; the pages are machine-translated): per page, a vote among the title, the meta +//! description, the syntax paragraph (aligned with the en-US page) and `=NAME(` examples, and an +//! entry needs two agreeing signals. Entries marked `reviewed` were decided by hand from the page +//! evidence and independent function-name references. Functions not listed keep their English name. +//! +//! Unless an entry says otherwise, `reviewed` means: At least two independent function translation references agree; conflicting machine-translated spellings rejected. +//! +//! Sources for the other words: +//! - bool: https://support.microsoft.com/ru-ru/excel/functions/address-function (a1 argument: ИСТИНА / ЛОЖЬ) +//! - errors: https://support.microsoft.com/ru-ru/excel/functions/error-type-function +//! - errors.#SPILL!: https://support.microsoft.com/ru-ru/excel/how-to-correct-a-spill-error +//! - table_items: https://support.microsoft.com/ru-ru/excel/using-structured-references-with-excel-tables +//! - errors.#CALC!: https://www.planetaexcel.ru/techniques/25/9457/ | https://coddy.tech/docs/ru/excel/filter (empty FILTER result -> #ВЫЧИСЛ!, English #CALC!) +//! - errors.#REF!: https://excel-academy.ru/faq/kak-ispravit-oshibki-ssyilka-i-imya-v-excel/ | https://coddy.tech/docs/ru/excel/ref-error | https://support.microsoft.com/ru-ru/excel/functions/sum-function (ERROR.TYPE table truncates spelling to #ССЫЛ!, corrected using independent formula examples) + +use super::Dialect; +use gridcraft_core::CellError; + +pub(super) const DIALECT: Dialect = Dialect { + list: ';', + decimal: ',', + array_column: ';', + array_row: ':', + bool_true: "ИСТИНА", + bool_false: "ЛОЖЬ", + errors: &[ + (CellError::Null, "#ПУСТО!"), + (CellError::Div0, "#ДЕЛ/0!"), + (CellError::Value, "#ЗНАЧ!"), + (CellError::Ref, "#ССЫЛКА!"), + (CellError::Name, "#ИМЯ?"), + (CellError::Num, "#ЧИСЛО!"), + (CellError::NA, "#Н/Д"), + (CellError::GettingData, "#ОЖИДАНИЕ_ДАННЫХ"), + (CellError::Spill, "#ПЕРЕНОС!"), + (CellError::Calc, "#ВЫЧИСЛ!"), + ], + table_items: ["#Все", "#Данные", "#Заголовки", "#Итого", "#Эта строка"], + functions: &[ + ("ACCRINT", "НАКОПДОХОД"), + ("ACCRINTM", "НАКОПДОХОДПОГАШ"), + ("ADDRESS", "АДРЕС"), + ("AGGREGATE", "АГРЕГАТ"), + ("AMORDEGRC", "АМОРУМ"), + ("AMORLINC", "АМОРУВ"), + ("AND", "И"), + ("ARABIC", "АРАБСКОЕ"), + ("AREAS", "ОБЛАСТИ"), + ("ARRAYTOTEXT", "МАССИВВТЕКСТ"), + ("AVEDEV", "СРОТКЛ"), + ("AVERAGE", "СРЗНАЧ"), + ("AVERAGEA", "СРЗНАЧА"), + ("AVERAGEIF", "СРЗНАЧЕСЛИ"), + ("AVERAGEIFS", "СРЗНАЧЕСЛИМН"), + ("BASE", "ОСНОВАНИЕ"), + ("BESSELI", "БЕССЕЛЬ.I"), + ("BESSELJ", "БЕССЕЛЬ.J"), + ("BESSELK", "БЕССЕЛЬ.K"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("BESSELY", "БЕССЕЛЬ.Y"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("BETA.DIST", "БЕТА.РАСП"), + ("BETA.INV", "БЕТА.ОБР"), + ("BETADIST", "БЕТАРАСП"), + ("BETAINV", "БЕТАОБР"), + ("BIN2DEC", "ДВ.В.ДЕС"), + ("BIN2HEX", "ДВ.В.ШЕСТН"), + ("BIN2OCT", "ДВ.В.ВОСЬМ"), + ("BINOM.DIST", "БИНОМ.РАСП"), + ("BINOM.DIST.RANGE", "БИНОМ.РАСП.ДИАП"), + ("BINOM.INV", "БИНОМ.ОБР"), + ("BINOMDIST", "БИНОМРАСП"), + ("BITAND", "БИТ.И"), + ("BITLSHIFT", "БИТ.СДВИГЛ"), + ("BITOR", "БИТ.ИЛИ"), + ("BITRSHIFT", "БИТ.СДВИГП"), + ("BITXOR", "БИТ.ИСКЛИЛИ"), + ("CEILING", "ОКРВВЕРХ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("CEILING.MATH", "ОКРВВЕРХ.МАТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("CEILING.PRECISE", "ОКРВВЕРХ.ТОЧН"), + ("CELL", "ЯЧЕЙКА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("CHAR", "СИМВОЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("CHIDIST", "ХИ2РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("CHIINV", "ХИ2ОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("CHISQ.DIST", "ХИ2.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("CHISQ.DIST.RT", "ХИ2.РАСП.ПХ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("CHISQ.INV", "ХИ2.ОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("CHISQ.INV.RT", "ХИ2.ОБР.ПХ"), + ("CHISQ.TEST", "ХИ2.ТЕСТ"), + ("CHITEST", "ХИ2ТЕСТ"), + ("CHOOSE", "ВЫБОР"), + ("CHOOSECOLS", "ВЫБОРСТОЛБЦ"), + ("CLEAN", "ПЕЧСИМВ"), + ("CODE", "КОДСИМВ"), + ("COLUMN", "СТОЛБЕЦ"), + ("COLUMNS", "ЧИСЛСТОЛБ"), + ("COMBIN", "ЧИСЛКОМБ"), + ("COMBINA", "ЧИСЛКОМБА"), + ("COMPLEX", "КОМПЛЕКСН"), + // reviewed: Title and metadata agree; syntax/examples incorrectly copied from CONCATENATE; common function table corroborates СЦЕП | sources: https://support.microsoft.com/ru-ru/excel/functions/concat-function | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ + ("CONCAT", "СЦЕП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("CONCATENATE", "СЦЕПИТЬ"), + ("CONFIDENCE", "ДОВЕРИТ"), + ("CONFIDENCE.NORM", "ДОВЕРИТ.НОРМ"), + ("CONFIDENCE.T", "ДОВЕРИТ.СТЬЮДЕНТ"), + ("CONVERT", "ПРЕОБР"), + ("CORREL", "КОРРЕЛ"), + ("COUNT", "СЧЁТ"), + ("COUNTA", "СЧЁТЗ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("COUNTBLANK", "СЧИТАТЬПУСТОТЫ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("COUNTIF", "СЧЁТЕСЛИ"), + ("COUNTIFS", "СЧЁТЕСЛИМН"), + ("COUPDAYBS", "ДНЕЙКУПОНДО"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("COUPDAYS", "ДНЕЙКУПОН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("COUPDAYSNC", "ДНЕЙКУПОНПОСЛЕ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("COUPNCD", "ДАТАКУПОНПОСЛЕ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("COUPNUM", "ЧИСЛКУПОН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("COUPPCD", "ДАТАКУПОНДО"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("COVAR", "КОВАР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("COVARIANCE.P", "КОВАРИАЦИЯ.Г"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("COVARIANCE.S", "КОВАРИАЦИЯ.В"), + ("CRITBINOM", "КРИТБИНОМ"), + ("CUBEKPIMEMBER", "КУБЭЛЕМЕНТКИП"), + ("CUBEMEMBER", "КУБЭЛЕМЕНТ"), + // reviewed: Microsoft title, metadata and examples agree with Functiontranslator; syntax incorrectly says КУБПОРЭЛЕМЕНТ (CUBERANKEDMEMBER) | sources: https://support.microsoft.com/ru-ru/excel/functions/cubememberproperty-function | https://functiontranslator.com/ru/ + ("CUBEMEMBERPROPERTY", "КУБСВОЙСТВОЭЛЕМЕНТА"), + ("CUBERANKEDMEMBER", "КУБПОРЭЛЕМЕНТ"), + ("CUBESET", "КУБМНОЖ"), + ("CUBESETCOUNT", "КУБЧИСЛОЭЛМНОЖ"), + ("CUBEVALUE", "КУБЗНАЧЕНИЕ"), + ("CUMIPMT", "ОБЩПЛАТ"), + ("CUMPRINC", "ОБЩДОХОД"), + ("DATE", "ДАТА"), + ("DATEDIF", "РАЗНДАТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("DATEVALUE", "ДАТАЗНАЧ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DAVERAGE", "ДСРЗНАЧ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("DAY", "ДЕНЬ"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("DAYS", "ДНИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DAYS360", "ДНЕЙ360"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DB", "ФУО"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DCOUNT", "БСЧЁТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DCOUNTA", "БСЧЁТА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DDB", "ДДОБ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("DEC2BIN", "ДЕС.В.ДВ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("DEC2HEX", "ДЕС.В.ШЕСТН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DEC2OCT", "ДЕС.В.ВОСЬМ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DECIMAL", "ДЕС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DEGREES", "ГРАДУСЫ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DELTA", "ДЕЛЬТА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DEVSQ", "КВАДРОТКЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DGET", "БИЗВЛЕЧЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DISC", "СКИДКА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DMAX", "ДМАКС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DMIN", "ДМИН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DOLLAR", "РУБЛЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DOLLARDE", "РУБЛЬ.ДЕС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DOLLARFR", "РУБЛЬ.ДРОБЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DPRODUCT", "БДПРОИЗВЕД"), + // reviewed: Microsoft title and meta give the Russian name; the syntax and examples were left untranslated (English name) | sources: https://support.microsoft.com/ru-ru/excel/functions/drop-function + ("DROP", "СБРОСИТЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DSTDEV", "ДСТАНДОТКЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DSTDEVP", "ДСТАНДОТКЛП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DSUM", "БДСУММ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DURATION", "ДЛИТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DVAR", "БДДИСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("DVARP", "БДДИСПП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("EDATE", "ДАТАМЕС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("EFFECT", "ЭФФЕКТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("ENCODEURL", "КОДИР.URL"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("EOMONTH", "КОНМЕСЯЦА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("ERF", "ФОШ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("ERF.PRECISE", "ФОШ.ТОЧН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("ERFC", "ДФОШ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("ERFC.PRECISE", "ДФОШ.ТОЧН"), + ("ERROR.TYPE", "ТИП.ОШИБКИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("EVEN", "ЧЁТН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("EXACT", "СОВПАД"), + ("EXPAND", "РАЗВЕРНУТЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("EXPON.DIST", "ЭКСП.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("EXPONDIST", "ЭКСПРАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("F.DIST", "F.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("F.DIST.RT", "F.РАСП.ПХ"), + ("F.INV", "F.ОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("F.INV.RT", "F.ОБР.ПХ"), + ("F.TEST", "F.ТЕСТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("FACT", "ФАКТР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("FACTDOUBLE", "ДВФАКТР"), + ("FALSE", "ЛОЖЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("FDIST", "FРАСП"), + // reviewed: Microsoft calc-error page and independent dynamic-array article show literal ФИЛЬТР formulas | sources: https://support.microsoft.com/ru-ru/excel/how-to-correct-a-calc-error | https://www.planetaexcel.ru/techniques/25/9457/ + ("FILTER", "ФИЛЬТР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("FILTERXML", "ФИЛЬТР.XML"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("FIND", "НАЙТИ"), + // reviewed: Two independent function tables agree (the Microsoft page could not be fetched) | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("FINDB", "НАЙТИБ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("FINV", "FРАСПОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("FISHER", "ФИШЕР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("FISHERINV", "ФИШЕРОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("FIXED", "ФИКСИРОВАННЫЙ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("FLOOR", "ОКРВНИЗ"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("FLOOR.MATH", "ОКРВНИЗ.МАТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("FLOOR.PRECISE", "ОКРВНИЗ.ТОЧН"), + ("FORECAST", "ПРЕДСКАЗ"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("FORECAST.LINEAR", "ПРЕДСКАЗ.ЛИНЕЙН"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("FORMULATEXT", "Ф.ТЕКСТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("FREQUENCY", "ЧАСТОТА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("FTEST", "ФТЕСТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("FV", "БС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("FVSCHEDULE", "БЗРАСПИС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("GAMMA", "ГАММА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("GAMMA.DIST", "ГАММА.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("GAMMA.INV", "ГАММА.ОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("GAMMADIST", "ГАММАРАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("GAMMAINV", "ГАММАОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("GAMMALN", "ГАММАНЛОГ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("GAMMALN.PRECISE", "ГАММАНЛОГ.ТОЧН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("GAUSS", "ГАУСС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("GCD", "НОД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("GEOMEAN", "СРГЕОМ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("GESTEP", "ПОРОГ"), + ("GROUPBY", "ГРУПППО"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("GROWTH", "РОСТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("HARMEAN", "СРГАРМ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("HEX2BIN", "ШЕСТН.В.ДВ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("HEX2DEC", "ШЕСТН.В.ДЕС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("HEX2OCT", "ШЕСТН.В.ВОСЬМ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("HLOOKUP", "ГПР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("HOUR", "ЧАС"), + ("HSTACK", "ГСТОЛБИК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("HYPERLINK", "ГИПЕРССЫЛКА"), + ("HYPGEOM.DIST", "ГИПЕРГЕОМ.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("HYPGEOMDIST", "ГИПЕРГЕОМЕТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("IF", "ЕСЛИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("IFERROR", "ЕСЛИОШИБКА"), + // reviewed: Microsoft title, meta and syntax agree, with Excel Academy and the excelworld title; two dictionaries and the excelworld syntax line spell ЕСЛИНД (kept as an alias) | sources: https://support.microsoft.com/ru-ru/excel/functions/ifna-function | https://excel-academy.ru/tools/excel-functions/ | http://www.excelworld.ru/publ/funcs/boolean/ifna/11-1-0-118 + ("IFNA", "ЕСНД"), + // reviewed: Microsoft meta and examples, a worked formula on mister-office and a function table agree; the page title УСЛОВИЯ is a machine translation (kept as an alias) | sources: https://support.microsoft.com/ru-ru/excel/functions/ifs-function (meta, examples) | https://mister-office.com/funktsii-excel/ifs-eslimn.html (=E8*ЕСЛИМН(...)) | https://functiontranslator.com/ru/ + ("IFS", "ЕСЛИМН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMABS", "МНИМ.ABS"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMAGINARY", "МНИМ.ЧАСТЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMARGUMENT", "МНИМ.АРГУМЕНТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMCONJUGATE", "МНИМ.СОПРЯЖ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMCOS", "МНИМ.COS"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMCOSH", "МНИМ.COSH"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMCOT", "МНИМ.COT"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMCSC", "МНИМ.CSC"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMCSCH", "МНИМ.CSCH"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMDIV", "МНИМ.ДЕЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMEXP", "МНИМ.EXP"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMLN", "МНИМ.LN"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMLOG10", "МНИМ.LOG10"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMLOG2", "МНИМ.LOG2"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMPOWER", "МНИМ.СТЕПЕНЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMPRODUCT", "МНИМ.ПРОИЗВЕД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMREAL", "МНИМ.ВЕЩ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMSEC", "МНИМ.SEC"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMSECH", "МНИМ.SECH"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMSIN", "МНИМ.SIN"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMSINH", "МНИМ.SINH"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMSQRT", "МНИМ.КОРЕНЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMSUB", "МНИМ.РАЗН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMSUM", "МНИМ.СУММ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IMTAN", "МНИМ.TAN"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("INDEX", "ИНДЕКС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("INDIRECT", "ДВССЫЛ"), + ("INFO", "ИНФОРМ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("INT", "ЦЕЛОЕ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("INTERCEPT", "ОТРЕЗОК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("INTRATE", "ИНОРМА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IPMT", "ПРПЛТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("IRR", "ВСД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ISBLANK", "ЕПУСТО"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("ISERR", "ЕОШ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ISERROR", "ЕОШИБКА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ISEVEN", "ЕЧЁТН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("ISFORMULA", "ЕФОРМУЛА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ISLOGICAL", "ЕЛОГИЧ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ISNA", "ЕНД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ISNONTEXT", "ЕНЕТЕКСТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ISNUMBER", "ЕЧИСЛО"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("ISO.CEILING", "ISO.ОКРВВЕРХ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ISODD", "ЕНЕЧЁТ"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ISOWEEKNUM", "НОМНЕДЕЛИ.ISO"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("ISPMT", "ПРОЦПЛАТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("ISREF", "ЕССЫЛКА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ISTEXT", "ЕТЕКСТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("KURT", "ЭКСЦЕСС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("LARGE", "НАИБОЛЬШИЙ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("LCM", "НОК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("LEFT", "ЛЕВСИМВ"), + // reviewed: Microsoft page names it ("Функция ЛЕВБ является нерекомендуемой"); two function tables agree | sources: https://support.microsoft.com/ru-ru/excel/functions/left-function | https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("LEFTB", "ЛЕВБ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("LEN", "ДЛСТР"), + // reviewed: Microsoft page names it ("Функция ДЛИНБ является нерекомендуемой"); two function tables agree | sources: https://support.microsoft.com/ru-ru/excel/functions/len-function | https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("LENB", "ДЛИНБ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("LINEST", "ЛИНЕЙН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("LOGEST", "ЛГРФПРИБЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("LOGINV", "ЛОГНОРМОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("LOGNORM.DIST", "ЛОГНОРМ.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("LOGNORM.INV", "ЛОГНОРМ.ОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("LOGNORMDIST", "ЛОГНОРМРАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("LOOKUP", "ПРОСМОТР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("LOWER", "СТРОЧН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MATCH", "ПОИСКПОЗ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MAX", "МАКС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MAXA", "МАКСА"), + // reviewed | sources: https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MAXIFS", "МАКСЕСЛИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MDETERM", "МОПРЕД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MDURATION", "МДЛИТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MEDIAN", "МЕДИАНА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MID", "ПСТР"), + // reviewed: Microsoft page names it ("Функция ПСТРБ является нерекомендуемой"); two function tables agree | sources: https://support.microsoft.com/ru-ru/excel/functions/mid-function | https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("MIDB", "ПСТРБ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MIN", "МИН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MINA", "МИНА"), + // reviewed | sources: https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MINIFS", "МИНЕСЛИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MINUTE", "МИНУТЫ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MINVERSE", "МОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MIRR", "МВСД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MMULT", "МУМНОЖ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MOD", "ОСТАТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MODE", "МОДА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MODE.MULT", "МОДА.НСК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MODE.SNGL", "МОДА.ОДН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MONTH", "МЕСЯЦ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("MROUND", "ОКРУГЛТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MULTINOMIAL", "МУЛЬТИНОМ"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("MUNIT", "МЕДИН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("N", "Ч"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("NA", "НД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("NEGBINOM.DIST", "ОТРБИНОМ.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("NEGBINOMDIST", "ОТРБИНОМРАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("NETWORKDAYS", "ЧИСТРАБДНИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("NETWORKDAYS.INTL", "ЧИСТРАБДНИ.МЕЖД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("NOMINAL", "НОМИНАЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("NORM.DIST", "НОРМ.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("NORM.INV", "НОРМ.ОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("NORM.S.DIST", "НОРМ.СТ.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("NORM.S.INV", "НОРМ.СТ.ОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("NORMDIST", "НОРМРАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("NORMINV", "НОРМОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("NORMSDIST", "НОРМСТРАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("NORMSINV", "НОРМСТОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("NOT", "НЕ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("NOW", "ТДАТА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("NPER", "КПЕР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("NPV", "ЧПС"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("NUMBERVALUE", "ЧЗНАЧ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("OCT2BIN", "ВОСЬМ.В.ДВ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("OCT2DEC", "ВОСЬМ.В.ДЕС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("OCT2HEX", "ВОСЬМ.В.ШЕСТН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ODD", "НЕЧЁТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("OFFSET", "СМЕЩ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("OR", "ИЛИ"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PDURATION", "ПДЛИТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("PERCENTILE", "ПЕРСЕНТИЛЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("PERCENTILE.EXC", "ПРОЦЕНТИЛЬ.ИСКЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("PERCENTILE.INC", "ПРОЦЕНТИЛЬ.ВКЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("PERCENTRANK", "ПРОЦЕНТРАНГ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("PERCENTRANK.EXC", "ПРОЦЕНТРАНГ.ИСКЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("PERCENTRANK.INC", "ПРОЦЕНТРАНГ.ВКЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PERMUT", "ПЕРЕСТ"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PERMUTATIONA", "ПЕРЕСТА"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PHI", "ФИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("PI", "ПИ"), + ("PIVOTBY", "СВОДПО"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("PMT", "ПЛТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("POISSON", "ПУАССОН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("POISSON.DIST", "ПУАССОН.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("POWER", "СТЕПЕНЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PPMT", "ОСПЛТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PRICE", "ЦЕНА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PRICEDISC", "ЦЕНАСКИДКА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PRICEMAT", "ЦЕНАПОГАШ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PROB", "ВЕРОЯТНОСТЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PRODUCT", "ПРОИЗВЕД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("PROPER", "ПРОПНАЧ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("PV", "ПС"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("QUARTILE", "КВАРТИЛЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("QUARTILE.EXC", "КВАРТИЛЬ.ИСКЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("QUARTILE.INC", "КВАРТИЛЬ.ВКЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("QUOTIENT", "ЧАСТНОЕ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("RADIANS", "РАДИАНЫ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("RAND", "СЛЧИС"), + ("RANDARRAY", "СЛУЧМАССИВ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("RANDBETWEEN", "СЛУЧМЕЖДУ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("RANK", "РАНГ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("RANK.AVG", "РАНГ.СР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("RANK.EQ", "РАНГ.РВ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("RATE", "СТАВКА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("RECEIVED", "ПОЛУЧЕНО"), + ("REGEXEXTRACT", "РЕГИЗВЛЕЧЬ"), + ("REGEXREPLACE", "РЕГЗАМЕНИТЬ"), + ("REGEXTEST", "РЕГТЕСТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("REPLACE", "ЗАМЕНИТЬ"), + // reviewed: Microsoft page names it ("Функция ЗАМЕНИТЬБ является нерекомендуемой"); two function tables agree | sources: https://support.microsoft.com/ru-ru/excel/functions/replace-function | https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("REPLACEB", "ЗАМЕНИТЬБ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("REPT", "ПОВТОР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("RIGHT", "ПРАВСИМВ"), + // reviewed: Microsoft page names it ("Функция ПРАВБ является нерекомендуемой"); two function tables agree | sources: https://support.microsoft.com/ru-ru/excel/functions/right-function | https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("RIGHTB", "ПРАВБ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ROMAN", "РИМСКОЕ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ROUND", "ОКРУГЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ROUNDDOWN", "ОКРУГЛВНИЗ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ROUNDUP", "ОКРУГЛВВЕРХ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ROW", "СТРОКА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("ROWS", "ЧСТРОК"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("RRI", "ЭКВ.СТАВКА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("RSQ", "КВПИРСОН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("SEARCH", "ПОИСК"), + // reviewed: Microsoft page names it ("Функция ПОИСКБ является нерекомендуемой"); two function tables agree | sources: https://support.microsoft.com/ru-ru/excel/functions/search-function | https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("SEARCHB", "ПОИСКБ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SECOND", "СЕКУНДЫ"), + ("SEQUENCE", "ПОСЛЕДОВ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("SERIESSUM", "РЯД.СУММ"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SHEET", "ЛИСТ"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SHEETS", "ЛИСТЫ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SIGN", "ЗНАК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SKEW", "СКОС"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SKEW.P", "СКОС.Г"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SLN", "АПЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SLOPE", "НАКЛОН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("SMALL", "НАИМЕНЬШИЙ"), + // reviewed: Independent article explicitly pairs English and Russian names and shows function syntax | sources: https://www.planetaexcel.ru/techniques/25/9457/ + ("SORT", "СОРТ"), + ("SORTBY", "СОРТПО"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SQRT", "КОРЕНЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SQRTPI", "КОРЕНЬПИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("STANDARDIZE", "НОРМАЛИЗАЦИЯ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("STDEV", "СТАНДОТКЛОН"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("STDEV.P", "СТАНДОТКЛОН.Г"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("STDEV.S", "СТАНДОТКЛОН.В"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("STDEVA", "СТАНДОТКЛОНА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("STDEVP", "СТАНДОТКЛОНП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("STDEVPA", "СТАНДОТКЛОНПА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("STEYX", "СТОШYX"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("SUBSTITUTE", "ПОДСТАВИТЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("SUBTOTAL", "ПРОМЕЖУТОЧНЫЕ.ИТОГИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("SUM", "СУММ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("SUMIF", "СУММЕСЛИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("SUMIFS", "СУММЕСЛИМН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("SUMPRODUCT", "СУММПРОИЗВ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SUMSQ", "СУММКВ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SUMX2MY2", "СУММРАЗНКВ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SUMX2PY2", "СУММСУММКВ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SUMXMY2", "СУММКВРАЗН"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("SWITCH", "ПЕРЕКЛЮЧ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("SYD", "АСЧ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("T", "Т"), + // reviewed: Independent detailed syntax and Microsoft syntax distinguish T.DIST from obsolete TDIST; both broad translation tables incorrectly conflate the pair | sources: https://www.formulafind.com/ru/функции/статистические/student-rasp-function | https://support.microsoft.com/ru-ru/excel/functions/t-dist-function + ("T.DIST", "СТЬЮДЕНТ.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("T.DIST.2T", "СТЬЮДЕНТ.РАСП.2Х"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("T.DIST.RT", "СТЬЮДЕНТ.РАСП.ПХ"), + ("T.INV", "СТЬЮДЕНТ.ОБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("T.INV.2T", "СТЬЮДЕНТ.ОБР.2Х"), + ("T.TEST", "СТЬЮДЕНТ.ТЕСТ"), + // reviewed: Microsoft title and meta give the Russian name; the syntax and examples were left untranslated (English name) | sources: https://support.microsoft.com/ru-ru/excel/functions/take-function + ("TAKE", "ВЗЯТЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("TBILLEQ", "РАВНОКЧЕК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("TBILLPRICE", "ЦЕНАКЧЕК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("TBILLYIELD", "ДОХОДКЧЕК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("TDIST", "СТЬЮДРАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("TEXT", "ТЕКСТ"), + ("TEXTAFTER", "ТЕКСТПОСЛЕ"), + ("TEXTBEFORE", "ТЕКСТДО"), + // reviewed | sources: https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("TEXTJOIN", "ОБЪЕДИНИТЬ"), + // reviewed: Microsoft syntax and examples give the Russian name; the title and meta were left untranslated (English name) | sources: https://support.microsoft.com/ru-ru/excel/functions/textsplit-function + ("TEXTSPLIT", "ТЕКСТРАЗД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("TIME", "ВРЕМЯ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("TIMEVALUE", "ВРЕМЗНАЧ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("TINV", "СТЬЮДРАСПОБР"), + ("TOCOL", "ПОСТОЛБЦ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("TODAY", "СЕГОДНЯ"), + ("TOROW", "ПОСТРОК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("TRANSPOSE", "ТРАНСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("TREND", "ТЕНДЕНЦИЯ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("TRIM", "СЖПРОБЕЛЫ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("TRIMMEAN", "УРЕЗСРЕДНЕЕ"), + ("TRUE", "ИСТИНА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("TRUNC", "ОТБР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("TTEST", "ТТЕСТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("TYPE", "ТИП"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("UNICHAR", "ЮНИСИМВ"), + // reviewed: Independent article explicitly pairs English and Russian names and shows function syntax | sources: https://www.planetaexcel.ru/techniques/25/9457/ + ("UNIQUE", "УНИК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("UPPER", "ПРОПИСН"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("VALUE", "ЗНАЧЕН"), + // reviewed: Microsoft title, meta, syntax and examples all agree; the function tables only list the English name | sources: https://support.microsoft.com/ru-ru/excel/functions/valuetotext-function + ("VALUETOTEXT", "ЗНАЧЕНИЕВТЕКСТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("VAR", "ДИСП"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("VAR.P", "ДИСП.Г"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("VAR.S", "ДИСП.В"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("VARA", "ДИСПА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("VARP", "ДИСПР"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("VARPA", "ДИСПРА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("VDB", "ПУО"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("VLOOKUP", "ВПР"), + ("VSTACK", "ВСТОЛБИК"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("WEBSERVICE", "ВЕБСЛУЖБА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("WEEKDAY", "ДЕНЬНЕД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("WEEKNUM", "НОМНЕДЕЛИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("WEIBULL", "ВЕЙБУЛЛ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("WEIBULL.DIST", "ВЕЙБУЛЛ.РАСП"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("WORKDAY", "РАБДЕНЬ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("WORKDAY.INTL", "РАБДЕНЬ.МЕЖД"), + // reviewed: Microsoft syntax and examples give the Russian name; the title and meta were left untranslated (English name) | sources: https://support.microsoft.com/ru-ru/excel/functions/wrapcols-function + ("WRAPCOLS", "СВЕРНСТОЛБЦ"), + // reviewed: Microsoft syntax and examples give the Russian name; the title and meta were left untranslated (English name) | sources: https://support.microsoft.com/ru-ru/excel/functions/wraprows-function + ("WRAPROWS", "СВЕРНСТРОК"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("XIRR", "ЧИСТВНДОХ"), + ("XLOOKUP", "ПРОСМОТРX"), + // reviewed: Microsoft title, meta, syntax and examples all agree (Latin X, like ПРОСМОТРX); the function tables only list the English name | sources: https://support.microsoft.com/ru-ru/excel/functions/xmatch-function + ("XMATCH", "ПОИСКПОЗX"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("XNPV", "ЧИСТНЗ"), + // reviewed | sources: https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("XOR", "ИСКЛИЛИ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://easy-excel.com/excel-in-other-languages/excel-functions-in-russian/ | https://excel-academy.ru/tools/excel-functions/ + ("YEAR", "ГОД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("YEARFRAC", "ДОЛЯГОДА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("YIELD", "ДОХОД"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("YIELDDISC", "ДОХОДСКИДКА"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ | https://excel-academy.ru/tools/excel-functions/ + ("YIELDMAT", "ДОХОДПОГАШ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("Z.TEST", "Z.ТЕСТ"), + // reviewed | sources: https://www.perfectxl.com/academy/functions/translations/english-russian/ | https://functiontranslator.com/ru/ + ("ZTEST", "ZТЕСТ"), + ], +}; diff --git a/crates/formula/src/lexer.rs b/crates/formula/src/lexer.rs index 4c41d3609d..5b8467dfbb 100644 --- a/crates/formula/src/lexer.rs +++ b/crates/formula/src/lexer.rs @@ -160,12 +160,17 @@ pub fn tokenize_locale(src: &str, locale: crate::FormulaLocale) -> Result= t.len() && rest.get(..t.len()).is_some_and(|p| p.eq_ignore_ascii_case(t)) { - found = Some(e); + found = Some((e, t.chars().count())); break; } } - let Some(e) = found else { return Err(LexError { msg: "unknown error literal".into(), pos: start }) }; - let len = e.as_str().chars().count(); + // The language's own spelling (`#NV`, `#Н/Д`); the longer match wins. + if let Some((e, len)) = locale.error_prefix(rest) + && found.is_none_or(|(_, english)| len > english) + { + found = Some((e, len)); + } + let Some((e, len)) = found else { return Err(LexError { msg: "unknown error literal".into(), pos: start }) }; // `#REF!A1` style is not valid; `#REF!` is an error literal. push(&mut out, Tok::Error(e), i + len); i += len; @@ -192,10 +197,17 @@ pub fn tokenize_locale(src: &str, locale: crate::FormulaLocale) -> Result j += 1, } } - let inner = src.get(pos_of(i + 1)..pos_of(j.saturating_sub(1))).unwrap_or("").to_string(); + let inner = src.get(pos_of(i + 1)..pos_of(j.saturating_sub(1))).unwrap_or(""); + let inner = if locale == crate::FormulaLocale::En { inner.to_string() } else { locale.struct_to_canonical(inner) }; push(&mut out, Tok::Struct(inner), j); i = j; } + // Inside braces the language's row separator ends a row, even where it is a word + // character (`.` in it-IT: `{1\2.3\4}`). + c if array_depth > 0 && c == locale.array_row_separator() => { + push(&mut out, Tok::Semicolon, i + 1); + i += 1; + } '.' if ch(i + 1) == Some(':') => { // Trim reference `A1.:E10` / `A1.:.E10` (the word before stopped at the dot). if ch(i + 2) == Some('.') && starts_range_end(ch(i + 3)) { @@ -213,8 +225,11 @@ pub fn tokenize_locale(src: &str, locale: crate::FormulaLocale) -> Result 0 && locale.array_row_separator() == ':'; + let is_row_ref = !rows_by_colon && { let mut k = j; if ch(k) == Some('.') && ch(k + 1) == Some(':') { k += 1; @@ -290,7 +305,10 @@ pub fn tokenize_locale(src: &str, locale: crate::FormulaLocale) -> Result { - if ch(i + 1) == Some('.') && starts_range_end(ch(i + 2)) { + if array_depth > 0 && locale.array_row_separator() == ':' { + push(&mut out, Tok::Semicolon, i + 1); + i += 1; + } else if ch(i + 1) == Some('.') && starts_range_end(ch(i + 2)) { push(&mut out, Tok::Trim(TrimMode::Trailing), i + 2); i += 2; } else { @@ -327,7 +345,9 @@ pub fn tokenize_locale(src: &str, locale: crate::FormulaLocale) -> Result { let mut j = i; - while ch(j).is_some_and(|c| is_word_char(c) && !(array_depth > 0 && c == locale.array_column_separator())) { + while ch(j).is_some_and(|c| { + is_word_char(c) && !(array_depth > 0 && (c == locale.array_column_separator() || c == locale.array_row_separator())) + }) { j += 1; } let w: String = chars.get(i..j).map(|s| s.iter().map(|c| c.1).collect()).unwrap_or_default(); @@ -337,13 +357,17 @@ pub fn tokenize_locale(src: &str, locale: crate::FormulaLocale) -> Result 0 && c == locale.array_column_separator())) { + while ch(k).is_some_and(|c| { + is_word_char(c) && !(array_depth > 0 && (c == locale.array_column_separator() || c == locale.array_row_separator())) + }) { k += 1; } k > j + 1 && ch(k) == Some('!') } { let mut k = j + 1; - while ch(k).is_some_and(|c| is_word_char(c) && !(array_depth > 0 && c == locale.array_column_separator())) { + while ch(k).is_some_and(|c| { + is_word_char(c) && !(array_depth > 0 && (c == locale.array_column_separator() || c == locale.array_row_separator())) + }) { k += 1; } let w2: String = chars.get(j + 1..k).map(|s| s.iter().map(|c| c.1).collect()).unwrap_or_default(); diff --git a/crates/formula/src/parser.rs b/crates/formula/src/parser.rs index 4fd3b7bb24..d5946ef666 100644 --- a/crates/formula/src/parser.rs +++ b/crates/formula/src/parser.rs @@ -27,7 +27,7 @@ pub(crate) fn parse_syntax(src: &str, locale: crate::FormulaLocale) -> Result Ok(e), @@ -66,7 +66,7 @@ struct Parser { toks: Vec, i: usize, depth: usize, - input: bool, + locale: crate::FormulaLocale, } fn word_is_cols(w: &str) -> Option<(u32, bool)> { @@ -375,7 +375,9 @@ impl Parser { }, Tok::Text(s) => Expr::Text(Arc::from(s)), Tok::Bool(b) => Expr::Bool(b), - Tok::Word(w) if self.input => crate::input::boolean_alias(&w) + Tok::Word(w) => self + .locale + .boolean(&w) .map(Expr::Bool) .ok_or_else(|| self.err(format!("array constants may only contain constants, found {}", describe(&Tok::Word(w)))))?, Tok::Error(e) => Expr::Error(e), diff --git a/crates/formula/tests/localized_input.rs b/crates/formula/tests/localized_input.rs new file mode 100644 index 0000000000..283cc531aa --- /dev/null +++ b/crates/formula/tests/localized_input.rs @@ -0,0 +1,137 @@ +//! German, Brazilian Portuguese, Russian, Italian and the full Spanish table: entry and display syntax. +use gridcraft_core::CellError; +use gridcraft_formula::FormulaLocale::{self, De, Es, It, PtBr, Ru}; +use gridcraft_formula::{parse, parse_input, print, print_input}; + +const LOCALIZED: [FormulaLocale; 5] = [Es, De, PtBr, Ru, It]; + +fn canonical(src: &str, locale: FormulaLocale) -> String { + print(&parse_input(src, locale, |_| false).unwrap_or_else(|e| panic!("{locale:?} `{src}`: {e}"))) +} + +fn shown(canonical: &str, locale: FormulaLocale) -> String { + print_input(&parse(canonical).unwrap(), locale, |_| false).unwrap() +} + +#[test] +fn each_language_spells_formulas_like_its_excel() { + for (locale, local, english) in [ + (De, "SUMME(A1;2,5)", "SUM(A1,2.5)"), + (De, "WENN(WAHR;SVERWEIS(A2;D:E;2;FALSCH);#NV)", "IF(TRUE,VLOOKUP(A2,D:E,2,FALSE),#N/A)"), + (De, "SUMME({1.2;3,5.4})", "SUM({1,2;3.5,4})"), + (De, "ZÄHLENWENN(Tabelle1[[#Kopfzeilen];[Spalte1]];\">1,5\")", "COUNTIF(Tabelle1[[#Headers],[Spalte1]],\">1,5\")"), + (De, "WENNFEHLER(1/0;#WERT!)", "IFERROR(1/0,#VALUE!)"), + (PtBr, "SE(VERDADEIRO;SOMA(1,5;2);#N/D)", "IF(TRUE,SUM(1.5,2),#N/A)"), + (PtBr, "PROCV(A2;Tabela1[#Tudo];2;FALSO)", "VLOOKUP(A2,Tabela1[#All],2,FALSE)"), + (PtBr, "SOMA({1\\2;3\\4})", "SUM({1,2;3,4})"), + (Ru, "СУММ({1;2:3;4})", "SUM({1,2;3,4})"), + (Ru, "СУММ(Таблица1[[#Итого];[Сумма]])", "SUM(Таблица1[[#Totals],[Сумма]])"), + (Es, "CONTAR.SI.CONJUNTO(A1:A3;\">1\")", "COUNTIFS(A1:A3,\">1\")"), + (Es, "SI.ERROR(1/0;#¡VALOR!)", "IFERROR(1/0,#VALUE!)"), + // Italian (see `input/it.rs`): `\` between array columns, `.` between rows. + (It, "SE(VERO;CERCA.VERT(A2;D:E;2;FALSO);#N/D)", "IF(TRUE,VLOOKUP(A2,D:E,2,FALSE),#N/A)"), + (It, "SOMMA({1\\2.3\\4})+1,5", "SUM({1,2;3,4})+1.5"), + (It, "SOMMA({1,5\\2.3\\4,25})", "SUM({1.5,2;3,4.25})"), + (It, "CONTA.SE(Tabella1[[#Intestazioni];[a]];\">1,5\")", "COUNTIF(Tabella1[[#Headers],[a]],\">1,5\")"), + (It, "SE.ERRORE(1/0;#DIV/0!)+CERCA.X(1;A:A;B:B)", "IFERROR(1/0,#DIV/0!)+XLOOKUP(1,A:A,B:B)"), + (It, "RIGHE(Tabella1[#Tutti])+ASS(#VALORE!)", "ROWS(Tabella1[#All])+ABS(#VALUE!)"), + (It, "E(VERO;O(FALSO;NON(VERO)))", "AND(TRUE,OR(FALSE,NOT(TRUE)))"), + (It, "SE.NON.DISP.(#N/D;MEDIA.PIÙ.SE(A1:A3;B1:B3;\">0\"))", "IFNA(#N/A,AVERAGEIFS(A1:A3,B1:B3,\">0\"))"), + (It, "MATR.SOMMA.PRODOTTO(A1:A3;B1:B3)+MAX(1;2)", "SUMPRODUCT(A1:A3,B1:B3)+MAX(1,2)"), + ] { + assert_eq!(canonical(local, locale), english, "{locale:?} entry"); + assert_eq!(shown(english, locale), local, "{locale:?} display"); + } +} + +#[test] +fn every_language_round_trips_canonical_formulas() { + for formula in [ + "SUM(1.5,-2.25,A1:B2 B2:C3)", + r#"IF(AND(TRUE,NOT(FALSE)),"a,b;c",#DIV/0!)"#, + r#"{1.5,TRUE;#N/A,"x;y"}"#, + "SUM((A1,B1),Sheet2!A:A)", + "Table1[[#This Row],[a]]+SUM(Table1[#Totals])+Table1[[#Headers],[a]:[b]]", + "LET(x,1,LAMBDA(y,x+y)(2))", + "XLOOKUP(1,A:A,B:B,#N/A)+IFNA(#GETTING_DATA,#SPILL!)", + "SUM(1:3)+ROWS($2:$2)", + "CEILING.MATH(2.5)+T.TEST(A1:A3,B1:B3,2,1)", + ] { + let expected = print(&parse(formula).unwrap()); + for locale in FormulaLocale::ALL { + let local = shown(formula, locale); + assert_eq!(canonical(&local, locale), expected, "{locale:?}: {formula} shown as {local}"); + } + } +} + +#[test] +fn english_names_and_any_letter_case_are_accepted() { + assert_eq!(canonical("SUM(1;2)+SUMME(3)", De), "SUM(1,2)+SUM(3)"); + assert_eq!(canonical("zählenwenn(A1:A3;1)", De), "COUNTIF(A1:A3,1)"); + assert_eq!(canonical("сумм(1;2)+#н/д", Ru), "SUM(1,2)+#N/A"); + assert_eq!(canonical("{истина:ложь}", Ru), "{TRUE;FALSE}"); + assert_eq!(canonical("somma.più.se(A1:A3;B1:B3;1)+falso+media(1)", It), "SUMIFS(A1:A3,B1:B3,1)+FALSE+AVERAGE(1)"); + assert_eq!(canonical("{vero.falso}", It), "{TRUE;FALSE}"); + // A local name that is another function's English name means the local function, as in + // Spanish Excel: DECIMAL is FIXED there, and the base conversion is CONV.DECIMAL. + assert_eq!(canonical("DECIMAL(1,5;1)", Es), "FIXED(1.5,1)"); + assert_eq!(canonical("CONV.DECIMAL(\"FF\";16)", Es), "DECIMAL(\"FF\",16)"); + // English separators are not the language's syntax. + assert!(parse_input("SUMME(1.5;2)", De, |_| false).is_err()); + assert!(parse_input("SUM(1,2)", Ru, |_| false).is_ok_and(|e| print(&e) == "SUM(1.2)")); +} + +#[test] +fn names_shadow_local_function_names_in_any_script() { + assert_eq!(canonical("LET(zählenwenn;LAMBDA(x;x*2);ZÄHLENWENN(3))", De), "LET(zählenwenn,LAMBDA(x,x*2),ZÄHLENWENN(3))"); + let known = |name: &str| name == "СУММ"; + assert_eq!(print(&parse_input("СУММ(1)", Ru, known).unwrap()), "СУММ(1)"); + assert_eq!(print_input(&parse("SUM(1)").unwrap(), Ru, known).unwrap(), "SUM(1)"); +} + +#[test] +fn language_tables_are_sorted_unique_and_unambiguous() { + for locale in LOCALIZED { + let table = locale.translations(); + assert!(table.len() > 400, "{locale:?}: {} names", table.len()); + assert!(table.windows(2).all(|w| w[0].0 < w[1].0), "{locale:?}: not sorted by canonical name"); + let mut locals: Vec = table.iter().map(|(_, local)| local.to_uppercase()).collect(); + locals.sort(); + let all = locals.len(); + locals.dedup(); + assert_eq!(locals.len(), all, "{locale:?}: two functions share a local name"); + for (en, local) in table { + assert_ne!(en, local, "{locale:?}: {en} is listed though it keeps its English name"); + assert_eq!(locale.function_name(en), *local); + assert_eq!(locale.canonical_name(local), *en); + // The TRUE() and FALSE() functions are spelled like the booleans; nothing else may be. + let upper = local.to_uppercase(); + let boolean = upper == locale.boolean_name(true) || upper == locale.boolean_name(false); + assert_eq!(boolean, matches!(*en, "TRUE" | "FALSE"), "{locale:?}: {en} = {local}"); + } + for e in CellError::ALL { + assert_eq!(canonical(locale.error_name(e), locale), e.as_str(), "{locale:?}"); + } + } +} + +#[test] +fn malformed_localized_input_is_an_error() { + for (locale, bad) in [ + (De, "SUMME({1.}"), + (De, "Tabelle1[[#Kopfzeilen];"), + (De, "#WERT"), + (Ru, "{ИСТИНА:"), + (Ru, "СУММ(1:"), + (PtBr, "SOMA(1,"), + (PtBr, "{SOMA(1)}"), + (Es, "#¡VALOR"), + ] { + assert!(parse_input(bad, locale, |_| false).is_err(), "{locale:?}: {bad}"); + } + for locale in LOCALIZED { + let chain = format!("{}+", locale.boolean_name(true)).repeat(300) + "1"; + assert!(parse_input(&chain, locale, |_| false).is_err(), "{locale:?}"); + } +} diff --git a/crates/ui-egui/examples/snapshot.rs b/crates/ui-egui/examples/snapshot.rs index a171199a1c..48c31603f1 100644 --- a/crates/ui-egui/examples/snapshot.rs +++ b/crates/ui-egui/examples/snapshot.rs @@ -1,7 +1,7 @@ //! Renders the whole GridCraft window offscreen (wgpu, no window) to a PNG. //! //! `cargo run --release -p gridcraft-ui-egui --example snapshot -- [--sample sales] [--in file.xlsx] -//! [--size 1440x900] [--scale 2] [--cmd 'id={json}']... [--tab Insert] [--dark] [--language en|zh|ja|ko|ru|pt|cs] +//! [--size 1440x900] [--scale 2] [--cmd 'id={json}']... [--tab Insert] [--dark] [--language en|zh|ja|ko|ru|pt|cs|it] //! [--dialog 'name={json}'] [--hf-edit header|footer] out.png` use gridcraft_engine::Session; diff --git a/crates/ui-egui/src/control.rs b/crates/ui-egui/src/control.rs index b753b00e8e..0ccbbeab03 100644 --- a/crates/ui-egui/src/control.rs +++ b/crates/ui-egui/src/control.rs @@ -194,7 +194,11 @@ pub fn handle(app: &mut SheetApp, ctx: &egui::Context, method: &str, p: &Json) - "Submit Print Job", "existing file.print sheet/pagination params → {printing,bytes,pending}; submits without opening a dialog", ), - ("app.language.set", "Interface Language", "{language: \"en\"|\"zh\"|\"ja\"|\"ko\"|\"ru\"|\"pt\"|\"de\"|\"cs\"} (alias: code)"), + ( + "app.language.set", + "Interface Language", + "{language: \"en\"|\"zh\"|\"ja\"|\"ko\"|\"ru\"|\"pt\"|\"de\"|\"cs\"|\"it\"} (alias: code)", + ), ("app.language.english", "Interface Language: English", ""), ("app.language.japanese", "Interface Language: Japanese", ""), ] { diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index 5e859c68ef..41184893c6 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -1578,16 +1578,21 @@ fn insert_function(app: &mut SheetApp, ui: &mut egui::Ui, d: &mut Dialog, confir }); let locale = app.ui.language.formula_locale(); let list = gridcraft_engine::cmd::formulas::function_list(); - let q = d.search.to_ascii_lowercase(); - let hits: Vec<&Json> = list + // Unicode lower case: local names and searches are not ASCII (`zählenwenn`, `сумм`). + let q = d.search.to_lowercase(); + let mut hits: Vec<&Json> = list .iter() .filter(|f| { q.is_empty() - || f["name"].as_str().is_some_and(|n| locale.function_name(n).to_ascii_lowercase().contains(&q)) - || f["description"].as_str().is_some_and(|n| n.to_ascii_lowercase().contains(&q)) + || f["name"].as_str().is_some_and(|n| locale.function_name(n).to_lowercase().contains(&q)) + || f["description"].as_str().is_some_and(|n| n.to_lowercase().contains(&q)) }) - .take(300) .collect(); + if locale != gridcraft_engine::formula::FormulaLocale::En { + // The list is sorted by English name; list it by the name shown. + hits.sort_by_cached_key(|&f| locale.function_name(f["name"].as_str().unwrap_or(""))); + } + hits.truncate(300); egui::ScrollArea::vertical().max_height(260.0).show(ui, |ui| { for (i, f) in hits.iter().enumerate() { let name = locale.function_name(f["name"].as_str().unwrap_or("")); diff --git a/crates/ui-egui/src/editor.rs b/crates/ui-egui/src/editor.rs index 767f1346a8..e8c5340c60 100644 --- a/crates/ui-egui/src/editor.rs +++ b/crates/ui-egui/src/editor.rs @@ -114,14 +114,18 @@ impl EditState { return; } let before = self.text.get(..self.byte_caret()).unwrap_or(""); - let word: String = - before.chars().rev().take_while(|c| c.is_ascii_alphanumeric() || *c == '.' || *c == '_').collect::().chars().rev().collect(); + let word: String = before.chars().rev().take_while(|c| is_name_char(*c)).collect::().chars().rev().collect(); if word.is_empty() || word.chars().next().is_some_and(|c| c.is_ascii_digit()) { return; } - let u = word.to_ascii_uppercase(); + // Unicode upper case: local function names (`ZÄHLENWENN`, `СУММ`) are not ASCII. + let u = word.to_uppercase(); // Not after a column letter of a reference like A1 (digits follow) – fine either way. - self.autocomplete = names.iter().filter(|n| n.starts_with(&u)).take(12).cloned().collect(); + // Sorted by the name shown, since a local name sits where its English name sorts. + let mut hits: Vec<&String> = names.iter().filter(|n| n.starts_with(&u)).collect(); + hits.sort_unstable(); + hits.dedup(); + self.autocomplete = hits.into_iter().take(12).cloned().collect(); if self.autocomplete.len() == 1 && self.autocomplete[0] == u { self.autocomplete.clear(); } @@ -133,7 +137,7 @@ impl EditState { let Some(name) = self.autocomplete.get(self.ac_index).cloned() else { return false }; let caret_b = self.byte_caret(); let before = self.text.get(..caret_b).unwrap_or(""); - let wlen: usize = before.chars().rev().take_while(|c| c.is_ascii_alphanumeric() || *c == '.' || *c == '_').map(char::len_utf8).sum(); + let wlen: usize = before.chars().rev().take_while(|c| is_name_char(*c)).map(char::len_utf8).sum(); let start = caret_b - wlen; let (Some(a), Some(b)) = (self.text.get(..start), self.text.get(caret_b..)) else { return false }; self.text = format!("{a}{name}({b}"); @@ -170,18 +174,11 @@ impl EditState { '{' | '[' => depth -= 1, '(' => { if depth == 0 { - let name: String = chars[..i] - .iter() - .rev() - .take_while(|c| c.is_ascii_alphanumeric() || **c == '.' || **c == '_') - .collect::() - .chars() - .rev() - .collect(); + let name: String = chars[..i].iter().rev().take_while(|c| is_name_char(**c)).collect::().chars().rev().collect(); if name.is_empty() { return None; } - return Some((name.to_ascii_uppercase(), arg)); + return Some((name.to_uppercase(), arg)); } depth -= 1; } @@ -193,6 +190,11 @@ impl EditState { } } +/// A character of a function name as typed: letters of any script, digits, `.` and `_`. +fn is_name_char(c: char) -> bool { + c.is_alphanumeric() || c == '.' || c == '_' +} + /// References in formula text with their byte spans and colour index (same reference text ⇒ /// same colour), for colouring the editor and outlining ranges on the grid. pub fn formula_refs(text: &str) -> Vec<(usize, usize, RangeRef, Option, usize)> { @@ -313,6 +315,20 @@ mod tests { assert_eq!(e.current_function(), Some(("SUM".into(), 1))); } + #[test] + fn autocomplete_and_hints_take_local_names_in_any_script() { + // Local names arrive in English order (ZÄHLENWENNS is COUNTIFS); the list shows them sorted. + let names: Vec = ["ZÄHLENWENNS", "ZÄHLENWENN", "ZEIT", "СУММ"].iter().map(|s| s.to_string()).collect(); + let mut e = EditState::new(0, CellRef::new(0, 0), "=zähl".into(), true, false); + e.update_autocomplete(&names); + assert_eq!(e.autocomplete, ["ZÄHLENWENN", "ZÄHLENWENNS"]); + assert!(e.accept_autocomplete()); + assert_eq!(e.text, "=ZÄHLENWENN("); + let mut e = EditState::new(0, CellRef::new(0, 0), "=ЕСЛИ(A1>0;сумм(B1;".into(), true, false); + e.locale = gridcraft_engine::formula::FormulaLocale::Ru; + assert_eq!(e.current_function(), Some(("СУММ".into(), 1))); + } + #[test] fn ref_spans() { let r = formula_refs("=A1+B2:C3*a1+Sheet2!D4"); diff --git a/crates/ui-egui/src/formula_locale.rs b/crates/ui-egui/src/formula_locale.rs index ad0725e547..ae471c57f9 100644 --- a/crates/ui-egui/src/formula_locale.rs +++ b/crates/ui-egui/src/formula_locale.rs @@ -52,8 +52,8 @@ pub(crate) fn display(text: &str, locale: FormulaLocale, wb: &Workbook, sheet: u .unwrap_or_else(|_| text.to_string()) } -// Descriptions/signatures for the supported Spanish function table; untranslated functions -// retain their English help. Parameter punctuation follows the same locale as entry. +// Descriptions/signatures for common Spanish functions; other functions keep their English help +// under their local name. Parameter punctuation follows the same locale as entry. const SPANISH_HELP: &[(&str, &str, &str)] = &[ ("SUM", "SUMA(número1; [número2]; ...)", "Suma los números."), ("AVERAGE", "PROMEDIO(número1; [número2]; ...)", "Devuelve el promedio de los números."), @@ -74,7 +74,11 @@ pub(crate) fn signature(name: &str, locale: FormulaLocale) -> Option { { return Some((*signature).into()); } - crate::formula_bar::function_signature(canonical).map(|s| s.replace(',', &locale.list_separator().to_string())) + let signature = crate::formula_bar::function_signature(canonical)?.replace(',', &locale.list_separator().to_string()); + Some(match signature.strip_prefix(canonical) { + Some(params) if locale != FormulaLocale::En => format!("{}{params}", locale.function_name(canonical)), + _ => signature, + }) } pub(crate) fn description(name: &str, locale: FormulaLocale) -> Option { diff --git a/crates/ui-egui/src/i18n.rs b/crates/ui-egui/src/i18n.rs index 406cc3dd51..60d1bfabc9 100644 --- a/crates/ui-egui/src/i18n.rs +++ b/crates/ui-egui/src/i18n.rs @@ -13,6 +13,7 @@ mod cs; mod de; mod es; mod fr; +mod it; mod ko; mod pt; mod ru; @@ -33,10 +34,11 @@ pub enum Language { De, Cs, Fr, + It, } impl Language { - pub const ALL: [Self; 10] = [Self::En, Self::Es, Self::Zh, Self::Ja, Self::Ko, Self::Ru, Self::PtBr, Self::De, Self::Cs, Self::Fr]; + pub const ALL: [Self; 11] = [Self::En, Self::Es, Self::Zh, Self::Ja, Self::Ko, Self::Ru, Self::PtBr, Self::De, Self::Cs, Self::Fr, Self::It]; /// The language's own name, shown in the switcher. pub fn name(self) -> &'static str { @@ -51,6 +53,7 @@ impl Language { Self::De => "Deutsch", Self::Cs => "Čeština", Self::Fr => "Français", + Self::It => "Italiano", } } @@ -67,6 +70,7 @@ impl Language { Self::De => "de", Self::Cs => "cs", Self::Fr => "fr", + Self::It => "it", } } @@ -86,6 +90,7 @@ impl Language { "de" => Some(Self::De), "cs" => Some(Self::Cs), "fr" => Some(Self::Fr), + "it" => Some(Self::It), _ => None, } } @@ -103,8 +108,18 @@ impl Language { } } + /// The formula language this interface language enters and shows. Japanese, Chinese and + /// Korean Excel use English function names; Czech and French have no function table yet. pub fn formula_locale(self) -> gridcraft_engine::formula::FormulaLocale { - if self == Self::Es { gridcraft_engine::formula::FormulaLocale::Es } else { gridcraft_engine::formula::FormulaLocale::En } + use gridcraft_engine::formula::FormulaLocale; + match self { + Self::Es => FormulaLocale::Es, + Self::De => FormulaLocale::De, + Self::PtBr => FormulaLocale::PtBr, + Self::Ru => FormulaLocale::Ru, + Self::It => FormulaLocale::It, + Self::En | Self::Zh | Self::Ja | Self::Ko | Self::Cs | Self::Fr => FormulaLocale::En, + } } /// Translates an interface label; untranslated labels fall back to English. @@ -123,6 +138,7 @@ impl Language { Self::De => de::translate(text), Self::Cs => cs::translate(text), Self::Fr => fr::translate(text), + Self::It => it::translate(text), }; translated.unwrap_or_else(|| text.rsplit_once('|').map_or(text, |(_, label)| label)) } @@ -587,6 +603,7 @@ mod tests { assert!(de::translate(english).is_some_and(|text| !text.is_empty()), "missing German: {english}"); assert!(cs::translate(english).is_some_and(|text| !text.is_empty()), "missing Czech: {english}"); assert!(fr::translate(english).is_some_and(|text| !text.is_empty()), "missing French: {english}"); + assert!(it::translate(english).is_some_and(|text| !text.is_empty()), "missing Italian: {english}"); } assert_eq!(Language::Ja.tr("Data"), "データ"); assert_eq!(Language::Zh.tr("Data"), "数据"); @@ -600,6 +617,8 @@ mod tests { assert_eq!(Language::De.tr("Sheet1!A1"), "Sheet1!A1"); assert_eq!(Language::Fr.tr("Data"), "Données"); assert_eq!(Language::Fr.tr("Sheet1!A1"), "Sheet1!A1"); + assert_eq!(Language::It.tr("Data"), "Dati"); + assert_eq!(Language::It.tr("Sheet1!A1"), "Sheet1!A1"); assert_eq!(Language::PtBr.tr("Date"), "Data"); assert_eq!(Language::PtBr.tr("Sheet1!A1"), "Sheet1!A1"); assert_eq!(Language::Ja.tr("Sheet1!A1"), "Sheet1!A1"); @@ -616,6 +635,8 @@ mod tests { assert_eq!(Language::Ja.tr("Orientation"), "方向"); assert_eq!(Language::Cs.tr("Page Layout|Orientation"), "Orientace"); assert_eq!(Language::Cs.tr("Orientation"), "Orientace textu"); + assert_eq!(Language::It.tr("Page Layout|Orientation"), "Orientamento"); + assert_eq!(Language::It.tr("Orientation"), "Orientamento testo"); assert_eq!(Language::parse("xx"), None); } @@ -654,6 +675,9 @@ mod tests { assert_eq!(Language::from_tag("fr-FR"), Some(Language::Fr)); assert_eq!(Language::from_tag("fr_CA"), Some(Language::Fr)); assert_eq!(Language::parse("fr"), Some(Language::Fr)); + assert_eq!(Language::from_tag("it-IT"), Some(Language::It)); + assert_eq!(Language::from_tag("it_CH.UTF-8"), Some(Language::It)); + assert_eq!(Language::parse("it"), Some(Language::It)); } #[test] diff --git a/crates/ui-egui/src/i18n/it.rs b/crates/ui-egui/src/i18n/it.rs new file mode 100644 index 0000000000..e37b5d3c28 --- /dev/null +++ b/crates/ui-egui/src/i18n/it.rs @@ -0,0 +1,399 @@ +//! Italian translations for the interface strings in i18n.rs. Ribbon tabs, groups and commands use +//! the names Italian Excel users know (feature names); descriptions and messages are written from +//! the meaning of the English. Anything absent falls back to English. Formula names and separators +//! are localized separately (`formula_locale`). + +pub(super) fn translate(text: &str) -> Option<&'static str> { + Some(match text { + "Paste" => "Incolla", + "Paste Values" => "Incolla valori", + "Paste Formulas" => "Incolla formule", + "Paste Formatting" => "Incolla formattazione", + "Transpose" => "Trasponi", + "Paste Link" => "Incolla collegamento", + "Paste Special…" => "Incolla speciale…", + "Insert Copied Cells" => "Inserisci celle copiate", + "Insert Copied Cells…" => "Inserisci celle copiate…", + "Insert Cut Cells" => "Inserisci celle tagliate", + "Insert Paste" => "Inserisci e incolla", + "Cut (⌘X)" => "Taglia (⌘X)", + "Copy (⌘C)" => "Copia (⌘C)", + "Format Painter (double-click to keep it on)" => "Copia formato (doppio clic per mantenerlo attivo)", + "Bold (⌘B)" => "Grassetto (⌘B)", + "Italic (⌘I)" => "Corsivo (⌘I)", + "Underline (⌘U)" => "Sottolineato (⌘U)", + "Double Underline" => "Sottolineatura doppia", + "Strikethrough" => "Barrato", + "Underline" => "Sottolineato", + "Increase Font Size" => "Aumenta dimensione carattere", + "Decrease Font Size" => "Riduci dimensione carattere", + "Wrap Text" => "Testo a capo", + "Merge & Center" => "Unisci e allinea al centro", + "Merge Cells" => "Unisci celle", + "Merge Across" => "Unisci in orizzontale", + "Unmerge Cells" => "Dividi celle", + "Fill Color" => "Colore riempimento", + "Font Color" => "Colore carattere", + "Borders" => "Bordi", + "Top\nAlign" => "Allinea\nin alto", + "Middle\nAlign" => "Allinea\nal centro", + "Bottom\nAlign" => "Allinea\nin basso", + "Left" => "A sinistra", + "Right" => "A destra", + "Center" => "Al centro", + "Horizontal" => "Orizzontale", + "Vertical Text" => "Testo verticale", + "Decrease Indent" => "Riduci rientro", + "Increase Indent" => "Aumenta rientro", + "Orientation" => "Orientamento testo", + "Page Layout|Orientation" => "Orientamento", + "Angle Counterclockwise" => "Ruota in senso antiorario", + "Angle Clockwise" => "Ruota in senso orario", + "Rotate Text Up" => "Ruota testo verso l'alto", + "Rotate Text Down" => "Ruota testo verso il basso", + "Accounting Number Format" => "Formato numero contabilità", + "Percent Style" => "Stile percentuale", + "Comma Style" => "Stile separatore", + "Increase Decimal" => "Aumenta decimali", + "Decrease Decimal" => "Diminuisci decimali", + "More Accounting Formats…" => "Altri formati contabilità…", + "Conditional\nFormatting" => "Formattazione\ncondizionale", + "Conditional Formatting" => "Formattazione condizionale", + "Format\nas Table" => "Formatta\ncome tabella", + "Cell\nStyles" => "Stili\ncella", + "Format Cells…" => "Formato celle…", + "Format Cell Alignment…" => "Allineamento celle…", + "Format\nPane" => "Riquadro\nformato", + "Format" => "Formato", + "Insert" => "Inserisci", + "Insert Cells…" => "Inserisci celle…", + "Delete" => "Elimina", + "Delete Cells…" => "Elimina celle…", + "Insert Sheet Rows" => "Inserisci righe foglio", + "Insert Sheet Columns" => "Inserisci colonne foglio", + "Delete Sheet Rows" => "Elimina righe foglio", + "Delete Sheet Columns" => "Elimina colonne foglio", + "Row Height…" => "Altezza righe…", + "AutoFit Row Height" => "Adatta altezza righe", + "Column Width…" => "Larghezza colonne…", + "AutoFit Column Width" => "Adatta larghezza colonne", + "Default Width…" => "Larghezza predefinita…", + "Hide Rows" => "Nascondi righe", + "Unhide Rows" => "Scopri righe", + "Hide Columns" => "Nascondi colonne", + "Unhide Columns" => "Scopri colonne", + "Lock Cell" => "Blocca cella", + "Clear" => "Cancella", + "Clear All" => "Cancella tutto", + "Clear Formats" => "Cancella formati", + "Clear Contents" => "Cancella contenuto", + "Clear Comments and Notes" => "Cancella commenti e note", + "Clear Hyperlinks" => "Cancella collegamenti ipertestuali", + "AutoSum" => "Somma automatica", + "AutoSum (⌘⇧T)" => "Somma automatica (⌘⇧T)", + "Flash\nFill" => "Riempimento\nrapido", + "Flash Fill" => "Riempimento rapido", + "Fill" => "Riempimento", + "Clear Print Area" => "Cancella area di stampa", + "Find &\nSelect" => "Trova e\nseleziona", + "Find…" => "Trova…", + "Replace…" => "Sostituisci…", + "Go To…" => "Vai a…", + "Go To Special…" => "Vai a formato speciale…", + "PivotTable" => "Tabella pivot", + "Recommended\nCharts" => "Grafici\nconsigliati", + "Table" => "Tabella", + "Pictures" => "Immagini", + "Shapes" => "Forme", + "Icons" => "Icone", + "Text\nBox" => "Casella\ndi testo", + "Comment" => "Commento", + "New\nComment" => "Nuovo\ncommento", + "New Note" => "Nuova nota", + "Show/Hide Note" => "Mostra/nascondi nota", + "Header &\nFooter" => "Intestazione\ne piè di pagina", + "Text to\nColumns" => "Testo in\ncolonne", + "Link" => "Collegamento", + "Symbol" => "Simbolo", + "Sparklines" => "Grafici sparkline", + "Checkbox" => "Casella di controllo", + "Insert checkboxes in the selected cells" => "Inserisci caselle di controllo nelle celle selezionate", + "Header & Footer" => "Intestazione e piè di pagina", + "Draw with ink" => "Disegna a penna", + "Eraser" => "Gomma", + "Ink to\nShape" => "Da input penna\na forma", + "Select\nObjects" => "Seleziona\noggetti", + "Themes" => "Temi", + "Margins" => "Margini", + "Size" => "Dimensioni", + "Print\nArea" => "Area\ndi stampa", + "Set Print Area" => "Imposta area di stampa", + "Breaks" => "Interruzioni", + "Insert Page Break" => "Inserisci interruzione di pagina", + "Remove Page Break" => "Rimuovi interruzione di pagina", + "Reset All Page Breaks" => "Reimposta tutte le interruzioni di pagina", + "Print\nTitles" => "Stampa\ntitoli", + "Sheet\nRight-to-Left" => "Foglio da destra\na sinistra", + "Sheet Right-to-Left" => "Foglio da destra a sinistra", + "Narrow" => "Stretti", + "Wide" => "Larghi", + "Normal" => "Normali", + "Portrait" => "Verticale", + "Landscape" => "Orizzontale", + "Custom Margins…" => "Margini personalizzati…", + "Insert\nFunction" => "Inserisci\nfunzione", + "Name\nManager" => "Gestione\nnomi", + "Define Name" => "Definisci nome", + "Use in Formula" => "Usa nella formula", + "Create from Selection" => "Crea da selezione", + "Trace Precedents" => "Individua precedenti", + "Trace Dependents" => "Individua dipendenti", + "Remove Arrows" => "Rimuovi frecce", + "Show Formulas" => "Mostra formule", + "Error Checking" => "Controllo errori", + "Evaluate Formula" => "Valuta formula", + "Watch Window" => "Finestra controllo celle", + "Calculation\nOptions" => "Opzioni\ndi calcolo", + "Calculate Now" => "Calcola ora", + "Calculate Sheet" => "Calcola foglio", + "Automatic" => "Automatico", + "Automatic Except for Data Tables" => "Automatico tranne che per le tabelle dati", + "Manual" => "Manuale", + "Sort &\nFilter" => "Ordina e\nfiltra", + "Sort" => "Ordina", + "Sort A to Z" => "Ordina dalla A alla Z", + "Sort Z to A" => "Ordina dalla Z alla A", + "Custom Sort…" => "Ordinamento personalizzato…", + "Filter" => "Filtro", + "Reapply" => "Riapplica", + "Get Data\n(Text/CSV)" => "Recupera dati\n(testo/CSV)", + "Remove\nDuplicates" => "Rimuovi\nduplicati", + "Data\nValidation" => "Convalida\ndati", + "Data Validation" => "Convalida dati", + "Data Validation…" => "Convalida dati…", + "Circle Invalid Data" => "Cerchia dati non validi", + "Clear Validation" => "Cancella convalida", + "Group" => "Raggruppa", + "Ungroup" => "Separa", + "Show Detail" => "Mostra dettagli", + "Hide Detail" => "Nascondi dettagli", + "Subtotal" => "Subtotale", + "Data\nAnalysis" => "Analisi\ndati", + "Data Analysis" => "Analisi dati", + "Solver" => "Risolutore", + "What-If\nAnalysis" => "Analisi\nda ipotesi", + "Data Table…" => "Tabella dati…", + "Scenario Manager…" => "Gestione scenari…", + "Goal Seek…" => "Ricerca obiettivo…", + "Forecast\nSheet" => "Foglio\nprevisione", + "Spelling" => "Controllo ortografia", + "Check\nAccessibility" => "Verifica\naccessibilità", + "Threaded Comments" => "Commenti in thread", + "Show\nComments" => "Mostra\ncommenti", + "Previous" => "Precedente", + "Next" => "Successivo", + "Previous Comment" => "Commento precedente", + "Next Comment" => "Commento successivo", + "Show All Notes" => "Mostra tutte le note", + "Convert to Comments" => "Converti in commenti", + "Protect\nWorkbook" => "Proteggi\ncartella di lavoro", + "Allow Edit\nRanges" => "Consenti modifica\nintervalli", + "Allow Edit Ranges" => "Consenti modifica intervalli", + "Unprotect\nSheet" => "Rimuovi protezione\nfoglio", + "Protect Sheet…" => "Proteggi foglio…", + "Comments" => "Commenti", + "Notes" => "Note", + "Page Break\nPreview" => "Anteprima\ninterruzioni di pagina", + "Page\nLayout" => "Layout\ndi pagina", + "Formula Bar" => "Barra della formula", + "Gridlines" => "Griglia", + "Headings" => "Intestazioni", + "Zoom" => "Zoom", + "100%" => "100%", + "Zoom to\nSelection" => "Zoom\nselezione", + "Freeze\nPanes" => "Blocca\nriquadri", + "Freeze Panes" => "Blocca riquadri", + "Freeze Top Row" => "Blocca riga superiore", + "Freeze First Column" => "Blocca prima colonna", + "Unfreeze Panes" => "Sblocca riquadri", + "Dark Mode" => "Modalità scura", + "Display theme" => "Tema dell'interfaccia", + "Animations" => "Animazioni", + "Glide the selection outline to the cell you move to instead of jumping there" => { + "Sposta il bordo della selezione in modo fluido fino alla cella di destinazione, invece di saltarci" + } + "System" => "Sistema", + "Light" => "Chiaro", + "Dark" => "Scuro", + "Interface language" => "Lingua dell'interfaccia", + "Interface size" => "Dimensioni dell'interfaccia", + "Auto" => "Automatico", + "Drag to freeze columns" => "Trascina per bloccare le colonne", + "Drag to freeze rows" => "Trascina per bloccare le righe", + "Command\nPalette" => "Riquadro\ncomandi", + "Agent\nControl" => "Controllo\nagente", + "Action\nJournal" => "Registro\nazioni", + "About\nGridCraft" => "Informazioni\nsu GridCraft", + "Share" => "Condividi", + "Add Chart\nElement" => "Aggiungi elemento\ngrafico", + "Change\nChart Type" => "Cambia tipo\ndi grafico", + "Switch\nRow/Column" => "Scambia\nrighe/colonne", + "Select\nData" => "Seleziona\ndati", + "Data Labels: None" => "Etichette dati: nessuna", + "Data Labels: Show" => "Etichette dati: mostra", + "Legend: None" => "Legenda: nessuna", + "Legend: Bottom" => "Legenda: in basso", + "Legend: Top" => "Legenda: in alto", + "Legend: Right" => "Legenda: a destra", + "Gridlines: None" => "Griglia: nessuna", + "Gridlines: Show" => "Griglia: mostra", + "Chart\nTitle" => "Titolo\ngrafico", + "Delete\nChart" => "Elimina\ngrafico", + "Convert\nto Range" => "Converti\nin intervallo", + "Table\nStyles" => "Stili\ntabella", + "Top 10 Items" => "Primi 10 elementi", + "Top 10%" => "Primo 10%", + "Bottom 10 Items" => "Ultimi 10 elementi", + "Bottom 10%" => "Ultimo 10%", + "Above Average" => "Sopra la media", + "Below Average" => "Sotto la media", + "Clear Rules from Entire Sheet" => "Cancella regole dall'intero foglio", + "Clear Rules from Selected Cells" => "Cancella regole dalle celle selezionate", + "Constants" => "Costanti", + "Data Bars" => "Barre dei dati", + "Color Scales" => "Scale di colori", + "Icon Sets" => "Set di icone", + "Home" => "Home", + "Draw" => "Disegno", + "Page Layout" => "Layout di pagina", + "Formulas" => "Formule", + "Data" => "Dati", + "Review" => "Revisione", + "View" => "Visualizza", + "Automate" => "Automatizza", + "Table Design" => "Struttura tabella", + "Chart Design" => "Struttura grafico", + "Ready" => "Pronto", + "Enter" => "Invio", + "Edit" => "Modifica", + "Point" => "Indica", + "Calculate" => "Calcola", + "Select destination and press Enter or choose Paste" => "Selezionare la destinazione e premere INVIO o scegliere Incolla", + "General" => "Generale", + "Number" => "Numero", + "Currency" => "Valuta", + "Accounting" => "Contabilità", + "Date" => "Data", + "Time" => "Ora", + "Percentage" => "Percentuale", + "Fraction" => "Frazione", + "Scientific" => "Scientifico", + "Text" => "Testo", + "Special" => "Speciale", + "Custom" => "Personalizzato", + "Short Date" => "Data in cifre", + "Long Date" => "Data estesa", + "More Number Formats…" => "Altri formati numeri…", + "Financial" => "Finanziarie", + "Logical" => "Logiche", + "Date &\nTime" => "Data\ne ora", + "Lookup &\nReference" => "Ricerca e\nriferimento", + "Math &\nTrig" => "Matematiche e\ntrigonometriche", + "More\nFunctions" => "Altre\nfunzioni", + "Sheet Options|View" => "Visualizza", + "Print" => "Stampa", + "Click to add data" => "Fare clic per aggiungere dati", + "Add header" => "Aggiungi intestazione", + "Add footer" => "Aggiungi piè di pagina", + "(none)" => "(nessuno)", + "Header" => "Intestazione", + "Footer" => "Piè di pagina", + "Page\nNumber" => "Numero\npagina", + "Number\nof Pages" => "Numero\ndi pagine", + "Current\nDate" => "Data\ncorrente", + "Current\nTime" => "Ora\ncorrente", + "File\nPath" => "Percorso\nfile", + "File\nName" => "Nome\nfile", + "Sheet\nName" => "Nome\nfoglio", + "Go to\nHeader" => "Vai a\nintestazione", + "Go to\nFooter" => "Vai a\npiè di pagina", + "Page Number" => "Numero pagina", + "Number of Pages" => "Numero di pagine", + "Current Date" => "Data corrente", + "Current Time" => "Ora corrente", + "File Path" => "Percorso file", + "File Name" => "Nome file", + "Sheet Name" => "Nome foglio", + "Go to Header" => "Vai a intestazione", + "Different First Page" => "Diversi per la prima pagina", + "Different Odd & Even Pages" => "Diversi per pagine pari e dispari", + "Go to Footer" => "Vai a piè di pagina", + "Ruler" => "Righello", + "File" => "File", + "Back" => "Indietro", + "New" => "Nuovo", + "Open" => "Apri", + "Info" => "Informazioni", + "Save" => "Salva", + "Save As" => "Salva con nome", + "Export" => "Esporta", + "Close" => "Chiudi", + "Options" => "Opzioni", + "Blank workbook" => "Cartella di lavoro vuota", + "Recent" => "Recenti", + "No recent workbooks yet." => "Non ci sono ancora cartelle di lavoro recenti.", + "More workbooks" => "Altre cartelle di lavoro", + "Browse…" => "Sfoglia…", + "Not saved yet" => "Non ancora salvata", + "Location" => "Percorso", + "Sheets" => "Fogli", + "Protect Workbook" => "Proteggi cartella di lavoro", + "Sheet structure is locked: sheets can't be added, moved, renamed or deleted." => { + "La struttura dei fogli è bloccata: non è possibile aggiungere, spostare, rinominare o eliminare fogli." + } + "Lock the sheet structure so sheets can't be added, moved, renamed or deleted." => { + "Blocca la struttura dei fogli, in modo che non sia possibile aggiungerli, spostarli, rinominarli o eliminarli." + } + "Properties" => "Proprietà", + "Title" => "Titolo", + "Subject" => "Oggetto", + "Author" => "Autore", + "Company" => "Società", + "Keywords" => "Parole chiave", + "Description" => "Descrizione", + "No workbook is open." => "Nessuna cartella di lavoro aperta.", + "Save as type" => "Salva come", + "Excel Workbook (*.xlsx)" => "Cartella di lavoro di Excel (*.xlsx)", + "CSV UTF-8 (Comma delimited) (*.csv)" => "CSV UTF-8 (delimitato da virgole) (*.csv)", + "Web Page (*.html)" => "Pagina Web (*.html)", + "PDF (*.pdf)" => "PDF (*.pdf)", + "Download" => "Scarica", + "A CSV file, web page or PDF is a copy: the workbook keeps its own file." => { + "Un file CSV, una pagina Web o un PDF sono copie: la cartella di lavoro conserva il proprio file." + } + "Save the workbook under another name or in another folder." => "Salva la cartella di lavoro con un altro nome o in un'altra cartella.", + "Print Active Sheets" => "Stampa fogli attivi", + "Print Entire Workbook" => "Stampa intera cartella di lavoro", + "Fit Sheet on One Page" => "Adatta foglio a una pagina", + "Page Setup…" => "Imposta pagina…", + "Page {page} of {pages}" => "Pagina {page} di {pages}", + "Nothing to print." => "Non c'è niente da stampare.", + "Previous page" => "Pagina precedente", + "Next page" => "Pagina successiva", + "Create PDF" => "Crea PDF", + "Save the sheet as a PDF document that keeps its page layout." => "Salva il foglio come documento PDF mantenendo il layout di pagina.", + "Change File Type" => "Cambia tipo di file", + "CSV (Comma delimited)" => "CSV (delimitato da virgole)", + "Save the active sheet as comma-separated text." => "Salva il foglio attivo come testo delimitato da virgole.", + "Web Page (.html)" => "Pagina Web (.html)", + "Save the workbook as a web page." => "Salva la cartella di lavoro come pagina Web.", + "Options|General" => "Generale", + "Options|Save" => "Salvataggio", + "Show formula bar" => "Mostra barra della formula", + "Save .xlsx workbooks automatically after every change" => "Salva automaticamente le cartelle di lavoro .xlsx dopo ogni modifica", + "Workbook calculation" => "Calcolo cartella di lavoro", + "Enable iterative calculation" => "Attiva calcolo iterativo", + "Calculation settings are saved with the workbook." => "Le impostazioni di calcolo vengono salvate con la cartella di lavoro.", + _ => return None, + }) +} diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index 0b19b2551d..e3d3ee0b25 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -520,7 +520,7 @@ impl SheetApp { self.ui.language = l; Ok(json!({"language": l})) } - None => Err(format!("unknown language {code:?} (use \"en\", \"es\", \"zh\", \"ja\", \"ko\", \"ru\", \"pt\" or \"cs\")")), + None => Err(format!("unknown language {code:?} (use \"en\", \"es\", \"zh\", \"ja\", \"ko\", \"ru\", \"pt\", \"cs\" or \"it\")")), } } "app.language.english" => { diff --git a/crates/ui-egui/src/theme.rs b/crates/ui-egui/src/theme.rs index 485b9a2f37..d847ae6e89 100644 --- a/crates/ui-egui/src/theme.rs +++ b/crates/ui-egui/src/theme.rs @@ -822,7 +822,7 @@ mod tests { ["sys-cjk-han-zh", "sys-cjk-han-ja", "sys-cjk-hangul", "sys-thai", "sys-hebrew", "sys-symbols", "sys-symbols-2"] ); assert_eq!(HanOrder::of(Language::Ja), HanOrder::Japanese); - for l in [Language::En, Language::Zh, Language::Ko, Language::Ru, Language::PtBr, Language::De, Language::Cs] { + for l in [Language::En, Language::Zh, Language::Ko, Language::Ru, Language::PtBr, Language::De, Language::Cs, Language::It] { assert_eq!(HanOrder::of(l), HanOrder::Chinese, "{l:?} shares the default order (no font rebuild)"); } } diff --git a/crates/ui-egui/tests/formula_locale.rs b/crates/ui-egui/tests/formula_locale.rs index fe21218b32..443e4963d0 100644 --- a/crates/ui-egui/tests/formula_locale.rs +++ b/crates/ui-egui/tests/formula_locale.rs @@ -172,20 +172,40 @@ fn canonical_engine_templates_enter_the_selected_formula_language() { } #[test] -fn portuguese_interface_retains_its_canonical_formula_fallback() { +fn portuguese_interface_enters_and_shows_portuguese_formulas() { let mut app = app(); app.run("app.language.set", json!({"code":"pt-BR"})).unwrap(); assert_eq!(app.ui.language, Language::PtBr); assert_eq!(app.ui.language.tr("Data"), "Dados"); - assert!(enter(&mut app, "=SUM(1.5,2.25)")); + assert!(enter(&mut app, "=SOMA(1,5;2,25)")); + assert_eq!(formula(&app), "SUM(1.5,2.25)"); app.begin_edit(None, true); - assert_eq!(app.editor.as_ref().unwrap().text, "=SUM(1.5,2.25)"); - assert!(!enter(&mut app, "=SUMA(1;2)")); + assert_eq!(app.editor.as_ref().unwrap().text, "=SOMA(1,5;2,25)"); + app.cancel_edit(); + // English separators are not Portuguese syntax. + assert!(!enter(&mut app, "=SUM(1.5,2.25)")); let restored: UiState = serde_json::from_str(&serde_json::to_string(&app.ui).unwrap()).unwrap(); assert_eq!(restored.language, Language::PtBr); assert_eq!(Language::Es.tr("Page Layout|Orientation"), "Orientación"); } +#[test] +fn german_and_russian_interfaces_enter_and_show_their_formulas() { + for (code, local, canonical, value) in [ + ("de", "=WENN(WAHR;SUMME({1.2;3,5.4});#NV)", "IF(TRUE,SUM({1,2;3.5,4}),#N/A)", 10.5), + ("ru", "=ЕСЛИ(ИСТИНА;СУММ({1;2:3;4});#Н/Д)", "IF(TRUE,SUM({1,2;3,4}),#N/A)", 10.0), + ] { + let mut app = app(); + app.run("app.language.set", json!({"code": code})).unwrap(); + assert!(enter(&mut app, local), "{code}"); + assert_eq!(formula(&app), canonical, "{code}"); + assert_eq!(app.session.active().unwrap().wb.active().unwrap().value(CellRef::new(0, 0)), Value::Number(value), "{code}"); + app.begin_edit(None, true); + assert_eq!(app.editor.as_ref().unwrap().text, local, "{code}"); + app.cancel_edit(); + } +} + #[test] fn czech_interface_retains_its_canonical_formula_fallback() { // The Czech table translates interface labels only: formulas keep canonical English names, @@ -201,3 +221,24 @@ fn czech_interface_retains_its_canonical_formula_fallback() { let restored: UiState = serde_json::from_str(&serde_json::to_string(&app.ui).unwrap()).unwrap(); assert_eq!(restored.language, Language::Cs); } + +#[test] +fn italian_interface_enters_and_shows_italian_formulas() { + let mut app = app(); + app.run("app.language.set", json!({"code":"it-IT"})).unwrap(); + assert_eq!(app.ui.language, Language::It); + assert_eq!(app.ui.language.tr("Formulas"), "Formule"); + assert!(enter(&mut app, "=SE(VERO;SOMMA(1,5;2,25);#N/D)")); + assert_eq!(formula(&app), "IF(TRUE,SUM(1.5,2.25),#N/A)"); + app.begin_edit(None, true); + assert_eq!(app.editor.as_ref().unwrap().text, "=SE(VERO;SOMMA(1,5;2,25);#N/D)"); + app.cancel_edit(); + // Lower-case and accented names match too; English separators are not Italian syntax. + assert!(enter(&mut app, "=somma.più.se(A1:A3;B1:B3;\">1\")")); + assert_eq!(formula(&app), "SUMIFS(A1:A3,B1:B3,\">1\")"); + assert!(enter(&mut app, "=SOMMA({1\\2.3\\4})")); + assert_eq!(formula(&app), "SUM({1,2;3,4})"); + assert!(!enter(&mut app, "=SUM(1.5,2.25)")); + let restored: UiState = serde_json::from_str(&serde_json::to_string(&app.ui).unwrap()).unwrap(); + assert_eq!(restored.language, Language::It); +} diff --git a/crates/ui-egui/tests/interaction.rs b/crates/ui-egui/tests/interaction.rs index 7093933895..71b95d18bf 100644 --- a/crates/ui-egui/tests/interaction.rs +++ b/crates/ui-egui/tests/interaction.rs @@ -260,6 +260,7 @@ fn language_switch_translates_the_ribbon_and_persists() { (Language::Ru, "Данные"), (Language::PtBr, "Dados"), (Language::De, "Daten"), + (Language::It, "Dati"), ] { h.state_mut().run("app.language.set", json!({"language": language.code()})).unwrap(); h.run_steps(2); // every locale renders the ribbon without panicking diff --git a/docs/decisions.md b/docs/decisions.md index 209b88d4d9..2f22b1dfba 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -3,13 +3,16 @@ ## Formula localization uses the existing interface preference PR #98 builds on the persisted `UiState.language` introduced by #31 and extended by #104. -Español selects the Spanish function table and list/decimal separators; there is no competing -locale setting. Formula syntax without a supplied translation table falls back to English. -The editor translates to canonical English before engine commands, and translates back only -for display. API, clipboard and XLSX syntax remain stable. Existing names override aliases. - -The revision is based directly on main after #31/#104 and Portuguese interface support (#82) -merged. Those locales retain their existing formula fallback; this change adds only Spanish. +Español, Deutsch, Português (Brasil) and Русский select their function table and separators; +there is no competing locale setting. Formula syntax without a translation table (English, +Japanese, Chinese, Korean, and for now Czech and French) stays English. The editor translates +to canonical English before engine commands, and translates back only for display. API, +clipboard and XLSX syntax remain stable. Existing names override aliases. + +Each formula language is data (`crates/formula/src/input/.rs`: names, booleans, +errors, table specifiers, separators) behind one `Dialect` table, so a language is added by a +data file and one `FormulaLocale` variant, without new parsing code. Every entry carries its +source; Microsoft's localized pages are machine-translated, so names need two agreeing signals. ## Preserve array evaluation when exporting formulas (#64) diff --git a/docs/formula-input.md b/docs/formula-input.md index e07132c8d9..570f7f5481 100644 --- a/docs/formula-input.md +++ b/docs/formula-input.md @@ -1,34 +1,53 @@ # Formula language -View → Interface language is the existing, persisted language preference. Choose **Español** -for Spanish formula entry and display. On first run the preference follows the system language. -English and the other interface languages currently use the English formula table and separators. +View → Interface language is the existing, persisted language preference, and it also picks the +formula language, as in Excel: function names follow the display language. On first run the +preference follows the system language. -| Spanish | Canonical English | +| Interface language | Formula language | | --- | --- | -| `SUMA` | `SUM` | -| `PROMEDIO` | `AVERAGE` | -| `SI` | `IF` | -| `CONTAR` | `COUNT` | -| `SUMAR.SI` | `SUMIF` | -| `CONTAR.SI` | `COUNTIF` | -| `BUSCARV` | `VLOOKUP` | -| `HOY` | `TODAY` | -| `VERDADERO`, `FALSO` | `TRUE`, `FALSE` (literals or function calls) | - -Names are case-insensitive. Spanish formulas use decimal commas (`1,5`), semicolon arguments -and reference unions, and backslashes between array columns (`{1\2;3\4}`). For example, -`=SI(VERDADERO;SUMA(1,5;2,25);0)` evaluates to 3.75. English mode retains comma arguments, -decimal points and comma array columns; it does not silently translate Spanish aliases. - -The cell editor, formula bar, Show Formulas, autocomplete, the Formula ribbon, Insert Function, and argument hints -use the selected formula language. Common Spanish function help is translated; functions -without a Spanish entry retain their English names/help. General interface labels and errors -fall back to English where Spanish translations are not provided. An edit captures its language -when it starts so switching the preference cannot reinterpret unfinished input. +| Español | Spanish | +| Deutsch | German | +| Português (Brasil) | Brazilian Portuguese | +| Русский | Russian | +| Italiano | Italian | +| English, 日本語, 中文, 한국어 | English (Japanese, Chinese and Korean Excel use English function names) | +| Čeština, Français | English for now: these languages have no function table yet | + +## What changes per language + +| | English | Spanish | German | Portuguese (Brazil) | Russian | Italian | +| --- | --- | --- | --- | --- | --- | --- | +| Example | `SUM`, `IF`, `VLOOKUP` | `SUMA`, `SI`, `BUSCARV` | `SUMME`, `WENN`, `SVERWEIS` | `SOMA`, `SE`, `PROCV` | `СУММ`, `ЕСЛИ`, `ВПР` | `SOMMA`, `SE`, `CERCA.VERT` | +| Function names translated | — | 424 | 403 | 412 | 459 | 455 | +| Booleans | `TRUE`, `FALSE` | `VERDADERO`, `FALSO` | `WAHR`, `FALSCH` | `VERDADEIRO`, `FALSO` | `ИСТИНА`, `ЛОЖЬ` | `VERO`, `FALSO` | +| Errors (e.g.) | `#VALUE!`, `#N/A` | `#¡VALOR!`, `#N/D` | `#WERT!`, `#NV` | `#VALOR!`, `#N/D` | `#ЗНАЧ!`, `#Н/Д` | `#VALORE!`, `#N/D` | +| Arguments and unions | `,` | `;` | `;` | `;` | `;` | `;` | +| Decimal separator | `.` | `,` | `,` | `,` | `,` | `,` | +| Array columns / rows | `,` / `;` | `\` / `;` | `.` / `;` | `\` / `;` | `;` / `:` | `\` / `.` | +| Table specifiers (e.g.) | `#Headers`, `#This Row` | `#Encabezados`, `#Esta fila` | `#Kopfzeilen`, `#Diese Zeile` | `#Cabeçalhos`, `#Esta Linha` | `#Заголовки`, `#Эта строка` | `#Intestazioni`, `#Questa riga` | + +For example, `=SI(VERDADERO;SUMA(1,5;2,25);0)` (Spanish), `=WENN(WAHR;SUMME({1.2;3,5.4});#NV)` +(German), `=ЕСЛИ(ИСТИНА;СУММ({1;2:3;4});#Н/Д)` (Russian) and `=SE(VERO;SOMMA({1\2.3\4});#N/D)` +(Italian) are stored as `IF(TRUE,SUM(1.5,2.25),0)`, `IF(TRUE,SUM({1,2;3.5,4}),#N/A)`, +`IF(TRUE,SUM({1,2;3,4}),#N/A)` and `IF(TRUE,SUM({1,2;3,4}),#N/A)`. + +Names, booleans and errors are case-insensitive in any script (`zählenwenn`, `сумм`). Functions +without a local name keep their English name, and canonical English names, booleans and errors +are also accepted with the language's separators. English mode retains comma arguments, decimal +points and comma array columns; it does not silently translate local names. + +## Where it applies + +The cell editor, formula bar, Show Formulas, autocomplete, the Formula ribbon, Insert Function +(searched and sorted by the local name), and argument hints use the selected formula language. +Common Spanish function help is translated; other help stays English, shown under the local +function name with the language's separators. General interface labels and errors fall back to +English where translations are not provided. An edit captures its language when it starts so +switching the preference cannot reinterpret unfinished input. Workbook/sheet names, table names, LET bindings and LAMBDA parameters take precedence over -aliases. Text, sheet names and table column names are unchanged. When a localized spelling +local names. Text, sheet names and table column names are unchanged. When a localized spelling would collide with a name, displayed formulas retain the canonical spelling to preserve meaning. Stored formulas, XLSX import/export, engine commands, control/API calls, CLI evaluation and @@ -36,3 +55,15 @@ clipboard exchange retain strict English syntax. This also applies to advanced d Name Manager and conditional-format rules. Localization happens at the cell/formula-bar editor boundary, including filling the selected range with Ctrl+Enter; it does not change the workbook format or teach the calculation engine ambiguous aliases. + +## Where the names come from + +Each table lives in `crates/formula/src/input/.rs` with its sources. Function names +come from Microsoft Support's localized Excel function pages, which are machine-translated and +sometimes wrong, so an entry needs two agreeing signals on its page (title, description, syntax +paragraph aligned with the English page, examples); entries marked `reviewed` were decided by +hand against independent function-name references. Booleans, errors and table specifiers cite +their sources per item. The tables have not yet been checked against a running localized Excel +or by native speakers; corrections are one-line edits with a source. The Italian table was +written from knowledge of Italian Excel instead (the array separators and the ERRORE.TIPO errors +cite Microsoft it-it pages; see `input/it.rs`) and has not been observed in Italian Excel either. diff --git a/docs/localization-parity.md b/docs/localization-parity.md index e7d1de9f70..aa7ad3008e 100644 --- a/docs/localization-parity.md +++ b/docs/localization-parity.md @@ -1,6 +1,6 @@ # Localization parity -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (German ribbon catalog added) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4 +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (Italian ribbon catalog and Italian formulas added) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4 Per-language status against Excel, which ships its UI in dozens of languages (Windows language packs cover 100+), with localized function names, argument separators, number and date formats, @@ -20,10 +20,13 @@ right-to-left sheets and full complex-script support. Part of - **About 2,200 user-visible strings** in all (heuristic source scan: ~1,700 UI and command strings plus ~500 function descriptions), so each shipped language covers **~12%** (measured count / estimated total). -- **en-US only formulas and formats.** Function names, `,` argument separator, `.` decimal - separator, en-US number and date formats (`crates/numfmt` says "en-US only"). Users ask for - localized function names and `;` separators (#45). German with localized numbers and formulas - is in PR #163 (open). +- **Formulas follow the interface language in Spanish, German, Brazilian Portuguese, + Russian and Italian** (#45): function names (403–459 per language), booleans, errors, table specifiers and + separators, at the editor boundary only; files and APIs keep canonical English + ([formula-input.md](formula-input.md)). The names come from machine-translated Microsoft pages + (two agreeing signals per entry, sources in `crates/formula/src/input/`) and have no native + review. French and Czech formulas stay English. Number and date formats are en-US only + (`crates/numfmt` says "en-US only"); PR #163 (German formulas and numbers) is open. - **Script support.** System-font fallback for CJK, Thai and Hebrew landed in #38 (closes #32; #142 is still open pending confirmation). There is no complex-text shaping: Arabic and Devanagari don't join or reorder, and there is no bidirectional layout. **Sheet Right-to-Left** @@ -55,7 +58,8 @@ separators, number/date formats, machine translation with agent review, and scri | Korean | ko | 266 (~12%) | no | Hangul via the CJK fallback; IME unverified | no | menus only | 6–10 h | | Vietnamese | vi | 0 (0%) | no | Latin with stacked diacritics: unverified | no | none | 6–10 h | -Other shipped languages: Russian (ru) and German (de), 266 labels each (~12%), menus only. +Other shipped languages: Russian (ru) and German (de), 266 labels each (~12%), menus only; Italian +(it), 381 labels (the full reference table), menus only, not yet reviewed by a second native speaker. **Total:** catalog work 10–20 h + languages 92–144 h ≈ **100–165 h**. Parallelizes almost fully once the catalog covers dialogs and commands. **Needs a human:** native-speaker review of every @@ -66,9 +70,9 @@ language (none so far) and of localized function names. 1. Extend the catalog from the ribbon to every user-visible string (dialogs, menus, task panes, status and error messages, command labels, function descriptions), with a missing-key check in `cargo xtask ci`. Language switching and the system-language default already exist (#31). -2. Locale-aware formulas: localized function-name tables and separators at the formula-bar - boundary only (files keep en-US invariant names), locale number and date formats, list - separators in CSV. +2. Locale-aware formulas: function tables and separators exist for es, de, pt-BR and ru at the + formula-bar boundary (files keep canonical names); still missing: tables for French and the + other languages, locale number and date formats, list separators in CSV. 3. Text shaping and fallback: a shaping engine for grid, editor and PDF text (Arabic, Devanagari, Thai), system font fallback for CJK, bidirectional runs, right-to-left sheet tabs and printing; embedded subset fonts in PDF. @@ -77,6 +81,9 @@ language (none so far) and of localized function names. | Date | Change | Summary | |---|---|---| +| 2026-10-12 | minor | Italian formulas (`input/it.rs`): 455 function names, `;` arguments, decimal comma, `\` / `.` array separators, VERO/FALSO, errors and table specifiers; the lexer ends an array row at a row separator that is a word character | +| 2026-10-12 | minor | Italian (it) ribbon table (`i18n/it.rs`, 381 labels: every key of the reference table, in the names Italian Excel users know); `it` locale tags (it-IT, it-CH, it_IT.UTF-8) resolve to Italian; formulas and number formats stay en-US | +| 2026-10-11 | minor | Formulas follow the interface language in es, de, pt-BR and ru (names, booleans, errors, table specifiers, separators); infrastructure item 2 partly done | | 2026-10-11 | minor | German ribbon catalog (`i18n/de.rs`, 266 labels, ~12%); `de` locale tags (de-DE, de-AT, de-CH…) resolve to German. PR #163 (localized German formulas/numbers) still open | | 2026-10-11 | minor | Sheet Right-to-Left mirrors the grid (#146) | | 2026-10-11 | minor | Czech (cs) ribbon table: 266 labels (~12%), menus only |