Skip to content

Commit 1a8c8bf

Browse files
committed
[FIX] localize and canonalize content
Task: 6089166
1 parent 53ec6b1 commit 1a8c8bf

13 files changed

Lines changed: 171 additions & 54 deletions

File tree

src/components/composer/composer/abstract_composer_store.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
splitReference,
1414
zoneToDimension,
1515
} from "../../../helpers/index";
16-
import { canonicalizeNumberContent } from "../../../helpers/locale";
1716
import { cycleFixedReference } from "../../../helpers/reference_type";
1817
import {
1918
AutoCompleteProvider,
@@ -98,6 +97,7 @@ export abstract class AbstractComposerStore extends SpreadsheetStore {
9897
}
9998
protected abstract confirmEdition(content: string): void;
10099
protected abstract getComposerContent(position: CellPosition): string;
100+
protected abstract getCurrentCanonicalContent(): string;
101101

102102
abstract stopEdition(direction?: Direction): void;
103103

@@ -361,10 +361,6 @@ export abstract class AbstractComposerStore extends SpreadsheetStore {
361361
}
362362
}
363363

364-
protected getCurrentCanonicalContent(): string {
365-
return canonicalizeNumberContent(this._currentContent, this.getters.getLocale());
366-
}
367-
368364
protected cancelEditionAndActivateSheet() {
369365
if (this.editionMode === "inactive") {
370366
return;

src/components/composer/composer/cell_composer_store.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ import {
1010
updateSelectionOnDeletion,
1111
updateSelectionOnInsertion,
1212
} from "../../../helpers/index";
13-
import { getDateTimeFormat, localizeFormula } from "../../../helpers/locale";
13+
import {
14+
canonicalizeNumberContent,
15+
getDateTimeFormat,
16+
localizeFormula,
17+
} from "../../../helpers/locale";
1418
import { dataValidationEvaluatorRegistry } from "../../../registries/data_validation_registry";
1519
import { _t } from "../../../translation";
1620
import {
@@ -296,4 +300,8 @@ export class CellComposerStore extends AbstractComposerStore {
296300
}
297301
return true;
298302
}
303+
304+
protected getCurrentCanonicalContent(): string {
305+
return canonicalizeNumberContent(this._currentContent, this.getters.getLocale());
306+
}
299307
}

src/components/composer/standalone_composer/standalone_composer_store.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Token, rangeTokenize } from "../../../formulas";
22
import { EnrichedToken } from "../../../formulas/composer_tokenizer";
3-
import { localizeContent } from "../../../helpers/locale";
3+
import { canonicalizeContent, localizeContent } from "../../../helpers/locale";
44
import { setXcToFixedReferenceType } from "../../../helpers/reference_type";
55
import { AutoCompleteProviderDefinition } from "../../../registries";
66
import { Get } from "../../../store_engine";
@@ -84,4 +84,8 @@ export class StandaloneComposerStore extends AbstractComposerStore {
8484
}
8585
return super.getTokenColor(token);
8686
}
87+
88+
protected getCurrentCanonicalContent(): string {
89+
return canonicalizeContent(this._currentContent, this.getters.getLocale());
90+
}
8791
}

src/components/side_panel/conditional_formatting/cf_editor/cf_editor.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
isColorValid,
1414
rangeReference,
1515
} from "../../../../helpers";
16-
import { canonicalizeCFRule } from "../../../../helpers/locale";
1716
import { cycleFixedReference } from "../../../../helpers/reference_type";
1817
import { _t } from "../../../../translation";
1918
import {
@@ -252,11 +251,10 @@ export class ConditionalFormattingEditor extends Component<Props, SpreadsheetChi
252251
return [CommandResult.InvalidRange];
253252
}
254253
const sheetId = this.env.model.getters.getActiveSheetId();
255-
const locale = this.env.model.getters.getLocale();
256254
const rule = newCf.rule || this.getEditedRule(this.state.currentCFType);
257255
const result = this.env.model.dispatch("ADD_CONDITIONAL_FORMAT", {
258256
cf: {
259-
rule: canonicalizeCFRule(rule, locale),
257+
rule,
260258
id: this.props.editedCf.id,
261259
},
262260
ranges: ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(sheetId, xc)),

src/components/side_panel/data_validation/data_validation_panel.xml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,15 @@
44
<t t-if="state.mode === 'list'">
55
<div class="o-dv-preview-list">
66
<t t-foreach="validationRules" t-as="rule" t-key="rule.id">
7-
<DataValidationPreview
8-
rule="localizeDVRule(rule)"
9-
onClick="() => this.onPreviewClick(rule.id)"
10-
/>
7+
<DataValidationPreview rule="rule" onClick="() => this.onPreviewClick(rule.id)"/>
118
</t>
129
</div>
1310
<div class="o-dv-add o-button-link p-4 float-end" t-on-click="addDataValidationRule">
1411
+ Add another rule
1512
</div>
1613
</t>
1714
<t t-else="">
18-
<DataValidationEditor rule="localizeDVRule(state.activeRule)" onExit.bind="onExitEditMode"/>
15+
<DataValidationEditor rule="state.activeRule" onExit.bind="onExitEditMode"/>
1916
</t>
2017
</div>
2118
</t>

src/components/side_panel/data_validation/dv_criterion_form/dv_input/dv_input.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component, useEffect, useRef, useState } from "@odoo/owl";
2-
import { canonicalizeContent } from "../../../../../helpers/locale";
2+
import { canonicalizeContent, localizeContent } from "../../../../../helpers/locale";
33
import { dataValidationEvaluatorRegistry } from "../../../../../registries/data_validation_registry";
44
import { _t } from "../../../../../translation";
55
import { DataValidationCriterionType, SpreadsheetChildEnv } from "../../../../../types";
@@ -80,9 +80,17 @@ export class DataValidationInput extends Component<Props, SpreadsheetChildEnv> {
8080
return evaluator.allowedValues ?? "any";
8181
}
8282

