@okta/odyssey-react-mui 1.9.1 → 1.9.3

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +8 -0
  3. package/dist/OdysseyCacheProvider.js +9 -4
  4. package/dist/OdysseyCacheProvider.js.map +1 -1
  5. package/dist/OdysseyProvider.js.map +1 -1
  6. package/dist/OdysseyTranslationProvider.js +6 -5
  7. package/dist/OdysseyTranslationProvider.js.map +1 -1
  8. package/dist/OdysseyTranslationProvider.types.js +1 -1
  9. package/dist/OdysseyTranslationProvider.types.js.map +1 -1
  10. package/dist/getTypedObjectKeys.js +14 -0
  11. package/dist/getTypedObjectKeys.js.map +1 -0
  12. package/dist/i18n.js +0 -2
  13. package/dist/i18n.js.map +1 -1
  14. package/dist/properties/ts/odyssey-react-mui_ok_PL.js +11 -2
  15. package/dist/properties/ts/odyssey-react-mui_ok_PL.js.map +1 -1
  16. package/dist/properties/ts/odyssey-react-mui_ok_SK.js +11 -2
  17. package/dist/properties/ts/odyssey-react-mui_ok_SK.js.map +1 -1
  18. package/dist/src/OdysseyCacheProvider.d.ts +1 -1
  19. package/dist/src/OdysseyCacheProvider.d.ts.map +1 -1
  20. package/dist/src/OdysseyProvider.d.ts +3 -2
  21. package/dist/src/OdysseyProvider.d.ts.map +1 -1
  22. package/dist/src/OdysseyTranslationProvider.d.ts +7 -8
  23. package/dist/src/OdysseyTranslationProvider.d.ts.map +1 -1
  24. package/dist/src/OdysseyTranslationProvider.types.d.ts +2 -2
  25. package/dist/src/OdysseyTranslationProvider.types.d.ts.map +1 -1
  26. package/dist/src/getTypedObjectKeys.d.ts +13 -0
  27. package/dist/src/getTypedObjectKeys.d.ts.map +1 -0
  28. package/dist/src/i18n.d.ts +4 -537
  29. package/dist/src/i18n.d.ts.map +1 -1
  30. package/dist/src/properties/ts/odyssey-react-mui_ok_PL.d.ts +11 -2
  31. package/dist/src/properties/ts/odyssey-react-mui_ok_PL.d.ts.map +1 -1
  32. package/dist/src/properties/ts/odyssey-react-mui_ok_SK.d.ts +11 -2
  33. package/dist/src/properties/ts/odyssey-react-mui_ok_SK.d.ts.map +1 -1
  34. package/dist/tsconfig.production.tsbuildinfo +1 -1
  35. package/package.json +3 -3
  36. package/src/OdysseyCacheProvider.tsx +5 -2
  37. package/src/OdysseyProvider.tsx +9 -6
  38. package/src/OdysseyTranslationProvider.test.tsx +34 -2
  39. package/src/OdysseyTranslationProvider.tsx +23 -18
  40. package/src/OdysseyTranslationProvider.types.ts +3 -2
  41. package/src/getTypedObjectKeys.ts +15 -0
  42. package/src/i18n.ts +5 -8
  43. package/src/properties/translations/odyssey-react-mui_ok_PL.properties +11 -2
  44. package/src/properties/translations/odyssey-react-mui_ok_SK.properties +11 -2
  45. package/src/properties/ts/odyssey-react-mui_ok_PL.ts +1 -1
  46. package/src/properties/ts/odyssey-react-mui_ok_SK.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okta/odyssey-react-mui",
3
- "version": "1.9.1",
3
+ "version": "1.9.3",
4
4
  "description": "React MUI components for Odyssey, Okta's design system",
5
5
  "author": "Okta, Inc.",
6
6
  "license": "Apache-2.0",
@@ -51,7 +51,7 @@
51
51
  "@mui/system": "^5.14.9",
52
52
  "@mui/utils": "^5.11.2",
53
53
  "@mui/x-date-pickers": "^5.0.15",
54
- "@okta/odyssey-design-tokens": "1.9.1",
54
+ "@okta/odyssey-design-tokens": "1.9.3",
55
55
  "date-fns": "^2.30.0",
56
56
  "i18next": "^23.5.1",
