i18n, vue-router and vuex upgrade

1. Configuration of i18n legacy as false.
2. Translation function t is called using the useI18n.
3. Used the i18n.global.t() function from i18n instead of this.$t()
4. Event bus error that occurred during logout.
5. Implemented vue-router 4.4.0 and vuex upgrade to 4.1.0

Change-Id: I9464d82c76dcc1445ce271983ea3ab9d7b03d265
Signed-off-by: Surya Venkatesan <suryav@ami.com>
diff --git a/package.json b/package.json
index 1b5c530..8b593c5 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
     "dependencies": {
         "@carbon/icons-vue": "10.49.1",
         "@novnc/novnc": "1.3.0",
-        "@vue/compat": "3.4.25",
+        "@vue/compat": "3.4.29",
         "@vue/vue3-jest": "27.0.0",
         "@vuelidate/core": "2.0.3",
         "@vuelidate/validators": "2.0.4",
@@ -30,11 +30,11 @@
         "date-fns-tz": "1.3.6",
         "js-cookie": "3.0.1",
         "lodash": "4.17.21",
-        "vue": "3.2.37",
+        "vue": "3.4.29",
         "vue-i18n": "9.13.1",
         "vue-loader": "17.4.2",
-        "vue-router": "3.5.1",
-        "vuex": "3.6.2",
+        "vue-router": "4.4.0",
+        "vuex": "4.1.0",
         "webpack-cli": "5.1.4",
         "xterm": "4.19.0",
         "xterm-addon-attach": "0.6.0",
diff --git a/src/components/AppHeader/AppHeader.vue b/src/components/AppHeader/AppHeader.vue
index 9d06680..6b19ac0 100644
--- a/src/components/AppHeader/AppHeader.vue
+++ b/src/components/AppHeader/AppHeader.vue
@@ -116,6 +116,7 @@
 import IconRenew from '@carbon/icons-vue/es/renew/20';
 import StatusIcon from '@/components/Global/StatusIcon';
 import LoadingBar from '@/components/Global/LoadingBar';
+import { useI18n } from 'vue-i18n';
 import { mapState } from 'vuex';
 
 export default {
@@ -137,6 +138,7 @@
   },
   data() {
     return {
+      $t: useI18n().t,
       isNavigationOpen: false,
       altLogo: process.env.VUE_APP_COMPANY_NAME || 'Built on OpenBMC',
     };
@@ -198,7 +200,7 @@
   },
   watch: {
     consoleWindow() {
-      if (this.consoleWindow === false) this.$eventBus.$consoleWindow.close();
+      if (this.consoleWindow === false) this.$eventBus.$consoleWindow?.close();
     },
     isAuthorized(value) {
       if (value === false) {
diff --git a/src/components/AppNavigation/AppNavigation.vue b/src/components/AppNavigation/AppNavigation.vue
index 4c93be5..eb8c2c6 100644
--- a/src/components/AppNavigation/AppNavigation.vue
+++ b/src/components/AppNavigation/AppNavigation.vue
@@ -60,12 +60,14 @@
 //Exact match alias set to support
 //dotenv customizations.
 import AppNavigationMixin from './AppNavigationMixin';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'AppNavigation',
   mixins: [AppNavigationMixin],
   data() {
     return {
+      $t: useI18n().t,
       isNavigationOpen: false,
       currentUserRole: null,
     };
diff --git a/src/components/AppNavigation/AppNavigationMixin.js b/src/components/AppNavigation/AppNavigationMixin.js
index b33b24b..c00e984 100644
--- a/src/components/AppNavigation/AppNavigationMixin.js
+++ b/src/components/AppNavigation/AppNavigationMixin.js
@@ -6,6 +6,7 @@
 import IconSecurity from '@carbon/icons-vue/es/security/16';
 import IconChevronUp from '@carbon/icons-vue/es/chevron--up/16';
 import IconDataBase from '@carbon/icons-vue/es/data--base--alt/16';
+import i18n from '@/i18n';
 const roles = {
   administrator: 'Administrator',
   operator: 'Operator',
@@ -29,88 +30,88 @@
       navigationItems: [
         {
           id: 'overview',
-          label: this.$t('appNavigation.overview'),
+          label: i18n.global.t('appNavigation.overview'),
           route: '/',
           icon: 'iconOverview',
         },
         {
           id: 'logs',
-          label: this.$t('appNavigation.logs'),
+          label: i18n.global.t('appNavigation.logs'),
           icon: 'iconLogs',
           children: [
             {
               id: 'event-logs',
-              label: this.$t('appNavigation.eventLogs'),
+              label: i18n.global.t('appNavigation.eventLogs'),
               route: '/logs/event-logs',
             },
             {
               id: 'post-code-logs',
-              label: this.$t('appNavigation.postCodeLogs'),
+              label: i18n.global.t('appNavigation.postCodeLogs'),
               route: '/logs/post-code-logs',
             },
           ],
         },
         {
           id: 'hardware-status',
-          label: this.$t('appNavigation.hardwareStatus'),
+          label: i18n.global.t('appNavigation.hardwareStatus'),
           icon: 'iconHealth',
           children: [
             {
               id: 'inventory',
-              label: this.$t('appNavigation.inventory'),
+              label: i18n.global.t('appNavigation.inventory'),
               route: '/hardware-status/inventory',
             },
             {
               id: 'sensors',
-              label: this.$t('appNavigation.sensors'),
+              label: i18n.global.t('appNavigation.sensors'),
               route: '/hardware-status/sensors',
             },
           ],
         },
         {
           id: 'operations',
-          label: this.$t('appNavigation.operations'),
+          label: i18n.global.t('appNavigation.operations'),
           icon: 'iconControl',
           children: [
             {
               id: 'factory-reset',
-              label: this.$t('appNavigation.factoryReset'),
+              label: i18n.global.t('appNavigation.factoryReset'),
               route: '/operations/factory-reset',
             },
             {
               id: 'kvm',
-              label: this.$t('appNavigation.kvm'),
+              label: i18n.global.t('appNavigation.kvm'),
               route: '/operations/kvm',
             },
             {
               id: 'key-clear',
-              label: this.$t('appNavigation.keyClear'),
+              label: i18n.global.t('appNavigation.keyClear'),
               route: '/operations/key-clear',
             },
             {
               id: 'firmware',
-              label: this.$t('appNavigation.firmware'),
+              label: i18n.global.t('appNavigation.firmware'),
               route: '/operations/firmware',
             },
             {
               id: 'reboot-bmc',
-              label: this.$t('appNavigation.rebootBmc'),
+              label: i18n.global.t('appNavigation.rebootBmc'),
               route: '/operations/reboot-bmc',
             },
             {
               id: 'serial-over-lan',
-              label: this.$t('appNavigation.serialOverLan'),
+              label: i18n.global.t('appNavigation.serialOverLan'),
               route: '/operations/serial-over-lan',
               exclusiveToRoles: [roles.administrator],
             },
             {
               id: 'server-power-operations',
-              label: this.$t('appNavigation.serverPowerOperations'),
+              label: i18n.global.t('appNavigation.serverPowerOperations'),
               route: '/operations/server-power-operations',
             },
             {
               id: 'virtual-media',
-              label: this.$t('appNavigation.virtualMedia'),
+              label: i18n.global.t('appNavigation.virtualMedia'),
               route: '/operations/virtual-media',
               exclusiveToRoles: [roles.administrator],
             },
@@ -118,71 +119,71 @@
         },
         {
           id: 'settings',
-          label: this.$t('appNavigation.settings'),
+          label: i18n.global.t('appNavigation.settings'),
           icon: 'iconSettings',
           children: [
             {
               id: 'date-time',
-              label: this.$t('appNavigation.dateTime'),
+              label: i18n.global.t('appNavigation.dateTime'),
               route: '/settings/date-time',
             },
             {
               id: 'network',
-              label: this.$t('appNavigation.network'),
+              label: i18n.global.t('appNavigation.network'),
               route: '/settings/network',
             },
             {
               id: 'power-restore-policy',
-              label: this.$t('appNavigation.powerRestorePolicy'),
+              label: i18n.global.t('appNavigation.powerRestorePolicy'),
               route: '/settings/power-restore-policy',
             },
             {
               id: 'snmp-alerts',
-              label: this.$t('appNavigation.snmpAlerts'),
+              label: i18n.global.t('appNavigation.snmpAlerts'),
               route: '/settings/snmp-alerts',
             },
           ],
         },
         {
           id: 'security-and-access',
-          label: this.$t('appNavigation.securityAndAccess'),
+          label: i18n.global.t('appNavigation.securityAndAccess'),
           icon: 'iconSecurityAndAccess',
           children: [
             {
               id: 'sessions',
-              label: this.$t('appNavigation.sessions'),
+              label: i18n.global.t('appNavigation.sessions'),
               route: '/security-and-access/sessions',
             },
             {
               id: 'ldap',
-              label: this.$t('appNavigation.ldap'),
+              label: i18n.global.t('appNavigation.ldap'),
               route: '/security-and-access/ldap',
             },
             {
               id: 'user-management',
-              label: this.$t('appNavigation.userManagement'),
+              label: i18n.global.t('appNavigation.userManagement'),
               route: '/security-and-access/user-management',
             },
             {
               id: 'policies',
-              label: this.$t('appNavigation.policies'),
+              label: i18n.global.t('appNavigation.policies'),
               route: '/security-and-access/policies',
             },
             {
               id: 'certificates',
-              label: this.$t('appNavigation.certificates'),
+              label: i18n.global.t('appNavigation.certificates'),
               route: '/security-and-access/certificates',
             },
           ],
         },
         {
           id: 'resource-management',
-          label: this.$t('appNavigation.resourceManagement'),
+          label: i18n.global.t('appNavigation.resourceManagement'),
           icon: 'iconResourceManagement',
           children: [
             {
               id: 'power',
-              label: this.$t('appNavigation.power'),
+              label: i18n.global.t('appNavigation.power'),
               route: '/resource-management/power',
             },
           ],
diff --git a/src/components/Global/ButtonBackToTop.vue b/src/components/Global/ButtonBackToTop.vue
index 3ceb691..f8d8b88 100644
--- a/src/components/Global/ButtonBackToTop.vue
+++ b/src/components/Global/ButtonBackToTop.vue
@@ -16,12 +16,14 @@
 import UpToTop24 from '@carbon/icons-vue/es/up-to-top/24';
 
 import { debounce } from 'lodash';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'BackToTop',
   components: { IconUpToTop: UpToTop24 },
   data() {
     return {
+      $t: useI18n().t,
       showButton: false,
     };
   },
diff --git a/src/components/Global/InputPasswordToggle.vue b/src/components/Global/InputPasswordToggle.vue
index cd86920..fadb99a 100644
--- a/src/components/Global/InputPasswordToggle.vue
+++ b/src/components/Global/InputPasswordToggle.vue
@@ -18,6 +18,7 @@
 <script>
 import IconView from '@carbon/icons-vue/es/view/20';
 import IconViewOff from '@carbon/icons-vue/es/view--off/20';
+import i18n from '@/i18n';
 
 export default {
   name: 'InputPasswordToggle',
@@ -25,7 +26,7 @@
   data() {
     return {
       isVisible: false,
-      togglePasswordLabel: this.$t('global.ariaLabel.showPassword'),
+      togglePasswordLabel: i18n.global.t('global.ariaLabel.showPassword'),
     };
   },
   methods: {
@@ -40,8 +41,12 @@
       }
 
       this.isVisible
-        ? (this.togglePasswordLabel = this.$t('global.ariaLabel.hidePassword'))
-        : (this.togglePasswordLabel = this.$t('global.ariaLabel.showPassword'));
+        ? (this.togglePasswordLabel = i18n.global.t(
+            'global.ariaLabel.hidePassword',
+          ))
+        : (this.togglePasswordLabel = i18n.global.t(
+            'global.ariaLabel.showPassword',
+          ));
     },
   },
 };
diff --git a/src/components/Global/LoadingBar.vue b/src/components/Global/LoadingBar.vue
index 337aaf0..49f2611 100644
--- a/src/components/Global/LoadingBar.vue
+++ b/src/components/Global/LoadingBar.vue
@@ -12,9 +12,11 @@
 </template>
 
 <script>
+import { useI18n } from 'vue-i18n';
 export default {
   data() {
     return {
+      $t: useI18n().t,
       loadingIndicatorValue: 0,
       isLoadingComplete: false,
       loadingIntervalId: null,
diff --git a/src/components/Global/Search.vue b/src/components/Global/Search.vue
index d53315b..5c51678 100644
--- a/src/components/Global/Search.vue
+++ b/src/components/Global/Search.vue
@@ -39,6 +39,8 @@
 <script>
 import IconSearch from '@carbon/icons-vue/es/search/16';
 import IconClose from '@carbon/icons-vue/es/close/20';
+import { useI18n } from 'vue-i18n';
+import i18n from '@/i18n';
 
 export default {
   name: 'Search',
@@ -47,12 +49,13 @@
     placeholder: {
       type: String,
       default: function () {
-        return this.$t('global.form.search');
+        return i18n.global.t('global.form.search');
       },
     },
   },
   data() {
     return {
+      $t: useI18n().t,
       filter: null,
     };
   },
diff --git a/src/components/Global/TableCellCount.vue b/src/components/Global/TableCellCount.vue
index acb4d44..25730a3 100644
--- a/src/components/Global/TableCellCount.vue
+++ b/src/components/Global/TableCellCount.vue
@@ -15,6 +15,7 @@
 </template>
 
 <script>
+import { useI18n } from 'vue-i18n';
 export default {
   props: {
     filteredItemsCount: {
@@ -26,6 +27,11 @@
       required: true,
     },
   },
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     filterActive() {
       return this.filteredItemsCount !== this.totalNumberOfCells;
diff --git a/src/components/Global/TableDateFilter.vue b/src/components/Global/TableDateFilter.vue
index 4e8c5b9..921268c 100644
--- a/src/components/Global/TableDateFilter.vue
+++ b/src/components/Global/TableDateFilter.vue
@@ -11,15 +11,15 @@
             id="input-from-date"
             v-model="fromDate"
             placeholder="YYYY-MM-DD"
-            :state="getValidationState($v.fromDate)"
+            :state="getValidationState(v$.fromDate)"
             class="form-control-with-button mb-3 mb-md-0"
-            @blur="$v.fromDate.$touch()"
+            @blur="v$.fromDate.$touch()"
           />
           <b-form-invalid-feedback role="alert">
-            <template v-if="!$v.fromDate.pattern">
+            <template v-if="!v$.fromDate.pattern">
               {{ $t('global.form.invalidFormat') }}
             </template>
-            <template v-if="!$v.fromDate.maxDate">
+            <template v-if="!v$.fromDate.maxDate">
               {{ $t('global.form.dateMustBeBefore', { date: toDate }) }}
             </template>
           </b-form-invalid-feedback>
@@ -57,15 +57,15 @@
             id="input-to-date"
             v-model="toDate"
             placeholder="YYYY-MM-DD"
-            :state="getValidationState($v.toDate)"
+            :state="getValidationState(v$.toDate)"
             class="form-control-with-button"
-            @blur="$v.toDate.$touch()"
+            @blur="v$.toDate.$touch()"
           />
           <b-form-invalid-feedback role="alert">
-            <template v-if="!$v.toDate.pattern">
+            <template v-if="!v$.toDate.pattern">
               {{ $t('global.form.invalidFormat') }}
             </template>
-            <template v-if="!$v.toDate.minDate">
+            <template v-if="!v$.toDate.minDate">
               {{ $t('global.form.dateMustBeAfter', { date: fromDate }) }}
             </template>
           </b-form-invalid-feedback>
@@ -102,6 +102,7 @@
 import { helpers } from '@vuelidate/validators';
 import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
 import { useVuelidate } from '@vuelidate/core';
+import { useI18n } from 'vue-i18n';
 
 const isoDateRegex = /([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/;
 
@@ -115,6 +116,7 @@
   },
   data() {
     return {
+      $t: useI18n().t,
       fromDate: '',
       toDate: '',
       offsetToDate: '',
@@ -158,8 +160,8 @@
   },
   methods: {
     emitChange() {
-      if (this.$v.$invalid) return;
-      this.$v.$reset(); //reset to re-validate on blur
+      if (this.v$.$invalid) return;
+      this.v$.$reset(); //reset to re-validate on blur
       this.$emit('change', {
         fromDate: this.fromDate ? new Date(this.fromDate) : null,
         toDate: this.toDate ? new Date(this.offsetToDate) : null,
diff --git a/src/components/Global/TableFilter.vue b/src/components/Global/TableFilter.vue
index 8c4f509..2ed88bf 100644
--- a/src/components/Global/TableFilter.vue
+++ b/src/components/Global/TableFilter.vue
@@ -55,6 +55,7 @@
 
 <script>
 import IconFilter from '@carbon/icons-vue/es/settings--adjust/20';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'TableFilter',
@@ -73,6 +74,7 @@
   },
   data() {
     return {
+      $t: useI18n().t,
       dropdownVisible: false,
       tags: [],
     };
diff --git a/src/components/Global/TableRowAction.vue b/src/components/Global/TableRowAction.vue
index 549f1b5..2129713 100644
--- a/src/components/Global/TableRowAction.vue
+++ b/src/components/Global/TableRowAction.vue
@@ -56,6 +56,7 @@
 
 <script>
 import { omit } from 'lodash';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'TableRowAction',
@@ -97,6 +98,11 @@
       default: true,
     },
   },
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     dataForExport() {
       return JSON.stringify(omit(this.rowData, 'actions'));
diff --git a/src/components/Global/TableToolbar.vue b/src/components/Global/TableToolbar.vue
index 7c0f490..85d7c9c 100644
--- a/src/components/Global/TableToolbar.vue
+++ b/src/components/Global/TableToolbar.vue
@@ -31,6 +31,7 @@
 </template>
 
 <script>
+import { useI18n } from 'vue-i18n';
 export default {
   name: 'TableToolbar',
   props: {
@@ -53,6 +54,7 @@
   },
   data() {
     return {
+      $t: useI18n().t,
       isToolbarActive: false,
     };
   },
diff --git a/src/components/Global/TableToolbarExport.vue b/src/components/Global/TableToolbarExport.vue
index 69646ea..c678555 100644
--- a/src/components/Global/TableToolbarExport.vue
+++ b/src/components/Global/TableToolbarExport.vue
@@ -10,6 +10,7 @@
 </template>
 
 <script>
+import { useI18n } from 'vue-i18n';
 export default {
   props: {
     data: {
@@ -21,6 +22,11 @@
       default: 'data',
     },
   },
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     dataForExport() {
       return JSON.stringify(this.data);
diff --git a/src/i18n.js b/src/i18n.js
index 8135a40..434ec10 100644
--- a/src/i18n.js
+++ b/src/i18n.js
@@ -21,7 +21,7 @@
   silentFallbackWarn: true,
   messages: loadLocaleMessages(),
   globalInjection: false,
-  legacy: true,
+  legacy: false,
 });
 
 export default i18n;
diff --git a/src/layouts/AppLayout.vue b/src/layouts/AppLayout.vue
index fa9c212..4f24263 100644
--- a/src/layouts/AppLayout.vue
+++ b/src/layouts/AppLayout.vue
@@ -47,7 +47,7 @@
     this.$root.$on('refresh-application', () => this.refresh());
     setInterval(() => {
       if (!localStorage.getItem('storedUsername')) {
-        this.$eventBus.$consoleWindow.close();
+        this.$eventBus.$consoleWindow?.close();
         this.refresh();
       }
     }, 10000);
diff --git a/src/router/index.js b/src/router/index.js
index 4e962fe..22a3a8c 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,5 +1,4 @@
-import Vue from 'vue';
-import VueRouter from 'vue-router';
+import { createRouter, createWebHistory } from 'vue-router';
 
 //Do not change store or routes import.
 //Exact match alias set to support
@@ -7,9 +6,8 @@
 import store from '../store';
 import routes from './routes';
 
-Vue.use(VueRouter);
-const router = new VueRouter({
-  base: process.env.BASE_URL,
+const router = createRouter({
+  history: createWebHistory(process.env.BASE_URL),
   routes,
   linkExactActiveClass: 'nav-link--current',
   scrollBehavior() {
diff --git a/src/router/routes.js b/src/router/routes.js
index 8b3ff17..d9e799a 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -30,7 +30,7 @@
 import VirtualMedia from '@/views/Operations/VirtualMedia';
 import Power from '@/views/ResourceManagement/Power';
 import SnmpAlerts from '@/views/Settings/SnmpAlerts';
-//import { i18n } from '@/i18n';
+import i18n from '@/i18n';
 
 const roles = {
   administrator: 'Administrator',
@@ -49,7 +49,7 @@
         name: 'login',
         component: Login,
         meta: {
-          //title: i18n.$t('appPageTitle.login'),
+          title: i18n.global.t('appPageTitle.login'),
         },
       },
       {
@@ -57,7 +57,7 @@
         name: 'change-password',
         component: ChangePassword,
         meta: {
-          //title: i18n.$t('appPageTitle.changePassword'),
+          title: i18n.global.t('appPageTitle.changePassword'),
           requiresAuth: true,
         },
       },
@@ -75,7 +75,7 @@
         name: 'serial-over-lan-console',
         component: SerialOverLanConsole,
         meta: {
-          //title: i18n.t('appPageTitle.serialOverLan'),
+          title: i18n.global.t('appPageTitle.serialOverLan'),
         },
       },
       {
@@ -83,7 +83,7 @@
         name: 'kvm-console',
         component: KvmConsole,
         meta: {
-          //title: i18n.t('appPageTitle.kvm'),
+          title: i18n.global.t('appPageTitle.kvm'),
         },
       },
     ],
@@ -100,7 +100,7 @@
         name: 'overview',
         component: Overview,
         meta: {
-          //title: i18n.t('appPageTitle.overview'),
+          title: i18n.global.t('appPageTitle.overview'),
         },
       },
       {
@@ -108,7 +108,7 @@
         name: 'profile-settings',
         component: ProfileSettings,
         meta: {
-          //title: i18n.t('appPageTitle.profileSettings'),
+          title: i18n.global.t('appPageTitle.profileSettings'),
         },
       },
       {
@@ -116,7 +116,7 @@
         name: 'event-logs',
         component: EventLogs,
         meta: {
-          //title: i18n.t('appPageTitle.eventLogs'),
+          title: i18n.global.t('appPageTitle.eventLogs'),
         },
       },
       {
@@ -124,7 +124,7 @@
         name: 'post-code-logs',
         component: PostCodeLogs,
         meta: {
-          //title: i18n.t('appPageTitle.postCodeLogs'),
+          title: i18n.global.t('appPageTitle.postCodeLogs'),
         },
       },
       {
@@ -132,7 +132,7 @@
         name: 'inventory',
         component: Inventory,
         meta: {
-          //title: i18n.t('appPageTitle.inventory'),
+          title: i18n.global.t('appPageTitle.inventory'),
         },
       },
       {
@@ -140,7 +140,7 @@
         name: 'sensors',
         component: Sensors,
         meta: {
-          //title: i18n.t('appPageTitle.sensors'),
+          title: i18n.global.t('appPageTitle.sensors'),
         },
       },
       {
@@ -148,7 +148,7 @@
         name: 'sessions',
         component: Sessions,
         meta: {
-          //title: i18n.t('appPageTitle.sessions'),
+          title: i18n.global.t('appPageTitle.sessions'),
         },
       },
       {
@@ -156,7 +156,7 @@
         name: 'ldap',
         component: Ldap,
         meta: {
-          //title: i18n.t('appPageTitle.ldap'),
+          title: i18n.global.t('appPageTitle.ldap'),
         },
       },
       {
@@ -164,7 +164,7 @@
         name: 'user-management',
         component: UserManagement,
         meta: {
-          //title: i18n.t('appPageTitle.userManagement'),
+          title: i18n.global.t('appPageTitle.userManagement'),
         },
       },
       {
@@ -172,7 +172,7 @@
         name: 'policies',
         component: Policies,
         meta: {
-          //title: i18n.t('appPageTitle.policies'),
+          title: i18n.global.t('appPageTitle.policies'),
         },
       },
       {
@@ -180,7 +180,7 @@
         name: 'certificates',
         component: Certificates,
         meta: {
-          //title: i18n.t('appPageTitle.certificates'),
+          title: i18n.global.t('appPageTitle.certificates'),
         },
       },
       {
@@ -188,7 +188,7 @@
         name: 'date-time',
         component: DateTime,
         meta: {
-          //title: i18n.t('appPageTitle.dateTime'),
+          title: i18n.global.t('appPageTitle.dateTime'),
         },
       },
       {
@@ -196,7 +196,7 @@
         name: 'snmp-alerts',
         component: SnmpAlerts,
         meta: {
-          //title: i18n.t('appPageTitle.snmpAlerts'),
+          title: i18n.global.t('appPageTitle.snmpAlerts'),
         },
       },
       {
@@ -204,7 +204,7 @@
         name: 'factory-reset',
         component: FactoryReset,
         meta: {
-          //title: i18n.t('appPageTitle.factoryReset'),
+          title: i18n.global.t('appPageTitle.factoryReset'),
         },
       },
       {
@@ -212,7 +212,7 @@
         name: 'key-clear',
         component: KeyClear,
         meta: {
-          //title: i18n.t('appPageTitle.keyClear'),
+          title: i18n.global.t('appPageTitle.keyClear'),
         },
       },
       {
@@ -220,7 +220,7 @@
         name: 'kvm',
         component: Kvm,
         meta: {
-          //title: i18n.t('appPageTitle.kvm'),
+          title: i18n.global.t('appPageTitle.kvm'),
         },
       },
       {
@@ -228,7 +228,7 @@
         name: 'firmware',
         component: Firmware,
         meta: {
-          //title: i18n.t('appPageTitle.firmware'),
+          title: i18n.global.t('appPageTitle.firmware'),
         },
       },
       {
@@ -236,7 +236,7 @@
         name: 'network',
         component: Network,
         meta: {
-          //title: i18n.t('appPageTitle.network'),
+          title: i18n.global.t('appPageTitle.network'),
         },
       },
       {
@@ -244,7 +244,7 @@
         name: 'power-restore-policy',
         component: PowerRestorePolicy,
         meta: {
-          //title: i18n.t('appPageTitle.powerRestorePolicy'),
+          title: i18n.global.t('appPageTitle.powerRestorePolicy'),
         },
       },
       {
@@ -252,7 +252,7 @@
         name: 'power',
         component: Power,
         meta: {
-          //title: i18n.t('appPageTitle.power'),
+          title: i18n.global.t('appPageTitle.power'),
         },
       },
       {
@@ -260,7 +260,7 @@
         name: 'reboot-bmc',
         component: RebootBmc,
         meta: {
-          //title: i18n.t('appPageTitle.rebootBmc'),
+          title: i18n.global.t('appPageTitle.rebootBmc'),
         },
       },
       {
@@ -268,7 +268,7 @@
         name: 'serial-over-lan',
         component: SerialOverLan,
         meta: {
-          //title: i18n.t('appPageTitle.serialOverLan'),
+          title: i18n.global.t('appPageTitle.serialOverLan'),
           exclusiveToRoles: [roles.administrator],
         },
       },
@@ -277,7 +277,7 @@
         name: 'server-power-operations',
         component: ServerPowerOperations,
         meta: {
-          //title: i18n.t('appPageTitle.serverPowerOperations'),
+          title: i18n.global.t('appPageTitle.serverPowerOperations'),
         },
       },
       {
@@ -285,7 +285,7 @@
         name: 'virtual-media',
         component: VirtualMedia,
         meta: {
-          //title: i18n.t('appPageTitle.virtualMedia'),
+          title: i18n.global.t('appPageTitle.virtualMedia'),
           exclusiveToRoles: [roles.administrator],
         },
       },
@@ -294,7 +294,7 @@
         name: 'page-not-found',
         component: PageNotFound,
         meta: {
-          //title: i18n.t('appPageTitle.pageNotFound'),
+          title: i18n.global.t('appPageTitle.pageNotFound'),
         },
       },
     ],
diff --git a/src/views/Login/Login.vue b/src/views/Login/Login.vue
index aaf1128..213dd48 100644
--- a/src/views/Login/Login.vue
+++ b/src/views/Login/Login.vue
@@ -8,7 +8,7 @@
     <b-form-group label-for="language" :label="$t('pageLogin.language')">
       <b-form-select
         id="language"
-        v-model="$i18n.locale"
+        v-model="userLocale"
         :options="languages"
         data-test-id="login-select-language"
       ></b-form-select>
@@ -67,8 +67,8 @@
 import { required } from '@vuelidate/validators';
 import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
 import { useVuelidate } from '@vuelidate/core';
-
-import i18n from '@/i18n';
+import { ref, watch } from 'vue';
+import { useI18n } from 'vue-i18n';
 import Alert from '@/components/Global/Alert';
 import InputPasswordToggle from '@/components/Global/InputPasswordToggle';
 
@@ -77,12 +77,20 @@
   components: { Alert, InputPasswordToggle },
   mixins: [VuelidateMixin],
   setup() {
+    const { locale } = useI18n();
+    const userLocale = ref(locale.value);
+    watch(userLocale, (newLocale) => {
+      locale.value = newLocale;
+      localStorage.setItem('storedLanguage', newLocale);
+    });
     return {
+      userLocale,
       v$: useVuelidate(),
     };
   },
   data() {
     return {
+      $t: useI18n().t,
       userInfo: {
         username: null,
         password: null,
@@ -125,10 +133,10 @@
       this.$store
         .dispatch('authentication/login', { username, password })
         .then(() => {
-          localStorage.setItem('storedLanguage', i18n.locale);
+          localStorage.setItem('storedLanguage', this.userLocale);
           localStorage.setItem('storedUsername', username);
           this.$store.commit('global/setUsername', username);
-          this.$store.commit('global/setLanguagePreference', i18n.locale);
+          this.$store.commit('global/setLanguagePreference', this.userLocale);
           return this.$store.dispatch('authentication/getUserInfo', username);
         })
         .then(({ PasswordChangeRequired }) => {
diff --git a/src/views/Logs/EventLogs/EventLogs.vue b/src/views/Logs/EventLogs/EventLogs.vue
index f52e211..c906fc6 100644
--- a/src/views/Logs/EventLogs/EventLogs.vue
+++ b/src/views/Logs/EventLogs/EventLogs.vue
@@ -282,6 +282,8 @@
 import SearchFilterMixin, {
   searchFilter,
 } from '@/components/Mixins/SearchFilterMixin';
+import { useI18n } from 'vue-i18n';
+import i18n from '@/i18n';
 
 export default {
   components: {
@@ -319,6 +321,7 @@
   },
   data() {
     return {
+      $t: useI18n().t,
       isBusy: true,
       fields: [
         {
@@ -332,31 +335,31 @@
         },
         {
           key: 'id',
-          label: this.$t('pageEventLogs.table.id'),
+          label: i18n.global.t('pageEventLogs.table.id'),
           sortable: true,
         },
         {
           key: 'severity',
-          label: this.$t('pageEventLogs.table.severity'),
+          label: i18n.global.t('pageEventLogs.table.severity'),
           sortable: true,
           tdClass: 'text-nowrap',
         },
         {
           key: 'date',
-          label: this.$t('pageEventLogs.table.date'),
+          label: i18n.global.t('pageEventLogs.table.date'),
           sortable: true,
           tdClass: 'text-nowrap',
         },
         {
           key: 'description',
-          label: this.$t('pageEventLogs.table.description'),
+          label: i18n.global.t('pageEventLogs.table.description'),
           tdClass: 'text-break',
         },
         process.env.VUE_APP_EVENT_LOGS_TOGGLE_BUTTON_DISABLED === 'true'
           ? {}
           : {
               key: 'status',
-              label: this.$t('pageEventLogs.table.status'),
+              label: i18n.global.t('pageEventLogs.table.status'),
             },
         {
           key: 'actions',
@@ -370,19 +373,19 @@
           ? [
               {
                 key: 'severity',
-                label: this.$t('pageEventLogs.table.severity'),
+                label: i18n.global.t('pageEventLogs.table.severity'),
                 values: ['OK', 'Warning', 'Critical'],
               },
             ]
           : [
               {
                 key: 'severity',
-                label: this.$t('pageEventLogs.table.severity'),
+                label: i18n.global.t('pageEventLogs.table.severity'),
                 values: ['OK', 'Warning', 'Critical'],
               },
               {
                 key: 'filterByStatus',
-                label: this.$t('pageEventLogs.table.status'),
+                label: i18n.global.t('pageEventLogs.table.status'),
                 values: ['Resolved', 'Unresolved'],
               },
             ],
@@ -394,7 +397,7 @@
           : [
               {
                 value: 'delete',
-                label: this.$t('global.action.delete'),
+                label: i18n.global.t('global.action.delete'),
               },
             ],
       currentPage: currentPage,
@@ -430,17 +433,17 @@
             ? [
                 {
                   value: 'export',
-                  title: this.$t('global.action.export'),
+                  title: i18n.global.t('global.action.export'),
                 },
               ]
             : [
                 {
                   value: 'export',
-                  title: this.$t('global.action.export'),
+                  title: i18n.global.t('global.action.export'),
                 },
                 {
                   value: 'delete',
-                  title: this.$t('global.action.delete'),
+                  title: i18n.global.t('global.action.delete'),
                 },
               ],
         };
@@ -484,11 +487,11 @@
     },
     deleteAllLogs() {
       this.$bvModal
-        .msgBoxConfirm(this.$t('pageEventLogs.modal.deleteAllMessage'), {
-          title: this.$t('pageEventLogs.modal.deleteAllTitle'),
-          okTitle: this.$t('global.action.delete'),
+        .msgBoxConfirm(i18n.global.t('pageEventLogs.modal.deleteAllMessage'), {
+          title: i18n.global.t('pageEventLogs.modal.deleteAllTitle'),
+          okTitle: i18n.global.t('global.action.delete'),
           okVariant: 'danger',
-          cancelTitle: this.$t('global.action.cancel'),
+          cancelTitle: i18n.global.t('global.action.cancel'),
           autoFocusButton: 'cancel',
         })
         .then((deleteConfirmed) => {
@@ -534,8 +537,8 @@
         this.$bvModal
           .msgBoxConfirm(this.$tc('pageEventLogs.modal.deleteMessage'), {
             title: this.$tc('pageEventLogs.modal.deleteTitle'),
-            okTitle: this.$t('global.action.delete'),
-            cancelTitle: this.$t('global.action.cancel'),
+            okTitle: i18n.global.t('global.action.delete'),
+            cancelTitle: i18n.global.t('global.action.cancel'),
             autoFocusButton: 'ok',
           })
           .then((deleteConfirmed) => {
@@ -557,8 +560,8 @@
                 'pageEventLogs.modal.deleteTitle',
                 this.selectedRows.length,
               ),
-              okTitle: this.$t('global.action.delete'),
-              cancelTitle: this.$t('global.action.cancel'),
+              okTitle: i18n.global.t('global.action.delete'),
+              cancelTitle: i18n.global.t('global.action.cancel'),
               autoFocusButton: 'ok',
             },
           )
diff --git a/src/views/Overview/Overview.vue b/src/views/Overview/Overview.vue
index d999be4..2bf4205 100644
--- a/src/views/Overview/Overview.vue
+++ b/src/views/Overview/Overview.vue
@@ -37,6 +37,7 @@
 import OverviewServer from './OverviewServer';
 import PageSection from '@/components/Global/PageSection';
 import PageTitle from '@/components/Global/PageTitle';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'Overview',
@@ -55,6 +56,7 @@
   mixins: [LoadingBarMixin],
   data() {
     return {
+      $t: useI18n().t,
       showDumps: process.env.VUE_APP_ENV_NAME === 'ibm',
     };
   },
diff --git a/src/views/Overview/OverviewCard.vue b/src/views/Overview/OverviewCard.vue
index aa5697d..342bf98 100644
--- a/src/views/Overview/OverviewCard.vue
+++ b/src/views/Overview/OverviewCard.vue
@@ -23,6 +23,7 @@
 </template>
 
 <script>
+import { useI18n } from 'vue-i18n';
 export default {
   name: 'OverviewCard',
   props: {
@@ -56,6 +57,11 @@
       default: '/',
     },
   },
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     dataForExport() {
       return JSON.stringify(this.data);
diff --git a/src/views/Overview/OverviewDumps.vue b/src/views/Overview/OverviewDumps.vue
index a2ae4e4..588363a 100644
--- a/src/views/Overview/OverviewDumps.vue
+++ b/src/views/Overview/OverviewDumps.vue
@@ -21,6 +21,7 @@
 <script>
 import OverviewCard from './OverviewCard';
 import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'Dumps',
@@ -28,6 +29,11 @@
     OverviewCard,
   },
   mixins: [DataFormatterMixin],
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     dumps() {
       return this.$store.getters['dumps/allDumps'];
diff --git a/src/views/Overview/OverviewEvents.vue b/src/views/Overview/OverviewEvents.vue
index 4d85dbd..0056af4 100644
--- a/src/views/Overview/OverviewEvents.vue
+++ b/src/views/Overview/OverviewEvents.vue
@@ -34,11 +34,17 @@
 import OverviewCard from './OverviewCard';
 import StatusIcon from '@/components/Global/StatusIcon';
 import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'Events',
   components: { OverviewCard, StatusIcon },
   mixins: [DataFormatterMixin],
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     eventLogData() {
       return this.$store.getters['eventLog/allEvents'];
diff --git a/src/views/Overview/OverviewFirmware.vue b/src/views/Overview/OverviewFirmware.vue
index c2c7f4a..0be920f 100644
--- a/src/views/Overview/OverviewFirmware.vue
+++ b/src/views/Overview/OverviewFirmware.vue
@@ -26,6 +26,7 @@
 import OverviewCard from './OverviewCard';
 import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
 import { mapState } from 'vuex';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'Firmware',
@@ -33,6 +34,11 @@
     OverviewCard,
   },
   mixins: [DataFormatterMixin],
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     ...mapState({
       server: (state) => state.system.systems[0],
diff --git a/src/views/Overview/OverviewInventory.vue b/src/views/Overview/OverviewInventory.vue
index 1da5685..4d923e1 100644
--- a/src/views/Overview/OverviewInventory.vue
+++ b/src/views/Overview/OverviewInventory.vue
@@ -30,6 +30,7 @@
 <script>
 import OverviewCard from './OverviewCard';
 import BVToastMixin from '@/components/Mixins/BVToastMixin';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'Inventory',
@@ -37,6 +38,11 @@
     OverviewCard,
   },
   mixins: [BVToastMixin],
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     systems() {
       let systemData = this.$store.getters['system/systems'][0];
diff --git a/src/views/Overview/OverviewNetwork.vue b/src/views/Overview/OverviewNetwork.vue
index f25c7e0..c2a7693 100644
--- a/src/views/Overview/OverviewNetwork.vue
+++ b/src/views/Overview/OverviewNetwork.vue
@@ -50,6 +50,7 @@
 <script>
 import OverviewCard from './OverviewCard';
 import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'Network',
@@ -57,6 +58,11 @@
     OverviewCard,
   },
   mixins: [DataFormatterMixin],
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     network() {
       return this.$store.getters['network/globalNetworkSettings'][0];
diff --git a/src/views/Overview/OverviewPower.vue b/src/views/Overview/OverviewPower.vue
index 0d84c76..74a737e 100644
--- a/src/views/Overview/OverviewPower.vue
+++ b/src/views/Overview/OverviewPower.vue
@@ -26,6 +26,7 @@
 import OverviewCard from './OverviewCard';
 import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
 import { mapGetters } from 'vuex';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'Power',
@@ -33,6 +34,11 @@
     OverviewCard,
   },
   mixins: [DataFormatterMixin],
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     ...mapGetters({
       powerCapValue: 'powerControl/powerCapValue',
diff --git a/src/views/Overview/OverviewQuickLinks.vue b/src/views/Overview/OverviewQuickLinks.vue
index 2ab7654..ef9ab12 100644
--- a/src/views/Overview/OverviewQuickLinks.vue
+++ b/src/views/Overview/OverviewQuickLinks.vue
@@ -28,6 +28,7 @@
 <script>
 import ArrowRight16 from '@carbon/icons-vue/es/arrow--right/16';
 import BVToastMixin from '@/components/Mixins/BVToastMixin';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'QuickLinks',
@@ -35,6 +36,11 @@
     IconArrowRight: ArrowRight16,
   },
   mixins: [BVToastMixin],
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     bmcTime() {
       return this.$store.getters['global/bmcTime'];
diff --git a/src/views/Overview/OverviewServer.vue b/src/views/Overview/OverviewServer.vue
index 8fc16d1..fe0e41d 100644
--- a/src/views/Overview/OverviewServer.vue
+++ b/src/views/Overview/OverviewServer.vue
@@ -26,6 +26,7 @@
 import OverviewCard from './OverviewCard';
 import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
 import { mapState } from 'vuex';
+import { useI18n } from 'vue-i18n';
 
 export default {
   name: 'Server',
@@ -33,6 +34,11 @@
     OverviewCard,
   },
   mixins: [DataFormatterMixin],
+  data() {
+    return {
+      $t: useI18n().t,
+    };
+  },
   computed: {
     ...mapState({
       server: (state) => state.system.systems[0],