Browse Source

fix(nc-gui): lazy load languages for initial load perf

pull/3602/head
braks 2 years ago
parent
commit
e31e1ad182
  1. 25
      packages/nc-gui/components/general/language/Menu.vue
  2. 4
      packages/nc-gui/composables/useGlobal/state.ts
  3. 6
      packages/nc-gui/lib/types.ts
  4. 8
      packages/nc-gui/nuxt-shim.d.ts
  5. 9
      packages/nc-gui/nuxt.config.ts
  6. 194
      packages/nc-gui/package-lock.json
  7. 2
      packages/nc-gui/package.json
  8. 1
      packages/nc-gui/pages/signin.vue
  9. 65
      packages/nc-gui/plugins/a.i18n.ts
  10. 9
      packages/nc-gui/plugins/state.ts

25
packages/nc-gui/components/general/language/Menu.vue

@ -1,14 +1,15 @@
<script lang="ts" setup> <script lang="ts" setup>
import { Language } from '~/lib' import { Language } from '~/lib'
import { onMounted, useGlobal, useI18n, useNuxtApp } from '#imports' import { onMounted, useGlobal, useI18n, useNuxtApp } from '#imports'
import { loadLocaleMessages } from '~/plugins/a.i18n'
const { $e } = useNuxtApp() const { $e, vueApp } = useNuxtApp()
const { lang: currentLang } = useGlobal() const { lang: currentLang } = useGlobal()
const { availableLocales = ['en'], locale } = useI18n() const { availableLocales = ['en'], locale } = useI18n()
const languages = $computed(() => availableLocales.sort()) const languages = $computed(() => Object.entries(Language).sort())
const isRtlLang = $computed(() => ['fa'].includes(currentLang.value)) const isRtlLang = $computed(() => ['fa'].includes(currentLang.value))
@ -21,7 +22,11 @@ function applyDirection() {
document.body.style.direction = targetDirection document.body.style.direction = targetDirection
} }
function changeLanguage(lang: string) { async function changeLanguage(lang: string) {
if (!availableLocales.includes(lang)) {
await loadLocaleMessages(vueApp.i18n, lang)
}
currentLang.value = lang currentLang.value = lang
locale.value = lang locale.value = lang
@ -37,15 +42,15 @@ onMounted(() => {
<template> <template>
<a-menu-item <a-menu-item
v-for="lang of languages" v-for="[key, lang] of languages"
:key="lang" :key="key"
:class="lang === locale ? '!bg-primary bg-opacity-10 text-primary' : ''" :class="key === locale ? '!bg-primary bg-opacity-10 text-primary' : ''"
class="group" class="group"
:value="lang" :value="key"
@click="changeLanguage(lang)" @click="changeLanguage(key)"
> >
<div :class="lang === locale ? '!font-semibold !text-primary' : ''" class="nc-project-menu-item capitalize"> <div :class="key === locale ? '!font-semibold !text-primary' : ''" class="nc-project-menu-item capitalize">
{{ Language[lang] || lang }} {{ Language[key] || lang }}
</div> </div>
</a-menu-item> </a-menu-item>

4
packages/nc-gui/composables/useGlobal/state.ts

@ -22,7 +22,7 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
/** /**
* Set initial language based on browser settings. * Set initial language based on browser settings.
* If the user has not set a preferred language, we fallback to 'en'. * If the user has not set a preferred language, we fall back to 'en'.
* If the user has set a preferred language, we try to find a matching locale in the available locales. * If the user has set a preferred language, we try to find a matching locale in the available locales.
*/ */
const preferredLanguage = preferredLanguages.reduce((locale, language) => { const preferredLanguage = preferredLanguages.reduce((locale, language) => {
@ -30,7 +30,7 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
const [lang, code] = language.split(/[_-]/) const [lang, code] = language.split(/[_-]/)
/** find all locales that match the language */ /** find all locales that match the language */
let availableLocales = i18n.availableLocales.filter((locale) => locale.startsWith(lang)) let availableLocales = i18n.global.availableLocales.filter((locale) => locale.startsWith(lang))
/** If we can match more than one locale, we check if the code of the language matches as well */ /** If we can match more than one locale, we check if the code of the language matches as well */
if (availableLocales.length > 1) { if (availableLocales.length > 1) {

6
packages/nc-gui/lib/types.ts

@ -1,5 +1,7 @@
import type { FilterType } from 'nocodb-sdk' import type { FilterType } from 'nocodb-sdk'
import type { Role } from './enums' import type { I18n } from 'vue-i18n'
import type { Language, Role } from './enums'
export interface User { export interface User {
id: string id: string
email: string email: string
@ -32,3 +34,5 @@ export interface Field {
export type Roles = Record<Role, boolean> export type Roles = Record<Role, boolean>
export type Filter = FilterType & { status?: 'update' | 'delete' | 'create'; parentId?: string; readOnly?: boolean } export type Filter = FilterType & { status?: 'update' | 'delete' | 'create'; parentId?: string; readOnly?: boolean }
export type NocoI18n = I18n<{}, unknown, unknown, string, false>

8
packages/nc-gui/nuxt-shim.d.ts vendored

@ -1,10 +1,6 @@
import type { Api as BaseAPI } from 'nocodb-sdk' import type { Api as BaseAPI } from 'nocodb-sdk'
import type { I18n } from 'vue-i18n'
import type { UseGlobalReturn } from './composables/useGlobal/types' import type { UseGlobalReturn } from './composables/useGlobal/types'
import type { NocoI18n } from './lib'
import type en from './lang/en.json'
type MessageSchema = typeof en
declare module '#app/nuxt' { declare module '#app/nuxt' {
interface NuxtApp { interface NuxtApp {
@ -21,7 +17,7 @@ declare module '#app/nuxt' {
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
interface App { interface App {
i18n: I18n<MessageSchema, unknown, unknown, false>['global'] i18n: NocoI18n
} }
} }

9
packages/nc-gui/nuxt.config.ts

@ -1,4 +1,5 @@
import path from 'path' import { fileURLToPath } from 'node:url'
import { dirname, resolve } from 'node:path'
import { defineNuxtConfig } from 'nuxt' import { defineNuxtConfig } from 'nuxt'
import vueI18n from '@intlify/vite-plugin-vue-i18n' import vueI18n from '@intlify/vite-plugin-vue-i18n'
import Icons from 'unplugin-icons/vite' import Icons from 'unplugin-icons/vite'
@ -13,9 +14,7 @@ export default defineNuxtConfig({
modules: ['@vueuse/nuxt', 'nuxt-windicss', '@nuxt/image-edge'], modules: ['@vueuse/nuxt', 'nuxt-windicss', '@nuxt/image-edge'],
ssr: false, ssr: false,
app: {
cdnURL: process.env.NODE_ENV === 'production' ? '.' : undefined,
},
css: [ css: [
'virtual:windi.css', 'virtual:windi.css',
'virtual:windi-devtools', 'virtual:windi-devtools',
@ -54,7 +53,7 @@ export default defineNuxtConfig({
}, },
plugins: [ plugins: [
vueI18n({ vueI18n({
include: path.resolve(__dirname, './lang'), include: [resolve(dirname(fileURLToPath(import.meta.url)), './lang/**')],
runtimeOnly: false, runtimeOnly: false,
}), }),
Icons({ Icons({

194
packages/nc-gui/package-lock.json generated

@ -29,7 +29,7 @@
"unique-names-generator": "^4.7.1", "unique-names-generator": "^4.7.1",
"vue-dompurify-html": "^3.0.0", "vue-dompurify-html": "^3.0.0",
"vue-github-button": "^3.0.3", "vue-github-button": "^3.0.3",
"vue-i18n": "^9.1.10", "vue-i18n": "^9.2.2",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"xlsx": "^0.17.3" "xlsx": "^0.17.3"
}, },
@ -79,7 +79,7 @@
} }
}, },
"../nocodb-sdk": { "../nocodb-sdk": {
"version": "0.96.3", "version": "0.96.4",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -1291,43 +1291,40 @@
} }
}, },
"node_modules/@intlify/core-base": { "node_modules/@intlify/core-base": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.1.10.tgz", "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.2.2.tgz",
"integrity": "sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==", "integrity": "sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==",
"dependencies": { "dependencies": {
"@intlify/devtools-if": "9.1.10", "@intlify/devtools-if": "9.2.2",
"@intlify/message-compiler": "9.1.10", "@intlify/message-compiler": "9.2.2",
"@intlify/message-resolver": "9.1.10", "@intlify/shared": "9.2.2",
"@intlify/runtime": "9.1.10", "@intlify/vue-devtools": "9.2.2"
"@intlify/shared": "9.1.10",
"@intlify/vue-devtools": "9.1.10"
}, },
"engines": { "engines": {
"node": ">= 10" "node": ">= 14"
} }
}, },
"node_modules/@intlify/devtools-if": { "node_modules/@intlify/devtools-if": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.1.10.tgz", "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.2.2.tgz",
"integrity": "sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==", "integrity": "sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==",
"dependencies": { "dependencies": {
"@intlify/shared": "9.1.10" "@intlify/shared": "9.2.2"
}, },
"engines": { "engines": {
"node": ">= 10" "node": ">= 14"
} }
}, },
"node_modules/@intlify/message-compiler": { "node_modules/@intlify/message-compiler": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.1.10.tgz", "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.2.2.tgz",
"integrity": "sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==", "integrity": "sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==",
"dependencies": { "dependencies": {
"@intlify/message-resolver": "9.1.10", "@intlify/shared": "9.2.2",
"@intlify/shared": "9.1.10",
"source-map": "0.6.1" "source-map": "0.6.1"
}, },
"engines": { "engines": {
"node": ">= 10" "node": ">= 14"
} }
}, },
"node_modules/@intlify/message-compiler/node_modules/source-map": { "node_modules/@intlify/message-compiler/node_modules/source-map": {
@ -1338,33 +1335,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/@intlify/message-resolver": {
"version": "9.1.10",
"resolved": "https://registry.npmjs.org/@intlify/message-resolver/-/message-resolver-9.1.10.tgz",
"integrity": "sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w==",
"engines": {
"node": ">= 10"
}
},
"node_modules/@intlify/runtime": {
"version": "9.1.10",
"resolved": "https://registry.npmjs.org/@intlify/runtime/-/runtime-9.1.10.tgz",
"integrity": "sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==",
"dependencies": {
"@intlify/message-compiler": "9.1.10",
"@intlify/message-resolver": "9.1.10",
"@intlify/shared": "9.1.10"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/@intlify/shared": { "node_modules/@intlify/shared": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.10.tgz", "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.2.tgz",
"integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==", "integrity": "sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==",
"engines": { "engines": {
"node": ">= 10" "node": ">= 14"
} }
}, },
"node_modules/@intlify/vite-plugin-vue-i18n": { "node_modules/@intlify/vite-plugin-vue-i18n": {
@ -1410,16 +1386,15 @@
} }
}, },
"node_modules/@intlify/vue-devtools": { "node_modules/@intlify/vue-devtools": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz", "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.2.2.tgz",
"integrity": "sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==", "integrity": "sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==",
"dependencies": { "dependencies": {
"@intlify/message-resolver": "9.1.10", "@intlify/core-base": "9.2.2",
"@intlify/runtime": "9.1.10", "@intlify/shared": "9.2.2"
"@intlify/shared": "9.1.10"
}, },
"engines": { "engines": {
"node": ">= 10" "node": ">= 14"
} }
}, },
"node_modules/@ioredis/commands": { "node_modules/@ioredis/commands": {
@ -2877,9 +2852,9 @@
} }
}, },
"node_modules/@vue/devtools-api": { "node_modules/@vue/devtools-api": {
"version": "6.1.4", "version": "6.2.1",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.1.tgz",
"integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" "integrity": "sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ=="
}, },
"node_modules/@vue/reactivity": { "node_modules/@vue/reactivity": {
"version": "3.2.37", "version": "3.2.37",
@ -14654,17 +14629,17 @@
} }
}, },
"node_modules/vue-i18n": { "node_modules/vue-i18n": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz", "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.2.2.tgz",
"integrity": "sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==", "integrity": "sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==",
"dependencies": { "dependencies": {
"@intlify/core-base": "9.1.10", "@intlify/core-base": "9.2.2",
"@intlify/shared": "9.1.10", "@intlify/shared": "9.2.2",
"@intlify/vue-devtools": "9.1.10", "@intlify/vue-devtools": "9.2.2",
"@vue/devtools-api": "^6.0.0-beta.7" "@vue/devtools-api": "^6.2.1"
}, },
"engines": { "engines": {
"node": ">= 10" "node": ">= 14"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^3.0.0" "vue": "^3.0.0"
@ -16184,33 +16159,30 @@
} }
}, },
"@intlify/core-base": { "@intlify/core-base": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.1.10.tgz", "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.2.2.tgz",
"integrity": "sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==", "integrity": "sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==",
"requires": { "requires": {
"@intlify/devtools-if": "9.1.10", "@intlify/devtools-if": "9.2.2",
"@intlify/message-compiler": "9.1.10", "@intlify/message-compiler": "9.2.2",
"@intlify/message-resolver": "9.1.10", "@intlify/shared": "9.2.2",
"@intlify/runtime": "9.1.10", "@intlify/vue-devtools": "9.2.2"
"@intlify/shared": "9.1.10",
"@intlify/vue-devtools": "9.1.10"
} }
}, },
"@intlify/devtools-if": { "@intlify/devtools-if": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.1.10.tgz", "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.2.2.tgz",
"integrity": "sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==", "integrity": "sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==",
"requires": { "requires": {
"@intlify/shared": "9.1.10" "@intlify/shared": "9.2.2"
} }
}, },
"@intlify/message-compiler": { "@intlify/message-compiler": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.1.10.tgz", "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.2.2.tgz",
"integrity": "sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==", "integrity": "sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==",
"requires": { "requires": {
"@intlify/message-resolver": "9.1.10", "@intlify/shared": "9.2.2",
"@intlify/shared": "9.1.10",
"source-map": "0.6.1" "source-map": "0.6.1"
}, },
"dependencies": { "dependencies": {
@ -16221,25 +16193,10 @@
} }
} }
}, },
"@intlify/message-resolver": {
"version": "9.1.10",
"resolved": "https://registry.npmjs.org/@intlify/message-resolver/-/message-resolver-9.1.10.tgz",
"integrity": "sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w=="
},
"@intlify/runtime": {
"version": "9.1.10",
"resolved": "https://registry.npmjs.org/@intlify/runtime/-/runtime-9.1.10.tgz",
"integrity": "sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==",
"requires": {
"@intlify/message-compiler": "9.1.10",
"@intlify/message-resolver": "9.1.10",
"@intlify/shared": "9.1.10"
}
},
"@intlify/shared": { "@intlify/shared": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.10.tgz", "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.2.tgz",
"integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==" "integrity": "sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q=="
}, },
"@intlify/vite-plugin-vue-i18n": { "@intlify/vite-plugin-vue-i18n": {
"version": "6.0.1", "version": "6.0.1",
@ -16264,13 +16221,12 @@
} }
}, },
"@intlify/vue-devtools": { "@intlify/vue-devtools": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz", "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.2.2.tgz",
"integrity": "sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==", "integrity": "sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==",
"requires": { "requires": {
"@intlify/message-resolver": "9.1.10", "@intlify/core-base": "9.2.2",
"@intlify/runtime": "9.1.10", "@intlify/shared": "9.2.2"
"@intlify/shared": "9.1.10"
} }
}, },
"@ioredis/commands": { "@ioredis/commands": {
@ -17429,9 +17385,9 @@
} }
}, },
"@vue/devtools-api": { "@vue/devtools-api": {
"version": "6.1.4", "version": "6.2.1",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.1.tgz",
"integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" "integrity": "sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ=="
}, },
"@vue/reactivity": { "@vue/reactivity": {
"version": "3.2.37", "version": "3.2.37",
@ -26119,14 +26075,14 @@
} }
}, },
"vue-i18n": { "vue-i18n": {
"version": "9.1.10", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz", "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.2.2.tgz",
"integrity": "sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==", "integrity": "sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==",
"requires": { "requires": {
"@intlify/core-base": "9.1.10", "@intlify/core-base": "9.2.2",
"@intlify/shared": "9.1.10", "@intlify/shared": "9.2.2",
"@intlify/vue-devtools": "9.1.10", "@intlify/vue-devtools": "9.2.2",
"@vue/devtools-api": "^6.0.0-beta.7" "@vue/devtools-api": "^6.2.1"
} }
}, },
"vue-router": { "vue-router": {

2
packages/nc-gui/package.json

@ -37,7 +37,7 @@
"unique-names-generator": "^4.7.1", "unique-names-generator": "^4.7.1",
"vue-dompurify-html": "^3.0.0", "vue-dompurify-html": "^3.0.0",
"vue-github-button": "^3.0.3", "vue-github-button": "^3.0.3",
"vue-i18n": "^9.1.10", "vue-i18n": "^9.2.2",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"xlsx": "^0.17.3" "xlsx": "^0.17.3"
}, },