57
57
  "material-react-table": "^2.0.2",
@@ -63,5 +63,5 @@
63
63
  "react": ">=17 <19",
64
64
  "react-dom": ">=17 <19"
65
65
  },
66
- "gitHead": "09181cf65fb26379fca04275a4adbed25478cdd1"
66
+ "gitHead": "0901a41daba0362bfc71aab39591e6c039e0526b"
67
67
  }
@@ -40,6 +40,8 @@ export type OdysseyCacheProviderProps = {
40
40
  const OdysseyCacheProvider = ({
41
41
  children,
42
42
  emotionRoot,
43
+ nonce,
44
+ stylisPlugins,
43
45
  }: OdysseyCacheProviderProps) => {
44
46
  const uniqueAlphabeticalId = useUniqueAlphabeticalId();
45
47
 
@@ -47,11 +49,12 @@ const OdysseyCacheProvider = ({
47
49
  return createCache({
48
50
  ...(emotionRoot && { container: emotionRoot }),
49
51
  key: uniqueAlphabeticalId,
50
- nonce: window.cspNonce,
52
+ nonce: nonce ?? window.cspNonce,
51
53
  prepend: true,
52
54
  speedy: false, // <-- Needs to be set to false when shadow-dom is used!! https://github.com/emotion-js/emotion/issues/2053#issuecomment-713429122
55
+ ...(stylisPlugins && { stylisPlugins }),
53
56
  });
54
- }, [emotionRoot, uniqueAlphabeticalId]);
57
+ }, [emotionRoot, nonce, stylisPlugins, uniqueAlphabeticalId]);
55
58
 
56
59
  return <CacheProvider value={emotionCache}>{children}</CacheProvider>;
57
60
  };
@@ -25,14 +25,17 @@ import {
25
25
  OdysseyTranslationProvider,
26
26
  OdysseyTranslationProviderProps,
27
27
  } from "./OdysseyTranslationProvider";
28
+ import { DefaultSupportedLanguages } from "./OdysseyTranslationProvider.types";
28
29
 
29
- export type OdysseyProviderProps = OdysseyCacheProviderProps &
30
+ export type OdysseyProviderProps<
31
+ SupportedLanguages extends string = DefaultSupportedLanguages
32
+ > = OdysseyCacheProviderProps &
30
33
  OdysseyThemeProviderProps &
