@swan-io/shared-business 11.3.5 → 11.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@swan-io/shared-business",
3
- "version": "11.3.5",
3
+ "version": "11.4.0",
4
4
  "engines": {
5
- "node": ">=22.12.0",
5
+ "node": "^22.12.0",
6
6
  "pnpm": "^10.2.0"
7
7
  },
8
8
  "files": [
@@ -26,10 +26,10 @@
26
26
  ],
27
27
  "license": "MIT",
28
28
  "peerDependencies": {
29
- "@swan-io/lake": "11.3.5"
29
+ "@swan-io/lake": "11.4.0"
30
30
  },
31
31
  "dependencies": {
32
- "@formatjs/intl": "^3.1.3",
32
+ "@formatjs/intl": "^3.1.4",
33
33
  "@placekit/client-js": "^2.3.0",
34
34
  "@swan-io/boxed": "^3.2.0",
35
35
  "@swan-io/request": "^2.0.0",
@@ -52,6 +52,6 @@
52
52
  "@types/react-native": "^0.72.8",
53
53
  "jsdom": "^26.0.0",
54
54
  "vitest": "^2.1.8",
55
- "@swan-io/lake": "11.3.5"
55
+ "@swan-io/lake": "11.4.0"
56
56
  }
57
57
  }
@@ -41,9 +41,7 @@ type ExtractFilterValue<T extends Filter<unknown>> = T extends {
41
41
  type: "checkbox";
42
42
  } ? T["items"][number]["value"][] | undefined : T extends {
43
43
  type: "radio";
44
- } ? T["items"][number]["value"] | undefined : T extends {
45
- type: "boolean";
46
- } ? boolean | undefined : string | undefined;
44
+ } ? T["items"][number]["value"] | undefined : string | undefined;
47
45
  type FiltersDefinition = Record<string, Filter<unknown>>;
48
46
  export type FiltersState<T extends FiltersDefinition> = Simplify<{
49
47
  [K in keyof T]: Simplify<ExtractFilterValue<T[K]>>;
@@ -56,4 +54,46 @@ type FiltersStackProps<Definition extends FiltersDefinition, State extends Filte
56
54
  onChangeFilters: (value: State) => void;
57
55
  };
58
56
  export declare const FiltersStack: <T extends FiltersDefinition>({ filters, openedFilters, definition, onChangeOpened, onChangeFilters, }: FiltersStackProps<T>) => import("react/jsx-runtime").JSX.Element | null;
57
+ export declare const filter: {
58
+ readonly checkbox: <T>(config: {
59
+ label: string;
60
+ items: Item<T>[];
61
+ }) => FilterCheckboxDef<T>;
62
+ readonly date: (config: {
63
+ label: string;
64
+ isSelectable?: (date: DatePickerDate, filters: unknown) => boolean;
65
+ validate?: (value: string, filters: unknown) => ValidatorResult;
66
+ }) => FilterDateDef;
67
+ readonly input: (config: {
68
+ label: string;
69
+ placeholder?: string;
70
+ validate?: (value: string) => ValidatorResult;
71
+ }) => FilterInputDef;
72
+ readonly radio: <T>(config: {
73
+ label: string;
74
+ items: Item<T>[];
75
+ }) => FilterRadioDef<T>;
76
+ };
77
+ export declare const useFiltersProps: <Definition extends FiltersDefinition, Filters extends Record<string, unknown>>({ available, filters, filtersDefinition, }: {
78
+ available?: (keyof Filters)[];
79
+ filters: Filters;
80
+ filtersDefinition: Definition;
81
+ }) => {
82
+ chooser: {
83
+ availableFilters: {
84
+ name: keyof Definition;
85
+ label: string;
86
+ }[];
87
+ filters: Filters;
88
+ label: string;
89
+ onAddFilter: (filter: keyof Filters) => void;
90
+ openFilters: (keyof Filters)[];
91
+ };
92
+ stack: {
93
+ definition: Definition;
94
+ filters: Filters;
95
+ openedFilters: (keyof Filters)[];
96
+ onChangeOpened: import("react").Dispatch<import("react").SetStateAction<(keyof Filters)[]>>;
97
+ };
98
+ };
59
99
  export {};
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Array, Dict, Option } from "@swan-io/boxed";
2
3
  import { Box } from "@swan-io/lake/src/components/Box";