83+
get localeInputValue(): string {
84+
const locale = this.env.model.getters.getLocale();
85+
return localizeContent(this.props.value, locale);
86+
}
87+
8388
onInputValueChanged(ev: Event) {
8489
this.state.shouldDisplayError = true;
85-
this.props.onValueChanged((ev.target as HTMLInputElement).value);
90+
const value = (ev.target as HTMLInputElement).value;
91+
const locale = this.env.model.getters.getLocale();
92+
const canonicalizedValue = canonicalizeContent(value, locale);
93+
this.props.onValueChanged(canonicalizedValue);
8694
}
8795

8896
onChangeComposerValue(str: string) {

src/components/side_panel/data_validation/dv_criterion_form/dv_input/dv_input.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
type="text"
77
t-ref="input"
88
t-on-input="onInputValueChanged"
9-
t-att-value="props.value"
9+
t-att-value="this.localeInputValue"
1010
class="o-input"
1111
t-att-class="{
1212
'o-invalid border-danger position-relative': errorMessage,

src/components/side_panel/data_validation/dv_editor/dv_editor.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Component, ComponentConstructor, useState } from "@odoo/owl";
22
import { Action } from "../../../../actions/action";
33
import { zoneToXc } from "../../../../helpers";
4-
import { canonicalizeContent } from "../../../../helpers/locale";
54
import { dataValidationEvaluatorRegistry } from "../../../../registries/data_validation_registry";
65
import {
76
AddDataValidationCommand,
@@ -89,16 +88,14 @@ export class DataValidationEditor extends Component<Props, SpreadsheetChildEnv>
8988

9089
get dispatchPayload(): Omit<AddDataValidationCommand, "type"> {
9190
const rule = { ...this.state.rule, ranges: undefined };
92-
const locale = this.env.model.getters.getLocale();
9391

9492
const criterion = rule.criterion;
9593
const criterionEvaluator = dataValidationEvaluatorRegistry.get(criterion.type);
9694

9795
const values = criterion.values
9896
.slice(0, criterionEvaluator.numberOfValues(criterion))
9997
.map((value) => value?.trim())
100-
.filter((value) => value !== "" && value !== undefined)
101-
.map((value) => canonicalizeContent(value, locale));
98+
.filter((value) => value !== "" && value !== undefined);
10299
rule.criterion = { ...criterion, values };
103100
return {
104101
sheetId: this.editingSheetId,

src/helpers/data_validation_helpers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { tryToNumber } from "../functions/helpers";
2-
import { DataValidationCriterion, DateCriterionValue, Locale } from "../types";
2+
import { DataValidationCriterion, DateCriterionValue, DEFAULT_LOCALE, Locale } from "../types";
33
import { parseLiteral } from "./cells";
44
import { DateTime, getDaysInMonth, jsDateToNumber, valueToDateNumber } from "./dates";
55
import { formatValue } from "./format/format";
@@ -66,7 +66,7 @@ export function getDateCriterionFormattedValues(values: string[], locale: Locale
6666
if (valueStr.startsWith("=")) {
6767
return valueStr;
6868
}
69-
const value = parseLiteral(valueStr, locale);
69+
const value = parseLiteral(valueStr, DEFAULT_LOCALE);
7070
if (typeof value === "number") {
7171
return formatValue(value, { format: locale.dateFormat, locale });
7272
}

src/registries/data_validation_registry.ts

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,13 @@ dataValidationEvaluatorRegistry.add("textContains", {
103103
criterionValueErrorString: DVTerms.CriterionError.notEmptyValue,
104104
numberOfValues: () => 1,
105105
name: _t("Text contains"),
106-
getPreview: (criterion) => _t('Text contains "%s"', criterion.values[0]),
106+
getPreview: (criterion: TextContainsCriterion, getters: Getters) => {
107+
const locale = getters.getLocale();
108+
const localizedValue = criterion.values[0]
109+
? localizeContent(criterion.values[0]?.toString(), locale)
110+
: "";
111+
return _t('Text contains "%s"', localizedValue);
112+
},
107113
});
108114

109115
dataValidationEvaluatorRegistry.add("textNotContains", {
@@ -119,7 +125,13 @@ dataValidationEvaluatorRegistry.add("textNotContains", {
119125
criterionValueErrorString: DVTerms.CriterionError.notEmptyValue,
120126
numberOfValues: () => 1,
121127
name: _t("Text does not contains"),
122-
getPreview: (criterion) => _t('Text does not contain "%s"', criterion.values[0]),
128+
getPreview: (criterion: TextNotContainsCriterion, getters: Getters) => {
129+
const locale = getters.getLocale();
130+
const localizedValue = criterion.values[0]
131+
? localizeContent(criterion.values[0]?.toString(), locale)
132+
: "";
133+
return _t('Text does not contain "%s"', localizedValue);
134+
},
123135
});
124136

125137
dataValidationEvaluatorRegistry.add("textIs", {
@@ -135,7 +147,13 @@ dataValidationEvaluatorRegistry.add("textIs", {
135147
criterionValueErrorString: DVTerms.CriterionError.notEmptyValue,
136148
numberOfValues: () => 1,
137149
name: _t("Text is exactly"),
138-
getPreview: (criterion) => _t('Text is exactly "%s"', criterion.values[0]),
150+
getPreview: (criterion: TextContainsCriterion, getters: Getters) => {
151+
const locale = getters.getLocale();
152+
const localizedValue = criterion.values[0]
153+
? localizeContent(criterion.values[0]?.toString(), locale)
154+
: "";
155+
return _t('Text is exactly "%s"', localizedValue);
156+
},
139157
});
140158

141159
/** Note: this regex doesn't allow for all the RFC-compliant mail addresses but should be enough for our purpose. */
@@ -430,7 +448,11 @@ dataValidationEvaluatorRegistry.add("isEqual", {
430448
criterionValueErrorString: DVTerms.CriterionError.numberValue,
431449
numberOfValues: () => 1,
432450
name: _t("Is equal to"),
433-
getPreview: (criterion) => _t("Value is equal to %s", criterion.values[0]),
451+
getPreview: (criterion: IsEqualCriterion, getters: Getters) => {
452+
const locale = getters.getLocale();
453+
const values = getNumberCriterionlocalizedValues(criterion, locale);
454+
return _t("Value is equal to %s", values[0]);
455+
},
434456
});
435457

436458
dataValidationEvaluatorRegistry.add("isNotEqual", {
@@ -455,7 +477,11 @@ dataValidationEvaluatorRegistry.add("isNotEqual", {
455477
criterionValueErrorString: DVTerms.CriterionError.numberValue,
456478
numberOfValues: () => 1,
457479
name: _t("Is not equal to"),
458-
getPreview: (criterion) => _t("Value is not equal to %s", criterion.values[0]),
480+
getPreview: (criterion: IsEqualCriterion, getters: Getters) => {
481+
const locale = getters.getLocale();
482+
const values = getNumberCriterionlocalizedValues(criterion, locale);
483+
return _t("Value is not equal to %s", values[0]);
484+
},
459485
});
460486

461487
dataValidationEvaluatorRegistry.add("isGreaterThan", {
@@ -480,7 +506,11 @@ dataValidationEvaluatorRegistry.add("isGreaterThan", {
480506
criterionValueErrorString: DVTerms.CriterionError.numberValue,
481507
numberOfValues: () => 1,
482508
name: _t("Is greater than"),
483-
getPreview: (criterion) => _t("Value is greater than %s", criterion.values[0]),
509+
getPreview: (criterion: IsGreaterThanCriterion, getters: Getters) => {
510+
const locale = getters.getLocale();
511+
const values = getNumberCriterionlocalizedValues(criterion, locale);
512+
return _t("Value is greater than %s", values[0]);
513+
},
484514
});
485515

486516
dataValidationEvaluatorRegistry.add("isGreaterOrEqualTo", {
@@ -505,7 +535,11 @@ dataValidationEvaluatorRegistry.add("isGreaterOrEqualTo", {
505535
criterionValueErrorString: DVTerms.CriterionError.numberValue,
506536
numberOfValues: () => 1,
507537
name: _t("Is greater or equal to"),
508-
getPreview: (criterion) => _t("Value is greater or equal to %s", criterion.values[0]),
538+
getPreview: (criterion: IsGreaterOrEqualToCriterion, getters: Getters) => {
539+
const locale = getters.getLocale();
540+
const values = getNumberCriterionlocalizedValues(criterion, locale);
541+
return _t("Value is greater or equal to %s", values[0]);
542+
},
509543
});
510544

511545
dataValidationEvaluatorRegistry.add("isLessThan", {
@@ -530,7 +564,11 @@ dataValidationEvaluatorRegistry.add("isLessThan", {
530564
criterionValueErrorString: DVTerms.CriterionError.numberValue,
531565
numberOfValues: () => 1,
532566
name: _t("Is less than"),
533-
getPreview: (criterion) => _t("Value is less than %s", criterion.values[0]),
567+
getPreview: (criterion: IsLessThanCriterion, getters: Getters) => {
568+
const locale = getters.getLocale();
569+
const values = getNumberCriterionlocalizedValues(criterion, locale);
570+
return _t("Value is less than %s", values[0]);
571+
},
534572
});
535573

536574
dataValidationEvaluatorRegistry.add("isLessOrEqualTo", {
@@ -555,7 +593,11 @@ dataValidationEvaluatorRegistry.add("isLessOrEqualTo", {
555593
criterionValueErrorString: DVTerms.CriterionError.numberValue,
556594
numberOfValues: () => 1,
557595
name: _t("Is less or equal to"),
558-
getPreview: (criterion) => _t("Value is less or equal to %s", criterion.values[0]),
596+
getPreview: (criterion: IsLessOrEqualToCriterion, getters: Getters) => {
597+
const locale = getters.getLocale();
598+
const values = getNumberCriterionlocalizedValues(criterion, locale);
599+
return _t("Value is less or equal to %s", values[0]);
600+
},
559601
});
560602

561603
dataValidationEvaluatorRegistry.add("isBetween", {
@@ -580,8 +622,11 @@ dataValidationEvaluatorRegistry.add("isBetween", {
580622
criterionValueErrorString: DVTerms.CriterionError.numberValue,
581623
numberOfValues: () => 2,
582624
name: _t("Is between"),
583-
getPreview: (criterion) =>
584-
_t("Value is between %s and %s", criterion.values[0], criterion.values[1]),
625+
getPreview: (criterion: IsBetweenCriterion, getters: Getters) => {
626+
const locale = getters.getLocale();
627+
const values = getNumberCriterionlocalizedValues(criterion, locale);
628+
return _t("Value is between %s and %s", values[0], values[1]);
629+
},
585630
});
586631

587632
dataValidationEvaluatorRegistry.add("isNotBetween", {
@@ -606,8 +651,11 @@ dataValidationEvaluatorRegistry.add("isNotBetween", {
606651
criterionValueErrorString: DVTerms.CriterionError.numberValue,
607652
numberOfValues: () => 2,
608653
name: _t("Is not between"),
609-
getPreview: (criterion) =>
610-
_t("Value is not between %s and %s", criterion.values[0], criterion.values[1]),
654+
getPreview: (criterion: IsNotBetweenCriterion, getters: Getters) => {
655+
const locale = getters.getLocale();
656+
const values = getNumberCriterionlocalizedValues(criterion, locale);
657+
return _t("Value is not between %s and %s", values[0], values[1]);
658+
},
611659
});
612660

613661
dataValidationEvaluatorRegistry.add("isBoolean", {
@@ -631,14 +679,23 @@ dataValidationEvaluatorRegistry.add("isValueInList", {
631679
.map((str) => str.toLowerCase())
632680
.includes(value.toString().toLowerCase());
633681
},
634-
getErrorString: (criterion: IsValueInListCriterion) =>
635-
_t("The value must be one of: %s", criterion.values.join(", ")),
682+
getErrorString: (criterion: IsValueInListCriterion, getters: Getters) => {
683+
const locale = getters.getLocale();
684+
const values = getNumberCriterionlocalizedValues(criterion, locale);
685+
const separator = `${locale.formulaArgSeparator || ","} `;
686+
return _t("The value must be one of: %s", values.join(separator));
687+
},
636688
isCriterionValueValid: () => true,
637689
criterionValueErrorString: "",
638690
numberOfValues: () => undefined,
639691
allowedValues: "onlyLiterals",
640692
name: _t("Value in list"),
641-
getPreview: (criterion) => _t("Value one of: %s", criterion.values.join(", ")),
693+
getPreview: (criterion: IsValueInListCriterion, getters: Getters) => {
694+
const locale = getters.getLocale();
695+
const values = getNumberCriterionlocalizedValues(criterion, locale);
696+
const separator = `${locale.formulaArgSeparator || ","} `;
697+
return _t("Value one of: %s", values.join(separator));
698+
},
642699
});
643700

644701
dataValidationEvaluatorRegistry.add("isValueInRange", {

0 commit comments

Comments
 (0)