Browse Source

Merge pull request #3602 from nocodb/fix/lang-loading

fix(nc-gui): lazy load languages for initial load perf
pull/3624/head
Pranav C 2 years ago committed by GitHub
parent
commit
45b1c9db39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      packages/nc-gui/components/general/language/Menu.vue
  2. 6
      packages/nc-gui/components/general/language/index.vue
  3. 4
      packages/nc-gui/composables/useGlobal/state.ts
  4. 6
      packages/nc-gui/layouts/base.vue
  5. 6
      packages/nc-gui/lib/types.ts
  6. 8
      packages/nc-gui/nuxt-shim.d.ts
  7. 10
      packages/nc-gui/nuxt.config.ts
  8. 194
      packages/nc-gui/package-lock.json
  9. 2
      packages/nc-gui/package.json
  10. 1
      packages/nc-gui/pages/signin.vue
  11. 65
      packages/nc-gui/plugins/a.i18n.ts
  12. 9
      packages/nc-gui/plugins/state.ts

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

@ -1,14 +1,15 @@
<script lang="ts" setup>
import { Language } from '~/lib'
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 { availableLocales = ['en'], locale } = useI18n()
const languages = $computed(() => availableLocales.sort())
const languages = $computed(() => Object.entries(Language).sort())
const isRtlLang = $computed(() => ['fa'].includes(currentLang.value))
@ -21,7 +22,11 @@ function applyDirection() {
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
locale.value = lang
@ -33,19 +38,25 @@ function changeLanguage(lang: string) {
onMounted(() => {
applyDirection()
})
defineExpose({
languages,
currentLang,
changeLanguage,
})
</script>
<template>
<a-menu-item
v-for="lang of languages"
:key="lang"
:class="lang === locale ? '!bg-primary bg-opacity-10 text-primary' : ''"
v-for="[key, lang] of languages"
:key="key"
:class="key === locale ? '!bg-primary bg-opacity-10 text-primary' : ''"
class="group"
:value="lang"
@click="changeLanguage(lang)"
:value="key"
@click="changeLanguage(key)"
>
<div :class="lang === locale ? '!font-semibold !text-primary' : ''" class="nc-project-menu-item capitalize">
{{ Language[lang] || lang }}
<div :class="key === locale ? '!font-semibold !text-primary' : ''" class="nc-project-menu-item capitalize">
{{ Language[key] || lang }}
</div>
</a-menu-item>

6
packages/nc-gui/components/general/language/index.vue

@ -1,6 +1,8 @@
<template>
<a-dropdown class="select-none color-transition" :trigger="['click']">
<MaterialSymbolsTranslate v-bind="$attrs" class="md:text-xl cursor-pointer nc-menu-translate" />
<a-dropdown class="select-none color-transition cursor-pointer" :trigger="['click']">
<div v-bind="$attrs" class="flex items-center justify-center">
<MaterialSymbolsTranslate class="md:text-xl nc-menu-translate" />
</div>
<template #overlay>
<a-menu class="scrollbar-thin-dull min-w-50 max-h-90vh overflow-auto !py-0 rounded">

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.
* 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.
*/
const preferredLanguage = preferredLanguages.reduce((locale, language) => {
@ -30,7 +30,7 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
const [lang, code] = language.split(/[_-]/)
/** 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 (availableLocales.length > 1) {

6
packages/nc-gui/layouts/base.vue

@ -103,9 +103,7 @@ hooks.hook('page:finish', () => {
<template #title> Switch language</template>
<Transition name="layout">
<div v-if="!signedIn" class="nc-lang-btn">
<GeneralLanguage />
</div>
<GeneralLanguage v-if="!signedIn" class="nc-lang-btn" />
</Transition>
</a-tooltip>
@ -116,7 +114,7 @@ hooks.hook('page:finish', () => {
</a-layout>
</template>
<style lang="scss" scoped>
<style lang="scss">
.nc-lang-btn {
@apply color-transition flex items-center justify-center fixed bottom-10 right-10 z-99 w-12 h-12 rounded-full shadow-md shadow-gray-500 p-2 !bg-primary text-white active:(ring ring-accent) hover:(ring ring-accent);

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

@ -1,5 +1,7 @@
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 {
id: string
email: string
@ -32,3 +34,5 @@ export interface Field {
export type Roles = Record<Role, 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 { I18n } from 'vue-i18n'
import type { UseGlobalReturn } from './composables/useGlobal/types'
import type en from './lang/en.json'
type MessageSchema = typeof en
import type { NocoI18n } from './lib'
declare module '#app/nuxt' {
interface NuxtApp {
@ -21,7 +17,7 @@ declare module '#app/nuxt' {
declare module '@vue/runtime-core' {
interface App {
i18n: I18n<MessageSchema, unknown, unknown, false>['global']
i18n: NocoI18n
}
}

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

@ -1,4 +1,4 @@
import path from 'path'
import { dirname, resolve } from 'node:path'
import { defineNuxtConfig } from 'nuxt'
import vueI18n from '@intlify/vite-plugin-vue-i18n'
import Icons from 'unplugin-icons/vite'
@ -13,9 +13,7 @@ export default defineNuxtConfig({
modules: ['@vueuse/nuxt', 'nuxt-windicss', '@nuxt/image-edge'],
ssr: false,
app: {
cdnURL: process.env.NODE_ENV === 'production' ? '.' : undefined,
},
css: [
'virtual:windi.css',
'virtual:windi-devtools',
@ -54,7 +52,7 @@ export default defineNuxtConfig({
},
plugins: [
vueI18n({
include: path.resolve(__dirname, './lang'),
include: [resolve(dirname('./lang/**'))],
runtimeOnly: false,
}),
Icons({
@ -103,6 +101,7 @@ export default defineNuxtConfig({
},
},
},
experimental: {
reactivityTransform: true,
},
@ -110,6 +109,7 @@ export default defineNuxtConfig({
image: {
dir: 'assets/',
},
autoImports: {
dirs: ['./context', './utils', './lib'],
imports: [{ name: 'useI18n', from: 'vue-i18n' }],

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

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

2
packages/nc-gui/package.json

@ -37,7 +37,7 @@
"unique-names-generator": "^4.7.1",
"vue-dompurify-html": "^3.0.0",
"vue-github-button": "^3.0.3",
"vue-i18n": "^9.1.10",
"vue-i18n": "^9.2.2",
"vuedraggable": "^4.1.0",
"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-input-password
v-model:value="form.password"
size="large"
class="password"
:placeholder="$t('msg.info.signUp.enterPassword')"
@focus="resetError"

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

@ -1,9 +1,11 @@
import { defineNuxtPlugin } from 'nuxt/app'
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({
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)
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) => {
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 { loadLocaleMessages, setI18nLanguage } from '~/plugins/a.i18n'
/**
* Initialize global state and watches for changes
@ -17,8 +18,14 @@ export default defineNuxtPlugin(async (nuxtApp) => {
const { api } = useApi()
const i18n = nuxtApp.vueApp.i18n
const currentLang = state.lang.value
await loadLocaleMessages(i18n, currentLang)
/** set i18n locale to stored language */
nuxtApp.vueApp.i18n.locale.value = state.lang.value
setI18nLanguage(i18n, state.lang.value)
try {
state.appInfo.value = await api.utils.appInfo()

Loading…
Cancel
Save