3
4
  import { FlatList } from "@swan-io/lake/src/components/FlatList";
4
5
  import { Icon } from "@swan-io/lake/src/components/Icon";
@@ -16,9 +17,10 @@ import { useMergeRefs } from "@swan-io/lake/src/hooks/useMergeRefs";
16
17
  import { usePreviousValue } from "@swan-io/lake/src/hooks/usePreviousValue";
17
18
  import { isNotNullish, isNullish } from "@swan-io/lake/src/utils/nullish";
18
19
  import dayjs from "dayjs";
19
- import { forwardRef, useCallback, useMemo, useRef, useState } from "react";
20
+ import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
20
21
  import { Pressable, StyleSheet, Text, View } from "react-native";
21
22
  import { P, match } from "ts-pattern";
23
+ import { locale, t } from "../utils/i18n";
22
24
  import { DatePickerModal } from "./DatePicker";
23
25
  const styles = StyleSheet.create({
24
26
  container: {
@@ -78,7 +80,7 @@ const FilterTag = forwardRef(({ onPress, onPressRemove, label, value = "", isAct
78
80
  const mergedRef = useMergeRefs(ref, forwardRef);
79
81
  return (_jsx(Pressable, { ref: mergedRef, onPress: onPress, children: ({ hovered }) => (_jsxs(_Fragment, { children: [_jsx(View, { style: [styles.shadowed, hovered && styles.hovered] }), _jsx(Tag, { label: label, color: "current", onPressRemove: onPressRemove, children: _jsxs(Box, { direction: "row", alignItems: "center", children: [_jsx(Text, { numberOfLines: 1, style: styles.value, children: value }), _jsx(Space, { width: 4 }), _jsx(Icon, { color: colors.current.primary, name: isActive ? "chevron-up-filled" : "chevron-down-filled", size: 16 })] }) })] })) }));
80
82
  });
81
- function FilterRadio({ label, items, width, value, onValueChange, onPressRemove, autoOpen = false, }) {
83
+ const FilterRadio = ({ label, items, width, value, onValueChange, onPressRemove, autoOpen = false, }) => {
82
84
  const inputRef = useRef(null);
83
85
  const [visible, { close, toggle }] = useDisclosure(autoOpen);
84
86
  const currentValue = useMemo(() => items.find(i => i.value === value), [items, value]);
@@ -89,8 +91,8 @@ function FilterRadio({ label, items, width, value, onValueChange, onPressRemove,
89
91
  close();
90
92
  }, children: [_jsx(LakeRadio, { value: isSelected }), _jsx(Space, { width: 12 }), _jsx(Text, { style: styles.itemLabel, children: item.label })] }));
91
93
  } }) })] }));
92
- }
93
- function FilterCheckbox({ label, items, width, checkAllLabel, value, onValueChange, onPressRemove, autoOpen = false, }) {
94
+ };
95
+ const FilterCheckbox = ({ label, items, width, checkAllLabel, value, onValueChange, onPressRemove, autoOpen = false, }) => {
94
96
  const inputRef = useRef(null);
95
97
  const [visible, { close, toggle }] = useDisclosure(autoOpen);
96
98
  const valueSet = useMemo(() => new Set(value), [value]);
@@ -141,8 +143,8 @@ function FilterCheckbox({ label, items, width, checkAllLabel, value, onValueChan
141
143
  .exhaustive();
142
144
  return (_jsxs(Pressable, { role: "radio", "aria-checked": isSelected, style: ({ hovered }) => [styles.radio, hovered && styles.itemHovered], onPress: onPress, children: [_jsx(LakeCheckbox, { value: isSelected }), _jsx(Space, { width: 12 }), _jsx(Text, { style: styles.itemLabel, children: item.label })] }));
143
145
  } }) })] }));
144
- }
145
- function FilterDate({ label, initialValue, noValueText, cancelText, submitText, dateFormat, isSelectable, validate, onValueChange, onPressRemove, autoOpen = false, }) {
146
+ };
147
+ const FilterDate = ({ label, initialValue, noValueText, cancelText, submitText, dateFormat, isSelectable, validate, onValueChange, onPressRemove, autoOpen = false, }) => {
146
148
  const inputRef = useRef(null);
147
149
  const [visible, { close, toggle }] = useDisclosure(autoOpen);
148
150
  const value = useMemo(() => (isNotNullish(initialValue) ? dayjs(initialValue).format(dateFormat) : ""), [initialValue, dateFormat]);
@@ -150,8 +152,8 @@ function FilterDate({ label, initialValue, noValueText, cancelText, submitText,
150
152
  const formattedValue = dayjs(value, dateFormat, true).toJSON();
151
153
  onValueChange(formattedValue);
152
154
  }, onDismiss: close })] }));
