feat(i18n): WIP (broken)

This commit is contained in:
Daniel Thompson-Yvetot
2019-12-31 11:07:47 +01:00
parent 29f7258303
commit e4992227cc
24 changed files with 419 additions and 1339 deletions

View File

@@ -26,7 +26,8 @@
"@quasar/extras": "1.3.3",
"lru-cache": "5.1.1",
"mermaid": "8.4.4",
"quasar": "1.5.11"
"quasar": "1.5.11",
"vue-i18n": "^8.15.3"
},
"devDependencies": {
"@quasar/app": "1.4.3",

View File

@@ -6,8 +6,9 @@ module.exports = function (ctx) {
// app boot file (/src/boot)
// --> boot files are part of "main.js"
boot: [
{path: 'mermaid', server: false },
'markdown'
{ path: 'mermaid', server: false },
'markdown',
'i18n'
],
css: [
@@ -31,7 +32,7 @@ module.exports = function (ctx) {
// lang: 'de', // Quasar language
// all: true, // --- includes everything; for dev only!
all: 'auto',
all: true,
components: [],
config: {
dark: true

View File

@@ -17,32 +17,10 @@
// todo: add Meta
import { Cookies } from 'quasar'
import Quasar from 'quasar'
import Quasar, { Cookies } from 'quasar'
import VueI18n from 'vue-i18n'
import localesList from '@nuyu/quasar-app-extension-i18n/src/i18n/localesList.json'
import LangSwitcher from '../components/LangSwitcher.vue'
// import { forage } from '@nuyu/quasar-app-extension-common/src/boot/curriedForage'
import { me } from '@nuyu/quasar-app-extension-common/src/boot/me'
/**
* Get and set the locale cookie
* @category i18n
* @type {function}
* @returns {string|boolean}
*/
const getLocaleForage = async function () {
const locale = await me.get('locale')
if (locale) {
// guard to make sure the cookie IS a real value
if (localesList.includes(locale)) {
return locale.toLowerCase()
}
} else {
return false
}
}
import localesList from '../../../i18n/localesList.json'
// import LangSwitcher from '../components/LangSwitcher.vue'
/**
* Get and set the locale cookie
@@ -77,7 +55,7 @@ const getBrowserLocale = function (ssrContext) {
const language = Quasar.lang.getLocale()
if (language) {
// todo: fix it. what the heck does this really do?
for (let locales of localesList) {
for (const locales of localesList) {
if (locales.startsWith(language.split('-')[0])) {
return locales
}
@@ -140,8 +118,8 @@ const replaceLocale = function (route, locale) {
* @property {object} router - object for route detection
* @returns {string} Decision tree result
*/
const getLocale = async function (routeLocale) {
const locale = await getLocaleForage()
const getLocale = function (ssrContext, routeLocale) {
const locale = getLocaleCookie(ssrContext)
if (typeof locale !== 'undefined') {
return getRoute(locale)
} else {
@@ -149,6 +127,7 @@ const getLocale = async function (routeLocale) {
}
}
/*
const reroute = function (val) {
let hostName = window.location.hostname
hostName = hostName.substring(hostName.lastIndexOf('.', hostName.lastIndexOf('.') - 1) + 1)
@@ -158,9 +137,10 @@ const reroute = function (val) {
if (location.search) route = route + location.search
return route
}
*/
export default async ({ app, Vue, ssrContext, router }) => {
Vue.component('LangSwitcher', LangSwitcher )
// Vue.component('LangSwitcher', LangSwitcher)
Vue.use(VueI18n)
app.i18n = new VueI18n({
silentTranslationWarn: true,
@@ -171,16 +151,9 @@ export default async ({ app, Vue, ssrContext, router }) => {
})
// always make sure that the fallback is loaded
app.loadedLanguages = ['en']
app.i18n.setLocaleMessage('en', require(`@nuyu/quasar-app-extension-i18n/src/i18n/locales/en.json`))
app.i18n.setLocaleMessage('en', require('../../../i18n/locales/en.json'))
router.beforeEach(async (to, from, next) => {
// todo: ignore quasar ? is this still needed for SSR?
/*
if (to.params.locale === 'src') {
next()
}
*/
// guard against non-available locales
if (to.params.locale) {
try {
@@ -195,7 +168,7 @@ export default async ({ app, Vue, ssrContext, router }) => {
}
try {
const userLocale = await me.get('locale')
const userLocale = Cookies.get('locale') || 'en' // app.$q.cookies.get('en') // Cookies.get('locale')
if (typeof userLocale !== 'function' && to.params.locale !== userLocale) {
next({
name: to.name,
@@ -214,7 +187,7 @@ export default async ({ app, Vue, ssrContext, router }) => {
}
const routeLocale = to.params.locale
const cookieLocale = await getLocale()
const cookieLocale = getLocale(ssrContext)
if (to.params.locale !== cookieLocale) {
// here we need to reroute
@@ -258,19 +231,17 @@ export default async ({ app, Vue, ssrContext, router }) => {
qLocale = locale
}
me.set({locale: locale})
// app.$q.cookies.set('locale', locale)
// on first load this will always be true
if (!app.loadedLanguages.includes(locale)) {
app.loadedLanguages.push(locale)
app.i18n.setLocaleMessage(locale, require(`@nuyu/quasar-app-extension-i18n/src/i18n/locales/${locale}.json`))
app.i18n.setLocaleMessage(locale, require(`../../../i18n/locales/${locale}.json`))
try {
await import(`quasar/lang/${qLocale}`)
.then((lang) => {
Quasar.lang.set(lang.default)
})
} catch (err) {
// todo: use sentry
console.log(err)
}
} else {
@@ -298,9 +269,9 @@ export default async ({ app, Vue, ssrContext, router }) => {
* @param ssrContext
* @returns {Promise<*>}
*/
async preFetch ({ currentRoute, redirect, ssrContext }) {
async preFetch ({ currentRoute, redirect, ssrContext }) {
if (ssrContext) {
let locale = getRoute(currentRoute.params.locale)
const locale = getRoute(currentRoute.params.locale)
let qLocale
if (locale === 'en') {
qLocale = 'en-us'
@@ -310,11 +281,10 @@ export default async ({ app, Vue, ssrContext, router }) => {
if (localesList.includes(locale)) {
await import(`quasar/lang/${qLocale}`)
.then((loc) => {
Quasar.lang.set(loc.default)
this.$q.lang.set(loc.default)
})
}
}
// todo: solve for app
}
})
}

View File

@@ -1,126 +1,130 @@
<template lang="pug">
div(style="z-index:20000000;")
q-select(
v-if="longStyle"
v-model="tempLocale"
:options="locales"
:label="$t('labels.interfaceLanguage')"
stack-label
outlined
dense
options-dense
:option-value="opt => opt.lang"
:option-label="opt => opt.langNative"
@input="val => changeLang(val.lang)"
popup-content-style="border-radius: 0 0 5px 5px, margin: 0 10px;"
)
// template(v-slot:selected="")
span {{ tempLocale.langNative }}
q-btn(
v-else
ref="selectLanguages"
icon="fal fa-globe"
:label="$t('langLabel')"
<template>
<div style="z-index:200000;">
<q-select
v-if="longStyle"
v-model="tempLocale"
:options="locales"
:label="$t('labels.interfaceLanguage')"
stack-label
outlined
dense
options-dense
:option-value="opt => opt.lang"
:option-label="opt => opt.langNative"
@input="val => changeLang(val.lang)"
popup-content-style="border-radius: 0 0 5px 5px, margin: 0 10px;"
/>
<q-btn
v-else
ref="selectLanguages"
icon="fal fa-globe"
:label="$t('langLabel')"
flat
dense
class="justify-right"
style="width:60px;text-align:right!important"
>
<q-menu
style="width:250px;"
anchor="bottom right"
self="top right"
:offset="[0,-1]"
content-class="menuCaret"
square
flat
dense
class="justify-right"
style="width:60px;text-align:right!important"
)
q-menu(
style="width:250px;"
anchor="bottom right"
self="top right"
:offset="[0,-1]"
content-class="menuCaret"
square
flat
)
q-list(dense, separator)
q-item(
clickable
v-close-popup
v-for="(language, index) in locales"
:key="index"
@click="changeLang(language.lang)"
:disable="routeLocale === language.lang"
)
q-item-section
.row
q-icon.col-1(
v-if="routeLocale === language.lang"
name="fal fa-check-circle"
color="primary"
)
q-icon.col-1(v-else name="fal fa-circle" color="grey-6")
.col-2
.col-8 {{ language.langNative }}
>
<q-list dense separator>
<q-item
clickable
v-close-popup
v-for="(language, index) in locales"
:key="index"
@click="changeLang(language.lang)"
:disable="routeLocale === language.lang"
>
<q-item-section>
<div class="row">
<q-icon class="col-1"
v-if="routeLocale === language.lang"
name="fal fa-check-circle"
color="primary"
/>
<q-icon class="col-1" v-else name="fal fa-circle" color="grey-6" />
<div class="col-2"></div>
<div class="col-8"> {{ language.langNative }} </div>
</div>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
</template>
<script>
import * as locales from '../i18n/localesObj.json'
/**
* @category i18n
* @component
*/
export default {
name: 'LangSwitcher',
props: {
lang: {
type: String,
default: 'en'
import * as locales from '../../../i18n/localesObj.json'
/**
* @category i18n
* @component
*/
export default {
name: 'LangSwitcher',
props: {
lang: {
type: String,
default: 'en'
},
longStyle: {
type: Boolean,
default: false
}
},
data () {
return {
locales: locales.default,
tempLocale: ''
}
},
computed: {
routeLocale () {
return this.$q.cookies.get('locale') || this.$route.params.locale
},
locale: {
get: function () {
const val = this.$q.cookies.get('locale') || this.$route.params.locale || 'en'
return val
},
longStyle: {
type: Boolean,
default: false
}
},
data () {
return {
locales: locales.default,
tempLocale: ''
}
},
computed: {
routeLocale () {
return this.$route.params.locale
},
locale: {
get: async function () {
const val = await this.$forage.getKeyValue({ key: 'user', value: 'locale' })() || this.$route.params.locale || 'en'
return val
},
set (val) {
return val
}
}
},
mounted () {
this.$nextTick(async () => {
const userLocale = await this.$forage.getKeyValue({ key: 'user', value: 'locale' })()
this.locales.forEach(obj => {
if (obj.lang === userLocale) {
this.tempLocale = obj
}
})
})
},
methods: {
reroute (val) {
let hostName = window.location.hostname
hostName = hostName.substring(hostName.lastIndexOf('.', hostName.lastIndexOf('.') - 1) + 1)
let route = document.location.pathname.split('/')
route[1] = val
route = route.join('/')
if (location.search) route = route + location.search
return route
},
changeLang: async function (val) {
if (val === this.$route.params.locale) { return }
const route = this.reroute(val)
this.$forage.mergeItem({ key: 'user', value: { locale: val } })()
// mutate if we have an ID
await this.$router.push(route)
set (val) {
return val
}
}
},
mounted () {
this.$nextTick(async () => {
const userLocale = this.$q.cookies.get('locale')
this.locales.forEach(obj => {
if (obj.lang === userLocale) {
this.tempLocale = obj
}
})
})
},
methods: {
reroute (val) {
// const hostName = window.location.hostname.substring(window.location.hostname.lastIndexOf('.', window.location.hostname.lastIndexOf('.') - 1) + 1)
let route = document.location.pathname.split('/')
route[1] = val
route = route.join('/')
if (location.search) route = route + location.search
return route
},
changeLang: async function (val) {
if (val === this.$route.params.locale) { return }
const route = this.reroute(val)
this.$q.cookies.set('locale', val)
// mutate if we have an ID
await this.$router.push(route)
}
}
}
</script>

View File

@@ -1,23 +1,14 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
// import { Cookies } from 'quasar'
import routes from './routes'
Vue.use(VueRouter)
/*
* If not building with SSR mode, you can
* directly export the Router instantiation
*/
export default function (/* { store, ssrContext } */) {
export default function ({ Vue, ssrContext }) {
// const cookies = process.env.SERVER ? Cookies.parseSSR(ssrContext) : Cookies
const Router = new VueRouter({
scrollBehavior: () => ({ x: 0, y: 0 }),
routes,
// Leave these as is and change from quasar.conf.js instead!
// quasar.conf.js -> build -> vueRouterMode
// quasar.conf.js -> build -> publicPath
routes: routes(), // routes(cookies),
mode: process.env.VUE_ROUTER_MODE,
base: process.env.VUE_ROUTER_BASE
})

View File

@@ -1,6 +1,10 @@
const routes = [
export default () => ([ // (cookies)
{
path: '/',
redirect: '/en' // cookies.get('locale') || '/en'
},
{
path: '/:locale',
component: () => import('layouts/MainLayout.vue'),
children: [
{
@@ -16,7 +20,7 @@ const routes = [
}
},
{
path: '/governance-and-guidance',
path: 'governance-and-guidance',
component: () => import('pages/Governance.vue'),
meta: {
name: 'Governance',
@@ -27,7 +31,7 @@ const routes = [
}
},
{
path: '/book',
path: 'book',
component: () => import('pages/Book.vue'),
meta: {
name: 'Book',
@@ -38,7 +42,7 @@ const routes = [
}
},
{
path: '/security',
path: 'security',
component: () => import('pages/Security.vue'),
meta: {
name: 'Security',
@@ -47,170 +51,140 @@ const routes = [
tags: 'tauri, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/security'
}
},
{
path: 'docs',
component: () => import('layouts/MainLayout.vue'),
children: [
{
path: 'docs', // todo: make this a nice list
name: 'docs',
component: () => import('pages/Docs.vue'),
meta: {
name: 'Docs',
page_title: 'Tauri - Documentation Overview.',
description: 'Table of Contents for the Documentation Pages.',
tags: 'open-source, native-apps, development, macos, windows, linux, documentation',
url: 'https://tauri.studio/docs'
}
},
{
path: 'introduction',
component: () => import('pages/Introduction.vue'),
meta: {
name: 'Introduction',
page_title: 'Tauri - The Overview.',
description: 'Learn about how Tauri works from a high-level and about the technology under the hood.',
tags: 'open-source, native-apps, development, macos, windows, linux, documentation, tauri',
url: 'https://tauri.studio/docs/introduction'
}
},
{
path: 'quickstart',
component: () => import('pages/Quickstart.vue'),
meta: {
name: 'Quickstart',
page_title: 'Tauri - Setup your environment in 5 minutes.',
description: 'Learn how to get your Linux, Mac or Windows development machine up and running with Node and Rust in order to make Tauri Apps.',
tags: 'tauri, quick-start, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/quickstart'
}
},
{
path: 'patterns',
component: () => import('pages/Patterns.vue'),
meta: {
name: 'Patterns',
page_title: 'Tauri - Design Patterns',
description: 'Learn about the variety of systems you can design with simple configuration changes - now includes flowcharts and grading to make it easier to compare and choose!',
tags: 'tauri, architecture, flowcharts, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/patterns'
}
},
{
path: 'frameworks',
component: () => import('pages/Frameworks.vue'),
meta: {
name: 'Frameworks',
page_title: 'Tauri - Design Patterns',
description: 'Learn about the variety of systems you can design with simple configuration changes - now includes flowcharts and grading to make it easier to compare and choose!',
tags: 'tauri, architecture, flowcharts, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/frameworks'
}
},
{
path: 'no-server',
component: () => import('pages/Noserver.vue'),
meta: {
name: 'No-Server',
page_title: 'Tauri - Design Patterns',
description: 'Learn about the variety of systems you can design with simple configuration changes - now includes flowcharts and grading to make it easier to compare and choose!',
tags: 'tauri, architecture, flowcharts, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/no-server'
}
},
{
path: 'config',
component: () => import('pages/Config.vue'),
meta: {
name: 'Config',
page_title: 'Tauri - Configuration',
description: 'Learn about the variety of ways you can configure tauri to meet your needs.',
tags: 'tauri, api, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/config'
}
},
{
path: 'api',
component: () => import('pages/API.vue'),
meta: {
name: 'API',
page_title: 'Tauri - API',
description: 'Learn about the various endpoints and communication protocols that Tauri enables you to use',
tags: 'tauri, api, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/api'
}
},
{
path: 'cli',
component: () => import('pages/Cli.vue'),
meta: {
name: 'CLI',
page_title: 'Tauri - Node.js CLI.',
description: 'Learn about the Node CLI commands and their configurations.',
tags: 'tauri, cli, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/cli'
}
},
{
path: 'bundler',
component: () => import('pages/Bundler.vue'),
meta: {
name: 'Bundler',
page_title: 'Tauri - Rust Bundler.',
description: 'Learn about the Rust bundler.',
tags: 'tauri, bundler, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/bundler'
}
},
{
path: 'partners',
component: () => import('pages/Partners.vue'),
meta: {
name: 'Partners',
page_title: 'Tauri - Partners',
description: 'Meet the ',
tags: 'development, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/partners'
}
}
]
}
]
},
{
path: '/docs',
meta: {
showDocslink: false
},
component: () => import('layouts/MainLayout.vue'),
children: [
{
path: '/docs', // todo: make this a nice list
name: 'docs',
component: () => import('pages/Docs.vue'),
meta: {
name: 'Docs',
page_title: 'Tauri - Documentation Overview.',
description: 'Table of Contents for the Documentation Pages.',
tags: 'open-source, native-apps, development, macos, windows, linux, documentation',
url: 'https://tauri.studio/docs'
}
},
{
path: '/docs/introduction',
component: () => import('pages/Introduction.vue'),
meta: {
name: 'Introduction',
page_title: 'Tauri - The Overview.',
description: 'Learn about how Tauri works from a high-level and about the technology under the hood.',
tags: 'open-source, native-apps, development, macos, windows, linux, documentation, tauri',
url: 'https://tauri.studio/docs/introduction'
}
},
{
path: '/docs/quickstart',
component: () => import('pages/Quickstart.vue'),
meta: {
name: 'Quickstart',
page_title: 'Tauri - Setup your environment in 5 minutes.',
description: 'Learn how to get your Linux, Mac or Windows development machine up and running with Node and Rust in order to make Tauri Apps.',
tags: 'tauri, quick-start, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/quickstart'
}
},
{
path: '/docs/patterns',
component: () => import('pages/Patterns.vue'),
meta: {
name: 'Patterns',
page_title: 'Tauri - Design Patterns',
description: 'Learn about the variety of systems you can design with simple configuration changes - now includes flowcharts and grading to make it easier to compare and choose!',
tags: 'tauri, architecture, flowcharts, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/patterns'
}
},
{
path: '/docs/frameworks',
component: () => import('pages/Frameworks.vue'),
meta: {
name: 'Frameworks',
page_title: 'Tauri - Design Patterns',
description: 'Learn about the variety of systems you can design with simple configuration changes - now includes flowcharts and grading to make it easier to compare and choose!',
tags: 'tauri, architecture, flowcharts, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/frameworks'
}
},
{
path: '/docs/no-server',
component: () => import('pages/Noserver.vue'),
meta: {
name: 'No-Server',
page_title: 'Tauri - Design Patterns',
description: 'Learn about the variety of systems you can design with simple configuration changes - now includes flowcharts and grading to make it easier to compare and choose!',
tags: 'tauri, architecture, flowcharts, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/no-server'
}
},
{
path: '/docs/config',
component: () => import('pages/Config.vue'),
meta: {
name: 'Config',
page_title: 'Tauri - Configuration',
description: 'Learn about the variety of ways you can configure tauri to meet your needs.',
tags: 'tauri, api, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/config'
}
},
{
path: '/docs/api',
component: () => import('pages/API.vue'),
meta: {
name: 'API',
page_title: 'Tauri - API',
description: 'Learn about the various endpoints and communication protocols that Tauri enables you to use',
tags: 'tauri, api, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/api'
}
},
{
path: '/docs/cli',
component: () => import('pages/Cli.vue'),
meta: {
name: 'CLI',
page_title: 'Tauri - Node.js CLI.',
description: 'Learn about the Node CLI commands and their configurations.',
tags: 'tauri, cli, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/cli'
}
},
{
path: '/docs/bundler',
component: () => import('pages/Bundler.vue'),
meta: {
name: 'Bundler',
page_title: 'Tauri - Rust Bundler.',
description: 'Learn about the Rust bundler.',
tags: 'tauri, bundler, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/docs/bundler'
}
},
{
path: '/contribute',
component: () => import('pages/Contribute.vue'),
meta: {
name: 'Contribute',
page_title: 'Tauri - Contribute.',
description: 'Learn about the stack and processes involved in Tauri Development, and get involved in making it better.',
tags: 'development, contributions, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/contribute'
}
},
{
path: '/wtf',
component: () => import('pages/WTF.vue'),
meta: {
name: 'WTF',
page_title: 'WTF Tauri?',
description: 'When things go wrong, this page will help you get back and track.',
tags: 'development, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/wtf'
}
},
{
path: '/partners',
component: () => import('pages/Partners.vue'),
meta: {
name: 'Partners',
page_title: 'Tauri - Partners',
description: 'Meet the ',
tags: 'development, open-source, native-apps, development, macos, windows, linux',
url: 'https://tauri.studio/partners'
}
}
]
path: '/*',
name: 'notfound',
redirect: '/en'
}
]
// Always leave this as last one
if (process.env.MODE !== 'ssr') {
routes.push({
path: '*',
component: () => import('pages/Error404.vue')
})
}
export default routes
])

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -1102,22 +1102,22 @@
resolved "https://registry.npmjs.org/@positron/stack-trace/-/stack-trace-1.0.0.tgz#14fcc712a530038ef9be1ce6952315a839f466a8"
integrity sha1-FPzHEqUwA475vhzmlSMVqDn0Zqg=
"@quasar/app@1.4.1":
version "1.4.1"
resolved "https://registry.npmjs.org/@quasar/app/-/app-1.4.1.tgz#414f856fb9751ad3fbca4c013c7cf11d780847b8"
integrity sha512-ofLV/t9ShZhNC9xh9pRjYtkCUuHf/dT1WexlVi/6vk6072xWoIoMpNaTPhoIioJY1NbN8AerfDY2igWmgCr8CA==
"@quasar/app@1.4.3":
version "1.4.3"
resolved "https://registry.npmjs.org/@quasar/app/-/app-1.4.3.tgz#e231d66be163501864f8fd6af807529124b2cfec"
integrity sha512-gYzyz7zQMbvwOyWjkXLZk3HNYr82Q7x7cabZ5/hoJSaAUk8fJNt5tZ4swLWc8xHDxj2a1VzDkFLlkVOrxJ1dUQ==
dependencies:
"@quasar/babel-preset-app" "1.1.7"
"@quasar/fastclick" "1.1.4"
"@vue/preload-webpack-plugin" "1.1.1"
autoprefixer "9.7.3"
chalk "3.0.0"
chokidar "3.3.0"
chokidar "3.3.1"
ci-info "2.0.0"
compression-webpack-plugin "3.0.1"
copy-webpack-plugin "5.1.1"
cross-spawn "7.0.1"
css-loader "3.3.2"
css-loader "3.4.0"
cssnano "4.1.10"
dot-prop "5.2.0"
elementtree "0.1.7"
@@ -1129,7 +1129,7 @@
hash-sum "2.0.0"
html-minifier "4.0.0"
html-webpack-plugin "3.2.0"
inquirer "7.0.0"
inquirer "7.0.1"
isbinaryfile "4.0.2"
launch-editor-middleware "2.2.1"
lodash.debounce "4.0.8"
@@ -1138,7 +1138,7 @@
log-update "3.3.0"
lru-cache "5.1.1"
memory-fs "0.5.0"
mini-css-extract-plugin "^0.8.0"
mini-css-extract-plugin "^0.8.1"
minimist "1.2.0"
ms "2.1.2"
node-loader "0.6.0"
@@ -1151,22 +1151,22 @@
postcss-safe-parser "4.0.1"
register-service-worker "1.6.2"
sass-loader "8.0.0"
semver "6.3.0"
semver "7.1.0"
strip-ansi "6.0.0"
stylus "0.54.7"
stylus-loader "3.0.2"
terser-webpack-plugin "2.3.0"
terser-webpack-plugin "2.3.1"
url-loader "3.0.0"
vue "2.6.11"
vue-loader "15.7.2"
vue-loader "15.8.3"
vue-router "3.1.3"
vue-server-renderer "2.6.11"
vue-style-loader "4.1.2"
vue-template-compiler "2.6.11"
vuex "3.1.2"
webpack "4.41.2"
webpack "4.41.3"
webpack-bundle-analyzer "3.6.0"
webpack-chain "6.1.0"
webpack-chain "6.2.0"
webpack-dev-server "3.9.0"
webpack-merge "4.2.2"
webpack-node-externals "1.7.2"
@@ -1330,7 +1330,7 @@
resolved "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==
"@vue/component-compiler-utils@^3.0.0":
"@vue/component-compiler-utils@^3.1.0":
version "3.1.0"
resolved "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.1.0.tgz#64cd394925f5af1f9c3228c66e954536f5311857"
integrity sha512-OJ7swvl8LtKtX5aYP8jHhO6fQBIRIGkU6rvWzK+CGJiNOnvg16nzcBkd9qMZzW8trI2AsqAKx263nv7kb5rhZw==
@@ -2515,10 +2515,10 @@ check-types@^8.0.3:
resolved "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552"
integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==
chokidar@3.3.0:
version "3.3.0"
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6"
integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==
chokidar@3.3.1:
version "3.3.1"
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450"
integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==
dependencies:
anymatch "~3.1.1"
braces "~3.0.2"
@@ -2526,9 +2526,9 @@ chokidar@3.3.0:
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.2.0"
readdirp "~3.3.0"
optionalDependencies:
fsevents "~2.1.1"
fsevents "~2.1.2"
chokidar@^2.0.2, chokidar@^2.1.8:
version "2.1.8"
@@ -3083,10 +3083,10 @@ css-declaration-sorter@^4.0.1:
postcss "^7.0.1"
timsort "^0.3.0"
css-loader@3.3.2:
version "3.3.2"
resolved "https://registry.npmjs.org/css-loader/-/css-loader-3.3.2.tgz#41b2086528aa4fbf8c0692e874bc14f081129b21"
integrity sha512-4XSiURS+YEK2fQhmSaM1onnUm0VKWNf6WWBYjkp9YbSDGCBTVZ5XOM6Gkxo8tLgQlzkZOBJvk9trHlDk4gjEYg==
css-loader@3.4.0:
version "3.4.0"
resolved "https://registry.npmjs.org/css-loader/-/css-loader-3.4.0.tgz#9fb263436783117a41d014e45e8eaeba54dd6670"
integrity sha512-JornYo4RAXl1Mzt0lOSVPmArzAMV3rGY2VuwtaDc732WTWjdwTaeS19nCGWMcSCf305Q396lhhDAJEWWM0SgPQ==
dependencies:
camelcase "^5.3.1"
cssesc "^3.0.0"
@@ -4719,7 +4719,7 @@ find-cache-dir@^2.0.0, find-cache-dir@^2.1.0:
make-dir "^2.0.0"
pkg-dir "^3.0.0"
find-cache-dir@^3.0.0, find-cache-dir@^3.1.0:
find-cache-dir@^3.0.0:
version "3.1.0"
resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.1.0.tgz#9935894999debef4cf9f677fdf646d002c4cdecb"
integrity sha512-zw+EFiNBNPgI2NTrKkDd1xd7q0cs6wr/iWnr/oUkI0yF9K9GqQ+riIt4aiyFaaqpaWbxPrJXHI+QvmNUQbX+0Q==
@@ -4728,6 +4728,15 @@ find-cache-dir@^3.0.0, find-cache-dir@^3.1.0:
make-dir "^3.0.0"
pkg-dir "^4.1.0"
find-cache-dir@^3.2.0:
version "3.2.0"
resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.2.0.tgz#e7fe44c1abc1299f516146e563108fd1006c1874"
integrity sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==
dependencies:
commondir "^1.0.1"
make-dir "^3.0.0"
pkg-dir "^4.1.0"
find-up@^1.0.0:
version "1.1.2"
resolved "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
@@ -4922,7 +4931,7 @@ fsevents@^1.2.7:
nan "^2.12.1"
node-pre-gyp "^0.12.0"
fsevents@~2.1.1:
fsevents@~2.1.2:
version "2.1.2"
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805"
integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==
@@ -5706,7 +5715,26 @@ ini@^1.3.4, ini@~1.3.0:
resolved "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
inquirer@7.0.0, inquirer@^7.0.0:
inquirer@7.0.1:
version "7.0.1"
resolved "https://registry.npmjs.org/inquirer/-/inquirer-7.0.1.tgz#13f7980eedc73c689feff3994b109c4e799c6ebb"
integrity sha512-V1FFQ3TIO15det8PijPLFR9M9baSlnRs9nL7zWu1MNVA2T9YVl9ZbrHJhYs7e9X8jeMZ3lr2JH/rdHFgNCBdYw==
dependencies:
ansi-escapes "^4.2.1"
chalk "^2.4.2"
cli-cursor "^3.1.0"
cli-width "^2.0.0"
external-editor "^3.0.3"
figures "^3.0.0"
lodash "^4.17.15"
mute-stream "0.0.8"
run-async "^2.2.0"
rxjs "^6.5.3"
string-width "^4.1.0"
strip-ansi "^5.1.0"
through "^2.3.6"
inquirer@^7.0.0:
version "7.0.0"
resolved "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a"
integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==
@@ -6992,10 +7020,10 @@ min-document@^2.19.0:
dependencies:
dom-walk "^0.1.0"
mini-css-extract-plugin@^0.8.0:
version "0.8.0"
resolved "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz#81d41ec4fe58c713a96ad7c723cdb2d0bd4d70e1"
integrity sha512-MNpRGbNA52q6U92i0qbVpQNsgk7LExy41MdAlG84FeytfDOtRIf/mCHdEgG8rpTKOaNKiqUnZdlptF469hxqOw==
mini-css-extract-plugin@^0.8.1:
version "0.8.2"
resolved "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.2.tgz#a875e169beb27c88af77dd962771c9eedc3da161"
integrity sha512-a3Y4of27Wz+mqK3qrcd3VhYz6cU0iW5x3Sgvqzbj+XmlrSizmvu8QQMl5oMYJjgHOC4iyt+w7l4umP+dQeW3bw==
dependencies:
loader-utils "^1.1.0"
normalize-url "1.9.1"
@@ -8060,7 +8088,7 @@ phin@^2.9.1:
resolved "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c"
integrity sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==
picomatch@^2.0.4, picomatch@^2.0.5:
picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7:
version "2.1.1"
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5"
integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==
@@ -8743,10 +8771,10 @@ qs@~6.5.2:
resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
quasar@1.5.9:
version "1.5.9"
resolved "https://registry.npmjs.org/quasar/-/quasar-1.5.9.tgz#866651eb425911afbbea7176b1d57ba8969f2fee"
integrity sha512-QdTiLNCqumBOOkeODZrDmxJY9KjjEEC1Gp4KPM5fRFEpSNvtHF5m68tt5/4mnCrS6V05ZpetYRizmCAnE9kkzw==
quasar@1.5.11:
version "1.5.11"
resolved "https://registry.npmjs.org/quasar/-/quasar-1.5.11.tgz#a1ff4a9389167eec27d465ddc9b7fdecc71cd2a5"
integrity sha512-+gyZYZc6qQRDYzfICmbEca6prRZV+nI9T6y7AczQu55w3C8GUNXZ6IF6OHH2Rwh0ftdeqcbOZ+9k8/IOeJFGLQ==
query-string@^4.1.0:
version "4.3.4"
@@ -8901,12 +8929,12 @@ readdirp@^2.2.1:
micromatch "^3.1.10"
readable-stream "^2.0.2"
readdirp@~3.2.0:
version "3.2.0"
resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839"
integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==
readdirp@~3.3.0:
version "3.3.0"
resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17"
integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==
dependencies:
picomatch "^2.0.4"
picomatch "^2.0.7"
redent@^1.0.0:
version "1.0.0"
@@ -9229,6 +9257,13 @@ rxjs@^6.4.0:
dependencies:
tslib "^1.9.0"
rxjs@^6.5.3:
version "6.5.4"
resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
dependencies:
tslib "^1.9.0"
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@@ -9357,7 +9392,12 @@ semver-truncate@^1.1.2:
resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
semver@6.3.0, semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.3.0:
semver@7.1.0:
version "7.1.0"
resolved "https://registry.npmjs.org/semver/-/semver-7.1.0.tgz#e5870a302d6929a86a967c346e699e19154e38e0"
integrity sha512-4P8Vc43MxQL6UKqSiEnf0jZNYx545R9W1HwXP6p65paPp86AUJiafZ8XG81hAbcldKMCUIbeykUTVYG19LB7Cw==
semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
@@ -9386,7 +9426,7 @@ send@0.17.1:
range-parser "~1.2.1"
statuses "~1.5.0"
serialize-javascript@^2.1.1, serialize-javascript@^2.1.2:
serialize-javascript@^2.1.2:
version "2.1.2"
resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61"
integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==
@@ -10190,36 +10230,36 @@ tempfile@^2.0.0:
temp-dir "^1.0.0"
uuid "^3.0.1"
terser-webpack-plugin@2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.0.tgz#00fd8f792a330dc572e2e2b468fd7cb5ffd7ea51"
integrity sha512-yez0HdpDf/iQVYGf+e/o8ZYWLb1g9d1nRRi5FIOZ4KfXbfSPT259UoqxPiSLhCnr0mlDoh+bucpYQSFbU0cEsQ==
terser-webpack-plugin@2.3.1:
version "2.3.1"
resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.1.tgz#6a63c27debc15b25ffd2588562ee2eeabdcab923"
integrity sha512-dNxivOXmDgZqrGxOttBH6B4xaxT4zNC+Xd+2K8jwGDMK5q2CZI+KZMA1AAnSRT+BTRvuzKsDx+fpxzPAmAMVcA==
dependencies:
cacache "^13.0.1"
find-cache-dir "^3.1.0"
find-cache-dir "^3.2.0"
jest-worker "^24.9.0"
schema-utils "^2.6.1"
serialize-javascript "^2.1.2"
source-map "^0.6.1"
terser "^4.4.2"
terser "^4.4.3"
webpack-sources "^1.4.3"
terser-webpack-plugin@^1.4.1:
version "1.4.2"
resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.2.tgz#e23c0d554587d1f473bd0cf68627720e733890a4"
integrity sha512-fdEb91kR2l+BVgES77N/NTXWZlpX6vX+pYPjnX5grcDYBF2CMnzJiXX4NNlna4l04lvCW39lZ+O/jSvUhHH/ew==
terser-webpack-plugin@^1.4.3:
version "1.4.3"
resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c"
integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==
dependencies:
cacache "^12.0.2"
find-cache-dir "^2.1.0"
is-wsl "^1.1.0"
schema-utils "^1.0.0"
serialize-javascript "^2.1.1"
serialize-javascript "^2.1.2"
source-map "^0.6.1"
terser "^4.1.2"
webpack-sources "^1.4.0"
worker-farm "^1.7.0"
terser@^4.0.0, terser@^4.1.2, terser@^4.4.2:
terser@^4.0.0, terser@^4.1.2:
version "4.4.2"
resolved "https://registry.npmjs.org/terser/-/terser-4.4.2.tgz#448fffad0245f4c8a277ce89788b458bfd7706e8"
integrity sha512-Uufrsvhj9O1ikwgITGsZ5EZS6qPokUOkCegS7fYOdGTv+OA90vndUbU6PEjr5ePqHfNUbGyMO7xyIZv2MhsALQ==
@@ -10228,6 +10268,15 @@ terser@^4.0.0, terser@^4.1.2, terser@^4.4.2:
source-map "~0.6.1"
source-map-support "~0.5.12"
terser@^4.4.3:
version "4.4.3"
resolved "https://registry.npmjs.org/terser/-/terser-4.4.3.tgz#401abc52b88869cf904412503b1eb7da093ae2f0"
integrity sha512-0ikKraVtRDKGzHrzkCv5rUNDzqlhmhowOBqC0XqUHFpW+vJ45+20/IFBcebwKfiS2Z9fJin6Eo+F1zLZsxi8RA==
dependencies:
commander "^2.20.0"
source-map "~0.6.1"
source-map-support "~0.5.12"
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@@ -10741,12 +10790,17 @@ vue-hot-reload-api@^2.3.0:
resolved "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==
vue-loader@15.7.2:
version "15.7.2"
resolved "https://registry.npmjs.org/vue-loader/-/vue-loader-15.7.2.tgz#cc89e2716df87f70fe656c9da9d7f8bec06c73d6"
integrity sha512-H/P9xt/nkocyu4hZKg5TzPqyCT1oKOaCSk9zs0JCbJuy0Q8KtR0bjJpnT/5R5x/Ckd1GFkkLQnQ1C4x6xXeLZg==
vue-i18n@^8.15.3:
version "8.15.3"
resolved "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.15.3.tgz#9f947802d9b734fcb92e2ce724da654f2f9fc0f4"
integrity sha512-PVNgo6yhOmacZVFjSapZ314oewwLyXHjJwAqjnaPN1GJAJd/dvsrShGzSiJuCX4Hc36G4epJvNXUwO8y7wEKew==
vue-loader@15.8.3:
version "15.8.3"
resolved "https://registry.npmjs.org/vue-loader/-/vue-loader-15.8.3.tgz#857cb9e30eb5fc25e66db48dce7e4f768602a23c"
integrity sha512-yFksTFbhp+lxlm92DrKdpVIWMpranXnTEuGSc0oW+Gk43M9LWaAmBTnfj5+FCdve715mTHvo78IdaXf5TbiTJg==
dependencies:
"@vue/component-compiler-utils" "^3.0.0"
"@vue/component-compiler-utils" "^3.1.0"
hash-sum "^1.0.2"
loader-utils "^1.1.0"
vue-hot-reload-api "^2.3.0"
@@ -10845,10 +10899,10 @@ webpack-bundle-analyzer@3.6.0:
opener "^1.5.1"
ws "^6.0.0"
webpack-chain@6.1.0:
version "6.1.0"
resolved "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.1.0.tgz#f13e0c773059c0ab8eae59c75cc3562bb1c82824"
integrity sha512-14CXazkg3GnUT0xPHkJyIgDKm5JAs6kpdMA1QozyZJl5qN+WRXXsMPn3O13a7C0EnT43cMGdnRX+cOS1mxRX/A==
webpack-chain@6.2.0:
version "6.2.0"
resolved "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.2.0.tgz#bcea7b0ad5feae6845d70e6fd7a048953f8ae77c"
integrity sha512-Kt/TCt6p4sL8YJ49m6/mMkU1gkGJUMu/6yevWbWnaHYTdKc7U6hNAm0d9RSdLIN28CGonmYD5FkABqE1UuNTTw==
dependencies:
deepmerge "^1.5.2"
javascript-stringify "^2.0.1"
@@ -10931,10 +10985,10 @@ webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-
source-list-map "^2.0.0"
source-map "~0.6.1"
webpack@4.41.2:
version "4.41.2"
resolved "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz#c34ec76daa3a8468c9b61a50336d8e3303dce74e"
integrity sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==
webpack@4.41.3:
version "4.41.3"
resolved "https://registry.npmjs.org/webpack/-/webpack-4.41.3.tgz#cb7592c43080337dbc9be9e98fc6478eb3981026"
integrity sha512-EcNzP9jGoxpQAXq1VOoTet0ik7/VVU1MovIfcUSAjLowc7GhcQku/sOXALvq5nPpSei2HF6VRhibeJSC3i/Law==
dependencies:
"@webassemblyjs/ast" "1.8.5"
"@webassemblyjs/helper-module-context" "1.8.5"
@@ -10956,7 +11010,7 @@ webpack@4.41.2:
node-libs-browser "^2.2.1"
schema-utils "^1.0.0"
tapable "^1.1.3"
terser-webpack-plugin "^1.4.1"
terser-webpack-plugin "^1.4.3"
watchpack "^1.6.0"
webpack-sources "^1.4.1"

14
i18n/.gitignore vendored
View File

@@ -1,14 +0,0 @@
.DS_Store
.thumbs.db
node_modules
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln

View File

@@ -1,32 +0,0 @@
Quasar App Extension Title <- change name
===
_Be sure to change this readme as appropriate for your app extension._
_Think about the organization of this file and how the information will be beneficial to the user._
> Add a short description of your App Extension. What does it do? How is it beneficial? Why would someone want to use it?
# Install
```bash
quasar ext add my-ext <- change name
```
Quasar CLI will retrieve it from NPM and install the extension.
## Prompts
> If your app extension uses prompts, explain them here, otherwise remove this section.
# Uninstall
```bash
quasar ext remove my-ext <- change name
```
# Info
> Add longer information here that will help the user of your app extension.
# Other Info
> Add other information that's not as important to know
# Donate
If you appreciate the work that went into this App Extension, please consider [donating to Quasar](https://donate.quasar.dev).

5
i18n/locales/en.json Normal file
View File

@@ -0,0 +1,5 @@
{
"langLabel": "EN",
"properName": "English",
"shortCode": "en"
}

3
i18n/localesList.json Normal file
View File

@@ -0,0 +1,3 @@
[
"en"
]

View File

@@ -3,10 +3,5 @@
"lang": "en",
"shortcode": "en",
"langNative": "English"
},
{
"lang": "es",
"shortcode": "es",
"langNative": "Español"
}
]

View File

@@ -1,18 +0,0 @@
{
"name": "@tauri-apps/quasar-app-extension-studio-i18n",
"version": "0.0.1",
"description": "common i18n locales and tools",
"author": "Daniel Thompson-Yvetot <denjell@sfosc.org>",
"main": "src/index.js",
"scripts": {
"test": "echo \"No test specified\" && exit 0"
},
"repository": {
"type": "git",
"url": ""
},
"dependencies": {
"vue-i18n": "^8.0.0"
},
"devDependencies": {}
}

View File

@@ -1,352 +0,0 @@
/**
* @module i18n
* @category i18n
* @description The i18n module serves a few important purposes:
* - Collect available locales
* - Collect common translation strings in all locales
* - Map quasar native i18n en-us to en
* - Rig vue-i18n
* - Detect and apply translation
* - Detect route parameter
* - Detect browser preference (default to en)
* - Detect user setting stored with forage (site & app) - even without a signup
* - Provide route guards
* - Provide components for language switching
* - Provide methods for direct language switching
* @mermaid
* graph TD
* F-->A
* F-->G
* subgraph RENDER
* E
* end
* subgraph SITE
* A-->B
* B-->C
* C-->D
* D-->E
* end
* subgraph APP
* G-->E
* end
* F((Entry))
* A[User Setting]
* B[Cookie Setting]
* C[Browser Locale]
* D[Route Param]
* G[User Setting]
* E(Apply Translation)
*/
// todo: add Meta
import { Cookies } from 'quasar'
import Quasar from 'quasar'
import VueI18n from 'vue-i18n'
import localesList from '@nuyu/quasar-app-extension-i18n/src/i18n/localesList.json'
import LangSwitcher from '../components/LangSwitcher.vue'
// import { forage } from '@nuyu/quasar-app-extension-common/src/boot/curriedForage'
import { me } from '@nuyu/quasar-app-extension-common/src/boot/me'
/**
* Get and set the locale cookie
* @category i18n
* @type {function}
* @returns {string|boolean}
*/
const getLocaleForage = async function () {
const locale = await me.get('locale')
if (locale) {
// guard to make sure the cookie IS a real value
if (localesList.includes(locale)) {
return locale.toLowerCase()
}
} else {
return false
}
}
/**
* Get and set the locale cookie
* @category i18n
* @type {function}
* @property {object} ssrContext - required for isomorphism
* @returns {string|boolean}
*/
const getLocaleCookie = function (ssrContext) {
const cookies = process.env.SERVER ? Cookies.parseSSR(ssrContext) : Cookies
const cookie = cookies.get('locale')
if (cookie) {
// guard to make sure the cookie IS a real value
if (localesList.includes(cookie)) {
return cookie.toLowerCase()
}
} else {
return false
}
}
/**
* Get the Locale that the Browser defines
* @category i18n
* @type {function}
* @param ssrContext
* @returns {undefined|*}
*/
const getBrowserLocale = function (ssrContext) {
// native Quasar version
if (!ssrContext) {
const language = Quasar.lang.getLocale()
if (language) {
// todo: fix it. what the heck does this really do?
for (let locales of localesList) {
if (locales.startsWith(language.split('-')[0])) {
return locales
}
}
} else {
return undefined
}
}
}
/**
* Detect that route locale param is a member of the set of locales
*
* @category i18n
* @type {function}
* @property {object} routeLocale - :locale param to check
* @returns {string} lower-cased locale
*
*/
const getRoute = function (routeLocale) {
// this guard makes sure only valid langs are served
try {
const validRoute = localesList.includes(routeLocale)
if (validRoute) {
return routeLocale
}
} catch (e) {
// fallback to
return 'en'
}
}
/**
* Replace locale in route
*
* @category i18n
* @type {function}
* @property {string} route - just the slashed route after the main URL
* @property {string} locale - as determined by replaceLocal
* @returns {string} new route
*/
const replaceLocale = function (route, locale) {
route = route.split('/')
route[1] = locale
return route.join('/')
}
/**
* Waterfall for Locale Discovery
*
* FLOW:
*
* 1. check if there's a forage
* 2. if not, look for browser pref
* 3. otherwise revert to route
*
* @category i18n
* @function
* @property {object} ssrContext - required for isomorphism
* @property {object} router - object for route detection
* @returns {string} Decision tree result
*/
const getLocale = async function (routeLocale) {
const locale = await getLocaleForage()
if (typeof locale !== 'undefined') {
return getRoute(locale)
} else {
return 'en'
}
}
const reroute = function (val) {
let hostName = window.location.hostname
hostName = hostName.substring(hostName.lastIndexOf('.', hostName.lastIndexOf('.') - 1) + 1)
let route = document.location.pathname.split('/')
route[1] = val
route = route.join('/')
if (location.search) route = route + location.search
return route
}
export default async ({ app, Vue, ssrContext, router }) => {
Vue.component('LangSwitcher', LangSwitcher )
Vue.use(VueI18n)
app.i18n = new VueI18n({
silentTranslationWarn: true,
fallbackLocale: 'en',
messages: {},
dateTimeFormats: {},
numberFormats: {}
})
// always make sure that the fallback is loaded
app.loadedLanguages = ['en']
app.i18n.setLocaleMessage('en', require(`@nuyu/quasar-app-extension-i18n/src/i18n/locales/en.json`))
router.beforeEach(async (to, from, next) => {
// todo: ignore quasar ? is this still needed for SSR?
/*
if (to.params.locale === 'src') {
next()
}
*/
// guard against non-available locales
if (to.params.locale) {
try {
localesList.includes(to.params.locale)
} catch (e) {
next({
name: to.name,
params: { locale: 'en' },
query: { to: to.query.to || null }
})
}
}
try {
const userLocale = await me.get('locale')
if (typeof userLocale !== 'function' && to.params.locale !== userLocale) {
next({
name: to.name,
params: { locale: userLocale || 'en' },
query: () => {
if (to.query.to) {
return { to: to.query.to }
} else {
return null
}
}
})
}
} catch (err) {
console.log(err)
}
const routeLocale = to.params.locale
const cookieLocale = await getLocale()
if (to.params.locale !== cookieLocale) {
// here we need to reroute
}
// const cookieLocale = getLocaleCookie(ssrContext)
// const browserLocale = getRoute(getBrowserLocale(ssrContext))
// if (app.userSelectedLocale === true) {
// cookie or route
let locale
if (cookieLocale) {
locale = cookieLocale
} else {
locale = routeLocale
}
locale = getRoute(locale) // => MUST BE EN
// }
/*
else {
if (browserLocale) {
locale = browserLocale
} else { locale = routeLocale }
}
*/
/*
// this is for when the lang routing is done in the browser
if (routeLocale !== locale) {
next({
path: replaceLocale(to.path, locale)
})
}
*/
// needed to set quasar locale because short code
let qLocale
if (locale === 'en') {
qLocale = 'en-us'
} else {
qLocale = locale
}
me.set({locale: locale})
// on first load this will always be true
if (!app.loadedLanguages.includes(locale)) {
app.loadedLanguages.push(locale)
app.i18n.setLocaleMessage(locale, require(`@nuyu/quasar-app-extension-i18n/src/i18n/locales/${locale}.json`))
try {
await import(`quasar/lang/${qLocale}`)
.then((lang) => {
Quasar.lang.set(lang.default)
})
} catch (err) {
// todo: use sentry
console.log(err)
}
} else {
try {
await import(`quasar/lang/${qLocale}`)
.then((lang) => {
Quasar.lang.set(lang.default)
})
} catch (err) {
console.log(err)
}
}
app.i18n.locale = locale
next()
})
Vue.mixin({
/**
* prefetch as a mixin for global access
* @category i18n
* @description Check the route
* @type {function}
* @param currentRoute
* @param redirect
* @param ssrContext
* @returns {Promise<*>}
*/
async preFetch ({ currentRoute, redirect, ssrContext }) {
if (ssrContext) {
let locale = getRoute(currentRoute.params.locale)
let qLocale
if (locale === 'en') {
qLocale = 'en-us'
} else {
qLocale = locale
}
if (localesList.includes(locale)) {
await import(`quasar/lang/${qLocale}`)
.then((loc) => {
Quasar.lang.set(loc.default)
})
}
}
// todo: solve for app
}
})
}
// we are exporting for convenience JUST in case
export {
getLocaleCookie,
getBrowserLocale,
getRoute,
replaceLocale,
getLocale
}

View File

@@ -1,141 +0,0 @@
<template lang="pug">
div(style="z-index:20000000;")
q-select(
v-if="longStyle"
v-model="tempLocale"
:options="locales"
:label="$t('labels.interfaceLanguage')"
stack-label
outlined
dense
options-dense
:option-value="opt => opt.lang"
:option-label="opt => opt.langNative"
@input="val => changeLang(val.lang)"
popup-content-style="border-radius: 0 0 5px 5px, margin: 0 10px;"
)
q-btn(
v-else
ref="selectLanguages"
icon="fal fa-globe"
:label="$t('langLabel')"
flat
dense
class="justify-right"
style="width:60px;text-align:right!important"
)
q-menu(
style="width:250px;"
anchor="bottom right"
self="top right"
:offset="[0,-1]"
content-class="menuCaret"
square
flat
)
q-list(dense, separator)
q-item(
clickable
v-close-popup
v-for="(language, index) in locales"
:key="index"
@click="changeLang(language.lang)"
:disable="routeLocale === language.lang"
)
q-item-section
.row
q-icon.col-1(
v-if="routeLocale === language.lang"
name="fal fa-check-circle"
color="primary"
)
q-icon.col-1(v-else name="fal fa-circle" color="grey-6")
.col-2
.col-8 {{ language.langNative }}
</template>
<script>
import * as locales from '../i18n/localesObj.json'
export default {
name: 'LangSwitcher',
props: {
lang: {
type: String,
default: 'en'
},
longStyle: {
type: Boolean,
default: false
}
},
data () {
return {
locales: locales.default,
tempLocale: ''
}
},
computed: {
routeLocale () {
return this.$route.params.locale
},
locale: {
get: async function () {
const val = await this.$forage.getKeyValue({ key: 'user', value: 'locale' })() || this.$route.params.locale || 'en'
return val
},
set (val) {
return val
}
}
},
mounted () {
this.$nextTick(async () => {
const userLocale = await this.$forage.getKeyValue({ key: 'user', value: 'locale' })()
this.locales.forEach(obj => {
if (obj.lang === userLocale) {
this.tempLocale = obj
}
})
})
},
methods: {
reroute (val) {
let hostName = window.location.hostname
hostName = hostName.substring(hostName.lastIndexOf('.', hostName.lastIndexOf('.') - 1) + 1)
let route = document.location.pathname.split('/')
route[1] = val
route = route.join('/')
if (location.search) route = route + location.search
return route
},
changeLang: async function (val) {
if (val === this.$route.params.locale) { return }
const route = this.reroute(val)
this.$forage.mergeItem({ key: 'user', value: { locale: val } })()
// mutate if we have an ID
if (await this.$meGet('id')) {
this.$apollo
.mutate({
mutation: gql`
mutation updateUser(
$change: String!
) {
updateUser (data: {
locale: $change
}) {
locale
}
}`,
variables: {
change: val
}
})
.catch(() => {})
}
await this.$router.push(route)
}
}
}
</script>

View File

@@ -1,204 +0,0 @@
{
"langLabel": "EN",
"properName": "English",
"shortCode": "en",
"titles": {
"splash": "NuYu MD",
"login": "NuYu Login",
"register": "NuYu Register",
"admin": {
"users": "Administer Users"
},
"user": {
"profile": "Profile",
"dashboard": "Dashboard",
"calendar": "Calendar"
}
},
"meta": {
"error": "Error",
"notice": "Notice",
"warning": "Warning",
"continue": "Continue",
"get_started": "Get Started"
},
"cookies": {
"title": "Our website uses cookies.",
"review": "Please take a moment to review our",
"linkText": "Privacy Policy"
},
"messages": {
"account_created": "Please check your email to verify your registration. This sometimes can take up to 10 minutes. Please check the spam folder if the email has not been received.",
"password_forgot": "Please check your email to reset your password.",
"verification_success": "Your e-mail has been verified. You can now login.",
"verification_failed": "Verification has failed.",
"password_recover_success": "Your password has been reset. You can now login with the new password.",
"logout_confirmation": "Are you sure you want to log out?",
"confirm": "Confirm",
"update_available": "A new update is available. Click on ok to reload the page.",
"hello": "Hello",
"start_onboarding": "To continue, please enter your basic details."
},
"errors": {
"general_error": "An error occurred. Please try again.",
"not_found": "Sorry, nothing here...",
"network": "Network error. Please check your internet connection",
"fields": "Please correct the input fields",
"first_name": {
"required": "First name is required",
"too_short": "First name is too short",
"too_long": "First name is too long",
"no_emoji": "\uD83D\uDE24 - Middle name may not have emoji",
"not_common_letter": "Middle name must only contain common letters"
},
"middle_name": {
"too_short": "Middle name is too short",
"too_long": "Middle name is too long",
"no_emoji": "\uD83D\uDE24 - Middle name may not have emoji",
"not_common_letter": "Middle name must only contain common letters"
},
"last_name": {
"required": "Last name is required",
"too_short": "Last name is too short",
"too_long": "Last name is too long",
"no_emoji": "\uD83D\uDE24 - Middle name may not have emoji",
"not_common_letter": "Middle name must only contain common letters"
},
"email": {
"required": "Email is required",
"too_long": "Email is too long",
"no_emoji": "\uD83D\uDE24 - Email may not have emoji",
"malformed": "Email doesn't look right"
},
"password": {
"required": "Password is required",
"too_short": "Password is too short - 8 chars minimum.",
"no_emoji": "\uD83D\uDE24 - Password may not have emoji",
"no_space": "Password may not have a space",
"one_upper": "Password must contain at least one uppercase",
"one_lower": "Password must contain at least one lowercase",
"one_number": "Password must contain at least one number",
"one_symbol": "Password must contain at least one symbol",
"confirm": "Passwords must match"
},
"dob": {
"malformed": "dob is malformed",
"under_18": "You must be 18 years of age or older"
},
"occupation": {
"too_short": "Occupation is too short",
"too_long": "Occupation is too long",
"no_emoji": "Occupation may not have emoji",
"not_common_letter": "Occupation may only contain common letters"
},
"children": {
"too_small": "You can't have less than 0 children",
"too_big": "That seems like too many children"
},
"locale": {
"too_short": "locale is too short",
"too_long": "locale is too long",
"no_emoji": "locale may not have emoji",
"not_common_letter": "locale may only contain common letters"
},
"street": {
"too_short": "street is too short",
"too_long": "street is too long",
"no_emoji": "street may not have emoji",
"not_common_letter": "street may only contain common letters"
},
"city": {
"too_short": "city is too short",
"too_long": "city is too long",
"no_emoji": "city may not have emoji",
"not_common_letter": "city may only contain common letters"
},
"token": {
"malformed": "That token doesn't look right. Please check your Email, or click below to be sent a new registration link.",
"length": "That token doesn't look right. Please check your Email, or click below to be sent a new registration link."
},
"timestamp": {
"malformed": "timestamp is malformed"
}
},
"buttons": {
"submit": "Submit",
"logout": "Logout",
"cancel": "Cancel",
"login": "Login",
"register": "Register",
"accept": "Accept",
"go_back": "Go back",
"send": "Send",
"close": "Close",
"next": "Next",
"previous": "Previous",
"updateAvatar": "Update Avatar",
"chooseFile": "Choose File"
},
"headers": {
"login": "Login",
"register": "Register",
"password_forgot": "Request a new password",
"password_recover": "Reset password",
"administrator": "Administrator",
"navigation": "Navigation",
"overview": "Overview",
"today": "Today",
"this_week": "This Week",
"upcoming": "Upcoming",
"articles": "Articles",
"article": "Article",
"validateToken": "Validation",
"activate": "Activate"
},
"labels": {
"my_account": "My account",
"register": "Register",
"logout": "Logout",
"login": "Login",
"email": "Email",
"name": "Name",
"firstName": "First Name",
"middleName": "Middle Name",
"lastName": "Last Name",
"password": "Password",
"telephone": "Telephone",
"repeat_password": "Repeat password",
"remember_me": "Remember me",
"password_forgot": "Forgot your password?",
"home": "Home",
"returnToLogin": "Return to Login",
"dob": "Date of Birth",
"sex": "Gender",
"race": "Race",
"children": "Children",
"occupation": "Occupation",
"interfaceLanguage": "Interface Language"
},
"error_labels": {
"password_length": "The minimum length of the password is {length} characters.",
"password_match": "Passwords do not match.",
"email": "A valid email address is required"
},
"users": {
"list": {
"table": {
"title": "All Users",
"rating": "Rating",
"firstName": "First Name",
"lastName": "Last Name",
"email": "Email",
"state": "State",
"status": "Status",
"role": "Role"
}
}
},
"table": {
"noResults": "Sorry, no results found."
},
"signup": {
"checkEmailText": "Please check your Email and click the confirmation link."
}
}

View File

@@ -1,76 +0,0 @@
{
"langLabel": "ES",
"properName": "Español",
"shortCode": "es",
"titles": {
"splash": "NuYu MD",
"login": "NuYu Login",
"register": "NuYu Registro"
},
"cookies": {
"title": "Nuestro sitio web utiliza cookies.",
"review": "Tómese un momento para revisar nuestra",
"linkText": "política de privacidad."
},
"messages": {
"account_created": "Please check your email to verify your registration. This sometimes can take up to 10 minutes. Please check the spam folder if the email has not been received.",
"password_forgot": "Please check your email to reset your password.",
"verification_success": "Your e-mail has been verified. You can now login.",
"verification_failed": "Verification has failed.",
"password_recover_success": "Your password has been reset. You can now login with the new password.",
"logout_confirmation": "Are you sure you want to log out?",
"confirm": "Confirm",
"update_available": "A new update is available. Click on ok to reload the page.",
"hello": "Hola"
},
"errors": {
"general_error": "An error occurred. Please try again.",
"not_found": "Sorry, nothing here...",
"network": "Network error. Please check your internet connection",
"fields": "Please correct the input fields"
},
"buttons": {
"submit": "Entregar",
"logout": "Cerrar sesión",
"cancel": "Cancelar",
"login": "Iniciar sesión",
"register": "Registrar",
"accept": "Aceptar",
"go_back": "Go back",
"send": "Send",
"close": "Close",
"next": "Next",
"previous": "Previous"
},
"headers": {
"login": "Iniciar sesión",
"register": "Registrar",
"password_forgot": "Request a new password",
"password_recover": "Reset password",
"administrator": "Administrator",
"navigation": "Navigation",
"overview": "Overview",
"today": "Today",
"this_week": "This Week",
"upcoming": "Upcoming",
"articles": "Articles",
"article": "Article"
},
"labels": {
"my_account": "My account",
"register": "Registrar",
"logout": "Cerrar sesión",
"login": "Inicio de sesión",
"email": "E-mail",
"name": "Nombre",
"firstName": "Nombre de pila",
"lastName": "Apellido",
"password": "Contraseña",
"repeat_password": "Repeat password",
"remember_me": "Recuérdame",
"password_forgot": "Forgot your password?",
"home": "Home",
"returnToLogin": "Volver al inicio de sesión",
"interfaceLanguage": "Interface Language"
}
}

View File

@@ -1,3 +0,0 @@
[
"en", "es"
]

View File

@@ -1,14 +0,0 @@
const extendQuasarConf = function (conf) {
// make sure boot file is registered
conf.boot.push('~@nuyu/quasar-app-extension-i18n/src/boot/i18n.js')
// make sure boot & component files transpile
conf.build.transpileDependencies.push(/quasar-app-extension-i18n[\\/]src/)
// conf.framework.components.push(['QMenu', 'QList'])
}
module.exports = function (api) {
// extend quasar.conf
api.extendQuasarConf(extendQuasarConf)
}

View File

@@ -1,10 +0,0 @@
/**
* Quasar App Extension install script
*
* Docs: https://quasar.dev/app-extensions/development-guide/install-api
* API: https://github.com/quasarframework/quasar/blob/master/app/lib/app-extension/InstallAPI.js
*/
module.exports = function (api) {
//
}

View File

@@ -1,44 +0,0 @@
/**
* Quasar App Extension prompts script
*
* Docs: https://quasar.dev/app-extensions/development-guide/prompts-api
*
* Inquirer prompts
* (answers are available as "api.prompts" in the other scripts)
* https://www.npmjs.com/package/inquirer#question
*
* Example:
return [
{
name: 'name',
type: 'string',
required: true,
message: 'Quasar CLI Extension name (without prefix)',
},
{
name: 'preset',
type: 'checkbox',
message: 'Check the features needed for your project:',
choices: [
{
name: 'Install script',
value: 'install'
},
{
name: 'Prompts script',
value: 'prompts'
},
{
name: 'Uninstall script',
value: 'uninstall'
}
]
}
]
*/
module.exports = function () {
return []
}

View File

@@ -1,10 +0,0 @@
/**
* Quasar App Extension uninstall script
*
* Docs: https://quasar.dev/app-extensions/development-guide/uninstall-api
* API: https://github.com/quasarframework/quasar/blob/master/app/lib/app-extension/UninstallAPI.js
*/
module.exports = function (api) {
//
}