31
- OdysseyTranslationProviderProps & {
34
+ OdysseyTranslationProviderProps<SupportedLanguages> & {
32
35
  children: ReactNode;
33
36
  };
34
37
 
35
- const OdysseyProvider = ({
38
+ const OdysseyProvider = <SupportedLanguages extends string>({
36
39
  children,
37
40
  designTokensOverride,
38
41
  emotionRoot,
@@ -42,7 +45,7 @@ const OdysseyProvider = ({
42
45
  stylisPlugins,
43
46
  themeOverride,
44
47
  translationOverrides,
45
- }: OdysseyProviderProps) => (
48
+ }: OdysseyProviderProps<SupportedLanguages>) => (
46
49
  <OdysseyCacheProvider
47
50
  nonce={nonce}
48
51
  emotionRoot={emotionRoot}
@@ -57,7 +60,7 @@ const OdysseyProvider = ({
57
60
  withCache={false}
58
61
  >
59
62
  <ScopedCssBaseline>
60
- <OdysseyTranslationProvider
63
+ <OdysseyTranslationProvider<SupportedLanguages>
61
64
  languageCode={languageCode}
62
65
  translationOverrides={translationOverrides}
63
66
  >
@@ -68,6 +71,6 @@ const OdysseyProvider = ({
68
71
  </OdysseyCacheProvider>
69
72
  );
70
73
 
71
- const MemoizedThemeProvider = memo(OdysseyProvider);
74
+ const MemoizedThemeProvider = memo(OdysseyProvider) as typeof OdysseyProvider;
72
75
 
73
76
  export { MemoizedThemeProvider as OdysseyProvider };
@@ -26,6 +26,38 @@ describe("OdysseyTranslationProvider", () => {
26
26
  expect(screen.getByText("Optional"));
27
27
  });
28
28
 
29
+ it("defaults to 'en' for unsupported langauges", () => {
30
+ render(
31
+ <OdysseyTranslationProvider languageCode="test">
32
+ <span>{odysseyTranslate("fieldlabel.optional.text")}</span>
33
+ </OdysseyTranslationProvider>
34
+ );
35
+
36
+ expect(screen.getByText("Optional"));
37
+ });
38
+
39
+ it("allows translations for non-okta supported languages for existing keys", () => {
40
+ const translationOverrides = {
41
+ ar: {
42
+ "fieldlabel.optional.text":
43
+ "\u063A\u064A\u0631 \u0645\u0637\u0644\u0648\u0628",
44
+ },
45
+ };
46
+
47
+ render(
48
+ <OdysseyTranslationProvider<"ar">
49
+ languageCode="ar"
50
+ translationOverrides={translationOverrides}
51
+ >
52
+ <TextField label="" isOptional />
53
+ </OdysseyTranslationProvider>
54
+ );
55
+
56
+ expect(
57
+ screen.getByText("\u063A\u064A\u0631 \u0645\u0637\u0644\u0648\u0628")
58
+ );
59
+ });
60
+
29
61
  it("can modify a translation bundle with translantionOverrides", () => {
30
62
  const translationOverrides = {
31
63
  en: {
@@ -35,7 +67,7 @@ describe("OdysseyTranslationProvider", () => {
35
67
 
36
68
  render(
37
69
  <OdysseyTranslationProvider translationOverrides={translationOverrides}>
38
- <TextField label={""} isOptional />
70
+ <TextField label="" isOptional />
39
71
  </OdysseyTranslationProvider>
40
72
  );
41
73
 
@@ -54,7 +86,7 @@ describe("OdysseyTranslationProvider", () => {
54
86
  languageCode="fr"
55
87
  translationOverrides={translationOverrides}
56
88
  >
57
- <TextField label={""} isOptional />
89
+ <TextField label="" isOptional />
58
90
  </OdysseyTranslationProvider>
59
91
  );
60
92
 
@@ -12,38 +12,43 @@
12
12
 
13
13
  import { ReactNode, useEffect } from "react";
14
14
 
15
- import { SupportedLanguages } from "./OdysseyTranslationProvider.types";
15
+ import { DefaultSupportedLanguages } from "./OdysseyTranslationProvider.types";
16
16
 
17
17
  import { i18n, defaultNS, resources } from "./i18n";
18
18
  import { I18nextProvider } from "react-i18next";
19
+ import { getTypedObjectKeys } from "./getTypedObjectKeys";
19
20
 
20
- export type TranslationOverrides = {
21
- [key in SupportedLanguages]?: Partial<(typeof resources)["en"]>;
22
- };
21
+ export type OdysseyI18nResourceKeys = (typeof resources)["en"];
22
+
23
+ export type TranslationOverrides<
24
+ SupportedLanguages extends string = DefaultSupportedLanguages
25
+ > = Record<SupportedLanguages, Partial<OdysseyI18nResourceKeys>>;
23
26
 
24
- const mergeBundleOverrides = (
27
+ const mergeBundleOverrides = <SupportedLanguages extends string>(
25
28
  languageCode: SupportedLanguages,
26
- translationOverrides: TranslationOverrides
29
+ translationOverrides: TranslationOverrides<SupportedLanguages>
27
30
  ) => {
28
- const bundle = resources[languageCode];
29
- const overrides = translationOverrides[languageCode];
31
+ const translationStrings = resources[languageCode] || {};
32
+ const translationStringOverrides = translationOverrides[languageCode];
30
33
  return {
31
- ...bundle,
32
- ...overrides,
34
+ ...translationStrings,
35
+ ...translationStringOverrides,
33
36
  };
34
37
  };
35
38
 
36
- export type OdysseyTranslationProviderProps = {
39
+ export type OdysseyTranslationProviderProps<
40
+ SupportedLanguages extends string = DefaultSupportedLanguages
41
+ > = {
37
42
  children: ReactNode;
38
- languageCode?: SupportedLanguages;
39
- translationOverrides?: TranslationOverrides;
43
+ languageCode?: SupportedLanguages | DefaultSupportedLanguages;
44
+ translationOverrides?: TranslationOverrides<SupportedLanguages>;
40
45
  };
41
46
 
42
- export const OdysseyTranslationProvider = ({
47
+ export const OdysseyTranslationProvider = <SupportedLanguages extends string>({
43
48
  children,
44
49
  languageCode,
45
50
  translationOverrides,
46
- }: OdysseyTranslationProviderProps) => {
51
+ }: OdysseyTranslationProviderProps<SupportedLanguages>) => {
47
52
  useEffect(() => {
48
53
  // Defaults to the browser's language if available otherwise `en` will be used
49
54
  i18n.changeLanguage(languageCode || window.navigator.language);
@@ -51,9 +56,9 @@ export const OdysseyTranslationProvider = ({
51
56
 
52
57
  useEffect(() => {
53
58
  if (translationOverrides) {
54
- Object.keys(translationOverrides).forEach((language) => {
55
- const bundle = mergeBundleOverrides(
56
- language as SupportedLanguages,
59
+ getTypedObjectKeys(translationOverrides).forEach((language) => {
60
+ const bundle = mergeBundleOverrides<SupportedLanguages>(
61
+ language,
57
62
  translationOverrides
58
63
  );
59
64
  i18n.addResourceBundle(language, defaultNS, bundle);
@@ -10,7 +10,7 @@
10
10
  * See the License for the specific language governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- export const supportedLanguages = [
13
+ export const defaultSupportedLanguages = [
14
14
  "cs", // Czech
15
15
  "da", // Danish
16
16
  "de", // German
@@ -42,4 +42,5 @@ export const supportedLanguages = [
42
42
  "zh_TW", // Chinese
43
43
  ] as const;
44
44
 
45
- export type SupportedLanguages = (typeof supportedLanguages)[number];
45
+ export type DefaultSupportedLanguages =
46
+ (typeof defaultSupportedLanguages)[number];
@@ -0,0 +1,15 @@
1
+ /*!
2
+ * Copyright (c) 2023-present, Okta, Inc. and/or its affiliates. All rights reserved.
3
+ * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
4
+ *
5
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
6
+ * Unless required by applicable law or agreed to in writing, software
7
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ *
10
+ * See the License for the specific language governing permissions and limitations under the License.
11
+ */
12
+
13
+ export const getTypedObjectKeys: <ObjectType>(
14
+ object: ObjectType
15
+ ) => Array<keyof ObjectType> = Object.keys;
package/src/i18n.ts CHANGED
@@ -43,14 +43,12 @@ import { translation as vi } from "./properties/ts/odyssey-react-mui_vi";
43
43
  import { translation as zhCN } from "./properties/ts/odyssey-react-mui_zh_CN";
44
44
  import { translation as znTW } from "./properties/ts/odyssey-react-mui_zh_TW";
45
45
 
46
- import {
47
- SupportedLanguages,
48
- supportedLanguages,
49
- } from "./OdysseyTranslationProvider.types";
50
-
51
- export const defaultLNG: SupportedLanguages = "en";
46
+ export const defaultLNG = "en";
52
47
  export const defaultNS = "translations";
53
- export const resources = {
48
+
49
+ // Note: This is type "string" to allow translation overrides from other languages
50
+ export type I18nResources = Record<string, typeof en>;
51
+ export const resources: I18nResources = {
54
52
  cs,
55
53
  da,
56
54
  de,
@@ -86,7 +84,6 @@ i18n.use(initReactI18next).init({
86
84
  defaultNS,
87
85
  ns: [defaultNS],
88
86
  fallbackLng: defaultLNG,
89
- supportedLngs: supportedLanguages,
90
87
  load: "currentOnly",
91
88
  keySeparator: false,
92
89
  interpolation: {
@@ -1,8 +1,17 @@
1
+ breadcrumbs.home.text = 》Ĥöɱé 한Ӝฐโ《
2
+ breadcrumbs.label.text = 》Ɓŕéåðçŕûɱƀš ئ䀕ヸ€홝한Ӝฐโ《
1
3
  fielderror.screenreader.text = 》Éŕŕöŕ 홝한Ӝฐโ《
2
4
  fieldlabel.optional.text = 》Öþţîöñåļ 䀕ヸ€홝한Ӝฐโ《
3
5
  fieldlabel.required.text = 》Ŕéǫûîŕéð 䀕ヸ€홝한Ӝฐโ《
6
+ passwordfield.icon.label.show = 》Šĥöŵ þåššŵöŕð ⾼ئ䀕ヸ€홝한Ӝฐโ《
7
+ passwordfield.icon.label.hide = 》Ĥîðé þåššŵöŕð ⾼ئ䀕ヸ€홝한Ӝฐโ《
8
+ severity.error = 》éŕŕöŕ 홝한Ӝฐโ《
9
+ severity.info = 》îñƒö 한Ӝฐโ《
4
10
  severity.success = 》šûççéšš ヸ€홝한Ӝฐโ《
5
11
  severity.warning = 》ŵåŕñîñĝ ヸ€홝한Ӝฐโ《
6
- severity.info = 》îñƒö 한Ӝฐโ《
7
- severity.error = 》éŕŕöŕ 홝한Ӝฐโ《
12
+ table.error = 》Éŕŕöŕ ļöåðîñĝ ðåţå· 홝한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《
13
+ table.fetchedrows.text = 》Ƒéţçĥéð {{totalRows}} ŕöŵ 홝한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《
14
+ table.fetchedrows.text_plural = 》Ƒéţçĥéð {{totalRows}} ţöţåļ ŕöŵš Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《
15
+ table.rows.text = 》{{totalRows}} ŕöŵ 한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《
16
+ table.rows.text_plural = 》{{totalRows}} ŕöŵš 한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《
8
17
  toast.close.text = 》çļöšé 홝한Ӝฐโ《
@@ -1,8 +1,17 @@
1
+ breadcrumbs.home.text = [[odyssey:odyssey-react-mui: breadcrumbs.home.text]]
2
+ breadcrumbs.label.text = [[odyssey:odyssey-react-mui: breadcrumbs.label.text]]
1
3
  fielderror.screenreader.text = [[odyssey:odyssey-react-mui: fielderror.screenreader.text]]
2
4
  fieldlabel.optional.text = [[odyssey:odyssey-react-mui: fieldlabel.optional.text]]
3
5
  fieldlabel.required.text = [[odyssey:odyssey-react-mui: fieldlabel.required.text]]
6
+ passwordfield.icon.label.show = [[odyssey:odyssey-react-mui: passwordfield.icon.label.show]]
7
+ passwordfield.icon.label.hide = [[odyssey:odyssey-react-mui: passwordfield.icon.label.hide]]
8
+ severity.error = [[odyssey:odyssey-react-mui: severity.error]]
9
+ severity.info = [[odyssey:odyssey-react-mui: severity.info]]
4
10
  severity.success = [[odyssey:odyssey-react-mui: severity.success]]
5
11
  severity.warning = [[odyssey:odyssey-react-mui: severity.warning]]
6
- severity.info = [[odyssey:odyssey-react-mui: severity.info]]
7
- severity.error = [[odyssey:odyssey-react-mui: severity.error]]
12
+ table.error = [[odyssey:odyssey-react-mui: table.error]]
13
+ table.fetchedrows.text = [[odyssey:odyssey-react-mui: table.fetchedrows.text]]
14
+ table.fetchedrows.text_plural = [[odyssey:odyssey-react-mui: table.fetchedrows.text_plural]]
15
+ table.rows.text = [[odyssey:odyssey-react-mui: table.rows.text]]
16
+ table.rows.text_plural = [[odyssey:odyssey-react-mui: table.rows.text_plural]]
8
17
  toast.close.text = [[odyssey:odyssey-react-mui: toast.close.text]]
@@ -1 +1 @@
1
- export const translation = {"fielderror.screenreader.text":"》Éŕŕöŕ 홝한Ӝฐโ《","fieldlabel.optional.text":"》Öþţîöñåļ 䀕ヸ€홝한Ӝฐโ《","fieldlabel.required.text":"》Ŕéǫûîŕéð 䀕ヸ€홝한Ӝฐโ《","severity.success":"》šûççéšš ヸ€홝한Ӝฐโ《","severity.warning":"》ŵåŕñîñĝ ヸ€홝한Ӝฐโ《","severity.info":"》îñƒö 한Ӝฐโ《","severity.error":"》éŕŕöŕ 홝한Ӝฐโ《","toast.close.text":"》çļöšé 홝한Ӝฐโ《"};
1
+ export const translation = {"breadcrumbs.home.text":"》Ĥöɱé 한Ӝฐโ《","breadcrumbs.label.text":"》Ɓŕéåðçŕûɱƀš ئ䀕ヸ€홝한Ӝฐโ《","fielderror.screenreader.text":"》Éŕŕöŕ 홝한Ӝฐโ《","fieldlabel.optional.text":"》Öþţîöñåļ 䀕ヸ€홝한Ӝฐโ《","fieldlabel.required.text":"》Ŕéǫûîŕéð 䀕ヸ€홝한Ӝฐโ《","passwordfield.icon.label.show":"》Šĥöŵ þåššŵöŕð ⾼ئ䀕ヸ€홝한Ӝฐโ《","passwordfield.icon.label.hide":"》Ĥîðé þåššŵöŕð ⾼ئ䀕ヸ€홝한Ӝฐโ《","severity.error":"》éŕŕöŕ 홝한Ӝฐโ《","severity.info":"》îñƒö 한Ӝฐโ《","severity.success":"》šûççéšš ヸ€홝한Ӝฐโ《","severity.warning":"》ŵåŕñîñĝ ヸ€홝한Ӝฐโ《","table.error":"》Éŕŕöŕ ļöåðîñĝ ðåţå· 홝한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《","table.fetchedrows.text":"》Ƒéţçĥéð {{totalRows}} ŕöŵ 홝한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《","table.fetchedrows.text_plural":"》Ƒéţçĥéð {{totalRows}} ţöţåļ ŕöŵš Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《","table.rows.text":"》{{totalRows}} ŕöŵ 한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《","table.rows.text_plural":"》{{totalRows}} ŕöŵš 한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《","toast.close.text":"》çļöšé 홝한Ӝฐโ《"};
@@ -1 +1 @@
1
- export const translation = {"fielderror.screenreader.text":"[[odyssey:odyssey-react-mui: fielderror.screenreader.text]]","fieldlabel.optional.text":"[[odyssey:odyssey-react-mui: fieldlabel.optional.text]]","fieldlabel.required.text":"[[odyssey:odyssey-react-mui: fieldlabel.required.text]]","severity.success":"[[odyssey:odyssey-react-mui: severity.success]]","severity.warning":"[[odyssey:odyssey-react-mui: severity.warning]]","severity.info":"[[odyssey:odyssey-react-mui: severity.info]]","severity.error":"[[odyssey:odyssey-react-mui: severity.error]]","toast.close.text":"[[odyssey:odyssey-react-mui: toast.close.text]]"};
1
+ export const translation = {"breadcrumbs.home.text":"[[odyssey:odyssey-react-mui: breadcrumbs.home.text]]","breadcrumbs.label.text":"[[odyssey:odyssey-react-mui: breadcrumbs.label.text]]","fielderror.screenreader.text":"[[odyssey:odyssey-react-mui: fielderror.screenreader.text]]","fieldlabel.optional.text":"[[odyssey:odyssey-react-mui: fieldlabel.optional.text]]","fieldlabel.required.text":"[[odyssey:odyssey-react-mui: fieldlabel.required.text]]","passwordfield.icon.label.show":"[[odyssey:odyssey-react-mui: passwordfield.icon.label.show]]","passwordfield.icon.label.hide":"[[odyssey:odyssey-react-mui: passwordfield.icon.label.hide]]","severity.error":"[[odyssey:odyssey-react-mui: severity.error]]","severity.info":"[[odyssey:odyssey-react-mui: severity.info]]","severity.success":"[[odyssey:odyssey-react-mui: severity.success]]","severity.warning":"[[odyssey:odyssey-react-mui: severity.warning]]","table.error":"[[odyssey:odyssey-react-mui: table.error]]","table.fetchedrows.text":"[[odyssey:odyssey-react-mui: table.fetchedrows.text]]","table.fetchedrows.text_plural":"[[odyssey:odyssey-react-mui: table.fetchedrows.text_plural]]","table.rows.text":"[[odyssey:odyssey-react-mui: table.rows.text]]","table.rows.text_plural":"[[odyssey:odyssey-react-mui: table.rows.text_plural]]","toast.close.text":"[[odyssey:odyssey-react-mui: toast.close.text]]"};