153
- }
154
- function FilterInput({ label, initialValue = "", noValueText, autoOpen = false, placeholder, validate, onValueChange, onPressRemove, }) {
155
+ };
156
+ const FilterInput = ({ label, initialValue = "", noValueText, autoOpen = false, placeholder, validate, onValueChange, onPressRemove, }) => {
155
157
  const [visible, { close, toggle }] = useDisclosure(autoOpen);
156
158
  const tagRef = useRef(null);
157
159
  const getValueState = useCallback((inputValue, isInitialValue) => {
@@ -171,7 +173,7 @@ function FilterInput({ label, initialValue = "", noValueText, autoOpen = false,
171
173
  const [{ inputValue, validValue, error }, setState] = useState(() => getValueState(initialValue, true));
172
174
  const onChangeText = useCallback((value) => setState(getValueState(value, false)), [getValueState]);
173
175
  return (_jsxs(View, { style: styles.container, children: [_jsx(FilterTag, { label: label, onPress: toggle, ref: tagRef, onPressRemove: onPressRemove, isActive: visible, value: validValue !== null && validValue !== void 0 ? validValue : noValueText }), _jsx(Popover, { role: "listbox", matchReferenceWidth: false, onDismiss: close, referenceRef: tagRef, returnFocus: false, visible: visible, children: _jsx(View, { style: [styles.dropdown, styles.inputContent], children: _jsx(LakeLabel, { label: label, render: id => (_jsx(LakeTextInput, { id: id, value: inputValue, error: error, style: styles.input, placeholder: placeholder, onChangeText: onChangeText })) }) }) })] }));
174
- }
176
+ };
175
177
  const getFilterValue = (_type, filters, name) => filters[name];
176
178
  export const FiltersStack = ({ filters, openedFilters, definition, onChangeOpened, onChangeFilters, }) => {
177
179
  const previousOpened = usePreviousValue(openedFilters);
@@ -206,3 +208,69 @@ export const FiltersStack = ({ filters, openedFilters, definition, onChangeOpene
206
208
  .exhaustive() }, filterName));
207
209
  }) }));
208
210
  };
211
+ export const filter = {
212
+ checkbox: (config) => ({
213
+ type: "checkbox",
214
+ label: config.label,
215
+ items: config.items,
216
+ checkAllLabel: t("common.filters.all"),
217
+ }),
218
+ date: (config) => ({
219
+ type: "date",
220
+ label: config.label,
221
+ cancelText: t("common.filters.cancel"),
222
+ submitText: t("common.filters.apply"),
223
+ noValueText: t("common.filters.none"),
224
+ dateFormat: locale.dateFormat,
225
+ isSelectable: config.isSelectable,
226
+ validate: config.validate,
227
+ }),
228
+ input: (config) => ({
229
+ type: "input",
230
+ label: config.label,
231
+ noValueText: t("common.filters.none"),
232
+ placeholder: config.placeholder,
233
+ validate: config.validate,
234
+ }),
235
+ radio: (config) => ({
236
+ type: "radio",
237
+ label: config.label,
238
+ items: config.items,
239
+ }),
240
+ };
241
+ export const useFiltersProps = ({ available, filters, filtersDefinition, }) => {
242
+ const availableFilters = useMemo(() => {
243
+ const availableSet = new Set(isNullish(available) ? Dict.keys(filtersDefinition) : available);
244
+ return Array.filterMap(Dict.entries(filtersDefinition), ([name, { label }]) => availableSet.has(name) ? Option.Some({ name, label }) : Option.None());
245
+ }, [available, filtersDefinition]);
246
+ const [openFilters, setOpenFilters] = useState(() => Dict.entries(filters)
247
+ .filter(([, value]) => isNotNullish(value))
248
+ .map(([name]) => name));
249
+ useEffect(() => {
250
+ setOpenFilters(openFilters => {
251
+ const currentlyOpenFilters = new Set(openFilters);
252
+ const openFiltersNotYetInState = Dict.entries(filters)
253
+ .filter(([name, value]) => isNotNullish(value) && !currentlyOpenFilters.has(name))
254
+ .map(([name]) => name);
255
+ return [...openFilters, ...openFiltersNotYetInState];
256
+ });
257
+ }, [filters]);
258
+ const onAddFilter = useCallback((filter) => {
259
+ setOpenFilters(openFilters => [...openFilters, filter]);
260
+ }, []);
261
+ return {
262
+ chooser: {
263
+ availableFilters,
264
+ filters,
265
+ label: t("common.filters"),
266
+ onAddFilter,
267
+ openFilters,
268
+ },
269
+ stack: {
270
+ definition: filtersDefinition,
271
+ filters,
272
+ openedFilters: openFilters,
273
+ onChangeOpened: setOpenFilters,
274
+ },
275
+ };
276
+ };
@@ -23,6 +23,11 @@
23
23
  "businessActivity.transportation": "Transportwesen",