1
packages/nc-gui/pages/signin.vue

@ -105,7 +105,6 @@ function resetError() {
<a-form-item :label="$t('labels.password')" name="password" :rules="formRules.password"> <a-form-item :label="$t('labels.password')" name="password" :rules="formRules.password">
<a-input-password <a-input-password
v-model:value="form.password" v-model:value="form.password"
size="large"
class="password" class="password"
:placeholder="$t('msg.info.signUp.enterPassword')" :placeholder="$t('msg.info.signUp.enterPassword')"
@focus="resetError" @focus="resetError"

65
packages/nc-gui/plugins/a.i18n.ts

@ -1,9 +1,11 @@
import { defineNuxtPlugin } from 'nuxt/app' import { defineNuxtPlugin } from 'nuxt/app'
import { createI18n } from 'vue-i18n' import { createI18n } from 'vue-i18n'
import { nextTick } from 'vue'
import type { NocoI18n } from '~/lib'
let i18n: ReturnType<typeof createI18n> let globalI18n: NocoI18n
export const createI18nPlugin = async () => export const createI18nPlugin = async (): Promise<NocoI18n> =>
createI18n({ createI18n({
locale: 'en', // Set the initial locale locale: 'en', // Set the initial locale
@ -12,49 +14,28 @@ export const createI18nPlugin = async () =>
legacy: false, // disable legacy API (we use the composition API and inject utilities) legacy: false, // disable legacy API (we use the composition API and inject utilities)
globalInjection: true, // enable global injection, so all utilities are injected into all components globalInjection: true, // enable global injection, so all utilities are injected into all components
// Associate each locale to a content file
messages: {
ar: await import('~/lang/ar.json'),
bn_IN: await import('~/lang/bn_IN.json'),
da: await import('~/lang/da.json'),
de: await import('~/lang/de.json'),
en: await import('~/lang/en.json'),
es: await import('~/lang/es.json'),
fa: await import('~/lang/fa.json'),
fi: await import('~/lang/fi.json'),
fr: await import('~/lang/fr.json'),
he: await import('~/lang/he.json'),
hi: await import('~/lang/hi.json'),
hr: await import('~/lang/hr.json'),
id: await import('~/lang/id.json'),
it: await import('~/lang/it.json'),
ja: await import('~/lang/ja.json'),
ko: await import('~/lang/ko.json'),
lv: await import('~/lang/lv.json'),
nl: await import('~/lang/nl.json'),
no: await import('~/lang/no.json'),
pl: await import('~/lang/pl.json'),
pt: await import('~/lang/pt.json'),
pt_BR: await import('~/lang/pt_BR.json'),
ru: await import('~/lang/ru.json'),
sv: await import('~/lang/sv.json'),
sl: await import('~/lang/sl.json'),
th: await import('~/lang/th.json'),
tr: await import('~/lang/tr.json'),
uk: await import('~/lang/uk.json'),
vi: await import('~/lang/vi.json'),
zh_Hans: await import('~/lang/zh-Hans.json'),
zh_Hant: await import('~/lang/zh-Hant.json'),
},
}) })
export const getI18n = () => globalI18n
export function setI18nLanguage(i18n: NocoI18n, locale: string): void {
i18n.global.locale.value = locale
}
export async function loadLocaleMessages(i18n: NocoI18n, locale: string) {
// load locale messages with dynamic import
const messages = await import(`../lang/${locale}.json`)
// set locale and locale message
i18n.global.setLocaleMessage(locale, messages.default)
return nextTick()
}
export default defineNuxtPlugin(async (nuxtApp) => { export default defineNuxtPlugin(async (nuxtApp) => {
i18n = (await createI18nPlugin()) as any globalI18n = await createI18nPlugin()
nuxtApp.vueApp.i18n = i18n.global as any nuxtApp.vueApp.i18n = globalI18n
nuxtApp.vueApp.use(i18n) nuxtApp.vueApp.use(globalI18n)
}) })
export const getI18n = () => i18n

9
packages/nc-gui/plugins/state.ts

@ -1,4 +1,5 @@
import { defineNuxtPlugin, useApi, useGlobal } from '#imports' import { defineNuxtPlugin, useApi, useGlobal } from '#imports'
import { loadLocaleMessages, setI18nLanguage } from '~/plugins/a.i18n'
/** /**
* Initialize global state and watches for changes * Initialize global state and watches for changes
@ -17,8 +18,14 @@ export default defineNuxtPlugin(async (nuxtApp) => {
const { api } = useApi() const { api } = useApi()
const i18n = nuxtApp.vueApp.i18n
const currentLang = state.lang.value
await loadLocaleMessages(i18n, currentLang)
/** set i18n locale to stored language */ /** set i18n locale to stored language */
nuxtApp.vueApp.i18n.locale.value = state.lang.value setI18nLanguage(i18n, state.lang.value)
try { try {
state.appInfo.value = await api.utils.appInfo() state.appInfo.value = await api.utils.appInfo()

Loading…
Cancel
Save