24
24
  "common.cancel": "Abbrechen",
25
25
  "common.close": "Schließen",
26
+ "common.filters": "Filter",
27
+ "common.filters.all": "Alle",
28
+ "common.filters.apply": "Anwenden",
29
+ "common.filters.cancel": "Abbrechen",
30
+ "common.filters.none": "Keine",
26
31
  "common.form.help.nbCharacters": "{nbCharacters} Zeichen",
27
32
  "common.form.help.nbDigits": "{nbDigits} Ziffern",
28
33
  "common.form.invalidTaxIdentificationNumber": "Diese Steueridentifikationsnummer ist ungültig",
@@ -23,6 +23,11 @@
23
23
  "businessActivity.transportation": "Transportation",
24
24
  "common.cancel": "Cancel",
25
25
  "common.close": "Close",
26
+ "common.filters": "Filters",
27
+ "common.filters.all": "All",
28
+ "common.filters.apply": "Apply",
29
+ "common.filters.cancel": "Cancel",
30
+ "common.filters.none": "None",
26
31
  "common.form.help.nbCharacters": "{nbCharacters} characters",
27
32
  "common.form.help.nbDigits": "{nbDigits} digits",
28
33
  "common.form.invalidTaxIdentificationNumber": "This tax identification number is invalid",
@@ -316,31 +321,31 @@
316
321
  "supportingDocuments.purpose.UltimateBeneficialOwnerProofOfAddress.description": "Include one document for each person who owns at least 25% of the capital or rights to vote, or any person who controls your company's executive bodies or management. Any document proving the individual's residence address. They must include the name and address of the individual and be dated less than 3 months old.\n\nAcceptable documents:\n- Documents related to the home (rental contract, mortgage statement, etc)\n- Home utility bills (for electricity, telephone, internet services, gas, water, etc)\n- Payroll (if it includes the worker's address)",
317
322
  "supportingDocuments.purpose.UltimateBeneficialOwnerProofOfIdentity": "Identity document of each beneficial owner",
318
323
  "supportingDocuments.purpose.UltimateBeneficialOwnerProofOfIdentity.description": "Include one document for each person who owns at least 25% of the capital or rights to vote, or any person who controls your company's executive bodies or management.\n\nAcceptable documents:\n- Passport\n- ID card (only applicable to citizens of member countries of the EEA zone)\n- Residence permit (only applicable to residents of member countries of the EEA zone)\n- Driver's license (only applicable to residents of member countries of the EEA zone)",
324
+ "supportingDocuments.rejectionReason.BadDocumentQuality": "The quality of the document is really low",
319
325
  "supportingDocuments.rejectionReason.CompanyNameMismatch": "The company name in the document submitted doesn't match our records.",
320
326
  "supportingDocuments.rejectionReason.DeclaredAmountMismatch": "The declared amount in the document submitted doesn't match our records.",
321
327
  "supportingDocuments.rejectionReason.ExpiredDocument": "The expiry date in the document submitted must be within the past 3 months.",
328
+ "supportingDocuments.rejectionReason.FullDocumentRequired": "Full document required",
329
+ "supportingDocuments.rejectionReason.HandwrittenOrCertifiedElectronicSignatureRequired": "The signature is not handwritten or electronically certified.",
330
+ "supportingDocuments.rejectionReason.IbanMismatch": "The beneficiary IBAN on the document submitted doesn't match the transaction request.",
322
331
  "supportingDocuments.rejectionReason.InvalidAddress": "The address in the document submitted doesn't match our records.",
323
332
  "supportingDocuments.rejectionReason.InvalidDocument": "The document is not valid.",
324
333
  "supportingDocuments.rejectionReason.InvalidOrMissingData": "The shareholder's name in the document submitted is invalid or missing.",
334
+ "supportingDocuments.rejectionReason.InvalidTransaction": "The information in the document submitted doesn't match this specific transaction.",
325
335
  "supportingDocuments.rejectionReason.MissingAccommodationProviderId": "An identity document for the accommodation provider is required.",
326
336
  "supportingDocuments.rejectionReason.MissingAccommodationProviderIdLetter": "The accommodation provider’s ID and proof of accommodation are required.",
327
337
  "supportingDocuments.rejectionReason.MissingAccommodationProviderLetter": "Proof of accommodation from the provider is required.",
328
- "supportingDocuments.rejectionReason.UnacceptableDocument": "Document cannot be accepted for the requested document type",
329
- "supportingDocuments.rejectionReason.ProviderColorIdDocumentRequired": "The document must be submitted in color.",
330
- "supportingDocuments.rejectionReason.MissingSignature": "The document submitted must be signed or dated.",
331
- "supportingDocuments.rejectionReason.BadDocumentQuality": "The quality of the document is really low",
332
- "supportingDocuments.rejectionReason.FullDocumentRequired": "Full document required",
338
+ "supportingDocuments.rejectionReason.MissingCompanyDomiciliationStatement": "The company domiciliation statement is required.",
339
+ "supportingDocuments.rejectionReason.MissingDescription": "More information is needed to understand the nature of this transaction. Please submit additional information.",
333
340
  "supportingDocuments.rejectionReason.MissingProviderProofOfAddress": "The accommodation provider's proof of address is required.",
334
341
  "supportingDocuments.rejectionReason.MissingProviderProofOfAddressAndIdDocument": "The accommodation provider's ID and proof of address are required.",
342
+ "supportingDocuments.rejectionReason.MissingSignature": "The document submitted must be signed or dated.",
335
343
  "supportingDocuments.rejectionReason.PowerOfAttorneyToSwanRequired": "Power of attorney must be provided to Swan.",
336
- "supportingDocuments.rejectionReason.MissingCompanyDomiciliationStatement": "The company domiciliation statement is required.",
337
- "supportingDocuments.rejectionReason.HandwrittenOrCertifiedElectronicSignatureRequired": "The signature is not handwritten or electronically certified.",
338
- "supportingDocuments.rejectionReason.MissingDescription": "More information is needed to understand the nature of this transaction. Please submit additional information.",
339
- "supportingDocuments.rejectionReason.InvalidTransaction": "The information in the document submitted doesn't match this specific transaction.",
340
- "supportingDocuments.rejectionReason.TransactionNameMismatch": "The issuer or beneficiary name on the document submitted doesn't match the transaction request.",
341
- "supportingDocuments.rejectionReason.TransactionDateMismatch": "The date on the document submitted doesn't match the transaction request.",
344
+ "supportingDocuments.rejectionReason.ProviderColorIdDocumentRequired": "The document must be submitted in color.",
342
345
  "supportingDocuments.rejectionReason.TransactionAmountMismatch": "The transaction amount on the document submitted doesn't match the transaction request.",
343
- "supportingDocuments.rejectionReason.IbanMismatch": "The beneficiary IBAN on the document submitted doesn't match the transaction request.",
346
+ "supportingDocuments.rejectionReason.TransactionDateMismatch": "The date on the document submitted doesn't match the transaction request.",
347
+ "supportingDocuments.rejectionReason.TransactionNameMismatch": "The issuer or beneficiary name on the document submitted doesn't match the transaction request.",
348
+ "supportingDocuments.rejectionReason.UnacceptableDocument": "Document cannot be accepted for the requested document type",
344
349
  "taxIdentificationNumber.label": "Tax identification number",
345
350
  "transactionStatement.creditor.accountNumber": "Creditor's account number",
346
351
  "transactionStatement.creditor.bankIdentifier": "Creditor's bank identifier",
@@ -23,6 +23,11 @@
23
23
  "businessActivity.transportation": "Transporte",
24
24
  "common.cancel": "Cancelar",
25
25
  "common.close": "Cerrar",
26
+ "common.filters": "Filtros",
27
+ "common.filters.all": "Todo",
28
+ "common.filters.apply": "Aplicar",
29
+ "common.filters.cancel": "Cancelar",
30
+ "common.filters.none": "Ninguno",
26
31
  "common.form.help.nbCharacters": "{nbCharacters} caracteres",
27
32
  "common.form.help.nbDigits": "{nbDigits} dígitos",
28
33
  "common.form.invalidTaxIdentificationNumber": "Este número de identificación fiscal no es válido",
@@ -23,6 +23,11 @@
23
23
  "businessActivity.transportation": "Kuljetusala",
24
24
  "common.cancel": "Peruuta",
25
25
  "common.close": "Sulje",
26
+ "common.filters": "Suodattimet",
27
+ "common.filters.all": "Kaikki",
28
+ "common.filters.apply": "Käytä",
29
+ "common.filters.cancel": "Peruuta",
30
+ "common.filters.none": "Ei yhtään",
26
31
  "common.form.help.nbCharacters": "{nbCharacters} merkkiä",
27
32
  "common.form.help.nbDigits": "{nbDigits} numeroa",
28
33
  "common.form.invalidTaxIdentificationNumber": "Virheellinen verotunnistenumero",
@@ -23,6 +23,11 @@
23
23
  "businessActivity.transportation": "Transports",
24
24
  "common.cancel": "Annuler",
25
25
  "common.close": "Fermer",
26
+ "common.filters": "Filtres",
27
+ "common.filters.all": "Tout",
28
+ "common.filters.apply": "Appliquer",
29
+ "common.filters.cancel": "Annuler",
30
+ "common.filters.none": "Aucun",
26
31
  "common.form.help.nbCharacters": "{nbCharacters} caractères",
27
32
  "common.form.help.nbDigits": "{nbDigits} chiffres",
28
33
  "common.form.invalidTaxIdentificationNumber": "Ce numéro d'identification fiscale n'est pas valide",
@@ -23,6 +23,11 @@
23
23
  "businessActivity.transportation": "Trasporto",
24
24
  "common.cancel": "Annulla",
25
25
  "common.close": "Chiudi",
26
+ "common.filters": "Filtri",
27
+ "common.filters.all": "Tutti",
28
+ "common.filters.apply": "Applica",
29
+ "common.filters.cancel": "Annulla",
30
+ "common.filters.none": "Nessuno",
26
31
  "common.form.help.nbCharacters": "{nbCharacters} caratteri",
27
32
  "common.form.help.nbDigits": "{nbDigits} cifre",
28
33
  "common.form.invalidTaxIdentificationNumber": "Codice fiscale non valido",
@@ -23,6 +23,11 @@
23
23
  "businessActivity.transportation": "Transport",
24
24
  "common.cancel": "Annuleren",
25
25
  "common.close": "Sluiten",
26
+ "common.filters": "Filters",
27
+ "common.filters.all": "Alle",
28
+ "common.filters.apply": "Toepassen",
29
+ "common.filters.cancel": "Annuleren",
30
+ "common.filters.none": "Geen",
26
31
  "common.form.help.nbCharacters": "{nbCharacters} tekens",
27
32
  "common.form.help.nbDigits": "{nbDigits} cijfers",
28
33
  "common.form.invalidTaxIdentificationNumber": "Dit fiscale identificatienummer is ongeldig",
@@ -23,6 +23,11 @@
23
23
  "businessActivity.transportation": "Transporte",
24
24
  "common.cancel": "Cancelar",
25
25
  "common.close": "Fechar",
26
+ "common.filters": "Filtros",
27
+ "common.filters.all": "Todos",
28
+ "common.filters.apply": "Aplicar",
29
+ "common.filters.cancel": "Cancelar",
30
+ "common.filters.none": "Nenhum",
26
31
  "common.form.help.nbCharacters": "{nbCharacters} caracteres",
27
32
  "common.form.help.nbDigits": "{nbDigits} dígitos",
28
33
  "common.form.invalidTaxIdentificationNumber": "Este número de identificação fiscal é inválido",